Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Programming Challenge 24-2

29 REPLIES 29
SOLVED
Reply
Message 1 of 30
john.uhden
1220 Views, 29 Replies

Programming Challenge 24-2

Here ya go, you challenge hungry carnivores.

Attached is a drawing of a simple closed polyline (red) being intersected at two points by an open polyline (white).  Actually there are 4 different versions of the same thing, the differences being the polyline directions.

Your challenge is to write a function (or more) to split the closed polylines into two (2) pieces at the intersection points so that each end of the two resulting polylines have coincident end points.  No, not necessarily startpoint coincident with startpoint and endpoint coincident with endpoint, but probably more like (equal start1 end2 fuzz) and (equal end1 start2 fuzz), so that they could be easily joined.

Your function must require only the selection of the open polyline, nothing more.

Unless you've programmed this before, you will be quite surprised with your first attempts.

I suggest that you copy the originals over to the right any number of times for testing.

Please include your initials in the name of the function that you post.

John F. Uhden

29 REPLIES 29
Message 21 of 30
dbroad
in reply to: john.uhden

@john.uhden None hurt.  I'd forgotten that lwpolys used vertex numbers for parameters rather than distances like other objects.  Not that it matters, but this would be an alternate reliable approach if you wanted to end with open polylines. Neither would be reliable if the polygons to be trimmed weren't fully convex.

 

 

;;returns a list of values from an association list that have the key
(DEFUN cdrs  (key lst / pr)
  (IF
    (SETQ pr (ASSOC key lst))
     (CONS (CDR pr)
	   (cdrs key (CDR (MEMBER pr lst))))))
