예제 #1
0
        public override IEnumerable <SvgAttribute> GetAttributes()
        {
            var baseAttributes = base.GetAttributes();

            if (baseAttributes != null)
            {
                foreach (var attr in baseAttributes)
                {
                    yield return(attr);
                }
            }

            var ci = CultureInfo.InvariantCulture;

            yield return(new SvgAttribute("fit-to-path", null,
                                          XmlNamespace.AurigmaVectorObjects,
                                          () => FitToPath.ToString(ci),
                                          v => FitToPath = SvgAttribute.ParseBooleanAttribute(v)
                                          ));

            yield return(new SvgAttribute("stretch", null,
                                          XmlNamespace.AurigmaVectorObjects,
                                          () => Stretch.ToString(ci),
                                          v => Stretch = SvgAttribute.ParseBooleanAttribute(v)
                                          ));

            yield return(new SvgAttribute("original-font-size", "0",
                                          XmlNamespace.AurigmaVectorObjects,
                                          () => OriginalFontSize.ToString(ci),
                                          v => OriginalFontSize = SvgAttribute.ParseFloatAttribute(v)
                                          ));

            yield return(new SvgAttribute("fit-to-path-step", "1",
                                          XmlNamespace.AurigmaVectorObjects,
                                          () => FitToPathStep.ToString(ci),
                                          v => FitToPathStep = SvgAttribute.ParseFloatAttribute(v)
                                          ));

            yield return(new SvgAttribute("path-start", "0",
                                          XmlNamespace.AurigmaVectorObjects,
                                          () => PathStart.ToString(ci),
                                          v => PathStart = SvgAttribute.ParseFloatAttribute(v)
                                          ));

            yield return(new SvgAttribute("path-end", "1",
                                          XmlNamespace.AurigmaVectorObjects,
                                          () => PathEnd.ToString(ci),
                                          v => PathEnd = SvgAttribute.ParseFloatAttribute(v)
                                          ));
        }
예제 #2
0
        /// <summary>
        /// Creates between 1 and 5 Béziers curves from parameters specified like in WPF.
        /// </summary>
        public static List <XPoint> BezierCurveFromArc(XPoint point1, XPoint point2, XSize size,
                                                       double rotationAngle, bool isLargeArc, bool clockwise, PathStart pathStart)
        {
            // See also http://www.charlespetzold.com/blog/blog.xml from January 2, 2008:
            // http://www.charlespetzold.com/blog/2008/01/Mathematics-of-ArcSegment.html
            double δx = size.Width;
            double δy = size.Height;

            Debug.Assert(δx * δy > 0);
            double factor             = δy / δx;
            bool   isCounterclockwise = !clockwise;

            // Adjust for different radii and rotation angle.
            XMatrix matrix = new XMatrix();

            matrix.RotateAppend(-rotationAngle);
            matrix.ScaleAppend(δy / δx, 1);
            XPoint pt1 = matrix.Transform(point1);
            XPoint pt2 = matrix.Transform(point2);

            // Get info about chord that connects both points.
            XPoint  midPoint  = new XPoint((pt1.X + pt2.X) / 2, (pt1.Y + pt2.Y) / 2);
            XVector vect      = pt2 - pt1;
            double  halfChord = vect.Length / 2;

            // Get vector from chord to center.
            XVector vectRotated;

            // (comparing two Booleans here!)
            if (isLargeArc == isCounterclockwise)
            {
                vectRotated = new XVector(-vect.Y, vect.X);
            }
            else
            {
                vectRotated = new XVector(vect.Y, -vect.X);
            }

            vectRotated.Normalize();

            // Distance from chord to center.
            double centerDistance = Math.Sqrt(δy * δy - halfChord * halfChord);

            if (double.IsNaN(centerDistance))
            {
                centerDistance = 0;
            }

            // Calculate center point.
            XPoint center = midPoint + centerDistance * vectRotated;

            // Get angles from center to the two points.
            double α = Math.Atan2(pt1.Y - center.Y, pt1.X - center.X);
            double β = Math.Atan2(pt2.Y - center.Y, pt2.X - center.X);

            // (another comparison of two Booleans!)
            if (isLargeArc == (Math.Abs(β - α) < Math.PI))
            {
                if (α < β)
                {
                    α += 2 * Math.PI;
                }
                else
                {
                    β += 2 * Math.PI;
                }
            }

            // Invert matrix for final point calculation.
            matrix.Invert();
            double sweepAngle = β - α;

            // Let the algorithm of GDI+ DrawArc to Bézier curves do the rest of the job
            return(BezierCurveFromArc(center.X - δx * factor, center.Y - δy, 2 * δx * factor, 2 * δy,
                                      α / Calc.Deg2Rad, sweepAngle / Calc.Deg2Rad, pathStart, ref matrix));
        }
