---
# System prepended metadata

title: FutuerCulclation

---

---
title : FutuerCulclation
robots : noindex, nofollow
lang : ja-jp
breaks : false
---

# FutuerCulclation

# MapConverter.java
```java=
import java.io.File;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import org.jhotdraw.geom.*;

import maps.MapException;
import maps.gml.GMLMap;
import maps.gml.GMLObject;
import maps.gml.GMLNode;
import maps.gml.GMLEdge;
import maps.gml.GMLShape;
import maps.gml.GMLRoad;
import maps.gml.GMLBuilding;
import maps.gml.GMLSpace;
import maps.gml.GMLDirectedEdge;
import maps.gml.GMLCoordinates;
import maps.gml.formats.RobocupFormat;

import rescuecore2.misc.Pair;

public class MapConverter {
	public static void main(String[] args){
        List<GMLMap> maps = new ArrayList<GMLMap>();
        List<SeparateGMLRoad> roadTypes = new ArrayList<SeparateGMLRoad>();
        List<AnalysisMap> analysis = new ArrayList<AnalysisMap>();

        MapConvertOptions option = new MapConvertOptions();
        option.parseOption(args);

        for(String fileName : option.readFileName){
            RobocupFormat format = RobocupFormat.INSTANCE;
            Map<GMLCoordinates,GMLNode> nodeCheck = new HashMap<GMLCoordinates,GMLNode>();
            Map<Pair<GMLNode,GMLNode>,GMLEdge> edgeCheck = new HashMap<Pair<GMLNode,GMLNode>,GMLEdge>();
            List<GMLNode> nodes = new ArrayList<GMLNode>();
            List<GMLEdge> edges = new ArrayList<GMLEdge>();
            List<GMLRoad> roads = new ArrayList<GMLRoad>();
            List<GMLBuilding> buildings = new ArrayList<GMLBuilding>();
            List<GMLShape> shapes = new ArrayList<GMLShape>();
            List<GMLShape> succesList = new ArrayList<GMLShape>();
            List<GMLShape> errorShapes = new ArrayList<GMLShape>();

            GMLMap map = null;
            SeparateGMLRoad roadType = new SeparateGMLRoad();
            AnalysisMap analys = null;

            File readFile = new File(fileName);

            try{
                map = format.read(readFile);
            }catch(MapException me){
                me.printStackTrace();
            }

            for(GMLObject o : map.getAllObjects()){
                if(o instanceof GMLNode){
                    GMLNode node = (GMLNode)o;
                    nodeCheck.put(node.getCoordinates(),node);
                    nodes.add(node);
                }else if(o instanceof GMLEdge){
                    GMLEdge edge = (GMLEdge)o;
                    edges.add(edge);
                    edgeCheck.put(new Pair<GMLNode,GMLNode>(edge.getStart(),edge.getEnd()), edge);
                    edgeCheck.put(new Pair<GMLNode,GMLNode>(edge.getEnd(),edge.getStart()), edge);
                }else if(o instanceof GMLShape){
                    shapes.add((GMLShape)o);
                    if(o instanceof GMLBuilding){
                        buildings.add((GMLBuilding)o);
                    }else if(o instanceof GMLRoad){
                        GMLRoad r = (GMLRoad)o;
                        roads.add(r);
                    }
                }else if(o instanceof GMLSpace){

                }else{
                    System.err.println("Unknown Object");
                }
            }

            if(option.checkOverlap){
                checkOverlapNode(nodes,map,edges,nodeCheck);
                checkOverlapEdge(edges,map,shapes,edgeCheck);
            }

            //checkShape(map,edges,shapes);
            //checkNeighbour(shapes,errorShapes);

            if(option.isAnalysis){
                roadType.separateRoads(roads, map);
                roadType.separateStreet(map);
                analys = new AnalysisMap(roadType,map);
                analys.detectionSemigloss();

                for(GMLBuilding building : buildings){
                    for(GMLGloss gloss : analys.getGlossList()){
                        gloss.setBuilding(building);
                    }
                }
                for(GMLGloss gloss: analys.getGlossList()){
                    gloss.calculation();
                }
                maps.add(map);
                roadTypes.add(roadType);
                analysis.add(analys);
            }

            /*
            Map<GMLNode,GMLShape> deleteList = new HashMap<GMLNode,GMLShape>();
            deleteList.put(new GMLNode(-1,1.0,1.0),new GMLBuilding(-9999)); //dummy

            for(int i = 0; i < option.step && deleteList.size() >= 1; ++i){
                deleteList.clear();
                errorCheck(nodes,shapes,roads,deleteList,map,option.rate,option.robust,succesList);
            }

            MapViewer view = new MapViewer(roadType,analys.getGlossList(),map,edges,deleteList,map.getMinX(),map.getMinY(),map.getMaxX(),map.getMaxY());
            System.out.println("YABAI:"+deleteList.size()+"node:"+nodes.size()+"building:"+buildings.size()+
                    "road:"+roads.size()+"cross:"+roadType.getCrossing().size());

            try{
                File newFile = new File(option.writeFileName);
                newFile.createNewFile();
                try{
                    format.write(map,newFile);
                }catch(MapException me){
                    me.printStackTrace();
                }
            }catch(Exception ie){
                ie.printStackTrace();
            }
            */
        }
	    System.out.println(maps.size());
        for(int i = 0; i < maps.size(); ++i){
            System.out.println("GROSS_NUM : " + analysis.get(i).getGlossList().size()); // GROSS NUM

                        // Viewer ON
                        CalcStatisticDataTool tool = new CalcStatisticDataTool(option.mapNames.get(i),maps.get(i),analysis.get(i).getGlossList(),roadTypes.get(i));
                        tool.setVisible(true);

                        //
						// Viewer OFF
						// CalcStatisticData calc = new CalcStatisticData(analysis.get(i).getGlossList(), maps.get(i), roadTypes.get(i));
						// calc.writeFile(option.mapNames.get(i));
        }

        System.out.println("OWATA");
	}

	static public void errorCheck(List<GMLNode> nodes,List<GMLShape> shapes,List<GMLRoad> roads,Map<GMLNode,GMLShape> deleteList,GMLMap map,
	        double rate, double robust, List<GMLShape> succesList){
	    for(GMLShape r : shapes){
            Polygon2D.Double edgeShape = new Polygon2D.Double();
            List<GMLNode> nList = new ArrayList<GMLNode>();
            boolean succes = true;

            if(!succesList.contains(r)){
                for(GMLDirectedEdge de : r.getEdges()){
                    GMLNode tempNode = de.getStartNode();
                    nList.add(tempNode);
                    double x;
                    double y;
                    if(r.getCentreX() > tempNode.getX()) x = tempNode.getX()+robust;
                    else x = tempNode.getX() - robust;
                    if(r.getCentreY() > tempNode.getY()) y = tempNode.getY()+robust;
                    else y = tempNode.getY() - robust;

                    edgeShape.addPoint(x,y);
                }
                for(GMLNode errorNode : nodes){
                    if(edgeShape.contains(errorNode.getX(),errorNode.getY())){
                        if(!nList.contains(errorNode)){
                            System.out.println("ErrorNodeID:"+errorNode.getID()+" x:"+errorNode.getX()+" y:"+errorNode.getY());
                            if(!deleteList.containsKey(errorNode)){
                                for(GMLShape shape : shapes){
                                    for(GMLDirectedEdge edge: shape.getEdges()){
                                        if(errorNode.getID() == edge.getStartNode().getID()){
                                            succes = false;
                                            deleteList.put(errorNode,shape);
                                            GMLNode checked = map.getNode(errorNode.getID());
                                            double cx = shape.getCentreX();
                                            double cy = shape.getCentreY();

                                            if(cx == Double.NEGATIVE_INFINITY || cx == Double.POSITIVE_INFINITY
                                                    || cy == Double.POSITIVE_INFINITY || cy == Double.NEGATIVE_INFINITY
                                                    ||Double.isNaN(cx) || Double.isNaN(cy)){
                                                cx = edge.getEndNode().getX();
                                                cy = edge.getEndNode().getY();
                                            }
                                            double nx = errorNode.getX()+((cx-errorNode.getX())*rate);
                                            double ny = errorNode.getY()+((cy-errorNode.getY())*rate);
                                            checked.setCoordinates(new GMLCoordinates(nx,ny));
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                System.out.println("RoadID:"+r.getID());
            }
            if(succes){
                succesList.add(r);
            }
        }
	}

	public static void checkNeighbour(List<GMLShape> shapes, List<GMLShape> errorShapes){
	    for(GMLShape shape : shapes){
	        boolean hasNeighbour = false;

	        for(GMLDirectedEdge edge : shape.getEdges()){
	            hasNeighbour = shape.hasNeighbour(edge);
	            if(hasNeighbour) break;
	        }

	        if(!hasNeighbour){
	            errorShapes.add(shape);
	        }
	    }
	}

    public static void checkShape(GMLMap map, List<GMLEdge> edges, List<GMLShape> shapes){
        List<GMLObject> deleteList = new ArrayList<GMLObject>();
        for(GMLShape shape : shapes){
            List<GMLDirectedEdge> newEdgeList = new ArrayList<GMLDirectedEdge>();
            List<GMLDirectedEdge> oldEdgeList = shape.getEdges();
            /*
            for(GMLDirectedEdge edge : newEdgeList){
                hasNeighbour = shape.hasNeighbour(edge);
            }

            if(!hasNeighbour){
                oldEdgeList.clear();
                GMLNode end = null;
                for(GMLDirectedEdge orgEdge: shape.getEdges()){
                    GMLDirectedEdge newEdge =null;
                    if(end != null){
                        if(end.getID() == orgEdge.getStartNode().getID()){
                            GMLEdge addEdge = map.createEdge(end, orgEdge.getEndNode());
                            edges.add(addEdge);
                            oldEdgeList.add(new GMLDirectedEdge(addEdge,end));
                        }else{
                            GMLEdge addEdge = map.createEdge(end, orgEdge.getStartNode());
                            edges.add(addEdge);
                            oldEdgeList.add(new GMLDirectedEdge(addEdge,end));
                        }
                        end = null;
                    }

                    for(GMLEdge edge: edges){
                        if(orgEdge.getEdge().getID()!=edge.getID() &&
                                (edge.getStart().getID() == orgEdge.getStartNode().getID()||
                                edge.getStart().getID() == orgEdge.getEndNode().getID())){
                            newEdge = new GMLDirectedEdge(edge,edge.getStart());
                            end = edge.getEnd();
                            break;
                        }
                    }
                    if(newEdge == null){
                        oldEdgeList.add(orgEdge);
                    }else{
                        deleteList.add(orgEdge.getEdge());
                        oldEdgeList.add(newEdge);
                    }
                }
            }*/

            GMLDirectedEdge target = (oldEdgeList.get(0));
            newEdgeList.add(target);
            GMLNode endNode = target.getEndNode();
            List<GMLEdge> checkList = new ArrayList<GMLEdge>();
            checkList.add(target.getEdge());

            for(int i = 1; i <= oldEdgeList.size()-1; ++i){
                for(GMLDirectedEdge edge : oldEdgeList){
                    if(!checkList.contains(edge.getEdge())){
                        if(endNode.equals(edge.getStartNode())){
                            newEdgeList.add(edge);
                            checkList.add(edge.getEdge());
                            endNode = edge.getEndNode();
                            break;
                        }else if(endNode.equals(edge.getStartNode())){
                            endNode = edge.getEndNode();
                            edge.reverse();
                            newEdgeList.add(edge);
                            checkList.add(edge.getEdge());
                            break;
                        }
                    }
                }
            }
            shape.setEdges(newEdgeList);
        }
        for(GMLObject delete : deleteList){
            map.remove(delete);
        }
    }

    public static void checkOverlapNode(List<GMLNode> nodes, GMLMap map, List<GMLEdge> edges, Map<GMLCoordinates,GMLNode>nodeCheck){
        List<GMLNode> errorNode = new ArrayList<GMLNode>();
        for(GMLEdge edge : edges){
            GMLNode start = nodeCheck.get(edge.getStart().getCoordinates());
            GMLNode end = nodeCheck.get(edge.getEnd().getCoordinates());

            if(start != null && (!edge.getStart().equals(start))){
                errorNode.add(edge.getStart());
                edge.setStart(start);
            }
            if(end != null && (!edge.getEnd().equals(end))){
                errorNode.add(edge.getEnd());
                edge.setEnd(end);
            }
        }
        for(GMLNode node : errorNode){
            map.remove(node);
            nodes.remove(node);
        }
    }

    public static void checkOverlapEdge(List<GMLEdge> edges, GMLMap map, List<GMLShape> shapes, Map<Pair<GMLNode,GMLNode>,GMLEdge>edgeCheck){
        List<GMLEdge> errorEdge = new ArrayList<GMLEdge>();
        for(GMLShape shape :shapes){
            for(GMLDirectedEdge edge : shape.getEdges()){
                GMLEdge edgeTemp = edgeCheck.get(new Pair<GMLNode,GMLNode>(edge.getStartNode(),edge.getEndNode()));
                if(edgeTemp != null && !edgeTemp.equals(edge.getEdge())){
                    shape.replaceEdge(edge, new GMLDirectedEdge(edgeTemp,edgeTemp.getStart()));
                    errorEdge.add(edge.getEdge());
                }
            }
        }
        for(GMLEdge edge : errorEdge){
            map.remove(edge);
            edges.remove(edge);
        }
    }
}
```

