diff --git a/CLAUDE.md b/CLAUDE.md index c1f29b6..e2ceed7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -74,7 +74,7 @@ No tests exist. No linter is configured. - **Colors** are `[Float]` RGBA (0–1), with predefined constants on `ScriptContext.Colors` (e.g., `.steel`, `.brass`, `.copper`). - **Geometry types accepted by `ScriptContext.add()`**: `Shape` (solids/shells/compounds/faces), `Wire`, `Edge` (the latter two are converted via `Shape.fromWire`/`Shape.fromEdge`). - **BREP over STEP**: BREP is the primary format (~1ms vs ~50ms for STEP). STEP export is optional (`ScriptContext(exportSTEP: false)` to disable; `occtkit run --format` controls it via source rewriting). -- **TopologyGraph export**: `ctx.addGraph(_)` writes `graph-N.json` (BREPGraph v1) and optionally `graph-N.sqlite`. `ctx.addGraphsForAllShapes(sqlite:)` is a convenience for batch export. +- **BRepGraph export**: `ctx.addGraph(_)` writes `graph-N.json` (BREPGraph v1) and optionally `graph-N.sqlite`. `ctx.addGraphsForAllShapes(sqlite:)` is a convenience for batch export. - **occtkit verbs throw, never `exit()`** — required so `--serve` can recover and continue. Use `ScriptError.message(...)` (in `ScriptContext.swift`) for ad-hoc failures; `GraphIO` helpers throw on every failure path. Standalone wrappers catch + exit 1 in their own `main.swift`. - **Adding a new verb** = one file in `Sources/occtkit/Commands/` plus one entry in `Registry.all` (`Sources/occtkit/Subcommand.swift`). Standalone targets should not gain new verbs; they exist only for legacy compatibility. @@ -82,10 +82,10 @@ No tests exist. No linter is configured. The full cohort graduated to v1.0 on 2026-05-07 alongside OCCT 8.0.0 GA. SemVer-stable from these floors — only bump on documented breaking changes. Pre-1.0 dep history (which API landed in which 0.x tag) lives in git log; consult it when you actually need to support an older floor, otherwise treat the v1.0 surface as the contract. -- **OCCTSwift** — `https://github.com/gsdali/OCCTSwift.git` (>= 1.7.1; xcframework built against **OCCT 8.0.0p1**). The B-Rep kernel: ~400+ methods for parametric CAD, the full ISO drawings stack (Sheet/TitleBlock/ProjectionSymbol/Section2D/Hatch/AutoCentermarks/CuttingPlaneLine/CosmeticThread/SurfaceFinish/GDT/DetailView/DrawingScale), `FeatureReconstructor` for `reconstruct`, the `SheetMetal` namespace for `compose-sheet-metal`, and the XCAF surfaces (`AssemblyNode.labelId`, `Document.node(at:)`) for `inspect-assembly` / `set-metadata`. **Floored at v1.7.1 (= OCCT 8.0.0p1)**: v1.7.0 realigned the BRepGraph wrapper to OCCT's redesigned graph model (definitions vs references/usages, persistent UIDs, controlled layers) and v1.7.1 made the derived graph reads real again — `adjacentFaces`/`faces(of:)`/`edges(of:)`/`sharedEdges`, `faceSameDomain`, `faceIsNaturalRestriction` — plus durable `UID`/`RefUID`/`ItemUID` identity. Our graph verbs (graph-validate/compact/dedup/ml, query-topology) build and run **unchanged** against it. Behaviour changes are **confined to the BRepGraph domain**: `edgeMaxContinuity`/`setEdgeRegularity` are now no-ops (use `Shape.maxContinuity` for continuity); `degenerated`/`closed`/`sameParameter`/`sameRange` setters no-op while their getters return the live derived value. The cookbook ergonomics relied on since v1.3.1 — `Shape.circularPatternCut` (#169), orientation-normalised `Shape.sweep` + `orientedForward`/`signedVolume` (#170), `concaveEdges`/`convexEdges`/`edges(where:)` selectors (#171) — are unchanged. The rest of the cohort still resolves at its existing floors (Viewport 1.0.4 / Tools 1.1.1 / AIS 1.0.2 / Mesh 1.0.0 / IO 1.0.0), all of which compile against 1.7.1. +- **OCCTSwift** — `https://github.com/gsdali/OCCTSwift.git` (>= 1.15.0; xcframework built against **OCCT 8.0.0p1**). The B-Rep kernel: ~400+ methods for parametric CAD, the full ISO drawings stack (Sheet/TitleBlock/ProjectionSymbol/Section2D/Hatch/AutoCentermarks/CuttingPlaneLine/CosmeticThread/SurfaceFinish/GDT/DetailView/DrawingScale), `FeatureReconstructor` for `reconstruct`, the `SheetMetal` namespace for `compose-sheet-metal`, and the XCAF surfaces (`AssemblyNode.labelId`, `Document.node(at:)`) for `inspect-assembly` / `set-metadata`. **Floored at v1.15.0**: v1.15.0 renamed the Swift wrapper class `TopologyGraph` → `BRepGraph` (OCCTSwift#335) to match the C++ package it wraps; this repo has migrated off the deprecated `TopologyGraph` typealias onto `BRepGraph` directly (OCCTSwiftScripts#78), so the floor must guarantee the `BRepGraph` symbol exists. Earlier, v1.7.0 realigned the BRepGraph wrapper to OCCT's redesigned graph model (definitions vs references/usages, persistent UIDs, controlled layers) and v1.7.1 made the derived graph reads real again — `adjacentFaces`/`faces(of:)`/`edges(of:)`/`sharedEdges`, `faceSameDomain`, `faceIsNaturalRestriction` — plus durable `UID`/`RefUID`/`ItemUID` identity. Our graph verbs (graph-validate/compact/dedup/ml, query-topology) build and run **unchanged** against it. Behaviour changes are **confined to the BRepGraph domain**: `edgeMaxContinuity`/`setEdgeRegularity` are now no-ops (use `Shape.maxContinuity` for continuity); `degenerated`/`closed`/`sameParameter`/`sameRange` setters no-op while their getters return the live derived value. The cookbook ergonomics relied on since v1.3.1 — `Shape.circularPatternCut` (#169), orientation-normalised `Shape.sweep` + `orientedForward`/`signedVolume` (#170), `concaveEdges`/`convexEdges`/`edges(where:)` selectors (#171) — are unchanged. The rest of the cohort still resolves at its existing floors (Viewport 1.0.4 / Tools 1.1.1 / AIS 1.0.2 / Mesh 1.0.0 / IO 1.0.0), all of which compile against 1.15.0. - **OCCTSwiftViewport** — `https://github.com/gsdali/OCCTSwiftViewport.git` (>= 1.0.0). Provides `OffscreenRenderer`, `CameraState`, `DisplayMode`, `ViewportBody` for `render-preview`. Graduated to v1.0.0 on 2026-05-08, one day after the rest of the cohort; floor unblocked by Tools v1.0.2 (closes #45). - **OCCTSwiftTools** — `https://github.com/gsdali/OCCTSwiftTools.git` (>= 1.0.0; resolves to v1.0.2+ for the widened Viewport constraint). Bridge layer between the B-Rep kernel and the Metal viewport. We use `CADFileLoader.shapeToBodyAndMetadata` in `render-preview` for Shape → `ViewportBody` conversion (both input bodies and highlight sub-shapes). Lives in its own repo since Viewport v0.55.0 split. - **OCCTSwiftAIS** — `https://github.com/gsdali/OCCTSwiftAIS.git` (>= 1.0.0). Headless-friendly subset only: `Trihedron` / `WorkPlane` / `Axis` / `PointCloud` scene objects (each emits `[ViewportBody]` via `makeBodies()`) for `render-preview`'s `--show-axes` / `--show-workplane` overlays, plus the SubShape selection vocabulary for `--highlight face[N]/edge[M]/vertex[K]`. Selection / Manipulator / SwiftUI surfaces aren't relevant to a CLI. `Dimension` overlays render via a SwiftUI Canvas inside `MetalViewportView` and so can't reach `OffscreenRenderer` — `--annotate-dimensions` is deferred (filed as OCCTSwiftViewport#26). Note: `OCCTSwiftAIS` re-exports a `DisplayMode` enum (3 cases) that collides with `OCCTSwiftViewport.DisplayMode` (6 cases); fully-qualify in `RenderPreview.swift` as `OCCTSwiftViewport.DisplayMode`. - **OCCTSwiftMesh** — `https://github.com/gsdali/OCCTSwiftMesh.git` (>= 1.0.0). LGPL-2.1 wrapper that vendors `meshoptimizer` (BSD-2-Clause / MIT-equivalent) inside `OCCTMeshOptimizer` for QEM decimation. Powers `simplify-mesh` via `Mesh.simplified(_:)`. Smoothing / repair / remeshing are future work. -- **OCCTSwiftIO** — `https://github.com/gsdali/OCCTSwiftIO.git` (>= 1.0.0). Provides `TopologyGraph.exportForML` / `exportJSON` via extension after OCCTSwift v0.171.0 hoisted them out of the kernel. **Pulled into the `GraphML` standalone target and the `graph-ml` verb only** — the rest of the package keeps its existing `ScriptManifest` type from `Sources/ScriptHarness/Manifest.swift` (which carries a `graphs` field that OCCTSwiftIO's `ScriptManifest` is missing). If a future verb wants progress-aware STEP loading via `ShapeLoader.load(from:format:progress:)`, broaden the dep then. +- **OCCTSwiftIO** — `https://github.com/gsdali/OCCTSwiftIO.git` (>= 1.0.0). Provides `BRepGraph.exportForML` / `exportJSON` via extension after OCCTSwift v0.171.0 hoisted them out of the kernel. **Pulled into the `GraphML` standalone target and the `graph-ml` verb only** — the rest of the package keeps its existing `ScriptManifest` type from `Sources/ScriptHarness/Manifest.swift` (which carries a `graphs` field that OCCTSwiftIO's `ScriptManifest` is missing). If a future verb wants progress-aware STEP loading via `ShapeLoader.load(from:format:progress:)`, broaden the dep then. - **macOS 15+**, **Swift 6.0+**. diff --git a/Package.resolved b/Package.resolved index 77f5add..521c9cf 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,13 +1,13 @@ { - "originHash" : "900580db2a730a42e874a9fd1f9d24315df3b8435efc49b7653a88235fce9a9d", + "originHash" : "902fcc11c2f4dd087ed5a213efa27f51334af57a8ae2692d8718df8dd65529b8", "pins" : [ { "identity" : "occtswift", "kind" : "remoteSourceControl", "location" : "https://github.com/SecondMouseAU/OCCTSwift.git", "state" : { - "revision" : "94eea64c25c265f268ecd6da6fef36b05a60ce9b", - "version" : "1.8.0" + "revision" : "b71b65760498052a3ce79c91b95a904fea6df459", + "version" : "1.15.0" } }, { @@ -15,8 +15,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SecondMouseAU/OCCTSwiftAIS.git", "state" : { - "revision" : "dcb814b6332706d40717f66c6f327698283b59cf", - "version" : "1.0.2" + "revision" : "b70a22e29b6f1dd64dcdd9ad773f3adb9fdef5a7", + "version" : "1.0.5" } }, { @@ -24,8 +24,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SecondMouseAU/OCCTSwiftIO.git", "state" : { - "revision" : "ef7a4ad2d9c057968cda24f08122534e54980f50", - "version" : "1.0.0" + "revision" : "566d870ed8551df548c3e847a8be55e0f6a6ddf1", + "version" : "1.0.2" } }, { @@ -33,8 +33,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SecondMouseAU/OCCTSwiftMesh.git", "state" : { - "revision" : "01bd6b1abce612de78081e0875e05beaaf4bfbe6", - "version" : "1.0.0" + "revision" : "fcb8b1d6efbb785f3363cf94b67d8501ae2a6a27", + "version" : "1.1.6" } }, { @@ -42,8 +42,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SecondMouseAU/OCCTSwiftTools.git", "state" : { - "revision" : "d71764d0468069369e71ee18e52c95e26a7aae0a", - "version" : "1.1.1" + "revision" : "632e1cd96560c4909e7ad949b540e208cd6b24bf", + "version" : "1.3.1" } }, { @@ -51,8 +51,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SecondMouseAU/OCCTSwiftViewport.git", "state" : { - "revision" : "6c8e95e62e2b25666ba9160af24bce22c7ccb08c", - "version" : "1.0.4" + "revision" : "66bee2038ba4b835d35f650b865241203f40c613", + "version" : "1.1.24" } } ], diff --git a/Package.swift b/Package.swift index f29b5f7..d57b161 100644 --- a/Package.swift +++ b/Package.swift @@ -86,7 +86,14 @@ let package = Package( // orientation #170, concave/convex/edges(where:) #171) are unchanged. // 1.8.0 adds Exporter.writeBREP(allowInvalid:) for the load-brep / // import `--allow-invalid` flags (OCCTMCP #41). - occtDep("OCCTSwift", from: "1.12.9"), // ≥1.12.9: OCCT kernel crash/hang fixes through #318 and #323 (patches 0003-0009) + // Bumped 1.12.9 -> 1.15.0 (OCCTSwiftScripts#78): v1.15.0 renamed the + // Swift wrapper class `TopologyGraph` -> `BRepGraph` (OCCTSwift#335) to + // match the C++ package it wraps. This repo has migrated its own + // `TopologyGraph` references to `BRepGraph`, and the bare `BRepGraph` + // symbol doesn't exist before v1.15.0 (only the deprecated typealias + // does, starting there) — the floor must track the rename, not just + // permit it via the open `from:` range. + occtDep("OCCTSwift", from: "1.15.0"), // ≥1.15.0: BRepGraph rename (OCCTSwift#335); also carries kernel crash/hang fixes through #318/#323 (patches 0003-0009) from the prior 1.12.9 floor // RenderPreview rasterizes through Viewport's OffscreenRenderer. // Floored at v1.0.4: v1.0.3 fixes an uncatchable quantize() crash on // body load (Viewport #30) and v1.0.4 makes the published Viewport @@ -117,7 +124,7 @@ let package = Package( // the `simplify-mesh` verb. occtDep("OCCTSwiftMesh", from: "1.0.0"), // OCCTSwiftIO v1.0.0 graduated alongside OCCTSwift v1.0.0. Provides - // TopologyGraph.exportForML / exportJSON via extension after OCCTSwift + // BRepGraph.exportForML / exportJSON via extension after OCCTSwift // v0.171.0 hoisted them out of the kernel. Pulled into GraphML and // graphml verbs only — the rest of the package keeps its existing // ScriptManifest type (with the `graphs` field) from ScriptHarness. diff --git a/README.md b/README.md index 5cc51e3..4c32133 100644 --- a/README.md +++ b/README.md @@ -264,7 +264,7 @@ The `occtkit` executable is a separate target — install via the `Makefile` abo - macOS 15+ - Swift 6.0+ -- [OCCTSwift](https://github.com/SecondMouseAU/OCCTSwift) `>= 1.0.1` (xcframework built against OCCT 8.0.0 GA) +- [OCCTSwift](https://github.com/SecondMouseAU/OCCTSwift) `>= 1.15.0` (xcframework built against OCCT 8.0.0 GA; floor required for the `BRepGraph` rename, see OCCTSwift#335) - [OCCTSwiftViewport](https://github.com/SecondMouseAU/OCCTSwiftViewport) `>= 1.0.0` (powers `render-preview`) - [OCCTSwiftTools](https://github.com/SecondMouseAU/OCCTSwiftTools) `>= 1.0.0` (bridge layer used by `render-preview` for Shape→ViewportBody conversion) - [OCCTSwiftAIS](https://github.com/SecondMouseAU/OCCTSwiftAIS) `>= 1.0.0` (headless overlays for `render-preview`'s `--show-axes` / `--show-workplane` / `--highlight`) diff --git a/Sources/GraphML/main.swift b/Sources/GraphML/main.swift index adc3315..6a46c45 100644 --- a/Sources/GraphML/main.swift +++ b/Sources/GraphML/main.swift @@ -7,7 +7,7 @@ import Foundation import OCCTSwift -import OCCTSwiftIO // TopologyGraph.exportForML / GraphExport extension (v0.171.0+) +import OCCTSwiftIO // BRepGraph.exportForML / GraphExport extension (v0.171.0+) import ScriptHarness struct MLExport: Codable { diff --git a/Sources/ScriptHarness/BREPGraphJSONExporter.swift b/Sources/ScriptHarness/BREPGraphJSONExporter.swift index 3929d38..8281fc7 100644 --- a/Sources/ScriptHarness/BREPGraphJSONExporter.swift +++ b/Sources/ScriptHarness/BREPGraphJSONExporter.swift @@ -1,12 +1,12 @@ // BREPGraphJSONExporter.swift // ScriptHarness // -// Serializes a TopologyGraph to a JSON file following the BREPGraph v1 schema. +// Serializes a BRepGraph to a JSON file following the BREPGraph v1 schema. import Foundation import OCCTSwift -/// Exports a `TopologyGraph` to a structured JSON file. +/// Exports a `BRepGraph` to a structured JSON file. public enum BREPGraphJSONExporter { /// Export a topology graph to a JSON file. @@ -14,7 +14,7 @@ public enum BREPGraphJSONExporter { /// - graph: The topology graph to export. /// - url: Destination file URL. /// - description: Optional description for the metadata. - public static func export(_ graph: TopologyGraph, to url: URL, description: String? = nil) throws { + public static func export(_ graph: BRepGraph, to url: URL, description: String? = nil) throws { let doc = buildDocument(graph, description: description) let encoder = JSONEncoder() encoder.outputFormatting = [.prettyPrinted, .sortedKeys] @@ -24,7 +24,7 @@ public enum BREPGraphJSONExporter { // MARK: - Document Assembly - static func buildDocument(_ g: TopologyGraph, description: String?) -> GraphDocument { + static func buildDocument(_ g: BRepGraph, description: String?) -> GraphDocument { let s = g.stats let statsBlock = StatsBlock( @@ -84,7 +84,7 @@ public enum BREPGraphJSONExporter { // MARK: - Nodes - static func buildNodes(_ g: TopologyGraph) -> NodesBlock { + static func buildNodes(_ g: BRepGraph) -> NodesBlock { // Vertices var vertices: [VertexNode] = [] for i in 0.. ReferencesBlock { - func collectRefs(_ refKind: TopologyGraph.RefKind, count: Int) -> [RefEntry] { + static func buildReferences(_ g: BRepGraph) -> ReferencesBlock { + func collectRefs(_ refKind: BRepGraph.RefKind, count: Int) -> [RefEntry] { var entries: [RefEntry] = [] for i in 0.. AdjacencyBlock { + static func buildAdjacency(_ g: BRepGraph) -> AdjacencyBlock { var f2fSrc: [Int] = [], f2fTgt: [Int] = [] var f2eSrc: [Int] = [], f2eTgt: [Int] = [] var e2vSrc: [Int] = [], e2vTgt: [Int] = [] @@ -306,7 +306,7 @@ public enum BREPGraphJSONExporter { // MARK: - Assembly - static func buildAssembly(_ g: TopologyGraph) -> AssemblyBlock { + static func buildAssembly(_ g: BRepGraph) -> AssemblyBlock { var products: [ProductEntry] = [] for i in 0.. String { + static func nodeKindName(_ kind: BRepGraph.NodeKind) -> String { switch kind { case .solid: return "solid" case .shell: return "shell" diff --git a/Sources/ScriptHarness/BREPGraphSQLiteExporter.swift b/Sources/ScriptHarness/BREPGraphSQLiteExporter.swift index 6af4bd5..8f4731a 100644 --- a/Sources/ScriptHarness/BREPGraphSQLiteExporter.swift +++ b/Sources/ScriptHarness/BREPGraphSQLiteExporter.swift @@ -1,7 +1,7 @@ // BREPGraphSQLiteExporter.swift // ScriptHarness // -// Serializes a TopologyGraph to a SQLite database with per-kind property tables, +// Serializes a BRepGraph to a SQLite database with per-kind property tables, // references, precomputed adjacency, and built-in analysis views. import Foundation @@ -11,7 +11,7 @@ import OCCTSwift import SQLite3 #endif -/// Exports a `TopologyGraph` to a SQLite database. +/// Exports a `BRepGraph` to a SQLite database. public enum BREPGraphSQLiteExporter { /// Export a topology graph to a SQLite file. @@ -19,7 +19,7 @@ public enum BREPGraphSQLiteExporter { /// - graph: The topology graph to export. /// - url: Destination `.sqlite` file URL. /// - description: Optional description stored in metadata. - public static func export(_ graph: TopologyGraph, to url: URL, description: String? = nil) throws { + public static func export(_ graph: BRepGraph, to url: URL, description: String? = nil) throws { // Remove existing file if FileManager.default.fileExists(atPath: url.path) { try FileManager.default.removeItem(at: url) @@ -252,7 +252,7 @@ public enum BREPGraphSQLiteExporter { // MARK: - Metadata - private static func insertMeta(_ db: OpaquePointer, graph g: TopologyGraph, description: String?) throws { + private static func insertMeta(_ db: OpaquePointer, graph g: BRepGraph, description: String?) throws { let metaInsert = "INSERT INTO meta (key, value) VALUES (?, ?)" try insert(db, metaInsert, "schema_version", "1.0.0") try insert(db, metaInsert, "generator", "OCCTSwift/BREPGraph") @@ -296,7 +296,7 @@ public enum BREPGraphSQLiteExporter { // MARK: - Nodes - private static func insertNodes(_ db: OpaquePointer, graph g: TopologyGraph) throws { + private static func insertNodes(_ db: OpaquePointer, graph g: BRepGraph) throws { // Vertices let nodeInsert = "INSERT INTO nodes (kind, idx, removed) VALUES (?, ?, ?)" let vtxInsert = "INSERT INTO vertex_props (idx, x, y, z, tolerance, edge_count) VALUES (?, ?, ?, ?, ?, ?)" @@ -312,7 +312,7 @@ public enum BREPGraphSQLiteExporter { let pt = g.vertexPoint(i) let removed = g.isRemoved(nodeKind: .vertex, nodeIndex: i) sqlite3_reset(nodeStmt) - sqlite3_bind_int(nodeStmt, 1, Int32(TopologyGraph.NodeKind.vertex.rawValue)) + sqlite3_bind_int(nodeStmt, 1, Int32(BRepGraph.NodeKind.vertex.rawValue)) sqlite3_bind_int(nodeStmt, 2, Int32(i)) sqlite3_bind_int(nodeStmt, 3, removed ? 1 : 0) sqlite3_step(nodeStmt) @@ -352,7 +352,7 @@ public enum BREPGraphSQLiteExporter { try insertCompSolidNodes(db, graph: g) } - private static func insertEdgeNodes(_ db: OpaquePointer, graph g: TopologyGraph) throws { + private static func insertEdgeNodes(_ db: OpaquePointer, graph g: BRepGraph) throws { let sql = """ INSERT INTO edge_props (idx, tolerance, degenerated, closed, has_curve, has_polygon_3d, same_parameter, same_range, max_continuity, range_first, range_last, @@ -377,7 +377,7 @@ public enum BREPGraphSQLiteExporter { let removed = g.isRemoved(nodeKind: .edge, nodeIndex: i) sqlite3_reset(nodeStmt) - sqlite3_bind_int(nodeStmt, 1, Int32(TopologyGraph.NodeKind.edge.rawValue)) + sqlite3_bind_int(nodeStmt, 1, Int32(BRepGraph.NodeKind.edge.rawValue)) sqlite3_bind_int(nodeStmt, 2, Int32(i)) sqlite3_bind_int(nodeStmt, 3, removed ? 1 : 0) sqlite3_step(nodeStmt) @@ -407,7 +407,7 @@ public enum BREPGraphSQLiteExporter { } } - private static func insertFaceNodes(_ db: OpaquePointer, graph g: TopologyGraph) throws { + private static func insertFaceNodes(_ db: OpaquePointer, graph g: BRepGraph) throws { let sql = """ INSERT INTO face_props (idx, tolerance, has_surface, has_triangulation, natural_restriction, wire_count, outer_wire, vertex_ref_count, shell_count, compound_count) @@ -429,7 +429,7 @@ public enum BREPGraphSQLiteExporter { for i in 0.. TopologyGraph { - guard let g = TopologyGraph(shape: shape) else { - throw ScriptError.message("Failed to build TopologyGraph from shape") + public static func buildGraph(from shape: Shape) throws -> BRepGraph { + guard let g = BRepGraph(shape: shape) else { + throw ScriptError.message("Failed to build BRepGraph from shape") } return g } /// Rebuild a Shape from the graph's roots. /// Single root → that shape; multiple → wrapped in a compound. - public static func rebuildShape(from graph: TopologyGraph) -> Shape? { + public static func rebuildShape(from graph: BRepGraph) -> Shape? { let roots = graph.rootNodes let pieces = roots.compactMap { graph.shape(nodeKind: $0.kind, nodeIndex: $0.index) } guard !pieces.isEmpty else { return nil } @@ -88,7 +88,7 @@ extension GraphIO { public let errorCount: Int public let warningCount: Int - public init(_ r: TopologyGraph.ValidationResult) { + public init(_ r: BRepGraph.ValidationResult) { self.isValid = r.isValid self.errorCount = r.errorCount self.warningCount = r.warningCount @@ -107,7 +107,7 @@ extension GraphIO { public let faces: Int } - public init(nodesBefore: Int, result: TopologyGraph.CompactResult, output: String) { + public init(nodesBefore: Int, result: BRepGraph.CompactResult, output: String) { self.nodesBefore = nodesBefore self.nodesAfter = result.nodesAfter self.removed = Removed( @@ -126,7 +126,7 @@ extension GraphIO { public let curveRewrites: Int public let output: String - public init(_ r: TopologyGraph.DeduplicateResult, output: String) { + public init(_ r: BRepGraph.DeduplicateResult, output: String) { self.canonicalSurfaces = r.canonicalSurfaces self.canonicalCurves = r.canonicalCurves self.surfaceRewrites = r.surfaceRewrites diff --git a/Sources/ScriptHarness/ScriptContext.swift b/Sources/ScriptHarness/ScriptContext.swift index 3201b82..f01c763 100644 --- a/Sources/ScriptHarness/ScriptContext.swift +++ b/Sources/ScriptHarness/ScriptContext.swift @@ -161,7 +161,7 @@ public final class ScriptContext: Sendable { try add(compound, id: id, color: color, name: name) } - // MARK: - Add TopologyGraph + // MARK: - Add BRepGraph /// Add a topology graph to the output. Exports as JSON and optionally SQLite. /// - Parameters: @@ -170,7 +170,7 @@ public final class ScriptContext: Sendable { /// - sourceBodyId: Optional body ID this graph was built from. /// - sqlite: Whether to also export a SQLite database (default: true). public func addGraph( - _ graph: TopologyGraph, + _ graph: BRepGraph, id: String? = nil, sourceBodyId: String? = nil, sqlite: Bool = true @@ -209,10 +209,10 @@ public final class ScriptContext: Sendable { } /// Build and export topology graphs for all shapes added so far. - /// Convenience method — builds a `TopologyGraph` per shape and exports each. + /// Convenience method — builds a `BRepGraph` per shape and exports each. public func addGraphsForAllShapes(sqlite: Bool = true) throws { for (shape, bodyID) in shapes.all { - guard let graph = TopologyGraph(shape: shape) else { continue } + guard let graph = BRepGraph(shape: shape) else { continue } try addGraph(graph, sourceBodyId: bodyID, sqlite: sqlite) } } diff --git a/Sources/occtkit/Commands/GraphML.swift b/Sources/occtkit/Commands/GraphML.swift index 9e64120..97ae5ad 100644 --- a/Sources/occtkit/Commands/GraphML.swift +++ b/Sources/occtkit/Commands/GraphML.swift @@ -1,6 +1,6 @@ import Foundation import OCCTSwift -import OCCTSwiftIO // TopologyGraph.exportForML / GraphExport extension (v0.171.0+) +import OCCTSwiftIO // BRepGraph.exportForML / GraphExport extension (v0.171.0+) import ScriptHarness enum GraphMLCommand: Subcommand { diff --git a/Sources/occtkit/Commands/GraphSelect.swift b/Sources/occtkit/Commands/GraphSelect.swift index f2b0ad6..77f8e35 100644 --- a/Sources/occtkit/Commands/GraphSelect.swift +++ b/Sources/occtkit/Commands/GraphSelect.swift @@ -10,7 +10,7 @@ // // Index spaces: face queries run over the Attributed Adjacency Graph (AAG), // whose face indices follow `shape.faces()` order — the same `face[N]` scheme -// `query-topology` emits. Edge/vertex queries run over the TopologyGraph +// `query-topology` emits. Edge/vertex queries run over the BRepGraph // (`edge[M]` / `vertex[K]`). Convexity is a property of the dihedral between two // faces, so it is reported on face *adjacencies* (AAG edges), not on a lone edge. // @@ -51,7 +51,7 @@ enum GraphSelectCommand: Subcommand { --query edges-class --class K edge indices matching: boundary | non-manifold | seam | degenerate Face indices follow shape.faces() order (the `face[N]` scheme query-topology emits); - edge/vertex indices are TopologyGraph indices (`edge[M]` / `vertex[K]`). + edge/vertex indices are BRepGraph indices (`edge[M]` / `vertex[K]`). """ // MARK: responses diff --git a/docs/guides/architecture.md b/docs/guides/architecture.md index 8a65629..72143bc 100644 --- a/docs/guides/architecture.md +++ b/docs/guides/architecture.md @@ -87,7 +87,7 @@ OCCTSwift B-Rep kernel (~400+ methods), ISO drawings, FeatureReconstr ├─ OCCTSwiftTools CADFileLoader (Shape → ViewportBody) → render-preview ├─ OCCTSwiftAIS Trihedron / WorkPlane / SubShape selection → render-preview overlays ├─ OCCTSwiftMesh meshoptimizer QEM decimation → simplify-mesh - └─ OCCTSwiftIO TopologyGraph.exportForML → graph-ml + └─ OCCTSwiftIO BRepGraph.exportForML → graph-ml │ OCCTSwiftScripts ── ScriptHarness + DrawingComposer + occtkit (29 verbs) │ diff --git a/docs/guides/cookbook/topology-graph.md b/docs/guides/cookbook/topology-graph.md index 42d8489..3aa1740 100644 --- a/docs/guides/cookbook/topology-graph.md +++ b/docs/guides/cookbook/topology-graph.md @@ -210,7 +210,7 @@ occtkit graph-select bracket_clean.brep --query edges-class --class boundary } ``` -Face indices follow `shape.faces()` order; edge and vertex indices are TopologyGraph indices. +Face indices follow `shape.faces()` order; edge and vertex indices are BRepGraph indices. --- diff --git a/docs/reference/ScriptHarness.md b/docs/reference/ScriptHarness.md index 26e3a98..d963a8d 100644 --- a/docs/reference/ScriptHarness.md +++ b/docs/reference/ScriptHarness.md @@ -113,10 +113,10 @@ try ctx.addCompound([a, b], id: "assembly", color: C.gray) // compound These are consumed by `occtkit graph-query` and the viewport's graph tooling. ```swift -public func addGraph(_ graph: TopologyGraph, id: String? = nil, +public func addGraph(_ graph: BRepGraph, id: String? = nil, sourceBodyId: String? = nil, sqlite: Bool = true) throws -/// Build + export a TopologyGraph for every shape added so far. +/// Build + export a BRepGraph for every shape added so far. public func addGraphsForAllShapes(sqlite: Bool = true) throws ``` diff --git a/docs/reference/occtkit-verbs.md b/docs/reference/occtkit-verbs.md index 23c2a2b..57970cc 100644 --- a/docs/reference/occtkit-verbs.md +++ b/docs/reference/occtkit-verbs.md @@ -162,7 +162,7 @@ DSL selectors and B-rep GNN selection (no full graph export needed). **Input:** `graph-select --query [ids]`. Queries: `face-neighbors --face N` · `edge-faces --edge M` · `vertex-edges --vertex K` · `face-adjacency` · `edges-class --class boundary|non-manifold|seam|degenerate`. -Face indices follow `shape.faces()` order (AAG); edge/vertex indices are TopologyGraph indices. +Face indices follow `shape.faces()` order (AAG); edge/vertex indices are BRepGraph indices. **Output:** per-query JSON tagged with `query`, e.g. `face-neighbors` returns `{ face, isPlanar, isVertical, isHorizontal, normal, neighbors[{face,convexity,sharedEdgeCount}] }`. diff --git a/docs/reference/script-harness.md b/docs/reference/script-harness.md index 212a7c7..21e3b97 100644 --- a/docs/reference/script-harness.md +++ b/docs/reference/script-harness.md @@ -208,7 +208,7 @@ Export a topology graph as JSON and optionally SQLite. ```swift try ctx.addGraph( - _ graph: TopologyGraph, + _ graph: BRepGraph, id: String? = nil, sourceBodyId: String? = nil, sqlite: Bool = true @@ -219,7 +219,7 @@ try ctx.addGraph( | name | type | required | description | |------|------|:--------:|-------------| -| `graph` | `TopologyGraph` | yes | A topology graph built from a shape | +| `graph` | `BRepGraph` | yes | A topology graph built from a shape | | `id` | `String?` | no | Graph identifier; default `"graph-N"` | | `sourceBodyId` | `String?` | no | Body ID this graph was derived from (for reference) | | `sqlite` | `Bool` | no | Also write a SQLite database (default `true`) | @@ -232,7 +232,7 @@ try ctx.addGraph( ```swift let shape = Shape.box(width: 10, height: 10, depth: 10)! try ctx.add(shape, id: "part") -if let graph = TopologyGraph(shape: shape) { +if let graph = BRepGraph(shape: shape) { try ctx.addGraph(graph, sourceBodyId: "part", sqlite: true) } ``` @@ -256,7 +256,7 @@ try ctx.addGraphsForAllShapes(sqlite: Bool = true) throws | `sqlite` | `Bool` | no | Also write SQLite databases (default `true`) | **What it does** — Convenience method that iterates all accumulated shapes, builds a -`TopologyGraph` for each, and exports each to JSON + optional SQLite. Skips shapes that fail +`BRepGraph` for each, and exports each to JSON + optional SQLite. Skips shapes that fail to build a graph. Each graph is linked to its source body ID in the manifest. **Example** diff --git a/docs/reference/topology-graph.md b/docs/reference/topology-graph.md index 22b10b5..3ea6b59 100644 --- a/docs/reference/topology-graph.md +++ b/docs/reference/topology-graph.md @@ -51,7 +51,7 @@ occtkit graph-validate shape.brep } ``` -**Drives** — `TopologyGraph.validate()` + `Shape.analyze()`. +**Drives** — `BRepGraph.validate()` + `Shape.analyze()`. --- @@ -88,7 +88,7 @@ occtkit graph-compact shape.brep shape_compact.brep } ``` -**Drives** — `TopologyGraph.compact()`. +**Drives** — `BRepGraph.compact()`. --- @@ -122,7 +122,7 @@ occtkit graph-dedup assembly.brep assembly_dedup.brep } ``` -**Drives** — `TopologyGraph.deduplicate()`. +**Drives** — `BRepGraph.deduplicate()`. --- @@ -218,7 +218,7 @@ occtkit graph-ml shape.brep --uv-samples 12 --edge-samples 24 } ``` -**Drives** — `TopologyGraph.exportForML()` + `AAG` (Attributed Adjacency Graph). +**Drives** — `BRepGraph.exportForML()` + `AAG` (Attributed Adjacency Graph). **Notes** — Face indices in `faceAdjacency` follow `shape.faces()` order (the same `face[N]` scheme `query-topology` emits). Convexity is a property of the dihedral between two faces: `"convex"` (outward-pointing), `"concave"` (inward), or `"smooth"` (near-zero curvature). @@ -237,8 +237,8 @@ Query B-rep graph adjacency and selection — return a focused neighbourhood rat | `` | string | yes | Path to the BREP file. | | `--query` | string | yes | One of `face-neighbors` \| `edge-faces` \| `vertex-edges` \| `face-adjacency` \| `edges-class`. | | `--face` | integer | no | Face index (required for `face-neighbors`). Follows `shape.faces()` order. | -| `--edge` | integer | no | Edge index (required for `edge-faces`). TopologyGraph index. | -| `--vertex` | integer | no | Vertex index (required for `vertex-edges`). TopologyGraph index. | +| `--edge` | integer | no | Edge index (required for `edge-faces`). BRepGraph index. | +| `--vertex` | integer | no | Vertex index (required for `vertex-edges`). BRepGraph index. | | `--class` | string | no | Edge class filter (required for `edges-class`): one of `boundary` \| `non-manifold` \| `seam` \| `degenerate`. | **Returns** — Depends on `--query`: @@ -268,6 +268,6 @@ occtkit graph-select shape.brep --query face-neighbors --face 2 } ``` -**Drives** — `AAG` (face queries) and `TopologyGraph` (edge/vertex queries). +**Drives** — `AAG` (face queries) and `BRepGraph` (edge/vertex queries). -**Notes** — Face indices follow `shape.faces()` order (the `face[N]` scheme from `query-topology`). Edge and vertex indices are TopologyGraph indices. The correct secondary parameter to supply depends on `--query`: `--face` for `face-neighbors`, `--edge` for `edge-faces`, `--vertex` for `vertex-edges`, `--class` for `edges-class`; none needed for `face-adjacency`. +**Notes** — Face indices follow `shape.faces()` order (the `face[N]` scheme from `query-topology`). Edge and vertex indices are BRepGraph indices. The correct secondary parameter to supply depends on `--query`: `--face` for `face-neighbors`, `--edge` for `edge-faces`, `--vertex` for `vertex-edges`, `--class` for `edges-class`; none needed for `face-adjacency`.