SelectCrossingPolygon. Как отловить некорректный контур?

Автор Тема: SelectCrossingPolygon. Как отловить некорректный контур?  (Прочитано 26492 раз)

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Небрежность в чистом виде. В этом случае можно было обойтись стандартным прямоугольным ВЭ.

Оффлайн Константин Виноградов

  • ADN OPEN
  • Сообщений: 12
  • Карма: 2
Здравствуйте. В первом посту данной теме нашел для себя интересный код, для выбора объектов внутри полилинии. Пытался его реализовать для замкнутой полилинии состоящей из 4х точек.
При выполнении метода tr.Commit(), отладчик выдает сообщение "ArgumentNullException was unhandled by user code". Пытался найти причину неприятности, по поиск оказался безуспешным.
Единственное обратил внимание, что объект gripPts, после выполнения метода pline.GetGripPoints остался пустым. Помогите пожалуйста решить мою проблему.

                Polyline pline = tr.GetObject(plineId, OpenMode.ForRead) as Polyline;               
                pline.GetGripPoints(gripPts, new IntegerCollection(), new IntegerCollection());
                tr.Commit();

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
По куску кода непонятно, давайте весь метод.
Навскидку - может объект не полилиния, может коллекцию забыли создать для gripPts.

Оффлайн Константин Виноградов

  • ADN OPEN
  • Сообщений: 12
  • Карма: 2
Виноват, но не хотел грузить форум лишним текстом. И еще я код адаптировал под visual basic.net. Проблемный участок находится на строчках 36-39.


Код - vb.net [Выбрать]
  1.   Public Sub GetAddressList(ByVal ed As Editor)
  2.     Dim doc As Document = Application.DocumentManager.MdiActiveDocument
  3.     Dim db As Database = doc.Database
  4.     Dim MyT As Transaction = db.TransactionManager.StartTransaction()
  5.  
  6.     Dim values() As TypedValue = {New TypedValue(DxfCode.ExtendedDataRegAppName, "PLCHOUSENUMBER"), _
  7.     New TypedValue(DxfCode.LayoutName, "MODEL")}
  8.     Dim sfilter As New SelectionFilter(values)
  9.     Dim Res As PromptSelectionResult
  10.     ed.WriteMessage(vbLf & "Выберите дома для нового кластера.")
  11.     ed.UpdateScreen()
  12.  
  13.     Dim pKeyOpts As PromptKeywordOptions = New PromptKeywordOptions("")
  14.     pKeyOpts.Message = vbLf & "Каким методом выбора объекта вы хотите воспользоваться?"
  15.     pKeyOpts.Keywords.Add("Полигон")
  16.     pKeyOpts.Keywords.Add("Одиночно")
  17.     pKeyOpts.AllowNone = False
  18.     Dim pKeyRes As PromptResult = ed.GetKeywords(pKeyOpts)
  19.  
  20.     Select Case pKeyRes.StringResult
  21.       Case "Полигон"
  22.         Dim entOpt As PromptEntityOptions
  23.         entOpt = New PromptEntityOptions("\nВыберите полилинию:")
  24.         entOpt.SetRejectMessage("Это не полилиния!")
  25.         entOpt.AddAllowedClass(GetType(Polyline), True)
  26.         Dim entRes As PromptEntityResult
  27.         entRes = ed.GetEntity(entOpt)
  28.         If entRes.Status <> PromptStatus.OK Then
  29.           Exit Sub
  30.         End If
  31.         Dim pLineId As ObjectId = entRes.ObjectId
  32.         Dim gripPts As Point3dCollection = New Point3dCollection()
  33.         Dim pline As Polyline
  34.         MyT = db.TransactionManager.StartTransaction()
  35.         pline = MyT.GetObject(pLineId, OpenMode.ForRead)
  36.         pline.GetGripPoints(gripPts, New IntegerCollection(), New IntegerCollection())
  37.  
  38.         '       MyT.AddNewlyCreatedDBObject(gripPts, True)
  39.         MyT.Commit()
  40.         MyT.Dispose()
  41.  
  42.         Res = ed.SelectCrossingPolygon(gripPts, sfilter)
  43.         '       Res = ed.GetEntity(peo)
  44.       Case "Одиночно"
  45.         Res = ed.GetSelection(sfilter)
  46.     End Select
  47.  
  48.     If Res.Status = PromptStatus.Error Then
  49.       ed.WriteMessage(ControlChars.CrLf)
  50.       ed.WriteMessage("Чертеж не содержит номеров домов.")
  51.       ed.UpdateScreen()
  52.       Return
  53.     End If
  54.  
  55.     Dim acBlkTbl As BlockTable
  56.     acBlkTbl = MyT.GetObject(db.BlockTableId, OpenMode.ForRead)
  57.     'Dim acBlkTblRec As BlockTableRecord
  58.     'acBlkTblRec = MyT.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
  59.  
  60.  
  61.     Dim SS As Autodesk.AutoCAD.EditorInput.SelectionSet = Res.Value
  62.     Dim IdArray As ObjectId() = SS.GetObjectIds()
  63.  
  64.     Dim Id As ObjectId
  65.     Dim c As Long = 0
  66.     ReDim ad(SS.Count - 1)
  67.  
  68.     For Each Id In IdArray
  69.       Dim hn As BlockReference = MyT.GetObject(Id, OpenMode.ForRead)
  70.       Dim rs As Array = hn.GetXDataForApplication("ESTATE_DATAS").AsArray()
  71.       Dim rsFID As ResultBuffer = hn.GetXDataForApplication("FID")
  72.       If rsFID = Nothing Then
  73.       Else
  74.         ad(c).Fid = rsFID.AsArray(2).Value
  75.       End If
  76.       c = c + 1
  77.     Next
  78.     ad = GetExcelData(ad)
  79.  
  80.     Dim AdData As AddressDatas
  81.     Dim quartes As Integer
  82.     quartes = 0
  83.     For Each AdData In ad
  84.       quartes = quartes + AdData.Quarters
  85.     Next
  86.     Dim s As StringBuilder = New StringBuilder()
  87.     s.Append("В выбраных домах количество квартир равняется ")
  88.     s.Append(quartes)
  89.     ed.WriteMessage(s.ToString())
  90.     ed.WriteMessage(ControlChars.CrLf)
  91.     ed.UpdateScreen()
  92.  
  93.     BuildAddressTable(ed, ad)
  94.   End Sub
  95.  

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
А тут налицо стандартные грабли использования транзакций. Смотрите сколько их открыто и сколько закрыто. А вообще - приучайте себя использовать конструкцию Using для транзакций.

