Оценка объектов в процессе выбора пользователем

Автор Тема: Оценка объектов в процессе выбора пользователем  (Прочитано 3979 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн PhilАвтор темы

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Доброго времени суток! Для правильной работы моей задачи необходима фильтрация объектов на этапе выбора их пользователем не только по типу, но и по свойствам. Необходимые для выбора объекты: отрезки или линейные сегменты незамкнутых 2d полилиний, ненулевой длины. Написал код, основываясь на общем для нужных типов объектов классе - Curve. Очень не хотелось писать отдельные функции для каждого типа в отдельности. Но может уважаемые гуру предложат более рациональный и короткий способ оценки? Буду очень признателен.

Основная процедура оценки:
Код - vb.net [Выбрать]
  1.     Private Sub EventOnEditorSelectCurves(ByVal Sender As Object,
  2.                                           ByVal acResultArgs As PromptForEntityEndingEventArgs)
  3.  
  4.         '' Объявление внутренних переменных
  5.         Dim acSelObjId As ObjectId = acResultArgs.Result.ObjectId
  6.         Dim acSelObjPnt As Point3d = acResultArgs.Result.PickedPoint
  7.         Dim acAllowObject As Boolean = (acSelObjId <> Nothing)
  8.         If Not acAllowObject Then Return
  9.  
  10.         '' Проверка типа объекта:
  11.         ''     допустимые объекты: Line, Polyline, Polyline2d
  12.         Dim acValidTypes() As Type = {GetType(Line), GetType(Polyline), GetType(Polyline2d)}
  13.         acAllowObject = CheckTypes(acSelObjId, acValidTypes)
  14.         If Not acAllowObject Then GoTo lexit
  15.  
  16.         '' Получение примитива по его ObjectId как CURVE
  17.         Dim acEntity As Entity = GetEntityFromId(acSelObjId)
  18.         acAllowObject = TypeOf acEntity Is Curve
  19.         Dim acCurve As Curve = CType(acEntity, Curve)
  20.  
  21.         '' Оценка свойств примитива как CURVE ...
  22.         '' ... вычисление длины кривой в целом:
  23.         ''     кривая из одного сегмента должна быть ненулевой длины
  24.         Dim acDeltaParam = acCurve.EndParam - acCurve.StartParam
  25.         acAllowObject = Not acCurve.StartPoint.IsEqualTo(acCurve.EndPoint) And
  26.         acAllowObject = acAllowObject And (acDeltaParam < 2)
  27.         acAllowObject = acAllowObject Or (acDeltaParam > 1)
  28.         If Not acAllowObject Then GoTo lexit
  29.  
  30.         '' ... кривая не должна быть замкнутой:
  31.         ''     замкнутые кривые /именно по свойству CLOSED/ не подходят по условию задачи
  32.         acAllowObject = Not acCurve.Closed
  33.         If Not acAllowObject Then GoTo lexit
  34.  
  35.         '' ... вычисление номера выделенного сегмента
  36.         Dim acPointOnCurve As Point3d = acCurve.GetClosestPointTo(acSelObjPnt, False)
  37.         Dim acPointParam As Double = acCurve.GetParameterAtPoint(acPointOnCurve)
  38.         Dim acSegmentId As Integer = Math.Floor(acPointParam)
  39.  
  40.         '' ... вычисление длины кривой на участке выделенного сегмента:
  41.         ''     длина кривой на выделенном сегменте не должна быть нулевой
  42.         Dim acStartDist As Double = acCurve.GetDistanceAtParameter(acSegmentId)
  43.         Dim acEndDist As Double = acCurve.GetDistanceAtParameter(acSegmentId + 1)
  44.         Dim acCurveLength = acEndDist - acStartDist
  45.  
  46.         acAllowObject = acCurveLength > 0
  47.         If Not acAllowObject Then GoTo lexit
  48.  
  49.         '' ... вычисление расстояния от начальной точки сегмента до конечной:
  50.         ''     по условиям выбранный сегмент должен быть отрезком
  51.         ''     /длина вдоль сегмента равна расстоянию между его концами/
  52.         Dim acStartPoint As Point3d = acCurve.GetPointAtParameter(acSegmentId)
  53.         Dim acEndPoint As Point3d = acCurve.GetPointAtParameter(acSegmentId + 1)
  54.         Dim acChordLength As Double = acStartPoint.DistanceTo(acEndPoint)
  55.  
  56.         acAllowObject = (acCurveLength - acChordLength) < Tolerance.Global.EqualPoint
  57.  
  58. lexit:  '' Если оценка отрицательная объекта - удаляем примитив из выбора
  59.         If Not acAllowObject Then acResultArgs.RemoveSelectedObject()
  60.  
  61.     End Sub


Вспомогательные функции:
Код - vb.net [Выбрать]
  1.     Public Function GetEntityFromId(ByVal acObjectId As ObjectId) As Entity
  2.  
  3.         '' Объявление внутренних переменных
  4.         Dim acEntity As Entity
  5.  
  6.         '' Выполняем доступ к объекту по его ObjectId
  7.         Using acTransaction As Transaction = acObjectId.Database.TransactionManager.StartTransaction()
  8.             acEntity = acTransaction.GetObject(acObjectId, OpenMode.ForRead)
  9.             acTransaction.Commit()
  10.         End Using
  11.  
  12.         '' Возвращаем ссылку на примитив
  13.         Return acEntity
  14.  
  15.     End Function
  16.  
  17.     Private Function CheckType(ByVal ObjId As ObjectId,
  18.                                ByVal acType As Type) As Boolean
  19.         Return ObjId.ObjectClass.IsDerivedFrom(RXClass.GetClass(acType))
  20.     End Function
  21.  
  22.     Private Function CheckTypes(ByVal ObjId As ObjectId,
  23.                                 ByVal acTypes() As Type) As Boolean
  24.         Dim acResult As Boolean = False
  25.         For Each acType In acTypes
  26.             acResult = CheckType(ObjId, acType)
  27.             If acResult Then Exit For
  28.         Next
  29.         Return acResult
  30.     End Function

/* Спойлеры убрал - код в котором меньше 300 строк не нужно заключать в спойлер. Александр Ривилис */
« Последнее редактирование: 15-03-2018, 22:27:17 от Александр Ривилис »

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 806
  • Карма: 166
    • Мои плагины к Автокаду
Не очень понятно, что собственно требуется. Не берусь судить код на бейсике (жуткие воспоминания...), но подход-то верный - все что можно оценить по свойствам общего предка, а потом уже по мере необходимости разбираться со свойствами присущими только наследникам.

Оффлайн PhilАвтор темы

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Требуется на выходе получить:
1. Отрезки Line или полилинии Polyline или Polyline2d
2. Если получена полилиния - она должна быть незамкнутой (Closed = false)
3. Если получена полилиния - определить указанный сегмент
4. Полученный сегмент должен быть линейным (не дуга)
5. Полученные сегменты или отрезки должны быть ненулевой длины

Не нашел адекватный конвертер с VB.NET на C#... Вообще можно было бы написать на последнем, но у меня наработана определенная база кода, перекодировать некогда...

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Phil
Функция GetEntityFromId потенциально очень плоха и может приводить к Fatal Error. Ты открываешь транзакцию, по ObjectId примитива получаешь Entity и (внимание!!!) транзакцию закрываешь. В этот момент Entity становится недействительной. Т.е. пользоваться Entity можно только внутри транзакции и никак иначе!!!
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн PhilАвтор темы

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Phil
Функция GetEntityFromId потенциально очень плоха и может приводить к Fatal Error. Ты открываешь транзакцию, по ObjectId примитива получаешь Entity и (внимание!!!) транзакцию закрываешь. В этот момент Entity становится недействительной. Т.е. пользоваться Entity можно только внутри транзакции и никак иначе!!!
Благодарю! Есть ли какая-то возможность пользоваться информационными функциями объекта по его ObjectId, не меняющими его свойства ?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Есть ли какая-то возможность пользоваться информационными функциями объекта по его ObjectId, не меняющими его свойства ?
Я не знаю что такое "информационные функции объекта". Давай как-то попроще с терминологией. :-)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн PhilАвтор темы

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Я не знаю что такое "информационные функции объекта". Давай как-то попроще с терминологией. :-)
Простите, сложно выражать свои мысли (или их отсутствие) ближе к полуночи... Функции и свойства, которые я использовал через Entity, приводя к типу Curve. Можно ли не получая Curve как-то добраться до вершин, сегментов и прочего на основе ObjectId ?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Можно ли не получая Curve как-то добраться до вершин, сегментов и прочего на основе ObjectId ?
Нет. Тебе нужно использовать транзакцию не внутри функции, а где-то снаружи. Кстати и работать будет быстрее - всего одна транзакция, а не по транзакции на каждый ObjectId.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Поворчу... а зачем вообще нужна отдельная функция GetEntityFromId?
Так разве не проще?
Код - C# [Выбрать]
  1. Db.Solid3d solid1 = objectId.Open(Db.OpenMode.ForRead) as Db.Solid3d;

