using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections;
using System.Linq;
namespace AcadTest
{
public class FlatSolidTest
{
[CommandMethod("FlatSolidTestRun")]
public void RunCmd()
{
SupportMethods.InitializeVars(out Document adoc, out Editor ed, out Database db);
if (SupportMethods.SelectEntity<Solid3d>(ed, out ObjectId id)
&& SupportMethods.GetPoint(ed, out Point3d pt, "\nSection base point: ")
&& SupportMethods.GetNextPoint(ed, pt, out Point3d secondPt, "\nSecond section point: ")
&& SupportMethods.GetPoint(ed, out Point3d forInsPt, "\nForeground objects position: ")
&& SupportMethods.GetNextPoint(ed, forInsPt, out Point3d viewInsPt, "\nBackground objects position: ")
&& SupportMethods.GetNextPoint(ed, viewInsPt, out Point3d intersInsPt, "\nIntersection objects position: "))
{
Vector3d viewDir;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord space = tr.GetObject
(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
Solid3d solid = tr.GetObject(id, OpenMode.ForRead) as Solid3d;
GetSectionEntities
(tr,
solid,
pt,
secondPt,
Vector3d.ZAxis,
true,
0.5,
out Entity[] forEnts,
out Entity[] backEnts,
out Entity[] intersEnts,
out viewDir);
void AddCol(Entity[] col, short colorIndex, Point3d pos)
{
Matrix3d move = Matrix3d.Displacement(pt.GetVectorTo(pos));
foreach (Entity ent in col)
{
ent.TransformBy(move);
ent.ColorIndex = colorIndex;
space.AppendEntity(ent);
tr.AddNewlyCreatedDBObject(ent, true);
}
}
AddCol(forEnts, 3, forInsPt);
AddCol(backEnts, 4, viewInsPt);
AddCol(intersEnts, 1, intersInsPt);
tr.Commit();
}
ed.WriteMessage("\nSection view direction: {0:0.00}, {1:0.00}, {2:0.00}", viewDir.X, viewDir.Y, viewDir.Z);
}
}
/// <summary>
/// Получение объектов сечения солида
/// </summary>
/// <param name="solid"></param>
/// <param name="basePoint"></param>
/// <param name="vertDir"></param>
/// <param name="viewDir"></param>
/// <param name="backEnts"></param>
/// <param name="intersEnts"></param>
public static void GetSectionEntities
(Transaction tr,
Solid3d solid,
Point3d basePoint,
Point3d secondPoint,
Vector3d vertDir, bool convertSplines,
double maxSegmentLen,
out Entity[] forEnts,
out Entity[] backEnts,
out Entity[] intersEnts,
out Vector3d viewDirection)
{
Point3dCollection pts = new Point3dCollection
{
basePoint,
secondPoint
};
Section sec = new Section(pts, vertDir);
viewDirection = sec.ViewingDirection;
BlockTableRecord space = tr.GetObject
(solid.Database.CurrentSpaceId, OpenMode.ForWrite)
as BlockTableRecord;
space.AppendEntity(sec);
tr.AddNewlyCreatedDBObject(sec, true);
sec.State = SectionState.Plane;
sec.GenerateSectionGeometry
(solid,
out Array intBoundaryEnts,
out Array intFillEnts,
out Array backgroundEnts,
out Array foregroundEnts,
out Array curveTangencyEnts);
void DisposeCollection(IEnumerable col)
{
foreach (Entity ent in col)
{
ent.Dispose();
}
}
// Уничтожаем штриховки пересечения
DisposeCollection(intFillEnts);
// Уничтожаем линии плавного перехода кривых
DisposeCollection(curveTangencyEnts);
//// По идее, выходной нужна именно эта коллекция
//// объектов-силуэтов перед сечением
//// Но в ней почему-то либо вовсе нет объектов,
//// либо их совсем мало - недостаточно для построения
//// вида.
forEnts = foregroundEnts.Cast<Entity>().ToArray();
// Получаем выходную коллекцию - силуэты за сечением.
backEnts = backgroundEnts.Cast<Entity>().ToArray();
// Получаем выходную коллецию - объекты, полученные
// непосредственно пересечением плоскости сечения
// с 3D-телом
intersEnts = intBoundaryEnts.Cast<Entity>().ToArray();
if (convertSplines)
{
// Преобразуем сплайны в полилинии
void ConvertSplines(Entity[] col)
{
for (int i = 0; i < col.Length; i++)
{
Entity ent = col[i];
if (ent is Spline spline)
{
double length
= spline.GetDistanceAtParameter(spline.EndParam)
- spline.GetDistanceAtParameter(spline.StartParam);
uint pointsCount = (uint)Math.Max
(length / maxSegmentLen,
spline.Type == SplineType.FitPoints
? spline.NumFitPoints
: spline.NumControlPoints);
Curve newEnt = spline.ToPolyline(pointsCount);
col[i] = newEnt;
ent.Dispose();
}
}
}
ConvertSplines(forEnts);
ConvertSplines(backEnts);
ConvertSplines(intersEnts);
}
}
}
}