1. 思路

这个问题其实涉及到OSG中的两个问题:多边形分格化和几何图元遍历。

1) 多边形分格化

在OpenGL/OSG中,由于效率的原因,默认是直接显示的简单的凸多边形。如果直接强行显示凹多边形,渲染结果是不确定的。所以对于复杂的凹多边形,需要将其分解成简单的凸多边形,这个过程就是多边形分格化。在OSG中是通过osgUtil::Tessellator类来实现多边形分格化的。

2) 几何图元遍历

对于二维的凹多边形,可以有办法计算其面积。但是对于三维空间的凹多边形,计算其面积却很困难。这是因为三维空间凹多边形甚至都有可能不是共面的。而我们知道,任何复杂的图形都是通过分解成三角形进行绘制的,只要获取分解成的三角形,计算其面积并相加(空间三角形的面积计算比较简单),就可以得到凹多边形的总面积。

在OSG中提供了一个用来访问图元的类:osg::PrimitiveFunctor,其继承类osg::TriangleFunctor可以获取其三角面图元。几何体类osg::Geometry提供了遍历几何图元的访问器接口。

2. 实现

其具体实现如下。注意在查找多边形分格化的资料的时候,提到了环绕数和环绕规则的概念。在OSG里面也有相应的参数设置。可惜这一段没有看明白,只能根据仿照例子来设置了。

#include <iostream>
#include <Windows.h> #include <osgViewer/Viewer>
#include <osgDB/ReadFile> #include <osgUtil/Tessellator>
#include <osg/TriangleFunctor> using namespace std;
using namespace osg; osg::ref_ptr<osg::Geometry> redPolygon; //计算空间三角形的面积
double CalTriangleArea(const osg::Vec3& a, const osg::Vec3& b, const osg::Vec3& c)
{
double area = 0; double side[3];//存储三条边的长度; side[0] = sqrt(pow(a.x() - b.x(), 2) + pow(a.y() - b.y(), 2) + pow(a.z() - b.z(), 2));
side[1] = sqrt(pow(a.x() - c.x(), 2) + pow(a.y() - c.y(), 2) + pow(a.z() - c.z(), 2));
side[2] = sqrt(pow(c.x() - b.x(), 2) + pow(c.y() - b.y(), 2) + pow(c.z() - b.z(), 2)); //不能构成三角形;
if (side[0] + side[1] <= side[2] || side[0] + side[2] <= side[1] || side[1] + side[2] <= side[0]) return area; //利用海伦公式。s=sqr(p*(p-a)(p-b)(p-c));
double p = (side[0] + side[1] + side[2]) / 2; //半周长;
area = sqrt(p*(p - side[0])*(p - side[1])*(p - side[2])); return area;
} //三角面片访问器
struct TriangleAreaFunctor
{
TriangleAreaFunctor()
{
sumArea = new double;
} ~TriangleAreaFunctor()
{
if (sumArea)
{
delete sumArea;
sumArea = nullptr;
}
} void operator() (const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3) const
{
*sumArea = *sumArea + CalTriangleArea(v1, v2, v3);
} double GetSumArea()
{
return *sumArea;
} protected:
double *sumArea = nullptr;
}; //
ref_ptr<Geode> createPolygon()
{
const float wall[6][3] =
{
{ -115.54f, 70.873f, -118.952f},
{ -111.516f, 70.7189f, -71.8492f },
{ -88.5345f, 70.8667f, -86.3565f },
{ -64.9495f, 71.8231f, -53.6525f },
{ -52.9755f, 69.028f, -129.093f },
{ -89.2272f, 71.1478f, -105.434f }
}; //
ref_ptr<Geode> geode = new Geode();
redPolygon = new osg::Geometry; //
osg::ref_ptr<osg::Vec3Array> redVex = new osg::Vec3Array;
redPolygon->setVertexArray(redVex); for (int i = 0; i< 6; i++)
{
redVex->push_back(osg::Vec3(wall[i][0], wall[i][1], wall[i][2]));
} redPolygon->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, 6)); //设置颜色数组
osg::ref_ptr<osg::Vec4Array> redColors = new osg::Vec4Array;
redColors->push_back(osg::Vec4(1.0, 0.0, 0.0, 0.5));
redPolygon->setColorArray(redColors);
redColors->setBinding(osg::Array::BIND_PER_PRIMITIVE_SET); //如果需要透明,则加入这个
redPolygon->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
redPolygon->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); //创建分格化对象(支持凹多边形)
osg::ref_ptr<osgUtil::Tessellator> tscx = new osgUtil::Tessellator;
//设置分格类型为几何体
tscx->setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
//设置只显示轮廓线为false。设置环绕规则,这里不太懂
tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_ODD);
//使用分格化
tscx->retessellatePolygons(*(redPolygon.get())); geode->addDrawable(redPolygon); return geode;
} int main()
{
//
ref_ptr<Group> root = new Group();
root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); //关闭默认光照
root->addChild(createPolygon()); //
osgViewer::Viewer viewer;
viewer.setSceneData(root);
viewer.setUpViewInWindow(100, 100, 800, 600);
viewer.run(); osg::TriangleFunctor<TriangleAreaFunctor> tf;
redPolygon->accept(tf);
cout << "面积:" << tf.GetSumArea() << endl; return 0;
}

渲染结果如下:

3. 参考

  1. OSG学习笔记(三)之如何将非三角面转换为三角面
  2. osg几何体的图元的遍历
  3. OSG计算并绘制模型中每一个三角面片的法向量
  4. OSG(OpenSceneGraph)基础学习9:OSG多边形分格化

OSG绘制空间凹多边形并计算其面积的更多相关文章

  1. opencv学习之路(27)、轮廓查找与绘制(六)——外接圆、椭圆拟合、逼近多边形曲线、计算轮廓面积及长度、提取不规则轮廓

    一.最小外接圆 #include "opencv2/opencv.hpp" #include<iostream> using namespace std; using ...

  2. google map 计算地图面积方法

    花了几个小时把js的google计算地图面积的算法改成了c# 的. class Program { static void Main(string[] args) { // a = new qq.ma ...

  3. ArcGIS应用——四种计算图斑面积的方法

    ArcGIS中有多种方法可计算出图斑面积,本文总结了四种方法,是否可堪称史上最全? 1.计算几何 本人认为这是最适合非专业人士的方法,直接利用ArcGIS中的计算几何功能进行计算. a.首先添加一do ...

  4. OpenJudge计算概论-计算三角形面积【海伦公式】

    /*============================================== 计算三角形面积 总时间限制: 1000ms 内存限制: 65536kB 描述 平面上有一个三角形,它的 ...

  5. 有一台机器,上面有m个储存空间。然后有n个请求,第i个请求计算时需要占 R[i]个空间,储存计算结果则需要占据O[i]个空间(据O[i]个空间(其中O[i]<R[i])。问怎么安排这n个请求的顺序,使

    有一台机器,上面有m个储存空间.然后有n个请求,第i个请求计算时需要占 R[i]个空间,储存计算结果则需要占据O[i]个空间(据O[i]个空间(其中O[i]<R[i]).问怎么安排这n个请求的顺 ...

  6. [math] 绘制空间几何体的直观图

    这么多年,一直凭着从天而降的神来之灵感画着立体图. 而今才知道在二维平面上绘制空间几何体的直观图也是有方法的.叫做“画法几何” 1. 斜二测图 就是倾斜y轴,使y轴与x轴成45度的夹角.见: http ...

  7. 计算平面面积和斜面面积-ArcGIS案例学习笔记

    计算平面面积和斜面面积-ArcGIS案例学习笔记 联系方式:谢老师,135_4855_4328,xiexiaokui#139.com 数据:实验数据\Chp8\Ex5\demTif.tif 平面面积= ...

  8. 计算概论(A)/基础编程练习2(8题)/3:计算三角形面积

    #include<stdio.h> #include<math.h> int main() { // 声明三角形的三个顶点坐标和面积 float x1, y1, x2, y2, ...

  9. 创建一个接口Shape,其中有抽象方法area,类Circle 、Rectangle实现area方法计算其面积并返回。又有Star实现Shape的area方法,其返回值是0,Star类另有一返回值boolean型方法isStar;在main方法里创建一个Vector,根据随机数的不同向其中加入Shape的不同子类对象(如是1,生成Circle对象;如是2,生成Rectangle对象;如是3,生成S

    题目补充: 创建一个接口Shape,其中有抽象方法area,类Circle .Rectangle实现area方法计算其面积并返回. 又有Star实现Shape的area方法,其返回值是0,Star类另 ...

随机推荐

  1. 转:Spring Boot启动过程

    之前在排查一个线上问题时,不得不仔细跑了很多遍Spring Boot的代码,于是整理一下,我用的是1.4.3.RELEASE. 首先,普通的入口,这没什么好说的,我就随便贴贴代码了: SpringAp ...

  2. 华为OSPF与ACL综合应用

    一. 实验拓扑图 二.实验要求 1.企业内网运行OSPF路由协议,区域规划如图所示:2.财务和研发所在的区域不受其他区域链路不稳定性影响:3.AR1.AR2.AR3只允许被IT登录管理:4.YF和CW ...

  3. python做单因素方差分析

    方差分析的主要功能就是验证两组样本,或者两组以上的样本均值是否有显著性差异,即均值是否一样. 这里有两个大点需要注意:①方差分析的原假设是:样本不存在显著性差异(即,均值完全相等):②两样本数据无交互 ...

  4. Ceph 块存储

    任何普通的linux主机都可以充当ceph客户机,客户机通过网络与ceph存储集群交互以存储或检索用户数据.Ceph RBD支持已经添加到linux主线内核中,从2.6.34以及以后版本开始. === ...

  5. 【系列专题】JavaScript设计模式 重温系列(9篇全)

    JavaScript 设计模式 [JS]164-JavaScript设计模式--单体模式 [JS]165-JavaScript设计模式--工厂模式 [JS]166-JavaScript设计模式--迭代 ...

  6. sqlserver 行转列、字符串行转列、自动生产行转列脚本

    行转列,老生常谈的问题.这里总结一下网上的方法. 1.生成测试数据: CREATE TABLE human( name ), --姓名 norm ), --指标 score INT , --分数 gr ...

  7. .NET Core 3终结点不能映射控制器

    今天在学.net core的时候发现了一个问题,终结点死活映射不了自己添加的控制器,后经过研究发现解决方法,可能这个问题不应该叫做问题,可是我是初学者,就把这个问题给拎出来.本人开发环境 VS2019 ...

  8. 简单介绍托管执行和 CLI

    目录 CIL 和 ILDASM 查看 myApp.dll 的 CIL 输出 使用 ILSpy 查看 myApp.dll 反编译后的代码 处理器不能直接解释程序集.程序集用的是另一种语言,即公共中间语言 ...

  9. Nginx配置实例-动静分离实例:搭建静态资源服务器

    场景 Nginx入门简介和反向代理.负载均衡.动静分离理解: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/102790862 U ...

  10. confluence 挖矿木马应急响应

    最近遇到一台confluence wiki主机被挖矿,收到CPU 告警异常之后,登录查看,进行分析. top c 命令查看,果然CPU 已经资源已经被吃完了.. 看到用户是confluence,100 ...