## SeparateGMLRoad.java

```java=
import java.util.List;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

import maps.gml.GMLRoad;
import maps.gml.GMLNode;
import maps.gml.GMLDirectedEdge;
import maps.gml.GMLBuilding;
import maps.gml.GMLMap;
import maps.gml.GMLObject;

import rescuecore2.misc.Pair;

enum GMLRoadType{
    MAIN,
    END,
    ENTRANCE,
    BTOB,
    UNKNOWN,
    CROSSING
}

public class SeparateGMLRoad {
    private List<GMLRoad> mainRoad;
    private List<GMLRoad> endRoad;
    private List<GMLRoad> entrance;
    private List<GMLRoad> buildingToBuilding;
    private List<GMLRoad> unknown;
    private List<GMLRoad> crossing;
    private Map<Integer,GMLRoad> idToCrossing;
    private Map<Integer,GMLRoadType> idToType;

    private List<GMLStreet> streets;  
    private Map<Integer,List<Pair<Integer,Integer>>> streetCrossingList;//cross1<street,cross2>
    
    public SeparateGMLRoad(){
        mainRoad = new ArrayList<GMLRoad>();
        endRoad = new ArrayList<GMLRoad>();
        entrance = new ArrayList<GMLRoad>();
        buildingToBuilding = new ArrayList<GMLRoad>();
        unknown = new ArrayList<GMLRoad>();
        crossing = new ArrayList<GMLRoad>();
        idToCrossing = new HashMap<Integer,GMLRoad>();
        idToType = new HashMap<Integer,GMLRoadType>();
        
        streets = new ArrayList<GMLStreet>();
        streetCrossingList = new HashMap<Integer,List<Pair<Integer,Integer>>>();
    }
    
    public GMLRoadType separateRoad(GMLRoad road, GMLMap map, List<GMLRoad> checkList){
        int roadNeighbour = 0;
        int buildingNeighbour = 0;
        
        if(entrance.contains(road)){
            return GMLRoadType.ENTRANCE;
        }else if(checkList.contains(road)){
            return GMLRoadType.MAIN;
        }
        checkList.add(road);
        for(GMLDirectedEdge edge: road.getEdges()){
            if(road.hasNeighbour(edge)){
                GMLObject object = map.getObject(road.getNeighbour(edge));
                if(object instanceof GMLBuilding){
                    buildingNeighbour++;
                }else if(object instanceof GMLRoad){
                    GMLRoadType type = separateRoad((GMLRoad)object,map,checkList);
                    if(type == GMLRoadType.MAIN || type == GMLRoadType.END || type == GMLRoadType.CROSSING){
                        roadNeighbour++;
                    }
                }
            }
        }
        
        //道分類
        if(roadNeighbour >= 3){
            crossing.add(road);
            idToCrossing.put(road.getID(), road);
            idToType.put(road.getID(), GMLRoadType.CROSSING);
            return GMLRoadType.CROSSING;
        }else if(roadNeighbour >= 2){
            mainRoad.add(road);
            idToType.put(road.getID(), GMLRoadType.MAIN);
            return GMLRoadType.MAIN;
        }else if(roadNeighbour == 0 && buildingNeighbour >= 2){
            buildingToBuilding.add(road);
            idToType.put(road.getID(), GMLRoadType.BTOB);
            return GMLRoadType.BTOB;
        }else if(roadNeighbour >= 1 && buildingNeighbour >= 1){
            entrance.add(road);
            idToType.put(road.getID(), GMLRoadType.ENTRANCE);
            return GMLRoadType.ENTRANCE;
        }else if(roadNeighbour >= 1){
            endRoad.add(road);
            idToType.put(road.getID(), GMLRoadType.END);
            return GMLRoadType.END;
        }
        unknown.add(road);
        idToType.put(road.getID(), GMLRoadType.UNKNOWN);
        return GMLRoadType.UNKNOWN;
    }
    
    public void separateRoads(List<GMLRoad> roads, GMLMap map){
        List<GMLRoad> checkList = new ArrayList<GMLRoad>();
        
        for(GMLRoad road : roads){
            int buildingCount = 0;
            int roadCount = 0;
            List<GMLNode> nodes = new ArrayList<GMLNode>();
            for(GMLDirectedEdge edge : road.getEdges()){
                if(road.hasNeighbour(edge)){
                    GMLObject o = map.getObject(road.getNeighbour(edge));
                    if(o instanceof GMLBuilding){
                        buildingCount++;
                    }else if(o instanceof GMLRoad){
                        roadCount++;
                        if(!nodes.contains(edge.getStartNode()))
                            nodes.add(edge.getStartNode());
                        if(!nodes.contains(edge.getEndNode()))
                            nodes.add(edge.getEndNode());
                    }
                }
            }
            if(buildingCount >= 1){
                if((roadCount == 2 && nodes.size() <= 3) || roadCount <= 1){
                    entrance.add(road);
                    idToType.put(road.getID(), GMLRoadType.ENTRANCE);
                }
            }
        }
        for(GMLRoad road : roads){
            separateRoad(road,map,checkList);
        }
    }
    
    public void separateStreet(GMLMap map){
        if(mainRoad.isEmpty()){
            System.err.println("need separate road!");
            return;
        }
        List<GMLRoad> checkList = new ArrayList<GMLRoad>();
        
        for(GMLRoad road : endRoad){
            GMLRoad next = road;
            List<GMLRoad> street = new ArrayList<GMLRoad>();
            do{
                checkList.add(next);
                street.add(next);
                for(GMLDirectedEdge edge : next.getEdges()){
                    if(next.hasNeighbour(edge)){
                        GMLObject o = map.getObject(next.getNeighbour(edge));
                        if(o instanceof GMLRoad){
                            GMLRoad temp = (GMLRoad)o;
                            if(!checkList.contains(temp) && idToType.get(temp.getID())!=GMLRoadType.ENTRANCE){
                                next = temp;
                            }
                        }
                    }
                }
            }while(idToType.get(next.getID()) != GMLRoadType.CROSSING);
            streets.add(new GMLStreet(street,road.getID(),next.getID(),streets.size()));
        }
        
        List<GMLRoad> startRoad = new ArrayList<GMLRoad>();
        for(GMLRoad road : crossing){
            for(GMLDirectedEdge edge : road.getEdges()){
                if(road.hasNeighbour(edge)){
                    GMLRoad temp = map.getRoad(road.getNeighbour(edge));
                    if(temp != null && !checkList.contains(temp) && idToType.get(temp.getID())!=GMLRoadType.ENTRANCE && idToType.get(temp.getID())!=GMLRoadType.CROSSING){
                        if(!startRoad.contains(temp))
                            startRoad.add(temp);
                    }else if(temp != null && idToType.get(temp.getID())==GMLRoadType.CROSSING && !checkList.contains(temp)){
                        List<Pair<Integer,Integer>> streetCross = streetCrossingList.get(road.getID());
                        if(streetCross == null) streetCross = new ArrayList<Pair<Integer,Integer>>();
                        streetCross.add(new Pair<Integer,Integer>(-1,temp.getID()));
                        streetCrossingList.put(road.getID(), streetCross);
                    }
                }
            }
        }
 
        for(GMLRoad road : startRoad){
            if(!checkList.contains(road)){
                GMLRoad cross1 = null;
                GMLRoad cross2 = null;
                int streetID = streets.size();
                GMLRoad next = null;
                List<GMLRoad> street = new ArrayList<GMLRoad>();
                checkList.add(road);
                street.add(road);
                for(GMLDirectedEdge edge: road.getEdges()){
                    if(road.hasNeighbour(edge)){
                        GMLObject o = map.getObject(road.getNeighbour(edge));
                        if(o instanceof GMLRoad){
                            if(idToType.get(o.getID()) == GMLRoadType.CROSSING){
                                if(cross1 != null) cross2 = (GMLRoad)o;
                                else cross1 = (GMLRoad)o;
                            }else{
                                next = (GMLRoad)o;
                            }
                        }
                    }
                }
                if(next != null){
                    boolean flag = true;
                    while(idToType.get(next.getID()) != GMLRoadType.CROSSING && flag){
                        flag = false;
                        checkList.add(next);
                        street.add(next);
                        for(GMLDirectedEdge edge : next.getEdges()){
                            if(next.hasNeighbour(edge)){
                                GMLObject o = map.getObject(next.getNeighbour(edge));
                                if(o instanceof GMLRoad){
                                    GMLRoad temp = (GMLRoad)o;
                                    if(!checkList.contains(temp) && idToType.get(temp.getID())!=GMLRoadType.ENTRANCE){
                                        next = temp;
                                        flag = true;
                                    }
                                }
                            }
                        }
                    }
                }
                if(next != null || cross2 != null){
                    if(cross2 == null)cross2 = next; 
                    streets.add(new GMLStreet(street,cross1.getID(),cross2.getID(),streets.size()));
                    List<Pair<Integer,Integer>> streetCross = streetCrossingList.get(cross1.getID());
                    if(streetCross == null) streetCross = new ArrayList<Pair<Integer,Integer>>();
                    if(idToType.get(cross2.getID()) == GMLRoadType.CROSSING) streetCross.add(new Pair<Integer,Integer>(streetID,cross2.getID()));
                    streetCrossingList.put(cross1.getID(), streetCross);
                    
                    streetCross = streetCrossingList.get(cross2.getID());
                    if(streetCross == null) streetCross = new ArrayList<Pair<Integer,Integer>>();
                    if(idToType.get(cross2.getID()) == GMLRoadType.CROSSING) streetCross.add(new Pair<Integer,Integer>(streetID,cross1.getID()));
                    streetCrossingList.put(cross2.getID(), streetCross);
                }
            }
        }
    }
    
    public GMLRoadType getRoadType(GMLRoad road){
        return idToType.get(road.getID());
    }
    
    public GMLRoadType getRoadType(int bid){
        return idToType.get(bid);
    }
    
    public List<GMLRoad> getMainRoads(){
        return mainRoad;
    }
    
    public List<GMLRoad> getEntrance(){
        return entrance;
    }
    
    public List<GMLRoad> getBtoB(){
        return buildingToBuilding;
    }
    
    public List<GMLRoad> getEndRoads(){
        return endRoad;
    }
    
    public List<GMLRoad> getUnknown(){
        return unknown;
    }
    
    public List<GMLRoad> getCrossing(){
        return crossing;
    }
    
    public List<GMLStreet> getStreets(){
        return streets;
    }
    
    public Map<Integer,List<Pair<Integer,Integer>>> getCrossingGraph(){
        return streetCrossingList;
    }
    
    public Map<Integer,GMLRoad> getIdToCrossing(){
        return idToCrossing;
    }
    
    public void writeFile(PrintWriter pw){
        pw.println("SeparateDataStart");
        pw.println("roadType");
        for(Integer id : idToType.keySet()){
            pw.print(id+":");
            switch(idToType.get(id)){
                case MAIN:
                    pw.println("main");
                    break;
                case END:
                    pw.println("end");
                    break;
                case CROSSING:
                    pw.println("cross");
                    break;
                case ENTRANCE:
                    pw.println("entrance");
                    break;
            }
        }
        pw.println("street");
        for(GMLStreet s : streets){
            pw.println(s.getID()+":"+s.getStartID()+":"+s.getEndID());
        }
    }
}
```

## AnalysisMap.java

```java=
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

import rescuecore2.misc.Pair;
import maps.gml.GMLRoad;
import maps.gml.GMLMap;

import org.jhotdraw.geom.*;

public class AnalysisMap{
    private int MAX_DISTANCE = 12;

    private SeparateGMLRoad separatedRoads;
    private Map<Integer,List<Pair<Integer,Integer>>> crossGraph;
    private List<List<Integer>> result;
    private List<List<GMLRoad>> resultRoads;
    private Map<Integer,Integer> glossCrossCount;

    private List<List<Integer>> twoCrossGloss;
    private List<List<GMLRoad>> twoCrossGlossRoads;
    private List<Integer> checkTwoCrossGloss;

    private List<Polygon2D.Double> poList;
    private List<Polygon2D.Double> twoCrossPoList;

    private List<GMLGloss> glossList;

    private GMLMap map;

    public AnalysisMap(SeparateGMLRoad sRoads, GMLMap map){
        this.separatedRoads = sRoads;
        crossGraph = separatedRoads.getCrossingGraph();
        result = new ArrayList<List<Integer>>();
        resultRoads = new ArrayList<List<GMLRoad>>();

        twoCrossGloss = new ArrayList<List<Integer>>();
        twoCrossGlossRoads = new ArrayList<List<GMLRoad>>();
        checkTwoCrossGloss = new ArrayList<Integer>();

        glossCrossCount = new HashMap<Integer,Integer>();
        for(GMLRoad road : separatedRoads.getCrossing()){
            glossCrossCount.put(road.getID(), 0);
        }

        poList = new ArrayList<Polygon2D.Double>();
        twoCrossPoList = new ArrayList<Polygon2D.Double>();

        glossList = new ArrayList<GMLGloss>();

        this.map = map;
    }

    private void searchSemigloss(GMLRoad cross){
        if(crossGraph.get(cross.getID()) != null){
            List<ExtendedCrossing> glossList = new ArrayList<ExtendedCrossing>();
            List<Integer> checkedCross = new ArrayList<Integer>();
            List<Integer> neighbours = new ArrayList<Integer>();

            int numStreet = crossGraph.get(cross.getID()).size();
            int numNeedGloss = numStreet;
            if(numStreet <= 3) numNeedGloss--;

            for(int i = 0; i < crossGraph.get(cross.getID()).size(); ++i){
                Pair<Integer, Integer> street = crossGraph.get(cross.getID()).get(i);
                if(separatedRoads.getIdToCrossing().get(street.second()) == null) System.out.println(street.second());
                else glossList.add(new ExtendedCrossing(separatedRoads.getIdToCrossing().get(street.second()),cross,street.first()));
                neighbours.add(street.second());
                for(int j = i+1; j < crossGraph.get(cross.getID()).size(); ++j){
                    Pair<Integer, Integer> street2 = crossGraph.get(cross.getID()).get(j);
                    if(street.second().equals(street2.second()) && !checkTwoCrossGloss.contains(street.second())){
                        checkTwoCrossGloss.add(cross.getID());
                        checkTwoCrossGloss.add(street2.second());
                        List<Integer> c = new ArrayList<Integer>();
                        c.add(street.second());
                        c.add(cross.getID());
                        twoCrossGloss.add(c);

                        GMLStreet gs = null;
                        if(street.first() != -1) gs = separatedRoads.getStreets().get(street.first());
                        GMLStreet gs2 = null;
                        if(street2.first() != -1) gs2 = separatedRoads.getStreets().get(street2.first());

                        List<GMLRoad> roadList = new ArrayList<GMLRoad>();
                        Polygon2D.Double p2 = new Polygon2D.Double();

                        if(gs != null && gs2 != null){
                            for(GMLRoad road : gs.getRoads()){
                                roadList.add(road);
                                p2.addPoint(road.getCentreX(), road.getCentreY());
                            }
                            roadList.add(separatedRoads.getIdToCrossing().get(gs.getEndID()));

                            if(gs.getEndID() == gs2.getStartID()){
                                for(GMLRoad road : gs2.getRoads()){
                                    roadList.add(road);
                                    p2.addPoint(road.getCentreX(), road.getCentreY());
                                }
                                GMLRoad road = separatedRoads.getIdToCrossing().get(gs2.getEndID());
                                roadList.add(road);
                                p2.addPoint(road.getCentreX(), road.getCentreY());
                            }else{
                                for(int k = gs2.getRoads().size()-1; k >= 0; --k){
                                    GMLRoad road = gs2.getRoads().get(k);
                                    roadList.add(road);
                                    p2.addPoint(road.getCentreX(), road.getCentreY());
                                }
                                GMLRoad road = separatedRoads.getIdToCrossing().get(gs2.getStartID());
                                roadList.add(road);
                                p2.addPoint(road.getCentreX(), road.getCentreY());
                            }
                        }else if(gs == null && gs2 != null){
                            GMLRoad start = separatedRoads.getIdToCrossing().get(gs2.getStartID());
                            GMLRoad end = separatedRoads.getIdToCrossing().get(gs2.getEndID());
                            roadList.add(start);
                            p2.addPoint(start.getCentreX(), start.getCentreY());
                            for(GMLRoad r : gs2.getRoads()){
                                roadList.add(r);
                                p2.addPoint(r.getCentreX(), r.getCentreY());
                            }
                            roadList.add(end);
                            p2.addPoint(end.getCentreX(), end.getCentreY());
                        }else if(gs2 == null && gs != null){
                            GMLRoad start = separatedRoads.getIdToCrossing().get(gs.getStartID());
                            GMLRoad end = separatedRoads.getIdToCrossing().get(gs.getEndID());
                            roadList.add(start);
                            p2.addPoint(start.getCentreX(), start.getCentreY());
                            for(GMLRoad r : gs.getRoads()){
                                roadList.add(r);
                                p2.addPoint(r.getCentreX(), r.getCentreY());
                            }
                            roadList.add(end);
                            p2.addPoint(end.getCentreX(), end.getCentreY());
                        }else{
                            GMLRoad r = separatedRoads.getIdToCrossing().get(street.second());
                            roadList.add(cross);
                            roadList.add(r);
                            p2.addPoint(cross.getCentreX(), cross.getCentreY());
                            p2.addPoint(r.getCentreX(), r.getCentreY());
                        }
                        twoCrossGlossRoads.add(roadList);
                        twoCrossPoList.add(p2);
                    }
                }
            }

            Collections.sort(glossList,new CrossComparator());
            ExtendedCrossing next;
            int numCompleteGloss = 0;
            if(glossList.size() > 0) {
              next=glossList.get(0);
              for(;numCompleteGloss < numNeedGloss;){
                  glossList.remove(0);
                  if(cross.getID() == next.getID()){
                      List<Integer> r = next.getCrossHistory();
                      r.remove(0);
                      checkedCross.addAll(r);
                      if(!checkCompleted(r)){
                          result.add(r);
                          numCompleteGloss++;

                          List<GMLRoad> roads = new ArrayList<GMLRoad>();
                          Polygon2D.Double p = new Polygon2D.Double();
                          for(int i = 0; i < next.getStreetHistory().size(); ++i){
                              GMLRoad cr = separatedRoads.getIdToCrossing().get(r.get(i));

                              if(next.getStreetHistory().get(i) != -1){
                                  GMLStreet start = separatedRoads.getStreets().get(next.getStreetHistory().get(i));
                                  if(cr.getID() != start.getStartID()){
                                      for(int j = 0; j < start.getRoads().size(); ++j){
                                          GMLRoad road = start.getRoads().get(j);
                                          roads.add(road);
                                          p.addPoint(road.getCentreX(), road.getCentreY());
                                      }
                                  }else{
                                      for(int j = start.getRoads().size()-1; j >= 0; --j){
                                          GMLRoad road = start.getRoads().get(j);
                                          roads.add(road);
                                          p.addPoint(road.getCentreX(), road.getCentreY());
                                      }
                                  }
                              }

                              roads.add(cr);
                              p.addPoint(cr.getCentreX(), cr.getCentreY());
                          }
                          resultRoads.add(roads);
                          poList.add(p);
                          for(Integer id : r){
                              glossCrossCount.put(id,glossCrossCount.get(id)+1);
                          }
                      }
                  }else if((!checkedCross.contains(next.getID()) || neighbours.contains(next.getID()))&&next.getCount()<=MAX_DISTANCE){
                      for(Pair<Integer,Integer> street : crossGraph.get(next.getID())){
                          if((!next.getCrossHistory().contains(street.second())) || (street.second()==cross.getID()&&next.getCount()>=3)){
                              List<Integer> streets = new ArrayList<Integer>();
                              List<Integer> crosses = new ArrayList<Integer>();
                              crosses.addAll(next.getCrossHistory());
                              streets.addAll(next.getStreetHistory());
                              crosses.add(street.second());
                              streets.add(street.first());

                              if(separatedRoads.getIdToCrossing().get(street.second()) != null)
                                  glossList.add(new ExtendedCrossing(separatedRoads.getIdToCrossing().get(street.second()),cross,crosses,streets));
                          }
                      }
                  }
                  if(glossList.isEmpty()){
                      break;
                  }else{
                      Collections.sort(glossList,new CrossComparator());
                      next=glossList.get(0);
                  }
              }
            }
        }
    }

    public void detectionSemigloss(){
        for(GMLRoad cross : separatedRoads.getCrossing()){
            searchSemigloss(cross);
        }

        result.addAll(twoCrossGloss);
        resultRoads.addAll(twoCrossGlossRoads);
        poList.addAll(twoCrossPoList);

        checkResult();

        MAX_DISTANCE += 4;
        for(Integer id : glossCrossCount.keySet()){
            if(glossCrossCount.get(id) == 0){
                searchSemigloss(separatedRoads.getIdToCrossing().get(id));
            }
        }

        for(int i = 0; i < result.size(); ++i){
            glossList.add(new GMLGloss(resultRoads.get(i)));
        }
    }

    public boolean checkCompleted(List<Integer> check){
        boolean isChecked = false;

        for(List<Integer> r : result){
            int count = 0;
            for(Integer id2 : r){
                if(check.contains(id2)) count++;
            }
            if(count >= r.size()){
                isChecked = true;
                break;
            }
        }

        return isChecked;
    }

    public void checkResult(){
        List<List<Integer>> deleteCross = new ArrayList<List<Integer>>();
        List<List<GMLRoad>> deleteRoads = new ArrayList<List<GMLRoad>>();
        List<Polygon2D> deletePoly = new ArrayList<Polygon2D>();

        for(int i = 0; i < resultRoads.size()-1; ++i){
            List<GMLRoad> list1 = resultRoads.get(i);
            for(int j = i+1; j < resultRoads.size(); ++j){
                List<GMLRoad> list2 = resultRoads.get(j);

                List<GMLRoad> small = list2;
                List<GMLRoad> big = list1;
                int bigNum = i;
                int smallNum = j;

                if(list1.size() < list2.size()){
                    big =list2;
                    small = list1;
                    bigNum = j;
                    smallNum = i;
                }

                if(list1.size() != list2.size()){
                    int pCount = 0;
                    int gCount = 0;
                    for(GMLRoad road : small){
                        if(big.contains(road)){
                            pCount++;
                        }else if(poList.get(bigNum).contains(road.getCentreX(), road.getCentreY())){
                            gCount++;
                        }
                    }
                    if(pCount+gCount == small.size()){
                        if(result.get(smallNum).size() == 2){
                   //------------------------------------------------------
                            List<GMLRoad> bigGloss = resultRoads.get(bigNum);
                            List<GMLRoad> smallGloss = resultRoads.get(smallNum);

                            List<GMLRoad> deleteTwoRoads = new ArrayList<GMLRoad>();
                            List<GMLRoad> addTwoRoads = new ArrayList<GMLRoad>();
                            boolean check = false;
                            int index = -1;
                            GMLRoad startR = null;
                            GMLRoad endR = null;

                            addTwoRoads.addAll(smallGloss);

                            for(int k = 0; k < bigGloss.size(); ++k){
                                GMLRoad r = bigGloss.get(k);
                                if(GMLRoadType.CROSSING != separatedRoads.getRoadType(r)){
                                    if(smallGloss.contains(r)) deleteTwoRoads.add(r);
                                }
                                if(r.equals(separatedRoads.getIdToCrossing().get(result.get(smallNum).get(0)))){
                                    if(!check){
                                        check = true;
                                        index = k;
                                        startR = separatedRoads.getIdToCrossing().get(result.get(smallNum).get(0));
                                        endR = separatedRoads.getIdToCrossing().get(result.get(smallNum).get(1));
                                    }
                                }else if(r.equals(separatedRoads.getIdToCrossing().get(result.get(smallNum).get(1)))){
                                    if(!check){
                                        check = true;
                                        index = k;
                                        startR = separatedRoads.getIdToCrossing().get(result.get(smallNum).get(1));
                                        endR = separatedRoads.getIdToCrossing().get(result.get(smallNum).get(0));
                                    }
                                }
                            }
                            bigGloss.removeAll(deleteTwoRoads);
                            bigGloss.remove(separatedRoads.getIdToCrossing().get(result.get(smallNum).get(0)));
                            bigGloss.remove(separatedRoads.getIdToCrossing().get(result.get(smallNum).get(1)));
                            addTwoRoads.removeAll(deleteTwoRoads);
                            if(index > bigGloss.size()){
                                index = bigGloss.size();
                            }
                            int startIndex = addTwoRoads.indexOf(startR);
                            int endIndex = addTwoRoads.indexOf(endR);

                            List<GMLRoad> addTwoRoads2 = new ArrayList<GMLRoad>();
                            if(endIndex < startIndex){
                                for(int l = addTwoRoads.size()-1; l >= 0 ;--l){
                                    addTwoRoads2.add(addTwoRoads.get(l));
                                }
                            }else{
                                addTwoRoads2 = addTwoRoads;
                            }
                            if(index < 0) bigGloss.addAll(0, addTwoRoads2);
                            else bigGloss.addAll(index, addTwoRoads2);
                  //-------------------------------------
                        }else{
                            deleteCross.add(result.get(bigNum));
                            deleteRoads.add(resultRoads.get(bigNum));
                            deletePoly.add(poList.get(bigNum));
                        }
                    }
                }
            }
        }
        result.removeAll(deleteCross);
        resultRoads.removeAll(deleteRoads);
        poList.removeAll(deletePoly);
    }

    public Map<Integer,Integer> getGlossCrossCount(){
        return glossCrossCount;
    }

    public List<List<Integer>> getResult(){
        return result;
    }

    public List<GMLGloss> getGlossList(){
        return glossList;
    }
}
```

