示例#1
0
 /**
  * Constructs a data object from the given <tt>jTrajectory</tt>.
  *
  * @param trajectory Trajectory of which the data needs to be stored.
  */
 public TrajectoryData(Trajectory trajectory) {
   // Get FCD fields as array
   for (java.lang.reflect.Field field : trajectory.getFCDclass().getFields())
     data.put(field.getName(), trajectory.getAsPrimitive(field));
   // Add scalar fields
   trajectory.addScalars(this);
 }
示例#2
0
  @Override
  protected synchronized void resetPlugin() {

    // make a copy so trajectories can remove themselves
    final List<Trajectory> list = new ArrayList<Trajectory>(trajectories);

    // remove all trajectories
    for (final Trajectory t : list) {
      t.cancel();
    }

    assert trajectories.size() == 0;

    this.layer.clear();
  }
示例#3
0
  @Override
  public synchronized void shutdown() throws Exception {
    super.shutdown();

    // make a copy so trajectories can remove themselves
    final List<Trajectory> list = new ArrayList<Trajectory>(trajectories);

    // remove all trajectories
    for (final Trajectory t : list) {
      t.cancel();
    }

    assert trajectories.size() == 0;

    timer.cancel();
  }
示例#4
0
 private void restart() {
   currentTrajectory = new Trajectory(ColorGenerator.getInstance().next());
   gameOver = false;
   ball.setPosition(new Point(INITIAL_BALL_POSITION));
   currentTrajectory.addPoint(ball.getPosition());
   synchronized (trajectoriesLock) {
     trajectories.add(currentTrajectory);
   }
   renderer.getTrajectoriesTableModel().addElement(currentTrajectory);
 }
示例#5
0
 private void clearTrajectories() {
   synchronized (trajectoriesLock) {
     trajectories.clear();
   }
   renderer.getTrajectoriesTableModel().removeAllElements();
   currentTrajectory = new Trajectory(ColorGenerator.getInstance().current());
   if (!gameOver) {
     currentTrajectory.addPoint(ball.getPosition());
     synchronized (trajectoriesLock) {
       trajectories.add(currentTrajectory);
     }
     renderer.getTrajectoriesTableModel().addElement(currentTrajectory);
   }
 }
