Silvercloak Posted March 31, 2012 Posted March 31, 2012 Hi, so my new project was given to me by a civ3d guy. He wants to break a bunch of lines or plines, sometimes contours - by a set distance. Took me a few days to think of how I would approach it. Below is my solution; however I have one small problem. I cannot seem to get the break command to respond using my selection set entity. Does anyone know how I could fix this? ;;;March 31, 2012 ;;;This program will allow the user to select multiple lines and plines ;;;then it will temporarily move each line and pline to a temporary layer then layer isolate to THAT layer ;;;place points along each line and pline at a given distance by the user ;;;break each line at each point, return all lines and plines to their original layer ;;;and then unisolate and return to the current layer (defun layerchg () (command "-layer" "m" lyname "") (setq n (sslength SS1)) (repeat n (setq ENT (ssname SS1 (- N 1))) (setq ENTLIST (entget ENT)) (setq ENTLIST (subst (cons 8 LYNAME) (assoc 8 ENTLIST) ENTLIST)) (entmod ENTLIST) (setq n (- n 1)) ) ) (defun breakpt () (command "layiso" SS1 "") (setvar "Clayer" Lyname) (repeat (setq n (sslength ss1)) (setq ENT (ssname SS1 (- N 1))) (command "measure" ENT MSMT "") (setq SSpt (ssget "X" '((0 . "Point")))) (repeat (setq nx (sslength SSpt)) (setq SSPTS (ssname SSpt (- N 1))) (setq ptent (entget SSPTS)) (setq ptloc (cdr(assoc 10 ptent))) [color="red"](command "break" ent "f" ptloc ptloc)[/color] (setq n (- n 1)) ) ;End breaking repeat (command "erase" SSPT) ) ;End repeat ) (defun c:Linchg () (setq CurLay (getvar "clayer")) (setq Osnmde (getvar "osmode")) (setq Cmd-Echo (getvar "cmdecho")) (prompt "\nSelect all lines and/or plines you wish to change: " ) (setq SS1 (ssget '((0 . "LINE,LWPOLYLINE")))) (setq Msmt (getreal "Please enter the distance between break points.") ) (setq LYNAME "Temporary") (layerchg) (breakpt) ) Mind you, this isn't finished or cleaned up yet. It's still a work in progress, but until I can figure out how to get this break command to listen to me - I can't really progress. Silvercloak Quote
pBe Posted April 1, 2012 Posted April 1, 2012 (defun breakpt () (command "layiso" SS1 "") (setvar "Clayer" Lyname) (repeat (setq n (sslength ss1)) (setq ENT (ssname SS1 (- N 1))) (command "measure" ENT MSMT[color=blue]);;;<-remove ""[/color] (setq SSpt (ssget "X" '((0 . "Point")))) (repeat (setq nx (sslength SSpt)) (setq SSPTS (ssname SSpt (- [color=blue]nx[/color] 1))) (setq ptent (entget SSPTS)) (setq ptloc (cdr(assoc 10 ptent))) (command "break" ent [color=blue]"_non"[/color] ptloc [color=blue]"_non"[/color] ptloc)[color=#0000ff];;;<-remove "f"[/color] [color=blue](entdel SSPTS);;<-- delete point entity as you go [/color] [color=blue] (setq ent (entlast)) [/color] [color=blue](setq nx (- nx 1))[/color] ) ;End breaking repeat [color=blue] ;;;(command "erase" SSPT "");; commented[/color] [color=blue](setq n (- n 1))[/color] ) ;End repeat ) HTH Quote
Silvercloak Posted April 1, 2012 Author Posted April 1, 2012 Thanks pBe!! You even corrected my bugs, that's awesome! edit: Oh crap... I don't know how to get these entities back on their original layers, especially if they've been taken from multiple different layers. As soon as they've been broken they become different entities don't they? Quote
BlackBox Posted April 1, 2012 Posted April 1, 2012 I haven't gone through the entire code, but you may want to consider using a sub function for your break functionality that accepts two entities and a coordinate list (the break point), pseudo code: (defun _break (e1 e2 coord) ;; <-- Do something ) Other than that, it looks like you need to localize your varibles. Consider using some error handling to restore the original sysvars, and also consider placing the subfunctions you're using underneath the command function (localized) unless you're going to be using them as subs in other command functions too. Just a thought. HTH Quote
Silvercloak Posted April 1, 2012 Author Posted April 1, 2012 This is my final edit of this, unless I can figure out how to return the line sets to their original layers. ;;;March 31, 2012 ;;;This program will allow the user to select multiple lines and plines ;;;then it will temporarily move each line and pline to a temporary layer then layer isolate to THAT layer ;;;place points along each line and pline at a given distance by the user ;;;break each line at each point, return all lines and plines to their original layer ;;;and then unisolate and return to the current layer (defun layerchg () (setq ENT (ssname SS1 (- N 1))) (setq ENTLIST (entget ENT)) (setq ENTLIST (subst (cons 8 LYNAME) (assoc 8 ENTLIST) ENTLIST)) (entmod ENTLIST) ) (defun breakpt () (command "layiso" SS1 "") (setvar "Clayer" Lyname) (command "measure" ENT MSMT) (setq SSpt (ssget "X" '((0 . "Point")))) (repeat (setq nx (sslength SSpt)) (setq SSPTS (ssname SSpt (- Nx 1))) (setq ptent (entget SSPTS)) (setq ptloc (cdr (assoc 10 ptent))) (command "break" ent "_non" ptloc "_non" ptloc) (entdel SSPTS) ;;<-- delete point entity as you go (setq ent (entlast)) (setq nx (- nx 1)) ;;(command "erase" SSPT) ) ;End repeat ) ;;;/ (defun c:BrkLns (/ SS1 Lyname ENT MSMT SSpt nx ptent ptloc SSPTS Curlay Osnmde CMD-Echo) (setq CurLay (getvar "clayer")) (setq Osnmde (getvar "osmode")) (setq Cmd-Echo (getvar "cmdecho")) (setvar "osmode" 0) (setvar "cmdecho" 1) (prompt "\nSelect all lines and/or plines you wish to change: " ) (setq SS1 (ssget '((0 . "LINE,LWPOLYLINE")))) (setq Msmt (getreal "Please enter the distance between break points.") ) (setq LYNAME "Temporary") (command "-layer" "m" lyname "") (setq n (sslength SS1)) (repeat n (layerchg) (breakpt) (setq n (- n 1)) ) (command "layuniso") (setvar "osmode" osnmde) (setvar "clayer" curlay) (setvar "cmdecho" cmd-echo) (princ) ) Quote
pBe Posted April 1, 2012 Posted April 1, 2012 (edited) Alright silvercloak, instead of giving you fish, we'll teach you how to fish. I think the reason why you change the layers of the selected object is because you NEED to ISOLATE and select the "POINT" entities without disturbing the other similar enities But in my opinion you're approach is too much work. You dont need to create those [point enitites] to identify the break point at a given distance, look into vlax-curve-getPointAtDist Try this (defun c:sample ( / ent dist pointlist lnt) (setq ent (car (entsel))) (setq dist (getdist "\nEnter Distance: ") d dist) (while (setq pt (vlax-curve-getPointAtDist ent d)) (setq pointlist (cons pt pointlist)) (setq d (+ dist d)) ) (foreach itm pointlist (print itm) (princ))) You can invoke a break while in the loop or after the list is generated. Try it and tell me what you think Edit: modify code.. Anyway, with this aproach you dont need to create the temporay layer Got it? Edited April 1, 2012 by pBe Quote
Silvercloak Posted April 1, 2012 Author Posted April 1, 2012 I haven't gone through the entire code, but you may want to consider using a sub function for your break functionality that accepts two entities and a coordinate list (the break point), pseudo code: (defun _break (e1 e2 coord) ;; <-- Do something ) Other than that, it looks like you need to localize your varibles. Consider using some error handling to restore the original sysvars, and also consider placing the subfunctions you're using underneath the command function (localized) unless you're going to be using them as subs in other command functions too. Just a thought. HTH Totally lost me there... Quote
Silvercloak Posted April 1, 2012 Author Posted April 1, 2012 Alright silvercloak, instead of giving you fish, we'll teach you how to fish.I think the reason why you change the layers of the selected object is because you NEED to ISOLATE and select the "POINT" entities without disturbing the other similar enities But in my opinion you're approach is too much work. You dont need to create those [point enitites] to identify the break point at a given distance, look into vlax-curve-getPointAtDist Try this (defun c:sample ( / ent dist pointlist lnt) (setq ent (car (entsel))) (setq dist (getdist "\nEnter Distance: ") d dist) (while (setq pt (vlax-curve-getPointAtDist ent d)) (setq pointlist (cons pt pointlist)) (setq d (+ dist d)) ) (foreach itm pointlist (print itm) (princ))) You can invoke a break while in the loop or after the list is generated. Try it and tell me what you think Edit: modify code.. Anyway, with this aproach you dont need to create the temporay layer Got it? Thanks pBe!! I'll give it a look and see what I can do Thanks for teaching me how to fish Quote
BlackBox Posted April 2, 2012 Posted April 2, 2012 Totally lost me there... Perhaps we'll revisit the sub-function discussion(s) once you're 'fishing'... Until then, IMO the most important of my suggestions is for you to properly localize your variables. Familiarize yourself with the DEFUN function to better understand the anatomy of a LISP function, specifically the Symbol, the differences between Arguments, and Variables, and the Expression itself. (defun [b]sym [/b]([color=blue][b][arguments][/b][/color] [b][color=red][/ variables...][/color][/b]) [color=seagreen][b]expr[/b][/color]...) In short, by not localizing your variables, when your code has completed, the variables that you've defined retain their assigned value(s) To verify this, from the command line, simply type an exclamation point "!" then the variable name that you'd like to check, and if the variable has any value it will be displayed at the command line: Example: Command: (setq myVar "This is a test.") "This is a test." Command: [b][color=red]![/color][/b]myVar "This is a test." Command: (setq myVar nil) nil Command: [color=red][b]![/b][/color]myVar nil Non-localized variables can lead to unintended behavior in subsequent calls to the same function, or even other functions that utilize the same variable(s). It is considered a best practice to localize your variables. By 'nesting' your sub-functions within the main command code, you can properly localize your variables, and feed those variables to the sub-functions all without exposing them (the defined variables) to other functions. This is similar (not exactly the same) to how .NET uses Namespaces, where (generally speaking) only classes, and methods defined within a given namespace can interact. Hopefully *some* of this makes some sense to you... I am sure this will be useful to you once you begin to 'fish' for yourself. HTH Quote
alanjt Posted April 2, 2012 Posted April 2, 2012 This thread may be of interest: http://www.theswamp.org/index.php?topic=39550.msg448171#msg448171 *have to be a member* Quote
alanjt Posted April 2, 2012 Posted April 2, 2012 Now that's pretty neat, Alan - Good job! Thanks - change that beer to coffee. I've posted several curve breaking routines throughout that thread. Quote
BlackBox Posted April 2, 2012 Posted April 2, 2012 Thanks - change that beer to coffee. Nahh... that's just frothy cappuccino. LoL I've posted several curve breaking routines throughout that thread. I'll have to check them out. Quote
alanjt Posted April 2, 2012 Posted April 2, 2012 Nahh... that's just frothy cappuccino. LoL Good enough. 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.