OsgEarth下战术标图

双线箭头

#ifndef __GV00003_H__
#define __GV00003_H__

#include "GVGeometry.h"
#include "Bezier.h"

class GV00003 : public GVGeometry
{
public:
	GV00003();
	~GV00003();

	int getControlPointCount();
	void getControlPoints(std::vector<GVCoord>& vtxBuffer);
	GVCoord getControlPoint(int idx);
	void setControlPointsEx(std::vector<GVCoord>& vtxBuffer);
	void setControlPoints(std::vector<GVCoord>& vtxBuffer);
	void setControlPoint(int idx, const GVCoord& vtx);
	bool toVertice(std::vector<GVCoord>& vtxBuffer, std::vector<int>* vtxBuffer2);
	double brokenLineDistance(int start, int end) const;

private:
	std::vector<GVCoord> _controlPoints;
	double scale[4];
};

#endif //__GV00003_H__
#pragma once

#include "GV00003.h"

#define Distance_3(coord1, coord2) (sqrt((coord1.lat - coord2.lat) * (coord1.lat - coord2.lat) + (coord1.lon - coord2.lon) * (coord1.lon - coord2.lon)))

GV00003::GV00003()
{
	scale[0] = 0.12;
	scale[1] = 0.15;
	scale[2] = 0.4;
	scale[3] = 0.3;
}

GV00003::~GV00003()
{

}

int GV00003::getControlPointCount()
{
	std::vector<GVCoord> controlPoints;
	getControlPoints(controlPoints);
	return controlPoints.size();
}

void GV00003::getControlPoints(std::vector<GVCoord>& vtxBuffer)
{
	if(_controlPoints.size() <= 0)
		return ;

	vtxBuffer = _controlPoints;
}

GVCoord GV00003::getControlPoint(int idx)
{
	if(idx >= 0 && idx < _controlPoints.size())
		return _controlPoints[idx];

	return GVCoord();
}

void GV00003::setControlPointsEx(std::vector<GVCoord> &vtxBuffer)
{
	_controlPoints = vtxBuffer;
}

void GV00003::setControlPoints(std::vector<GVCoord>& vtxBuffer)
{
	_controlPoints.clear();
	_controlPoints = vtxBuffer;

	if(_controlPoints.size() > 2)
	{
		GVCoord arrowHead = _controlPoints[_controlPoints.size()-1];
		GVCoord arrowTailLeft = _controlPoints[0];
		GVCoord arrowTailRight = _controlPoints[1];

		double brockenLineLength = Distance_3(GVCoord((arrowTailLeft.lon + arrowTailRight.lon)/2, (arrowTailLeft.lat + arrowTailRight.lat)/2, 0), arrowHead);

		if(_controlPoints.size() > 3)
		{
			brockenLineLength = Distance_3(_controlPoints[_controlPoints.size()-2], _controlPoints[_controlPoints.size()-1]);
		}

		GVCoord penultimatePointOnAxis;
		penultimatePointOnAxis.lon = (arrowTailLeft.lon + arrowTailRight.lon)/2;
		penultimatePointOnAxis.lat = (arrowTailLeft.lat + arrowTailRight.lat)/2;
		if(_controlPoints.size() > 3)
		{
			penultimatePointOnAxis = _controlPoints[_controlPoints.size()-2];
		}

		double arrowTopLength = 2 * brockenLineLength * scale[0];
		double arrowNeckWidthHalf = arrowTopLength * scale[1];
		double arrowEarWidthHalf = arrowTopLength * scale[2];
		double arrowEarthLength = arrowTopLength * scale[3];

		GVCoord arrowNeckRight;
		GVCoord arrowEarLeft;
		GVCoord arrowEarMiddle;

		osg::Vec3d vecTop = osg::Vec3d(arrowHead.lon - penultimatePointOnAxis.lon, arrowHead.lat - penultimatePointOnAxis.lat, 0);
		vecTop.normalize();
		arrowEarMiddle.lon = arrowHead.lon - arrowTopLength * vecTop.x();
		arrowEarMiddle.lat = arrowHead.lat - arrowTopLength * vecTop.y();

		osg::Vec3d vecTopVertical = osg::Vec3d(-vecTop.y(), vecTop.x(), 0);
		arrowEarLeft.lon = arrowEarMiddle.lon + arrowEarWidthHalf * vecTopVertical.x();
		arrowEarLeft.lat = arrowEarMiddle.lat + arrowEarWidthHalf * vecTopVertical.y();

		GVCoord arrowNeckMiddle;
		arrowNeckMiddle.lon = arrowHead.lon - (arrowTopLength - arrowEarthLength) * vecTop.x();
		arrowNeckMiddle.lat = arrowHead.lat - (arrowTopLength - arrowEarthLength) * vecTop.y();

		arrowNeckRight.lon = arrowNeckMiddle.lon - arrowNeckWidthHalf * vecTopVertical.x();
		arrowNeckRight.lat = arrowNeckMiddle.lat - arrowNeckWidthHalf * vecTopVertical.y();

		_controlPoints.insert(_controlPoints.begin(), arrowEarMiddle);
		_controlPoints.insert(_controlPoints.begin(), arrowEarLeft);
		_controlPoints.insert(_controlPoints.begin(), arrowNeckRight);
	}
}

