Beispiel #1
0
 abstract protected object GetBiome(Center p);
Beispiel #2
0
        private void BuildGraph(FortunesAlgorithm <PortableColor> v)
        {
            var pointCenterMap = new Dictionary <PointDouble, Center>();
            var points         = v.GetSiteCoordinates();

            points.ForEach((p) =>
            {
                var c   = new Center();
                c.loc   = p;
                c.index = centers.Count;
                centers.Add(c);
                pointCenterMap[p] = c;
            });

            //bug fix
            centers.ForEach((c) =>
            {
                v.GetRegion(c.loc);
            });

            var libedges       = v.Edges;
            var pointCornerMap = new Dictionary <int, Corner>();

            foreach (var libedge in libedges)
            {
                LineSegment vEdge = libedge.VoronoiEdge();
                LineSegment dEdge = libedge.DelaunayLine();

                var edge = new Edge();
                edge.index = edges.Count;
                edges.Add(edge);

                edge.v0 = MakeCorner(pointCornerMap, vEdge.p0);
                edge.v1 = MakeCorner(pointCornerMap, vEdge.p1);
                edge.d0 = pointCenterMap[dEdge.p0];
                edge.d1 = pointCenterMap[dEdge.p1];

                // Centers point to edges. Corners point to edges.
                if (edge.d0 != null)
                {
                    edge.d0.borders.Add(edge);
                }
                if (edge.d1 != null)
                {
                    edge.d1.borders.Add(edge);
                }
                if (edge.v0 != null)
                {
                    edge.v0.protrudes.Add(edge);
                }
                if (edge.v1 != null)
                {
                    edge.v1.protrudes.Add(edge);
                }

                // Centers point to centers.
                if (edge.d0 != null && edge.d1 != null)
                {
                    AddToCenterList(edge.d0.neighbors, edge.d1);
                    AddToCenterList(edge.d1.neighbors, edge.d0);
                }

                // Corners point to corners
                if (edge.v0 != null && edge.v1 != null)
                {
                    AddToCornerList(edge.v0.adjacent, edge.v1);
                    AddToCornerList(edge.v1.adjacent, edge.v0);
                }

                // Centers point to corners
                if (edge.d0 != null)
                {
                    AddToCornerList(edge.d0.corners, edge.v0);
                    AddToCornerList(edge.d0.corners, edge.v1);
                }
                if (edge.d1 != null)
                {
                    AddToCornerList(edge.d1.corners, edge.v0);
                    AddToCornerList(edge.d1.corners, edge.v1);
                }

                // Corners point to centers
                if (edge.v0 != null)
                {
                    AddToCenterList(edge.v0.touches, edge.d0);
                    AddToCenterList(edge.v0.touches, edge.d1);
                }
                if (edge.v1 != null)
                {
                    AddToCenterList(edge.v1.touches, edge.d0);
                    AddToCenterList(edge.v1.touches, edge.d1);
                }
            }
        }
Beispiel #3
0
        private void DrawPolygon3D <T>(Center c, PortableColor color, IVertexFactory <T> factory, List <T> vertexBuffer)
        {
            //only used if Center c is on the edge of the graph. allows for completely filling in the outer polygons
            Corner edgeCorner1 = null;
            Corner edgeCorner2 = null;

            foreach (Center n in c.neighbors)
            {
                var e = EdgeWithCenters(c, n);

                if (e.v0 == null)
                {
                    //outermost voronoi edges aren't stored in the graph
                    continue;
                }

                //find a corner on the exterior of the graph
                //if this Edge e has one, then it must have two,
                //finding these two corners will give us the missing
                //triangle to render. this special triangle is handled
                //outside this for loop
                var cornerWithOneAdjacent = e.v0.border ? e.v0 : e.v1;
                if (cornerWithOneAdjacent.border)
                {
                    if (edgeCorner1 == null)
                    {
                        edgeCorner1 = cornerWithOneAdjacent;
                    }
                    else
                    {
                        edgeCorner2 = cornerWithOneAdjacent;
                    }
                }
                var p = Transform((float)c.loc.X, (float)c.loc.Y, (float)c.elevation);
                var q = Transform((float)e.v0.loc.X, (float)e.v0.loc.Y, (float)e.v0.elevation);
                var r = Transform((float)e.v1.loc.X, (float)e.v1.loc.Y, (float)e.v1.elevation);
                AddTriangle(p, r, q, color, factory, vertexBuffer);
            }

            //handle the missing triangle
            if (edgeCorner2 != null)
            {
                //if these two outer corners are NOT on the same exterior edge of the graph,
                //then we actually must render a polygon (w/ 4 points) and take into consideration
                //one of the four corners (either 0,0 or 0,height or width,0 or width,height)
                //note: the 'missing polygon' may have more than just 4 points. this
                //is common when the number of sites are quite low (less than 5), but not a problem
                //with a more useful number of sites.
                //TODO: find a way to fix this

                if (CloseEnough(edgeCorner1.loc.X, edgeCorner2.loc.X, 1))
                {
                    var p = Transform((float)c.loc.X, (float)c.loc.Y, (float)c.elevation);
                    var q = Transform((float)edgeCorner1.loc.X, (float)edgeCorner1.loc.Y, (float)edgeCorner1.elevation);
                    var r = Transform((float)edgeCorner2.loc.X, (float)edgeCorner2.loc.Y, (float)edgeCorner2.elevation);
                    AddTriangle(p, r, q, color, factory, vertexBuffer);
                }
                else
                {
                    /*
                     * var points = new PointInt32[] {
                     *  new PointInt32((int)c.loc.X, (int)c.loc.Y),
                     *  new PointInt32((int)edgeCorner1.loc.X, (int)edgeCorner1.loc.Y),
                     *  new PointInt32((int)((CloseEnough(edgeCorner1.loc.X, bounds.x, 1) || CloseEnough(edgeCorner2.loc.X, bounds.x, .5)) ? bounds.x : bounds.right), (int)((CloseEnough(edgeCorner1.loc.Y, bounds.y, 1) || CloseEnough(edgeCorner2.loc.Y, bounds.y, .5)) ? bounds.y : bounds.bottom)),
                     *  new PointInt32((int)edgeCorner2.loc.X, (int)edgeCorner2.loc.Y),
                     * };
                     *
                     * g.FillPolygon(color, points);
                     * c.area += 0; //TODO: area of polygon given vertices*/
                }
            }
        }
