src/main/java/com/mxgraph/util/mxCurve.java
protected void createCoreCurve()
	{
		// Curve is marked invalid until all of the error situations have
		// been checked
		valid = false;

		if (guidePoints == null || guidePoints.isEmpty())
		{
			return;
		}

		for (int i = 0; i < guidePoints.size(); i++)
		{
			if (guidePoints.get(i) == null)
			{
				return;
			}
		}

		// Reset the cached bounds value
		minXBounds = minYBounds = 10000000;
		maxXBounds = maxYBounds = 0;

		mxSpline spline = new mxSpline(guidePoints);

		// Need the rough length of the spline, so we can get
		// more samples for longer edges
		double lengthSpline = spline.getLength();

		// Check for errors in the spline calculation or zero length curves
		if (Double.isNaN(lengthSpline) || !spline.checkValues()
				|| lengthSpline < 1)
		{
			return;
		}

		mxSpline1D splineX = spline.getSplineX();
		mxSpline1D splineY = spline.getSplineY();
		double baseInterval = 12.0 / lengthSpline;
		double minInterval = 1.0 / lengthSpline;

		// Store the last two spline positions. If the next position is 
		// very close to where the extrapolation of the last two points 
		// then double the interval. This diviation is terms the "flatness".
		// There is a range where the interval is kept the same, any 
		// variation from this range of flatness invokes a proportional 
		// adjustment to try to reenter the range without 
		// over compensating
		double interval = baseInterval;
		// These deviations are only tested against either 
		// dimension individually, working out the correct 
		// distance is too computationally intensive
		double minDeviation = 0.15;
		double maxDeviation = 0.3;
		double preferedDeviation = (maxDeviation + minDeviation) / 2.0;

		// x1, y1 are the position two iterations ago, x2, y2
		// the position on the last iteration
		double x1 = -1.0;
		double x2 = -1.0;
		double y1 = -1.0;
		double y2 = -1.0;

		// Store the change in interval amount between iterations.
		// If it changes the extrapolation calculation must
		// take this into account.
		double intervalChange = 1;

		List<mxPoint> coreCurve = new ArrayList<mxPoint>();
		List<Double> coreIntervals = new ArrayList<Double>();
		boolean twoLoopsComplete = false;

		for (double t = 0; t <= 1.5; t += interval)
		{
			if (t > 1.0)
			{
				// Use the point regardless of the accuracy, 
				t = 1.0001;
				mxPoint endControlPoint = guidePoints
						.get(guidePoints.size() - 1);
				mxPoint finalPoint = new mxPoint(endControlPoint.getX(),
						endControlPoint.getY());
				coreCurve.add(finalPoint);
				coreIntervals.add(t);
				updateBounds(endControlPoint.getX(), endControlPoint.getY());
				break;
			}
			// Whether or not the accuracy of the current point is acceptable
			boolean currentPointAccepted = true;

			double newX = splineX.getFastValue(t);
			double newY = splineY.getFastValue(t);

			// Check if the last points are valid (indicated by
			// dissimilar values)
			// Check we're not in the first, second or last run
			if (x1 != -1.0 && twoLoopsComplete && t != 1.0001)
			{
				// Work out how far the new spline point
				// deviates from the extrapolation created 
				// by the last two points
				double diffX = Math.abs(((x2 - x1) * intervalChange + x2)
						- newX);
				double diffY = Math.abs(((y2 - y1) * intervalChange + y2)
						- newY);

				// If either the x or y of the straight line
				// extrapolation from the last two points
				// is more than the 1D deviation allowed
				// go back and re-calculate with a smaller interval
				// It's possible that the edge has curved too fast
				// for the algorithmn. If the interval is
				// reduced to less than the minimum permitted
				// interval, it may be that it's impossible
				// to get within the deviation because of
				// the extrapolation overshoot. The minimum 
				// interval is set to draw correctly for the
				// vast majority of cases.
				if ((diffX > maxDeviation || diffY > maxDeviation)
						&& interval != minInterval)
				{
					double overshootProportion = maxDeviation
							/ Math.max(diffX, diffY);

					if (interval * overshootProportion <= minInterval)
					{
						// Set the interval 
						intervalChange = minInterval / interval;
					}
					else
					{
						// The interval can still be reduced, half 
						// the interval and go back and redo
						// this iteration
						intervalChange = overshootProportion;
					}

					t -= interval;
					interval *= intervalChange;
					currentPointAccepted = false;
				}
				else if (diffX < minDeviation && diffY < minDeviation)
				{
					intervalChange = 1.4;
					interval *= intervalChange;
				}
				else
				{
					// Try to keep the deviation around the prefered value
					double errorRatio = preferedDeviation
							/ Math.max(diffX, diffY);
					intervalChange = errorRatio / 4.0;
					interval *= intervalChange;
				}

				if (currentPointAccepted)
				{
					x1 = x2;
					y1 = y2;
					x2 = newX;
					y2 = newY;
				}
			}
			else if (x1 == -1.0)
			{
				x1 = x2 = newX;
				y1 = y2 = newY;
			}
			else if (x1 == x2 && y1 == y2)
			{
				x2 = newX;
				y2 = newY;
				twoLoopsComplete = true;
			}
			if (currentPointAccepted)
			{
				mxPoint newPoint = new mxPoint(newX, newY);
				coreCurve.add(newPoint);
				coreIntervals.add(t);
				updateBounds(newX, newY);
			}
		}

		if (coreCurve.size() < 2)
		{
			// A single point makes no sense, leave the curve as invalid
			return;
		}

		mxPoint[] corePoints = new mxPoint[coreCurve.size()];
		int count = 0;

		for (mxPoint point : coreCurve)
		{
			corePoints[count++] = point;
		}

		points = new Hashtable<String, mxPoint[]>();
		curveLengths = new Hashtable<String, Double>();
		points.put(CORE_CURVE, corePoints);
		curveLengths.put(CORE_CURVE, lengthSpline);

		double[] coreIntervalsArray = new double[coreIntervals.size()];
		count = 0;

		for (Double tempInterval : coreIntervals)
		{
			coreIntervalsArray[count++] = tempInterval.doubleValue();
		}

		intervals = new Hashtable<String, double[]>();
		intervals.put(CORE_CURVE, coreIntervalsArray);

		valid = true;
	}
/**
	 * Creates the core curve that is based on the guide points passed into
	 * this class instance
	 */
Creates the core curve that is based on the guide points passed into
this class instance
Creates the core curve that is based on the guide points passed into this class instance
protected void createCoreCurve()
	{
		valid = false;
		if (guidePoints == null || guidePoints.isEmpty())
		{
			return;
		}
		for (int i = 0; i < guidePoints.size(); i++)
		{
			if (guidePoints.get(i) == null)
			{
				return;
			}
		}
		minXBounds = minYBounds = 10000000;
		maxXBounds = maxYBounds = 0;
		mxSpline spline = new mxSpline(guidePoints);
		double lengthSpline = spline.getLength();
		if (Double.isNaN(lengthSpline) || !spline.checkValues()
				|| lengthSpline < 1)
		{
			return;
		}
		mxSpline1D splineX = spline.getSplineX();
		mxSpline1D splineY = spline.getSplineY();
		double baseInterval = 12.0 / lengthSpline;
		double minInterval = 1.0 / lengthSpline;
		double interval = baseInterval;
		double minDeviation = 0.15;
		double maxDeviation = 0.3;
		double preferedDeviation = (maxDeviation + minDeviation) / 2.0;
		double x1 = -1.0;
		double x2 = -1.0;
		double y1 = -1.0;
		double y2 = -1.0;
		double intervalChange = 1;
		List<mxPoint> coreCurve = new ArrayList<mxPoint>();
		List<Double> coreIntervals = new ArrayList<Double>();
		boolean twoLoopsComplete = false;
		for (double t = 0; t <= 1.5; t += interval)
		{
			if (t > 1.0)
			{
				t = 1.0001;
				mxPoint endControlPoint = guidePoints
						.get(guidePoints.size() - 1);
				mxPoint finalPoint = new mxPoint(endControlPoint.getX(),
						endControlPoint.getY());
				coreCurve.add(finalPoint);
				coreIntervals.add(t);
				updateBounds(endControlPoint.getX(), endControlPoint.getY());
				break;
			}
			boolean currentPointAccepted = true;
			double newX = splineX.getFastValue(t);
			double newY = splineY.getFastValue(t);
			if (x1 != -1.0 && twoLoopsComplete && t != 1.0001)
			{
				double diffX = Math.abs(((x2 - x1) * intervalChange + x2)
						- newX);
				double diffY = Math.abs(((y2 - y1) * intervalChange + y2)
						- newY);
				if ((diffX > maxDeviation || diffY > maxDeviation)
						&& interval != minInterval)
				{
					double overshootProportion = maxDeviation
							/ Math.max(diffX, diffY);
					if (interval * overshootProportion <= minInterval)
					{
						intervalChange = minInterval / interval;
					}
					else
					{
						intervalChange = overshootProportion;
					}
					t -= interval;
					interval *= intervalChange;
					currentPointAccepted = false;
				}
				else if (diffX < minDeviation && diffY < minDeviation)
				{
					intervalChange = 1.4;
					interval *= intervalChange;
				}
				else
				{
					double errorRatio = preferedDeviation
							/ Math.max(diffX, diffY);
					intervalChange = errorRatio / 4.0;
					interval *= intervalChange;
				}
				if (currentPointAccepted)
				{
					x1 = x2;
					y1 = y2;
					x2 = newX;
					y2 = newY;
				}
			}
			else if (x1 == -1.0)
			{
				x1 = x2 = newX;
				y1 = y2 = newY;
			}
			else if (x1 == x2 && y1 == y2)
			{
				x2 = newX;
				y2 = newY;
				twoLoopsComplete = true;
			}
			if (currentPointAccepted)
			{
				mxPoint newPoint = new mxPoint(newX, newY);
				coreCurve.add(newPoint);
				coreIntervals.add(t);
				updateBounds(newX, newY);
			}
		}
		if (coreCurve.size() < 2)
		{
			return;
		}
		mxPoint[] corePoints = new mxPoint[coreCurve.size()];
		int count = 0;
		for (mxPoint point : coreCurve)
		{
			corePoints[count++] = point;
		}
		points = new Hashtable<String, mxPoint[]>();
		curveLengths = new Hashtable<String, Double>();
		points.put(CORE_CURVE, corePoints);
		curveLengths.put(CORE_CURVE, lengthSpline);
		double[] coreIntervalsArray = new double[coreIntervals.size()];
		count = 0;
		for (Double tempInterval : coreIntervals)
		{
			coreIntervalsArray[count++] = tempInterval.doubleValue();
		}
		intervals = new Hashtable<String, double[]>();
		intervals.put(CORE_CURVE, coreIntervalsArray);
		valid = true;
	}