예제 #3
0
        /// <summary>
        /// Appends a Bézier curve for an arc within a full quadrant.
        /// </summary>
        static void AppendPartialArcQuadrant(List <XPoint> points, double x, double y, double width, double height, double α, double β, PathStart pathStart, XMatrix matrix)
        {
            Debug.Assert(α >= 0 && α <= 360);
            Debug.Assert(β >= 0);
            if (β > 360)
            {
                β = β - Math.Floor(β / 360) * 360;
            }
            Debug.Assert(Math.Abs(α - β) <= 90);

            // Scanling factor.
            double δx = width / 2;
            double δy = height / 2;

            // Center of ellipse.
            double x0 = x + δx;
            double y0 = y + δy;

            // We have the following quarters:
            //     |
            //   2 | 3
            // ----+-----
            //   1 | 0
            //     |
            // If the angles lie in quarter 2 or 3, their values are subtracted by 180 and the
            // resulting curve is reflected at the center. This algorithm works as expected (simply tried out).
            // There may be a mathematically more elegant solution...
            bool reflect = false;

            if (α >= 180 && β >= 180)
            {
                α      -= 180;
                β      -= 180;
                reflect = true;
            }

            double cosα, cosβ, sinα, sinβ;

            if (width == height)
            {
                // Circular arc needs no correction.
                α = α * Calc.Deg2Rad;
                β = β * Calc.Deg2Rad;
            }
            else
            {
                // Elliptic arc needs the angles to be adjusted such that the scaling transformation is compensated.
                α    = α * Calc.Deg2Rad;
                sinα = Math.Sin(α);
                if (Math.Abs(sinα) > 1E-10)
                {
                    α = Math.PI / 2 - Math.Atan(δy * Math.Cos(α) / (δx * sinα));
                }
                β    = β * Calc.Deg2Rad;
                sinβ = Math.Sin(β);
                if (Math.Abs(sinβ) > 1E-10)
                {
                    β = Math.PI / 2 - Math.Atan(δy * Math.Cos(β) / (δx * sinβ));
                }
            }

            double κ = 4 * (1 - Math.Cos((α - β) / 2)) / (3 * Math.Sin((β - α) / 2));

            sinα = Math.Sin(α);
            cosα = Math.Cos(α);
            sinβ = Math.Sin(β);
            cosβ = Math.Cos(β);

            //XPoint pt1, pt2, pt3;
            if (!reflect)
            {
                // Calculation for quarter 0 and 1.
                switch (pathStart)
                {
                case PathStart.MoveTo1st:
                    points.Add(matrix.Transform(new XPoint(x0 + δx * cosα, y0 + δy * sinα)));
                    break;

                case PathStart.LineTo1st:
                    points.Add(matrix.Transform(new XPoint(x0 + δx * cosα, y0 + δy * sinα)));
                    break;

                case PathStart.Ignore1st:
                    break;
                }
                points.Add(matrix.Transform(new XPoint(x0 + δx * (cosα - κ * sinα), y0 + δy * (sinα + κ * cosα))));
                points.Add(matrix.Transform(new XPoint(x0 + δx * (cosβ + κ * sinβ), y0 + δy * (sinβ - κ * cosβ))));
                points.Add(matrix.Transform(new XPoint(x0 + δx * cosβ, y0 + δy * sinβ)));
            }
            else
            {
                // Calculation for quarter 2 and 3.
                switch (pathStart)
                {
                case PathStart.MoveTo1st:
                    points.Add(matrix.Transform(new XPoint(x0 - δx * cosα, y0 - δy * sinα)));
                    break;

                case PathStart.LineTo1st:
                    points.Add(matrix.Transform(new XPoint(x0 - δx * cosα, y0 - δy * sinα)));
                    break;

                case PathStart.Ignore1st:
                    break;
                }
                points.Add(matrix.Transform(new XPoint(x0 - δx * (cosα - κ * sinα), y0 - δy * (sinα + κ * cosα))));
                points.Add(matrix.Transform(new XPoint(x0 - δx * (cosβ + κ * sinβ), y0 - δy * (sinβ - κ * cosβ))));
                points.Add(matrix.Transform(new XPoint(x0 - δx * cosβ, y0 - δy * sinβ)));
            }
        }
예제 #4
0
        /// <summary>
        /// Creates between 1 and 5 Béziers curves from parameters specified like in GDI+.
        /// </summary>
        public static List <XPoint> BezierCurveFromArc(double x, double y, double width, double height, double startAngle, double sweepAngle,
                                                       PathStart pathStart, ref XMatrix matrix)
        {
            List <XPoint> points = new List <XPoint>();

            // Normalize the angles.
            double α = startAngle;

            if (α < 0)
            {
                α = α + (1 + Math.Floor((Math.Abs(α) / 360))) * 360;
            }
            else if (α > 360)
            {
                α = α - Math.Floor(α / 360) * 360;
            }
            Debug.Assert(α >= 0 && α <= 360);

            double β = sweepAngle;

            if (β < -360)
            {
                β = -360;
            }
            else if (β > 360)
            {
                β = 360;
            }

            if (α == 0 && β < 0)
            {
                α = 360;
            }
            else if (α == 360 && β > 0)
            {
                α = 0;
            }

            // Is it possible that the arc is small starts and ends in same quadrant?
            bool smallAngle = Math.Abs(β) <= 90;

            β = α + β;
            if (β < 0)
            {
                β = β + (1 + Math.Floor((Math.Abs(β) / 360))) * 360;
            }

            bool clockwise     = sweepAngle > 0;
            int  startQuadrant = Quadrant(α, true, clockwise);
            int  endQuadrant   = Quadrant(β, false, clockwise);

            if (startQuadrant == endQuadrant && smallAngle)
            {
                AppendPartialArcQuadrant(points, x, y, width, height, α, β, pathStart, matrix);
            }
            else
            {
                int  currentQuadrant = startQuadrant;
                bool firstLoop       = true;
                while (true)
                {
                    if (currentQuadrant == startQuadrant && firstLoop)
                    {
                        double ξ = currentQuadrant * 90 + (clockwise ? 90 : 0);
                        AppendPartialArcQuadrant(points, x, y, width, height, α, ξ, pathStart, matrix);
                    }
                    else if (currentQuadrant == endQuadrant)
                    {
                        double ξ = currentQuadrant * 90 + (clockwise ? 0 : 90);
                        AppendPartialArcQuadrant(points, x, y, width, height, ξ, β, PathStart.Ignore1st, matrix);
                    }
                    else
                    {
                        double ξ1 = currentQuadrant * 90 + (clockwise ? 0 : 90);
                        double ξ2 = currentQuadrant * 90 + (clockwise ? 90 : 0);
                        AppendPartialArcQuadrant(points, x, y, width, height, ξ1, ξ2, PathStart.Ignore1st, matrix);
                    }

                    // Don't stop immediately if arc is greater than 270 degrees.
                    if (currentQuadrant == endQuadrant && smallAngle)
                    {
                        break;
                    }
                    smallAngle = true;

                    if (clockwise)
                    {
                        currentQuadrant = currentQuadrant == 3 ? 0 : currentQuadrant + 1;
                    }
                    else
                    {
                        currentQuadrant = currentQuadrant == 0 ? 3 : currentQuadrant - 1;
                    }

                    firstLoop = false;
                }
            }
            return(points);
        }
예제 #5
0
        /// <summary>
        /// Evaluates a Zero or More Path
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public override BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            List <List <INode> > paths = new List <List <INode> >();
            BaseMultiset         initialInput = context.InputMultiset;
            int step = 0, prevCount = 0, skipCount = 0;

            String subjVar = PathStart.VariableName;
            String objVar = PathEnd.VariableName;
            bool   bothTerms = (subjVar == null && objVar == null);
            bool   reverse = false;

            if (subjVar == null || (context.InputMultiset.ContainsVariable(subjVar)))
            {
                // Work Forwards from the Starting Term or Bound Variable
                // OR if there is no Ending Term or Bound Variable work forwards regardless
                if (subjVar == null)
                {
                    paths.Add(((NodeMatchPattern)PathStart).Node.AsEnumerable().ToList());
                }
                else if (context.InputMultiset.ContainsVariable(subjVar))
                {
                    paths.AddRange((from s in context.InputMultiset.Sets
                                    where s[subjVar] != null
                                    select s[subjVar]).Distinct().Select(n => n.AsEnumerable().ToList()));
                }
            }
            else if (objVar == null || (context.InputMultiset.ContainsVariable(objVar)))
            {
                // Work Backwards from Ending Term or Bound Variable
                if (objVar == null)
                {
                    paths.Add(((NodeMatchPattern)PathEnd).Node.AsEnumerable().ToList());
                }
                else
                {
                    paths.AddRange((from s in context.InputMultiset.Sets
                                    where s[objVar] != null
                                    select s[objVar]).Distinct().Select(n => n.AsEnumerable().ToList()));
                }
                reverse = true;
            }

            if (paths.Count == 0)
            {
                GetPathStarts(context, paths, reverse);
            }

            // Traverse the Paths
            do
            {
                prevCount = paths.Count;
                foreach (List <INode> path in paths.Skip(skipCount).ToList())
                {
                    foreach (INode nextStep in EvaluateStep(context, path, reverse))
                    {
                        List <INode> newPath = new List <INode>(path);
                        newPath.Add(nextStep);
                        paths.Add(newPath);
                    }
                }

                // Update Counts
                // skipCount is used to indicate the paths which we will ignore for the purposes of
                // trying to further extend since we've already done them once
                step++;
                if (paths.Count == 0)
                {
                    break;
                }
                skipCount = prevCount;

                // Can short circuit evaluation here if both are terms and any path is acceptable
                if (bothTerms)
                {
                    bool exit = false;
                    foreach (List <INode> path in paths)
                    {
                        if (reverse)
                        {
                            if (PathEnd.Accepts(context, path[0]) && PathStart.Accepts(context, path[path.Count - 1]))
                            {
                                exit = true;
                                break;
                            }
                        }
                        else
                        {
                            if (PathStart.Accepts(context, path[0]) && PathEnd.Accepts(context, path[path.Count - 1]))
                            {
                                exit = true;
                                break;
                            }
                        }
                    }
                    if (exit)
                    {
                        break;
                    }
                }
            } while (paths.Count > prevCount || (step == 1 && paths.Count == prevCount));

            if (paths.Count == 0)
            {
                // If all path starts lead nowhere then we get the Null Multiset as a result
                context.OutputMultiset = new NullMultiset();
            }
            else
            {
                context.OutputMultiset = new Multiset();

                // Evaluate the Paths to check that are acceptable
                HashSet <ISet> returnedPaths = new HashSet <ISet>();
                foreach (List <INode> path in paths)
                {
                    if (reverse)
                    {
                        if (PathEnd.Accepts(context, path[0]) && PathStart.Accepts(context, path[path.Count - 1]))
                        {
                            Set s = new Set();
                            if (!bothTerms)
                            {
                                if (subjVar != null)
                                {
                                    s.Add(subjVar, path[path.Count - 1]);
                                }
                                if (objVar != null)
                                {
                                    s.Add(objVar, path[0]);
                                }
                            }
                            // Make sure to check for uniqueness
                            if (returnedPaths.Contains(s))
                            {
                                continue;
                            }
                            context.OutputMultiset.Add(s);
                            returnedPaths.Add(s);

                            // If both are terms can short circuit evaluation here
                            // It is sufficient just to determine that there is one path possible
                            if (bothTerms)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (PathStart.Accepts(context, path[0]) && PathEnd.Accepts(context, path[path.Count - 1]))
                        {
                            Set s = new Set();
                            if (!bothTerms)
                            {
                                if (subjVar != null)
                                {
                                    s.Add(subjVar, path[0]);
                                }
                                if (objVar != null)
                                {
                                    s.Add(objVar, path[path.Count - 1]);
                                }
                            }
                            // Make sure to check for uniqueness
                            if (returnedPaths.Contains(s))
                            {
                                continue;
                            }
                            context.OutputMultiset.Add(s);
                            returnedPaths.Add(s);

                            // If both are terms can short circuit evaluation here
                            // It is sufficient just to determine that there is one path possible
                            if (bothTerms)
                            {
                                break;
                            }
                        }
                    }
                }

                // Now add the zero length paths into
                IEnumerable <INode> nodes;
                if (subjVar != null)
                {
                    if (objVar != null)
                    {
                        nodes = (from s in context.OutputMultiset.Sets
                                 where s[subjVar] != null
                                 select s[subjVar]).Concat(from s in context.OutputMultiset.Sets
                                                           where s[objVar] != null
                                                           select s[objVar]).Distinct();
                    }
                    else
                    {
                        nodes = (from s in context.OutputMultiset.Sets
                                 where s[subjVar] != null
                                 select s[subjVar]).Distinct();
                    }
                }
                else if (objVar != null)
                {
                    nodes = (from s in context.OutputMultiset.Sets
                             where s[objVar] != null
                             select s[objVar]).Distinct();
                }
                else
                {
                    nodes = Enumerable.Empty <INode>();
                }

                if (bothTerms)
                {
                    // If both were terms transform to an Identity/Null Multiset as appropriate
                    if (context.OutputMultiset.IsEmpty)
                    {
                        context.OutputMultiset = new NullMultiset();
                    }
                    else
                    {
                        context.OutputMultiset = new IdentityMultiset();
                    }
                }

                // Then union in the zero length paths
                context.InputMultiset = initialInput;
                ZeroLengthPath zeroPath    = new ZeroLengthPath(PathStart, PathEnd, Path);
                BaseMultiset   currResults = context.OutputMultiset;
                context.OutputMultiset = new Multiset();
                BaseMultiset results = context.Evaluate(zeroPath);//zeroPath.Evaluate(context);
                context.OutputMultiset = currResults;
                foreach (ISet s in results.Sets)
                {
                    if (!context.OutputMultiset.Sets.Contains(s))
                    {
                        context.OutputMultiset.Add(s.Copy());
                    }
                }
            }

            context.InputMultiset = initialInput;
            return(context.OutputMultiset);
        }
