Ejemplo n.º 1
0
        public EllipsePieceSegment(FPoint center, float radiusX, float radiusY, float aStart = 0, float aEnd = FloatMath.TAU, CircularDirection dir = CircularDirection.CW)
        {
            this.center    = center;
            this.radiusX   = radiusX;
            this.radiusY   = radiusY;
            this.direction = dir;

            angleStart = aStart;
            angleEnd   = aEnd;

            if (dir == CircularDirection.CW)
            {
                Length = FloatMath.TAU * FloatMath.Sqrt((radiusX * radiusX + radiusY * radiusY) / 2f) * (angleEnd - angleStart) / FloatMath.TAU;

                Boundings = EllipseHelper.CalculateEllipseSegmentsBoundingBox(center.X, center.Y, radiusX, radiusY, angleStart, angleEnd);
            }
            else
            {
                // inverted

                Length = FloatMath.TAU * FloatMath.Sqrt((radiusX * radiusX + radiusY * radiusY) / 2f) * (angleStart - angleEnd) / FloatMath.TAU;

                Boundings = EllipseHelper.CalculateEllipseSegmentsBoundingBox(center.X, center.Y, radiusX, radiusY, angleEnd, angleStart);
            }
        }
Ejemplo n.º 2
0
		public CirclePieceSegment(FPoint center, float radius, float aStart = 0, float aEnd = FloatMath.TAU)
		{
			this.center = center;
			this.radius = radius;

			if (aStart < aEnd)
			{
				direction = CircularDirection.CW;

				angleStart = aStart;
				angleEnd = aEnd;
			}
			else
			{
				direction = CircularDirection.CCW;

				angleStart = aEnd;
				angleEnd = aStart;
			}

			Length = (2 * FloatMath.PI * radius) * (angleEnd - angleStart) / FloatMath.TAU;
			directionZero = new Vector2(radius, 0);
			
			Boundings = GeometryHelper.CalculateEllipseSegmentsBoundingBox(center.X, center.Y, radius, radius, angleStart, angleEnd);
		}
Ejemplo n.º 3
0
        public CirclePieceSegment(FPoint center, float radius, float aStart = 0, float aEnd = FloatMath.TAU)
        {
            this.center = center;
            this.radius = radius;

            if (aStart < aEnd)
            {
                direction = CircularDirection.CW;

                angleStart = aStart;
                angleEnd   = aEnd;
            }
            else
            {
                direction = CircularDirection.CCW;

                angleStart = aEnd;
                angleEnd   = aStart;
            }

            Length        = (2 * FloatMath.PI * radius) * (angleEnd - angleStart) / FloatMath.TAU;
            directionZero = new Vector2(radius, 0);

            Boundings = EllipseHelper.CalculateEllipseSegmentsBoundingBox(center.X, center.Y, radius, radius, angleStart, angleEnd);
        }
Ejemplo n.º 4
0
		public EllipsePieceSegment(FPoint center, float radiusX, float radiusY, float aStart = 0, float aEnd = FloatMath.TAU, CircularDirection dir = CircularDirection.CW)
		{
			this.center = center;
			this.radiusX = radiusX;
			this.radiusY = radiusY;
			this.direction = dir;

			angleStart = aStart;
			angleEnd = aEnd;

			if (dir == CircularDirection.CW)
			{
				Length = FloatMath.TAU * FloatMath.Sqrt((radiusX * radiusX + radiusY * radiusY) / 2f) * (angleEnd - angleStart) / FloatMath.TAU;

				Boundings = GeometryHelper.CalculateEllipseSegmentsBoundingBox(center.X, center.Y, radiusX, radiusY, angleStart, angleEnd);
			}
			else
			{
				// inverted
				
				Length = FloatMath.TAU * FloatMath.Sqrt((radiusX * radiusX + radiusY * radiusY) / 2f) * (angleStart - angleEnd) / FloatMath.TAU;

				Boundings = GeometryHelper.CalculateEllipseSegmentsBoundingBox(center.X, center.Y, radiusX, radiusY, angleEnd, angleStart);
			}


		}
        public R1CDirection()
            : base()
        {
            circularDirection = new CircularDirection <R1CDirection, R1Point>();
            directionHelper   = new R1Direction <R1CDirection>();

            InitializeAttributes();
        }
        public R1CDirection(R1Direction <R1CDirection> directionHelper)
        {
            this.directionHelper = directionHelper;

            circularDirection = new CircularDirection <R1CDirection, R1Point>(
                CreateCanSwitchList(), true, 1);

            InitializeAttributes();
        }
        public R1CDirection(R1Point startingPoint, int direction, float directionLength,
                            float directionDivisor, List <float> speedList, List <bool> canSwitchList,
                            int numberOfRepeatations, bool canSwitch, float speed)
        {
            circularDirection = new CircularDirection <R1CDirection, R1Point>(
                canSwitchList, canSwitch, numberOfRepeatations);

            directionHelper = new R1Direction <R1CDirection>(startingPoint, direction,
                                                             directionLength, directionDivisor, speedList, speed);


            InitializeAttributes();
        }
Ejemplo n.º 8
0
    /// <summary>
    /// Finds the coords. of the next item in the <see cref="PackedLayout"/> if it's
    /// added vertically.
    /// </summary>
    /// <param name="x">X coord. of previous node</param>
    /// <param name="y">Y coord. of previous node</param>
    /// <param name="verts">The list of all nodes</param>
    /// <param name="v">The index of the previous node in verts</param>
    /// <param name="newx">Returns the x coord. of the new node</param>
    /// <param name="newy">Returns the y coord. of the new node</param>
    /// <param name="dir">Whether the nodes are arranged Clockwise or Counterclockwise</param>
    /// <returns>true if a node can be added vertically and still be on the ellipse</returns>
    private bool nextv(double x, double y, CircularVertex[] verts, int v, out double newx, out double newy, CircularDirection dir) {
      newx = 0;
      newy = 0;
      bool inv = false; //true if it changes sides
      if (x >= 0 ^ dir == CircularDirection.Clockwise) {
        // y decreases
        newy = y - ((verts[v].Height + verts[v + 1].Height) / 2 + ESpacing);
        if (newy < -Yradius) {
          // y increases
          newy = y + ((verts[v].Height + verts[v + 1].Height) / 2 + ESpacing);
          if (newy > Yradius) { return false; }
          inv = true;
        }
      } else {
        // y increases
        newy = y + ((verts[v].Height + verts[v + 1].Height) / 2 + ESpacing);
        if (newy > Yradius) {
          // y decreases
          newy = y - ((verts[v].Height + verts[v + 1].Height) / 2 + ESpacing);
          if (newy < -Yradius) { return false; }
          inv = true;
        }
      }

      newx = Math.Sqrt(1 - newy * newy / (Yradius * Yradius)) * ERadius;
      if (x < 0 ^ inv) { newx = -newx; }
      if (Math.Abs(x - newx) > (verts[v].Width + verts[v + 1].Width) / 2) { return false; } else return true;
    }
Ejemplo n.º 9
0
    private Random rand; // Packed layout sometimes alternates between 2 radii.  If this happens, a random value is added to stop the cycle.

    /// <summary>
    /// Finds the coords. of the next item in the <see cref="PackedLayout"/> if it's
    /// added horizontally.
    /// </summary>
    /// <param name="x">X coord. of previous node</param>
    /// <param name="y">Y coord. of previous node</param>
    /// <param name="verts">The list of all nodes</param>
    /// <param name="v">The index of the previous node in verts</param>
    /// <param name="newx">Returns the x coord. of the new node</param>
    /// <param name="newy">Returns the y coord. of the new node</param>
    /// <param name="dir">Whether the nodes are arranged Clockwise or Counterclockwise</param>
    /// <returns>true if a node can be added horizontally and still be on the ellipse</returns>
    private bool nexth(double x, double y, CircularVertex[] verts, int v, out double newx, out double newy, CircularDirection dir) {
      newx = 0;
      newy = 0;
      bool inv = false; //true if it changes sides
      if (y >= 0 ^ dir == CircularDirection.Clockwise) {
        // x increases
        newx = x + ((verts[v].Width + verts[v + 1].Width) / 2 + ESpacing);
        if (newx > ERadius) {
          // x decreases
          newx = x - ((verts[v].Width + verts[v + 1].Width) / 2 + ESpacing);
          if (newx < -ERadius) { return false; }
          inv = true;
        }
      } else {

        // x decreases
        newx = x - ((verts[v].Width + verts[v + 1].Width) / 2 + ESpacing);
        if (newx < -ERadius) {
          newx = x + ((verts[v].Width + verts[v + 1].Width) / 2 + ESpacing);
          if (newx > ERadius) { return false; }
          inv = true;
        }
      }

      newy = Math.Sqrt(1 - newx * newx / (ERadius * ERadius)) * Yradius;
      if (y < 0 ^ inv) { newy = -newy; }
      if (Math.Abs(y - newy) > (verts[v].Height + verts[v + 1].Height) / 2) { return false; } else return true;
    }
