Center and radius of a circle passing through 3 points in a plane

⚓ Rust    📅 2025-08-19    👤 surdeus    👁️ 5      

surdeus

Hi,
I'm a Rust beginner and as a first exercise I chose Centre and radius of a circle passing through 3 points in a plane - Rosetta Code. There is no Rust version available and maybe I could contribute to one.
Kind regards, Pascal

// Version
//
// V 0.1.3 2025-08-19 Code coverage check with cargo-llvm-cov (note: unclear how to ignore functions and modules)
// V 0.1.2 2025-08-18 check for float overflow when coordinate values are squared;
//                    visibility of parent module from as seen from module tests
// V 0.1.1 2025-08-17 use of Result in fn circle_through_3_points_2_d(..)
// V 0.1.0 2025-08-17 sketch with two tests that pass
//
// Write a function which returns the centre and radius of a circle passing through three points in a plane.
// Demonstrate the function using the points (22.83,2.07) (14.39,30.24) and (33.65,17.31)
// (from https://rosettacode.org/wiki/Centre_and_radius_of_a_circle_passing_through_3_points_in_a_plane# 2025-08-13)

use core::f64;
use std::f64::MAX;
use num::complex::{Complex, ComplexFloat};

struct Circle {
    // wondering why it is not possible to nest structures. I would have preferred to define a Circle from its
    // center (a Point) and radius.
    center_x: f64,
    center_y: f64,
    radius: f64
}

fn circle_through_3_points_2_d(p1x: f64, p1y: f64, p2x: f64, p2y: f64, p3x: f64, p3y: f64) -> Result<Circle, String> {
    // following https://math.stackexchange.com/questions/213658/get-the-equation-of-a-circle-when-given-3-points
    // following https://web.archive.org/web/20060909065617/http://www.math.okstate.edu/~wrightd/INDRA/MobiusonCircles/node4.html

    // interpret the three points (p1,p2,p3) as being in the complex plane (z1,z2,z3) and 
    // map the two points z1 and z2 to 0 and to 1 in C with z -> (z - z1) / (z2 - z1).
    // This maps p1 to z1=0, p2 to z2=1, p3 to z3.
    // >> would execution time bei smaller when avoiding complex numbers?
    let z1 = num::complex::Complex::new(p1x, p1y);
    let z2 = num::complex::Complex::new(p2x, p2y);
    let z3: Complex<f64> = num::complex::Complex::new(p3x, p3y);

    // check for identity of two points
    if (z1 == z2) || (z2 == z3) || (z3 == z1) {
        // these are not three distinct vertices of a triangle
        // assumptions are not met: refuse computation
        return Err("at least two of three points are identical".to_string())
    }

    // check for overflow: squares will be computed later, make sure this doesn't cause an overflow 
    if 
    z1.re().abs() > MAX.sqrt() || z1.im().abs() > MAX.sqrt() || 
    z2.re().abs() > MAX.sqrt() || z2.im().abs() > MAX.sqrt() || 
    z3.re().abs() > MAX.sqrt()|| z3.im().abs() > MAX.sqrt() {
        return Err("at least one coordinat > MAX.sqrt()".to_string())
    }  

    // now we transform in the complex plane zi -> zti such that
    // zt1 = 0, zt2 = 1, zt3 = to be computed
    let zt3: Complex<f64> = (z3 - z1) / (z2 - z1);

    // check for colinearity
    if zt3.im == 0.0 { 
        return Err("three points are colinear".to_string())
    }

    // the transformed center of the circle is on the line x=0.5, all y except y=0.0. 
    // Determine its specific position
    let ct: Complex<f64> = (zt3 - zt3 * zt3.conj()) / (zt3 - zt3.conj());
    let c: Complex<f64> = (z2-z1) * ct + z1;
    let r: f64 = (z1-c).norm();

    let c = Circle { center_x: c.re, center_y: c.im, radius: r };
    return Ok(c)
}

fn main() {
    let result = circle_through_3_points_2_d(22.83, 2.07, 14.39, 30.24, 33.65, 17.31);
    match result {
        Ok(circle) => {
            println!("circle.center_x={}", circle.center_x); 
            println!("circle.center_y={}", circle.center_y); 
            println!("circle.radius={}", circle.radius);
        }
        Err(e) => println!("{}",e)
    }
}

3 posts - 3 participants

Read full topic

🏷️ Rust_feed