1

(2 ответов, оставленных в ObjectARX)

Понял, Александр, спасибо.
Сделал.

2

(2 ответов, оставленных в ObjectARX)

Добрый день, коллеги.

Есть компонент, написанный на C++ & ObjectARX2013.
Требуется адаптировать его к ObjectARX2015 (а затем к ObjectARX2017).
В коде используется тип 'ulong'.
Этот тип определен в ObjectARX2013\inc\adesk.h:

#ifdef __LP64__
    typedef UInt32         ulong;
#else
    typedef unsigned long  ulong;
#endif

В ObjectARX2015\inc\adesk.h этот тип не определен.
Просмотрел документацию ObjectARX2015, в разделе изменений ничего по этому поводу не нашел.
Как быть?

3

(3 ответов, оставленных в .NET)

fixo пишет:

Еще пример, не помню где взял

Спасибо за пример.
Буду разбираться.

4

(3 ответов, оставленных в .NET)

Разобрался.
Исключение происходит, когда _dragLine.Length равна 0.
TransientManager оказался не при чем.
Тем не менее, если у кого то есть информация про TransientManager и его использование, был бы благодарен.

5

(3 ответов, оставленных в .NET)

Здравствуйте, коллеги.
Есть вопросы по Autocad .Net API C#.

Мне нужно создать объект, аналог C++ CustomObject, с навороченной логикой построения & редактирования. Решил начать с примера Dragging a Line in Certain Angle. Чтобы усложнить графику, попытался провести еще одну линию со смещением от основной.

private void DrawDragLine(Point3d mousePoint)
{
    ClearTransientGraphics();

    Point3d pt = CalculateEndPoint(mousePoint);

    _dragLine = new Line(_startPoint, pt);
    _dragLine.SetDatabaseDefaults(_db);
    _dragLine.ColorIndex = _colorIndex;
    
    /// начало моей вставки
    try
    {
        DBObjectCollection objects = _dragLine.GetOffsetCurves( 10 ); // <- здесь происходит исключение
        // Autodesk.AutoCAD.Runtime.Exception: eAmbiguousOutput
        // ...
    }
    catch(Exception ex)
    {
        MessageBox.Show( ex.ToString() );
    }
    /// конец моей вставки

    IntegerCollection col = new IntegerCollection();
    TransientManager.CurrentTransientManager.AddTransient(_dragLine, TransientDrawingMode.Highlight, 128, col);

    //whenever the dragged line updated, reset _endPoint
    _endPoint = pt;
}

Ну и собственно вопросы:
1. Почему происходит исключение, из-за чего оно происходит?
2. Насколько сложной может быть графика в TransientManager, какие ограничения существуют?
В документации об этом минимум информации.

6

(7 ответов, оставленных в .NET)

Я имел в виду недостаточно подробную официальную информацию по .Net API в целом и по Undo/Redo в частности. В документации по ObjectARX зачастую написано - это враппер такого-то класса, это враппер такого-то. Приходится собирать информацию по крупицам.
Выручают такие сайты как through-the-interface и опыт коллег - Александра Ривилиса и Fixo.
Еще хуже с документацией по Civil API.

7

(7 ответов, оставленных в .NET)

Спасибо, буду пробовать.
А подробнее видимо нигде не описано.

8

(7 ответов, оставленных в .NET)

За ссылку спасибо, но там очень коротко.

fixo пишет:

db.disableundorecording(true,false)...

Посмотрел, но мне непонятно - когда требуется отключать Undo?
Метод DisableUndoRecording есть и у Database и у DBObject, в чем разница?

9

(7 ответов, оставленных в .NET)

Здравствуйте, коллеги.

Не могу найти в документации нормального описания механизма Undo/Redo через .Net, может кто подскажет где почитать?
Я так понимаю этот механизм напрямую связан с транзакциями? Т.е. я могу несколько операций выполнить внутри одной транзакции (включая вложенные транзакции) и это гарантирует, что при Undo все эти операции будут отменены?

Немного подробнее о своей задаче.
Есть модель данных с моими объектами. Модель сохраняется в Xrecord. Модель отображается в панели в виде дерева и в виде поллиний в чертеже. Я хочу объединить создание экземпляра своего объекта и его отображение в чертеже, чтобы при Undo удалялись и примитивы и узлы дерева.
Вопрос - как перехватить событие, что произошло Undo, и обновить свою панель с деревом?