Ejemplo n.º 10
0
    private double correctlastangle = 0; // when the sweep angle < 360, this is the target angle of the last node
    /// <summary>
    /// Arranges the items so the spacing between any item and
    /// an adjacent item is the same, but takes into account the assumption
    /// that the nodes are rectangular.  This one assumes partial sweep, i.e., <see cref="SweepAngle" /> is
    /// less than 360.
    /// </summary>
    /// <param name="vertices">The items to arrange</param>
    /// <param name="sweep">The range of the angles of the nodes (in radians)</param>
    /// <param name="start">The angle of the first node</param>
    /// <param name="dir">
    /// Specifies whether the nodes are arranged clockwise or counterclockwise.  Other
    /// values will be assumed to indicate clockwise (this function doesn't do bidirectionals - those
    /// are achieved by calling this function once for even nodes and again in the other direction for
    /// odd nodes.
    /// </param>
    private void PackedLayoutSemi(List<CircularVertex> vertices, double sweep, double start, CircularDirection dir) {
      // do layout
      double x = ERadius * Math.Cos(start * Math.PI / 180);
      double y = Yradius * Math.Sin(start * Math.PI / 180);
      CircularVertex[] verts = vertices.ToArray();
      for (int v = 0; v < verts.Length; v++) {
        verts[v].Center = new Point(x, y);

        if (v == verts.Length - 1) { break; } // avoid index out of bounds
        double newx;
        double newy;
        if (!nexth(x, y, verts, v, out newx, out newy, dir)) {
          nextv(x, y, verts, v, out newx, out newy, dir);
        }
        x = newx;
        y = newy;
      }

      // check for gap, find gap sizes
      packediters++;
      if (packediters > 128) {
        return;
      }

      // compute gap
      CircularVertex last = vertices.ElementAt(vertices.Count - 1);
      double lastangle = Math.Atan2(y, x);
      double diff = dir == CircularDirection.Clockwise ? correctlastangle - lastangle : lastangle - correctlastangle;
      diff = Math.Abs(diff) < Math.Abs(diff - 2 * Math.PI) ? diff : diff - 2 * Math.PI;
      double gap = diff * (ERadius + Yradius) / 2;
      //return;
      // record this
      vertexarrangement.compare2(gap, verts);

      // avoid period 2 stuff

      if (packediters > 36 && packediters % 13 == 0) {
        ERadius *= (packediters % 2 == 0 ? .75 : 1.1) + rand.NextDouble() * .15;
        Yradius = ERadius * EAspectRatio;
      }

      // change radii accordingly
      if (Math.Abs(gap) > 2.5) {
        this.ERadius -= gap / (2 * Math.PI);
        this.Yradius = ERadius * EAspectRatio;
        PackedLayoutSemi(vertices, sweep, start, dir);
      }
    }
