...
 
Commits (8)
No preview for this file type
......@@ -8,236 +8,264 @@ import de.jtem.halfedge.Vertex;
public class FunctionalUtils {
private static final double
EPS = 1E-5;
public static <
V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
HDS extends HalfEdgeDataStructure<V, E, F>
> void calculateFDGradient(HDS hds, Functional<V, E, F> app, int dim, DomainValue x, Gradient G) {
calculateFDGradient(hds, app, dim, x, G, EPS);
}
public static <
V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
HDS extends HalfEdgeDataStructure<V, E, F>
> void calculateFDGradient(HDS hds, Functional<V, E, F> app, int dim, DomainValue x, Gradient G, double eps) {
MyEnergy E = new MyEnergy();
for (int i = 0; i < dim; i++){
double xi = x.get(i);
x.set(i, xi + eps);
app.evaluate(hds, x, E, null, null);
double f1 = E.get();
x.set(i, xi - eps);
app.evaluate(hds, x, E, null, null);
double f2 = E.get();
double fdGrad = (f1 - f2) / (2 * eps);
G.set(i, fdGrad);
x.set(i, xi);
}
}
public static <
V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
HDS extends HalfEdgeDataStructure<V, E, F>
> void calculateFDHessian(HDS hds, Functional<V, E, F> app, int dim, DomainValue x, Hessian H) {
calculateFDHessian(hds, app, dim, x, H, EPS);
}
public static <
V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
HDS extends HalfEdgeDataStructure<V, E, F>
> void calculateFDHessian(HDS hds, Functional<V, E, F> app, int dim, DomainValue x, Hessian H, double eps) {
MyEnergy E = new MyEnergy();
app.evaluate(hds, x, E, null, null);
double y = E.get();
for (int i = 0; i < dim; i++){
for (int j = 0; j < dim; j++){
double fdHessian = 0.0;
double xi = x.get(i);
double xj = x.get(j);
if (i == j) {
x.set(i, xi + eps);
app.evaluate(hds, x, E, null, null);
double iPlus = E.get();
x.set(i, xi + 2*eps);
app.evaluate(hds, x, E, null, null);
double i2Plus = E.get();
x.set(i, xi - eps);
app.evaluate(hds, x, E, null, null);
double iMinus = E.get();
x.set(i, xi - 2*eps);
app.evaluate(hds, x, E, null, null);
double i2Minus = E.get();
fdHessian = (-i2Plus/eps + 16*iPlus/eps - 30*y/eps + 16*iMinus/eps - i2Minus/eps) / (12 * eps);
} else {
x.set(i, xi + eps);
x.set(j, xj + eps);
app.evaluate(hds, x, E, null, null);
double iPlusjPlus = E.get();
x.set(i, xi + eps);
x.set(j, xj - eps);
app.evaluate(hds, x, E, null, null);
double iPlusjMinus = E.get();
x.set(i, xi - eps);
x.set(j, xj + eps);
app.evaluate(hds, x, E, null, null);
double iMinusjPlus = E.get();
x.set(i, xi - eps);
x.set(j, xj - eps);
app.evaluate(hds, x, E, null, null);
double iMinusjMinus = E.get();
fdHessian = (iPlusjPlus/eps - iPlusjMinus/eps - iMinusjPlus/eps + iMinusjMinus/eps) / (4 * eps);
}
x.set(i, xi);
x.set(j, xj);
H.set(i, j, fdHessian);
}
}
}
public static
<
V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>
>
double[] getPosition(V v, DomainValue x, double[] pos) {
if(pos == null) {
pos = new double[3];
}
pos[0] = x.get(v.getIndex() * 3 + 0);
pos[1] = x.get(v.getIndex() * 3 + 1);
pos[2] = x.get(v.getIndex() * 3 + 2);
return pos;
}
public static double[] getHomogPosition(DomainValue x, Vertex<?,?,?> v) {
double[] pos = new double[4];
pos[0] = x.get(v.getIndex() * 3 + 0);
pos[1] = x.get(v.getIndex() * 3 + 1);
pos[2] = x.get(v.getIndex() * 3 + 2);
pos[3] = 1.0;
return pos;
}
public static void addVectorToGradient(Gradient G, int startIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
G.add(startIndex+i, d[i]);
}
}
public static void subtractVectorFromGradient(Gradient G, int startIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
G.add(startIndex+i, -d[i]);
}
}
public static void addRowToHessian(Hessian H, int rowIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
H.add(rowIndex,i, d[i]);
}
}
public static void subtractRowFromHessian(Hessian H, int rowIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
H.add(rowIndex,i, -d[i]);
}
}
public static void addColumnToHessian(Hessian H, int colIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
H.add(i, colIndex, d[i]);
}
}
public static void subtractColumnFromHessian(Hessian H, int colIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
H.add(i, colIndex, -d[i]);
}
}
public static void addToDiagonal(Hessian H, double[] d) {
for (int i = 0; i < d.length; i++) {
H.add(i, i, d[i]);
}
}
public static double angle(double[] a, double[] b) {
return Math.atan2(Rn.euclideanNorm(Rn.crossProduct(null, a, b)),Rn.innerProduct(a, b));
}
// Calculate the angle at vj spanned by vi-vj and vk-vj
public static double angle(double[] vi, double[] vj, double[] vk) {
return angle(Rn.subtract(null, vi, vj), Rn.subtract(null, vk, vj) );
}
public static void angleGradient(
//input
double[] vi, double[] vj, double[] vk,
//output
double[] di, double[] dj, double[] dk) {
double[]
a = new double[3],
b = new double[3];
Rn.subtract(a, vi, vj);
Rn.subtract(b, vk, vj);
angleGradient(a,b,di);
angleGradient(b,a,dk);
Rn.times(dj, -1.0, Rn.add(null, di, dk) );
}
public static void angleGradient(
//input
double[] a, double[] b,
//output
double[] ta)
{
double al = Rn.euclideanNorm(a);
Rn.projectOntoComplement(ta, b, a);
Rn.normalize(ta, ta);
Rn.times(ta, - 1.0 / al, ta);
}
//M = v*w^t
public static void outerProduct(double[] v, double[] w, double[][] M)
{
for (int i = 0; i < M.length; i++) {
for (int j = 0; j < M[0].length; j++) {
M[i][j] = v[i] * w[j];
}
}
}
// M = v * v^t;
public static void outerProduct(double[] v, double[][] M) {
outerProduct(v,v,M);
}
public static double[] getVectorFromGradient(Gradient g, int i) {
return new double[]{g.get(i),g.get(i+1),g.get(i+2)};
}
public static void setVectorToGradient(Gradient g, int startIndex, double[] vg) {
for (int i = 0; i < vg.length; i++) {
g.set(startIndex+i, vg[i]);
}
}
public static void setVectorToDomainValue(DomainValue x, int startIndex, double[] vg) {
for (int i = 0; i < vg.length; i++) {
x.set(startIndex+i, vg[i]);
}
}
private static final double
EPS = 1E-5;
public static <
V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
HDS extends HalfEdgeDataStructure<V, E, F>
> void calculateFDGradient(HDS hds, Functional<V, E, F> app, int dim, DomainValue x, Gradient G) {
calculateFDGradient(hds, app, dim, x, G, EPS);
}
public static <
V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
HDS extends HalfEdgeDataStructure<V, E, F>
> void calculateFDGradient(HDS hds, Functional<V, E, F> app, int dim, DomainValue x, Gradient G, double eps) {
MyEnergy E = new MyEnergy();
for (int i = 0; i < dim; i++) {
double xi = x.get(i);
x.set(i, xi + eps);
app.evaluate(hds, x, E, null, null);
double f1 = E.get();
x.set(i, xi - eps);
app.evaluate(hds, x, E, null, null);
double f2 = E.get();
double fdGrad = (f1 - f2) / (2 * eps);
G.set(i, fdGrad);
x.set(i, xi);
}
}
public static <
V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
HDS extends HalfEdgeDataStructure<V, E, F>
> void calculateFDHessian(HDS hds, Functional<V, E, F> app, int dim, DomainValue x, Hessian H) {
calculateFDHessian(hds, app, dim, x, H, EPS);
}
public static <
V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
HDS extends HalfEdgeDataStructure<V, E, F>
> void calculateFDHessian(HDS hds, Functional<V, E, F> app, int dim, DomainValue x, Hessian H, double eps) {
MyEnergy E = new MyEnergy();
app.evaluate(hds, x, E, null, null);
double y = E.get();
for (int i = 0; i < dim; i++) {
for (int j = 0; j < dim; j++) {
double fdHessian = 0.0;
double xi = x.get(i);
double xj = x.get(j);
if (i == j) {
x.set(i, xi + eps);
app.evaluate(hds, x, E, null, null);
double iPlus = E.get();
x.set(i, xi + 2 * eps);
app.evaluate(hds, x, E, null, null);
double i2Plus = E.get();
x.set(i, xi - eps);
app.evaluate(hds, x, E, null, null);
double iMinus = E.get();
x.set(i, xi - 2 * eps);
app.evaluate(hds, x, E, null, null);
double i2Minus = E.get();
fdHessian = (-i2Plus / eps + 16 * iPlus / eps - 30 * y / eps + 16 * iMinus / eps - i2Minus / eps) / (12 * eps);
} else {
x.set(i, xi + eps);
x.set(j, xj + eps);
app.evaluate(hds, x, E, null, null);
double iPlusjPlus = E.get();
x.set(i, xi + eps);
x.set(j, xj - eps);
app.evaluate(hds, x, E, null, null);
double iPlusjMinus = E.get();
x.set(i, xi - eps);
x.set(j, xj + eps);
app.evaluate(hds, x, E, null, null);
double iMinusjPlus = E.get();
x.set(i, xi - eps);
x.set(j, xj - eps);
app.evaluate(hds, x, E, null, null);
double iMinusjMinus = E.get();
fdHessian = (iPlusjPlus / eps - iPlusjMinus / eps - iMinusjPlus / eps + iMinusjMinus / eps) / (4 * eps);
}
x.set(i, xi);
x.set(j, xj);
H.set(i, j, fdHessian);
}
}
}
public static <
V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>
>
double[] getPosition(V v, DomainValue x, double[] pos) {
if (pos == null) {
pos = new double[3];
}
pos[0] = x.get(v.getIndex() * 3 + 0);
pos[1] = x.get(v.getIndex() * 3 + 1);
pos[2] = x.get(v.getIndex() * 3 + 2);
return pos;
}
public static double[] getHomogPosition(DomainValue x, Vertex<?, ?, ?> v) {
double[] pos = new double[4];
pos[0] = x.get(v.getIndex() * 3 + 0);
pos[1] = x.get(v.getIndex() * 3 + 1);
pos[2] = x.get(v.getIndex() * 3 + 2);
pos[3] = 1.0;
return pos;
}
public static void addVectorToGradient(Gradient G, int startIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
G.add(startIndex + i, d[i]);
}
}
public static void addVectorToGradient(Gradient G, int[] indices, double[] d) {
for (int i = 0; i < d.length; i++) {
G.add(indices[i], d[i]);
}
}
public static void subtractVectorFromGradient(Gradient G, int startIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
G.add(startIndex + i, -d[i]);
}
}
public static void addRowToHessian(Hessian H, int rowIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
H.add(rowIndex, i, d[i]);
}
}
public static void subtractRowFromHessian(Hessian H, int rowIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
H.add(rowIndex, i, -d[i]);
}
}
public static void addColumnToHessian(Hessian H, int colIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
H.add(i, colIndex, d[i]);
}
}
public static void subtractColumnFromHessian(Hessian H, int colIndex, double[] d) {
for (int i = 0; i < d.length; i++) {
H.add(i, colIndex, -d[i]);
}
}
public static void addToDiagonal(Hessian H, double[] d) {
for (int i = 0; i < d.length; i++) {
H.add(i, i, d[i]);
}
}
public static double angle(double[] a, double[] b) {
return Math.atan2(Rn.euclideanNorm(Rn.crossProduct(null, a, b)), Rn.innerProduct(a, b));
}
// Calculate the angle at vj spanned by vi-vj and vk-vj
public static double angle(double[] vi, double[] vj, double[] vk) {
return angle(Rn.subtract(null, vi, vj), Rn.subtract(null, vk, vj));
}
public static void angleGradient(
//input
double[] vi, double[] vj, double[] vk,
//output
double[] di, double[] dj, double[] dk) {
double[]
a = new double[3],
b = new double[3];
Rn.subtract(a, vi, vj);
Rn.subtract(b, vk, vj);
angleGradient(a, b, di);
angleGradient(b, a, dk);
Rn.times(dj, -1.0, Rn.add(null, di, dk));
}
public static void angleGradient(
//input
double[] a, double[] b,
//output
double[] ta) {
double al = Rn.euclideanNorm(a);
Rn.projectOntoComplement(ta, b, a);
Rn.normalize(ta, ta);
Rn.times(ta, -1.0 / al, ta);
}
//M = v*w^t
public static void outerProduct(double[] v, double[] w, double[][] M) {
for (int i = 0; i < M.length; i++) {
for (int j = 0; j < M[0].length; j++) {
M[i][j] = v[i] * w[j];
}
}
}
// M = v * v^t;
public static void outerProduct(double[] v, double[][] M) {
outerProduct(v, v, M);
}
public static double[] getVectorFromGradient(Gradient g, int i) {
return new double[]{g.get(i), g.get(i + 1), g.get(i + 2)};
}
public static void setVectorToGradient(Gradient g, int startIndex, double[] vg) {
for (int i = 0; i < vg.length; i++) {
g.set(startIndex + i, vg[i]);
}
}
public static void setVectorToDomainValue(DomainValue x, int startIndex, double[] vg) {
for (int i = 0; i < vg.length; i++) {
x.set(startIndex + i, vg[i]);
}
}
public static double[] getRange(DomainValue x, int start, int size) {
double[] range = new double[size];
for (int i = 0; i < size; i++) {
range[i] = x.get(start + i);
}
return range;
}
public static double[] getRange(DomainValue x, int[] indices) {
double[] value = new double[indices.length];
for (int i = 0; i < indices.length; i++) {
value[i] = x.get(indices[i]);
}
return value;
}
public static void setRange(DomainValue x, int[] coordinateIndices, double[] coordinates) {
for(int i = 0; i < coordinateIndices.length; ++i) {
x.set(coordinateIndices[i], coordinates[i]);
}
}
}
......@@ -31,9 +31,6 @@ OF SUCH DAMAGE.
package de.jtem.halfedgetools.plugin;
import java.util.HashSet;
import java.util.Set;
import de.jreality.plugin.job.JobMonitorPlugin;
import de.jtem.halfedgetools.jreality.node.DefaultJREdge;
import de.jtem.halfedgetools.jreality.node.DefaultJRFace;
......@@ -42,78 +39,27 @@ import de.jtem.halfedgetools.jreality.node.DefaultJRVertex;
import de.jtem.halfedgetools.plugin.algorithm.generator.ConvexHullGenerator;
import de.jtem.halfedgetools.plugin.algorithm.generator.RandomEllipsoidGenerator;
import de.jtem.halfedgetools.plugin.algorithm.generator.RandomSphereGenerator;
import de.jtem.halfedgetools.plugin.algorithm.geometry.CopyVertexPositions;
import de.jtem.halfedgetools.plugin.algorithm.geometry.PasteVertexPositions;
import de.jtem.halfedgetools.plugin.algorithm.geometry.PerturbPlugin;
import de.jtem.halfedgetools.plugin.algorithm.geometry.ProjectPlugin;
import de.jtem.halfedgetools.plugin.algorithm.geometry.SwapPosTexPos;
import de.jtem.halfedgetools.plugin.algorithm.selection.BoundaryEdgeSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.BoundaryFaceSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.BoundaryVertexSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.ClearEdgeSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.ClearFaceSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.ClearSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.ClearVertexSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.ExportSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.ImportSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.InvertEdgeSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.InvertFaceSelection;
import de.jtem.halfedgetools.plugin.algorithm.selection.InvertVertexSelection;
import de.jtem.halfedgetools.plugin.algorithm.geometry.*;
import de.jtem.halfedgetools.plugin.algorithm.selection.*;
import de.jtem.halfedgetools.plugin.algorithm.simplification.GarlandHeckbertPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.CatmullClarkLinearPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.CatmullClarkPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.DooSabinPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.DualGraphSubdivisionPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.LoopLinearPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.LoopPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.MedialGraphLinearPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.QuadGraphLinearPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.Sqrt3LinearPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.Sqrt3Plugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.StellarLinearPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.TriangulateCutCornersPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.TriangulatePlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.DelaunayPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.EdgeCollapsePlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.EdgeFlipperPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.EdgeRemoverFillPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.EdgeRemoverPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.EdgeSplitterPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.FaceCollapserPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.FaceCreatePlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.FaceRemoverPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.FaceScalerPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.FaceSplitterPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.FillHolesPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.RemoveSelectedNodesPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.RemoveVertexFillPlugin;
import de.jtem.halfedgetools.plugin.algorithm.topology.VertexRemoverPlugin;
import de.jtem.halfedgetools.plugin.algorithm.subdivision.*;
import de.jtem.halfedgetools.plugin.algorithm.topology.*;
import de.jtem.halfedgetools.plugin.algorithm.vectorfield.CurvatureVectorFields;
import de.jtem.halfedgetools.plugin.data.VisualizationInterface;
import de.jtem.halfedgetools.plugin.data.source.FacePlanarityDataSource;
import de.jtem.halfedgetools.plugin.data.source.SceneGraphTestSource;
import de.jtem.halfedgetools.plugin.data.visualizer.ColoredBeadsVisualizer;
import de.jtem.halfedgetools.plugin.data.visualizer.HistogramVisualizer;
import de.jtem.halfedgetools.plugin.data.visualizer.Immersion3DVisualizer;
import de.jtem.halfedgetools.plugin.data.visualizer.LabelVisualizer;
import de.jtem.halfedgetools.plugin.data.visualizer.NodeColorVisualizer;
import de.jtem.halfedgetools.plugin.data.visualizer.SceneGraphNodeVisualizer;
import de.jtem.halfedgetools.plugin.data.visualizer.TableDataVisualizer;
import de.jtem.halfedgetools.plugin.data.visualizer.TextDumpVisualizer;
import de.jtem.halfedgetools.plugin.data.visualizer.VectorFieldVisualizer;
import de.jtem.halfedgetools.plugin.data.visualizer.*;
import de.jtem.halfedgetools.plugin.misc.RerunLastAlgorithmPlugin;
import de.jtem.halfedgetools.plugin.modes.EditMode;
import de.jtem.halfedgetools.plugin.modes.SelectionMode;
import de.jtem.halfedgetools.plugin.texturespace.TextureSpaceInterface;
import de.jtem.halfedgetools.plugin.visualizers.DirichletEnergyVisualizer;
import de.jtem.halfedgetools.plugin.visualizers.EdgeLengthVisualizer;
import de.jtem.halfedgetools.plugin.visualizers.FacePlanarityVisualizer;
import de.jtem.halfedgetools.plugin.visualizers.NodeIndexVisualizer;
import de.jtem.halfedgetools.plugin.visualizers.NormalVisualizer;
import de.jtem.halfedgetools.plugin.visualizers.*;
import de.jtem.halfedgetools.plugin.widget.ContextMenuWidget;
import de.jtem.halfedgetools.plugin.widget.ViewSwitchWidget;
import de.jtem.jrworkspace.plugin.Plugin;
import java.util.HashSet;
import java.util.Set;
public class HalfedgePluginFactory {
......@@ -218,7 +164,7 @@ public class HalfedgePluginFactory {
s.add(new Immersion3DVisualizer<DefaultJRVertex, DefaultJREdge, DefaultJRFace, DefaultJRHDS>());
s.add(new SceneGraphNodeVisualizer());
s.add(new FacePlanarityDataSource());
s.add(new SceneGraphTestSource());
s.add(new PointSetVisualizer());
return s;
}
......
......@@ -59,6 +59,7 @@ public abstract class AbstractDataVisualization implements DataVisualization, Co
public boolean isActive() {
return active;
}
@Override
public void setActive(boolean active) {
this.active = active;
......
package de.jtem.halfedgetools.plugin.data.visualizer;
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;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
abstract class AbstractCoordinateAndIndexFactory<COORDTYPE>
extends AbstractCoordinateFactory<COORDTYPE> {
double meanEdgeLength = 1.0;
List<int[]> edgeIndices = new LinkedList<>();
public AbstractCoordinateAndIndexFactory() { }
<V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
N extends Node<V, E, F>
>
void updateCoordinatesAndIndices(Collection<N> nodes, AdapterSet aSet) {
if (nodes.isEmpty()) {
return;
}
int numNullValue = updateVertexCoordinates(nodes, aSet);
updateEdgeIndices(nodes, aSet);
if (numNullValue > 0) {
System.err.println("Vector field adapter " + adapter + " has " + numNullValue + " null entries");
}
}
abstract <V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
N extends Node<V, E, F>
> void updateEdgeIndices(Collection<N> nodes, AdapterSet aSet);
public void setMeanEdgeLength(double meanEdgeLength) {
this.meanEdgeLength = meanEdgeLength;
}
}
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.math.Pn;
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.Adapter;
import de.jtem.halfedgetools.adapter.AdapterSet;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public abstract class AbstractCoordinateFactory<T> {
List<double[]> vertexCoordinates = new LinkedList<>();
Adapter<T> adapter;
public void setAdapter(Adapter adapter) {
this.adapter = adapter;
}
<V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>, N extends Node<V, E, F>>
double[] convertTo3DVector(double[] v) throws NullPointerException {
double[] vector3D = new double[3];
if (v.length == 3) {
System.arraycopy(v, 0, vector3D, 0, 3);
} else if (v.length == 4) {
vector3D = Pn.dehomogenize(null, v);
} else {
throw new RuntimeException(
"Adapter does not return vectors in 3-space or homogeneous 4-space.");
}
return vector3D;
}
public abstract <V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
N extends Node<V, E, F>
> int updateVertexCoordinates(Collection<N> nodes, AdapterSet aSet);
}
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.scene.Appearance;
import de.jreality.scene.SceneGraphComponent;
import de.jtem.halfedge.*;
import de.jtem.halfedgetools.adapter.Adapter;
import de.jtem.halfedgetools.plugin.HalfedgeLayer;
import de.jtem.halfedgetools.plugin.data.AbstractDataVisualization;
import de.jtem.halfedgetools.plugin.data.DataVisualizer;
import de.jtem.halfedgetools.selection.Selection;
import java.util.LinkedList;
import java.util.List;
import static de.jreality.shader.CommonAttributes.*;
public abstract class AbstractSceneGraphComponentVisualization extends AbstractDataVisualization {
protected SceneGraphComponent sceneGraphComponent = new SceneGraphComponent();
protected Appearance appearance = new Appearance(
"Vector Field Appearance");
protected Selection selection = null;
public AbstractSceneGraphComponentVisualization(HalfedgeLayer layer, Adapter<?> source, DataVisualizer visualizer, DataVisualizer.NodeType type) {
super(layer, source, visualizer, type);
}
void initAppearance() {
appearance.setAttribute(LINE_SHADER + "." + DEPTH_FUDGE_FACTOR,
0.88888);
appearance.setAttribute(EDGE_DRAW, true);
appearance.setAttribute(VERTEX_DRAW, false);
appearance.setAttribute(LINE_SHADER + "." + TUBES_DRAW, false);
appearance.setAttribute(LINE_SHADER + "." + LINE_WIDTH, 1.0);
appearance.setAttribute(LINE_SHADER + "." + TUBE_RADIUS, 0.1);
appearance.setAttribute(LINE_SHADER + "." + PICKABLE, false);
appearance.setAttribute(DEPTH_FUDGE_FACTOR, 0.9999);
appearance.setAttribute(LINE_SHADER + "." + POLYGON_SHADER
+ "." + SMOOTH_SHADING, true);
appearance.setAttribute(POLYGON_SHADER + "." + SMOOTH_SHADING,
true);
}
@Override
public final void update() {
sceneGraphComponent.setVisible(isActive());
if (!isActive()) {
return;
}
clearSceneGraphComponent();
updateSceneGraphComponent();
updateAppearance();
HalfedgeLayer layer = getLayer();
layer.removeTemporaryGeometry(sceneGraphComponent);
layer.addTemporaryGeometry(sceneGraphComponent);
}
public abstract void updateAppearance();
public abstract void updateSceneGraphComponent();
void clearSceneGraphComponent() {
sceneGraphComponent.setGeometry(null);
List<SceneGraphComponent> sgc = sceneGraphComponent.getChildComponents();
int n = sgc.size();
for (int i = 0; i < n; i++) {
sceneGraphComponent.removeChild(sgc.get(0));
}
}
List<? extends Node> getNodes(HalfEdgeDataStructure<?, ?, ?> hds) {
List<? extends Node> nodes;
switch (getType()) {
case Vertex:
if (selection == null) {
nodes = hds.getVertices();
} else {
nodes = new LinkedList<Vertex<?, ?, ?>>(selection.getVertices());
}
break;
case Edge:
if (selection == null) {
nodes = hds.getEdges();
} else {
nodes = new LinkedList<Edge<?, ?, ?>>(selection.getEdges());
}
break;
default:
if (selection == null) {
nodes = hds.getFaces();
} else {
nodes = new LinkedList<Face<?, ?, ?>>(selection.getFaces());
}
break;
}
return nodes;
}
}
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.math.Rn;
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;
import java.util.Collection;
public abstract class AbstractVectorCoordinateAndIndexFactory<COORDTYPE>
extends AbstractCoordinateAndIndexFactory<COORDTYPE> {
protected boolean
normalized = true,
centered = true;
protected double
scale = 1.0;
protected void add3DVector(double[] v, double[] p) throws NullPointerException {
double[] v3D = convertTo3DVector(v);
if (normalized) {
Rn.normalize(v3D, v3D);
Rn.times(v3D, meanEdgeLength, v3D);
}
if (centered) {
Rn.times(v3D, scale / 2., v3D);
vertexCoordinates.add(Rn.subtract(null, p, v3D));
vertexCoordinates.add(Rn.add(null, p, v3D));
} else {
Rn.times(v3D, scale / 2., v3D);
vertexCoordinates.add(p);
vertexCoordinates.add(Rn.add(null, p, v3D));
}
}
@Override
<V extends Vertex<V, E, F>, E extends Edge<V, E, F>, F extends Face<V, E, F>, N extends Node<V, E, F>> void updateEdgeIndices(Collection<N> nodes, AdapterSet aSet) {
edgeIndices.clear();
for (int i = 0; i < vertexCoordinates.size(); i += 2) {
edgeIndices.add(new int[]{i, i+1});
}
}
}
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.geometry.IndexedLineSetFactory;
import de.jreality.math.Rn;
import de.jreality.scene.IndexedLineSet;
import java.awt.*;
import java.util.List;
class ArrowLineSetCreator implements LineSetCreator {
private double thickness = .1;
private Color color = Color.BLACK;
public ArrowLineSetCreator(double thickness, Color color) {
this.thickness = thickness;
this.color = color;
}
@Override
public IndexedLineSet createLineSet(java.util.List<double[]> vData, List<int[]> iData) {
int numOfVectors = vData.size() / 2;
int numcoords = 6 * numOfVectors;
int numedges = 2 * numOfVectors;
double[][] coords = new double[numcoords][];
int[][] edges = new int[numedges][];
double[] radii = new double[numcoords];
Color[] edgecolors = new Color[numedges];
double[] startcoords, targetcoords, vector;
int[] ids;
int startid, targetid;
for (int i = 0; i < numOfVectors; i++) {
ids = iData.get(i);
if (ids.length != 2)
throw new RuntimeException("Is not a single edge (= vector)!");
startid = ids[0];
targetid = ids[1];
startcoords = vData.get(startid);
targetcoords = vData.get(targetid);
vector = Rn.subtract(null, targetcoords, startcoords);
coords[i + 0 * numOfVectors] = Rn.subtract(null, startcoords,
Rn.setEuclideanNorm(null, 0.001, vector));
coords[i + 1 * numOfVectors] = startcoords.clone();
coords[i + 2 * numOfVectors] = targetcoords.clone();
radii[i + 0 * numOfVectors] = 0.001;
radii[i + 1 * numOfVectors] = thickness;
radii[i + 2 * numOfVectors] = thickness;
edgecolors[i] = color;
edges[i] = new int[]{i + 0 * numOfVectors,
i + 1 * numOfVectors, i + 2 * numOfVectors};
coords[i + 3 * numOfVectors] = Rn.subtract(null,
targetcoords, Rn.times(null, 0.001, vector));
radii[i + 3 * numOfVectors] = 0.001;
coords[i + 4 * numOfVectors] = targetcoords.clone();
radii[i + 4 * numOfVectors] = 1.5 * thickness;
coords[i + 5 * numOfVectors] = Rn.add(null, targetcoords,
Rn.times(null, .2, vector));
radii[i + 5 * numOfVectors] = 0.001;
edges[i + numOfVectors] = new int[]{i + 3 * numOfVectors,
i + 4 * numOfVectors, i + 5 * numOfVectors};
edgecolors[i + numOfVectors] = Color.black;
}
IndexedLineSetFactory ilsf = new IndexedLineSetFactory();
if (numcoords != 0) {
ilsf.setVertexCount(numcoords);
ilsf.setEdgeCount(numedges);
ilsf.setVertexCoordinates(coords);
ilsf.setVertexRelativeRadii(radii);
ilsf.setEdgeIndices(edges);
ilsf.setEdgeColors(edgecolors);
ilsf.update();
}
return ilsf.getIndexedLineSet();
}
}
package de.jtem.halfedgetools.plugin.data.visualizer;
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;
import java.util.Collection;
public class CoordinateFactory extends AbstractCoordinateFactory<double[][]> {
@Override
public <V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
N extends Node<V, E, F>>
int updateVertexCoordinates(Collection<N> nodes, AdapterSet aSet) {
vertexCoordinates.clear();
int numNullValues = 0;
for (N node : nodes) {
double[][] v = adapter.get(node, aSet);
try {
for (int i = 0; i < v.length; i++) {
vertexCoordinates.add(convertTo3DVector(v[i]));
}
} catch (NullPointerException e) {
numNullValues++;
}
}
return numNullValues;
}
}
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.scene.IndexedLineSet;
import java.util.List;
interface LineSetCreator {
IndexedLineSet createLineSet(List<double[]> vData, List<int[]> iData);
}
package de.jtem.halfedgetools.plugin.data.visualizer;
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;
import de.jtem.halfedgetools.adapter.type.generic.BaryCenter3d;
import java.util.Collection;
class MultiVectorCoordinateAndIndexFactory extends AbstractVectorCoordinateAndIndexFactory<double[][]> {
public <V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
N extends Node<V, E, F>
> int updateVertexCoordinates(Collection<N> nodes, AdapterSet aSet) {
aSet.setParameter("alpha", .5);
int numNullValues = 0;
for (N node : nodes) {
double[][] v = adapter.get(node, aSet);
try {
for (int i = 0; i < v.length; i++) {
double[] p = aSet.getD(BaryCenter3d.class, node);
add3DVector(v[i], p);
}
} catch (NullPointerException e) {
numNullValues++;
}
}
return numNullValues;
}
}
......@@ -14,6 +14,7 @@ import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
......@@ -169,23 +170,23 @@ public class NodeColorVisualizer extends DataVisualizerPlugin implements ActionL
a.addAll(hif.getActiveVolatileAdapters());
switch (getType()) {
case Vertex:
List<? extends Vertex<?,?,?>> vList = getColoredNodes(hds.getVertices(), a, minmax);
List<?> vList = getColoredNodes(hds.getVertices(), a, minmax);
a.add(new ColorAdapter(minmax[0], minmax[1]));
PointSet ps = createVertices(vList, a, true);
PointSet ps = createVertices((List<Vertex<?,?,?>>)vList, a, true);
ps.setName("Vertex Colors Geometry");
geomComponent.setGeometry(ps);
break;
case Edge:
List<? extends Edge<?,?,?>> eList = getColoredNodes(hds.getEdges(), a, minmax);
List<?> eList = getColoredNodes(hds.getEdges(), a, minmax);
a.add(new ColorAdapter(minmax[0], minmax[1]));
IndexedLineSet ils = createEdges(eList, a, true);
IndexedLineSet ils = createEdges((List<Edge<?,?,?>>)eList, a, true);
ils.setName("Edge Colors Geometry");
geomComponent.setGeometry(ils);
break;
case Face:
List<? extends Face<?,?,?>> fList = getColoredNodes(hds.getFaces(), a, minmax);
List<?> fList = getColoredNodes(hds.getFaces(), a, minmax);
a.add(new ColorAdapter(minmax[0], minmax[1]));
IndexedFaceSet ifs = createOffsetFaces(fList, a, offset, true);
IndexedFaceSet ifs = createOffsetFaces((List<? extends Face<?, ?, ?>>)fList, a, offset, true);
ifs.setName("Face Colors Geometry");
geomComponent.setGeometry(ifs);
break;
......
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.geometry.PointSetFactory;
import de.jtem.halfedge.HalfEdgeDataStructure;
import de.jtem.halfedge.Node;
import de.jtem.halfedgetools.adapter.Adapter;
import de.jtem.halfedgetools.adapter.AdapterSet;
import de.jtem.halfedgetools.plugin.HalfedgeLayer;
import de.jtem.halfedgetools.plugin.data.DataVisualization;
import de.jtem.halfedgetools.plugin.data.DataVisualizerPlugin;
import java.util.List;
public class PointSetVisualizer extends DataVisualizerPlugin {
@Override
public boolean canRead(Adapter<?> a, NodeType type) {
boolean accept = false;
accept |= a.checkType(double[][].class);
return accept;
}
@Override
public DataVisualization createVisualization(HalfedgeLayer layer, NodeType type, Adapter<?> source) {
PointSetVisualization vis = new PointSetVisualization(layer, source, this, type);
layer.addTemporaryGeometry(vis.sceneGraphComponent);
return vis;
}
@Override
public void disposeVisualization(DataVisualization vis) {
PointSetVisualization psVis = (PointSetVisualization) vis;
vis.getLayer().removeTemporaryGeometry(psVis.sceneGraphComponent);
}
@Override
public String getName() {
return "Points";
}
public class PointSetVisualization extends AbstractSceneGraphComponentVisualization {
private AbstractCoordinateFactory<double[][]> coordinateFactory = new CoordinateFactory();
public PointSetVisualization(HalfedgeLayer layer, Adapter<?> source, PointSetVisualizer pointSetVisualizer, NodeType type) {
super(layer, source, pointSetVisualizer, type);
sceneGraphComponent.setName("Points");
coordinateFactory.setAdapter(source);
initAppearance();
}
@Override
public void updateAppearance() {
}
@Override
public void updateSceneGraphComponent() {
PointSetFactory psf = new PointSetFactory();
HalfEdgeDataStructure<?, ?, ?> hds = getLayer().get();
AdapterSet aSet = getLayer().getEffectiveAdapters();
List<? extends Node> nodes = getNodes(hds);
coordinateFactory.updateVertexCoordinates(nodes, aSet);
psf.setVertexCount(coordinateFactory.vertexCoordinates.size());
psf.setVertexCoordinates(coordinateFactory.vertexCoordinates.toArray(new double[][]{}));
psf.update();
sceneGraphComponent.setGeometry(psf.getGeometry());
}
}
}
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.geometry.IndexedLineSetFactory;
import de.jreality.scene.IndexedLineSet;
import java.util.List;
class SimpleLineSetCreator implements LineSetCreator {
@Override
public IndexedLineSet createLineSet(List<double[]> vData, List<int[]> iData) {
IndexedLineSetFactory ilf = new IndexedLineSetFactory();
if (vData.size() == 0) {
return ilf.getIndexedLineSet();
}
ilf.setVertexCount(vData.size());
ilf.setEdgeCount(vData.size() / 2);
ilf.setVertexCoordinates(vData.toArray(new double[][]{}));
ilf.setEdgeIndices(iData.toArray(new int[][]{}));
ilf.update();
return ilf.getIndexedLineSet();
}
}
package de.jtem.halfedgetools.plugin.data.visualizer;
import de.jreality.geometry.IndexedLineSetFactory;
import de.jreality.math.Rn;
import de.jreality.scene.IndexedLineSet;
import java.awt.*;
import java.util.List;
class TubeLineSetCreator implements LineSetCreator {
private double thickness = .1;
private Color color = Color.BLACK;
public TubeLineSetCreator(double thickness, Color color) {
this.thickness = thickness;
this.color = color;
}
@Override
public IndexedLineSet createLineSet(List<double[]> vData, List<int[]> iData) {
int numOfVectors = vData.size() / 2;
int numcoords = 4 * numOfVectors;
int numedges = numOfVectors;
double[][] coords = new double[numcoords][];
int[][] edges = new int[numedges][];
double[] radii = new double[numcoords];
Color[] edgecolors = new Color[numedges];
double[] startcoords, targetcoords, vector;
int[] ids;
int startid, targetid;
for (int i = 0; i < numOfVectors; i++) {
ids = iData.get(i);
if (ids.length != 2)
throw new RuntimeException("Is not a single edge (= vector)!");
startid = ids[0];
targetid = ids[1];
startcoords = vData.get(startid);
targetcoords = vData.get(targetid);
vector = Rn.subtract(null, targetcoords, startcoords);
coords[i + 0 * numOfVectors] = Rn.subtract(null, startcoords,
Rn.setEuclideanNorm(null, 0.001, vector));
coords[i + 1 * numOfVectors] = startcoords.clone();
coords[i + 2 * numOfVectors] = targetcoords.clone();
radii[i + 0 * numOfVectors] = 0.001;
radii[i + 1 * numOfVectors] = thickness;
radii[i + 2 * numOfVectors] = thickness;
edgecolors[i] = color;
coords[i + 3 * numOfVectors] = Rn.add(null, targetcoords,
Rn.setEuclideanNorm(null, 0.001, vector));
radii[i + 3 * numOfVectors] = 0.001;
edges[i] = new int[]{i + 0 * numOfVectors,
i + 1 * numOfVectors, i + 2 * numOfVectors,
i + 3 * numOfVectors};
}
IndexedLineSetFactory ilsf = new IndexedLineSetFactory();
if (numcoords != 0) {
ilsf.setVertexCount(numcoords);
ilsf.setEdgeCount(numedges);
ilsf.setVertexCoordinates(coords);
ilsf.setVertexRelativeRadii(radii);
ilsf.setEdgeIndices(edges);
ilsf.setEdgeColors(edgecolors);
ilsf.update();
}
return ilsf.getIndexedLineSet();
}
}
package de.jtem.halfedgetools.plugin.data.visualizer;
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;
import de.jtem.halfedgetools.adapter.type.generic.BaryCenter3d;
import java.util.Collection;
class VectorCoordinateAndIndexFactory extends AbstractVectorCoordinateAndIndexFactory<double[]> {
public <V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>,
N extends Node<V, E, F>
>
int updateVertexCoordinates(Collection<N> nodes, AdapterSet aSet) {
aSet.setParameter("alpha", .5);
int numNullValues = 0;
for (N node : nodes) {
try {
double[] v = adapter.get(node, aSet);
double[] p = aSet.getD(BaryCenter3d.class, node);
add3DVector(v, p);
} catch (NullPointerException e) {
numNullValues++;
}
}
return numNullValues;
}
}
......@@ -78,7 +78,6 @@ public class LayerComponent extends SceneComponent {
updateSelection();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public synchronized void updateGeometry() {
vertexComponent.getPoints().clear();
vertexComponent.getAnnotations().clear();
......@@ -91,9 +90,9 @@ public class LayerComponent extends SceneComponent {
AdapterSet a = layer.getEffectiveAdapters();
// faces
for (Face f : new LinkedList<Face>(hds.getFaces())) {
for(Face f : new LinkedList<>(hds.getFaces())) {
if (!f.isValid()) continue;
Shape faceShape = getFaceShape(a, f);
Shape faceShape = this.<Vertex, Edge, Face>getFaceShape(a, f);
faces.append(faceShape, false);
double[] p = a.getDefault(TextureBaryCenter2d.class, f, defaultCoord);
Annotation indexAnnotation = new Annotation("" + f.getIndex(), p[0], p[1], Annotation.CENTER);
......@@ -120,7 +119,6 @@ public class LayerComponent extends SceneComponent {
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public synchronized void updateSelection() {
if (layer == null) return;
SelectionInterface sif = layer.getHalfedgeInterface().getSelectionInterface();
......@@ -172,7 +170,7 @@ public class LayerComponent extends SceneComponent {
}
for (Face f : s.getFaces()) {
if (!f.isValid()) return;
Shape faceShape = getFaceShape(a, f);
Shape faceShape = this.<Vertex, Edge, Face>getFaceShape(a, f);
Integer channel = s.getChannel(f);
SceneComponent fComp = fMap.get(channel);
if (!fMap.containsKey(channel)) {
......@@ -198,12 +196,13 @@ public class LayerComponent extends SceneComponent {
return new Line2D.Float((float)s[0], (float)s[1], (float)t[0], (float)t[1]);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private Shape getFaceShape(AdapterSet a, Face f) {
private <V extends Vertex<V, E, F>,
E extends Edge<V, E, F>,
F extends Face<V, E, F>
> Shape getFaceShape(AdapterSet a, F f) {
Path2D p = new Path2D.Float();
boolean start = true;
for (Object ov : HalfEdgeUtils.boundaryVertices(f)) {
Vertex<?, ?, ?> v = (Vertex<?, ?, ?>)ov;
for (V v : HalfEdgeUtils.boundaryVertices(f)) {
double[] t = a.getDefault(TexturePosition2d.class, v, defaultCoord);
if (start) {
p.moveTo(t[0], t[1]);
......