Как вычислить логическую симметричную разницу («Delat-Mesh») на двух 3D-сетках в JavaScript?

#javascript #algorithm #multidimensional-array #mesh #boolean-operations

Вопрос:

Обновление (2021-06-03): Чтобы прояснить мой вопрос, так как до сих пор не было ответа

Я хочу вычислить различия (логическую симметричную разницу, XOR) двух 3D-сеток и сохранить определенную «дельта-сетку» на втором шаге в виде файла в формате OBJ.

Существует ли реализация JavaScript для вычисления логической симметричной разности?

Чтобы прояснить свой вопрос, я добавил еще одну картинку: введите описание изображения здесь

Для этой цели я уже реализовал код на JavaScript, который считывает два OBJ-файла и передает их в массивы. Каждый массив содержит вершины, индексы вершин для описания граней и т. Д.

Результат: (Shape_1 и Shape_2-входные сетки (модель A и B), а Shape_3-желаемая выходная сетка для расчета)

 Shape_1_Vertices = {
    "array_3D_Mesh_1": [
        {
            "0": {
                "X": -25,
                "Y": -15,
                "Z": 0
            }
        },
        {
            "1": {
                "X": -25,
                "Y": -15,
                "Z": 100
            }
        },
        {
            "2": {
                "X": -25,
                "Y": 15,
                "Z": 0
            }
        },
        {
            "3": {
                "X": -25,
                "Y": 15,
                "Z": 100
            }
        },
        {
            "4": {
                "X": 25,
                "Y": -15,
                "Z": 0
            }
        },
        {
            "5": {
                "X": 25,
                "Y": -15,
                "Z": 100
            }
        },
        {
            "6": {
                "X": 25,
                "Y": 15,
                "Z": 0
            }
        },
        {
            "7": {
                "X": 25,
                "Y": 15,
                "Z": 100
            }
        }
    ]
}

Shape_1_Faces = {
    "array_FaceIndices_Mesh_1": [
        {
            "face0": {
                "1": 2,
                "2": 0,
                "3": 3
            }
        },
        {
            "face1": {
                "1": 3,
                "2": 0,
                "3": 1
            }
        },
        {
            "face2": {
                "1": 6,
                "2": 2,
                "3": 7
            }
        },
        {
            "face3": {
                "1": 7,
                "2": 2,
                "3": 3
            }
        },
        {
            "face4": {
                "1": 4,
                "2": 6,
                "3": 5
            }
        },
        {
            "face5": {
                "1": 5,
                "2": 6,
                "3": 7
            }
        },
        {
            "face6": {
                "1": 0,
                "2": 4,
                "3": 1
            }
        },
        {
            "face7": {
                "1": 1,
                "2": 4,
                "3": 5
            }
        },
        {
            "face8": {
                "1": 1,
                "2": 5,
                "3": 3
            }
        },
        {
            "face9": {
                "1": 3,
                "2": 5,
                "3": 7
            }
        },
        {
            "face10": {
                "1": 4,
                "2": 0,
                "3": 6
            }
        },
        {
            "face11": {
                "1": 6,
                "2": 0,
                "3": 2
            }
        }
    ]
}

Shape_2_Vertices = {
    "array_3D_Mesh_2": [
        {
            "0": {
                "X": -20,
                "Y": -40,
                "Z": 0
            }
        },
        {
            "1": {
                "X": -20,
                "Y": -40,
                "Z": 40
            }
        },
        {
            "2": {
                "X": -20,
                "Y": 40,
                "Z": 0
            }
        },
        {
            "3": {
                "X": -20,
                "Y": 40,
                "Z": 40
            }
        },
        {
            "4": {
                "X": 20,
                "Y": -40,
                "Z": 0
            }
        },
        {
            "5": {
                "X": 20,
                "Y": -40,
                "Z": 40
            }
        },
        {
            "6": {
                "X": 20,
                "Y": 40,
                "Z": 0
            }
        },
        {
            "7": {
                "X": 20,
                "Y": 40,
                "Z": 40
            }
        }
    ]
}

Shape_2_Faces = {
    "array_FaceIndices_Mesh_2": [
        {
            "face0": {
                "1": 0,
                "2": 4,
                "3": 1
            }
        },
        {
            "face1": {
                "1": 1,
                "2": 4,
                "3": 5
            }
        },
        {
            "face2": {
                "1": 2,
                "2": 0,
                "3": 3
            }
        },
        {
            "face3": {
                "1": 3,
                "2": 0,
                "3": 1
            }
        },
        {
            "face4": {
                "1": 6,
                "2": 2,
                "3": 7
            }
        },
        {
            "face5": {
                "1": 7,
                "2": 2,
                "3": 3
            }
        },
        {
            "face6": {
                "1": 4,
                "2": 6,
                "3": 5
            }
        },
        {
            "face7": {
                "1": 5,
                "2": 6,
                "3": 7
            }
        },
        {
            "face8": {
                "1": 7,
                "2": 3,
                "3": 5
            }
        },
        {
            "face9": {
                "1": 5,
                "2": 3,
                "3": 1
            }
        },
        {
            "face10": {
                "1": 4,
                "2": 0,
                "3": 6
            }
        },
        {
            "face11": {
                "1": 6,
                "2": 0,
                "3": 2
            }
        }
    ]
}