По поводу фильтрации... может попробовать как то так (код не проверял):
Код - C# [Выбрать]
  1.             Db.TypedValue[] tv = new Db.TypedValue[5];
  2.             tv.SetValue(new Db.TypedValue((int)Db.DxfCode.Operator, "<AND"), 0);
  3.             tv.SetValue(new Db.TypedValue((int)Db.DxfCode.Start, "*LINE,CIRCLE"), 1);
  4.             tv.SetValue(new Db.TypedValue((int)Db.DxfCode.LayerName, "*"), 2);
  5.             tv.SetValue(new Db.TypedValue((int)70, 0), 3); // незамкнутая полилиния
  6.             tv.SetValue(new Db.TypedValue((int)Db.DxfCode.Operator, "AND>"), 4);
  7.  
  8.             Ed.SelectionFilter sf = new Ed.SelectionFilter(tv);
  9.  
  10.             Ed.PromptSelectionResult psr = ed.GetSelection(sf);
  11.             if (psr.Status != Ed.PromptStatus.OK) return;

Оффлайн PhilАвтор темы

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Поворчу... а зачем вообще нужна отдельная функция GetEntityFromId?
Так разве не проще?
Благодарю за напоминание :) Читал, но практики использования не было, забыл...
По поводу фильтрации... может попробовать как то так (код не проверял):
Можно конечно и так, но мне не слишком нравится достаточно большая негибкость в задании условий.  Мне нужно не просто выбрать отрезок или незамкнутую полилинию, но отрезок или сегмент полилинии, который был бы отрезком ненулевой длины. И потом, Если я хочу ввести подсказки по поводу правильного/неправильного выбора или иные действия по мере выбора, приведенного выше подхода будет мало.

Оффлайн PhilАвтор темы

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Phil
Функция GetEntityFromId потенциально очень плоха и может приводить к Fatal Error. Ты открываешь транзакцию, по ObjectId примитива получаешь Entity и (внимание!!!) транзакцию закрываешь. В этот момент Entity становится недействительной. Т.е. пользоваться Entity можно только внутри транзакции и никак иначе!!!
Да, кстати, при каких условиях может наступить крах или иная ошибка? Понимаю. что согласно справке это некорректно, но я уже работал с Entity описанным образом и вне транзакции, читая свойства Entity, но ничего в них не меняя. Все успешно работало...

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
Да, кстати, при каких условиях может наступить крах или иная ошибка?
В любой момент может произойти уборка "мусора", это не прогнозируется и не контролируется. Соответственно и объект может в любой момент быь уничтожен.

Оффлайн PhilАвтор темы

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Добрый день! Нашел несколько ошибок и слабых мест, переписал код для выбора отрезка или сегмента полилинии по следующим критериям:
  1. Отрезки Line или полилинии Polyline, Polyline2d или Polyline3d
  2. Если получена полилиния - она должна быть незамкнутой (Closed = false)
  3. Если получена полилиния - определить указанный сегмент
  4. Полученный сегмент должен быть линейным (не дуга)
  5. Полученные сегменты или отрезки должны быть ненулевой длины
При написании кода старался минимально привязываться к свойствам конкретных классов, пользоваться методами только общего предка Curve. К сожалению, поведение классов Line и Polyline в отношении Parameter существенно отличается (у первого Parameter = Distance = Length, у второго - 0 <= Parameter <= 1) пришлось написать 2 функции-костыля. На выходе из процедуры получаем концевые точки выбранного отрезка/сегмента полилинии. Выкладываю код, может кому-то понадобится, а может будут предложения по его улучшению.

Основная процедура:

Код - vb.net [Выбрать]
  1.     Private Sub QueryLine(ByVal acEditor As Editor,
  2.                           ByRef acPoint_1 As Point3d,
  3.                           ByRef acPoint_2 As Point3d,
  4.                           ByRef acCommandSuccess As Boolean)
  5.  
  6.         '' Объявление внутренних констант
  7.         Const acSelectMessage As String = vbCrLf & "Выберите отрезок или линейный сегмент плоской полилинии : "
  8.         Const acRejectMessage As String = vbCrLf & "Выбран объект недопустимого типа ..."
  9.  
  10.         '' Определение параметров запроса ПРИМИТИВА
  11.         Dim prmtEntityOpts As PromptEntityOptions = New PromptEntityOptions("")
  12.         prmtEntityOpts.Message = acSelectMessage
  13.         prmtEntityOpts.SetRejectMessage(acRejectMessage)
  14.         prmtEntityOpts.AllowNone = False
  15.         prmtEntityOpts.AllowObjectOnLockedLayer = True
  16.  
  17.         '' Выполнение запроса ПРИМИТИВА
  18.         Dim acEventSelection = New PromptForEntityEndingEventHandler(AddressOf EventOnEditorSelectCurves)
  19.         AddHandler acEditor.PromptForEntityEnding, acEventSelection
  20.  
  21.         Dim prmtEntityResult As PromptEntityResult = acEditor.GetEntity(prmtEntityOpts)
  22.         RemoveHandler acEditor.PromptForEntityEnding, acEventSelection
  23.  
  24.         '' Оценка успешности выполнения запроса
  25.         acCommandSuccess = prmtEntityResult.Status = PromptStatus.OK
  26.         If Not acCommandSuccess Then Return
  27.  
  28.         '' Вычисление выбранного концов отрезки или сегмента полилинии:
  29.         '' ... фильтр пропустил бы только подходящие по условиям примитивы
  30.         Dim acSelObjId As ObjectId = prmtEntityResult.ObjectId
  31.         Dim acSelObjPnt As Point3d = prmtEntityResult.PickedPoint
  32.         acSelObjPnt = ConvertPoint(acEditor, acSelObjPnt)
  33.  
  34.         Using acTrans As Transaction =
  35.             acSelObjId.Database.TransactionManager.StartTransaction()
  36.  
  37.             '' Получение примитива по его ObjectId как CURVE
  38.             Dim acEntity As Entity = acTrans.GetObject(acSelObjId, OpenMode.ForRead)
  39.             Dim acCurve As Curve = CType(acEntity, Curve)
  40.  
  41.             Dim acViewVector As Vector3d = GetViewDirection(acEditor)
  42.             Dim acPointOnCurve As Point3d = acCurve.GetClosestPointTo(acSelObjPnt, acViewVector, False)
  43.             Dim acSegmentStart As Double = GetCurveSegmentStart(acCurve, acPointOnCurve)
  44.             Dim acSegmentEnd As Double = GetCurveSegmentEnd(acCurve, acPointOnCurve)
  45.  
  46.             acPoint_1 = acCurve.GetPointAtParameter(acSegmentStart)
  47.             acPoint_2 = acCurve.GetPointAtParameter(acSegmentEnd)
  48.  
  49.             acTrans.Commit()
  50.         End Using
  51.     End Sub

Процедура обработки события выбора примитива

Код - vb.net [Выбрать]
  1.     Private Sub EventOnEditorSelectCurves(ByVal Sender As Object,
  2.                                           ByVal acResultArgs As PromptForEntityEndingEventArgs)
  3.  
  4.         '' Объявление внутренних постоянных
  5.         Const msg_Correct_Object_Required = "Выбран неверный объект или неверная точка указания объекта." & vbCrLf &
  6.                                             "Необходимо выбрать отрезок или линейный сегмент плоской полилинии." & vbCrLf &
  7.                                             "Выбранный объект должен иметь ненулевую длину."
  8.         '' Объявление внутренних переменных
  9.         Dim acEditor As Editor = CType(Sender, Editor)
  10.         Dim acSelObjId As ObjectId = acResultArgs.Result.ObjectId
  11.         Dim acSelObjPnt As Point3d = acResultArgs.Result.PickedPoint
  12.  
  13.         Dim acAllowObject As Boolean = (acSelObjId <> Nothing)
  14.         If Not acAllowObject Then Return
  15.  
  16.         '' Конвертируем точку примитиво-указания
  17.         acSelObjPnt = ConvertPoint(acEditor, acSelObjPnt)
  18.  
  19.         '' Проверка типа объекта:
  20.         ''     допустимые объекты: Line, Polyline, Polyline2d
  21.         Dim acValidTypes() As Type = {GetType(Line), GetType(Polyline), GetType(Polyline2d), GetType(Polyline3d)}
  22.         acAllowObject = CheckTypes(acSelObjId, acValidTypes)
  23.         If Not acAllowObject Then GoTo lexit
  24.  
  25.         '' Старт транзакции для работы с объектами чертежа
  26.         Using acTrans As Transaction =
  27.             acSelObjId.Database.TransactionManager.StartTransaction()
  28.  
  29.             '' Получение примитива по его ObjectId как CURVE
  30.             Dim acEntity As Entity = acTrans.GetObject(acSelObjId, OpenMode.ForRead)
  31.             Dim acCurve As Curve = CType(acEntity, Curve)
  32.  
  33.             '' Оценка свойств примитива как CURVE ...
  34.             '' ... вычисление длины кривой в целом:
  35.             ''     кривая из одного сегмента должна быть ненулевой длины
  36.             Dim acDist_1 = acCurve.GetDistanceAtParameter(acCurve.StartParam)
  37.             Dim acDist_2 = acCurve.GetDistanceAtParameter(acCurve.EndParam)
  38.             acAllowObject = (acDist_2 - acDist_1) > 0
  39.             If Not acAllowObject Then GoTo lexit
  40.  
  41.             '' ... кривая не должна быть замкнутой:
  42.             ''     замкнутые кривые /именно по свойству CLOSED/ не подходят по условию задачи
  43.             acAllowObject = Not acCurve.Closed
  44.             If Not acAllowObject Then GoTo lexit
  45.  
  46.             '' ... вычисление номера выделенного сегмента
  47.             Dim acViewVector As Vector3d = GetViewDirection(acEditor)
  48.             Dim acPointOnCurve As Point3d = acCurve.GetClosestPointTo(acSelObjPnt, acViewVector, False)
  49.             Dim acSegmentStart As Double = GetCurveSegmentStart(acCurve, acPointOnCurve)
  50.             Dim acSegmentEnd As Double = GetCurveSegmentEnd(acCurve, acPointOnCurve)
  51.             acAllowObject = acSegmentEnd > acSegmentStart
  52.             If Not acAllowObject Then GoTo lexit
  53.  
  54.             '' ... вычисление длины кривой на участке выделенного сегмента:
  55.             ''     длина кривой на выделенном сегменте не должна быть нулевой
  56.             Dim acStartDist As Double = acCurve.GetDistanceAtParameter(acSegmentStart)
  57.             Dim acEndDist As Double = acCurve.GetDistanceAtParameter(acSegmentEnd)
  58.             Dim acCurveLength = acEndDist - acStartDist
  59.  
  60.             acAllowObject = acCurveLength > 0
  61.             If Not acAllowObject Then GoTo lexit
  62.  
  63.             '' ... вычисление расстояния от начальной точки сегмента до конечной:
  64.             ''     по условиям выбранный сегмент должен быть отрезком
  65.             ''     /длина вдоль сегмента равна расстоянию между его концами/
  66.             Dim acStartPoint As Point3d = acCurve.GetPointAtParameter(acSegmentStart)
  67.             Dim acEndPoint As Point3d = acCurve.GetPointAtParameter(acSegmentEnd)
  68.             Dim acChordLength As Double = acStartPoint.DistanceTo(acEndPoint)
  69.  
  70.             acAllowObject = (acCurveLength - acChordLength) <= Tolerance.Global.EqualPoint
  71.             If Not acAllowObject Then GoTo lexit
  72.  
  73.             acTrans.Commit()
  74.         End Using
  75.  
  76.         '' Если объект удовлетворяет всем условиям - выход из функции
  77.         Return
  78.  
  79. lexit:  '' Если оценка отрицательная объекта - удаляем примитив из выбора
  80.         acResultArgs.RemoveSelectedObject()
  81.         EditorMsg(acEditor, msg_Correct_Object_Required)
  82.  
  83.     End Sub

Вспомогательные функции

