Нахождение касательной к примитивам

Т.к. все отрезки, дуги, полилинии - потомки от Curve, то к ним можно применять метод GetFirstDerivative. Но почему то с некоторыми участками полилинии это не работает. Выдается вектор отзеркаленный по оси y.

if ( resultPnt.Status == PromptStatus.OK)// если точка получена {
// получаем линейный объект на котором расположена точка по ID
NativePlatform.DatabaseServices.Entity lineObj =
tr.GetObject(SelectFilteredObjectsInWindow(resultPnt.Value), OpenMode.ForWrite) as NativePlatform.DatabaseServices.Entity;
// принимаем объект как кривую и находим касательную
NativePlatform.Geometry.Vector3d tempVector = (lineObj as Curve).GetFirstDerivative(resultPnt.Value);
//получаем угол вектора по отношению к оси Х
double angle = tempVector.GetAngleTo(NativePlatform.Geometry.Vector3d.XAxis);
editor.WriteMessage(
$“\nУгол = {angle}.”);

// Завершаем транзакцию
tr.Commit();
return (angle, resultPnt.Value);// угол, точка
}

Часто первый и последний участок неправильно работают, а когда обращаю полилинию (меняю направление), то неправильноработающие участки начинают работать правильно, а правильно работавшие, начинают работать неправильно.

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

У меня просто функция dll, сделанная под БИМ Строительство 25, работающая с моими параметрическими объектами из базы ))), она у вас не заработает. Дайте пару дней, я напишу под обычный Нанокад и выложу.

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

Кстати, утверждение, что “все отрезки, дуги, полилинии - потомки от Curve”, подтверждается. Тест работает одинаково на всех отрезках полилиний, а также дугах, окружностях, сплайнах, спиралях, эллипсах.

1 лайк

Может вы свой файл dll выложите, я протестирую у себя

Здесь весь проект
TestCurve.zip (99,7 КБ)

У меня на компьютере при запуске команды “TEST“ выдает ошибку -

test - test
Command started

Ошибка 25 (Illegal entity type)
GetPipe
Command ended, 0 ms

Ни метода, ни типа GetPipe в коде команды TEST нет. Используйте отладчик для изучения проблемы.

Предположу, что Вы пытаетесь применить команду к объекту, который отфильтровывается в коде (строка 78). Попробуйте отключить фильтр, присвоив, например, filter=null. С объектом “Трасса” у меня это получилось.

Ларчик просто открывался, TEST уже было зарезервировано, сменил в коде на TESTTEST, заработало))

ничего не могу понять, мистика вот ваш код

Vector3d tempVector = (lineObj as Curve).GetFirstDerivative(StartPoint);
double rangle = tempVector.GetAngleTo(Vector3d.XAxis);
double angle = rangle * 180 / Math.PI;
editor.WriteMessage($“\nПроизводная = {tempVector}.”);
editor.WriteMessage($“\nУгол = {angle}.”);

вот мой

NativePlatform.Geometry.Vector3d tempVector = (lineObj as Curve).GetFirstDerivative(resultPnt.Value);
//получаем угол вектора по отношению к оси Х
double angle = tempVector.GetAngleTo(NativePlatform.Geometry.Vector3d.XAxis);
double angle1 = angle*180/Math.PI;
editor.WriteMessage(
$“\nУгол = {angle1}.”);

у меня почему то если У начальной точки больше У конечной точки отрезка, то выдает неправильный угол = 360-правильный угол

а у вас все правильно работает

Как выглядят в сравнении первые производные, т.е. tempVector, в одной и той же точке и у одного и того же lineObj? Желательно их вывести в WriteMessage.

Понял, функция

double rangle = tempVector.GetAngleTo(Vector3d.XAxis);

никогда не выдает угол больше 180 градусов, поэтому если отрезок направлен слева верх в право вниз, должен быть угол больше 180, а выдается угол меньше 180

Существует две основные перегрузки этого метода:

1. Простая форма (между двумя векторами)

public double GetAngleTo(Vector3d vector)

  • Что делает: Возвращает кратчайший угол между текущим вектором и переданным в качестве аргумента.

  • Диапазон: От 0 до π (от 0° до 180°).

  • Особенность: Метод всегда возвращает минимальный положительный угол, независимо от порядка векторов.

2. С использованием опорного вектора

public double GetAngleTo(Vector3d vector, Vector3d refVec)

  • Что делает: Вычисляет угол в плоскости, перпендикулярной опорному вектору refVec.

  • Диапазон: От 0 до 2π (от 0° до 360°).

  • Особенность: Позволяет определить направление угла (по часовой или против часовой стрелки) относительно заданного направления. Если результат векторного произведения двух исходных векторов сонаправлен с refVec, возвращается обычный угол, иначе — минус этот угол.

если бы не ваш пример, я бы долго разбирался, хотел уже все переписывать )))

если угол может быть больше 180, нужно проверить направление вектора касательной, если y < 0, то угол будет больше 180

if (tempVector[1] < 0) angle = Math.PI*2-angle;