Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
Solve equation system to get the center and radius solution in 3rd party category for Three Points Circle by borosdani
def checkio(data):
'''
The input 3 point coordinates defines a triangle.
The fuction shall return the coordinate of the center and the radius of a circle.
The circle is a circle around the triangle.
'''
# Example output: "(x-x0)^2+(y-y0)^2=r^2"
import numpy as np
from math import sqrt
# get the distance between 2 point
def distance(x1, y1, x2, y2):
# Pythagorean theorem
dx = x2 - x1
dy = y2 - y1
return sqrt(dx ** 2 + dy ** 2)
# get info from data
pattern = r"(\d,\d)"
import re
points_str = re.findall(pattern, data)
points = []
for p in points_str:
x, y = p.split(",")
points.append([float(x), float(y)])
# set triangle's point coordinates
x1, y1 = points[0]
x2, y2 = points[1]
x3, y3 = points[2]
def get_center_coord(x1, y1, x2, y2, x3, y3):
"""
The solution comes from solving the following equation system:
(x1 - x0)**2 + (y1 - y0)**2 == r**2
(x2 - x0)**2 + (y2 - y0)**2 == r**2
(x3 - x0)**2 + (y3 - y0)**2 == r**2
It can be converted to a linear system
2 * (x2 - x1) * x0 + 2 * (y2 - y1) * y0 = x2 ** 2 - x1 ** 2 + y2 ** 2 - y1 ** 2
2 * (x3 - x1) * x0 + 2 * (y3 - y1) * y0 = x3 ** 2 - x1 ** 2 + y3 ** 2 - y1 ** 2
regular form: a * [x0, y0] = b
use numpy package
"""
# set the linear system
a = np.array([[2 * (x2 - x1), 2 * (y2 - y1)], [2 * (x3 - x1), 2 * (y3 - y1)]])
b = np.array([x2 ** 2 - x1 ** 2 + y2 ** 2 - y1 ** 2, x3 ** 2 - x1 ** 2 + y3 ** 2 - y1 ** 2])
x0, y0 = np.linalg.solve(a, b)
return x0, y0
# get circle center coordinate
x0, y0 = get_center_coord(x1, y1, x2, y2, x3, y3)
# get radius
r = distance(x0, y0, x1, y1)
# the following function is from:
# https://kfolds.com/rounding-in-python-when-arithmetic-isnt-quite-right-11a79a30390a
def round_decimal(x, digits = 0):
import decimal
#casting to string then converting to decimal
x = decimal.Decimal(str(x))
#rounding for integers
if digits == 0:
return int(x.quantize(decimal.Decimal("1"), rounding='ROUND_HALF_UP'))
#string in scientific notation for significant digits: 1e^x
if digits > 1:
string = '1e' + str(-1*digits)
else:
string = '1e' + str(-1*digits)
#rounding for floating points
return float(x.quantize(decimal.Decimal(string), rounding='ROUND_HALF_UP'))
# round coordinates and radius right (in case of r = 2.635 round returns 2.64 which is not ok)
x0 = round_decimal(x0, 2)
y0 = round_decimal(y0, 2)
r = round_decimal(r, 2)
# Check if parameters are integer then convert to int
if x0.is_integer():
x0 = int(x0)
if y0.is_integer():
y0 = int(y0)
if r.is_integer():
r = int(r)
# return a string in a required form
return "(x-" + str(x0) + ")^2+(y-" + str(y0) + ")^2=" + str(r) + "^2"
#These "asserts" using only for self-checking and not necessary for auto-testing
if __name__ == '__main__':
assert checkio("(2,2),(6,2),(2,6)") == "(x-4)^2+(y-4)^2=2.83^2"
assert checkio("(3,7),(6,9),(9,7)") == "(x-6)^2+(y-5.75)^2=3.25^2"
Aug. 22, 2018