private static ComplexArea GetArea(EdgeSpan span) { var middle = span.GetMidPoint(); var leftMost = Math.Min(span.NotInSet.Real, span.InSet.Real); var rightMost = Math.Max(span.NotInSet.Real, span.InSet.Real); var bottomMost = Math.Min(span.NotInSet.Imaginary, span.InSet.Imaginary); var topMost = Math.Max(span.NotInSet.Imaginary, span.InSet.Imaginary); var horizontalDistance = rightMost - leftMost; var verticalDistance = topMost - bottomMost; var horizontalLongest = horizontalDistance > verticalDistance; var paddingPercentage = 0.1; var sideLength = horizontalLongest ? horizontalDistance : verticalDistance; var paddingLength = paddingPercentage * sideLength; var paddedLength = sideLength + 2 * paddingLength; var halfPaddedLength = paddedLength / 2; return(new ComplexArea( realRange: new DoubleRange(middle.Real - halfPaddedLength, middle.Real + halfPaddedLength), imagRange: new DoubleRange(middle.Imaginary - halfPaddedLength, middle.Imaginary + halfPaddedLength))); }
public static EdgeSpan find_edge_path(DMesh3 mesh, int v0, int v1) { if (v0 == v1) { throw new Exception("same vertices!"); } int eid = mesh.FindEdge(v0, v1); if (eid >= 0) { return(EdgeSpan.FromEdges(mesh, new List <int>() { eid })); } DijkstraGraphDistance dist = DijkstraGraphDistance.MeshVertices(mesh); //DijkstraGraphDistance dist = DijkstraGraphDistance.MeshVerticesSparse(mesh); dist.AddSeed(v0, 0); dist.ComputeToNode(v1); List <int> vpath = new List <int>(); bool bOK = dist.GetPathToSeed(v1, vpath); Util.gDevAssert(bOK); vpath.Reverse(); return(EdgeSpan.FromVertices(mesh, vpath)); }
public void ShouldFindMiddle(double aR, double aI, double bR, double bI, double expectedR, double expectedI) { var span = new EdgeSpan(new Complex(aR, aI), new Complex(bR, bI)); var middle = span.GetMidPoint(); Assert.That(middle.Real, Is.EqualTo(expectedR).Within(0.00000001f), "Incorrect real component."); Assert.That(middle.Imaginary, Is.EqualTo(expectedI).Within(0.00000001f), "Incorrect imaginary component."); }
Polygon2d to_polygon(EdgeSpan span, Frame3f polyFrame) { int NV = span.VertexCount; Polygon2d poly = new Polygon2d(); for (int k = 0; k < NV; ++k) { poly.AppendVertex(polyFrame.ToPlaneUV((Vector3f)span.GetVertex(k), 2)); } return(poly); }
public VehicleRegionLink LinkFrom(EdgeSpan span) { ulong key = span.UniqueHashCode(); if (!links.TryGetValue(key, out VehicleRegionLink regionLink)) { regionLink = new VehicleRegionLink(); regionLink.span = span; links.Add(key, regionLink); } return(regionLink); }
public WaterRegionLink LinkFrom(EdgeSpan span) { ulong key = span.UniqueHashCode(); WaterRegionLink regionLink; if (!this.links.TryGetValue(key, out regionLink)) { regionLink = new WaterRegionLink(); regionLink.span = span; this.links.Add(key, regionLink); } return(regionLink); }
private static IntVec3 LinkClosestCell(IntVec3 cell, RegionLink link) { EdgeSpan span = link.span; int num = 0; int num2 = 0; if (span.dir == SpanDirection.North) { num2 = span.length - 1; } else { num = span.length - 1; } IntVec3 root = span.root; return(new IntVec3(Mathf.Clamp(cell.x, root.x, root.x + num), 0, Mathf.Clamp(cell.z, root.z, root.z + num2))); }
static Complex FindBorderPointMagnitudeSquared(EdgeSpan span, int iterationLimit) { // var initialLength2 = span.LengthSquared(); int maxSubdivisions = 38; //double oldLength = 0; //while (oldLength != initialLength2) //{ // maxSubdivisions++; // oldLength = initialLength2; // initialLength2 /= 2; //} //Console.WriteLine(maxSubdivisions); double lastLength = 0; for (int i = 0; i < maxSubdivisions; i++) { //var length = span.LengthSquared(); //if (length == lastLength) //{ // return span.NotInSet; //} //lastLength = length; var middle = span.GetMidPoint(); var escapeTime = ScalarDoubleKernel.FindEscapeTime(middle, iterationLimit); span = escapeTime.IsInfinite ? new EdgeSpan(middle, span.NotInSet) : new EdgeSpan(span.InSet, middle); //if (i % 10 == 0) //{ // Console.WriteLine(i); //} } return(span.NotInSet); }
// NO DOES NOT WORK. DOES NOT FIND EDGE SPANS THAT ARE IN PLANE BUT HAVE DIFFERENT NORMAL! // NEED TO COLLECT UP SPANS USING NORMAL HISTOGRAM NORMALS! // ALSO NEED TO ACTUALLY CHECK FOR COPLANARITY, NOT JUST SAME NORMAL!! Dictionary <Vector3d, List <EdgeSpan> > find_coplanar_span_sets(DMesh3 mesh, EdgeLoop loop) { double dot_thresh = 0.999; var span_sets = new Dictionary <Vector3d, List <EdgeSpan> >(); int NV = loop.Vertices.Length; int NE = loop.Edges.Length; var edge_normals = new Vector3d[NE]; for (int k = 0; k < NE; ++k) { edge_normals[k] = mesh.GetTriNormal(mesh.GetEdgeT(loop.Edges[k]).a); } // find coplanar verts // [RMS] this is wrong, if normals vary smoothly enough we will mark non-coplanar spans as coplanar bool[] vert_coplanar = new bool[NV]; int nc = 0; for (int k = 0; k < NV; ++k) { int prev = (k == 0) ? NV - 1 : k - 1; if (edge_normals[k].Dot(ref edge_normals[prev]) > dot_thresh) { vert_coplanar[k] = true; nc++; } } if (nc < 2) { return(null); } int iStart = 0; while (vert_coplanar[iStart]) { iStart++; } int iPrev = iStart; int iCur = iStart + 1; while (iCur != iStart) { if (vert_coplanar[iCur] == false) { iPrev = iCur; iCur = (iCur + 1) % NV; continue; } var edges = new List <int>() { loop.Edges[iPrev] }; int span_start_idx = iCur; while (vert_coplanar[iCur]) { edges.Add(loop.Edges[iCur]); iCur = (iCur + 1) % NV; } if (edges.Count > 1) { Vector3d span_n = edge_normals[span_start_idx]; var span = EdgeSpan.FromEdges(mesh, edges); span.CheckValidity(); foreach (var pair in span_sets) { if (pair.Key.Dot(ref span_n) > dot_thresh) { span_n = pair.Key; break; } } List <EdgeSpan> found; if (span_sets.TryGetValue(span_n, out found) == false) { span_sets[span_n] = new List <EdgeSpan>() { span }; } else { found.Add(span); } } } return(span_sets); }
private void SweepInTwoDirectionsAndTryToCreateLink(Rot4 potentialOtherRegionDir, IntVec3 c) { if (!potentialOtherRegionDir.IsValid) { return; } HashSet <IntVec3> hashSet = this.linksProcessedAt[potentialOtherRegionDir.AsInt]; if (hashSet.Contains(c)) { return; } IntVec3 c2 = c + potentialOtherRegionDir.FacingCell; if (c2.InBoundsShip(this.map) && this.regionGrid.GetRegionAt_NoRebuild_InvalidAllowed(c2) == this.newReg) { return; } RegionType expectedRegionType = WaterRegionTypeUtility.GetExpectedRegionType(c2, this.map); if (expectedRegionType == RegionType.None) { return; } Rot4 rot = potentialOtherRegionDir; rot.Rotate(RotationDirection.Clockwise); int num = 0; int num2 = 0; hashSet.Add(c); if (!WaterRegionTypeUtility.IsOneCellRegion(expectedRegionType)) { for (;;) { IntVec3 intVec = c + rot.FacingCell * (num + 1); if (!intVec.InBoundsShip(this.map) || this.regionGrid.GetRegionAt_NoRebuild_InvalidAllowed(intVec) != this.newReg || WaterRegionTypeUtility.GetExpectedRegionType(intVec + potentialOtherRegionDir.FacingCell, this.map) != expectedRegionType) { break; } if (!hashSet.Add(intVec)) { Log.Error("We've processed the same cell twice.", false); } num++; } for (; ;) { IntVec3 intVec2 = c - rot.FacingCell * (num2 + 1); if (!intVec2.InBoundsShip(this.map) || this.regionGrid.GetRegionAt_NoRebuild_InvalidAllowed(intVec2) != this.newReg || WaterRegionTypeUtility.GetExpectedRegionType(intVec2 + potentialOtherRegionDir.FacingCell, this.map) != expectedRegionType) { break; } if (!hashSet.Add(intVec2)) { Log.Error("We've processed the same cell twice.", false); } num2++; } } int length = num + num2 + 1; SpanDirection dir; IntVec3 root; if (potentialOtherRegionDir == Rot4.North) { dir = SpanDirection.East; root = c - rot.FacingCell * num2; root.z++; } else if (potentialOtherRegionDir == Rot4.South) { dir = SpanDirection.East; root = c + rot.FacingCell * num; } else if (potentialOtherRegionDir == Rot4.East) { dir = SpanDirection.North; root = c + rot.FacingCell * num; root.x++; } else { dir = SpanDirection.North; root = c - rot.FacingCell * num2; } EdgeSpan span = new EdgeSpan(root, dir, length); WaterRegionLink regionLink = MapExtensionUtility.GetExtensionToMap(this.map).getWaterRegionLinkDatabase.LinkFrom(span); regionLink.Register(this.newReg); this.newReg.links.Add(regionLink); }
private static int SpanEndZ(EdgeSpan e) => e.root.z + (e.dir == SpanDirection.North ? e.length : 0);
private static int SpanEndX(EdgeSpan e) => e.root.x + (e.dir == SpanDirection.East ? e.length : 0);
private static int SpanCenterZ(EdgeSpan e) => e.root.z + (e.dir == SpanDirection.North ? e.length / 2 : 0);
private static int SpanCenterX(EdgeSpan e) => e.root.x + (e.dir == SpanDirection.East ? e.length / 2 : 0);
public static int SpanCenterX2(EdgeSpan e) { return(e.root.x + ((e.dir == SpanDirection.East) ? (e.length / 2) : 0)); }
private static int SpanCenterX(EdgeSpan e) { return(e.root.x + ((e.dir != SpanDirection.East) ? 0 : (e.length / 2))); }
public static void quick_test_2() { DMesh3 target = TestUtil.LoadTestInputMesh("cylinder_orig.obj"); DMeshAABBTree3 targetSpatial = new DMeshAABBTree3(target, true); DMesh3 mesh = TestUtil.LoadTestInputMesh("cylinder_approx.obj"); DMeshAABBTree3 meshSpatial = new DMeshAABBTree3(mesh, true); double search_dist = 10.0; MeshTopology topo = new MeshTopology(target); topo.Compute(); RemesherPro r = new RemesherPro(mesh); r.SetTargetEdgeLength(2.0); r.SmoothSpeedT = 0.5; r.SetProjectionTarget(MeshProjectionTarget.Auto(target)); MeshConstraints cons = new MeshConstraints(); r.SetExternalConstraints(cons); int set_id = 1; foreach (var loop in topo.Loops) { DCurveProjectionTarget curveTarget = new DCurveProjectionTarget(loop.ToCurve(target)); set_id++; // pick a set of points we will find paths between. We will chain // up those paths and constrain them to target loops. // (this part is the hack!) List <int> target_verts = new List <int>(); List <int> mesh_verts = new List <int>(); for (int k = 0; k < loop.VertexCount; k += 5) { target_verts.Add(loop.Vertices[k]); Vector3d vCurve = target.GetVertex(loop.Vertices[k]); int mesh_vid = meshSpatial.FindNearestVertex(vCurve, search_dist); mesh_verts.Add(mesh_vid); } int NT = target_verts.Count; // find the paths to assemble the edge chain // [TODO] need to filter out junction vertices? or will they just handle themselves // because they can be collapsed away? List <int> vert_seq = new List <int>(); for (int k = 0; k < NT; k++) { EdgeSpan e = find_edge_path(mesh, mesh_verts[k], mesh_verts[(k + 1) % NT]); int n = e.Vertices.Length; for (int i = 0; i < n - 1; ++i) { vert_seq.Add(e.Vertices[i]); } } // now it's easy, just add the loop constraint EdgeLoop full_loop = EdgeLoop.FromVertices(mesh, vert_seq); MeshConstraintUtil.ConstrainVtxLoopTo(cons, mesh, full_loop.Vertices, curveTarget, set_id); } r.FastestRemesh(); TestUtil.WriteTestOutputMesh(mesh, "curves_test_out.obj"); }
public static int SpanCenterZ2(EdgeSpan e) { return(e.root.z + ((e.dir == SpanDirection.North) ? (e.length / 2) : 0)); }
private static int SpanCenterZ(EdgeSpan e) { return(e.root.z + ((e.dir != SpanDirection.North) ? 0 : (e.length / 2))); }
void extract_topology() { var graph = new DGraph3(); // add vertices to graph, and store mappings int[] mapV = new int[Mesh.MaxVertexID]; int[] mapVFrom = new int[AllVertices.Count]; foreach (int vid in AllVertices) { int new_vid = graph.AppendVertex(Mesh.GetVertex(vid)); mapV[vid] = new_vid; mapVFrom[new_vid] = vid; } // add edges to graph. graph-to-mesh eid mapping is stored via graph edge-group-id int[] mapE = new int[Mesh.MaxEdgeID]; foreach (int eid in AllEdges) { Index2i ev = Mesh.GetEdgeV(eid); int new_a = mapV[ev.a]; int new_b = mapV[ev.b]; int new_eid = graph.AppendEdge(new_a, new_b, eid); mapE[eid] = new_eid; } // extract the graph topology DGraph3Util.Curves curves = DGraph3Util.ExtractCurves(graph, true); // reconstruct mesh spans / curves / junctions from graph topology int NP = curves.PathEdges.Count; Spans = new EdgeSpan[NP]; for (int pi = 0; pi < NP; ++pi) { List <int> pathE = curves.PathEdges[pi]; for (int k = 0; k < pathE.Count; ++k) { pathE[k] = graph.GetEdgeGroup(pathE[k]); } Spans[pi] = EdgeSpan.FromEdges(Mesh, pathE); } int NL = curves.LoopEdges.Count; Loops = new EdgeLoop[NL]; for (int li = 0; li < NL; ++li) { List <int> loopE = curves.LoopEdges[li]; for (int k = 0; k < loopE.Count; ++k) { loopE[k] = graph.GetEdgeGroup(loopE[k]); } Loops[li] = EdgeLoop.FromEdges(Mesh, loopE); } JunctionVertices = new HashSet <int>(); foreach (int gvid in curves.JunctionV) { JunctionVertices.Add(mapVFrom[gvid]); } }