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

it.unibo.alchemist.model.physics.environments.InfiniteHalls Maven / Gradle / Ivy

/*
 * Copyright (C) 2010-2023, Danilo Pianini and contributors
 * listed, for each module, in the respective subproject's build.gradle.kts file.
 *
 * This file is part of Alchemist, and is distributed under the terms of the
 * GNU General Public License, with a linking exception,
 * as described in the file LICENSE in the Alchemist distribution's top directory.
 */

package it.unibo.alchemist.model.physics.environments;

import it.unibo.alchemist.model.Incarnation;
import it.unibo.alchemist.model.positions.Euclidean2DPosition;

/**
 * @param  concentration type
 */
public final class InfiniteHalls extends LimitedContinuos2D {

    private static final long serialVersionUID = -7481116157809902856L;
    private static final double DEFAULT_SIZE = 10;
    private static final double[] BORDERS = { 0.89, 0.39, 0.51, 0.09, 0.81 };
    private static final int EXI = 0, CII = 1, CFI = 2, SII = 3, SFI = 4;
    private final double s, ex, ci, cf, si, sf;
    private boolean doorsOpen;

    /**
     * Default builder. Builds halls of size 10 with open doors.
     * @param incarnation the incarnation to be used.
     */
    public InfiniteHalls(final Incarnation incarnation) {
        this(incarnation, DEFAULT_SIZE);
    }

    /**
     * @param incarnation the incarnation to be used.
     * @param size
     *            the size of a single hall
     */
    public InfiniteHalls(final Incarnation incarnation, final double size) {
        this(incarnation, size, true);
    }

    /**
     * @param incarnation the incarnation to be used.
     * @param allOpen
     *            sets all the doors to open.
     */
    public InfiniteHalls(final Incarnation incarnation, final boolean allOpen) {
        this(incarnation, DEFAULT_SIZE, allOpen);
    }

    /**
     * @param incarnation the incarnation to be used.
     * @param size
     *            the size of a single hall
     * @param allOpen
     *            sets all the doors to open.
     */
    public InfiniteHalls(final Incarnation incarnation, final double size, final boolean allOpen) {
        super(incarnation);
        doorsOpen = allOpen;
        s = size;
        ex = size * BORDERS[EXI];
        ci = size * BORDERS[CII];
        cf = size * BORDERS[CFI];
        si = size * BORDERS[SII];
        sf = size * BORDERS[SFI];
    }

    /**
     * @return the hall size
     */
    public double getHallSize() {
        return s;
    }

    /**
     * @return external border margin
     */
    public double getEx() {
        return ex;
    }

    /**
     * @return Central corridor initial margin
     */
    public double getCi() {
        return ci;
    }

    /**
     * @return Central corridor initial margin
     */
    public double getCf() {
        return cf;
    }

    /**
     * @return Other corridor initial margin
     */
    public double getSi() {
        return si;
    }

    /**
     * @return Other corridor initial margin
     */
    public double getSf() {
        return sf;
    }

    /**
     * Checks whether a position is allowed or not.
     * 
     * @param xp
     *            the x coordinate
     * @param yp
     *            the y coordinate
     * @return true if the position is allowed
     */
    public boolean allowed(final double xp, final double yp) {
        final double x = (xp % s + s) % s;
        final double y = (yp % s + s) % s;
        return x >= ex // Right corridor
            || y >= ex // Upper corridor
            || x >= ci && x <= cf // Vertical lane
            || doorsOpen && y >= ci && y <= cf // Horizontal lane
            || x >= si && x <= sf && y >= si && y <= sf; // Room
    }

    @Override
    protected boolean isAllowed(final Euclidean2DPosition p) {
        final double[] coord = p.getCoordinates();
        return allowed(coord[0], coord[1]);
    }

    @Override
    protected Euclidean2DPosition next(final double ox, final double oy, final double nx, final double ny) {
        if (allowed(nx, ny)) {
            return makePosition(nx - ox, ny - oy);
        }
        final int snx = (int) (ox / s);
        final int sny = (int) (oy / s);
        final double oxm = ox % s;
        final double oym = oy % s;
        final double x = (nx % s + s) % s;
        final double y = (ny % s + s) % s;
        double nxm = nx;
        double nym = ny;
        if (oxm >= ex) {
            // Right corridor
            if (x < ex) {
                nxm = snx * s + ex;
            } else if (x > s) {
                nxm = snx * s + s;
            }
        } else if (oym >= ex) {
            // Upper corridor
            if (y < ex) {
                nym = sny * s + ex;
            } else if (y > s) {
                nym = sny * s + s;
            }
        } else if (oxm >= si && oxm <= sf && oym <= si && oxm <= sf) {
            // Main room
            if (x < si) {
                nxm = snx * s + si;
            } else if (x > sf) {
                nxm = snx * s + sf;
            }
            if (y < si) {
                nym = sny * s + si;
            } else if (y > sf) {
                nym = sny * s + sf;
            }
        } else if (doorsOpen && oym >= ci && oym <= cf) {
            // Horizontal lane passes (room positions and corridors already
            // checked)
            if (y > cf) {
                nym = sny * s + cf;
            } else if (y < ci) {
                nym = sny * s + ci;
            }
        } else if (oxm >= ci && oxm <= cf) {
            // Vertical lane passes (room positions and corridors already
            // checked)
            if (x < ci) {
                nxm = snx * s + ci;
            } else if (x > cf) {
                nxm = snx * s + cf;
            }
        }
        return new Euclidean2DPosition(nxm, nym);
    }

    /**
     * @return true if the room has 4 open accesses, false otherwise
     */
    public boolean isDoorsOpen() {
        return doorsOpen;
    }

    /**
     * @param isOpen
     *            must be true if the user wants all the four exits of the room
     *            to be open. If false, only two passages will be available.
     */
    public void setDoorsOpen(final boolean isOpen) {
        doorsOpen = isOpen;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy