Commit efd546db authored by gsavin's avatar gsavin

Improve code increasing common code between forces implementation.

parent 132fbda6
......@@ -28,6 +28,8 @@
*/
package org.graphstream.boids;
import java.util.Collection;
import org.miv.pherd.geom.Point3;
import org.miv.pherd.geom.Vector3;
......@@ -77,16 +79,26 @@ public abstract class BoidForces {
*/
public int countRep;
protected Boid boid;
/**
* Direction of the boid.
*/
protected Vector3 dir;
/**
* Forces all set at zero.
*/
public BoidForces() {
public BoidForces(Boid b) {
barycenter = new Point3();
direction = new Vector3();
attraction = new Vector3();
repulsion = new Vector3();
countAtt = 0;
countRep = 0;
boid = b;
dir = new Vector3(((BoidGraph) b.getGraph()).getRandom().nextDouble(),
((BoidGraph) b.getGraph()).getRandom().nextDouble(), 0);
}
/**
......@@ -99,7 +111,67 @@ public abstract class BoidForces {
* @param startCell
* The start cell (usually the root cell of the n-tree).
*/
public abstract void compute();
public void compute() {
Collection<Boid> neigh;
BoidSpecies species = boid.getSpecies();
Vector3 dir = getDirection();
Vector3 rep = new Vector3();
Point3 nextPos = getNextPosition();
barycenter.set(0, 0, 0);
direction.fill(0);
attraction.fill(0);
repulsion.fill(0);
countAtt = 0;
countRep = 0;
neigh = getNeighborhood();
for (Boid b : neigh) {
actionWithNeighboor(b, rep);
}
boid.checkNeighborhood(neigh.toArray(new Boid[neigh.size()]));
if (countAtt > 0) {
barycenter.scale(1f / countAtt, 1f / countAtt, 1f / countAtt);
direction.scalarDiv(countAtt);
attraction
.set(barycenter.x - boid.getPosition().x, barycenter.y
- boid.getPosition().y, barycenter.z
- boid.getPosition().z);
}
if (countRep > 0) {
repulsion.scalarDiv(countRep);
}
direction.scalarMult(species.getDirectionFactor());
attraction.scalarMult(species.getAttractionFactor());
repulsion.scalarMult(species.getRepulsionFactor());
dir.scalarMult(species.getInertia());
dir.add(direction);
dir.add(attraction);
dir.add(repulsion);
if (((BoidGraph) boid.getGraph()).isNormalizeMode()) {
double len = dir.normalize();
if (len <= species.getMinSpeed())
len = species.getMinSpeed();
else if (len >= species.getMaxSpeed())
len = species.getMaxSpeed();
dir.scalarMult(species.getSpeedFactor() * len);
} else {
dir.scalarMult(species.getSpeedFactor());
}
checkWalls();
nextPos.move(dir);
boid.setAttribute("xyz", nextPos.x, nextPos.y, nextPos.z);
}
/**
* Integrate a repulsion vector.
......@@ -132,6 +204,81 @@ public abstract class BoidForces {
barycenter.move(p);
}
/**
* A boid particle p2 that is visible by p1 as been found, integrate it in
* the forces that apply to the boid p1.
*
* @param p1
* The source boid.
* @param b
* the boid visible by p1.
* @param rep
* The repulsion to compute.
*/
protected void actionWithNeighboor(Boid b, Vector3 rep) {
Point3 p1 = boid.getPosition();
Point3 p2 = b.getPosition();
BoidSpecies p1Species = boid.getSpecies();
BoidSpecies p2Species = b.getSpecies();
double v = boid.getSpecies().getViewZone();
rep.set(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z);
double len = rep.length();
if (len != 0) {
if (p1Species != p2Species)
rep.scalarMult(1 / (len * len) * p2Species.getFearFactor());
else
rep.scalarMult(1 / (len * len));
}
double a = Math.log(Math.min(len, v)) / Math.log(v);
rep.scalarMult(a);
repulsion.add(rep);
countRep++;
if (p1Species == p2Species) {
barycenter.move(p2);
direction.add(b.getForces().getDirection());
countAtt++;
}
}
/**
* Check the boid does not go out of the space walls.
*/
protected void checkWalls() {
float aarea = 0.000001f;
Point3 lo = ((BoidGraph) boid.getGraph()).getLowAnchor();
Point3 hi = ((BoidGraph) boid.getGraph()).getHighAnchor();
Vector3 dir = getDirection();
Point3 nextPos = getNextPosition();
if (nextPos.x + dir.data[0] <= lo.x + aarea) {
nextPos.x = lo.x + aarea;
dir.data[0] = -dir.data[0];
} else if (nextPos.x + dir.data[0] >= hi.x - aarea) {
nextPos.x = hi.x - aarea;
dir.data[0] = -dir.data[0];
}
if (nextPos.y + dir.data[1] <= lo.y + aarea) {
nextPos.y = lo.y + aarea;
dir.data[1] = -dir.data[1];
} else if (nextPos.y + dir.data[1] >= hi.y - aarea) {
nextPos.y = hi.y - aarea;
dir.data[1] = -dir.data[1];
}
if (nextPos.z + dir.data[2] <= lo.z + aarea) {
nextPos.z = lo.z + aarea;
dir.data[2] = -dir.data[2];
} else if (nextPos.z + dir.data[2] >= hi.z - aarea) {
nextPos.z = hi.z - aarea;
dir.data[2] = -dir.data[2];
}
}
/**
* True if the given position is visible by the boid.
*
......@@ -169,6 +316,7 @@ public abstract class BoidForces {
// If there is an angle of view.
//
if (species.getAngleOfView() > -1) {
double angle;
Vector3 dir = new Vector3(boid.getForces().getDirection());
Vector3 light = new Vector3(point.x - pos.x, point.y - pos.y,
point.z - pos.z);
......@@ -176,7 +324,7 @@ public abstract class BoidForces {
dir.normalize();
light.normalize();
double angle = dir.dotProduct(light);
angle = dir.dotProduct(light);
//
// In the field of view.
......@@ -194,9 +342,15 @@ public abstract class BoidForces {
return false;
}
public Vector3 getDirection() {
return dir;
}
public abstract void setPosition(double x, double y, double z);
public abstract Point3 getPosition();
public abstract Vector3 getDirection();
public abstract Point3 getNextPosition();
public abstract Collection<Boid> getNeighborhood();
}
\ No newline at end of file
......@@ -28,6 +28,8 @@
*/
package org.graphstream.boids;
import org.miv.pherd.geom.Point3;
/**
* Object used to create and compute forces of boids.
*
......@@ -57,6 +59,5 @@ public interface BoidForcesFactory {
* @param maxy
* @param maxz
*/
void resize(double minx, double miny, double minz, double maxx,
double maxy, double maxz);
void resize(Point3 low, Point3 high);
}
......@@ -43,6 +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.geom.Point3;
import java.util.Random;
......@@ -119,6 +120,9 @@ public class BoidGraph extends AdjacencyListGraph {
protected BoidForcesFactory forcesFactory;
protected Point3 lowAnchor;
protected Point3 highAnchor;
/**
* New context.
*/
......@@ -129,6 +133,8 @@ public class BoidGraph extends AdjacencyListGraph {
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;
......@@ -196,7 +202,19 @@ public class BoidGraph extends AdjacencyListGraph {
public void setArea(double area) {
this.area = area;
forcesFactory.resize(-area, -area, -area, area, area, area);
lowAnchor.set(-area, -area, -area);
highAnchor.set(area, area, area);
forcesFactory.resize(lowAnchor, highAnchor);
}
public Point3 getLowAnchor() {
return lowAnchor;
}
public Point3 getHighAnchor() {
return highAnchor;
}
public long getRandomSeed() {
......@@ -251,7 +269,7 @@ public class BoidGraph extends AdjacencyListGraph {
public Random getRandom() {
return random;
}
public BoidSpecies getOrCreateSpecies(String name) {
return getOrCreateSpecies(name, null);
}
......@@ -499,7 +517,7 @@ public class BoidGraph extends AdjacencyListGraph {
Boid b = species.createBoid(id);
BoidForces f = forcesFactory.createNewForces(b);
b.setForces(f);
return b;
......
......@@ -28,17 +28,42 @@
*/
package org.graphstream.boids.forces.greedy;
import java.util.Collection;
import java.util.LinkedList;
import org.graphstream.boids.Boid;
import org.graphstream.boids.BoidForces;
import org.graphstream.boids.BoidGraph;
import org.miv.pherd.geom.Point3;
import org.miv.pherd.geom.Vector3;
public class GreedyForces extends BoidForces {
Point3 position;
Vector3 direction;
public GreedyForces(Boid b) {
super(b);
}
/*
* (non-Javadoc)
*
* @see org.graphstream.boids.BoidForces#compute()
*/
public void compute() {
// TODO Auto-generated method stub
BoidGraph g = (BoidGraph) boid.getGraph();
LinkedList<Boid> contacts = new LinkedList<Boid>();
Vector3 rep = new Vector3();
for (Boid b : g.<Boid> getEachNode()) {
if (isVisible(boid, b.getPosition())) {
actionWithNeighboor(b, rep);
contacts.add(b);
}
}
boid.checkNeighborhood(contacts.toArray(new Boid[contacts.size()]));
}
/*
......@@ -59,7 +84,32 @@ public class GreedyForces extends BoidForces {
position.set(x, y, z);
}
/*
* (non-Javadoc)
*
* @see org.graphstream.boids.BoidForces#getDirection()
*/
public Vector3 getDirection() {
return direction;
}
/*
* (non-Javadoc)
*
* @see org.graphstream.boids.BoidForces#getNeighborhood()
*/
public Collection<Boid> getNeighborhood() {
// TODO Auto-generated method stub
return null;
}
/*
* (non-Javadoc)
*
* @see org.graphstream.boids.BoidForces#getNextPosition()
*/
public Point3 getNextPosition() {
// TODO Auto-generated method stub
return null;
}
}
......@@ -31,21 +31,40 @@ package org.graphstream.boids.forces.greedy;
import org.graphstream.boids.Boid;
import org.graphstream.boids.BoidForces;
import org.graphstream.boids.BoidForcesFactory;
import org.miv.pherd.geom.Point3;
public class GreedyForcesFactory implements BoidForcesFactory {
/*
* (non-Javadoc)
*
* @see
* org.graphstream.boids.BoidForcesFactory#createNewForces(org.graphstream
* .boids.Boid)
*/
public BoidForces createNewForces(Boid b) {
// TODO Auto-generated method stub
return null;
}
public void resize(double minx, double miny, double minz, double maxx,
double maxy, double maxz) {
/*
* (non-Javadoc)
*
* @see org.graphstream.boids.BoidForcesFactory#step()
*/
public void step() {
// TODO Auto-generated method stub
}
public void step() {
/*
* (non-Javadoc)
*
* @see
* org.graphstream.boids.BoidForcesFactory#resize(org.miv.pherd.geom.Point3,
* org.miv.pherd.geom.Point3)
*/
public void resize(Point3 low, Point3 high) {
// TODO Auto-generated method stub
}
......
......@@ -30,7 +30,6 @@ package org.graphstream.boids.forces.ntree;
import java.util.Iterator;
import org.graphstream.boids.forces.ntree.NTreeForcesFactory.BoidParticle;
import org.miv.pherd.Particle;
import org.miv.pherd.geom.Vector3;
import org.miv.pherd.ntree.BarycenterCellData;
......@@ -98,7 +97,7 @@ public class BoidCellData extends BarycenterCellData {
y += particle.getPosition().y;
z += particle.getPosition().z;
dir.add(particle.dir);
dir.add(particle.b.getForces().getDirection());
n++;
}
......
/*
* 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.ntree;
import org.graphstream.boids.Boid;
import org.graphstream.boids.BoidGraph;
import org.miv.pherd.Particle;
import org.miv.pherd.geom.Point3;
/**
* Internal representation of the boid position, and direction in the forces
* system.
*
* @author Guilhelm Savin
* @author Antoine Dutot
*/
public class BoidParticle extends Particle {
protected Boid b;
/**
* New particle.
*
* @param ctx
* The set of global parameters.
*/
public BoidParticle(BoidGraph ctx, Boid b) {
super(b.getId(), ctx.getRandom().nextDouble() * (ctx.getArea() * 2)
- ctx.getArea(), ctx.getRandom().nextDouble()
* (ctx.getArea() * 2) - ctx.getArea(), 0);
this.b = b;
}
/*
* (non-Javadoc)
*
* @see org.miv.pherd.Particle#move(int)
*/
@Override
public void move(int time) {
b.getForces().compute();
moved = true;
}
/*
* (non-Javadoc)
*
* @see org.miv.pherd.Particle#inserted()
*/
@Override
public void inserted() {
}
/*
* (non-Javadoc)
*
* @see org.miv.pherd.Particle#removed()
*/
@Override
public void removed() {
}
public Boid getBoid() {
return b;
}
public void setPosition(double x, double y, double z) {
initPos(x, y, z);
}
public Point3 getNextPosition() {
return nextPos;
}
}
\ No newline at end of file
......@@ -28,17 +28,15 @@
*/
package org.graphstream.boids.forces.ntree;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.graphstream.boids.Boid;
import org.graphstream.boids.BoidForces;
import org.graphstream.boids.BoidSpecies;
import org.graphstream.boids.forces.ntree.NTreeForcesFactory.BoidParticle;
import org.miv.pherd.Particle;
import org.miv.pherd.geom.Point3;
import org.miv.pherd.geom.Vector3;
import org.miv.pherd.ntree.Cell;
/**
......@@ -58,6 +56,7 @@ public class NTreeForces extends BoidForces {
BoidParticle p;
public NTreeForces(BoidParticle p) {
super(p.b);
this.p = p;
}
......@@ -78,41 +77,14 @@ public class NTreeForces extends BoidForces {
public void setPosition(double x, double y, double z) {
p.setPosition(x, y, z);
}
public Vector3 getDirection() {
return p.dir;
}
/*
* (non-Javadoc)
*
* @see org.graphstream.boids.BoidForces#compute()
* @see org.graphstream.boids.BoidForces#getNextPosition()
*/
public void compute() {
Cell startCell = p.getCell().getTree().getRootCell();
barycenter.set(0, 0, 0);
direction.fill(0);
attraction.fill(0);
repulsion.fill(0);
countAtt = 0;
countRep = 0;
Set<Boid> contacts = new HashSet<Boid>();
exploreTree(startCell, contacts);
p.b.checkNeighborhood(contacts.toArray(new Boid[contacts.size()]));
if (countAtt > 0) {
barycenter.scale(1f / countAtt, 1f / countAtt, 1f / countAtt);
direction.scalarDiv(countAtt);
attraction.set(barycenter.x - p.b.getPosition().x, barycenter.y
- p.b.getPosition().y, barycenter.z - p.b.getPosition().z);
}
if (countRep > 0) {
repulsion.scalarDiv(countRep);
}
public Point3 getNextPosition() {
return p.getNextPosition();
}
/**
......@@ -125,7 +97,7 @@ public class NTreeForces extends BoidForces {
* The cell to explore recursively.
*/
protected void exploreTree(Cell cell, Set<Boid> contacts) {
if (intersection(p.b, cell)) {
if (intersection(boid, cell)) {
if (cell.isLeaf())
forcesFromCell(cell, contacts);
else {
......@@ -148,21 +120,15 @@ public class NTreeForces extends BoidForces {
*/
protected void forcesFromCell(Cell cell, Set<Boid> contacts) {
Iterator<? extends Particle> particles = cell.getParticles();
Vector3 rep = new Vector3();
while (particles.hasNext()) {
Particle particle = particles.next();
if (particle instanceof BoidParticle) {
if (p != particle && isVisible(p.b, particle.getPosition())) {
if (p != particle && isVisible(boid, particle.getPosition()))
contacts.add(((BoidParticle) particle).b);
actionWithNeighboor((BoidParticle) particle, rep);