Flatten all objects regardless their Elevations

Flatten all objects regardless their Elevations

hanywillim
Enthusiast Enthusiast
2,806 Views
19 Replies
Message 1 of 20

Flatten all objects regardless their Elevations

hanywillim
Enthusiast
Enthusiast

Hi Friends,
i have this lisp to flatten all objects inside and outside blocks but i have line with Elevation "3.000E+99" but it seems the lisp does Not flatten it and i have no idea why, If anyone can help to illustrate that to me and update the lisp to flatten all object regardless their elevations .
Thanks in advance.
Drawing with the issue in the attachments. 


 

(defun C:flatall ( / a n ss)
;  (vl-load-com)
  ; flatten objects inside blocks
   (vlax-for b (vla-get-blocks (setq a (vla-get-activedocument (vlax-get-acad-object)))) ; select all blocks
       (if (= :vlax-false (vla-get-isxref b)) ; ignore xref blocks
           (vlax-for o b
               (if (vlax-write-enabled-p o) ; chk if object can be moved
                   (foreach e '(1e99 -1e99)
                       (vlax-invoke o 'move '(0.0 0.0 0.0) (list 0.0 0.0 e))    ; flatten to 1e99 -1e99 which = 0 elevation 
                   ) ; foreach
               ) ; if
           ) ; vlax-for
       ) ; if
   ) ; vlax-for
  ; flatten objects outside blocks
   (if(setq ss (ssget"_X")) ; select all objects
     (progn     
      (setq ss (mapcar 'vlax-ename->vla-object (mapcar 'cadr (ssnamex ss)))) ; cnvert to list of entities then to vl obj
      (foreach i (list 1e99 -1e99) 
       (mapcar(function(lambda (x) (vla-move x (vlax-3d-point (list 0 0 0)) (vlax-3d-point (list 0 0 i))))) ss)    ; flatten to 1e99 -1e99 which = 0 elevation 
      ) ; foreach
     ) ; progn
   ) ; if ss
   (vla-regen a acallviewports) ; regen 
   (princ)
) ; defun flatall

 

 

0 Likes
2,807 Views
19 Replies
Replies (19)
Message 2 of 20

pendean
Community Legend
Community Legend
Can you share your DWG file here?
0 Likes
Message 3 of 20

arq.vr02.fernheim
Contributor
Contributor

This should flatten thinks. But keep an eye about blocks and text.

This works also inside of the block editor.

0 Likes
Message 4 of 20

ronjonp
Mentor
Mentor

Post your drawing.

 

Also .. just an observation but could improve speed on large drawings.

(if (setq ss (ssget "_X"))
    (progn (foreach o (mapcar 'vlax-ename->vla-object (mapcar 'cadr (ssnamex ss)))
	     ;; Check that the object can be moved like above
	     (if (vlax-write-enabled-p o)
	       (progn (vla-move o (vlax-3d-point '(0 0 0)) (vlax-3d-point '(0 0 1e99)))
		      (vla-move o (vlax-3d-point '(0 0 0)) (vlax-3d-point '(0 0 -1e99)))
	       )
	     )
	   )
	   ;; This code processes the entire drawing twice .. the code above does the same in one round
;;;      (foreach i (list 1e99 -1e99)
;;;	(mapcar	(function
;;;		  (lambda (x) (vla-move x (vlax-3d-point (list 0 0 0)) (vlax-3d-point (list 0 0 i))))
;;;		)
;;;		ss
;;;	)
;;;      )
    )
  )
0 Likes
Message 5 of 20

hanywillim
Enthusiast
Enthusiast

attached,  Thanks in advance

0 Likes
Message 6 of 20

hanywillim
Enthusiast
Enthusiast
i attached the drawing with the issue , thanks in advance
0 Likes
Message 7 of 20

leeminardi
Mentor
Mentor

Could the following be the issue?

 

AutoCAD's precision is about 15 significant digits.   Typically a drawing will have coordinates less than a million.  At a million you have 8 decimal places.  So, if you move the object in Z by an amount greater than 10e15 and then back by - 10e15 the z coordinates will be zeroed because at 10e15 all precision for the 15 right most digits are lost.  However, if you have a line at 3.000E+99 and you move it back and forth by 1e99  you don't lose any significant digits!

lee.minardi
0 Likes
Message 8 of 20

ronjonp
Mentor
Mentor

Do a search for SUPERFLATTEN. It works on that drawing. Since you don't check for the *Layout block this is all you need for your code. (still does not work on that drawing)

 

