Jump to content

Calculate x,y/x,y,z for a 2d/3d curve


Recommended Posts

Posted

For a 2d / 3d curve, how to calculate 10,000 values
  (for example) x, y / x, y, z at a given step x, in autolisp.

Posted

Use the vlax-curve-getpointatdist or vlax-curve-getpointatparam function, supplied with your entity name and a given distance or parameter value.

Posted

Better to go to the mathematical formula, so provide that.

 

Your request is to vauge and 10,000 points big number. Explain more.

Posted

I have a 3d curve in autocad from x = 108 to x = 12064. I would like to calculate y, z for x = 108, 110, 112, 114,........12064, with dx = 2.

Posted

You still need to explain more for any one here to help, at least an image of the curve.

Posted

Also, what do you want to do with the calculated values?

Posted

If the curve is an AutoCAD spline then it's a NURBS (non-uniform rational B-spline).  If you have not changed the weighing factors of the spline's CVs (they all equal 1) then it can be represented as a B-spline.

The attached Excel/VBA macro-enable file includes a B-spline function that I programmed to help me get a better understanding of splines.  It will duplicate the curve AutoCAD creates given the same set of CVs.  You could use its BSpline  function to generate as many points along the spline as you wish. To get 10000 points use an increment of ((number_of_CVs) - degree)/ 10000  for u.

The function has three arguments: BSpline(u, degree, CVs)

u = the independent parametric variable of the spline

degree is of course the degree of the spline.  The default value in AutoCAD is 3

CVs is an array of the coordinates of the control vertices (x, or y, or z)

 

How many CVs are in your curve?

 

Lee

 

B-Spline-Calculator-degn.xlsm

  • Like 1
Posted

Sounds like a curve drawn on a tilted plane and wants the 3d answers on world co-ords. Which is not a true arc but like lrm a spline.

 

Have a look at "The Opera House Sydney" 

Posted

The steps dx=2 in 3D or 2D? 

 

19 hours ago, roy437 said:

I have a 3d curve in autocad from x = 108 to x = 12064. I would like to calculate y, z for x = 108, 110, 112, 114,........12064, with dx = 2.

 

Posted
On 12/10/2019 at 8:45 PM, Lee Mac said:

Use the vlax-curve-getpointatdist or vlax-curve-getpointatparam function, supplied with your entity name and a given distance or parameter value.

Thanks Lee

Here's my code, where I used the bisection method. I am waiting for a point of view from you.

 

(defun c:fx( / a b c curve-obj delim dx ent eps fil lc name_file nd p pe ps x x0 xe xs )
;
;  Input data
;---------------------------------------------------
  (setq
              nd 6        ; number of digits decimal
             eps 0.000001
           delim " " ; space, tab or comma
              dx (getreal "\nIncrement dx : ")
       name_file (getstring "\nOut file : ")
             ent (car (entsel)) ; select curve
  )
;---------------------------------------------------
  (setq
              fil (open (strcat (getvar "DWGPREFIX") name_file) "w")
        curve-Obj (vlax-ename->vla-object ent)
               ps (vlax-curve-getStartPoint curve-Obj)
               pe (vlax-curve-getEndPoint   curve-Obj)
               lc (vlax-curve-getdistatparam curve-Obj (vlax-curve-getendparam curve-Obj))
                a 0.0
                b lc
               xs (car ps)
               xe (car pe)
               x0 (+ xs dx)
                x xe
  )
  (write-line (strcat (rtos xs 2 nd) delim (rtos (cadr ps) 2 nd) delim (rtos (caddr ps) 2 nd)) fil)
  (while (< x0 xe)
;              Bisection method
;-----------------------------------------------------
    (while (> (abs (- x x0)) eps)
      (setq
            c (* 0.5 (+ a b))
            p (vlax-curve-getPointAtDist curve-Obj c)
            x (car p)
      )
      (if (> x x0) (setq b c) (setq a c))
    )
;-----------------------------------------------------
    (write-line (strcat (rtos x0 2 nd) delim (rtos (cadr p) 2 nd) delim (rtos (caddr p) 2 nd)) fil)
    (setq
          x0 (+ x0 dx)
           a (vlax-curve-getDistAtPoint curve-Obj p)
           b lc
    )
  )
  (write-line (strcat (rtos xe 2 nd) delim (rtos (cadr pe) 2 nd) delim (rtos (caddr pe) 2 nd)) fil)
  (close fil)
  (princ)
)

 

Posted

Forget code show us a picture with out that we have no idea what it is your trying to do. 

Posted

I now see what you want to do.  In short you a searching for the spline's parametric value that corresponds to a specific value of x. 

 

Your program appears to work well assuming that the spline is a monotonic function in x. If there are multiple points on the spline for a value of x you will only get one of them.  If the spline swings out before the beginning of the spline or beyond it the points on these sections will not be determined (of course this cannot happen for monotonic functions).

 

I suggest you add a counter in the while loop of the bisection code to limit the number of iterations to converge to a solution to avoid the potential of the program hanging.  I would also suggest adding a message at the end stating that the program is  finished and state the complete path and filename of the  output file.

 

