public static AxisAlignedBox2d ToAABox2d(this BoundingBoxXYZ _bb, Frame3f _frame) { var min = _frame.ToPlaneUV((Vector3f)_bb.Min.ToVector3d(), 2); var max = _frame.ToPlaneUV((Vector3f)_bb.Max.ToVector3d(), 2); return(new AxisAlignedBox2d(min, max)); }
/// <summary> /// Builds the UV values for thw mesh represented by the vertices /// </summary> /// <param name="vertices"></param> /// <returns></returns> protected Vector2[] BuildUVs(Vector3[] vertices) { List <Vector2> ret = new List <Vector2>(); List <Vector3d> vertices3d = vertices.ToList <Vector3>().ConvertAll(item => (Vector3d)item); // // create a UV mapping plane // to make image planes work - we assume that the origin of UV plane is the last vertex // OrthogonalPlaneFit3 orth = new OrthogonalPlaneFit3(vertices3d); Frame3f frame = new Frame3f(vertices[vertices.Length - 1], -1 * orth.Normal); // // check the orientation of the plane in UV space. // for image planes - we assume that the x direction from the first point to the second point should always be positive // if not - reverse the frame // if (Math.Sign( frame.ToPlaneUV((Vector3f)vertices3d[0], 2).x - frame.ToPlaneUV((Vector3f)vertices3d[1], 2).x ) > -1) { frame = new Frame3f(vertices[vertices.Length - 1], orth.Normal); } // // map all of the points to UV space // foreach (Vector3d v in vertices3d) { ret.Add(frame.ToPlaneUV((Vector3f)v, 2)); } // // normalize UVs to [0..1, 0..1] // float maxX = float.NegativeInfinity; float maxY = float.NegativeInfinity; float minX = float.PositiveInfinity; float minY = float.PositiveInfinity; for (int i = 0; i < ret.Count; i++) { Vector2 v = ret[i]; maxX = maxX > v.x ? maxX : v.x; minX = minX < v.x ? minX : v.x; maxY = maxY > v.y ? maxY : v.y; minY = minY < v.y ? minY : v.y; } scaleX = maxX - minX; scaleY = maxY - minY; for (int i = 0; i < ret.Count; i++) { ret[i] = new Vector2((ret[i].x - minX) / scaleX, (ret[i].y - minY) / scaleY); } return(ret.ToArray()); }
public static Segment2d IntoFrame(this Segment3d _seg3d, Frame3f _frame) { var seg2f = new Segment2f (_frame.ToPlaneUV((Vector3f)_seg3d.P0, 2), _frame.ToPlaneUV((Vector3f)_seg3d.P1, 2)); return(new Segment2d(seg2f.P0, seg2f.P1)); }
public List <GeneralPolygon2d> GetSolids() { Frame3f f = frameL; if (OutputSpace != CoordSpace.ObjectCoords) { f = SceneTransforms.TransformTo(f, SO, CoordSpace.ObjectCoords, OutputSpace); } PlanarComplex complex = new PlanarComplex(); foreach (DCurve3 c in localCurves.Loops) { Polygon2d poly = new Polygon2d(); for (int i = 0; i < c.VertexCount; ++i) { Vector2f uv = f.ToPlaneUV((Vector3f)c[i], 2); poly.AppendVertex(uv); } complex.Add(poly); } PlanarComplex.FindSolidsOptions options = PlanarComplex.FindSolidsOptions.SortPolygons; var info = complex.FindSolidRegions(options); return(info.Polygons); }
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 static GeneralPolygon2d ToPolygon(this List <Dataline> list, ref Frame3f frame) { List <VertexLookup> VertexTable = list[0].VertexTable; Vector3d[] vertices = new Vector3d[VertexTable.Count]; for (int j = 0; j < VertexTable.Count; j++) { vertices[j] = VertexTable.Find(item => item.Vertex == j).Com.transform.position; } OrthogonalPlaneFit3 orth = new OrthogonalPlaneFit3(vertices); frame = new Frame3f(orth.Origin, orth.Normal); GeneralPolygon2d poly = new GeneralPolygon2d(new Polygon2d()); for (int i = 0; i < list.Count; i++) { VertexTable = list[i].VertexTable; vertices = new Vector3d[VertexTable.Count]; for (int j = 0; j < VertexTable.Count; j++) { vertices[j] = VertexTable.Find(item => item.Vertex == j).Com.transform.position; } List <Vector2d> vertices2d = new List <Vector2d>(); foreach (Vector3d v in vertices) { Vector2f vertex = frame.ToPlaneUV((Vector3f)v, 3); if (i != 0 && !poly.Outer.Contains(vertex)) { break; } vertices2d.Add(vertex); } Polygon2d p2d = new Polygon2d(vertices2d); if (i == 0) { p2d = new Polygon2d(vertices2d); p2d.Reverse(); poly.Outer = p2d; } else { try { poly.AddHole(p2d, true, true); } catch { p2d.Reverse(); poly.AddHole(p2d, true, true); } } } return(poly); }
public static void CalculateUVs(this DMesh3 dMesh) { dMesh.EnableVertexUVs(Vector2f.Zero); OrthogonalPlaneFit3 orth = new OrthogonalPlaneFit3(dMesh.Vertices()); Frame3f frame = new Frame3f(orth.Origin, orth.Normal); AxisAlignedBox3d bounds = dMesh.CachedBounds; AxisAlignedBox2d boundsInFrame = new AxisAlignedBox2d(); for (int i = 0; i < 8; i++) { boundsInFrame.Contain(frame.ToPlaneUV((Vector3f)bounds.Corner(i), 3)); } Vector2f min = (Vector2f)boundsInFrame.Min; float width = (float)boundsInFrame.Width; float height = (float)boundsInFrame.Height; for (int i = 0; i < dMesh.VertexCount; i++) { Vector2f UV = frame.ToPlaneUV((Vector3f)dMesh.GetVertex(i), 3); UV.x = (UV.x - min.x) / width; UV.y = (UV.y - min.y) / height; dMesh.SetVertexUV(i, UV); } }
/// <summary> /// create Polygon by projecting polygon3 into frame /// </summary> public MeshInsertProjectedPolygon(DMesh3 mesh, DCurve3 polygon3, Frame3f frame, int seedTri) { if (polygon3.Closed == false) { throw new Exception("MeshInsertPolyCurve(): only closed polygon3 supported for now"); } Mesh = mesh; ProjectFrame = frame; SeedTriangle = seedTri; Polygon = new Polygon2d(); foreach (Vector3d v3 in polygon3.Vertices) { Vector2f uv = frame.ToPlaneUV((Vector3f)v3, 2); Polygon.AppendVertex(uv); } }
public static GeneralPolygon2d ToPolygon(this List <DCurve3> list, ref Frame3f frame) { OrthogonalPlaneFit3 orth = new OrthogonalPlaneFit3(list[0].Vertices); frame = new Frame3f(orth.Origin, orth.Normal); GeneralPolygon2d poly = new GeneralPolygon2d(new Polygon2d()); for (int i = 0; i < list.Count; i++) { List <Vector3d> vertices = list[i].Vertices.ToList(); List <Vector2d> vertices2d = new List <Vector2d>(); foreach (Vector3d v in vertices) { Vector2f vertex = frame.ToPlaneUV((Vector3f)v, 3); if (i != 0 && !poly.Outer.Contains(vertex)) { break; } vertices2d.Add(vertex); } Polygon2d p2d = new Polygon2d(vertices2d); if (i == 0) { p2d = new Polygon2d(vertices2d); p2d.Reverse(); poly.Outer = p2d; } else { try { poly.AddHole(p2d, true, true); } catch { p2d.Reverse(); poly.AddHole(p2d, true, true); } } } return(poly); }
public List <Polygon2d> GetPolygons() { Frame3f f = frameL; if (OutputSpace != CoordSpace.ObjectCoords) { f = SceneTransforms.TransformTo(f, SO, CoordSpace.ObjectCoords, OutputSpace); } List <Polygon2d> polygons = new List <Polygon2d>(); foreach (DCurve3 c in localCurves.Loops) { Polygon2d poly = new Polygon2d(); for (int i = 0; i < c.VertexCount; ++i) { Vector2f uv = f.ToPlaneUV((Vector3f)c[i], 2); poly.AppendVertex(uv); } polygons.Add(poly); } return(polygons); }
public bool Insert() { Func <int, bool> is_contained_v = (vid) => { Vector3d v = Mesh.GetVertex(vid); Vector2f vf2 = ProjectFrame.ToPlaneUV((Vector3f)v, 2); return(Polygon.Contains(vf2)); }; MeshVertexSelection vertexROI = new MeshVertexSelection(Mesh); Index3i seedT = Mesh.GetTriangle(SeedTriangle); // if a seed vert of seed triangle is containd in polygon, we will // flood-fill out from there, this gives a better ROI. // If not, we will try flood-fill from the seed triangles. List <int> seed_verts = new List <int>(); for (int j = 0; j < 3; ++j) { if (is_contained_v(seedT[j])) { seed_verts.Add(seedT[j]); } } if (seed_verts.Count == 0) { seed_verts.Add(seedT.a); seed_verts.Add(seedT.b); seed_verts.Add(seedT.c); } // flood-fill out from seed vertices until we have found all vertices // contained in polygon vertexROI.FloodFill(seed_verts.ToArray(), is_contained_v); // convert vertex ROI to face ROI MeshFaceSelection faceROI = new MeshFaceSelection(Mesh, vertexROI, 1); faceROI.ExpandToOneRingNeighbours(); faceROI.FillEars(true); // this might be a good idea... // construct submesh RegionOperator regionOp = new RegionOperator(Mesh, faceROI); DSubmesh3 roiSubmesh = regionOp.Region; DMesh3 roiMesh = roiSubmesh.SubMesh; // save 3D positions of unmodified mesh Vector3d[] initialPositions = new Vector3d[roiMesh.MaxVertexID]; // map roi mesh to plane MeshTransforms.PerVertexTransform(roiMesh, roiMesh.VertexIndices(), (v, vid) => { Vector2f uv = ProjectFrame.ToPlaneUV((Vector3f)v, 2); initialPositions[vid] = v; return(new Vector3d(uv.x, uv.y, 0)); }); // save a copy of 2D mesh and construct bvtree. we will use // this later to project back to 3d // [TODO] can we use a better spatial DS here, that takes advantage of 2D? DMesh3 projectMesh = new DMesh3(roiMesh); DMeshAABBTree3 projecter = new DMeshAABBTree3(projectMesh, true); MeshInsertUVPolyCurve insertUV = new MeshInsertUVPolyCurve(roiMesh, Polygon); //insertUV.Validate() bool bOK = insertUV.Apply(); if (!bOK) { throw new Exception("insertUV.Apply() failed"); } if (SimplifyInsertion) { insertUV.Simplify(); } int[] insertedPolyVerts = insertUV.CurveVertices; // grab inserted loop, assuming it worked EdgeLoop insertedLoop = null; if (insertUV.Loops.Count == 1) { insertedLoop = insertUV.Loops[0]; } // find interior triangles List <int> interiorT = new List <int>(); foreach (int tid in roiMesh.TriangleIndices()) { Vector3d centroid = roiMesh.GetTriCentroid(tid); if (Polygon.Contains(centroid.xy)) { interiorT.Add(tid); } } if (RemovePolygonInterior) { MeshEditor editor = new MeshEditor(roiMesh); editor.RemoveTriangles(interiorT, true); InteriorTriangles = null; } else { InteriorTriangles = interiorT.ToArray(); } // map back to 3d Vector3d a = Vector3d.Zero, b = Vector3d.Zero, c = Vector3d.Zero; foreach (int vid in roiMesh.VertexIndices()) { // [TODO] somehow re-use exact positions from regionOp maps? // construct new 3D pos w/ barycentric interpolation Vector3d v = roiMesh.GetVertex(vid); int tid = projecter.FindNearestTriangle(v); Index3i tri = projectMesh.GetTriangle(tid); projectMesh.GetTriVertices(tid, ref a, ref b, ref c); Vector3d bary = MathUtil.BarycentricCoords(ref v, ref a, ref b, ref c); Vector3d pos = bary.x * initialPositions[tri.a] + bary.y * initialPositions[tri.b] + bary.z * initialPositions[tri.c]; roiMesh.SetVertex(vid, pos); } bOK = BackPropagate(regionOp, insertedPolyVerts, insertedLoop); return(bOK); }
/// <summary> /// Makes the actual mesh /// </summary> protected void _redraw() { if (lines.Count > 0) { Polygon = new List <DCurve3>(); foreach (Dataline ring in lines) { foreach (VertexLookup v in ring.VertexTable) { VertexTable.Add(v); } DCurve3 curve = new DCurve3(); curve.Vector3(ring.GetVertexPositions(), true); Polygon.Add(curve); } } MeshFilter mf = Shape.GetComponent <MeshFilter>(); MeshCollider[] mc = Shape.GetComponents <MeshCollider>(); mf.mesh = null; Mesh mesh = new Mesh(); Mesh imesh = new Mesh(); mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; imesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; Frame3f frame = new Frame3f(); Vector3[] vertices; GeneralPolygon2d polygon2d; Delaunator delaunator; List <int> triangles = new List <int>(); try { // // Map 3d Polygon to the bext fit 2d polygon and also return the frame used for the mapping // polygon2d = Polygon.ToPolygon(ref frame); // // calculate the dalaunay triangulation of the 2d polygon // delaunator = new Delaunator(polygon2d.AllVerticesItr().ToPoints()); IEnumerable <Vector2d> vlist = delaunator.Points.ToVectors2d(); vertices = new Vector3[vlist.Count()]; // // for each vertex in the dalaunay triangulatin - map back to a 3d point and also populate the vertex table // for (int i = 0; i < vlist.Count(); i++) { Vector2d v = vlist.ElementAt(i); try { Vector3d v1 = Polygon.AllVertexItr().Find(item => v.Distance(frame.ToPlaneUV((Vector3f)item, 2)) < 0.001); vertices[i] = Shape.transform.InverseTransformPoint((Vector3)v1); VertexLookup vl = VertexTable.Find(item => v1.Distance(item.Com.transform.position) < 0.001); if (vl != null) { vl.pVertex = i; } } catch { Debug.Log("Mesh Error"); } } // // eaxtract the triangles from the delaunay triangulation // IEnumerable <ITriangle> tris = delaunator.GetTriangles(); for (int i = 0; i < tris.Count(); i++) { ITriangle tri = tris.ElementAt(i); if (polygon2d.Contains(tri.CetIncenter())) { int index = 3 * i; triangles.Add(delaunator.Triangles[index]); triangles.Add(delaunator.Triangles[index + 1]); triangles.Add(delaunator.Triangles[index + 2]); } } } catch (Exception e) { throw new Exception("feature is not a valid Polygon : " + e.ToString()); } // // build the mesh entity // mesh.vertices = vertices; mesh.triangles = triangles.ToArray(); mesh.uv = BuildUVs(vertices); mesh.RecalculateBounds(); mesh.RecalculateNormals(); imesh.vertices = mesh.vertices; imesh.triangles = triangles.Reverse <int>().ToArray(); imesh.uv = mesh.uv; imesh.RecalculateBounds(); imesh.RecalculateNormals(); mf.mesh = mesh; try { mc[0].sharedMesh = mesh; mc[1].sharedMesh = imesh; } catch (Exception e) { Debug.Log(e.ToString()); } }
/// <summary> /// Generates the actual mesh for the polyhedron /// </summary> private void MakeMesh() { MeshFilter mf; mf = Shape.GetComponent <MeshFilter>(); if (mf == null) { mf = Shape.AddComponent <MeshFilter>(); } mf.mesh = null; Mesh mesh = new Mesh(); TriangulatedPolygonGenerator tpg = new TriangulatedPolygonGenerator(); Frame3f frame = new Frame3f(); tpg.Polygon = Polygon.ToPolygon(ref frame); tpg.Generate(); int nv = tpg.vertices.Count; VertexTable.Clear(); foreach (Dataline ring in Polygon) { foreach (VertexLookup v in ring.VertexTable) { VertexTable.Add(v); } } IEnumerable <Vector3d> vlist = tpg.vertices.AsVector3d(); Vector3[] vertices = new Vector3[vlist.Count()]; for (int i = 0; i < vlist.Count(); i++) { Vector3d v = vlist.ElementAt(i); try { VertexLookup vl = VertexTable.Find(item => v.xy.Distance(frame.ToPlaneUV(item.Com.transform.position, 3)) < 0.001); vertices[i] = Shape.transform.InverseTransformPoint(vl.Com.transform.position); vl.pVertex = i; } catch { VertexTable.Add(new VertexLookup() { pVertex = i, Com = VertexTable[0].Com }); vertices[i] = Shape.transform.InverseTransformPoint((Vector3)frame.FromFrameV(v)); } } List <Vector2> uvs = new List <Vector2>(); IEnumerable <Vector2d> uv2d = tpg.uv.AsVector2f(); foreach (Vector2d uv in uv2d) { uvs.Add((Vector2)uv); } mesh.vertices = vertices.ToArray(); mesh.triangles = tpg.triangles.ToArray <int>(); mesh.uv = uvs.ToArray <Vector2>(); mesh.RecalculateBounds(); mesh.RecalculateNormals(); mf.mesh = mesh; }