protected void createCoreCurve ( ) { valid = false ; if ( guidePoints == null || guidePoints . isEmpty ( ) ) { return ; } for ( int i = 0 ; i < guidePoints . size ( ) ; i ++ ) { if ( guidePoints . get ( i ) == null ) { return ; } } minXBounds = minYBounds = 10000000 ; maxXBounds = maxYBounds = 0 ; mxSpline spline = new mxSpline ( guidePoints ) ; double lengthSpline = spline . getLength ( ) ; if ( Double . isNaN ( lengthSpline ) || ! spline . checkValues ( ) || lengthSpline < 1 ) { return ; } mxSpline1D splineX = spline . getSplineX ( ) ; mxSpline1D splineY = spline . getSplineY ( ) ; double baseInterval = 12.0 / lengthSpline ; double minInterval = 1.0 / lengthSpline ; double interval = baseInterval ; double minDeviation = 0.15 ; double maxDeviation = 0.3 ; double preferedDeviation = ( maxDeviation + minDeviation ) / 2.0 ; double x1 = - 1.0 ; double x2 = - 1.0 ; double y1 = - 1.0 ; double y2 = - 1.0 ; double intervalChange = 1 ; List < mxPoint > coreCurve = new ArrayList < mxPoint > ( ) ; List < Double > coreIntervals = new ArrayList < Double > ( ) ; boolean twoLoopsComplete = false ; for ( double t = 0 ; t <= 1.5 ; t += interval ) { if ( t > 1.0 ) { t = 1.0001 ; mxPoint endControlPoint = guidePoints . get ( guidePoints . size ( ) - 1 ) ; mxPoint finalPoint = new mxPoint ( endControlPoint . getX ( ) , endControlPoint . getY ( ) ) ; coreCurve . add ( finalPoint ) ; coreIntervals . add ( t ) ; updateBounds ( endControlPoint . getX ( ) , endControlPoint . getY ( ) ) ; break ; } boolean currentPointAccepted = true ; double newX = splineX . getFastValue ( t ) ; double newY = splineY . getFastValue ( t ) ; if ( x1 != - 1.0 && twoLoopsComplete && t != 1.0001 ) { double diffX = Math . abs ( ( ( x2 - x1 ) * intervalChange + x2 ) - newX ) ; double diffY = Math . abs ( ( ( y2 - y1 ) * intervalChange + y2 ) - newY ) ; if ( ( diffX > maxDeviation || diffY > maxDeviation ) && interval != minInterval ) { double overshootProportion = maxDeviation / Math . max ( diffX , diffY ) ; if ( interval * overshootProportion <= minInterval ) { intervalChange = minInterval / interval ; } else { intervalChange = overshootProportion ; } t -= interval ; interval *= intervalChange ; currentPointAccepted = false ; } else if ( diffX < minDeviation && diffY < minDeviation ) { intervalChange = 1.4 ; interval *= intervalChange ; } else { double errorRatio = preferedDeviation / Math . max ( diffX , diffY ) ; intervalChange = errorRatio / 4.0 ; interval *= intervalChange ; } if ( currentPointAccepted ) { x1 = x2 ; y1 = y2 ; x2 = newX ; y2 = newY ; } } else if ( x1 == - 1.0 ) { x1 = x2 = newX ; y1 = y2 = newY ; } else if ( x1 == x2 && y1 == y2 ) { x2 = newX ; y2 = newY ; twoLoopsComplete = true ; } if ( currentPointAccepted ) { mxPoint newPoint = new mxPoint ( newX , newY ) ; coreCurve . add ( newPoint ) ; coreIntervals . add ( t ) ; updateBounds ( newX , newY ) ; } } if ( coreCurve . size ( ) < 2 ) { return ; } mxPoint [ ] corePoints = new mxPoint [ coreCurve . size ( ) ] ; int count = 0 ; for ( mxPoint point : coreCurve ) { corePoints [ count ++ ] = point ; } points = new Hashtable < String , mxPoint [ ] > ( ) ; curveLengths = new Hashtable < String , Double > ( ) ; points . put ( CORE_CURVE , corePoints ) ; curveLengths . put ( CORE_CURVE , lengthSpline ) ; double [ ] coreIntervalsArray = new double [ coreIntervals . size ( ) ] ; count = 0 ; for ( Double tempInterval : coreIntervals ) { coreIntervalsArray [ count ++ ] = tempInterval . doubleValue ( ) ; } intervals = new Hashtable < String , double [ ] > ( ) ; intervals . put ( CORE_CURVE , coreIntervalsArray ) ; valid = true ; }
Creates the core curve that is based on the guide points passed into
 this class instance
