Commit 12fdc83b authored by Ant01n3's avatar Ant01n3

Merge branch 'master' of github.com:graphstream/gs-boids

parents 44f63c2c fbe65e39
......@@ -189,13 +189,13 @@
<dependency>
<groupId>org.graphstream</groupId>
<artifactId>gs-core</artifactId>
<version>1.1.1</version>
<version>1.2-git</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>org.graphstream</groupId>
<artifactId>gs-algo</artifactId>
<version>1.1</version>
<version>1.2-git</version>
<optional>false</optional>
</dependency>
</dependencies>
......
......@@ -33,9 +33,7 @@ import java.util.LinkedList;
import org.graphstream.graph.implementations.AbstractGraph;
import org.graphstream.graph.implementations.AdjacencyListNode;
import org.miv.pherd.Particle;
import org.miv.pherd.geom.Point3;
import org.miv.pherd.geom.Vector3;
/**
* Represents a single bird-oid object.
......@@ -62,7 +60,6 @@ import org.miv.pherd.geom.Vector3;
public class Boid extends AdjacencyListNode {
protected final BoidSpecies species;
protected BoidParticle particle;
/** Parameters of this group of boids. */
......@@ -80,23 +77,22 @@ public class Boid extends AdjacencyListNode {
public Boid(AbstractGraph graph, BoidSpecies species, String id) {
super(graph, id);
this.particle = new BoidParticle((BoidGraph) graph);
this.species = species;
this.forces = getDefaultForces();
this.forces = null;
}
/**
* Force the position of the boid in space.
*/
public void setPosition(double x, double y, double z) {
particle.setPosition(x, y, z);
forces.setPosition(x, y, z);
}
/**
* Actual position of the boid in space.
*/
public Point3 getPosition() {
return particle.getPosition();
return forces.getPosition();
}
/**
......@@ -106,23 +102,16 @@ public class Boid extends AdjacencyListNode {
return species;
}
/**
* The underlying particle of the force system this boids is linked to.
*/
public BoidParticle getParticle() {
return particle;
public void setForces(BoidForces forces) {
this.forces = forces;
}
/**
* The forces acting on the boids, this is a set of vectors and parameters
* computed at each time step.
*/
public BoidForces getDefaultForces() {
return new BoidForces.BasicForces();
public BoidForces getForces() {
return forces;
}
protected void checkNeighborhood(BoidParticle... particles) {
if (particles != null) {
public void checkNeighborhood(Boid... boids) {
if (boids != null) {
Iterator<Boid> it = getNeighborNodeIterator();
LinkedList<Boid> toRemove = null;
......@@ -130,14 +119,14 @@ public class Boid extends AdjacencyListNode {
boolean found = false;
Boid b = it.next();
for (BoidParticle p : particles) {
if (p.getId().equals(b.getParticle().getId())) {
for (Boid b2 : boids) {
if (b == b2) {
found = true;
break;
}
}
if (!found && !forces.isVisible(b.particle, this.getPosition())) {
if (!found && !forces.isVisible(b, this.getPosition())) {
if (toRemove == null)
toRemove = new LinkedList<Boid>();
......@@ -152,12 +141,14 @@ public class Boid extends AdjacencyListNode {
toRemove.clear();
toRemove = null;
}
for (BoidParticle p : particles) {
if (getEdgeBetween(p.getBoid().getId()) == null) {
getGraph().addEdge(getEdgeId(this, p.getBoid()), getId(),
p.getBoid().getId());
}
for (Boid b2 : boids) {
if (getEdgeBetween(b2) == null)
getGraph().addEdge(getEdgeId(this, b2), this, b2);
}
} else {
while (getDegree() > 0)
getGraph().removeEdge(getEdge(0));
}
}
......@@ -176,140 +167,4 @@ public class Boid extends AdjacencyListNode {
return String.format("%s--%s", b1.getId(), b2.getId());
}
/**
* Internal representation of the boid position, and direction in the forces
* system.
*
* @author Guilhelm Savin
* @author Antoine Dutot
*/
class BoidParticle extends Particle {
/**
* Direction of the boid.
*/
protected Vector3 dir;
/**
* Set of global parameters.
*/
protected BoidGraph ctx;
/**
* Number of boids in view at each step.
*/
protected int contacts = 0;
/**
* Number of boids of my group in view at each step.
*/
protected int mySpeciesContacts = 0;
/**
* New particle.
*
* @param ctx
* The set of global parameters.
*/
public BoidParticle(BoidGraph ctx) {
super(Boid.this.getId(), ctx.random.nextDouble() * (ctx.area * 2)
- ctx.area, ctx.random.nextDouble() * (ctx.area * 2)
- ctx.area, 0);
this.dir = new Vector3(ctx.random.nextDouble(), ctx.random
.nextDouble(), 0);
this.ctx = ctx;
}
@Override
public void move(int time) {
contacts = 0;
mySpeciesContacts = 0;
forces.compute(Boid.this, cell.getTree().getRootCell());
forces.direction.scalarMult(species.directionFactor);
forces.attraction.scalarMult(species.attractionFactor);
forces.repulsion.scalarMult(species.repulsionFactor);
dir.scalarMult(species.inertia);
dir.add(forces.direction);
dir.add(forces.attraction);
dir.add(forces.repulsion);
if (ctx.normalizeMode) {
double len = dir.normalize();
if (len <= species.minSpeed)
len = species.minSpeed;
else if (len >= species.maxSpeed)
len = species.maxSpeed;
dir.scalarMult(species.speedFactor * len);
} else {
dir.scalarMult(species.speedFactor);
}
if (ctx.storeForcesAttributes)
forces.store(this);
checkWalls();
nextPos.move(dir);
Boid.this.setAttribute("xyz", pos.x, pos.y, pos.z);
moved = true;
}
@Override
public void inserted() {
}
@Override
public void removed() {
}
public Boid getBoid() {
return Boid.this;
}
public void setPosition(double x, double y, double z) {
initPos(x, y, z);
}
/**
* Check the boid does not go out of the space walls.
*/
protected void checkWalls() {
// /float area = ctx.area;
float aarea = 0.000001f;
if (nextPos.x + dir.data[0] <= ctx.getSpace().getLoAnchor().x
+ aarea) {
nextPos.x = ctx.getSpace().getLoAnchor().x + aarea;
dir.data[0] = -dir.data[0];
} else if (nextPos.x + dir.data[0] >= ctx.getSpace().getHiAnchor().x
- aarea) {
nextPos.x = ctx.getSpace().getHiAnchor().x - aarea;
dir.data[0] = -dir.data[0];
}
if (nextPos.y + dir.data[1] <= ctx.getSpace().getLoAnchor().y
+ aarea) {
nextPos.y = ctx.getSpace().getLoAnchor().y + aarea;
dir.data[1] = -dir.data[1];
} else if (nextPos.y + dir.data[1] >= ctx.getSpace().getHiAnchor().y
- aarea) {
nextPos.y = ctx.getSpace().getHiAnchor().y - aarea;
dir.data[1] = -dir.data[1];
}
if (nextPos.z + dir.data[2] <= ctx.getSpace().getLoAnchor().z
+ aarea) {
nextPos.z = ctx.getSpace().getLoAnchor().z + aarea;
dir.data[2] = -dir.data[2];
} else if (nextPos.z + dir.data[2] >= ctx.getSpace().getHiAnchor().z
- aarea) {
nextPos.z = ctx.getSpace().getHiAnchor().z - aarea;
dir.data[2] = -dir.data[2];
}
}
}
}
\ No newline at end of file
This diff is collapsed.
/*
* Copyright 2006 - 2012
* Antoine Dutot <antoine.dutot@graphstream-project.org>
* Guilhelm Savin <guilhelm.savin@graphstream-project.org>
*
* This file is part of gs-boids <http://graphstream-project.org>.
*
* gs-boids is a library whose purpose is to provide a boid behavior to a set of
* particles.
*
* This program is free software distributed under the terms of two licenses, the
* CeCILL-C license that fits European law, and the GNU Lesser General Public
* License. You can use, modify and/ or redistribute the software under the terms
* of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
* URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
*/
package org.graphstream.boids;
import org.miv.pherd.geom.Point3;
/**
* Object used to create and compute forces of boids.
*
*/
public interface BoidForcesFactory {
/**
* Create a new forces object for a boid.
*
* @param b
* the boid
* @return a new forces object associate with the boid
*/
BoidForces createNewForces(Boid b);
/**
* Compute forces for all boids.
*/
void step();
/**
* Resize the space.
*
* @param minx
* @param miny
* @param minz
* @param maxx
* @param maxy
* @param maxz
*/
void resize(Point3 low, Point3 high);
/**
* Terminate all operations.
*/
void end();
}
......@@ -113,8 +113,8 @@ public class BoidGenerator extends SourceBase implements Generator {
*/
public void end() {
ctx.clearSinks();
ctx.pbox.removeAllParticles();
ctx.clear();
ctx = null;
}
......
......@@ -35,6 +35,7 @@ import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import org.graphstream.boids.forces.ntree.NTreeForcesFactory;
import org.graphstream.graph.Graph;
import org.graphstream.graph.NodeFactory;
import org.graphstream.graph.implementations.AbstractNode;
......@@ -42,10 +43,7 @@ import org.graphstream.graph.implementations.AdjacencyListGraph;
import org.graphstream.stream.file.FileSourceDGS;
import org.graphstream.ui.swingViewer.Viewer;
import org.graphstream.ui.swingViewer.util.Camera;
import org.miv.pherd.ParticleBox;
import org.miv.pherd.ntree.Anchor;
import org.miv.pherd.ntree.CellSpace;
import org.miv.pherd.ntree.OctreeCellSpace;
import org.miv.pherd.geom.Point3;
import java.util.Random;
......@@ -100,13 +98,6 @@ public class BoidGraph extends AdjacencyListGraph {
*/
protected long randomSeed;
protected CellSpace space;
/**
* The particles.
*/
protected ParticleBox pbox;
/**
* Species for boids.
*/
......@@ -127,6 +118,11 @@ public class BoidGraph extends AdjacencyListGraph {
*/
protected Random random;
protected BoidForcesFactory forcesFactory;
protected Point3 lowAnchor;
protected Point3 highAnchor;
/**
* New context.
*/
......@@ -134,11 +130,11 @@ public class BoidGraph extends AdjacencyListGraph {
super("boids-context");
setNodeFactory(new BoidFactory());
int maxParticlesPerCell = 10;
random = new Random();
randomSeed = random.nextLong();
random = new Random(randomSeed);
lowAnchor = new Point3(-1, -1, -1);
highAnchor = new Point3(1, 1, 1);
loop = false;
normalizeMode = true;
removeCaughtBoids = false;
......@@ -147,9 +143,7 @@ public class BoidGraph extends AdjacencyListGraph {
area = 1;
maxSteps = 0;
boidSpecies = new HashMap<String, BoidSpecies>();
space = new OctreeCellSpace(new Anchor(-area, -area, -area),
new Anchor(area, area, area));
pbox = new ParticleBox(maxParticlesPerCell, space, new BoidCellData());
forcesFactory = new NTreeForcesFactory(this);
}
public BoidGraph(String dgsConfig) throws IOException {
......@@ -200,10 +194,11 @@ public class BoidGraph extends AdjacencyListGraph {
config.removeSink(this);
}
// Access
public CellSpace getSpace() {
return space;
public void setForcesFactory(BoidForcesFactory bff) {
if (forcesFactory != null)
forcesFactory.end();
forcesFactory = bff;
}
public double getArea() {
......@@ -212,11 +207,19 @@ public class BoidGraph extends AdjacencyListGraph {
public void setArea(double area) {
this.area = area;
lowAnchor.set(-area, -area, -area);
highAnchor.set(area, area, area);
Anchor lo = new Anchor(-area, -area, -area);
Anchor hi = new Anchor(area, area, area);
forcesFactory.resize(lowAnchor, highAnchor);
}
public Point3 getLowAnchor() {
return lowAnchor;
}
this.space.resize(lo, hi);
public Point3 getHighAnchor() {
return highAnchor;
}
public long getRandomSeed() {
......@@ -260,25 +263,16 @@ public class BoidGraph extends AdjacencyListGraph {
this.storeForcesAttributes = storeForcesAttributes;
}
public int getMaxParticlesPerCell() {
return pbox.getNTree().getMaxParticlePerCell();
}
public int getMaxSteps() {
return maxSteps;
}
public void setMaxSteps(int maxSteps) {
this.maxSteps = maxSteps;
}
/**
* The current particle box.
*
* @return The particle box.
*/
public ParticleBox getPbox() {
return pbox;
public Random getRandom() {
return random;
}
public BoidSpecies getOrCreateSpecies(String name) {
......@@ -399,14 +393,14 @@ public class BoidGraph extends AdjacencyListGraph {
while (loop) {
stepBegins(step);
for (BoidSpecies sp : boidSpecies.values())
sp.terminateLoop();
sleep(sleepTime);
step++;
if (maxSteps > 0 && step > maxSteps)
loop = false;
}
......@@ -419,7 +413,7 @@ public class BoidGraph extends AdjacencyListGraph {
@Override
public void stepBegins(double step) {
super.stepBegins(step);
pbox.step();
forcesFactory.step();
}
public boolean isLooping() {
......@@ -527,7 +521,9 @@ public class BoidGraph extends AdjacencyListGraph {
species = getDefaultSpecies();
Boid b = species.createBoid(id);
pbox.addParticle(b.getParticle());
BoidForces f = forcesFactory.createNewForces(b);
b.setForces(f);
return b;
}
......
/*
* Copyright 2006 - 2012
* Antoine Dutot <antoine.dutot@graphstream-project.org>
* Guilhelm Savin <guilhelm.savin@graphstream-project.org>
*
* This file is part of gs-boids <http://graphstream-project.org>.
*
* gs-boids is a library whose purpose is to provide a boid behavior to a set of
* particles.
*
* This program is free software distributed under the terms of two licenses, the
* CeCILL-C license that fits European law, and the GNU Lesser General Public
* License. You can use, modify and/ or redistribute the software under the terms
* of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
* URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
*/
package org.graphstream.boids.forces.greedy;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Random;
import org.graphstream.boids.Boid;
import org.graphstream.boids.BoidForces;
import org.graphstream.boids.BoidGraph;
import org.miv.pherd.geom.Point3;
public class GreedyForces extends BoidForces {
Point3 position;
Point3 nextPosition;
public GreedyForces(Boid b) {
super(b);
BoidGraph ctx = (BoidGraph) b.getGraph();
Random r = ctx.getRandom();
Point3 lo = ctx.getLowAnchor();
Point3 hi = ctx.getHighAnchor();
position = new Point3();
nextPosition = new Point3();
position.x = r.nextDouble() * (hi.x - lo.x) + lo.x;
position.y = r.nextDouble() * (hi.y - lo.y) + lo.y;
position.z = 0;
nextPosition.copy(position);
}
/*
* (non-Javadoc)
*
* @see org.graphstream.boids.BoidForces#getPosition()
*/
public Point3 getPosition() {
return position;
}
/*
* (non-Javadoc)
*
* @see org.graphstream.boids.BoidForces#setPosition(double, double, double)
*/
public void setPosition(double x, double y, double z) {
position.set(x, y, z);
}
/*
* (non-Javadoc)
*
* @see org.graphstream.boids.BoidForces#getNeighborhood()
*/
public Collection<Boid> getNeighborhood() {
BoidGraph g = (BoidGraph) boid.getGraph();
LinkedList<Boid> contacts = new LinkedList<Boid>();
for (Boid b : g.<Boid> getEachNode()) {
if (isVisible(boid, b.getPosition()))
contacts.add(b);
}
return contacts;
}
/*
* (non-Javadoc)
*
* @see org.graphstream.boids.BoidForces#getNextPosition()
*/
public Point3 getNextPosition() {
return nextPosition;
}
}
/*
* Copyright 2006 - 2012
* Antoine Dutot <antoine.dutot@graphstream-project.org>
* Guilhelm Savin <guilhelm.savin@graphstream-project.org>
*
* This file is part of gs-boids <http://graphstream-project.org>.
*
* gs-boids is a library whose purpose is to provide a boid behavior to a set of
* particles.
*