Я создаю преобразователь файла CAD сверху двух библиотек (Opencascade и DWF Toolkit).
Однако моим вопросом является агностик платформы:
Данный:
Я генерировал сетку, поскольку список треугольных поверхностей формирует модель, созданную через мое приложение. Каждый Треугольник определяется через три вершины, которые состоят из трех плаваний (x, y и координата z). Так как треугольники формируют сетку, большинство вершин совместно используется более затем одним треугольником.
Цель:
Я должен найти список уникальных вершин, и генерировать массив поверхностей, состоящих из кортежей трех индексов в этом списке.
То, что я хочу сделать, является этим:
//step 1: build a list of unique vertices
for each triangle
for each vertex in triangle
if not vertex in listOfVertices
Add vertex to listOfVertices
//step 2: build a list of faces
for each triangle
for each vertex in triangle
Get Vertex Index From listOfvertices
AddToMap(vertex Index, triangle)
В то время как у меня действительно есть реализация, которая делает это, step1 (поколение списка уникальных вершин) действительно медленно в порядке O (n!), так как каждая вершина уже сравнивается со всеми вершинами в списке. Я думал "Эй, позволяет, создают hashmap компонентов моих вершин с помощью станд.:: карта, которая должна ускорить вещи!", только, чтобы найти, что генерация уникального ключа от трех значений с плавающей точкой не является тривиальной задачей.
Здесь, эксперты stackoverflow играют роль: Мне нужна некоторая хеш-функция, которая работает над 3 плаваниями или любой другой функцией, генерирующей уникальное значение от положения 3-й вершины.
Выгрузите все вершины в массив, затем выполните unique (sort (array))
. Это должно быть O (k n log (n)), где k - среднее количество треугольников, имеющих общую вершину, обычно k <7.
Единственное предостережение, о котором я могу думать, это то, что ваша уникальная
функция должна иметь возможность принимать указатель на функцию сравнения, поскольку вы, вероятно, захотите считать свои вершины равными if
distance(vertex1, vertex2) < threshold
, но это кажется быть ОК .
Обычная идея для получения хеша состоит в том, чтобы умножить каждый битовый шаблон поплавка на простое число и сложить их вместе. Примерно так:
unsigned int hash_point(float x, float y, float z)
{
unsigned int* px = (unsigned int*)&x;
unsigned int* py = (unsigned int*)&y;
unsigned int* pz = (unsigned int*)&z;
return (*px)*PRIME1 + (*py)*PRIME2 + (*pz)*PRIME3;
}
Обратите внимание, что sizeof (unsigned int) здесь считается равным sizeof (float). Образец приведен только для иллюстрации основной идеи, вы должны настроить его под свои нужды.
Три решения. Конечно, есть и другие
В случаях 2 и 3, если вы хотите указать некоторый допуск, вам нужно будет выполнить поиск более чем в одной части дерева или сетки. В случае BSP это означает проверку того, что вы находитесь в пределах допуска разделяющей плоскости, и если да, то повторение на обе половины. В случае сетки это означает проверку всех соседних ячеек, которые находятся в пределах допуска. Ни то, ни другое не является слишком твердым, но означает, что будет сложнее использовать готовое решение.