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

com.uwsoft.editor.renderer.utils.PolygonUtils Maven / Gradle / Ivy

Go to download

overlap2d-runtime-libgdx provides functionality to load, manipulate and render scenes generated by Overlap2D.

The newest version!
package com.uwsoft.editor.renderer.utils;

import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by CyberJoe on 7/4/2015.
 */
public class PolygonUtils {

    public static Array mergeTouchingPolygons(Vector2[][] polys) {

        Set uniqueEdges = new HashSet();
        Set duplicateEdges = new HashSet();

        for(int i = 0; i < polys.length; i++) {
            for(int j = 0; j < polys[i].length; j++) {
                Edge edge = null;
                if(j < polys[i].length - 1) {
                    edge = new Edge(polys[i][j].x, polys[i][j].y, polys[i][j+1].x, polys[i][j+1].y);
                } else if(j == polys[i].length - 1) {
                    edge = new Edge(polys[i][j].x, polys[i][j].y, polys[i][0].x, polys[i][0].y);
                }
                if(uniqueEdges.contains(edge)) {
                    duplicateEdges.add(edge);
                } else {
                    uniqueEdges.add(edge);
                }
            }
        }

        uniqueEdges.removeAll(duplicateEdges);

        Array result = new Array();
        while(uniqueEdges.size() > 0) {
            Vector2[] mesh = extractClosedLoop(uniqueEdges);
            mesh = clearUnnecessaryVertices(mesh);
            result.add(mesh);
        }

        return result;
    }

    public static Vector2[] mergeTouchingPolygonsToOne(Vector2[][] polys) {
        Array result = mergeTouchingPolygons(polys);

        return result.get(0);
    }

    public static Vector2[] clearUnnecessaryVertices(Vector2[] points) {
        Array result = new Array();
        if(points.length < 3) return points;
        for(int i = 0; i < points.length; i++) {
            Vector2 currPoint = points[i];
            Vector2 prevPoint = points[points.length-1];
            Vector2 nextPoint = points[0];
            if (i > 0) prevPoint = points[i-1];
            if( i < points.length-1) nextPoint = points[i+1];
            if(Intersector.pointLineSide(prevPoint, nextPoint, currPoint) != 0) {
                result.add(currPoint);
            }
        }

        return result.toArray(Vector2.class);
    }

    public static Vector2[] extractClosedLoop(Set edges) {
        ArrayList sortedList = new ArrayList();
        Edge edge = (Edge) edges.toArray()[0];
        edges.remove(edge);
        sortedList.add(edge);
        while(edges.size() > 0) {
            boolean result2 = false;
            boolean result1 = appendNextEdge(sortedList, edges);
            if(edges.size() > 0) {
                result2 = appendPrevEdge(sortedList, edges);
            }
            if(!result1 && !result2) {
                break;
            }
        }

        Vector2[] result = new Vector2[sortedList.size()];
        int iterator = 0;
        for(Edge tmp: sortedList) {
            result[iterator++] = tmp.start;
        }

        return result;
    }

    public static boolean appendNextEdge(ArrayList sortedList, Set edges) {
        Edge lastEdge = sortedList.get(sortedList.size()-1);
        Vector2 point = lastEdge.end;
        for(Edge edge: edges) {
            if(edge.linkedTo(point)) {
                if(edge.end.equals(lastEdge.end)) {
                    edge.reverse();
                }
                edges.remove(edge);
                sortedList.add(edge);
                return true;
            }
        }

        return false;
    }

    public static boolean appendPrevEdge(ArrayList sortedList, Set edges) {
        Edge prevEdge = sortedList.get(0);
        Vector2 point = prevEdge.start;
        for(Edge edge: edges) {
            if(edge.linkedTo(point)) {
                if(edge.start.equals(prevEdge.start)) {
                    edge.reverse();
                }
                edges.remove(edge);
                sortedList.add(0, edge);
                return true;
            }
        }

        return false;
    }

    @Deprecated
    public static Vector2[] extractClosedLoopOld(Set edges) {
        ArrayList sortedList = new ArrayList();
        Edge nextEdge = (Edge) edges.toArray()[0];
        sortedList.add(nextEdge);
        sortedList = recursivelySortChainPoints(edges, nextEdge, sortedList);
        edges.removeAll(sortedList);

        Vector2[] result = new Vector2[sortedList.size()];
        int iterator = 0;
        for(Edge edge: sortedList) {
            result[iterator++] = edge.start;
        }

        return result;
    }

    @Deprecated
    private static ArrayList recursivelySortChainPoints(Set edges, Edge edge, ArrayList sortedList) {
        Edge nextEdge = findLink(edges, edge, edge.end);
        if(!edge.end.equals(nextEdge.start)) nextEdge.reverse();
        sortedList.add(nextEdge);
        if(sortedList.get(0).linkedTo(sortedList.get(sortedList.size() - 1)) && sortedList.size() >= 3) {
            //loop is closed
            return sortedList;
        }
        return recursivelySortChainPoints(edges, nextEdge, sortedList);
    }

    public static Edge findLink(Set edges, Edge edge, Vector2 point) {
        for(Edge linkedEdge: edges) {
            if(!linkedEdge.equals(edge) && linkedEdge.linkedTo(point)) {
                return linkedEdge;
            }
        }

        return null;
    }

    public static class Edge {
        public Vector2 start;
        public Vector2 end;

        public Edge(float startX, float startY, float endX, float endY) {
            start = new Vector2(startX, startY);
            end = new Vector2(endX, endY);
        }

        public Edge(Vector2 start, Vector2 end) {
            this.start = start;
            this.end = end;
        }

        public boolean linkedTo(Vector2 point) {
            if(start.equals(point) || end.equals(point)) return true;
            return false;
        }

        public boolean linkedTo(Edge edge) {
            if(!this.equals(edge) && (start.equals(edge.end) || end.equals(edge.start) || end.equals(edge.end) || start.equals(edge.start))) return true;
            return false;
        }

        public void reverse() {
            Vector2 tmp = new Vector2(start);
            start = end;
            end = tmp;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null) return false;
            if (getClass() != obj.getClass()) return false;
            Edge other = (Edge)obj;
            if(hashCode() == other.hashCode()) return true;
            return false;
        }

        @Override
        public int hashCode () {
            return start.hashCode() + end.hashCode();
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy