土地管理与地籍测量——土地面积量算程序设计

实验任务

解析法计算任意地块的面积,是地籍测量的基础性工作。通过计算机高级语言编程,试写一段计算面积的程序源代码。

程序界面

在这里插入图片描述

程序功能

输入方式

  1. 通过导入外部文件,外部文件格式如图1所示。
    在这里插入图片描述
    在这里插入图片描述

  2. 还可如图2所示通过导入底图描摹获取。图中的线条可以通过鼠标点击绘制。
    在这里插入图片描述

查看信息

  1. 程序可以查看各个点的坐标,如图4所示
    在这里插入图片描述

2.程序中可以查看这块土地的属性,即:从原始文件中读取地号、权利人、土地坐落、土地用途等必要信息,如图5所示。
在这里插入图片描述

程序计算

程序可以根据解析法计算土地的周长与面积,如图6所示。在这里插入图片描述

文件导出

程序可以导出土地的属性信息、坐标点以及计算所得的周长和面积,方法是点击“开始”->“导出文件”,弹出如图7所示对话框,选择导出文件即可。最终结果保存形式如图8所示。
在这里插入图片描述
在这里插入图片描述

概要设计

在本次程序编写中,有如下问题需要考虑

  1. 外业测量的数据并不是首尾相连的,所以在画图和计算前必须将第一个点的数据追加到最后,实现相连;
  2. 外部导入的数据必须考虑缩放因子与平移因子;
	X_max = points[0].first;
	Y_max = points[0].second;
	X_min = points[0].first;
	Y_min = points[0].second;

	for (; it2 != points.end(); it2++) {
		if (it2->first > X_max)
			X_max = it2->first;
		if (it2->first < X_min)
			X_min = it2->first;
		if (it2->second > Y_max)
			Y_max = it2->second;
		if (it2->second < Y_min)
			Y_min = it2->second;
	}
	X_paint = 351;
	Y_paint = 480;

	dx = (X_max - X_min) / X_paint;
	dy = (Y_max - Y_min) / Y_paint;

	mx = X_min-15 ;
	my = Y_min-15 ;

  1. 因为涉及中文读取、显示与输出,所以需要考虑中文编码问题,防止出现乱码;
  2. 老师给的面积计算公式要求第一个点必须是原点,如果不是原点需要在计算面积前进行改化。
for (int i = 0; i < pts.size(); i++) {
		pts[i].first -= points[0].first;
		pts[i].second -= points[0].second;
	}
  1. 对于本软件要求,还需考虑外部文件的格式与包含内容,在阅读学习了地籍测量方面的规范后,添加了几项必要属性信息。

详细设计

1.根据解析法计算土地面积公式,编写如下的静态库。

template<typename T>
class Area
{
public:
	T CaculateSquare(vector<pair<T, T>> &points);
	T CaculateCircumference(vector<pair<T, T>> &points);
};

template<typename T>
T Area<T>::CaculateSquare(vector<pair<T, T>>& points)
{
	T squre = 0.0;
	vector<pair<T, T>> pts = points;

	for (int i = 0; i < pts.size(); i++) {
		pts[i].first -= points[0].first;
		pts[i].second -= points[0].second;
	}


	for (int i = 0; i < points.size() - 1; i++) {
		squre += abs(1.0 / 2 * (pts[i].first*pts[i + 1].second - pts[i + 1].first*pts[i].second));

	}
	return squre;
}

template<typename T>
T Area<T>::CaculateCircumference(vector<pair<T, T>>& points)
{
	T circum = 0.0;
	for (int i = 0; i < points.size() - 1; i++) {
		circum += sqrt(pow((points[i].first - points[i + 1].first), 2) + pow((points[i].second - points[i + 1].second), 2));
	}
	return circum;

编写自定义绘图控件,如下为绘图类的定义与方法定义。

namespace Ui {
	class PaintWidget;
}

class PaintWidget : public QWidget
{
	Q_OBJECT

public:
	PaintWidget(QWidget *parent = nullptr);
	void mousePressEvent(QMouseEvent *);
	
	void paintEvent(QPaintEvent *event);//绘制图像
	void mouseMoveEvent(QMouseEvent *e);//当鼠标移动后实时刷新画布
	void PaintWidget::paintClean();//清空画面

	~PaintWidget();
	QVector<QPointF> pointList;
	QVector<QLineF> linefList;
protected:
	//void paintEvent(QPaintEvent *event);
	bool bDraw;             //是否处于绘制状态
	bool bLeftClick;            //是否已经开始左键点击,同时标识是否开始进行绘制
	bool bMove;             //是否处于绘制时的鼠标移动状态
	
	QPointF movePoint;

private:
	Ui::PaintWidget *ui;
	QPoint startPos;
	QPoint endPos;
	QPixmap *pix;
signals:
	void singalDrawOver();
};

编写主窗口的实现类。以下是主窗口的类定义与方法定义。

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
	Q_OBJECT

public:
	MainWindow(QWidget *parent = nullptr);
	
	~MainWindow();

	std::vector<std::pair<std::string, std::string>> heads;
	std::vector<std::pair<double, double>>points;
	QString filename;
	double square=0, circumference=0;

public slots:
	//用于计算面积周长
	void btnClicked();
	//用于打开文本文件
	void actionTriggered();
	//用于加载底图
	void actionTriggered01();
	//用于清除绘图
	void btn_clearClicked();
	//用于查看各点信息
	void btn_watchClicked();
	//用于把周长、面积、土地信息导出来
	void actionTriggered02();

private:
	Ui::MainWindow *ui;
	//用于把文件中的点画出来
	void paintOutPoint();
};

编写主函数,用于启动界面

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	MainWindow w;
	QFile qssFile(":style.qss");
	qssFile.open(QFile::ReadOnly);
	QString qss;
	if (qssFile.isOpen())
	{
		qss = QLatin1String(qssFile.readAll());
		qApp->setStyleSheet(qss);
		qssFile.close();
	}
	w.show();
	return a.exec();
}

附:计算土地面积周长源代码(C++)

main.cpp

#include "MainWindow.h"
#include <QApplication>
#include<QFile>

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	MainWindow w;
	QFile qssFile(":style.qss");
	qssFile.open(QFile::ReadOnly);
	QString qss;
	if (qssFile.isOpen())
	{
		qss = QLatin1String(qssFile.readAll());
		qApp->setStyleSheet(qss);
		qssFile.close();
	}
	w.show();
	return a.exec();
}

mathlib/Area.hpp

template<typename T>
class Area
{
public:
	T CaculateSquare(vector<pair<T, T>> &points);
	T CaculateCircumference(vector<pair<T, T>> &points);
};

template<typename T>
T Area<T>::CaculateSquare(vector<pair<T, T>>& points)
{
	T squre = 0.0;
	vector<pair<T, T>> pts = points;

	for (int i = 0; i < pts.size(); i++) {
		pts[i].first -= points[0].first;
		pts[i].second -= points[0].second;
	}


	for (int i = 0; i < points.size() - 1; i++) {
		squre += abs(1.0 / 2 * (pts[i].first*pts[i + 1].second - pts[i + 1].first*pts[i].second));

	}
	return squre;
}

template<typename T>
T Area<T>::CaculateCircumference(vector<pair<T, T>>& points)
{
	T circum = 0.0;
	for (int i = 0; i < points.size() - 1; i++) {
		circum += sqrt(pow((points[i].first - points[i + 1].first), 2) + pow((points[i].second - points[i + 1].second), 2));

	}
	return circum;
}

PaintWidget.h

#ifndef PAINTWIDGET_H
#define PAINTWIDGET_H

#include <QWidget>
#include<QMouseEvent>
#include<QPaintEvent>
#include<qdebug.h>

namespace Ui {
	class PaintWidget;
}

class PaintWidget : public QWidget
{
	Q_OBJECT

public:
	PaintWidget(QWidget *parent = nullptr);
	void mousePressEvent(QMouseEvent *);
	
	void paintEvent(QPaintEvent *event);//绘制图像
	void mouseMoveEvent(QMouseEvent *e);//当鼠标移动后实时刷新画布
	void PaintWidget::paintClean();//清空画面

	~PaintWidget();
	QVector<QPointF> pointList;
	QVector<QLineF> linefList;
protected:
	//void paintEvent(QPaintEvent *event);
	bool bDraw;             //是否处于绘制状态
	bool bLeftClick;            //是否已经开始左键点击,同时标识是否开始进行绘制
	bool bMove;             //是否处于绘制时的鼠标移动状态
	
	QPointF movePoint;

private:
	Ui::PaintWidget *ui;
	QPoint startPos;
	QPoint endPos;
	QPixmap *pix;
signals:
	void singalDrawOver();
};

#endif // PAINTWIDGET_H

PaintWidget.cpp

#include "PaintWidget.h"
#include "ui_PaintWidget.h"
#include<QPainter>
#include<iostream>
using namespace std;

PaintWidget::PaintWidget(QWidget *parent) :
	QWidget(parent),
	ui(new Ui::PaintWidget)
{
	ui->setupUi(this);
	//填充背景色
	setAutoFillBackground(true);
	setBackgroundRole(QPalette::Base);

	setMouseTracking(true);
}

PaintWidget::~PaintWidget()
{
	delete ui;
}

void PaintWidget::mousePressEvent(QMouseEvent *e) {
	pointList.push_back(QPointF(e->x(), e->y()));
}

//清空图上点
void PaintWidget::paintClean() {
	pointList.clear();
	linefList.clear();
	update();
}

void PaintWidget::paintEvent(QPaintEvent * event)
{
	QPainter painter(this);
	int num = pointList.size();
	for (int i = 0; i < num; i++) {
		
		painter.drawEllipse(QPoint(pointList[i].x(), pointList[i].y()), 1, 1);
	}

	if (num > 1) {
		for (int i = 0; i < num - 1; i++) {
			painter.drawLine(QPoint(pointList[i].x(), pointList[i].y()), QPoint(pointList[i + 1].x(), pointList[i + 1].y()));

		}
	}
}

void PaintWidget::mouseMoveEvent(QMouseEvent * e)
{
	update();
}

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
//#include  "PaintWidget.h"
#include<QtGui>
#include<vector>
#include<string>
#include<qpoint.h>


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
	Q_OBJECT

public:
	MainWindow(QWidget *parent = nullptr);
	
	~MainWindow();

	std::vector<std::pair<std::string, std::string>> heads;
	std::vector<std::pair<double, double>>points;
	QString filename;
	double square=0, circumference=0;

public slots:
	//用于计算面积周长
	void btnClicked();
	//用于打开文本文件
	void actionTriggered();
	//用于加载底图
	void actionTriggered01();
	//用于清除绘图
	void btn_clearClicked();
	//用于查看各点信息
	void btn_watchClicked();
	//用于把周长、面积、土地信息导出来
	void actionTriggered02();

private:
	Ui::MainWindow *ui;
	//用于把文件中的点画出来
	void paintOutPoint();
};
#endif // MAINWINDOW_H

MainWindow.cpp

#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "SXWidget.h"
#include<mathlib/AreaAndRound.h>

#include<qfiledialog.h>
#include<iostream>
#include<fstream>
#include<sstream>


