2014-09-18 2 views
1

포트란에 포인트가있는 STL 파일을 채우려고합니다. 기본 코드를 작성했지만 작동하지 않습니다.포트란 - STL의 포인트

내 방법은 난수 생성기를 사용하여 점을 생성하는 것이 었습니다. 그런 다음이 점을 STL 경계 상자의 크기로 표준화합니다.

그런 다음 STL의 첫 번째 삼각형에 대해 "z"좌표를 내 보냅니다. 임의의 점이 첫 번째 삼각형의 "x"와 "y"좌표의 최대 값과 최소값인지 확인합니다. 그렇다면 나는 임의의 점을 삼각형 평면에 수직으로 투영하고 평면과 교차해야하는 "z"값을 계산합니다. 그런 다음 임의의 점의 z 값이 투영 된 점의 값보다 작은 지 확인합니다 (레이 캐스팅). 그렇다면 처음에 0으로 설정된 카운터를 1 씩 증가시킵니다.

STL의 모든 삼각형에 대해 이렇게합니다. 카운터가 무작위 포인트라도 볼륨 밖에 있으면, 홀수 인 경우 무작위 포인트가 볼륨 안에 있고 포인트가 저장됩니다.

그런 다음 새로운 임의의 점을 생성하고 다시 시작합니다. 나는 아래에 중요한 코드를 포함시켰다. 길이에 대한 사과 (많은 댓글과 가독성을위한 빈 줄). 테스트 STL 파일 (here에서 가져온 배) -

! 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 

내 결과는 완전 쓰레기 (이미지 참조) enter image description here 이미지 1이었다. 프로그램의 일부 (코드는 표시되지 않음)는 이진 STL 파일을 읽고 각 삼각형의 표면 법선과이 삼각형을 구성하는 정점을 저장합니다. 그런 다음 정점을 텍스트 파일에 쓰고 위 그림과 같이 각 삼각형의 정점을 연결하는 GNUPLOT을 호출합니다. 이 플롯은 STL 파일을 올바르게 읽고 저장하는 테스트입니다. 표면 법선을 사용하지 않습니다. enter image description here. 이미지 2 - 이것은 STL 볼륨 내부에있는 것으로 받아 들여진 후보 포인트의 플롯입니다. (위의 코드에 표시된 마지막 if 루프에 저장 됨). 이 허용 된 점은 나중에 텍스트 파일에 쓰여지고 GNUPLOT (NOT SHOWN)으로 그려집니다. 알고리즘이 작동했다면이 플롯은 위에 표시된 삼각형 메쉬의 점 구름이어야합니다. (또한 랜덤 파티클이 올바른 범위에서 생성되도록 8 경계 상자 좌표를 표시합니다.)

평행선을 실행하거나 가장자리와 교차하는 광선에 대해 생성 된 점을 고려하지 않은 점을 높이 평가합니다. 난 그냥 거친 코드로 시작하고 싶었어. 내 방법론이나 코드에 문제가 있다면 조언 해 주실 수 있습니까? 질문이 너무 광범위하다면 알려주고 삭제하겠습니다.

+0

이미지에 댓글을 달 수 있습니까?그들이 보여주는 것> 두 코드 모두 결과입니까? –

+0

@VladimirF, 위의 이미지에 몇 가지 설명을 추가했습니다. 요약하면 Image 1은 프로그램에 의해 읽혀지고 올바른 저장을 보장하기 위해 그려진 일반적인 삼각 메쉬입니다. 이미지 2는 점으로 채워진 동일한 볼륨의 플롯을 나타냅니다 (위의 코드를 사용하여 테스트되었고 삼각형 화 된 메쉬 내부에있는 임의의 점). – 1QuickQuestion

+1

그래서 당신이 필요로하는 것은 점이 비 convex 다면체 안에 있는지 확인하는 것입니다. 나는 그것을 위해 도서관을 사용할 것이다. 나는 OFF 파일을 읽으려고 CGAL을 사용하지만 내부로 또는 직접적으로 리턴하지는 않는다. 그래서 나는 레이와의 교차 수를 세어야한다. http://gts.sourceforge.net/은 어떻습니까? –

답변

1

나는 내 코드가 다른 사람들에게 유용 할 수 있음을 깨달았다. GNU GPL v3 라이센스하에 https://github.com/LadaF/Fortran---CGAL-polyhedra에 두었습니다.

포인트가 포인트 안에 있는지 여부를 쿼리 할 수 ​​있습니다. 먼저 파일을 cgal_polyhedron_read으로 읽습니다. type(c_ptr) :: ptree을 보관하고 다음에 사용할 때 사용하십시오.

함수 cgal_polyhedron_inside은 점이 다면체 안에 있는지 여부를 반환합니다. 외부에 있어야하는 하나의 참조 점이 필요합니다.

끝나면 cgal_polyhedron_finalize으로 전화하십시오.

파일을 OFF 파일에서 순수하게 3 중 ​​선택되는 매니 폴드 메쉬로 사용해야합니다. http://www.cs.princeton.edu/~min/meshconv/을 사용하여 STL 파일에서 생성 할 수 있습니다.

+0

cgal_polyhedron_read (ptree, fname) 호출을 사용하는 주 프로그램에서 "ptree"유형을 정의하는 방법에 대해 의견을 말씀해 주시겠습니까? 여기서 ptree는 유형 출력입니다. – 1QuickQuestion

+1

'test.f90'을보고'make_test_gcc.sh'를 사용하여 컴파일하십시오. gcc 4.8 및 CGAL 4.1로 테스트되었습니다. –

+0

저는 MinGW와 gfortran을 사용하여 Windows 7에서 작동하도록 CGAL을 시도하는 것을 포기했습니다. 우분투에서 컴파일하면 " '_zn5boost6system15system_categoryev'기호에 대한 정의되지 않은 참조 오류가 발생했습니다. 이것은 메이크 파일의 끝 부분에 -lboost_system을 추가하여 해결되었습니다 [여기] (http://stackoverflow.com/questions/20057127/freeling-error-with-python-and-java-api-undefined-symbol-zn5boost6system15sys) – 1QuickQuestion