/* * Copyright 2014 MovingBlocks * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.terasology.math.delaunay; import java.util.ArrayList; import java.util.List; import org.terasology.math.geom.Vector2f; final class EdgeList { private float deltax; private float xmin; private int hashsize; private final List<Halfedge> hash; private Halfedge leftEnd; private Halfedge rightEnd; public EdgeList(float xmin, float deltax, int sqrtNumSites) { this.xmin = xmin; this.deltax = deltax; this.hashsize = 2 * sqrtNumSites; this.hash = new ArrayList<Halfedge>(hashsize); // two dummy Halfedges: leftEnd = Halfedge.createDummy(); rightEnd = Halfedge.createDummy(); leftEnd.edgeListLeftNeighbor = null; leftEnd.edgeListRightNeighbor = rightEnd; rightEnd.edgeListLeftNeighbor = leftEnd; rightEnd.edgeListRightNeighbor = null; for (int i = 0; i < hashsize; i++) { hash.add(null); } hash.set(0, leftEnd); hash.set(hashsize - 1, rightEnd); } /** * Insert newHalfedge to the right of lb * * @param lb * @param newHalfedge * */ public void insert(Halfedge lb, Halfedge newHalfedge) { newHalfedge.edgeListLeftNeighbor = lb; newHalfedge.edgeListRightNeighbor = lb.edgeListRightNeighbor; lb.edgeListRightNeighbor.edgeListLeftNeighbor = newHalfedge; lb.edgeListRightNeighbor = newHalfedge; } /** * This function only removes the Halfedge from the left-right list. We * cannot dispose it yet because we are still using it. * * @param halfEdge * */ public void remove(Halfedge halfEdge) { halfEdge.edgeListLeftNeighbor.edgeListRightNeighbor = halfEdge.edgeListRightNeighbor; halfEdge.edgeListRightNeighbor.edgeListLeftNeighbor = halfEdge.edgeListLeftNeighbor; halfEdge.edge = Edge.DELETED; halfEdge.edgeListLeftNeighbor = null; halfEdge.edgeListRightNeighbor = null; } /** * Find the rightmost Halfedge that is still left of p * * @param p * @return * */ public Halfedge edgeListLeftNeighbor(Vector2f p) { int i; int bucket; Halfedge halfEdge; /* Use hash table to get close to desired halfedge */ bucket = (int) ((p.getX() - xmin) / deltax * hashsize); if (bucket < 0) { bucket = 0; } if (bucket >= hashsize) { bucket = hashsize - 1; } halfEdge = getHash(bucket); if (halfEdge == null) { for (i = 1; true; ++i) { halfEdge = getHash(bucket - i); if (halfEdge != null) { break; } halfEdge = getHash(bucket + i); if (halfEdge != null) { break; } } } /* Now search linear list of halfedges for the correct one */ if (halfEdge == leftEnd || (halfEdge != rightEnd && halfEdge.isLeftOf(p))) { do { halfEdge = halfEdge.edgeListRightNeighbor; } while (halfEdge != rightEnd && halfEdge.isLeftOf(p)); halfEdge = halfEdge.edgeListLeftNeighbor; } else { do { halfEdge = halfEdge.edgeListLeftNeighbor; } while (halfEdge != leftEnd && !halfEdge.isLeftOf(p)); } /* Update hash table and reference counts */ if (bucket > 0 && bucket < hashsize - 1) { hash.set(bucket, halfEdge); } return halfEdge; } /** * Get entry from hash table, pruning any deleted nodes */ private Halfedge getHash(int b) { Halfedge halfEdge; if (b < 0 || b >= hashsize) { return null; } halfEdge = hash.get(b); if (halfEdge != null && halfEdge.edge == Edge.DELETED) { /* Hash table points to deleted halfedge. Patch as necessary. */ hash.set(b, null); // still can't dispose halfEdge yet! return null; } else { return halfEdge; } } }