| Правила | Регистрация | Пользователи | Поиск | Сообщения за день | Все разделы прочитаны |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Поворот и зеркалирование вставляемого блока в Autocad через Delphi

Поворот и зеркалирование вставляемого блока в Autocad через Delphi

Ответ
Поиск в этой теме
Непрочитано 20.05.2014, 17:38 #1
Поворот и зеркалирование вставляемого блока в Autocad через Delphi
kolio
 
Регистрация: 02.08.2013
Сообщений: 9

всем привет
вставляю блок в программу так:

Код:
[Выделить все]
Doc := acad.ActiveDocument;
        LayerName := 'scat_'+inttostr(Doc.Layers.Count)+'1';
        Doc.Layers.Add(LayerName);
        LayersCount := Doc.Layers.Count;
        for i := 0 to LayersCount-1 do begin
          Layer := Doc.Layers.Item(i);
          if AnsiCompareText(Layer.Name, LayerName) = 0 then Break;
        end;
        Doc.ActiveLayer := Layer;

        P1 := VarArrayCreate([0, 2], varDouble);
        P1 := acad.ActiveDocument.Utility.GetPoint(EmptyParam, 'точка');
        Angle := acad.ActiveDocument.Utility.GetAngle(p1, 'угол');
        RetVal := acad.ActiveDocument.ModelSpace.insertblock(P1, 'c:\1.dwg', 1,1,1,Angle,EmptyParam);
        RetVal.Update;
1. создаю слой, на который будет ложиться блок
2. предлагаю юзеру выбрать точку вставки
3. предлагаю юзеру выбрать угол наклона вставки блока
4. вставляю блок из файла программно

ПРОБЛЕМА:
увы не знаю команду как сделать так, чтобы при указании первой точки сразу вставился блок и потом начал уже крутить блок на определенный угол мышкой, как это сделано автокадом когда нажать на кнопку "вставить блок" и в окошке выблрать "указать угол при вставке". при этом указываешь точку вставки и потом уже вставляется блок и его крутишь

аналогично не знаю как сделать зеркалирование объекта относительно задаваемой оси с помощью мышки как это делается в автокаде командой ЗЕРКАЛО (как то так)

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

и еще 1 вопрос, может кто знает какая команда включения ОРТО? чтобы угол поворота был не произвольный а только 0 90 180 270. так как объекты вставляются именно под 90градусов все

прошу помощи мужики

----- добавлено через ~9 мин. -----
может кто знает как на VBA сделать это
код не особо отличается от delphi
Просмотров: 5074
 
Непрочитано 20.05.2014, 19:28
#2
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,702
Отправить сообщение для Do$ с помощью Skype™


Цитата:
Сообщение от kolio Посмотреть сообщение
увы не знаю команду как сделать так, чтобы при указании первой точки сразу вставился блок и потом начал уже крутить блок на определенный угол мышкой, как это сделано автокадом когда нажать на кнопку "вставить блок" и в окошке выблрать "указать угол при вставке". при этом указываешь точку вставки и потом уже вставляется блок и его крутишь
Делается так: вставляем блок, а потом получаем уже вставленный блок и запускаем для него команду ROTATE. В нее передаем сам блок и точку его вставки.
Цитата:
Сообщение от kolio Посмотреть сообщение
аналогично не знаю как сделать зеркалирование объекта относительно задаваемой оси с помощью мышки как это делается в автокаде командой ЗЕРКАЛО (как то так)
а тут-то какие проблемы?
Цитата:
Сообщение от kolio Посмотреть сообщение
и еще 1 вопрос, может кто знает какая команда включения ОРТО? чтобы угол поворота был не произвольный а только 0 90 180 270. так как объекты вставляются именно под 90градусов все
переменная ORTHOMODE
__________________
Толковый выбор приходит с опытом, а к нему приводит выбор бестолковый. (The Mechanic)
Do$ вне форума  
 
Автор темы   Непрочитано 20.05.2014, 20:26
#3
kolio


 
Регистрация: 02.08.2013
Сообщений: 9


да, я знаю команду RetVal.rotate(p1,1)
где p1 = точка куда первый раз клацнули
ну и 1 = угол в радианах

и он поворачивает объект на определенный угол
а мне бы чтобы мышкой водить
или вы имеете ввиду Acad.ActiveDocument.SendCommand('rotate' + #13); ?

ORTHOMODE я так понял это переменная окружения автокада. попробую. спасибо уже продвижение хоть какое то есть
конечно я понимаю, что лучше arx сразу делать или на .net
но увы только delphi знаю. но документации и примеров маловато в инете по связкам COM+ что либо еще
kolio вне форума  
 
Непрочитано 21.05.2014, 06:41
#4
Boxa

КЖ; C#
 
Регистрация: 03.11.2005
Санкт-Петербург
Сообщений: 2,588


Делфи еще в 2003 году научился работать с net. Соответственно как писать программу решает программист. Хочет, использует Com модель, хочет net.
В net, то что Вы хотите реализуется с помощью класса Jig и его наследников.
Boxa вне форума  
 
Непрочитано 21.05.2014, 09:04
#5
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,702
Отправить сообщение для Do$ с помощью Skype™


Цитата:
Сообщение от kolio Посмотреть сообщение
или вы имеете ввиду Acad.ActiveDocument.SendCommand('rotate' + #13); ?
Именно. Не знаю, как в Delphi будет выглядеть строка командного запроса, но нужно сделать так, чтобы объект и базовая точка передавались программно, а угол поворота задавался пользователем. В лиспе это делается с помощью функции command и специального аргумента pause.

Цитата:
Сообщение от kolio Посмотреть сообщение
ORTHOMODE я так понял это переменная окружения автокада. попробую. спасибо уже продвижение хоть какое то есть
Это правильнее называется "системная переменная AutoCAD". В COM API должен быть какой-то метод типа SetVariable для изменения их значений.

Цитата:
Сообщение от kolio Посмотреть сообщение
но документации и примеров маловато в инете по связкам COM+ что либо еще
Ищите в справке или в интернете AutoCAD ActiveX Reference.
или http://vbamodel.narod.ru/
__________________
Толковый выбор приходит с опытом, а к нему приводит выбор бестолковый. (The Mechanic)
Do$ вне форума  
 
Автор темы   Непрочитано 21.05.2014, 12:15
#6
kolio


 
Регистрация: 02.08.2013
Сообщений: 9


орто научился выставлять
Doc.SetVariable('ORTHOMODE',1);

комманда _rotate тоже подходит. но!
для этого нужно выделить вставленный последний объект и сказать, команде rotate, что базовая точка поворота это точка вставки

пока только проблема с выделением объекта
переменная объекта есть, но команды типа RetVal.Select(....) не нашел

может кто-то чуть подправит меня на истинный путь? буду благодарен
kolio вне форума  
 
Непрочитано 21.05.2014, 13:10
#7
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,702
Отправить сообщение для Do$ с помощью Skype™


На AutoLISP как-то так:
Код:
[Выделить все]
(command "_rotate" (entlast) "" (cdr (assoc 10 (entget (entlast)))) pause)
Как вариант - просто через SendCommand передать это в виде строки.
__________________
Толковый выбор приходит с опытом, а к нему приводит выбор бестолковый. (The Mechanic)
Do$ вне форума  
 
Автор темы   Непрочитано 21.05.2014, 16:40
#8
kolio


 
Регистрация: 02.08.2013
Сообщений: 9


жалко, что так резко головой об автокад ударился
Код:
[Выделить все]
acad.ActiveDocument.SelectionSets.Add('S1');
acad.ActiveDocument.SelectionSets.Item('S1').Select(acSelectionSetLast);
этот код добаляет мой блок в S1.
если вызвать acad.ActiveDocument.SelectionSets.Item('S1').Highlight(true);
то блок подсвечивает. но без базовой точки. как будто не до конца выделил. непонятно.
обычно при выделении видна базовая точка

боюсь, что иду по неверному пути
я думал нужно его выделить программно и дать комманду _rotate
но если выделить объект и набрать _rotate 300,300 45 то
оно после каждого пробела предлагает выбрать базовую точку(к примеру 300,300), и потом угол наклона, который или мышкой или программно 45 поставил
в принципе это и нужно , но мать его!!!!! объект не выделяется визуально моим кодом но когда делаю acad.ActiveDocument.SelectionSets.Item('S1').count
то выдает что 1 элемент есть

есть команда _.qselect которая предлагает по параметрам выбрать объекты
имя его я знаю. но увы не знаю параметров этой команды. может кто видел хелп по командам autocad? с описанием параметров

Последний раз редактировалось kolio, 21.05.2014 в 17:18.
kolio вне форума  
 
Непрочитано 21.05.2014, 20:21
#9
kakt00z

инженер-проектировщик КИПиА
 
Регистрация: 30.08.2008
Минск
Сообщений: 159


1. попробуйте вместо .Highlight(true) дать .Highlight(2); (3,4) - это для выделения
и, по моему, вид подсветки на набор не влияет
2. чтобы повернуть блок не обязательно его выделять, ... я, правда, не особо помню как там в делфи, но думаю смысл на ActiveX лиспе, vba, С# и.т.п. должен быть один и тот же.
3. чтобы крутить вставленный блок - его нужно сначала вставить а потом, отлавливая положение мышЫ, менять его параметр rotate (на лиспе это реализуется с помощью команды grread и последующей обработке ее значений)
kakt00z вне форума  
 
Непрочитано 22.05.2014, 10:15
#10
Boxa

КЖ; C#
 
Регистрация: 03.11.2005
Санкт-Петербург
Сообщений: 2,588


Цитата:
Сообщение от kolio Посмотреть сообщение
боюсь, что иду по неверному пути
COM средствами реализовать то, что вы хотите невозможно, по этому Вам приходится выдумывать костыли в виде вызова Lisp, хотя если перейти на .net то все работает штатными средствами.
Вот пример накидал: http://youtu.be/11KTfvp2kyM


Код:
[Выделить все]
 
using System;
using App = Autodesk.AutoCAD.ApplicationServices;
using cad = Autodesk.AutoCAD.ApplicationServices.Application;
using Db = Autodesk.AutoCAD.DatabaseServices;
using Ed = Autodesk.AutoCAD.EditorInput;
using Gem = Autodesk.AutoCAD.Geometry;
using Rtm = Autodesk.AutoCAD.Runtime;

namespace AddBlock
{
    public class Commands
    {
        [Rtm.CommandMethod("AddBlock")]
        static public void AddBlock()
        {
            // Тут храним имя блока с которым работаем, по хорошему надо вынести в xml
            string BlockName = "1111111";
            
            // Получение текущего документа и базы данных
            App.Document acDoc = App.Application.DocumentManager.MdiActiveDocument;
            Db.Database acCurDb = acDoc.Database;
            Ed.Editor acEd = acDoc.Editor;

            // Тут нужна проверка на наличие в базе блока с указанным именем
            using (Db.Transaction acTrans = acCurDb.TransactionManager.StartOpenCloseTransaction())
            {
                Db.BlockTable acBlTbl = (Db.BlockTable)acTrans.GetObject(acCurDb.BlockTableId, Db.OpenMode.ForRead);
                if (acBlTbl.Has(BlockName) == true)
                {
                    acEd.WriteMessage("\nХорошо, блок " + BlockName + " присутствует в базе чертежа. ");
                }
                else
                {
                    acEd.WriteMessage("\nОшибка, блок " + BlockName + " отсутствует в базе чертежа. ");
                    acEd.WriteMessage("\nПрограмма завершена с ошибкой.");
                    return;
                }
            }

            Ed.PromptPointOptions p1Opt = new Ed.PromptPointOptions("\nУкажите первую точку:");
            Ed.PromptPointResult p1Res = acDoc.Editor.GetPoint(p1Opt);
            if (p1Res.Status != Ed.PromptStatus.OK)
                return;

            // старт транзакции
            using (Db.Transaction acTrans = acCurDb.TransactionManager.StartOpenCloseTransaction())
            {
                Db.BlockTable bt = (Db.BlockTable)acTrans.GetObject(acCurDb.BlockTableId,Db.OpenMode.ForRead);
                Db.BlockTableRecord blockDef = (Db.BlockTableRecord)acTrans.GetObject(bt[BlockName], Db.OpenMode.ForRead);

                Db.BlockTableRecord ms = (Db.BlockTableRecord)acTrans.GetObject(bt[Db.BlockTableRecord.ModelSpace],Db.OpenMode.ForWrite);

                Db.ObjectId IDObj = new Db.ObjectId();
                using (Db.BlockReference blockRef = new Db.BlockReference(p1Res.Value, blockDef.ObjectId))
                {
                    ms.AppendEntity(blockRef);
                    acTrans.AddNewlyCreatedDBObject(blockRef, true);

                    //////Нет у меня тут атрибутов
                    ////foreach (Db.ObjectId id in blockDef)
                    ////{
                    ////    Db.DBObject obj = id.GetObject(Db.OpenMode.ForRead);
                    ////    Db.AttributeDefinition attDef = (Db.AttributeDefinition)obj;

                    ////    //If (attDef IsNot Nothing) AndAlso (Not attDef.Constant) Then
                    ////    // тут я что то накосячил с условиями, должно быть как в примере выше
                    ////    if(attDef != null) 
                    ////    {
                    ////        using (Db.AttributeReference attRef = new Db.AttributeReference())
                    ////        {
                    ////            attRef.SetAttributeFromBlock(attDef, blockRef.BlockTransform);
                    ////            blockRef.AttributeCollection.AppendAttribute(attRef);
                    ////            acTrans.AddNewlyCreatedDBObject(attRef, true);
                    ////        }
                    ////    }
                    ////}
                    blockRef.Layer = "0"; // имя слоя
                    IDObj = blockRef.ObjectId;
                }

                Db.BlockReference acBlock = (Db.BlockReference)acTrans.GetObject(IDObj, Db.OpenMode.ForWrite);
                BlockJig entJig = new BlockJig(acBlock);
                acDoc.TransactionManager.QueueForGraphicsFlush();

                Ed.PromptPointResult pkr = (Ed.PromptPointResult)acEd.Drag(entJig);
                if (pkr.Status == Ed.PromptStatus.OK)
                {
                    Gem.Point2d tmpP1 = new Gem.Point2d(p1Res.Value.X, p1Res.Value.Y);
                    Gem.Point2d tmpP2 = new Gem.Point2d(pkr.Value.X, pkr.Value.Y);

                    acBlock.Rotation = tmpP1.GetVectorTo(tmpP2).Angle;
                    acDoc.TransactionManager.QueueForGraphicsFlush();
                }
                acTrans.Commit();
            }
        }
    }


    class BlockJig : Ed.EntityJig
    {
        private Gem.Point3d mCenterPt;
        private Gem.Point3d mActualPoint;

        public BlockJig(Db.BlockReference br)
            : base(br)
        {
            mCenterPt = br.Position;
        }

        protected override Ed.SamplerStatus Sampler(Ed.JigPrompts prompts)
        {
            Ed.JigPromptPointOptions jigOpts = new Ed.JigPromptPointOptions();

            jigOpts.UserInputControls = (Ed.UserInputControls.Accept3dCoordinates
                                        | Ed.UserInputControls.NoZeroResponseAccepted
                                        | Ed.UserInputControls.NoNegativeResponseAccepted);
            jigOpts.Message = "\nEnter insert point: ";
            Ed.PromptPointResult dres = (Ed.PromptPointResult)prompts.AcquirePoint(jigOpts);
            if (mActualPoint == dres.Value)
            {
                return Ed.SamplerStatus.NoChange;
            }
            else
            {
                mActualPoint = dres.Value;
            }
            return Ed.SamplerStatus.OK;
        }

        protected override bool Update()
        {
            // тут надо бы переписать с получением plan и на point3D
            Gem.Point2d tmpP1 = new Gem.Point2d(mCenterPt.X, mCenterPt.Y);
            Gem.Point2d tmpP2 = new Gem.Point2d(mActualPoint.X, mActualPoint.Y);
            Double angle = tmpP1.GetVectorTo(tmpP2).Angle;
            try
            {

                ((Db.BlockReference)Entity).Rotation = angle;
            }
            catch (System.Exception generatedExceptionName)
            {
                return false;
            }
            return true;
        }

        public Db.Entity GetEntity()
        {
            return Entity;
        }
    }
}


Последний раз редактировалось Boxa, 22.05.2014 в 13:01. Причина: Блин, код то не вставился =( Исправляю.
Boxa вне форума  
 
Непрочитано 22.05.2014, 10:29
#11
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,702
Отправить сообщение для Do$ с помощью Skype™


В автокаде подсветка(Highlight) и выделение - понятия различные. Подсветить с помощью ActiveX можно, а вот полноценно выделить - вроде бы никаких методов нет для этого. Обычно используют костыли в виде SendCommand и в него передают команды или лисп-функцию SSSETFIRST с нужными наборами.
__________________
Толковый выбор приходит с опытом, а к нему приводит выбор бестолковый. (The Mechanic)
Do$ вне форума  
 
Автор темы   Непрочитано 22.05.2014, 12:25
#12
kolio


 
Регистрация: 02.08.2013
Сообщений: 9


эээххххх. я в расстройстве
какой то неполноценная связь в COM. насколько я понял просто не все возможности программы реализовали автокадовцы в нём

я в печали полной

правда попробовал
Код:
[Выделить все]
Acad.ActiveDocument.SendCommand('(command "_rotate" (entlast) "" (cdr (assoc 10 (entget (entlast)))) pause)' + #13);
всё получилось. Спасибо Do$. всё как и задумывалось работает
но автолисп я не знаю. страшноватый какой-то язык по виду

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

а LISP поддерживается в 2013-2014 версии?

Спасибо Вохе за видео. Приятно общаться с человеком который делится знаниями на таком уровне. Завидую Вам в хорошем смысле слова.

Последний раз редактировалось kolio, 22.05.2014 в 12:47.
kolio вне форума  
 
Непрочитано 22.05.2014, 14:08
#13
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,702
Отправить сообщение для Do$ с помощью Skype™


Цитата:
Сообщение от kolio Посмотреть сообщение
а LISP поддерживается в 2013-2014 версии?
Да, поддерживается.
__________________
Толковый выбор приходит с опытом, а к нему приводит выбор бестолковый. (The Mechanic)
Do$ вне форума  
 
Непрочитано 22.05.2014, 16:53
#14
Boxa

КЖ; C#
 
Регистрация: 03.11.2005
Санкт-Петербург
Сообщений: 2,588


Цитата:
Сообщение от kolio Посмотреть сообщение
Спасибо Вохе за видео. Приятно общаться с человеком который делится знаниями на таком уровне. Завидую Вам в хорошем смысле слова.
Всё чем я могу Вам помочь, это выложить отладочную сборку dll. Используя программы типа Spices.Net Decompiler( .NET Reflector 8 + DelphiLanguage plugIn), Вы волне сможете, самостоятельно посмотреть, как это написано на Delphi.NET

ЗЫ.
Сразу код не запостился, а я убегал и не заметил оплошности. Удачи. Надеюсь у Вас все получится.
Вложения
Тип файла: zip AddLine.zip (3.8 Кб, 30 просмотров)

Последний раз редактировалось Boxa, 22.05.2014 в 17:11.
Boxa вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Поворот и зеркалирование вставляемого блока в Autocad через Delphi

Размещение рекламы
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Документация Проектировщику на Torrents DEM Разное 262 24.02.2024 17:19
Видеоуроки AutoCAD kosmax AutoCAD 173 17.02.2017 15:08
1. AutoCAD Кулик Алексей aka kpblc FAQ: Часто задаваемые вопросы 25 27.09.2016 13:29
AutoCAD 2008, программное удаление объектов RTEXT из состава блока Кулик Алексей aka kpblc Программирование 3 28.04.2009 08:48
AutoCad и Delphi. Добавление точки Зойберг Программирование 15 28.02.2008 23:18