void GV00003::setControlPoint(int idx, const GVCoord& vtx)
{
	int cpSize = _controlPoints.size();
	if(idx < 0 || idx >= cpSize)
		return ;

	GVCoord arrowHead = _controlPoints[_controlPoints.size()-1];
	GVCoord arrowTailLeft = _controlPoints[3];
	GVCoord arrowTailRight = _controlPoints[4];

	double brockenLineLength = Distance_3(GVCoord((arrowTailLeft.lon + arrowTailRight.lon)/2, (arrowTailLeft.lat + arrowTailRight.lat)/2, 0), arrowHead);

	if(_controlPoints.size() > 6)
	{
		brockenLineLength = Distance_3(_controlPoints[_controlPoints.size()-2], _controlPoints[_controlPoints.size()-1]);
	}

	GVCoord penultimatePointOnAxis;
	penultimatePointOnAxis.lon = (arrowTailLeft.lon + arrowTailRight.lon)/2;
	penultimatePointOnAxis.lat = (arrowTailLeft.lat + arrowTailRight.lat)/2;
	if(_controlPoints.size() > 6)
	{
		penultimatePointOnAxis = _controlPoints[_controlPoints.size()-2];
	}

	double arrowTopLength = 2 * brockenLineLength * scale[0];
	double arrowNeckWidthHalf = arrowTopLength * scale[1];
	double arrowEarWidthHalf = arrowTopLength * scale[2];
	double arrowEarthLength = arrowTopLength * scale[3];

	osg::Vec3d vecTop = osg::Vec3d(arrowHead.lon - penultimatePointOnAxis.lon, arrowHead.lat - penultimatePointOnAxis.lat, 0);
	vecTop.normalize();
	osg::Vec3d vecTopVertical = osg::Vec3d(-vecTop.y(), vecTop.x(), 0);

	if(idx == 0)
	{
		GVCoord arrowNeckMiddle;
		arrowNeckMiddle.lon = arrowHead.lon - (arrowTopLength - arrowEarthLength) * vecTop.x();
		arrowNeckMiddle.lat = arrowHead.lat - (arrowTopLength - arrowEarthLength) * vecTop.y();

		osg::Vec3d vec = osg::Vec3d(vtx.lon - arrowNeckMiddle.lon, vtx.lat - arrowNeckMiddle.lat, 0);
		double projectLength = vec * vecTopVertical;
		if(projectLength >= 0){
			projectLength = 0.3 * arrowNeckWidthHalf;
		}else{
			if(abs(projectLength) > 0.7 * arrowEarWidthHalf){
				projectLength = 0.7 * arrowEarWidthHalf;
			}else{
				projectLength = abs(projectLength);
			}
		}

		_controlPoints[0].lon = arrowNeckMiddle.lon - projectLength * vecTopVertical.x();
		_controlPoints[0].lat = arrowNeckMiddle.lat - projectLength * vecTopVertical.y();

		scale[1] = projectLength / arrowTopLength;
	}else if(idx == 1){
		double distanceTop = Distance_3(_controlPoints[1], arrowHead);
		osg::Vec3d vec = osg::Vec3d(arrowHead.lon - vtx.lon, arrowHead.lat - vtx.lat, 0);
		vec.normalize();
		_controlPoints[1].lon = arrowHead.lon - distanceTop * vec.x();
		_controlPoints[1].lat = arrowHead.lat - distanceTop * vec.y();

		vec.x() = distanceTop * vec.x();
		vec.y() = distanceTop * vec.y();
		arrowEarWidthHalf = abs(vec * vecTopVertical);

		_controlPoints[2].lon = _controlPoints[1].lon - arrowEarWidthHalf * vecTopVertical.x();
		_controlPoints[2].lat = _controlPoints[1].lat - arrowEarWidthHalf * vecTopVertical.y();

		double arrowTopLengthNew = Distance_3(_controlPoints[2], arrowHead);

		scale[0] = (arrowTopLengthNew / 2.0) / brockenLineLength;
		scale[1] = arrowNeckWidthHalf / arrowTopLengthNew;
		scale[2] = arrowEarWidthHalf / arrowTopLengthNew;
		scale[3] = (arrowEarthLength - (arrowTopLength - arrowTopLengthNew)) / arrowTopLengthNew;
		arrowTopLength = arrowTopLengthNew;
	}else if(idx == 2){
		osg::Vec3d vec = osg::Vec3d(arrowHead.lon - vtx.lon, arrowHead.lat - vtx.lat, 0);
		double projectLength = vec * vecTop;
		static double maxLength = arrowTopLength;

		if(projectLength > 0 && projectLength < maxLength)
		{
			_controlPoints[2].lon = arrowHead.lon - projectLength * vecTop.x();
			_controlPoints[2].lat = arrowHead.lat - projectLength * vecTop.y();

			arrowTopLength = projectLength;
			arrowNeckWidthHalf = arrowTopLength * scale[1];
			arrowEarWidthHalf = arrowTopLength * scale[2];
			arrowEarthLength = arrowTopLength * scale[3];

			scale[0] = (arrowTopLength / 2.0) / brockenLineLength;

			_controlPoints[1].lon = _controlPoints[2].lon + arrowEarWidthHalf * vecTopVertical.x();
			_controlPoints[1].lat = _controlPoints[2].lat + arrowEarWidthHalf * vecTopVertical.y();

			GVCoord arrowNeckMiddle;
			arrowNeckMiddle.lon = _controlPoints[2].lon + arrowEarthLength * vecTop.x();
			arrowNeckMiddle.lat = _controlPoints[2].lat + arrowEarthLength * vecTop.y();

			_controlPoints[0].lon = arrowNeckMiddle.lon - arrowNeckWidthHalf * vecTopVertical.x();
			_controlPoints[0].lat = arrowNeckMiddle.lat - arrowNeckWidthHalf * vecTopVertical.y();
		}
	}else{
		_controlPoints[idx] = vtx;

		GVCoord arrowHead = _controlPoints[_controlPoints.size()-1];
		GVCoord arrowTailLeft = _controlPoints[3];
		GVCoord arrowTailRight = _controlPoints[4];

		double brockenLineLength = Distance_3(GVCoord((arrowTailLeft.lon + arrowTailRight.lon)/2, (arrowTailLeft.lat + arrowTailRight.lat)/2, 0), arrowHead);

		if(_controlPoints.size() > 6)
		{
			brockenLineLength = Distance_3(_controlPoints[_controlPoints.size()-2], _controlPoints[_controlPoints.size()-1]);
		}

		GVCoord penultimatePointOnAxis;
		penultimatePointOnAxis.lon = (arrowTailLeft.lon + arrowTailRight.lon)/2;
		penultimatePointOnAxis.lat = (arrowTailLeft.lat + arrowTailRight.lat)/2;
		if(_controlPoints.size() > 6)
		{
			penultimatePointOnAxis = _controlPoints[_controlPoints.size()-2];
		}

		double arrowTopLength = 2 * brockenLineLength * scale[0];
		double arrowNeckWidthHalf = arrowTopLength * scale[1];
		double arrowEarWidthHalf = arrowTopLength * scale[2];
		double arrowEarthLength = arrowTopLength * scale[3];

		GVCoord arrowNeckRight;
		GVCoord arrowEarLeft;
		GVCoord arrowEarMiddle;

		osg::Vec3d vecTop = osg::Vec3d(arrowHead.lon - penultimatePointOnAxis.lon, arrowHead.lat - penultimatePointOnAxis.lat, 0);
		vecTop.normalize();

		arrowEarMiddle.lon = arrowHead.lon - arrowTopLength * vecTop.x();
		arrowEarMiddle.lat = arrowHead.lat - arrowTopLength * vecTop.y();

		osg::Vec3d vecTopVertical = osg::Vec3d(-vecTop.y(), vecTop.x(), 0);
		arrowEarLeft.lon = arrowEarMiddle.lon + arrowEarWidthHalf * vecTopVertical.x();
		arrowEarLeft.lat = arrowEarMiddle.lat + arrowEarWidthHalf * vecTopVertical.y();

		GVCoord arrowNeckMiddle;
		arrowNeckMiddle.lon = arrowHead.lon - (arrowTopLength - arrowEarthLength) * vecTop.x();
		arrowNeckMiddle.lat = arrowHead.lat - (arrowTopLength - arrowEarthLength) * vecTop.y();

		arrowNeckRight.lon = arrowNeckMiddle.lon - arrowNeckWidthHalf * vecTopVertical.x();
		arrowNeckRight.lat = arrowNeckMiddle.lat - arrowNeckWidthHalf * vecTopVertical.y();

		_controlPoints[0] = arrowNeckRight;
		_controlPoints[1] = arrowEarLeft;
		_controlPoints[2] = arrowEarMiddle;
	}
}

