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.transforms.AffineTransform;
import edu.stanford.rsl.conrad.geometry.transforms.Translation;
import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
import edu.stanford.rsl.conrad.utils.CONRAD;
/**
* Creates a Pyramid
*/
public class Pyramid extends SimpleSurface {
/**
*
*/
private static final long serialVersionUID = -3684428666704786034L;
private Axis principalAxis = new Axis(new SimpleVector(0,0,1));
public Pyramid() {
// TODO Auto-generated constructor stub
}
/**
* @param dx
* @param dy
* @param dz
*/
public Pyramid(double dx, double dy, double dz) {
this();
init(dx, dy, dz, null);
}
/**
* @param dx
* @param dy
* @param dz
* @param transform
*/
public Pyramid(double dx, double dy, double dz,AffineTransform transform){
this();
init(dx, dy, dz, transform);
}
/**
* @param p
*/
public Pyramid(Pyramid p) {
super(p);
// TODO Auto-generated constructor stub
principalAxis = (p.principalAxis != null) ? p.principalAxis.clone() : null;
}
public void init(double dx, double dy, double dz, AffineTransform transform){
if(transform == null){
SimpleMatrix mat = new SimpleMatrix(3,3);
mat.identity();
this.transform = new AffineTransform(mat, new SimpleVector(3));
}
this.transform = new Translation(0, 0, 0);
this.min = new PointND(-dx, -dy, -dz);
//this.min = this.transform.transform(this.min);
this.max = new PointND(dx, dy, 0);
//this.max = this.transform.transform(this.max);
}
@Override
public boolean isBounded() {
// TODO Auto-generated method stub
return true;
}
@Override
public Axis getPrincipalAxis() {
// TODO Auto-generated method stub
return null;
}
@Override
public AbstractShape tessellate(double accuracy) {
// TODO Auto-generated method stub
return null;
}
@Override
public AbstractShape clone() {
// TODO Auto-generated method stub
return null;
}
public PointND interpolatePoint(double factor, PointND[] point){
PointND first;
PointND second;
if (factor < 0.25){
first = point[0];
second = point[1];
}else if (factor < 0.5){
first = point[1];
second = point[2];
factor -= 0.25;
}else if (factor < 0.75){
first = point[2];
second = point[3];
factor -= 0.5;
}else {
first = point[3];
second = point[0];
factor -= 0.75;
}
return interpolation(first, second, 4.0*factor);
}
public PointND interpolation(PointND first, PointND second, double factor){
SimpleVector resultVector = first.getAbstractVector().multipliedBy(1.0 - factor);
resultVector.add(second.getAbstractVector().multipliedBy(factor));
return new PointND(resultVector);
}
public float[] getRasterPoints(int elementCountU, int elementCountV){
if (elementCountV < 2 || elementCountV < 3){
System.out.println("Error! elementCounts too small.");
return null;
}
PointND[] point = new PointND[4];
int numberOfCurves = elementCountU;
int pointsOnCurve = elementCountV;
float[] curve = new float[numberOfCurves*pointsOnCurve*3];
double range = (max.get(2) - min.get(2));
double a = 0.5*(max.get(0) - min.get(0))/ range;
double b = 0.5*(max.get(1) - min.get(1))/ range;
double height;
for (int j = 0; j < numberOfCurves; j++){
//double factor = ((double)j/(numberOfCurves - 1));
height = j*(max.get(2) - min.get(2))/(numberOfCurves - 1);
//double coorZ = (double)min.get(2) + factor;
double coorZ = (min.get(2) + height)/range;
for (int i = 0; i < pointsOnCurve; i++){
double v = ((double)i/(pointsOnCurve));
point[0] = transform.transform(new PointND(min.get(0)*a*Math.abs(coorZ), min.get(1)*b*Math.abs(coorZ), coorZ*range));
point[1] = transform.transform(new PointND(max.get(0)*a*Math.abs(coorZ), min.get(1)*b*Math.abs(coorZ), coorZ*range));
point[2] = transform.transform(new PointND(max.get(0)*a*Math.abs(coorZ), max.get(1)*b*Math.abs(coorZ), coorZ*range));
point[3] = transform.transform(new PointND(min.get(0)*a*Math.abs(coorZ), max.get(1)*b*Math.abs(coorZ), coorZ*range));
PointND rasterPointV = interpolatePoint(v, point);
curve[(i*numberOfCurves+j)*3] = (float)rasterPointV.get(0);
curve[(i*numberOfCurves+j)*3+1] = (float)rasterPointV.get(1);
curve[(i*numberOfCurves+j)*3+2] = (float)(coorZ*range);
}
}
return curve;
}
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){
Pyramid pyramid = new Pyramid(10,10,10);
if (pyramid != null) {
float[] rasterPoints = pyramid.getRasterPoints(3, 16);
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);
}
PointCloudViewer pcv = new PointCloudViewer("Pyramid Visualization", pointsList);
pcv.setVisible(true);
}
}
@Override
public ArrayList<PointND> getHits(AbstractCurve other) {
// TODO Auto-generated method stub
//throw new RuntimeException("Not implemented yet");
//return null;
StraightLine buff = (StraightLine) other;
StraightLine line = new StraightLine(buff.getPoint().clone(), buff.getDirection().clone());
line.applyTransform(transform.inverse());
ArrayList<PointND> hitsOnShape = General.intersectRayWithCuboid(line, min, max);
return getCorrectedHits(hitsOnShape);
}
@Override
public boolean isMember(PointND point, boolean pointTransformed) {
// TODO Auto-generated method stub
//throw new RuntimeException("Not implemented yet");
//return false;
// 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(double u, double v) {
// TODO Auto-generated method stub
throw new RuntimeException("Not implemented yet");
//return null;
}
@Override
public int getDimension() {
return 3;
}
@Override
public PointND[] getRasterPoints(int number) {
// TODO Auto-generated method stub
//getRasterPoints((int)Math.sqrt(number), (int)Math.sqrt(number));
throw new RuntimeException("Not implemented yet");
}
}
/*
* Copyright (C) 2010-2014 Zijia Guo, Andreas Maier
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/