Jump to content

How to create boundary box with spline entity?


kwwong6

Recommended Posts

Thank you Lee Mac for you information. But code done by Lt Dan's legs really can work well for me.

 

It would depend on the length of the spline - for smaller splines, the code will become inaccurate.

Link to comment
Share on other sites

  • Replies 51
  • Created
  • Last Reply

Top Posters In This Topic

  • marko_ribar

    17

  • kwwong6

    12

  • Lee Mac

    9

  • MSasu

    6

Top Posters In This Topic

Posted Images

A better approximation, tracing FirstDeriv. Local min and max are at the points where a component of FirstDeriv vector is changing its sign.

(vl-load-com)
(defun getSplineBoundingBox (e / f d i dir p1 p2 lst)
 
 (defun f (x1 x2 tg1 tg2 axis / a1 a2 xm tgm)
   (cond ((equal (setq a1 (axis tg1)) 0.0 1e- (vlax-curve-GetPointAtParam e x1))
         ((equal (setq a2 (axis tg2)) 0.0 1e- (vlax-curve-GetPointAtParam e x2))
         (T (setq xm (/ (- (* x1 a2) (* x2 a1)) (- a2 a1))
                  tgm (vlax-curve-GetFirstDeriv e xm))
            (if
              (<= (* a1 (axis tgm)) 0.0)
              (f x1 xm tg1 tgm axis)
              (f xm x2 tgm tg2 axis)
            )
         )
   )
 )

 (setq d (/ (- (vlax-curve-GetEndParam e) (setq x1 (vlax-curve-GetStartParam e))) 500.0)
       dir (cond
             ((mapcar '(lambda (x) (not (equal 1.0 (abs x) 1e-10))) (cdr (assoc 210 (entget e)))))
             ('(T T T))
           )
       lst (list (vlax-curve-GetPointAtParam e x1))
       tg1 (vlax-curve-GetFirstDeriv e x1)
 )
 (repeat 500
   (setq x2 (+ x1 d)
         tg2 (vlax-curve-GetFirstDeriv e x2)
         )
   (foreach axis
      (vl-remove nil
          (mapcar
            (function
              (lambda (tg1 tg2 dir a)
                (if (and dir (<= (* tg1 tg2) 0.0))
                    a
                )
              )
            )
            tg1  tg2  dir (list car cadr caddr)
          )
       )
     (setq lst (cons (f x1 x2 tg1 tg2 axis) lst))
   )
   (setq x1 x2 tg1 tg2)
 )
 (setq lst (cons (vlax-curve-GetPointAtParam e (vlax-curve-GetEndParam e)) lst))
 (mapcar '(lambda ( a ) (apply 'mapcar (cons a lst))) '(min max))
 )

Although the function getSplineBoundingBox will return the correct corners for any spline, including 3D, the test function works for planar splines in WCS.

(defun C:TEST ( / ss e l)
 (if
   (setq ss (ssget '((0 . "SPLINE"))))
   (repeat (sslength ss)
     (setq l (getSplineBoundingBox (setq e (ssname ss 0))))
     (command "RECTANGLE" "non" (car l) "non" (cadr l))
     (ssdel e ss)
     )
   )
 (princ)
 )

Link to comment
Share on other sites

I don't see why your test function wouldn't look like this :

 

 (defun C:TEST ( / ss e lst)
 (if
   (setq ss (ssget '((0 . "SPLINE"))))
   (repeat (sslength ss)
     (setq lst (getSplineBoundingBox (setq e (ssname ss 0))))
     (if (and (equal (caddr (car lst)) 0.0 1e-6) (equal (caddr (cadr lst)) 0.0 1e-6))
       (command "RECTANGLE" "non" (car lst) "non" (cadr lst))
       (command "BOX" "non" (car lst) "non" (cadr lst))
     )
     (ssdel e ss)
     )
   )
 (princ)
 )

In addition to what you discovered Stefan, I modified my old BoundingBoxofModelSpace.lsp so I'll post it here...

All thanks to you Stefan and also Lee Mac from who I borrowed almost whole code...

 

M.R.

BoundingBoxofModelSpace-new.lsp

BoundingBoxofModelSpace.lsp

Edited by marko_ribar
Link to comment
Share on other sites

Marko,

I let the decision of using BoundingBox points to the user so I didn't give much attention to the test function. Anyway, your test function will fail if the spline is parallel to yOz or zOx plane...

 

Unfortunately, my getSplineBoundingBox function is not working if the Spline doesn't have C1 continuity, that is, if it has sharp corners.

 

I don't know right now how to manage this, but I'm sure someone around here will find a solution

Link to comment
Share on other sites

Never mind Stefan, you already did nice job... I've updated my BBMSPACE routine, and if someone finds solution to this problem, it is only task to switch your subfunction in my code...

 

M.R.

Edited by marko_ribar
Link to comment
Share on other sites

Lee, I made TraceCurve so I can entmake wipeout. I'm still a beginner when it comes to the vlax-curve methods.

Link to comment
Share on other sites

Since nobody download my LSP, and since Lee's subfunction for adding objects to block that is posted on www doesn't include block rotation I've decided to post whole code with my modification of Lee's subfunction... If Lee could see it and maybe he has something to comment...

 

(vl-load-com)
(defun getSplineBoundingBox (e / f d i dir p1 p2 lst)
 
 (defun f (x1 x2 tg1 tg2 axis / a1 a2 xm tgm)
   (cond ((equal (setq a1 (axis tg1)) 0.0 1e- (vlax-curve-GetPointAtParam e x1))
         ((equal (setq a2 (axis tg2)) 0.0 1e- (vlax-curve-GetPointAtParam e x2))
         (T (setq xm (/ (- (* x1 a2) (* x2 a1)) (- a2 a1))
                  tgm (vlax-curve-GetFirstDeriv e xm))
            (if
              (<= (* a1 (axis tgm)) 0.0)
              (f x1 xm tg1 tgm axis)
              (f xm x2 tgm tg2 axis)
            )
         )
   )
 )

 (setq d (/ (- (vlax-curve-GetEndParam e) (setq x1 (vlax-curve-GetStartParam e))) 500.0)
       dir (cond
             ((mapcar '(lambda (x) (not (equal 1.0 (abs x) 1e-10))) (cdr (assoc 210 (entget e)))))
             ('(T T T))
           )
       lst (list (vlax-curve-GetPointAtParam e x1))
       tg1 (vlax-curve-GetFirstDeriv e x1)
 )
 (repeat 500
   (setq x2 (+ x1 d)
         tg2 (vlax-curve-GetFirstDeriv e x2)
         )
   (foreach axis
      (vl-remove nil
          (mapcar
            (function
              (lambda (tg1 tg2 dir a)
                (if (and dir (<= (* tg1 tg2) 0.0))
                    a
                )
              )
            )
            tg1  tg2  dir (list car cadr caddr)
          )
       )
     (setq lst (cons (f x1 x2 tg1 tg2 axis) lst))
   )
   (setq x1 x2 tg1 tg2)
 )
 (setq lst (cons (vlax-curve-GetPointAtParam e (vlax-curve-GetEndParam e)) lst))
 (mapcar '(lambda ( a ) (apply 'mapcar (cons a lst))) '(min max))
)

(defun newblkname ( / k blkn)
 (setq k 0)
 (while (not (null (tblsearch "BLOCK" (setq blkn (itoa (setq k (1+ k))))))))
 blkn
)

;;----------------=={ Add Objects to Block }==----------------;;
;; ;;
;; Adds all objects in the provided SelectionSet to the ;;
;; definition of the specified block. ;;
;;------------------------------------------------------------;;
;; Author: Lee McDonnell, June 2010 ;;
;; ;;
;; Copyright © 2010 by Lee McDonnell, All Rights Reserved. ;;
;; Contact: Lee Mac @ TheSwamp.org, CADTutor.net ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; block - Entity name of reference insert ;;
;; ss - SelectionSet of objects to add to definition ;;
;;------------------------------------------------------------;;

(defun LM:AddObjectstoBlock ( block ss / ObjLst org doc vector )
;; © Lee Mac 2010
(vl-load-com)

(setq ObjLst (LM:ss->vla ss) org (vlax-3D-point '(0. 0. 0.)))

(setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))

(setq vector
(vlax-3D-point
(mapcar '- (cdr (assoc 10 (entget block)))
(cdr
(assoc 10
(entget
(tblobjname "BLOCK"
(cdr (assoc 2 (entget block)))
)
)
)
)
)
)
)

(setq rot (- (* pi 2.0) (vla-get-rotation (vlax-ename->vla-object block))))

(mapcar '(lambda ( obj ) (vla-rotate obj (vlax-3D-point (cdr (assoc 10 (entget block)))) rot)) ObjLst)

(mapcar '(lambda ( obj ) (vla-move obj vector org)) ObjLst)

(vla-CopyObjects (vla-get-ActiveDocument (vlax-get-acad-object))
(LM:ObjectVariant ObjLst)
(vla-item (vla-get-Blocks doc)
(LM:GetBlockName (vlax-ename->vla-object block))
)
)

(LM:ApplyFootoSS (lambda ( x ) (entdel x)) ss)

(vla-regen doc acAllViewports)
)

;;-----------------=={ Remove From Block }==------------------;;
;; ;;
;; Removes an Entity from a Block Definition ;;
;;------------------------------------------------------------;;
;; Author: Lee McDonnell, June 2010 ;;
;; ;;
;; Copyright © 2010 by Lee McDonnell, All Rights Reserved. ;;
;; Contact: Lee Mac @ TheSwamp.org, CADTutor.net ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; ent - Entity name of Object to Delete from Block [ENAME] ;;
;;------------------------------------------------------------;;

(defun LM:RemovefromBlock ( ent )
;; © Lee Mac 2010
(vl-load-com)

(vla-Delete (vlax-ename->vla-object ent))
(vla-regen
(vla-get-ActiveDocument (vlax-get-acad-object)) acAllViewports
)
)

;;------------------=={ Safearray Variant }==-----------------;;
;; ;;
;; Creates a populated Safearray Variant of a specified ;;
;; data type ;;
;;------------------------------------------------------------;;
;; Author: Lee McDonnell, June 2010 ;;
;; ;;
;; Copyright © 2010 by Lee McDonnell, All Rights Reserved. ;;
;; Contact: Lee Mac @ TheSwamp.org, CADTutor.net ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; datatype - variant type enum (eg vlax-vbDouble) ;;
;; data - list of static type data ;;
;;------------------------------------------------------------;;
;; Returns: VLA Variant Object of type specified ;;
;;------------------------------------------------------------;;

(defun LM:SafearrayVariant ( datatype data )
;; © Lee Mac 2010
(vlax-make-variant
(vlax-safearray-fill
(vlax-make-safearray datatype
(cons 0 (1- (length data)))
)
data
)
)
)

;;-------------------=={ Object Variant }==-------------------;;
;; ;;
;; Creates a populated Object Variant ;;
;;------------------------------------------------------------;;
;; Author: Lee McDonnell, June 2010 ;;
;; ;;
;; Copyright © 2010 by Lee McDonnell, All Rights Reserved. ;;
;; Contact: Lee Mac @ TheSwamp.org, CADTutor.net ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; lst - list of VLA Objects to populate the Variant. ;;
;;------------------------------------------------------------;;
;; Returns: VLA Object Variant ;;
;;------------------------------------------------------------;;

(defun LM:ObjectVariant ( lst )
;; © Lee Mac 2010
(LM:SafearrayVariant vlax-vbobject lst)
)

;;-----------------=={ SelectionSet -> VLA }==----------------;;
;; ;;
;; Converts a SelectionSet to a list of VLA Objects ;;
;;------------------------------------------------------------;;
;; Author: Lee McDonnell, June 2010 ;;
;; ;;
;; Copyright © 2010 by Lee McDonnell, All Rights Reserved. ;;
;; Contact: Lee Mac @ TheSwamp.org, CADTutor.net ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; ss - Valid SelectionSet (Pickset) ;;
;;------------------------------------------------------------;;
;; Returns: List of VLA Objects ;;
;;------------------------------------------------------------;;

(defun LM:ss->vla ( ss )
;; © Lee Mac 2010
(if ss
(
(lambda ( i / e lst )
(while (setq e (ssname ss (setq i (1+ i))))
(setq lst (cons (vlax-ename->vla-object e) lst))
)
lst
)
-1
)
)
)

;;-------------------=={ Get Block Name }==-------------------;;
;; ;;
;; Retrieves the Block Name as per the Block Definition ;;
;;------------------------------------------------------------;;
;; Author: Lee McDonnell, June 2010 ;;
;; ;;
;; Copyright © 2010 by Lee McDonnell, All Rights Reserved. ;;
;; Contact: Lee Mac @ TheSwamp.org, CADTutor.net ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; obj - VLA Block Reference Object ;;
;;------------------------------------------------------------;;
;; Returns: Block Name [sTR] ;;
;;------------------------------------------------------------;;

(defun LM:GetBlockName ( obj )
(vlax-get-property obj
(if (vlax-property-available-p obj 'EffectiveName)
'EffectiveName 'Name
)
)
)

;;------------------=={ Apply Foo to SS }==-------------------;;
;; ;;
;; Applies a function to every entity in a SelectionSet ;;
;;------------------------------------------------------------;;
;; Author: Lee McDonnell, June 2010 ;;
;; ;;
;; Copyright © 2010 by Lee McDonnell, All Rights Reserved. ;;
;; Contact: Lee Mac @ TheSwamp.org, CADTutor.net ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; foo - a function taking one argument (an entity name) ;;
;; ss - valid SelectionSet (pickset) ;;
;;------------------------------------------------------------;;
;; Returns: Last evaluation of function foo ;;
;;------------------------------------------------------------;;

(defun LM:ApplyFootoSS ( foo ss )
;; © Lee Mac 2010
(
(lambda ( i / e )
(while (setq e (ssname ss (setq i (1+ i)))) (foo e))
)
-1
)
)

(defun BBMSP (ss boxblptlst / xmin xmax ymin ymax emin emax boxsplptlst ss n entss msp blks blck blckins ent)
(setq msp (vla-get-modelspace (vla-get-activedocument (vlax-get-acad-object))))
(setq xmin (- (car (getvar 'viewctr)) (* (/ (car (getvar 'screensize)) (cadr (getvar 'screensize))) (/ (getvar 'viewsize) 2.0))) xmax (+ (car (getvar 'viewctr)) (* (/ (car (getvar 'screensize)) (cadr (getvar 'screensize))) (/ (getvar 'viewsize) 2.0))))
(setq ymin (- (cadr (getvar 'viewctr)) (/ (getvar 'viewsize) 2.0)) ymax (+ (cadr (getvar 'viewctr)) (/ (getvar 'viewsize) 2.0)))
(setq emin (list xmin ymin) emax (list xmax ymax))
(if (null ss) (setq ss (ssget "_WP" (list emin (list (car emax) (cadr emin)) emax (list (car emin) (cadr emax)))))) 
(if ss
(progn
(repeat (setq n (sslength ss))
(setq entss (ssname ss (setq n (1- n))))
(if (eq (cdr (assoc 0 (entget entss))) "SPLINE")
(progn
(if (and (equal (caddr (car (getSplineBoundingBox entss))) 0.0 1e-6) (equal (caddr (cadr (getSplineBoundingBox entss))) 0.0 1e-6))
(setq boxspl (entmakex (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 4) '(70 . 1) (cons 10 (car (getSplineBoundingBox entss))) (cons 10 (list (caadr (getSplineBoundingBox entss)) (cadar (getSplineBoundingBox entss)) 0.0)) (cons 10 (cadr (getSplineBoundingBox entss))) (cons 10 (list (caar (getSplineBoundingBox entss)) (cadadr (getSplineBoundingBox entss)) 0.0)) '(210 0.0 0.0 1.0))))
(setq boxspl (vlax-vla-object->ename (vla-addbox msp (vlax-3d-point (mapcar '/ (mapcar '+ (car (getSplineBoundingBox entss)) (cadr (getSplineBoundingBox entss))) (list 2.0 2.0 2.0))) (- (caadr (getSplineBoundingBox entss)) (caar (getSplineBoundingBox entss))) (- (cadadr (getSplineBoundingBox entss)) (cadar (getSplineBoundingBox entss))) (- (caddr (cadr (getSplineBoundingBox entss))) (caddr (car (getSplineBoundingBox entss)))))))
)
(setq boxsplptlst (cons (car (getSplineBoundingBox entss)) boxsplptlst))
(ssdel entss ss)
(ssadd boxspl ss)
)
)
)
(setq blks (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))))
(setq blck (vla-add blks (vlax-3d-point '(0 0 0)) (newblkname)))
(setq blckins (vla-insertBlock msp (vlax-3d-point '(0 0 0)) (vla-get-name blck) 1 1 1 0))
(setq ent (entlast))
(LM:AddObjectstoBlock ent ss)
(vla-update blckins)
(vla-getboundingbox blckins 'minpoint 'maxpoint)
(setq minpt (vlax-safearray->list minpoint))
(setq maxpt (vlax-safearray->list maxpoint))
(foreach pt boxsplptlst
(LM:RemovefromBlock (car (nentselp pt)))
)
(if boxblptlst
(foreach pt boxblptlst
(LM:RemovefromBlock (car (nentselp pt)))
)
)
(vla-Explode blckins)
(vla-Erase blckins)
(vla-PurgeAll (vla-get-activedocument (vlax-get-acad-object)))
(if (and (equal (caddr minpt) 0.0 1e-6) (equal (caddr maxpt) 0.0 1e-6))
(entmakex (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 4) '(70 . 1) (cons 10 (list (car minpt) (cadr minpt) 0.0)) (cons 10 (list (car maxpt) (cadr minpt) 0.0)) (cons 10 (list (car maxpt) (cadr maxpt) 0.0)) (cons 10 (list (car minpt) (cadr maxpt) 0.0)) '(210 0.0 0.0 1.0)))
(vla-addbox msp (vlax-3d-point (mapcar '/ (mapcar '+ minpt maxpt) (list 2.0 2.0 2.0))) (- (car maxpt) (car minpt)) (- (cadr maxpt) (cadr minpt)) (- (caddr maxpt) (caddr minpt)))
)
(print (list minpt maxpt))
(prompt "\nminpt - !minpt;maxpt - !maxpt")
)
(prompt "\nError : no entities in Model Space that make bounding box")
)
)

(defun c:BBMSPACE ( / osm ap boxblptlst ss n entss msp boxbl)
(alert "\nIf you haven't saved changes made to your DWG, it is strongly recommended that you save DWG before execution of this routine")
(alert "\nMake sure inserted Blocks and Xrefs are at distance so their imaginary Bounding Box don't overlap")
(setq ap (getvar 'aperture))
(setq osm (getvar 'osmode))
(setvar 'aperture 50)
(setvar 'osmode 0)
(setq msp (vla-get-modelspace (vla-get-activedocument (vlax-get-acad-object))))
(setq ss (ssget "_X" '((410 . "Model"))))
(if ss
(progn
(repeat (setq n (sslength ss))
(setq entss (ssname ss (setq n (1- n))))
(if (eq (cdr (assoc 0 (entget entss))) "INSERT")
(progn
(vla-getboundingbox (vlax-ename->vla-object entss) 'minpt 'maxpt)
(setq minpt (vlax-safearray->list minpt) maxpt (vlax-safearray->list maxpt))
(if (and (equal (caddr minpt) 0.0 1e-6) (equal (caddr maxpt) 0.0 1e-6))
(progn
(setq boxbl (entmakex (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 4) '(70 . 1) (cons 10 (list (car minpt) (cadr minpt) 0.0)) (cons 10 (list (car maxpt) (cadr minpt) 0.0)) (cons 10 (list (car maxpt) (cadr maxpt) 0.0)) (cons 10 (list (car minpt) (cadr maxpt) 0.0)) '(210 0.0 0.0 1.0))))
(LM:AddObjectstoBlock entss (ssadd boxbl))
(entupd entss)
(vl-cmdf "_.ZOOM" "o" entss "")
(if (vlax-property-available-p (vlax-ename->vla-object entss) 'Path) (vl-cmdf "-XREF" "B" (cdr (assoc 2 (entget entss)))))
(vl-cmdf "-REFEDIT" (osnap minpt "_end") "ok" "" "")
(vl-cmdf "-LAYER" "U" "*" "")
(vl-cmdf "_.ERASE" (ssget "C" (osnap minpt "_end") (osnap minpt "_end")) "")
(bbmsp nil nil)
(vl-cmdf "_.REFCLOSE" "")
(vl-cmdf "-REFEDIT" (osnap minpt "_end") "ok" "" "")
(vl-cmdf "_.REFSET" "r" (osnap minpt "_end") "")
(vl-cmdf "_.REFCLOSE" "")
(entupd entss)
(setq boxblptlst (cons (osnap minpt "_end") boxblptlst))
)
(progn
(setq boxbl (vlax-vla-object->ename (vla-addbox msp (vlax-3d-point (mapcar '/ (mapcar '+ minpt maxpt) (list 2.0 2.0 2.0))) (- (car maxpt) (car minpt)) (- (cadr maxpt) (cadr minpt)) (- (caddr maxpt) (caddr minpt)))))
(LM:AddObjectstoBlock entss (ssadd boxbl))
(entupd entss)
(vl-cmdf "_.ZOOM" "o" entss "")
(if (vlax-property-available-p (vlax-ename->vla-object entss) 'Path) (vl-cmdf "-XREF" "B" (cdr (assoc 2 (entget entss)))))
(vl-cmdf "-REFEDIT" (osnap minpt "_end") "ok" "" "")
(vl-cmdf "-LAYER" "U" "*" "")
(vl-cmdf "_.ERASE" (ssget "C" (osnap minpt "_end") (osnap minpt "_end")) "")
(bbmsp nil nil)
(vl-cmdf "_.REFCLOSE" "")
(vl-cmdf "-REFEDIT" (osnap minpt "_end") "ok" "" "")
(vl-cmdf "_.REFSET" "r" (osnap minpt "_end") "")
(vl-cmdf "_.REFCLOSE" "")
(entupd entss)
(setq boxblptlst (cons (osnap minpt "_end") boxblptlst))
)
)
)
)
)
(if (setq ss (ssget "_X" '((410 . "Model"))))
(repeat (setq n (sslength ss))
(setq entss (ssname ss (setq n (1- n))))
(if (eq (cdr (assoc 0 (entget entss))) "INSERT")
(ssdel entss ss)
)
)
)
(vl-cmdf "_.ZOOM" "e")
)
)
(bbmsp ss boxblptlst)
(vl-cmdf "_.copybase" '(0.0 0.0 0.0) (ssadd (entlast)) "" "")
(alert "\nIf you had Xrefs attached in DWG - close DWG (discard changes), open DWG and \"pasteclip\" Bounding Box to 0,0,0")
(setvar 'aperture ap)
(setvar 'osmode osm)
(princ)
)

M.R.

Edited by marko_ribar
Link to comment
Share on other sites

Thanks Lee, your new functions are OK... I guess I don't visit your site too often... I've added new version of *.lsp in above post...

 

Thanks again, M.R.

 

P.S. I'VE NOTICED THAT YOUR OLD VERSION THAT I MODIFIED, IN THIS CASE, FUNCTIONS BETTER THAN NEW VERSION WITH YOUR LATEST SUBFUNCTIONS...

Edited by marko_ribar
P.S.
Link to comment
Share on other sites

I am so stupid there were sys variables for this thing...

 

This will work no matter of geometry orientation or type of geometry (blocks, xrefs, ... )...

 

(defun c:BBMSPACE ( / osm msp ) (vl-load-com)
 (setq msp (vla-get-modelspace (vla-get-activedocument (vlax-get-acad-object))))
 (setq osm (getvar 'osmode))
 (vl-cmdf "_.UCS" "w")
 (vl-cmdf "-VIEW" "TOP")
 (vl-cmdf "_.ZOOM" "e")
 (setvar 'osmode 0)
 (setq emin (getvar 'extmin))
 (setq emax (getvar 'extmax))
 (if (not (or (equal (caddr emin) (caddr emax) 1e-3) (equal (cadr emin) (cadr emax) 1e-3) (equal (car emin) (car emax) 1e-3)))
 (vla-addbox msp (vlax-3d-point (mapcar '/ (mapcar '+ emin emax) (list 2.0 2.0 2.0))) (- (car emax) (car emin)) (- (cadr emax) (cadr emin)) (- (caddr emax) (caddr emin)))
 )
 (if (equal (caddr emin) (caddr emax) 1e-3)
 (progn
 (vl-cmdf "-VIEW" "TOP")
 (vl-cmdf "_.RECTANGLE" "non" (list (car emin) (cadr emin) (caddr emin)) "non" (list (car emax) (cadr emax) (caddr emin)))
 )
 )
 (if (equal (cadr emin) (cadr emax) 1e-3) 
 (progn
 (vl-cmdf "-VIEW" "FRONT")
 (vl-cmdf "_.RECTANGLE" "non" (list (car emin) (caddr emin) (- (cadr emin))) "non" (list (car emax) (caddr emax) (- (cadr emin))))
 )
 )
 (if (equal (car emin) (car emax) 1e-3) 
 (progn
 (vl-cmdf "-VIEW" "RIGHT")
 (vl-cmdf "_.RECTANGLE" "non" (list (cadr emin) (caddr emin) (car emin)) "non" (list (cadr emax) (caddr emax) (car emin)))
 )
 )
 (print (list emin emax))
 (prompt "\nminpt - !emin;maxpt - !emax")
 (setvar 'osmode osm)
 (princ)
)

M.R.

BBMSPACE.lsp

Edited by marko_ribar
Link to comment
Share on other sites

One again thank you all guru here. Thx a lot for Marko Ribar. I like your code on post#28 , but this code a bit slow for the drawing if have many spline. I have a doubt about the code post#28. If insert a block in the drawing, your program cannot work.

 

For the post#31, I really like it, this code running very fast, but i don't know why the boundary are not exact to the spline.

 

After I understand your code, I make my own code:-

 

(defun c:spp2 (/ sp1 sp2 ss ss1 cab)
(setq cab `)
(command "osmode" 0)
(command "ucs" "w")
(setq sp1 (getpoint "\nPls Pick First Point "))
(setq sp2 (getcorner sp1 "\nPls Pick Second Point ")) 
(if ( /= (setq ss (ssget "c" sp1 sp2 '((-4 . "<and") (-4 . "<or") (0 . "SPLINE") (-4 . "or>")(-4 . "<OR")(8 . "0")(8 . "PLINE")(-4 . "OR>")(-4 . "and>")))) nill)
   (progn
       (spp1 ss)
   )
)
(if (/= (setq ss1 (ssget "c" sp1 sp2 '((-4 . "<and")(-4 . "<OR") (0 . "LINE")(0 . "CIRCLE")(0 . "ARC")(0 . "ELLIPSE")(0 . "LWPOLYLINE")(0 . "POLYLINE")(0 . "INSERT")(-4 . "OR>")(-4 . "<OR")(8 . "0")(8 . "PLINE")(-4 . "OR>")(-4 . "and>")))) nil)
       (progn                
           (out1 ss1)
       );progn
);if
(setq cab (mapcar '(lambda ( a ) (apply 'mapcar (cons a rar))) '(min max)))
(command "rectang" (nth 0 cab) (nth 1 cab))
(command "osmode" 37)
);defun    

(defun spp1 (aaa)
(setq sq `)
(setq vv (ss2en aaa))
(mapcar '(lambda (k)
(setq sa (vlax-curve-getEndParam k )) 
(setq c 0)
(while (> sa c)
(setq sq (cons  (vlax-curve-getPointAtParam k c) sq))
(setq c (+ c 0.1))
);while
(setq sq (cons  (vlax-curve-getPointAtParam k sa) sq))
(setq rar (mapcar '(lambda ( a ) (apply 'mapcar (cons a sq))) '(min max)))
(setq sq rar)
) vv)
);defun

(defun ss2en (ss  / abc ss i )        
(setq abc `)        
(setq i 0)        
(setq nn (sslength ss))         
(repeat nn        
   (setq sname (ssname ss i))    
   (setq abc (cons sname abc))    
   (setq i (+ i 1))    
);repeat        
(apply 'list abc)        
);defun        



(defun LM:SSBoundingBox ( ss1 / i l1 l2 ll ur )
   (repeat (setq i (sslength ss1))
       (vla-getboundingbox (vlax-ename->vla-object (ssname ss1 (setq i (1- i)))) 'll 'ur)
       (setq l1 (cons (vlax-safearray->list ll) l1)
             l2 (cons (vlax-safearray->list ur) l2)
       )
   )
   (mapcar '(lambda ( c d ) (apply 'mapcar (cons c d))) '(min max) (list l1 l2))
)

(defun out1 ( ss1 / ss1 )
(setq bb `)
           (if (/= (sslength ss1) nil)
               (progn
                   (setq bb (LM:SSBoundingBox ss1))
               );progn
           );if
           (mapcar '(lambda (x)
               (setq rar (cons x rar))
           ) bb)
   (princ)
)
(vl-load-com)


 

My code have a bug, for block rotation, the box will have gap. Any guru can help me to solve it?

Link to comment
Share on other sites

kwwong6, can you tell us what version of CAD are you running... My code posted at post #31 are exact on spline objects as with all other objects... I am running A2008 and >. I checked on A2012 too... Can you explain better your case with spline... Maybe post *.dwg...

 

Sincerely, M.R.

Link to comment
Share on other sites

Indeed you're wright kwwong6... My code from post #31 has some gaps... So it's not ab CAD version... But also with your code there is also now different bug - precision of result bounding box is dependable of segmentation along curve object (see attached dwg)... Anyway, if you don't need exact results I would suggest that you use my code, as it's applicable to all type of objects and any orientation... As you stated your code will bug with blocks rotated...

 

M.R.

test_spline.dwg

Link to comment
Share on other sites

And my code from post #28 gave exact results... So, after all my coding payed off. This is I supose just for this case, when all objects are splines and in WCS plane (not vertical like Stefan explained - when parallel with xOz or yOz plane - suggested only solution is code post #31 although it's not precise)... But, when you have blocks and they ovelap, maybe the best solution is to explode them, execute my code - post #28, close DWG discard changes, open again and paste BBOX in DWG with blocks or xrefs...

 

M.R.

test_spline.dwg

Edited by marko_ribar
Link to comment
Share on other sites

If you need more precise just modify this line in my program.

 

(setq c (+ c 0.001))

 

 

For this changes the program will run slowly but more precise and I can accept this tolerance .

 

Thx.

Link to comment
Share on other sites

Here is my new version and it is faster than code in post #28 and I think that now doesn't matter weather blocks or xrefs overlap... Still remains problem with SPLINES parallel to xOz and yOz plane... But everything else functions perfectly...

 

(vl-load-com)
(defun getSplineBoundingBox (e / f d i dir p1 p2 lst)
 
 (defun f (x1 x2 tg1 tg2 axis / a1 a2 xm tgm)
   (cond ((equal (setq a1 (axis tg1)) 0.0 1e- (vlax-curve-GetPointAtParam e x1))
         ((equal (setq a2 (axis tg2)) 0.0 1e- (vlax-curve-GetPointAtParam e x2))
         (T (setq xm (/ (- (* x1 a2) (* x2 a1)) (- a2 a1))
                  tgm (vlax-curve-GetFirstDeriv e xm))
            (if
              (<= (* a1 (axis tgm)) 0.0)
              (f x1 xm tg1 tgm axis)
              (f xm x2 tgm tg2 axis)
            )
         )
   )
 )

 (setq d (/ (- (vlax-curve-GetEndParam e) (setq x1 (vlax-curve-GetStartParam e))) 500.0)
       dir (cond
             ((mapcar '(lambda (x) (not (equal 1.0 (abs x) 1e-10))) (cdr (assoc 210 (entget e)))))
             ('(T T T))
           )
       lst (list (vlax-curve-GetPointAtParam e x1))
       tg1 (vlax-curve-GetFirstDeriv e x1)
 )
 (repeat 500
   (setq x2 (+ x1 d)
         tg2 (vlax-curve-GetFirstDeriv e x2)
         )
   (foreach axis
      (vl-remove nil
          (mapcar
            (function
              (lambda (tg1 tg2 dir a)
                (if (and dir (<= (* tg1 tg2) 0.0))
                    a
                )
              )
            )
            tg1  tg2  dir (list car cadr caddr)
          )
       )
     (setq lst (cons (f x1 x2 tg1 tg2 axis) lst))
   )
   (setq x1 x2 tg1 tg2)
 )
 (setq lst (cons (vlax-curve-GetPointAtParam e (vlax-curve-GetEndParam e)) lst))
 (mapcar '(lambda ( a ) (apply 'mapcar (cons a lst))) '(min max))
)

;;----------------=={ Add Objects to Block }==----------------;;
;;                                                            ;;
;;  Adds all objects in the provided SelectionSet to the      ;;
;;  definition of the specified block.                        ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2011 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  doc   - Document Object in which block resides.           ;;
;;  block - Entity name of reference insert                   ;;
;;  ss    - SelectionSet of objects to add to definition      ;;
;;------------------------------------------------------------;;

(defun LM:AddObjectstoBlock ( doc block ss / lst mat )
 
 (setq lst (LM:ss->vla ss)
       mat (LM:Ref->Def block)
       mat (vlax-tmatrix (append (mapcar 'append (car mat) (mapcar 'list (cadr mat))) '((0. 0. 0. 1.))))
 )
 (foreach obj lst (vla-transformby obj mat))

 (vla-CopyObjects doc (LM:SafearrayVariant vlax-vbobject lst)
   (vla-item (vla-get-Blocks doc) (cdr (assoc 2 (entget block))))
 )
 (foreach obj lst (vla-delete obj))
 (vla-regen doc acAllViewports)
)

;;-----------------=={ Remove From Block }==------------------;;
;;                                                            ;;
;;  Removes an Entity from a Block Definition                 ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2011 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  ent - Entity name of Object to Delete from Block [ENAME]  ;;
;;------------------------------------------------------------;;

(defun LM:RemovefromBlock ( doc ent )
 (vla-delete (vlax-ename->vla-object ent))
 (vla-regen doc acAllViewports)
 (princ)
)

;;------------------=={ Safearray Variant }==-----------------;;
;;                                                            ;;
;;  Creates a populated Safearray Variant of a specified      ;;
;;  data type                                                 ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2011 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  datatype - variant type enum (eg vlax-vbDouble)           ;;
;;  data     - list of static type data                       ;;
;;------------------------------------------------------------;;
;;  Returns:  VLA Variant Object of type specified            ;;
;;------------------------------------------------------------;;
                        
(defun LM:SafearrayVariant ( datatype data )
 (vlax-make-variant
   (vlax-safearray-fill
     (vlax-make-safearray datatype (cons 0 (1- (length data)))) data
   )    
 )
)

;;------------=={ SelectionSet -> VLA Objects }==-------------;;
;;                                                            ;;
;;  Converts a SelectionSet to a list of VLA Objects          ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2011 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  ss - Valid SelectionSet (Pickset)                         ;;
;;------------------------------------------------------------;;
;;  Returns:  List of VLA Objects, else nil                   ;;
;;------------------------------------------------------------;;

(defun LM:ss->vla ( ss / i l )
 (if ss
   (repeat (setq i (sslength ss))
     (setq l (cons (vlax-ename->vla-object (ssname ss (setq i (1- i)))) l))
   )
 )
)

;;---------------=={ Block Ref -> Block Def }==---------------;;
;;                                                            ;;
;;  Returns the Transformation Matrix and Translation Vector  ;;
;;  for transforming Block Reference Geometry to the Block    ;;
;;  Definiton.                                                ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2011 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  e - Block Reference Entity                                ;;
;;------------------------------------------------------------;;
;;  Returns:  List of 3x3 Transformation Matrix, Vector       ;;
;;------------------------------------------------------------;;

(defun LM:Ref->Def ( e / _dxf a l n )

 (defun _dxf ( x l ) (cdr (assoc x l)))

 (setq l (entget e) a (- (_dxf 50 l)) n (_dxf 210 l))
 (
   (lambda ( m )
     (list m
       (mapcar '- (_dxf 10 (tblsearch "BLOCK" (_dxf 2 l)))
         (mxv m
           (trans (_dxf 10 l) n 0)
         )
       )
     )
   )
   (mxm
     (list
       (list (/ 1. (_dxf 41 l)) 0. 0.)
       (list 0. (/ 1. (_dxf 42 l)) 0.)
       (list 0. 0. (/ 1. (_dxf 43 l)))
     )
     (mxm
       (list
         (list (cos a) (sin (- a)) 0.)
         (list (sin a) (cos a)     0.)
         (list    0.        0.     1.)
       )
       (mapcar '(lambda ( e ) (trans e n 0 t))
        '(
           (1. 0. 0.)
           (0. 1. 0.)
           (0. 0. 1.)
         )
       )
     )
   )
 )
)

;; Matrix x Vector  -  Vladimir Nesterovsky
(defun mxv ( m v )
 (mapcar '(lambda ( r ) (apply '+ (mapcar '* r v))) m)
)

;; Matrix x Matrix  -  Vladimir Nesterovsky
(defun mxm ( m q )
 (mapcar (function (lambda ( r ) (mxv (trp q) r))) m)
)

;; Matrix Transpose  -  Doug Wilson
(defun trp ( m )
 (apply 'mapcar (cons 'list m))
)

(defun BBB (ss / xmin xmax ymin ymax emin emax ss n entss bb bbl)
(setq xmin (- (car (getvar 'viewctr)) (* (/ (car (getvar 'screensize)) (cadr (getvar 'screensize))) (/ (getvar 'viewsize) 2.0))) xmax (+ (car (getvar 'viewctr)) (* (/ (car (getvar 'screensize)) (cadr (getvar 'screensize))) (/ (getvar 'viewsize) 2.0))))
(setq ymin (- (cadr (getvar 'viewctr)) (/ (getvar 'viewsize) 2.0)) ymax (+ (cadr (getvar 'viewctr)) (/ (getvar 'viewsize) 2.0)))
(setq emin (list xmin ymin) emax (list xmax ymax))
(if (null ss) (setq ss (ssget "_WP" (list emin (list (car emax) (cadr emin)) emax (list (car emin) (cadr emax)))))) 
(if ss
(progn
(repeat (setq n (sslength ss))
(setq entss (ssname ss (setq n (1- n))))
(if (eq (cdr (assoc 0 (entget entss))) "SPLINE")
(progn
(setq bb (getSplineBoundingBox entss))
(setq bbl (cons (car bb) bbl) bbl (cons (cadr bb) bbl))
)
(progn
(vla-getboundingbox (vlax-ename->vla-object entss) 'minpt 'maxpt)
(setq bb (list (vlax-safearray->list minpt) (vlax-safearray->list maxpt)))
(setq bbl (cons (car bb) bbl) bbl (cons (cadr bb) bbl))
)
)
)
(setq minpt ((lambda (x) (apply 'mapcar (cons 'min x))) bbl))
(setq maxpt ((lambda (x) (apply 'mapcar (cons 'max x))) bbl))
(if (and (equal (caddr minpt) 0.0 1e-6) (equal (caddr maxpt) 0.0 1e-6))
(entmakex (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 4) '(70 . 1) (cons 10 (list (car minpt) (cadr minpt) 0.0)) (cons 10 (list (car maxpt) (cadr minpt) 0.0)) (cons 10 (list (car maxpt) (cadr maxpt) 0.0)) (cons 10 (list (car minpt) (cadr maxpt) 0.0)) '(210 0.0 0.0 1.0)))
(vla-addbox msp (vlax-3d-point (mapcar '/ (mapcar '+ minpt maxpt) (list 2.0 2.0 2.0))) (- (car maxpt) (car minpt)) (- (cadr maxpt) (cadr minpt)) (- (caddr maxpt) (caddr minpt)))
)
(print (list minpt maxpt))
(prompt "\nminpt - !minpt;maxpt - !maxpt")
)
(prompt "\nError : no entities in Model Space that make bounding box")
)
)

(defun c:BBOX ( / osm ap adoc boxblptlst ss sss pt n entss msp boxbl e)
(alert "\nIf you haven't saved changes made to your DWG, it is strongly recommended that you save DWG before execution of this routine")
(vl-cmdf "_.UCS" "w")
(vl-cmdf "_.PLAN" "")
(setq ap (getvar 'aperture))
(setq osm (getvar 'osmode))
(setvar 'aperture 50)
(setvar 'osmode 0)
(setq msp (vla-get-modelspace (setq adoc (vla-get-activedocument (vlax-get-acad-object)))))
(setq ss (ssget '((410 . "Model"))))
(setq sss (ssadd))
(if ss
(progn
(repeat (setq n (sslength ss))
(setq entss (ssname ss (setq n (1- n))))
(if (eq (cdr (assoc 0 (entget entss))) "INSERT")
(progn
(vla-getboundingbox (vlax-ename->vla-object entss) 'minpt 'maxpt)
(setq minpt (vlax-safearray->list minpt) maxpt (vlax-safearray->list maxpt))
(if (and (equal (caddr minpt) 0.0 1e-6) (equal (caddr maxpt) 0.0 1e-6))
(progn
(setq boxbl (entmakex (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 4) '(70 . 1) (cons 10 (list (car minpt) (cadr minpt) 0.0)) (cons 10 (list (car maxpt) (cadr minpt) 0.0)) (cons 10 (list (car maxpt) (cadr maxpt) 0.0)) (cons 10 (list (car minpt) (cadr maxpt) 0.0)) '(210 0.0 0.0 1.0))))
(LM:AddObjectstoBlock adoc entss (ssadd boxbl))
(entupd entss)
(vl-cmdf "_.ZOOM" "o" entss "")
(if (vlax-property-available-p (vlax-ename->vla-object entss) 'Path) (vl-cmdf "-XREF" "B" (cdr (assoc 2 (entget entss)))))
(ssadd entss ss)
(vl-cmdf "-REFEDIT" (osnap (list (car minpt) (cadr minpt)) "_end") "ok" "" "")
(vl-cmdf "-LAYER" "U" "*" "")
(vl-cmdf "_.ERASE" (ssget "C" (mapcar '+ minpt (list -0.01 -0.01 -0.01)) (mapcar '+ minpt (list 0.01 0.01 0.01))) "")
(bbb nil)
(vl-cmdf "_.REFCLOSE" "")
(vl-cmdf "-REFEDIT" (osnap (list (car minpt) (cadr minpt)) "_end") "ok" "" "")
(vl-cmdf "_.REFSET" "r" (osnap (list (car minpt) (cadr minpt)) "_end") "")
(vl-cmdf "_.REFSET" "r" (osnap (list (car minpt) (cadr maxpt)) "_end") "")
(vl-cmdf "_.REFSET" "r" (osnap (list (car maxpt) (cadr maxpt)) "_end") "")
(vl-cmdf "_.REFSET" "r" (osnap (list (car maxpt) (cadr minpt)) "_end") "")
(vl-cmdf "_.REFCLOSE" "")
(entupd entss)
(setq boxblptlst (cons (setq pt (osnap (list (car minpt) (cadr maxpt)) "_end")) boxblptlst))
(ssadd (setq e (ssname (ssget "C" (mapcar '+ pt (list -0.01 -0.01 -0.01)) (mapcar '+ pt (list 0.01 0.01 0.01))) 0)) sss)
(entupd (cdr (assoc -1 (entmod (subst (cons 67 1) (assoc 67 (entget e)) (entget e)))))) 
)
(progn
(setq boxbl (vlax-vla-object->ename (vla-addbox msp (vlax-3d-point (mapcar '/ (mapcar '+ minpt maxpt) (list 2.0 2.0 2.0))) (- (car maxpt) (car minpt)) (- (cadr maxpt) (cadr minpt)) (- (caddr maxpt) (caddr minpt)))))
(LM:AddObjectstoBlock adoc entss (ssadd boxbl))
(entupd entss)
(vl-cmdf "_.ZOOM" "o" entss "")
(if (vlax-property-available-p (vlax-ename->vla-object entss) 'Path) (vl-cmdf "-XREF" "B" (cdr (assoc 2 (entget entss)))))
(ssadd entss ss)
(vl-cmdf "-REFEDIT" (osnap (list (car minpt) (cadr minpt)) "_end") "ok" "" "")
(vl-cmdf "-LAYER" "U" "*" "")
(vl-cmdf "_.ERASE" (ssget "C" (mapcar '+ minpt (list -0.01 -0.01 -0.01)) (mapcar '+ minpt (list 0.01 0.01 0.01))) "")
(bbb nil)
(vl-cmdf "_.REFCLOSE" "")
(vl-cmdf "-REFEDIT" (osnap (list (car minpt) (cadr minpt)) "_end") "ok" "" "")
(vl-cmdf "_.REFSET" "r" (osnap (list (car minpt) (cadr minpt)) "_end") "")
(vl-cmdf "_.REFSET" "r" (osnap (list (car minpt) (cadr maxpt)) "_end") "")
(vl-cmdf "_.REFSET" "r" (osnap (list (car maxpt) (cadr maxpt)) "_end") "")
(vl-cmdf "_.REFSET" "r" (osnap (list (car maxpt) (cadr minpt)) "_end") "")
(vl-cmdf "_.REFCLOSE" "")
(entupd entss)
(setq boxblptlst (cons (setq pt (osnap (list (car minpt) (cadr maxpt)) "_end")) boxblptlst))
(ssadd (setq e (ssname (ssget "C" (mapcar '+ pt (list -0.01 -0.01 -0.01)) (mapcar '+ pt (list 0.01 0.01 0.01))) 0)) sss)
(entupd (cdr (assoc -1 (entmod (subst (cons 67 1) (assoc 67 (entget e)) (entget e))))))
)
)
)
)
)
)
)
(repeat (setq n (sslength sss))
(setq e (ssname sss (setq n (1- n))))
(entupd (cdr (assoc -1 (entmod (subst (cons 67 0) (assoc 67 (entget e)) (entget e))))))
)
(vl-cmdf "_.ZOOM" "e")
(foreach pt boxblptlst
(ssadd (ssname (ssget "C" (mapcar '+ pt (list -0.01 -0.01 -0.01)) (mapcar '+ pt (list 0.01 0.01 0.01))) 0) ss)
)
(if ss
(repeat (setq n (sslength ss))
(setq entss (ssname ss (setq n (1- n))))
(if (eq (cdr (assoc 0 (entget entss))) "INSERT")
(ssdel entss ss)
)
)
)
(bbb ss)
(vl-cmdf "_.copybase" '(0.0 0.0 0.0) (ssadd (entlast)) "" "")
(foreach pt boxblptlst
(vl-cmdf "_.ERASE" (ssget "C" (mapcar '+ pt (list -0.01 -0.01 -0.01)) (mapcar '+ pt (list 0.01 0.01 0.01))) "")
)
(vl-cmdf "_.pasteclip" '(0.0 0.0 0.0))
(print (list minpt maxpt))
(prompt "\nminpt - !minpt;maxpt - !maxpt")
(alert "\nIf you had Xrefs attached in DWG - close DWG (discard changes), open DWG and \"pasteclip\" Bounding Box to 0,0,0")
(setvar 'aperture ap)
(setvar 'osmode osm)
(princ)
)

P.S. Now you select objects like in your code, and thanks for posting it - it helped me to modify my algorithm to be better and faster...

 

M.R.

BoundingBox.lsp

Edited by marko_ribar
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...