package edu.stanford.rsl.conrad.geometry.splines;
import java.util.ArrayList;
import edu.stanford.rsl.conrad.geometry.AbstractShape;
import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
public class SurfaceUniformCubicBSpline extends SurfaceBSpline {
public SurfaceUniformCubicBSpline(ArrayList<PointND> list, double[] uKnots,
double[] vKnots) {
super(list, uKnots, vKnots);
}
public SurfaceUniformCubicBSpline(String last, ArrayList<PointND> list,
double[] uKnots, double[] vKnots) {
super(last, list, uKnots, vKnots);
}
public SurfaceUniformCubicBSpline(String name,
ArrayList<PointND> controlPoints, SimpleVector uKnots,
SimpleVector vKnots) {
super(name, controlPoints,uKnots, vKnots);
}
public SurfaceUniformCubicBSpline(ArrayList<PointND> initialPoints,
SimpleVector uKnots, SimpleVector vKnots) {
super(initialPoints, uKnots, vKnots);
}
public SurfaceUniformCubicBSpline(SurfaceBSpline spline) {
super(spline);
}
/**
*
*/
private static final long serialVersionUID = -7498785267911679836L;
protected synchronized void init(){
dimension = points.get(0).getDimension();
int degreeU = 0;
while(uKnots.getElement(degreeU) == 0) degreeU++;
degreeU --;
int degreeV = 0;
while(uKnots.getElement(degreeV) == 0) degreeV++;
degreeV --;
numberOfUPoints = uKnots.getLen() - ((degreeU+1));
numberOfVPoints = vKnots.getLen() - ((degreeV+1));
assert(numberOfUPoints * numberOfVPoints == points.size());
ArrayList<PointND> temp = new ArrayList<PointND>();
for(int i = 0; i < numberOfUPoints; i++){
temp.add(points.get(0));
}
uSpline = new UniformCubicBSpline(temp, uKnots); //TODO: decrease duplicate code (Generics<T>)
vSplines = new BSpline[numberOfUPoints];
for(int i = 0; i < numberOfUPoints; i++){
temp = new ArrayList<PointND>();
for(int j = 0; j < numberOfVPoints; j++){
temp.add(points.get((i*numberOfVPoints)+j));
}
vSplines[i] = new UniformCubicBSpline(temp, vKnots);
}
max = new PointND(-Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE);
min = new PointND(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
for (PointND p: points) {
max.updateIfHigher(p);
min.updateIfLower(p);
}
generateBoundingPlanes();
}
@Override
public PointND evaluate(double u, double v){
double [] p = new double [getControlPoints().get(0).getDimension()];
double internal = ((u * uSpline.getKnots().length) -3.0);
int numPts = uSpline.getControlPoints().size();
double step = internal- Math.floor(internal);
//System.out.println(u + " " + internal);
double [] weights = UniformCubicBSpline.getWeights(step);
for (int i=0;i<4;i++){
double [] loc = (internal+i < 0)? vSplines[0].evaluate(v).getCoordinates(): (internal+i>=numPts)? vSplines[numPts-1].evaluate(v).getCoordinates() : vSplines[(int) (internal+i)].evaluate(v).getCoordinates();
for (int j = 0; j < loc.length; j++)
p[j] += (loc[j] * weights[i]);
//p[j] =weights[i];
//p[j] = loc[j];
}
return new PointND(p);
}
@Override
public AbstractShape clone() {
return new SurfaceUniformCubicBSpline(this);
}
}
/*
* Copyright (C) 2010-2014 Andreas Maier
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/