Jump to content

Get coordinates of 3rd point based on known distance between it and 1st and 2nd point?


vanowm

Recommended Posts

If we have lengths of each side of a triangle ( L1, L2, L3 ), we can draw 2 circles at a distance of L1 from each other, with radius of L2 and L3 respectively. Center of each circle would give us P1 and P2 coordinates and intersection of these circles would be the P3 point.

 

How would we get P3 coordinates without drawing anything in autolisp if P1 and P2 are already known? (Looking for a most performance efficient way)

 

 

Thank you.

 

TLDR;

Working code in this reply.

Edited by vanowm
Link to comment
Share on other sites

Here comes a quick one. Not fully tested

(defun c:pp()
  (setq l1 10.0 l2 13.6 l3 9.21)
  (setq p1 (list 3.3 2.2) p2 (polar p1 0.1234 l1))
  
  (setq p (* (+ l1 l2 l3) 0.5))
  (setq area (sqrt (* p (- p l1) (- p l2) (- p l3))))
  (setq h (/ area l1 0.5))
  (setq h1 (sqrt (- (* l2 l2) (* h h))))
  (setq ang (atan h h1))
  (setq p3 (polar p1 (+ ang (angle p1 p2)) l2))
  (setq p4 (polar p1 (- ang (angle p1 p2)) l2))
  )

Just a word of warning: working in 2D, there are two solutions to your request. This Lisp will show one of them in P3, and the other one in P4. You will need more conditions to find the right one

  • Thanks 1
Link to comment
Share on other sites

This is called the compass method, since it relies on laying out two circles (aka using a compass).  It is commonly used by surveyors.

 

Here is a solution that uses a custom circle-circle-intersection function.  There can be no intersections, 1 if the circles are tangent or 2 intersections.  Not sure why AutoLisp doesn't include this a core function like 'inters'.

 

There are a bunch of library functions included because that's how my brain works.

; ========================================================= Circle Circle Intersection functions

(defun C:CompassLayout (/ 
			MyColour CP1 Rad1 CircleEnt1 CP2 Rad2 CircleEnt2 Ans P3	
			)
; Layout a point in 2D by compass method
; KJM - May 2023
; Creates globals:
;	NewPoint - (point) 2D point coordinates
;	PointEnt - (ename) ename of point
; Uses custom functions:
;	MakeCircle
;	CircleCircleInt
;	MakePoint

(setq MyColour 1)	; colour for temporary circles or point (set to nil for 'bylayer')


; Get first point (2D) and layout distance
(setq CP1 (getpoint "\nSelect first point..."))
(setq CP1 (list (car CP1) (cadr CP1) 0.0))			; force 2D 	
(setq Rad1 (getdist CP1 "\nEnter layout distance from point..."))

; Draw circle using custom function
(setq CircleEnt1 (makecircle CP1 Rad1 nil MyColour))

; Get second point (2D) and layout distance
(setq CP2 (getpoint "\nSelect second point..."))
(setq CP2 (list (car CP2) (cadr CP2) 0.0))			; force 2D	
(setq Rad2 (getdist CP2 "\nEnter layout distance from point..."))

; Draw circle using custom function
(setq CircleEnt2 (makecircle CP2 Rad2 nil MyColour))

; Get intersections using custom function
(setq Ans (CircleCircleInt CP1 Rad1 CP2 Rad2 0.001))
(prompt "\n  Ans = ")(princ Ans)(princ)

(if Ans
  (progn
  	; Have 1 intersection (tangent) or 2 intersections
  	(if (> (length Ans) 1)
  	  (progn
  		; 2 intersections, find closest one to desired point
  		(setq P3 (getpoint "\nSelect a point nearest the desired intersection..."))
  	
  		(if (<= (distance P3 (nth 0 Ans)) (distance P3 (nth 1 Ans)))
			(setq NewPoint (nth 0 Ans))	; first point is closest
			(setq NewPoint (nth 1 Ans))	; second point is closest
		) ; close if
	  )
	  (progn
	  	; 1 intersection, circles are tangent
	  	(setq NewPoint (nth 0 Ans))
	  )
	) ; close if

	; Draw point using custom function and report	
	(setq PointEnt (makepoint NewPoint nil MyColour))
	(prompt "\n  Point ")(princ (rtos (car NewPoint) 2 3))(prompt " , ")(princ (rtos (cadr NewPoint) 2 3))(prompt " , ")(princ (rtos (caddr NewPoint) 2 3))
	
	; Access point entity via variable 'PointEnt' or point via variable 'NewPoint'
	
  )
) ; close if

; Cleanup
(entdel CircleEnt1)
(entdel CircleEnt2)

(prompt "\nCompleted!")
(princ)
)



