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). */