Package trafficjams.model.factories

Source Code of trafficjams.model.factories.RoadMapFactory

package trafficjams.model.factories;

import trafficjams.model.Numbers;
import trafficjams.model.classes.CrossRoad;
import trafficjams.model.classes.Road;
import trafficjams.model.interfaces.ICrossRoad;
import trafficjams.model.interfaces.IRoad;
import trafficjams.model.registers.RoadMap;
import trafficjams.model.trafficutils.CrossDirections;
import trafficjams.model.util.Point;

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

/**
* Created by IntelliJ IDEA.
* User: Администратор
* Date: 13.11.11
* Time: 15:25
* To change this template use File | Settings | File Templates.
*/
public class RoadMapFactory {
    static {
        instance = new RoadMapFactory();
    }

    public static final  int left = CrossDirections.left ;
    public static final int right = CrossDirections.right ;
    public static final int up = CrossDirections.up;
    public static final int down = CrossDirections.down;

    private static final RoadMapFactory instance;

    public static RoadMapFactory getInstance(){
        return instance;
    }

    public RoadMap makeRoadMap(int crossCount, int autoCount, int tryCount) throws Exception {
        System.out.println("Try to get road map: "+(crossCount-tryCount+1));
        RoadMap retVal = new RoadMap();
        float gorLength = Numbers.mapWidth / (float)crossCount /*- 2*/ ;
        float vertLength = Numbers.mapHeight / (float) crossCount /*- 2*/ ;
        ICrossRoad[][] a_crossRoads= new ICrossRoad[crossCount][crossCount];
        ArrayList<ICrossRoad> l_crossRoads = new ArrayList<ICrossRoad>(crossCount*crossCount);
        ArrayList<IRoad> roads = new ArrayList<IRoad>();
        Road r = null;

        //создаем перекрестки и дороги ввиде сетки, уже смещенной
        for (int i = 0 ; i<crossCount; ++i){
            if (i==0){
                for (int j = 0 ; j < crossCount; ++j){
                    CrossRoad currCross = new CrossRoad(retVal);
                    l_crossRoads.add(currCross);
                    currCross.setCoord(new Point(gorLength*i + gorLength*rand(), vertLength*j + vertLength * rand()));
                    a_crossRoads[i][j] = currCross;
                    if (j==0){
                        continue;
                    }
                    r = new Road(retVal);
                    roads.add(r);
                    r.setFCross(a_crossRoads[i][j-1]);
                    r.setLCross(currCross);

                    ((CrossRoad)a_crossRoads[i][j-1]).setRoadForDirection(r, right);
                    currCross.setRoadForDirection(r, left);

                }
                continue;
            }

            for (int j = 0 ; j < crossCount; ++j){
                CrossRoad currCross = new CrossRoad(retVal);
                l_crossRoads.add(currCross);
                currCross.setCoord(new Point(gorLength*i + gorLength*rand(), vertLength*j + vertLength * rand()));
                a_crossRoads[i][j] = currCross;
                r = new Road(retVal);
                roads.add(r);
                r.setFCross(a_crossRoads[i-1][j]);
                r.setLCross(currCross);
                ((CrossRoad)a_crossRoads[i-1][j]).setRoadForDirection(r, down);
                currCross.setRoadForDirection(r, up);
                if (j==0){
                    continue;
                }
                r = new Road(retVal);
                roads.add(r);
                r.setFCross(a_crossRoads[i][j-1]);
                r.setLCross(currCross);

                ((CrossRoad)a_crossRoads[i][j-1]).setRoadForDirection(r, right);
                currCross.setRoadForDirection(r, left);

            }
        }

        //убиваем координаты выходящие за границы(выставляем в границы)
        this.removeNegatives(l_crossRoads);

        //выбираем дороги для уничтожения
        ArrayList<IRoad> toDelete = new ArrayList<IRoad>();
        for (IRoad __r : roads){
            if (Math.random()<Numbers.percent){
                toDelete.add(__r);
            }
        }

        //удаляем дороги
        for (IRoad __r : toDelete){
            if (!roads.remove(__r))
                throw new Exception("дорога не удалилась!");
            Road _r = (Road) __r;
            ((CrossRoad)_r.getFCross()).deleteRoad(_r);
            ((CrossRoad)_r.getLCross()).deleteRoad(_r);
        }

        //удаляем перекрестки в которые входят 0 или 2 дороги (и соединяем дорогий то что разъединилось)
        for (int i = 0 ; i<crossCount ; ++i){
            for (int j = 0 ; j<crossCount; ++j){
                CrossRoad cr = (CrossRoad) a_crossRoads[i][j];
                if (cr.getType()  == 0){
                    if (!l_crossRoads.remove(a_crossRoads[i][j]))
                        throw new Exception("перекресток не удалился!");
                    a_crossRoads[i][j] = null;
                }
                if (cr.getType()  == 2){
                    if (!l_crossRoads.remove(a_crossRoads[i][j]))
                        throw new Exception("перекресток не удалился!");
                    a_crossRoads[i][j] = null;
                    IRoad[] rd = cr.get2Roads();
                    CrossRoad c0 = (CrossRoad)((Road)rd[0]).getOtherEnd(cr);
                    CrossRoad c1 = (CrossRoad)((Road)rd[1]).getOtherEnd(cr);

                    if (!(roads.remove(rd[0]) && roads.remove(rd[1])))
                        throw new Exception("road remove error");

                    IRoad newRoad = this.createConnector(c0,c1);
                    roads.add(newRoad);
                    ((CrossRoad) c0).setRoadForDirection(newRoad, c0.deleteRoad(rd[0]));
                    ((CrossRoad) c1).setRoadForDirection(newRoad, c1.deleteRoad(rd[1]));
                }
            }
        }

        //проверяем на связность
        if (!this.isCorrect(l_crossRoads, roads, tryCount)){
            return this.makeRoadMap(crossCount,autoCount,--tryCount);
        }

        //проверяем перекрестки и инициализируем очереди
        for (ICrossRoad iCrossRoad: l_crossRoads){
            CrossRoad crossRoad = (CrossRoad) iCrossRoad;
            if (crossRoad.getType()==2){
                return this.makeRoadMap(crossCount, autoCount, --tryCount);
            }
            crossRoad.initQueues();
        }

        ///выставляем длины дорог
        float maxLength = 0;
        float minLength = Math.max(Numbers.mapHeight, Numbers.mapWidth);
        for (IRoad __r : roads){
            Road _r = (Road)__r;
            float l = 0;
            float x1 = _r.getFCross().getCoord().getX();
            float x2 = _r.getLCross().getCoord().getX();
            float y1 = _r.getFCross().getCoord().getY();
            float y2 = _r.getLCross().getCoord().getY();
            l = (float) Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
            _r.setLength(l);
            if (l>maxLength){
                maxLength = l;
            }
            if (l<minLength){
                minLength = l ;
            }
        }
        retVal.setMaxSpeed(maxLength / Numbers.HOUR_IN_SECONDS ) ;
        retVal.setMinDist(minLength  / Numbers.AUTO_SHORROAD_COUNT);
        retVal.setCrossBuffer(retVal.getMinDist() * Numbers.CROSS_BUFFER_PERCENT);
        //и макс скорость и мин дистанцию

        retVal.setL_crossRoads(l_crossRoads);
        retVal.setA_crossRoads(a_crossRoads);
        retVal.setRoads((ArrayList<IRoad>)roads);
        return retVal;
    }   //makeRoadMap