(defun c:flatall (/)
  (vlax-for b (vla-get-blocks (setq a (vla-get-activedocument (vlax-get-acad-object))))
    (if	(= 0 (vlax-get b 'isxref))
      (vlax-for	o b
	(if (vlax-write-enabled-p o)
	  (foreach e '(1e99 -1e99) (vlax-invoke o 'move '(0.0 0.0 0.0) (list 0.0 0.0 e)))
	)
      )
    )
  )
  (vla-regen a acallviewports)
  (princ)
)
(vl-load-com)

 

0 Likes
Message 9 of 20

hanywillim
Enthusiast
Enthusiast

You mean your code is equivalent to the code I posted in the beginning but more faster as long as i work only in the model space ( But is your code handle both the inside and outside blocks objects? )

0 Likes
Message 10 of 20

hanywillim
Enthusiast
Enthusiast

Yes you are right, SuperFlatten lisp is working as a charm with this drawing but i still does not get the isuue and how it fix it.
And if you could help to update the lisp to fix the elevation for the drawing i attached (by adding the missed part from supperflatten lisp) because the superflatten lisp is handle to many Casses but i want to use the shorten lisp you provide. 

0 Likes
Message 11 of 20

CADaSchtroumpf
Advisor
Advisor

Try my version, seem to work's with your drawing.

0 Likes
Message 12 of 20

ronjonp
Mentor
Mentor

@hanywillim wrote:

You mean your code is equivalent to the code I posted in the beginning but more faster as long as i work only in the model space ( But is your code handle both the inside and outside blocks objects? )


Yes it does inside blocks and the layouts. Think of Modelspace and paperspace tabs as 'blocks' that hold all the objects we draft.

 

Object Model.

0 Likes
Message 13 of 20

ronjonp
Mentor
Mentor

@hanywillim wrote:

Yes you are right, SuperFlatten lisp is working as a charm with this drawing but i still does not get the isuue and how it fix it.
And if you could help to update the lisp to fix the elevation for the drawing i attached (by adding the missed part from supperflatten lisp) because the superflatten lisp is handle to many Casses but i want to use the shorten lisp you provide. 


@hanywillim Try this hack 🙂

 

(defun c:flatall (/)
  (vlax-for b (vla-get-blocks (setq a (vla-get-activedocument (vlax-get-acad-object))))
    (if	(= 0 (vlax-get b 'isxref))
      (vlax-for	o b
	(if (vlax-write-enabled-p o)
	  (progn (if (= "AcDbLine" (vla-get-objectname o))
		   (foreach p '(startpoint endpoint)
		     (vlax-put o p (append (mapcar '+ '(0 0) (vlax-get o p)) '(0.)))
		   )
		   (foreach e '(1e99 -1e99) (vlax-invoke o 'move '(0. 0. 0.) (list 0. 0. e)))
		 )
	  )
	)
      )
    )
  )
  (vla-regen a acallviewports)
  (princ)
)
(vl-load-com)

 

0 Likes
Message 14 of 20

3dwannab
Advocate
Advocate

This drawing attached flattens the objects but it moves all the objects to the X plane.

 

All the programs I've tried here don't work.

 

0 Likes
Message 15 of 20

Kent1Cooper
Consultant
Consultant

@3dwannab wrote:

This drawing attached flattens the objects but it moves all the objects to the X plane.

.....


What is "the X plane"?  There's an X axis, but not an X plane -- an orthogonal plane is defined by two axis directions.  You must mean either the XY plane [all at Z=0] or the XZ plane [all at Y=0].  Or maybe you mean all at X=0, which would be in the YZ plane.  Your sample drawing already has everything in the XY plane at Z=0, which is what the world [and AutoCAD's FLATTEN command] considers the definition of "flattened."  For you, is this an unwanted "after" condition?  If so, what was the "before" condition?  What do you want instead?  If you mean you want things with Z-coordinate differences to be made flat parallel to the XY plane but not in that plane at Z=0, then which of a given object's varying Z values should be the level it should be flattened at?  If the drawing is the "before" condition, what are you looking for as an "after" result?  Etc.

Kent Cooper, AIA
0 Likes
Message 16 of 20

pendean
Community Legend
Community Legend

@3dwannab wrote:

This drawing attached flattens the objects but it moves all the objects to the X plane.

 


Explain more please: your file is NOTHING like the topic of this entire discussion (their file was astronomically far away from 0,0,0 in the Z-elevation, nothing more, they just needed to MOVE their content), but your file is perfectly "flat" and needs no more flattening at all

pendean_0-1728390656608.png

pendean_1-1728390798825.png

 

 

Notice the Y in the second screenshot: Are you by chance needing (or think you need) to draw "elevations" and non-plan "sections" in the vertical plane for some reason? I'm guessing based on your adopted screen name that 2D sections somehow need to be that way.

0 Likes
Message 17 of 20

3dwannab
Advocate
Advocate

I'm just trying to get my head around how the drawing can be flattened and still behave oddly when I run the ops post. Something is not quite right with the objects. See the attached drawing which shows on the left the hatch that will shoot up in the drawing when I run the OPs code with the hatch on the right which is newly created using inherited props from the dodgy hatch behaves just fine.

 

 

0 Likes
Message 18 of 20

pendean
Community Legend
Community Legend

@3dwannab What is NONZ command?

 

pendean_0-1728418250433.png

 

pendean_1-1728418359202.png

 

All looks normal when I rotate the UCS to FRONT for example too.pendean_2-1728418621624.png

 

0 Likes
Message 19 of 20

3dwannab
Advocate
Advocate

@pendean, it was the same as the OPs only I had the command changed. I was thinking this was a flattening issue.

 

But I found the issue. The extrusion was very much off. The DXF code 220 looked like this (210 0.0 4.44806e-10 1.0). Sorry for hijacking the thread. I didn't know this was the case.

 

I fixed that by writing this lisp in case anyone has encountered this issue when running the OPs code.

 

It's funny that superflatten.lsp or the native FLATTEN command don't take care of this.

 

 

(vl-load-com)
;;
;; Fix the extrusuion values of hatches so they are 0,0,1
;;
;; TESTING VERSION
;;
;; Thread here: https://www.cadtutor.net/forum/topic/92094-flatten-issue-with-drawing
;;
;; 3dwannab 2024.10.08
;;
;; TO DO:
;; - Make this work for ENTITIES inside BLOCKS
;;

(defun c:FXHatchExtrusion_To_0 (/ *error* acDoc cnt dxf210 ent entData newEntData newExtrude newExtrudeVal obj oldExtrude ss typ var_cmdecho) 

  (defun *error* (errmsg) 
    (and acDoc (vla-EndUndoMark acDoc))
    (and errmsg 
         (not (wcmatch (strcase errmsg) "*CANCEL*,*EXIT*"))
         (princ (strcat "\n<< Error: " errmsg " >>\n"))
    )
    (setvar 'cmdecho var_cmdecho)
  )

  ;; Start the undo mark here
  (setq acDoc (vla-get-ActiveDocument (vlax-get-acad-object)))
  (or (vla-EndUndoMark acDoc) (vla-StartUndoMark acDoc))

  ;; Get any system variables here
  (setq var_cmdecho (getvar "cmdecho"))
  (setvar 'cmdecho 0)

  (if (setq ss (ssget "_:L" '((0 . "HATCH")))) 

    (progn 

      (repeat (setq cnt (sslength ss)) 

        (setq cnt (1- cnt))
        (setq ent (_dxf -1 (entget (ssname ss cnt))))
        (setq entData (entget ent)) ; Get the entity's data list

        (setq obj (vlax-ename->vla-object ent))
        (setq typ (cdr (assoc 0 (entget ent))))

        (cond 
          ;; Placeholder condition for other entities
          ; ((= typ "**")
          ; ) ;; end cond

          ;; Condition for HATCHES.
          ((= typ "HATCH")
           (setq newExtrudeVal 0.0) ; Set this to 0.0
           (if (setq dxf210 (assoc 210 entData)) 
             (progn 
               (setq oldExtrude (cdr dxf210)) ;; Extract the current extrude components
               (setq newExtrude (list (nth 0 oldExtrude) newExtrudeVal (nth 2 oldExtrude))) ;; Create the new extrude with the modified Y component
               (setq newEntData (subst (cons 210 newExtrude) dxf210 entData)) ;; Replace the old extrude with the new extrude
               (entmod newEntData) ;; Apply the changes to the HATCH entity
               (entupd ent) ; Update the entity to reflect the change
             )
           )
          ) ;; end cond HATCH
        )
      )
    ) ;; progn
  ) ;; if ssget

  (if ss 
    (progn 
      (princ (strcat ">> " (itoa (sslength ss)) (if (> (sslength ss) 1) "  objects extrude values are" "  objects extrude value is") " fixed <<\n"))
      (sssetfirst nil ss)
      (command "_.regen")
    )
  )

  (vla-EndUndoMark acDoc)

  (*error* nil)
  (princ)
)

;; -----------------------------------------------------------------------
;; ----------------------=={ Functions START }==--------------------------

;;----------------------------------------------------------------------;;
;; _dxf
;; Finds the association pair, strips 1st element
;; args   - dxfcode elist
;; Example  - (_dxf -1 (entget (ssname (ssget) 0)))
;; Returns  - <Entity name: xxxxxxxxxxx>

(defun _dxf (code elist) 
  (cdr (assoc code elist))
)

;;(c:FXHatchExtrusion_To_0) ;; Unlbock for testing

 

 

0 Likes
Message 20 of 20

pendean
Community Legend
Community Legend
Thanks for sharing your solution.