示例#6
0
  public static void main(String[] args) {

    String inputPrmFile = args[3];
    String inputConfFile = args[4];
    String inputTopFile = args[5];
    String outputTrajFile = args[6];
    String outputEnergyFile = args[7];
    String ITSout = args[8];

    MdSystem<LJParticle> system =
        GromacsImporter.buildLJParticleSystem(
            "JOB_NAME", inputPrmFile, inputConfFile, inputTopFile);

    MdParameter prm = system.getParam();

    final double dt = prm.getDt();
    final int nsteps = prm.getNsteps();
    final int nstlist = prm.getNstlist();
    final int nstxout = prm.getNstxout();
    final int nstvout = prm.getNstvout();
    final int nstenergy = prm.getNstenergy();
    final int nstlog = 10; // prm.getNstlog();
    final double T0 = prm.getT0();
    final double TRef = prm.getRefT();
    final double tauT = prm.getTauT();
    final boolean convertHbonds = prm.convertHbonds();
    if (convertHbonds) {
      system.convertHBondsToConstraints();
    }

    /** ************ ITS setup *************** */
    final int ksize = 12;
    final double Tstep = 25.0; // T increment
    final int ITSEnergyFreq = nstxout; // frequency of energy storing for ITS

    final double[] Temps = new double[ksize];
    final double[] p0 = new double[ksize];

    for (int i = 0; i < ksize; i++) {
      Temps[i] = T0 + i * Tstep;
      p0[i] = 1.0 / ksize;
    }
    /** ************************************* */
    final BigDecimal[] n0 = new BigDecimal[ksize];
    MathContext mathset = new MathContext(5);
    n0[0] = new BigDecimal("5.99880e-03", mathset);
    n0[1] = new BigDecimal("3.64660e+209", mathset);
    n0[2] = new BigDecimal("1.23850e+391", mathset);
    n0[3] = new BigDecimal("2.59790e+548", mathset);
    n0[4] = new BigDecimal("1.21530e+686", mathset);
    n0[5] = new BigDecimal("2.85080e+807", mathset);
    n0[6] = new BigDecimal("2.93170e+915", mathset);
    n0[7] = new BigDecimal("1.33400e+1012", mathset);
    n0[8] = new BigDecimal("1.18050e+1099", mathset);
    n0[9] = new BigDecimal("4.27230e+1177", mathset);
    n0[10] = new BigDecimal("1.70190e+1249", mathset);
    n0[11] = new BigDecimal("2.87210e+1314", mathset);

    // gen valocity
    system.genRandomVelocities(T0);

    /** MPI preparation * */
    MPI.Init(args);
    final int rank = MPI.COMM_WORLD.Rank();
    final int np = MPI.COMM_WORLD.Size();

    Integrator<MdSystem<LJParticle>> integrator = new VelocityVerlet<MdSystem<LJParticle>>(dt);

    FastLJC<MdSystem<LJParticle>> nonbond = new FastLJC<MdSystem<LJParticle>>(system);

    DomainDecomposition<MdSystem<LJParticle>> decomposition =
        new DomainDecomposition<MdSystem<LJParticle>>(system, np);

    Thermostat<MdSystem<LJParticle>> thermostat =
        new BerendsenThermostat<MdSystem<LJParticle>>(TRef, tauT);

    // push initial positions to the new trajectory
    system.forwardPosition(integrator);

    // get partitions using new positions
    system.partition(decomposition);

    Domain domain = decomposition.getDomain(rank);

    DomainNeighborList<MdSystem<LJParticle>> nblist =
        new DomainNeighborList<MdSystem<LJParticle>>(system, domain);

    int SUB_CAPACITY = domain.getCapacity();

    // head node
    if (rank == 0) {

      try {
        PrintStream ps = new PrintStream(outputTrajFile);
        PrintStream psEnergy = new PrintStream(outputEnergyFile);
        PrintStream psITS = new PrintStream(ITSout);

        ITS<MdSystem<LJParticle>> its = new ITS<MdSystem<LJParticle>>(T0, ksize, Temps, p0, n0);
        double Uorg = 0.0;

        for (int tstep = 0; tstep < nsteps; tstep++) {

          if (tstep % nstlog == 0) {
            System.out.println(String.format("Computing t = %5.3f ps", tstep * dt));
          }

          // integrate forward (apply position constraints if applicable)
          if (tstep != 0) {
            system.forwardPosition(integrator);
            system.applyPositionConstraint();
          }

          // (I) update domains and send them to slave nodes
          if (tstep % nstlist == 0) {
            // updates partitions using new positions
            system.partition(decomposition);

            // send updated partition info to slave nodes
            for (int proc = 1; proc < np; proc++) {
              int[] partition = decomposition.exportPartition(proc);
              MPI.COMM_WORLD.Send(partition, 0, SUB_CAPACITY, MPI.INT, proc, 99);
            }
            // update local neighbor list
            nblist.update(system);
          }

          // (II) export new positions to slave nodes
          for (int proc = 1; proc < np; proc++) {
            Domain domainEach = decomposition.getDomain(proc);
            double[] positionArray = system.exportNewPositions(domainEach);

            MPI.COMM_WORLD.Send(positionArray, 0, 3 * SUB_CAPACITY, MPI.DOUBLE, proc, 99);
          }

          // (ITS Step 0 ) compute original energy
          {
            double nonbondEnergy = 0.0;
            nonbondEnergy = system.getNonBondEnergy(nonbond, nblist);
            // receive partial nonbond energies from slave-nodes and add
            for (int proc = 1; proc < np; proc++) {
              double[] partialEnergy = new double[1];

              MPI.COMM_WORLD.Recv(partialEnergy, 0, 1, MPI.DOUBLE, proc, 99);
              nonbondEnergy += partialEnergy[0];
            }
            double coulombEnergy = 0.0; // temporary.
            double bond = system.getBondEnergy();
            double angle = system.getAngleEnergy();
            double dihedral = system.getDihedralEnergy();
            Uorg = nonbondEnergy + bond + angle + dihedral;

            if (tstep % ITSEnergyFreq == 0) {
              its.printEnergy(psITS, system, Uorg);
            }
          }

          // update non-bonded forces
          system.updateNonBondForce(nonbond, nblist);

          // update long-ranged forces

          // update bonded forces
          system.updateBondForce();

          // update angle forces
          system.updateAngleForce();

          // update dihedral forces
          system.updateDihedralForce();

          // (III) receive computed forces from slaves
          for (int proc = 1; proc < np; proc++) {
            double[] forceArray = new double[3 * SUB_CAPACITY];

            MPI.COMM_WORLD.Recv(forceArray, 0, 3 * SUB_CAPACITY, MPI.DOUBLE, proc, 99);

            Domain domainEach = decomposition.getDomain(proc);
            system.importNewForces(domainEach, forceArray);
          }

          // (ITS step 1 ) Apply biasing forces
          its.applyBiasForce(system, Uorg);

          // forward velocities
          system.forwardVelocity(integrator);
          // apply velocity constraints
          system.correctConstraintVelocity();

          // apply temperature coupling
          thermostat.apply(system);

          // print energy (using information in newTraj )
          if (tstep % nstenergy == 0) {
            double nonbondEnergy = 0.0;
            nonbondEnergy = system.getNonBondEnergy(nonbond, nblist);
            // receive partial nonbond energies from slave-nodes and add
            for (int proc = 1; proc < np; proc++) {
              double[] partialEnergy = new double[1];

              MPI.COMM_WORLD.Recv(partialEnergy, 0, 1, MPI.DOUBLE, proc, 99);
              nonbondEnergy += partialEnergy[0];
            }

            double coulombEnergy = 0.0; // temporary.
            mymd.MdIO.printEnergy(system, nonbondEnergy, coulombEnergy, psEnergy);
          }

          // update current trajectories from new trajectories
          system.update();

          if (tstep % nstxout == 0) {
            mymd.MdIO.writeGro(system, ps);
          }
        }

        ps.close();
        psEnergy.close();
      } catch (java.io.IOException ex) {

      }
    }
    // slave nodes
    else {

      decomposition = null;
      String slaveName = String.format("slave-%d", rank);

      /**
       * * change subSystem constructor so it accepts a MdSystem object as an input parameter.
       * SubSystem is needed only if MdSystem object exists. *
       */
      // create a sub-system for slave node
      Trajectory subTraj = new Trajectory(system.getSize());
      subTraj.setBox(system.getBox());
      SubSystem<LJParticle> subsystem =
          new SubSystem.Builder<LJParticle>()
              .name(slaveName)
              .particles(system.getParticles())
              .parameters(system.getParam())
              .topology(system.getTopology())
              .subTrajectory(subTraj)
              .build();

      // mother system is freed. no longer needed for slave nodes
      system = null;

      for (int tstep = 0; tstep < nsteps; tstep++) {

        // (I) receive updated partition info from head node
        if (tstep % nstlist == 0) {
          int[] partition = new int[SUB_CAPACITY];
          MPI.COMM_WORLD.Recv(partition, 0, SUB_CAPACITY, MPI.INT, 0, 99);

          // import received array to its local domain
          domain.importArray(partition);
        }

        // (II) receives new positions
        double[] positionArray = new double[3 * SUB_CAPACITY];
        MPI.COMM_WORLD.Recv(positionArray, 0, SUB_CAPACITY * 3, MPI.DOUBLE, 0, 99);

        // import new positions into the subsystem
        subsystem.importNewPositions(domain, positionArray);

        if (tstep % nstlist == 0) {
          // update local neighbor list
          nblist.update(subsystem);
        }

        // (ITS 0 step)
        double[] partialEnergy = new double[1];
        partialEnergy[0] = subsystem.getNonBondEnergy(nonbond, nblist);

        MPI.COMM_WORLD.Send(partialEnergy, 0, 1, MPI.DOUBLE, 0, 99);

        // compute non-bonded forces
        subsystem.updateNonBondForce(nonbond, nblist);

        // PME

        // (III) export forces and send them to head-node
        double[] forceArray = subsystem.exportNewForces(domain);
        MPI.COMM_WORLD.Send(forceArray, 0, SUB_CAPACITY * 3, MPI.DOUBLE, 0, 99);

        if (tstep % nstenergy == 0) {
          partialEnergy = new double[1];
          partialEnergy[0] = subsystem.getNonBondEnergy(nonbond, nblist);

          MPI.COMM_WORLD.Send(partialEnergy, 0, 1, MPI.DOUBLE, 0, 99);
        }

        // reset force components
        subsystem.update();
      }
    }

    MPI.Finalize();
  }