Ejemplo n.º 11
0
    /// <summary>
    /// Arranges the items so the spacing between any item and
    /// an adjacent item is the same, but takes into account the assumption
    /// that the nodes are rectangular.  This one assumes 360 degree sweep
    /// </summary>
    /// <param name="vertices">The items to arrange</param>
    /// <param name="sweep">The range of the angles of the nodes (in radians)</param>
    /// <param name="start">The angle of the first node</param>
    /// <param name="dir">
    /// Specifies whether the nodes are arranged clockwise or counterclockwise.  Other
    /// values will be assumed to indicate clockwise (this function doesn't do bidirectionals - those
    /// are achieved by calling this function once for even nodes and again in the other direction for
    /// odd nodes.
    /// </param>
    private void PackedLayoutFull(List<CircularVertex> vertices, double sweep, double start, CircularDirection dir) {
      // do layout
      double x = ERadius * Math.Cos(start * Math.PI / 180);
      double y = Yradius * Math.Sin(start * Math.PI / 180);
      CircularVertex[] verts = vertices.ToArray();
      for (int v = 0; v < verts.Length; v++) {
        verts[v].Center = new Point(x, y);

        if (v == verts.Length - 1) { break; } // avoid index out of bounds
        double newx;
        double newy; // ***** fix problems
        if (!nexth(x, y, verts, v, out newx, out newy, dir)) {
          nextv(x, y, verts, v, out newx, out newy, dir);
        }
        x = newx;
        y = newy;
      }

      // check for gap, find gap sizes
      packediters++;
      if (packediters > 128) {
        return;
      }
      double locfx = verts[0].Center.X;
      double locfy = verts[0].Center.Y;
      double loclx = verts[verts.Length - 1].Center.X;
      double locly = verts[verts.Length - 1].Center.Y;
      double gapx = Math.Abs(locfx - loclx) - ((verts[0].Width + verts[verts.Length - 1].Width) / 2 + ESpacing);
      double gapy = Math.Abs(locfy - locly) - ((verts[0].Height + verts[verts.Length - 1].Height) / 2 + ESpacing);

      // compute gap
      double gap = 0;
      if (Math.Abs(gapy) < 2.5) {
        double hgap = Math.Abs(locfx - loclx);
        double max = (verts[0].Width + verts[verts.Length - 1].Width) / 2;
        if (hgap < max) {
          gap = 0;
        }
        gapx = hgap - max;
      } else {
        // gapy not 0
        if (gapy > 0) { gap = gapy; } else {
          if (Math.Abs(gapx) < 2.5) {
            gap = 0;
          } else gap = gapx;
        }
      }

      // check for excessive overlap
      bool overlap = false;
      if (Math.Abs(loclx) > Math.Abs(locly)) {
        // use x
        overlap = loclx > 0 ^ locfy > locly;
      } else {
        // use y
        overlap = locly > 0 ^ locfx < loclx;
      }
      overlap = dir == CircularDirection.Clockwise ? overlap : !overlap;

      // if there's an excessive overlap, gap must be <0
      if (overlap) {
        gap = -Math.Abs(gap);

        gap = Math.Min(gap, -verts[verts.Length - 1].Width);
        gap = Math.Min(gap, -verts[verts.Length - 1].Height);
      }

      // record this
      vertexarrangement.compare(gap, verts);

      // avoid period 2 stuff

      if (packediters > 36 && packediters % 13 == 0) {
        ERadius *= (packediters % 2 == 0 ? .75 : 1.1) + rand.NextDouble() * .15;
        Yradius = ERadius * EAspectRatio;
      }

      // change radii accordingly
      if (Math.Abs(gap) > 2.5) {
        this.ERadius -= gap / (2 * Math.PI);
        this.Yradius = ERadius * EAspectRatio;
        PackedLayoutFull(vertices, sweep, start, dir);
      }
    }
Ejemplo n.º 12
0
    /// <summary>
    /// Arranges the items so the spacing between any item and
    /// an adjacent item is the same, but takes into account the assumption
    /// that the nodes are rectangular.
    /// </summary>
    /// <param name="vertices">The items to arrange</param>
    /// <param name="sweep">The range of the angles of the nodes (in radians)</param>
    /// <param name="start">The angle of the first node</param>
    /// <param name="dir">
    /// Specifies whether the nodes are arranged clockwise or counterclockwise.  Other
    /// values will be assumed to indicate clockwise (this function doesn't do bidirectionals - those
    /// are achieved by calling this function once for even nodes and again in the other direction for
    /// odd nodes.
    /// </param>
    private void PackedLayout(List<CircularVertex> vertices, double sweep, double start, CircularDirection dir) {
      packediters = 0;
      vertexarrangement = new VertexArrangement();

      // give rand a constant seed value each time so the same result is produced each time
      rand = new Random(0);

      if (sweep < 360) {
        correctlastangle = start + (dir == CircularDirection.Clockwise ? ESweepAngle : -ESweepAngle);
        while (correctlastangle < 0) { correctlastangle += 360; }
        correctlastangle %= 360;
        if (correctlastangle > 180) { correctlastangle -= 360; }
        correctlastangle *= Math.PI / 180;
        PackedLayoutSemi(vertices, sweep, start, dir);
      } else {
        PackedLayoutFull(vertices, sweep, start, dir);
      }
      vertexarrangement.commit(vertices);
      return;
    }
