/* 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,2011, 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.traits; import org.jcae.mesh.amibe.ds.Triangle; import org.jcae.mesh.amibe.ds.Vertex; import org.jcae.mesh.amibe.ds.TraceInterface; import org.jcae.mesh.amibe.ds.TraceNull; import org.jcae.mesh.amibe.ds.TraceRecord; import org.jcae.mesh.amibe.ds.TraceReplay; import org.jcae.mesh.amibe.metrics.KdTree; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.Collection; public class MeshTraitsBuilder extends TraitsBuilder { // TraitsBuilder already uses bits 0-7 private static final int BITTRIANGLES = 8; private static final int BITNODES = 9; private static final int BITGROUPS = 10; private static final int BITKDTREE = 11; private static final int BITTRACE = 12; private static final int TRIANGLES = 1 << BITTRIANGLES; private static final int NODES = 1 << BITNODES; private static final int GROUPLIST = 1 << BITGROUPS; private static final int KDTREE = 1 << BITKDTREE; private static final int TRACE = 1 << BITTRACE; private static final int TRACEREPLAY = 1 << 29; private static final int TRIANGLESET = 1 << 30; private static final int NODESET = 1 << 31; private VertexTraitsBuilder vertexTraitsBuilder = new VertexTraitsBuilder(); private HalfEdgeTraitsBuilder halfedgeTraitsBuilder = new HalfEdgeTraitsBuilder(); private TriangleTraitsBuilder triangleTraitsBuilder = new TriangleTraitsBuilder(); private int dimension; private final TraceInterface singletonTraceNull = new TraceNull(); /** * Constructor. */ public MeshTraitsBuilder() { super(); attributes |= TRIANGLES; } /** * Adds triangle list to mesh traits. * * @return this instance */ public final MeshTraitsBuilder addTriangleList() { attributes &= ~TRIANGLESET; return this; } /** * Adds triangle set to mesh traits. * * @return this instance */ public final MeshTraitsBuilder addTriangleSet() { attributes |= TRIANGLESET; return this; } /** * Returns collection of triangles. * * @param t mesh traits * @return collection of triangles */ @SuppressWarnings("unchecked") public final Collection<Triangle> getTriangles(Traits t) { return (Collection<Triangle>) t.array[index[BITTRIANGLES]]; } /** * Tells whether mesh traits stores collection of triangles. This method * always returns <code>true</code> because our data structure is based on * triangles. * * @return <code>true</code> */ public final boolean hasTriangles() { return true; } /** * Adds node list to mesh traits. * * @return this instance */ public final MeshTraitsBuilder addNodeList() { attributes |= NODES; attributes &= ~NODESET; return this; } /** * Adds node set to mesh traits. * * @return this instance */ public final MeshTraitsBuilder addNodeSet() { attributes |= NODES; attributes |= NODESET; return this; } /** * Returns collection of nodes. * * @param t mesh traits * @return collection of nodes */ @SuppressWarnings("unchecked") public final Collection<Vertex> getNodes(Traits t) { if ((attributes & NODES) != 0) return (Collection<Vertex>) t.array[index[BITNODES]]; return null; } /** * Tells whether mesh traits stores collection of nodes. * * @return <code>true</code> if {@link #addNodeList} or {@link #addNodeSet} * was called, <code>false</code> otherwise. */ public final boolean hasNodes() { return hasCapability(NODES); } public final boolean hasTrace() { return hasCapability(TRACE); } /** * Adds group list to mesh traits. * * @return this instance */ public MeshTraitsBuilder addGroupList() { attributes |= GROUPLIST; return this; } /** * Returns collection of groups. * * @param t mesh traits * @return collection of groups */ public Collection getGroups(Traits t) { if ((attributes & GROUPLIST) != 0) return (Collection) t.array[index[BITGROUPS]]; return null; } /** * Adds {@link KdTree} instance to mesh traits. * * @return this instance */ public final MeshTraitsBuilder addKdTree(int d) { attributes |= KDTREE; dimension = d; return this; } /** * Returns {@link KdTree} instance. * * @param t mesh traits * @return {@link KdTree} instance */ public final KdTree getKdTree(Traits t) { if ((attributes & KDTREE) != 0) return (KdTree) t.array[index[BITKDTREE]]; return null; } /** * Adds {@link KdTree} instance to mesh traits. * * @return this instance */ public final MeshTraitsBuilder addTraceRecord() { attributes |= TRACE; attributes &= ~TRACEREPLAY; return this; } public final MeshTraitsBuilder addTraceReplay() { attributes |= TRACE | TRACEREPLAY; return this; } public final TraceInterface getTrace(Traits t) { if ((attributes & TRACE) != 0) return (TraceInterface) t.array[index[BITTRACE]]; return singletonTraceNull; } @Override protected void subInitTraits(Traits t) { // These methods must be synchronized with ensureCapacity() if ((attributes & TRIANGLESET) != 0) t.array[index[BITTRIANGLES]] = new LinkedHashSet<Triangle>(); else if ((attributes & TRIANGLES) != 0) t.array[index[BITTRIANGLES]] = new ArrayList<Triangle>(); if ((attributes & NODESET) != 0) t.array[index[BITNODES]] = new LinkedHashSet<Vertex>(); else if ((attributes & NODES) != 0) t.array[index[BITNODES]] = new ArrayList<Vertex>(); if ((attributes & GROUPLIST) != 0) t.array[index[BITGROUPS]] = new ArrayList(); if ((attributes & KDTREE) != 0) t.array[index[BITKDTREE]] = new KdTree(dimension); if ((attributes & TRACE) != 0) { if ((attributes & TRACEREPLAY) != 0) t.array[index[BITTRACE]] = new TraceReplay(); else t.array[index[BITTRACE]] = new TraceRecord(); } } /** * Resizes internal collections of vertices and triangles. * * @param triangles desired number of triangles * @param t mesh traits */ public final void ensureCapacity(int triangles, Traits t) { // These methods must be synchronized with subInitTraits() if ((attributes & TRIANGLESET) != 0) { Collection<Triangle> oldList = (Collection<Triangle>) t.array[index[BITTRIANGLES]]; if (oldList.size() < triangles) { LinkedHashSet<Triangle> newList = new LinkedHashSet<Triangle>(triangles); newList.addAll(oldList); oldList.clear(); t.array[index[BITTRIANGLES]] = newList; } } else if ((attributes & TRIANGLES) != 0) { ArrayList<Triangle> oldList = (ArrayList<Triangle>) t.array[index[BITTRIANGLES]]; oldList.ensureCapacity(triangles); } int nodes = (int) (0.51 * triangles); if ((attributes & NODESET) != 0) { Collection<Vertex> oldList = (Collection<Vertex>) t.array[index[BITNODES]]; if (oldList.size() < nodes) { LinkedHashSet<Vertex> newList = new LinkedHashSet<Vertex>(nodes); newList.addAll(oldList); oldList.clear(); t.array[index[BITNODES]] = newList; } } else if ((attributes & NODES) != 0) { ArrayList<Triangle> oldList = (ArrayList<Triangle>) t.array[index[BITNODES]]; oldList.ensureCapacity(nodes); } } /** * Adds {@link VertexTraitsBuilder}, {@link HalfEdgeTraitsBuilder} or {@link TriangleTraitsBuilder} * instance to current mesh traits. * * @param t traits builder * @return {@link KdTree} instance */ public final MeshTraitsBuilder add(TraitsBuilder t) { if (t instanceof VertexTraitsBuilder) vertexTraitsBuilder = (VertexTraitsBuilder) t; else if (t instanceof HalfEdgeTraitsBuilder) halfedgeTraitsBuilder = (HalfEdgeTraitsBuilder) t; else if (t instanceof TriangleTraitsBuilder) triangleTraitsBuilder = (TriangleTraitsBuilder) t; else throw new RuntimeException(); return this; } /** * Returns {@link VertexTraitsBuilder} instance. * * @return {@link VertexTraitsBuilder} instance */ public final VertexTraitsBuilder getVertexTraitsBuilder() { return vertexTraitsBuilder; } /** * Returns {@link HalfEdgeTraitsBuilder} instance. * * @return {@link HalfEdgeTraitsBuilder} instance */ public final HalfEdgeTraitsBuilder getHalfEdgeTraitsBuilder() { return halfedgeTraitsBuilder; } /** * Returns {@link TriangleTraitsBuilder} instance. * * @return {@link TriangleTraitsBuilder} instance */ public final TriangleTraitsBuilder getTriangleTraitsBuilder() { return triangleTraitsBuilder; } /** * Returns default 2D <code>MeshTraitsBuilder</code> instance. This instance * calls following methods: {@link #addTriangleList}, {@link #addKdTree} * and {@link TriangleTraitsBuilder#addVirtualHalfEdge}. It is implicitly used when * calling {@link org.jcae.mesh.amibe.patch.Mesh2D} constructor without * {@link MeshTraitsBuilder} argument. */ public static MeshTraitsBuilder getDefault2D() { MeshTraitsBuilder ret = new MeshTraitsBuilder(); ret.addTriangleList(); ret.addKdTree(2); ret.triangleTraitsBuilder = new TriangleTraitsBuilder(); ret.triangleTraitsBuilder.addVirtualHalfEdge(); return ret; } /** * Returns default 3D <code>MeshTraitsBuilder</code> instance. This instance * calls following methods: {@link #addTriangleSet} and * {@link TriangleTraitsBuilder#addHalfEdge}. It is implicitly used when * calling {@link org.jcae.mesh.amibe.ds.Mesh} constructor without * {@link MeshTraitsBuilder} argument. */ public static MeshTraitsBuilder getDefault3D() { MeshTraitsBuilder ret = new MeshTraitsBuilder(); ret.addTriangleSet(); ret.triangleTraitsBuilder = new TriangleTraitsBuilder(); ret.triangleTraitsBuilder.addHalfEdge(); return ret; } }