Nice code.

 

lrm (a.k.a. Lee M. but not Lee Mac!) 

Posted (edited)

I agree with lrm for what he stated, but then again, I don't know what method to suggest you that is fast enough and that covers those issues lrm mentioned... Maybe one that is not so slow but the code should be bigger :

1. You flatten your 3D curve

2. You construct XLINE with point at relative X coordinate 0.0 and with direction (0.0 1.0 0.0) - X coordinate must be smallest one - so suggested method of finding this point is by using (vlax-curve-getclosestpointtoprojection curve '(-1e+99 -1e+99 0.0) '(0.0 1.0 0.0))

3. You find intersection point of XLINE and flattened curve (there may be more than 1)

4. You construct XLINE from intersection point(s) you found in step 3. with direction (0.0 0.0 1.0)

5. You find intersection point(s) of XLINE from step 4. and your curve in 3D

6. You remove both helper XLINES and repeat from step 2. with point at relative X coordinate incremented for dx

You loop 2-6 all until no intersection points found in step 3.

 

Some notes I spot in your posted code (defun c:fx( / ... ) ... ) should actually be (defun c:fx ( / ... ) ... ) - note space char after fx and (

To improve speed of computation, you don't need to use curve-Obj as 'VLA-OBJECT - (vlax-curve-xxx) functions operate as well and faster also with 'ENAME type variables - so no need line (setq curveObj (vlax-ename->vla-object ent)) - just change it to (setq curveObj ent)...

 

How will you flatten 3D curve and to remain its accuracy with real curve is up to you, but you can try command PROJECTGEOMETRY and choose XY plane for projection... At least you'll know you tried it...

 

M.R.

Edited by marko_ribar
Posted

If you are concerned about the speed of execution one thing you could easily change is to remove the write statements and instead store the results in an array and then do one write to a file at the end of the program.  The jumping between lisp execution and file writing is time consuming. It's better to limit how often that is done.

 

It would be interesting to see the average of how many iterations are needed to converge to a solution in the bisection loop for each value of x. 

 

Usually a Newton Raphson numerical algorithm will converge faster than the simple bisection method but I don't see how to use it efficiently in this case. 

Posted

As related to Marko’s ‘flatten’ suggestion, the 3d Curve could be linearized.  Copy the 3d Curve.  Step through every control point and remove the Y and Z components.  The resultant spline (probably even 3d Poly) will be a straight curve aligned to the X axis.  More importantly, it will have the same parametric span as the original.

On that straight curve use vlax-curve-getParamAtDist for a desired X location.  Take that parametric value and evaluate the 3d curve via vlax-curve-getPointAtParam to retrieve the Y and Z components.

Posted

Here is an example of the 3d to 1d curve - upon which my theory can be tested with the VLAX functions.

EqualParam.dwg

  • Thanks 1
Posted

I think that SEANT approach may be bingo for monotonic 3d curves, but still I'd rather suggest you using flattening to 2d - this way you are loosing only 1 dimension (remove all z components)... Because of loosing 2 dimensions like SEANT suggested, his method may fail with curves like HELIX or similar...

Thanks for attention...

M.R.

Posted (edited)

My $0.05 not sure about how fast but a pretty simple method and as we want in terms of x axis is if you draw a vertical line crossing the 3dpline you can trim it and get the xyz of endpoint.

 

Using Seant equalparam.dwg need to get last 3 values of controlpoints. I just did plan and moved green line I have not done the x y translation so line end is 0,0.

 

Testing now tried to upload GIF not working. tested on 2000 steps still fast.

(defun getend (lstxyz  / )
(setq x (- (length lstxyz) 1 ))
(setq z (nth x lstxyz))
(setq y (nth (- x 1) lstxyz))
(setq x (nth (- x 2) lstxyz))
(setq xy (list x y))
(setq lst2 (cons (list x y z) lst2))
)
(defun c:test ( )
(setq oldsnap (getvar 'osmode))
(setq lst2 '())
(setvar 'orthomode 1)
(setq p3 (getpoint "\nPick start of X line"))
(setq p1 (getpoint "\npick point 1 end X line "))
(setq xl1 (car p1))
(setq y1 (cadr p1))
(setq p2 (getpoint p1 "\npick point 2 "))
(setq y2 (cadr p2))
(setvar 'osmode 0)
(setq len (distance p1 p3))
(setq diff (/ len 20.0))
(setq obj (vlax-ename->vla-object (car (entsel "\npick object "))))
(repeat (- (fix (/ len diff)) 1)
(setq lst (vlax-get Obj 'controlpoints))
(getend lst)
(setq xl1 (- xl1 diff))
(setq p1 (list xl1 y1))
(setq p2 (list xl1 y2))
(command "line" p1 p2 "")
(command "trim" (entlast) "" xy "")
(command "erase" (entlast) "")
)
(setq lst2 (cons (list (nth 0 lst)(nth 1 lst)(nth 2 lst)x y z) lst2))
(setvar 'osmode oldsnap)
(princ lst2)
(princ)
)
(c:test)

Edited by BIGAL

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...