OsgEarth下量取球面面积

#ifndef AREA_H
#define AREA_H

#include "handleadapter.h"

class Area : public HandleAdapter
{
public:
	Area(GraphicsView* view);
	~Area();

protected:
	virtual void slotPicked(osg::Vec3d pos);
	virtual void slotMoveing(osg::Vec3d pos);
	virtual void slotRightHandle();

private:
	void drawPolygon(osg::Vec3d pos = osg::Vec3d());

private:
	std::vector<osg::Vec3d> m_vecPoints;
	osgEarth::Symbology::Style m_polygonStyle;
	osgEarth::Symbology::Style m_textStyle;
	osgEarth::Annotation::FeatureNode* m_pFeatureNode;
	osgEarth::Annotation::FeatureEditor* m_pPolygonEdit;
	osgEarth::Annotation::PlaceNode* m_pPlaceNode;

	/添加橡皮筋功能
	osgEarth::Symbology::Style m_stippleLineStyle;
	osgEarth::Annotation::FeatureNode* m_pStippleFeatureNode;
};

#endif // AREA_H
#include "area.h"
#include "calcmath.h"

Area::Area(GraphicsView* view)
: HandleAdapter(view)
{
	m_vecPoints.clear();
	m_pFeatureNode = NULL;
	//m_pPolygonEdit = NULL;
	m_pPlaceNode = NULL;
	m_pStippleFeatureNode = NULL;


	m_polygonStyle.getOrCreate<osgEarth::Symbology::PolygonSymbol>()->fill()->color() = osgEarth::Symbology::Color::Yellow;
	m_polygonStyle.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()->clamping() = osgEarth::Symbology::AltitudeSymbol::CLAMP_TO_TERRAIN;
	m_polygonStyle.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()->technique() = osgEarth::Symbology::AltitudeSymbol::TECHNIQUE_DRAPE;
	m_polygonStyle.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()->verticalOffset() = 0.1;
	/*********橡皮筋**********/
	m_stippleLineStyle.getOrCreate<osgEarth::Symbology::LineSymbol>()->stroke()->color() = osgEarth::Symbology::Color::Red;
	m_stippleLineStyle.getOrCreate<osgEarth::Symbology::LineSymbol>()->stroke()->width() = 2.0;
	m_stippleLineStyle.getOrCreate<osgEarth::Symbology::LineSymbol>()->tessellation() = 20.0;
	m_stippleLineStyle.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()->clamping() = osgEarth::Symbology::AltitudeSymbol::CLAMP_TO_TERRAIN;
	m_stippleLineStyle.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()->technique() = osgEarth::Symbology::AltitudeSymbol::TECHNIQUE_DRAPE;
	m_stippleLineStyle.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()->verticalOffset() = 0.1;
	m_stippleLineStyle.getOrCreate<osgEarth::Symbology::LineSymbol>()->stroke()->stipple() = 255;

	m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->alignment()= osgEarth::Symbology::TextSymbol::ALIGN_LEFT_TOP;
	m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->encoding()= osgEarth::Symbology::TextSymbol::ENCODING_UTF8;
	m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->declutter()	= true;
	m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->halo()= osgEarth::Symbology::Color::White;
	m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->haloOffset() = 0.05;
	m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->fill()->color()	= osg::Vec4(1, 0.5, 0, 1);
	m_textStyle.getOrCreate<osgEarth::Symbology::RenderSymbol>()->lighting() = false;
	m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->font() = "simhei.ttf";
	m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->size() = 25.0;
}

Area::~Area()
{

}

void Area::slotPicked(osg::Vec3d pos)
{
	/*m_vecPoints.push_back(pos);
	if (m_vecPoints.size() <= 2)
	{
		return;
	}

	drawPolygon();*/
	
	m_vecPoints.push_back(pos);
	if (m_vecPoints.size() <= 1)
	{
		return;
	}

	/*if (m_pPolygonEdit != NULL)
	{
		m_pPolygonEdit->removeChildren(0, m_pPolygonEdit->getNumChildren());
		m_pPolygonEdit = NULL;
	}*/
	if (m_pFeatureNode == NULL)
	{
		osgEarth::Features::Feature* pFeature = new osgEarth::Features::Feature(new osgEarth::Symbology::Polygon, m_pMap3D->getSRS(), m_polygonStyle);
		m_pFeatureNode = new osgEarth::Annotation::FeatureNode(m_pMap3D->getMapNode(), pFeature);

		m_pPlaceNode = new osgEarth::Annotation::PlaceNode(m_pMap3D->getMapNode(), osgEarth::GeoPoint::GeoPoint(), "", m_textStyle);
		m_pPlaceNode->setDynamic(true);

		m_pLayerGroup->addChild(m_pFeatureNode);
		m_pLayerGroup->addChild(m_pPlaceNode);
		
	}
	osgEarth::Symbology::Geometry* pGeometry = m_pFeatureNode->getFeature()->getGeometry();
	pGeometry->clear();
	m_pFeatureNode->setStyle(m_polygonStyle);
	for (auto& n : m_vecPoints)
	{
		pGeometry->push_back(n);
	
	}	
	CalcMath math;
	QString str = QStringLiteral("面积:%1 ㎡").arg(QString::number(math.calcArea(m_vecPoints), 'g', 9));
	m_pPlaceNode->setText(str.toStdString());
	m_pPlaceNode->setPosition(osgEarth::GeoPoint::GeoPoint(m_pMap3D->getSRS(), pos));
	///
	m_pFeatureNode->init();

	if (m_pStippleFeatureNode != NULL)
	{
		m_pStippleFeatureNode->getFeature()->getGeometry()->clear();
		m_pStippleFeatureNode->init();
	}

	/*if (m_pPolygonEdit == NULL)
	{
		m_pPolygonEdit = new osgEarth::Annotation::FeatureEditor(m_pFeatureNode);
		m_pLayerGroup->addChild(m_pPolygonEdit);
	}*/
}

