ballistic-solver 0.3.2__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.
- ballistic_solver-0.3.2/.github/workflows/ci.yml +29 -0
- ballistic_solver-0.3.2/.github/workflows/release.yml +208 -0
- ballistic_solver-0.3.2/.gitignore +60 -0
- ballistic_solver-0.3.2/CMakeLists.txt +108 -0
- ballistic_solver-0.3.2/LICENSE +21 -0
- ballistic_solver-0.3.2/PKG-INFO +197 -0
- ballistic_solver-0.3.2/README.md +190 -0
- ballistic_solver-0.3.2/bindings/dotnet/BallisticSolver.cs +34 -0
- ballistic_solver-0.3.2/bindings/python/CMakeLists.txt +27 -0
- ballistic_solver-0.3.2/bindings/python/ballistic_solver/__init__.py +6 -0
- ballistic_solver-0.3.2/bindings/python/pybind_module.cpp +155 -0
- ballistic_solver-0.3.2/cmake/BallisticSolverConfig.cmake.in +15 -0
- ballistic_solver-0.3.2/examples/c/basic.c +91 -0
- ballistic_solver-0.3.2/examples/cpp/basic.cpp +48 -0
- ballistic_solver-0.3.2/examples/dotnet/BallisticSolver.csproj +17 -0
- ballistic_solver-0.3.2/examples/dotnet/Basic.cs +108 -0
- ballistic_solver-0.3.2/examples/python/basic.py +8 -0
- ballistic_solver-0.3.2/include/ballistic_solver_c_api.h +69 -0
- ballistic_solver-0.3.2/pyproject.toml +20 -0
- ballistic_solver-0.3.2/src/ballistic_solver_c_api.cpp +97 -0
- ballistic_solver-0.3.2/src/ballistic_solver_core.hpp +1077 -0
- ballistic_solver-0.3.2/tests/smoke_test.c +61 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ "main" ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ "main" ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build-test:
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
os: [windows-latest, ubuntu-latest, macos-latest]
|
|
15
|
+
config: [Release]
|
|
16
|
+
runs-on: ${{ matrix.os }}
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Configure (CMake)
|
|
23
|
+
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.config }}
|
|
24
|
+
|
|
25
|
+
- name: Build
|
|
26
|
+
run: cmake --build build --config ${{ matrix.config }} -j
|
|
27
|
+
|
|
28
|
+
- name: Test (ctest)
|
|
29
|
+
run: ctest --test-dir build -C ${{ matrix.config }} --output-on-failure
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
name: Release Native + PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
tag:
|
|
10
|
+
description: "v0.3.2"
|
|
11
|
+
required: true
|
|
12
|
+
type: string
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: write
|
|
16
|
+
id-token: write
|
|
17
|
+
|
|
18
|
+
env:
|
|
19
|
+
TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
native:
|
|
23
|
+
name: Build native (${{ matrix.os }})
|
|
24
|
+
if: >
|
|
25
|
+
(github.event_name == 'push' && startsWith(github.ref_name, 'v')) ||
|
|
26
|
+
(github.event_name == 'workflow_dispatch' && startsWith(inputs.tag, 'v'))
|
|
27
|
+
strategy:
|
|
28
|
+
fail-fast: false
|
|
29
|
+
matrix:
|
|
30
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
31
|
+
runs-on: ${{ matrix.os }}
|
|
32
|
+
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
with:
|
|
36
|
+
fetch-depth: 0
|
|
37
|
+
ref: refs/tags/${{ env.TAG }}
|
|
38
|
+
|
|
39
|
+
- name: Configure (CMake Release)
|
|
40
|
+
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
|
41
|
+
|
|
42
|
+
- name: Build
|
|
43
|
+
run: cmake --build build --config Release --parallel
|
|
44
|
+
|
|
45
|
+
- name: Test
|
|
46
|
+
run: ctest --test-dir build -C Release --output-on-failure
|
|
47
|
+
|
|
48
|
+
- name: Package native (Linux/macOS)
|
|
49
|
+
if: runner.os != 'Windows'
|
|
50
|
+
shell: bash
|
|
51
|
+
run: |
|
|
52
|
+
set -euo pipefail
|
|
53
|
+
mkdir -p dist
|
|
54
|
+
cp -f include/ballistic_solver_c_api.h dist/
|
|
55
|
+
|
|
56
|
+
if [[ "${RUNNER_OS}" == "Linux" ]]; then
|
|
57
|
+
libpath="$(find build -maxdepth 10 -type f -name "libballistic_solver.so" -print -quit)"
|
|
58
|
+
else
|
|
59
|
+
libpath="$(find build -maxdepth 10 -type f -name "libballistic_solver.dylib" -print -quit)"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
if [[ -z "${libpath:-}" ]]; then
|
|
63
|
+
echo "ERROR: shared library not found under build/"
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
cp -f "$libpath" dist/
|
|
68
|
+
os="$(echo "${RUNNER_OS}" | tr '[:upper:]' '[:lower:]')"
|
|
69
|
+
(cd dist && zip -r "../ballistic_solver_${TAG}_${os}.zip" .)
|
|
70
|
+
|
|
71
|
+
- name: Package native (Windows)
|
|
72
|
+
if: runner.os == 'Windows'
|
|
73
|
+
shell: pwsh
|
|
74
|
+
run: |
|
|
75
|
+
New-Item -ItemType Directory -Force dist | Out-Null
|
|
76
|
+
Copy-Item -Force include\ballistic_solver_c_api.h dist\
|
|
77
|
+
|
|
78
|
+
$dll = Get-ChildItem -Path build -Recurse -Filter ballistic_solver.dll -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
79
|
+
if (-not $dll)
|
|
80
|
+
{
|
|
81
|
+
Write-Error "ERROR: ballistic_solver.dll not found under build/"
|
|
82
|
+
exit 1
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
Copy-Item -Force $dll.FullName dist\
|
|
86
|
+
Compress-Archive -Path dist\* -DestinationPath "ballistic_solver_$($env:TAG)_windows.zip" -Force
|
|
87
|
+
|
|
88
|
+
- uses: actions/upload-artifact@v4
|
|
89
|
+
with:
|
|
90
|
+
name: native-${{ runner.os }}
|
|
91
|
+
path: ballistic_solver_*.zip
|
|
92
|
+
if-no-files-found: error
|
|
93
|
+
|
|
94
|
+
py_wheels:
|
|
95
|
+
name: Build python wheels (${{ matrix.os }})
|
|
96
|
+
if: >
|
|
97
|
+
(github.event_name == 'push' && startsWith(github.ref_name, 'v')) ||
|
|
98
|
+
(github.event_name == 'workflow_dispatch' && startsWith(inputs.tag, 'v'))
|
|
99
|
+
strategy:
|
|
100
|
+
fail-fast: false
|
|
101
|
+
matrix:
|
|
102
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
103
|
+
runs-on: ${{ matrix.os }}
|
|
104
|
+
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@v4
|
|
107
|
+
with:
|
|
108
|
+
fetch-depth: 0
|
|
109
|
+
ref: refs/tags/${{ env.TAG }}
|
|
110
|
+
|
|
111
|
+
- name: Build wheels (cibuildwheel)
|
|
112
|
+
uses: pypa/cibuildwheel@v3.3.1
|
|
113
|
+
with:
|
|
114
|
+
package-dir: .
|
|
115
|
+
output-dir: wheelhouse
|
|
116
|
+
env:
|
|
117
|
+
CIBW_BUILD: "cp310-* cp311-* cp312-*"
|
|
118
|
+
CIBW_SKIP: "*-win32 *-manylinux_i686 *-musllinux_*"
|
|
119
|
+
CIBW_ARCHS_MACOS: "universal2"
|
|
120
|
+
CIBW_BUILD_VERBOSITY: "3"
|
|
121
|
+
CIBW_TEST_COMMAND: >-
|
|
122
|
+
python -c "import ballistic_solver; print('import_ok')"
|
|
123
|
+
|
|
124
|
+
- uses: actions/upload-artifact@v4
|
|
125
|
+
with:
|
|
126
|
+
name: pywheels-${{ runner.os }}
|
|
127
|
+
path: wheelhouse/*.whl
|
|
128
|
+
if-no-files-found: error
|
|
129
|
+
|
|
130
|
+
sdist:
|
|
131
|
+
name: Build python sdist
|
|
132
|
+
if: >
|
|
133
|
+
(github.event_name == 'push' && startsWith(github.ref_name, 'v')) ||
|
|
134
|
+
(github.event_name == 'workflow_dispatch' && startsWith(inputs.tag, 'v'))
|
|
135
|
+
runs-on: ubuntu-latest
|
|
136
|
+
|
|
137
|
+
steps:
|
|
138
|
+
- uses: actions/checkout@v4
|
|
139
|
+
with:
|
|
140
|
+
fetch-depth: 0
|
|
141
|
+
ref: refs/tags/${{ env.TAG }}
|
|
142
|
+
|
|
143
|
+
- uses: actions/setup-python@v5
|
|
144
|
+
with:
|
|
145
|
+
python-version: "3.12"
|
|
146
|
+
|
|
147
|
+
- name: Build sdist
|
|
148
|
+
shell: bash
|
|
149
|
+
run: |
|
|
150
|
+
set -euo pipefail
|
|
151
|
+
python -m pip install -U pip build
|
|
152
|
+
python -m build --sdist
|
|
153
|
+
|
|
154
|
+
- uses: actions/upload-artifact@v4
|
|
155
|
+
with:
|
|
156
|
+
name: pysdist
|
|
157
|
+
path: dist/*.tar.gz
|
|
158
|
+
if-no-files-found: error
|
|
159
|
+
|
|
160
|
+
publish:
|
|
161
|
+
name: Publish (PyPI + GitHub Release assets)
|
|
162
|
+
needs: [native, py_wheels, sdist]
|
|
163
|
+
if: >
|
|
164
|
+
(github.event_name == 'push' && startsWith(github.ref_name, 'v')) ||
|
|
165
|
+
(github.event_name == 'workflow_dispatch' && startsWith(inputs.tag, 'v'))
|
|
166
|
+
runs-on: ubuntu-latest
|
|
167
|
+
|
|
168
|
+
steps:
|
|
169
|
+
- uses: actions/checkout@v4
|
|
170
|
+
|
|
171
|
+
- uses: actions/download-artifact@v4
|
|
172
|
+
with:
|
|
173
|
+
path: artifacts
|
|
174
|
+
merge-multiple: true
|
|
175
|
+
|
|
176
|
+
- name: Collect PyPI dist
|
|
177
|
+
shell: bash
|
|
178
|
+
run: |
|
|
179
|
+
set -euo pipefail
|
|
180
|
+
mkdir -p dist
|
|
181
|
+
find artifacts -type f \( -name "*.whl" -o -name "*.tar.gz" \) -exec cp {} dist/ \;
|
|
182
|
+
ls -la dist
|
|
183
|
+
|
|
184
|
+
- name: Publish to PyPI
|
|
185
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
186
|
+
with:
|
|
187
|
+
packages-dir: dist
|
|
188
|
+
|
|
189
|
+
- name: Create release if missing
|
|
190
|
+
env:
|
|
191
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
192
|
+
shell: bash
|
|
193
|
+
run: |
|
|
194
|
+
set -euo pipefail
|
|
195
|
+
if gh release view "${TAG}" > /dev/null 2>&1; then
|
|
196
|
+
echo "Release ${TAG} already exists."
|
|
197
|
+
else
|
|
198
|
+
gh release create "${TAG}" --title "${TAG}" --generate-notes
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
- name: Upload assets to GitHub Release
|
|
202
|
+
env:
|
|
203
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
204
|
+
shell: bash
|
|
205
|
+
run: |
|
|
206
|
+
set -euo pipefail
|
|
207
|
+
gh release upload "${TAG}" artifacts/*.zip --clobber
|
|
208
|
+
gh release upload "${TAG}" dist/* --clobber
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Build outputs
|
|
2
|
+
build/
|
|
3
|
+
out/
|
|
4
|
+
cmake-build-*/
|
|
5
|
+
CMakeFiles/
|
|
6
|
+
CMakeCache.txt
|
|
7
|
+
cmake_install.cmake
|
|
8
|
+
Makefile
|
|
9
|
+
compile_commands.json
|
|
10
|
+
**/dist/
|
|
11
|
+
|
|
12
|
+
# Object / binary / library files
|
|
13
|
+
*.o
|
|
14
|
+
*.obj
|
|
15
|
+
*.exe
|
|
16
|
+
*.out
|
|
17
|
+
*.a
|
|
18
|
+
*.lib
|
|
19
|
+
*.so
|
|
20
|
+
*.dll
|
|
21
|
+
*.dylib
|
|
22
|
+
*.whl
|
|
23
|
+
*.zip
|
|
24
|
+
|
|
25
|
+
# Debug symbols / misc
|
|
26
|
+
*.pdb
|
|
27
|
+
*.ilk
|
|
28
|
+
*.dSYM/
|
|
29
|
+
*.log
|
|
30
|
+
|
|
31
|
+
# IDE/editor
|
|
32
|
+
.vscode/
|
|
33
|
+
.idea/
|
|
34
|
+
*.user
|
|
35
|
+
*.suo
|
|
36
|
+
*.vcxproj*
|
|
37
|
+
*.filters
|
|
38
|
+
*.xcodeproj/
|
|
39
|
+
*.xcworkspace/
|
|
40
|
+
|
|
41
|
+
# OS
|
|
42
|
+
.DS_Store
|
|
43
|
+
Thumbs.db
|
|
44
|
+
|
|
45
|
+
# Visual Studio
|
|
46
|
+
.vs/
|
|
47
|
+
|
|
48
|
+
# .NET build outputs
|
|
49
|
+
**/bin/
|
|
50
|
+
**/obj/
|
|
51
|
+
|
|
52
|
+
# Python
|
|
53
|
+
__pycache__/
|
|
54
|
+
*.py[cod]
|
|
55
|
+
**/*.egg-info/
|
|
56
|
+
.venv/
|
|
57
|
+
venv/
|
|
58
|
+
|
|
59
|
+
# Assets
|
|
60
|
+
assets/
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.20)
|
|
2
|
+
|
|
3
|
+
project(ballistic_solver
|
|
4
|
+
VERSION 0.3.0
|
|
5
|
+
LANGUAGES C CXX
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
set(CMAKE_C_STANDARD 11)
|
|
9
|
+
set(CMAKE_C_STANDARD_REQUIRED ON)
|
|
10
|
+
set(CMAKE_C_EXTENSIONS OFF)
|
|
11
|
+
|
|
12
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
13
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
14
|
+
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
15
|
+
|
|
16
|
+
add_library(ballistic_solver SHARED
|
|
17
|
+
src/ballistic_solver_c_api.cpp
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
target_include_directories(ballistic_solver
|
|
21
|
+
PUBLIC
|
|
22
|
+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
23
|
+
$<INSTALL_INTERFACE:include>
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
target_compile_definitions(ballistic_solver PRIVATE
|
|
27
|
+
BALLISTIC_SOLVER_EXPORTS
|
|
28
|
+
BALLISTIC_SOLVER_ABI_VERSION=2
|
|
29
|
+
BALLISTIC_SOLVER_VERSION_STRING=\"${PROJECT_VERSION}\"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
if (MSVC)
|
|
33
|
+
target_compile_options(ballistic_solver PRIVATE /W4 /utf-8)
|
|
34
|
+
else()
|
|
35
|
+
target_compile_options(ballistic_solver PRIVATE -Wall -Wextra -Wpedantic)
|
|
36
|
+
endif()
|
|
37
|
+
|
|
38
|
+
add_executable(ballistic_solver_example
|
|
39
|
+
examples/c/basic.c
|
|
40
|
+
)
|
|
41
|
+
target_link_libraries(ballistic_solver_example PRIVATE ballistic_solver)
|
|
42
|
+
|
|
43
|
+
include(CTest)
|
|
44
|
+
if (BUILD_TESTING)
|
|
45
|
+
add_executable(smoke_test
|
|
46
|
+
tests/smoke_test.c
|
|
47
|
+
)
|
|
48
|
+
target_link_libraries(smoke_test PRIVATE ballistic_solver)
|
|
49
|
+
|
|
50
|
+
add_test(
|
|
51
|
+
NAME smoke_test
|
|
52
|
+
COMMAND $<TARGET_FILE:smoke_test>
|
|
53
|
+
)
|
|
54
|
+
endif()
|
|
55
|
+
|
|
56
|
+
include(GNUInstallDirs)
|
|
57
|
+
|
|
58
|
+
install(TARGETS ballistic_solver
|
|
59
|
+
EXPORT ballistic_solverTargets
|
|
60
|
+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
61
|
+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
62
|
+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
|
|
66
|
+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Minimal find_package(CONFIG) support
|
|
70
|
+
set(_pkgdir ${CMAKE_INSTALL_LIBDIR}/cmake/ballistic_solver)
|
|
71
|
+
|
|
72
|
+
install(EXPORT ballistic_solverTargets
|
|
73
|
+
FILE ballistic_solverTargets.cmake
|
|
74
|
+
NAMESPACE ballistic_solver::
|
|
75
|
+
DESTINATION ${_pkgdir}
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
include(CMakePackageConfigHelpers)
|
|
79
|
+
|
|
80
|
+
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ballistic_solverConfig.cmake"
|
|
81
|
+
"include(\"\${CMAKE_CURRENT_LIST_DIR}/ballistic_solverTargets.cmake\")\n"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
write_basic_package_version_file(
|
|
85
|
+
"${CMAKE_CURRENT_BINARY_DIR}/ballistic_solverConfigVersion.cmake"
|
|
86
|
+
VERSION ${PROJECT_VERSION}
|
|
87
|
+
COMPATIBILITY SameMajorVersion
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
install(FILES
|
|
91
|
+
"${CMAKE_CURRENT_BINARY_DIR}/ballistic_solverConfig.cmake"
|
|
92
|
+
"${CMAKE_CURRENT_BINARY_DIR}/ballistic_solverConfigVersion.cmake"
|
|
93
|
+
DESTINATION ${_pkgdir}
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
set_target_properties(ballistic_solver PROPERTIES OUTPUT_NAME "ballistic_solver")
|
|
97
|
+
|
|
98
|
+
if(DEFINED SKBUILD_PLATLIB_DIR)
|
|
99
|
+
set(BS_NATIVE_DIR "${SKBUILD_PLATLIB_DIR}/ballistic_solver/_native")
|
|
100
|
+
else()
|
|
101
|
+
set(BS_NATIVE_DIR "${CMAKE_INSTALL_LIBDIR}")
|
|
102
|
+
endif()
|
|
103
|
+
|
|
104
|
+
install(TARGETS ballistic_solver
|
|
105
|
+
RUNTIME DESTINATION "${BS_NATIVE_DIR}" # Windows .dll
|
|
106
|
+
LIBRARY DESTINATION "${BS_NATIVE_DIR}" # Linux .so / macOS .dylib
|
|
107
|
+
ARCHIVE DESTINATION "${BS_NATIVE_DIR}" # .lib
|
|
108
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 <ujinf74>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ballistic-solver
|
|
3
|
+
Version: 0.3.2
|
|
4
|
+
License-Expression: MIT
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
|
|
8
|
+
<img width="2024" height="512" alt="banner" src="https://github.com/user-attachments/assets/f4e57e3f-f584-4938-a321-e9dd83dbbac3" />
|
|
9
|
+
|
|
10
|
+
**ballistic-solver** is a native C/C++ numerical solver that computes launch angles to intercept **moving targets** under **gravity** and **quadratic air drag**.
|
|
11
|
+
Unlike vacuum / closed-form approaches, this solver **simulates the projectile** and **solves the intercept numerically**, targeting robustness for real-time simulations even when trajectories are strongly curved.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
### Python (wheel)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install ballistic-solver
|
|
21
|
+
````
|
|
22
|
+
|
|
23
|
+
Requires Python **>= 3.10**.
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
import ballistic_solver as bs
|
|
27
|
+
|
|
28
|
+
result = bs.solve(
|
|
29
|
+
relPos0=(120, 30, 5),
|
|
30
|
+
relVel=(2, -1, 0),
|
|
31
|
+
v0=90,
|
|
32
|
+
kDrag=0.002,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
print(result["theta"], result["phi"], result["miss"])
|
|
36
|
+
print(result["success"], result["status"], result["message"])
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
#### Signature (actual binding)
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
solve(relPos0, relVel, v0, kDrag, arcMode=0, params=None) -> dict
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
* `arcMode` accepts `0/1` or `"low"/"high"` (case-insensitive).
|
|
46
|
+
* **Important:** the `arcMode` argument **overrides** `params.arcMode` even if `params` is provided.
|
|
47
|
+
|
|
48
|
+
Returned dict keys include:
|
|
49
|
+
|
|
50
|
+
* `success`, `theta`, `phi`, `miss`, `tStar`, `relMissAtStar`
|
|
51
|
+
* `status`, `message`
|
|
52
|
+
* `iterations`, `acceptedSteps`, `lastLambda`, `lastAlpha`
|
|
53
|
+
|
|
54
|
+
### C ABI (stable interface)
|
|
55
|
+
|
|
56
|
+
```c
|
|
57
|
+
void ballistic_inputs_init(BallisticInputs* in);
|
|
58
|
+
int32_t ballistic_solve(const BallisticInputs* in, BallisticOutputs* out);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
See `ballistic_solver_c_api.h` for `BallisticInputs/Outputs` definitions and defaults.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Demo (Unity)
|
|
66
|
+
|
|
67
|
+
Highly curved trajectories under strong air drag, still converging to a hit against moving targets.
|
|
68
|
+
|
|
69
|
+
[https://github.com/user-attachments/assets/dcaf7479-cb94-477a-b71e-470a5b4c6004](https://github.com/user-attachments/assets/dcaf7479-cb94-477a-b71e-470a5b4c6004)
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Key properties
|
|
74
|
+
|
|
75
|
+
* Moving targets supported
|
|
76
|
+
* Strong air resistance (quadratic drag) supported
|
|
77
|
+
* Robust in strongly nonlinear regimes (no analytic assumptions)
|
|
78
|
+
* Best-effort result returned even without perfect convergence
|
|
79
|
+
* Explicit success / failure reporting (+ diagnostic message)
|
|
80
|
+
* Stable C ABI for multi-language use
|
|
81
|
+
* Header-only C++ core
|
|
82
|
+
* Low / High arc selection (since v0.2.0)
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Arc mode (since v0.2.0)
|
|
87
|
+
|
|
88
|
+
C ABI convention:
|
|
89
|
+
|
|
90
|
+
* `arcMode = 0` → Low
|
|
91
|
+
* `arcMode = 1` → High
|
|
92
|
+
|
|
93
|
+
High arc example:
|
|
94
|
+
|
|
95
|
+
[https://github.com/user-attachments/assets/4334ed87-597e-4ad4-b21e-c1a1a17e8cd8](https://github.com/user-attachments/assets/4334ed87-597e-4ad4-b21e-c1a1a17e8cd8)
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## How it works (high level)
|
|
100
|
+
|
|
101
|
+
1. Simulate projectile motion using RK4 integration with drag (+ wind in core/C ABI)
|
|
102
|
+
2. Track the closest approach between projectile and target
|
|
103
|
+
3. Express the miss at closest approach as an angular residual
|
|
104
|
+
4. Solve the nonlinear system using damped least squares (Levenberg–Marquardt)
|
|
105
|
+
5. Accelerate Jacobian updates with Broyden-style refinement
|
|
106
|
+
6. Return the best solution found
|
|
107
|
+
|
|
108
|
+
Failure cases are explicitly detected and reported.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Advanced parameters (C ABI)
|
|
113
|
+
|
|
114
|
+
`BallisticInputs` exposes additional controls (all have defaults via `ballistic_inputs_init`):
|
|
115
|
+
|
|
116
|
+
* `g` (gravity)
|
|
117
|
+
* `wind[3]` (wind vector)
|
|
118
|
+
* `dt` (RK4 step)
|
|
119
|
+
* `tMax` (max sim time)
|
|
120
|
+
* `tolMiss` (hit tolerance)
|
|
121
|
+
* `maxIter` (LM iterations)
|
|
122
|
+
|
|
123
|
+
Note: The current Python binding exposes many tuning parameters via `BallisticParams`,
|
|
124
|
+
but does **not** expose `wind` as a Python field.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Status codes (SolveStatus)
|
|
129
|
+
|
|
130
|
+
`BallisticOutputs.status` / Python `result["status"]` corresponds to the core enum:
|
|
131
|
+
|
|
132
|
+
* `0` = Ok
|
|
133
|
+
* `1` = InvalidInput
|
|
134
|
+
* `2` = InitialResidualFailed
|
|
135
|
+
* `3` = JacobianFailed
|
|
136
|
+
* `4` = LMStepSingular
|
|
137
|
+
* `5` = ResidualFailedDuringSearch
|
|
138
|
+
* `6` = LineSearchRejected
|
|
139
|
+
* `7` = LambdaTriesExhausted
|
|
140
|
+
* `8` = MaxIterReached
|
|
141
|
+
|
|
142
|
+
`message` contains a short diagnostic string.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Using prebuilt binaries
|
|
147
|
+
|
|
148
|
+
Download the archive for your platform from **Releases**.
|
|
149
|
+
|
|
150
|
+
Each release contains:
|
|
151
|
+
|
|
152
|
+
* Shared library
|
|
153
|
+
|
|
154
|
+
* Windows: `ballistic_solver.dll`
|
|
155
|
+
* Linux: `libballistic_solver.so`
|
|
156
|
+
* macOS: `libballistic_solver.dylib`
|
|
157
|
+
* C ABI header: `ballistic_solver_c_api.h`
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## C# / Unity usage
|
|
162
|
+
|
|
163
|
+
A C# P/Invoke example is available in:
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
examples/dotnet/
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
On Windows, place `ballistic_solver.dll` next to the executable
|
|
170
|
+
(or ensure it is discoverable via PATH),
|
|
171
|
+
then call `ballistic_solve` via `DllImport`.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Build from source
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
cmake -S . -B build
|
|
179
|
+
cmake --build build -j
|
|
180
|
+
ctest --test-dir build
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The shared library target is `ballistic_solver`.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## ABI notes
|
|
188
|
+
|
|
189
|
+
* Plain C layout across the ABI boundary
|
|
190
|
+
* Fixed-size arrays only
|
|
191
|
+
* No dynamic allocation across the boundary
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
MIT License
|