;;Main program: Divide a closed polyline into 2 parts with a fence polyline
(DEFUN c:splitp	 (/ ss f pts fo cpo ipts p2  cp cp2 len len1 pt1 pt2)
  (PROMPT
    "\n Select open fence polygon to trim intersecting closed polyline by.")
  (AND
    ;;Select only one lwpolyline that must not be closed.
    (SETQ ss (SSGET ":S+."
		    '((0 . "lwpolyline")
		      (-4 . "<NOT")
		      (-4 . "&")
		      (70 . 1)
		      (-4 . "NOT>"))))
    (SETQ f (SSNAME ss 0))					      ;fence polyline entity
    (SETQ pts (cdrs 10 (ENTGET f)))				      ;Use only verticies.
    ;;Select only lwpolylines that are closed and intersect the fence polyline
    ;;Weakness: The fence polyline may actually have bulges. May need to either exclude
    ;;fence polylines that are bulged or make the PTS list more refined at bulges.
    (SETQ ss (SSGET "F" pts '((0 . "lwpolyline") (-4 . "&") (70 . 1))))
    (SETQ cp (SSNAME ss 0))
    (NOT (COMMAND "_.undo" "_end" "_.undo" "_be"))
    (NOT (COMMAND "_.COPY" cp "" "_NON" "0,0" ""))
    (SETQ cp2 (ENTLAST))					      ;Closed polyline copy entity
    (SETQ fo (VLAX-ENAME->VLA-OBJECT f))			      ;fence object
    (SETQ cpo (VLAX-ENAME->VLA-OBJECT cp))			      ;closed polygon object
    (SETQ ipts (VLAX-INVOKE fo 'intersectwith cpo ACEXTENDNONE))      ;flat list of intersections
    (SETQ p2 (CDDDR ipts))
    ;;Second intersection
    (SETQ len1 (VLAX-CURVE-GETDISTATPOINT cp p2)
	  len  (VLA-GET-LENGTH cpo))
    (COND
      ((< 0 len1 len)
       (SETQ pt1 (VLAX-CURVE-GETPOINTATDIST cp (* len1 0.9)))
       (SETQ pt2 (VLAX-CURVE-GETPOINTATDIST cp (+ len1 (* 0.1(- len len1))))))
      ((= len1 0)
       (SETQ pt1 (VLAX-CURVE-GETPOINTATDIST cp (* 0.1 len)))
       (SETQ pt2 (VLAX-CURVE-GETPOINTATDIST cp2 (* 0.9 len)))))
    (NOT (COMMAND "_.TRIM" "O" "S" f "" (list cp pt1) ""))
    (NOT (COMMAND "_.TRIM" f ""  (list cp2 pt2) ""))
    (NOT (COMMAND "_.undo" "_e"))
    )
  (PRINC))

 

 

 

Architect, Registered NC, VA, SC, & GA.
Message 22 of 30
Kent1Cooper
in reply to: dbroad


@dbroad wrote:

.... lwpolys used vertex numbers for parameters rather than distances like other objects.  ....


It's distances for Lines, Rays and Xlines, but not for other objects.

 

For Splines, the end parameter is close to, but not quite the same as, the length when first drawn:

Kent1Cooper_0-1710526795418.png

[I think the difference is greater when the shape is more convoluted.]  But it can get really wacky if you make certain changes.  For example, that same one, with its starting part Trimmed off, making it much shorter, retains the same end parameter value, which is now very different from the length:

Kent1Cooper_1-1710527008469.png

But if I Trim off the downstream end instead, it does change the end parameter to something similar to the length:

Kent1Cooper_2-1710527110338.png

Similarly, grip-editing in some ways can change the shape and length without changing the end parameter value.

 

For Circles and Arcs and Ellipses, it's angle-based, with a quadrant point being parameter 0.  For a Circle or closed Ellipse, the parameter values always start at 0 and end at 2pi, no matter what the distance along the curve.  But if an Arc or partial Ellipse crosses the 0° direction [the easterly quadrant point for an Arc, some quadrant point for an Ellipse depending on how it was drawn], the start parameter is something under 2pi of course, but since the parameter values must increase continually along the length, the end parameter ends up being greater than 2pi,  But again, it's about the angle from the center, not about the distance along the curve.

 

Further complicating that, in an Ellipse, it's angle-based, but it's about the angles along the virtual Circle that the Ellipse is a projection of, not about the "raw" angle from the center of the Ellipse.  Here:

Kent1Cooper_3-1710528329901.png

the yellow Points are at the quadrants, the green ones are at 12ths of the overall length along the curve [done with DIVIDE], but the red ones are at equal parameter spacings [1/12 of 2pi].  So while a given difference in parameter value along an Arc or Circle always represents the same difference in length along it, that's not true for an Ellipse, where the distance difference represented by a given parameter difference varies depending on where along it those parameters fall.

Kent Cooper, AIA
Message 23 of 30
john.uhden
in reply to: Kent1Cooper

@Kent1Cooper , @dbroad , @komondormrex , @CodeDing , et al,

After weeks of battling with closed polylines, and the TRIM and BOUNDARY commands and copies,

I finally solved the problem...

The specs said to break the objects, but it didn't say to break them once at each intersection.

So rather than avoid the BREAK command, I used it to break entities 0.01 units before and 0.01 units after the point of intersection.  You would have to zoom in really tight to see the resulting gaps.  Plus it's not for use in building a nuclear power plant or a Hadron collider.  AND the fence line can have bulged (arced) segments, and it can break ellipses.

But forget hatches.  With patterns like AR-SAND AND AR-CONC and interior islands it's just not worth my effort (well unless they scream for it).

 

johnuhden_0-1712272257213.png

 

John F. Uhden

Message 24 of 30
john.uhden
in reply to: john.uhden

Of course I hadn't covered the condition where an intersection point falls at or near the start=end of a closed polyline.

So now I am struggling all over again.  But I have sufficient confidence in myself to overcome the problem.

Though a little wish of luck might help. 😊

John F. Uhden

Message 25 of 30
john.uhden
in reply to: john.uhden

Ahah!

It appears that if the first point of intersection with a closed polyline happens to be its start/end point, then the polyline must advance in a CCW direction, otherwise the gap break is not the short distance but the long way around.

But I have a CCW function that I can use to test and then reverse if found to be CW.

John F. Uhden

Message 26 of 30
john.uhden
in reply to: john.uhden

To Hello with all that.

Well, I finally solved my problem...

  • I added points to the fence polyline through arced (bulged) segments.
    (not changing the polyline, but by adding points to its coordinate list)
  • It's not perfect (it can't be) but very close for including objects in a selection set.
  • I have to add a test whether there's enough left of a trimmed object to bother trimming.
    (This is only for cutting up objects that occupy both sides of a demolition boundary, and the backhoe's teeth are not like razors.)
  • I went back to the TRIM command using tiny circles as the trim lines and selecting each trim point at its center.
  • Had to temporarily entdel the fence polyline so the trim didn't pick on that.
  • Also had to temporarily zoom in to each intersection point for the trim command to obey the point of trimming.
    (Remember that AutoCAD finds intersections and stuff visually, not mathematically, and its eyesight is only so good.)
  • Had to convert splines to plines to circumvent odd failures (not sure if we ever use them anyway).
  • HIP HIP HOORAY!!

John F. Uhden

Message 27 of 30
john.uhden
in reply to: dbroad

@dbroad 

Hey, Doug. Thanks for the LIKE.
Some may think it's annoying zooming center 57 times for 16 objects, but I kinda like it because it let's me see that it's doing its job even though it's adding time to the processing. But as I said, you have to be zoomed in for AutoCAD to "see" inside the circle to the trim point even though it's always in the dead center of the circle. Of course trying to do it all manually would be torture. I'd let you try it out but it's company software (it's hard to believe but I'm actually getting paid for it, while working from home nonetheless, i.e. no hour long commute!).

John F. Uhden

Message 28 of 30
dbroad
in reply to: john.uhden

Might be nice if you were to post a before and after drawing. Still fuzzy about what you were trying to do.

Architect, Registered NC, VA, SC, & GA.
Message 29 of 30
john.uhden
in reply to: dbroad

@dbroad ,

Yes, Katinka wants me to be nice, so here ya go (attached).

Maybe I never did state the purpose:

One of my coworkers (very talented) requested a utility to break objects that straddle a fence boundary.  The boundary represents the limit of demolition, and the objects inside the boundary will be assigned to various *-DEMO layers that he can control separately.  I already had a DEMO.LSP that changes selected objects to layers that start out identical to their previous layer except the suffix "-DEMO" is added to the names.   He hates "heavy" drawings, so he doesn't like the alternative of loading two of the same xref with each being either trimmed along the boundary or the two being separated by a layer of WIPEOUTs.

Ya know, I started with the concept of using the BREAK command and having no gap between the inside and outside, but you can't break circles at one point and splines don't behave consistently either.  So it evolved through 6 previous builds before employing the idea of using tiny circles to trim each object leaving a miniscule gap between inside and outside that won't be noticed at normal zoom levels.

Not having psychic capabilities, this assignment became one of the most difficult ever.

John F. Uhden

Message 30 of 30
dbroad
in reply to: john.uhden

Thanks for the explanation and the before/after dwg.

Architect, Registered NC, VA, SC, & GA.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost