osgEarth3.2+qt5.14+osg3.6.5
#ifndef CIRCLEDRAWER_H
#define CIRCLEDRAWER_H
#include <osgEarth/MapNode>
#include <osgEarth/Geometry>
#include <osgEarth/GeoMath>
#include <osgEarth/CircleNode>
#include <osgEarth/Style>
#include <osgViewer/Viewer>
#include <osgGA/GUIEventHandler>
#include <vector>
class CircleDrawer: public osgGA::GUIEventHandler
{
public:
CircleDrawer( osg::ref_ptr<osgEarth::MapNode> mapNode);
~CircleDrawer();
void removeSelectCircle(osg::ref_ptr<osg::Node> node);
void removeCircle();
void removeAllCircles();
void createPieSegment();
void createCircle(osg::Vec3d position,double radiusCir);
//获取绘制状态
bool getIsDrawCir();
//设置绘制状态
void setIsDrawCir(bool isDraw);
//事件处理
bool handle(const osgGA::GUIEventAdapter &ea,osgGA::GUIActionAdapter &aa);
private:
osg::ref_ptr<osgEarth::MapNode> _mapNode;
osg::ref_ptr<osgEarth::CircleNode> _circleNode;
osgEarth::Style _circleStyle; // 样式
bool isDrawCir; //开启绘制圆
bool isDeletDrawCir; //开启删除圆
double radiusCir; //圆半径
osg::NodePath nodePaths;
std::vector<osg::ref_ptr<osgEarth::CircleNode>> _circleNodes; // 保存所有绘制的矩形
};
#endif // CIRCLEDRAWER_H
#include "CircleDrawer.h"
CircleDrawer::CircleDrawer(osg::ref_ptr<osgEarth::MapNode> mapNode)
:_mapNode(mapNode)
,_circleNode(nullptr)
,isDrawCir(false)
,isDeletDrawCir(true)
,radiusCir(500.0)
{
_circleStyle.getOrCreate<osgEarth::PolygonSymbol>()->fill()->color() = osgEarth::Color(osgEarth::Color::Yellow, 0.25); // 黄色半透明
nodePaths.push_back(mapNode);
}
CircleDrawer::~CircleDrawer()
{
}
void CircleDrawer::removeSelectCircle(osg::ref_ptr<osg::Node> node)
{
_mapNode->removeChild(node); // 从地图中移除
}
void CircleDrawer::removeCircle()
{
if (!_circleNodes.empty()) {
osg::ref_ptr<osgEarth::CircleNode> lastNode = _circleNodes.back();
_mapNode->removeChild(lastNode); // 从地图中移除
_circleNodes.pop_back(); // 从列表中移除
}
}
void CircleDrawer::removeAllCircles()
{
for (auto& node : _circleNodes) {
_mapNode->removeChild(node); // 从地图中移除
}
_circleNodes.clear(); // 清空列表
}
bool CircleDrawer::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
{
if (!_mapNode)
return false;
osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer *>(&aa);
if (!viewer)
return false;
if (!isDrawCir)
return false;
switch (ea.getEventType()) {
case osgGA::GUIEventAdapter::PUSH: {
switch (ea.getButton()) {
case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON: {
osgUtil::LineSegmentIntersector::Intersections intersections;
if (viewer->computeIntersections(ea.getX(), ea.getY(), nodePaths, intersections)) {
const osgUtil::LineSegmentIntersector::Intersection &intersection = *intersections.begin();
osg::Vec3d worldPoint = intersection.getWorldIntersectPoint();
const osgEarth::SpatialReference *mapSRS = _mapNode->getMapSRS();
const osgEarth::SpatialReference *geoSRS = osgEarth::SpatialReference::get("wgs84");
osgEarth::GeoPoint geoPoint;
geoPoint.fromWorld(mapSRS, worldPoint);
osgEarth::GeoPoint wgs84Point;
geoPoint.transform(geoSRS, wgs84Point);
double lon = wgs84Point.x();
double lat = wgs84Point.y();
double height = wgs84Point.z();
osgEarth::GeoPoint position(geoSRS, lon, lat, height, osgEarth::AltitudeMode::ALTMODE_RELATIVE);
osg::ref_ptr<osgEarth::CircleNode> circleNode = new osgEarth::CircleNode();
circleNode->set(position, osgEarth::Distance(radiusCir, osgEarth::Units::METERS), _circleStyle);
circleNode->setName("CirCle");
_circleNode = circleNode;
_circleNodes.push_back(_circleNode);
_mapNode->addChild(_circleNode);
}
break;
}
case osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON: {
osg::ref_ptr<osg::Node> node = NULL;
osgUtil::LineSegmentIntersector::Intersections intersections;
if (viewer->computeIntersections(ea.getX(), ea.getY(), nodePaths, intersections)) {
for (const auto &intersection : intersections) {
for (auto i : intersection.nodePath) {
if (i->getName().find("CirCle") != std::string::npos) {
node = i;
break;
}
}
if (node)
break;
}
}
if (node) {
removeSelectCircle(node);
}
break;
}
}
break;
}
case osgGA::GUIEventAdapter::KEYDOWN: {
switch (ea.getKey()) {
case osgGA::GUIEventAdapter::KEY_Delete:
removeCircle();
break;
case osgGA::GUIEventAdapter::KEY_BackSpace:
removeAllCircles();
break;
default:
std::cerr << "Warning: Unhandled mouse button event." << std::endl;
break;
}
break;
}
default:
break;
}
return false;
}
//绘制扇形的例子
void CircleDrawer::createPieSegment()
{
// 定义圆的样式
osgEarth::Style circleStyle;
osgEarth::LineSymbol* line = circleStyle.getOrCreate<osgEarth::LineSymbol>();
line->stroke()->color() = osgEarth::Color::Yellow; // 设置边框颜色为黄色
line->stroke()->width() = 2.0f; // 设置边框宽度
line->stroke()->smooth() = true; // 抗锯齿
// (配置样式细节, 例如填充颜色、边框等)
osgEarth::PolygonSymbol* polygon = circleStyle.getOrCreate<osgEarth::PolygonSymbol>();
polygon->fill()->color() = osgEarth::Color(1.0, 0.0, 0.0, 0.5); // 半透明红色
// 定义圆心位置
const osgEarth::SpatialReference* geoSRS = osgEarth::SpatialReference::get("wgs84"); // WGS84 地理坐标系
osgEarth::GeoPoint position(
geoSRS,
109.002, // 经度
23.519, // 纬度
60, // 高度
osgEarth::AltitudeMode::ALTMODE_RELATIVE
);
// 定义半径
osgEarth::Distance radius(100, osgEarth::Units::METERS);
// 创建 CircleNode
osgEarth::CircleNode* circleNode = new osgEarth::CircleNode();
circleNode->set(
position, // 圆心位置
radius, // 半径
circleStyle, // 样式
osgEarth::Angle(0.0, osgEarth::Units::DEGREES), // 起始角度
osgEarth::Angle(45.0, osgEarth::Units::DEGREES), // 终止角度
true // 是否为扇形
);
// 将 CircleNode 添加到地图节点
_mapNode->addChild(circleNode);
}
//绘制圆
void CircleDrawer::createCircle(osg::Vec3d position,double radiusCir)
{
osgEarth::Style circleStyle;
osgEarth::PolygonSymbol* polygon = circleStyle.getOrCreate<osgEarth::PolygonSymbol>();
polygon->fill()->color() = osgEarth::Color(osgEarth::Color::Yellow, 0.25);
const osgEarth::SpatialReference* geoSRS = osgEarth::SpatialReference::get("wgs84"); // WGS84 地理坐标系
osgEarth::GeoPoint positions(geoSRS, position.x(), position.y(), 80, osgEarth::AltitudeMode::ALTMODE_RELATIVE);
osg::ref_ptr<osgEarth::CircleNode> circleNode = new osgEarth::CircleNode();
circleNode->set(positions,osgEarth::Distance(radiusCir, osgEarth::Units::METERS),circleStyle);
circleNode->setName("CirCle");
_circleNode=circleNode;
// 保存到列表中
_circleNodes.push_back(_circleNode);
_mapNode->addChild(_circleNode);
}
bool CircleDrawer::getIsDrawCir()
{
return isDrawCir;
}
void CircleDrawer::setIsDrawCir(bool isDraw)
{
isDrawCir=isDraw;
}