(defun C:TestCCI (/ Ent1 EntData1 CP1 Rad1 Ent2 EntData2 CP2 Rad2 Ans CNT MyPoint LastEnt)
; Test function for 'CircleCircleInt'
; KJM - April 1998

(command ".UNDO" "M")

(setq Ent1 (car (entsel "\nSelect an arc or circle...")))
(setq EntData1 (entget Ent1))
(setq CP1 (cdr (assoc 10 EntData1)))
(setq Rad1 (cdr (assoc 40 EntData1)))


(setq Ent2 (car (entsel "\nSelect another arc or circle...")))
(setq EntData2 (entget Ent2))
(setq CP2 (cdr (assoc 10 EntData2)))
(setq Rad2 (cdr (assoc 40 EntData2)))

; Get intersections
(setq Ans (CircleCircleInt CP1 Rad1 CP2 Rad2 0.001))
(prompt "\n  Ans = ")(princ Ans)(princ)

; Plot points
(setq CNT 0)
(repeat (length Ans)
	(setq MyPoint (nth CNT Ans))

	(command ".point" MyPoint)
	(setq Lastent (entlast))

	(command ".change" Lastent "" "P" "C" 1 "")	; colour red

	(setq CNT (1+ CNT))
) ; close repeat
(princ)
)




(defun CircleCircleInt (CP1 Rad1 CP2 Rad2 tol /
			Verbose OutList dummy PX1 PY1 PX2 PY2 DistCP MyCase Des XX1 XX2 YY1 YY2
			IX1 IX2 IY1 IY2 Check11 Check12 Check21 Check22
			)
; Find 2D intersection between 2 circles
; KJM - April 1998
; Input:
;	CP1 - (point) centre of circle 1
;	Rad1 - (real) radius of circle 1
;	CP2 - (point) centre of circle 2
;	Rad2 - (real) radius of circle 2
;	tol - (real) tolerance distance, if nil then use 1e-8
; Returns:
;	list of intersection points (nil if no intersections, 1 if tangent, or 2 if circles cross in two locations)
; Uses custom functions:
;	neg
;	FuzzyWeed

(setq Verbose 0)

(setq OutList nil)

; set tolerance if not specified
(if (eq tol nil)
	(setq tol 1e-8)
)	


; Swap circles so that Circle 1 is larger of the two
(if (> Rad2 Rad1)
  (progn
  	(setq dummy Rad1 Rad1 Rad2 Rad2 dummy)
  	(setq dummy CP1 CP1 CP2 CP2 dummy)
  )
)

; Force points to 2D
(setq PX1 (nth 0 CP1) PY1 (nth 1 CP1))
(setq PX2 (nth 0 CP2) PY2 (nth 1 CP2))
(setq CP1 (list PX1 PY1 0.0))
(setq CP2 (list PX2 PY2 0.0))


; Check distance between circle centres, can be one of 5 cases
(setq DistCP (distance CP1 CP2))

(if (eq Verbose 1)
  (progn
	(prompt "\n  Rad1 = ")(princ Rad1)(prompt "  Rad2 = ")(princ Rad2)(prompt "  DistCP = ")(princ DistCP)
	(prompt "\n  R1+R2 = ")(princ (+ Rad1 Rad2))(prompt "  R1-R2 = ")(princ (- Rad1 Rad2))
	(prompt "\n  Outside Tangency check D - (R1+R2) = ")(princ (- DistCP (+ Rad1 Rad2)))
	(prompt "  Inner Tangency check D - (R1-R2) = ")(princ (- DistCP (- Rad1 Rad2)))
	(princ)
  )
)

(cond
	((or (< (- DistCP (- Rad1 Rad2)) tol) (equal DistCP (- Rad1 Rad2) tol))
	  (progn
	  	(if (equal DistCP (- Rad1 Rad2) tol)
		  (progn
		  	; Inner tangency
		  	(setq MyCase 2)
		  )
		  (progn
			; Circle 2 entirely within circle 1
			(setq MyCase 1)
		  )
		)
	  )	
	)

	((or (> (- DistCP (+ Rad1 Rad2)) tol) (equal DistCP (+ Rad1 Rad2) tol))
	  (progn
	  	(if (equal DistCP (+ Rad1 Rad2) tol)
		  (progn
		  	; Outer tangency
		  	(setq MyCase 4)
		  )	
		  (progn	
		  	; Circles do not intersect
		  	(setq MyCase 5)
		  )
		)
	  )
	)
	
	((and (> DistCP (abs (- Rad1 Rad2))) (< DistCP (+ Rad1 Rad2)))
	  (progn
	  	; Intersecting circles
	  	(setq MyCase 3)
	  )	
	)
) ; close cond

(if (eq Verbose 1)
  (progn
	(prompt "\n  Case = ")(princ MyCase)(princ)
  )
)

(if (eq MyCase 3)
  (progn
  	; Intersecting circles with two points of intersection
  	
  	; Area of triange DistDP-Rad1-Rad2 by Heron's formula
  	(setq des (* 0.25 (sqrt (*
  				(+ DistCP Rad1 Rad2)
  				(+ DistCP Rad1 (neg Rad2))
  				(+ DistCP (neg Rad1) Rad2)
  				(+ (neg DistCP) Rad1 Rad2)
  	))))
  	
  	; Get 2-x and 2-y values
  	(setq XX1  (+
  			(* 0.5 (+ PX1 PX2))
  			(/ (* (- PX2 PX1) (- (* Rad1 Rad1) (* Rad2 Rad2))) (* 2.0 DistCP DistCP))
  	))
  	
  	(setq XX2 (/ (* 2.0 des (- PY1 PY2)) (* DistCP DistCP)))
  	
  	(setq IX1 (+ XX1 XX2))
  	(setq IX2 (- XX1 XX2))
  	
  	(setq YY1 (+
			(* 0.5 (+ PY1 PY2))
			(/ (* (- PY2 PY1) (- (* Rad1 Rad1) (* Rad2 Rad2))) (* 2.0 DistCP DistCP))
  	))
  	
  	(setq YY2 (/ (* 2.0 des (- PX1 PX2)) (* DistCP DistCP)))
  	
  	(setq IY1 (- YY1 YY2))
  	(setq IY2 (+ YY1 YY2))
  	

	(if (eq Verbose 1)
	  (progn	
		(prompt "\n  Des = ")(princ Des)
		(prompt "\n  X1 = ")(princ IX1)(prompt "  X2 = ")(princ IX2)(prompt "  Y1 = ")(princ IY1)(prompt "  Y2 = ")(princ IY2)(princ)
	  )
	)
	
	; Find which X goes with which Y by determining which pair lies on circle
	(setq Check11 (list IX1 IY1 0.0))
	(setq Check12 (list IX1 IY2 0.0))
	(setq Check21 (list IX2 IY1 0.0))
	(setq Check22 (list IX2 IY2 0.0))

	; Verify coordinates that lie on circle radius

	(if (equal (distance CP1 Check11) Rad1 0.001)
		(setq OutList (cons Check11 OutList))
	)
	(if (equal (distance CP1 Check12) Rad1 0.001)
		(setq OutList (cons Check12 OutList))
	)
	(if (equal (distance CP1 Check21) Rad1 0.001)
		(setq OutList (cons Check21 OutList))
	)
	(if (equal (distance CP1 Check22) Rad1 0.001)
		(setq OutList (cons Check22 OutList))
	)

	(setq OutList (fuzzyweed OutList 0.0001))	; remove very close points ('almost' tangent condition)

  )
) ; close if

(if (member MyCase (list 2 4))
  (progn
  	; Inner or outer tangent circles with one point of intersection (aka tangency)
  	(setq Check11 (polar CP1 (angle CP1 CP2) Rad1))
  	
  	(setq OutList (list Check11))		; Note point (list) within list
  )
) ; close if


; Return list of intersections
OutList
)	


; ========================================================= Helper functions


