2014-09-18 4 views
1

Я пытаюсь заполнить файл STL точками в Fortran. Я написал базовый код, но он не работает.Fortran - Point in STL

Мой метод заключается в использовании генератора случайных чисел для генерации точки. Затем я нормализую эту точку к размерам ограничивающего прямоугольника STL.

Затем я выбрасываю координату «z» для первого треугольника в STL. Я проверяю, является ли случайная точка с максимальным и минимальным значением координаты «x» и «y» первого треугольника. Если это так, я проектирую случайную точку вертикально на плоскость треугольника и вычисляю значение «z», если оно пересечет плоскость. Затем я проверяю, меньше ли значение z случайной точки, чем значение прогнозируемой точки (лучевое кастинг). Если да, я увеличиваю счетчик, который первоначально установлен на ноль, на единицу.

Я делаю это для каждого треугольника в STL. Если счетчик равен даже случайной точке за пределами тома, если это нечетно, случайная точка находится внутри тома, и точка сохраняется.

Затем я создаю новую случайную точку и начинаю снова. Я включил важный код ниже. Извинения за длину (много комментариев и пустых строк для удобочитаемости).

! 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 файл (корабль взят из here). Часть программы (код не показан) читается в двоичных файлах STL и сохраняет нормали поверхности каждого треугольника и вершины, составляющие этот треугольник. Затем я написал вершины в текстовый файл и вызываю GNUPLOT для соединения вершин каждого треугольника, как показано выше. Этот график является просто испытанием, гарантирующим, что файлы STL будут считаны и сохранены правильно. Он не использует поверхностные нормали. enter image description here. Изображение 2 - Это график точек кандидата, которые были приняты как находящиеся внутри тома STL. (Сохраняется в последнем цикле if, показанном в коде выше). Затем эти принятые точки затем записываются в текстовый файл и отображаются с помощью GNUPLOT (NOT SHOWN). Если бы алгоритм работал, этот график должен быть облаком точек триангулированной сетки, показанной выше. (Он также отображает 8 границ прямоугольника, чтобы гарантировать, что случайные частицы сгенерированы в правильном диапазоне)

Я ценю, что это не учитывает точки, созданные на вершинах или лучах, которые параллельны и пересекаются с ребрами. Я просто хотел начать с грубого кода. Не могли бы вы посоветовать, есть ли проблема с моей методологией или кодом? Дайте мне знать, если вопрос слишком широк, и я удалю его и постараюсь быть более конкретным.

+0

Не могли бы вы прокомментировать изображения.Что они показывают> Являются ли оба результата вашего кода? –

+0

@VladimirF, я добавил некоторые комментарии к вышеуказанным изображениям. Короче - Image 1 представляет собой общую триангулированную сетку, которая была прочитана программой, а затем построена для обеспечения правильного хранения. Изображение 2 предназначено для построения одного и того же объема, заполненного точками (то есть случайных точек, которые были проверены с использованием вышеприведенного кода и оказались внутри триангулированной сетки). – 1QuickQuestion

+1

Итак, что вам нужно, чтобы проверить, находится ли точка внутри не выпуклого многогранника? Для этого я бы использовал библиотеку. Я использую CGAL для чтения OFF-файла, но он не возвращается внутри или нет напрямую, тогда мне приходится подсчитывать количество пересечений с лучом. Как насчет http://gts.sourceforge.net/? –

ответ

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. Вы можете создать его из файла STL, используя http://www.cs.princeton.edu/~min/meshconv/.

+0

Не могли бы вы прокомментировать, как вы определяете тип «ptree» в основной программе, которая использует вызов cgal_polyhedron_read (ptree, fname)? Где ptree - выход типа. – 1QuickQuestion

+1

См. 'Test.f90', скомпилируйте его с помощью' make_test_gcc.sh'. Протестировано с помощью gcc 4.8 и CGAL 4.1. –

+0

Я сдался, пытаясь заставить CGAL работать на Windows 7 с помощью MinGW и gfortran. Компиляция на Ubuntu дала ошибку «неопределенная ссылка на символ» _zn5boost6system15system_categoryev ». Это было разрешено путем добавления -lboost_system в конец make-файла, как выделено [здесь] (http://stackoverflow.com/questions/20057127/freeling-error-with-python-and-java-api-undefined-symbol-zn5boost6system15sys) – 1QuickQuestion

 Смежные вопросы

  • Нет связанных вопросов^_^