Creates the core curve that is based on the guide points passed into this class instance
// Curve is marked invalid until all of the error situations have // been checked // Reset the cached bounds value // Need the rough length of the spline, so we can get // more samples for longer edges // Check for errors in the spline calculation or zero length curves // Store the last two spline positions. If the next position is  // very close to where the extrapolation of the last two points  // then double the interval. This diviation is terms the "flatness". // There is a range where the interval is kept the same, any  // variation from this range of flatness invokes a proportional  // adjustment to try to reenter the range without  // over compensating // These deviations are only tested against either  // dimension individually, working out the correct  // distance is too computationally intensive // x1, y1 are the position two iterations ago, x2, y2 // the position on the last iteration // Store the change in interval amount between iterations. // If it changes the extrapolation calculation must // take this into account. // Use the point regardless of the accuracy,  // Whether or not the accuracy of the current point is acceptable // Check if the last points are valid (indicated by // dissimilar values) // Check we're not in the first, second or last run // Work out how far the new spline point // deviates from the extrapolation created  // by the last two points // If either the x or y of the straight line // extrapolation from the last two points // is more than the 1D deviation allowed // go back and re-calculate with a smaller interval // It's possible that the edge has curved too fast // for the algorithmn. If the interval is // reduced to less than the minimum permitted // interval, it may be that it's impossible // to get within the deviation because of // the extrapolation overshoot. The minimum  // interval is set to draw correctly for the // vast majority of cases. // Set the interval  // The interval can still be reduced, half  // the interval and go back and redo // this iteration // Try to keep the deviation around the prefered value // A single point makes no sense, leave the curve as invalid