Официальный форум российского программного комплекса T-FLEX PLM


Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Регистрация
Войти
 
Страницы: 1
[ Закрыто ] Как узнать куда направлена нормаль - внутрь или наружу, Вопросы, возникающие при вставке 3D фрагмента
 
Всем добрый день. Решается задача программной вставки 3D фрагмента. Прогаммно делается так:
1. Строится точка, в которой будет вставлен 3D фрагмент (например, отверстие)
2. В этой точке создается ЛСК, к которой он будет привязан
3. Вставляется фрагмент
4. Привязывается к построенной ЛСК
5. Вычитается из тела.

При построении ЛСК используется нормаль поверхности, на которой будет располагаться фрагмент, и оси Z присваивается значение этой нормали. А теперь вопрос, как узнать, куда направлена эта нормаль, внутрь или наружу тела?
 
Привет,
Если я правильно понимаю, есть некий 3D объект, относительно которого необходимо вставить 3D фрагмент с вычитанием. Основой для построения фрагмента является рабочая плоскость. То есть, после выделения одной из граней выполняется макрокоманда, так?
 
Цитата
Vite написал:
Если я правильно понимаю, есть некий 3D объект, относительно которого необходимо вставить 3D фрагмент с вычитанием.
По сути да. У меня длл, где есть команда меню "Вставить КТЭ". Затем происходит его привязка, а именно выбор плоскости, на которой он будет расположен, и грани, от которых задаются расстояния до КТЭ, например центра, если это отверстия. Пошагово - это точка, лск, вставка фрагмента, совмещение его лск с созданной. И вот как определить, куда направлена нормаль, чтобы фрагмент оказался внутри тела, а не перевернут на 180 градусов?
 
Когда создается (ЛСК), по умолчанию направление осей ориентировано в соответствии глобальной системы координат. После привязки (ЛСК) к 3D узлу, нужно сориентировать направление осей:
1. Начало координат
2. Направление оси X
3. Направление оси Y

Классы
- LCS (Базовый класс для всех локальных систем координат (ЛСК))
- LCS::GeometryData (Множество геометрических данных системы координат)
- LCSPoint (Узел, построенный по координатам относительно системы координат)
- LCSTransformation (Преобразование)
- LCSWorkplane (Рабочая плоскость по локальной системе координат)
- OrientationType (Какой парой осей локальной системы координат задаётся рабочая плоскость)

Думаю, должно быть просто. Нужно определить положение рабочей плоскости, относительно (ГСК), и далее определить какая ось проходит по нормали.
Orientation_LCS.PNG (35.19 КБ)
Изменено: Vite - 13.10.2015 15:36:51
 
Собственно в процессе построения ось Z ЛСК ориентируется параллельно нормали плоскости и задача сейчас заключается в том, чтобы понять, куда эта нормаль направлена, внутрь тела или наружу. Визуально это понятно, как довернуть в случае чего оси, но в моем случае все должно происходить автоматически и быть скрыто от пользователя. Он просто тычет на грань, указывает на каком расстоянии от какой грани и все.
 
По умолчанию, нормаль обращена вне объекта (см. снимок). Все что нужно сделать после определения начальной точки координат, повторно выбрать ту же грань для определения направления оси X по нормали.
 
Вот в этом то вся и фишка, что нет.
На рисунке значения нормалей 3 поверхностей, параллельных друг другу, 3-я грань - самая нижняя в детали, не видна просто. На надпись "ребра" не обращайте внимания, просто осталось со старого кода. И в голову приходит только идея сместить точку (или создать новую, там уже по ходу разобраться, как проще), в которой построена ЛСК, на миллиметр вдоль ее оси Z и проверять, находится ли она в теле. Если нет, то направление правильное, иначе перевернуть ось.
Код
var pSurf = modelFace.Surface as PlaneSurface;
if (pSurf != null)
{
    pt = pSurf.Plane.Origin;
    dir = pSurf.Plane.Normal;
}
normal.JPG (40.94 КБ)
normal2.JPG (54.46 КБ)
Изменено: Batarejka - 14.10.2015 14:56:51
 
Сложно оценить Вашу программу, относительно картинки. Опишите последовательность действий, в какой момент выполняется макрокоманда.
Вот что у меня получилось, используя стандартные инструменты (см. вложение). Единственная грань (наклонная грань справа), где потребовалось дополнительное определение оси Y.
Orientation_LCS_3.PNG (132.37 КБ)
 