bool GV00003::toVertice(std::vector<GVCoord>& vtxBuffer, std::vector<int>* vtxBuffer2)
{
	if(_controlPoints.size() < 6)
		return false;

	GVCoord arrowHead = _controlPoints[_controlPoints.size()-1];
	GVCoord arrowTailLeft = _controlPoints[3];
	GVCoord arrowTailRight = _controlPoints[4];

	double brockenLineLength = Distance_3(GVCoord((arrowTailLeft.lon + arrowTailRight.lon)/2, (arrowTailLeft.lat + arrowTailRight.lat)/2, 0), arrowHead);

	if(_controlPoints.size() > 6)
	{
		brockenLineLength = Distance_3(_controlPoints[_controlPoints.size()-2], _controlPoints[_controlPoints.size()-1]);
	}

	GVCoord penultimatePointOnAxis;
	penultimatePointOnAxis.lon = (arrowTailLeft.lon + arrowTailRight.lon)/2;
	penultimatePointOnAxis.lat = (arrowTailLeft.lat + arrowTailRight.lat)/2;
	if(_controlPoints.size() > 6)
	{
		penultimatePointOnAxis = _controlPoints[_controlPoints.size()-2];
	}

	double arrowTopLength = 2 * brockenLineLength * scale[0];
	double arrowNeckWidthHalf = arrowTopLength * scale[1];
	double arrowEarWidthHalf = arrowTopLength * scale[2];
	double arrowEarthLength = arrowTopLength * scale[3];

	GVCoord arrowNeckRight, arrowNeckLeft;
	GVCoord arrowEarRight, arrowEarLeft;

	osg::Vec3d vecTop = osg::Vec3d(arrowHead.lon - penultimatePointOnAxis.lon, arrowHead.lat - penultimatePointOnAxis.lat, 0);
	vecTop.normalize();
	osg::Vec3d vecTopVertical = osg::Vec3d(-vecTop.y(), vecTop.x(), 0);

	arrowEarLeft = _controlPoints[1];
	arrowEarRight.lon = arrowEarLeft.lon - 2 * arrowEarWidthHalf * vecTopVertical.x();
	arrowEarRight.lat = arrowEarLeft.lat - 2 * arrowEarWidthHalf * vecTopVertical.y();

	arrowNeckRight = _controlPoints[0];
	arrowNeckLeft.lon = arrowNeckRight.lon + 2 * arrowNeckWidthHalf * vecTopVertical.x();
	arrowNeckLeft.lat = arrowNeckRight.lat + 2 * arrowNeckWidthHalf * vecTopVertical.y();

	double arrowTailWidth = Distance_3(arrowTailLeft, arrowTailRight);

	GVCoord arrowTailMiddle;
	arrowTailMiddle.lon = (arrowTailLeft.lon + arrowTailRight.lon)/2;
	arrowTailMiddle.lat = (arrowTailLeft.lat + arrowTailRight.lat)/2;

	double offset = arrowTailWidth/2.0 - arrowNeckWidthHalf;

	Bezier bezier;

	if(_controlPoints.size() == 6)
	{
		osg::Vec3d vecTail = osg::Vec3d(arrowTailLeft.lon - arrowTailRight.lon, arrowTailLeft.lat - arrowTailRight.lat, 0);
		vecTail.normalize();

		GVCoord topTailMiddle;
		topTailMiddle.lon = (arrowHead.lon + arrowTailMiddle.lon) / 2;
		topTailMiddle.lat = (arrowHead.lat + arrowTailMiddle.lat) / 2;

		GVCoord arrowBodyLeft, arrowBodyRight;
		arrowBodyLeft.lon = topTailMiddle.lon + (arrowNeckWidthHalf + 0.25 * offset) * vecTail.x();
		arrowBodyLeft.lat = topTailMiddle.lat + (arrowNeckWidthHalf + 0.25 * offset) * vecTail.y();
		arrowBodyRight.lon = topTailMiddle.lon - (arrowNeckWidthHalf + 0.25 * offset) * vecTail.x();
		arrowBodyRight.lat = topTailMiddle.lat - (arrowNeckWidthHalf + 0.25 * offset) * vecTail.y();

		std::vector<GVCoord> keyPoints;
		std::vector<GVCoord> bezierPoints;
		double t = (_controlPoints[3].lon - _controlPoints[5].lon) * (_controlPoints[4].lat - _controlPoints[5].lat) - (_controlPoints[4].lon - _controlPoints[5].lon) * (_controlPoints[3].lat - _controlPoints[5].lat);
		keyPoints.clear();
		bezierPoints.clear();
		if(t < 0)
		{
			keyPoints.push_back(arrowTailRight);
			keyPoints.push_back(arrowBodyRight);
		}
		else
		{
			keyPoints.push_back(arrowTailLeft);
			keyPoints.push_back(arrowBodyLeft);
		}
		keyPoints.push_back(arrowNeckLeft);

		bezier.getBezier(keyPoints, &bezierPoints);
		for(int i=0; i<bezierPoints.size(); i++)
			vtxBuffer.push_back(bezierPoints[i]);

		double t1 = 0.0;
		for(; t1<=1; t1+=0.02)
		{
			double x = (1-t1) * bezierPoints[bezierPoints.size()-1].lon + t1 * arrowEarLeft.lon;
			double y = (1-t1) * bezierPoints[bezierPoints.size()-1].lat + t1 * arrowEarLeft.lat;
			vtxBuffer.push_back(GVCoord(x, y, 0.0));
		}

		vtxBuffer.push_back(arrowEarLeft);

		t1 = 0.0;
		for(; t1<=1; t1+=0.02)
		{
			double x = (1-t1) * arrowEarLeft.lon + t1 * arrowHead.lon;
			double y = (1-t1) * arrowEarLeft.lat + t1 * arrowHead.lat;
			vtxBuffer.push_back(GVCoord(x, y, 0.0));
		}

		vtxBuffer.push_back(arrowHead);

		t1 = 0.0;
		for(; t1<=1; t1+=0.02)
		{
			double x = (1-t1) * arrowHead.lon + t1 * arrowEarRight.lon;
			double y = (1-t1) * arrowHead.lat + t1 * arrowEarRight.lat;
			vtxBuffer.push_back(GVCoord(x, y, 0.0));
		}

		vtxBuffer.push_back(arrowEarRight);

		keyPoints.clear();
		bezierPoints.clear();
		keyPoints.push_back(arrowNeckRight);
		if(t < 0)
		{
			keyPoints.push_back(arrowBodyLeft);
			keyPoints.push_back(arrowTailLeft);
		}
		else
		{
			keyPoints.push_back(arrowBodyRight);
			keyPoints.push_back(arrowTailRight);
		}
		bezier.getBezier(keyPoints, &bezierPoints);

		t1 = 0.0;
		for(; t1<=1; t1+=0.02)
		{
			double x = (1-t1) * arrowEarRight.lon + t1 * bezierPoints[0].lon;
			double y = (1-t1) * arrowEarRight.lat + t1 * bezierPoints[0].lat;
			vtxBuffer.push_back(GVCoord(x, y, 0.0));
		}

		for(int i=0; i<bezierPoints.size(); i++)
			vtxBuffer.push_back(bezierPoints[i]);

		vtxBuffer2->push_back(vtxBuffer.size());
	}
	else
	{
		double axisBrokenLineLength = Distance_3(arrowTailMiddle, _controlPoints[5]);
		axisBrokenLineLength += brokenLineDistance(5, _controlPoints.size()-1);

		double currentTopBrokenLineLength = 0;
		std::vector<GVCoord> keyPointsLeft, keyPointsRight;
		std::vector<GVCoord> bezierPointsLeft, bezierPointsRight;

		keyPointsLeft.clear();
		keyPointsRight.clear();
		keyPointsLeft.push_back(arrowNeckLeft);
		keyPointsRight.push_back(arrowNeckRight);

		for (int i=_controlPoints.size()-2; i>4; i--)
		{
			currentTopBrokenLineLength = brokenLineDistance(i, _controlPoints.size()-1);
			double rate = pow(currentTopBrokenLineLength / axisBrokenLineLength, 2);
			osg::Vec3d vecNear = osg::Vec3d(_controlPoints[i+1].lon - _controlPoints[i].lon, _controlPoints[i+1].lat - _controlPoints[i].lat, 0);
			vecNear.normalize();
			osg::Vec3d vecNearVertical = osg::Vec3d(-vecNear.y(), vecNear.x(), 0);
			GVCoord bodyLeft, bodyRight;
			bodyLeft.lon = _controlPoints[i].lon + (arrowNeckWidthHalf + rate * offset) * vecNearVertical.x();
			bodyLeft.lat = _controlPoints[i].lat + (arrowNeckWidthHalf + rate * offset) * vecNearVertical.y();
			bodyRight.lon = _controlPoints[i].lon - (arrowNeckWidthHalf + rate * offset) * vecNearVertical.x();
			bodyRight.lat = _controlPoints[i].lat - (arrowNeckWidthHalf + rate * offset) * vecNearVertical.y();
			keyPointsLeft.push_back(bodyLeft);
			keyPointsRight.push_back(bodyRight);
		}
		keyPointsLeft.push_back(arrowTailLeft);
		keyPointsRight.push_back(arrowTailRight);

		double t = (_controlPoints[3].lon - _controlPoints[5].lon) * (_controlPoints[4].lat - _controlPoints[5].lat) - (_controlPoints[4].lon - _controlPoints[5].lon) * (_controlPoints[3].lat - _controlPoints[5].lat);
		if(t < 0)
		{
			keyPointsLeft[keyPointsLeft.size()-1] = arrowTailRight;
			keyPointsRight[keyPointsRight.size()-1] = arrowTailLeft;
		}

		bezier.getBezier(keyPointsLeft, &bezierPointsLeft);
		for (int i=bezierPointsLeft.size()-1; i>=0; i--)
			vtxBuffer.push_back(bezierPointsLeft[i]);

		double t1 = 0.0;
		for (; t1<=1; t1+=0.02)
		{
			double x = (1-t1) * bezierPointsLeft[0].lon + t1 * arrowEarLeft.lon;
			double y = (1-t1) * bezierPointsLeft[0].lat + t1 * arrowEarLeft.lat;
			vtxBuffer.push_back(GVCoord(x, y, 0.0));
		}

		vtxBuffer.push_back(arrowEarLeft);

		t1 = 0;
		for (; t1<=1; t1+=0.02)
		{
			double x = (1-t1) * arrowEarLeft.lon + t1 * arrowHead.lon;
			double y = (1-t1) * arrowEarLeft.lat + t1 * arrowHead.lat;
			vtxBuffer.push_back(GVCoord(x, y, 0.0));
		}

		vtxBuffer.push_back(arrowHead);

		t1 = 0;
		for (; t1<=1; t1+=0.02)
		{
			double x = (1-t1) * arrowHead.lon + t1 * arrowEarRight.lon;
			double y = (1-t1) * arrowHead.lat + t1 * arrowEarRight.lat;
			vtxBuffer.push_back(GVCoord(x, y, 0.0));
		}

		vtxBuffer.push_back(arrowEarRight);

		bezier.getBezier(keyPointsRight, &bezierPointsRight);

		t1 = 0;
		for (; t1<=1; t1+=0.02)
		{
			double x = (1-t1) * arrowEarRight.lon + t1 * bezierPointsRight[0].lon;
			double y = (1-t1) * arrowEarRight.lat + t1 * bezierPointsRight[0].lat;
			vtxBuffer.push_back(GVCoord(x, y, 0.0));
		}

		for(int i=0; i<bezierPointsRight.size(); i++)
			vtxBuffer.push_back(bezierPointsRight[i]);

		vtxBuffer2->push_back(vtxBuffer.size());
	}

	return true;
}

