/* * Project Info: http://jcae.sourceforge.net * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * (C) Copyright 2015, by Airbus Group SAS */ package org.jcae.mesh.amibe.projection; import java.util.Collection; import org.jcae.mesh.amibe.ds.Triangle; import org.jcae.mesh.amibe.ds.Vertex; import org.jcae.mesh.amibe.util.HashFactory; /** * Find triangles which are close to an edge * @author Jerome Robert */ public class EdgeTrianglesLocator { private final Collection<Triangle> trianglesInAABB = HashFactory.createSet(); private final Collection<Triangle> trianglesInOBB = HashFactory.createSet(); private final double[] aabb = new double[6]; private final double[] matrix = new double[12]; private final TriangleInterAABB taabb = new TriangleInterAABB(); private final TriangleKdTree kdTree; private static void compteEdgeAABB(Vertex v1, Vertex v2, double[] aabb) { aabb[0] = Math.min(v1.getX(), v2.getX()); aabb[1] = Math.min(v1.getY(), v2.getY()); aabb[2] = Math.min(v1.getZ(), v2.getZ()); aabb[3] = Math.max(v1.getX(), v2.getX()); aabb[4] = Math.max(v1.getY(), v2.getY()); aabb[5] = Math.max(v1.getZ(), v2.getZ()); } private static double normalize(double[] m, int c) { c = c * 4; double norm = Math.sqrt(m[c] * m[c] + m[c+1] * m[c+1] + m[c+2] * m[c+2]); m[c] /= norm; m[c+1] /= norm; m[c+2] /= norm; return norm; } /** * Compute a transformation where the image of v1,v2 is along x. * @param m a 3x4 matrix, rotation and translation * see From Efficient Construction of Perpendicular Vectors without Branching * by Michael M. Stark */ private static double nullSpace(Vertex v1, Vertex v2, double[] m) { // image of X m[0] = v2.getX() - v1.getX(); m[1] = v2.getY() - v1.getY(); m[2] = v2.getZ() - v1.getZ(); double norm = normalize(m, 0); // compute a vector very not collinear to X double x = Math.abs(m[0]); double y = Math.abs(m[1]); double z = Math.abs(m[2]); boolean uyx = (x - y) < 0; boolean uzx = (x - z) < 0; boolean uzy = (y - z) < 0; boolean xm = uyx && uzx; boolean ym = !xm && uzy; boolean zm = !(xm || ym); x = xm ? 1 : 0; y = ym ? 1 : 0; z = zm ? 1 : 0; // image of Y m[4] = m[2] * y - m[1] * z; m[5] = m[0] * z - m[2] * x; m[6] = m[1] * x - m[0] * y; normalize(m, 1); // image of Z m[8] = m[1] * m[6] - m[2] * m[5]; m[9] = m[4] * m[2] - m[6] * m[0]; m[10] = m[0] * m[5] - m[1] * m[4]; // translation x = -v1.getX(); y = -v1.getY(); z = -v1.getZ(); m[3] = m[0] * x + m[1] * y + m[2] * z; m[7] = m[4] * x + m[5] * y + m[6] * z; m[11] = m[8] * x + m[9] * y + m[10] * z; return norm; } public EdgeTrianglesLocator(TriangleKdTree kdTree) { this.kdTree = kdTree; } public void locate(Vertex v1, Vertex v2, int group, double tolerance) { compteEdgeAABB(v1, v2, aabb); for (int i = 0; i < 3; i++) { aabb[i] -= tolerance; aabb[3 + i] += tolerance; } trianglesInAABB.clear(); kdTree.getNearTriangles(aabb, trianglesInAABB, group); double norm = nullSpace(v1, v2, matrix); aabb[0] = 0; aabb[1] = -tolerance; aabb[2] = -tolerance; aabb[3] = norm; aabb[4] = tolerance; aabb[5] = tolerance; trianglesInOBB.clear(); for (Triangle t : trianglesInAABB) { if (isValidTriangle(t)) { taabb.setTriangle(t, matrix); if (taabb.triBoxOverlap(aabb, true)) { trianglesInOBB.add(t); } } } } public Collection<Triangle> getResult() { return trianglesInOBB; } protected boolean isValidTriangle(Triangle t) { return true; } }