Собственно последовательность действий, я уже описала выше:

Цитата
Batarejka написал:
Прогаммно делается так:
1. Строится точка, в которой будет вставлен 3D фрагмент (например, отверстие)
2. В этой точке создается ЛСК, к которой он будет привязан
3. Вставляется фрагмент
4. Привязывается к построенной ЛСК
5. Вычитается из тела.
И вот как происходит. В моем меню есть пункт "Вставить КТЭ". Я нажимаю на него и происходит следующий диалог с пользователем:
- Выберите грань для расположения КТЭ - ожидание выбора
- Выберите первую грань для привязки КТЭ - ожидание выбора, после выбора задание расстояния, на котором от этой грани расположен КТЭ
- Выберите вторую грань для привязки КТЭ - аналогично предыдущему пункту
Всё!
И вот как только пользователь это сделал, у меня есть нормали выбранных граней. На моих рисунках есть эти значения. Так вот, получается, что нормаль может быть направлена и внутрь тела (верхняя грань, нормаль 0,0-1). А я хочу, чтобы ось Z создаваемой мной ЛСК для КТЭ была параллельна нормали плоскости привязки, но обязательна направлена вне тела.

По факту задачу можно сформулировать так: Как программно построить ЛСК на плоскости, чтобы ось Z была перпендикулярна ей и направлена вне тела?
Код
//нормаль и точка на выбранной грани
var pSurf = modelFace.Surface as PlaneSurface;
if (pSurf != null)
{
    pt = pSurf.Plane.Origin;
    dir = pSurf.Plane.Normal;
}
//точка для ЛСК, координаты для положения вычисляются после выбора всех граней
var nd3D = new CoordinateNode3D(currentDocument)
{
    X = otLSK.Geometry.Origin.X*1000,
    Y = otLSK.Geometry.Origin.Y*1000,
    Z = otLSK.Geometry.Origin.Z*1000
};
//ЛСК для КТЭ                   
var lks = new PointsLCS(currentDocument)
{
    Name = insKTE.LSKname,
    Color = 13,
    PointToOrigin = nd3D.Geometry.Point
};
//доворот ЛСК
var transformations = lks.Transformations.AddBaseTransfGroup();
transformations.SetLCS(otLSK, false);
transformations.TransfContainer.SourceCSType = TransformationLCSType.CenterOfBoundBox;
transformations.Name = insKTE.Name + "_MoveRotate";

и вот тут нужно понять, как перевернуть оси.
Я уже не знаю, как это еще объяснить, если опять не понятно.
 
Вы создаете 3D узел по аналогии с операцией "По граням и смещениям", или что-то другое?
Изменено: Vite - 16.10.2015 16:16:59
 
Если я правильно понял, то нужно вставить фрагмент и чтоб он встал в тело и вычился?
То это эквивалент операции отверстие. Может просто положить все такие тела в базу, а програмно использовать операцию отверстие с выбранным фрагментом?
Ушёл остывать)
 
Вот не обязательно вычитание. Отверстие - это как пример, а могут быть и более сложные элементы, а также не только вычитание, но и сложение.
 
Цитата
Vite написал:
Вы создаете 3D узел по аналогии с операцией "По граням и смещениям", или что-то другое?
ммм, ну по факту так и получается, грань, накоторой эта точка будет и потом расстояния от других граней, все это потом через пересчет в ГСК и постановка точки в этих координатах. Просто расчеты не приводила тут, а сразу задание точки.
 
@Batarejka, класс PointsLCS поддерживает свойства:
- PointToOrigin (Точка, задающая начало системы координат)
- DirectionToAxisX (Направление задающее ось Х)
- DirectionToAxisY (Направление задающее ось Y)

Это то что Вам нужно, для определения нормали.

