Programming Challenge 6/22

Programming Challenge 6/22

john.uhden
Mentor Mentor
2,088 Views
47 Replies
Message 1 of 48

Programming Challenge 6/22

john.uhden
Mentor
Mentor

This one has my head spinning.

The challenge is to write a function that returns the point on an ellipse where the tangent direction is equal to the one entered.

The function shall take two (2) arguments:

1.  the ename of the ellipse

2.  the desired tangent angle in radians

No, you will not make your own ellipse, nor have your function select one, nor add any code to confirm that the entity is in fact an ellipse.  If you can't use what I give you below, then tell your boss (if you have one) and tell your family (if you have one) and tell your friend (if you have one) that you are taking a one-way trip to the Ukraine (or Chatsworth, NJ if you prefer).

I am ignorant of any direct way to find the point, so to me it will require iteration to converge on the solution.

You may use a fuzz of 1e-8, nothing larger.  @calderg1000 is the only one entitled to use a fuzz of zero.

This exercise is only for determining the point in space where Tommy Lee Jones must exit the space station to land on the moon.  It's not for like building a geometrically perfect playground or something.

The ellipse is defined as:

(setq ellipse
(entmakex
'((0 . "ELLIPSE")(100 . "AcDbEntity")(67 . 0)(410 . "Model")
(8 . "0")(100 . "AcDbEllipse")(10 36.0 5.0 0.0)(11 -2.0 1.5 0.0)
(210 0.0 0.0 1.0)(40 . 0.5)(41 . 0.0)(42 . 5.0))
)
)

The angle in radians = 5.8

I have no idea as yet what the solution is, nor may I ever find out except by trial and error, or if @LeeMinardi shows me with his vector voodoo.

John F. Uhden

0 Likes
2,089 Views
47 Replies
Replies (47)
Message 41 of 48

john.uhden
Mentor
Mentor
Accepted solution

@_gile , et al

Well, I think I may have solved using my convergence approach on a mirrored ellipse (210 0.0 0.0 -1.0)...