double GV00003::brokenLineDistance(int start, int end) const
{
	double axisBrokenlineLength = 0;
	for(int i=start; i<end; i++)
	{
		axisBrokenlineLength += Distance_3(_controlPoints[i], _controlPoints[i+1]);
	}

	return axisBrokenlineLength;
}

腰子

#ifndef __GV00004_H__
#define __GV00004_H__

#include "GVGeometry.h"
#include "KidNey.h"

class GV00004 : public GVGeometry
{
public:
	GV00004();
	~GV00004();

	int getControlPointCount();
	void getControlPoints(std::vector<GVCoord>& vtxBuffer);
	GVCoord getControlPoint(int idx);
	void setControlPointsEx(std::vector<GVCoord>& vtxBuffer);
	void setControlPoints(std::vector<GVCoord>& vtxBuffer);
	void setControlPoint(int idx, const GVCoord& vtx);
	bool toVertice(std::vector<GVCoord>& vtxBuffer, std::vector<int>* vtxBuffer2);

private:
	std::vector<GVCoord> _controlPoints;
	std::vector<double> _s;

	KidNey kidney;
};

#endif //__GV00004_H__
#pragma once

#include "GV00004.h"

GV00004::GV00004()
{

}

GV00004::~GV00004()
{

}

int GV00004::getControlPointCount()
{
	return _controlPoints.size();
}

void GV00004::getControlPoints(std::vector<GVCoord>& vtxBuffer)
{
	if(_controlPoints.size() <= 0)
		return ;
	vtxBuffer = _controlPoints;
}

GVCoord GV00004::getControlPoint(int idx)
{
	if(idx >= 0 && idx < _controlPoints.size())
		return _controlPoints[idx];

	return GVCoord();
}

void GV00004::setControlPointsEx(std::vector<GVCoord> &vtxBuffer)
{
	_controlPoints = vtxBuffer;
}

void GV00004::setControlPoints(std::vector<GVCoord>& vtxBuffer)
{
	if (vtxBuffer.size() == 1)
	{
		return;
	}

	if(vtxBuffer.size() > 1)
	{
		kidney.setKidNeyConreolPoints(_controlPoints, vtxBuffer);
		kidney.getKidNeyScales(_s);
	}
}

void GV00004::setControlPoint(int idx, const GVCoord& vtx)
{
	int cpSize = _controlPoints.size();
	if(idx < 0 || idx >= cpSize)
		return ;
	
	kidney.setKidNeyConreolPoint(_controlPoints, idx, vtx, _s);

}

bool GV00004::toVertice(std::vector<GVCoord>& vtxBuffer, std::vector<int>* vtxBuffer2)
{
	if(_controlPoints.size() >= 12)
	{
		kidney.drawKidNey(_controlPoints);

		vtxBuffer = kidney.tmpBuffer;
		vtxBuffer2->push_back(kidney.tmpBuffer2[0]);
	}

	return true;
}

