package edu.stanford.rsl.conrad.geometry.shapes.simple; import java.util.ArrayList; import edu.stanford.rsl.apps.gui.opengl.PointCloudViewer; import edu.stanford.rsl.conrad.geometry.AbstractCurve; import edu.stanford.rsl.conrad.geometry.AbstractShape; import edu.stanford.rsl.conrad.geometry.Axis; import edu.stanford.rsl.conrad.geometry.General; import edu.stanford.rsl.conrad.geometry.shapes.compound.CompoundShape; import edu.stanford.rsl.conrad.geometry.transforms.AffineTransform; import edu.stanford.rsl.conrad.numerics.SimpleMatrix; import edu.stanford.rsl.conrad.numerics.SimpleVector; import edu.stanford.rsl.conrad.utils.CONRAD; /** * Creates a Box. */ public class Box extends SimpleSurface { public static final long serialVersionUID = 1760483762488429473L; private Axis principalAxis = new Axis(new SimpleVector(1,0,0)); //protected PointND lowerCorner; public PointND lowerCorner; // invisible in OpenCLBox, the suggestion is to change to 'public' //protected PointND upperCorner; public PointND upperCorner; public Box(){ SimpleMatrix mat = new SimpleMatrix(3,3); mat.identity(); transform = new AffineTransform(mat, new SimpleVector(0,0,0)); } /** * Generates a box of size dx*dy*dz at between (0,0,0) and (dx,dy,dz) * @param dx * @param dy * @param dz */ public Box(double dx, double dy, double dz){ this(); init((new PointND(0,0,0)),dx, dy, dz); } public Box(Box b){ super(b); principalAxis = b.principalAxis!=null ? b.principalAxis.clone() : null; lowerCorner = b.lowerCorner != null ? b.lowerCorner.clone() : null; upperCorner = b.upperCorner != null ? b.upperCorner.clone() : null; } protected void init(PointND origin, double dx, double dy, double dz) { min = origin; lowerCorner = min; max = new PointND(origin.get(0)+ dx,origin.get(1)+dy,origin.get(2)+dz); upperCorner = max; generateBoundingPlanes(); } @Override public boolean isMember(PointND point, boolean pointTransformed) { // TODO: Correct for new boundary conditions // Now, only the bounding box is checked. for (int j=0; j < point.getDimension(); j++){ double coord = point.get(j); if (coord > max.get(j) + CONRAD.SMALL_VALUE || coord < min.get(j) - CONRAD.SMALL_VALUE) { return false; } } return true; } @Override public PointND evaluate(PointND u) { return null; } @Override public int getDimension() { return 3; } @Override public int getInternalDimension() { return 0; } @Override public ArrayList<PointND> intersect(AbstractCurve other) { StraightLine buff = (StraightLine) other; StraightLine line = new StraightLine(buff.getPoint().clone(), buff.getDirection().clone()); line.applyTransform(transform.inverse()); ArrayList<PointND> hitsOnShape = General.intersectRayWithCuboid(line, lowerCorner, upperCorner); return getCorrectedHits(hitsOnShape); } @Override public boolean isBounded() { return true; } @Override public PointND[] getRasterPoints(int number) { PointND one = transform.transform(new PointND(lowerCorner.get(0), lowerCorner.get(1), lowerCorner.get(2))); PointND two = transform.transform(new PointND(upperCorner.get(0), lowerCorner.get(1), lowerCorner.get(2))); PointND three = transform.transform(new PointND(lowerCorner.get(0), upperCorner.get(1), lowerCorner.get(2))); PointND four = transform.transform(new PointND(upperCorner.get(0), upperCorner.get(1), lowerCorner.get(2))); PointND five = transform.transform(new PointND(lowerCorner.get(0), lowerCorner.get(1), upperCorner.get(2))); PointND six = transform.transform(new PointND(upperCorner.get(0), lowerCorner.get(1), upperCorner.get(2))); PointND seven = transform.transform(new PointND(lowerCorner.get(0), upperCorner.get(1), upperCorner.get(2))); PointND eight = transform.transform(new PointND(upperCorner.get(0), upperCorner.get(1), upperCorner.get(2))); int subNumber = number /12; Edge e01 = new Edge(one, two); Edge e02 = new Edge(one, three); Edge e03 = new Edge(one, five); Edge e04 = new Edge(two, six); Edge e05 = new Edge(two, four); Edge e06 = new Edge(three, four); Edge e07 = new Edge(seven, three); Edge e08 = new Edge(four, eight); Edge e09 = new Edge(five, six); Edge e10 = new Edge(five, seven); Edge e11 = new Edge(six, eight); Edge e12 = new Edge(seven, eight); PointND [] points01 = e01.getRasterPoints(subNumber); PointND [] points02 = e02.getRasterPoints(subNumber); PointND [] points03 = e03.getRasterPoints(subNumber); PointND [] points04 = e04.getRasterPoints(subNumber); PointND [] points05 = e05.getRasterPoints(subNumber); PointND [] points06 = e06.getRasterPoints(subNumber); PointND [] points07 = e07.getRasterPoints(subNumber); PointND [] points08 = e08.getRasterPoints(subNumber); PointND [] points09 = e09.getRasterPoints(subNumber); PointND [] points10 = e10.getRasterPoints(subNumber); PointND [] points11 = e11.getRasterPoints(subNumber); PointND [] points12 = e12.getRasterPoints(subNumber); PointND [] points = new PointND[12 * subNumber]; int offset = 0; System.arraycopy(points01, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points02, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points03, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points04, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points05, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points06, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points07, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points08, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points09, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points10, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points11, 0, points, offset, subNumber); offset += subNumber; System.arraycopy(points12, 0, points, offset, subNumber); return points; } @Override public ArrayList<PointND> getHits(AbstractCurve other) { // TODO Auto-generated method stub return null; } @Override public Axis getPrincipalAxis() { return principalAxis ; } @Override public PointND evaluate(double u, double v) { // TODO Auto-generated method stub return null; } @Override public AbstractShape tessellate(double accuracy) { PointND one = transform.transform(new PointND(lowerCorner.get(0), lowerCorner.get(1), lowerCorner.get(2))); PointND two = transform.transform(new PointND(upperCorner.get(0), lowerCorner.get(1), lowerCorner.get(2))); PointND three = transform.transform(new PointND(lowerCorner.get(0), upperCorner.get(1), lowerCorner.get(2))); PointND four = transform.transform(new PointND(upperCorner.get(0), upperCorner.get(1), lowerCorner.get(2))); PointND five = transform.transform(new PointND(lowerCorner.get(0), lowerCorner.get(1), upperCorner.get(2))); PointND six = transform.transform(new PointND(upperCorner.get(0), lowerCorner.get(1), upperCorner.get(2))); PointND seven = transform.transform(new PointND(lowerCorner.get(0), upperCorner.get(1), upperCorner.get(2))); PointND eight = transform.transform(new PointND(upperCorner.get(0), upperCorner.get(1), upperCorner.get(2))); CompoundShape shape = new CompoundShape(); shape.add(new Triangle(one, two, four)); shape.add(new Triangle(one, three, four)); shape.add(new Triangle(one, two, six)); shape.add(new Triangle(one, five, six)); shape.add(new Triangle(two, four, eight)); shape.add(new Triangle(two, six, eight)); shape.add(new Triangle(one, three, seven)); shape.add(new Triangle(one, five, seven)); shape.add(new Triangle(six, five, seven)); shape.add(new Triangle(six, seven, eight)); shape.add(new Triangle(three, four, eight)); shape.add(new Triangle(three, seven, eight)); return shape; } public float[] getRasterPointsOld(int elementCountU, int elementCountV) { //if (elementCountU % 8 != 0 || elementCountV % 8 != 0){ // System.out.println("Error! valuesU and valuesV have to be a multiple of 4"); // return null; //} int pointsOnCurve = elementCountU; int numberOfCurves = elementCountV; int extraValuesPerEdge = (elementCountU-4)/4; PointND[] points = new PointND[8]; points[0] = transform.transform(new PointND(lowerCorner.get(0), lowerCorner.get(1), upperCorner.get(2))); points[1] = transform.transform(new PointND(upperCorner.get(0), lowerCorner.get(1), upperCorner.get(2))); points[2] = transform.transform(new PointND(upperCorner.get(0), upperCorner.get(1), upperCorner.get(2))); points[3] = transform.transform(new PointND(lowerCorner.get(0), upperCorner.get(1), upperCorner.get(2))); points[4] = transform.transform(new PointND(lowerCorner.get(0), lowerCorner.get(1), lowerCorner.get(2))); points[5] = transform.transform(new PointND(upperCorner.get(0), lowerCorner.get(1), lowerCorner.get(2))); points[6] = transform.transform(new PointND(upperCorner.get(0), upperCorner.get(1), lowerCorner.get(2))); points[7] = transform.transform(new PointND(lowerCorner.get(0), upperCorner.get(1), lowerCorner.get(2))); float[] curve = new float[elementCountU*elementCountV*3]; /* for (int i = 0; i < pointsOnCurve; i++) { for (int j = 0; j < numberOfCurves; j++){ if (i%(extraValuesPerEdge+1) == 0) { //regular corner point curve[(j*pointsOnCurve+i)*3] = (float) points[i%(extraValuesPerEdge)].get(0); curve[(j*pointsOnCurve+i)*3+1] = (float) points[i%4].get(1); } curve[(j*pointsOnCurve+i)*3] = (float) points[i%4].get(0); curve[(j*pointsOnCurve+i)*3+1] = (float) points[i%4].get(1); //curve[(j*pointsOnCurve+i)*3+2] = (float) (points[i%4].get(2)-points[]; //curve[i] = (new PointND(((min.get(0)+ max.get(0))/2)+0.5*(max.get(0)-min.get(0))*Math.cos(angle), ((min.get(1)+ max.get(1))/2)+0.5*(max.get(1)-min.get(1))*Math.sin(angle), max.get(2))); //lowerCurve[i] = (new PointND(((min.get(0)+ max.get(0))/2)+0.5*(max.get(0)-min.get(0))*Math.cos(angle), ((min.get(1)+ max.get(1))/2)+0.5*(max.get(1)-min.get(1))*Math.sin(angle), min.get(2))); } } */ int k = 0; for (int i = 0; i < pointsOnCurve; i++) { for (int j = 0; j < numberOfCurves; j++){ k = (4*i)/pointsOnCurve; curve[(i*numberOfCurves+j)*3] = (float) points[k%4].get(0); curve[(i*numberOfCurves+j)*3+1] = (float) points[k%4].get(1); curve[(i*numberOfCurves+j)*3+2] = (float) (points[k%4].get(2) - (points[k%4].get(2)-points[k%4+4].get(2)) * ((float) j/(numberOfCurves-1))); //curve[i] = (new PointND(((min.get(0)+ max.get(0))/2)+0.5*(max.get(0)-min.get(0))*Math.cos(angle), ((min.get(1)+ max.get(1))/2)+0.5*(max.get(1)-min.get(1))*Math.sin(angle), max.get(2))); //lowerCurve[i] = (new PointND(((min.get(0)+ max.get(0))/2)+0.5*(max.get(0)-min.get(0))*Math.cos(angle), ((min.get(1)+ max.get(1))/2)+0.5*(max.get(1)-min.get(1))*Math.sin(angle), min.get(2))); } } return curve; } public PointND interpolateU(double u, PointND [] points, int offset){ PointND first; PointND second; if (u <= 0.25){ first = points[0+offset]; second = points[1+offset]; } else if (u <= 0.5){ u -= 0.25; first = points[1+offset]; second = points[2+offset]; } else if (u <= 0.75){ u -= 0.5; first = points[2+offset]; second = points[3+offset]; } else { u -= 0.75; first = points[3+offset]; second = points[0+offset]; } return interpolate(first, second, u*4.0); } public PointND interpolate(PointND first, PointND second, double factor){ SimpleVector resultVector = first.getAbstractVector().multipliedBy(1.0-factor); resultVector.add(second.getAbstractVector().multipliedBy(factor)); return new PointND(resultVector); } @Override public float[] getRasterPoints(int elementCountU, int elementCountV) { PointND[] points = new PointND[8]; points[0] = transform.transform(new PointND(lowerCorner.get(0), lowerCorner.get(1), upperCorner.get(2))); points[1] = transform.transform(new PointND(upperCorner.get(0), lowerCorner.get(1), upperCorner.get(2))); points[2] = transform.transform(new PointND(upperCorner.get(0), upperCorner.get(1), upperCorner.get(2))); points[3] = transform.transform(new PointND(lowerCorner.get(0), upperCorner.get(1), upperCorner.get(2))); points[4] = transform.transform(new PointND(lowerCorner.get(0), lowerCorner.get(1), lowerCorner.get(2))); points[5] = transform.transform(new PointND(upperCorner.get(0), lowerCorner.get(1), lowerCorner.get(2))); points[6] = transform.transform(new PointND(upperCorner.get(0), upperCorner.get(1), lowerCorner.get(2))); points[7] = transform.transform(new PointND(lowerCorner.get(0), upperCorner.get(1), lowerCorner.get(2))); float[] curve = new float[elementCountU*elementCountV*3]; for (int j = 0; j < elementCountV; j++){ double v = ((double)j)/(elementCountV-1); for (int i = 0; i < elementCountU; i++) { double u = ((double)i)/(elementCountU); PointND top = interpolateU(u, points, 0); PointND bottom = interpolateU(u, points, 4); PointND gridPoint = interpolate(bottom, top, v); curve[(j*elementCountU+i)*3] = (float) gridPoint.get(0); curve[(j*elementCountU+i)*3+1] = (float) gridPoint.get(1); curve[(j*elementCountU+i)*3+2] = (float) gridPoint.get(2); } } return curve; } /*public float[] getRasterPointsNew(int elementCountU, int elementCountV){ int pointsOnCurve = elementCountU; int numberOfCurves = elementCountV; int extraValuesPerEdge = (elementCountU-4)/4; float[] curve = new float[elementCountU*elementCountV*3]; for (int j = 0; j < numberOfCurves; j++) { for (int i = 0; i < pointsOnCurve; i++){ for (int k = 0; k < (int)pointsOnCurve/4; k++){ curve[(j*pointsOnCurve+i+k)*3] = (float) (lowerCorner.get(0) + i*(upperCorner.get(0)-lowerCorner.get(0))/(pointsOnCurve-1)); } curve[(j*pointsOnCurve+i+k)*3+1] = (float) (lowerCorner.get(1) + i*(upperCorner.get(1)-lowerCorner.get(1))/(pointsOnCurve-1)); curve[(j*pointsOnCurve+i+k)*3+2] = (float) (lowerCorner.get(2) + j*(upperCorner.get(2)-lowerCorner.get(2))/(numberOfCurves-1)); } } return curve; }*/ @Override public AbstractShape clone() { return new Box(this); } /** * @return the lowerCorner */ public PointND getLowerCorner() { return lowerCorner; } /** * @param lowerCorner the lowerCorner to set */ public void setLowerCorner(PointND lowerCorner) { this.lowerCorner = lowerCorner; } /** * @return the upperCorner */ public PointND getUpperCorner() { return upperCorner; } /** * @param upperCorner the upperCorner to set */ public void setUpperCorner(PointND upperCorner) { this.upperCorner = upperCorner; } /** * @param principalAxis the principalAxis to set */ public void setPrincipalAxis(Axis principalAxis) { this.principalAxis = principalAxis; } public ArrayList<PointND> getPointCloud(int u, int v){ float[] rasterPoints = this.getRasterPoints(u, v); //PointND[] points = box.getRasterPoints(256); ArrayList<PointND> pointsList= new ArrayList<PointND>(); for (int i= 0; i < rasterPoints.length/3; i++){ PointND point = new PointND(rasterPoints[(i*3)],rasterPoints[(i*3)+1],rasterPoints[(i*3)+2]); // PointND point = new PointND(points[i].get(0),points[i].get(1),points[i].get(2)); pointsList.add(point); } return pointsList; } /* public static void main(String [] args){ Box box = new Box (1,1,1); ArrayList<PointND> pointsList=box.getPointCloud(40, 10); PointCloudViewer pcv = new PointCloudViewer("Box Visualization", pointsList); pcv.setVisible(true); }*/ } /* * Copyright (C) 2010-2014 Andreas Maier, Rotimi X Ojo, Zijia Guo * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */