/* 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,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 gnu.trove.set.hash.TCustomHashSet;
import org.jcae.mesh.cad.CADShape;
import org.jcae.mesh.cad.CADShapeFactory;
import org.jcae.mesh.cad.CADShapeEnum;
import org.jcae.mesh.cad.CADExplorer;
import org.jcae.mesh.cad.CADIterator;
import java.util.Collection;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Iterator;
import gnu.trove.set.hash.THashSet;
import java.util.Collections;
/**
* Graph cell. This class is a decorator for the CAD graph.
*/
public class BCADGraphCell
{
/**
* Unique identifier.
*/
private int id = -1;
/**
* Link to root graph.
*/
private final BCADGraph graph;
/**
* CAD shape.
*/
private final CADShape shape;
/**
* CAD shape type.
*/
private final CADShapeEnum type;
/**
* Link to the reversed shape, if it does exist.
*/
private BCADGraphCell reversed;
/**
* List of parents.
*/
private final Collection<BCADGraphCell> parents = new LinkedHashSet<BCADGraphCell>();
/**
* List of discretizations.
*/
private Collection<BDiscretization> discrete = new ArrayList<BDiscretization>();
/**
* Constructor.
* @param g graph cell
* @param s CAD shape contained in this cell
* @param t CAD shape type
*/
protected BCADGraphCell (BCADGraph g, CADShape s, CADShapeEnum t)
{
graph = g;
shape = s;
type = t;
}
/**
* Returns cell id.
* @return cell id
*/
public final int getId()
{
return id;
}
/**
* Sets cell id.
* @param i cell id
*/
public final void setId(int i)
{
id = i;
}
/**
* Returns CAD graph.
* @return CAD graph
*/
public final BCADGraph getGraph()
{
return graph;
}
/**
* Returns CAD shape.
* @return CAD shape
*/
public final CADShape getShape()
{
return shape;
}
/**
* Returns shape orientation.
* @return shape orientation
*/
public final int getOrientation()
{
return shape.orientation();
}
/**
* Returns cell containing reversed shape.
* @return cell containing reversed shape
*/
public final BCADGraphCell getReversed()
{
return reversed;
}
/**
* Returns CAD shape type.
* @return CAD shape type
*/
public final CADShapeEnum getType()
{
return type;
}
public final Collection<BCADGraphCell> getParents()
{
return Collections.unmodifiableCollection(parents);
}
final void addParent(BCADGraphCell that)
{
assert that != null;
parents.add(that);
}
/**
* Binds two cells containing reversed shapes together. These shapes then
* contain the same discretizations.
*/
final void bindReversed(BCADGraphCell that)
{
assert shape.equals(that.shape);
assert shape.orientation() != that.shape.orientation();
reversed = that;
that.reversed = this;
if (shape.orientation() != 0)
discrete = that.discrete;
else
that.discrete = discrete;
}
/**
* Returns an iterator on geometrical elements of a given type.
* CAD graph is traversed recursively and geometrical elements of
* a given type are returned. There are no duplicates, but shapes
* with different orientations may both be listed.
*
* @param cse CAD shape type
* @return iterator on geometrical elements.
*/
public final Iterator<BCADGraphCell> shapesExplorer(CADShapeEnum cse)
{
return shapesExplorer(cse, new TCustomHashSet<CADShape>(
KeepOrientationHashingStrategy.getInstance()));
}
/**
* Returns an iterator on unique geometrical elements.
* CAD graph is traversed recursively and geometrical elements of a
* given type are returned. There are no duplicates, shapes with
* different orientations are listed only once.
*
* @param cse CAD shape type
* @return iterator on unique geometrical elements.
*/
public final Iterator<BCADGraphCell> uniqueShapesExplorer(CADShapeEnum cse)
{
return shapesExplorer(cse, new THashSet<CADShape>());
}
/**
* Returns an iterator on all geometrical elements of a given type.
* CAD graph is traversed recursively and geometrical elements of a
* given type are returned, even if they have already been seen.
*
* @param cse CAD shape type
* @return iterator on all geometrical elements.
*/
public Iterator<BCADGraphCell> allShapesExplorer(CADShapeEnum cse)
{
return shapesExplorer(cse, null);
}
private Iterator<BCADGraphCell> shapesExplorer(final CADShapeEnum cse, final Collection<CADShape> cadShapeSet)
{
final CADExplorer exp = CADShapeFactory.getFactory().newExplorer();
exp.init(shape, cse);
return new Iterator<BCADGraphCell>()
{
public boolean hasNext()
{
return exp.more();
}
public BCADGraphCell next()
{
CADShape curr = exp.current();
BCADGraphCell ret = graph.getByShape(curr);
if (cadShapeSet == null)
{
if (exp.more())
exp.next();
}
else
{
cadShapeSet.add(curr);
while (exp.more())
{
if (!cadShapeSet.contains(exp.current()))
break;
exp.next();
}
}
return ret;
}
public void remove()
{
}
};
}
/**
* Returns an iterator on immediate sub-shapes.
* There are no duplicates, but shapes with different orientations may
* both be listed.
*
* @return an iterator on immediate sub-shapes
*/
public final Iterator<BCADGraphCell> shapesIterator()
{
return shapesIterator(new TCustomHashSet<CADShape>(
KeepOrientationHashingStrategy.getInstance()));
}
/**
* Returns an iterator on immediate sub-shapes.
* There are no duplicates, shapes with different orientations are
* listed only once.
*
* @return an iterator on immediate sub-shapes
*/
public Iterator<BCADGraphCell> uniqueShapesIterator()
{
return shapesIterator(new THashSet<CADShape>());
}
/**
* Returns an iterator on all immediate sub-shapes.
*
* @return an iterator on all immediate sub-shapes
*/
public final Iterator<BCADGraphCell> allShapesIterator()
{
return shapesIterator(null);
}
private Iterator<BCADGraphCell> shapesIterator(final Collection<CADShape> cadShapeSet)
{
final CADIterator it = CADShapeFactory.getFactory().newIterator();
it.initialize(shape);
return new Iterator<BCADGraphCell>()
{
public boolean hasNext()
{
return it.more();
}
public BCADGraphCell next()
{
CADShape curr = it.value();
BCADGraphCell ret = graph.getByShape(curr);
if (cadShapeSet == null)
{
if (it.more())
it.next();
}
else
{
cadShapeSet.add(curr);
while (it.more())
{
if (!cadShapeSet.contains(it.value()))
break;
it.next();
}
}
return ret;
}
public void remove()
{
}
};
}
/**
* Returns the BDiscretization instance corresponding to a given submesh.
*
* @param sub submesh
* @return the discretization corresponding to a given submesh.
*/
public final BDiscretization getDiscretizationSubMesh(BSubMesh sub)
{
for (BDiscretization discr : discrete)
{
if (discr.contains(sub))
return discr;
}
return null;
}
final void addSubMeshConstraint(BSubMesh sub, Constraint cons)
{
BDiscretization d = getDiscretizationSubMesh(sub);
if (d != null)
throw new RuntimeException("Constraint "+cons+" cannot be applied to shape "+shape+", another constraint "+d.getConstraint()+" is already defined");
BDiscretization found = null;
for (BDiscretization discr : discrete)
{
if (discr.getConstraint() == cons)
{
found = discr;
break;
}
}
if (found == null)
{
found = new BDiscretization(this, cons);
discrete.add(found);
}
found.addSubMesh(sub);
}
final void removeSubMeshConstraint(BSubMesh sub, Constraint cons)
{
BDiscretization d = getDiscretizationSubMesh(sub);
if (d == null)
throw new RuntimeException("Constraint "+cons+" cannot be removed from shape "+shape+", beacause it doesn't exist");
discrete.remove(d);
}
/**
* Returns an immutable view of the list of BDiscretization instances bound to this cell.
*/
public final Collection<BDiscretization> getDiscretizations()
{
return Collections.unmodifiableCollection(discrete);
}
final void addImplicitConstraints(CADShapeEnum cse, boolean recursive)
{
for (BDiscretization discr : discrete)
{
Iterator<BCADGraphCell> itc;
if (recursive)
itc = shapesExplorer(cse);
else
itc = shapesIterator();
while (itc.hasNext())
{
BCADGraphCell child = itc.next();
if (!recursive && child.getType() != cse)
continue;
boolean allIntersectionsEmpty = false;
BDiscretization discrChild = null;
for (BDiscretization dc : child.discrete)
{
if (!discr.emptyIntersection(dc))
{
discrChild = dc;
break;
}
}
if (discrChild == null)
{
discrChild = new BDiscretization(child, null);
child.discrete.add(discrChild);
allIntersectionsEmpty = true;
}
discrChild.combineConstraint(discr);
discrChild.addAllSubMeshes(discr);
/*
* We want to ensure that in each BCADGraphCell, the intersection of
* the submeshes list for any two different BDiscretization is void.
*
* If a new BDiscretization has been created, there is no need to
* perform an additionnal test to enforce this.
* But if we had an intersection between the submesh list of discr and
* the one of discrChild, we have to check if the combined BDiscretization
* has an intersection with other child BDiscretization.
* The other child BDiscretization that intersect discrChild has to be removed
* after combination with discrChild.
*/
if (!allIntersectionsEmpty)
{
for (Iterator<BDiscretization> itd = child.discrete.iterator(); itd.hasNext(); )
{
BDiscretization otherDiscrChild = itd.next();
if ((otherDiscrChild != discrChild) &&
(!discrChild.emptyIntersection(otherDiscrChild)))
{
discrChild.combineConstraint(otherDiscrChild);
discrChild.addAllSubMeshes(otherDiscrChild);
itd.remove();
}
}
}
}
}
}
final void removeDiscretizations()
{
discrete.clear();
}
@Override
public final String toString()
{
String ret = id+" "+shape+" "+shape.orientation()+" "+Integer.toHexString(hashCode());
if (reversed != null)
ret += " rev="+Integer.toHexString(reversed.hashCode());
return ret;
}
}