单线箭头

#ifndef __GV00005_H__
#define __GV00005_H__

#include "GVGeometry.h"
#include "Bezier.h"

class GV00005 : public GVGeometry
{
public:
	GV00005();
	~GV00005();

	int getControlPointCount();
	void getControlPoints(std::vector<GVCoord>& vtxBuffer);
	GVCoord getControlPoint(int idx);
	void setControlPointsEx(std::vector<GVCoord>& vtxBuffer);
	void setControlPoints(std::vector<GVCoord>& vtxBuffer);
	void setControlPoint(int idx, const GVCoord& vtx);
	bool toVertice(std::vector<GVCoord>& vtxBuffer, std::vector<int>* vtxBuffer2);

private:
	std::vector<GVCoord> _controlPoints;
};

#endif //__GV00005_H__
#pragma once

#include "GV00005.h"

static double getLen(GVCoord coord0, GVCoord coord1)
{
	return sqrt(pow(coord1.lon - coord0.lon, 2) + pow(coord1.lat - coord0.lat, 2));
}

static double cal_angle(const GVCoord &start_point, const GVCoord &end_point)
{
	double PI = osg::PI;
	double x01 = end_point.lon - start_point.lon;
	double y01 = end_point.lat - start_point.lat;
	double alpha;

	if(fabs(x01) <= 0.00001)
	{
		alpha = PI / 2.0;
		if(y01 < 0)
			alpha = -alpha + PI * 2.0;
	}
	else
		alpha = atan(y01 / x01);

	if(x01 < 0)
		alpha += PI;
	else if(y01 < 0)
		alpha += 2.0 * PI;

	return alpha;
}

GV00005::GV00005()
{

}

GV00005::~GV00005()
{

}

int GV00005::getControlPointCount()
{
	std::vector<GVCoord> controlPoints;
	getControlPoints(controlPoints);
	return controlPoints.size();
}

void GV00005::getControlPoints(std::vector<GVCoord>& vtxBuffer)
{
	if(_controlPoints.size() <= 0)
		return ;
	vtxBuffer = _controlPoints;
}

GVCoord GV00005::getControlPoint(int idx)
{
	if(idx >= 0 && idx < _controlPoints.size())
		return _controlPoints[idx];

	return GVCoord();
}

void GV00005::setControlPointsEx(std::vector<GVCoord> &vtxBuffer)
{
	_controlPoints = vtxBuffer;
}

void GV00005::setControlPoints(std::vector<GVCoord>& vtxBuffer)
{
	_controlPoints = vtxBuffer;
}

void GV00005::setControlPoint(int idx, const GVCoord& vtx)
{
	int cpSize = _controlPoints.size();
	if(idx < 0 || idx >= cpSize)
		return ;
	_controlPoints[idx] = vtx;

}

bool GV00005::toVertice(std::vector<GVCoord>& vtxBuffer, std::vector<int>* vtxBuffer2)
{
	if(_controlPoints.size() < 2)
		return true;

	Bezier bezier;
	std::vector<GVCoord> bezierPoints;
	bezier.getBezier(_controlPoints, &bezierPoints);

	vtxBuffer = bezierPoints;
	vtxBuffer2->push_back(bezierPoints.size());

	double length = 0.0;

	for(int i=0; i<bezierPoints.size()-1; i++)
	{
		length += sqrt((bezierPoints[i].lon - bezierPoints[i+1].lon) * (bezierPoints[i].lon - bezierPoints[i+1].lon)
			   + (bezierPoints[i].lat - bezierPoints[i+1].lat) * (bezierPoints[i].lat - bezierPoints[i+1].lat));
	}

	double r = length / 50.0;
	int position = bezierPoints.size();
	for(int i=bezierPoints.size()-1; i>0; i--)
	{
		if (getLen(bezierPoints[i], bezierPoints[bezierPoints.size()-1]) > r)
		{
			position = i;
			break;
		}
	}

	double angle1 = cal_angle(bezierPoints[position], _controlPoints[_controlPoints.size()-1]);
	GVCoord arrowP0, arrowP1, arrowP2;
	arrowP0.lon = bezierPoints[position].lon + r * 0.2 * cos(angle1 + osg::PI/2);
	arrowP0.lat = bezierPoints[position].lat + r * 0.2 * sin(angle1 + osg::PI/2);
	arrowP1.lon = bezierPoints[position].lon + r * 0.2 * cos(angle1 - osg::PI/2);
	arrowP1.lat = bezierPoints[position].lat + r * 0.2 * sin(angle1 - osg::PI/2);
	arrowP2 = _controlPoints[_controlPoints.size()-1];

	vtxBuffer.push_back(arrowP0);
	vtxBuffer.push_back(arrowP1);
	vtxBuffer.push_back(arrowP2);
	vtxBuffer.push_back(arrowP0);
	vtxBuffer2->push_back(4);

	return true;
}

车辆行进

#ifndef __GV00006_H__
#define __GV00006_H__

#include "GVGeometry.h"
#include "Bezier.h"
#include "ConfigControlPoints.h"

class GV00006 : public GVGeometry
{
public:
	GV00006();
	~GV00006();

	int getControlPointCount();
	void getControlPoints(std::vector<GVCoord>& vtxBuffer);
	GVCoord getControlPoint(int idx);
	void setControlPointsEx(std::vector<GVCoord>& vtxBuffer);
	void setControlPoints(std::vector<GVCoord>& vtxBuffer);
	void setControlPoint(int idx, const GVCoord& vtx);
	bool toVertice(std::vector<GVCoord>& vtxBuffer, std::vector<int>* vtxBuffer2);

private:
	std::vector<GVCoord> _controlPoints;
	double s0;

	Bezier bezier;
	ConfigControlPoints cfcp;
};

#endif //__GV00006_H__
#pragma once

#include "GV00006.h"

static double getLen(GVCoord coord0, GVCoord coord1)
{
	return sqrt(pow(coord1.lon - coord0.lon, 2) + pow(coord1.lat - coord0.lat, 2));
}

static double cal_angle(const GVCoord &start_point, const GVCoord &end_point)
{
	double PI = osg::PI;
	double x01 = end_point.lon - start_point.lon;
	double y01 = end_point.lat - start_point.lat;
	double alpha;

	if(fabs(x01) <= 0.00001)
	{
		alpha = PI / 2.0;
		if(y01 < 0)
			alpha = -alpha + PI * 2.0;
	}
	else
		alpha = atan(y01 / x01);

	if(x01 < 0)
		alpha += PI;
	else if(y01 < 0)
		alpha += 2.0 * PI;

	return alpha;
}

GV00006::GV00006()
{
	s0 = 0.5;
}

GV00006::~GV00006()
{

}

int GV00006::getControlPointCount()
{
	std::vector<GVCoord> controlPoints;
	getControlPoints(controlPoints);
	return controlPoints.size();
}

void GV00006::getControlPoints(std::vector<GVCoord>& vtxBuffer)
{
	if(_controlPoints.size() <= 0)
		return ;
	vtxBuffer = _controlPoints;
}

GVCoord GV00006::getControlPoint(int idx)
{
	if(idx >= 0 && idx < _controlPoints.size())
		return _controlPoints[idx];

	return GVCoord();
}

void GV00006::setControlPointsEx(std::vector<GVCoord> &vtxBuffer)
{
	cfcp.configControlPoints(vtxBuffer);
	_controlPoints = vtxBuffer;
}

void GV00006::setControlPoints(std::vector<GVCoord>& vtxBuffer)
{
	cfcp.configControlPoints(vtxBuffer);

	if (vtxBuffer.size() < 2)
	{
		return;
	}

	_controlPoints = vtxBuffer;

	std::vector<GVCoord> bezierPoints;
	bezier.getBezier(_controlPoints, &bezierPoints);

	double len1 = 0.0;
	for (int i=1; i<bezierPoints.size(); i++)
	{
		len1 += getLen(bezierPoints[i], bezierPoints[i-1]);
	}

	double tempLen = 0.0;
	int num = 0;
	for (int i=1; i<bezierPoints.size(); i++)
	{
		tempLen += getLen(bezierPoints[i], bezierPoints[i-1]);
		if (tempLen >= (len1 * s0))
		{
			num = i;
			break;
		}
	}
	_controlPoints.push_back(bezierPoints[num]);
}

void GV00006::setControlPoint(int idx, const GVCoord& vtx)
{
	int cpSize = _controlPoints.size();
	if(idx < 0 || idx >= cpSize)
		return ;

	GVCoord modify = vtx;
	cfcp.configControlPoints(modify, _controlPoints);

	if (idx >= 0 && idx <= _controlPoints.size()-2)
	{
		_controlPoints[idx] = modify;

		std::vector<GVCoord> myControlPoints;
		for (int i=0; i<_controlPoints.size()-1; i++)
		{
			myControlPoints.push_back(_controlPoints[i]);
		}

		std::vector<GVCoord> bezierPoints;
		bezier.getBezier(myControlPoints, &bezierPoints);

		double len1 = 0.0;
		for (int i=1; i<bezierPoints.size(); i++)
		{
			len1 += getLen(bezierPoints[i], bezierPoints[i-1]);
		}

		double tempLen = 0.0;
		int num = 0;
		for (int i=1; i<bezierPoints.size(); i++)
		{
			tempLen += getLen(bezierPoints[i], bezierPoints[i-1]);
			if (tempLen >= (len1 * s0))
			{
				num = i;
				break;
			}
		}
		_controlPoints[cpSize-1] = bezierPoints[num];
	}
	
	if (idx == _controlPoints.size()-1)
	{
		std::vector<GVCoord> myControlPoints;
		for (int i=0; i<_controlPoints.size()-1; i++)
		{
			myControlPoints.push_back(_controlPoints[i]);
		}

		std::vector<GVCoord> tempBezierPoints;
		bezier.getBezier(myControlPoints, &tempBezierPoints);

		double length = 0.0;
		for (int k=1; k<tempBezierPoints.size(); k++)
		{
			length += getLen(tempBezierPoints[k], tempBezierPoints[k-1]);
		}

		double min = getLen(tempBezierPoints[0], modify);
		int minPoint = 0;
		for (int i=0; i<tempBezierPoints.size(); i++)
		{
			if (getLen(tempBezierPoints[i], modify) < min)
			{
				min = getLen(tempBezierPoints[i], modify);
				minPoint = i;
			}
		}
		_controlPoints[idx] = tempBezierPoints[minPoint];

		double pointLength = 0.0;
		for (int i=1; i<=minPoint; i++)
		{
			pointLength += getLen(tempBezierPoints[i], tempBezierPoints[i-1]);
		}
		s0 = pointLength / length;
	}

}