(defun MakePoint (MyPoint MyLayer MyColour / LastEnt OutList)
; Entmake a point
; KJM - Dec 2018
; Input:
;	MyPoint - point coordinate
;	MyLayer - layer name for point (will be created if necessary), will used current layer if nil
;	MyColour - ACI colour number for point (will used 'bylayer' if nil)
; Returns:
; 	returns entity name of point
;	Draws point as specified

(if (eq MyLayer nil)
	(setq MyLayer (getvar "CLAYER"))
)


(setq OutList (list '(0 . "POINT") (cons 10 MyPoint)))

(if MyLayer
	(setq OutList (append OutList (list (cons 8 MyLayer))))
)

(if MyColour
	(setq OutList (append OutList (list (cons 62 MyColour))))
)	

(entmake OutList)

(setq LastEnt (entlast))
LastEnt
)


  

(defun MakeCircle (MyPoint MyRad MyLayer MyColour / LastEnt OutList)
; Entmake a circle
; KJM - Dec 2018
; Input:
;	MyPoint - circle centre coordinate
;	MyRad - radius of circle
;	MyLayer - layer name for circle (will be created if necessary), will used current layer if nil
;	MyColour - ACI colour number for circle (will use 'bylayer' if nil)
; Returns:
; 	returns entity name of circle
;	Draws circle as specified

(if (eq MyLayer nil)
	(setq MyLayer (getvar "CLAYER"))
)

(setq OutList (list '(0 . "CIRCLE") (cons 10 MyPoint) (cons 40 MyRad)))

(if MyLayer
	(setq OutList (append OutList (list (cons 8 MyLayer))))
)

(if MyColour
	(setq OutList (append OutList (list (cons 62 MyColour))))
)	

(entmake OutList)

(setq LastEnt (entlast))
LastEnt
)




(defun Neg (Val / )
; Multiply a value by -1.0
	(* -1.0 Val)
)



(defun FuzzyWeed (MyList tol / OutList CNT Item Found CNT1 Item1)
; Remove duplicates from a list, intended for point or number comparison
; KJM - May 1988, Mod KJM Jan 1991 - added variable tol
; Input:
;	MyList - (list) a list of numbers, or list of points
;	tol - (real) threshold for comparison e.g. 0.001.  Default nil = 1e-8
; Returns:
;	list with duplicates removed
; Uses custom functions:
;	none!


; default
(if (eq tol nil)
	(setq tol 1e-8)
)	

(setq OutList nil)

(if (> (length MyList) 1)
  (progn
	(setq CNT 0)
	(repeat (length MyList)
		(setq Item (nth CNT MyList)) 			; get element
	
	  	(setq found 0)
		
		(if (eq CNT 0)
		  (progn
			(setq OutList (cons Item OutList))	; automatically add first item to output list
		  )
		  (progn
		  	; Compare against all other values in output list
		  	(setq CNT1 0)
	
			(repeat (length OutList)
				(setq Item1 (nth CNT1 OutList))
				
				(if (equal Item Item1 tol)		; this works for numbers or lists
					(setq found (1+ found))	
				)
			
				(setq CNT1 (1+ CNT1))
			) ; close repeat	

			(if (eq found 0)	
				(setq OutList (cons Item OutList)) 	; not found, add to new list
			)
		  )
		)
		(setq CNT (1+ CNT))
	) ; close repeat
	(setq OutList (reverse OutList))
  )
  (progn
  	; Only a single item list passed to routine
  	(setq OutList MyList)
  )
) ; close if

OutList
)

 

Link to comment
Share on other sites

8 hours ago, fuccaro said:

Here comes a quick one. Not fully tested

(defun c:pp()
  (setq l1 10.0 l2 13.6 l3 9.21)
  (setq p1 (list 3.3 2.2) p2 (polar p1 0.1234 l1))
  
  (setq p (* (+ l1 l2 l3) 0.5))
  (setq area (sqrt (* p (- p l1) (- p l2) (- p l3))))
  (setq h (/ area l1 0.5))
  (setq h1 (sqrt (- (* l2 l2) (* h h))))
  (setq ang (atan h h1))
  (setq p3 (polar p1 (+ ang (angle p1 p2)) l2))
  (setq p4 (polar p1 (- ang (angle p1 p2)) l2))
  )

Just a word of warning: working in 2D, there are two solutions to your request. This Lisp will show one of them in P3, and the other one in P4. You will need more conditions to find the right one

Thank you. So basically, it's just a converted to lisp trigonometry formula, there is no built-in function for this?

 

Not sure what do you mean by 2 solutions, other than orientation of the triangle, there should be only one solution...your P4 produces incorrect result (I've rounded each side to 10, 13 and 9):

image.png.fc636b8b53513cfe5667be2cb77a40e4.png

 

 

@kirby2, thank you for this. I'm looking for a most efficient solution. I already have routine that draw triangles by using circles, it works well, but very slow, if in Autocad 2002 it would process 100 triangles in 1 second, in Autocad 2023 it takes about 5-6 seconds, so I'm trying find a way optimize it by not drawing anything, which should speed it up 10 fold at least.

Edited by vanowm
Link to comment
Share on other sites

13 minutes ago, vanowm said:

Thank you. So basically, it's just a converted to lisp trigonometry formula, there is no built-in function for this?

 

Not sure what do you mean by 2 solutions, other than orientation of the triangle, there should be only one solution...your P4 produces incorrect result (I've rounded each side to 10, 13 and 9):

image.png.fc636b8b53513cfe5667be2cb77a40e4.png

 

 

@kirby2, thank you for this. I'm looking for a most efficient solution. I already have routine that draw triangles by using circles, it works well, but very slow, if in Autocad 2002 it would process 100 triangles in 1 second, in Autocad 2023 it takes about 5-6 seconds, so I'm trying find a way optimize it by not drawing anything, which should speed it up 10 fold at least.

 

 

 

@vanowm, would you, please upload such lisp and the dwg it result from.>

 

I really do not get the idea. 

 

 

 

Link to comment
Share on other sites

This offers the two possible solutions

(defun c:2xd ( / cc1 r1 cc2 r2 dce dxf_210 xi yi i cr1 cr2 vi xt yt h1 h2 h i1 i2 key i)
  (initget 9)
  (setq cc1 (getpoint "\nFirst start point?: "))
  (initget 9)
  (setq cc2 (getpoint cc1 "\nSecond start point?: "))
  (grdraw cc1 cc2 1)
  (initget 39)
  (setq r1 (getdist cc1 "\nFirst length?: "))
  (initget 39)
  (setq r2 (getdist cc2 "\nSecond length?: "))
  (grdraw cc1 cc2 0)
  (setq
    dce (distance cc1 cc2)
    dxf_210 (trans '(0 0 1) 1 0 T)
  )
  (if (equal (/ dce (+ r1 r2)) 1E-16)
    (setq
      xi (/ (+ (* r2 (car cc1)) (* r1 (car cc2))) dce)
      yi (/ (+ (* r2 (cadr cc1)) (* r1 (cadr cc2))) dce)
      i (cons xi (cons yi '(0.0)))
    )
    (if (and (not (zerop (- r1 r2))) (equal (/ dce (+ r1 r2)) 1E-16))
      (progn
        (if (= r1 (max r1 r2))
          (setq cr1 cc1 cr2 cc2)
          (setq cr1 cc2 cr2 cc1)
        )
        (setq
          xi (/ (- (* (max r1 r2) (car cr2)) (* (min r1 r2) (car cr1))) dce)
          yi (/ (- (* (max r1 r2) (cadr cr2)) (* (min r1 r2) (cadr cr1))) dce)
          i (cons xi (cons yi '(0.0)))
        )
      )
      (progn
        (if (or (> dce (+ r1 r2)) (< (+ (min r1 r2) dce) (max r1 r2)))
          (prompt "\nNo intersection !...")
          (progn
            (setq vi (angle cc1 cc2))
            (if (> r1 r2)
              (setq
                xt (- (/ (* (+ r1 dce r2) (- (+ r1 dce) r2)) (* 2 dce)) r1)
                yt (- dce xt)
                h1 (sqrt (- (expt r1 2) (expt xt 2)))
                h2 (sqrt (- (expt r2 2) (expt yt 2)))
                xi (/ (+ (* yt (car cc1)) (* xt (car cc2))) dce)
                yi (/ (+ (* yt (cadr cc1)) (* xt (cadr cc2))) dce)
              )
              (setq
                xt (- (/ (* (+ r2 dce r1) (- (+ r2 dce) r1)) (* 2 dce)) r2)
                yt (- dce xt)
                h1 (sqrt (- (expt r2 2) (expt xt 2)))
                h2 (sqrt (- (expt r1 2) (expt yt 2)))
                xi (/ (+ (* xt (car cc1)) (* yt (car cc2))) dce)
                yi (/ (+ (* xt (cadr cc1)) (* yt (cadr cc2))) dce)
              )
            )
            (setq
              h (/ (+ h1 h2) 2)
              i1 (polar (cons xi (cons yi '(0.0))) (+ vi (/ pi 2)) h)
              i2 (polar (cons xi (cons yi '(0.0))) (- vi (/ pi 2)) h)
            )
            (princ "\n<Move cursor> for choice; <Enter>/[Space]/Right-Click for end!.")
            (while (and (not (member (setq key (grread T 4 2)) '((2 13) (2 32)))) (/= (car key) 25))
              (redraw)
;             (grdraw cc1 cc2 7)
              (cond
                ((eq (car key) 5)
                  (if (< (distance i1 (cadr key)) (distance i2 (cadr key)))
                    (set 'i i1)
                    (set 'i i2)
                  )
                  (grdraw cc1 i 7)
                  (grdraw i cc2 7)
                )
              )
            )
            (entmake
              (list
                '(0 . "LWPOLYLINE")
                '(100 . "AcDbEntity")
                (cons 67 (if (eq (getvar "CVPORT") 1) 1 0))
                (cons 410 (if (eq (getvar "CVPORT") 1) (getvar "CTAB") "Model"))
                (cons 8 (getvar "CLAYER"))
                (cons 62 (atoi (getvar "CECOLOR")))
                (cons 6 (getvar "CELTYPE"))
                (cons 370 (getvar "CELWEIGHT"))
                '(100 . "AcDbPolyline")
                '(90 . 3)
                (if (eq (getvar "PLINEGEN") 1) '(70 . 128) '(70 . 0))
                (cons 43 (getvar "PLINEWID"))
                (cons 38 (getvar "ELEVATION"))
                (cons 39 (getvar "THICKNESS"))
                (cons 10 (list (car cc1) (cadr cc1)))
                '(40 . 0.0)
                '(41 . 0.0)
                '(42 . 0.0)
                '(91 . 0)
                (cons 10 (list (car i) (cadr i)))
                '(40 . 0.0)
                '(41 . 0.0)
                '(42 . 0.0)
                '(91 . 0)
                (cons 10 (list (car cc2) (cadr cc2)))
                '(40 . 0.0)
                '(41 . 0.0)
                '(42 . 0.0)
                '(91 . 0)
                (cons 210 dxf_210)
              )
            )
          )
        )
      )
    )
  )
  (prin1)
)

 

Edited by Tsuky
  • Like 2
Link to comment
Share on other sites

9 hours ago, vanowm said:

Not sure what do you mean by 2 solutions, other than orientation of the triangle, there should be only one solution...

 

If you have two circles that interest your going to have two solutions unless their tangent to each other. you need a third circle to limit it to one point.

https://www.101computing.net/cell-phone-trilateration-algorithm

Link to comment
Share on other sites

@vanowm - not sure about not drawing anything, could wrap the output in a loop but you would always need to either intervene to specify which of the two possible intersections is the correct one, or supply more criteria (e.g. angle P1-NewPoint-P2 is always approx. 90 degrees, NewPoint is always on the right hand side of segment P1-P2, etc.)

 

@mhupp - thanks for the link.  A rabbit hole of good stuff there.

Link to comment
Share on other sites

@kirby2 In my case the side at which triangle is calculated is always the same, so that shouldn't be a problem (I think).

 

@mhupp there can't be tangent circles when all sides of a triangle are known, otherwise it would create a line, not a triangle.

Link to comment
Share on other sites

One way around the 2 point intersection of 2 circles is to use 2 arcs instead. The arc center point are the ends and the side of the arcs is based on the P1 P2 direction so arcs say are always to left.

 

image.thumb.png.d6275abc18266ad3e2dde521fa610f8c.png

(defun c:trilen ( / l1 l2 l3 pt1 pt2 pt3 obj1 obj2)
(setq L1 (getreal "\nEnter L1 "))
(setq L2 (getreal "\nEnter L2 "))
(setq L3 (getreal "\nEnter L3 "))

(setq pt1 (getpoint "\nPick left point "))
(setq pt2 (polar pt1 0.0 l1))
(command "line" pt1 pt2 "")

(setq pt3 (polar pt1 pi l2))
(command "arc" "C" pt1 pt3 "a" 180)
(setq obj1 (vlax-ename->vla-object (entlast)))

(setq pt3 (polar pt2 0.0 l2))
(command "arc" "C" pt2 pt3 "a" -180)
(setq obj2 (vlax-ename->vla-object (entlast)))

(setq intpt (vlax-invoke obj2 'intersectWith obj1 acExtendThisEntity))
(vla-delete obj1)
(vla-delete obj2)

(command "line" Pt1 intpt "")
(command "line" Pt2 intpt "")

(princ)
)

 

  • Like 1
Link to comment
Share on other sites

On 5/26/2023 at 11:32 PM, vanowm said:

Not sure what do you mean by 2 solutions, other than orientation of the triangle, there should be only one solution...your P4 produces incorrect result

I see there was no week-end in this thread... :)

Yes, there are two solutions because the triangle can be drawn in two directions.

I found your initial request really with minutes before I had to go home, that's why I marked my post as "not fully tested"

The line:

 (setq p4 (polar p1 (- ang (angle p1 p2)) l2))

should become:

(setq p4 (polar p1 (- (angle p1 p2) ang) l2))

Take care!

Link to comment
Share on other sites

On 5/27/2023 at 8:52 AM, mhupp said:

 

If you have two circles that interest your going to have two solutions unless their tangent to each other.

... or you may have no solution if the circles are too fare from each other

Link to comment
Share on other sites

On 5/27/2023 at 4:48 PM, vanowm said:

  @mhupp there can't be tangent circles when all sides of a triangle are known, otherwise it would create a line, not a triangle.

 

1 hour ago, fuccaro said:

... or you may have no solution if the circles are too fare from each other

 

It's was a general statement their is always going to be two intersecting points if two circles interest. only way to have one is if their tangent.

and if they are to far apart to intersect then yes they don't have any intersecting points.

Link to comment
Share on other sites

In any triangle a side must be greater than the difference between the other two sides, and less than their sum.

Link to comment
Share on other sites

One little detail you guys seem to miss - if a triangle has known length of all 3 sides, circles drawn from any two corners will always intersect at 3rd corner.

 

@fuccaro would you please update your original answer, so future visitors don't have to go through entire topic just to get the answer...So far that's the only answer that calculates 3rd point without drawing anything.

Link to comment
Share on other sites

Quote

One little detail you guys seem to miss - if a triangle has known length of all 3 sides, circles drawn from any two corners will always intersect at 3rd corner.

Someone has to explain to me the difference between these two triangles of the same dimensions...!🤪

kite.PNG

  • Funny 1
  • Agree 1
Link to comment
Share on other sites

@Tsuky The two triangles P1-P2-P3 and P1-P2-P3' are both possible given two points and the radial distances to a third point.  However, only one is (likely) the correct corner of the triangle for the purposed of laying out point P3 .  Both triangle have identical area and share the baseline segment P1-P2

 

@vanowm Just curious what situation are you dealing with where you always know the third point is on a certain side of line segment P1-P2?   e.g. segment P1-P2-P3 is always counter-clockwise such that P3 is always on the right hand side of baseline P1-P2, etc.   I work in civil engineering / surveying and either situation can often be the case.

Link to comment
Share on other sites

@fuccaro It seems something wrong with the formula, it produces incorrect triangle:

(defun pp(/ l1 l2 l3 p1 p2 p3 p4 p area h h1 ang)
  (setq l1 3 l2 2 l3 4)
  (setq p1 (list 0 0) p2 (list 0 l1))
  
  (setq p (* (+ l1 l2 l3) 0.5))
  (setq area (sqrt (* p (- p l1) (- p l2) (- p l3))))
  (setq h (/ area l1 0.5))
  (setq h1 (sqrt (- (* l2 l2) (* h h))))
  (setq ang (atan h h1))
  (setq p3 (polar p1 (+ ang (angle p1 p2)) l2))
  (setq p4 (polar p1 (- (angle p1 p2) ang) l2))
  (command "line" p1 p2 p3 p1 "")
)
(pp)

It supposed to draw a triangle with sides of 3, 2 and 4, but it draws with 3, 2 and 3.16

image.png.7d72b7263193d1e3f562fbf6693affc1.png

Link to comment
Share on other sites

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...