void Area::slotMoveing(osg::Vec3d pos)
{
	/*if (m_vecPoints.size() < 2)
	{
		return;
	}
	drawPolygon(pos);*/
	if (m_vecPoints.size() < 2)
	{
		return;
	}
	if (m_pStippleFeatureNode == NULL)
	{
		osgEarth::Features::Feature* pFeature = new osgEarth::Features::Feature(new osgEarth::Annotation::LineString, m_pMap3D->getSRS(), m_stippleLineStyle);
		m_pStippleFeatureNode = new osgEarth::Annotation::FeatureNode(m_pMap3D->getMapNode(), pFeature);
		m_pLayerGroup->addChild(m_pStippleFeatureNode);
	
	}
	std::vector<osg::Vec3d> vecPoints = m_vecPoints;//??
	osgEarth::Symbology::Geometry* pGeometry = m_pStippleFeatureNode->getFeature()->getGeometry();
	pGeometry->clear();
	m_pStippleFeatureNode->setStyle(m_stippleLineStyle);
	pGeometry->push_back(m_vecPoints[0]);
	pGeometry->push_back(pos);
	pGeometry->push_back(m_vecPoints[m_vecPoints.size() - 1]);

	//
	if (pos != osg::Vec3d())//?????
	{
		//pGeometry->push_back(pos);
		vecPoints.push_back(pos);
	}

	CalcMath math;
	QString str = QStringLiteral("面积:%1 ㎡").arg(QString::number(math.calcArea(vecPoints), 'g', 9));
	m_pPlaceNode->setText(str.toStdString());
	m_pPlaceNode->setPosition(osgEarth::GeoPoint::GeoPoint(m_pMap3D->getSRS(), pos));

	m_pStippleFeatureNode->init();
}

void Area::slotRightHandle()
{
	
	if (m_pStippleFeatureNode != NULL)
	{
		m_pStippleFeatureNode->getFeature()->getGeometry()->clear();
		m_pStippleFeatureNode->init();
		CalcMath math;
		QString str = QStringLiteral("面积:%1 ㎡").arg(QString::number(math.calcArea(m_vecPoints), 'g', 9));
		m_pPlaceNode->setText(str.toStdString());
		m_pPlaceNode->setPosition(osgEarth::GeoPoint::GeoPoint(m_pMap3D->getSRS(), m_vecPoints[0]));
	}
	if (m_pFeatureNode!= nullptr)
	{
		m_pFeatureNode = nullptr;
		m_vecPoints.clear();
	}	
	
}

#ifndef MATH_H
#define MATH_H

#include "link.h"
class CalcMath
{
public:
	CalcMath();
	~CalcMath();

	// 球面面积计算公式
	double calcArea(std::vector<osg::Vec3d> points);

private:
	
};

#endif // MATH_H
#include "calcmath.h"

CalcMath::CalcMath()
{

}

CalcMath::~CalcMath()
{

}

double CalcMath::calcArea(std::vector<osg::Vec3d> points)
{
	double dTotalArea = 0.0;
	int iCount = points.size();
	if (iCount > 2)
	{
		double dLowX = 0.0;
		double dLowY = 0.0;
		double dMiddleX = 0.0;
		double dMiddleY = 0.0;
		double dHighX = 0.0;
		double dHighY = 0.0;
		double AM = 0.0;
		double BM = 0.0;
		double CM = 0.0;
		double AL = 0.0;
		double BL = 0.0;
		double CL = 0.0;
		double AH = 0.0;
		double BH = 0.0;
		double CH = 0.0;
		//Coefficient系数
		double dCoefficientL = 0.0;
		double dCoefficientH = 0.0;
		//tangent切线
		double dALtangent = 0.0;
		double dBLtangent = 0.0;
		double dCLtangent = 0.0;
		double dAHtangent = 0.0;
		double dBHtangent = 0.0;
		double dCHtangent = 0.0;
		//NormalLine法线     
		double dANormalLine = 0.0;
		double dBNormalLine = 0.0;
		double dCNormalLine = 0.0;
		//Orientation  Value方向值  
		double dOrientationValue = 0.0;
		//余弦角
		double dAngleCos = 0.0;

		double dSum1 = 0.0;
		double dSum2 = 0.0;
		int iCount2 = 0;
		int iCount1 = 0;

		double dSum = 0.0;

		for (int i = 0; i < iCount; i++)
		{
			if (i == 0)
			{
				//换算成弧度;
				dLowX = osg::DegreesToRadians(points.at(iCount - 1).x());
				dLowY = osg::DegreesToRadians(points.at(iCount - 1).y());
				dMiddleX = osg::DegreesToRadians(points.at(0).x());
				dMiddleY = osg::DegreesToRadians(points.at(0).y());
				dHighX = osg::DegreesToRadians(points.at(1).x());
				dHighY = osg::DegreesToRadians(points.at(1).y());
			}
			else if (i == iCount - 1)
			{
				dLowX = osg::DegreesToRadians(points.at(iCount - 2).x());
				dLowY = osg::DegreesToRadians(points.at(iCount - 2).y());
				dMiddleX = osg::DegreesToRadians(points.at(iCount - 1).x());
				dMiddleY = osg::DegreesToRadians(points.at(iCount - 1).y());
				dHighX = osg::DegreesToRadians(points.at(0).x());
				dHighY = osg::DegreesToRadians(points.at(0).y());
			}
			else
			{
				dLowX = osg::DegreesToRadians(points.at(i - 1).x());
				dLowY = osg::DegreesToRadians(points.at(i - 1).y());
				dMiddleX = osg::DegreesToRadians(points.at(i).x());
				dMiddleY = osg::DegreesToRadians(points.at(i).y());
				dHighX = osg::DegreesToRadians(points.at(i + 1).x());
				dHighY = osg::DegreesToRadians(points.at(i + 1).y());
			}
			AM = cos(dMiddleY) * cos(dMiddleX);
			BM = cos(dMiddleY) * sin(dMiddleX);
			CM = sin(dMiddleY);
			AL = cos(dLowY) * cos(dLowX);
			BL = cos(dLowY) * sin(dLowX);
			CL = sin(dLowY);
			AH = cos(dHighY) * cos(dHighX);
			BH = cos(dHighY) * sin(dHighX);
			CH = sin(dHighY);

			dCoefficientL = (AM*AM + BM*BM + CM*CM) / (AM*AL + BM*BL + CM*CL);
			dCoefficientH = (AM*AM + BM*BM + CM*CM) / (AM*AH + BM*BH + CM*CH);

			dALtangent = dCoefficientL * AL - AM;
			dBLtangent = dCoefficientL * BL - BM;
			dCLtangent = dCoefficientL * CL - CM;
			dAHtangent = dCoefficientH * AH - AM;
			dBHtangent = dCoefficientH * BH - BM;
			dCHtangent = dCoefficientH * CH - CM;

			dAngleCos = (dAHtangent * dALtangent + dBHtangent * dBLtangent + dCHtangent * dCLtangent) /
				(sqrt(dAHtangent * dAHtangent + dBHtangent * dBHtangent + dCHtangent * dCHtangent) *
				sqrt(dALtangent * dALtangent + dBLtangent * dBLtangent + dCLtangent * dCLtangent));

			dAngleCos = acos(dAngleCos);

			dANormalLine = dBHtangent * dCLtangent - dCHtangent * dBLtangent;
			dBNormalLine = 0 - (dAHtangent * dCLtangent - dCHtangent * dALtangent);
			dCNormalLine = dAHtangent * dBLtangent - dBHtangent * dALtangent;

			if (AM != 0)
			{
				dOrientationValue = dANormalLine / AM;
			}
			else if (BM != 0)
			{
				dOrientationValue = dBNormalLine / BM;
			}
			else
			{
				dOrientationValue = dCNormalLine / CM;
			}
			if (dOrientationValue > 0)
			{
				dSum1 += dAngleCos;
				iCount1++;
			}
			else
			{
				dSum2 += dAngleCos;
				iCount2++;
			}
		}
		if (dSum1 > dSum2)
		{
			dSum = dSum1 + (2 * osg::PI*iCount2 - dSum2);
		}
		else
		{
			dSum = (2 * osg::PI*iCount1 - dSum1) + dSum2;
		}

		dTotalArea = (dSum - (iCount - 2)*osg::PI)* osg::WGS_84_RADIUS_EQUATOR *
			osg::WGS_84_RADIUS_EQUATOR;
	}
	return dTotalArea;
}

 

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海亲王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值