geompp 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geompp-0.1.1/CMakeLists.txt +136 -0
- geompp-0.1.1/PKG-INFO +126 -0
- geompp-0.1.1/README.md +105 -0
- geompp-0.1.1/geompp/__init__.py +91 -0
- geompp-0.1.1/pyproject.toml +66 -0
- geompp-0.1.1/src/bind_bbox2d.cpp +17 -0
- geompp-0.1.1/src/bind_bbox3d.cpp +13 -0
- geompp-0.1.1/src/bind_free_functions.cpp +57 -0
- geompp-0.1.1/src/bind_helpers.hpp +69 -0
- geompp-0.1.1/src/bind_line2d.cpp +44 -0
- geompp-0.1.1/src/bind_line3d.cpp +36 -0
- geompp-0.1.1/src/bind_line_segment2d.cpp +31 -0
- geompp-0.1.1/src/bind_line_segment3d.cpp +31 -0
- geompp-0.1.1/src/bind_lvsparser.cpp +30 -0
- geompp-0.1.1/src/bind_plane.cpp +29 -0
- geompp-0.1.1/src/bind_point2d.cpp +20 -0
- geompp-0.1.1/src/bind_point3d.cpp +21 -0
- geompp-0.1.1/src/bind_polygon2d.cpp +25 -0
- geompp-0.1.1/src/bind_polygon3d.cpp +25 -0
- geompp-0.1.1/src/bind_polyline2d.cpp +41 -0
- geompp-0.1.1/src/bind_polyline3d.cpp +41 -0
- geompp-0.1.1/src/bind_precision.cpp +15 -0
- geompp-0.1.1/src/bind_ray2d.cpp +30 -0
- geompp-0.1.1/src/bind_ray3d.cpp +30 -0
- geompp-0.1.1/src/bind_triangle2d.cpp +41 -0
- geompp-0.1.1/src/bind_triangle3d.cpp +38 -0
- geompp-0.1.1/src/bind_vector2d.cpp +28 -0
- geompp-0.1.1/src/bind_vector3d.cpp +31 -0
- geompp-0.1.1/src/bindings.cpp +53 -0
- geompp-0.1.1/tests/__init__.py +0 -0
- geompp-0.1.1/tests/test_geompp.py +679 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.15)
|
|
2
|
+
project(geompp_python LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
|
|
7
|
+
set(GEOMPP_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../geompp")
|
|
8
|
+
|
|
9
|
+
# ─── pybind11 ────────────────────────────────────────────────────────────────
|
|
10
|
+
# Prefer an installed copy; fall back to FetchContent.
|
|
11
|
+
find_package(pybind11 2.11 CONFIG QUIET)
|
|
12
|
+
if(NOT pybind11_FOUND)
|
|
13
|
+
message(STATUS "pybind11 not found, fetching via FetchContent...")
|
|
14
|
+
include(FetchContent)
|
|
15
|
+
FetchContent_Declare(
|
|
16
|
+
pybind11
|
|
17
|
+
URL https://github.com/pybind/pybind11/archive/refs/tags/v2.13.6.zip
|
|
18
|
+
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
|
19
|
+
)
|
|
20
|
+
FetchContent_MakeAvailable(pybind11)
|
|
21
|
+
endif()
|
|
22
|
+
|
|
23
|
+
# ─── geompp sources (only needed in standalone / pip-install mode) ────────────
|
|
24
|
+
set(GEOMPP_SOURCES
|
|
25
|
+
${GEOMPP_ROOT}/src/constants.cpp
|
|
26
|
+
${GEOMPP_ROOT}/src/geompp_log.cpp
|
|
27
|
+
${GEOMPP_ROOT}/src/utils.cpp
|
|
28
|
+
${GEOMPP_ROOT}/src/lsv_parser.cpp
|
|
29
|
+
${GEOMPP_ROOT}/src/point2d.cpp
|
|
30
|
+
${GEOMPP_ROOT}/src/vector2d.cpp
|
|
31
|
+
${GEOMPP_ROOT}/src/line2d.cpp
|
|
32
|
+
${GEOMPP_ROOT}/src/ray2d.cpp
|
|
33
|
+
${GEOMPP_ROOT}/src/line_segment2d.cpp
|
|
34
|
+
${GEOMPP_ROOT}/src/polyline2d.cpp
|
|
35
|
+
${GEOMPP_ROOT}/src/triangle2d.cpp
|
|
36
|
+
${GEOMPP_ROOT}/src/polygon2d.cpp
|
|
37
|
+
${GEOMPP_ROOT}/src/bbox2d.cpp
|
|
38
|
+
${GEOMPP_ROOT}/src/point3d.cpp
|
|
39
|
+
${GEOMPP_ROOT}/src/vector3d.cpp
|
|
40
|
+
${GEOMPP_ROOT}/src/line3d.cpp
|
|
41
|
+
${GEOMPP_ROOT}/src/line_segment3d.cpp
|
|
42
|
+
${GEOMPP_ROOT}/src/polyline3d.cpp
|
|
43
|
+
${GEOMPP_ROOT}/src/ray3d.cpp
|
|
44
|
+
${GEOMPP_ROOT}/src/plane.cpp
|
|
45
|
+
${GEOMPP_ROOT}/src/triangle3d.cpp
|
|
46
|
+
${GEOMPP_ROOT}/src/polygon3d.cpp
|
|
47
|
+
${GEOMPP_ROOT}/src/bbox3d.cpp
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# ─── Binding sources (one file per class) ─────────────────────────────────────
|
|
51
|
+
set(BINDING_SOURCES
|
|
52
|
+
src/bindings.cpp
|
|
53
|
+
src/bind_precision.cpp
|
|
54
|
+
src/bind_point2d.cpp
|
|
55
|
+
src/bind_point3d.cpp
|
|
56
|
+
src/bind_vector2d.cpp
|
|
57
|
+
src/bind_vector3d.cpp
|
|
58
|
+
src/bind_line_segment2d.cpp
|
|
59
|
+
src/bind_line_segment3d.cpp
|
|
60
|
+
src/bind_line2d.cpp
|
|
61
|
+
src/bind_line3d.cpp
|
|
62
|
+
src/bind_ray2d.cpp
|
|
63
|
+
src/bind_ray3d.cpp
|
|
64
|
+
src/bind_polygon2d.cpp
|
|
65
|
+
src/bind_polygon3d.cpp
|
|
66
|
+
src/bind_polyline2d.cpp
|
|
67
|
+
src/bind_polyline3d.cpp
|
|
68
|
+
src/bind_triangle2d.cpp
|
|
69
|
+
src/bind_triangle3d.cpp
|
|
70
|
+
src/bind_bbox2d.cpp
|
|
71
|
+
src/bind_bbox3d.cpp
|
|
72
|
+
src/bind_plane.cpp
|
|
73
|
+
src/bind_lvsparser.cpp
|
|
74
|
+
src/bind_free_functions.cpp
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# ─── Python extension module ─────────────────────────────────────────────────
|
|
78
|
+
# Two modes:
|
|
79
|
+
#
|
|
80
|
+
# • Parent-CMake mode (-DBUILD_PYTHON=ON from root):
|
|
81
|
+
# The `geompp` static-library target already exists. Link against it so
|
|
82
|
+
# we don't recompile 23 source files and glog a second time.
|
|
83
|
+
#
|
|
84
|
+
# • Standalone mode (pip install ./geompp_python):
|
|
85
|
+
# No parent target. Compile geompp sources directly into the extension
|
|
86
|
+
# and fetch glog ourselves.
|
|
87
|
+
#
|
|
88
|
+
if(TARGET geompp)
|
|
89
|
+
# ── parent mode ──────────────────────────────────────────────────────────
|
|
90
|
+
message(STATUS "geompp_python: linking against existing `geompp` target")
|
|
91
|
+
|
|
92
|
+
pybind11_add_module(_geompp NO_EXTRAS ${BINDING_SOURCES})
|
|
93
|
+
target_include_directories(_geompp PRIVATE ${GEOMPP_ROOT}/include src)
|
|
94
|
+
# glog is transitively pulled in through geompp's PUBLIC link deps
|
|
95
|
+
target_link_libraries(_geompp PRIVATE geompp)
|
|
96
|
+
|
|
97
|
+
else()
|
|
98
|
+
# ── standalone mode ───────────────────────────────────────────────────────
|
|
99
|
+
message(STATUS "geompp_python: standalone build — compiling geompp sources into extension")
|
|
100
|
+
|
|
101
|
+
if(NOT TARGET glog::glog)
|
|
102
|
+
include(FetchContent)
|
|
103
|
+
FetchContent_Declare(
|
|
104
|
+
glog
|
|
105
|
+
URL https://github.com/google/glog/archive/refs/tags/v0.7.1.zip
|
|
106
|
+
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
|
107
|
+
)
|
|
108
|
+
set(WITH_GFLAGS OFF CACHE BOOL "" FORCE)
|
|
109
|
+
set(WITH_GTEST OFF CACHE BOOL "" FORCE)
|
|
110
|
+
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
|
111
|
+
FetchContent_MakeAvailable(glog)
|
|
112
|
+
endif()
|
|
113
|
+
|
|
114
|
+
pybind11_add_module(_geompp NO_EXTRAS ${BINDING_SOURCES} ${GEOMPP_SOURCES})
|
|
115
|
+
target_include_directories(_geompp PRIVATE ${GEOMPP_ROOT}/include src)
|
|
116
|
+
target_link_libraries(_geompp PRIVATE glog::glog)
|
|
117
|
+
|
|
118
|
+
endif()
|
|
119
|
+
|
|
120
|
+
# Windows: suppress min/max macros from <windows.h>
|
|
121
|
+
if(WIN32)
|
|
122
|
+
target_compile_definitions(_geompp PRIVATE NOMINMAX WIN32_LEAN_AND_MEAN)
|
|
123
|
+
endif()
|
|
124
|
+
|
|
125
|
+
# ─── Post-build: copy extension into package directory ───────────────────────
|
|
126
|
+
add_custom_command(TARGET _geompp POST_BUILD
|
|
127
|
+
COMMAND ${CMAKE_COMMAND} -E copy
|
|
128
|
+
$<TARGET_FILE:_geompp>
|
|
129
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/geompp/$<TARGET_FILE_NAME:_geompp>"
|
|
130
|
+
COMMENT "Copying _geompp into geompp_python/geompp/"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# ─── Install ─────────────────────────────────────────────────────────────────
|
|
134
|
+
# pip/scikit-build-core: installs _geompp.so|pyd into the `geompp` package dir.
|
|
135
|
+
# Root-CMake: installs alongside the rest of the project if `cmake --install` is run.
|
|
136
|
+
install(TARGETS _geompp DESTINATION geompp)
|
geompp-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: geompp
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Python bindings for geompp — a C++ 2D/3D geometry library
|
|
5
|
+
Keywords: geometry,2d,3d,math,computational-geometry,cad
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: C++
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Project-URL: Homepage, https://github.com/amastrobera/geompp
|
|
16
|
+
Project-URL: Repository, https://github.com/amastrobera/geompp
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
[← back](../README.md)
|
|
23
|
+
|
|
24
|
+
# geompp
|
|
25
|
+
|
|
26
|
+
Python bindings for [geompp](https://github.com/amastrobera/geompp) — a C++ 2D/3D geometry library.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install geompp
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Pre-built wheels are available for:
|
|
35
|
+
|
|
36
|
+
| Platform | Python versions |
|
|
37
|
+
|---|---|
|
|
38
|
+
| Linux x86_64 | 3.8 · 3.9 · 3.10 · 3.11 · 3.12 |
|
|
39
|
+
| Windows x64 | 3.8 · 3.9 · 3.10 · 3.11 · 3.12 |
|
|
40
|
+
|
|
41
|
+
If your platform or Python version is not in the table above, pip will compile
|
|
42
|
+
from source — you will need CMake ≥ 3.15 and a C++20-capable compiler.
|
|
43
|
+
|
|
44
|
+
## Quick start
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
import geompp
|
|
48
|
+
|
|
49
|
+
# Points & vectors
|
|
50
|
+
p = geompp.Point2D(1.0, 2.0)
|
|
51
|
+
v = geompp.Vector2D(3.0, 0.0)
|
|
52
|
+
q = p + v # Point2D(4, 2)
|
|
53
|
+
diff = q - p # Vector2D(3, 0)
|
|
54
|
+
|
|
55
|
+
# Lines and intersection
|
|
56
|
+
l1 = geompp.Line2D.make(geompp.Point2D(0,0), geompp.Point2D(1,0))
|
|
57
|
+
l2 = geompp.Line2D.make(geompp.Point2D(0.5,-1), geompp.Point2D(0.5,1))
|
|
58
|
+
hit = l1.intersection(l2) # Point2D(0.5, 0) or None
|
|
59
|
+
|
|
60
|
+
# 3D
|
|
61
|
+
p3 = geompp.Point3D(1, 2, 3)
|
|
62
|
+
plane = geompp.Plane.xy()
|
|
63
|
+
proj = plane.project_onto(p3) # Point3D(1, 2, 0)
|
|
64
|
+
|
|
65
|
+
# Precision
|
|
66
|
+
geompp.set_decimal_precision(geompp.DP_SIX)
|
|
67
|
+
|
|
68
|
+
# File parser
|
|
69
|
+
parser = geompp.LVSParser.open("geometry.lsv")
|
|
70
|
+
while parser.has_next():
|
|
71
|
+
item = parser.next()
|
|
72
|
+
if item is not None:
|
|
73
|
+
print(geompp.LVSParser.to_wkt(item))
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Classes
|
|
77
|
+
|
|
78
|
+
| 2D | 3D |
|
|
79
|
+
|----|----|
|
|
80
|
+
| Point2D | Point3D |
|
|
81
|
+
| Vector2D | Vector3D |
|
|
82
|
+
| Line2D | Line3D |
|
|
83
|
+
| Ray2D | Ray3D |
|
|
84
|
+
| LineSegment2D | LineSegment3D |
|
|
85
|
+
| Polyline2D | Polyline3D |
|
|
86
|
+
| Triangle2D | Triangle3D |
|
|
87
|
+
| Polygon2D | Polygon3D |
|
|
88
|
+
| BBox2D | BBox3D |
|
|
89
|
+
| | Plane |
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## Build the python bindings from source
|
|
93
|
+
|
|
94
|
+
### Linux
|
|
95
|
+
|
|
96
|
+
Build
|
|
97
|
+
```
|
|
98
|
+
mkdir build && cd build
|
|
99
|
+
cmake .. [-DCMAKE_BUILD_TYPE=Release] [-DBUILD_PYTHON=ON]
|
|
100
|
+
make -j6
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The `-DBUILD_PYTHON=ON` will build locally the python bindings and run the smoke tests immediately.
|
|
104
|
+
|
|
105
|
+
To try out the library after building it use this
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# from the main directory geompp
|
|
109
|
+
pip3 install --break-system-packages ./geompp_python
|
|
110
|
+
python3 -c "import geompp as g; print(g.Point3D(1,2,3).to_wkt())"
|
|
111
|
+
# should print POINT (1 2 3)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
### Windows
|
|
116
|
+
|
|
117
|
+
Build the library
|
|
118
|
+
```powershell
|
|
119
|
+
mkdir build_win
|
|
120
|
+
cd build_win
|
|
121
|
+
cmake -S .. -G "Visual Studio 18 2026" -A x64
|
|
122
|
+
cmake --build . --target geompp [--config Release] [-DBUILD_PYTHON=ON]
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The `-DBUILD_PYTHON=ON` will build locally the python bindings and run the smoke tests immediately.
|
|
126
|
+
|
geompp-0.1.1/README.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
[← back](../README.md)
|
|
2
|
+
|
|
3
|
+
# geompp
|
|
4
|
+
|
|
5
|
+
Python bindings for [geompp](https://github.com/amastrobera/geompp) — a C++ 2D/3D geometry library.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install geompp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Pre-built wheels are available for:
|
|
14
|
+
|
|
15
|
+
| Platform | Python versions |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Linux x86_64 | 3.8 · 3.9 · 3.10 · 3.11 · 3.12 |
|
|
18
|
+
| Windows x64 | 3.8 · 3.9 · 3.10 · 3.11 · 3.12 |
|
|
19
|
+
|
|
20
|
+
If your platform or Python version is not in the table above, pip will compile
|
|
21
|
+
from source — you will need CMake ≥ 3.15 and a C++20-capable compiler.
|
|
22
|
+
|
|
23
|
+
## Quick start
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
import geompp
|
|
27
|
+
|
|
28
|
+
# Points & vectors
|
|
29
|
+
p = geompp.Point2D(1.0, 2.0)
|
|
30
|
+
v = geompp.Vector2D(3.0, 0.0)
|
|
31
|
+
q = p + v # Point2D(4, 2)
|
|
32
|
+
diff = q - p # Vector2D(3, 0)
|
|
33
|
+
|
|
34
|
+
# Lines and intersection
|
|
35
|
+
l1 = geompp.Line2D.make(geompp.Point2D(0,0), geompp.Point2D(1,0))
|
|
36
|
+
l2 = geompp.Line2D.make(geompp.Point2D(0.5,-1), geompp.Point2D(0.5,1))
|
|
37
|
+
hit = l1.intersection(l2) # Point2D(0.5, 0) or None
|
|
38
|
+
|
|
39
|
+
# 3D
|
|
40
|
+
p3 = geompp.Point3D(1, 2, 3)
|
|
41
|
+
plane = geompp.Plane.xy()
|
|
42
|
+
proj = plane.project_onto(p3) # Point3D(1, 2, 0)
|
|
43
|
+
|
|
44
|
+
# Precision
|
|
45
|
+
geompp.set_decimal_precision(geompp.DP_SIX)
|
|
46
|
+
|
|
47
|
+
# File parser
|
|
48
|
+
parser = geompp.LVSParser.open("geometry.lsv")
|
|
49
|
+
while parser.has_next():
|
|
50
|
+
item = parser.next()
|
|
51
|
+
if item is not None:
|
|
52
|
+
print(geompp.LVSParser.to_wkt(item))
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Classes
|
|
56
|
+
|
|
57
|
+
| 2D | 3D |
|
|
58
|
+
|----|----|
|
|
59
|
+
| Point2D | Point3D |
|
|
60
|
+
| Vector2D | Vector3D |
|
|
61
|
+
| Line2D | Line3D |
|
|
62
|
+
| Ray2D | Ray3D |
|
|
63
|
+
| LineSegment2D | LineSegment3D |
|
|
64
|
+
| Polyline2D | Polyline3D |
|
|
65
|
+
| Triangle2D | Triangle3D |
|
|
66
|
+
| Polygon2D | Polygon3D |
|
|
67
|
+
| BBox2D | BBox3D |
|
|
68
|
+
| | Plane |
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## Build the python bindings from source
|
|
72
|
+
|
|
73
|
+
### Linux
|
|
74
|
+
|
|
75
|
+
Build
|
|
76
|
+
```
|
|
77
|
+
mkdir build && cd build
|
|
78
|
+
cmake .. [-DCMAKE_BUILD_TYPE=Release] [-DBUILD_PYTHON=ON]
|
|
79
|
+
make -j6
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The `-DBUILD_PYTHON=ON` will build locally the python bindings and run the smoke tests immediately.
|
|
83
|
+
|
|
84
|
+
To try out the library after building it use this
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# from the main directory geompp
|
|
88
|
+
pip3 install --break-system-packages ./geompp_python
|
|
89
|
+
python3 -c "import geompp as g; print(g.Point3D(1,2,3).to_wkt())"
|
|
90
|
+
# should print POINT (1 2 3)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
### Windows
|
|
95
|
+
|
|
96
|
+
Build the library
|
|
97
|
+
```powershell
|
|
98
|
+
mkdir build_win
|
|
99
|
+
cd build_win
|
|
100
|
+
cmake -S .. -G "Visual Studio 18 2026" -A x64
|
|
101
|
+
cmake --build . --target geompp [--config Release] [-DBUILD_PYTHON=ON]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The `-DBUILD_PYTHON=ON` will build locally the python bindings and run the smoke tests immediately.
|
|
105
|
+
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
geompp — Python bindings for the geompp C++ geometry library.
|
|
3
|
+
|
|
4
|
+
Classes
|
|
5
|
+
-------
|
|
6
|
+
2D primitives:
|
|
7
|
+
Point2D, Vector2D, Line2D, Ray2D, LineSegment2D,
|
|
8
|
+
Polyline2D, Triangle2D, Polygon2D, BBox2D
|
|
9
|
+
|
|
10
|
+
3D primitives:
|
|
11
|
+
Point3D, Vector3D, Line3D, Ray3D, LineSegment3D,
|
|
12
|
+
Polyline3D, Triangle3D, Polygon3D, BBox3D, Plane
|
|
13
|
+
|
|
14
|
+
Parser:
|
|
15
|
+
LVSParser
|
|
16
|
+
|
|
17
|
+
Free functions
|
|
18
|
+
--------------
|
|
19
|
+
are_collinear(p1, p2, p3)
|
|
20
|
+
remove_duplicates(points)
|
|
21
|
+
remove_duplicates_from_sorted_list(points)
|
|
22
|
+
remove_collinear(points)
|
|
23
|
+
linear_combination(points, weights)
|
|
24
|
+
average(points)
|
|
25
|
+
|
|
26
|
+
Precision
|
|
27
|
+
---------
|
|
28
|
+
set_decimal_precision(dp) # e.g. DP_THREE, DP_SIX, DP_NINE
|
|
29
|
+
get_decimal_precision() -> int
|
|
30
|
+
DP_THREE, DP_SIX, DP_NINE
|
|
31
|
+
|
|
32
|
+
Intersection return values
|
|
33
|
+
--------------------------
|
|
34
|
+
``intersection()`` methods return ``None`` when there is no intersection, or
|
|
35
|
+
the geometry object of the intersection otherwise. For polylines and triangles
|
|
36
|
+
the return can be a single point *or* a list of points / a segment / a polygon
|
|
37
|
+
depending on the geometry involved — use ``isinstance()`` to discriminate.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from ._geompp import ( # noqa: F401
|
|
41
|
+
# precision
|
|
42
|
+
DP_THREE,
|
|
43
|
+
DP_SIX,
|
|
44
|
+
DP_NINE,
|
|
45
|
+
set_decimal_precision,
|
|
46
|
+
get_decimal_precision,
|
|
47
|
+
# 2D
|
|
48
|
+
Point2D,
|
|
49
|
+
Vector2D,
|
|
50
|
+
Line2D,
|
|
51
|
+
Ray2D,
|
|
52
|
+
LineSegment2D,
|
|
53
|
+
Polyline2D,
|
|
54
|
+
Triangle2D,
|
|
55
|
+
Polygon2D,
|
|
56
|
+
BBox2D,
|
|
57
|
+
# 3D
|
|
58
|
+
Point3D,
|
|
59
|
+
Vector3D,
|
|
60
|
+
Line3D,
|
|
61
|
+
Ray3D,
|
|
62
|
+
LineSegment3D,
|
|
63
|
+
Polyline3D,
|
|
64
|
+
Triangle3D,
|
|
65
|
+
Polygon3D,
|
|
66
|
+
BBox3D,
|
|
67
|
+
Plane,
|
|
68
|
+
# parser
|
|
69
|
+
LVSParser,
|
|
70
|
+
# free functions
|
|
71
|
+
are_collinear,
|
|
72
|
+
remove_duplicates,
|
|
73
|
+
remove_duplicates_from_sorted_list,
|
|
74
|
+
remove_collinear,
|
|
75
|
+
linear_combination,
|
|
76
|
+
average,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
__version__ = "1.0.0"
|
|
80
|
+
|
|
81
|
+
__all__ = [
|
|
82
|
+
"DP_THREE", "DP_SIX", "DP_NINE",
|
|
83
|
+
"set_decimal_precision", "get_decimal_precision",
|
|
84
|
+
"Point2D", "Vector2D", "Line2D", "Ray2D", "LineSegment2D",
|
|
85
|
+
"Polyline2D", "Triangle2D", "Polygon2D", "BBox2D",
|
|
86
|
+
"Point3D", "Vector3D", "Line3D", "Ray3D", "LineSegment3D",
|
|
87
|
+
"Polyline3D", "Triangle3D", "Polygon3D", "BBox3D", "Plane",
|
|
88
|
+
"LVSParser",
|
|
89
|
+
"are_collinear", "remove_duplicates", "remove_duplicates_from_sorted_list",
|
|
90
|
+
"remove_collinear", "linear_combination", "average",
|
|
91
|
+
]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["scikit-build-core>=0.9", "pybind11>=2.11"]
|
|
3
|
+
build-backend = "scikit_build_core.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "geompp"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "Python bindings for geompp — a C++ 2D/3D geometry library"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
keywords = ["geometry", "2d", "3d", "math", "computational-geometry", "cad"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: C++",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: Microsoft :: Windows",
|
|
18
|
+
"Operating System :: POSIX :: Linux",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"Intended Audience :: Science/Research",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.optional-dependencies]
|
|
25
|
+
dev = ["pytest>=7"]
|
|
26
|
+
|
|
27
|
+
[tool.pytest.ini_options]
|
|
28
|
+
addopts = "--import-mode=importlib"
|
|
29
|
+
testpaths = ["tests"]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/amastrobera/geompp"
|
|
33
|
+
Repository = "https://github.com/amastrobera/geompp"
|
|
34
|
+
|
|
35
|
+
# ─── scikit-build-core configuration ─────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
[tool.scikit-build]
|
|
38
|
+
cmake.build-type = "Release"
|
|
39
|
+
|
|
40
|
+
# The Python package directory to include in the wheel
|
|
41
|
+
wheel.packages = ["geompp"]
|
|
42
|
+
|
|
43
|
+
# Include geompp C++ sources in the source distribution
|
|
44
|
+
sdist.include = [
|
|
45
|
+
"../geompp/include/**",
|
|
46
|
+
"../geompp/src/**",
|
|
47
|
+
"../geompp/CMakeLists.txt",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[tool.scikit-build.cmake.define]
|
|
51
|
+
# Silence glog's own tests/examples during build
|
|
52
|
+
WITH_GFLAGS = "OFF"
|
|
53
|
+
WITH_GTEST = "OFF"
|
|
54
|
+
BUILD_TESTING = "OFF"
|
|
55
|
+
|
|
56
|
+
# ─── cibuildwheel (optional, for CI wheel building) ──────────────────────────
|
|
57
|
+
[tool.cibuildwheel]
|
|
58
|
+
build = "cp38-* cp39-* cp310-* cp311-* cp312-*"
|
|
59
|
+
skip = "*-win32 *_i686 *-musllinux*"
|
|
60
|
+
|
|
61
|
+
[tool.cibuildwheel.windows]
|
|
62
|
+
archs = ["AMD64"]
|
|
63
|
+
|
|
64
|
+
[tool.cibuildwheel.linux]
|
|
65
|
+
archs = ["x86_64"]
|
|
66
|
+
manylinux-x86_64-image = "manylinux_2_28"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#include "bind_helpers.hpp"
|
|
2
|
+
|
|
3
|
+
void bind_bbox2d(py::module_& m) {
|
|
4
|
+
py::class_<geompp::BBox2D>(m, "BBox2D",
|
|
5
|
+
"2D axis-aligned bounding box.")
|
|
6
|
+
.def(py::init<const geompp::Point2D&, const geompp::Point2D&>(), "min"_a, "max"_a)
|
|
7
|
+
.def(py::init<const geompp::LineSegment2D&>(), "segment"_a)
|
|
8
|
+
.def(py::init<const geompp::Polyline2D&>(), "polyline"_a)
|
|
9
|
+
.def(py::init<const geompp::Polygon2D&>(), "polygon"_a)
|
|
10
|
+
.def(py::init<const geompp::Triangle2D&>(), "triangle"_a)
|
|
11
|
+
.def(py::init<const geompp::BBox2D&>())
|
|
12
|
+
.def_property_readonly("min", &geompp::BBox2D::min)
|
|
13
|
+
.def_property_readonly("max", &geompp::BBox2D::max)
|
|
14
|
+
.def("contains", &geompp::BBox2D::Contains, "point"_a)
|
|
15
|
+
BIND_ALMOST_EQUALS(BBox2D)
|
|
16
|
+
.def("__eq__", [](const geompp::BBox2D& a, const geompp::BBox2D& b) { return a == b; });
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#include "bind_helpers.hpp"
|
|
2
|
+
|
|
3
|
+
void bind_bbox3d(py::module_& m) {
|
|
4
|
+
py::class_<geompp::BBox3D>(m, "BBox3D",
|
|
5
|
+
"3D axis-aligned bounding box.")
|
|
6
|
+
.def(py::init<const geompp::Point3D&, const geompp::Point3D&>(), "min"_a, "max"_a)
|
|
7
|
+
.def(py::init<const geompp::BBox3D&>())
|
|
8
|
+
.def_property_readonly("min", &geompp::BBox3D::min)
|
|
9
|
+
.def_property_readonly("max", &geompp::BBox3D::max)
|
|
10
|
+
.def("contains", &geompp::BBox3D::Contains, "point"_a)
|
|
11
|
+
BIND_ALMOST_EQUALS(BBox3D)
|
|
12
|
+
.def("__eq__", [](const geompp::BBox3D& a, const geompp::BBox3D& b) { return a == b; });
|
|
13
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#include "bind_helpers.hpp"
|
|
2
|
+
|
|
3
|
+
void bind_free_functions(py::module_& m) {
|
|
4
|
+
m.def("are_collinear",
|
|
5
|
+
[](const geompp::Point2D& p1, const geompp::Point2D& p2, const geompp::Point2D& p3) {
|
|
6
|
+
return geompp::are_collinear(p1, p2, p3);
|
|
7
|
+
}, "p1"_a, "p2"_a, "p3"_a, "True if three 2D points are collinear.");
|
|
8
|
+
|
|
9
|
+
m.def("are_collinear",
|
|
10
|
+
[](const geompp::Point3D& p1, const geompp::Point3D& p2, const geompp::Point3D& p3) {
|
|
11
|
+
return geompp::are_collinear(p1, p2, p3);
|
|
12
|
+
}, "p1"_a, "p2"_a, "p3"_a, "True if three 3D points are collinear.");
|
|
13
|
+
|
|
14
|
+
m.def("remove_duplicates_from_sorted_list",
|
|
15
|
+
[](const std::vector<geompp::Point2D>& pts) {
|
|
16
|
+
return geompp::remove_duplicates_from_sorted_list(pts);
|
|
17
|
+
}, "points"_a, "Remove consecutive duplicate 2D points.");
|
|
18
|
+
|
|
19
|
+
m.def("remove_duplicates_from_sorted_list",
|
|
20
|
+
[](const std::vector<geompp::Point3D>& pts) {
|
|
21
|
+
return geompp::remove_duplicates_from_sorted_list(pts);
|
|
22
|
+
}, "points"_a, "Remove consecutive duplicate 3D points.");
|
|
23
|
+
|
|
24
|
+
m.def("remove_duplicates",
|
|
25
|
+
[](const std::vector<geompp::Point2D>& pts) { return geompp::remove_duplicates(pts); },
|
|
26
|
+
"points"_a, "Remove all duplicate 2D points.");
|
|
27
|
+
|
|
28
|
+
m.def("remove_duplicates",
|
|
29
|
+
[](const std::vector<geompp::Point3D>& pts) { return geompp::remove_duplicates(pts); },
|
|
30
|
+
"points"_a, "Remove all duplicate 3D points.");
|
|
31
|
+
|
|
32
|
+
m.def("remove_collinear",
|
|
33
|
+
[](const std::vector<geompp::Point2D>& pts) { return geompp::remove_collinear(pts); },
|
|
34
|
+
"points"_a, "Remove collinear 2D points.");
|
|
35
|
+
|
|
36
|
+
m.def("remove_collinear",
|
|
37
|
+
[](const std::vector<geompp::Point3D>& pts) { return geompp::remove_collinear(pts); },
|
|
38
|
+
"points"_a, "Remove collinear 3D points.");
|
|
39
|
+
|
|
40
|
+
m.def("linear_combination",
|
|
41
|
+
[](const std::vector<geompp::Point2D>& pts, const std::vector<double>& w) {
|
|
42
|
+
return geompp::linear_combination(pts, w);
|
|
43
|
+
}, "points"_a, "weights"_a, "Weighted linear combination of 2D points.");
|
|
44
|
+
|
|
45
|
+
m.def("linear_combination",
|
|
46
|
+
[](const std::vector<geompp::Point3D>& pts, const std::vector<double>& w) {
|
|
47
|
+
return geompp::linear_combination(pts, w);
|
|
48
|
+
}, "points"_a, "weights"_a, "Weighted linear combination of 3D points.");
|
|
49
|
+
|
|
50
|
+
m.def("average",
|
|
51
|
+
[](const std::vector<geompp::Point2D>& pts) { return geompp::average(pts); },
|
|
52
|
+
"points"_a, "Arithmetic mean of 2D points.");
|
|
53
|
+
|
|
54
|
+
m.def("average",
|
|
55
|
+
[](const std::vector<geompp::Point3D>& pts) { return geompp::average(pts); },
|
|
56
|
+
"points"_a, "Arithmetic mean of 3D points.");
|
|
57
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <pybind11/operators.h>
|
|
4
|
+
#include <pybind11/pybind11.h>
|
|
5
|
+
#include <pybind11/stl.h>
|
|
6
|
+
|
|
7
|
+
#include "bbox2d.hpp"
|
|
8
|
+
#include "bbox3d.hpp"
|
|
9
|
+
#include "constants.hpp"
|
|
10
|
+
#include "line2d.hpp"
|
|
11
|
+
#include "line3d.hpp"
|
|
12
|
+
#include "line_segment2d.hpp"
|
|
13
|
+
#include "line_segment3d.hpp"
|
|
14
|
+
#include "lsv_parser.hpp"
|
|
15
|
+
#include "plane.hpp"
|
|
16
|
+
#include "point2d.hpp"
|
|
17
|
+
#include "point3d.hpp"
|
|
18
|
+
#include "polygon2d.hpp"
|
|
19
|
+
#include "polygon3d.hpp"
|
|
20
|
+
#include "polyline2d.hpp"
|
|
21
|
+
#include "polyline3d.hpp"
|
|
22
|
+
#include "ray2d.hpp"
|
|
23
|
+
#include "ray3d.hpp"
|
|
24
|
+
#include "triangle2d.hpp"
|
|
25
|
+
#include "triangle3d.hpp"
|
|
26
|
+
#include "utils.hpp"
|
|
27
|
+
#include "vector2d.hpp"
|
|
28
|
+
#include "vector3d.hpp"
|
|
29
|
+
|
|
30
|
+
namespace py = pybind11;
|
|
31
|
+
using namespace pybind11::literals;
|
|
32
|
+
|
|
33
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
34
|
+
// Helper: convert std::optional<std::variant<Ts...>> to py::object.
|
|
35
|
+
//
|
|
36
|
+
// pybind11 3.x variant_caster fails for class-typed variants, so we use
|
|
37
|
+
// std::visit + py::cast explicitly instead of relying on the auto type caster.
|
|
38
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
39
|
+
template <typename Variant>
|
|
40
|
+
inline py::object opt_variant_to_py(const std::optional<Variant>& opt) {
|
|
41
|
+
if (!opt.has_value()) return py::none();
|
|
42
|
+
return std::visit([](const auto& v) -> py::object {
|
|
43
|
+
return py::cast(v);
|
|
44
|
+
}, opt.value());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
48
|
+
// Macro: almost_equals() with and without epsilon
|
|
49
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
50
|
+
#define BIND_ALMOST_EQUALS(T) \
|
|
51
|
+
.def("almost_equals", \
|
|
52
|
+
[](const geompp::T& self, const geompp::T& other) { \
|
|
53
|
+
return self.AlmostEquals(other); \
|
|
54
|
+
}, "other"_a) \
|
|
55
|
+
.def("almost_equals", \
|
|
56
|
+
[](const geompp::T& self, const geompp::T& other, double eps) { \
|
|
57
|
+
return self.AlmostEquals(other, eps); \
|
|
58
|
+
}, "other"_a, "epsilon"_a)
|
|
59
|
+
|
|
60
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
61
|
+
// Macro: WKT serialization + file I/O
|
|
62
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
63
|
+
#define BIND_SERIALIZATION(T) \
|
|
64
|
+
.def("to_wkt", &geompp::T::ToWkt) \
|
|
65
|
+
.def_static("from_wkt", &geompp::T::FromWkt, "wkt"_a) \
|
|
66
|
+
.def("to_file", &geompp::T::ToFile, "path"_a) \
|
|
67
|
+
.def_static("from_file", &geompp::T::FromFile, "path"_a) \
|
|
68
|
+
.def("__repr__", &geompp::T::ToWkt) \
|
|
69
|
+
.def("__str__", &geompp::T::ToWkt)
|