package bs.bs2d.fea;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.vecmath.Point2f;
import javax.vecmath.Vector2f;
/**
* Triangular mesh element defined by three nodes as its vertices
* @author Djen
*/
public class TriElement extends MeshEntity{
private Node2D[] nodes;
private Edge[] edges;
public TriElement(int index, Node2D[] nodes) {
globalIndex = index;
this.nodes = Arrays.copyOf(nodes, nodes.length);
edges = new Edge[3];
}
protected TriElement(int index){
globalIndex = index;
}
protected void setEdge(int index, Edge edge){
if(index > 2)
throw new IllegalArgumentException("index out of bounds: " + index);
edges[index] = edge;
}
public Edge getEdge(int index){
if(index > 2)
throw new IllegalArgumentException("index out of bounds: " + index);
return edges[index];
}
public Edge[] getEdges() {
return edges;
}
public Node2D getNode(int index){
if(index > 2)
throw new IllegalArgumentException("index out of bounds: " + index);
return nodes[index];
}
public Node2D[] getNodes() {
return nodes;
}
public List<Node2D> getNodesAsList(){
return Arrays.asList(nodes);
}
public List<Edge> getEdgesAsList(){
return Arrays.asList(edges);
}
public List<Edge> getOuterEdges(){
ArrayList<Edge> elist = new ArrayList<>(3);
for(Edge e : edges){
if(e.isOuter())
elist.add(e);
}
return elist;
}
/**
* @param edge the edge to check
* @return true if this element contains this edge
*/
public boolean containsEdge(Edge edge){
return getEdgesAsList().contains(edge);
}
/**
* @param node the node to check
* @return true if this element contains the given node
*/
public boolean containsNode(Node2D node){
return getNodesAsList().contains(node);
}
/**
* Calculates the inner angle of this element at the given node
* @param node the node for wich to return the angle
* @return the inner angle at the given node
*/
public float getAngleAtNode(Node2D node){
if(!getNodesAsList().contains(node))
throw new IllegalArgumentException("Node is not contained in this "
+ "element: " + node.toString());
Vector2f vnode = new Vector2f(node.getPoint2f());
Vector2f[] vec = new Vector2f[2];
int idx = 0;
for(int i=0; i<3; i++){
if(nodes[i] == node)
continue;
vec[idx] = new Vector2f(nodes[i].getPoint2f());
vec[idx].sub(vnode);
idx++;
}
return vec[0].angle(vec[1]);
}
/**
* switches this elements orientation by exchanging elements 0 and 1 in this
* element's node array.
*/
protected void reorient(){
Node2D n = nodes[0];
nodes[0] = nodes[1];
nodes[1] = n;
}
/**
* Calculates the surface area of this triangular element.
* @return the area of the triangle
*/
public float getArea(){
float area = 0;
area += (nodes[0].getX() + nodes[2].getX()) * (nodes[0].getY() - nodes[2].getY());
area += (nodes[1].getX() + nodes[0].getX()) * (nodes[1].getY() - nodes[0].getY());
area += (nodes[2].getX() + nodes[1].getX()) * (nodes[2].getY() - nodes[1].getY());
return Math.abs(area) / 2;
}
@Override
public String toString() {
return String.format("Element %d [ %d | %d | %d ]", globalIndex,
nodes[0].globalIndex,
nodes[1].globalIndex,
nodes[2].globalIndex);
}
public Shape getShape(){
GeneralPath path = new GeneralPath();
Point2f p = nodes[0].getPoint2f();
path.moveTo(p.x, p.y);
p = nodes[1].getPoint2f();
path.lineTo(p.x, p.y);
p = nodes[2].getPoint2f();
path.lineTo(p.x, p.y);
path.closePath();
return path;
}
}