【问题标题】:Fortran - Point in STLFortran - STL 中的点
【发布时间】:2014-09-18 21:12:34
【问题描述】:

我正在尝试用 Fortran 中的点填充 STL 文件。我已经编写了一个基本代码,但它不起作用。

我的方法是使用随机数生成器来生成一个点。然后我将此点标准化为 STL 边界框的尺寸。

然后我抛出 STL 中第一个三角形的“z”坐标。我检查随机点是否具有第一个三角形的“x”和“y”坐标的最大值和最小值。如果是这样,我将随机点垂直投影到三角形平面上,并计算它与平面相交的“z”值。然后我检查随机点的 z 值是否小于投影点的值(射线投射)。如果是,我将最初设置为零的计数器加一。

我对 STL 中的每个三角形都这样做。如果计数器是偶数则随机点在体积外,如果是奇数则随机点在体积内并存储。

然后我生成一个新的随机点并重新开始。我在下面包含了重要的代码。为篇幅道歉(为了便于阅读,有很多 cmets 和空行)。

! Set inital counter for validated points
k = 1

! Do for all randomly generated points
DO i=1,100000

  ! Create a random point with coordinates x, y and z.
  CALL RANDOM_NUMBER(rand)

  ! Normalise the random coordinates to the bounding box.
  rand(1:3) = (rand(1:3) * (cord(1:3) - cord(4:6))) + cord(4:6)

  ! Set the initial counter for the vertices
  j = 1

  ! Set the number of intersections with the random point and the triangle
  no_insect = 0 

  ! Do for all triangles in STL
  DO num = 1, notri

      ! Get the maximum "x" value for the current triangle
      maxtempx = MAXVAL(vertices(1,j:j+2))

      ! Get the minimum "x" value for the current triangle
      mintempx = MINVAL(vertices(1,j:j+2))

      ! If the random point is within the bounds continue
      IF (rand(1)>=mintempx .AND. rand(1)<=maxtempx) THEN

        ! Get the maximum "y" value for the current triangle
        maxtempy = MAXVAL(vertices(2,j:j+2))

        ! Get the minimum "y" value for the current triangle
        mintempy = MINVAL(vertices(2,j:j+2))    

        ! If the random point is within the bounds continue     
        IF (rand(2)>=mintempy .AND. rand(2)<=maxtempy) THEN

            ! Find the "z" value of the point as projected onto the triangle plane
            tempz = ((norm(1,num)*(rand(1)-vertices(1,j))) &
                +(norm(2,num)*(rand(2)-vertices(2,j))) &
                - (norm(3,num)*vertices(3,j))) / (-norm(3,num))

            ! If the "z" value of the randomly generated point goes vertically up
            ! through the projected point then increase the number of plane intersections
            ! by one. (Ray casting vertically up, could go down also).

            IF (rand(3)<= tempz) THEN
                no_insect = no_insect + 1   
            END IF  

        END IF
    END IF

    ! Go to the start of the next triangle
    j = j + 3
  END DO  

  ! If there is an odd number of triangle intersections not 
  ! including 0 intersections then store the point

  IF (MOD(no_insect,2)/=0 .AND. no_insect/=0) THEN
    point(k,1:3) = rand(1:3)
    WRITE(1,"(1X, 3(F10.8, 3X))") point(k,1), point(k,2), point(k,3)
    k = k + 1
  END IF

END DO 

我的结果完全是垃圾(见图片) 图片 1 - 测试 STL 文件(来自here)。程序的一部分(代码未显示)读取二进制 STL 文件并存储每个三角形的表面法线和构成该三角形的顶点。然后我将顶点写入一个文本文件并调用 GNUPLOT 来连接每个三角形的顶点,如上所示。该图只是一个测试,以确保正确读取和存储 STL 文件。它不使用表面法线。 。 图 2 - 这是被接受为在 STL 体积内的候选点的图。 (存储在上面代码所示的最终 if 循环中)。这些接受的点随后被写入文本文件并用 GNUPLOT(未显示)绘制。如果算法有效,这个图应该是上面显示的三角网格的点云。 (它还绘制了 8 个边界框坐标,以确保随机粒子生成在正确的范围内)

我明白这没有考虑在顶点或射线上生成的点,这些点平行运行并与边缘相交。我只是想从一个粗略的代码开始。您能否告知我的方法或代码是否有问题?如果问题太宽泛,请告诉我,我将删除它并尝试更具体。

【问题讨论】:

  • 你能评论这些图片吗?它们显示了什么>都是你的代码的结果吗?
  • @VladimirF ,我在上面的图片中添加了一些 cmets。简而言之 - 图 1 是一个通用的三角网格,它已被程序读入,然后绘制以确保正确存储。图 2 旨在绘制由点填充的相同体积的图(即使用上述代码测试并发现位于三角网格内的随机点)。
  • 那么你需要检查一个点是否在非凸多面体内?我会为此使用图书馆。我使用 CGAL 读取 OFF 文件,但它不直接返回内部或不直接返回,然后我必须计算与射线相交的数量。 gts.sourceforge.net 呢?
  • @VladimirF 是的,我正在尝试检查一个点是否在非凸三维多面体内。我对编码和 Fortran 很陌生(以前从未使用过库)而且我不知道任何 C++。我会看一下 GTS 库,看看有没有什么我可以使用的。
  • 但是仍然可以在这里询问算法,但要知道这并不容易。

标签: fortran raycasting particles


【解决方案1】:

我意识到我的代码对其他人来说可能很方便。我将它放在https://github.com/LadaF/Fortran---CGAL-polyhedra 下,遵循 GNU GPL v3 许可。

您可以查询一个点是否在一个点内。首先,您通过以下方式读取文件 cgal_polyhedron_read。您必须存储已装箱的 type(c_ptr) :: ptree,并在下次调用时使用它。

函数cgal_polyhedron_inside 返回一个点是否在多面体内部。它需要一个参考点,必须知道它在外面。

完成后致电cgal_polyhedron_finalize

您必须在 OFF 文件中将该文件作为纯三对角流形网格。您可以使用 http://www.cs.princeton.edu/~min/meshconv/ 从 STL 文件创建它。

【讨论】:

  • 您能否评论一下您如何在使用调用 cgal_polyhedron_read(ptree, fname) 的主程序中定义“ptree”类型?其中 ptree 是类型输出。
  • 查看test.f90,使用make_test_gcc.sh进行编译。使用 gcc 4.8 和 CGAL 4.1 测试。
  • 我放弃了尝试让 CGAL 使用 MinGW 和 gfortran 在 Windows 7 上工作。在 Ubuntu 上编译给出了错误“未定义对符号 '_zn5boost6system15system_categoryev' 的引用”。这已通过将 -lboost_system 添加到 makefile 的末尾来解决,如突出显示的 here
猜你喜欢
  • 1970-01-01
  • 2018-11-14
  • 1970-01-01
  • 2012-10-08
  • 2017-10-18
  • 2021-05-06
  • 1970-01-01
  • 2010-09-20
  • 1970-01-01
相关资源
最近更新 更多