示例#7
0
  private void update() {
    if (renderer.shouldRestart()) {
      restart();

      renderer.setSpeedX(0.0);
      renderer.setSpeedY(0.0);
      renderer.setMagnusForce(0.0);
      renderer.refreshInformationPanel();

      renderer.resetRestartFlag();
      renderer.stop();
    }
    if (renderer.shouldClearTrajectories()) {
      clearTrajectories();
      renderer.resetClearTrajectoriesFlag();
    }
    if (renderer.hasStarted()) {
      if (!gameOver) {
        synchronized (ballLock) {
          Vector gravitationalForce = new Vector(0.0, -9.81 * ball.getMass());
          Vector frictionForce = Vector.product(-dragCoefficient, ball.getSpeed());
          Vector magnusForceTmp =
              Vector.product(MAGNUS_COEFFICIENT * ball.getFrequency(), ball.getSpeed());
          Vector magnusForce = new Vector(-magnusForceTmp.y, magnusForceTmp.x);

          renderer.setSpeedX(ball.getSpeed().x);
          renderer.setSpeedY(ball.getSpeed().y);
          renderer.setMagnusForce(magnusForce.length());
          renderer.refreshInformationPanel();

          ball.applyForce(Vector.sum(Vector.sum(gravitationalForce, frictionForce), magnusForce));
          ball.update();
          if (ball.getPosition().x <= 0.0) {
            gameOver = true;
          }
          double dy = ball.getPosition().y - ball.getSize().y / 2 - GROUND_Y;
          if (dy <= 0.0) {
            double t = dy / ball.getSpeed().y;
            double dx = t * ball.getSpeed().x;
            Point newPosition = ball.getPosition();
            newPosition.x -= dx;
            newPosition.y -= dy;
            ball.setPosition(newPosition);
            gameOver = true;
          }
          currentTrajectory.addPoint(ball.getPosition());

          renderer.getTrajectoriesTableModel().refreshCell(trajectories.size() - 1, 1);
          renderer.getTrajectoriesTableModel().refreshCell(trajectories.size() - 1, 2);
        }
      }
    } else {
      double initialSpeedX = renderer.getInitialSpeed() * Math.cos(renderer.getInitialDirection());
      double initialSpeedY = renderer.getInitialSpeed() * Math.sin(renderer.getInitialDirection());
      dragCoefficient = renderer.getDragCoefficient();
      synchronized (ballLock) {
        ball.setSpeed(new Vector(initialSpeedX, initialSpeedY));
        ball.setFrequency(renderer.getFrequency());
      }
    }
  }
  public void surfaceCreated(SurfaceHolder holder) {
    renderThread = new DashTillPuffRenderThread(this);
    slicing1_x2 = getWidth();
    slicing1_y2 = getHeight();
    slicing2_x1 = slicing1_x2;
    slicing2_x2 = 2 * slicing2_x1;
    slicing2_y2 = slicing1_y2;

    spaceship_y1 = getHeight() / 2 - spaceship_size / 2;
    spaceship_y2 = spaceship_y1 + spaceship_size;
    // Create the sliding background , cosmic factory , and the space ship
    BitmapFactory.Options options = new BitmapFactory.Options();
    background =
        BitmapFactory.decodeResource(
            this.getResources(), R.drawable.dashtillpuffwallpaper, options);
    spaceship =
        BitmapFactory.decodeResource(
            this.getResources(), R.drawable.dashtillpuffspaceship, options);
    blackhole =
        BitmapFactory.decodeResource(
            this.getResources(), R.drawable.dashtillpuffblackhole, options);
    blueplanet =
        BitmapFactory.decodeResource(
            this.getResources(), R.drawable.dashtillpuffblueplanet, options);
    cloud =
        BitmapFactory.decodeResource(this.getResources(), R.drawable.dashtillpuffcloud, options);
    earth =
        BitmapFactory.decodeResource(this.getResources(), R.drawable.dashtillpuffearth, options);
    glossyplanet =
        BitmapFactory.decodeResource(
            this.getResources(), R.drawable.dashtillpuffglossyplanet, options);
    goldenstar =
        BitmapFactory.decodeResource(
            this.getResources(), R.drawable.dashtillpuffgoldenstar, options);
    neutronstar =
        BitmapFactory.decodeResource(
            this.getResources(), R.drawable.dashtillpuffneutronstar, options);
    shinystar =
        BitmapFactory.decodeResource(
            this.getResources(), R.drawable.dashtillpuffshinystar, options);
    star1 =
        BitmapFactory.decodeResource(this.getResources(), R.drawable.dashtillpuffstar1, options);
    star2 =
        BitmapFactory.decodeResource(this.getResources(), R.drawable.dashtillpuffstar2, options);

    // putting the cosmic project in an array to easily randomly choose them
    cosmicArray = new Bitmap[10];
    cosmicArray[0] = blackhole;
    cosmicArray[1] = blueplanet;
    cosmicArray[2] = cloud;
    cosmicArray[3] = earth;
    cosmicArray[4] = glossyplanet;
    cosmicArray[5] = goldenstar;
    cosmicArray[6] = neutronstar;
    cosmicArray[7] = shinystar;
    cosmicArray[8] = star1;
    cosmicArray[9] = star2;

    trajectory = new Trajectory(this);
    trajectory.setList();

    cosmicfactory = new CosmicFactory(this, trajectory);
    cosmicfactory.setClusterList();

    safe_distance = spaceship_size / 2 + cosmicfactory.cell_width / 2 - 5;
    renderThread.start();
  }
  @Override
  public void tick(Canvas c) {

    // moving the sliding background
    slicing1_x1 -= move;
    slicing1_x2 -= move;
    slicing2_x1 -= move;
    slicing2_x2 -= move;

    // if sliding background is out of the screen, chane the x coordinates to move it back again
    if (slicing1_x2 <= 0) {
      slicing1_x1 = slicing2_x2;
      slicing1_x2 = slicing1_x1 + getWidth();
    }
    if (slicing2_x2 <= 0) {
      slicing2_x1 = slicing1_x2;
      slicing2_x2 = slicing2_x1 + getWidth();
    }
    drawWallPaper(c); // calling to draw the sliding background

    spaceship_y1 += YDown + YVel;
    spaceship_y2 += YDown + YVel;

    if (spaceship_y1 <= 0) {
      spaceship_y1 = 0;
      spaceship_y2 = spaceship_size;
    }

    if (spaceship_y2 >= getHeight()) {
      spaceship_y2 = getHeight();
      spaceship_y1 = spaceship_y2 - spaceship_size;
    }
    pointY = spaceship_y1 + spaceship_size / 2;
    trajectory.tick(c); // calling trajectory tick for the trajectory
    cosmicfactory.tick(c); // calling cosmicfactory tick for the cosmic factory objects
    drawSpaceShip(c); // drawing the spaceship

    // counter for the score
    counter++;
    if (counter % 10 == 0) { // to slow down the counter
      score++; // the real score
    }

    // printing the score on the top left of the screen
    Paint paint2 = new Paint();
    paint2.setColor(Color.WHITE);
    paint2.setTextSize(100);
    c.drawText(Integer.toString(score), 50, 100, paint2);

    // cheking if spaceship is hitting any objects
    int distance;
    check:
    for (int i = 0; i < 10; i++) {
      CosmicObject obj1 = cosmicfactory.Clusters.get(0).get(i);
      CosmicObject obj2 = cosmicfactory.Clusters.get(1).get(i);
      if (obj1.centerX <= pointX + safe_distance && obj1.centerX >= pointX - safe_distance) {
        distance =
            (int)
                Math.sqrt(Math.pow(obj1.centerX - pointX, 2) + Math.pow(obj1.centerY - pointY, 2));
        if (distance < safe_distance) {
          lose = 1;
          break check;
        }
      }

      if (obj2.centerX <= pointX + safe_distance && obj2.centerX >= pointX - safe_distance) {
        distance =
            (int)
                Math.sqrt(Math.pow(obj2.centerX - pointX, 2) + Math.pow(obj2.centerY - pointY, 2));
        if (distance < safe_distance) {
          lose = 1;
          break check;
        }
      }
      /*
      if (obj2.x1 <= 350 && obj2.x2 >= 200) {
          if ((spaceship_y1 >= obj2.y1 && spaceship_y1 <= obj2.y2) ||
                  (spaceship_y2 >= obj2.y1 && spaceship_y2 <= obj2.y2))
          {
              lose = 1;
              break check;
          }
      }*/

    }

    // if lost print out gameover and the score and stop the program
    if (lose == 1) {
      Paint paint4 = new Paint();
      paint4.setColor(Color.WHITE);
      paint4.setTextSize(250);
      c.drawText("Game Over", getWidth() / 2 - 600, getHeight() / 2 - 50, paint4);

      Paint paint5 = new Paint();
      paint5.setColor(Color.WHITE);
      paint5.setTextSize(150);
      c.drawText(
          "Your Score  " + Integer.toString(score),
          getWidth() / 2 - 600,
          getHeight() / 2 + 100,
          paint5);
      renderThread.interrupt();
    }
  }
