Crate togo

Crate togo 

Expand description

Basic 2D geometric operations.

This library provides core 2D geometric primitives and operations including:

  • Primitives: Points, Segments, Circles, Arcs, Polylines, Intervals
  • Distance Calculations: Between points, segments, circles, and arcs
  • Intersection Detection: Line-line, circle-circle, arc-arc, and mixed geometric types
  • Geometric Algorithms: Convex hull, area calculation, bounding shapes

Important: All arcs in this library are CCW (counter-clockwise) oriented.

§Examples

§Distance and intersection calculations

use togo::prelude::*;

// Create primitives
let p = point(10.0, 0.0);
let c = circle(point(0.0, 0.0), 5.0);
let seg = segment(point(0.0, 0.0), point(5.0, 0.0));
let a1 = arc(point(1.0, 0.0), point(0.0, 1.0), point(0.0, 0.0), 1.0);

// Compute distances
let (dist_to_circle, _, _) = dist_point_circle(&p, &c);
assert_eq!(dist_to_circle, 5.0);

let (dist_to_segment, _) = dist_point_segment(&point(5.0, 5.0), &seg);
assert_eq!(dist_to_segment, 5.0);

// Distance between arcs
let a2 = arc(point(4.0, 0.0), point(2.0, 0.0), point(3.0, 0.0), 1.0);
let dist = dist_arc_arc(&a1, &a2);
assert!(dist > 0.0);

§Intersection tests

use togo::prelude::*;

// Segment intersection
let seg1 = segment(point(0.0, 0.0), point(2.0, 2.0));
let seg2 = segment(point(0.0, 2.0), point(2.0, 0.0));
match int_segment_segment(&seg1, &seg2) {
    SegmentSegmentConfig::OnePoint(pt, ..) => {
        assert!(point(1.0, 1.0).close_enough(pt, 1e-10));
    },
    _ => assert!(false, "Expected segment intersection"),
}

// Circle intersection
let c1 = circle(point(0.0, 0.0), 3.0);
let c2 = circle(point(4.0, 0.0), 3.0);
match int_circle_circle(c1, c2) {
    CircleCircleConfig::NoncocircularTwoPoints(_, _) => {
        assert!(true); // Two points found
    },
    _ => assert!(false, "Expected two intersection points"),
}

§Geometric algorithms

use togo::prelude::*;
use togo::algo::{pointline_area, points_convex_hull, arc_bounding_circle};

// Polygon area
let triangle = vec![
    point(0.0, 0.0),
    point(4.0, 0.0),
    point(2.0, 3.0),
    point(0.0, 0.0),
];
let area = pointline_area(&triangle);
assert_eq!(area, 6.0);

// Convex hull computation
let points = vec![
    point(0.0, 0.0), point(2.0, 1.0), point(1.0, 2.0),
    point(3.0, 0.0), point(2.0, 3.0), point(0.0, 2.0),
];
let hull = points_convex_hull(&points);
assert_eq!(hull.len(), 4); // 4 points on convex hull

// Bounding shape for an arc
let quarter_arc = arc(point(1.0, 0.0), point(0.0, 1.0), point(0.0, 0.0), 1.0);
let bounding = arc_bounding_circle(&quarter_arc);
assert_eq!(bounding.r, 0.7071067811865476); // sqrt(2)/2

§Distance computations

use togo::prelude::*;
    let l = line(point(0.0, 3.0), point(1.0, 0.0)); // Line with point and direction
    let c = circle(point(0.0, 0.0), 2.0);
    let result = dist_line_circle(&l, &c);
    match result {
        DistLineCircleConfig::OnePair(dist, _param, _line_pt, _circle_pt) => {
            assert_eq!(1.0, dist);
        }
        _ => assert!(false),
    }

    // Distance from point to arc
    let p = point(2.0, 0.0);
    let a = arc(point(0.0, 1.0), point(1.0, 0.0), point(0.0, 0.0), 1.0);
    match dist_point_arc(&p, &a) {
        DistPointArcConfig::OnePoint(dist, _) => {
            assert_eq!(1.0, dist);
        }
        _ => assert!(false),
    }

    // Distance from segment to arc
    let seg = segment(point(3.0, 0.0), point(4.0, 0.0));
    let a = arc(point(0.0, 1.0), point(1.0, 0.0), point(0.0, 0.0), 1.0);
    let dist = dist_segment_arc(&seg, &a);
    assert_eq!(2.0, dist);
use togo::prelude::*;
    // Distance from segment to circle
    let seg = segment(point(3.0, 0.0), point(4.0, 0.0));
    let c = circle(point(0.0, 0.0), 1.0);
    let result = dist_segment_circle(&seg, &c);
    // Function returns DistSegmentCircleConfig enum
    match result {
        DistSegmentCircleConfig::OnePoint(dist, closest) => {
            assert_eq!(2.0, dist); // Distance should be non-negative
        }
        _ => assert!(false),
    }

    // Distance between two segments
    let seg1 = segment(point(0.0, 0.0), point(1.0, 0.0));
    let seg2 = segment(point(0.0, 2.0), point(1.0, 2.0));
    let dist = dist_segment_segment(&seg1, &seg2);
    assert_eq!(dist, 2.0); // Parallel segments 2 units apart

§Intersection computations

use togo::prelude::*;

// Interval-interval intersection
let iv1 = interval(1.0, 5.0);
let iv2 = interval(3.0, 7.0);
let result = int_interval_interval(iv1, iv2);
match result {
    IntervalConfig::Overlap(start, end) => {
        // Intervals overlap from 3.0 to 5.0
        assert_eq!(start, 3.0);
        assert_eq!(end, 5.0);
    },
    _ => assert!(false),
}

// Line-line intersection
let l1 = line(point(0.0, 0.0), point(1.0, 0.0)); // Line with origin and direction
let l2 = line(point(0.0, 0.0), point(0.0, 1.0)); // Line with origin and direction
let result = int_line_line(&l1, &l2);
match result {
    LineLineConfig::OnePoint(pt, _param1, _param2) => {
        // Lines intersect at origin
        assert_eq!(point(0.0, 0.0), pt);
    },
    _ => assert!(false),
}

Modules§

algo
Algorithm module containing various geometric algorithms.
constants
Centralized epsilon and tolerance constants for numeric stability.
distance
Distance computation algorithms module.
intersection
Intersection algorithms module.
poly
Large polyline test data for benchmarking This module provides 1000-arc non-intersecting polylines
prelude