## CalcStatisticData.java

```java=
import java.util.List;

import java.io.File;
import java.io.BufferedWriter;
import java.io.PrintWriter;
import java.io.FileWriter;

import maps.gml.GMLRoad;
import maps.gml.GMLBuilding;
import maps.gml.GMLMap;
import maps.gml.GMLDirectedEdge;
import maps.gml.GMLCoordinates;

import java.util.Map;
import java.util.HashMap;

import java.math.BigDecimal;

public class CalcStatisticData {
    private double c1;
    private double c9;
    private double c13;
    private double c13num;

    private double buildingCoverage;//
    private double buildingLength;//

    private double buildingDependent;//
    private double maxAdjacentDistance;//
    private double distributionRatio;//

    private double contactRoadDistance;//
    private BigDecimal clearance;//

    private BigDecimal roadLength;
    private double roadDensity;//
    private BigDecimal buildingNumberDensity;//

    Map<Integer,Double> roads;

    public CalcStatisticData(List<GMLGloss> glossList, GMLMap map, SeparateGMLRoad separate){
        buildingCoverage = 0;
        c1 = 0;
        buildingLength = 0;

        buildingDependent = 0;
        maxAdjacentDistance = 0;
        c9 = 0;
        distributionRatio = 0;

        c13 = 0;
        c13num = 0;

        contactRoadDistance = 0;
        clearance = new BigDecimal(0);

        roadLength = new BigDecimal(0);
        roadDensity = 0;

        for(GMLGloss gloss : glossList){
            //buildings-----------------------------------------------
            int bNum = gloss.getBuildingsInArea().size();

            if(bNum > 0){
                double bD = 0;
                double bC = 0;
                double mL = 0;
                double dR = 0;
                double MinL = 0;

                for(GMLBuilding b : gloss.getBuildingsInArea()){
                    double maxDependArea = Double.MIN_VALUE;
                    double maxLength = Double.MIN_VALUE;
                    double minLength = Double.MAX_VALUE;

                    bC+=gloss.getBuildingsArea().get(b.getID());


                    for(Integer id : gloss.getNeighbourBuildings().get(gloss.getBuildingIdInGloss(b.getID()))){
                        double length = gloss.getBuildingToBuildings().get(b.getID()).get(id);
                        double area = gloss.getBuildingsArea().get(id);

                        if(maxDependArea < area) maxDependArea = area;
                        if(maxLength < length) maxLength = length;
                        if(minLength > length) minLength = length;
                    }
                    if(maxDependArea != Double.MIN_VALUE) bD += maxDependArea/gloss.getBuildingsArea().get(b.getID());
                    if(maxLength != Double.MIN_VALUE){
                        mL += maxLength;
                        MinL += minLength;
                        dR += (maxLength - minLength) / maxLength;
                    }
                }
                double tmpGloss = Math.sqrt(gloss.getArea());
                c1 += bC/Math.pow(tmpGloss + 1.5, 2);
                buildingCoverage += bC/gloss.getArea();
                buildingDependent += bD/bNum;
                maxAdjacentDistance += mL/bNum;
                c9 += MinL/bNum;
                distributionRatio += dR/bNum;
                //buildingsEnd------------------------------------------------------
            }

            int rLCount = 0;
            double crd = 0;
            for(Integer id : gloss.getSemiGlossToBuildings().keySet()){
                for(Double length : gloss.getSemiGlossToBuildings().get(id)){
                    crd += length;
                    rLCount++;
                }
            }
            if(rLCount > 0) {
              contactRoadDistance += crd/rLCount;
            }

            if(gloss.getFollowBuildings().size() > 0) {

            }

            if(gloss.getFollowBuildings().size() > 0) {
              c13num += gloss.getFollowBuildings().size();
              for(List l : gloss.getFollowBuildings()) {
                if(l.size() > 0) {
                  c13 += l.size();
                }
              }
            }

            if(gloss.getClearance().size() > 0){
                BigDecimal cl = new BigDecimal(0);
                for(Double c : gloss.getClearance()){
                    if(c > 0){
                        cl = cl.add(new BigDecimal(c));
                    }
                }
                cl = cl.divide(new BigDecimal(gloss.getClearance().size()),BigDecimal.ROUND_HALF_UP);
                clearance = clearance.add(cl);
            }

        }
        //end Gloss --------------------------------------------
        buildingCoverage = buildingCoverage/glossList.size();
        c1 = c1/glossList.size();
        buildingDependent = buildingDependent/glossList.size();
        maxAdjacentDistance = maxAdjacentDistance/glossList.size();
        c9 = c9/glossList.size();
        distributionRatio = distributionRatio/glossList.size();
        contactRoadDistance = contactRoadDistance/glossList.size();
        clearance = clearance.divide(new BigDecimal(glossList.size()),BigDecimal.ROUND_HALF_UP);
        c13 = c13/c13num;

        double mapArea = (map.getMaxX()-map.getMinX()) * (map.getMaxY()-map.getMinY());

        buildingNumberDensity = new BigDecimal(map.getBuildings().size()/mapArea);

        for(GMLBuilding b : map.getBuildings()){
            double bL = 0;
            for(GMLDirectedEdge edge : b.getEdges()){
                double x1 = edge.getStartNode().getX();
                double y1 = edge.getStartNode().getY();
                double x2 = edge.getEndNode().getX();
                double y2 = edge.getEndNode().getY();

                bL += Math.sqrt(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)));
            }
            buildingLength += bL;
        }

        buildingLength = buildingLength/map.getBuildings().size();

        roads = new HashMap<Integer,Double>();

        for(GMLRoad r : map.getRoads()){
            double roadArea = 0;
            double cx = r.getCentreX();
            double cy = r.getCentreY();

            List<GMLCoordinates> point = r.getCoordinates();
            for(int i = point.size(),u=0;i-->0;u=i){
                roadArea += (point.get(i).getX()-point.get(u).getX())*(point.get(i).getY()+point.get(u).getY());
            }
            roadDensity += Math.abs(0.5*roadArea);

            for(GMLDirectedEdge edge : r.getEdges()){
                double length = 0;
                if(r.hasNeighbour(edge)){
                    if(map.getObject(r.getNeighbour(edge)) instanceof GMLRoad){
                       if(separate.getRoadType(r.getNeighbour(edge)) != GMLRoadType.ENTRANCE){
                           double x = edge.getStartNode().getX() - (edge.getStartNode().getX()-edge.getEndNode().getX());
                           double y = edge.getStartNode().getY() - (edge.getStartNode().getY()-edge.getEndNode().getY());
                           length = Math.sqrt((cx-x)*(cx-x)+(cy-y)*(cy-y));
                           if(separate.getRoadType(r) == GMLRoadType.END) length *= 2;

                           if(separate.getRoadType(r) != GMLRoadType.ENTRANCE){
                               if(Double.isInfinite(length) || Double.isNaN(length)){
                                   System.out.println(r.getID());
                               }else{
                                   System.out.println(length);
                                   roadLength = roadLength.add(new BigDecimal(length));
                               }

                           if(roads.containsKey(r.getID()))
                               roads.put(r.getID(), roads.get(r.getID())+length);
                           else
                               roads.put(r.getID(), length);
                           }
                       }
                    }
                }
            }

        }
        roadDensity = roadDensity/mapArea;

    }

    public Map<Integer,Double> getRoads(){
        return roads;
    }

    public void writeFile(String name){
        try{
            File file = new File(name+".csv");
            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));

            pw.println("c1,c2,c5,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16");
            pw.print(c1+","+buildingCoverage+","+buildingLength+","+buildingDependent+","+maxAdjacentDistance+","+c9+","+distributionRatio+","+contactRoadDistance+","+clearance+","+c13+","+roadLength+","+roadDensity+","+buildingNumberDensity);
            pw.flush();
            pw.close();

            System.out.println(file.getName()+ "Finish!");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
```

## GMLGloss.java

```java=
import maps.gml.GMLBuilding;
import maps.gml.GMLRoad;
import maps.gml.GMLDirectedEdge;
import maps.gml.GMLCoordinates;
import rescuecore2.misc.gui.ScreenTransform;
import org.jhotdraw.geom.*;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.awt.Polygon;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;

import rescuecore2.misc.Pair;

public class GMLGloss {   
    private List<GMLRoad> roads;
    private double semiGlossArea;
    private Polygon2D.Double gloss;
    
    private List<GMLBuilding> buildingsInArea;
    private Map<Integer,Double> buildingsArea;
    
    private List<GMLDirectedEdge> semiGloss;
    private List<Polygon2D> semiGlossShape;
    private List<GMLCoordinates> semiGlossPoints;
    
    private List<List<GMLBuilding>> followBuildings;
    private List<Double> clearance;
    private List<Double> length;
    
    private List<List<Integer>> neighbourBuildings;
    
    private Map<Integer,List<Double>> semiGlossToBuildings;
    private Map<Integer,Map<Integer,Double>> buildingToBuildings;
    
    public GMLGloss(List<GMLRoad> roads){
        this.roads = roads;
        gloss = new Polygon2D.Double();
        semiGlossArea = 0;
        semiGloss = new ArrayList<GMLDirectedEdge>();
        semiGlossShape = new ArrayList<Polygon2D>();
        semiGlossPoints = new ArrayList<GMLCoordinates>();

        buildingsArea = new HashMap<Integer,Double>();
        followBuildings = new ArrayList<List<GMLBuilding>>();
        clearance = new ArrayList<Double>();
        length = new ArrayList<Double>();
        
        neighbourBuildings = new ArrayList<List<Integer>>();
        
        semiGlossToBuildings = new HashMap<Integer,List<Double>>();
        buildingToBuildings = new HashMap<Integer,Map<Integer,Double>>();
        
        int index = 1;
        for(GMLRoad road : roads){
            if(index >= roads.size()) index = 0;
            gloss.addPoint(road.getCentreX(), road.getCentreY());
            for(GMLDirectedEdge edge : road.getEdges()){
                if(road.hasNeighbour(edge)){
                   if(road.getNeighbour(edge).intValue() == roads.get(index).getID()){
                        gloss.addPoint((edge.getStartCoordinates().getX()+edge.getEndNode().getX())/2, (edge.getStartCoordinates().getY()+edge.getEndNode().getY())/2);
                    }
                }
            }           
            index++;
        }
        
        for(GMLRoad road : roads){
            for(GMLDirectedEdge edge : road.getEdges()){
                GMLCoordinates p1 = edge.getStartCoordinates();
                GMLCoordinates p2 = edge.getEndCoordinates();
                if(gloss.contains(p1.getX(), p1.getY()) && gloss.contains(p2.getX(), p2.getY())){
                    if(!semiGloss.contains(edge)){
                        semiGloss.add(edge);
                        
                        semiGlossShape.add(getPolygon2DFromEdge(edge,5.0));
                    }
                    if(!semiGlossPoints.contains(p1)){
                        semiGlossPoints.add(p1);
                    }
                    if(!semiGlossPoints.contains(p2)){
                        semiGlossPoints.add(p2);
                    }
                }
            }
        }
        for(int i=semiGlossPoints.size(),u=0;i-->0;u=i){
            semiGlossArea += (semiGlossPoints.get(i).getX()-semiGlossPoints.get(u).getX())*(semiGlossPoints.get(i).getY()+semiGlossPoints.get(u).getY());
        }
        semiGlossArea = Math.abs(0.5*semiGlossArea);
        
        buildingsInArea = new ArrayList<GMLBuilding>();
    }
    
    public void calculation(){
        calcBuildingArea();
        
        followBuildings();
        calcClearance();
        
        neighbourBuildings();
        
        for(GMLBuilding b : buildingsInArea){
            if(!semiGlossToBuildings.containsKey(b.getID())){
                semiGlossToBuildings.put(b.getID(), calcContactRoadDistance(b));
            }
        }
    }
    
    private void calcBuildingArea(){
        if(buildingsInArea.size() <= 0) return;
        
        for(GMLBuilding building : buildingsInArea){
            double buildingArea = 0;
            List<GMLCoordinates> point = building.getCoordinates();
            for(int i = point.size(),u=0;i-->0;u=i){    
                buildingArea += (point.get(i).getX()-point.get(u).getX())*(point.get(i).getY()+point.get(u).getY());
            }
            buildingsArea.put(building.getID(),Math.abs(0.5*buildingArea));
        }
    }
    
    private void followBuildings(){
        int count = 0;
        for(Polygon2D fArea : semiGlossShape){
            List<GMLBuilding> fB = new ArrayList<GMLBuilding>();
            Polygon2D.Double fA = (Polygon2D.Double)fArea;
            GMLCoordinates start = semiGloss.get(count).getStartCoordinates();
            GMLCoordinates end = semiGloss.get(count).getEndCoordinates();
            Line2D line1 = new Line2D.Double(start.getX(), start.getY(), end.getX(), end.getY());
            
            for(int i = 0; i < buildingsInArea.size(); ++i){
                GMLBuilding building = buildingsInArea.get(i);
                List<GMLDirectedEdge> edges = building.getEdges();
                double length = Double.MAX_VALUE;
                for(int j = 0; j < edges.size(); ++j){
                    GMLDirectedEdge edge = edges.get(j);
                    Line2D.Double line2 = new Line2D.Double(edge.getStartNode().getX(), edge.getStartNode().getY(), edge.getEndNode().getX(), edge.getEndNode().getY());
                    if(contains(fA,line2)){
                        if(!fB.contains(building)){
                            fB.add(building);
                        }
                        if(fA.contains(line2.getP1())){
                            double temp = line1.ptLineDist(line2.getP1());
                            if(length > temp) length = temp;
                        }
                        if(fA.contains(line2.getP2())){
                            double temp = line1.ptLineDist(line2.getP2());
                            if(length > temp) length = temp;
                        }
                        if(length == Double.MAX_VALUE){
                            Polygon2D fA2 = this.getPolygon2DFromEdge(edge, 100);
                            if(fA2.contains(line1.getP1())){
                                double temp = line2.ptLineDist(line1.getP1());
                                if(length > temp) length = temp;
                            }
                            if(fA2.contains(line1.getP2())){
                                double temp = line2.ptLineDist(line1.getP1());
                                if(length > temp) length = temp;
                            }
                        }
                    }
                }
                if(length != Double.MAX_VALUE){
                    List<Double> lengthList = new ArrayList<Double>();
                    if(semiGlossToBuildings.containsKey(building.getID())){
                        lengthList = semiGlossToBuildings.get(building.getID());
                    }
                    lengthList.add(length);
                    semiGlossToBuildings.put(building.getID(), lengthList);
                }
            }
            followBuildings.add(fB);
            count++;
        }
    }
    
    private boolean contains(Polygon2D area, Line2D line){
        Polygon2D.Double fA = (Polygon2D.Double)area;
        Line2D.Double line1 = (Line2D.Double)line;
        
        if(fA.contains(line1.getP1()) && fA.contains(line1.getP2())) return true;
        
        for(int k = 0; k < fA.npoints; ++k){
            int next = k+1;
            if(next == fA.npoints) next = 0;
            Line2D.Double line2 = new Line2D.Double(fA.xpoints[k], fA.ypoints[k], fA.xpoints[next], fA.ypoints[next]);
            if((line1.intersectsLine(line2))){
                if(line1.ptLineDist(line2.getP1())!=0 && line1.ptLineDist(line2.getP2())!=0 && line2.ptLineDist(line1.getP1())!=0 && line2.ptLineDist(line1.getP2())!=0){
                    return true;
                }else{
                    Point2D center = new Point2D.Double(line1.x1+((line1.x2-line1.x1)/2),line1.y1+((line1.y2-line1.y2)/2));
                    if(fA.contains(center)){
                        return true;
                    }
                }
            }
        }
        return false;
    }
    
    private void calcClearance(){
        for(int i = 0; i < semiGloss.size(); ++i){
            GMLDirectedEdge edge = semiGloss.get(i);
            double length = Math.sqrt((edge.getStartNode().getX()-edge.getEndNode().getX())*(edge.getStartNode().getX()-edge.getEndNode().getX())+(edge.getStartNode().getY()-edge.getEndNode().getY())*(edge.getStartNode().getY()-edge.getEndNode().getY()));
            double bL = 0;
            
            for(GMLBuilding building : followBuildings.get(i)){
                double[] ra = range(building,edge);
                bL += ra[1]-ra[0];
            }
            double cL = length - bL;
            clearance.add(cL/length);
            this.length.add(length);
        }
    }
    
    private double[] range(GMLBuilding building, GMLDirectedEdge road) {
        Vector2d x;
        Vector2d r = new Vector2d(road.getStartNode().getX(), road.getStartNode().getY(), road.getEndNode().getX(), road.getEndNode().getY());
        double min=Double.MAX_VALUE, max = Double.MIN_VALUE, length;
        
        double rlength = r.length();
        Vector2d ix;
        Vector2d ir = new Vector2d(r);
        double dot1, dot2;
        ir.inverse();
        
        
        // road to normal vector
        r.normalize();

        for (GMLCoordinates v : building.getCoordinates())
        {
            x = new Vector2d(road.getStartNode().getX(), road.getStartNode().getY(), v.getX(), v.getY());

            length = Math.abs(r.projection(x));
            
            ix = new Vector2d(road.getEndNode().getX(), road.getEndNode().getY(), v.getX(), v.getY());
            dot1 = r.dot(x);
            dot2 = ir.dot(ix);
            if(dot1 <= 0) { //if(dot1 < 0) {
                length = 0;
            }
            if (dot2 <= 0) { //if (dot2 < 0) {
                length = rlength;
            }
            

            if (max < length)
            {
                max = length;
            }
            if (min > length) 
            {
                min = length;
            }
        }

        // create result
        double[] res = new double[2];
        res[0] = min;
        res[1] = max;

        return res;
    }
    
    private void neighbourBuildings(){
        double maxRange = gloss.getBounds2D().getWidth()+gloss.getBounds2D().getHeight();
        
        for(GMLBuilding building1 : buildingsInArea){
            List<Integer> neighbourBuilding = new ArrayList<Integer>();
            Map<Integer,Double> b2bLength = new HashMap<Integer,Double>();
            for(GMLDirectedEdge edge1 : building1.getEdges()){
                double minValue = Double.MAX_VALUE;
                int minID = -1;
                Line2D line1 = new Line2D.Double(edge1.getStartNode().getX(), edge1.getStartNode().getY(), edge1.getEndNode().getX(), edge1.getEndNode().getY());
                Polygon2D p2 = this.getPolygon2DFromEdge(edge1, maxRange);
                
                for(GMLBuilding building2 : buildingsInArea){
                    if(!building1.equals(building2)){
                        for(GMLDirectedEdge edge2 : building2.getEdges()){
                            if(edge1.getEdge().equals(edge2.getEdge())){
                                minValue = 0;
                                minID = building2.getID();
                                b2bLength.put(minID, minValue);
                            }else{
                            Line2D line2 = new Line2D.Double(edge2.getStartNode().getX(), edge2.getStartNode().getY(), edge2.getEndNode().getX(), edge2.getEndNode().getY());
                                if(contains(p2,line2)){
                                    double l = Double.MAX_VALUE;
                                    if(p2.contains(line2.getP1())){
                                        double temp = line1.ptLineDist(line2.getP1());
                                        if(l > temp && temp != 0) l = temp;
                                    }
                                    if(p2.contains(line2.getP2())){
                                        double temp = line1.ptLineDist(line2.getP2());
                                        if(l > temp && temp != 0) l = temp;
                                    }
                                    if(l == Double.MAX_VALUE){
                                        Polygon2D p22 = getPolygon2DFromEdge(edge2,maxRange);
                                        if(p22.contains(line1.getP1())){
                                            double temp = line2.ptLineDist(line1.getP1());
                                            if(l > temp && temp != 0) l = temp;
                                        }
                                        if(p22.contains(line1.getP2())){
                                            double temp = line2.ptLineDist(line1.getP2());
                                            if(l > temp && temp != 0) l = temp;
                                        }
                                    }
                                    
                                    if(minValue >= l && l >= 0){
                                        if(b2bLength.containsKey(building2.getID())){
                                            double ml = b2bLength.get(building2.getID());
                                            if(ml > l){
                                                b2bLength.put(building2.getID(), l);
                                            }
                                        }else{
                                            b2bLength.put(building2.getID(), l);
                                        }
                                        
                                        if(minValue != l){
                                            minValue = l;
                                            minID = building2.getID();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if(minID != -1){
                    neighbourBuilding.add(minID);
                }
            }
            neighbourBuildings.add(neighbourBuilding);
            buildingToBuildings.put(building1.getID(),b2bLength);
        }
    }
    
    private List<Double> calcContactRoadDistance(GMLBuilding b){
        List<Double> result = new ArrayList<Double>();
        double maxRange = gloss.getBounds2D().getWidth()+gloss.getBounds2D().getHeight();
        double minLength = Double.MAX_VALUE;
        
        for(int i = 0; i < gloss.npoints; ++i){
            int next = i+1;
            if(next == gloss.npoints) next = 0;
            
            Line2D line1 = new Line2D.Double(gloss.xpoints[i], gloss.ypoints[i], gloss.xpoints[next], gloss.ypoints[next]);
            Polygon2D pA = this.getPolygon2DFromEdge(line1, maxRange);
            
            for(GMLCoordinates p : b.getCoordinates()){
                if(pA.contains(p.getX(), p.getY())){
                    double temp = line1.ptLineDist(p.getX(), p.getY());
                    if(minLength > temp) minLength = temp;
                }
            }
        }
        if(minLength == Double.MAX_VALUE) System.out.println("YABASHI");
        
        for(GMLDirectedEdge edge : semiGloss){
            Polygon2D pA = getPolygon2DFromEdge(edge,maxRange);
            Line2D line1 = new Line2D.Double(edge.getStartNode().getX(), edge.getStartNode().getY(), edge.getEndNode().getX(), edge.getEndNode().getY());
            
            for(GMLCoordinates p : b.getCoordinates()){
                if(pA.contains(p.getX(), p.getY())){
                    double temp = line1.ptLineDist(p.getX(), p.getY());
                    if(minLength > temp) result.add(temp);
                }
            }
        }
        
        return result;
    }
    
    private double calcl2lLength(Line2D line1, Line2D line2){
        double result = Double.MAX_VALUE;
        double temp;
        
        double x1 = line1.getX1();
        double y1 = line1.getY1();
        double x2 = line1.getX2();
        double y2 = line1.getY2();
        double x3 = line2.getX1();
        double y3 = line2.getY1();
        double x4 = line2.getX2();
        double y4 = line2.getY2();
        
        if(Math.abs(x1-x2) == Math.abs(x3-x4) && Math.abs(y1-y2) == Math.abs(y3-y4)){
            return line1.ptLineDist(x3, y3);
        }
        
        if((x1>x3&&x1<x4) || (x1>x4&&x1<x3) || (y1>y3&&y1<y4) || (y1>y4&&y1<y3)){
            temp = line2.ptLineDist(x1, y1);
            if(result > temp && temp  > 0) result = temp;
        }
        if((x2>x3&&x2<x4) || (x2>x4&&x2<x3) || (y2>y3&&y2<y4) || (y2>y4&&y2<y3)){
            temp = line2.ptLineDist(x2, y2);
            if(result > temp && temp  > 0) result = temp;
        }
        if((x3>x1&&x3<x2) || (x3>x2&&x3<x1) || (y3>y1&&y3<y2) || (y3>y2&&y3<y1)){
            temp = line1.ptLineDist(x3,y3);
            if(result > temp && temp  > 0) result = temp;
        }
        if((x4>x1&&x4<x2) || (x4>x2&&x4<x1) || (y4>y1&&y4<y2) || (y4>y2&&y4<y1)){
            temp = line1.ptLineDist(x4,y4);
            if(result > temp && temp  > 0) result = temp;
        }
        
        if(result == Double.MAX_VALUE) return -1;
        else return result;
    }
    
    private double calcl2lLength(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
        double result = Double.MAX_VALUE;
        double temp;
        
        Line2D.Double line1 = new Line2D.Double(x1, y1, x2, y2);
        Line2D.Double line2 = new Line2D.Double(x3, y3, x4, y4);
        
        return calcl2lLength(line1,line2);
    }
    
    public Map<Integer,List<Double>> getSemiGlossToBuildings(){
        return semiGlossToBuildings;
    }
    
    public Map<Integer,Map<Integer,Double>> getBuildingToBuildings(){
        return buildingToBuildings;
    }
    
    public List<GMLDirectedEdge> getSemiGloss(){
        return semiGloss;
    }
    
    public List<List<GMLBuilding>> getFollowBuildings(){
        return followBuildings;
    }
    
    public List<Double> getClearance(){
        return clearance;
    }
    
    public List<Double> getLength(){
        return length;
    }
    
    public int getBuildingIdInGloss(int buildingID){
        int i = 0;
        
        for(GMLBuilding b : buildingsInArea){
            if(b.getID() == buildingID) return i;
            
            i++;
        }
        return -1;
    }
    
    public List<Integer> getRoadIdInGloss(GMLRoad road){
        List<Integer> result = new ArrayList<Integer>();
        
        for(GMLDirectedEdge edge : road.getEdges()){
            int i = 0;
            for(GMLDirectedEdge edge2 : semiGloss){
                if(edge.equals(edge2)) result.add(i);
                i++;
            }
        }
        
        return result;
    }
    
    public List<Polygon> getSemiGlossShape(ScreenTransform trans){
        List<Polygon> result = new ArrayList<Polygon>();
        
        for(Polygon2D p2 : semiGlossShape){
            Polygon p = new Polygon();
            for(int i = 0; i < p2.npoints; ++i){
                p.addPoint(trans.xToScreen(((Polygon2D.Double)p2).xpoints[i]),trans.yToScreen(((Polygon2D.Double)p2).ypoints[i]));
            }
            result.add(p);
        }
        return result;
    }
    
    public double getArea(){
        return semiGlossArea;
    }
    
    public Map<Integer,Double> getBuildingsArea(){
        return buildingsArea;
    }
    
    public List<GMLBuilding> getBuildingsInArea(){
        return buildingsInArea;
    }
    
    private Polygon2D getPolygon2DFromEdge(Line2D edge, double space){
        Polygon2D result = new Polygon2D.Double();
        
        Point2D start = edge.getP1();
        Point2D end = edge.getP2();

        double xDif = Math.abs(start.getX()-end.getX());
        double yDif = Math.abs(start.getY()-end.getY());
        
        if(xDif == 0){
            result.addPoint(start.getX()-space, start.getY());
            result.addPoint(start.getX()+space, start.getY());
            result.addPoint(end.getX()+space, end.getY());
            result.addPoint(end.getX()-space, end.getY());
        }else if(yDif == 0){
           result.addPoint(start.getX(), start.getY()+space);
           result.addPoint(start.getX(), start.getY()-space);
           result.addPoint(end.getX(), end.getY()-space);
           result.addPoint(end.getX(), end.getY()+space);
       }else{
           if(xDif > yDif){
               //yokonaga
               if(start.getX() > end.getX()){
                Point2D temp = end;
                end = start;
                start = temp;
               }
               if(start.getY() < end.getY()){
                   ///
                   double ang = Math.atan2(yDif,xDif);
                   double ySlope = space * Math.cos(ang);
                   double xSlope = space * Math.sin(ang);
                  result.addPoint(start.getX()+xSlope, start.getY()-ySlope);
                  result.addPoint(start.getX()-xSlope, start.getY()+ySlope);
                  result.addPoint(end.getX()-xSlope, end.getY()+ySlope);
                  result.addPoint(end.getX()+xSlope, end.getY()-ySlope);
               }else{
                   //¥
                   double ang = Math.atan2(yDif,xDif);
                   double ySlope = space * Math.cos(ang);
                   double xSlope = space * Math.sin(ang);
                   result.addPoint(start.getX()-xSlope, start.getY()-ySlope);
                   result.addPoint(start.getX()+xSlope, start.getY()+ySlope);
                   result.addPoint(end.getX()+xSlope, end.getY()+ySlope);
                   result.addPoint(end.getX()-xSlope, end.getY()-ySlope);
               }
           }else{
               //tatenaga
               if(start.getY() > end.getY()){
                   Point2D temp = end;
                   end = start;
                   start = temp;
               }
               if(start.getX() < end.getX()){
                   //¥
                   double ang = Math.atan2(yDif,xDif);
                   double ySlope = space * Math.cos(ang);
                   double xSlope = space * Math.sin(ang);
                   result.addPoint(start.getX()+xSlope, start.getY()-ySlope);
                   result.addPoint(start.getX()-xSlope, start.getY()+ySlope);
                   result.addPoint(end.getX()-xSlope, end.getY()+ySlope);
                   result.addPoint(end.getX()+xSlope, end.getY()-ySlope);
               }else{
                   ///
                   double ang = Math.atan2(yDif,xDif);
                   double ySlope = space * Math.cos(ang);
                   double xSlope = space * Math.sin(ang);
                   result.addPoint(start.getX()-xSlope, start.getY()-ySlope);
                   result.addPoint(start.getX()+xSlope, start.getY()+ySlope);
                   result.addPoint(end.getX()+xSlope, end.getY()+ySlope);
                   result.addPoint(end.getX()-xSlope, end.getY()-ySlope);
               }
           }
       }
        
        return result;
    }
    
    private Polygon2D getPolygon2DFromEdge(GMLDirectedEdge edge, double space){
        Polygon2D result = new Polygon2D.Double();
        
        GMLCoordinates start = edge.getStartCoordinates();
        GMLCoordinates end = edge.getEndCoordinates();

        double xDif = Math.abs(start.getX()-end.getX());
        double yDif = Math.abs(start.getY()-end.getY());
        
        if(xDif == 0){
            result.addPoint(start.getX()-space, start.getY());
            result.addPoint(start.getX()+space, start.getY());
            result.addPoint(end.getX()+space, end.getY());
            result.addPoint(end.getX()-space, end.getY());
        }else if(yDif == 0){
           result.addPoint(start.getX(), start.getY()+space);
           result.addPoint(start.getX(), start.getY()-space);
           result.addPoint(end.getX(), end.getY()-space);
           result.addPoint(end.getX(), end.getY()+space);
       }else{
           if(xDif > yDif){
               //yokonaga
               if(start.getX() > end.getX()){
                GMLCoordinates temp = end;
                end = start;
                start = temp;
               }
               if(start.getY() < end.getY()){
                   ///
                   double ang = Math.atan2(yDif,xDif);
                   double ySlope = space * Math.cos(ang);
                   double xSlope = space * Math.sin(ang);
                  result.addPoint(start.getX()+xSlope, start.getY()-ySlope);
                  result.addPoint(start.getX()-xSlope, start.getY()+ySlope);
                  result.addPoint(end.getX()-xSlope, end.getY()+ySlope);
                  result.addPoint(end.getX()+xSlope, end.getY()-ySlope);
               }else{
                   //¥
                   double ang = Math.atan2(yDif,xDif);
                   double ySlope = space * Math.cos(ang);
                   double xSlope = space * Math.sin(ang);
                   result.addPoint(start.getX()-xSlope, start.getY()-ySlope);
                   result.addPoint(start.getX()+xSlope, start.getY()+ySlope);
                   result.addPoint(end.getX()+xSlope, end.getY()+ySlope);
                   result.addPoint(end.getX()-xSlope, end.getY()-ySlope);
               }
           }else{
               //tatenaga
               if(start.getY() > end.getY()){
                   GMLCoordinates temp = end;
                   end = start;
                   start = temp;
               }
               if(start.getX() < end.getX()){
                   //¥
                   double ang = Math.atan2(yDif,xDif);
                   double ySlope = space * Math.cos(ang);
                   double xSlope = space * Math.sin(ang);
                   result.addPoint(start.getX()+xSlope, start.getY()-ySlope);
                   result.addPoint(start.getX()-xSlope, start.getY()+ySlope);
                   result.addPoint(end.getX()-xSlope, end.getY()+ySlope);
                   result.addPoint(end.getX()+xSlope, end.getY()-ySlope);
               }else{
                   ///
                   double ang = Math.atan2(yDif,xDif);
                   double ySlope = space * Math.cos(ang);
                   double xSlope = space * Math.sin(ang);
                   result.addPoint(start.getX()-xSlope, start.getY()-ySlope);
                   result.addPoint(start.getX()+xSlope, start.getY()+ySlope);
                   result.addPoint(end.getX()+xSlope, end.getY()+ySlope);
                   result.addPoint(end.getX()-xSlope, end.getY()-ySlope);
               }
           }
       }
        
        return result;
    }
    
    public Polygon2D getGloss(){
       return gloss; 
    }
    
    public List<List<Integer>> getNeighbourBuildings(){
        return neighbourBuildings;
    }
    
    public Polygon getPolygon(ScreenTransform trans){
        Polygon p = new Polygon();
        for(int i = 0; i < gloss.npoints; ++i){
            p.addPoint(trans.xToScreen(gloss.xpoints[i]), trans.yToScreen(gloss.ypoints[i]));
        }
        return p;
    }
    
    public boolean setBuilding(GMLBuilding building){
        for(GMLDirectedEdge edge : building.getEdges()){
            for(GMLCoordinates point : edge.getPoints()){
                if(!(gloss.contains(point.getX(), point.getY()))){
                    return false;
                }
            }
        }
        
        buildingsInArea.add(building);   
        return true;
    }
    
    private class Vector2d
    {

        public double x;
        public double y;

        public Vector2d()
        {
            this.x = 0;
            this.y = 0;
        }

        public Vector2d(Vector2d v)
        {
            this.x = v.x;
            this.y = v.y;
        }
        
        public Vector2d(double x, double y)
        {
            this.x = x;
            this.y = y;
        }
        
        public Vector2d(double x1, double y1, double x2, double y2)
        {
            this.x = x2 - x1;
            this.y = y2 - y1;
        }

        public double length()
        {
            return Math.sqrt(x*x + y*y);
        }

        public double dot(Vector2d v)
        {
            return x*v.x + y*v.y;
        }

        public Vector2d norm()
        {
            double l = this.length();
            return new Vector2d(x/l, y/l);
        }

        public void normalize()
        {
            double l = this.length();
            this.x /= l;
            this.y /= l;
        }

        public void add(Vector2d v)
        {
            this.x += v.x;
            this.y += v.y;
        }

        public void mul(double scale)
        {
            this.x *= scale;
            this.y *= scale;
        }

        public void inverse()
        {
            this.x *= -1;
            this.y *= -1;
        }

        public double angular(Vector2d v)
        {
            double denom = this.length() * v.length();
            return Math.acos(this.dot(v) /denom);
        }

        public double projection(Vector2d v)
        {
            double denom = this.length() * v.length();
            return v.length() * this.dot(v) / denom;
        }

    }
}
```