bool GV00006::toVertice(std::vector<GVCoord>& vtxBuffer, std::vector<int>* vtxBuffer2)
{
	if(_controlPoints.size() < 3)
		return true;

	std::vector<GVCoord> bezierPoints;
	std::vector<GVCoord> myControlPoints;

	for (int i=0; i<_controlPoints.size()-1; i++)
	{
		myControlPoints.push_back(_controlPoints[i]);
	}

	bezier.getBezier(myControlPoints, &bezierPoints);

	double length = 0.0;

	for(int i=0; i<bezierPoints.size()-1; i++)
	{
		length += sqrt((bezierPoints[i].lon - bezierPoints[i+1].lon) * (bezierPoints[i].lon - bezierPoints[i+1].lon)
			+ (bezierPoints[i].lat - bezierPoints[i+1].lat) * (bezierPoints[i].lat - bezierPoints[i+1].lat));
	}

	double r = length / 50.0;

	int start = 0;
	int end = bezierPoints.size() - 1;
	for(int i=0; i<bezierPoints.size(); i++)
	{
		if (getLen(bezierPoints[i], _controlPoints[_controlPoints.size()-1]) < r)
		{
			start = i;
			break;
		}
	}

	for(int i=start; i<bezierPoints.size(); i++)
	{
		if (getLen(bezierPoints[i], _controlPoints[_controlPoints.size()-1]) > r)
		{
			end = i;
			break;
		}
	}

	for (int i=0; i<=start; i++)
	{
		vtxBuffer.push_back(bezierPoints[i]);
	}
	vtxBuffer2->push_back(start+1);

	double angle2 = cal_angle(bezierPoints[start], bezierPoints[end]);
	double distance = getLen(bezierPoints[start], bezierPoints[end]);
	GVCoord p0, p1, p2, p3, p4;
	p0.lon = bezierPoints[start].lon + distance * 0.35 * cos(angle2 + osg::PI/2);
	p0.lat = bezierPoints[start].lat + distance * 0.35 * sin(angle2 + osg::PI/2);
	p1.lon = bezierPoints[start].lon + distance * 0.15 * cos(angle2 - osg::PI/2);
	p1.lat = bezierPoints[start].lat + distance * 0.15 * sin(angle2 - osg::PI/2);
	p2.lon = p1.lon + distance * cos(angle2);
	p2.lat = p1.lat + distance * sin(angle2);
	p3.lon = p2.lon + distance * 0.25 * cos(angle2 + osg::PI/2);
	p3.lat = p2.lat + distance * 0.25 * sin(angle2 + osg::PI/2);
	p4.lon = p0.lon + distance * 0.7 * cos(angle2);
	p4.lat = p0.lat + distance * 0.7 * sin(angle2);

	vtxBuffer.push_back(p0);
	vtxBuffer.push_back(p1);
	vtxBuffer.push_back(p2);
	vtxBuffer.push_back(p3);
	vtxBuffer.push_back(p4);
	vtxBuffer.push_back(p0);
	vtxBuffer2->push_back(6);

	int position = bezierPoints.size();
	for(int i=bezierPoints.size()-1; i>0; i--)
	{
		if (getLen(bezierPoints[i], bezierPoints[bezierPoints.size()-1]) > r)
		{
			position = i;
			break;
		}
	}

	double angle1 = cal_angle(bezierPoints[position], _controlPoints[_controlPoints.size()-2]);
	GVCoord arrowP0, arrowP1, arrowP2;
	arrowP0.lon = bezierPoints[position].lon + r * 0.2 * cos(angle1 + osg::PI/2);
	arrowP0.lat = bezierPoints[position].lat + r * 0.2 * sin(angle1 + osg::PI/2);
	arrowP1.lon = bezierPoints[position].lon + r * 0.2 * cos(angle1 - osg::PI/2);
	arrowP1.lat = bezierPoints[position].lat + r * 0.2 * sin(angle1 - osg::PI/2);
	arrowP2 = _controlPoints[_controlPoints.size()-2];

	vtxBuffer.push_back(arrowP0);
	vtxBuffer.push_back(arrowP1);
	vtxBuffer.push_back(arrowP2);
	vtxBuffer.push_back(arrowP0);
	vtxBuffer2->push_back(4);

	for (int i=end; i<=position; i++)
	{
		vtxBuffer.push_back(bezierPoints[i]);
	}
	vtxBuffer2->push_back(position-end+1);

	return true;
}

源码地址:https://github.com/zengjunyu/osgEarth_Annotation/tree/master

修改功能:https://download.csdn.net/download/sailingw/20340551 

  • 2
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 16
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

海亲王

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

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

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

打赏作者

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

抵扣说明:

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

余额充值