package org.jzy3d.plot3d.builder.concrete;
import java.util.ArrayList;
import java.util.List;
import org.jzy3d.colors.Color;
import org.jzy3d.colors.ColorMapper;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.plot3d.primitives.AbstractComposite;
import org.jzy3d.plot3d.primitives.AbstractDrawable;
import org.jzy3d.plot3d.primitives.Point;
import org.jzy3d.plot3d.primitives.Polygon;
import org.jzy3d.plot3d.primitives.Shape;
public class RingTessellator extends OrthonormalTessellator{
public RingTessellator(float ringMin, float ringMax, ColorMapper cmap, Color factor){
this.ringMin = ringMin;
this.ringMax = ringMax;
this.cmap = cmap;
this.factor = factor;
}
@SuppressWarnings("unused")
private RingTessellator(){
throw new RuntimeException("Forbidden constructor!");
}
@Override
public AbstractComposite build(float[] x, float[] y, float[] z) {
setData(x, y, z);
Shape s = new Shape();
s.add(getInterpolatedRingPolygons());
return s;
}
/**************************************************************************************/
/** Load data standing on an orthonormal grid.
*
* Each input point (i.e. the association of x[i], y[j], z[i][j]) will be
* represented by a polygon centered on this point. The default coordinates
* of this polygon will be:
*
* - x[i-1], y[j+1], z[i-1][j+1]
*
- x[i-1], y[j-1], z[i-1][j-1]
*
- x[i+1], y[j-1], z[i+1][j-1]
*
- x[i+1], y[j+1], z[i+1][j+1]
*
* There are thus three types of polygons:
*
* - those that stand completely inside the ringMin and ringMax radius and
* that have the previous coordinates.
*
- those that stand completely outside the ringMin and ringMax radius and
* that won't be added to the list of polygons.
*
- those that have some points in and some points out of the ringMin and
* ringMax radius. These polygons are recomputed so that "out" points are replaced
* by two points that make the smooth contour. According to the number of "out"
* points, the modified polygon will gather 3, 4, or 5 points.
*
* As a consequence, it is suggested to provide data ranging outside of ringMin
* and ringMax, in order to be sure to have a perfect round surface.
*
* @param ringMin the minimum radius of this ring.
* @param ringMax the maximum radius of this ring.
* @param colorFactor a weighting factor for the color returned by the Colormap.
*/
public List getInterpolatedRingPolygons(){
List polygons = new ArrayList();
boolean[] isIn;
for(int xi=0; xi= minRadius;
isIn[1] = !Float.isNaN(p[1].xyz.z) && radius[1] < maxRadius && radius[1] >= minRadius;
isIn[2] = !Float.isNaN(p[2].xyz.z) && radius[2] < maxRadius && radius[2] >= minRadius;
isIn[3] = !Float.isNaN(p[3].xyz.z) && radius[3] < maxRadius && radius[3] >= minRadius;
return isIn;
}
protected float radius2d(Point p){
return (float)Math.sqrt(p.xyz.x*p.xyz.x + p.xyz.y*p.xyz.y);
}
/**
* Return a point that is the intersection between a segment and a circle
* @throws ArithmeticException if points do not stand on an squared (orthonormal) grid.
*/
private Point findPoint(Point p1, Point p2, float ringRadius){
// We know that the seeked point is on a horizontal or vertial line
float x3, y3, z3;
float w1, w2;
double alpha;
// We know x3 and radius and seek y3, using intermediate alpha
if(p1.xyz.x==p2.xyz.x){
x3 = p1.xyz.x;
alpha = Math.acos(x3/ringRadius);
if(p1.xyz.y<0 && p2.xyz.y<0)
y3 = -(float)Math.sin(alpha)*ringRadius;
else if(p1.xyz.y>0 && p2.xyz.y>0)
y3 = (float)Math.sin(alpha)*ringRadius;
else if(p1.xyz.y==-p2.xyz.y)
y3 = 0; // ne peut pas arriver
else
throw new ArithmeticException(("no alignement between p1(" +p1.xyz.x + "," + p1.xyz.y + "," + p1.xyz.z + ") and p2(" +p2.xyz.x + "," + p2.xyz.y + "," + p2.xyz.z + ")"));
// and now get z3
if(!Float.isNaN(p1.xyz.z) && Float.isNaN(p2.xyz.z))
z3 = p1.xyz.z;
else if(Float.isNaN(p1.xyz.z) && !Float.isNaN(p2.xyz.z))
z3 = p2.xyz.z;
else if(!Float.isNaN(p1.xyz.z) && !Float.isNaN(p2.xyz.z)){
w2 = (float)( Math.sqrt( (x3 -p1.xyz.x)*(x3 -p1.xyz.x) + (y3 -p1.xyz.y)*(y3 -p1.xyz.y) )
/ Math.sqrt( (p2.xyz.x-p1.xyz.x)*(p2.xyz.x-p1.xyz.x) + (p2.xyz.y-p1.xyz.y)*(p2.xyz.y-p1.xyz.y) ));
w1 = 1-w2;
z3 = w1*p1.xyz.z+w2*p2.xyz.z;
}
else
throw new ArithmeticException(("can't compute z3 with p1(" +p1.xyz.x + "," + p1.xyz.y + ") and p2(" +p2.xyz.x + "," + p2.xyz.y + ")"));
}
// We know y3 and radius and seek x3, using intermediate alpha
else if(p1.xyz.y==p2.xyz.y){
y3 = p1.xyz.y;
alpha = Math.asin(y3/ringRadius);
if(p1.xyz.x<0 && p2.xyz.x<0)
x3 = -(float)Math.cos(alpha)*ringRadius;
else if(p1.xyz.x>0 && p2.xyz.x>0)
x3 = (float)Math.cos(alpha)*ringRadius;
else if(p1.xyz.x==-p2.xyz.x)
x3 = 0; // ne peut pas arriver
else
throw new ArithmeticException(("no alignement between p1(" +p1.xyz.x + "," + p1.xyz.y + "," + p1.xyz.z + ") and p2(" +p2.xyz.x + "," + p2.xyz.y + "," + p2.xyz.z + ")"));
// and now get z3
if(!Float.isNaN(p1.xyz.z) && Float.isNaN(p2.xyz.z))
z3 = p1.xyz.z;
else if(Float.isNaN(p1.xyz.z) && !Float.isNaN(p2.xyz.z))
z3 = p2.xyz.z;
else if(!Float.isNaN(p1.xyz.z) && !Float.isNaN(p2.xyz.z)){
w2 = (float)( Math.sqrt( (x3 -p1.xyz.x)*(x3 -p1.xyz.x) + (y3 -p1.xyz.y)*(y3 -p1.xyz.y) )
/ Math.sqrt( (p2.xyz.x-p1.xyz.x)*(p2.xyz.x-p1.xyz.x) + (p2.xyz.y-p1.xyz.y)*(p2.xyz.y-p1.xyz.y) ));
w1 = 1-w2;
z3 = w1*p1.xyz.z+w2*p2.xyz.z;
}
else
throw new ArithmeticException(("can't compute z3 with p1(" +p1.xyz.x + "," + p1.xyz.y + ") and p2(" +p2.xyz.x + "," + p2.xyz.y + ")"));
}
else
throw new ArithmeticException(("no alignement between p1(" +p1.xyz.x + "," + p1.xyz.y + ") and p2(" +p2.xyz.x + "," + p2.xyz.y + ")"));
return new Point(new Coord3d(x3, y3, z3));
}
/************************************************************************************************/
protected float ringMin;
protected float ringMax;
protected ColorMapper cmap;
protected Color factor;
}
Ads help maintain this website.