10

(2 ответов, оставленных в .NET)

ага, похоже она, спасибо за оперативность!

11

(2 ответов, оставленных в .NET)

Здравствуйте, коллеги.
Не могу найти как достучаться к Единицам Чертежа (команда _Units) на C#.
В частности мне нужно для линейных размеров получить точность - количество разрядов дробной части.
Поможете?

12

(11 ответов, оставленных в ObjectARX)

Позволю себе обновить эту древнюю тему.
Столкнулся с подобной задачей, привожу свой рабочий код без Ray.

PromptEntityOptions promptOptions = new PromptEntityOptions( "\nSelect Polyline: " );
PromptEntityResult entity = Application.DocumentManager.MdiActiveDocument.Editor.GetEntity( promptOptions );

// Exit if the user presses ESC or cancels the command
if ( entity.Status != PromptStatus.OK )
{
    return;
}

PromptPointOptions promptPointOptions = new PromptPointOptions( "\nSelect Point: " );
PromptPointResult userPoint = Application.DocumentManager.MdiActiveDocument.Editor.GetPoint( promptPointOptions );

// Exit if the user presses ESC or cancels the command
if ( userPoint.Status != PromptStatus.OK )
{
    return;
}

// Get the current document and database
Document document = Application.DocumentManager.MdiActiveDocument;
Database database = document.Database;

// Start a transaction
using ( Transaction transaction = database.TransactionManager.StartTransaction() )
{
    using ( Curve curve = (Curve)transaction.GetObject( entity.ObjectId, OpenMode.ForRead ) )
    {
        Point3d pointOnCurve = curve.GetClosestPointTo( userPoint.Value, true );
        Vector3d tangentVector = curve.GetFirstDerivative( pointOnCurve );
        Vector3d perpendicularVector = tangentVector.GetPerpendicularVector();
        perpendicularVector = perpendicularVector.GetNormal();

        double distance = 50.0;
        Point3d startPoint = pointOnCurve + perpendicularVector * distance;
        Point3d endPoint = pointOnCurve - perpendicularVector * distance;

        using ( BlockTable blockTable = (BlockTable)transaction.GetObject( database.BlockTableId, OpenMode.ForRead ) )
        {
            using ( BlockTableRecord blockTableRecord = (BlockTableRecord)transaction.GetObject( blockTable[ BlockTableRecord.ModelSpace ], OpenMode.ForWrite ) )
            {
                Circle circle = new Circle();
                circle.SetDatabaseDefaults();
                circle.ColorIndex = 1;
                circle.Radius = 10;
                circle.Center = pointOnCurve;
                blockTableRecord.AppendEntity( circle );
                transaction.AddNewlyCreatedDBObject( circle, true );

                Polyline perpendicularPolyline = new Polyline();
                perpendicularPolyline.SetDatabaseDefaults();
                perpendicularPolyline.ColorIndex = 2;
                perpendicularPolyline.AddVertexAt( 0, new Point2d( startPoint.X, startPoint.Y ), 0, 0, 0 );
                perpendicularPolyline.AddVertexAt( 1, new Point2d( endPoint.X, endPoint.Y ), 0, 0, 0 );

                blockTableRecord.AppendEntity( perpendicularPolyline );
                transaction.AddNewlyCreatedDBObject( perpendicularPolyline, true );
            }
        }
    }

    transaction.Commit();
}

Application.DocumentManager.MdiActiveDocument.Editor.UpdateScreen();

13

(11 ответов, оставленных в .NET)

Александр, спасибо огромное, теперь работает!
Удачи вам в ваших проектах!

Приведу рабочий код:

Plane planeXoy = new Plane( 
 Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem.CoordinateSystem3d.Origin,
 Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis
);

Point3dCollection intersectionPoints = new Point3dCollection();

// получение точек пересечения 
curve1.IntersectWith( curve2, Intersect.OnBothOperands, planeXoy, intersectionPoints, IntPtr.Zero, IntPtr.Zero );

List< double > intersectionDistances = new List< double >();

// получение дистанций точек пересечения
foreach ( Point3d intersectionPoint in intersectionPoints )
{
    intersectionDistances.Add( curve1.GetParameterAtPoint( intersectionPoint ) );
}

// добавление начала и конца кривой (БЕЗ ЭТИХ ДВУХ СТРОЧЕК ТОЖЕ РАБОТАЕТ)
intersectionDistances.Insert( 0, curve1.StartParam );
intersectionDistances.Add( curve1.EndParam );

// сортировка по дистанциям
intersectionDistances.Sort();

// получение участков кривых рассеченной полилинии
DBObjectCollection splitCurves = curve1.GetSplitCurves( new DoubleCollection( intersectionDistances.ToArray() ) );

// преобразование в участков кривых в коллекцию Entity, фактически это коллекция Polyline
IList< Entity > splitEntities = splitCurves.OfType< Entity >().ToList();

if ( splitEntities.Count > 0 )
{
    using ( BlockTable blockTable = (BlockTable)transaction.GetObject( database.BlockTableId, OpenMode.ForRead ) )
    {
        using ( BlockTableRecord blockTableRecord = (BlockTableRecord)transaction.GetObject( blockTable[ BlockTableRecord.ModelSpace ], OpenMode.ForWrite ) )
        {
            // полилиния инициализируется первым участком
            Entity polyline = splitEntities[ 0 ];

            polyline.SetDatabaseDefaults();
            polyline.ColorIndex = 3;

            // из коллекции учасков первый исключается - он уже использован
            splitEntities.RemoveAt( 0 );

            if ( splitEntities.Count > 0 )
            {
                // объединение участков кривых обратно в одну полилинию
                polyline.JoinEntities( splitEntities.ToArray() );
            }

            blockTableRecord.AppendEntity( polyline );

            transaction.AddNewlyCreatedDBObject( polyline, true );
        }
    }
}

14

(11 ответов, оставленных в .NET)

Еще в массив параметров нужно добавить начальный и конечный параметры.

не понял

15

(11 ответов, оставленных в .NET)

Александр Ривилис пишет:

Третье: Никогда не пиши так:

Дмитрий Гилин пишет:

Не спрашивайте какое исключение, оно не информативное, ничего полезного не сообщает.

То что для тебя бесполезно для других может оказаться весьма полезным.

Я вчера торопился, некогда было восстанавливать код с исключением, вот текст:

Autodesk.AutoCAD.Runtime.Exception: eNotApplicable
   в Autodesk.AutoCAD.DatabaseServices.Entity.JoinEntities(Entity[] otherEntities)
   в Point.GeoSeries.AutocadInteraction.Backroom.Snooper.MainForm.button11_Click(Object sender, EventArgs e) в C:\Dmitry\...\Snooper\MainForm.cs:строка 890
   в System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   в System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   в System.Windows.Forms.Control.WndProc(Message& m)
   в System.Windows.Forms.ButtonBase.WndProc(Message& m)
   в System.Windows.Forms.Button.WndProc(Message& m)
   в System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Александр Ривилис пишет:

Я посмотрел описание этого метода в ObjectARX и судя по всему примитивы, для которых выполняется JoinEntities не должны быть в базе чертежа.

Это исключительно для того, чтобы отобразить на экране полученные сегменты, т.е. для проверки.

16

(11 ответов, оставленных в .NET)

Шансы? т.е. никаких гарантий? спасибо, буду пробовать, отпишусь.

17

(11 ответов, оставленных в .NET)

Найденные ссылки по теме (возможно нужна регистрация):
http://forums.autodesk.com/t5/NET/Polyl … rue#M22600
http://www.theswamp.org/index.php?topic=30636.0

18

(11 ответов, оставленных в .NET)

Александр, примерно вот так:

Plane plane = new Plane(
  Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem.CoordinateSystem3d.Origin,
Application.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis );

Point3dCollection intersections = new Point3dCollection();

// получение точек пересечения
curve1.IntersectWith( curve2, Intersect.OnBothOperands, plane, intersections, IntPtr.Zero, IntPtr.Zero );

// разделение полилинии на кусочки
DBObjectCollection splitObjects = curve1.GetSplitCurves( intersections );

// преобразование коллекции DBObject к коллекции Entity
Entity[] splitEntities = splitObjects.OfType< Entity >().ToArray();

