# 3-Point Circle & Arc Functions

## Introduction

On this page I demonstrate a set of geometric functions which may be used to construct a Circle or Arc from three supplied points.

Each function may be tested with a non-dynamic or dynamic test program, the latter demonstrating real-time entity modification to create the illusion of a dynamic effect - this technique is unfortunately underpinned by the grread function to monitor user input, hence restricting the use of standard AutoCAD functionality such as Object Snap, Tracking, Orthomode, etc.

Finally, I utilise my Arc->Bulge function, taken from my set of Bulge Conversion Functions, to construct a function to create a 'PolyArc' (LWPolyline Arc Segment) from three supplied points.

## 3-Point Circle

 Function Syntax (LM:3PCircle ) Current Version 1.0 Donate
Arguments
Symbol Type Description
p1, p2, p3 List Points through which to construct the Circle
Returns
Type Description
List List of: (<center> <radius>) of Circle

### Function Description

This function will return a list of the center and radius of a circle whose circumference passes through three supplied points.

The function will return nil if the circle is undefined, such as the case if the three supplied points are collinear.

Select all
```;; 3-Point Circle  -  Lee Mac
;; Returns the Center and Radius of the Circle defined
;; by three supplied points.

(defun LM:3PCircle ( p1 p2 p3 / cn m1 m2 )
(setq m1 (mid p1 p2)
m2 (mid p2 p3)
)
(if
(setq cn
(inters
m1 (polar m1 (+ (angle p1 p2) (/ pi 2.)) 1.0)
m2 (polar m2 (+ (angle p2 p3) (/ pi 2.)) 1.0)
nil
)
)
(list cn (distance cn p1))
)
)

;; Midpoint  -  Lee Mac
;; Returns the midpoint of two points

(defun mid ( a b )
(mapcar (function (lambda ( a b ) (/ (+ a b) 2.0))) a b)
)
```

### Test Programs

Here are two programs with which to test the above LM:3PCircle function. 3PCircle will construct a circle from three selected points; 3PGrCircle will prompt for two points, then display a real-time preview of the circle whilst the user selects the third point.

Select all
```(defun c:3PCircle ( / p1 p2 p3 lst )
(if
(and
(setq p1  (getpoint "\nSpecify 1st Point: "))
(setq p2  (getpoint "\nSpecify 2nd Point: " p1))
(setq p3  (getpoint "\nSpecify 3rd Point: " p2))
(setq lst (LM:3PCircle (trans p1 1 0) (trans p2 1 0) (trans p3 1 0)))
)
(entmake (append '((0 . "CIRCLE")) (mapcar 'cons '(10 40) lst)))
)
(princ)
)

(defun c:3PGrCircle ( / p1 p2 p3 lst cir )
(if
(and
(setq p1  (getpoint "\nSpecify 1st Point: "))
(setq p2  (getpoint "\nSpecify 2nd Point: " p1))
(setq lst (LM:3PCircle (setq p1 (trans p1 1 0)) (setq p2 (trans p2 1 0)) (trans p3 1 0)))
(setq cir (entmakex (append '((0 . "CIRCLE")) (mapcar 'cons '(10 40) lst))))
(setq cir (list (cons -1 cir)))
(princ "\nSpecify 3rd Point: ")
)
(while (= 5 (car (setq gr (grread t 13 0))))
(if (setq lst (LM:3PCircle p1 p2 (trans (cadr gr) 1 0)))
(entmod (append cir (mapcar 'cons '(10 40) lst)))
)
)
)
(princ)
)
```

## 3-Point Arc

 Function Syntax (LM:3PArc ) Current Version 1.0 Donate
Arguments
Symbol Type Description
p1, p2, p3 List Points through which to construct the Arc
Returns
Type Description
List List of: (<center> <start angle> <end angle> <radius>) of Arc

### Function Description

This function will return a list of the center, start angle, end angle and radius of an arc passing through three supplied points, two of which are the endpoints of the arc.

The return values are ordered to be consistent with my 'LM:Arc->Bulge' and 'LM:Bulge->Arc' functions as part of my Bulge Conversion Functions.

The function will return nil if the arc is undefined, such as the case if the three supplied points are collinear.

Select all
```;; 3-Point Arc  -  Lee Mac
;; Returns the Center, Start/End Angle and Radius of the
;; Arc defined by three supplied points.

(defun LM:3PArc ( p1 p2 p3 / cn m1 m2 )
(setq m1 (mid p1 p2)
m2 (mid p2 p3)
)
(if
(setq cn
(inters
m1 (polar m1 (+ (angle p1 p2) (/ pi 2.)) 1.0)
m2 (polar m2 (+ (angle p2 p3) (/ pi 2.)) 1.0)
nil
)
)
(append (list cn)
(if (LM:Clockwise-p p1 p2 p3)
(list (angle cn p3) (angle cn p1))
(list (angle cn p1) (angle cn p3))
)
(list (distance cn p1))
)
)
)

;; Midpoint  -  Lee Mac
;; Returns the midpoint of two points

(defun mid ( a b )
(mapcar (function (lambda ( a b ) (/ (+ a b) 2.0))) a b)
)

;; Clockwise-p  -  Lee Mac
;; Returns T if p1,p2,p3 are clockwise oriented

(defun LM:Clockwise-p ( p1 p2 p3 )
(< (* (- (car  p2) (car  p1)) (- (cadr p3) (cadr p1)))
)
)
```

### Test Programs

Here are again two programs with which to test the above LM:3PArc function. 3PArc will construct an arc from three selected points; 3PGrArc will prompt for two points, then display a real-time preview of the arc whilst the user selects the third point.

Select all
```(defun c:3PArc ( / p1 p2 p3 lst )
(if
(and
(setq p1  (getpoint "\nSpecify 1st Point: "))
(setq p2  (getpoint "\nSpecify 2nd Point: " p1))
(setq p3  (getpoint "\nSpecify 3rd Point: " p2))
(setq lst (LM:3PArc (trans p1 1 0) (trans p2 1 0) (trans p3 1 0)))
)
(entmake (append '((0 . "ARC")) (mapcar 'cons '(10 50 51 40) lst)))
)
(princ)
)

(defun c:3PGrArc ( / p1 p2 p3 lst arc )
(if
(and
(setq p1  (getpoint "\nSpecify 1st Point: "))
(setq p2  (getpoint "\nSpecify 2nd Point: " p1))
(setq lst (LM:3PArc (setq p1 (trans p1 1 0)) (setq p2 (trans p2 1 0)) (trans p3 1 0)))
(setq arc (entmakex (append '((0 . "ARC")) (mapcar 'cons '(10 50 51 40) lst))))
(setq arc (list (cons -1 arc)))
(princ "\nSpecify 3rd Point: ")
)
(while (= 5 (car (setq gr (grread t 13 0))))
(if (setq lst (LM:3PArc p1 p2 (trans (cadr gr) 1 0)))
(entmod (append arc (mapcar 'cons '(10 50 51 40) lst)))
)
)
)
(princ)
)
```

## 3-Point PolyArc

Finally, below is a program, 3PPolyArc, which utilises a combination of my LM:3PArc and LM:Arc->Bulge functions to create a 3-Point 'PolyArc' - that is, an LWPolyline arc segment constructed from three points.

Select all
```(defun c:3PPolyArc ( / p1 p2 p3 lst )
(if
(and
(setq p1  (getpoint "\nSpecify 1st Point: "))
(setq p2  (getpoint "\nSpecify 2nd Point: " p1))
(setq p3  (getpoint "\nSpecify 3rd Point: " p2))
(setq lst (LM:3PArc (trans p1 1 0) (trans p2 1 0) (trans p3 1 0)))
(setq lst (apply 'LM:Arc->Bulge lst))
)
(entmake
(list
'(0 . "LWPOLYLINE")
'(100 . "AcDbEntity")
'(100 . "AcDbPolyline")
'(90 . 2)
'(70 . 0)
(cons 10 (car   lst))
)
)
)
(princ)
)

;; Arc to Bulge  -  Lee Mac 2011
;; cen  - Centre
;; ang1 - Start Angle
;; ang2 - End Angle
;; Returns: (<vertex> <vertex> <bulge>)

(defun LM:Arc->Bulge ( cen ang1 ang2 rad )
(list