public static ExcavationSection Interpolate(ExcavationSection startSection, ExcavationSection endSection, double ratio) { ExcavationSection result = new ExcavationSection(); for (int i = 0; i < Math.Max(startSection.Elements.Count, endSection.Elements.Count); i++) { int startIndex = Math.Min(i, startSection.Elements.Count - 1); int endIndex = Math.Min(i, endSection.Elements.Count - 1); double hStart = startSection.Elements[startIndex].H; double vStart = startSection.Elements[startIndex].V; double hlStart = startSection.Elements[startIndex].HeightLimit; double llStart = startSection.Elements[startIndex].LengthLimit; double hEnd = startSection.Elements[endIndex].H; double vEnd = startSection.Elements[endIndex].V; double hlEnd = startSection.Elements[endIndex].HeightLimit; double llEnd = startSection.Elements[endIndex].LengthLimit; double h = hStart + ratio * (hEnd - hStart); double v = vStart + ratio * (vEnd - vStart); double hl = ((hlStart > 0 && hlEnd > 0) ? hlStart + ratio * (hlEnd - hlStart) : Math.Max(hlStart, hlEnd)); double ll = ((llStart > 0 && llEnd > 0) ? llStart + ratio * (llEnd - llStart) : Math.Max(llStart, llEnd)); ExcavationSectionElement ele = new ExcavationSectionElement(h, v); ele.HeightLimit = hl; ele.LengthLimit = ll; result.Elements.Add(ele); } return(result); }
protected List <ExcavationSection> ExcavateCurve(Side slopeSide = Side.Right, double offset = 0) { double len = ExcavationBottom.GetLength(); int nmax = (int)Math.Ceiling(len / ExcavationStepSize); double dist = 0.0; double distStep = len / ((double)nmax); if (!ExcavationBottom.Closed) { nmax++; } List <ExcavationSection> outputSections = new List <ExcavationSection>(); for (int i = 0; i < nmax; i++) { double param = dist > len ? ExcavationBottom.EndParam : dist < 0 ? ExcavationBottom.StartParam : ExcavationBottom.GetParameterAtDistance(dist); Point3d bottomPoint = ExcavationBottom.GetPointAtParameter(param); Vector3d normal = ExcavationBottom.GetNormalVector(param); ExcavationSection section = GetSection(ExcavationBottom, dist); Point3d pt = bottomPoint + (slopeSide == Side.Right ? 1 : -1) * normal * Math.Abs(offset); Vector3d dir = (slopeSide == Side.Right ? 1 : -1) * normal; ExcavationSection outSection = ExcavateSlopeAtPoint(Mesh, section, pt, dir); outputSections.Add(outSection); dist += distStep; } return(outputSections); }
protected ExcavationSection GetSection(Curve excavationBottom, double distance) { double curveLength = excavationBottom.GetLength(); if (sections.Count == 0) { throw new InvalidOperationException("No sections defined."); } if (sections.Count == 1) { return(sections[0]); } // Find the section before and closest to the given distance int startIndex = 0; double minDiff = double.MaxValue; for (int i = 0; i < distances.Count; i++) { double diff = distance - distances[i]; if (diff < 0) { diff += curveLength; } if (diff < minDiff) { minDiff = diff; startIndex = i; } } if (Math.Abs(minDiff) < LengthTolerance) { return(sections[startIndex]); } // Find the section after and closest to the given distance int endIndex = 0; minDiff = double.MaxValue; for (int i = 0; i < distances.Count; i++) { double diff = distances[i] - distance; if (diff < 0) { diff += curveLength; } if (diff < minDiff) { minDiff = diff; endIndex = i; } } if (Math.Abs(minDiff) < LengthTolerance) { return(sections[endIndex]); } // Interpolate between start and end sections double startDistance = distances[startIndex]; double endDistance = distances[endIndex]; if (startDistance > endDistance) { startDistance -= curveLength; } if (Math.Abs(endDistance - startDistance) < LengthTolerance) { return(sections[startIndex]); } double ratio = (distance - startDistance) / (endDistance - startDistance); return(ExcavationSection.Interpolate(sections[startIndex], sections[endIndex], ratio)); }
public void AddSection(double distance, ExcavationSection section) { distances.Add(distance); sections.Add(section); }
protected static ExcavationSection ExcavateSlopeAtPoint(TriangleNet.Mesh surfaceMesh, ExcavationSection section, Point3d bottomPoint, Vector3d normal) { double xyLen = Math.Sqrt(normal.X * normal.X + normal.Y * normal.Y); ExcavationSection outSection = new ExcavationSection(); foreach (ExcavationSectionElement inputelement in section.Elements) { ExcavationSectionElement element = (ExcavationSectionElement)inputelement.Clone(); element.HasIntersection = false; element.HasTopPoint = false; element.CurrentRatio = double.MaxValue; element.BottomPoint = bottomPoint; // Calculate 3D slope Vector3d slope = new Vector3d(normal.X / xyLen * element.H, normal.Y / xyLen * element.H, element.V); slope = slope / slope.Length; element.Slope = slope; // Intersects slope vectors with surface triangles foreach (TriangleNet.Data.Triangle tri in surfaceMesh.Triangles) { TriangleNet.Data.Vertex v1 = tri.GetVertex(0); TriangleNet.Data.Vertex v2 = tri.GetVertex(1); TriangleNet.Data.Vertex v3 = tri.GetVertex(2); // Intersect the 3D ray from excavation bottom with the triangle double t; Point3d topPoint; bool intersect = RayTriangleIntersection(bottomPoint, slope, new Point3d(v1.X, v1.Y, v1.Attributes[0]), new Point3d(v2.X, v2.Y, v2.Attributes[0]), new Point3d(v3.X, v3.Y, v3.Attributes[0]), out t, out topPoint); double xyDist = double.MaxValue; double zDist = double.MaxValue; if (intersect) { xyDist = new Vector3d(topPoint.X - bottomPoint.X, topPoint.Y - bottomPoint.Y, 0).Length; zDist = topPoint.Z - bottomPoint.Z; } if (!intersect || (element.HeightLimit > 0 && zDist > element.HeightLimit) || (element.LengthLimit > 0 && xyDist > element.LengthLimit)) { t = double.MaxValue; } if (t < element.CurrentRatio) { element.CurrentRatio = t; element.TopPoint = topPoint; element.HasIntersection = true; } } // Create the output section if (element.HasIntersection) { // This element intersected the surface // Add to output section and end calculation element.HasTopPoint = true; outSection.Elements.Add(element); break; } else { // No intersections // Add to output section and continue calculation // Calculate the top point for this element (bottom point for the next element) if (element.HeightLimit > 0) { element.TopPoint = element.BottomPoint + slope * element.HeightLimit / element.V; element.HasTopPoint = true; } else if (element.LengthLimit > 0) { element.TopPoint = element.BottomPoint + slope * element.LengthLimit / element.H; element.HasTopPoint = true; } else { element.HasTopPoint = false; } outSection.Elements.Add(element); bottomPoint = element.TopPoint; } } return(outSection); }
public void TrenchExcavation() { if (!CheckLicense.Check()) { return; } Autodesk.AutoCAD.ApplicationServices.Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Topography.SurfaceType surface = Topography.PickSurface(); if (surface == Topography.SurfaceType.None) { return; } if (!Topography.EnsureSurfaceNotEmpty(surface)) { return; } Topography topo = Topography.Instance; TriangleNet.Mesh mesh = (surface == Topography.SurfaceType.Original ? topo.OriginalTIN : topo.ProposedTIN); // Pick polyline bool flag = true; ObjectId centerlineId = ObjectId.Null; while (flag) { PromptEntityOptions entityOpts = new PromptEntityOptions("\nKazı tabanı [Seçenekler]:", "Settings"); entityOpts.SetRejectMessage("\nSelect a curve."); entityOpts.AddAllowedClass(typeof(Curve), false); PromptEntityResult entityRes = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.GetEntity(entityOpts); if (entityRes.Status == PromptStatus.Keyword && entityRes.StringResult == "Settings") { ShowSettings(); continue; } else if (entityRes.Status == PromptStatus.OK) { centerlineId = entityRes.ObjectId; break; } else { return; } } using (Transaction tr = db.TransactionManager.StartTransaction()) using (BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite)) { Curve centerline = tr.GetObject(centerlineId, OpenMode.ForRead) as Curve; // Excavate TrenchExcavation ex = new TrenchExcavation(mesh, centerline, Width, ExcavationStepSize); ExcavationSection slope = new ExcavationSection(); slope.AddSlope(ExcavationH, ExcavationV); ex.AddSection(0, slope); ex.Excavate(); // Draw excavation boundries Point3dCollection bottombounds = new Point3dCollection(); Point3dCollection topbounds = new Point3dCollection(); bool closed = true; bool alt = false; foreach (ExcavationSection section in ex.OutputSections) { if (section.Elements[section.Elements.Count - 1].HasTopPoint) { bottombounds.Add(section.Elements[0].BottomPoint); topbounds.Add(section.Elements[section.Elements.Count - 1].TopPoint); Point3d pt1 = section.Elements[0].BottomPoint; Point3d pt2 = section.Elements[section.Elements.Count - 1].TopPoint; if (alt) { pt1 = pt1 + (pt2 - pt1) / 2; } Line line = AcadUtility.AcadEntity.CreateLine(db, pt1, pt2); line.ColorIndex = 11; btr.AppendEntity(line); tr.AddNewlyCreatedDBObject(line, true); } else { if (bottombounds.Count > 1) { Polyline3d pline = AcadUtility.AcadEntity.CreatePolyLine3d(db, bottombounds); btr.AppendEntity(pline); tr.AddNewlyCreatedDBObject(pline, true); } if (topbounds.Count > 1) { Polyline3d pline = AcadUtility.AcadEntity.CreatePolyLine3d(db, topbounds); btr.AppendEntity(pline); tr.AddNewlyCreatedDBObject(pline, true); } closed = false; topbounds = new Point3dCollection(); } alt = !alt; } if (bottombounds.Count > 1) { Polyline3d pline = AcadUtility.AcadEntity.CreatePolyLine3d(db, bottombounds); btr.AppendEntity(pline); tr.AddNewlyCreatedDBObject(pline, true); } if (topbounds.Count > 1) { Polyline3d pline = AcadUtility.AcadEntity.CreatePolyLine3d(db, closed, topbounds); btr.AppendEntity(pline); tr.AddNewlyCreatedDBObject(pline, true); } tr.Commit(); } }