Commit a5912a7b authored by Alina Hinzmann's avatar Alina Hinzmann

- extracted the alignment of the labels (calculation of a trafomatrix

and anchorpoint) to a seperate class
- cleaned up update() method in visualization by creating inner class
Label and others
- cleaned up the rest and the comments accordingly
parent 05fc4904
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.math.Matrix;
import de.jreality.util.Rectangle3D;
import de.jtem.halfedge.Edge;
import de.jtem.halfedge.Face;
import de.jtem.halfedge.Node;
import de.jtem.halfedge.Vertex;
import de.jtem.halfedgetools.adapter.AdapterSet;
public abstract class AbstractLabelPosition implements LabelPosition {
@Override
public Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Node<?, ?, ?> n, AdapterSet as, boolean labelFlip) {
if(Vertex.class.isAssignableFrom(n.getClass())) {
return getTransformationMatrix(labelBoundingBox, (Vertex<?,?,?>)n, as, labelFlip);
} else if(Edge.class.isAssignableFrom(n.getClass())) {
return getTransformationMatrix(labelBoundingBox, (Edge<?,?,?>)n, as, labelFlip);
} else if(Face.class.isAssignableFrom(n.getClass())) {
return getTransformationMatrix(labelBoundingBox, (Face<?,?,?>)n, as, labelFlip);
}
return null;
}
@Override
public abstract Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Vertex<?, ?, ?> v, AdapterSet as, boolean labelFlip);
@Override
public abstract Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Edge<?, ?, ?> e, AdapterSet as, boolean labelFlip);
@Override
public abstract Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Face<?, ?, ?> f, AdapterSet as, boolean labelFlip);
}
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.math.Matrix;
import de.jreality.util.Rectangle3D;
import de.jtem.halfedge.Edge;
import de.jtem.halfedge.Face;
import de.jtem.halfedge.Node;
import de.jtem.halfedge.Vertex;
import de.jtem.halfedgetools.adapter.AdapterSet;
public interface LabelPosition {
public Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Node<?,?,?> n, AdapterSet as, boolean labelFlip);
public Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Vertex<?,?,?> v, AdapterSet as, boolean labelFlip);
public Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Edge<?, ?, ?> e, AdapterSet as, boolean labelFlip);
public Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Face<?,?,?> f, AdapterSet as, boolean labelFlip);
}
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.math.Matrix;
import de.jreality.math.MatrixBuilder;
import de.jreality.math.Rn;
import de.jreality.util.Rectangle3D;
import de.jtem.halfedge.Edge;
import de.jtem.halfedge.Face;
import de.jtem.halfedge.Vertex;
import de.jtem.halfedgetools.adapter.AdapterSet;
import de.jtem.halfedgetools.adapter.type.Normal;
import de.jtem.halfedgetools.adapter.type.generic.BaryCenter3d;
import de.jtem.halfedgetools.adapter.type.generic.EdgeVector;
import de.jtem.halfedgetools.adapter.type.generic.Position3d;
public class ZUpLabelPosition extends AbstractLabelPosition {
private double[]
upDirection = new double[]{0,0,1};
public String toString(){
return "Z up";
}
@Override
public Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Vertex<?,?,?> v, AdapterSet as, boolean labelFlip) {
double[] labelbbCenter = labelBoundingBox.getCenter();
double[] center = as.getD(Position3d.class, v);
double[] normal = as.getD(Normal.class, v);
Matrix M = MatrixBuilder.euclidean() //generate the trafo-matrix, done/to read from bottom to top
.translate(center) //translate the label to the vertex position
.rotateFromTo(upDirection, normal) //new double[]{0, 0,1}, normal) //rotate the updirection to the vertexnormal
.getMatrix();
if(labelFlip){
M.multiplyOnRight(MatrixBuilder.euclidean().rotateY(Math.PI).getMatrix()); //if the label shall be flipped: rotate it 180degree around central axis of its boundingbox (since translated in the origin this is the y-axis)
}
M.multiplyOnRight(MatrixBuilder.euclidean().translate(Rn.negate(null, labelbbCenter)).getMatrix()); //translate the labels center to the origin
return M;
}
@Override
public Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Edge<?, ?, ?> e, AdapterSet as, boolean labelFlip) {
double[] labelbbCenter = labelBoundingBox.getCenter();
double[] edgeVector = as.getD(EdgeVector.class, e); //get edge as vector
double[][] localCoordinateSystem = getFacesCoordinateSystem(e.getLeftFace(),as);
double[] anchorPoint = getAnchorPoint(edgeVector, localCoordinateSystem, labelBoundingBox);
double[] edgeCenter = as.getD(BaryCenter3d.class, e);
double[] faceCenter = as.getD(BaryCenter3d.class, e.getLeftFace());
Rn.linearCombination(edgeCenter, 0.95, edgeCenter, 0.05, faceCenter);
Matrix M = getTransformationMatrix(localCoordinateSystem, edgeCenter);
M.multiplyOnRight(MatrixBuilder.euclidean().translate(Rn.negate(null, anchorPoint)).getMatrix());
if(labelFlip){
M.multiplyOnRight(MatrixBuilder.euclidean().translate(labelbbCenter).getMatrix());
M.multiplyOnRight(MatrixBuilder.euclidean().rotateY(Math.PI).getMatrix());
M.multiplyOnRight(MatrixBuilder.euclidean().translate(Rn.negate(null, labelbbCenter)).getMatrix());
}
return M;
}
@Override
public Matrix getTransformationMatrix(Rectangle3D labelBoundingBox, Face<?, ?, ?> f, AdapterSet as, boolean labelFlip) {
double[] labelbbCenter = labelBoundingBox.getCenter();
double[] center = as.getD(BaryCenter3d.class, f);
double[][] localCoordinateSystem = getFacesCoordinateSystem(f,as);
Matrix M = getTransformationMatrix(localCoordinateSystem, center);
if(labelFlip){
M.multiplyOnRight(MatrixBuilder.euclidean().rotateY(Math.PI).getMatrix()); //if the label shall be flipped: rotate it 180degree around central axis of its boundingbox (since translated in the origin this is the y-axis)
}
M.multiplyOnRight(MatrixBuilder.euclidean().translate(Rn.negate(null, labelbbCenter)).getMatrix());
return M;
}
/**
* Calculates a 3-dim coordinate system as double[][] on the basis of a given face.
* @param f the face for which the coordinate system is calculated
* @param as the adapterset
* @return facesCoordinateSystem where
* facesCoordinateSystem[2] is the normal of the face
* facesCoordinateSystem[1] is the normalized projection of the upDirection onto the normals complement
* facesCoordinateSystem[0] is their crossproduct
*
* If the normal is almost the same as updirection and therefore facesCoordinateSystem[1] almost zero, then {0, 1,0} is projected as alternate upDirection.
*/
private double[][] getFacesCoordinateSystem(Face<?,?,?> f, AdapterSet as) {
// double[] upDirection = new double[]{0,0,1};
double[][] facesCoordinateSystem = new double[3][3];
facesCoordinateSystem[2] = as.getD(Normal.class, f); //the faces normal
facesCoordinateSystem[1] = Rn.projectOntoComplement(null, upDirection, facesCoordinateSystem[2]); // projection of the upDirection onto the normals complement
if(Rn.euclideanNorm(facesCoordinateSystem[1]) < 1E-6){ //if the normal is almost the same as updirection -> facesCoordinateSystem[1] almost zero
facesCoordinateSystem[1] = Rn.projectOntoComplement(null, new double[]{0, 1,0}, facesCoordinateSystem[2]); //then choose {0, 1,0} as alternate upDirection for projecting
}
Rn.normalize(facesCoordinateSystem[1], facesCoordinateSystem[1]);
facesCoordinateSystem[0] = Rn.crossProduct(null, facesCoordinateSystem[1], facesCoordinateSystem[2]);
return facesCoordinateSystem;
}
/**
* Sets up the trafo-matrix we need for placing the labels.
* @param faceCoordinateSystem giving the desired directions for alignment of the label
* @param basePoint the targetpoint the label will be translated to
* @return the transformation matrix
*/
private Matrix getTransformationMatrix(double[][] faceCoordinateSystem, double[]basePoint) {
Matrix matrix = new Matrix(
faceCoordinateSystem[0][0], faceCoordinateSystem[1][0], faceCoordinateSystem[2][0], basePoint[0],
faceCoordinateSystem[0][1], faceCoordinateSystem[1][1], faceCoordinateSystem[2][1], basePoint[1],
faceCoordinateSystem[0][2], faceCoordinateSystem[1][2], faceCoordinateSystem[2][2], basePoint[2],
0,0,0,1
);
return matrix;
}
/**
* Computes which corner point of the labels boundingbox should be used as anchorpoint of the label on an edge.
* @param edge the edge the label shall be attached to, given as vector
* @param localCoordinateSystem the coordinate system given by the incident face to its left
* @param bb a rectangle representing the boundingbox of the label
* @return anchorPoint the corner point of the labels boundingbox which suits best as anchorpoint for a label
*/
private double[] getAnchorPoint(double[] edge, double[][] localCoordinateSystem, Rectangle3D bb) {
//Calculate the scalar product of the edge with the x- and y-directions of the local coordinate system, this gives how the edge-vector is directed within this 2D-xy-coord.system.
//E.g. if <e,x-axis> > 0 and <e,y-axis> < 0 the edge is located in the upper left corner. Then the anchorpoint should be the upper right point of the labels bb.
//We figured out: Turning the edge clockwise by 90° always gives the direction of the bb-corner one should pick as anchorpoint,
//this turning is a multiplication by ({0, -1}; {1, 0}), we apply this to our coord.system to directly get out the signs for the anchorpoint: ({0, -1}; {1, 0})*{x,y} = {y, -x}
double signX = Rn.innerProduct(edge, localCoordinateSystem[1]); //therefore <e,x-axis> is interpreted as <e,y-axis>
double signY = -Rn.innerProduct(edge, localCoordinateSystem[0]); // and <e,y-axis> as -<e,x-axis>
double[] anchorPoint = new double[3];
anchorPoint[0] = (signX>0)?bb.getMaxX():bb.getMinX(); //if the edge is on the upper half of the xy-coord.system chose MaxX of bb as x-coordinate for the anchorpoint, otherwise MinX
anchorPoint[1] = (signY>0)?bb.getMaxY():bb.getMinY(); //if the edge is on the right half of the xy-coord.system chose MaxY of bb as y-coordinate for the anchorpoint, otherwise MinY
if(Math.abs(signX) < 1E-6) { //if the edge is aligned with the x-axis
anchorPoint[0] = bb.getCenter()[0]; //the anchorpoint should be in the middle of the upper or lower boundingbox-edge
}
if(Math.abs(signY) < 1E-6) { //if the edge is aligned with the y-axis
anchorPoint[1] = bb.getCenter()[1]; //the anchorpoint should be in the middle of the left- or righthand boundingbox-edge
}
anchorPoint[2] = bb.getMinZ(); //and we always take the min in z-direction, such that a 3D-label-boundingbox would stick out to the geometry's outside
return anchorPoint;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment