OSG绘制空间凹多边形并计算其面积

目录

  • 1. 思路

    • 1) 多边形分格化
    • 2) 几何图元遍历
  • 2. 实现
  • 3. 参考

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多边形分格化

原文地址:https://www.cnblogs.com/charlee44/p/11145898.html

时间: 2024-08-06 04:24:43

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

用python计算菌斑面积

研究生课题需要所以写了一个: import numpy as np from PIL import Image import skimage.io #把图片二值化 def binaryzation(pic_id, new_id): img = Image.open(pic_id) img = img.convert("L") imgs = skimage.io.imread(pic_id) ttt = 1.4 * np.mean(imgs) WHITE, BLACK = 255, 0

计算三角形面积

double numberone, double numberTwo, double numberThree//三条边,注意两边之和大于第三编double doubleS = 0;            double doubleArea = 0;            doubleS = (numberone + numberTwo + numberThree) / 2;            doubleArea = Math.Sqrt(doubleS * (doubleS - number

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

ArcGIS中有多种方法可计算出图斑面积,本文总结了四种方法,是否可堪称史上最全? 1.计算几何 本人认为这是最适合非专业人士的方法,直接利用ArcGIS中的计算几何功能进行计算. a.首先添加一double类型字段,用来存储面积数值. b.执行计算几何操作 在随后的对话框里选择对应的属性即可. 2.字段计算器 字段计算器是一种较高级的用法,在计算计算器中可以编辑个性化个脚本代码(VB Script 或者 Python),进行一些复杂的计算.计算图斑面积是其中最简单的应用之一. Python脚本

创建一个接口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类另有一返回值boolean型方法isStar: 在main方法里创建一个Vector,根据随机数的不同向其中加入Shape的不同子类对象(如是1,生成Circle对象: 如是2,生成Rectangle对象:如是3,生成Star对象).然后将Vector中元素依次取出,判断其是否为Star类.如是返回其

已知三点计算三角形面积

1.#转化为通过三边计算三角形面积 1 import math 2 def cal_area(p1,p2,p3): 9 a = float(math.sqrt((p2[0]-p3[0])*(p2[0]-p3[0])+(p2[1]-p3[1])*(p2[1]-p3[1]))) 10 b = float(math.sqrt((p1[0]-p3[0])*(p1[0]-p3[0])+(p1[1]-p3[1])*(p1[1]-p3[1]))) 11 c = float(math.sqrt((p1[0]-p

计算矩形面积

描述用户输入矩形的长和宽,计算其面积并输出,结果四舍五入,保留2位小数.???????????????????????????????????????????????????????????????????????????????????????????????? 输入格式第一行输入一个数字,代表矩形的长????????????????????????????????????????????????????????????????????????????????????????????????

Java入门:基础算法之计算三角形面积

本部分介绍如何计算三角形面积. /** * @author: 理工云课堂 * @description: 程序计算三角形的面积.三角形的底和高由用户输入 */ import java.util.Scanner; class AreaTriangleDemo { public static void main(String args[]) { Scanner scanner = new Scanner(System.in); System.out.println("Enter the width

使用R进行分类时,ROC的绘制和AUC的计算

在之前的这篇日志中,我简单介绍了使用R进行Logistic Regression时,Recall,Precision,TPR,FPR等等的计算,但是如果依照这种方法绘制ROC曲线(关于ROC和AUC的概念,网上有很多介绍,例如:http://beader.me/2013/12/15/auc-roc/ )就太过于麻烦了,需要手动调整分类阈值.其实R也提供了最基本的ROC曲线绘制的工具包(Package),结合这篇日志,我也同时介绍一下R Package的安装和学习方法: 在这里:http://ww

c# 磁盘空间计算 和 目录空间 、 文件大小 计算

namespace CommonLibrary.SystemUtils { /// <summary> /// 表示存储空间大小计量单位 /// </summary> public enum SizeUnitMode { /// <summary> /// 字节 /// </summary> Byte, /// <summary> /// 千字节 /// </summary> KiloByte, /// <summary>