Код
namespace Test
{
    public class Class4
    {
        public static void Run()
        {
            Document document = TFlex.Application.ActiveDocument;
            document.BeginChanges("Create LCS");

            // ..

            CoordinateNode3D n3D = new CoordinateNode3D(document);
            n3D.X = 0;
            n3D.Y = 0;
            n3D.Z = 0;

            PointsLCS pointsLCS = new PointsLCS(document);
            pointsLCS.PointToOrigin = n3D.Geometry.Point;
            //pointsLCS.DirectionToAxisX = /* Направление оси X (грань) */
            //pointsLCS.DirectionToAxisY = /* Направление оси Y (ребро) */

            // ..

            document.EndChanges();
        }
    }
}
LCS_params.PNG (7.09 КБ)
 
Ага, спасибо, туда я почему-то не долезла. Но, все равно остается открытым вопрос с этим кодом.
Цитата
Vite написал:
//pointsLCS.DirectionToAxisX = /* Направление оси X (грань) */
//pointsLCS.DirectionToAxisY = /* Направление оси Y (ребро) */
Собственно сами значения какие указывать? У меня по факту есть три выбранные грани PlaneSurface. Как инфу из них можно использовать для направления осей в нужную мне сторону.
 
Когда я пытаюсь сделать следующее
pointsLCS.DirectionToAxisX = SelectedPlane.Plane.Normal;

То получаю ошибку невозможно преобразовать BaseDirection к ModelDirection.
Как все это делать руками я прекрасно вижу. Но если абстрагироваться от этого и представить, что есть только три выбранные грани и расстояния от двух. И вот как тут построить правильно ЛСК. Хочу ось Z перпендикулярно грани, а не X :nono: Хотя уже и на Х согласна, лишь бы всегда перпендикулярно и от тела была направлена.
 
@Batarejka,
- Свойство DirectionToAxisX принимает значение свойства PlaneDirection, класса TFlex.Model.Model3D.Geometry.ModelFace.GeometryData
- Свойство DirectionToAxisY принимает значение свойства LineDirection, класса TFlex.Model.Model3D.Geometry.ModelEdge.GeometryData
Изменено: Vite - 20.10.2015 17:55:33
 
Vite,да, с этим я уже разобралась. На шаг раньше нормаль получать просто нужно, с ModelFace, а не PlaneSurface.
В класс, описывающий вставляемый элемент, хотела добавить свойство типа ModelFace и хранить ссылку на поверхность, на которую вставляется элемент. Только вот при выполнении выдается ошибка "Объект был удален. Ссылки на объекты модели не должны сохраняться". Получается, что просто сохранить и передавать ссылку на грань я не могу?
Изменено: Batarejka - 21.10.2015 09:34:43
 
Цитата
Batarejka написал:
Получается, что просто сохранить и передавать ссылку на грань я не могу?

Для определения свойства DirectionToAxisX, необходимо получить структуру данных PlaneDirection, в контексте выделенной грани. Что представляет собой "Грань" в структуре модели?
Свойство GroupType определено как TFlex.Model.ObjectType.Topol (Топологический элемент: грань, цикл, ребро, вершина).

Структура данных в контексте выделенной грани:
TFlex.Model.ModelObject[0]
- TFlex.Model.Model3D.TopolReference
-- Topol (TFlex.Model.Model3D.Geometry.ModelFace)
--- Geometry (TFlex.Model.Model3D.Geometry.ModelFace.GeometryData)
---- PlaneDirection (TFlex.Model.Model3D.Geometry.ModelDirection)

Код
using TFlex.Model;
using TFlex.Model.Model3D;
using TFlex.Model.Model3D.Geometry;

namespace Test
{
    public class Class4
    {
        public static void Run()
        {
            Document document = TFlex.Application.ActiveDocument;
            document.BeginChanges("Create LCS");

            CoordinateNode3D n3D = new CoordinateNode3D(document);
            
            n3D.X = 0;
            n3D.Y = 0;
            n3D.Z = 0;

            PointsLCS pointsLCS = new PointsLCS(document);

            foreach (TopolReference topolRef in document.Selection.GetAllObjects())
            {
                pointsLCS.PointToOrigin = n3D.Geometry.Point;

                ModelFace face = (ModelFace)topolRef.Topol;

                if (face != null)
                {
                    pointsLCS.DirectionToAxisX = face.Geometry.PlaneDirection;
                }
            }

            document.EndChanges();
        }
    }
}


Если я не ошибаюсь, класс OnFaceOffsetPoint реализует аналог функции "По граням и смещениям".
Изменено: Vite - 22.10.2015 07:16:22
Страницы: 1