Really need a LISP or VBA to create 3D Spline (cable)

Really need a LISP or VBA to create 3D Spline (cable)

CrazyIvan
Advocate Advocate
1,147 Views
16 Replies
Message 1 of 17

Really need a LISP or VBA to create 3D Spline (cable)

CrazyIvan
Advocate
Advocate

I work with utilities and I provide drawings in 3D using AutoCAD.  I am looking for some help creating either a LISP or VBA that can generate 3D Splines which represent jumpers/cables connecting equipment.  These termination points have different points in X, Y and Z planes, so it is really tedious to create these manually every time I connect equipment together using jumpers.

 

In the image below, the way I am thinking this would work is to Select each of the identified number points in order, 1-4, then give it a bend radius.  The bend using the minimum bend radius along the path between 1/2 and 4/3 at least 6" away from points 2 and 3 before bending starts.  The minimum bend radius would be 30", but would like the option to change it if necessary for larger cable sizes.

 

I've also attached a dwg of the example I am working with.

 

If anyone could provide this, you would be my savior.  So, thanks!

 

JumperLISPNeeded.jpg

0 Likes
Accepted solutions (1)
1,148 Views
16 Replies
Replies (16)
Message 2 of 17

CrazyIvan
Advocate
Advocate

P.S. What you are looking at, if you aren't familiar, is aluminum cable connecting equipment, as what is shown in the image below._3D Jumper.jpg

0 Likes
Message 3 of 17

leeminardi
Mentor
Mentor

[EDIT 9/19/2023 the code has been modified to include the straight 6" section at both ends forming one spline for the jumper that can be referenced by the sweep sommand to create a solid 3D tube.]

 

Thefollowing code will create a smooth spline from the points 6" beyond point 2 and point 3. 

The requirement to ensure a minimum 30" radius is tough to meet.  The parameter "a" in the code can be adjusted to influence the curvature of the spline.  It must be noted that the 4 input points do not lie on a plane. As part of the solution I wanted to find the midpoint of the line at the shortest distance between two lines defined by the 4 points.  I could not get the vlisp function "inters" to provide the point so the program calculates the pseudo intersection point (pIntr) numerically by projecting a point from one infinite line defined by points 1 and 2 to the other line defined by points 3 and 4 then back and forth between the two lines.  I found that 10 iterations provided an acceptable solution.  More testing is advised.

leeminardi_0-1694962163551.png

I was going to have one continuous spline from point 2 to point 3 but the transition from the 6" straight sections to a tangent curvature would require multiple CVs at the same point.  The sweep command will not work with coincident CVs.  Adding these straight section to the code is straightforward.  E.g., a cylinder from p2 to s1, and s5 to p3.  Or

 

 

(command "_cylinder" p2 radius "a" s1)

 

 

leeminardi_1-1694962496385.png

 

 

 

 

(defun c:jumper (/ p1 p2 p3 p4 pa pb dot1 dot2 u12 u43 pIntr s1 s2 s3 s4 s5 da db e1 e2 e3)
; create a spline from 4 user specified points such that the spline start 6 units
; from point 2 and point 3.
; Lee Minardi  9/17/2023
; modified 9/19/2023 to create spline with 6" straight ends at each end/  
 
  (setq	p1 (getpoint "\nPick point #1: ")
	p2 (getpoint "\nPick point #2: ")
	p3 (getpoint "\nPick point #3: ")
	p4 (getpoint "\nPick point #4: ")
  )
(setq pa  p2
      pb  p3
      u12 (unitvector p1 p2)
      u43 (unitvector p4 p3)
)
(repeat	10  ; find the midpoint of the shorest distance between two non-intersecting 3D lines.
  (setq	dot1 (dot
	       (mapcar '- pa pb)
	       u43
	     )
  )
  (setq	dot2 (dot
	       (mapcar '- pb pa)
	       u12
	     )
  )
  (setq	pb (mapcar '+
		   pb
		   (mapcar '*
			   (list dot1 dot1 dot1)
			   u43
		   )
	   )
	pa
	   (mapcar '+
		   pa
		   (mapcar '*
			   (list dot2 dot2 dot2)
			   u12
		   )
	   )
  )
)					; repeat
; pa and pb are points on the two 3D lines where they are closest
; pIntr is the midpoint of the line from pa to pb  
(setq pIntr (mapcar '/ (mapcar '+ pa pb) '(2. 2. 2.))) ; "intersetion" point
(setq a	 0.3  ; allows tuning of the spline's amount of curvature
      s1 (mapcar '+ p2 (mapcar '* u12 '(6 6 6)))
      da (* a (distance s1 pa))
      s2 (mapcar '+ s1 (mapcar '* u12 (list da da da)))
      s5 (mapcar '+ p3 (mapcar '* u43 '(6 6 6)))
      db (* a (distance s5 pb))
      s4 (mapcar '+ s5 (mapcar '* u43 (list db db db)))
)
(initcommandversion)  ; enable "normal" spline syntax
(command "_spline"	 "m"	 "cv"	 "_non"	 s1	 "_non"
	 s2	 "_non"	 pIntr	 "_non"	 s4	 "_non"	 s5
	 ""
	)
(setq e1 (entlast))
(command "_line" s5 p3 "")
(setq e2 (entlast))
(command "_line" p2 s1 "")
(setq e3 (entlast))
(command "_join" e1 e2 e3 "") 
  
  (princ)
)
;;; Compute the dot product of 2 vectors a and b
(defun dot (a b / dd)
  (setq dd (mapcar '* a b))
  (setq dd (+ (nth 0 dd) (nth 1 dd) (nth 2 dd)))
)					;end of dot
(defun unitvector (pt1 pt2 / p d uv)
  (setq	p  (mapcar '- pt2 pt1)
	d  (distance pt1 pt2)
	uv (mapcar '/ p (list d d d))
  )
)

 

 

 

lee.minardi
Message 4 of 17

Kent1Cooper
Consultant
Consultant

@leeminardi wrote:

.... I was going to have one continuous spline from point 2 to point 3 but the transition from the 6" straight sections to a tangent curvature would require multiple CVs at the same point.  ....


You should be able to do that by drawing the 6" straight end sections as Lines [or, for that matter, 2-point-only Splines], and the Spline between their near ends in whatever way works, and then JOINing them together.  JOIN will take care of that multiple-at-one-point part to leave the new end segments straight.

EDIT:  Maybe like this [minimally tested]:

 

(defun C:JUMPER (/ osm p1 p2 p3 p4 endA endB)
  (setq
    osm (getvar 'osmode)
    p1 (getpoint "\nInternal end of jumper connector at one end: ")
    p2 (getpoint "\nExternal end of that jumper connector: ")
    p3 (getpoint "\nExternal end of jumper connector at other end: ")
    p4 (getpoint "\nInternal end of that jumper connector: ")
  ); setq
  (setvar 'osmode 0)
  (command "_.line" p1 p2 "")
  (setq endA (entlast))
  (command "_.line" p4 p3 "")
  (setq endB (entlast))
  (command "_.lengthen" "_delta" 6 p2 p3 "")
  (setq ; new closer ends [afer 6-unit straight extension]
    p2 (vlax-curve-getEndPoint endA)
    p3 (vlax-curve-getEndPoint endB)
  ); setq
  (command
    "_.spline" p2 p3 "" p1 p4
    "_.join" (entlast) endA endB ""
  ); command
  (setvar 'osmode osm)
  (prin1)
)

 

As for the radius limitation, there is no such thing as "the radius" for a Spline, since it has constantly-varying radius, if that even means anything -- a "radius" implies a center point from which it is measured, but there's no such thing for an irregular Spline.  The above, using no additional fit points between the inboard ends of the straight pieces, sort of does the "broadest" curvature available for the configuration of the points you're starting with.  If it can be determined that it's "too tight" in the middle, then "loosening" the "radius" there [however that would be done] would require "tightening" the "radius" in the areas where it comes off the straight end parts, and vice versa, so might you be trading too-tightness in one area for the same in another?  I imagine there are physical relationships possible in which that minimum is not achievable.

 

Further EDIT:  The above was at first using (initcommandversion) as >here< to make the SPLINE command operate the way it does at the Command line with the tangency options.  But I recalled the way tangencies could be done way back, under the old native core underlying operation of the command, and in this case that was easier.  Tangencies can be specified for both start and end at the end of the command, and both are in the away-from-the-end direction.  Try starting SPLINE in an AutoLisp (command) function, with just (command "_.spline"), give it some points [two are enough] and Enter to get the offered  <start tangent> default, and it asks for tangency directions, where you'll see how it works -- that simplified the code above, for not needing to calculate a point to define the start tangency, because the appropriate point already existed.  That other topic would need to change the points to use that approach, with [in their image] their 4 being below 1.

Kent Cooper, AIA
0 Likes
Message 5 of 17

leeminardi
Mentor
Mentor

@Kent1Cooper 

 

Thank you for your comments.

 

1. Regarding using one continuous spline that starts at point 2 and ends at point 3, I tried that in an earlier version of the program. It created that spline but with 3 coincident CVs at the transition point between the straight and curve portion of the spline.  I found that the sweep command could not handle it. As you now point out, joining a straight line with a spline will yield a continuous spline that is copasetic with sweep!  Who knew? Thanks. I'll leave it to the OP to make the change.

 

2. You wrote " As for the radius limitation, there is no such thing as "the radius" for a Spline, since it has constantly-varying radius ..."  . In fact, splines do have an instantaneous radius of curvature.  I wrote the program below to calculate and graphically show the radius of curvature at points along a spline. The length of the green lines in the image below indicate the radius of curvature. The shortest green line is about 70" long, greater than the minimum required radius of 30".

leeminardi_0-1694985034320.png

 

(defun C:DOCL (/ path inc n osm	par der1 der2 curva p perp normv p2 sf
	       curveType ans)
; = Degree Of Curvature - Lines
; Creates curvature lines or radius-of-curvature lines
; normal to a spline.
; LRM 8/18/2022 edited to place curvature vectors outside  
  (setq
    path (car (entsel))
    inc	 (/ (vlax-curve-getEndParam path) 100)
    n	 0
    osm	 (getvar 'osmode)
  )
  (setvar 'osmode 0)
  (setvar "cmdecho" 0)
  (initget "y n")
  (setq ans (getkword  "Do you want radius-of-curvature instead of curvature? [y/n] <n>: "))
	(if (= ans "y")
	   (setq curveType 1)
	   (setq curveType 2
		 sf	   (getdist "Enter scale factor.")
	   )
	)
  (repeat 100
    (setq par (* inc n))
    (setq der1 (vlax-curve-getfirstDeriv path par)
	  der2 (vlax-curve-getSecondDeriv path par)
    )
    ; calculate curvature at point par
    (setq d (distance '(0 0 0) (cross der1 der2)))
    (if	(> (abs d) 1.0e-15)
      (progn
	(setq curva (/ (expt (distance '(0 0 0) der1) 3) d))
	(if (= curveType 2)
	    (setq curva (* -1. (* sf (/ 1. curva))))
	  )
	(princ "\n") (princ n)
	(princ "   curvature = ") (princ curva)
	(setq p	    (vlax-curve-getPointAtParam path par)
	      perp  (unitv (cross der1 (cross der2 der1)))
	      normv (mapcar '* perp (list curva curva curva))
	      p2    (mapcar '+ p normv)
	)
	(command "_.line" p p2 "")
      )					; end progn
    )
    (setq n (1+ n))
  )
  (setvar 'osmode osm)
  (setvar "cmdecho" 1)
  (princ)
)


  ;;; Compute the cross product of 2 vectors a and b
(defun cross (a b / crs)
  (setq	crs (list
	      (- (* (nth 1 a) (nth 2 b))
		 (* (nth 1 b) (nth 2 a))
	      )
	      (- (* (nth 0 b) (nth 2 a))
		 (* (nth 0 a) (nth 2 b))
	      )
	      (- (* (nth 0 a) (nth 1 b))
		 (* (nth 0 b) (nth 1 a))
	      )
	    )				;end list
  )					;end setq c
)					;end cross
  (defun unitV ( v / d)
  (setq d (distance '(0 0 0) v)
	d (mapcar '/ v (list d d d))))

 

3.  As for defining the tangent for the end of a spline my preference is to use CVs rather than tangent option and fit points.  I think the position of CVs provide a more intuitive method for setting the radius of curvature at the start and end of the spline.  

 

As noted in my thread regarding spline command syntax in vlisp thank you for the (initcommandverison) tip.

lee.minardi
0 Likes
Message 6 of 17

diagodose2009
Collaborator
Collaborator

Clipboard01.jpgYou can simulate spline with sjn & cos.

You execute with C:Dan[enter]

Please you check freshui.zip

 

0 Likes
Message 7 of 17

leeminardi
Mentor
Mentor

The correlation of your comment to the topic of the thread is not clear.  The thread concerns spline creation not springs.  Can you clarify the significance of your post to the discussion?

lee.minardi
0 Likes
Message 8 of 17

CrazyIvan
Advocate
Advocate

Thanks for all the great replies. I will check this out and see if they work!

0 Likes
Message 9 of 17

CrazyIvan
Advocate
Advocate
This is great! I did have a question though. How did you get it to apply a tube to the spline? I see the "_cylinder" but I did not see that in the code or in the command when running it.

Thanks!
0 Likes
Message 10 of 17

leeminardi
Mentor
Mentor

I used the sweep command referencing a circle after running the program that created the spline. It could be included in the program but you would need to supply  the tube diameter. 

lee.minardi
0 Likes
Message 11 of 17

CrazyIvan
Advocate
Advocate

I think Ø7/8"  would be fine to at least show some thickness.

0 Likes
Message 12 of 17

leeminardi
Mentor
Mentor

@CrazyIvan   I've modified the code in my post #3 to include the 6" straight sections.  The resulting spline can be referenced with the sweep command. You can adjust the shape of how the spline curves by tweaking the value of "a" in the line of code 

(setq a	 0.3 ...

Try different values to see what you like.  I also recommend trying @Kent1Cooper's program.  It produces a slightly different curve.

Good luck!

 

lee.minardi
Message 13 of 17

CrazyIvan
Advocate
Advocate

Hey, would you be able to repost that original version you had?  I accidentally overwrote it on my end and was trying to see the difference between that and the updated one.  And I think that original one was actually better for what I am trying to do.  Thanks!

 

Thanks!

0 Likes
Message 14 of 17

leeminardi
Mentor
Mentor

I am traveling and do not have access to the original file. The primary difference is lines 61 through 66. You can delete these. They create one continuous spline  from P2 to P3

lee.minardi
Message 15 of 17

CrazyIvan
Advocate
Advocate

Thanks!  I appreciate your taking the time to respond while on the road; it's not necessary. If you get a chance once you are settled at your destination, maybe you could take a look.

 

That did something strange. The spline wraps around the back and comes back forward.  Not sure.

 

ODD.jpg

 

 

0 Likes
Message 16 of 17

leeminardi
Mentor
Mentor
Accepted solution

The code in post #3 that was modified on 9/19 will create one continuous spline from p2 to p3.  This spline includes the 6" straight sections.

If you delete lines 61 through 66 and reload the code it will create one spline from the points 6" out from points 2 and 3.  I tested the result and in both cases an appropriate spline was created that is compatible with the sweep function.

leeminardi_0-1695507554363.png

 

lee.minardi
Message 17 of 17

CrazyIvan
Advocate
Advocate

Thanks!  Originally, it drew a smooth spline from p1 to p4.  That is what I was looking for.

0 Likes