Beispiel #4
0
        private void DrawPolygon(IGraphics g, Center c, PortableColor color)
        {
            //only used if Center c is on the edge of the graph. allows for completely filling in the outer polygons
            Corner edgeCorner1 = null;
            Corner edgeCorner2 = null;

            c.area = 0;
            foreach (Center n in c.neighbors)
            {
                Edge e = EdgeWithCenters(c, n);

                if (e.v0 == null)
                {
                    //outermost voronoi edges aren't stored in the graph
                    continue;
                }

                //find a corner on the exterior of the graph
                //if this Edge e has one, then it must have two,
                //finding these two corners will give us the missing
                //triangle to render. this special triangle is handled
                //outside this for loop
                Corner cornerWithOneAdjacent = e.v0.border ? e.v0 : e.v1;
                if (cornerWithOneAdjacent.border)
                {
                    if (edgeCorner1 == null)
                    {
                        edgeCorner1 = cornerWithOneAdjacent;
                    }
                    else
                    {
                        edgeCorner2 = cornerWithOneAdjacent;
                    }
                }

                DrawTriangle(g, color, e.v0, e.v1, c);
                c.area += Math.Abs(c.loc.X * (e.v0.loc.Y - e.v1.loc.Y)
                                   + e.v0.loc.X * (e.v1.loc.Y - c.loc.Y)
                                   + e.v1.loc.X * (c.loc.Y - e.v0.loc.Y)) / 2;
            }

            //handle the missing triangle
            if (edgeCorner2 != null)
            {
                //if these two outer corners are NOT on the same exterior edge of the graph,
                //then we actually must render a polygon (w/ 4 points) and take into consideration
                //one of the four corners (either 0,0 or 0,height or width,0 or width,height)
                //note: the 'missing polygon' may have more than just 4 points. this
                //is common when the number of sites are quite low (less than 5), but not a problem
                //with a more useful number of sites.
                //TODO: find a way to fix this

                if (CloseEnough(edgeCorner1.loc.X, edgeCorner2.loc.X, 1))
                {
                    DrawTriangle(g, color, edgeCorner1, edgeCorner2, c);
                }
                else
                {
                    var points = new PointInt32[] {
                        new PointInt32((int)c.loc.X, (int)c.loc.Y),
                        new PointInt32((int)edgeCorner1.loc.X, (int)edgeCorner1.loc.Y),
                        new PointInt32((int)((CloseEnough(edgeCorner1.loc.X, bounds.x, 1) || CloseEnough(edgeCorner2.loc.X, bounds.x, .5)) ? bounds.x : bounds.right), (int)((CloseEnough(edgeCorner1.loc.Y, bounds.y, 1) || CloseEnough(edgeCorner2.loc.Y, bounds.y, .5)) ? bounds.y : bounds.bottom)),
                        new PointInt32((int)edgeCorner2.loc.X, (int)edgeCorner2.loc.Y),
                    };

                    g.FillPolygon(color, points);
                    c.area += 0; //TODO: area of polygon given vertices
                }
            }
        }
Beispiel #5
0
        private void DrawTriangle(IGraphics g, PortableColor c, Corner c1, Corner c2, Center center)
        {
            var points = new PointInt32[]
            {
                new PointInt32((int)center.loc.X, (int)center.loc.Y),
                new PointInt32((int)c1.loc.X, (int)c1.loc.Y),
                new PointInt32((int)c2.loc.X, (int)c2.loc.Y),
            };

            g.DrawPolygon(c, points);
        }