/*
* Copyright (c) 2005 by L. Paul Chew.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package org.openjump.core.graph.delauneySimplexInsert;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* A Triangulation on vertices (generic type V).
* A Triangulation is a set of Simplices (see Simplex below).
* For efficiency, we keep track of the neighbors of each Simplex.
* Two Simplices are neighbors of they share a facet.
*
* @author Paul Chew
*
* Created July 2005. Derived from an earlier, messier version.
*/
public class Triangulation {
private HashMap neighbors; // Maps Simplex to Set of neighbors
/**
* Constructor.
* @param simplex the initial Simplex.
*/
public Triangulation (Simplex simplex) {
neighbors = new HashMap();
neighbors.put(simplex, new HashSet());
}
/**
* String representation.
* Shows number of simplices currently in the Triangulation.
* @return a String representing the Triangulation
*/
public String toString () {
return "Triangulation (with " + neighbors.size() + " elements)";
}
/**
* Size (# of Simplices) in Triangulation.
* @return the number of Simplices in this Triangulation
*/
public int size () {
return neighbors.size();
}
/**
* True iff the simplex is in this Triangulation.
* @param simplex the simplex to check
* @return true iff the simplex is in this Triangulation
*/
public boolean contains (Simplex simplex) {
return this.neighbors.containsKey(simplex);
}
/**
* Iterator.
* @return an iterator for every Simplex in the Triangulation
*/
public Iterator iterator () {
return Collections.unmodifiableSet(this.neighbors.keySet()).iterator();
}
/**
* Print stuff about a Triangulation.
* Used for debugging.
*/
public void printStuff () {
boolean remember = Simplex.moreInfo;
System.out.println("Neighbor data for " + this);
for (Iterator it = neighbors.keySet().iterator(); it.hasNext();) {
Simplex simplex = (Simplex) it.next();
Simplex.moreInfo = true;
System.out.print(" " + simplex + ":");
Simplex.moreInfo = false;
for (Iterator otherIt = ((Set) neighbors.get(simplex)).iterator();
otherIt.hasNext();)
System.out.print(" " + otherIt.next());
System.out.println();
}
Simplex.moreInfo = remember;
}
/* Navigation */
/**
* Report neighbor opposite the given vertex of simplex.
* @param vertex a vertex of simplex
* @param simplex we want the neighbor of this Simplex
* @return the neighbor opposite vertex of simplex; null if none
* @throws IllegalArgumentException if vertex is not in this Simplex
*/
public Simplex neighborOpposite (Object vertex, Simplex simplex) {
if (!simplex.contains(vertex))
throw new IllegalArgumentException("Bad vertex; not in simplex");
SimplexLoop: for (Iterator it = ((Set) neighbors.get(simplex)).iterator();
it.hasNext();) {
Simplex s = (Simplex) it.next();
for (Iterator otherIt = simplex.iterator(); otherIt.hasNext(); ) {
Object v = otherIt.next();
if (v.equals(vertex)) continue;
if (!s.contains(v)) continue SimplexLoop;
}
return s;
}
return null;
}
/**
* Report neighbors of the given simplex.
* @param simplex a Simplex
* @return the Set of neighbors of simplex
*/
public Set neighbors (Simplex simplex) {
return new HashSet((Set) this.neighbors.get(simplex));
}
/* Modification */
/**
* Update by replacing one set of Simplices with another.
* Both sets of simplices must fill the same "hole" in the
* Triangulation.
* @param oldSet set of Simplices to be replaced
* @param newSet set of replacement Simplices
*/
public void update (Set oldSet,
Set newSet) {
// Collect all simplices neighboring the oldSet
Set allNeighbors = new HashSet();
for (Iterator it = oldSet.iterator(); it.hasNext();)
allNeighbors.addAll((Set) neighbors.get((Simplex) it.next()));
// Delete the oldSet
for (Iterator it = oldSet.iterator(); it.hasNext();) {
Simplex simplex = (Simplex) it.next();
for (Iterator otherIt = ((Set) neighbors.get(simplex)).iterator();
otherIt.hasNext();)
((Set) neighbors.get(otherIt.next())).remove(simplex);
neighbors.remove(simplex);
allNeighbors.remove(simplex);
}
// Include the newSet simplices as possible neighbors
allNeighbors.addAll(newSet);
// Create entries for the simplices in the newSet
for (Iterator it = newSet.iterator(); it.hasNext();)
neighbors.put((Simplex) it.next(), new HashSet());
// Update all the neighbors info
for (Iterator it = newSet.iterator(); it.hasNext();) {
Simplex s1 = (Simplex) it.next();
for (Iterator otherIt = allNeighbors.iterator(); otherIt.hasNext();) {
Simplex s2 = (Simplex) otherIt.next();
if (!s1.isNeighbor(s2)) continue;
((Set) neighbors.get(s1)).add(s2);
((Set) neighbors.get(s2)).add(s1);
}
}
}
}