MainWindow::MainWindow(QWidget *parent)
	: QMainWindow(parent)
	, ui(new Ui::MainWindow)
{
	ui->setupUi(this);
	//ui->PaintWidget->setStyleSheet("QWidget{background:white}");
	//ui->PaintWidget->ch

	//计算按钮
	connect(ui->btn, SIGNAL(clicked()), this, SLOT(btnClicked()));
	
	//打开文件按钮
	connect(ui->action01, SIGNAL(triggered()), this, SLOT(actionTriggered()));

	//清空图层按钮
	connect(ui->btn_clear, SIGNAL(clicked()), this, SLOT(btn_clearClicked()));

	//查看列表按钮
	connect(ui->btn_watch, SIGNAL(clicked()), this, SLOT(btn_watchClicked()));

	//打开底图按钮
	connect(ui->action02, SIGNAL(triggered()), this, SLOT(actionTriggered01()));
	
	//导出文件
	connect(ui->action03, SIGNAL(triggered()), this, SLOT(actionTriggered02()));

}


MainWindow::~MainWindow()
{
	delete ui;
}
#include<qdebug.h>
void MainWindow::actionTriggered()
{

	//把文件的头部信息与点位信息写入内存
	filename= QFileDialog::getOpenFileName(this, QString::fromLocal8Bit("打开"), "", tr("(*.txt)"));
	
	//filename= "C:\\Users\\sishu\\Desktop\\temperary\\input.txt";
	qDebug() << filename;
	std::ifstream ifs(filename.toStdString());
	std::string temp;
	std::pair<std::string, std::string> oneHead;
	std::pair<double, double> onePoint;
	while (std::getline(ifs, temp)) {
		if (temp != "END") {
			std::istringstream iss(temp);
			std::string s1,s2;

			iss >> oneHead.first >> oneHead.second;
			heads.push_back(oneHead);
		}
		if (temp == "END") { break; }
	}
	while (std::getline(ifs, temp)) {
		std::istringstream iss(temp);
		std::string s1,s2,s3;
		iss >> s1 >> s2 >> s3;
		onePoint.first = atof(s2.c_str());
		onePoint.second = atof(s3.c_str());
		points.push_back(onePoint);
	}

	points.push_back(points[0]);
	
	//头表格
	//表头
	QStandardItemModel* model = new QStandardItemModel();
	QStringList labels ;
	labels << QStringLiteral("属性名") << QStringLiteral("属性值");
	model->setHorizontalHeaderLabels(labels);

	QStandardItem *item = nullptr;
	for (int i = 0; i < heads.size(); i++) {
		item = new QStandardItem(QString::fromStdString(heads[i].first));
		model->setItem(i, 0, item);
		item = new QStandardItem(QString::fromStdString(heads[i].second));
		model->setItem(i, 1, item);
	}

	ui->tableView_2->setModel(model);
	paintOutPoint();
}
void MainWindow::actionTriggered01()
{
	QString filename2;
	filename2 = QFileDialog::getOpenFileName(this, QString::fromLocal8Bit("打开"), "", tr("(*.jpg)"));
	ui->myWidget->style();

	/*SXWidget *sxwidget = new SXWidget;
	sxwidget->show();*/
}
void MainWindow::btn_clearClicked()
{
	ui->myWidget->paintClean();

}
void MainWindow::btn_watchClicked()
{
	if (points.size()==0) {
		double dx, dy, mx, my;

		dx = dy = 1.0125;
		mx = my = 2.3235;
		std::pair<double, double> onePoint;
		for (int i = 0; i < ui->myWidget->pointList.count(); i++) {
			onePoint.first = ui->myWidget->pointList[i].x()*dx+mx;
			onePoint.second = ui->myWidget->pointList[i].y()*dy+my;
			points.push_back(onePoint);
		}
	}
	//表头
	QStandardItemModel* model = new QStandardItemModel();
	QStringList labels = QObject::trUtf8("id,x,y").simplified().split(",");
	model->setHorizontalHeaderLabels(labels);
	QStandardItem *item = nullptr;
	for (int i = 0; i < points.size(); i++) {
		item = new QStandardItem(QString("%1").arg(i));
		model->setItem(i, 0, item);
		item = new QStandardItem(QString::number(points[i].first));
		model->setItem(i, 1, item);
		item = new QStandardItem(QString::number(points[i].second));
		model->setItem(i, 2, item);
	}
	ui->tableView->setModel(model);
}
#include<codecvt>
//接口是两个std::string
std::string gb2312_to_utf8(std::string const &strGb2312)
{
	std::vector<wchar_t> buff(strGb2312.size());
#ifdef _MSC_VER
	std::locale loc("zh-CN");
#else
	std::locale loc("zh_CN.GB18030");
#endif
	wchar_t* pwszNext = nullptr;
	const char* pszNext = nullptr;
	mbstate_t state = {};
	int res = std::use_facet<std::codecvt<wchar_t, char, mbstate_t> >
		(loc).in(state,
			strGb2312.data(), strGb2312.data() + strGb2312.size(), pszNext,
			buff.data(), buff.data() + buff.size(), pwszNext);
	if (std::codecvt_base::ok == res)
	{
		//转UTF8
		std::wstring_convert<std::codecvt_utf8<wchar_t>> cutf8;
		return cutf8.to_bytes(std::wstring(buff.data(), pwszNext));
	}
	return "";
}
std::string qstr2str(const QString qstr)
{
	QByteArray cdata = qstr.toLocal8Bit();
	return std::string(cdata);
}
///乱码真的难搞
void MainWindow::actionTriggered02()
{
	QString out_filename;
	QString temp,temp1;
	out_filename = QFileDialog::getOpenFileName(this, QString::fromLocal8Bit("打开"), "", tr("(*.txt)"));
	std::ofstream ofs(out_filename.toStdString());
	std::vector<std::pair<std::string, std::string>>::iterator it = heads.begin();
	for (; it != heads.end(); it++) {
		//ofs << it->first << "	" << it->second<<std::endl;
		
		temp=QString::fromStdString(it->first);
		temp1 = QString::fromStdString(it->second);
		ofs << qstr2str(temp) << "	" << qstr2str(temp1) <<std::endl;
	}
	ofs << "END" << std::endl;
	std::vector<std::pair<double, double>>::iterator its = points.begin();
	int i = 0;
	for (; its != points.end(); its++) {
		ofs <<i<<"	" <<its->first << "	" << its->second<<std::endl;
		i++;
	}
	ofs << "面积" << "	" << ui->areaEdit->text().toStdString() <<std::endl;
	ofs << "周长" << "	" << ui->roundEdit->text().toStdString() <<std::endl;
}
void MainWindow::paintOutPoint()
{
	//首先计算外部点转换到像素点的比例尺
	double X_max, Y_max, X_min, Y_min;
	
	int X_paint, Y_paint;
	double dx, dy;
	double mx, my;

	std::vector < std::pair<double, double> > ::iterator it2 = points.begin();
	X_max = points[0].first;
	Y_max = points[0].second;
	X_min = points[0].first;
	Y_min = points[0].second;

	for (; it2 != points.end(); it2++) {
		if (it2->first > X_max)
			X_max = it2->first;
		if (it2->first < X_min)
			X_min = it2->first;
		if (it2->second > Y_max)
			Y_max = it2->second;
		if (it2->second < Y_min)
			Y_min = it2->second;
	}
	X_paint = 351;
	Y_paint = 480;

	dx = (X_max - X_min) / X_paint;
	dy = (Y_max - Y_min) / Y_paint;

	mx = X_min-15 ;
	my = Y_min-15 ;
	QPointF point;
	std::vector < std::pair<double, double> > ::iterator it = points.begin();
	qDebug() << dx << " " << dy;
	for (; it != points.end(); it++) {
		point = QPoint(int((it->first-mx)/dx), int((it->second-my)/dy));
		ui->myWidget->pointList.push_back(point);
		
		qDebug() << point.x() << " " << point.y() << " ";
	}
	ui->myWidget->update();
}
void MainWindow::btnClicked() {
	Area<double> area;
	ui->areaEdit->setText(QString::number(area.CaculateSquare(points),'f',3));
	ui->roundEdit->setText(QString::number(area.CaculateCircumference(points),'f',3));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值