(defun @tanpt (ellipse tang / obj ctr Normal factor p ang param)
  ;; where ellipse = ellipse ename
  ;;       tang = desired tangent angle in radians
  (setq ctr (vlax-get (setq obj (vlax-ename->vla-object ellipse)) 'center)
        Normal (vlax-get obj 'Normal)
        factor (if (minusp (last Normal)) -1.0 1.0)
        p (polar ctr (- tang (* pi 0.5)) 1000) ;; gotta start somewhere
        p (vlax-curve-getclosestpointto ellipse p)   ;; ""
        param (vlax-curve-getparamatpoint ellipse p)
  )
  (while (not (equal tang (setq ang (angle '(0 0 0)(vlax-curve-getfirstderiv ellipse param))) 1e-8))
    (setq param (+ param (* factor (- tang ang))))
    (print param)(prin1 ang)
  )
  (print ang)
  (setq p (vlax-curve-getpointatparam ellipse param))
  (setvar "pdmode" 34)
  (entmakex (list '(0 . "POINT")(cons 10 p)'(62 . 1)))
  p
)

A factor of 1.0 seems to be good enough too, which speeds it up a lot.

What's odd is that it doesn't fail on an open ellipse, which may be "wrong" yet interesting to observe and note.

Go ahead, try it with an angle of 3.2 radians.

John F. Uhden

0 Likes
Message 42 of 48

_gile
Consultant
Consultant
Accepted solution

This one, starting with the same method as @doaiena, seems to work whatever the Ellipse normal (assuming the angle is specified according to the ellipse plane).

 

EDIT: Added the an argument (onCurve) to specify if points which do not lie on an elliptacal arc have to be returned or not.

 

 

;; getPointAtTangent
;; Gets the tangent point on the ellipse for the supplied angle
;;
;; Arguments
;; ellipse : the ellipse ename.
;; tanAng  : the angle in radians of the tangent direction (about ellipse OCS).
;; onCurve : if specified as nil, the ellipse is considered as closed;
;;           if non nil the point must lie on the elliptical arc.
;;
;; Returns the point on the ellipse (WCS coordinates) or nil if onCurve argument is non nil
;; and the point does not not lie on the elliptical arc.
(defun getPointAtTangent (ellipse tanAng onCurve / tan majRad minRad center normal baseAng point)
  (defun tan (x) (/ (sin x) (cos x)))
  (setq	majRad	(getpropertyvalue ellipse "MajorRadius")
	minRad	(getpropertyvalue ellipse "MinorRadius")
	center	(getpropertyvalue ellipse "Center")
	normal  (getpropertyvalue ellipse "Normal")
	baseAng	(angle '(0. 0. 0.) (trans (getpropertyvalue ellipse "MajorAxis") 0 normal))
	tanAng	(- tanAng baseAng)
	point	(list
		  (/ (* majRad majRad (tan tanAng) -1.)
		     (sqrt (+ (* majRad majRad (tan tanAng) (tan tanAng)) (* minRad minRad)))
		  )
		  (* (/	(* minRad minRad)
			(sqrt (+ (* majRad majRad (tan tanAng) (tan tanAng)) (* minRad minRad)))
		     )
		  )
		  0.
		)
  )
  (if (< 0. (cos tanAng))
    (setq point (mapcar '- point))
  )
  (setq point
	 (mapcar '+
	  (trans
	    (mapcar
	      '(lambda (r) (apply '+ (mapcar '* r point)))
	      (list (list (cos baseAng) (- (sin baseAng)) 0.)
		    (list (sin baseAng) (cos baseAng) 0.)
		    '(0. 0. 1.)
	      )
	    )
	    normal
	    0
	  )
	  center
  )
	)
  (if (or (not onCurve) (vlax-curve-getParamAtPoint ellipse point))
    point
  )
)

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 43 of 48

_gile
Consultant
Consultant

@john.uhden

A dichotomic search is also a method by successive approximations. In this example, we start by testing in the middle of the ellipse (EndParam / 2) if it is not the expected result, we search in the first half if it is too big (EndParam / 4) or in the second half if it is too small (3 * EndParam / 4) and so on until an acceptable result.

 

The upper method directy computes the result.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 44 of 48

john.uhden
Mentor
Mentor

@_gile 

I am distressed that I can't run your function (without changing it) because I have only 2002 running at home, thus no getpropertyvalue.

But it looks perfect, and if you say it works, then it works.

And no convergence required.  That's very clever.

What did you think about my function that somehow runs with parameters greater than the endparam?

Did you notice that when the normal was negative Z, sometimes the params were also negative?  I don't get that.

I find that no matter how you program it, it can find the apex and nadir points of a rotated closed ellipse.  Same for Xmin and Xmax.  Yes, you could use getboundingbox, but that won't give you the points on the ellipse.  You would have to intersectwith a line defined by adjacent corners.

John F. Uhden

0 Likes
Message 45 of 48

john.uhden
Mentor
Mentor

@_gile 

I think I would not find my way out of a dichotomic forest.

John F. Uhden

0 Likes
Message 46 of 48

_gile
Consultant
Consultant

@john.uhden The same without getpropetyvalue.

(defun getPointAtTangent (ellipse tanAng onCurve / tan elst majRad minRad center normal baseAng point)
  (defun tan (x) (/ (sin x) (cos x)))
  (setq	elst (entget ellipse)
	majRad	(distance '(0. 0. 0.) (cdr (assoc 11 elst)))
	minRad	(* majRad (cdr (assoc 40 elst)))
	center	(cdr (assoc 10 elst))
	normal  (cdr (assoc 210 elst))
	baseAng	(angle '(0. 0. 0.) (trans (cdr (assoc 11 elst)) 0 normal))
	tanAng	(- tanAng baseAng)
	point	(list
		  (/ (* majRad majRad (tan tanAng) -1.)
		     (sqrt (+ (* majRad majRad (tan tanAng) (tan tanAng)) (* minRad minRad)))
		  )
		  (* (/	(* minRad minRad)
			(sqrt (+ (* majRad majRad (tan tanAng) (tan tanAng)) (* minRad minRad)))
		     )
		  )
		  0.
		)
  )
  (if (< 0. (cos tanAng))
    (setq point (mapcar '- point))
  )
  (setq	point
	 (mapcar '+
		 (trans
		   (mapcar
		     '(lambda (r) (apply '+ (mapcar '* r point)))
		     (list (list (cos baseAng) (- (sin baseAng)) 0.)
			   (list (sin baseAng) (cos baseAng) 0.)
			   '(0. 0. 1.)
		     )
		   )
		   normal
		   0
		 )
		 center
	 )
  )
  (if (or (not onCurve) (vlax-curve-getParamAtPoint ellipse point))
    point
  )
)


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 47 of 48

john.uhden
Mentor
Mentor

@_gile 

Thanks for saving me the trouble.  I did change your code slightly to entmakex a point, but it's perfect!

I guess @doaiena should get some credit for coming up with the approach.

I am waiting to see what @hak_vz promised this weekend.

Do you think these stupid challenges may be just a waste of our time?  I have another one thought up already, geared for architects, builders, and DIY homeowners.  Wait a second, the architects won't care; they just draw the plans.

John F. Uhden

0 Likes
Message 48 of 48

Sea-Haven
Mentor
Mentor

Bricscad no getpropertyvalue. 

 

A find query used in data base of 10,000 takes 13 goes to find correct answer using an index method as Gile suggested, ditchotomic,  jump 1/2 more less ?, jump 1/2 1/2 and so on.  In this case limit tolerance or actual number of guesses which has been done. 

 

Another architects, builders, and DIY homeowners I may be lucky and have a head start, my code.

SeaHaven_0-1647142431024.png

 

0 Likes