Пример #1
0
 static RenderTolerance()
 {
     // cache this values - only do the check once
     isVistaOrNewer      = Const.IsVistaOrNewer;
     isSoftwareRendering = (RenderCapability.Tier == 0);
     isSquare96Dpi       = ((MathEx.AreCloseEnough(Const.DpiX, Const.DpiY)) && (MathEx.AreCloseEnough(Const.DpiX, 96.0)));
     ResetDefaults();
 }
Пример #2
0
        private static Matrix GetConversionToRelative(Point min, Point max)
        {
            double width  = max.X - min.X;
            double height = max.Y - min.Y;
            double scaleX = MathEx.AreCloseEnough(width, 0.0) ? 0.0 : 1.0 / width;
            double scaleY = MathEx.AreCloseEnough(height, 0.0) ? 0.0 : 1.0 / height;

            Matrix result = new ScaleTransform(scaleX, scaleY).Value;

            result.OffsetX = -min.X * scaleX;
            result.OffsetY = -min.Y * scaleY;

            return(result);
        }
Пример #3
0
        private bool CompareStroke(Stroke originalStroke, Stroke currerntStroke)
        {
            if (originalStroke.StylusPoints.Count != currerntStroke.StylusPoints.Count)
            {
                return(false);
            }

            for (int i = 0; i < originalStroke.StylusPoints.Count; i++)
            {
                if (!(MathEx.AreCloseEnough((Point)originalStroke.StylusPoints[i], (Point)currerntStroke.StylusPoints[i])))
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #4
0
        public void NormalizeTextureCoordinates()
        {
            // Shortcuts for common cases 
            if (MathEx.AreCloseEnough(minUV, new Point()))
            {
                if (MathEx.AreCloseEnough(maxUV, new Point()) ||
                     MathEx.AreCloseEnough(maxUV, new Point(1, 1)))
                {
                    // pre-normalized or no UV's
                    return;
                }
            }

            double scaleX = maxUV.X - minUV.X;
            double scaleY = maxUV.Y - minUV.Y;
            scaleX = MathEx.AreCloseEnough(scaleX, 0.0) ? 0.0 : 1.0 / scaleX;
            scaleY = MathEx.AreCloseEnough(scaleY, 0.0) ? 0.0 : 1.0 / scaleY;

            double offsetX = -minUV.X * scaleX;
            double offsetY = -minUV.Y * scaleY;

            foreach (Triangle t in frontFaceTriangles)
            {
                t.vertex1.TextureCoordinates.X = offsetX + (t.vertex1.U * scaleX);
                t.vertex1.TextureCoordinates.Y = offsetY + (t.vertex1.V * scaleY);
                t.vertex2.TextureCoordinates.X = offsetX + (t.vertex2.U * scaleX);
                t.vertex2.TextureCoordinates.Y = offsetY + (t.vertex2.V * scaleY);
                t.vertex3.TextureCoordinates.X = offsetX + (t.vertex3.U * scaleX);
                t.vertex3.TextureCoordinates.Y = offsetY + (t.vertex3.V * scaleY);
            }
            foreach (Triangle t in backFaceTriangles)
            {
                t.vertex1.TextureCoordinates.X = offsetX + (t.vertex1.U * scaleX);
                t.vertex1.TextureCoordinates.Y = offsetY + (t.vertex1.V * scaleY);
                t.vertex2.TextureCoordinates.X = offsetX + (t.vertex2.U * scaleX);
                t.vertex2.TextureCoordinates.Y = offsetY + (t.vertex2.V * scaleY);
                t.vertex3.TextureCoordinates.X = offsetX + (t.vertex3.U * scaleX);
                t.vertex3.TextureCoordinates.Y = offsetY + (t.vertex3.V * scaleY);
            }
        }
Пример #5
0
        private static bool DeepEquals(object obj1, object obj2, bool skipUnimportant)
        {
            if (object.ReferenceEquals(obj1, obj2))
            {
                // Shortcut- if they are the same object, return true;
                return(true);
            }
            Type type1 = obj1.GetType();
            Type type2 = obj2.GetType();

            if (type1 != type2)
            {
                return(false);
            }
            if (type1 == typeof(string))
            {
                return(obj1.ToString() == obj2.ToString());
            }

            bool        equals;
            TrustedType trustedType = PT.Trust(type1);

            TrustedPropertyInfo[] properties = trustedType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (TrustedPropertyInfo property in properties)
            {
                if (skipUnimportant)
                {
                    // If we don't care about the property (declared by Freezable or its ancestors), skip it!
                    if (IsPropertyDeclaredByAncestorsOf(PT.Untrust(property.DeclaringType), typeof(Freezable)) ||
                        IsPropertyDeclaredByAncestorsOf(PT.Untrust(property.DeclaringType), typeof(FrameworkElement)))
                    {
                        continue;
                    }
                }
                if (IsPropertyProblematic(property))
                {
                    continue;
                }
                if (property.Name == "Item")
                {
                    if (obj1 is IEnumerable)
                    {
                        equals = DeepEquals((IEnumerable)obj1, (IEnumerable)obj2, skipUnimportant);
                    }
                    else
                    {
                        // This is an indexer.  We can't really compare it.
                        equals = true;
                    }
                }
                else
                {
                    object value1 = property.GetValue(obj1, null);
                    object value2 = property.GetValue(obj2, null);

                    if (property.PropertyType.IsValueType)
                    {
                        switch (property.PropertyType.Name)
                        {
                        case "Double": equals = MathEx.AreCloseEnough((double)value1, (double)value2); break;

                        case "Point": equals = MathEx.AreCloseEnough((Point)value1, (Point)value2); break;

                        case "Vector": equals = MathEx.AreCloseEnough((Vector)value1, (Vector)value2); break;

                        case "Rect": equals = MathEx.AreCloseEnough((Rect)value1, (Rect)value2); break;

                        case "Matrix": equals = MathEx.AreCloseEnough((Matrix)value1, (Matrix)value2); break;

                        case "Point3D": equals = MathEx.AreCloseEnough((Point3D)value1, (Point3D)value2); break;

                        case "Point4D": equals = MathEx.AreCloseEnough((Point4D)value1, (Point4D)value2); break;

                        case "Quaternion": equals = MathEx.AreCloseEnough((Quaternion)value1, (Quaternion)value2); break;

                        case "Vector3D": equals = MathEx.AreCloseEnough((Vector3D)value1, (Vector3D)value2); break;

                        case "Rect3D": equals = MathEx.AreCloseEnough((Rect3D)value1, (Rect3D)value2); break;

                        case "Matrix3D": equals = MathEx.AreCloseEnough((Matrix3D)value1, (Matrix3D)value2); break;

                        default: equals = object.Equals(value1, value2); break;
                        }
                    }
                    else
                    {
                        equals = DeepEquals(value1, value2, skipUnimportant);
                    }
                }
                if (!equals)
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #6
0
 /// <summary/>
 public static bool IsAffine(Matrix3D m)
 {
     return(MathEx.AreCloseEnough(m.M14, 0) && MathEx.AreCloseEnough(m.M24, 0) &&
            MathEx.AreCloseEnough(m.M34, 0) && MathEx.AreCloseEnough(m.M44, 1));
 }
Пример #7
0
        private Side LineSide(Point3D p1, Point3D p2, double x, double y)
        {
            // If the two points are the same, this is not a line, thus (x,y)
            //  cannot be on either side of it.
            if (MathEx.AreCloseEnough(p1.X, p2.X) && MathEx.AreCloseEnough(p1.Y, p2.Y))
            {
                return(Side.None);
            }

            // Account for precision errors along the triangle edges based on
            // RenderTolerance.PixelToEdgeTolerance value and exit early if we're too close to call.
            double pixelToEdgeTolerance = RenderTolerance.PixelToEdgeTolerance;

            //Increase edge tolerance in Vista nonstandard DPI
            //We *shouldn't* need this at any other time
            //If the ref-renderer is improved to better handle interior edge AA, this can be removed
            if (!RenderTolerance.IsSquare96Dpi && Const.IsVistaOrNewer)
            {
                pixelToEdgeTolerance *= 3;
            }

            // pixelToEdgeTolerance is only used to generate tolerance map. We can be more precise when we determine
            // if a point is inside a triangle. Use a smaller tolerance for this calculation.
            //


            double triangleEdgeTolerance = Math.Min(pixelToEdgeTolerance, RenderTolerance.DefaultPixelToEdgeTolerance);
            double distanceToLine        = MathEx.DistanceFromLine2D(new Point3D(x, y, 0), p1, p2);

            if (Math.Abs(distanceToLine) < pixelToEdgeTolerance)
            {
                // We've just been guaranteed that (x,y) is really close to the line passing through
                //  p1 and p2.
                // This means that if (x,y) is within the bounds of the line *segment* (p1 and p2 are endpoints)
                //  plus tolerance, then (x,y) must be on the line segment (edge).

                Rect bounds = new Rect(new Point(p1.X, p1.Y), new Point(p2.X, p2.Y));
                if (MathEx.Inflate(bounds, pixelToEdgeTolerance).Contains(new Point(x, y)))
                {
                    pixelOnEdge = true;
                }

                // We don't know which side we're on because we're too close,
                //  so report that we're on whichever side the caller wants us to be.
                // Any final uncertainty will be decided by the value of "pixelOnEdge."

                if (Math.Abs(distanceToLine) < triangleEdgeTolerance)
                {
                    return(Side.Both);
                }
            }

            // Cross product's Z component will be positive if the point is on the left of the line,
            // and negative if the point is on the right. Zero if the point is on the line.
            double crossProductZ = (p1.X - x) * (p2.Y - y) - (p1.Y - y) * (p2.X - x);

            if (MathEx.AreCloseEnough(crossProductZ, 0))
            {
                // For the case where the triangle edge is right over a pixel center
                //  and PixelToEdgeTolerance is too small (e.g. 0), we will test a neighboring pixel.

                // This case counts as on the edge too
                pixelOnEdge = true;

                // The pixel that we test is based on D3D's rendering convention
                //  (this guarantees that we don't render the same edge twice)

                if (!MathEx.AreCloseEnough(p1.Y, p2.Y))
                {
                    return(LineSide(p1, p2, x + 1, y));
                }
                else
                {
                    return(LineSide(p1, p2, x, y + 1));
                }
            }
            else if (crossProductZ < 0)
            {
                return(Side.Right);
            }
            else
            {
                return(Side.Left);
            }
        }