    private boolean isCorrect(ArrayList<ICrossRoad> crosses, ArrayList<IRoad> roads, int tryCount) throws Exception {
        if (tryCount<0)
            throw new Exception("не удалось получить планарный связный граф");

        //java.util.
        HashSet<CrossRoad> register = new HashSet<CrossRoad>();
        this.checkBfs(crosses, register);
        if (register.size() != crosses.size()){
            return false;
        }

        for (IRoad r1 :roads){
            for (IRoad r2 : roads){
                if (r1.equals(r2)){
                    continue;
                }
                if (this.roadsCross(r1,r2))
                    return false;
            }
        }
        return true;
    }

    private void checkBfs(ArrayList<ICrossRoad> crosses, HashSet<CrossRoad> register) throws Exception {
        CrossRoad cr = (CrossRoad) crosses.get(0);
        if (cr != null){
            register.add(cr);
            _checkBfs(cr, register);
        }
    }

    private void _checkBfs(CrossRoad cr, HashSet<CrossRoad> register) throws Exception {
        for (IRoad r : cr.getRoads()){
            if (r != null){
                CrossRoad _cr = (CrossRoad)((Road) r).getOtherEnd((ICrossRoad)cr);
                if (!register.contains(_cr)){
                    register.add(_cr);
                    this._checkBfs(_cr, register);
                }
            }
        }
    }

    private boolean roadsCross(IRoad r1, IRoad r2) {
        return false;
       /* Point a = r1.getFCross().getCoord();
        Point b = r1.getLCross().getCoord();
        Point c = r2.getFCross().getCoord();
        Point d = r2.getLCross().getCoord();

        return _roadsCross (a.getX(), b.getX(), c.getX(), d.getX())
    && _roadsCross (a.getY(), b.getY(), c.getY(), d.getY())
    && area(a,b,c) * area(a,b,d) <= 0
    && area(c,d,a) * area(c,d,b) <= 0;  */

    }

    private float area(Point a, Point b, Point c) {
        return Math.signum((b.getX() - a.getX()) * (c.getY() - a.getY()) - (b.getY() - a.getY()) * (c.getX() - a.getX()));
    }

    private boolean _roadsCross(float a, float b , float c , float d) {
        float t = a;
        if (a > b){
            a = b;
            b = t;
        }
        t = c ;
      if (c > d){
            c = d;
            d = t;
        }
      return Math.max(a,c) <= Math.min(b,d);
    }

    private void removeNegatives(ArrayList<ICrossRoad> l_crossRoads) {
        for (ICrossRoad _cr : l_crossRoads){
            CrossRoad cr = (CrossRoad) _cr;
            Point p = cr.getCoord();
            float d = 0 ;
            if (p.getX()<0){
               // p.setX(Math.abs(p.getX()));
                p.setX(0);
            }
            if (p.getY()<0){
                //p.setY(Math.abs(p.getY()));
                p.setY(0);
            }
            if (p.getX()>Numbers.mapWidth){
                //p.setX(2*Numbers.mapWidth - p.getX());
                p.setX(0);
            }
            if (p.getY()>Numbers.mapWidth){
               //p.setY((2*Numbers.mapHeight-p.getY()));
               p.setY(0);
            }
            cr.setCoord(p);
        }
    }

    private IRoad createConnector(ICrossRoad c0, ICrossRoad c1) {
        Road retVal = new Road(c0.getMap());
        if (c0.getCoord().getY()<c1.getCoord().getY()){
            retVal.setFCross(c0);
            retVal.setLCross(c1);
        }else {
            if (c0.getCoord().getX()<c1.getCoord().getX()){
                retVal.setFCross(c0);
                retVal.setLCross(c1);
            }else {
                retVal.setFCross(c1);
                retVal.setLCross(c0);
            }
        }
        return retVal;
    }

    private float rand(){
        return (float) (0.5f*Math.pow(-1, Math.round(Math.random())) * Math.random());
        //return 0.0f;
    }
}
TOP

Related Classes of trafficjams.model.factories.RoadMapFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.