Код - vb.net [Выбрать]
  1.     '' Конвертация координат точки из ТЕКУЩЕЙ СК в МИРОВУЮ СК
  2.     Public Function ConvertPoint(ByVal acEditor As Editor,
  3.                                  ByVal acPoint As Point3d) As Point3d
  4.  
  5.         '' Получение текущей ТЕКУЩЕЙ СК
  6.         Dim acCurrentCS As CoordinateSystem3d =
  7.             acEditor.CurrentUserCoordinateSystem.CoordinateSystem3d
  8.  
  9.         '' Получение матрицы перевода из ТЕКУЩЕЙ СК в МИРОВУЮ СК
  10.         Dim acMatrix_WCS = New Matrix3d()
  11.         acMatrix_WCS = Matrix3d.AlignCoordinateSystem(Point3d.Origin,
  12.                                                       Vector3d.XAxis,
  13.                                                       Vector3d.YAxis,
  14.                                                       Vector3d.ZAxis,
  15.                                                       acCurrentCS.Origin,
  16.                                                       acCurrentCS.Xaxis,
  17.                                                       acCurrentCS.Yaxis,
  18.                                                       acCurrentCS.Zaxis)
  19.         '' Возврат трансформированной точки с координатами
  20.         '' опорной точки из ТЕКУЩЕЙ СК в МИРОВУЮ
  21.         Return acPoint.TransformBy(acMatrix_WCS)
  22.  
  23.     End Function
  24.  
  25.     '' Определение вектора "направления взгляда"
  26.     Private Function GetViewDirection(ByVal acEditor As Editor) As Vector3d
  27.  
  28.         Dim acUCS As Matrix3d = acEditor.CurrentUserCoordinateSystem
  29.         Dim acViewPoint As Point3d = Application.GetSystemVariable("VIEWDIR")
  30.         Dim acViewVector As Vector3d = (acViewPoint - Point3d.Origin).TransformBy(acUCS).GetNormal()
  31.  
  32.         Return acViewVector
  33.     End Function
  34.  
  35.     '' Определение принадлежности кривой к классу отрезков
  36.     Private Function IsLine(ByVal acCurve As Curve) As Boolean
  37.         Return (TypeOf acCurve Is Line)
  38.     End Function
  39.  
  40.     '' Определение принадлежности кривой к классу полилиний
  41.     Private Function IsPolyline(ByVal acCurve As Curve) As Boolean
  42.         Return (TypeOf acCurve Is Polyline) Or
  43.                (TypeOf acCurve Is Polyline2d) Or
  44.                (TypeOf acCurve Is Polyline3d)
  45.     End Function
  46.  
  47.     '' Определение параметра начала отрезка или сегмента полилинии
  48.     Private Function GetCurveSegmentStart(ByVal acCurve As Curve,
  49.                                           ByVal acPickPoint As Point3d) As Integer
  50.         If IsPolyline(acCurve) Then
  51.             Dim acParam = Math.Floor(acCurve.GetParameterAtPoint(acPickPoint))
  52.             If acParam = acCurve.EndParam Then acParam -= 1
  53.             Return acParam
  54.         ElseIf IsLine(acCurve) Then
  55.             Return acCurve.StartParam
  56.         Else
  57.             Return -1
  58.         End If
  59.     End Function
  60.  
  61.     '' Определение параметра конца отрезка или сегмента полилинии
  62.     Private Function GetCurveSegmentEnd(ByVal acCurve As Curve,
  63.                                           ByVal acPickPoint As Point3d) As Integer
  64.         If IsPolyline(acCurve) Then
  65.             Dim acParam = Math.Ceiling(acCurve.GetParameterAtPoint(acPickPoint))
  66.             If acParam = acCurve.StartParam Then acParam += 1
  67.             Return acParam
  68.         ElseIf IsLine(acCurve) Then
  69.             Return acCurve.EndParam
  70.         Else
  71.             Return -1
  72.         End If
  73.     End Function
  74.  
  75.     Private Function CheckType(ByVal ObjId As ObjectId,
  76.                                ByVal acType As Type) As Boolean
  77.         Return ObjId.ObjectClass.IsDerivedFrom(RXClass.GetClass(acType))
  78.     End Function
  79.  
  80.     Private Function CheckTypes(ByVal ObjId As ObjectId,
  81.                                 ByVal acTypes() As Type) As Boolean
  82.         Dim acResult As Boolean = False
  83.         For Each acType In acTypes
  84.             acResult = CheckType(ObjId, acType)
  85.             If acResult Then Exit For
  86.         Next
  87.         Return acResult
  88.     End Function

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Функция ConvertPoint переусложнена. Там можно всё в одну строку записать:
Код - vb.net [Выбрать]
  1. Return acPoint.TransformBy(acEditor.CurrentUserCoordinateSystem))
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение