Тема: Контур

Добрый день, Приложение внешнее - C#.
Суть такова:
есть набор кругов, квадратов и они могут пересекаться или нет.

         +-----------+
         |           |
 +-------|---+       | +-----------+
 |       +---|-------+ |           |
 +-----------+         +-----------+

И нужно их объединить или провести контур, так чтоб получить единый объект, типа:

         +-----------+
         |           |
 +-------+           +-------------+
 |           +---------+           |
 +-----------+         +-----------+
Каким-нить образом можно  реализовать подобное ?
Спасибо.

Re: Контур

Ну, что никто не знает ка объединить две и более области ???
Не обязательно на шарпе, любой пример. Аналог - union.

Re: Контур

1) Использовать собственную математику
2) Превратить в регионы, объединить а потом расчленить. Примеры смотри в
AutoCAD Developer Help->ActiveX and VBA Reference.

Re: Контур

> Александр Ривилис
Общий регион будет создаваться да
только в этом случае он останется
расчлененным на две части, а не как
желаемый один общий
IMHO
~'J'~

Re: Контур

> Fatty
Ну тогда остается вариант с собственной математикой. Только вот задача поставлена не корректно. Если эти контура пересекаются - то все понятно и регионы для решения задачи подходят. А вот если пересечения нет, то что делать - из рисунка не ясно. Чего это вдруг правый контур вдруг удлинился в лево - не понимаю. С таким же успехом их все можно было бы объединить в один прямоугольник с BoundingBox охватывающий все остальные контура...

Re: Контур

> Александр Ривилис
Я попытался вечерок поворчать над этой темой,
но слаб умишком еси, откуда мне математику
знать, я и до десяти-то с трудом понимаю
А задача интересная, уже не раз встречалась,
но пока решения не видел
Наверно только всемогущий C++ одолеет, тут
ведь интегралами пахнет, кажись...
~'J'~

Re: Контур

> Fatty
Стоп. Только сейчас увидел, что рисунок исправлен. Регионы рулят!

Re: Контур

Да регионы сделали, есть там класс AcadRegion и метод AddRegion

AcadCircle[] obj = new AcadCircle[2];
...
инициализация кругов
...
object region = AcadApp.ActiveDocument.ModelSpace.AddRegion(obj);
AcadRegion circle1 = region[0]
AcadRegion circle2 = region[1]
// как объединиить circle1 и circle2 ???

Уже пошарил в примерах, не нашел и инет обгуглил как мог, тоже нету ниче sad...
Ну не может такого быть, чтобы эта операция (через командную строку это union) не была где-то в качестве метода приделана!

Re: Контур

> Buger
Плохо искал в указанном мной месте. Уточняю. Метод называется Boolean. И параметр в тоем случае acUnion.

Re: Контур

Благодарю, Александр! Так и знал, что это проблемы перевода smile Искали уже все - и Merge, и Union, и Append, и еще кучу вариантов, но вот чтобы Boolean smile)) Я не спорю, название логичное - булевы операции они и есть булевы операции, но вот ни разу не видел, чтобы они назывались в библиотеке булевыми операциями smile

Re: Контур

> Александр Ривилис
Ничего подобного, регион создается, да
только расчлененный, как я и говорил

Imports System
Imports System.IO
Imports System.Collections
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Interop
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.DatabaseServices
Imports graph = Autodesk.AutoCAD.GraphicsInterface
Imports Autodesk.AutoCAD.ApplicationServices
Imports AcDb = Autodesk.AutoCAD.DatabaseServices
Imports AcadApp = Autodesk.AutoCAD.ApplicationServices.Application
Imports AcGe = Autodesk.AutoCAD.Geometry
Imports AcRx = Autodesk.AutoCAD.Runtime
Public Class RegMan
    <CommandMethod("UReg")> _
        Public Shared Sub UnionRegions()
        Dim doc As Document = AcadApp.DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Dim ed As Editor = doc.Editor
        Dim docLock As DocumentLock = doc.LockDocument
        Dim tr As Transaction = doc.TransactionManager.StartTransaction()
        Using tr
            Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
            Dim btr As BlockTableRecord = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite),  _
BlockTableRecord)
            Dim objIdColl As ObjectIdCollection = SelectEntities(db, tr)
            If objIdColl Is Nothing Then
                Return
            End If
            Dim ColRegion As AcDb.DBObjectCollection = New AcDb.DBObjectCollection()
            For Each oId As ObjectId In objIdColl
                Dim entPLine As Entity = (CType(tr.GetObject(oId, OpenMode.ForRead, False), Entity))
                Dim pLine As Polyline = (CType(entPLine, Polyline))
                If pLine.Closed = False Then
                    Throw New AcRx.Exception(AcRx.ErrorStatus.WrongObjectType)
                Else
                    Dim entArray() As Polyline = {pLine}
                    Dim regs() As Object = DirectCast(entArray, Object())
                    Dim dbColl As DBObjectCollection = New DBObjectCollection()
                    dbColl.Add(regs(0))
                    Dim myRegion As Region = CType(Region.CreateFromCurves(dbColl)(0), Region)
                    btr.AppendEntity(myRegion)
                    tr.AddNewlyCreatedDBObject(myRegion, True)
                    ColRegion.Add(myRegion)
                End If
            Next
            Dim oReg As Region
            oReg = DirectCast(ColRegion(0), Region)
            '//MessageBox.Show(String.Format("Handle is: {0}", oReg.Handle))
            For i As Integer = 1 To ColRegion.Count - 1
                Dim oEnt As Region = DirectCast(ColRegion.Item(i), Region)
                '//MessageBox.Show(String.Format("Handle is: {0}", oEnt.Handle))
                oReg.BooleanOperation(AcDb.BooleanOperationType.BoolUnite, oEnt)
                db.Dispose()
            Next
            '//MessageBox.Show(String.Format("Handle is: {0}", oReg.Handle))
            tr.Commit()
            ed.Regen()
        End Using
        docLock.Dispose()
    End Sub
'// by Paul Richardson
Public Shared Function SelectEntities(ByVal db As Database, ByVal tr As Transaction) As ObjectIdCollection
        Dim ed As Editor = AcadApp.DocumentManager.MdiActiveDocument.Editor
        Dim opts As New PromptSelectionOptions()
        opts.MessageForAdding = "Select the polylines to create regions: "
        Dim psr As PromptSelectionResult = ed.GetSelection(opts)
        If psr.Status <> Autodesk.AutoCAD.EditorInput.PromptStatus.OK Then
            ed.WriteMessage(vbCr & "0 entities selected!")
            Return Nothing
        End If
        Dim idc As New ObjectIdCollection()
        For Each id As ObjectId In psr.Value.GetObjectIds()
            idc.Add(id)
        Next
        Return idc
    End Function
End Class

~'J'~

Re: Контур

> Fatty
Что такое раслененный регион? Состоящий из нескольких непересекающихся контуров?

Re: Контур

> Александр Ривилис
Ну вот: у него два контура накладываются, а
один отдельно, когда создается общий регион,
эти два объединятся по общему контуру, а
нехороший третий как был отдельно, так и останется,
хотя будет входить в общий регион:

         +-----------+
         |           |
 +-------|           | +-----------+
 |           |-------+ |           |
 +-----------+         +-----------+

~'J'~

Re: Контур

> Fatty
Я же сказал, чтобы ты посмотрел исправленную его картинку - там все три контура пересекаются! smile

Re: Контур

P.S.: Точнее на исправленной картинке третий контур и останется отдельным. А если этот регион расчленить, то получится две отдельных полилинии, которые не пересекаются - что как я понял и требуется.

Re: Контур

> Александр Ривилис
А, я не обратил внимания, что исправлено
Мой код вроде как рабочий, только не конвертируется
на C# с этого сайта почему-то:
http://labs.developerfusion.co.uk/conve … sharp.aspx
~'J'~

Re: Контур

> Fatty
А SharpDeveloper'ом не?

Re: Контур

> Александр Ривилис
Да как-то влом его cкачать да устанавливать...
~'J'~

Re: Контур

> Fatty
Вот результат конвертирования, но работу не проверял.

using System;
using System.IO;
using System.Collections;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using graph = Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.ApplicationServices;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using AcGe = Autodesk.AutoCAD.Geometry;
using AcRx = Autodesk.AutoCAD.Runtime;
public class RegMan
{
    [CommandMethod("UReg")]
    public static void UnionRegions()
    {
        Document doc = AcadApp.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;
        Editor ed = doc.Editor;
        DocumentLock docLock = doc.LockDocument;
        Transaction tr = doc.TransactionManager.StartTransaction();
        using (tr) {
            BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
            ObjectIdCollection objIdColl = SelectEntities(db, tr);
            if (objIdColl == null)
            {
                return;
            }
            AcDb.DBObjectCollection ColRegion = new AcDb.DBObjectCollection();
            foreach (ObjectId oId in objIdColl) {
                Entity entPLine = ((Entity)tr.GetObject(oId, OpenMode.ForRead, false));
                Polyline pLine = ((Polyline)entPLine);
                if (pLine.Closed == false)
                {
                    throw new AcRx.Exception(AcRx.ErrorStatus.WrongObjectType);
                }
                else
                {
                    Polyline[] entArray = {pLine};
                    object[] regs = (object[])entArray;
                    DBObjectCollection dbColl = new DBObjectCollection();
                    dbColl.Add(regs(0));
                    Region myRegion = (Region)Region.CreateFromCurves(dbColl)(0);
                    btr.AppendEntity(myRegion);
                    tr.AddNewlyCreatedDBObject(myRegion, true);
                    ColRegion.Add(myRegion);
                }
            }
            Region oReg;
            oReg = (Region)ColRegion(0);
            ////MessageBox.Show(String.Format("Handle is: {0}", oReg.Handle))
            for (int i = 1; i <= ColRegion.Count - 1; i++) {
                Region oEnt = (Region)ColRegion.Item(i);
                ////MessageBox.Show(String.Format("Handle is: {0}", oEnt.Handle))
                oReg.BooleanOperation(AcDb.BooleanOperationType.BoolUnite, oEnt);
                db.Dispose();
            }
            ////MessageBox.Show(String.Format("Handle is: {0}", oReg.Handle))
            tr.Commit();
            ed.Regen();
        }
        docLock.Dispose();
    }
    //// by Paul Richardson
    public static ObjectIdCollection SelectEntities(Database db, Transaction tr)
    {
        Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
        PromptSelectionOptions opts = new PromptSelectionOptions();
        opts.MessageForAdding = "Select the polylines to create regions: ";
        PromptSelectionResult psr = ed.GetSelection(opts);
        if (psr.Status != Autodesk.AutoCAD.EditorInput.PromptStatus.OK)
        {
            ed.WriteMessage(Constants.vbCr + "0 entities selected!");
            return null;
        }
        ObjectIdCollection idc = new ObjectIdCollection();
        foreach (ObjectId id in psr.Value.GetObjectIds()) {
            idc.Add(id);
        }
        return idc;
    }
}

Самое смешное, что ты снова не прочитал постановку задачи. Приложение должно быть внешним, т.е. только через ActiveX! smile

Re: Контур

С регионами все замечательно работает, аналогично самому антокаду. Для конвертации кода идем сюда http://www.aisto.com/roeder/dotnet/ и забираем
Reflector for .NET - просмотр исходников из .Net сборок на C#? VB.Net, Delphi.Net, MC++.Net, Chrome, IL. И никогда проблем с переводом не будет! :)

Re: Контур

Кстати http://labs.developerfusion.co.uk/conve … sharp.aspx
загнулся как я ему подсунул код .Net3 из WWF )))

Re: Контур

> Buger
Если переводить C# на VB вот тут работает
получше:
http://www.kamalpatel.net/ConvertCSharp2VB.aspx
иногда переводит код который на других сайтах
ни в какую
~'J'~