/* jCAE stand for Java Computer Aided Engineering. Features are : Small CAD modeler, Finite element mesher, Plugin architecture. Copyright (C) 2005, by EADS CRC Copyright (C) 2007,2009, by EADS France This library 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 library 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.jcae.mesh.amibe.validation; import org.jcae.mesh.amibe.ds.AbstractHalfEdge; import org.jcae.mesh.amibe.ds.Triangle; import org.jcae.mesh.amibe.ds.Vertex; import org.jcae.mesh.amibe.metrics.Matrix3D; import org.jcae.mesh.amibe.traits.MeshTraitsBuilder; /** * Compute angles between adjacent triangles. * This class implements the {@link QualityProcedure#quality(Object)} * method to compute angles between adjacent triangles. The inner * products between the normal to the triangle and the normal to * adjacent triangles are computed, and the quality of the triangle * is set to the minimal value. This is very useful to detect * inverted triangles in 3D on smooth surfaces. */ public class DihedralAngle extends QualityProcedure { private AbstractHalfEdge ot; private AbstractHalfEdge sym; private final double[] temp1 = new double[3]; private final double[] temp2 = new double[3]; private final double[] temp3 = new double[3]; private final double[] temp4 = new double[3]; @Override protected void setValidationFeatures() { usageStr = new String[]{"DihedralAngle", "smallest dot product of normals with adjacent triangles"}; type = QualityProcedure.FACE; } /** * Returns <code>MeshTraitsBuilder</code> instance needed by this class. */ @Override public final MeshTraitsBuilder getMeshTraitsBuilder() { return MeshTraitsBuilder.getDefault3D(); } @Override public float quality(Object o) { if (!(o instanceof Triangle)) throw new IllegalArgumentException(); Triangle t = (Triangle) o; ot = t.getAbstractHalfEdge(ot); sym = t.getAbstractHalfEdge(sym); float ret = 1.0f; for (int i = 0; i < 3; i++) { ot = ot.next(); if (ot.hasAttributes(AbstractHalfEdge.BOUNDARY | AbstractHalfEdge.NONMANIFOLD)) continue; if (!ot.hasSymmetricEdge()) continue; sym = ot.sym(sym); if (t.getGroupId() != sym.getTri().getGroupId()) continue; Vertex p0 = ot.origin(); Vertex p1 = ot.destination(); Vertex p2 = ot.apex(); Vertex p3 = sym.apex(); Matrix3D.computeNormal3D(p0, p1, p2, temp1, temp2, temp3); Matrix3D.computeNormal3D(p1, p0, p3, temp1, temp2, temp4); float dot = (float) Matrix3D.prodSca(temp3, temp4); if (dot < ret) ret = dot; } return ret; } }