gsc Posted January 10, 2023 Posted January 10, 2023 Hi, In a LISP routine I use this command to offset several closed polylines (simple line shapes, no arcs) to the outside of the closed polyline (vlax-invoke obj 'offset distance))) If the distance is a positive value, the offset is performed to the outside (and a negative value to inside) But "Outside/Inside" also depends on the direction in which the closed polyline is drawn. If the closed polyline is drawn in counter clockwise direction and the offset distance value is positive, then the offset command wants to offset the polyline to the inside. If this is the case AND the offset distance is set too large, the LISP function errors because it is not possible to create an offset with that distance to the inside (only to the outside). The initial closed polylines which needs to be offset, are drawn from a LIST of coordinates The order of the LIST with points of each closed polyline are either in clockwise or counter clockwise direction Is it possible to re-order a LIST of points always in clockwise direction? Quote
Steven P Posted January 10, 2023 Posted January 10, 2023 Just quickly some hints and will think about this shortly. You can use reverse to alter reverse a list of points, or here http://www.theswamp.org/index.php?topic=50007.msg552346#msg552346 This might come in useful, working out where the centre of the shape is (setq p (osnap (vlax-curve-getStartPoint (entlast)) "gcen")) if you want to do some thinking but an internet search comes up with this thread https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/polyline-direction-clockwise-or-counterclockwise/td-p/6050612 which I think this is the good stuff:: (defun ListClockwise-p (lst / z vlst) (vl-catch-all-apply 'minusp (list (if (not (equal 0.0 (setq z (apply '+ (mapcar (function (lambda (u v) (- (* (car u) (cadr v)) (* (car v) (cadr u))) ) ) (setq vlst (mapcar (function (lambda (a b) (mapcar '- b a)) ) (mapcar (function (lambda (x) (car lst))) lst) (cdr (reverse (cons (car lst) (reverse lst)))) ) ) (cdr (reverse (cons (car vlst) (reverse vlst)))) ) ) ) 1e-6 ) ) z (progn (prompt "\n\nChecked vectors are colinear - unable to determine clockwise-p of list") nil ) ) ) ) ) 1 Quote
mhupp Posted January 10, 2023 Posted January 10, 2023 (edited) *Side-note About using gcen method. This didn't work so well with plots of land that shared borders with each other. I think it had to do with the draw order. But it sometimes it was picking the geo center of the adjacent plots so it wasn't 100% accurate. This is what i used to check CW of a polyline. See example at start of lisp. will offset + or - depending on CW function. ;;----------------------------------------------------------------------------;; ; Checking if pline drawn CW or CCW - Writer Evgeniy Elpanov By Bill Gilliss ;(vla-offset (vlax-ename->vla-object entity) (if (CW entity) -0.01 0.01)) (defun CW (poly / lw lst LL UR) (setq lw (vlax-ename->vla-object poly)) (vla-GetBoundingBox lw 'LL 'UR) (setq LL (vlax-safearray->list LL) UR (vlax-safearray->list UR) lst (mapcar (function (lambda (x) (vlax-curve-getParamAtPoint poly (vlax-curve-getClosestPointTo poly x) ) ) ) (list LL (list (car LL) (cadr UR)) UR (list (car UR) (cadr LL)) ) ) ) (if (or (<= (car lst) (cadr lst) (caddr lst) (cadddr lst)) (<= (cadr lst) (caddr lst) (cadddr lst) (car lst)) (<= (caddr lst) (cadddr lst) (car lst) (cadr lst)) (<= (cadddr lst) (car lst) (cadr lst) (caddr lst)) ) ;_ or t ) ) --Edit Another way is to offset with "both" option. Then check area of the polylines. tho if you have some funky shapes their could be more then two polylines created. Edited January 10, 2023 by mhupp 1 Quote
Steven P Posted January 10, 2023 Posted January 10, 2023 (edited) OK a very quick test on this: Hatch the area and create the boundary, delete the hatch and retain the boundary. Offset that and delete the first created boundary? Selection is done by clicking inside the closed polyline - though haven't checked or tried to break this idea yet that might fix drawing order of polylines on top of each other. Quickly checking, the hatch boundary is always drawn clockwise..... again I need to check this Lunch first though This will do it.. if there is nothing within the closed polyline - not perfect because it is for quite specific case (defun c:offsetoutside (/ ent dist obj) (vl-load-com) (princ "Pick a point inside the closed polyline shape") (command "-hatch" pause "") (setq myhatch (entlast)) (command "-hatchedit" myhatch "b" "P" "N") (setq MyBoundary (entlast)) (entdel myhatch) (setq dist (getreal "Enter Offset Distance")) (setq obj (vlax-ename->vla-object MyBoundary)) (vla-offset obj dist) ) Edited January 10, 2023 by Steven P Quote
gsc Posted January 10, 2023 Author Posted January 10, 2023 1 hour ago, Steven P said: Just quickly some hints and will think about this shortly. You can use reverse to alter reverse a list of points, or here http://www.theswamp.org/index.php?topic=50007.msg552346#msg552346 This might come in useful, working out where the centre of the shape is (setq p (osnap (vlax-curve-getStartPoint (entlast)) "gcen")) if you want to do some thinking but an internet search comes up with this thread https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/polyline-direction-clockwise-or-counterclockwise/td-p/6050612 which I think this is the good stuff:: (defun ListClockwise-p (lst / z vlst) (vl-catch-all-apply 'minusp (list (if (not (equal 0.0 (setq z (apply '+ (mapcar (function (lambda (u v) (- (* (car u) (cadr v)) (* (car v) (cadr u))) ) ) (setq vlst (mapcar (function (lambda (a b) (mapcar '- b a)) ) (mapcar (function (lambda (x) (car lst))) lst) (cdr (reverse (cons (car lst) (reverse lst)))) ) ) (cdr (reverse (cons (car vlst) (reverse vlst)))) ) ) ) 1e-6 ) ) z (progn (prompt "\n\nChecked vectors are colinear - unable to determine clockwise-p of list") nil ) ) ) ) ) I was already testing this sub function, but thanx anyway! Quote
gsc Posted January 11, 2023 Author Posted January 11, 2023 The sub function works perfectly i.c.w. a condition, Thanx for the hint! Quote
BIGAL Posted January 12, 2023 Posted January 12, 2023 This is what I use for CW CCW. ; Checking if pline is CW or CCW and set to CCW ; Orignal idea by Kent Cooper, 1 August 2018 Offsetinorout.lsp ; By Alan H July 2020 (defun AH:chkcwccw (ent / objnew area1 area2 obj minpoint maxpoint) (setq obj (vlax-ename->vla-object ent)) (vla-GetBoundingBox obj 'minpoint 'maxpoint) (setq pointmin (vlax-safearray->list minpoint)) (setq pointmax (vlax-safearray->list maxpoint)) (setq dist (/ (distance pointmin pointmax) 20.0)) (vla-offset obj dist) (setq objnew (vlax-ename->vla-object (entlast))) (setq area1 (vlax-get objnew 'Area)) (vla-delete objnew) (vla-offset obj (- dist)) (setq objnew (vlax-ename->vla-object (entlast))) (setq area2 (vlax-get objnew 'Area)) (vla-delete objnew) (if (> area1 area2) (progn (command "reverse" ent "") (setq y (+ y 1)) ) ) ) Quote
gsc Posted January 13, 2023 Author Posted January 13, 2023 10 hours ago, BIGAL said: This is what I use for CW CCW. ; Checking if pline is CW or CCW and set to CCW ; Orignal idea by Kent Cooper, 1 August 2018 Offsetinorout.lsp ; By Alan H July 2020 (defun AH:chkcwccw (ent / objnew area1 area2 obj minpoint maxpoint) (setq obj (vlax-ename->vla-object ent)) (vla-GetBoundingBox obj 'minpoint 'maxpoint) (setq pointmin (vlax-safearray->list minpoint)) (setq pointmax (vlax-safearray->list maxpoint)) (setq dist (/ (distance pointmin pointmax) 20.0)) (vla-offset obj dist) (setq objnew (vlax-ename->vla-object (entlast))) (setq area1 (vlax-get objnew 'Area)) (vla-delete objnew) (vla-offset obj (- dist)) (setq objnew (vlax-ename->vla-object (entlast))) (setq area2 (vlax-get objnew 'Area)) (vla-delete objnew) (if (> area1 area2) (progn (command "reverse" ent "") (setq y (+ y 1)) ) ) ) This is even a shorter code! Thanx for sharing, but my start is already a list of points of which I create the closed polylines. In short: My main routine places a dynamical block of a jack-up vessel (which is used to install Monopiles for windfarms at sea) somewhere in the world (WCS) to check if the 4 legs (the closed polylines) of the jack-up vessel don't conflict with restricted areas around the Monopile. If the dynamical block in a certain heading is inserted at the center point of the monopile, I need to offset those legs with a certain (safety) distance to check if one of them conflicts with a restricted area. So I have a subroutine which gets the WCS coordinates of the 4 legs of that block Instance in a list, of which we don't know if the list is CW/CCW ordered. And of course if we draw the legs inside the dynamical block already in the correct direction, this CW/CCW sub routine is not needed, but we have several Jack-up vessels and we are increasing and I don't want to bother my colleagues that they have to think about the drawing direction of the legs for new Jack-up Vessels because all 4 or 6 of them are symmetrical and therefor easy to mirror, which already causes the CW/CWW issue. Quote
BIGAL Posted January 13, 2023 Posted January 13, 2023 (edited) Pretty sure lee-mac submitted something that looks at 3 points and from angles determines CW or CCW. Edited January 13, 2023 by BIGAL Quote
mhupp Posted January 13, 2023 Posted January 13, 2023 1 hour ago, BIGAL said: Pretty sure lee-mac submitted something that looks at 3 points and from angles determines CW or CCW. http://www.lee-mac.com/clockwisep.html Quote
Recommended Posts
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.