Shape_4_Vertices = {
    "array_3D_Mesh_4": [
        {
            "0": {
                "X": -25,
                "Y": -15,
                "Z": 0
            }
        },
        {
            "1": {
                "X": -25,
                "Y": -15,
                "Z": 100
            }
        },
        {
            "2": {
                "X": -25,
                "Y": 15,
                "Z": 0
            }
        },
        {
            "3": {
                "X": -25,
                "Y": 15,
                "Z": 100
            }
        },
        {
            "4": {
                "X": -20,
                "Y": -40,
                "Z": 0
            }
        },
        {
            "5": {
                "X": -20,
                "Y": -40,
                "Z": 40
            }
        },
        {
            "6": {
                "X": -20,
                "Y": -15,
                "Z": 0
            }
        },
        {
            "7": {
                "X": -20,
                "Y": -15,
                "Z": 40
            }
        },
        {
            "8": {
                "X": -20,
                "Y": 15,
                "Z": 0
            }
        },
        {
            "9": {
                "X": -20,
                "Y": 15,
                "Z": 40
            }
        },
        {
            "10": {
                "X": -20,
                "Y": 40,
                "Z": 0
            }
        },
        {
            "11": {
                "X": -20,
                "Y": 40,
                "Z": 40
            }
        },
        {
            "12": {
                "X": 20,
                "Y": -40,
                "Z": 0
            }
        },
        {
            "13": {
                "X": 20,
                "Y": -40,
                "Z": 40
            }
        },
        {
            "14": {
                "X": 20,
                "Y": -15,
                "Z": 0
            }
        },
        {
            "15": {
                "X": 20,
                "Y": -15,
                "Z": 40
            }
        },
        {
            "16": {
                "X": 20,
                "Y": 15,
                "Z": 0
            }
        },
        {
            "17": {
                "X": 20,
                "Y": 15,
                "Z": 40
            }
        },
        {
            "18": {
                "X": 20,
                "Y": 40,
                "Z": 0
            }
        },
        {
            "19": {
                "X": 20,
                "Y": 40,
                "Z": 40
            }
        },
        {
            "20": {
                "X": 25,
                "Y": -15,
                "Z": 0
            }
        },
        {
            "21": {
                "X": 25,
                "Y": -15,
                "Z": 100
            }
        },
        {
            "22": {
                "X": 25,
                "Y": 15,
                "Z": 0
            }
        },
        {
            "23": {
                "X": 25,
                "Y": 15,
                "Z": 100
            }
        }
    ]
}

