Exemple #1
0
        private void OneChain()
        {
            // Here are all unattached edges.
            var edgeKvps = m_edgeMap.Where(kvp => kvp.Value.Count == 1).ToArray();

            Edge[] edges = edgeKvps.Select(kvp => kvp.Key).ToArray();

            Trace.WriteLine(string.Format("Chain length {0}", edges.Length));

            // Find all the vertices connected to two polygons.
            // This will necessarily lie on the edges above.
            // These are vertices that are candidates for filling in with a polygon.
            Vector3D[]         vertices  = m_vertexMap.Where(kvp => kvp.Value.Count > 1).Select(kvp => kvp.Key).ToArray();
            HashSet <Vector3D> edgeVerts = new HashSet <Vector3D>();

            foreach (Edge e in edges)
            {
                edgeVerts.Add(e.Start);
                edgeVerts.Add(e.End);
            }
            //Vector3D[] vertices = edgeVerts.ToArray();

            // XXX - Things that are hard.
            //	- How can we tell when a vertex is done?
            //  - How to avoid duplicating edges and vertices?

            // Attempt to fill those verts.
            foreach (Vector3D v in vertices)
            {
                Edge[] connectedEdges = m_vertexToEdgeMap[v].Intersect(edges, new H3.Cell.EdgeEqualityComparer()).ToArray();

                // Is it on the chain?
                if (connectedEdges.Length != 2)
                {
                    continue;
                }

                Edge     e1     = connectedEdges[0];
                Edge     e2     = connectedEdges[1];
                Vector3D v1     = e1.Opp(v) - v;
                Vector3D v2     = e2.Opp(v) - v;
                double   angle  = v1.AngleTo(v2);
                int      nSides = PolyWithAngle(angle);
                if (nSides != 0)
                {
                    Vector3D normal = v1.Cross(v2);
                    Polygon  poly   = Polygon.CreateEuclidean(nSides, v, e1.Opp(v), normal);

                    // Things may have changed, so we must double check.
                    if (m_edgeMap[e1].Count == 1 &&
                        m_edgeMap[e2].Count == 1)
                    {
                        AddPoly(poly);
                        Trace.WriteLine(string.Format("Added {0}-gon", nSides));
                    }
                }
            }
        }
Exemple #2
0
            public bool Equals(Segment s1, Segment s2)
            {
                if (s1.Type == SegmentType.Arc || s2.Type == SegmentType.Arc)
                {
                    throw new System.NotImplementedException();
                }

                Edge e1 = new Edge(s1.P1, s1.P2);
                Edge e2 = new Edge(s2.P1, s2.P2);

                return(m_comparer.Equals(e1, e2));
            }
Exemple #3
0
        private static void UpdateEdgeMap(EdgeMap eMap, Polygon poly)
        {
            foreach (Segment s in poly.Segments)
            {
                Edge           e = SegToEdge(s);
                List <Polygon> polys;
                if (!eMap.TryGetValue(e, out polys))
                {
                    polys   = new List <Polygon>();
                    eMap[e] = polys;
                }

                polys.Add(poly);
            }
        }
Exemple #4
0
        private static Edge AdjacentEdge(Edge[] edges, Edge e, Vector3D v)
        {
            H3.Cell.EdgeEqualityComparer comparer = new H3.Cell.EdgeEqualityComparer();
            foreach (Edge edge in edges)
            {
                if (comparer.Equals(e, edge))
                {
                    continue;
                }
                if (edge.Start == v || edge.End == v)
                {
                    return(edge);
                }
            }

            return(null);
        }
Exemple #5
0
        private static Circle3D ConstructRotationCircle(Edge hinge, Vector3D hingePoint, Vector3D polyPoint)
        {
            Vector3D hingeAxis = EdgeAxis(hinge);
            Circle3D c         = new Circle3D
            {
                Center = Euclidean3D.ProjectOntoLine(hingeAxis, hingePoint, polyPoint),
                Normal = hingeAxis,
                Radius = Euclidean3D.DistancePointLine(hingeAxis, hingePoint, polyPoint)
            };

            if (c.Normal.Dot(c.Center) < 0)
            {
                c.Normal *= -1;
            }

            return(c);
        }
Exemple #6
0
        private static void UpdateVertexToEdgeMap(VertexToEdgeMap map, Polygon poly)
        {
            foreach (Segment s in poly.Segments)
            {
                Edge       e     = SegToEdge(s);
                Vector3D[] verts = new Vector3D[] { e.Start, e.End };
                foreach (Vector3D v in verts)
                {
                    HashSet <Edge> edges;
                    if (!map.TryGetValue(v, out edges))
                    {
                        edges  = new HashSet <Edge>(new H3.Cell.EdgeEqualityComparer());
                        map[v] = edges;
                    }

                    edges.Add(e);
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Connects two polygons by rotating them about edges of a static polygon
        /// The three polygons will meet at a single vertex afterward (this vertex will be convex).
        /// </summary>
        private static void ConnectPolys(Polygon staticPoly, Polygon poly1, Polygon poly2)
        {
            // All three polygons should share one vertex.
            // The edges connected to this vertex (that are in the static polyhedron)
            // will be the hinges we rotate around to connect poly1 and poly2.
            // These are also the edges the static poly shares with the other two.

            Vector3D[] iVerts = staticPoly.Vertices.Intersect(poly1.Vertices).Intersect(poly2.Vertices).ToArray();
            if (iVerts.Length != 1)
            {
                throw new System.ArgumentException();
            }
            Vector3D vertex = iVerts.First();

            // Get our hinges and the two edges we want to merge.
            Edge hinge1 = Hinge(staticPoly, poly1);
            Edge hinge2 = Hinge(staticPoly, poly2);
            Edge e1     = AdjacentEdge(poly1, hinge1, vertex);
            Edge e2     = AdjacentEdge(poly2, hinge2, vertex);

            // Construct circles through the edges they will rotate through when hinged.
            Circle3D c1 = ConstructRotationCircle(hinge1, vertex, e1.Opp(vertex));
            Circle3D c2 = ConstructRotationCircle(hinge2, vertex, e2.Opp(vertex));

            // These circles both lie on the same sphere (with center = vertex and radius 1),
            // and will intersect in two points. Those two points will determine the two
            // locations we can hinge our polys to.
            Vector3D i1, i2;

            SphericalTrig.IntersectionSmart(vertex, c1, c2, out i1, out i2);

            // XXX - Need to think more about how to choose among options.
            double a1 = (e1.Opp(vertex) - c1.Center).AngleTo(i1 - c1.Center);
            double a2 = (e2.Opp(vertex) - c2.Center).AngleTo(i1 - c2.Center);

            RotatePoly(poly1, EdgeAxis(hinge1), -a1);
            RotatePoly(poly2, EdgeAxis(hinge2), a2);
        }
Exemple #8
0
            public int GetHashCode(Segment s)
            {
                Edge e = SegToEdge(s);

                return(m_comparer.GetHashCode(e));
            }
Exemple #9
0
 /// <summary>
 /// Returns the edge adjacent to e and connected to v.
 /// </summary>
 private static Edge AdjacentEdge(Polygon poly, Edge e, Vector3D v)
 {
     Edge[] edges = poly.Segments.Select(s => SegToEdge(s)).ToArray();
     return(AdjacentEdge(edges, e, v));
 }
Exemple #10
0
 private static Vector3D EdgeAxis(Edge e)
 {
     return(e.End - e.Start);
 }
Exemple #11
0
 private static Vector3D EdgeMidpoint(Edge e)
 {
     return((e.Start + e.End) / 2);
 }