예제 #6
0
 /// <summary>
 /// Gets the String representation of the Algebra
 /// </summary>
 /// <returns></returns>
 public override string ToString()
 {
     return("ZeroOrMorePath(" + PathStart.ToString() + ", " + Path.ToString() + ", " + PathEnd.ToString() + ")");
 }
예제 #7
0
        /// <summary>
        /// Creates between 1 and 5 Béziers curves from parameters specified like in WPF.
        /// </summary>
        public static List<XPoint> BezierCurveFromArc(XPoint point1, XPoint point2, XSize size,
            double rotationAngle, bool isLargeArc, bool clockwise, PathStart pathStart)
        {
            // See also http://www.charlespetzold.com/blog/blog.xml from January 2, 2008: 
            // http://www.charlespetzold.com/blog/2008/01/Mathematics-of-ArcSegment.html
            double δx = size.Width;
            double δy = size.Height;
            Debug.Assert(δx * δy > 0);
            double factor = δy / δx;
            bool isCounterclockwise = !clockwise;

            // Adjust for different radii and rotation angle.
            XMatrix matrix = new XMatrix();
            matrix.RotateAppend(-rotationAngle);
            matrix.ScaleAppend(δy / δx, 1);
            XPoint pt1 = matrix.Transform(point1);
            XPoint pt2 = matrix.Transform(point2);

            // Get info about chord that connects both points.
            XPoint midPoint = new XPoint((pt1.X + pt2.X) / 2, (pt1.Y + pt2.Y) / 2);
            XVector vect = pt2 - pt1;
            double halfChord = vect.Length / 2;

            // Get vector from chord to center.
            XVector vectRotated;

            // (comparing two Booleans here!)
            if (isLargeArc == isCounterclockwise)
                vectRotated = new XVector(-vect.Y, vect.X);
            else
                vectRotated = new XVector(vect.Y, -vect.X);

            vectRotated.Normalize();

            // Distance from chord to center.
            double centerDistance = Math.Sqrt(δy * δy - halfChord * halfChord);
            if (double.IsNaN(centerDistance))
                centerDistance = 0;

            // Calculate center point.
            XPoint center = midPoint + centerDistance * vectRotated;

            // Get angles from center to the two points.
            double α = Math.Atan2(pt1.Y - center.Y, pt1.X - center.X);
            double β = Math.Atan2(pt2.Y - center.Y, pt2.X - center.X);

            // (another comparison of two Booleans!)
            if (isLargeArc == (Math.Abs(β - α) < Math.PI))
            {
                if (α < β)
                    α += 2 * Math.PI;
                else
                    β += 2 * Math.PI;
            }

            // Invert matrix for final point calculation.
            matrix.Invert();
            double sweepAngle = β - α;

            // Let the algorithm of GDI+ DrawArc to Bézier curves do the rest of the job
            return BezierCurveFromArc(center.X - δx * factor, center.Y - δy, 2 * δx * factor, 2 * δy,
              α / Calc.Deg2Rad, sweepAngle / Calc.Deg2Rad, pathStart, ref matrix);
        }
예제 #8
0
        /// <summary>
        /// Appends a Bézier curve for an arc within a full quadrant.
        /// </summary>
        static void AppendPartialArcQuadrant(List<XPoint> points, double x, double y, double width, double height, double α, double β, PathStart pathStart, XMatrix matrix)
        {
            Debug.Assert(α >= 0 && α <= 360);
            Debug.Assert(β >= 0);
            if (β > 360)
                β = β - Math.Floor(β / 360) * 360;
            Debug.Assert(Math.Abs(α - β) <= 90);

            // Scanling factor.
            double δx = width / 2;
            double δy = height / 2;

            // Center of ellipse.
            double x0 = x + δx;
            double y0 = y + δy;

            // We have the following quarters:
            //     |
            //   2 | 3
            // ----+-----
            //   1 | 0
            //     |
            // If the angles lie in quarter 2 or 3, their values are subtracted by 180 and the
            // resulting curve is reflected at the center. This algorithm works as expected (simply tried out).
            // There may be a mathematically more elegant solution...
            bool reflect = false;
            if (α >= 180 && β >= 180)
            {
                α -= 180;
                β -= 180;
                reflect = true;
            }

            double cosα, cosβ, sinα, sinβ;
            if (width == height)
            {
                // Circular arc needs no correction.
                α = α * Calc.Deg2Rad;
                β = β * Calc.Deg2Rad;
            }
            else
            {
                // Elliptic arc needs the angles to be adjusted such that the scaling transformation is compensated.
                α = α * Calc.Deg2Rad;
                sinα = Math.Sin(α);
                if (Math.Abs(sinα) > 1E-10)
                    α = Math.PI / 2 - Math.Atan(δy * Math.Cos(α) / (δx * sinα));
                β = β * Calc.Deg2Rad;
                sinβ = Math.Sin(β);
                if (Math.Abs(sinβ) > 1E-10)
                    β = Math.PI / 2 - Math.Atan(δy * Math.Cos(β) / (δx * sinβ));
            }

            double κ = 4 * (1 - Math.Cos((α - β) / 2)) / (3 * Math.Sin((β - α) / 2));
            sinα = Math.Sin(α);
            cosα = Math.Cos(α);
            sinβ = Math.Sin(β);
            cosβ = Math.Cos(β);

            //XPoint pt1, pt2, pt3;
            if (!reflect)
            {
                // Calculation for quarter 0 and 1.
                switch (pathStart)
                {
                    case PathStart.MoveTo1st:
                        points.Add(matrix.Transform(new XPoint(x0 + δx * cosα, y0 + δy * sinα)));
                        break;

                    case PathStart.LineTo1st:
                        points.Add(matrix.Transform(new XPoint(x0 + δx * cosα, y0 + δy * sinα)));
                        break;

                    case PathStart.Ignore1st:
                        break;
                }
                points.Add(matrix.Transform(new XPoint(x0 + δx * (cosα - κ * sinα), y0 + δy * (sinα + κ * cosα))));
                points.Add(matrix.Transform(new XPoint(x0 + δx * (cosβ + κ * sinβ), y0 + δy * (sinβ - κ * cosβ))));
                points.Add(matrix.Transform(new XPoint(x0 + δx * cosβ, y0 + δy * sinβ)));
            }
            else
            {
                // Calculation for quarter 2 and 3.
                switch (pathStart)
                {
                    case PathStart.MoveTo1st:
                        points.Add(matrix.Transform(new XPoint(x0 - δx * cosα, y0 - δy * sinα)));
                        break;

                    case PathStart.LineTo1st:
                        points.Add(matrix.Transform(new XPoint(x0 - δx * cosα, y0 - δy * sinα)));
                        break;

                    case PathStart.Ignore1st:
                        break;
                }
                points.Add(matrix.Transform(new XPoint(x0 - δx * (cosα - κ * sinα), y0 - δy * (sinα + κ * cosα))));
                points.Add(matrix.Transform(new XPoint(x0 - δx * (cosβ + κ * sinβ), y0 - δy * (sinβ - κ * cosβ))));
                points.Add(matrix.Transform(new XPoint(x0 - δx * cosβ, y0 - δy * sinβ)));
            }
        }
예제 #9
0
        /// <summary>
        /// Creates between 1 and 5 Béziers curves from parameters specified like in GDI+.
        /// </summary>
        public static List<XPoint> BezierCurveFromArc(double x, double y, double width, double height, double startAngle, double sweepAngle,
            PathStart pathStart, ref XMatrix matrix)
        {
            List<XPoint> points = new List<XPoint>();

            // Normalize the angles.
            double α = startAngle;
            if (α < 0)
                α = α + (1 + Math.Floor((Math.Abs(α) / 360))) * 360;
            else if (α > 360)
                α = α - Math.Floor(α / 360) * 360;
            Debug.Assert(α >= 0 && α <= 360);

            double β = sweepAngle;
            if (β < -360)
                β = -360;
            else if (β > 360)
                β = 360;

            if (α == 0 && β < 0)
                α = 360;
            else if (α == 360 && β > 0)
                α = 0;

            // Is it possible that the arc is small starts and ends in same quadrant?
            bool smallAngle = Math.Abs(β) <= 90;

            β = α + β;
            if (β < 0)
                β = β + (1 + Math.Floor((Math.Abs(β) / 360))) * 360;

            bool clockwise = sweepAngle > 0;
            int startQuadrant = Quadrant(α, true, clockwise);
            int endQuadrant = Quadrant(β, false, clockwise);

            if (startQuadrant == endQuadrant && smallAngle)
                AppendPartialArcQuadrant(points, x, y, width, height, α, β, pathStart, matrix);
            else
            {
                int currentQuadrant = startQuadrant;
                bool firstLoop = true;
                do
                {
                    if (currentQuadrant == startQuadrant && firstLoop)
                    {
                        double ξ = currentQuadrant * 90 + (clockwise ? 90 : 0);
                        AppendPartialArcQuadrant(points, x, y, width, height, α, ξ, pathStart, matrix);
                    }
                    else if (currentQuadrant == endQuadrant)
                    {
                        double ξ = currentQuadrant * 90 + (clockwise ? 0 : 90);
                        AppendPartialArcQuadrant(points, x, y, width, height, ξ, β, PathStart.Ignore1st, matrix);
                    }
                    else
                    {
                        double ξ1 = currentQuadrant * 90 + (clockwise ? 0 : 90);
                        double ξ2 = currentQuadrant * 90 + (clockwise ? 90 : 0);
                        AppendPartialArcQuadrant(points, x, y, width, height, ξ1, ξ2, PathStart.Ignore1st, matrix);
                    }

                    // Don't stop immediately if arc is greater than 270 degrees.
                    if (currentQuadrant == endQuadrant && smallAngle)
                        break;
                    smallAngle = true;

                    if (clockwise)
                        currentQuadrant = currentQuadrant == 3 ? 0 : currentQuadrant + 1;
                    else
                        currentQuadrant = currentQuadrant == 0 ? 3 : currentQuadrant - 1;

                    firstLoop = false;
                } while (true);
            }
            return points;
        }
예제 #10
0
    void AppendPartialArc(System.Windows.Point point1, System.Windows.Point point2, double rotationAngle,
      System.Windows.Size size, bool isLargeArc, System.Windows.Media.SweepDirection sweepDirection, PathStart pathStart)
    {
#if true
      //AppendPartialArc(currentPoint, seg.Point, seg.RotationAngle, seg.Size, seg.IsLargeArc, seg.SweepDirection, PathStart.Ignore1st);

      int pieces;
      PointCollection points = GeometryHelper.ArcToBezier(point1.X, point1.Y, size.Width, size.Height, rotationAngle, isLargeArc, 
        sweepDirection == SweepDirection.Clockwise, point2.X, point2.Y, out pieces);

      int count = points.Count;
      int start = count % 3 == 1 ? 1 : 0;
      if (start == 1)
        AppendFormat("{0:0.####} {1:0.####} m\n", points[0].X, points[0].Y);
      for (int idx = start; idx < count; idx += 3)
        AppendFormat("{0:0.####} {1:0.####} {2:0.####} {3:0.####} {4:0.####} {5:0.####} c\n",
          points[idx].X, points[idx].Y,
          points[idx + 1].X, points[idx + 1].Y,
          points[idx + 2].X, points[idx + 2].Y);

#else
      List<XPoint> points = GeometryHelper.BezierCurveFromArc((XPoint)point1, (XPoint)point2, rotationAngle, (XSize)size,
        isLargeArc, sweepDirection == SweepDirection.Clockwise, pathStart);
      int count = points.Count;
      int start = count % 3 == 1 ? 1 : 0;
      if (start == 1)
        AppendFormat("{0:0.####} {1:0.####} m\n", points[0].X, points[0].Y);
      for (int idx = start; idx < count; idx += 3)
        AppendFormat("{0:0.####} {1:0.####} {2:0.####} {3:0.####} {4:0.####} {5:0.####} c\n",
          points[idx].X, points[idx].Y,
          points[idx + 1].X, points[idx + 1].Y,
          points[idx + 2].X, points[idx + 2].Y);
#endif
    }
 // Use this for initialization
 void Start()
 {
     // get the path manager
     WaveManager = GameObject.Find("PathPoint (0)").GetComponent <PathStart>();
 }
