/// <summary> /// Setup the ratios for each curve of the path. Ratios are based on /// the speed that that portion of the path must follow. It is complicated /// by the fact that we must work on the curve via ratios rather than discreet /// points along it. /// </summary> private void InitRatios() { int nFrames; // for each curve along the path for (int i = 0; i < lengthRatios.Count; i++) { try { // this curve amounts to what % of the total path length double lengthPortion = (double)(lengthRatios[i].length / (double)pathLength); // based on total path time, how much time should be spent traversing this curve double timePortion = (lengthPortion * traversalTime); // how fast must sprite travel on this curve based on time spent on it. // Remember, this gets re-considered as a ratio later so the speed really // won't be different for this curve than others. double thisSpeed = lengthRatios[i].length / timePortion; // determine how far to travel per frame double frameSpeed = thisSpeed / SpriteManager.FPS; // determine how many frames will show while travelling this curve nFrames = (int)Math.Round(lengthRatios[i].length / frameSpeed); // at least show one frame in this curve, no matter what nFrames = nFrames < 1? 1: nFrames; // determine the ratio for the curve based on the number of frames to show double ratio = (double)(1.0d / (double)nFrames); // store what we calculated LengthRatio lrRef = lengthRatios[i]; lrRef.length = lengthRatios[i].length; lrRef.ratio = ratio; lengthRatios[i] = lrRef; } catch (Exception e) { throw e; } } ratioStep = lengthRatios[0].ratio; }
/// <summary> /// Determine and store the length of each curve segment along the whole path /// /// Assumption: /// points has 3*n+1 points in it. /// /// </summary> private void FillInSegmentLengths() { if (lengthRatios == null) { throw new Exception("lengthRatios must be defined assigned before calling FillInEndTangents"); } pathLength = 0; for (int i = 0; i < segmentCount; i++) { LengthRatio lr = new LengthRatio(); lr.length = BezierSprite.CalculateCurveLength( points.GetRange(i * 3, 4).ToArray() // there are 4 points to each segment. * 3 because we start each next segment with the end point of the previous segment ); lr.ratio = defaultRatio; // default value since we haven't calc'd ratios yet lengthRatios[i] = lr; pathLength += lr.length; // calc length of whole path } }
/// <summary> /// Determine and store the length of each curve segment along the whole path /// /// Assumption: /// points has 3*n+1 points in it. /// /// </summary> private void FillInSegmentLengths() { if (lengthRatios == null) throw new Exception("lengthRatios must be defined assigned before calling FillInEndTangents"); pathLength = 0; for (int i = 0; i < segmentCount; i++) { LengthRatio lr = new LengthRatio(); lr.length = BezierSprite.CalculateCurveLength( points.GetRange(i * 3, 4).ToArray() // there are 4 points to each segment. * 3 because we start each next segment with the end point of the previous segment ); lr.ratio = defaultRatio; // default value since we haven't calc'd ratios yet lengthRatios[i] = lr; pathLength += lr.length; // calc length of whole path } }
/// <summary> /// If the ratio is 0.0d we calculate tangents based on the end points to their /// nearest guide point. This does that. /// </summary> private void FillInEndTangents() { if (lengthRatios == null) { throw new Exception("lengthRatios must be defined assigned before calling FillInEndTangents"); } for (int i = 0; i < segmentCount; i++) { LengthRatio lr = lengthRatios[i]; Point pt; // we can't determine angles if guide points are exactly the same as node points. // Therefore, if that is the case, find another guide point to use. // if first guide point is not same as first node if (points[i * 3] != points[i * 3 + 1]) { pt = points[i * 3 + 1]; } else // else if 2nd guide point is not same as first node if (points[i * 3] != points[i * 3 + 2]) { pt = points[i * 3 + 2]; } else // else if end point is not same as first node if (points[i * 3] != points[i * 3 + 3]) { pt = points[i * 3 + 3]; } else // else all points in curve are the same - just accept it and move on { pt = points[i * 3]; } if (pt == points[i * 3]) // all points in curve are same, set tangent to 0 degrees { lr.startTangent = 0.0d; lr.endTangent = 0.0d; continue; } else { lr.startTangent = CalculateAngleBetweenPoints(points[i * 3], pt); } // if 2nd guide point is not same as 2nd node if (points[i * 3 + 3] != points[i * 3 + 2]) { pt = points[i * 3 + 2]; } else // else if 1st guide point is not same as 2nd node if (points[i * 3 + 3] != points[i * 3 + 1]) { pt = points[i * 3 + 1]; } else // else if 1st node is not same as 2nd node if (points[i * 3 + 3] != points[i * 3 + 0]) { pt = points[i * 3 + 0]; } lr.endTangent = CalculateAngleBetweenPoints(pt, points[i * 3 + 3]); lengthRatios[i] = lr; } }