Lisp create boundary...

Lisp create boundary...

daohaquang
Enthusiast Enthusiast
6,941 Views
12 Replies
Message 1 of 13

Lisp create boundary...

daohaquang
Enthusiast
Enthusiast

I have 1 lisp to create Boundary, The way it works is to point to space and then make 1 Boundary, then combine them to total Boundary, but working with many object it takes a long time.
I want to select all objects at once and then create a total Boundary
Can you helps me??

222.jpg

(defun c:bo1()
  (setq p (getpoint "pick :"))
  (command "._boundary" "A" "O" "R" "" p "")
  (Command "._region" "L" "")
  (setq el (entlast)) (redraw el 3)
  (while (setq p (getpoint "pick diem :"))
      (command "._boundary" p "")
      (Command "._region" "L" "")
    (command "._union" el "L" "")
    (setq el (entlast))
    (redraw el 3)
  )
(redraw el 4)
)

 

0 Likes
6,942 Views
12 Replies
Replies (12)
Message 2 of 13

ronjonp
Mentor
Mentor

Get your intersection points then use this: http://www.lee-mac.com/convexhull.html

Message 3 of 13

marko_ribar
Advisor
Advisor

@ronjonp 

ConvexHull don't work like that... Please look at OP's picture...

I have something that can do this kind of thing, but I am not going to post it...

Just to let you know that it's very possible to do it with ALISP...

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 4 of 13

hak_vz
Advisor
Advisor

@daohaquang 

You will not get any better result from this. What @ronjonp  proposes will work only for straight edges.

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 5 of 13

marko_ribar
Advisor
Advisor

@hak_vz 

OP's code is good enough, but just to inform you - BOUNDARY command or BPOLY sometimes make small mistakes... Perhaps you haven't noticed this behaviour, so I am just telling you this to let you know... But all in all, OP could use something like superboundary plugin, which I don't use, create boundaries automatically and finally convert them into REGIONs and finally apply UNION command... Resulting REGION could be at the end converted into LWPOLYLINE for example if OP needs such entity as a result...

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 6 of 13

Sea-Haven
Mentor
Mentor

Agree region is way to go copy all say to right fixed distance then region select all, union select all, explode pedit and join move last back to left fixed amount. Original lines still there and new pline.

 

It only took a few seconds to do manually.

Message 7 of 13

Kent1Cooper
Consultant
Consultant

@daohaquang wrote:

I have 1 lisp to create Boundary, .... I want to select all objects at once and then create a total Boundary ....


How about this?  It Isolates the selected objects so there can be other things in the area but they won't interfere, draws a CIRCLE that's guaranteed to be outboard of all the selected objects, does a BOUNDARY command picking a place that's guaranteed to be between the selected objects and the Circle, ERASEs the Circle and the Polyline that lies on it from the BOUNDARY command [which in limited testing always appears to be the "last" object], and Unisolates to bring any other objects in the area back to visibility.

 

