📄 parametriccurve.java
字号:
vt += LINEAR_MATRIX.M[i][1] * (Math.pow(t, 3 - i)); } p = endingSegmentControl[0]; result = result.add(p.multiply(vt)); // 0 vt = 0; for ( int i = 0; i < 4; i++ ) { vt += LINEAR_MATRIX.M[i][2] * (Math.pow(t, 3 - i)); } p = new Vector3D(0, 0, 0); result = result.add(p.multiply(vt)); // 0 vt = 0; for ( int i = 0; i < 4; i++ ) { vt += LINEAR_MATRIX.M[i][3] * (Math.pow(t, 3 - i)); } p = new Vector3D(0, 0, 0); result = result.add(p.multiply(vt)); return result; } /** Note that current implemented quadratic spline interpolation strategy is to first express the second order quadric as a third order Bezier spline, and later evaluate the Bezier spline, as noted on [.FONT2006]. @todo Express this interpolation as a QUAD_MATRIX and similar scheme to other points in this class. */ private Vector3D evaluateQuadratic(int nseg, double t) { Vector3D[] startingSegmentControl = points.get(nseg - 1); Vector3D[] endingSegmentControl = points.get(nseg); Vector3D p; Vector3D qp0, qp1, qp2; qp0 = startingSegmentControl[0]; qp1 = endingSegmentControl[1]; qp2 = endingSegmentControl[0]; // p0 Vector3D result = qp0; double vt = 0; for ( int i = 0; i < 4; i++ ) { vt += BEZIER_MATRIX.M[i][0] * (Math.pow(t, 3 - i)); } result = result.multiply(vt); // p1 vt = 0; for ( int i = 0; i < 4; i++ ) { vt += BEZIER_MATRIX.M[i][1] * (Math.pow(t, 3 - i)); } p = qp0.add((qp1.substract(qp0)).multiply(2/3)); result = result.add(p.multiply(vt)); // p2 vt = 0; for (int i = 0; i < 4; i++) { vt += BEZIER_MATRIX.M[i][2] * (Math.pow(t, 3 - i)); } p = qp1.add((qp2.substract(qp0)).multiply(1/3)); result = result.add(p.multiply(vt)); // p3 vt = 0; for (int i = 0; i < 4; i++) { vt += BEZIER_MATRIX.M[i][3] * (Math.pow(t, 3 - i)); } p = endingSegmentControl[0]; result = result.add(p.multiply(vt)); return result; } private Vector3D evaluateHermite(int nseg, double t) { Vector3D[] startingSegmentControl = points.get(nseg - 1); Vector3D[] endingSegmentControl = points.get(nseg); // p1 Vector3D result = startingSegmentControl[0]; double vt = 0; for ( int i = 0; i < 4; i++ ) { vt += HERMITE_MATRIX.M[i][0] * (Math.pow(t, 3 - i)); } result = result.multiply(vt); // p4 vt = 0; for ( int i = 0; i < 4; i++ ) { vt += HERMITE_MATRIX.M[i][1] * (Math.pow(t, 3 - i)); } Vector3D p = endingSegmentControl[0]; result = result.add(p.multiply(vt)); // r1 vt = 0; for ( int i = 0; i < 4; i++ ) { vt += HERMITE_MATRIX.M[i][2] * (Math.pow(t, 3 - i)); } p = startingSegmentControl[2]; result = result.add(p.multiply(vt)); // r4 vt = 0; for ( int i = 0; i < 4; i++ ) { vt += HERMITE_MATRIX.M[i][3] * (Math.pow(t, 3 - i)); } p = endingSegmentControl[1]; result = result.add(p.multiply(vt)); return result; } private Vector3D evaluateBezier(int nseg, double t) { Vector3D[] startingSegmentControl = points.get(nseg - 1); Vector3D[] endingSegmentControl = points.get(nseg); Vector3D p; // p1 Vector3D result = startingSegmentControl[0]; double vt = 0; for ( int i = 0; i < 4; i++ ) { vt += BEZIER_MATRIX.M[i][0] * (Math.pow(t, 3 - i)); } result = result.multiply(vt); // p2 vt = 0; for ( int i = 0; i < 4; i++ ) { vt += BEZIER_MATRIX.M[i][1] * (Math.pow(t, 3 - i)); } p = startingSegmentControl[2]; result = result.add(p.multiply(vt)); // p3 vt = 0; for (int i = 0; i < 4; i++) { vt += BEZIER_MATRIX.M[i][2] * (Math.pow(t, 3 - i)); } p = endingSegmentControl[1]; result = result.add(p.multiply(vt)); // p4 vt = 0; for (int i = 0; i < 4; i++) { vt += BEZIER_MATRIX.M[i][3] * (Math.pow(t, 3 - i)); } p = endingSegmentControl[0]; result = result.add(p.multiply(vt)); return result; } private Vector3D evaluateBspline(int nseg, double t) { if (points.size() < 4) { return null; } Vector3D result = new Vector3D(0, 0, 0); for (int np = 0; np < 4; np++) { double vt = 0; for (int i = 0; i < 4; i++) { vt += UNRBSPLINE_MATRIX.M[i][np] * (Math.pow(t, 3 - i)); } Vector3D p = points.get(nseg - np)[0]; // Note the 1/6 multiplication! result = result.add(p.multiply(vt / 6)); } return result; } private int calculatePointPosition(int pin) { int pout, i; pout = 0; for ( i = 0; i < types.size() && i < pin; i++ ) { if ( types.get(i) == BREAK ) { pout = -1; } else { pout++; } } return pout; } /** This method calculates the interpolation points for the segment that ends in the point `endingPointForSegment`.<P> Note that as evaluation is able to manage the linear/corner case under the same numerical schema that is used for other curve types, the polyline can be interpreted as multiple segments for applications requiring. However, in cases as simple drawing, this leads to unnecessary line primitives. Due to that situation, the user can specify if breaking rects or not. */ public ArrayList<Vector3D> calculatePoints(int endingPointForSegment, boolean withBrokenRects) { ArrayList<Vector3D> pol = new ArrayList<Vector3D> (); // `relativePoint` is used to estimate current starting point // for curve. Starting points are -1 for break points (i.e. no curve), // and some curves needs previous N relative points, so this is // used to prevent computation of undefined curve segments. int relativePoint = calculatePointPosition(endingPointForSegment); if ( (relativePoint <= 2 && types.get(endingPointForSegment) == UNRBSPLINE) || relativePoint < 0 ) { // The Uniform Non Rational B Splines require a least 3 control // points, which do not form a curve segment. // A break control point doesn't define any points return pol; } if ( (types.get(endingPointForSegment) == CORNER && !withBrokenRects) || relativePoint <= 0 || (types.get(endingPointForSegment) == UNRBSPLINE && relativePoint < 3)) { pol.add(points.get(endingPointForSegment - 1)[0]); pol.add(points.get(endingPointForSegment)[0]); } else { Vector3D q = evaluate(endingPointForSegment, 0); if (q == null) { return pol; } pol.add(q); for ( int i = 1; i <= approximationSteps; i++ ) { q = evaluate(endingPointForSegment, (double)i / (double)approximationSteps); if (q != null) { pol.add(q); } } } return pol; } /** This method returns an aproximate minmax of current curve, based on a sampling (evaluation) of points. */ public double[] getMinMax() { double minmax[] = new double[6]; int i, j; for ( i = 0; i < 3; i++ ) minmax[i] = Double.MAX_VALUE; for ( ; i < 6; i++ ) minmax[i] = Double.MIN_VALUE; Vector3D p; for ( i = 1; i < types.size(); i++ ) { ArrayList polyline = calculatePoints(i, false); for ( j = 0; j < polyline.size(); j++ ) { p = (Vector3D)polyline.get(j); if ( p.x < minmax[0] ) minmax[0] = p.x; if ( p.y < minmax[1] ) minmax[1] = p.y; if ( p.z < minmax[2] ) minmax[2] = p.z; if ( p.x > minmax[3] ) minmax[3] = p.x; if ( p.y > minmax[4] ) minmax[4] = p.y; if ( p.z > minmax[5] ) minmax[5] = p.z; } } return minmax; } /** Check the general interface contract in superclass method Geometry.doContainmentTest. @todo Check efficiency for this implementation. Note that for the special application of volume rendering generation, it is better to provide another method, to add voxels after a path following over the line. */ public int doContainmentTest(Vector3D p, double distanceTolerance) { int i, j; Vector3D vec; for ( i = 1; i < types.size(); i++ ) { if ( types.get(i).intValue() == BREAK ) { i++; continue; } // Build a polyline for approximating the [i] curve segment ArrayList polyline = calculatePoints(i, false); // Solve problem for the polyline for ( j = 0; j < polyline.size(); j++ ) { vec = (Vector3D) polyline.get(j); if ( VSDK.vectorDistance(vec, p) < distanceTolerance ) { return LIMIT; } } } return OUTSIDE; }}//===========================================================================//= EOF =//===========================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -