Trimming lines under dynamic block

Trimming lines under dynamic block

dlbsurveysuk
Collaborator Collaborator
245 Views
14 Replies
Message 1 of 15

Trimming lines under dynamic block

dlbsurveysuk
Collaborator
Collaborator

Hi, I've got the following code that makes use of Lee mac's "Set Dynamic Block Property Value" routine to insert a dynamic block between two parallel lines using 3 picks to specify the insertion point, rotation+length, and width.

 

The first problem is that quite often one side of the block is not exactly over the line below (even though I've snapped perpendicular to it). I noticed this because the line below can't be trimmed out below the block.

I've discovered that if I include a vla-sendcommand to FLATTEN the block after insertion it will then be perfectly over the line which now becomes trimmable.

 

Solving the first problem causes a second problem - the dynamic block loses it's grips and is no longer adjustable.

 

Any ideas? (dynamic block attached)

Thanks.

 

;; Set Dynamic Block Property Value  -  Lee Mac
;; Modifies the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; val - [any] New value for property
;; Returns: [any] New value if successful, else nil

(defun LM:setdynpropvalue ( blk prp val )
    (setq prp (strcase prp))
    (vl-some
       '(lambda ( x )
            (if (= prp (strcase (vla-get-propertyname x)))
                (progn
                    (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                    (cond (val) (t))
                )
            )
        )
        (vlax-invoke blk 'getdynamicblockproperties)
    )
)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(defun c:WIN (/ *error* osm normal pt1 pt2 pt3 d w o)

         (defun *error* (MSG)
            (if (/= MSG "Function cancelled")
                (princ (strcat "\nError: " MSG)))
              (if osm (setvar 'osmode OSM))
          (princ) )

(vl-load-com)
(setq OSM (getvar 'osmode))
(setq NORMAL (trans '(0.0 0.0 1.0) 2 0 T))

(setvar 'osmode 512)
  (setq PT1 (getpoint "\nInsertion point: "))
  (setq PT2 (getpoint PT1 "\nRotation and length: "))
(setvar 'osmode 128)
  (setq PT3 (getpoint PT2 "\nWidth: "))
(setvar 'osmode 0)

(entmake
      (list
           '(0 . "INSERT") '(8 . "WINDOW") '(2 .  "fulldw") (cons 10 (trans PT1 1 0))
           (cons 50 (+ (angle PT1 PT2) (angle '(0.0 0.0 0.0) (trans '(1.0 0.0 0.0) 2 NORMAL T))))
            (cons 41 1) (cons 42 1) (cons 43 1)
      )
)

	(setq o (vlax-ename->vla-object (entlast)))

	(setq d (distance PT1 PT2))
	(setq w (distance PT2 PT3))

    (LM:setdynpropvalue o "Length Stretch" (rtos d 2 3))
    (LM:setdynpropvalue o "Distance3" (rtos w 2 3))

(setvar 'osmode OSM)

(vla-Sendcommand (vla-Get-ActiveDocument (vlax-Get-Acad-Object)) "_FLATTEN\r_L\r\r\r")
(vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) "WIN ")

(princ)
)

 

0 Likes
246 Views
14 Replies
Replies (14)
Message 2 of 15

dlbsurveysuk
Collaborator
Collaborator

Was thinking maybe the block isn't perfect in some way, but if not, why is it fine a lot of the time?

 

Also, I forgot to mention that if I don't flatten the block I can zoom in, grab the dynamic grip and re snap perpendicular, which also corrects things. 

0 Likes
Message 3 of 15

dlbsurveysuk
Collaborator
Collaborator

Or maybe it's something to do with the precision of (setq w (distance PT2 PT3)) and (LM:setdynpropvalue o "Distance3" (rtos w 2 3)) ?

0 Likes
Message 4 of 15

dlbsurveysuk
Collaborator
Collaborator

Attached screenshot to clarify.

 

If, after running the Lisp I measure from the block corner to perp the red wall line it gives 0.000 but the wall line is not trimmable. If I then grab the "3. Width" grip and re-snap perp to the wall line, I can then trim out the wall line (red) below the block.

 

Dynamic-Grips.JPG

0 Likes
Message 5 of 15

Sea-Haven
Mentor
Mentor

A maybe when selecting point 3 you don't need perp but nearest etc would be ok, you pick an object say a line can then use.

 

(defun wow ( / )
  (setq ent (entsel "\nPick 1st point on line  "))
  (setq pt1 (cadr ent))
  (setq obj (vlax-ename->vla-object (car ent)))
  (setq pt1 (vlax-curve-getclosestpointto obj pt1))

  (setq ent (entsel "\nPick 2nd point on line  "))
  (setq pt2 (cadr ent))
  (setq obj (vlax-ename->vla-object (car ent)))
  (setq pt2 (vlax-curve-getclosestpointto obj pt2))

  (setq ent (entsel "\nPick 3rd point on line  "))
  (setq obj (vlax-ename->vla-object (car ent)))
  (setq pt3 (vlax-curve-getclosestpointto obj pt1))
  (princ)
)
(wow)

 

0 Likes
Message 6 of 15

dlbsurveysuk
Collaborator
Collaborator

Thanks for the reply.

 

This works if I edit

(setq pt3 (vlax-curve-getclosestpointto obj pt1))

to 

(setq pt3 (vlax-curve-getclosestpointto obj pt2))

 AND I am in WCS.

 

It no longer works in a UCS (plan rotated around the z axis).

 

Also, I forgot to mention that I'm using this for tracing over point clouds.

 

With my code the GETPOINT gave me crosshairs and the OSNAP snapped to linework.

 

With ENTSEL it gives me a selection box and I have to selection cycle to choose the linework and not the point cloud. I don't know if there is a way to force crosshairs and auto ignore the point cloud?

 

Thanks.

0 Likes
Message 7 of 15

ВeekeeCZ
Consultant
Consultant

Must be missing something...

Why do you limit the precision in the first place? Just supply the function with a full real number. 

Also, the usage of FLATEN. It does not make any sense. Don't use it.

 

You should also post some dwg in real coordinates where it 'often' fails. Can't really replicate the issue.

0 Likes
Message 8 of 15

dlbsurveysuk
Collaborator
Collaborator

OK. Thanks for the tips. I can't remember why the precision was limited, I cobbled this code together some time ago.

 

The FLATTEN was a bit random, it is commented out.

 

I'll edit the code and see how it performs.

0 Likes
Message 9 of 15

dlbsurveysuk
Collaborator
Collaborator

This is another routine that inserts a dynamic block between two lines in a similar way to the previous one. I've edited the code to remove the precision limit.

 

This one fails to be exactly over the lines pretty much every time. So I can't trim to the block unless I do some manual re-snapping.

 

Test drawing attached showing after insertion with a "overhang" of zero, so the ends of the block should be bang over the vertical lines to be trimmed.

 

Maybe sorting this one will point me in the right direction to fix the previous one?

 

(defun c:CILL (/ *error* osm normal pt1 pt2 pt3 d w o)

         (defun *error* (MSG)
            (if (/= MSG "Function cancelled")
                (princ (strcat "\nError: " MSG)))
              (if osm (setvar 'osmode OSM))
          (princ) )

(setq OSM (getvar 'osmode))

  (setq NORMAL (trans '(0.0 0.0 1.0) 1 0 T))

(setvar 'osmode 512)
     (setq PT1 (getpoint "Insertion Point...?"))
(setvar 'osmode 128)
     (setq PT2 (getpoint PT1 "\nLength: "))
(setvar 'osmode 0)
    (setq PT3 (getpoint PT2 "\nOverhang: "))

      (entmake
	(list
	    '(0 . "INSERT")
	    '(8 . "WINDOW")
	    '(100 . "AcDbEntity")
	    '(100 . "AcDbBlockReference")
	    (cons 2 "wcill - PA1")
	    (cons 10 (trans pt1 1 NORMAL))
	    (cons 50 (+ (angle '(0 0 0) (trans (getvar 'ucsxdir) 0 NORMAL T)) 0)) ;;; zero rotation
	    (cons 210 NORMAL)
	)
      )

	(setq o (vlax-ename->vla-object (entlast)))

	(setq d (distance PT1 PT2))
	(setq w (distance PT2 PT3))

    (LM:setdynpropvalue o "Distance1" d)
    (LM:setdynpropvalue o "Distance2" w)

(setvar 'osmode OSM)

(princ)
)

  

0 Likes
Message 10 of 15

ВeekeeCZ
Consultant
Consultant

This seems to be working.... didn't try the UCS though.

 

(defun c:WIN (/ *error* osm normal p1 p2 p3 d w o a e e1 e2 pm)
  
  (defun *error* (MSG)
    (if (/= MSG "Function cancelled")
      (princ (strcat "\nError: " MSG)))
    (if osm (setvar 'osmode OSM))
    (princ) )
  
  (vl-load-com)
  (setq OSM (getvar 'osmode))
  (setq NORMAL (trans '(0.0 0.0 1.0) 2 0 T))
  
  (setvar 'osmode 512)
  (setq p1 (getpoint "\nInsertion point: "))
  (setq e1 (car (nentselp p1)))
  (setq p2 (getpoint p1 "\nRotation and length: "))

  (setvar 'osmode 128)
  (setq p3 (getpoint p2 "\nWidth: "))
  (setq e2 (car (nentselp p3)))

  (setq a (angle p1 p2))
  (setq d (distance p1 p2))
  (setq w (distance p2 p3))
  (setq pm (polar p3 a (/ d -2)))
  
  (setq e (entmakex (list '(0 . "INSERT") '(8 . "WINDOW") '(2 .  "fulldw") (cons 10 (trans p1 1 0))
			  (cons 50 (+ a (angle '(0.0 0.0 0.0) (trans '(1.0 0.0 0.0) 2 NORMAL T))))
			  (cons 41 1) (cons 42 1) (cons 43 1)
			  )))
  
  (setpropertyvalue e  "AcDbDynBlockPropertyLength Stretch" d)
  (setpropertyvalue e  "AcDbDynBlockPropertyDistance3" w)
  (setq d2 (getpropertyvalue e "AcDbDynBlockPropertyDistance2"))

  (command "_.break" e1 "_non" p1 "_non" p2)
  (command "_.break" e2 "_non" (polar pm a (/ d2 -2)) "_non" (polar pm a (/ d2 2)))

  (setvar 'osmode OSM)
  
  (princ)
  )

 

0 Likes
Message 11 of 15

dlbsurveysuk
Collaborator
Collaborator

Thanks. That does seem to work. (I've removed your BREAK commands because the idea is to insert the dynamic block, then do adjustments using the dynamic grips, and then trim out the wall lines)

 

I've applied your coding (which basically removes the need for the Lee Mac routine) to the CILL routine from above, and I'm still getting the same problem of each end of the block not sitting directly over the linework.

 

(defun c:CILL (/ *error* osm normal pt1 pt2 pt3 d w o entc)

         (defun *error* (MSG)
            (if (/= MSG "Function cancelled")
                (princ (strcat "\nError: " MSG)))
              (if osm (setvar 'osmode OSM))
          (princ) )

(setq OSM (getvar 'osmode))

  (setq NORMAL (trans '(0.0 0.0 1.0) 1 0 T))

(setvar 'osmode 512)
     (setq PT1 (getpoint "Insertion Point...?"))
(setvar 'osmode 128)
     (setq PT2 (getpoint PT1 "\nLength: "))
(setvar 'osmode 0)
    (setq PT3 (getpoint PT2 "\nOverhang: "))

   (setq entc
      (entmakex
	(list
	    '(0 . "INSERT")
	    '(8 . "WINDOW")
	    '(100 . "AcDbEntity")
	    '(100 . "AcDbBlockReference")
	    (cons 2 "wcill - PA1")
	    (cons 10 (trans pt1 1 NORMAL))
	    (cons 50 (+ (angle '(0 0 0) (trans (getvar 'ucsxdir) 0 NORMAL T)) 0)) ;;; zero rotation
	    (cons 210 NORMAL)
	)
      )
    )

	(setq d (distance PT1 PT2))
	(setq w (distance PT2 PT3))

  (setpropertyvalue entc "AcDbDynBlockPropertyDistance1" d)
  (setpropertyvalue entc "AcDbDynBlockPropertyDistance2" w)

(setvar 'osmode OSM)

(princ)
)
0 Likes
Message 12 of 15

ВeekeeCZ
Consultant
Consultant

I don't know what you mean by "not sitting over the linework". Don't know what's expected behaviour. 

The coding is so simple that it is more likely that the block definition is wrong than the coding.

0 Likes
Message 13 of 15

Sea-Haven
Mentor
Mentor

Ok in the add window or door in what I have we pick a line then use that line to get pt2, by using getdist from pt1, use polar command, using code I posted already to snap pt1 correctly. Then pt3.

 

An extra in the window we ask offset from end rather than pick a point,  it has MID as a default.

 

Can you not just add a wipeout to your block ? Not tested.

0 Likes
Message 14 of 15

Moshe-A
Mentor
Mentor

@dlbsurveysuk  hi,

 

First i think you can use BREAK command but the problem with it, at first prompt (e.g Select object:  ) you answer with only the object ename (e.g e1 / e2) you can also provide the point (same as return from entsel) as (list <ename> pt) and if this does not solve the issue i would change the order:

 

first accept all input from user (e.g start point, open width, wall width, rotation) then go straight to break the wall (so the block does not interfere) only then insert the block.

 

enjoy,

Moshe 

0 Likes
Message 15 of 15

dlbsurveysuk
Collaborator
Collaborator

Apologies. You are correct, the block definition was incorrect.

 

Sorry for any wasted time, although you have shown me how to manipulate the block property values without using the Lee Mac routine, which has been helpful.

 

Thanks.