public QuadraticBezierCurve3D(Vector3 point1, Vector3 controlPoint, Vector3 point2) { this(); addPoint(point1, controlPoint, point2); }
public CubicBezierCurve3D(Vector3 point1, Vector3 controlPoint1, Vector3 controlPoint2, Vector3 point2) { this(); addPoint(point1, controlPoint1, controlPoint2, point2); }
public LinearBezierCurve3D(Vector3 point1, Vector3 point2) { this(); addPoint(point1, point2); }
bezierPath.addCurve(new LinearBezierCurve3D(mPreviousPoint.clone(), p)); break; case HORIZONTAL: bezierPath.addCurve(new LinearBezierCurve3D(mPreviousPoint.clone(), p)); break; case CURVE_TO: cp2.add(mPreviousPoint); mPreviousControlPoint.setAll(cp2); bezierPath.addCurve(new CubicBezierCurve3D(mPreviousPoint.clone(), cp1, cp2, p)); break; case SMOOTH_CURVE_TO: c = new Vector3(Double.parseDouble(vals[2]), -Double.parseDouble(vals[3]), 0); p = mCurrentCommandIsRelative ? c.addAndSet(mPreviousPoint, c) : c; cp1 = reflect(mPreviousControlPoint, mPreviousPoint); cp2 = new Vector3(Double.parseDouble(vals[0]), -Double.parseDouble(vals[1]), 0); if (mCurrentCommandIsRelative) cp2.add(mPreviousPoint); bezierPath.addCurve(new CubicBezierCurve3D(mPreviousPoint.clone(), cp1, cp2, p)); break; case LINE_TO: c = new Vector3(Double.parseDouble(vals[0]), -Double.parseDouble(vals[1]), 0); p = mCurrentCommandIsRelative ? c.addAndSet(mPreviousPoint, c) : c; bezierPath.addCurve(new LinearBezierCurve3D(mPreviousPoint.clone(), p)); break; default: return;
/** * Adds a {@link List} of object configurations to the animation at the end of the list. * * @param objects {@link List} of {@link CoalesceConfig} The new configurations to add to the animation list. */ public void addCoalescingGroup(List<CoalesceConfig> objects) { for (CoalesceConfig config : objects) { mCoalesceObjects.add(config); mThetaRanges.add(config.spiral.calculateThetaForRadius(config.endProximity)); } }
/** * Calculates the position on the spiral for the specified polar angle. This takes an additional * parameter of a {@link Vector3} which will be set to the calculated position. * * @param result {@link Vector3} to set with the updated position. * @param theta {@code double} the polar angle to calculate for, in degrees. */ public void calculatePointDegrees(Vector3 result, double theta) { calculatePoint(result, Math.toRadians((mSpiralIn ? mThetaOffset - theta : theta + mThetaOffset))); }
public void calculatePoint(Vector3 point, double t) { int currentIndex = (int) Math.floor((t == 1 ? t - DELTA : t) * mNumCurves); mCurrentCurve = mCurves.get(currentIndex); double tdivnum = (t * mNumCurves) - currentIndex; mCurrentCurve.calculatePoint(point, tdivnum); }
public Vector3 getCurrentTangent() { if(mCurrentCurve == null) return null; return mCurrentCurve.getCurrentTangent(); }
public int selectPoint(Vector3 point) { double minDist = Double.MAX_VALUE; mSelectedIndex = -1; for (int i = 0; i < mNumPoints; i++) { Vector3 p = mPoints.get(i); double distance = pow2(p.x - point.x) + pow2(p.y - point.y) + pow2(p.z - point.z); if (distance < minDist && distance < EPSILON) { minDist = distance; mSelectedIndex = i; } } return mSelectedIndex; }
public void setOrientToPath(boolean orientToPath) { if (mSplinePath == null) throw new RuntimeException("You must set a spline path before orientation to path is possible."); mOrientToPath = orientToPath; mSplinePath.setCalculateTangents(orientToPath); }
/** * Calculates the position on the spiral for the specified polar angle. This takes an additional * parameter of a {@link Vector3} which will be set to the calculated position. * * @param result {@link Vector3} to set with the updated position. * @param theta {@code double} the polar angle to calculate for, in degrees. */ public void calculatePointDegrees(Vector3 result, double theta) { calculatePoint(result, Math.toRadians((mSpiralIn ? mThetaOffset - theta : theta + mThetaOffset))); }
public void calculatePoint(Vector3 result, final double t) { if (mCalculateTangents) { double prevt = t == 0 ? t + DELTA : t - DELTA; double nextt = t == 1 ? t - DELTA : t + DELTA; p(mCurrentTangent, prevt); p(mTempNext, nextt); mCurrentTangent.subtract(mTempNext); mCurrentTangent.multiply(.5); mCurrentTangent.normalize(); } p(result,t); }
/** * Returns an approximation of the length of the curve. The more segments the more precise the result. * * @param segments * @return */ public double getLength(int segments) { double totalLength = 0; mSegmentLengths = new double[segments + 1]; mSegmentLengths[0] = 0; calculatePoint(mTempPrevLen, 0); for (int i = 1; i <= segments; i++) { double t = (double) i / (double) segments; calculatePoint(mTempPointLen, t); double dist = mTempPrevLen.distanceTo(mTempPointLen); totalLength += dist; mSegmentLengths[i] = dist; mTempPrevLen.setAll(mTempPointLen); } return totalLength; }
/** * Parses an SVG Path string * * @param pathString * @return */ public List<CompoundCurve3D> parseString(String pathString) { mPreviousPoint = new Vector3(); mStartPoint = new Vector3(); mPreviousControlPoint = new Vector3(); return pathStringToLine(pathString); }
/** * Constructs a {@link ArchimedeanSpiral3D} with the specified parameters. * * @param scale {@code double} Factor which determines the overal size of the spiral. * @param density {@code double} Factor which determines how tightly the spiral is curled. Smaller values result in tighter curling. * @param start {@link Vector3} The point where the spiral should start from. * @param normal {@link Vector3} The normal vector of the plane the spiral is in. This is assumed to be * orthogonal to the vector formed from the start to the origin. * @param spiralIn {@code boolean} True if the spiral should move from the staring point in. False to move from starting point out. * Note that for an Archimedean spiral, inward spiraling is not infinite as is the case for a logarithmic * spiral. A sufficient number of rotations will cause a "loop" to form and it will begin spiraling outward. */ public ArchimedeanSpiral3D(double scale, double density, Vector3 start, Vector3 normal, boolean spiralIn) { super(density, start, normal, spiralIn); // Calculate the remaining conditions a = scale; mInvDensity = 1.0 / mDensity; // Calculate the starting offset mThetaOffset = mSpiralIn ? calculateThetaForRadius(mStart.length()) : mRotation.getXAxis().angle(mStart); }
/** * Constructs a {@link LogarithmicSpiral3D} with the specified parameters. * * @param density {@code double} Factor which determines how tightly the spiral is curled. Larger values result in tighter curling. * @param start {@link Vector3} The point where the spiral should start from. * @param normal {@link Vector3} The normal vector of the plane the spiral is in. This is assumed to be * orthogonal to the vector formed from the start to the origin. * @param spiralIn {@code boolean} True if the spiral should move from the staring point in. False to move from starting point out. */ public LogarithmicSpiral3D(double density, Vector3 start, Vector3 normal, boolean spiralIn) { super(density, start, normal, spiralIn); // Calculate the remaining conditions a = mStart.length(); // Calculate the starting offset mThetaOffset = mSpiralIn ? calculateThetaForRadius(mStart.length()) : mRotation.getXAxis().angle(mStart); }
/** * Adds an object configuration to the animation at the end of the list. * * @param object {@link CoalesceConfig} The new configuration to add to the animation list. */ public void addCoalescingObject(CoalesceConfig object) { mCoalesceObjects.add(object); mThetaRanges.add(object.spiral.calculateThetaForRadius(object.endProximity)); }
@Override protected void applyTransformation() { synchronized (mCoalesceObjects) { synchronized (mThetaRanges) { int i; final int j = mCoalesceObjects.size(); for (i = 0; i < j; ++i) { // Retrieve the configuration CoalesceConfig config = mCoalesceObjects.get(i); double theta = mThetaRanges.get(i) * mInterpolatedTime; // Calculate the next point config.spiral.calculatePoint(config.object.getPosition(), theta); // Add the coalesce point to translate our spiral config.object.getPosition().add(config.coalesceAroundPoint); } } } }
@Override protected void applyTransformation() { mSplinePath.calculatePoint(mTempPoint1, mInterpolatedTime); mTransformable3D.setPosition(mTempPoint1); if(mTarget != null) { mTransformable3D.setLookAt(mTarget.getPosition()); if(mUp != null) mTransformable3D.setUpAxis(mUp); } if (mOrientToPath) { // -- calculate tangent mSplinePath.calculatePoint(mTempPoint2, mInterpolatedTime + mLookatDelta * (mIsReversing ? -1 : 1)); mTransformable3D.setLookAt(mTempPoint2); } }
/** * Constructs a basic coalescence animation. * * @param rootConfig {@link CoalesceConfig} The root object of the animation. This is simply the first item in * item in the animation list. */ public CoalesceAnimation3D(CoalesceConfig rootConfig) { mCoalesceObjects = Collections.synchronizedList(new CopyOnWriteArrayList<CoalesceConfig>()); mThetaRanges = Collections.synchronizedList(new CopyOnWriteArrayList<Double>()); mTransformable3D = rootConfig.object; mCoalesceObjects.add(rootConfig); mThetaRanges.add(rootConfig.spiral.calculateThetaForRadius(rootConfig.endProximity)); }