Skip to content

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.cs declares [DllImport("NPSEngine")]. No app code or shell code may talk to the C ABI directly. See layers-and-contracts.md and docs/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.h is the only surface the C# side sees. The full inventory (call-site counts, gated symbols, orphan-audit) is in docs/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.GenerateDemoToolpath produces 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 8 Test* hooks and GetMeshBounds.
  • ~45 public method declarations on nps::Engine (including overloads/ctors; see engine-modules.md).
  • 91 Catch2 TEST_CASEs in engine_tests.cpp.
  • 115 C# [Fact] / [Theory] methods in tests/NPSEngine.Tests.
  • engine.cpp is 7,003 LOC; engine_tests.cpp is 4,447 LOC; nps_c_api.h is 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

Where to go next