예제 #12
0
        /// <summary>
        /// Evaluates a Zero Length Path.
        /// </summary>
        /// <param name="context">Evaluation Context.</param>
        /// <returns></returns>
        public override BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            if (AreBothTerms())
            {
                if (AreSameTerms())
                {
                    return(new IdentityMultiset());
                }
                else
                {
                    return(new NullMultiset());
                }
            }

            String subjVar = PathStart.VariableName;
            String objVar  = PathEnd.VariableName;

            context.OutputMultiset = new Multiset();

            // Determine the Triples to which this applies
            if (subjVar != null)
            {
                // Subject is a Variable
                if (context.InputMultiset.ContainsVariable(subjVar))
                {
                    // Subject is Bound
                    if (objVar != null)
                    {
                        // Object is a Variable
                        if (context.InputMultiset.ContainsVariable(objVar))
                        {
                            // Both Subject and Object are Bound
                            foreach (ISet s in context.InputMultiset.Sets.Where(x => x[subjVar] != null && x[objVar] != null && PathStart.Accepts(context, x[subjVar]) && PathEnd.Accepts(context, x[objVar])))
                            {
                                ISet x = new Set();
                                x.Add(subjVar, x[subjVar]);
                                context.OutputMultiset.Add(x);
                                x = new Set();
                                x.Add(objVar, x[objVar]);
                                context.OutputMultiset.Add(x);
                            }
                        }
                        else
                        {
                            // Subject is bound but Object is Unbound
                            foreach (ISet s in context.InputMultiset.Sets.Where(x => x[subjVar] != null && PathStart.Accepts(context, x[subjVar])))
                            {
                                ISet x = s.Copy();
                                x.Add(objVar, x[subjVar]);
                                context.OutputMultiset.Add(x);
                            }
                        }
                    }
                    else
                    {
                        // Object is a Term
                        // Preseve sets where the Object Term is equal to the currently bound Subject
                        INode objTerm = ((NodeMatchPattern)PathEnd).Node;
                        foreach (ISet s in context.InputMultiset.Sets)
                        {
                            INode temp = s[subjVar];
                            if (temp != null && temp.Equals(objTerm))
                            {
                                context.OutputMultiset.Add(s.Copy());
                            }
                        }
                    }
                }
                else
                {
                    // Subject is Unbound
                    if (objVar != null)
                    {
                        // Object is a Variable
                        if (context.InputMultiset.ContainsVariable(objVar))
                        {
                            // Object is Bound but Subject is unbound
                            foreach (ISet s in context.InputMultiset.Sets.Where(x => x[objVar] != null && PathEnd.Accepts(context, x[objVar])))
                            {
                                ISet x = s.Copy();
                                x.Add(subjVar, x[objVar]);
                                context.OutputMultiset.Add(x);
                            }
                        }
                        else
                        {
                            // Subject and Object are Unbound
                            HashSet <INode> nodes = new HashSet <INode>();
                            foreach (Triple t in context.Data.Triples)
                            {
                                nodes.Add(t.Subject);
                                nodes.Add(t.Object);
                            }
                            foreach (INode n in nodes)
                            {
                                Set s = new Set();
                                s.Add(subjVar, n);
                                s.Add(objVar, n);
                                context.OutputMultiset.Add(s);
                            }
                        }
                    }
                    else
                    {
                        // Object is a Term
                        // Create a single set with the Variable bound to the Object Term
                        Set s = new Set();
                        s.Add(subjVar, ((NodeMatchPattern)PathEnd).Node);
                        context.OutputMultiset.Add(s);
                    }
                }
            }
            else if (objVar != null)
            {
                // Subject is a Term but Object is a Variable
                if (context.InputMultiset.ContainsVariable(objVar))
                {
                    // Object is Bound
                    // Preseve sets where the Subject Term is equal to the currently bound Object
                    INode subjTerm = ((NodeMatchPattern)PathStart).Node;
                    foreach (ISet s in context.InputMultiset.Sets)
                    {
                        INode temp = s[objVar];
                        if (temp != null && temp.Equals(subjTerm))
                        {
                            context.OutputMultiset.Add(s.Copy());
                        }
                    }
                }
                else
                {
                    // Object is Unbound
                    // Create a single set with the Variable bound to the Suject Term
                    Set s = new Set();
                    s.Add(objVar, ((NodeMatchPattern)PathStart).Node);
                    context.OutputMultiset.Add(s);
                }
            }
            else
            {
                // Should already have dealt with this earlier (the AreBothTerms() and AreSameTerms() branch)
                throw new RdfQueryException("Reached unexpected point of ZeroLengthPath evaluation");
            }

            return(context.OutputMultiset);
        }
 // Use this for initialization
 void Start()
 {
     // set the model as a random model in the inputed list
     GetComponent <MeshFilter>().mesh = models[Random.Range(0, models.Count)];
     WaveManager = GameObject.Find("PathPoint (0)").GetComponent <PathStart>();
 }
예제 #14
0
        void AppendPartialArc(SysPoint point1, SysPoint point2, double rotationAngle,
            SysSize size, bool isLargeArc, SweepDirection sweepDirection, PathStart pathStart)
        {
            const string format = Config.SignificantFigures4;

            Debug.Assert(pathStart == PathStart.Ignore1st);

            int pieces;
            PointCollection points = GeometryHelper.ArcToBezier(point1.X, point1.Y, size.Width, size.Height, rotationAngle, isLargeArc,
              sweepDirection == SweepDirection.Clockwise, point2.X, point2.Y, out pieces);

            int count = points.Count;
            int start = count % 3 == 1 ? 1 : 0;
            if (start == 1)
                AppendFormatPoint("{0:" + format + "} {1:" + format + "} m\n", points[0].X, points[0].Y);
            for (int idx = start; idx < count; idx += 3)
                AppendFormat3Points("{0:" + format + "} {1:" + format + "} {2:" + format + "} {3:" + format + "} {4:" + format + "} {5:" + format + "} c\n",
                  points[idx].X, points[idx].Y,
                  points[idx + 1].X, points[idx + 1].Y,
                  points[idx + 2].X, points[idx + 2].Y);
        }
