00 — Overview¶
What NPS is¶
NPS is a desktop 3D-printing analysis tool. It loads 3MF mesh files, parses G-code (text or binary BGCode), runs a small suite of physics / structural / motion / hole / retraction / flow analyzers, and renders the result on a 2D canvas. There are two thin Avalonia apps:
- SlicerApp — toolpath + analysis visualizer; consumes a loaded mesh + generated/parsed G-code, renders layers, overlays, and findings.
- SimulatorApp — same as Slicer, plus renders the underlying 3D mesh polygons in the background alongside the toolpath.
Both apps share one C# shell, one C# host border, and one deep C++ engine.
30-second shape¶
flowchart TB
subgraph L5["L5 apps (Avalonia)"]
SA["src/SlicerApp<br/>MainWindow.axaml.cs"]
XA["src/SimulatorApp<br/>MainWindow.axaml.cs"]
end
subgraph L4["L4 Nps.Shell"]
VC["ViewportController.cs"]
SH["FixtureLocator / StatusSink /<br/>ShellTrace / Controls/*"]
end
subgraph L3["L3 Nps.EngineHost"]
ES["EngineSession.cs"]
AB["NpsAbi.cs<br/>(sole P/Invoke surface)"]
SH1["SafeEngineHandle<br/>SafeGcodeViewportHandle"]
end
subgraph L2["L2 C ABI (nps_c_api.h)"]
ABI["59 prod exports +<br/>9 test-gated (NPS_ENABLE_TEST_HOOKS)"]
end
subgraph L1["L1 Session (nps::Engine)"]
ENG["engine.h (279 LOC) +<br/>engine.cpp (7,003 LOC)"]
end
subgraph L0["L0 modules (under src/Engine)"]
ZIP["engine_zip"]
T3MF["engine_threemf"]
GCD["engine_gcode + engine_gcode_store"]
ANA["engine_analysis + engine_material"]
VPT["engine_viewport"]
CLR["engine_color + engine_data"]
MSH["engine_mesh_store"]
end
SA --> L4
XA --> L4
L4 --> L3
L3 --> L2
L2 --> L1
L1 --> L0
L3 -.sole host border.-> AB
AB -.P/Invoke.-> ABI
L5 -.no direct.-> L2
L4 -.no direct.-> L2
L3 -.no direct.-> L1
L0 -.no upward include.-> L1
Why this shape¶
- One host border. Only
Nps.EngineHost.NpsAbi.csdeclares[DllImport("NPSEngine")]. No app code or shell code may talk to the C ABI directly. Seelayers-and-contracts.mdanddocs/architecture.md. - Deep C++ engine owns every domain concept — 3MF loading, mesh resolution, color decoding, G-code parse + generate, analyzers, viewport buffer prep. C# is marshaling and Avalonia chrome only.
- Frozen C ABI.
src/Engine/abi/nps_c_api.his the only surface the C# side sees. The full inventory (call-site counts, gated symbols, orphan-audit) is indocs/abi-inventory.md. - No STL crosses the ABI. PODs, opaque handles, C strings, raw caller-owned buffers only. No C++ exceptions.
- Demo toolpath is honest.
GenerateGcode/EngineSession.GenerateDemoToolpathproduces a demo toolpath (square perimeter + diagonal infill modulated by a sampled scalar field). It is not a production slice and is labeled as such in every surface (engine.h, the emitted G-code header, UI status strings, and here).
What is where (high-level)¶
| Path | Role | Layer |
|---|---|---|
src/SlicerApp/ |
Slicer UI (toolpath + analysis) | L5 |
src/SimulatorApp/ |
Simulator UI (toolpath + 3D mesh) | L5 |
src/Nps.Shell/ |
Shared shell: ViewportController, FixtureLocator, StatusSink, keybindings |
L4 |
src/Nps.EngineHost/ |
Sole host border: NpsAbi.cs, SafeHandles, EngineSession.cs |
L3 |
src/Engine/engine.h + engine.cpp |
C++ session facade + implementations | L1 |
src/Engine/abi/nps_c_api.h |
Frozen C ABI, PODs, exports | L2 |
src/Engine/internal/* |
C++ modules (zip, threemf, gcode, analysis, viewport, color) | L0 |
tests/NPSEngine.Tests/ |
C# xUnit interop harness | L5/T |
src/Engine/tests/engine_tests.cpp |
C++ Catch2 harness | L1/T |
4-colors+Benchy+AMS+test-v2.3mf |
Primary golden fixture (repo root) | fixture |
scripts/, lefthook.yml |
Quality gates | tooling |
Key counts (from ground truth)¶
- 68 C ABI symbols total; 59 production, 9 test-gated
(
NPS_ENABLE_TEST_HOOKS). The 9 include 8Test*hooks andGetMeshBounds. - ~45 public method declarations on
nps::Engine(including overloads/ctors; seeengine-modules.md). - 91 Catch2
TEST_CASEs inengine_tests.cpp. - 115 C#
[Fact]/[Theory]methods intests/NPSEngine.Tests. engine.cppis 7,003 LOC;engine_tests.cppis 4,447 LOC;nps_c_api.his 418 LOC.
Primary golden fixture¶
The repo-root fixture 4-colors+Benchy+AMS+test-v2.3mf is the canonical
load-test input. Both harnesses assert these exact counts:
| Field | Expected |
|---|---|
| Plates | 1 |
| Total vertices | 16562 |
| Total triangles | 33097 |
| Palette colors | 4 (ARGB: 0xFFC12E1F, 0xFFFEC600, 0xFF00AE42, 0xFF0A2989) |
Removing or renaming the fixture breaks three independent gates (ctest, dotnet test, pre-push hook).
See also¶
layers-and-contracts.mddocs/architecture.md(full contract layer)docs/abi-inventory.md(C ABI inventory with call-site counts)glossary.md
Where to go next¶
- Slicer workflows — end-to-end click-to-engine traces for the Slicer app.
- Simulator workflows — the same traces for the Simulator app (playback, mesh underlay).