(vl-load-com)
(defun C:CBM ; = Collective Boundary of Multiple objects
  (/ ss n eLL eUR LL UR cir bbsize)
  (prompt "\nTo Draw the Boundary enclosed Collectively by Multiple objects,")
  (if (setq ss (ssget))
    (progn ; then
      (repeat (setq n (sslength ss)); gather collective bounding box
        (vla-getboundingbox (vlax-ename->vla-object (ssname ss (setq n (1- n)))) 'minpt 'maxpt)
        (setq
          eLL (vlax-safearray->list minpt); entity Lower Left
          eUR (vlax-safearray->list maxpt); and Upper Right
          LL (if LL (mapcar 'min eLL LL) eLL); collective Lower Left
          UR (if UR (mapcar 'max eUR UR) eUR); and Upper Right
        ); setq
      ); repeat
      (command
        "_.isolateobjects" ss "" ; so Boundary won't be complicated by other things
        "_.circle" "_none" (setq ctr (mapcar '/ (mapcar '+ LL UR) '(2 2 2))) "_none" UR)
      (setq
        cir (entlast)
        bbsize (mapcar '- UR LL); bounding box size
      ); setq
      (command
        "_.boundary"
          "_none"
          (polar
            ctr
            (if (> (cadr bbsize) (car bbsize)) 0 (/ pi 2))
              ; extents more vertical? then angle to right; else upward
            (* (cdr (assoc 40 (entget cir))) 0.9); inside Circle, outside selected objects
          ); polar
          ""
        "_.erase" "_last" cir ""
        "_.unisolateobjects"
      ); command
    ); progn
    (prompt "\nNothing selected."); else
  ); if
  (princ)
); defun

 

 

Kent Cooper, AIA
Message 8 of 13

marko_ribar
Advisor
Advisor

Good Kent,

I'd just slightly mod. your code if you don't mind...

 

(vl-load-com)
(defun C:CBM ; = Collective Boundary of Multiple objects
  (/ ss n eLL eUR LL UR cir bbsize)
  (prompt "\nTo Draw the Boundary enclosed Collectively by Multiple objects,")
  (if (setq ss (ssget))
    (progn ; then
      (repeat (setq n (sslength ss)); gather collective bounding box
        (vla-getboundingbox (vlax-ename->vla-object (ssname ss (setq n (1- n)))) 'minpt 'maxpt)
        (setq
          eLL (vlax-safearray->list minpt); entity Lower Left
          eUR (vlax-safearray->list maxpt); and Upper Right
          LL (if LL (mapcar 'min eLL LL) eLL); collective Lower Left
          UR (if UR (mapcar 'max eUR UR) eUR); and Upper Right
        ); setq
      ); repeat
      (command
        "_.isolateobjects" ss "" ; so Boundary won't be complicated by other things
        "_.circle" "_none" (setq ctr (mapcar '/ (mapcar '+ LL UR) '(2 2 2))) "_none" (polar UR (angle ctr UR) 10.0))
      (command "_.zoom" "_extents")
(setq cir (entlast) bbsize (mapcar '- UR LL); bounding box size ); setq (command "_.boundary" "_none" (polar ctr 0.0 (- (cdr (assoc 40 (entget cir))) 1.0)); polar - inside Circle, outside selected objects "" "_.erase" "_last" cir "" "_.unisolateobjects" ); command
(command "_.zoom" "_previous") ); progn (prompt "\nNothing selected."); else ); if (princ) ); defun

Regards...

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 9 of 13

Kent1Cooper
Consultant
Consultant

@marko_ribar wrote:

.... I'd just slightly mod. your code if you don't mind...

 

....
        "_.circle" "_none" (setq ctr (mapcar '/ (mapcar '+ LL UR) '(2 2 2))) "_none" (mapcar '+ UR '(10.0 10.0 0.0)))
      (command "_.zoom" "_extents")
... "_.boundary" "_none" (polar ctr 0.0 (- (cdr (assoc 40 (entget cir))) 1.0)); polar - inside Circle, outside selected objects "" ....

You didn't indicate the other change you made.  Given the other changes, maybe that's appropriate, subject to the comments below.  Another change you should have made would be to eliminate the 'bbsize' variable, since it was used only to decide the angle in the (polar) function, and your change eliminated the choice there.

 

The Zooming is worthwhile in case the temporary Circle is outside the viewing area.  It would have to be completely outside it to cause trouble, so it doesn't seem likely very often, but it could happen.

 

I would not have guessed that Zooming to the Extents when objects are Isolated goes to the Extents of only those objects.  It would be just as effective to Zoom to the Circle under the Object option.

 

But rather than use 10 units beyond the extents of the selected objects, and 1 unit less than the Circle's radius, I would do something proportional to the size of their extents.  I find in experimentation that in a very small situation, the Circle can be so enormously larger than the selected objects that they are a tiny speck in the middle, and the Boundary result will not be correct.  And in a very large situation, the pick point can be so close to the Circle that it will be considered "on" it by the Boundary command, which will cause an error.

Kent Cooper, AIA
Message 10 of 13

marko_ribar
Advisor
Advisor

@Kent1Cooper wrote:
...

But rather than use 10 units beyond the extents of the selected objects, and 1 unit less than the Circle's radius, I would do something proportional to the size of their extents.  I find in experimentation that in a very small situation, the Circle can be so enormously larger than the selected objects that they are a tiny speck in the middle, and the Boundary result will not be correct.  And in a very large situation, the pick point can be so close to the Circle that it will be considered "on" it by the Boundary command, which will cause an error.


This is the reason I wanted to force users to code for new (bndr) function rather than use old BOUNDARY command. I have my version, but as I stated I don't want to post it... Better is to persuade users to try to code it. Although the task could be exhsaustive, satisfaction when finished would be worth it... Just to be clear, although original boundary command uses fuzzes to make asumption of making closures around vertices (some errors may occur), when I coded for (bndr) I had to make sure all gaps in DWG must not occur... When using 'addregion methods, everything must be exact, simply AutoCAD won't operate if something is unperfectly drawn... Maybe this is the reason why BPOLY or BOUNDARY is still so widely used in solving various problems in 2D geometry...

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 11 of 13

daohaquang
Enthusiast
Enthusiast

I used them, your idea is quite good but I use it on a large drawing, it doesn't work perfectly, thanks anyway

0 Likes
Message 12 of 13

xos300
Explorer
Explorer

@daohaquang just a suggestion maybe you can use the command LINEWORKSHRINKWRAP to generate the boundaries of the objects or insert a call to this command in your Lisp code.

 
0 Likes
Message 13 of 13

Kent1Cooper
Consultant
Consultant

@xos300 wrote:

.... maybe you can use the command LINEWORKSHRINKWRAP .....


[If you have the Civil3D overlay program.  It's not a command in "vanilla" AutoCAD.]

Kent Cooper, AIA