Shape_4_Faces = {
    "array_FaceIndices_Mesh_4": [
        {
            "face0": {
                "1": 9,
                "2": 7,
                "3": 8
            }
        },
        {
            "face1": {
                "1": 8,
                "2": 7,
                "3": 6
            }
        },
        {
            "face2": {
                "1": 16,
                "2": 14,
                "3": 17
            }
        },
        {
            "face3": {
                "1": 17,
                "2": 14,
                "3": 15
            }
        },
        {
            "face4": {
                "1": 9,
                "2": 17,
                "3": 7
            }
        },
        {
            "face5": {
                "1": 7,
                "2": 17,
                "3": 15
            }
        },
        {
            "face6": {
                "1": 8,
                "2": 16,
                "3": 9
            }
        },
        {
            "face7": {
                "1": 9,
                "2": 16,
                "3": 17
            }
        },
        {
            "face8": {
                "1": 7,
                "2": 15,
                "3": 6
            }
        },
        {
            "face9": {
                "1": 6,
                "2": 15,
                "3": 14
            }
        },
        {
            "face10": {
                "1": 16,
                "2": 22,
                "3": 14
            }
        },
        {
            "face11": {
                "1": 14,
                "2": 22,
                "3": 20
            }
        },
        {
            "face12": {
                "1": 16,
                "2": 8,
                "3": 18
            }
        },
        {
            "face13": {
                "1": 18,
                "2": 8,
                "3": 10
            }
        },
        {
            "face14": {
                "1": 6,
                "2": 0,
                "3": 8
            }
        },
        {
            "face15": {
                "1": 8,
                "2": 0,
                "3": 2
            }
        },
        {
            "face16": {
                "1": 6,
                "2": 14,
                "3": 4
            }
        },
        {
            "face17": {
                "1": 4,
                "2": 14,
                "3": 12
            }
        },
        {
            "face18": {
                "1": 6,
                "2": 4,
                "3": 7
            }
        },
        {
            "face19": {
                "1": 7,
                "2": 4,
                "3": 5
            }
        },
        {
            "face20": {
                "1": 15,
                "2": 7,
                "3": 13
            }
        },
        {
            "face21": {
                "1": 13,
                "2": 7,
                "3": 5
            }
        },
        {
            "face22": {
                "1": 9,
                "2": 17,
                "3": 11
            }
        },
        {
            "face23": {
                "1": 11,
                "2": 17,
                "3": 19
            }
        },
        {
            "face24": {
                "1": 15,
                "2": 13,
                "3": 14
            }
        },
        {
            "face25": {
                "1": 14,
                "2": 13,
                "3": 12
            }
        },
        {
            "face26": {
                "1": 16,
                "2": 18,
                "3": 17
            }
        },
        {
            "face27": {
                "1": 17,
                "2": 18,
                "3": 19
            }
        },
        {
            "face28": {
                "1": 4,
                "2": 12,
                "3": 5
            }
        },
        {
            "face29": {
                "1": 5,
                "2": 12,
                "3": 13
            }
        },
        {
            "face30": {
                "1": 9,
                "2": 11,
                "3": 8
            }
        },
        {
            "face31": {
                "1": 8,
                "2": 11,
                "3": 10
            }
        },
        {
            "face32": {
                "1": 18,
                "2": 10,
                "3": 19
            }
        },
        {
            "face33": {
                "1": 19,
                "2": 10,
                "3": 11
            }
        },
        {
            "face34": {
                "1": 6,
                "2": 7,
                "3": 0
            }
        },
        {
            "face35": {
                "1": 0,
                "2": 7,
                "3": 1
            }
        },
        {
            "face36": {
                "1": 1,
                "2": 7,
                "3": 15
            }
        },
        {
            "face37": {
                "1": 1,
                "2": 15,
                "3": 21
            }
        },
        {
            "face38": {
                "1": 21,
                "2": 15,
                "3": 20
            }
        },
        {
            "face39": {
                "1": 20,
                "2": 15,
                "3": 14
            }
        },
        {
            "face40": {
                "1": 2,
                "2": 0,
                "3": 3
            }
        },
        {
            "face41": {
                "1": 3,
                "2": 0,
                "3": 1
            }
        },
        {
            "face42": {
                "1": 8,
                "2": 2,
                "3": 9
            }
        },
        {
            "face43": {
                "1": 9,
                "2": 2,
                "3": 3
            }
        },
        {
            "face44": {
                "1": 9,
                "2": 3,
                "3": 23
            }
        },
        {
            "face45": {
                "1": 9,
                "2": 23,
                "3": 17
            }
        },
        {
            "face46": {
                "1": 17,
                "2": 23,
                "3": 22
            }
        },
        {
            "face47": {
                "1": 17,
                "2": 22,
                "3": 16
            }
        },
        {
            "face48": {
                "1": 20,
                "2": 22,
                "3": 21
            }
        },
        {
            "face49": {
                "1": 21,
                "2": 22,
                "3": 23
            }
        },
        {
            "face50": {
                "1": 1,
                "2": 21,
                "3": 3
            }
        },
        {
            "face51": {
                "1": 3,
                "2": 21,
                "3": 23
            }
        }
    ]
}
 

Чтобы прояснить, что я имею в виду, я приложил фотографию.
введите описание изображения здесь

  1. показывает исходные сравниваемые тела, которые доступны по отдельности в формате OBJ
  2. показывает наложенное расположение обоих тел. (Позиционирование автоматически корректно и по желанию во время импорта, так что мне не нужно беспокоиться об этом).
  3. показывает желаемую «дельта-сетку», которую я хочу рассчитать и вывести в виде файла в формате OBJ. (Тело в пунктирной рамке показывает пересечение, которое в конце нужно вырезать, но оно не представляет интереса).

Если вы хотите реализовать мое намерение с помощью логических операций, вам придется выполнить логическую симметричную разницу или XOR (исключающее ИЛИ).

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

Shape_1_Input_Model_A
Shape_2_Input_Model_B
Shape_4_Desired_Output http://www.filedropper.com/shape4

Комментарии:

1. en.wikipedia.org/wiki/Constructive_solid_geometry это название этой темы, и для JS, в частности, вы могли бы проверить ThreeCSG

2. Я думаю, вам нужно предоставить нам более подробную информацию о вводимых ресурсах и ожидаемых результатах. Например, вы перечисляете грани как элементы с тремя свойствами — 1 , 2 , 3 — каждое из которых указывает на строку, которая, предположительно, является именем одной из вершин в вашем списке вершин. Но что означают эти индексы? И почему, когда все кажется прямоугольниками, ваше лицо должно быть указано с тремя вершинами вместо четырех? Хотя фотографии дают некоторый контекст, нам нужны более полные и реалистичные данные для работы.

3. @tevemadar: Спасибо за ваш ответ, я проверю это.

4. @Scott Sauyet: Большое вам спасибо за ваш ответ. Я добавил еще одну картинку, чтобы проиллюстрировать свое намерение. Показанные массивы граней и вершин принадлежат структуре данных OBJ, которую можно увидеть в левом нижнем углу на новом рисунке. Я читаю импортированные сетки в формате OBJ-файла и переношу их в массивы для выполнения вычислений на нем. конечная цель состоит в том, чтобы получить сетку булевой симметричной разности и экспортировать ее…

5. @Mec-Eng: Хотя дополнительные изображения-это здорово, то, что нам действительно нужно, чтобы ответить на этот вопрос, — это реальные реалистичные входные данные и запрошенные выходные данные.