Тема: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

1. Указываем диаметр труб.
2. Выбираем направляющие(линии, полилинии, 3Д-полилинии, дуги, окружности, эллипсы) и жмём Enter.

(defun c:xpipe(/ ACTDOC ACTLAY ACTSP BASELINE
           BASESET CIRENT DICOUNT DIVDID
           EXCIR LAYST OBJTYPE OLDDIA
           OLDECHO STARTPT XORD YORD
           ZORD *ERROR*)
  (vl-load-com)
  (defun *error* (msg)
    (vla-put-Lock actLay laySt)
    (setvar "CMDECHO" oldEcho)
    (vla-EndUndoMark actDoc)
    (princ)
    ); end of *error*
  (if(not pipe:exDia)(setq pipe:exDia 40.0))
  (setq actDoc
    (vla-get-ActiveDocument
      (vlax-get-Acad-object))
    actLay(vla-get-ActiveLayer actDoc)
        oldDia pipe:exDia
        oldEcho(getvar "CMDECHO")
   ); end setq
  (vla-StartUndoMark actDoc)
  (setvar "CMDECHO" 0)
  (if(= 0(vla-get-ActiveSpace actDoc))
    (setq actSp(vla-get-PaperSpace actDoc))
    (setq actSp(vla-get-ModelSpace actDoc))
    ); end if
  (setq laySt(vla-get-Lock actLay))
  (vla-put-Lock actLay :vlax-false)
  (setq pipe:exDia
    (getreal
      (strcat
        "\nSpecify pipe diameter <"(rtos pipe:exDia)">: ")))
  (if(null pipe:exDia)(setq pipe:exDia oldDia))
  (princ "\n<<< Select objects to extrude and press Enter >>>")
  (if
    (setq baseSet
      (ssget '((-4 . "<OR")(0 . "*LINE")(0 . "CIRCLE")
           (0 . "ARC")(0 . "ELLIPSE")(-4 . "OR>")
           (-4 . "<NOT")(-4 . "<OR")(0 . "SPLINE")
                (0 . "MLINE")(-4 . "OR>")(-4 . "NOT>"))))
    (progn
      (setq baseSet(vl-remove-if 'listp
                              (mapcar
                'cadr
                (ssnamex baseSet))))
      (foreach pathEnt baseSet
      (setq baseLine
        (vlax-ename->vla-object pathEnt)
       objType(vla-get-ObjectName baseLine)
            startPt(vlax-curve-getStartPoint baseLine)
            3dPos
        (vlax-curve-getFirstDeriv baseLine
          (vlax-curve-getParamAtPoint baseLine startPt))
           diCount(strlen
            (itoa
         (apply 'max
          (mapcar 'abs
           (mapcar 'fix startPt)))))
       divDid "1"
       ); end setq
      (repeat diCount
   (setq divDid(strcat divDid "0"))
   ); end repeat
      (setq divDid(atoi divDid))
      (if(/= 0.0(car 3dPos))
   (setq XOrd(/(car 3dPos)divDid))
   (setq XOrd (car 3dPos))
   ); end if
      (if(/= 0.0(cadr 3dPos))
   (setq YOrd(/(cadr 3dPos)divDid))
   (setq YOrd (cadr 3dPos))
   ); end if
      (if(/= 0.0(nth 2 3dPos))
   (setq ZOrd(/(nth 2 3dPos)divDid))
   (setq ZOrd (nth 2 3dPos))
   ); end if
      (setq 3dPos(list XOrd YOrd ZOrd))
  (setq exCir
     (vla-addCircle actSp
       (vlax-3d-Point startPt)
       (/ pipe:exDia 2)))
  (vla-put-Normal exCir(vlax-3D-point 3dPos))
  (setq cirEnt(vlax-vla-object->ename exCir))
  (command "_.extrude" cirEnt "" "_p" pathEnt)
  (command "_.erase" cirEnt "")
   ); end foreach
      (vla-put-Lock actLay laySt)
      (setvar "CMDECHO" oldEcho)
      (vla-EndUndoMark actDoc)
       ); end progn
      ); end if
    (princ)
    ); end  of c:xpipe

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

> {Smirnoff}
А, где обещанная труба? Цилиндр получается. Или я чего- то не понял.

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

> Forma
Сказано же сказано же "трубопроводов" а они обычно цилиндрическими солидами отрисовываются, а не полностью как трубы.
Если нужно именно трубу рисовать можно дополнить или просто отрисуй два солида по одной направляющей и воспользуйся _subtract.
Трубы вместо цилиндров рисовать когда это не требуется рисовать не рекомендую, размер чертежа сразу же возрастёт.

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Трубы как трубы:

(defun c:xtube(/ 3DPOS ACTDOC ACTLAY ACTSP BASELINE
           BASESET DICOUNT DIVDID EXCIR EXENT
           EXTUBE INCIR INENT INTUBE LAYST
           OBJTYPE OLDECHO OLDEXDIA OLDINDIA
           STARTPT XORD YORD ZORD *ERROR*)
  (vl-load-com)
  (defun *error* (msg)
    (vla-put-Lock actLay laySt)
    (setvar "CMDECHO" oldEcho)
    (vla-EndUndoMark actDoc)
    (princ)
    ); end of *error*
  (if(not tube:exDia)(setq tube:exDia 40.0))
  (if(not tube:inDia)(setq tube:inDia 37.0))
  (setq actDoc
    (vla-get-ActiveDocument
      (vlax-get-Acad-object))
    actLay(vla-get-ActiveLayer actDoc)
        oldexDia tube:exDia
    oldinDia tube:inDia
        oldEcho(getvar "CMDECHO")
   ); end setq
  (vla-StartUndoMark actDoc)
  (setvar "CMDECHO" 0)
  (if(= 0(vla-get-ActiveSpace actDoc))
    (setq actSp(vla-get-PaperSpace actDoc))
    (setq actSp(vla-get-ModelSpace actDoc))
    ); end if
  (setq laySt(vla-get-Lock actLay))
  (vla-put-Lock actLay :vlax-false)
  (setq tube:exDia
    (getreal
      (strcat
        "\nSpecify external diameter <"(rtos tube:exDia)">: "))
       tube:inDia
    (getreal
      (strcat
        "\nSpecify internal diameter <"(rtos tube:inDia)">: "))
    ); end setq
  (if(null tube:inDia)(setq tube:inDia oldinDia))
  (if(null tube:exDia)(setq tube:exDia oldexDia))
  (if(< tube:inDia tube:exDia)
    (progn
  (princ "\n<<< Select objects to extrude and press Enter >>>")
  (if
    (setq baseSet
      (ssget '((-4 . "<OR")(0 . "*LINE")(0 . "CIRCLE")
           (0 . "ARC")(0 . "ELLIPSE")(-4 . "OR>")
           (-4 . "<NOT")(-4 . "<OR")(0 . "SPLINE")
                (0 . "MLINE")(-4 . "OR>")(-4 . "NOT>"))))
    (progn
      (setq baseSet(vl-remove-if 'listp
                              (mapcar
                'cadr
                (ssnamex baseSet))))
      (foreach pathEnt baseSet
      (setq baseLine
        (vlax-ename->vla-object pathEnt)
       objType(vla-get-ObjectName baseLine)
            startPt(vlax-curve-getStartPoint baseLine)
            3dPos
        (vlax-curve-getFirstDeriv baseLine
          (vlax-curve-getParamAtPoint baseLine startPt))
           diCount(strlen
            (itoa
         (apply 'max
          (mapcar 'abs
           (mapcar 'fix startPt)))))
       divDid "1"
       ); end setq
      (repeat diCount
   (setq divDid(strcat divDid "0"))
   ); end repeat
      (setq divDid(atoi divDid))
      (if(/= 0.0(car 3dPos))
   (setq XOrd(/(car 3dPos)divDid))
   (setq XOrd (car 3dPos))
   ); end if
      (if(/= 0.0(cadr 3dPos))
   (setq YOrd(/(cadr 3dPos)divDid))
   (setq YOrd (cadr 3dPos))
   ); end if
      (if(/= 0.0(nth 2 3dPos))
   (setq ZOrd(/(nth 2 3dPos)divDid))
   (setq ZOrd (nth 2 3dPos))
   ); end if
      (setq 3dPos(list XOrd YOrd ZOrd))
  (setq exCir
     (vla-addCircle actSp
       (vlax-3d-Point startPt)
       (/ tube:exDia 2))
    inCir
     (vla-addCircle actSp
       (vlax-3d-Point startPt)
       (/ tube:inDia 2))
    ); end setq
  (vla-put-Normal exCir(vlax-3D-point 3dPos))
  (vla-put-Normal inCir(vlax-3D-point 3dPos))
  (setq exEnt(vlax-vla-object->ename exCir)
    inEnt(vlax-vla-object->ename inCir)
    ) ; end setq
  (command "_.extrude" exEnt "" "_p" pathEnt)
  (setq exTube(entlast))
  (command "_.extrude" inEnt "" "_p" pathEnt)
  (setq inTube(entlast))
  (command "_subtract" exTube "" inTube "")
  (command "_.erase" exEnt "")
  (command "_.erase" inEnt "")
  (vla-delete baseLine)
   ); end foreach
      (vla-put-Lock actLay laySt)
      (setvar "CMDECHO" oldEcho)
       ); end progn
      ); end if
     ); end progn
    (princ "\nInternal diameter more or equal than external diameter! ")
    ); end if
  (vla-EndUndoMark actDoc)
    (princ)
    ); end  of c:xtube

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Если нужно оставить направляющую стереть строчку:

(vla-delete baseLine)

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

> {Smirnoff}
Теперь понял. Я не знал, что такое трубопроводы.

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

{Smirnoff} пишет:

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

Так. Для справки. Если чертеж машиностроительный, то приходится все изображать. К примеру. Недавно проектировал конструкцию на прямоугольных трубах. В 3d естесственно. Какой- то девайс к сельхозмашине.  Так, что выбора нет :(

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

> Forma
Да конечно в машиностроительных чертежал трубы изображаются как есть. Я об этом не подумал потому что черчу в основном сети. Кстати если нужно и отрисовку прямоугольных труб таким образом сделать.

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

> {Smirnoff}
Было бы неплохо. Только я задачу не смогу грамотно поставить. Есть путаница с внутренними и наружными радиусами. Но, если не подходить строго, то можно принять наружный радиус равный сумме внутреннего и толщины стенки. Критиков много будет. Одному так. Другому этак. Не хочется связываться.

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Классная штука, но есть небольшая неприятность: не отрабатывает, если в качестве базовой линии предлагается полилиния, пересекающая саму себя. Конечно можно использовать 2 разные пересекающиеся полилинии, но всётаки ... хочется совершенства!

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

> Kosarev
Стандартная команда _EXTRUDE которая используется в программе не работает в случае самопересечения полилинии. Можно конечно проверять полилинии на самопересечение, отрисовывать отдельные солиды и сращивать их. Однако думаю что "овчинка не стоит выделки". Если такое случается то проще разбить полилинию, отрисовать солиды и сделать для них _UNION - "руками".

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

В таком случае может имеет смысл сделать проверку, предупреждающую о невозможности использования ТАКИХ полилиний (остальные пропускать), или в местах пересечения делать разрыв полилиний на куски с автоматическим обновлением набора примитивов, используемых как базовые, или хотя бы убирать ИХ из набора, т.о. исключить возможность неприятного "зависания". Я, например, был бы рад, т.к. из всех подобных програм, которые приходилось использовать, эта мне больше всего нравиться. С уважением...

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

> Kosarev
Хорошо, постараюсь сделать попозже. У меня на данный момент куча обязательств и совсем не времени чтобы их выполнить. Немного надо разгрести дела.
Предупреждать о наличии таких полилиний (вернее о невозможности экструдирования каких либо объектов) несложно, поскольку поскольку это страндартрная ошибка и ей соответствует значение системной переменной ERRNO.
Вот найти точки самопересечения, разрезать полилинии в этих местах и срастить солиды займет побольше кода.

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Послушайте, разве нельзя заранее разобраться с полилинией, а потом уж выдавливать? Зачем необоснованно усложнять программу, IMHO. Пусть это будет ограничением, тем более, что это является ограничением самого AutoCAD'а.

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Я не программист и мои замечания прошу не принимать "близко к сердцу", т.к. они вытекают исключительно из МОИХ личных представлений об удобстве использования той или иной программы. С полилиниями разобраться можно, конечно. Но представьте всего на одно мгновение, что ВЫ некто ПРОСТОЙ пользователь Kosarev, который и в русском языке-то после 3-х литров пива не очень, не говоря уже о LISP-е, и тут Вы запускаете (c:xtube), выбираете НАШУ злощастную характерную полилинию и ... облом!!! Настроение падает до уровня, когда рыба уже не клюёт... Красивые машины начинают нравиться больше, чем красивые женщины... Все признаки острой депрессии, знаете ли. А самое противное, что мозгов произвести самостоятельное хирургическое вмешательство в тело (c:xtube) не хватает, или займёт несоизмеримо больше времени, чем у того, кто "понятие имеет", вот ВЫ (ну т.е. я) и обращаете свой взор, полный надежд, на www.autocad.ru, желая получить совершенство...
Метафоры убедительны?

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

> Kosarev
Вы правы безусловно и не только как пользователь но и с точки зрения программирования. Если программа что-то не может обработать то она должна об этом по крайней мере сообщать. Стандарный _EXTRUDE об этом сообщает, а в программе для уменьшения количества "мусора" в текстовом экране отключен эхо-вывод. В общем обрабатывать такие полилинии не обещаю, а сообщение и чтобы программа не останвливалась сделаю.

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Будем терпеливо, в разумных пределах, ждать...

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Ни черта он не прав, как пользователь. Если бы он умел вручную выдавливать объекты по траектории, он бы не просил усложнять программу, а делал бы саму траекторию корректной, IMHO. Конечно, ПРОСТОМУ пользователю лучше налиться пивом, чем изучить команды AutoCAD'а и вот здесь у него главный "облом", все остальное от лукавого.
Ух, как я зол, не знаю почему, да простит меня Господь Бог.

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Ну я, типа, умею выдавливать объекты от случая к случаю, а пивом "наливаюсь", исключительно когда поступают предложения, от которых невозможно отказаться. А в полемику по поводу усложнения вступил потому, что мы находмся в разделе "ГОТОВЫЕ ПРОГРАММЫ". И если автор считает, что степень готовности вполне удовлетворительна, то имеет право злиться и даже просто послать коротко по русски, и я пойду ... в раздел "LISP", где буду выяснять для начала как отследить полилинию, которая пересекает сама себя от других и т.д. Да, кстати (c:xpipe) не обрабатывает также любые 3d-полилинии, а желательно бы. Со всем уважением...

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Владимир Громов пишет:

Ни черта он не прав, как пользователь. Если бы он умел вручную выдавливать объекты по траектории, он бы не просил усложнять программу, а делал бы саму траекторию корректной, IMHO.

Дело не в том что пользователь должен правильно или неправильно выбирать направляющую, а в том что программа должна сообщить о причине ошибки. А не прекратить работу по неизвестной причине. Стандартная _EXTRUDE это делает, программа нет в этом и "косяк".
Я кстати сам незнал об этом свойстве _EXTRUDE, потому что вголову не приходило экструдировать самопересекающиеся полилинии. Вот теперь знаю...

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

а макрос для кнопки можно получить?

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

> алгебра
Если код сохранить в файле xtube.lsp, то макрос для кнопки или пункта меню может выглядеть так:

^C^C(if (not C:XTUBE) (load "xtube")) XTUBE

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Люди, помогите!!
Я нашел как рисовать 3D трубы с помощью Вашего ЛИПСа - огромное спасибо, но задача в другом. Как в нарисованном файле измерить трубопроводы, которые уже нарисованны?
Может, кто-то знает?
Для обсуждения кладу файлик Pipe_long_calc.dwg по адресу
http://dwg.ru/dwl/index.php?id=639
Заранее благодарен!!!

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

может определить объем и разделить на площадь сечения;)
P.S. Если это 3D

Re: LISP. Быстрая отрисовка 3D трубопроводов (экструдирование)

Хорошо,
и как это делается?