Jump to content
kwwong6

How to create boundary box with spline entity?

Recommended Posts

kwwong6

Hi pro guru.

Anybody can help me how to write a lisp can create a boundary box with spline entity?:lol::lol:

Share this post


Link to post
Share on other sites
MSasu

Not sure what you mean by "boundary box" - if is about "bounding box", then please check this routine written by Lee Mac.

Share this post


Link to post
Share on other sites
kwwong6

Yes I mean like the routine written by Lee Mac. But this Lisp cannot correctly make the bounding box for the spline. I need is really close to the spline ==> "mean no gap".

 

Thanks in advance.

Share this post


Link to post
Share on other sites
Lee Mac

Indeed, the BoundingBox method is inaccurate for Splines.

 

An alternative approach might be to approximate the Spline using an appropriate point list, then calculate the bounds of such point list; though, this algorithm will undoubtedly be slower than the BoundingBox method.

 

Here is an example to demonstrate this method (you will need to download my Entity to Point List function):

 

(defun BoundingBox ( ent / l )
   (if (setq l (LM:Entity->PointList ent))
       (mapcar '(lambda ( a ) (apply 'mapcar (cons a l))) '(min max))
   )
)

Share this post


Link to post
Share on other sites
MSasu

Alternatively may create a copy in place of the spline, apply FLATTEN command on it and use Lee’s routine for bounding box; remove helper polyline just after.

Share this post


Link to post
Share on other sites
Lee Mac

Nice idea Mircea!

 

Here is another method (excuse the messy code):

 

(defun SplineBoundingBox ( ent / pt1 pt2 res var )
   (if (setq ent (entmakex (entget ent)))
       (progn
           (setq var (mapcar 'getvar '(peditaccept cmdecho)))
           (mapcar 'setvar '(peditaccept cmdecho) '(1 0))
           (command "_.pedit" ent 10 "")
           (mapcar 'setvar '(peditaccept cmdecho) var)
           (if (not (equal ent (setq ent (entlast))))
               (progn
                   (vla-getboundingbox (vlax-ename->vla-object ent) 'pt1 'pt2)
                   (setq res (mapcar 'vlax-safearray->list (list pt1 pt2)))
               )
           )
           (entdel ent)
       )
   )
   res
)

Test function:

(defun c:test ( / bb en )
   (princ "\nSelect a Spline: ")
   (if (setq en (ssget "_+.:E:S:L" '((0 . "SPLINE"))))
       (if (setq bb (SplineBoundingBox (ssname en 0)))
           (entmakex
               (list
                   (cons 0 "LWPOLYLINE")
                   (cons 100 "AcDbEntity")
                   (cons 100 "AcDbPolyline")
                   (cons 90 4)
                   (cons 70 1)
                   (list 10 (caar  bb) (cadar  bb))
                   (list 10 (caadr bb) (cadar  bb))
                   (list 10 (caadr bb) (cadadr bb))
                   (list 10 (caar  bb) (cadadr bb))
               )
           )
           (princ "\nUnable to retrieve Bounding Box.")
       )
   )
   (princ)
)
(vl-load-com) (princ)

Share this post


Link to post
Share on other sites
marko_ribar

I think that Lee's code won't be correct for earlier versions of ACAD... If you don't need exactly but approx result, try this...

 

(defun SplineBoundingBox ( ent / xmin xmax ymin ymax res cmde )
   (setq cmde (getvar 'cmdecho))
   (setvar 'cmdecho 0)
   (vl-cmdf "_.ucs" "w")
   (vl-cmdf "_.plan" "")
   (vl-cmdf "_.zoom" "o" ent "")
   (setq ymin (- (cadr (getvar 'viewctr)) (/ (getvar 'viewsize) 2.0)) ymax (+ (cadr (getvar 'viewctr)) (/ (getvar 'viewsize) 2.0)))
   (vl-cmdf "_.ucs" "z" 90)
   (vl-cmdf "_.plan" "")
   (vl-cmdf "_.zoom" "o" ent "")
   (setq xmax (- (car (trans (getvar 'viewctr) 1 0)) (/ (getvar 'viewsize) 2.0)) xmin (+ (car (trans (getvar 'viewctr) 1 0)) (/ (getvar 'viewsize) 2.0)))
   (vl-cmdf "_.zoom" "p")
   (vl-cmdf "_.zoom" "p")
   (vl-cmdf "_.zoom" "p")
   (vl-cmdf "_.zoom" "p")
   (vl-cmdf "_.zoom" "p")
   (vl-cmdf "_.ucs" "p")
   (vl-cmdf "_.ucs" "p")
   (setvar 'cmdecho cmde)
   (setq res (list (list xmin ymin 0.0) (list xmax ymax 0.0)))
   res
)

(defun c:test ( / bb en )
   (princ "\nSelect a Spline: ")
   (if (setq en (ssget "_+.:E:S:L" '((0 . "SPLINE"))))
       (if (setq bb (SplineBoundingBox (ssname en 0)))
           (entmakex
               (list
                   (cons 0 "LWPOLYLINE")
                   (cons 100 "AcDbEntity")
                   (cons 100 "AcDbPolyline")
                   (cons 90 4)
                   (cons 70 1)
                   (list 10 (caar  bb) (cadar  bb))
                   (list 10 (caadr bb) (cadar  bb))
                   (list 10 (caadr bb) (cadadr bb))
                   (list 10 (caar  bb) (cadadr bb))
               )
           )
           (princ "\nUnable to retrieve Bounding Box.")
       )
   )
   (princ)
)

 

If you want exact results, consider converting SPLINE to POLYLINE like Mircea suggested or if you have A2010 or above (not sure for A2009) A2008 doesn't support - try SPLINEDIT -> Convert to polyline and obtain Bounding Box from pline - after remove dummy pline... If you have A2010 or above, then try also Lee's code - just checked on my A2012 and it worked...

Also check this thread from theswamp...

 

M.R.

Edited by marko_ribar

Share this post


Link to post
Share on other sites
kwwong6

Thank for Lee Mac and Marko Ribar Lisp. After try on my AutoCAD 2007, still cannot work well. Maybe my AutoCAD are version are too old. Both of your code cannot support. Anyway thank you both of you. I still need to find out how to break though it.

Share this post


Link to post
Share on other sites
MSasu

Please check this solution to convert the said spline to a polyline using your AutoCAD version.

Share this post


Link to post
Share on other sites
Lee Mac
Thank for Lee Mac and Marko Ribar Lisp. After try on my AutoCAD 2007, still cannot work well. Maybe my AutoCAD are version are too old. Both of your code cannot support. Anyway thank you both of you. I still need to find out how to break though it.

 

kwwong6,

 

As far as I know, the solution that I posted in reply#4 should work in AutoCAD 2007.

Share this post


Link to post
Share on other sites
MSasu

Lee, I'm afraid that PEDIT command of version 2007 doesn't support spline as input.

Command: PEDIT

Select polyline or [Multiple]:

Object selected is not a polyline

I think the programmatically alternative is to parse the spline entity with an appropriate defame and trace it with a polyline. Not sure to how to establish that defame size.

Share this post


Link to post
Share on other sites
kwwong6

Ya! Lee Mac of course can work. But result are having small gap. I attach a drawing for you so see.

 

Thanks.

spline.zip

Share this post


Link to post
Share on other sites
Lt Dan's legs

 
 (defun tracecurve ( obj di / cycle st )
   (defun cycle ( st stp seg l )
     (cond
       ( (< (+ st seg) stp )
         (cycle (+ seg st) stp seg
           (cons (vlax-curve-getPointAtParam obj st) l)
         )
       )
       ( t
         (and (< st stp)
           (setq l
             (cons (vlax-curve-getPointAtParam obj st) l)
           )
         )
         (reverse
           (cons (vlax-curve-getPointAtParam obj stp) l)
         )
       )
     )
   )
   (if
     (and (not (minusp di))(not (zerop di))
       (vl-position 
         (vla-get-objectname 
           (cond
             ( (eq 'ENAME (type obj))(vlax-ename->vla-object obj ))
             ( obj )
           )
         ) '("AcDbCircle" "AcDbArc" "AcDbEllipse" "AcDbSpline")
       )
     )
     (cycle 
       (setq st (vlax-curve-getStartParam obj))
       (vlax-curve-getEndParam obj)
       (- (vlax-curve-getParamAtDist obj 0.125) st)
       nil
     )
   )
 )

 

Modifying Lee Mac's suggestion, though I don't know why his way wouldn't work for you.

 
(defun BoundingBox ( ent / l )
   (if (setq l (tracecurve ent 0.125))
       (mapcar '(lambda ( a ) (apply 'mapcar (cons a l))) '(min max))
   )
)

Share this post


Link to post
Share on other sites
MSasu

@kwwong6 and Lt Dan's legs: Are you both saying that Lee's code from post 6 is working on your AutoCAD 2007?!?

Share this post


Link to post
Share on other sites
kwwong6
@kwwong6 and Lt Dan's legs: Are you both saying that Lee's code from post 6 is working on your AutoCAD 2007?!?

 

Yes, no problem running on AutoCAD 2007. Just having small gap as I upload the attached drawing from post 12.

 

Thank you very much for LT Dan's Legs. Your code really work!!!!! But if for multi select the spline, Can you modify your code?

Share this post


Link to post
Share on other sites
Lee Mac
Lee, I'm afraid that PEDIT command of version 2007 doesn't support spline as input.

I think the programmatically alternative is to parse the spline entity with an appropriate defame and trace it with a polyline. Not sure to how to establish that defame size.

 

MSasu,

 

I was referring to post#4 in my last post, this solution does not involve the use of PEDIT

Share this post


Link to post
Share on other sites
Lee Mac
Modifying Lee Mac's suggestion' date=' though I don't know why his way wouldn't work for you.

 
(defun BoundingBox ( ent / l )
   (if (setq l (tracecurve ent 0.125))
       (mapcar '(lambda ( a ) (apply 'mapcar (cons a l))) '(min max))
   )
)

[/quote']

 

But your 'tracecurve' is using linear steps; this will be far less accurate than the method used in my Entity to Point List function :?

Share this post


Link to post
Share on other sites
Lee Mac
Ya! Lee Mac of course can work. But result are having small gap. I attach a drawing for you so see.

 

Thanks.

 

kwwong,

 

You could never achieve an exact bounding box using this method since this method is approximating a continuous curve with a discrete number of points; for true accuracy, you would need an infinite number of points. You could of course increase the accuracy by increasing the number of points in the approximation, but at a severe loss in performance.

Share this post


Link to post
Share on other sites
MSasu
MSasu,I was referring to post#4 in my last post, this solution does not involve the use of PEDIT

My mistake then. Sorry for inconvenience!

Share this post


Link to post
Share on other sites
kwwong6

Thank you Lee Mac for you information. But code done by Lt Dan's legs really can work well for me. Anybody can make this code to multi select spline?

 

Thanks in advance.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×