/** * */ package wblut.geom; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import javolution.util.FastList; import wblut.hemesh.HEC_Geodesic; import wblut.hemesh.HE_Mesh; import wblut.math.WB_Fast; import wblut.math.WB_RandomSphere; // TODO: Auto-generated Javadoc /** * The Class WB_Frame. * * @author Frederik Vanhoutte, W:Blut */ public class WB_Frame { /** The struts. */ private FastList<WB_FrameStrut> struts; /** The nodes. */ private FastList<WB_FrameNode> nodes; /** * Instantiates a new w b_ frame. */ public WB_Frame() { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); } /** * Instantiates a new w b_ frame. * * @param points the points * @param connections the connections */ public WB_Frame(final WB_Point3d[] points, final WB_IndexedSegment[] connections) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final WB_Point3d point : points) { addNode(point, 1); } for (final WB_IndexedSegment connection : connections) { addStrut(connection.i1(), connection.i2()); } } /** * Instantiates a new w b_ frame. * * @param points the points * @param connections the connections */ public WB_Frame(final WB_Point3d[] points, final Collection<WB_IndexedSegment> connections) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final WB_Point3d point : points) { addNode(point, 1); } for (final WB_IndexedSegment connection : connections) { addStrut(connection.i1(), connection.i2()); } } /** * Adds the. * * @param points the points * @param connections the connections */ public void add(final WB_Point3d[] points, final Collection<WB_IndexedSegment> connections) { if (struts == null) { struts = new FastList<WB_FrameStrut>(); } if (nodes == null) { nodes = new FastList<WB_FrameNode>(); } final int nodeoffset = nodes.size(); for (final WB_Point3d point : points) { addNode(point, 1); } for (final WB_IndexedSegment connection : connections) { addStrut(connection.i1() + nodeoffset, connection.i2() + nodeoffset); } } /** * Adds the. * * @param frame the frame */ public void add(final WB_Frame frame) { if (struts == null) { struts = new FastList<WB_FrameStrut>(); } if (nodes == null) { nodes = new FastList<WB_FrameNode>(); } final int nodeoffset = nodes.size(); for (final WB_FrameNode node : frame.nodes) { addNode(node, node.getValue()); } for (final WB_IndexedSegment connection : frame.getIndexedSegments()) { addStrut(connection.i1() + nodeoffset, connection.i2() + nodeoffset); } } /** * Instantiates a new w b_ frame. * * @param points the points * @param connections the connections */ public WB_Frame(final Collection<WB_Point3d> points, final Collection<WB_IndexedSegment> connections) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final WB_Point3d point : points) { addNode(point, 1); } for (final WB_IndexedSegment connection : connections) { addStrut(connection.i1(), connection.i2()); } } /** * Instantiates a new w b_ frame. * * @param points the points * @param connections the connections */ public WB_Frame(final WB_Point3d[] points, final int[][] connections) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final WB_Point3d point : points) { addNode(point.x, point.y, point.z, 1); } for (final int[] connection : connections) { addStrut(connection[0], connection[1]); } } /** * Instantiates a new w b_ frame. * * @param points the points * @param connections the connections */ public WB_Frame(final Collection<WB_Point3d> points, final int[][] connections) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final WB_Point3d point : points) { addNode(point.x, point.y, point.z, 1); } for (final int[] connection : connections) { addStrut(connection[0], connection[1]); } } /** * Instantiates a new w b_ frame. * * @param points the points * @param connections the connections */ public WB_Frame(final double[][] points, final int[][] connections) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final double[] point : points) { addNode(point[0], point[1], point[2], 1); } for (final int[] connection : connections) { addStrut(connection[0], connection[1]); } } /** * Instantiates a new w b_ frame. * * @param points the points * @param connections the connections */ public WB_Frame(final float[][] points, final int[][] connections) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final float[] point : points) { addNode(point[0], point[1], point[2], 1); } for (final int[] connection : connections) { addStrut(connection[0], connection[1]); } } /** * Instantiates a new w b_ frame. * * @param points the points * @param connections the connections */ public WB_Frame(final int[][] points, final int[][] connections) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final int[] point : points) { addNode(point[0], point[1], point[2], 1); } for (final int[] connection : connections) { addStrut(connection[0], connection[1]); } } /** * Instantiates a new w b_ frame. * * @param points the points */ public WB_Frame(final WB_Point3d[] points) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final WB_Point3d point : points) { addNode(point.x, point.y, point.z, 1); } } /** * Instantiates a new w b_ frame. * * @param points the points */ public WB_Frame(final Collection<WB_Point3d> points) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final WB_Point3d point : points) { addNode(point.x, point.y, point.z, 1); } } /** * Instantiates a new w b_ frame. * * @param points the points */ public WB_Frame(final double[][] points) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final double[] point : points) { addNode(point[0], point[1], point[2], 1); } } /** * Instantiates a new w b_ frame. * * @param points the points */ public WB_Frame(final float[][] points) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final float[] point : points) { addNode(point[0], point[1], point[2], 1); } } /** * Instantiates a new w b_ frame. * * @param points the points */ public WB_Frame(final int[][] points) { struts = new FastList<WB_FrameStrut>(); nodes = new FastList<WB_FrameNode>(); for (final int[] point : points) { addNode(point[0], point[1], point[2], 1); } } /** * Adds the node. * * @param x the x * @param y the y * @param z the z * @param v the v * @return the int */ public int addNode(final double x, final double y, final double z, final double v) { final int n = nodes.size(); nodes.add(new WB_FrameNode(new WB_Point3d(x, y, z), n, v)); return n; } /** * Adds the node. * * @param pos the pos * @param v the v * @return the int */ public int addNode(final WB_Point3d pos, final double v) { final int n = nodes.size(); nodes.add(new WB_FrameNode(pos, n, v)); return n; } /** * Removes the node. * * @param node the node */ public void removeNode(final WB_FrameNode node) { for (final WB_FrameStrut strut : node.getStruts()) { removeStrut(strut); } nodes.remove(node); } /** * Adds the nodes. * * @param pos the pos * @return the int */ public int addNodes(final Collection<WB_Point3d> pos) { int n = nodes.size(); final Iterator<WB_Point3d> pItr = pos.iterator(); while (pItr.hasNext()) { nodes.add(new WB_FrameNode(pItr.next(), n, 1)); n++; } return n; } /** * Adds the strut. * * @param i the i * @param j the j * @return the int */ public int addStrut(final int i, final int j) { if (i == j) { throw new IllegalArgumentException( "Strut can't connect a node to itself: " + i + " " + j + "."); } final int nn = nodes.size(); if ((i < 0) || (j < 0) || (i >= nn) || (j >= nn)) { throw new IllegalArgumentException( "Strut indices outside node range."); } final int n = struts.size(); WB_FrameStrut strut; if (i <= j) { strut = new WB_FrameStrut(nodes.get(i), nodes.get(j), n); } else { strut = new WB_FrameStrut(nodes.get(j), nodes.get(i), n); } if (!nodes.get(i).addStrut(strut)) { System.out.println("WB_Frame : Strut " + i + "-" + j + " already added."); } else if (!nodes.get(j).addStrut(strut)) { System.out.println("WB_Frame : Strut " + i + "-" + j + " already added."); } else { struts.add(strut); } return n; } /** * Removes the strut. * * @param strut the strut */ public void removeStrut(final WB_FrameStrut strut) { nodes.get(strut.getStartIndex()).removeStrut(strut); nodes.get(strut.getEndIndex()).removeStrut(strut); struts.remove(strut); } /** * Gets the struts. * * @return the struts */ public ArrayList<WB_FrameStrut> getStruts() { final ArrayList<WB_FrameStrut> result = new ArrayList<WB_FrameStrut>(); result.addAll(struts); return result; } /** * Gets the segments. * * @return the segments */ public ArrayList<WB_ExplicitSegment> getSegments() { final ArrayList<WB_ExplicitSegment> result = new ArrayList<WB_ExplicitSegment>(); for (final WB_FrameStrut strut : struts) { result.add(strut.toSegment()); } return result; } /** * Gets the indexed segments. * * @return the indexed segments */ public ArrayList<WB_IndexedSegment> getIndexedSegments() { final ArrayList<WB_Point3d> apoints = getPoints(); WB_Point3d[] ipoints = new WB_Point3d[apoints.size()]; ipoints = apoints.toArray(ipoints); final ArrayList<WB_IndexedSegment> result = new ArrayList<WB_IndexedSegment>(); for (final WB_FrameStrut strut : struts) { result.add(new WB_IndexedSegment(strut.getStartIndex(), strut .getEndIndex(), ipoints)); } return result; } /** * Gets the number of struts. * * @return the number of struts */ public int getNumberOfStruts() { return struts.size(); } /** * Gets the nodes. * * @return the nodes */ public ArrayList<WB_FrameNode> getNodes() { final ArrayList<WB_FrameNode> result = new ArrayList<WB_FrameNode>(); result.addAll(nodes); return result; } /** * Gets the points. * * @return the points */ public ArrayList<WB_Point3d> getPoints() { final ArrayList<WB_Point3d> result = new ArrayList<WB_Point3d>(); result.addAll(nodes); return result; } /** * Gets the points as array. * * @return the points as array */ public WB_Point3d[] getPointsAsArray() { final ArrayList<WB_Point3d> result = new ArrayList<WB_Point3d>(); result.addAll(nodes); final ArrayList<WB_Point3d> apoints = getPoints(); final WB_Point3d[] ipoints = new WB_Point3d[apoints.size()]; return apoints.toArray(ipoints); } /** * Gets the number of nodes. * * @return the number of nodes */ public int getNumberOfNodes() { return nodes.size(); } /** * Gets the node. * * @param i the i * @return the node */ public WB_FrameNode getNode(final int i) { if ((i < 0) || (i >= nodes.size())) { throw new IllegalArgumentException("Index outside of node range."); } return nodes.get(i); } /** * Gets the strut. * * @param i the i * @return the strut */ public WB_FrameStrut getStrut(final int i) { if ((i < 0) || (i >= struts.size())) { throw new IllegalArgumentException("Index outside of strut range."); } return struts.get(i); } /** * Gets the distance to frame. * * @param p the p * @return the distance to frame */ public double getDistanceToFrame(final WB_Point3d p) { double d = Double.POSITIVE_INFINITY; for (int i = 0; i < struts.size(); i++) { final WB_FrameStrut strut = struts.get(i); final WB_ExplicitSegment S = new WB_ExplicitSegment(strut.start(), strut.end()); d = Math.min(d, WB_Distance.distance(p, S)); } return d; } /** * Gets the closest node on frame. * * @param p the p * @return the closest node on frame */ public int getClosestNodeOnFrame(final WB_Point3d p) { double mind = Double.POSITIVE_INFINITY; int q = -1; for (int i = 0; i < nodes.size(); i++) { final double d = WB_Distance.sqDistance(p, nodes.get(i)); if (d < mind) { mind = d; q = i; } } return q; } /** * Gets the closest point on frame. * * @param p the p * @return the closest point on frame */ public WB_Point3d getClosestPointOnFrame(final WB_Point3d p) { double mind = Double.POSITIVE_INFINITY; WB_Point3d q = new WB_Point3d(p); for (int i = 0; i < struts.size(); i++) { final WB_FrameStrut strut = struts.get(i); final WB_ExplicitSegment S = new WB_ExplicitSegment(strut.start(), strut.end()); final double d = WB_Distance.distance(p, S); if (d < mind) { mind = d; q = WB_Intersection.closestPoint(S, p); } } return q; } /** * Gets the distance to frame. * * @param x the x * @param y the y * @param z the z * @return the distance to frame */ public double getDistanceToFrame(final double x, final double y, final double z) { double d = Double.POSITIVE_INFINITY; for (int i = 0; i < struts.size(); i++) { final WB_FrameStrut strut = struts.get(i); final WB_ExplicitSegment S = new WB_ExplicitSegment(strut.start(), strut.end()); d = Math.min(d, WB_Distance.distance(new WB_Point3d(x, y, z), S)); } return d; } /** * Gets the closest point on frame. * * @param x the x * @param y the y * @param z the z * @return the closest point on frame */ public WB_Point3d getClosestPointOnFrame(final double x, final double y, final double z) { double mind = Double.POSITIVE_INFINITY; WB_Point3d q = new WB_Point3d(x, y, z); for (int i = 0; i < struts.size(); i++) { final WB_FrameStrut strut = struts.get(i); final WB_ExplicitSegment S = new WB_ExplicitSegment(strut.start(), strut.end()); final double d = WB_Distance.distance(new WB_Point3d(x, y, z), S); if (d < mind) { mind = d; q = WB_Intersection.closestPoint(S, new WB_Point3d(x, y, z)); } } return q; } /** * Smooth bi nodes. */ public void smoothBiNodes() { final WB_Point3d[] newPos = new WB_Point3d[nodes.size()]; int id = 0; for (final WB_FrameNode node : nodes) { if (node.getOrder() == 2) { newPos[id] = node.getNeighbor(0) .addAndCopy(node.getNeighbor(1)); newPos[id].mult(0.5); newPos[id].add(node); newPos[id].mult(0.5); } id++; } id = 0; for (final WB_FrameNode node : nodes) { if (node.getOrder() == 2) { node.set(newPos[id]); } id++; } } /** * Refine. * * @param threshold the threshold * @return the w b_ frame */ public WB_Frame refine(final double threshold) { final FastList<WB_Point3d> npoints = new FastList<WB_Point3d>(); for (final WB_FrameNode node : nodes) { npoints.add(node); } for (final WB_FrameStrut strut : struts) { if (strut.getLength() > threshold) { final WB_Point3d start = strut.start(); final WB_Point3d end = strut.end(); final WB_Point3d mid = WB_Point3d.interpolate(start, end, 0.5); npoints.add(mid); } } final int n = getNumberOfNodes(); int id = 0; final WB_Frame result = new WB_Frame(npoints); for (final WB_FrameStrut strut : struts) { if (strut.getLength() > threshold) { final int start = strut.getStartIndex(); final int end = strut.getEndIndex(); result.addStrut(start, n + id); result.addStrut(n + id, end); id++; } else { final int start = strut.getStartIndex(); final int end = strut.getEndIndex(); result.addStrut(start, end); } } return result; } /** * To point cloud. * * @param n the n * @param r the r * @param d the d * @param l the l * @param rr the rr * @param dr the dr * @return the list */ public List<WB_Point3d> toPointCloud(int n, double r, double d, int l, double rr, double dr) { List<WB_Point3d> points = new FastList<WB_Point3d>(); double sl, dsl; int divs; WB_Plane P; WB_Vector3d u, localu, v; WB_Point3d offset; WB_Point3d p; WB_RandomSphere rnd = new WB_RandomSphere(); double da = 2.0 * Math.PI / n; for (WB_FrameStrut strut : struts) { sl = strut.getLength() - 2 * rr; if (sl > 0) { divs = (int) WB_Fast.max(1, Math.round(sl / d)); dsl = sl / divs; P = strut.toPlane(); u = P.getU().multAndCopy(r); v = strut.toNormVector().get(); offset = strut.start().addAndCopy(v, rr); v.mult(dsl); for (int i = 0; i <= divs; i++) { for (int j = 0; j < n; j++) { p = strut.start().addAndCopy(v, i); localu = u.get(); localu.rotateAboutAxis(j * da, new WB_Point3d(), P.getNormal()); p.add(localu); p.add(rnd.nextVector().mult(dr)); points.add(p); } } } } for (WB_FrameNode node : nodes) { final HE_Mesh ball = new HE_Mesh(new HEC_Geodesic().setRadius(rr) .setLevel(l).setCenter(node)); for (WB_Point3d q : ball.getVerticesAsPoint()) { points.add(q.add(rnd.nextVector().mult(dr))); } } return points; } }