using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.Civil;
using Autodesk.Civil.DatabaseServices;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices.Styles;
namespace ALC_SurfaceBoundery
{
public class MyCommands
{
public static ObjectId SelectSurface()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
ObjectId result = ObjectId.Null;
PromptEntityOptions entOpts = new PromptEntityOptions("\nSelect surface: ");
entOpts.SetRejectMessage("...not a surface, try again!:");
entOpts.AddAllowedClass(typeof(TinSurface), true);
PromptEntityResult entRes = ed.GetEntity(entOpts);
if (entRes.Status == PromptStatus.OK) result = entRes.ObjectId;
return result;
}
[CommandMethod("alcSurfaceBounderyFromSurface")]
public void alcSB()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
CivilDocument civdoc = CivilApplication.ActiveDocument;
Database db = Application.DocumentManager.MdiActiveDocument.Database;
Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = db.TransactionManager;
ed.WriteMessage("\nFirst surface:");
ObjectId idSurface1= SelectSurface();
if (idSurface1 == ObjectId.Null) return;
ed.WriteMessage("\nSecond surface:");
ObjectId idSurface2 = SelectSurface();
if (idSurface2 == ObjectId.Null) return;
using (Transaction trans = tm.StartTransaction())
{
try
{
TinSurface s1 = tm.GetObject(idSurface1, OpenMode.ForWrite) as TinSurface;
TinSurface s2 = tm.GetObject(idSurface2, OpenMode.ForRead) as TinSurface;
ObjectIdCollection objIdCol1 = new ObjectIdCollection ();
// list all boundaries off surface 2 from definition
if (s2.BoundariesDefinition.Count > 0)
{
for (int i = 0; i < s2.BoundariesDefinition.Count; i++)
{
SurfaceOperationAddBoundary soab = s2.BoundariesDefinition[i];
ed.WriteMessage("\n {0}, Type {1}, ", soab.Name.ToString(), soab.BoundaryType.ToString());
foreach (SurfaceBoundary sb in soab)
{
Point3dCollection v = sb.Vertices;
ed.WriteMessage(" Vertices: {0}", v.Count);
for (int j = 0; j < v.Count; j++)
{
ed.WriteMessage("\n" + v[j].ToString());
}
}
}
}
// check for outer boundery in the Surface defenitions
bool isOuterBounderyDefined = false;
if (s2.BoundariesDefinition.Count > 0)
{
for (int i = 0; i < s2.BoundariesDefinition.Count; i++)
{
SurfaceOperationAddBoundary soab = s2.BoundariesDefinition[i];
if (soab[0].BoundaryType == SurfaceBoundaryType.Outer)
{
Point3dCollection v = soab[0].Vertices;
isOuterBounderyDefined = true;
// add the vertices as hide boundery to surface 1
s1.BoundariesDefinition.AddBoundaries(v, 0.1, SurfaceBoundaryType.Hide, true);
ed.WriteMessage("\nOuter boundary found");
break;
}
}
}
if (!isOuterBounderyDefined)
{
ed.WriteMessage("\nNo outer boundary found, will be created by Extract Border");
// extracte border from surface 2 and add as hide boundary to surface 1
// create a new style called 'example style':
ObjectId idStyle = civdoc.Styles.SurfaceStyles.Add("Extraction");
// modify the style to display boundaries, exterior only:
SurfaceStyle ss = idStyle.GetObject(OpenMode.ForWrite) as SurfaceStyle;
ss.GetDisplayStylePlan(SurfaceDisplayStyleType.Boundary).Visible = true;
ss.BoundaryStyle.DisplayExteriorBoundaries = true;
ss.BoundaryStyle.DisplayInteriorBoundaries = false;
// assign this style to the surface
ObjectId idCurrent = s2.StyleId;
s2.StyleId = idStyle;
//extract the exterior border
ObjectIdCollection borders = s2.ExtractBorder(SurfaceExtractionSettingsType.Plan);
s1.BoundariesDefinition.AddBoundaries(borders, 0.1, SurfaceBoundaryType.Hide, true);
// change back the style
s2.StyleId = idStyle;
civdoc.Styles.SurfaceStyles.Remove("Extraction");
}
// process show and hide boundaries
if (s2.BoundariesDefinition.Count > 0)
{
for (int i = 0; i < s2.BoundariesDefinition.Count; i++)
{
if (s2.BoundariesDefinition[i].BoundaryType == SurfaceBoundaryType.Hide)
{
Point3dCollection v = s2.BoundariesDefinition[i][0].Vertices;
// add the vertices as show boundery to surface 1
ed.WriteMessage("\n Innner boundary (hole) found with {0} vertices", v.Count);
for (int j = 0; j < v.Count; j++)
{
ed.WriteMessage("\n" + v[j].ToString());
}
s1.BoundariesDefinition.AddBoundaries(v, 0.1, SurfaceBoundaryType.Show, true);
}
if (s2.BoundariesDefinition[i].BoundaryType == SurfaceBoundaryType.Show)
{
Point3dCollection v = s2.BoundariesDefinition[i][0].Vertices;
// add the vertices as show boundery to surface 1
ed.WriteMessage("\n innner boundary (island) found with {0} verices", v.Count);
s1.BoundariesDefinition.AddBoundaries(v, 0.1, SurfaceBoundaryType.Hide, true);
}
}
}
s1.Rebuild();
}
catch
{
ed.WriteMessage("\n Does not work");
}
trans.Commit();
}
}
}
}
With surfaces that has polylines as boundaries it works well, but I could not figure out yet how to handle if your surface for creating the boundary is also build by surfaces as boundaries.
Regards
Andreas Luka (Lu An Jie)
http://www.luka-consult.de
Creator of the LX-Stair App for Civil 3D