Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ let package = Package(
// setters no-op but getters return the live derived value. The cookbook
// ergonomics relied on since v1.3.1 (circularPatternCut #169, sweep
// orientation #170, concave/convex/edges(where:) #171) are unchanged.
.package(url: "https://github.com/gsdali/OCCTSwift.git", from: "1.7.1"),
// 1.8.0 adds Exporter.writeBREP(allowInvalid:) for the load-brep /
// import `--allow-invalid` flags (OCCTMCP #41).
.package(url: "https://github.com/gsdali/OCCTSwift.git", from: "1.8.0"),
// 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
Expand Down
7 changes: 5 additions & 2 deletions Sources/ScriptHarness/GraphIO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ public enum GraphIO {
}
}

public static func writeBREP(_ shape: Shape, to path: String) throws {
/// - Parameter allowInvalid: skip the `shape.isValid` write gate so an
/// in-progress / loose-face reconstruction can be persisted as-is
/// (OCCTSwift ≥ 1.8.0; loadBREP doesn't gate on read).
public static func writeBREP(_ shape: Shape, to path: String, allowInvalid: Bool = false) throws {
let url = URL(fileURLWithPath: path)
do {
try Exporter.writeBREP(shape: shape, to: url)
try Exporter.writeBREP(shape: shape, to: url, allowInvalid: allowInvalid)
} catch {
throw ScriptError.message("Failed to write BREP at \(path): \(error.localizedDescription)")
}
Expand Down
27 changes: 19 additions & 8 deletions Sources/occtkit/Commands/Import.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ enum ImportCommand: Subcommand {
Usage:
import <input> --emit-manifest <dir>
[--format auto|step|iges|stl|obj]
[--id-prefix <p>] [--preserve-assembly] [--heal-on-import]
[--id-prefix <p>] [--preserve-assembly] [--heal-on-import] [--allow-invalid]
import <request.json> (JSON request from file)
import (JSON request from stdin)
"""
Expand All @@ -55,6 +55,7 @@ enum ImportCommand: Subcommand {
var idPrefix: String
var preserveAssembly: Bool
var healOnImport: Bool
var allowInvalid: Bool
}

private enum Format: String, Decodable {
Expand All @@ -68,6 +69,7 @@ enum ImportCommand: Subcommand {
let idPrefix: String?
let preserveAssembly: Bool?
let healOnImport: Bool?
let allowInvalid: Bool?
}

struct Response: Encodable {
Expand Down Expand Up @@ -107,7 +109,8 @@ enum ImportCommand: Subcommand {
let document = try loadDocumentSTEP(path: req.inputPath)
assembly = try walkAssembly(
document: document, emitDir: emitDir,
idPrefix: req.idPrefix, bodies: &bodies, addedIds: &addedIds
idPrefix: req.idPrefix, allowInvalid: req.allowInvalid,
bodies: &bodies, addedIds: &addedIds
)
} else {
if req.preserveAssembly && format != .step {
Expand All @@ -116,7 +119,7 @@ enum ImportCommand: Subcommand {
let shape = try loadSingleShape(format: format, path: req.inputPath)
let id = "\(req.idPrefix)_0"
let bodyURL = emitDir.appendingPathComponent("\(id).brep")
try GraphIO.writeBREP(shape, to: bodyURL.path)
try GraphIO.writeBREP(shape, to: bodyURL.path, allowInvalid: req.allowInvalid)
bodies.append(BodyDescriptor(id: id, file: "\(id).brep"))
addedIds.append(id)
}
Expand Down Expand Up @@ -185,6 +188,7 @@ enum ImportCommand: Subcommand {
document: Document,
emitDir: URL,
idPrefix: String,
allowInvalid: Bool,
bodies: inout [BodyDescriptor],
addedIds: inout [String]
) throws -> Response.Assembly {
Expand All @@ -195,7 +199,8 @@ enum ImportCommand: Subcommand {
for root in roots {
let component = try walkNode(
node: root, idPrefix: idPrefix, parentPathSegment: nil,
emitDir: emitDir, bodies: &bodies, addedIds: &addedIds, counter: &counter
emitDir: emitDir, allowInvalid: allowInvalid,
bodies: &bodies, addedIds: &addedIds, counter: &counter
)
components.append(component)
}
Expand All @@ -209,6 +214,7 @@ enum ImportCommand: Subcommand {
idPrefix: String,
parentPathSegment: String?,
emitDir: URL,
allowInvalid: Bool,
bodies: inout [BodyDescriptor],
addedIds: inout [String],
counter: inout Int
Expand All @@ -219,7 +225,7 @@ enum ImportCommand: Subcommand {
// Write geometry if this node has any (pure-assembly nodes have no shape).
if let shape = node.shape {
let bodyURL = emitDir.appendingPathComponent("\(id).brep")
try GraphIO.writeBREP(shape, to: bodyURL.path)
try GraphIO.writeBREP(shape, to: bodyURL.path, allowInvalid: allowInvalid)
bodies.append(BodyDescriptor(
id: id,
file: "\(id).brep",
Expand All @@ -238,7 +244,8 @@ enum ImportCommand: Subcommand {
for child in node.children {
children.append(try walkNode(
node: child, idPrefix: idPrefix, parentPathSegment: id,
emitDir: emitDir, bodies: &bodies, addedIds: &addedIds, counter: &counter
emitDir: emitDir, allowInvalid: allowInvalid,
bodies: &bodies, addedIds: &addedIds, counter: &counter
))
}

Expand Down Expand Up @@ -272,6 +279,7 @@ enum ImportCommand: Subcommand {
var idPrefix: String = "imported"
var preserveAssembly = false
var healOnImport = false
var allowInvalid = false
var i = 1
while i < args.count {
switch args[i] {
Expand All @@ -290,6 +298,8 @@ enum ImportCommand: Subcommand {
preserveAssembly = true
case "--heal-on-import":
healOnImport = true
case "--allow-invalid":
allowInvalid = true
default:
throw ScriptError.message("Unknown flag: \(args[i])")
}
Expand All @@ -298,7 +308,7 @@ enum ImportCommand: Subcommand {
guard let emitManifest else { throw ScriptError.message("--emit-manifest is required") }
return Request(inputPath: inputPath, emitManifest: emitManifest, format: format,
idPrefix: idPrefix, preserveAssembly: preserveAssembly,
healOnImport: healOnImport)
healOnImport: healOnImport, allowInvalid: allowInvalid)
}

private static func valueOrThrow(args: [String], i: Int, flag: String) throws -> String {
Expand Down Expand Up @@ -326,7 +336,8 @@ enum ImportCommand: Subcommand {
format: raw.format ?? .auto,
idPrefix: raw.idPrefix ?? "imported",
preserveAssembly: raw.preserveAssembly ?? false,
healOnImport: raw.healOnImport ?? false
healOnImport: raw.healOnImport ?? false,
allowInvalid: raw.allowInvalid ?? false
)
}
}
14 changes: 10 additions & 4 deletions Sources/occtkit/Commands/LoadBrep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ enum LoadBrepCommand: Subcommand {
static let summary = "Load a BREP and emit a manifest entry for OCCTSwiftViewport"
static let usage = """
Usage:
load-brep <input.brep> --emit-manifest <dir> [--id <bodyId>] [--color <hex>]
load-brep <input.brep> --emit-manifest <dir> [--id <bodyId>] [--color <hex>] [--allow-invalid]
load-brep <request.json> (JSON request from file)
load-brep (JSON request from stdin)
"""
Expand All @@ -39,13 +39,15 @@ enum LoadBrepCommand: Subcommand {
var emitManifest: String
var id: String?
var color: String?
var allowInvalid: Bool
}

private struct JSONRequest: Decodable {
let inputBrep: String
let emitManifest: String
let id: String?
let color: String?
let allowInvalid: Bool?
}

struct Response: Encodable {
Expand All @@ -71,7 +73,7 @@ enum LoadBrepCommand: Subcommand {
let emitDir = URL(fileURLWithPath: req.emitManifest)
try? FileManager.default.createDirectory(at: emitDir, withIntermediateDirectories: true)
let bodyURL = emitDir.appendingPathComponent("\(bodyId).brep")
try GraphIO.writeBREP(shape, to: bodyURL.path)
try GraphIO.writeBREP(shape, to: bodyURL.path, allowInvalid: req.allowInvalid)

let manifest = ScriptManifest(
description: "Imported via load-brep",
Expand Down Expand Up @@ -104,6 +106,7 @@ enum LoadBrepCommand: Subcommand {
var emitManifest: String?
var id: String?
var color: String?
var allowInvalid = false
var i = 1
while i < args.count {
switch args[i] {
Expand All @@ -119,13 +122,16 @@ enum LoadBrepCommand: Subcommand {
i += 1
guard i < args.count else { throw ScriptError.message("--color expects a value") }
color = args[i]
case "--allow-invalid":
allowInvalid = true
default:
throw ScriptError.message("Unknown flag: \(args[i])")
}
i += 1
}
guard let emitManifest else { throw ScriptError.message("--emit-manifest is required") }
return Request(inputBrep: inputBrep, emitManifest: emitManifest, id: id, color: color)
return Request(inputBrep: inputBrep, emitManifest: emitManifest, id: id, color: color,
allowInvalid: allowInvalid)
}

private static func readFile(_ path: String) throws -> Data {
Expand All @@ -143,7 +149,7 @@ enum LoadBrepCommand: Subcommand {
throw ScriptError.message("Invalid JSON: \(error.localizedDescription)")
}
return Request(inputBrep: raw.inputBrep, emitManifest: raw.emitManifest,
id: raw.id, color: raw.color)
id: raw.id, color: raw.color, allowInvalid: raw.allowInvalid ?? false)
}

// MARK: - Helpers (shared with Import)
Expand Down
Loading