Ad

Sunday, September 27, 2020

Corridor Surface Shrink

This post is in regard to this Civil 3D Idea: 

https://forums.autodesk.com/t5/civil-3d-ideas/corridor-boundaries/idi-p/5908587

This post will provide a workflow to programmatically delete tin triangles outside of the corridor. 

This code deletes triangles, but it could be modified to add the polylines as boundaries instead of going through the triangles that are outside of the corridor.

It's not full proof, but it's intended to quickly get triangles that are outside of the corridor for design purposes.

The MPolygon requires a reference to this dll: 

C:\Program Files\Autodesk\AutoCAD 2021\AcMPolygonMGD.dll

    public class CorridorShrinkwrap
    {
        [CommandMethod("CorridorShrinkwrap")]
        public void CorridorShrinkwrapCommand()
        {
            var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            var ed = doc.Editor;
            var db = doc.Database;

            try
            {
                using (var tr = doc.TransactionManager.StartTransaction())
                using (var btr = db.CurrentSpaceId.GetObject(OpenMode.ForWrite) as BlockTableRecord)
                {
                    var corridorTypVals = new List<TypedValue>
                            {
                                new TypedValue((int)DxfCode.Operator, "<OR"),
                                new TypedValue((int)DxfCode.Start, RXClass.GetClass(typeof(Corridor)).DxfName),
                                new TypedValue((int)DxfCode.Operator, "OR>")
                            };

                    var corrObjIds = ed.GetEntities(corridorTypVals, "\nSelect corridor: ", "\nSelection objects to remove",
                                                     out List<FullSubentityPath> xrefPaths);

                    if (!corrObjIds.Any())
                    {
                        return;
                    }

                    ed.UnHighlightSelectedXREFSubEntities(xrefPaths);

                    var strRslt = ed.GetString("\nEnter link code to shrink to: ");

                    if (strRslt.Status != Autodesk.AutoCAD.EditorInput.PromptStatus.OK)
                    {
                        return;
                    }

                    var code = strRslt.StringResult;
                    var tolerance = Tolerance.Global.EqualPoint;

                    foreach (var corrObjId in corrObjIds)
                    {
                        var corr = corrObjId.GetObject(OpenMode.ForWrite) as Corridor;
                        var polylines = new List<Polyline>();
                        var mpolys = new List<MPolygon>();
                        foreach (var baseline in corr.Baselines)
                        {
                            foreach (var region in baseline.BaselineRegions)
                            {
                                var polyPts = new List<Tuple<ObjectId, CalculatedPoint, CalculatedPoint>>();

                                foreach (var assembly in region.AppliedAssemblies)
                                {                                    
                                    foreach (var subAss in assembly.GetAppliedSubassemblies())
                                    {
                                        var links = subAss.Links.Where(x => x.CorridorCodes.Contains(code));
                                        if (!links.Any())
                                        {
                                            continue;
                                        }
                                        var linkPoints = links.SelectMany(x => x.CalculatedPoints.Select(y => y)).OrderBy(z => z.StationOffsetElevationToBaseline.Y).ToList();
                                        polyPts.Add(new Tuple<ObjectId, CalculatedPoint, CalculatedPoint>(subAss.SubassemblyId, linkPoints.First(), linkPoints.Last()));
                                    }
                                }

                                // Collect the points by subassembly.
                                var polyInfos = polyPts.GroupBy(x => x.Item1).ToDictionary(x => x.Key, x => x.OrderBy(y => y.Item2.StationOffsetElevationToBaseline.X).ToList());

                                foreach (var kvp in polyInfos)
                                {
                                    var poly = new Polyline();

                                    foreach (var pt in kvp.Value)
                                    {
                                        poly.AddVertexAt(poly.NumberOfVertices, pt.Item2.XYZ.ToPoint2d(), 0, 0, 0);
                                    }

                                    kvp.Value.Reverse();
                                    
                                    foreach (var pt in kvp.Value)
                                    {
                                        poly.AddVertexAt(poly.NumberOfVertices, pt.Item3.XYZ.ToPoint2d(), 0, 0, 0);
                                    }

                                    poly.Closed = true;

                                    var plObjId = btr.AppendEntity(poly);
                                    tr.AddNewlyCreatedDBObject(poly, true);

                                    polylines.Add(poly);

                                    var mPoly = new MPolygon();
                                    mPoly.AppendLoopFromBoundary(poly, true, tolerance);

                                    mpolys.Add(mPoly);
                                }

                                // find the surfaces that contain the code. 
                                foreach (var corrSurf in corr.CorridorSurfaces.Where(x => x.LinkCodes().Contains(code)))
                                {
                                    var edgesToDelete = new List<TinSurfaceEdge>();
                                    var corrTinSurf = corrSurf.SurfaceId.GetObject(OpenMode.ForWrite) as TinSurface;
                                    foreach (var tinEdge in corrTinSurf.Triangles.SelectMany(x => new List<TinSurfaceEdge> { x.Edge1, x.Edge2, x.Edge3 }).Distinct())
                                    {
                                        using (var tempLine = new Line(tinEdge.Vertex1.Location, tinEdge.Vertex2.Location))
                                        {
                                            var midPt = tempLine.GetPointAtParameter((tempLine.EndParam - tempLine.StartParam) / 2);
                                            if (mpolys.Where(x => x.IsPointInsideMPolygon(midPt, tolerance).Count == 1).Any())
                                            {
                                                continue;
                                            }
                                            edgesToDelete.Add(tinEdge);
                                        }
                                    }

                                    if (!edgesToDelete.Any())
                                    {
                                        continue;
                                    }
                                    corrTinSurf.DeleteLines(edgesToDelete);
                                }
                            }
                        }

                        // dispose of the polylines. 
                        foreach (var poly in polylines)
                        {
                            poly.Dispose();
                        }

                        foreach (var mPoly in mpolys)
                        {
                            mPoly.Dispose();
                        }
                    }

                    tr.Commit();
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nError: " + ex.Message);
            }
        }
    }

No comments:

LinkWithin

Blog Widget by LinkWithin

Ad