using ( BlockTable blockTable = (BlockTable)transaction.GetObject( database.BlockTableId, OpenMode.ForRead ) )
{
    using ( BlockTableRecord blockTableRecord = (BlockTableRecord)transaction.GetObject( blockTable[ BlockTableRecord.ModelSpace ], OpenMode.ForWrite ) )
    {
        // добавление каждого кусочка разбитой полилинии в Record и в транзакцию 
        foreach ( Entity entity in splitEntities )
        {
            blockTableRecord.AppendEntity( entity );
            transaction.AddNewlyCreatedDBObject( entity, true );
        }

        // создание новой полилинии
        using ( Polyline polyline = new Polyline() )
        {
            // создание полилинии из кусочков
            polyline.JoinEntities( splitEntities ); // <- вот здесь происходит исключение

            blockTableRecord.AppendEntity( polyline );
            transaction.AddNewlyCreatedDBObject( polyline, true );
        }
    }
}

transaction.Commit();

19

(11 ответов, оставленных в .NET)

Здравствуйте, коллеги.
Есть вопрос по Autocad .Net API C#.

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

Решаю следующим образом.
1. Методом Curve.IntersectWith() получаю точки пересечения, для проверки рисую в этих точках окружности красным цветом - да, точки пересечения найдены верно.
2. Методу Curve.GetSplitCurves() подсовываю полученные точки и получаю разбитую поллинию, для проверки рисую эти линии желтым - отлично, похоже на правду, пол задачи решено.
3. Пытаюсь объединить кусочки полилинии обратно в целую полилинию, вызываю метод Polyline.JoinEntities(), получаю исключение.
Не спрашивайте какое исключение, оно не информативное, ничего полезного не сообщает. Пробовал из исходной кривой исключать дуги, пробовал в качестве обеих полилиний использовать два простых отрезка - ничего не помогает.
4. Стал искать информацию по JoinEntities() на форуме автодеск, действительно проблема существует, но решения нет.
5. Решил последовательно пробежаться по кусочкам полилинии, полученным после GetSplitCurves() и создать из них новую полилинию, оказалось что после разбиения эти кусочки лежат в каком-то хаотичном порядке, вершины в произвольном направлении.
6. Сейчас сижу пишу алгоритм, который будет в этом хаосе отыскивать соседние кусочки, выправлять их направление и складывать вместе.

Но может быть есть способ элегантнее?
Спасибо.

http://img13.imageshost.ru/img/2012/02/29/image_4f4e37d455f2c.png

P.S. перед публикацией топика увидел пример на лиспе по схожей проблеме
https://www.caduser.ru/forum/topic49414.html
но вопрос остается - хотелось бы реализовать на .Net

20

(7 ответов, оставленных в .NET)

Думаю, можно, просто сюда добавить код удаляющий созданные объекты com.

Вариант конечно...

Короче я понял, спасибо.

21

(7 ответов, оставленных в .NET)

Пример:

try
{
   NetAction1();
   NetAction2();
   ComAction3();
   NetAction4();
   NetAction5();
   transaction.Commit();
}
catch
{
   transaction.Abort();
}

Не могу себе представить что будет в случае Abort.

22

(7 ответов, оставленных в .NET)

А как тогда объединить все действия в одно, чтобы можно было отменить одним Undo?

23

(7 ответов, оставленных в .NET)

Здравствуйте, есть вопрос по Civil.

Для того чтобы использовать функциональность Civil можно использовать либо .Net API, либо COM API, либо и то и другое вместе. Работая через .Net, рекомендуется использовать транзакции, но как использовать транзакции через COM API? Непонятно.

Пример моей задачи, действия которой хочется выполнить в рамках одной транзакции.
1. Создать полилинию (.Net API).
2. По полилинии создать характерную линию (COM API).
3. Удаление полилинии (.Net API).
4. Изменение координат точек характерной линии.
5. Возможно создание коридора по нескольким характерным линиям.

Заранее спасибо.

24

(3 ответов, оставленных в .NET)

По второй ссылке как раз создание характерной линии.

25

(3 ответов, оставленных в .NET)

В документации по Civil сказано, что через .Net API создать Характерные Линии нельзя, но можно создать через COM API, используя IAeccLandFeatureLine::AddFromPolyline().
http://wikihelp.autodesk.com/AutoCAD_Ci … eature_320

Сам очень долго искал ответ/пример, нашел вот здесь, на VB.Net:
http://blog.civil3dreminders.com/2008/1 … g-box.html