/* jCAE stand for Java Computer Aided Engineering. Features are : Small CAD
modeler, Finite element mesher, Plugin architecture.
Copyright (C) 2006, by EADS CRC
Copyright (C) 2007,2008,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.bora.ds;
import org.jcae.mesh.bora.algo.*;
import org.jcae.mesh.cad.CADShapeEnum;
import java.util.logging.Logger;
import java.lang.reflect.Constructor;
import java.util.logging.Level;
public class Hypothesis
{
private static final Logger LOGGER = Logger.getLogger(Hypothesis.class.getName());
private HypInterface hyp = HypNoneInstance;
// Now, length is the target length and is the variable that is used;
// In the near future we will want to enforce a maximum length lengthMax
private double length = -1.0, lengthMin = -1.0, lengthMax = -1.0;
private double deflection = -1.0;
private boolean lengthBool = false, numberBool = false;
private int numberMin = -1, numberMax = -1;
private boolean locked = false;
// Unique identitier
private final int id;
private static int nextId = -1;
private static final Class<?> [] innerClasses = Hypothesis.class.getDeclaredClasses();
private static final HypNone HypNoneInstance = new HypNone();
public Hypothesis()
{
nextId++;
id = nextId;
}
public Hypothesis(int i)
{
id = i;
if (i > nextId)
nextId = i;
}
public final int getId()
{
return id;
}
/**
* Sets element type.
*
* @param e element type
*/
public final void setElement(String e)
{
checkLock();
hyp = getAlgo(e);
if (LOGGER.isLoggable(Level.FINE))
LOGGER.log(Level.FINE, "("+Integer.toHexString(this.hashCode())+") Setting element type to "+e+" "+hyp.getClass().getName());
}
/**
* Gets element type.
*
* @return element type
*/
public final String getElement()
{
return hyp.getType();
}
/**
* Checks compatibility with geometrical objects.
*
* @param cse geometrical object type
* @return <code>true</code> if this hypothesis can be appplied on
* geometrical objects of a given type, and <code>false</code>
* otherwise.
*/
final boolean checkCompatibility(CADShapeEnum cse)
{
return hyp == null || hyp.getType() == null || hyp.dim() == cse;
}
/**
* Sets target length.
*
* @param l length
*/
public final void setLength(double l)
{
setLength(l, false);
}
/**
* Sets target length.
*
* @param l length
* @param b hard constraint
*/
private void setLength(double l, boolean b)
{
checkLock();
if (LOGGER.isLoggable(Level.FINE))
LOGGER.log(Level.FINE, "("+Integer.toHexString(this.hashCode())+") Setting length to "+l+"; strong constraint: "+b);
length = l;
lengthBool = b;
}
public final double getLength()
{
return length;
}
public final double getDeflection()
{
return deflection;
}
/**
* Sets length interval.
*
* @param l1 length min
* @param l2 length max
*/
@SuppressWarnings("unused")
private void setLength(double l1, double l2)
{
setLength(l1, l2,false);
}
/**
* Sets length interval.
*
* @param l1 length min
* @param l2 length max
* @param b hard constraint
*/
private void setLength(double l1, double l2, boolean b)
{
checkLock();
if (LOGGER.isLoggable(Level.FINE))
LOGGER.log(Level.FINE, "("+Integer.toHexString(this.hashCode())+") Setting length; min="+l1+" max="+l2+"; strong constraint: "+b);
lengthMin = l1;
lengthMax = l2;
lengthBool = b;
}
/**
* Sets deflection.
*
* @param d deflection
*/
public final void setDeflection(double d)
{
checkLock();
if (LOGGER.isLoggable(Level.FINE))
LOGGER.log(Level.FINE, "("+Integer.toHexString(this.hashCode())+") Setting deflection to "+d);
deflection = d;
}
/**
* Sets number of segments.
*
* @param n number of segments.
*/
public void setNumber(int n)
{
setNumber(n, false);
}
/**
* Sets number of segments.
*
* @param n number of segments.
* @param b hard constraint
*/
private void setNumber(int n, boolean b)
{
checkLock();
if (LOGGER.isLoggable(Level.FINE))
LOGGER.log(Level.FINE, "("+Integer.toHexString(this.hashCode())+") Setting number of discretized points to "+n+"; strong constraint: "+b);
numberMin = n;
numberMax = n;
numberBool = b;
}
/**
* Sets number of segments.
*
* @param n1 minimal number of segments
* @param n2 maximal number of segments
*/
@SuppressWarnings("unused")
private void setNumber(int n1, int n2)
{
setNumber(n1, n2, false);
}
/**
* Sets number of segments.
*
* @param n1 minimal number of segments
* @param n2 maximal number of segments
* @param b hard constraint
*/
private void setNumber(int n1, int n2, boolean b)
{
checkLock();
if (LOGGER.isLoggable(Level.FINE))
LOGGER.log(Level.FINE, "("+Integer.toHexString(this.hashCode())+") Setting number of discretized points; min="+n1+" max="+n2+"; strong constraint: "+b);
numberMin = n1;
numberMax = n2;
numberBool = b;
}
/**
* Locks the hypothesis so that it cannot be modified.
*/
public void lock()
{
locked = true;
}
private void checkLock()
{
if (locked)
throw new RuntimeException("Cannot modify an Hypothesis after it has been aplied!");
}
private static double combineDouble(double current, double that)
{
if (current < 0.0)
return that;
else if (that < 0.0 || that > current)
return current;
else
return that;
}
/**
* Combines with another hypothesis.
*
* @return <code>true</code> if hypothesis have been successfully combined, <code>false</code> otherwise.
*/
final boolean combine(Hypothesis that)
{
String elt = getElement();
if (elt != null && that.getElement() != null && !elt.equals(that.getElement()))
return false;
length = combineDouble(length, that.length);
lengthMin = combineDouble(lengthMin, that.lengthMin);
lengthMax = combineDouble(lengthMax, that.lengthMax);
deflection = combineDouble(deflection, that.deflection);
lengthBool |= that.lengthBool;
return true;
}
@Override
public final String toString()
{
String ret = "Hyp. "+id+" elementType: "+hyp.getType();
if (length >= 0.0)
ret += " length: "+length;
if (lengthMin >= 0.0)
ret += " lengthMin: "+lengthMin;
if (lengthMax >= 0.0)
ret += " lengthMax: "+lengthMax;
if (lengthBool)
ret += " lengthBool: "+lengthBool;
if (deflection >= 0.0)
ret += " deflection: "+deflection;
if (numberMin >= 0)
ret += " numberMin: "+numberMin;
if (numberMax >= 0)
ret += " numberMax: "+numberMax;
if (numberBool)
ret += " numberBool: "+numberBool;
return ret;
}
final Hypothesis createInheritedHypothesis(CADShapeEnum cse)
{
Hypothesis ret = new Hypothesis();
ret.length = length;
ret.lengthMin = lengthMin;
ret.lengthMax = lengthMax;
ret.lengthBool = lengthBool;
ret.deflection = deflection;
ret.hyp = getAlgo(hyp.impliedType(cse));
return ret;
}
final AlgoInterface findAlgorithm(CADShapeEnum cse)
{
AlgoInterface ret = null;
try {
if (cse == CADShapeEnum.VERTEX)
{
Constructor<Vertex0d> cons = Vertex0d.class.getConstructor();
ret = cons.newInstance();
}
else if (cse == CADShapeEnum.EDGE)
{
Constructor<UniformLengthDeflection1d> cons = UniformLengthDeflection1d.class.getConstructor(double.class, double.class, boolean.class);
ret = cons.newInstance(length, deflection, true);
}
else if (cse == CADShapeEnum.FACE)
{
Constructor<Basic2d> cons = Basic2d.class.getConstructor(double.class, double.class, boolean.class, boolean.class);
ret = cons.newInstance(length, deflection, true, true);
}
else if (cse == CADShapeEnum.SOLID)
{
Constructor<TetGen> cons = TetGen.class.getConstructor(double.class);
ret = cons.newInstance(length);
if (!ret.isAvailable())
LOGGER.severe("TetGen not available!");
/*
Constructor cons = Netgen.class.getConstructor(double.class);
ret = (AlgoInterface) cons.newInstance(length);
if (!ret.isAvailable())
LOGGER.severe("Netgen not available!");
*/
}
} catch (Exception ex)
{
ex.printStackTrace();
System.exit(1);
}
return ret;
}
private static interface HypInterface
{
public String impliedType(CADShapeEnum d);
public String getType();
public CADShapeEnum dim();
}
private static HypInterface getAlgo(String elt)
{
HypInterface h = HypNoneInstance;
if (elt == null)
return h;
try {
for (int i = 0; i < innerClasses.length; i++)
{
if (innerClasses[i].getName().equals(Hypothesis.class.getName()+"$Hyp"+elt))
h = (HypInterface) innerClasses[i].newInstance();
}
} catch (Exception ex) {
ex.printStackTrace();
h = HypNoneInstance;
}
return h;
}
private static class HypNone implements HypInterface
{
public CADShapeEnum dim()
{
return null;
}
public String getType()
{
return null;
}
public String impliedType(CADShapeEnum d)
{
return null;
}
}
@SuppressWarnings("unused")
private static class HypV1 implements HypInterface
{
// Hypothesis.getAlgo() needs access to this constructor
HypV1() {}
public CADShapeEnum dim()
{
return CADShapeEnum.VERTEX;
}
public final String getType()
{
return "V1";
}
public String impliedType(CADShapeEnum d)
{
if (d == CADShapeEnum.VERTEX)
return getType();
return null;
}
}
@SuppressWarnings("unused")
private static class HypE2 implements HypInterface
{
// Hypothesis.getAlgo() needs access to this constructor
HypE2() {}
public CADShapeEnum dim()
{
return CADShapeEnum.EDGE;
}
public final String getType()
{
return "E2";
}
public String impliedType(CADShapeEnum d)
{
if (d == CADShapeEnum.VERTEX)
return "V1";
else if (d == CADShapeEnum.EDGE)
return getType();
else
return null;
}
}
@SuppressWarnings("unused")
private static class HypT3 implements HypInterface
{
// Hypothesis.getAlgo() needs access to this constructor
HypT3() {}
public CADShapeEnum dim()
{
return CADShapeEnum.FACE;
}
public final String getType()
{
return "T3";
}
public String impliedType(CADShapeEnum d)
{
if (d == CADShapeEnum.VERTEX)
return "V1";
else if (d == CADShapeEnum.EDGE)
return "E2";
else if (d == CADShapeEnum.FACE)
return getType();
else
return null;
}
}
@SuppressWarnings("unused")
private static class HypQ4 implements HypInterface
{
// Hypothesis.getAlgo() needs access to this constructor
HypQ4() {}
public CADShapeEnum dim()
{
return CADShapeEnum.FACE;
}
public final String getType()
{
return "Q4";
}
public String impliedType(CADShapeEnum d)
{
if (d == CADShapeEnum.VERTEX)
return "V1";
else if (d == CADShapeEnum.EDGE)
return "E2";
else if (d == CADShapeEnum.FACE)
return getType();
else
return null;
}
}
@SuppressWarnings("unused")
private static class HypT4 implements HypInterface
{
// Hypothesis.getAlgo() needs access to this constructor
HypT4() {}
public CADShapeEnum dim()
{
return CADShapeEnum.SOLID;
}
public final String getType()
{
return "T4";
}
public String impliedType(CADShapeEnum d)
{
if (d == CADShapeEnum.VERTEX)
return "V1";
else if (d == CADShapeEnum.EDGE)
return "E2";
else if (d == CADShapeEnum.FACE)
return "T3";
else if (d == CADShapeEnum.SOLID)
return getType();
else
return null;
}
}
}