示例#10
0
  @Override
  protected void createWays(CardinalPoint begin) {

    // Clear all the trajectories
    this.trajectories.row(begin).clear();

    // Set all flows as not available
    this.available_flows.put(begin, CardinalPoint.NORTH, false);
    this.available_flows.put(begin, CardinalPoint.EAST, false);
    this.available_flows.put(begin, CardinalPoint.SOUTH, false);
    this.available_flows.put(begin, CardinalPoint.WEST, false);

    // For each way beginning at the Cardinal Point
    for (int i = 0; i < this.nb_ways.get(Flow.IN, begin); i++) {

      // Create the future way
      Trajectory way = new Trajectory();
      way.setLane(Lane.MID);
      way.setBegin(begin);

      // Get the zone in the conflict zone, dx and dy
      CardinalPoint zone = getZone(begin, Flow.IN);
      int zone_size = this.conflict_zone_size.get(zone);
      int begin_zone_size = this.conflict_zone_size.get(begin);

      int dx = getDX(begin, Flow.IN);
      int dy = getDY(begin, Flow.IN);

      // For each cell of the way before the conflict zone
      // *
      for (int j = this.ways_size.get(Flow.IN, begin); j > 0; j--) {

        // Determine coordinate of the cell
        int cell_x;
        int cell_y;

        // If begin is West or East
        if (begin.isHorizontal()) {
          // X depends of begin zone size, dx and j
          cell_x = this.center_x + dx * (begin_zone_size + j);

          // Y depends of zone size, dy and i
          cell_y = this.center_y + dy * (zone_size - i);
        }
        // If begin is North or South
        else {
          // X depends of zone size, dx and i
          cell_x = this.center_x + dx * (zone_size - i);

          // Y depends of begin zone size, dy and j
          cell_y = this.center_y + dy * (begin_zone_size + j);
        }

        // Add cell to the future way
        way.addCell(new Cell(cell_x, cell_y));
      }
      // */

      /* ----- Casual Case : right lane ----- */
      // *
      if (i == 0) {
        way.setLane(Lane.RIGHT);
        if (this.nb_ways.get(Flow.OUT, begin.getRight()) >= 1) {
          // Create right way, copy of the beginning of way
          Trajectory right_way = new Trajectory(way);

          CardinalPoint right = begin.getRight();
          int right_zone_size = this.conflict_zone_size.get(right);
          int right_dx = getDX(right, Flow.OUT);
          int right_dy = getDY(right, Flow.OUT);

          // For each cell of the way in the conflict zone (j = 0, not 1)
          // For each cell of the way after the conflict zone
          for (int j = 0; j <= this.ways_size.get(Flow.OUT, begin.getRight()); j++) {

            // Determine coordinate of the cell
            int cell_x;
            int cell_y;

            // If begin is West or East
            if (right.isHorizontal()) {
              // X depends of front zone size, dx and j
              cell_x = this.center_x + right_dx * (right_zone_size + j);

              // Y depends of zone size, dy and i
              cell_y = this.center_y + right_dy * (right_zone_size - i);
            }
            // If begin is North or South
            else {
              // X depends of zone size, dx and i
              cell_x = this.center_x + right_dx * (right_zone_size - i);

              // Y depends of front zone size, dy and j
              cell_y = this.center_y + right_dy * (right_zone_size + j);
            }

            // Add cell to the future way
            right_way.addCell(new Cell(cell_x, cell_y));
          }

          // Add the way to the array of trajectories
          this.trajectories.put(begin, this.nb_ways.get(Flow.IN, begin) + i, right_way);

          // Set the flow begin -> right as available
          this.available_flows.put(begin, right, true);
        }
      }
      // */

      /* ----- Casual Case : left lane ----- */
      // *
      if (i == this.nb_ways.get(Flow.IN, begin) - 1) {
        way.setLane(Lane.LEFT);
        if (i < this.nb_ways.get(Flow.OUT, begin.getRight())) {

          // Create right way, copy of the beginning of way
          Trajectory left_way = new Trajectory(way);

          CardinalPoint left = begin.getLeft();
          int left_zone_size = this.conflict_zone_size.get(left);
          int left_dx = getDX(left, Flow.OUT);
          int left_dy = getDY(left, Flow.OUT);

          // If it an indonesian intersection or not
          int n_in;
          int n_out;
          ArrayList<Cell> tmp = new ArrayList<>();
          if (this.indonesian_cross) {
            n_in = begin_zone_size - 1;
            n_out = left_zone_size - 1;
            if (left.isHorizontal()) {
              tmp.add(new Cell(this.center_x, this.center_y + dy));
              tmp.add(new Cell(this.center_x + left_dx, this.center_y));
            } else {
              tmp.add(new Cell(this.center_x + dx, this.center_y));
              tmp.add(new Cell(this.center_x, this.center_y + left_dy));
            }
          } else {
            n_in = begin_zone_size;
            n_out = left_zone_size;
            if (left.isHorizontal()) {
              tmp.add(new Cell(this.center_x + dx, this.center_y));
              tmp.add(new Cell(this.center_x + dx, this.center_y + left_dy));
              tmp.add(new Cell(this.center_x, this.center_y + left_dy));
            } else {
              tmp.add(new Cell(this.center_x, this.center_y + dy));
              tmp.add(new Cell(this.center_x + left_dx, this.center_y + dy));
              tmp.add(new Cell(this.center_x + left_dx, this.center_y));
            }
          }

          for (int j = 0; j < n_in; j++) {
            // Determine coordinate of the cell
            int cell_x;
            int cell_y;

            if (begin.isHorizontal()) {
              // X depends of begin zone size, j and dx
              cell_x = this.center_x + dx * (begin_zone_size - j);

              // Y depends of zone size, i and dy
              cell_y = this.center_y + dy * (zone_size - i);
            } else {
              // X depends of zone size, i and dx
              cell_x = this.center_x + dx * (zone_size - i);

              // Y depends of begin zone size, j and dy
              cell_y = this.center_y + dy * (begin_zone_size - j);
            }

            // Add cell to the future way
            left_way.addCell(new Cell(cell_x, cell_y));
          }

          for (Cell cell : tmp) left_way.addCell(cell);

          for (int j = n_out - 1; j >= 0; j--) {
            // Determine coordinate of the cell
            int cell_x;
            int cell_y;

            if (left.isHorizontal()) {
              // X depends of begin zone size, j and dx
              cell_x = this.center_x + left_dx * (left_zone_size - j);

              // Y depends of zone size, i and dy
              cell_y = this.center_y + left_dy * (left_zone_size - i);
            } else {
              // X depends of zone size, i and dx
              cell_x = this.center_x + left_dx * (left_zone_size - i);

              // Y depends of begin zone size, j and dy
              cell_y = this.center_y + left_dy * (left_zone_size - j);
            }

            // Add cell to the future way
            left_way.addCell(new Cell(cell_x, cell_y));
          }

          // For each cell of the way after the conflict zone
          for (int j = 1; j <= this.ways_size.get(Flow.OUT, begin.getLeft()); j++) {

            // Determine coordinate of the cell
            int cell_x;
            int cell_y;

            // If begin is West or East
            if (left.isHorizontal()) {
              // X depends of front zone size, dx and j
              cell_x = this.center_x + left_dx * (left_zone_size + j);

              // Y depends of zone size, dy and i
              cell_y = this.center_y + left_dy * (left_zone_size - i);
            }
            // If begin is North or South
            else {
              // X depends of zone size, dx and i
              cell_x = this.center_x + left_dx * (left_zone_size - i);

              // Y depends of front zone size, dy and j
              cell_y = this.center_y + left_dy * (left_zone_size + j);
            }

            // Add cell to the future way
            left_way.addCell(new Cell(cell_x, cell_y));
          }

          // Add the way to the array of trajectories
          this.trajectories.put(begin, this.nb_ways.get(Flow.IN, begin) + i, left_way);

          // Set the flow begin -> left as available
          this.available_flows.put(begin, left, true);
        }
      }
      // */

      /* ----- General Case : front lane ----- */

      // If the front way can be create
      // *
      if (i < this.nb_ways.get(Flow.OUT, begin.getFront())
          && !(i == this.nb_ways.get(Flow.IN, begin) - 1
              && this.nb_ways.get(Flow.IN, begin) >= 3)) { // If nb_ways >= 3, left way only go left

        int front_zone_size = this.conflict_zone_size.get(begin.getFront());

        // For each cell of the way in the conflict zone
        for (int j = 0; j < begin_zone_size + front_zone_size + 1; j++) {
          // Determine coordinate of the cell
          int cell_x;
          int cell_y;

          if (begin.isHorizontal()) {
            // X depends of begin zone size, j and dx
            cell_x = this.center_x + dx * (begin_zone_size - j);

            // Y depends of zone size, i and dy
            cell_y = this.center_y + dy * (zone_size - i);
          } else {
            // X depends of zone size, i and dx
            cell_x = this.center_x + dx * (zone_size - i);

            // Y depends of begin zone size, j and dy
            cell_y = this.center_y + dy * (begin_zone_size - j);
          }

          // Add cell to the future way
          way.addCell(new Cell(cell_x, cell_y));
        }

        // For each cell of the way after the conflict zone
        for (int j = 1; j <= this.ways_size.get(Flow.OUT, begin.getFront()); j++) {

          // Determine coordinate of the cell
          int cell_x;
          int cell_y;

          // If begin is West or East
          if (begin.isHorizontal()) {
            // X depends of front zone size, dx and j
            cell_x = this.center_x - dx * (front_zone_size + j);

            // Y depends of zone size, dy and i
            cell_y = this.center_y + dy * (zone_size - i);
          }

          // If begin is North or South
          else {
            // X depends of zone size, dx and i
            cell_x = this.center_x + dx * (zone_size - i);

            // Y depends of front zone size, dy and j
            cell_y = this.center_y - dy * (front_zone_size + j);
          }

          // Add cell to the future way
          way.addCell(new Cell(cell_x, cell_y));
        }
      }
      // */

      // Add the way to the array of trajectories
      this.trajectories.put(begin, i, way);

      // Set the flow begin -> front as available
      this.available_flows.put(begin, begin.getFront(), true);
    }
  }