예제 #15
0
 void AppendPartialArc(System.Windows.Point point1, System.Windows.Point point2, double rotationAngle,
   System.Windows.Size size, bool isLargeArc, System.Windows.Media.SweepDirection sweepDirection, PathStart pathStart)
 {
   List<XPoint> points = GeometryHelper.BezierCurveFromArc((XPoint)point1, (XPoint)point2, rotationAngle, (XSize)size,
     isLargeArc, sweepDirection == SweepDirection.Clockwise, pathStart);
   int count = points.Count;
   int start = count % 3 == 1 ? 1 : 0;
   if (start == 1)
     AppendFormat("{0:0.####} {1:0.####} m\n", points[0].X, points[0].Y);
   for (int idx = start; idx < count; idx += 3)
     AppendFormat("{0:0.####} {1:0.####} {2:0.####} {3:0.####} {4:0.####} {5:0.####} c\n",
       points[idx].X, points[idx].Y,
       points[idx + 1].X, points[idx + 1].Y,
       points[idx + 2].X, points[idx + 2].Y);
 }
예제 #16
0
    public void OnGUI()
    {
        #region UIRendering
        //load the gui skin
        GUI.skin = skin;
        int       ResolutionWidth  = Screen.width;
        int       ResolutionHeight = Screen.height;
        PathStart WaveManager      = GameObject.Find("PathPoint (0)").GetComponent <PathStart>();

        //draw the tower selection grid
        int boxNumber = ((Screen.height - 315) / 100) * 2;
        List <GUIContent> TowerSelectionGrid = new List <GUIContent>();
        for (int i = towerPage * boxNumber; i < Towers.Count && i < boxNumber + towerPage * boxNumber; i++)
        {
            TowerSelectionGrid.Add(new GUIContent(Towers[i].Name + "\n<size=16>cost:" + Towers[i].TowerObject.GetComponent <Tower>().getCost() + "</size>", Towers[i].GuiTexture == null ? NoTowerImage : Towers[i].GuiTexture));
        }
        for (int i = TowerSelectionGrid.Count; i < boxNumber; i++)
        {
            TowerSelectionGrid.Add(new GUIContent(""));
        }


        //draw the box for money and health;
        GUI.Box(new Rect(ResolutionWidth - 200, 0, 200, 100), new GUIContent("Health:" + GameObject.FindGameObjectWithTag("ProtectedObject").GetComponent <ProtectedObject>().health
                                                                             + "\n Money:" + money + "\n Score:" + PathManager.Score));
        selectorGrid = GUI.SelectionGrid(new Rect(ResolutionWidth - 200, 105, 200, ResolutionHeight - 315), selectorGrid, TowerSelectionGrid.ToArray(), 2);

        //draw the next button for tower page
        if (towerPage == TowerPageMax)
        {
            GUI.Box(new Rect(ResolutionWidth - 98, ResolutionHeight - 205, 98, 100), new GUIContent("<color=#808080ff>next</color>"));
        }
        else
        if (GUI.Button(new Rect(ResolutionWidth - 98, ResolutionHeight - 205, 98, 100), new GUIContent("next")))
        {
            towerPage += 1;
        }
        //draw the previous button for tower page
        if (towerPage == 0)
        {
            GUI.Box(new Rect(ResolutionWidth - 200, ResolutionHeight - 205, 98, 100), new GUIContent("<color=#808080ff>Previous</color>"));
        }
        else
        if (GUI.Button(new Rect(ResolutionWidth - 200, ResolutionHeight - 205, 98, 100), new GUIContent("Previous")))
        {
            towerPage -= 1;
        }

        //check if the player can go to the next wave
        if (WaveManager.CanNextWave)
        {
            //check if the level is finished
            if (WaveManager.isFinalWave)
            {
                // create finished texture
                GUIStyle  OuterBox = new GUIStyle(GUI.skin.box);
                Texture2D texture  = new Texture2D(1, 1);
                texture.SetPixel(0, 0, Color.white);
                texture.Apply();
                OuterBox.normal.background = texture;

                //display finished message and the button to end the game
                GUI.Label(new Rect(ResolutionWidth / 2 - 500, ResolutionHeight / 2 - 100, 500, 150), "", OuterBox);
                GUI.Label(new Rect(ResolutionWidth / 2 - 500, ResolutionHeight / 2 - 100, 500, 150), new GUIContent("<size=128><color=Black>Great Job</color></size>"));
                if (GUI.Button(new Rect(ResolutionWidth - 200, ResolutionHeight - 100, 200, 100), new GUIContent("Exit to Main Menu")))
                {
                    PlayerPrefs.SetInt("level:" + UnityEngine.SceneManagement.SceneManager.GetActiveScene().buildIndex, (int)PathManager.Score);

                    UnityEngine.SceneManagement.SceneManager.LoadScene(0);
                }
            }
            //otherwise show a button to go to next level
            else if (GUI.Button(new Rect(ResolutionWidth - 200, ResolutionHeight - 100, 200, 100), new GUIContent("Next Wave" + WaveManager.TimeToNextWave)))
            {
                WaveManager.nextWave();
            }
        }
        else
        {
            GUI.Box(new Rect(ResolutionWidth - 200, ResolutionHeight - 100, 200, 100), new GUIContent("Wave In Progress"));
        }

        //show options button
        if (GUI.Button(new Rect(8, ResolutionHeight - 40, 32, 32), GearSymbol))
        {
            Options = !Options;
        }

        //show music button
        if (GUI.Button(new Rect(48, ResolutionHeight - 40, 32, 32), music ? MusicSymbol : NoMusicSymbol))
        {
            music = !music;
            PlayerPrefs.SetInt("music", music ? 1 : 0);
            AudioListener.volume = music ? 1 : 0;
        }



        #endregion

        #region UIControls

        //move camera around
        if (Input.GetAxis("Mouse ScrollWheel") < 0 || Input.GetAxis("Mouse ScrollWheel") > 0 && Camera.main != null)
        {
            Camera.main.orthographicSize = Mathf.Max(Mathf.Min(-8 * scrollSpeed * Input.GetAxis("Mouse ScrollWheel") + Camera.main.orthographicSize, 50), 5);
        }

        //if user presses e open the options menu
        if (Input.GetKeyDown(KeyCode.Escape) & Time.unscaledTime - buttonTime > .5f)
        {
            Options    = !Options;
            buttonTime = Time.unscaledTime;
        }

        //show options menu
        if (Options)
        {
            //draw options box
            Rect OptionsBox = new Rect((ResolutionWidth - 200) / 2, (ResolutionHeight - 132) / 2, 200, 152);
            GUI.Box(OptionsBox, "");

            //draw the quit buttons
            if (GUI.Button(new Rect(OptionsBox.xMin + (OptionsBox.width - 150) / 2, OptionsBox.yMin + 16, 150, 50), "Quit To Windows"))
            {
                Application.Quit();
            }
            if (GUI.Button(new Rect(OptionsBox.xMin + (OptionsBox.width - 150) / 2, OptionsBox.yMin + 66, 150, 50), "Quit To Main Menu"))
            {
                UnityEngine.SceneManagement.SceneManager.LoadScene(0);
            }
            hardness = !GUI.Toggle(new Rect(OptionsBox.xMin + (OptionsBox.width - 150) / 2, OptionsBox.yMin + 116, 150, 50), hardness, "Hard Mode");
            PlayerPrefs.SetInt("Hardness", hardness?1:0);
        }
        //show the diologue for selling towers
        else if (ThingToSell != null)
        {
            //convert 3d point to 2d screen position
            Vector3 screenPosition = Camera.main.WorldToScreenPoint(ThingToSell.transform.position + Vector3.up); // gets screen position.\
            screenPosition.y = Screen.height - (screenPosition.y + 1);                                            // inverts y
            Rect rect = new Rect(screenPosition.x - 50,
                                 screenPosition.y - 12, 100, 60);                                                 // makes a rect centered at the player ( 100x24 )
            GUI.Box(rect, "", GUI.skin.box);
            //shjow sell button
            if (GUI.Button(new Rect(rect.xMin + 4, rect.yMin + 4, 92, 24), "Sell", GUI.skin.button))
            {
                money += hardness? ThingToSell.getCost() / 2:0;
                Destroy(ThingToSell.gameObject);
            }
            //show cancel button
            else if (GUI.Button(new Rect(rect.xMin + 4, rect.yMin + 28, 92, 24), "Cancel", GUI.skin.button))
            {
                ThingToSell = null;
            }
        }
        //check for user mouse click
        else if (Input.GetMouseButtonDown(0))
        {
            if (justclicked == false)
            {
                //check iuf the user clicked on a tile
                RaycastHit hit;
                Ray        clicked3D = Camera.main.ScreenPointToRay(Input.mousePosition);
                Physics.Raycast(clicked3D, out hit, 100000f);
                if (hit.transform != null && hit.transform.gameObject.tag == "BuildTile")
                {
                    //if clicked on a tile create tower
                    BuildTile Tile = hit.transform.gameObject.GetComponent <BuildTile>();
                    if (Tile.Tower == null)
                    {
                        if (money >= Towers[selectorGrid + towerPage * boxNumber].TowerObject.GetComponent <Tower>().getCost())
                        {
                            money     -= Towers[selectorGrid + towerPage * boxNumber].TowerObject.GetComponent <Tower>().getCost();
                            Tile.Tower = (Instantiate(Towers[selectorGrid + towerPage * boxNumber].TowerObject, hit.transform.position + new Vector3(0, .75f, 0), new Quaternion()) as GameObject);
                        }
                    }
                }
                //if user clicked on tower show sell diologue
                else if (hit.transform != null && hit.transform.gameObject.tag == "Tower")
                {
                    ThingToSell = hit.transform.gameObject.GetComponent <Tower>();
                }
            }
            justclicked = !justclicked;
        }



        //move camera based on arrow keys and wasd
        MousePositionMoving = new Vector3(0, 0, 0);
        if (Input.GetMouseButton(2) == true)
        {
            MousePositionMoving = new Vector3(MouseLastX - Input.mousePosition.x, MouseLastY - Input.mousePosition.y, 0) * (Camera.main.orthographicSize / 160);
        }
        MouseLastX = (int)Input.mousePosition.x;
        MouseLastY = (int)Input.mousePosition.y;
        Camera.main.transform.Translate(new Vector3(Input.GetAxis("Horizontal") * cameraMouseSpeed, Input.GetAxis("Vertical") * cameraMouseSpeed, 0) + MousePositionMoving);


        //if user presses e turn the camera
        if (Input.GetKey(KeyCode.E))
        {
            //Find point from camera and angle to y = zero point
            float   angle;
            Vector3 axis;
            this.transform.rotation.ToAngleAxis(out angle, out axis);

            Vector3 LookDir  = this.transform.rotation * new Vector3(0, 0, 1);
            Vector2 RatioDir = new Vector2(LookDir.x, LookDir.z);
            RatioDir.Normalize();



            //rotate around this point
            Vector3 endPoint = new Vector3(transform.position.x + RatioDir.x * transform.position.y, 0, transform.position.z + RatioDir.y * transform.position.y);
            this.transform.RotateAround(endPoint, Vector3.up, scrollSpeed / -3);
        }
        //if user presses e turn the camera
        if (Input.GetKey(KeyCode.Q))
        {
            //Find point from camera and angle to y = zero point
            float   angle;
            Vector3 axis;
            this.transform.rotation.ToAngleAxis(out angle, out axis);

            Vector3 LookDir  = this.transform.rotation * new Vector3(0, 0, 1);
            Vector2 RatioDir = new Vector2(LookDir.x, LookDir.z);
            RatioDir.Normalize();

            //rotate around this point
            Vector3 endPoint = new Vector3(transform.position.x + RatioDir.x * transform.position.y, 0, transform.position.z + RatioDir.y * transform.position.y);
            this.transform.RotateAround(endPoint, Vector3.up, scrollSpeed / 3);
        }
        #endregion
    }