I’m trying to find the intersection of two lofted surfaces via .NET. The 2009 BREP namespace only allows direct conversion of solids and regions, as far as I can tell.
There is a method using P/Invoke to expose unmanaged code – as demonstrated in the Autodesk Brep WebCast (
http://download.autodesk.com/media/adn/ACADBrep.NETAPIWebcast_24Jun08.zip)
The Brep conversion actually works well enough to allow the construction of a Autodesk.AutoCAD.Geometry.SurfaceSurfaceIntersector object, and even return the geometry to append the appropriate curve.
The problem is that a minute or two after running the routine AutoCAD crashes. Testing the routine from the Webcast, it, too, crashes shortly (1 - 3 min) after running.
It seems like some reference/pointer is left unresolved: Any suggestions on a better dispose method?
The pertinent code from that webcast is shown below -
// (C) Copyright 2002-2007 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
public class LibWrap
{
// Declaration to P/Invoke the "body" method on the AcDbSurface object
[DllImport("acdb17.dll",
EntryPoint = "?body@AcDbSurface@@UBEPAXXZ",
CallingConvention = CallingConvention.ThisCall)]
public static extern IntPtr GetSurfBody(IntPtr ths);
// Declaration to P/Invoke the "setBody" method on the AcDbBody object
[DllImport("acdb17.dll",
EntryPoint = "?setBody@AcDbBody@@UAE?AW4ErrorStatus@Acad@@PBX@Z",
CallingConvention = CallingConvention.ThisCall)]
public static extern int CreateSurfBdy(IntPtr ths, IntPtr bdyPtr);
}
[CommandMethod("SurfaceIntero")]
static public void SurfaceIntero() // This method can have any name
{
// Method to interrogate the AutoCAD Surface object using the B-Rep API
// Obtain the necessary objects, Database, editor and transaction
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Transaction tr = db.TransactionManager.StartTransaction();
try
{
// Prompt to select a surface
PromptEntityOptions prEntOpt = new PromptEntityOptions("Select a Surface: ");
prEntOpt.SetRejectMessage("\nPlease select only a Surface");
prEntOpt.AddAllowedClass(typeof(Autodesk.AutoCAD.DatabaseServices.Surface), true);
PromptEntityResult prEntRes = ed.GetEntity(prEntOpt);
Autodesk.AutoCAD.DatabaseServices.Surface surf = (Autodesk.AutoCAD.DatabaseServices.Surface)tr.GetObject(prEntRes.ObjectId, OpenMode.ForRead);
// Use P/Invoke to obtain the unmanaged body pointer for the surface object. We need to do this
// because unfortunately, the BRep .NET API does not directly reference the body object within the surface
IntPtr bdyPtr = LibWrap.GetSurfBody(surf.UnmanagedObject);
//(Body)Body.Create(bdyPtr, false);
// Create a new Body object
Body bdy = new Body();
// Use P/Invoke to set the newly created body object with the data from the
// Surface body object
LibWrap.CreateSurfBdy(bdy.UnmanagedObject, bdyPtr);
// Now we can create the BRep topology object
Brep brp = new Brep(bdy);
//ObjectId[] objIds = { prEntRes.ObjectId };
//FullSubentityPath fullSubPath = new FullSubentityPath(objIds, SubentityId.Null);
//BrepEntity brp = new Autodesk.AutoCAD.BoundaryRepresentation.Face(fullSubPath);
// Find the area of the faces on the Surface
foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face fc in brp.Faces)
{
ed.WriteMessage("\nThe surface area: {0}", fc.GetSurfaceArea());
//fc.Dispose();
}
//brp.Dispose();
tr.Commit();
bdy.Dispose();
}
catch (System.Exception ex)
{
ed.WriteMessage("Exception in SurfaceTrav: {0}", ex.Message);
}
finally
{
tr.Dispose();
}
}