Ejemplo n.º 13
0
 /// <summary>
 /// Arranges the items so the distance between any item and
 /// an adjacent item is the same
 /// </summary>
 /// <param name="vertices">The items to arrange</param>
 /// <param name="sweep">The range of the angles of the nodes (in radians)</param>
 /// <param name="start">The angle of the first node</param>
 /// <param name="dir">
 /// Specifies whether the nodes are arranged clockwise or counterclockwise.  Other
 /// values will be assumed to indicate clockwise (this function doesn't do bidirectionals - those
 /// are achieved by calling this function once for even nodes and again in the other direction for
 /// odd nodes.
 /// </param>
 private void DistanceLayout(List<CircularVertex> vertices, double sweep, double start, CircularDirection dir) {
   double theta = start * Math.PI / 180;
   int num = vertices.Count();
   for (int i = 0; i < num; i++) {
     CircularVertex cv = vertices.ElementAt(i);
     cv.Center = new Point(ERadius * Math.Cos(theta), Yradius * Math.Sin(theta));
     cv.ActualAngle = theta * 180 / Math.PI;
     double thetachange = EllipseAngle(
       ERadius,
       Yradius,
       dir == CircularDirection.Clockwise ? theta : -theta,
       constdist
     );
     theta += dir == CircularDirection.Clockwise ? thetachange : -thetachange;
   }
 }
Ejemplo n.º 14
0
 /// <summary>
 /// Arranges the items so the spacing between any item and
 /// an adjacent item is the same
 /// </summary>
 /// <param name="vertices">The items to arrange</param>
 /// <param name="sweep">The range of the angles of the nodes (in radians)</param>
 /// <param name="start">The angle of the first node</param>
 /// <param name="dir">
 /// Specifies whether the nodes are arranged clockwise or counterclockwise.  Other
 /// values will be assumed to indicate clockwise (this function doesn't do bidirectionals - those
 /// are achieved by calling this function once for even nodes and again in the other direction for
 /// odd nodes.
 /// </param>
 private void SpacingLayout(List<CircularVertex> vertices, double sweep, double start, CircularDirection dir) {
   double theta = start * Math.PI / 180;
   int num = vertices.Count();
   for (int i = 0; i < num; i++) {
     CircularVertex curr = vertices.ElementAt(i);
     CircularVertex next = vertices.ElementAt(i == num - 1 ? 0 : i + 1);
     double x = ERadius * Math.Cos(theta);
     double y = Yradius * Math.Sin(theta);
     curr.Center = new Point(x, y);
     curr.ActualAngle = theta * 180 / Math.PI;
     double rad = Math.Sqrt(x * x + y * y);
     double meandiam = (curr.Diameter + next.Diameter) / 2;
     double thetachange = EllipseAngle(
       ERadius,
       Yradius,
       dir == CircularDirection.Clockwise ? theta : -theta,
       meandiam + ESpacing
     );
     theta += dir == CircularDirection.Clockwise ? thetachange : -thetachange;
   }
 }
Ejemplo n.º 15
0
 /// <summary>
 /// Arranges the items so the angle between any item and
 /// an adjacent item is the same
 /// </summary>
 /// <param name="vertices">The items to arrange</param>
 /// <param name="sweep">The range of the angles of the nodes (in radians)</param>
 /// <param name="start">The angle of the first node</param>
 /// <param name="dir">
 /// Specifies whether the nodes are arranged clockwise or counterclockwise.  Other
 /// values will be assumed to indicate clockwise (this function doesn't do bidirectionals - those
 /// are achieved by calling this function once for even nodes and again in the other direction for
 /// odd nodes.
 /// </param>
 private void AngleLayout(List<CircularVertex> vertices, double sweep, double start, CircularDirection dir) {
   double theta0 = start * Math.PI / 180;
   double _SweepingAngle = sweep * Math.PI / 180;
   //double e = ERadius > Yradius ? Math.Sqrt(ERadius * ERadius - Yradius * Yradius) / ERadius : Math.Sqrt(Yradius * Yradius - ERadius * ERadius) / Yradius;
   int num = vertices.Count();
   for (int i = 0; i < num; i++) {
     double theta = theta0 + (dir == CircularDirection.Clockwise ? (i * _SweepingAngle) / (ESweepAngle >= 360 ? num : num - 1) : -(i * _SweepingAngle) / num);
     CircularVertex cv = vertices.ElementAt(i);
     double w = ERadius * Math.Tan(theta) / Yradius;
     double r = Math.Sqrt((ERadius * ERadius + Yradius * Yradius * w * w) / (1 + w * w));
     cv.Center = new Point(r * Math.Cos(theta), r * Math.Sin(theta));
     cv.ActualAngle = theta * 180 / Math.PI;
   }
 }