Skip to content

Commit

Permalink
Add SkeletonProjector & use it in MeshLiaison
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromerobert committed Sep 25, 2019
1 parent f804082 commit 20477c6
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 8 deletions.
25 changes: 22 additions & 3 deletions amibe/src/org/jcae/mesh/amibe/algos3d/RemeshSkeleton.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
Expand Down Expand Up @@ -114,6 +115,7 @@ public void compute()
EdgesCollapserNG edgeCollapser = new EdgesCollapserNG(mesh);
main: for(List<Vertex> polyline: skeleton.getPolylinesVertices())
{
int[] groups = null;
RemeshPolyline rp = new RemeshPolyline(mesh, polyline, metric);
rp.setBuildBackgroundLink(true);
List<Vertex> toInsert = rp.compute();
Expand Down Expand Up @@ -160,9 +162,14 @@ else if(dd <= tolerance)
Vertex oldDestination = toSplit.destination();
mesh.vertexSplit(toSplit, v);
liaison.addVertex(v, toSplit.getTri());
//TODO this will be slow as as toSplit.getTri() may be far
//from the wanted triangle so we will loop on all triangles
liaison.move(v, v, true);
if(groups == null) {
// Lazily get the list of groups which is the same for all edges of this polyline
groups = getGroups(toSplit);
} else {
assert(Arrays.equals(groups, getGroups(toSplit)));
}
boolean r = liaison.moveToClosestEdge(v, groups);
assert(r);
AbstractHalfEdge e = getEdge(v, oldDestination);
edgeIndex.set(segId, e);
swapVolume = m2 * m2 * m2 / 64;
Expand All @@ -178,6 +185,18 @@ else if(dd <= tolerance)
}
}

private static int[] getGroups(AbstractHalfEdge edge) {
Iterator<AbstractHalfEdge> it = edge.fanIterator();
List<Integer> r = new ArrayList<Integer>();
while(it.hasNext()) {
r.add(it.next().getTri().getGroupId());
}
// convert the ArrayList to int[]
int[] rr = new int[r.size()];
for(int i = 0; i < rr.length; i++)
rr[i] = r.get(i);
return rr;
}
public static void main(final String[] args) {
try {
Mesh mesh = new Mesh();
Expand Down
40 changes: 40 additions & 0 deletions amibe/src/org/jcae/mesh/amibe/metrics/Location.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,44 @@ public double distance3D(Location end)
public String toString() {
return "(" + x + ", " + y + ", " + z + ")";
}

public static double dot(double[] v1, double[] v2)
{
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}

/**
* Return the distance between this and an edge
* @param origin the origin of the edge
* @param destination the destination of the edge
* @param projection the projection of this on the edge
* @return the square of the distance
*/
public double sqrDistance3D(Location origin, Location destination, Location projection) {
// adapted from https://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistPointSegment.h
double direction[] = new double[3];
destination.sub(origin, direction);
double diff[] = new double[3];
sub(destination, diff);
if(dot(direction, diff) < 0) {
projection.moveTo(origin);
sub(origin, diff);
double t = dot(direction, diff);
if (t > 0) {
double sqrLength = dot(direction, direction);
if (sqrLength > 0) {
t /= sqrLength;
projection.moveTo(
origin.getX() + t * direction[0],
origin.getY() + t * direction[1],
origin.getZ() + t * direction[2]);
}
}
} else {
projection.moveTo(destination);
}

sub(projection, diff);
return dot(diff, diff);
}
}
21 changes: 16 additions & 5 deletions amibe/src/org/jcae/mesh/amibe/projection/MeshLiaison.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jcae.mesh.amibe.metrics.Location;
import static org.jcae.mesh.amibe.metrics.Location.dot;
import org.jcae.mesh.amibe.util.HashFactory;

public abstract class MeshLiaison
Expand All @@ -49,6 +50,7 @@ public abstract class MeshLiaison
protected final Mesh backgroundMesh;
protected final Mesh currentMesh;
private Skeleton skeleton;
private SkeletonProjector skeletonProjector;

protected final double [] work1 = new double[3];
protected final double [] work2 = new double[3];
Expand Down Expand Up @@ -229,6 +231,20 @@ public final boolean move(Vertex v, Location target, int group, boolean doCheck)

protected abstract boolean move(Vertex v, Location target, boolean backup, int group, boolean doCheck);

/**
* Get the projection of a vertex on the closest edge of the skeleton (list of edge which are non-manifold or
* border of groups)
* @param v the vertex being projected
* @param groups the list of adjacent groups around the edge (all edges will be tested if empty)
* @return true if a projection has been found
*/
public boolean moveToClosestEdge(Vertex v, int ... groups) {
if(skeletonProjector == null) {
skeletonProjector = new SkeletonProjector(backgroundMesh);
}
return skeletonProjector.moveToClosestEdge(v, groups);
}

public final boolean project(Vertex v, Location target, Vertex start)
{
throw new RuntimeException("Not implemented yet");
Expand Down Expand Up @@ -598,11 +614,6 @@ private static double norm2(double[] v)
return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
}

private static double dot(double[] v1, double[] v2)
{
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}

public static class TriangleDistance
{
private double s, t;
Expand Down
64 changes: 64 additions & 0 deletions amibe/src/org/jcae/mesh/amibe/projection/SkeletonProjector.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* jCAE stand for Java Computer Aided Engineering. Features are : Small CAD
modeler, Finite element mesher, Plugin architecture.
Copyright (C) 2019, by Airbus S.A.S.
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.projection;

import org.jcae.mesh.amibe.algos3d.Skeleton;
import org.jcae.mesh.amibe.ds.AbstractHalfEdge;
import org.jcae.mesh.amibe.ds.Mesh;
import org.jcae.mesh.amibe.ds.Vertex;
import org.jcae.mesh.amibe.metrics.Location;

import java.util.Collection;
import java.util.List;

/** Project points on the skeleton of a mesh */
public class SkeletonProjector {
private final Skeleton skeleton;

public SkeletonProjector(Mesh mesh) {
skeleton = new Skeleton(mesh, 0);
}

public boolean moveToClosestEdge(Vertex v, int[] groups) {
Collection<List<AbstractHalfEdge>> polylines;
if(groups.length == 0)
polylines = skeleton.getPolylines();
else
polylines = skeleton.getPolylines(groups);
double minDistSqr = Double.POSITIVE_INFINITY;
Location projection = new Location();
Location bestProjection = new Location();
boolean found = false;
// TODO: This is O(n) for each vertex so O(n^2) to move all vertices. If this is too slow we should rework
// TriangleKdTree to ObjectKdTree<Triangle or AbstractHalfEdge> and use it to find the closest edge.
for(List<AbstractHalfEdge> p: polylines) {
for(AbstractHalfEdge edge: p) {
double distSqr = v.sqrDistance3D(edge.origin(), edge.destination(), projection);
if(distSqr < minDistSqr) {
found = true;
bestProjection.moveTo(projection);
minDistSqr = distSqr;
}
}
}
v.moveTo(bestProjection);
return found;
}
}

0 comments on commit 20477c6

Please sign in to comment.