All Downloads are FREE. Search and download functionalities are using the official Maven repository.

signalprocesser.voronoi.statusstructure.VLinkedNode Maven / Gradle / Ivy

/*
 * "Concave" hulls by Glenn Hudson and Matt Duckham
 *
 * Source code downloaded from https://archive.md/l3Un5#selection-571.0-587.218 on 3rd November 2021.
 *
 * - This software is Copyright (C) 2008 Glenn Hudson released under Gnu Public License (GPL). Under 
 *   GPL you are free to use, modify, and redistribute the software. Please acknowledge Glenn Hudson 
 *   and Matt Duckham as the source of this software if you do use or adapt the code in further research 
 *   or other work. For full details of GPL see http://www.gnu.org/licenses/gpl-3.0.txt.
 * - This software comes with no warranty of any kind, expressed or implied.
 * 
 * A paper with full details of the characteristic hulls algorithm is published in Pattern Recognition.
 * Duckham, M., Kulik, L., Worboys, M.F., Galton, A. (2008) Efficient generation of simple polygons for
 * characterizing the shape of a set of points in the plane. Pattern Recognition v41, 3224-3236
 *
 * The software was developed by Glenn Hudson while working with me as an RA. The characteristic shapes 
 * algorithm is collaborative work between Matt Duckham, Lars Kulik, Antony Galton, and Mike Worboys.
 * 
 */

package signalprocesser.voronoi.statusstructure;

import java.util.ArrayList;

import signalprocesser.voronoi.VPoint;
import signalprocesser.voronoi.VoronoiShared;
import signalprocesser.voronoi.eventqueue.EventQueue;
import signalprocesser.voronoi.eventqueue.VCircleEvent;
import signalprocesser.voronoi.eventqueue.VSiteEvent;

public class VLinkedNode {
    
    /* ***************************************************** */
    // Variables
    
    public VSiteEvent siteevent;
    
    private VLinkedNode prev;
    private VLinkedNode next;
    
    private ArrayList circleevents;
    
    /* ***************************************************** */
    // Constructors
    
    protected VLinkedNode() { }
    public VLinkedNode(VSiteEvent _siteevent) {
        this.siteevent = _siteevent;
    }
    
    /* ***************************************************** */
    // Methods
    
    public boolean hasCircleEvents() {
        return ( circleevents!=null && circleevents.size()>0 );
    }
    public ArrayList getCircleEvents() { return circleevents; }
    public void removeCircleEvents(EventQueue eventqueue) {
        if ( circleevents==null ) return;
        
        for ( VCircleEvent circleevent : circleevents ) {
            // Unlink to leaf node
            circleevent.leafnode = null;
            
            // Remove from queue
            boolean flag = eventqueue.removeEvent( circleevent );
            // IGNORE FLAG - errors being thrown as a result of using
            //  this flag from circle events when this method is called...
            //if ( flag==false ) {
            //    throw new RuntimeException("Event not removed from queue when expected to be able to.");
            //}
        }
        circleevents = null;
    }
    
    public void addCircleEvent(EventQueue eventqueue) {
        if ( prev!=null && next!=null ) {
            VCircleEvent circleevent = VoronoiShared.calculateCenter(prev.siteevent, this.siteevent, next.siteevent);
            if ( circleevent!=null ) {
                addCircleEvent( circleevent );
                circleevent.leafnode = this;
                eventqueue.addEvent(circleevent);
            }
        }
    }
    private void addCircleEvent(VCircleEvent _circleevent) {
        if ( circleevents==null ) {
            circleevents = new ArrayList();
        }
        circleevents.add( _circleevent );
    }
    
    public VLinkedNode getPrev() { return prev; }
    public VLinkedNode getNext() { return next; }
    
    public void setNext(VLinkedNode node) {
        // Set forward link
        if ( next!=null ) {
            next.prev = null;
        }
        this.next = node;
        
        // Set back link
        if ( node!=null ) {
            if ( node.prev!=null ) {
                node.prev.next = null;
            }
            
            node.prev = this;
        }
    }
    
    public VPoint getIntersectWithNext(int sweepline) {
        VSiteEvent v1 = siteevent;
        VSiteEvent v2 = next.siteevent;
        
        // Calculate a, b and c of the parabola
        v1.calcParabolaConstants(sweepline);
        v2.calcParabolaConstants(sweepline);
        
        // Determine where two parabola meet
        double intersects[] = VoronoiShared.solveQuadratic(v2.a-v1.a, v2.b-v1.b, v2.c-v1.c);
        return new VPoint( (int) intersects[0] , sweepline + siteevent.getYValueOfParabola(intersects[0]) );
    }
    
    public boolean isLeafNode() { return true; }
    
    public boolean isInternalNode() { return false; }
    
    public VLinkedNode cloneLinkedNode() {
        VLinkedNode clone = new VLinkedNode(this.siteevent);
        // DO NOT DUPLICATE prev/next values
        // DO NOT DUPLICATE circle events???? (?!)
        return clone;
    }
    
    /* ***************************************************** */
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy