Python example: mrpt_math_example.py
Geometry primitives, polygons, histograms and matrices with mrpt.math.
Modules: mrpt.math
1#!/usr/bin/env python3
2"""
3Geometry primitives, polygons, histograms and matrices with mrpt.math.
4
5Demonstrates:
6 - TPoint2D / TPoint3D: 2D and 3D points
7 - TPose2D / TPose3D: 2D and 3D poses (position + orientation)
8 - TSegment2D / TSegment3D: line segments
9 - TLine2D / TLine3D: infinite lines
10 - TPlane: 3D plane
11 - TBoundingBox: axis-aligned bounding box
12 - TTwist2D / TTwist3D: velocity twists
13 - CPolygon: 2D polygon
14 - CHistogram: 1D histogram
15 - wrapToPi / wrapTo2Pi: angle normalisation
16 - CMatrixDouble / CVectorDouble: dynamic matrices (bridge to numpy)
17"""
18
19import math, numpy as np
20from mrpt.math import (
21 TPoint2D, TPoint3D,
22 TPose2D, TPose3D,
23 TSegment2D, TSegment3D,
24 TLine2D, TLine3D,
25 TPlane,
26 TBoundingBox,
27 TTwist2D, TTwist3D,
28 CPolygon,
29 CHistogram,
30 wrapToPi, wrapTo2Pi,
31 CMatrixDouble, CVectorDouble,
32)
33
34# ---------------------------------------------------------------------------
35# Points and poses
36# ---------------------------------------------------------------------------
37p2 = TPoint2D(1.0, 2.0)
38p3 = TPoint3D(1.0, 2.0, 3.0)
39print(f"TPoint2D: {p2}")
40print(f"TPoint3D: {p3}")
41assert p2.x == 1.0 and p2.y == 2.0
42assert p3.z == 3.0
43
44pose2 = TPose2D(1.0, 0.5, math.pi / 4)
45pose3 = TPose3D(1.0, 2.0, 0.5, 0.1, 0.2, 0.3)
46print(f"\nTPose2D: {pose2}")
47print(f"TPose3D: {pose3}")
48
49# ---------------------------------------------------------------------------
50# Segment distance
51# ---------------------------------------------------------------------------
52seg = TSegment2D(TPoint2D(0, 0), TPoint2D(4, 0))
53dist = seg.distance(TPoint2D(2, 3))
54print(f"\nTSegment2D distance to (2,3): {dist:.4f}") # should be 3
55assert abs(dist - 3.0) < 1e-6
56
57# ---------------------------------------------------------------------------
58# Line from two points
59# ---------------------------------------------------------------------------
60line = TLine2D(TPoint2D(0, 0), TPoint2D(1, 1))
61print(f"\nTLine2D: {line}")
62d = line.distance(TPoint2D(1, 0))
63print(f" distance to (1,0): {d:.4f}") # sqrt(2)/2 ≈ 0.7071
64assert abs(d - math.sqrt(2) / 2) < 1e-6
65
66# ---------------------------------------------------------------------------
67# Plane
68# ---------------------------------------------------------------------------
69plane = TPlane(TPoint3D(0,0,0), TPoint3D(1,0,0), TPoint3D(0,1,0)) # XY plane
70print(f"\nTPlane (XY plane): {plane}")
71d3 = plane.distance(TPoint3D(0, 0, 5))
72print(f" distance to (0,0,5): {d3:.4f}") # should be 5
73assert abs(d3 - 5.0) < 1e-6
74
75# ---------------------------------------------------------------------------
76# BoundingBox
77# ---------------------------------------------------------------------------
78bb = TBoundingBox(TPoint3D(-1,-1,-1), TPoint3D(1,1,1))
79print(f"\nTBoundingBox: {bb}")
80ctr_x = (bb.min.x + bb.max.x) / 2
81ctr_y = (bb.min.y + bb.max.y) / 2
82ctr_z = (bb.min.z + bb.max.z) / 2
83print(f" center: ({ctr_x},{ctr_y},{ctr_z})")
84assert ctr_x == 0.0 and ctr_y == 0.0
85
86# ---------------------------------------------------------------------------
87# Twists
88# ---------------------------------------------------------------------------
89tw2 = TTwist2D(1.0, 0.0, 0.1) # vx, vy, omega
90tw3 = TTwist3D(1.0, 0.0, 0.0, 0.0, 0.0, 0.1)
91print(f"\nTTwist2D: {tw2}")
92print(f"TTwist3D: {tw3}")
93
94# ---------------------------------------------------------------------------
95# CPolygon
96# ---------------------------------------------------------------------------
97poly = CPolygon()
98poly.add_vertex(0, 0)
99poly.add_vertex(1, 0)
100poly.add_vertex(1, 1)
101poly.add_vertex(0, 1)
102print(f"\nCPolygon: {len(poly)} vertices")
103assert len(poly) == 4
104
105# ---------------------------------------------------------------------------
106# CHistogram
107# ---------------------------------------------------------------------------
108hist = CHistogram(0.0, 10.0, 10) # [0,10], 10 bins
109for v in [1.5, 2.5, 2.5, 7.0]:
110 hist.add(v)
111bins, counts = hist.getHistogramNormalized()
112n_bins = len(counts) # getBinCount(i) returns count for bin i, not total bins
113print(f"\nCHistogram ({n_bins} bins): {counts}")
114assert n_bins == 10
115
116# ---------------------------------------------------------------------------
117# Angle wrapping
118# ---------------------------------------------------------------------------
119print(f"\nwrapToPi(3π/2) = {wrapToPi(3*math.pi/2):.4f} (expect ~-1.5708)")
120print(f"wrapTo2Pi(-π/4) = {wrapTo2Pi(-math.pi/4):.4f} (expect ~4.7124)")
121assert abs(wrapToPi(3*math.pi/2) - (-math.pi/2)) < 1e-9
122assert abs(wrapTo2Pi(-math.pi/4) - (7*math.pi/4)) < 1e-9
123print(" wrap checks ✓")
124
125# ---------------------------------------------------------------------------
126# CMatrixDouble — numpy bridge (minimal API)
127# ---------------------------------------------------------------------------
128m = CMatrixDouble(3, 3)
129print(f"\nCMatrixDouble(3,3): {m}")
130arr = np.array([[1.0, 2.0], [3.0, 4.0]])
131m2 = CMatrixDouble(arr) # construct from numpy
132np_out = m2.as_numpy()
133print(f" CMatrixDouble from numpy, back to numpy: {np_out}")
134np.testing.assert_allclose(np_out, arr)
135print(" matrix numpy bridge ✓")