5e2812a6f3
v6.2.1 — Blender Integration Addon: - 5 files, 1,732 lines: __init__, operators (9 ops), panels (4 panels) - preferences, vde_bridge (subprocess CLI bridge) - Import/Export STEP, primitives, boolean, SDF→Mesh v6.2.2 — .NET/C# Bindings (VdeSharp): - 8 files: NativeMethods (50+ P/Invoke), BrepModel, MeshData, SdfEngine, Assembly - C API extended with 20 new functions (STEP I/O, Boolean, SDF, Assembly) - vde_capi rebuilt as SHARED library - Example: import STEP → boolean → export v6.2.3 — Developer Docs + Plugin System: - 7 docs: architecture, contributing, API overview, building, testing, plugin-system - plugin_system.h/.cpp: PluginInterface, PluginManager, dlopen/LoadLibrary - README.md updated with v6 features - Syntax-check passed (GCC 10.2.1, -Wall -Wextra -Wpedantic)
192 lines
6.5 KiB
C#
192 lines
6.5 KiB
C#
using System.Runtime.InteropServices;
|
||
|
||
namespace VdeSharp;
|
||
|
||
/// <summary>
|
||
/// Managed wrapper around a native VDE B-Rep model (VdeBodyHandle).
|
||
/// Provides STEP/IGES import/export, Boolean operations, and mesh tessellation.
|
||
/// </summary>
|
||
public class BrepModel : IDisposable
|
||
{
|
||
/// <summary>Native engine context handle</summary>
|
||
private readonly nint _ctx;
|
||
|
||
/// <summary>Native B-Rep body handle</summary>
|
||
internal nint _handle;
|
||
|
||
private bool _disposed;
|
||
|
||
/// <summary>Returns the native handle (for internal use).</summary>
|
||
internal nint Handle => _handle;
|
||
|
||
/// <summary>
|
||
/// Wraps an existing native body handle. Used internally by factory methods.
|
||
/// </summary>
|
||
internal BrepModel(nint ctx, nint handle)
|
||
{
|
||
_ctx = ctx;
|
||
_handle = handle;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates a box primitive.
|
||
/// </summary>
|
||
public static BrepModel CreateBox(nint ctx, double w, double h, double d)
|
||
{
|
||
nint hdl = NativeMethods.vde_body_create_box(ctx, w, h, d);
|
||
return new BrepModel(ctx, hdl);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates a cylinder primitive.
|
||
/// </summary>
|
||
public static BrepModel CreateCylinder(nint ctx, double radius, double height, int segments = 32)
|
||
{
|
||
nint hdl = NativeMethods.vde_body_create_cylinder(ctx, radius, height, segments);
|
||
return new BrepModel(ctx, hdl);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates a sphere primitive.
|
||
/// </summary>
|
||
public static BrepModel CreateSphere(nint ctx, double radius, int su = 32, int sv = 32)
|
||
{
|
||
nint hdl = NativeMethods.vde_body_create_sphere(ctx, radius, su, sv);
|
||
return new BrepModel(ctx, hdl);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Imports B-Rep models from a STEP file.
|
||
/// Returns an array of BrepModel instances.
|
||
/// </summary>
|
||
public static unsafe BrepModel[] LoadStep(nint ctx, string path)
|
||
{
|
||
nint* bodiesPtr;
|
||
int count = NativeMethods.vde_body_load_step(ctx, path, &bodiesPtr);
|
||
if (count <= 0) return Array.Empty<BrepModel>();
|
||
|
||
var result = new BrepModel[count];
|
||
for (int i = 0; i < count; i++)
|
||
result[i] = new BrepModel(ctx, bodiesPtr[i]);
|
||
|
||
// Free the pointer array (but NOT the individual handles)
|
||
Marshal.FreeHGlobal((nint)bodiesPtr);
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Imports B-Rep models from an IGES file.
|
||
/// </summary>
|
||
public static unsafe BrepModel[] LoadIges(nint ctx, string path)
|
||
{
|
||
nint* bodiesPtr;
|
||
int count = NativeMethods.vde_body_load_iges(ctx, path, &bodiesPtr);
|
||
if (count <= 0) return Array.Empty<BrepModel>();
|
||
|
||
var result = new BrepModel[count];
|
||
for (int i = 0; i < count; i++)
|
||
result[i] = new BrepModel(ctx, bodiesPtr[i]);
|
||
|
||
Marshal.FreeHGlobal((nint)bodiesPtr);
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Exports a list of BrepModel instances to a STEP file.
|
||
/// </summary>
|
||
public static void SaveStep(nint ctx, BrepModel[] bodies, string path)
|
||
{
|
||
var handles = new nint[bodies.Length];
|
||
for (int i = 0; i < bodies.Length; i++)
|
||
handles[i] = bodies[i]._handle;
|
||
NativeMethods.vde_body_save_step(ctx, handles, handles.Length, path);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Exports a list of BrepModel instances to an IGES file.
|
||
/// </summary>
|
||
public static void SaveIges(nint ctx, BrepModel[] bodies, string path)
|
||
{
|
||
var handles = new nint[bodies.Length];
|
||
for (int i = 0; i < bodies.Length; i++)
|
||
handles[i] = bodies[i]._handle;
|
||
NativeMethods.vde_body_save_iges(ctx, handles, handles.Length, path);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Saves this single body to a STEP file.
|
||
/// </summary>
|
||
public void SaveStep(string path)
|
||
=> SaveStep(_ctx, new[] { this }, path);
|
||
|
||
/// <summary>
|
||
/// Saves this single body to an IGES file.
|
||
/// </summary>
|
||
public void SaveIges(string path)
|
||
=> SaveIges(_ctx, new[] { this }, path);
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// Boolean operations
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
/// <summary>Boolean union: this ∪ other</summary>
|
||
public BrepModel Union(BrepModel other)
|
||
{
|
||
nint hdl = NativeMethods.vde_body_boolean(_ctx, _handle, other._handle, 0);
|
||
return new BrepModel(_ctx, hdl);
|
||
}
|
||
|
||
/// <summary>Boolean intersection: this ∩ other</summary>
|
||
public BrepModel Intersect(BrepModel other)
|
||
{
|
||
nint hdl = NativeMethods.vde_body_boolean(_ctx, _handle, other._handle, 1);
|
||
return new BrepModel(_ctx, hdl);
|
||
}
|
||
|
||
/// <summary>Boolean difference: this \ other</summary>
|
||
public BrepModel Diff(BrepModel other)
|
||
{
|
||
nint hdl = NativeMethods.vde_body_boolean(_ctx, _handle, other._handle, 2);
|
||
return new BrepModel(_ctx, hdl);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// Tessellation / Mesh
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
/// <summary>
|
||
/// Tessellates the B-Rep model into a triangle mesh.
|
||
/// </summary>
|
||
/// <param name="deflection">Chord height error for tessellation (default 0.01)</param>
|
||
public MeshData ToMesh(double deflection = 0.01)
|
||
{
|
||
nint mh = NativeMethods.vde_body_to_mesh(_ctx, _handle, deflection);
|
||
var mesh = new MeshData(mh, ownsHandle: true);
|
||
mesh.ExtractFromNative();
|
||
return mesh;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Deep clone of this B-Rep model.
|
||
/// </summary>
|
||
public BrepModel Clone()
|
||
{
|
||
nint hdl = NativeMethods.vde_body_clone(_ctx, _handle);
|
||
return new BrepModel(_ctx, hdl);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// IDisposable
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
public void Dispose()
|
||
{
|
||
if (!_disposed && _handle != nint.Zero)
|
||
{
|
||
NativeMethods.vde_body_free(_handle);
|
||
_handle = nint.Zero;
|
||
_disposed = true;
|
||
}
|
||
}
|
||
}
|