コード例 #1
0
ファイル: DistanceField.cs プロジェクト: fealty/Frost
        public Canvas CreateField(Shape geometry, double normalizedBaseline, Device2D device2D)
        {
            Rectangle normalizedRegion = device2D.Geometry.MeasureRegion(geometry);

            Matrix3X2 transform = Matrix3X2.Identity;

            transform.Translate(
                (0.5f - (normalizedRegion.Width / 2.0f)) * EmLength,
                (0.5f - (normalizedRegion.Height / 2.0f)) * EmLength,
                out transform);

            transform.Translate(
                -normalizedRegion.X * EmLength, -normalizedRegion.Y * EmLength, out transform);

            transform.Scale(EmLength, EmLength, out transform);

            mDecomposer.Decompose(geometry, ref transform, device2D);

            Rectangle newReg = new Rectangle(0, 0, EmLength, EmLength);

            mSample = ComputeTree(ref newReg, device2D);

            float maxNegative = float.MinValue;

            float pixel = EmLength / ResolvedLength;

            for(int y = 0; y < ResolvedLength; ++y)
            {
                for(int x = 0; x < ResolvedLength; ++x)
                {
                    float distance = 0.0f;

                    Point point = new Point((pixel * x), (pixel * y));

                    distance += mSample.SampleSample(ref point);

                    maxNegative = Math.Max(maxNegative, distance);

                    mField[y, x] = distance;
                }
            }

            int rgbaIndex = 0;

            for(int y = 0; y < ResolvedLength; ++y)
            {
                for(int x = 0; x < ResolvedLength; ++x)
                {
                    double distance = mField[y, x];

                    const double test = 0.5;

                    if(distance < 0.0)
                    {
                        distance = Math.Abs(distance) / Math.Abs(maxNegative);

                        distance = test + ((1.0 - test) * distance);
                    }
                    else
                    {
                        distance = Math.Abs(distance) / Math.Abs(maxNegative);

                        distance = test - (test * distance);
                    }

                    distance = Math.Min(1.0, distance);
                    distance = Math.Max(0.0, distance);

                    byte value = Convert.ToByte(255 - (distance * 255));

                    //byte[] bytes = BitConverter.GetBytes(value);

                    mRgbaData[rgbaIndex + 0] = 0;
                    mRgbaData[rgbaIndex + 1] = 0;
                    mRgbaData[rgbaIndex + 2] = 0;
                    mRgbaData[rgbaIndex + 3] = value;

                    rgbaIndex += 4;
                }
            }

            Canvas newCanvas = new Canvas(new Size(ResolvedLength, ResolvedLength), Frost.Surfacing.SurfaceUsage.Normal);

            device2D.Resources.Copy(mRgbaData, newCanvas);

            return newCanvas;
        }
コード例 #2
0
ファイル: GeometryNode.cs プロジェクト: fealty/Frost
        public override void Query(ref Point point, out Sample.Location sample)
        {
            sample.Distance = float.MaxValue;

            FullLine selectedLine = _Lines[0];

            if(_Lines.Length > 1)
            {
                foreach(FullLine line in _Lines)
                {
                    Point point1 = line.Point1;
                    Point point2 = line.Point2;

                    float newDistance = point.SquaredDistanceTo(point1, point2);

                    if(newDistance < sample.Distance)
                    {
                        sample.Distance = newDistance;

                        selectedLine = line;
                    }
                }
            }

            sample.Distance = point.DistanceTo(
                selectedLine.Point1, selectedLine.Point2, out sample.Intersection);
        }
コード例 #3
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;
        }
コード例 #4
0
ファイル: Program.cs プロジェクト: fealty/Frost
        private void TestTest(Sample s, Device2D device2D)
        {
            Rectangle region = s.Region;

            device2D.Painter.StrokeRectangle(region);

            /*float mag = 50;

            Frost.Point tl =
                new Frost.Point(
                    region.Left + s.TopLeft.Intersection.X * mag,
                    region.Top + s.TopLeft.Intersection.Y * mag);
            Frost.Point tr =
                new Frost.Point(
                    region.Right + s.TopRight.Intersection.X * mag,
                    region.Top + s.TopRight.Intersection.Y * mag);
            Frost.Point bl =
                new Frost.Point(
                    region.Left + s.BottomLeft.Intersection.X * mag,
                    region.Bottom + s.BottomLeft.Intersection.Y * mag);
            Frost.Point br =
                new Frost.Point(
                    region.Right + s.BottomRight.Intersection.X * mag,
                    region.Bottom + s.BottomRight.Intersection.Y * mag);

            tl = s.TopLeft.Intersection;
            tr = s.TopRight.Intersection;
            bl = s.BottomLeft.Intersection;
            br = s.BottomRight.Intersection;

            mDevice2D.Painter.SetBrush(Color.Green);
            if(s.TopLeft.Distance > 0.0)
                mDevice2D.Painter.Stroke(region.Left, region.Top, tl.X, tl.Y);
            if(s.TopRight.Distance > 0.0)
                mDevice2D.Painter.Stroke(region.Right, region.Top, tr.X, tr.Y);
            if(s.BottomLeft.Distance > 0.0)
                mDevice2D.Painter.Stroke(region.Left, region.Bottom, bl.X, bl.Y);
            if(s.BottomRight.Distance > 0.0)
                mDevice2D.Painter.Stroke(region.Right, region.Bottom, br.X, br.Y);//*/
            device2D.Painter.SetBrush(Color.Red);

            foreach(Sample ss in s.Children)
            {
                TestTest(ss, device2D);
            }
        }