Example #1
0
 /// <summary>
 /// 构造方法:创建并初始化Editor类型对象。
 /// </summary>
 public Editor()
 {
     StringDictionary.Clear();
     Int32Dictionary.Clear();
     BooleanDictionary.Clear();
     DoubleDictionary.Clear();
 }
Example #2
0
        private void DrawSubdivision(Subdivision division)
        {
            // generate new random subdivision if desired
            if (division == null)
            {
                PointD offset = new PointD(OutputBox.Width * 0.2, OutputBox.Height * 0.2);
                SizeD  scale  = new SizeD(OutputBox.Width * 0.6, OutputBox.Height * 0.6);

                int      count  = MersenneTwister.Default.Next(4, 12);
                PointD[] points = new PointD[count];

                for (int i = 0; i < points.Length; i++)
                {
                    points[i] = new PointD(
                        offset.X + MersenneTwister.Default.NextDouble() * scale.Width,
                        offset.Y + MersenneTwister.Default.NextDouble() * scale.Height);
                }

                // outer bounds for Voronoi pseudo-vertices
                double margin = 3 * FontSize;
                RectD  bounds = new RectD(margin, margin,
                                          OutputBox.Width - 2 * margin, OutputBox.Height - 2 * margin);

                var result = Voronoi.FindAll(points, bounds);
                division = result.ToVoronoiSubdivision().Source;
            }

            _division = division;
            _division.Validate();
            _nearestEdge = -1;

            _edges = DrawSubdivision(OutputBox, FontSize, division);
            OutputBox.Children.Add(VertexCircle);
        }
Example #3
0
        /// <summary>
        /// Updates the <see cref="SubdivisionFace"/> keys in the specified dictionaries after the
        /// specified <see cref="SubdivisionEdge"/> has been split.</summary>
        /// <param name="edge">
        /// The <see cref="SubdivisionEdge"/> whose splitting resulted in the current <see
        /// cref="SplitEdgeResult"/>.</param>
        /// <param name="edgeToFace1">
        /// An <see cref="Int32Dictionary{T}"/> that maps the keys of any existing half-edges to the
        /// keys of the incident bounded <see cref="Subdivision.Faces"/> of the corresponding <see
        /// cref="Subdivision.Edges"/> in a first <see cref="Subdivision"/>.</param>
        /// <param name="edgeToFace2">
        /// An <see cref="Int32Dictionary{T}"/> that maps the keys of any existing half-edges to the
        /// keys of the incident bounded <see cref="Subdivision.Faces"/> of the corresponding <see
        /// cref="Subdivision.Edges"/> in a second <see cref="Subdivision"/>.</param>
        /// <remarks>
        /// <b>UpdateFaces</b> ensures that the mapping between original and intersected faces
        /// established by the <see cref="Subdivision.Intersection"/> algorithm is kept up-to-date
        /// when edge splitting results in a valid <see cref="CreatedEdge"/>.</remarks>

        public void UpdateFaces(SubdivisionEdge edge,
                                Int32Dictionary <Int32> edgeToFace1, Int32Dictionary <Int32> edgeToFace2)
        {
            if (CreatedEdge == null)
            {
                return;
            }
            int face;

            if (edgeToFace1.TryGetValue(edge._key, out face))
            {
                Debug.Assert(face != 0);
                edgeToFace1.Add(CreatedEdge._key, face);
            }

            if (edgeToFace2.TryGetValue(edge._key, out face))
            {
                Debug.Assert(face != 0);
                edgeToFace2.Add(CreatedEdge._key, face);
            }
        }
Example #4
0
 /// <summary>
 /// 方法:存入int类型的配置信息。
 /// </summary>
 /// <param name="key">关键字</param>
 /// <param name="value">配置信息</param>
 public void PutInt32(string key, int value)
 {
     Int32Dictionary.Add(key, value);
 }
Example #5
0
 /// <summary>
 /// 构造方法:创建并初始化Editor类型对象。
 /// </summary>
 /// <param name="key">关键字</param>
 /// <param name="value">配置信息</param>
 public Editor(String key, Int32 value)
 {
     Int32Dictionary.Clear();
     PutInt32(key, value);
 }
