/* jCAE stand for Java Computer Aided Engineering. Features are : Small CAD modeler, Finite element mesher, Plugin architecture. Copyright (C) 2005, by EADS CRC 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.traits.MeshTraitsBuilder; import gnu.trove.list.array.TFloatArrayList; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Comparator; import java.util.List; import org.jcae.mesh.amibe.ds.Triangle; /** * Abstract class to compute quality criteria. * All functions implementing quality criteria have to inherit from * this class. These functions can compute values either on elements * or nodes, and can work either on 2D or 3D meshes. * * For these reasons, <code>quality</code> method's argument is an * <code>Object</code>, and caller is responsible for passing the * right argument. */ public abstract class QualityProcedure { public static final int FACE = 1; public static final int NODE = 2; public static final int EDGE = 3; // By default, values are computed by faces. int type = FACE; String [] usageStr; private TFloatArrayList data; private static final Class<QualityProcedure> [] subClasses = new Class[]{ // AbsoluteDeflection2D.class, Disabled for now Area.class, DihedralAngle.class, MaxAngleFace.class, MaxLengthFace.class, MinAngleFace.class, MinLengthFace.class, NodeConnectivity.class, null }; public static String [] getListSubClasses() { String [] ret = new String[2*subClasses.length-2]; int idx = 0; try { for (Class<QualityProcedure> c: subClasses) { if (c == null) break; Constructor<QualityProcedure> cons = c.getConstructor(); QualityProcedure qproc = cons.newInstance(); String [] str = qproc.usageStr; ret[2*idx] = str[0]; ret[2*idx+1] = str[1]; idx++; } } catch (NoSuchMethodException ex) { } catch (IllegalAccessException ex) { } catch (InstantiationException ex) { } catch (InvocationTargetException ex) { } return ret; } protected abstract void setValidationFeatures(); QualityProcedure() { setValidationFeatures(); } /** * Return element type. * * @return element type */ public final int getType() { return type; } /** * Return the quality factor for a given object. * * @param o entity at which quality is computed * Returns quality factor. */ public abstract float quality(Object o); /** * Returns default scale factor. */ final float getScaleFactor() { return 1.0f; } /** * Returns <code>MeshTraitsBuilder</code> instance needed by this class. */ public MeshTraitsBuilder getMeshTraitsBuilder() { return new MeshTraitsBuilder(); } /** * Finish quality computations. * By default, this method does nothing and can be overriden * when post-processing is needed. */ public void finish() { } /** * Make output array visible by the {@link #finish} method. * @see QualityFloat#setQualityProcedure * * @param d array containing output values */ public final void bindResult(TFloatArrayList d) { data = d; } /** * Return the highest or lowest quality triangles in the list * @param qualityProcedure The quality procedure to use * @param input The list of Triangle to test * @param nb The number of triangles to return. If the number is positive * the lowest quality triangles are return else the highest quality triangles * are return * @return The triangles with the lowest or highest quality */ public static List<Triangle> worstTriangles(QualityProcedure qualityProcedure, final List<Triangle> input, final int nb, final boolean reverse) { Integer[] indices = new Integer[input.size()]; for (int i = 0; i < indices.length; i++) { indices[i] = i; } final float[] qualities = new float[indices.length]; int k = 0; for (Triangle t : input) { qualities[k++] = qualityProcedure.quality(t); } Arrays.sort(indices, new Comparator<Integer>() { public int compare(Integer o1, Integer o2) { if(reverse) return Float.compare(qualities[o2], qualities[o1]); else return Float.compare(qualities[o1], qualities[o2]); } }); Triangle[] toReturn; if (nb > 0) { toReturn = new Triangle[nb]; for (int i = 0; i < nb; i++) toReturn[i] = input.get(indices[i]); } else { toReturn = new Triangle[-nb]; for (int i = 0; i < -nb; i++) toReturn[i] = input.get(indices[indices.length - i - 1]); } return Arrays.asList(toReturn); } }