Offset Multiple Polylines to New Layer?

3arizona
Advocate
Advocate

Offset Multiple Polylines to New Layer?

3arizona
Advocate
Advocate

Can someone help me add to this lisp?   I want to place each of the 4 offsets to an existing layer.

Layer Names: 

L1, L2, L3 & L4

 

Thanks

 

 (defun C:TEST(/ lstDis obj)
 (setq lstDIS '(1  2 -1 -3))
 (while (setq obj (car (entsel "\nSelect object:")))
 (foreach dis lstDIS
 (vla-offset (vlax-ename->vla-object obj) dis)
 )
 )
 (princ)
 )
0 Likes
Reply
Accepted solutions (3)
2,826 Views
18 Replies
Replies (18)

Kent1Cooper
Consultant
Consultant

A couple of ways you could do that [untested].  A list of pairs:

(defun C:TEST1(/ lstDisLyr ent obj)
  (setq lstDisLyr '((1 "L1") (2 "L2") (-1 "L3") (-3 "L4")))
  (while (setq ent (car (entsel "\nSelect object:")))
    (foreach pair lstDisLyr
(vla-offset (setq obj (vlax-ename->vla-object ent)) (car pair))
(vla-put-Layer obj (cadr pair)) ) ) (princ) )

or a pair of lists:

(defun C:TEST(/ lstDis lstLAY ent obj)
  (setq lstDIS '(1  2 -1 -3) lstLAY '("L1" "L2" "L3" "L4"))
  (while (setq ent (car (entsel "\nSelect object:")))
    (foreach dis lstDIS
      (vla-offset (setq obj (vlax-ename->vla-object ent)) dis)
(vla-put-Layer obj (nth (vl-position dis lstDIS) lstLAY)) ) ) (princ) )

… and there are surely other ways.

Kent Cooper, AIA
0 Likes

3arizona
Advocate
Advocate

Kent,

Both lisps work. only one problem,  offsets lines do not keep layer sequence. I can go around and set the layer sequence to match line work. I've attached a drawing so that you can see it better. 

 

thank you for your time

0 Likes

Kent1Cooper
Consultant
Consultant

@3arizona wrote:

...  offsets lines do not keep layer sequence. ....


Oh, of course -- my fault.  This part:
  (vla-put-Layer obj  ... ;;; [that's still the source  object]

should be

  (vla-put-Layer (vlax-ename->vla-object (entlast)) ... ;;; [that's the new one]

 

And that also means there's no need for the 'obj' variable, so it can be removed from the localized variables list at the beginning, and this part:

  (vla-offset (setq obj (vlax-ename->vla-object ent))  ...

can be just this

  (vla-offset (vlax-ename->vla-object ent)  ... 

Kent Cooper, AIA
0 Likes

Moshe-A
Mentor
Mentor

Kent hi,

 

Weird,  it looks like (vla-offset) does not return the newly create line but in the documentation it saids it does

 

Return Value (RetVal)

Type: Variant (array of objects)

An array of the newly created objects resulting from the offset.

 

 

Moshe

 

0 Likes

ronjonp
Advisor
Advisor

Try this mod of Kent's code:

(defun c:test1 (/ e o)
  (while (setq e (car (entsel "\nSelect object:")))
    (foreach pair '((1 "L1") (2 "L2") (-1 "L3") (-3 "L4"))
      ;; vlax-invoke will return a list of objects rather than an array
      (setq o (car (vlax-invoke (vlax-ename->vla-object e) 'offset (car pair))))
      ;; Use entmod so layer does not need to exist
      (entmod (append (entget (vlax-vla-object->ename o)) (list (cons 8 (cadr pair)))))
    )
  )
  (princ)
)

3arizona
Advocate
Advocate

Works!  is there a way i can change Layer L1 thickness to .01? 

 

thanks

0 Likes

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

....  (vla-put-Layer (vlax-ename->vla-object (entlast)) ... ;;; [that's the new one]


I wouldn't think it matters what (vla-offset) returns, only that it makes  a new object [which admittedly could be more than one with convoluted Polyline or Spline shapes].  But it seems that in the process, for (vla-... purposes,(entlast) somehow doesn't "register" until maybe after the sequence for the particular entry in the (foreach) loop -- in any case the above adjustment didn't work.  But in place of the (vla-put-Layer) approach, this CHPROP approach does  recognize (entlast) within that loop, and works for me:

 

(defun C:TEST2 (/ lstDisLyr ent)
  (setq lstDisLyr '((1 "L1") (2 "L2") (-1 "L3") (-3 "L4")))
  (while (setq ent (car (entsel "\nSelect object:")))
    (foreach pair lstDisLyr
      (vla-offset (vlax-ename->vla-object ent) (car pair))
      (command "_.chprop" (entlast) "" "_layer" (cadr pair) "")
    )
  )
  (princ)
)

[The Layers do need to exist in the drawing already.]

 

Kent Cooper, AIA
0 Likes

Kent1Cooper
Consultant
Consultant

@3arizona wrote:

....  is there a way i can change Layer L1 thickness to .01? ....


Careful about your terminology.  Layers can't have  thickness -- only objects can [AutoCAD's meaning of the word is up off the page,  in the Z-axis direction].  Layers can have lineweight, if that's what you mean.

 

If the Layers would already exist, make that setting a part of that Layer outside the routine -- there's no point in imposing that every time you run it.

 

If the Layers might not  already exist in the drawing, you could incorporate a Layer command into the routine that would create all those Layers and assign whatever properties you want to them, as you would at the command line with the -LAYER command.  For example:

 

(command "_.layer"

  "_new" "L1,L2,L3,L4"

  "_color" 1 "L1" "_color" 2 "L2" "_color" 3 "L3" "_color" 4 "L4"

  "_lweight" 0.01 "L1"

  ""

)

Kent Cooper, AIA
0 Likes

3arizona
Advocate
Advocate

I appreciate your time. 1 step i forgot to ask. Current command is set for multiple command. how do i make it exit command Without hitting enter at the end.

 

Thanks and have a great weekend

.

 

0 Likes

ronjonp
Advisor
Advisor

Why do you choose to use a command call to entlast when vla-offset creates an object that can be modified? THIS IMO is a simpler solution.

Kent1Cooper
Consultant
Consultant
Accepted solution

@3arizona wrote:

.... Current command is set for multiple command. how do i make it exit command Without hitting enter at the end.  ....


If you want to do it to only one  object, you can just take it out of the (while) loop.  Remove the red parts:
....

  (while (setq ent (car (entsel "\nSelect object:")))
    (foreach pair lstDisLyr
      (vla-offset (vlax-ename->vla-object ent) (car pair))
      (command "_.chprop" (entlast) "" "_layer" (cadr pair) "")
    )
  )

....

Kent Cooper, AIA
0 Likes

3arizona
Advocate
Advocate

Kent,

 

The lisp has been working like charm.  I've been using this to offset rectangles. I just noticed that if i draw a rectangle using corner to corner (no dimension) the lines offset inward (that's what i want). If i draw a rectangle using coordinates (Rectangle;pick point;@30,20) it offsets outwards.  I put in an option to pick an offset side and it still offsets outward. 

 

Is there a fix for this? I'm good if it offsets to one side all the time as long as it consistent.

Pick Offset Side:

(setq ent (car (entsel "\nSelect object:")))
(setq p (getpoint "\n Specify side offset :"))
(foreach dis lstDIS
(vla-offset (vlax-ename->vla-object ent) dis)
(vla-put-Layer (vlax-ename->vla-object (entlast)) (nth (vl-position dis lstDIS) lstLAY))

0 Likes

ronjonp
Advisor
Advisor

You need to check if the polyline is drawn clockwise or not.

0 Likes

3arizona
Advocate
Advocate

RPEREZ,

 

i figured that was the problem. I want to know if somehow the lisp can be forced to always offset one direction, either in or out. 

 

thanks

0 Likes

dlanorh
Advisor
Advisor
You're not using "p" anywhere. What governs whether the offset is "left", "right", outwards or inwards is the sign of the distance (+ or -) , how the polyline is constructed (clockwise or anti clockwise) and whether it is closed or open. A polyline that is closed on itself by specifying the start coords as the end coords, can still be considered an open polyline by autocad until the closed option or property is used.

I am not one of the robots you're looking for

0 Likes

ronjonp
Advisor
Advisor
Accepted solution

Try something like this:

(defun c:foo (/ lm:clockwise-p a e o l)
  ;; Clockwise-p  -  Lee Mac
  ;; Returns T if p1,p2,p3 are clockwise oriented
  (defun lm:clockwise-p	(p1 p2 p3)
    ((lambda (n) (< (car (trans p2 0 n)) (car (trans p1 0 n)))) (mapcar '- p1 p3))
  )
  ;; Change your layer names and offset distances here
  (setq l '((15 "L1") (30 "L2") (45 "L3") (60 "L4")))
  (if (setq s (ssget '((0 . "lwpolyline") (-4 . ">") (90 . 2))))
    (foreach e (vl-remove-if 'listp (mapcar 'cadr (ssnamex s)))
      (setq a (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= 10 (car x))) (entget e))))
      (setq a (cond ((lm:clockwise-p (car a) (cadr a) (caddr a)) -)
		    (+)
	      )
      )
      (foreach pair l
	;; vlax-invoke will return a list of objects rather than an array
	(setq o (car (vlax-invoke (vlax-ename->vla-object e) 'offset (a (car pair)))))
	;; Use entmod so layer does not need to exist
	(entmod (append (entget (vlax-vla-object->ename o)) (list (cons 8 (cadr pair)))))
      )
    )
  )
  (princ)
)
0 Likes

Kent1Cooper
Consultant
Consultant
Accepted solution

@3arizona wrote:

....  I've been using this to offset rectangles. I just noticed that if i draw a rectangle using corner to corner (no dimension) the lines offset inward (that's what i want). If i draw a rectangle using coordinates (Rectangle;pick point;@30,20) it offsets outwards.  ….


I think that may vary depending on in what order you pick the corners -- lower-left to upper-right may give a different result than lower-right to upper-left.  But if they're always rectangles, maybe the easiest way to guarantee Offsetting inward is with a regular Offset command, using the halfway point between opposite corners as the to-which-side input.

 

If 'pl' is the Polyline rectangle's entity name, you can do it in various ways, for instance:

(command "_.offset" YourDistance pl

  (polar

    (setq v0 (vlax-curve-getStartPoint pl))

    (angle v0 (setq v2 (vlax-curve-getPointAtParam pl 2.0)))

    (/ (distance v0 v2) 2)

  )

  ""

)

 

And to guarantee Offsetting outward, calculate a point guaranteed to be outside:

 

(command "_.offset" YourDistance pl

  (polar

    (setq v0 (vlax-curve-getStartPoint pl))

    (angle v0 (setq v2 (vlax-curve-getPointAtParam pl 2.0)))

    (* (distance v0 v2) 1.1)

  )

  ""

)

 

But that would need to be modified if other shapes might sometimes be involved.  There are routines out there that will, for example, use (vla-offset) and then compare the length or area of the result to the original, and if its not the right relationship, delete that one and do the (vla-offset) again with the opposite sign on the distance. 

Kent Cooper, AIA
0 Likes

3arizona
Advocate
Advocate

Kent/ RPEREZ

 

Thank you both. I truly appreciate it. 

0 Likes