Оффлайн Константин Виноградов

  • ADN OPEN
  • Сообщений: 12
  • Карма: 2
На счет граблей, согласен. Я когда пытался найти причину создал лишнюю параллельную транзакцию. В данном методе я все переделал под использовании конструкции using для транзакции, но ошибка осталась та же. В pline содержатся 4 точки, в gripPts.
Ниже код приложил, как кнопку скрыть добавить на этом форуме не нашел.
Код - vb.net [Выбрать]
  1.   Public Sub GetAddressList(ByVal ed As Editor)
  2.     Dim doc As Document = Application.DocumentManager.MdiActiveDocument
  3.     Dim db As Database = doc.Database
  4.  
  5.     Dim values() As TypedValue = {New TypedValue(DxfCode.ExtendedDataRegAppName, "PLCHOUSENUMBER"), _
  6.     New TypedValue(DxfCode.LayoutName, "MODEL")}
  7.     Dim sfilter As New SelectionFilter(values)
  8.     Dim Res As PromptSelectionResult
  9.     ed.WriteMessage(vbLf & "Выберите дома для нового кластера.")
  10.     ed.UpdateScreen()
  11.  
  12.     Dim pKeyOpts As PromptKeywordOptions = New PromptKeywordOptions("")
  13.     pKeyOpts.Message = vbLf & "Каким методом выбора объекта вы хотите воспользоваться?"
  14.     pKeyOpts.Keywords.Add("Полигон")
  15.     pKeyOpts.Keywords.Add("Одиночно")
  16.     pKeyOpts.AllowNone = False
  17.     Dim pKeyRes As PromptResult = ed.GetKeywords(pKeyOpts)
  18.  
  19.     Select Case pKeyRes.StringResult
  20.       Case "Полигон"
  21.         Dim entOpt As PromptEntityOptions
  22.         entOpt = New PromptEntityOptions("\nВыберите полилинию:")
  23.         entOpt.SetRejectMessage("Это не полилиния!")
  24.         entOpt.AddAllowedClass(GetType(Polyline), True)
  25.         Dim entRes As PromptEntityResult
  26.         entRes = ed.GetEntity(entOpt)
  27.         If entRes.Status <> PromptStatus.OK Then
  28.           Exit Sub
  29.         End If
  30.         Dim pLineId As ObjectId = entRes.ObjectId
  31.         Dim gripPts As Point3dCollection = New Point3dCollection()
  32.         Dim pline As Polyline
  33.         Using MyT As Transaction = db.TransactionManager.StartTransaction()
  34.           pline = MyT.GetObject(pLineId, OpenMode.ForRead)
  35.           pline.GetGripPoints(gripPts, New IntegerCollection(), New IntegerCollection())
  36.           '       MyT.AddNewlyCreatedDBObject(gripPts, True)
  37.           MyT.Commit()
  38.           MyT.Dispose()
  39.         End Using
  40.         Res = ed.SelectCrossingPolygon(gripPts, sfilter)
  41.         '       Res = ed.GetEntity(peo)
  42.       Case "Одиночно"
  43.         Res = ed.GetSelection(sfilter)
  44.     End Select
  45.  
  46.     If Res.Status = PromptStatus.Error Then
  47.       ed.WriteMessage(ControlChars.CrLf)
  48.       ed.WriteMessage("Чертеж не содержит номеров домов.")
  49.       ed.UpdateScreen()
  50.       Return
  51.     End If
  52.     Using MyT As Transaction = db.TransactionManager.StartTransaction()
  53.       Dim acBlkTbl As BlockTable
  54.       acBlkTbl = MyT.GetObject(db.BlockTableId, OpenMode.ForRead)
  55.       'Dim acBlkTblRec As BlockTableRecord
  56.       'acBlkTblRec = MyT.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
  57.     End Using
  58.  
  59.  
  60.     Dim SS As Autodesk.AutoCAD.EditorInput.SelectionSet = Res.Value
  61.     Dim IdArray As ObjectId() = SS.GetObjectIds()
  62.     Dim Id As ObjectId
  63.     Dim c As Long = 0
  64.     ReDim ad(SS.Count - 1)
  65.     Using MyT As Transaction = db.TransactionManager.StartTransaction()
  66.       For Each Id In IdArray
  67.  
  68.         Dim hn As BlockReference = MyT.GetObject(Id, OpenMode.ForRead)
  69.  
  70.         Dim rs As Array = hn.GetXDataForApplication("ESTATE_DATAS").AsArray()
  71.         Dim rsFID As ResultBuffer = hn.GetXDataForApplication("FID")
  72.  
  73.         If rsFID = Nothing Then
  74.  
  75.         Else
  76.           ad(c).Fid = rsFID.AsArray(2).Value
  77.         End If
  78.         c = c + 1
  79.  
  80.       Next
  81.     End Using
  82.     ad = GetExcelData(ad)
  83.  
  84.     Dim AdData As AddressDatas
  85.     Dim quartes As Integer
  86.     quartes = 0
  87.     For Each AdData In ad
  88.       quartes = quartes + AdData.Quarters
  89.     Next
  90.     Dim s As StringBuilder = New StringBuilder()
  91.     s.Append("В выбраных домах количество квартир равняется ")
  92.     s.Append(quartes)
  93.     ed.WriteMessage(s.ToString())
  94.     ed.WriteMessage(ControlChars.CrLf)
  95.     ed.UpdateScreen()
  96.  
  97.     BuildAddressTable(ed, ad)
  98.   End Sub
  99.  

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Давай полностью проект (в zip-архиве) вместе с файлом, на котором экспериментируешь и укажи версию AutoCAD. Хотя мне совершенно непонятно зачем вызывать метод GetGripPoints для получения вершин полилинии.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Ну как минимум явный вызов .Dispose() не нужен.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Ну как минимум явный вызов .Dispose() не нужен.
100%
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин Виноградов

  • ADN OPEN
  • Сообщений: 12
  • Карма: 2
В приложении полностью проект, команда в Autocad Unitcount.
На счет .dispose попробую удалить.
Версия autocad 2008
« Последнее редактирование: 15-05-2014, 14:15:33 от Константин Виноградов »

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Версия autocad 2008
Похоже это баг в AutoCAD .NET API этой версии, а так как она уже давно не поддерживается, то находи вершины полилинии другим способом.
Кстати, этот код не будет работать ни в одной ПСК не равной МСК и если чертеж не будет виден целиком на экране.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин Виноградов

  • ADN OPEN
  • Сообщений: 12
  • Карма: 2
Версия autocad 2008
Похоже это баг в AutoCAD .NET API этой версии, а так как она уже давно не поддерживается, то находи вершины полилинии другим способом.
Кстати, этот код не будет работать ни в одной ПСК не равной МСК и если чертеж не будет виден целиком на экране.
Спасибо большое за ответ.
Очень жаль. Похоже придется перенести код на Autocad 2011 (для другой версии лицензии нет), который вроде тоже не поддерживается уже. Хотя может и стоило бы вручную перебрать вершины полилинии и добавить их в коллекцию Point3DCollection.
На счет МСК не проблем, а вот почему весь чертеж должен быть виден на экране, подскажите пожалуйста?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
На счет МСК не проблем, а вот почему весь чертеж должен быть виден на экране, подскажите пожалуйста?
Метод Editor.SelectCrossingPolygon, как и большинство методов Editor.SelectXXX, требует чтобы все точки, которые ему переданы были видны на экране, т.к. этот метод оперирует не с базой данных чертежа, а с его отображением на экран (точнее на активный видовой порт).
Поэтому по возможности следует отказаться от использования этих методов, т.к. их использование может приводить к очень странным результатам.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Константин Виноградов

  • ADN OPEN
  • Сообщений: 12
  • Карма: 2
Александр Ривилис,  спасибо понял. Данную проблему раньше встречал при обычном выборе объектов, когда точки выбора за видовой экран уходили.
Извините, что замучил, но хотел задать последний вопрос. Я вот смотрю почти везде примеры приведены на C#, стоит ли мне с Visual Basic перейти на C#? Данный переход проблем в принципе не составит.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Я вот смотрю почти везде примеры приведены на C#, стоит ли мне с Visual Basic перейти на C#? Данный переход проблем в принципе не составит.
Лично я рекомендовал бы перейти на C#.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение