/*
* Project Info: http://jcae.sourceforge.net
*
* This program 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 program 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 program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* (C) Copyright 2013, by EADS France
*/
package org.jcae.mesh.amibe.algos3d;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jcae.mesh.amibe.algos2d.Initial;
import org.jcae.mesh.amibe.ds.AbstractHalfEdge;
import org.jcae.mesh.amibe.ds.Mesh;
import org.jcae.mesh.amibe.ds.MeshParameters;
import org.jcae.mesh.amibe.ds.Triangle;
import org.jcae.mesh.amibe.ds.Vertex;
import org.jcae.mesh.amibe.patch.Mesh2D;
import org.jcae.mesh.amibe.patch.Vertex2D;
import org.jcae.mesh.amibe.traits.MeshTraitsBuilder;
import org.jcae.mesh.amibe.traits.TriangleTraitsBuilder;
import org.jcae.mesh.amibe.util.HashFactory;
import org.jcae.mesh.xmldata.Amibe2VTK;
import org.jcae.mesh.xmldata.MeshWriter;
// Jython script exemple to use this class
/*
#! /usr/bin/env jython
import sys
amibe_root='/home/robert/AserisFD/zebra/zebra/jcae/amibe'
sys.path.append(amibe_root+'/dist/amibe.jar')
sys.path.append('/usr/share/java/trove-3.jar')
sys.path.append(amibe_root+'/python')
from org.jcae.mesh.amibe.ds import *
from org.jcae.mesh.amibe.algos3d import *
from org.jcae.mesh.xmldata import *
m = Mesh();
d = Delaunay2D(m, Delaunay2D.Dir.Z, 1);
d.addVertex(0, 0);
d.addVertex(0, 1);
d.addVertex(1, 1);
d.addVertex(1, 0);
d.nextPolyline();
d.addVertex(0.3,0.3);
d.addVertex(0.3,0.7);
d.addVertex(0.7,0.7);
d.addVertex(0.7,0.3);
d.nextPolyline();
d.compute();
MeshWriter.writeObject3D(m, "/tmp/m.amibe", None);
Amibe2VTK("/tmp/m.amibe").write("/tmp/toto.vtp");
*/
/**
* Wrap org.jcae.mesh.amibe.algos2d to make it work on 3D meshes
* @author Jerome Robert
*/
public class Delaunay2D {
private final Dir direction;
private final int group;
public static enum Dir {X, Y, Z};
private List<Vertex> orderedVertices;
private int start;
private final Mesh mesh;
/**
* Create a mesh from a a set of closed polyline.
* More than one polyline can be give to create holes in the created surface.
* The surface is aligned on a principal plane.
* A polyline can be given in the input mesh but in that case the polyline
* must be unique (no holes).
* @param mesh a mesh containging only one closed beam contour
* @param direction The direction of the plane of the surface
*/
public Delaunay2D(Mesh mesh, Dir direction, int group)
{
this.mesh = mesh;
this.direction = direction;
this.group = group;
}
/** Add a new vertex to the current polyline */
public Vertex addVertex(double x, double y)
{
if(orderedVertices == null)
orderedVertices = new ArrayList<Vertex>(1000);
Vertex r;
switch(direction)
{
case X: r = mesh.createVertex(0, x, y); break;
case Y: r = mesh.createVertex(y, 0, x); break;
case Z: r = mesh.createVertex(x, y, 0); break;
default:
throw new IllegalStateException();
}
orderedVertices.add(r);
return r;
}
/** Close the current polyline */
public void nextPolyline()
{
orderedVertices.add(orderedVertices.get(start));
start = orderedVertices.size();
}
public void compute()
{
if(orderedVertices == null)
{
PolylineFactory polylineFactory = new PolylineFactory(mesh, -1, 0, true);
orderedVertices = polylineFactory.get(-1).iterator().next();
compute(orderedVertices, true);
}
else
compute(orderedVertices, false);
}
private void compute(List<Vertex> orderedVertices, boolean closeLoop)
{
Vertex2D[] border = new Vertex2D[orderedVertices.size()+ (closeLoop ? 1 : 0)];
TriangleTraitsBuilder ttb = new TriangleTraitsBuilder();
ttb.addVirtualHalfEdge();
MeshTraitsBuilder mtb = new MeshTraitsBuilder();
mtb.addKdTree(2);
mtb.add(ttb);
Mesh2D m = new Mesh2D(mtb, new MeshParameters(), null);
int k = 0;
Map<Vertex2D, Vertex> v2dTov3d = HashFactory.createMap();
Map<Vertex, Vertex2D> v3dTov2d = HashFactory.createMap();
for(Vertex v: orderedVertices)
{
border[k] = v3dTov2d.get(v);
if(border[k] == null)
{
double uu, vv;
switch(direction)
{
case X: uu = v.getY(); vv = v.getZ(); break;
case Y: uu = v.getZ(); vv = v.getX(); break;
case Z: uu = v.getX(); vv = v.getY(); break;
default:
throw new IllegalStateException();
}
border[k] = (Vertex2D) m.createVertex(uu, vv);
v2dTov3d.put(border[k], v);
v3dTov2d.put(v, border[k]);
}
k++;
}
if(closeLoop)
border[k] = border[0];
new Initial(m, mtb, border, null).compute();
Vertex[] tmp = new Vertex[3];
for(Triangle t:m.getTriangles())
{
k = 0;
if(t.hasAttributes(AbstractHalfEdge.OUTER))
continue;
tmp[k++] = v2dTov3d.get(t.getV0());
tmp[k++] = v2dTov3d.get(t.getV1());
tmp[k++] = v2dTov3d.get(t.getV2());
Triangle t3d = mesh.createTriangle(tmp[0], tmp[1], tmp[2]);
t3d.setGroupId(group);
mesh.add(t3d);
if(mesh.hasNodes())
for(Vertex v:tmp)
mesh.add(v);
}
}
}