コード例 #1
0
ファイル: DistanceField.cs プロジェクト: fealty/Frost
        private Sample ComputeTree(
			ref Rectangle region,
			Device2D device2D,
			ref Sample.Location parentTopLeft,
			ref Sample.Location parentTopRight,
			ref Sample.Location parentBottomLeft,
			ref Sample.Location parentBottomRight,
			double level = 1.0)
        {
            Sample sample = new Sample(ref region);

            // define the points on the rectangle to test
            Point topLeft = new Point(region.Left, region.Top);
            Point topRight = new Point(region.Right, region.Top);
            Point bottomLeft = new Point(region.Left, region.Bottom);
            Point bottomRight = new Point(region.Right, region.Bottom);

            // the method was not called recursively, so compute the distances to each point
            if(level <= 1.0)
            {
                mDecomposer.Query(
                    ref topLeft, device2D, out sample.TopLeft.Distance, out sample.TopLeft.Intersection);
                mDecomposer.Query(
                    ref topRight, device2D, out sample.TopRight.Distance, out sample.TopRight.Intersection);
                mDecomposer.Query(
                    ref bottomLeft, device2D, out sample.BottomLeft.Distance, out sample.BottomLeft.Intersection);
                mDecomposer.Query(
                    ref bottomRight, device2D, out sample.BottomRight.Distance, out sample.BottomRight.Intersection);
            }
            else
            {
                // use distances already computed by the caller
                sample.TopLeft = parentTopLeft;
                sample.TopRight = parentTopRight;
                sample.BottomLeft = parentBottomLeft;
                sample.BottomRight = parentBottomRight;
            }

            // do not subdivide lower than a resolved resolution unit
            if(level > MaxLevel)
            {
                return sample;
            }

            int boundaryContains = 0;

            Thickness thick = new Thickness(MaximumError);

            Rectangle boundary = region.Expand(thick);

            boundaryContains += boundary.Contains(sample.TopLeft.Intersection) ? 1 : 0;
            boundaryContains += boundary.Contains(sample.TopRight.Intersection) ? 1 : 0;
            boundaryContains += boundary.Contains(sample.BottomLeft.Intersection) ? 1 : 0;
            boundaryContains += boundary.Contains(sample.BottomRight.Intersection) ? 1 : 0;

            // compute the intersection of the region with the shape
            int boundaryIntersection = 0;

            boundaryIntersection += sample.TopLeft.Distance >= 0.0 ? 1 : -1;
            boundaryIntersection += sample.TopRight.Distance >= 0.0 ? 1 : -1;
            boundaryIntersection += sample.BottomLeft.Distance >= 0.0 ? 1 : -1;
            boundaryIntersection += sample.BottomRight.Distance >= 0.0 ? 1 : -1;

            double s = Math.Abs(boundaryIntersection) != 4 || boundaryContains > 0 ? 0.0 : 1.0;

            double error = MinimumError + ((MaximumError - MinimumError) * s);

            float halfWidth = region.Width / 2.0f;
            float halfHeight = region.Height / 2.0f;

            Point leftCenter = new Point(region.Left, region.Top + halfHeight);
            Point topCenter = new Point(region.Left + halfWidth, region.Top);
            Point rightCenter = new Point(region.Right, region.Top + halfHeight);
            Point bottomCenter = new Point(region.Left + halfWidth, region.Bottom);
            Point center = new Point(region.Left + halfWidth, region.Top + halfHeight);

            Sample.Location centerLocation = new Sample.Location();

            mDecomposer.Query(
                ref center, device2D, out centerLocation.Distance, out centerLocation.Intersection);

            boundaryContains += boundary.Contains(centerLocation.Intersection) ? 1 : 0;

            if(boundaryContains == 0)
            {
                return sample;
            }

            Sample.Location leftCenterLocation = new Sample.Location();
            Sample.Location topCenterLocation = new Sample.Location();
            Sample.Location rightCenterLocation = new Sample.Location();
            Sample.Location bottomCenterLocation = new Sample.Location();

            mDecomposer.Query(
                ref leftCenter, device2D, out leftCenterLocation.Distance, out leftCenterLocation.Intersection);
            mDecomposer.Query(
                ref topCenter, device2D, out topCenterLocation.Distance, out topCenterLocation.Intersection);
            mDecomposer.Query(
                ref rightCenter,
                device2D,
                out rightCenterLocation.Distance,
                out rightCenterLocation.Intersection);
            mDecomposer.Query(
                ref bottomCenter,
                device2D,
                out bottomCenterLocation.Distance,
                out bottomCenterLocation.Intersection);

            double reconstructedLeftCenter = (sample.TopLeft.Distance + sample.BottomLeft.Distance) / 2.0;
            double reconstructedTopCenter = (sample.TopLeft.Distance + sample.TopRight.Distance) / 2.0;
            double reconstructedRightCenter = (sample.TopRight.Distance + sample.BottomRight.Distance) / 2.0;
            double reconstructedBottomCenter = (sample.BottomLeft.Distance + sample.BottomRight.Distance) /
                                               2.0;
            double reconstructedCenter = (reconstructedTopCenter + reconstructedBottomCenter) / 2.0;

            bool isLeftCenterInvalid = Math.Abs(reconstructedLeftCenter - leftCenterLocation.Distance) >
                                       error;
            bool isTopCenterInvalid = Math.Abs(reconstructedTopCenter - topCenterLocation.Distance) > error;
            bool isRightCenterInvalid = Math.Abs(reconstructedRightCenter - rightCenterLocation.Distance) >
                                        error;
            bool isBottomCenterInvalid =
                Math.Abs(reconstructedBottomCenter - bottomCenterLocation.Distance) > error;
            bool isCenterInvalid = Math.Abs(reconstructedCenter - centerLocation.Distance) > error;

            if(isLeftCenterInvalid || isTopCenterInvalid || isRightCenterInvalid || isBottomCenterInvalid ||
               isCenterInvalid)
            {
                Rectangle topLeftRegion = new Rectangle(
                    topLeft.X, topLeft.Y, center.X - topLeft.X, center.Y - topLeft.Y);

                sample.Children.Add(
                    ComputeTree(
                        ref topLeftRegion,
                        device2D,
                        ref sample.TopLeft,
                        ref topCenterLocation,
                        ref leftCenterLocation,
                        ref centerLocation,
                        level + 1.0));

                Rectangle topRightRegion = new Rectangle(
                    center.X, topRight.Y, topRight.X - center.X, center.Y - topRight.Y);

                sample.Children.Add(
                    ComputeTree(
                        ref topRightRegion,
                        device2D,
                        ref topCenterLocation,
                        ref sample.TopRight,
                        ref centerLocation,
                        ref rightCenterLocation,
                        level + 1.0));

                Rectangle bottomRightRegion = new Rectangle(
                    center.X, center.Y, bottomRight.X - center.X, bottomRight.Y - center.Y);

                sample.Children.Add(
                    ComputeTree(
                        ref bottomRightRegion,
                        device2D,
                        ref centerLocation,
                        ref rightCenterLocation,
                        ref bottomCenterLocation,
                        ref sample.BottomRight,
                        level + 1.0));

                Rectangle bottomLeftRegion = new Rectangle(
                    bottomLeft.X, center.Y, center.X - bottomLeft.X, bottomLeft.Y - center.Y);

                sample.Children.Add(
                    ComputeTree(
                        ref bottomLeftRegion,
                        device2D,
                        ref leftCenterLocation,
                        ref centerLocation,
                        ref sample.BottomLeft,
                        ref bottomCenterLocation,
                        level + 1.0));
            }

            return sample;
        }
コード例 #2
0
ファイル: DistanceField.cs プロジェクト: fealty/Frost
        private Sample ComputeTree(ref Rectangle region, Device2D device2D)
        {
            Sample.Location empty = new Sample.Location();

            return ComputeTree(ref region, device2D, ref empty, ref empty, ref empty, ref empty);
        }