/*******************************************************************************
* Copyright 2010 Simon Mieth
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.kabeja.math;
public class NURBS {
protected Point3D[] controlPoints;
protected double[] knots;
protected double[] weights;
protected int degree;
protected boolean closed = false;
public NURBS(Point3D[] controlPoints, double[] knots, double[] weights,
int degree) {
this.controlPoints = controlPoints;
this.knots = knots;
this.weights = weights;
this.degree = degree;
//some init stuff
if (this.weights.length == 0) {
this.weights = new double[this.controlPoints.length];
}
for (int i = 0; i < weights.length; i++) {
if (weights[i] == 0.0) {
weights[i] = 1.0;
}
}
}
public double[] getBasicFunctions(int i, double u) {
double[] n = new double[degree + 1];
n[0] = 1.0;
double[] left = new double[degree + 1];
double[] right = new double[degree + 1];
for (int j = 1; j <= degree; j++) {
left[j] = u - this.knots[(i + 1) - j];
right[j] = this.knots[i + j] - u;
double saved = 0.0;
for (int r = 0; r < j; r++) {
double t = n[r] / (right[r + 1] + left[j - r]);
n[r] = saved + (right[r + 1] * t);
saved = left[j - r] * t;
}
n[j] = saved;
}
return n;
}
public Point3D getPointAt(int i, double u) {
Point3D p = new Point3D();
double[] n = this.getBasicFunctions(i, u);
double t = 0.0;
for (int j = 0; j <= this.degree; j++) {
int d = i - this.degree + j;
double w = this.weights[d];
p.setX(p.getX() + (n[j] * this.controlPoints[d].getX() * w));
p.setY(p.getY() + (n[j] * this.controlPoints[d].getY() * w));
p.setZ(p.getZ() + (n[j] * this.controlPoints[d].getZ() * w));
t += (n[j] * w);
}
p.setX((p.getX() / t));
p.setY(p.getY() / t);
p.setZ(p.getZ() / t);
return p;
}
public Point3D getPointAt(double u) {
int interval = this.findSpawnIndex(u);
return this.getPointAt(interval, u);
}
public int findSpawnIndex(double u) {
if (u == this.knots[this.controlPoints.length + 1]) {
return this.controlPoints.length;
}
int low = this.degree;
int high = this.controlPoints.length + 1;
int mid = (low + high) / 2;
while ((u < this.knots[mid]) || (u >= this.knots[mid + 1])) {
if (u < this.knots[mid]) {
high = mid;
} else {
low = mid;
}
mid = (low + high) / 2;
}
return mid;
}
public Point3D[] getControlPoints() {
return controlPoints;
}
public void setControlPoints(Point3D[] controlPoints) {
this.controlPoints = controlPoints;
}
public double[] getKnots() {
return knots;
}
public void setKnots(double[] knots) {
this.knots = knots;
}
public double[] getWeights() {
return weights;
}
public void setWeights(double[] weights) {
this.weights = weights;
}
public int getDegree() {
return degree;
}
public void setDegree(int degree) {
this.degree = degree;
}
public boolean isClosed() {
return closed;
}
public void setClosed(boolean closed) {
this.closed = closed;
}
}