Example #6
0
        /// <summary>
        /// Draws the specified <see cref="Subdivision"/> to the specified <see cref="Canvas"/>.
        /// </summary>
        /// <param name="canvas">
        /// The <see cref="Canvas"/> to draw on.</param>
        /// <param name="fontSize">
        /// The <see cref="Control.FontSize"/> for all text labels.</param>
        /// <param name="division">
        /// The <see cref="Subdivision"/> to draw on <paramref name="canvas"/>.</param>
        /// <returns>
        /// An <see cref="Int32Dictionary{T}"/> that maps the keys of all half-edges in <paramref
        /// name="division"/> to the corresponding WPF <see cref="Path"/>.</returns>

        internal static Int32Dictionary <Path> DrawSubdivision(
            Canvas canvas, double fontSize, Subdivision division)
        {
            canvas.Children.Clear();
            var edges = new Int32Dictionary <Path>(division.Edges.Count);

            // draw vertices
            const double radius = 2.0;

            foreach (PointD vertex in division.Vertices.Keys)
            {
                var circle = new Ellipse()
                {
                    Width  = 2 * radius, Height = 2 * radius,
                    Stroke = Brushes.Black,
                    Fill   = Brushes.Black
                };

                Canvas.SetLeft(circle, vertex.X - radius);
                Canvas.SetTop(circle, vertex.Y - radius);

                canvas.Children.Add(circle);
            }

            // draw half-edges with keys
            foreach (var pair in division.Edges)
            {
                LineD line = pair.Value.ToLine();

                double deltaX = line.End.X - line.Start.X;
                double deltaY = line.End.Y - line.Start.Y;
                double length = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);

                // slightly offset half-edge toward incident face
                double offsetX = radius * deltaX / length;
                double offsetY = radius * deltaY / length;

                double x0 = line.Start.X + offsetX - offsetY;
                double y0 = line.Start.Y + offsetX + offsetY;
                double x1 = line.End.X - offsetX - offsetY;
                double y1 = line.End.Y + offsetX - offsetY;

                // draw hook in direction of half-edge
                double angle     = line.Angle + 0.75 * Math.PI;
                Point  hookStart = new Point(x1 - deltaX / 4, y1 - deltaY / 4);
                Point  hookEnd   = new Point(
                    hookStart.X + Math.Cos(angle) * 8,
                    hookStart.Y + Math.Sin(angle) * 8);

                PathFigure[] figures = new PathFigure[] {
                    new PathFigure(new Point(x0, y0), new PathSegment[] {
                        new LineSegment(new Point(x1, y1), true)
                    }, false),
                    new PathFigure(hookStart, new PathSegment[] {
                        new LineSegment(hookEnd, true)
                    }, false)
                };

                PathGeometry geometry = new PathGeometry(figures);
                geometry.Freeze();
                Path path = new Path()
                {
                    Stroke = Brushes.Red, Data = geometry
                };
                canvas.Children.Add(path);
                edges.Add(pair.Key, path);

                // draw key of current half-edge
                double centerX   = (line.Start.X + line.End.X) / 2;
                double fontSizeX = (pair.Key < 10 && deltaY > 0) ? fontSize / 2 : fontSize;
                double textX     = centerX - fontSizeX * deltaY / length - fontSize / 1.8;

                double centerY = (line.Start.Y + line.End.Y) / 2;
                double textY   = centerY + fontSize * deltaX / length - fontSize / 1.5;

                TextBlock text = new TextBlock(new Run(pair.Key.ToString()));
                Canvas.SetLeft(text, textX);
                Canvas.SetTop(text, textY);
                canvas.Children.Add(text);
            }

            // draw keys of bounded faces
            foreach (var pair in division.Faces)
            {
                if (pair.Key == 0)
                {
                    continue;
                }

                PointD    centroid = pair.Value.OuterEdge.CycleCentroid;
                TextBlock text     = new TextBlock(new Run(pair.Key.ToString()));
                text.FontWeight = FontWeights.Bold;

                Canvas.SetLeft(text, centroid.X - fontSize / 2);
                Canvas.SetTop(text, centroid.Y - fontSize / 2);
                canvas.Children.Add(text);
            }

            return(edges);
        }