Commit 816beba3 authored by David Cazier's avatar David Cazier

- Stats améliorées.

- Simplification des faces optimisées (en deux passse pour éviter le O(n^2) et les faces oubliées)
- Ajout de paramètres au programme : la taille minimal des cellules, le nombre d'itérarions avant l'arrêt de la simulation
parent 7d618dcf
......@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8)
project(SocialAgents)
#add_definitions(-DSPATIAL_HASHING)
add_definitions(-DSPATIAL_HASHING)
SET(CGoGN_ROOT_DIR ${CMAKE_SOURCE_DIR}/../CGoGN CACHE STRING "CGoGN root dir")
include(${CGoGN_ROOT_DIR}/apps_cmake.txt)
......
......@@ -8,7 +8,7 @@
#include "spatialHashing.h"
#include "Algo/MovingObjects/particle_cell_2D.h"
class Simulator;
class Simulator ;
class Agent
{
......@@ -16,78 +16,69 @@ public:
#ifdef SPATIAL_HASHING
Agent(Simulator* sim, const VEC3& position) ;
#else
Agent(Simulator* sim, const VEC3& position, Dart d);
Agent(Simulator* sim, const VEC3& position, Dart d) ;
#endif
VEC3 getPosition();
VEC3 getPosition() ;
void updateAgentNeighbors();
void updateObstacleNeighbors();
void updateAgentNeighbors() ;
void updateObstacleNeighbors() ;
void update();
void computePrefVelocity();
void computeNewVelocity();
void update() ;
void computeNewVelocity2();
void computePrefVelocity() ;
void computeNewVelocity() ;
bool linearProgram1(
const std::vector<Line>& lines, unsigned int lineNo,
float radius, const VEC3& optVelocity,
bool directionOpt, VEC3& result
);
void computeNewVelocity2() ;
unsigned int linearProgram2(
const std::vector<Line>& lines, float radius,
const VEC3& optVelocity, bool directionOpt,
VEC3& result
);
bool linearProgram1(const std::vector<Line>& lines, unsigned int lineNo, float radius,
const VEC3& optVelocity, bool directionOpt, VEC3& result) ;
void linearProgram3(
const std::vector<Line>& lines, unsigned int numObstLines,
unsigned int beginLine, float radius,
VEC3& result
);
std::vector<std::pair<float, Agent*> > agentNeighbors_;
std::vector<std::pair<float, Obstacle*> > obstacleNeighbors_;
unsigned int linearProgram2(const std::vector<Line>& lines, float radius,
const VEC3& optVelocity, bool directionOpt, VEC3& result) ;
void linearProgram3(const std::vector<Line>& lines, unsigned int numObstLines,
unsigned int beginLine, float radius, VEC3& result) ;
std::vector<std::pair<float, Agent*> > agentNeighbors_ ;
std::vector<std::pair<float, Obstacle*> > obstacleNeighbors_ ;
#ifdef SPATIAL_HASHING
VEC3 pos ;
#else
CGoGN::Algo::MovingObjects::ParticleCell2D<PFP> part_;
CGoGN::Algo::MovingObjects::ParticleCell2D<PFP> part_ ;
#endif
std::vector<VEC3> goals_;
VEC3 finalGoal;
Dart finalDart;
unsigned int curGoal_;
static unsigned int maxNeighbors_;
static float maxSpeed_;
static float neighborDist_;
static float neighborDistSq_;
static float radius_;
static float timeHorizon_;
static float timeHorizonObst_;
static float range_;
static float rangeSq_;
std::vector<VEC3> goals_ ;
VEC3 finalGoal ;
Dart finalDart ;
unsigned int curGoal_ ;
static unsigned int maxNeighbors_ ;
static float maxSpeed_ ;
static float neighborDist_ ;
static float neighborDistSq_ ;
static float radius_ ;
static float timeHorizon_ ;
static float timeHorizonObst_ ;
static float range_ ;
static float rangeSq_ ;
static float timeStep ;
static unsigned int cptAgent ;
unsigned int agentNo ;
VEC3 velocity_;
VEC3 newVelocity_;
VEC3 prefVelocity_;
VEC3 meanSpeed_;
VEC3 velocity_ ;
VEC3 newVelocity_ ;
VEC3 prefVelocity_ ;
VEC3 meanSpeed_ ;
// VEC3 meanPos_;
Simulator* sim_;
};
Simulator* sim_ ;
} ;
#endif
......@@ -10,24 +10,26 @@ namespace CGoGN
namespace CityGenerator
{
template<typename PFP>
template <typename PFP>
bool notDiagonalAdjacentToAnObstacle(typename PFP::MAP& map, Dart d, CellMarker& buildingMark) ;
template<typename PFP> Algo::Modelisation::Polyhedron<PFP> generateGrid(EnvMap& envMap) ;
template <typename PFP> Algo::Modelisation::Polyhedron<PFP> generateGrid(EnvMap& envMap) ;
template<typename PFP> void generateCity(EnvMap& envMap) ;
template <typename PFP> void generateCity(EnvMap& envMap) ;
template<typename PFP>
template <typename PFP>
Algo::Modelisation::Polyhedron<PFP> generateTrianGrid(typename PFP::MAP& map,
typename PFP::TVEC3& position, unsigned int cX, unsigned int cY, float sideLength,
CellMarker& obstacleMark, CellMarker& buildingMark) ;
typename PFP::TVEC3& position,
unsigned int cX, unsigned int cY,
float sideLength, CellMarker& obstacleMark,
CellMarker& buildingMark) ;
template<typename PFP>
template <typename PFP>
Dart extrudeFaceAndMark(typename PFP::MAP& map, typename PFP::TVEC3& position, Dart d,
CellMarker& buildingMark, float height) ;
CellMarker& buildingMark, float height) ;
#ifndef SPATIAL_HASHING
template<typename PFP>
template <typename PFP>
bool animateCity(EnvMap* envMap) ;
#endif
......@@ -37,43 +39,42 @@ bool animateCity(EnvMap* envMap) ;
//template <typename PFP>
//void generateCity(typename PFP::MAP& map, typename PFP::TVEC3& position, CellMarker& obstacleMark, CellMarker& buildingMark, float sideSize, unsigned int nbSquares);
template<typename PFP>
template <typename PFP>
Dart generateBuilding(EnvMap& envMap, Dart d, float height, unsigned int buildingType) ;
template<typename PFP>
void generateMall(typename PFP::MAP& map, typename PFP::TVEC3& position,
CellMarker& obstacleMark, CellMarker& buildingMark, float sideSize) ;
template <typename PFP>
void generateMall(typename PFP::MAP& map, typename PFP::TVEC3& position, CellMarker& obstacleMark,
CellMarker& buildingMark, float sideSize) ;
template<typename PFP>
void generatePathToUpperStair(typename PFP::MAP& map, typename PFP::TVEC3& position,
Dart dLower, Dart dUpper) ;
template <typename PFP>
void generatePathToUpperStair(typename PFP::MAP& map, typename PFP::TVEC3& position, Dart dLower,
Dart dUpper) ;
/*******************************************************************************/
template<typename PFP>
void generatePlanet(typename PFP::MAP& map, typename PFP::TVEC3& position,
CellMarker& obstacleMark, CellMarker& buildingMark, float radius,
unsigned int nbSquares) ;
template <typename PFP>
void generatePlanet(typename PFP::MAP& map, typename PFP::TVEC3& position, CellMarker& obstacleMark,
CellMarker& buildingMark, float radius, unsigned int nbSquares) ;
/*******************************************************************************/
template<typename PFP>
template <typename PFP>
void simplifyFreeSpace(typename PFP::MAP& map, typename PFP::TVEC3& position) ;
template<typename PFP>
template <typename PFP>
bool isAnEar(typename PFP::MAP& map, typename PFP::TVEC3& position, Dart dd, float& area) ;
template<typename PFP>
template <typename PFP>
bool canRemoveEdgeConvex(typename PFP::MAP& map, typename PFP::TVEC3& position, Dart d,
CellMarker& obstacleMark) ;
CellMarker& obstacleMark) ;
template<typename PFP>
template <typename PFP>
void convexifyFreeSpace(typename PFP::MAP& map, typename PFP::TVEC3& position,
CellMarker& obstacleMark, CellMarker& buildingMark) ;
CellMarker& obstacleMark, CellMarker& buildingMark) ;
template<typename PFP>
template <typename PFP>
void installGuardRail(typename PFP::MAP& map, typename PFP::TVEC3& position,
CellMarker& obstacleMark, CellMarker& buildingMark, float height) ;
CellMarker& obstacleMark, CellMarker& buildingMark, float height) ;
}
......
......@@ -9,11 +9,12 @@ namespace CGoGN
namespace CityGenerator
{
template<typename PFP>
template <typename PFP>
bool notAdjacentToAnObstacle(typename PFP::MAP& map, Dart d, CellMarker& buildingMark)
{
Dart dd = d ;
do {
do
{
if (buildingMark.isMarked(dd)) return false ;
dd = map.phi1(dd) ;
} while (dd != d) ;
......@@ -21,11 +22,12 @@ bool notAdjacentToAnObstacle(typename PFP::MAP& map, Dart d, CellMarker& buildin
return true ;
}
template<typename PFP>
template <typename PFP>
bool notDiagonalAdjacentToAnObstacle(typename PFP::MAP& map, Dart d, CellMarker& buildingMark)
{
Dart dd = d ;
do {
do
{
if (buildingMark.isMarked(map.alpha1(map.alpha1(dd)))) return false ;
dd = map.phi1(dd) ;
} while (dd != d) ;
......@@ -33,15 +35,15 @@ bool notDiagonalAdjacentToAnObstacle(typename PFP::MAP& map, Dart d, CellMarker&
return true ;
}
template<typename PFP>
template <typename PFP>
Algo::Modelisation::Polyhedron<PFP> generateGrid(EnvMap& envMap)
{
unsigned int nx = envMap.geometry.size(0) / envMap.maxCellSize ;
unsigned int ny = envMap.geometry.size(1) / envMap.maxCellSize ;
if (nx < 1) nx = 1;
if (ny < 1) ny = 1;
if (nx < 1) nx = 1 ;
if (ny < 1) ny = 1 ;
std::cout << " - Generate Grid : " << nx << " x " << ny << std::endl;
std::cout << " - Generate Grid : " << nx << " x " << ny << std::endl ;
Algo::Modelisation::Polyhedron<PFP> prim(envMap.map, envMap.position) ;
Dart d = prim.grid_topo(nx, ny) ;
......@@ -51,7 +53,8 @@ Algo::Modelisation::Polyhedron<PFP> generateGrid(EnvMap& envMap)
envMap.buildingMark.mark(boundary) ;
Dart e = boundary ;
do {
do
{
envMap.obstacleMark.mark(e) ;
e = envMap.map.phi1(e) ;
} while (e != boundary) ;
......@@ -59,28 +62,32 @@ Algo::Modelisation::Polyhedron<PFP> generateGrid(EnvMap& envMap)
return prim ;
}
template<typename PFP>
template <typename PFP>
void generateCity(EnvMap& envMap)
{
unsigned int nbBuilding = 1000 ;
std::cout << " - Generate City : " << nbBuilding << " buildings" << std::endl;
std::cout << " - Generate City : " << nbBuilding << " buildings" << std::endl ;
generateGrid<PFP>(envMap) ;
Dart dEnd = envMap.map.end() ;
for (Dart d = envMap.map.begin() ; d != dEnd && nbBuilding > 0 ; envMap.map.next(d)) {
if ( !envMap.buildingMark.isMarked(d) && (rand() % 12 == 0)
&& notDiagonalAdjacentToAnObstacle<PFP>(envMap.map, d, envMap.buildingMark)) {
for (Dart d = envMap.map.begin(); d != dEnd && nbBuilding > 0; envMap.map.next(d))
{
if (!envMap.buildingMark.isMarked(d) && (rand() % 12 == 0)
&& notDiagonalAdjacentToAnObstacle<PFP>(envMap.map, d, envMap.buildingMark))
{
generateBuilding<PFP>(envMap, d, (1 + (rand() % 3)) * 2.0f, rand() % 4) ;
--nbBuilding ;
}
}
}
template<typename PFP>
template <typename PFP>
Algo::Modelisation::Polyhedron<PFP> generateTrianGrid(typename PFP::MAP& map,
typename PFP::TVEC3& position, unsigned int cX, unsigned int cY, float sideLength,
CellMarker& obstacleMark, CellMarker& buildingMark)
typename PFP::TVEC3& position,
unsigned int cX, unsigned int cY,
float sideLength, CellMarker& obstacleMark,
CellMarker& buildingMark)
{
Algo::Modelisation::Polyhedron<PFP> prim(map, position) ;
prim.grid_topo(cX, cY) ;
......@@ -90,11 +97,13 @@ Algo::Modelisation::Polyhedron<PFP> generateTrianGrid(typename PFP::MAP& map,
Dart dY = prim.getDart() ; //remind the first quad of the line
Dart dX = prim.getDart() ; //goes through the line
bool odd = true ; //odd line or not
for (unsigned int i = 0 ; i < cX * cY ;) {
for (unsigned int i = 0; i < cX * cY;)
{
Dart dNext = map.phi1(map.phi2(map.phi1(dX))) ;
Dart toCut = dX ;
if (odd) {
if (odd)
{
toCut = map.phi1(toCut) ; //change the side of the split face
position[toCut][0] -= sideLength / 2.0f ; //move vertices for equilateral triangles
}
......@@ -104,37 +113,46 @@ Algo::Modelisation::Polyhedron<PFP> generateTrianGrid(typename PFP::MAP& map,
++i ;
if (i % cX == 0 && i > 0) //goes up and change side of split
{
{
Dart endSquare = map.newOrientedFace(3) ; //add triangle add end of lines to make a square
Dart dN ;
if (odd) {
if (odd)
{
dN = map.phi1(map.phi2(map.phi1(dX))) ;
map.sewFaces(dN, endSquare) ;
position[map.phi_1(endSquare)] = position[map.phi1(endSquare)] ;
position[map.phi_1(endSquare)][0] += sideLength / 2.0f ;
}
else {
else
{
dN = map.phi1(dX) ;
map.sewFaces(dN, endSquare) ;
position[map.phi_1(endSquare)] = position[endSquare] ;
}
if (odd) dY = map.phi2(map.phi_1(map.phi2(map.phi1(dY)))) ;
else dY = map.phi2(map.phi1(map.phi2(map.phi_1(dY)))) ;
if (odd)
dY = map.phi2(map.phi_1(map.phi2(map.phi1(dY)))) ;
else
dY = map.phi2(map.phi1(map.phi2(map.phi_1(dY)))) ;
dX = dY ;
odd = !odd ;
}
else dX = dNext ;
else
dX = dNext ;
}
Dart boundary ;
for (Dart d = map.begin() ; d != map.end() ; map.next(d)) {
if (map.phi2(d) == d) {
for (Dart d = map.begin(); d != map.end(); map.next(d))
{
if (map.phi2(d) == d)
{
Dart dA = map.alpha1(map.phi1(d)) ;
if (map.phi2(dA) == dA && position[dA] == position[map.phi1(d)]
&& position[map.phi1(dA)] == position[d]) map.sewFaces(dA, d) ;
else {
&& position[map.phi1(dA)] == position[d])
map.sewFaces(dA, d) ;
else
{
obstacleMark.mark(d) ;
boundary = d ;
}
......@@ -146,7 +164,8 @@ Algo::Modelisation::Polyhedron<PFP> generateTrianGrid(typename PFP::MAP& map,
if (odd) //last top line if odd
{
for (unsigned int i = 0 ; i < cX ; ++i) {
for (unsigned int i = 0; i < cX; ++i)
{
dX = map.phi1(dX) ;
position[dX][0] -= sideLength / 2.0f ;
}
......@@ -164,14 +183,15 @@ Algo::Modelisation::Polyhedron<PFP> generateTrianGrid(typename PFP::MAP& map,
return prim ;
}
template<typename PFP>
template <typename PFP>
Dart extrudeFaceAndMark(typename PFP::MAP& map, typename PFP::TVEC3& position, Dart d,
CellMarker& buildingMark, float height)
CellMarker& buildingMark, float height)
{
Dart dRoof = Algo::Modelisation::extrudeFace<PFP>(map, position, d, height) ;
buildingMark.mark(dRoof) ;
Dart dd = dRoof ;
do {
do
{
buildingMark.mark(map.phi2(dd)) ;
dd = map.phi1(dd) ;
} while (dd != dRoof) ;
......@@ -179,7 +199,7 @@ Dart extrudeFaceAndMark(typename PFP::MAP& map, typename PFP::TVEC3& position, D
}
#ifndef SPATIAL_HASHING
template<typename PFP>
template <typename PFP>
bool animateCity(EnvMap* envMap)
{
typename PFP::MAP& map = envMap->map ;
......@@ -191,20 +211,23 @@ bool animateCity(EnvMap* envMap)
std::vector<Dart>& newBuildings = envMap->newBuildings ;
unsigned int state = rand() % 10 ;
if (state < 2) {
if (state < 2)
{
map.setCurrentLevel(0) ;
//generate new building
Dart d(rand() % map.getNbDarts()) ;
if ( !map.isDartValid(d)) map.next(d) ;
if (!map.isDartValid(d)) map.next(d) ;
while (d != map.end() && map.getDartLevel(d) > 0)
map.next(d) ;
if (d != map.end()) {
if ( !buildingMark.isMarked(d) && agents[d].size() == 0
&& agentNeighbors[d].size() == 0 && !map.faceIsSubdivided(d)
&& notAdjacentToAnObstacle<PFP>(map, d, obstacleMark)
&& notDiagonalAdjacentToAnObstacle<PFP>(map, d, obstacleMark)) {
if (d != map.end())
{
if (!buildingMark.isMarked(d) && agents[d].size() == 0 && agentNeighbors[d].size() == 0
&& !map.faceIsSubdivided(d)
&& notAdjacentToAnObstacle<PFP>(map, d, obstacleMark)
&& notDiagonalAdjacentToAnObstacle<PFP>(map, d, obstacleMark))
{
map.setCurrentLevel(map.getMaxLevel()) ;
d = generateBuilding<PFP>(envMap, d, 2.0f, 0) ;
newBuildings.push_back(d) ;
......@@ -214,33 +237,37 @@ bool animateCity(EnvMap* envMap)
map.setCurrentLevel(map.getMaxLevel()) ;
}
else if (state < 6 && newBuildings.size() > 0) {
else if (state < 6 && newBuildings.size() > 0)
{
//take a newBuilding and make it higher
state = rand() % newBuildings.size() ;
Dart d = newBuildings[state] ;
//decide if we create a new floor, or just make it higher
unsigned int typeOfUpdate = rand() % 10 ;
if (typeOfUpdate < 9) {
if (typeOfUpdate < 9)
{
Dart dd = d ;
do {
do
{
position[dd][2] += 2.0f ;
dd = map.phi1(dd) ;
} while (dd != d) ;
if (position[dd][2] > ((10 + rand() % 10) * 10.0f))
newBuildings.erase(newBuildings.begin() + state) ;
if (position[dd][2] > ((10 + rand() % 10) * 10.0f)) newBuildings.erase(
newBuildings.begin() + state) ;
}
else {
else
{
typename PFP::VEC3 c = Algo::Geometry::faceCentroid<PFP>(map, d, position) ;
Dart dRoofSmall = Algo::Modelisation::extrudeFace<PFP>(map, position, d, 0.0f) ;
Dart dd = dRoofSmall ;
do {
do
{
position[dd] = position[dd] + (c - position[dd]) / 3.0f ;
dd = map.phi1(dd) ;
} while (dd != dRoofSmall) ;
// Dart dRoof = Algo::Modelisation::extrudeFace<PFP>(map,position,dRoofSmall,2.0f);
Dart dRoof = extrudeFaceAndMark<PFP>(map, position, dRoofSmall, buildingMark,
2.0f) ;
Dart dRoof = extrudeFaceAndMark<PFP>(map, position, dRoofSmall, buildingMark, 2.0f) ;
newBuildings.erase(newBuildings.begin() + state) ;
newBuildings.push_back(dRoof) ;
......@@ -257,7 +284,7 @@ bool animateCity(EnvMap* envMap)
//template <typename PFP>
//void generateCity(typename PFP::MAP& map, typename PFP::TVEC3& position, CellMarker& obstacleMark, CellMarker& buildingMark, float sideSize, unsigned int nbSquares)
template<typename PFP>
template <typename PFP>
Dart generateBuilding(EnvMap& envMap, Dart d, float height, unsigned int buildingType)
{
typename PFP::MAP& map = envMap.map ;
......@@ -268,13 +295,14 @@ Dart generateBuilding(EnvMap& envMap, Dart d, float height, unsigned int buildin
// mark the face as obstacle before extrusion
Dart dd = d ;
buildingMark.mark(dd) ;
do {
do
{
obstacleMark.mark(dd) ;
Dart next = map.phi1(dd) ;
Dart previous = map.phi_1(dd) ;
Obstacle* o = new Obstacle(position[dd], position[next], position[previous],
position[map.phi1(next)]) ;
position[map.phi1(next)]) ;
#ifdef SPATIAL_HASHING
VEC3 ov = o->p2 - o->p1 ;
......@@ -310,85 +338,95 @@ Dart generateBuilding(EnvMap& envMap, Dart d, float height, unsigned int buildin
Dart dRoof ;
dRoof = extrudeFaceAndMark<PFP>(map, position, d, buildingMark, height) ;
switch (buildingType) {
case 0 : {
break ;
}
case 1 : {
dRoof = extrudeFaceAndMark<PFP>(map, position, dRoof, buildingMark, height / 3) ;
Dart dNext = map.phi1(dRoof) ;
Dart dPrev = map.phi2(map.phi_1(dRoof)) ;
map.collapseEdge(dNext) ;
map.collapseEdge(dPrev) ;
break ;
}
case 2 : {
dRoof = extrudeFaceAndMark<PFP>(map, position, dRoof, buildingMark, height / 3) ;
Dart dNext = map.phi1(dRoof) ;
Dart dPrev = map.phi2(map.phi_1(dRoof)) ;
typename PFP::VEC3 mid1 = (position[dNext] + position[map.phi1(dNext)]) / 2.0f ;
typename PFP::VEC3 mid2 = (position[dPrev] + position[map.phi1(dPrev)]) / 2.0f ;
map.collapseEdge(dNext) ;
map.collapseEdge(dPrev) ;
position[dRoof] = mid2 ;
position[map.phi1(dRoof)] = mid1 ;
break ;
switch (buildingType)
{
case 0 :
{
break ;
}
case 1 :
{
dRoof = extrudeFaceAndMark<PFP>(map, position, dRoof, buildingMark, height / 3) ;
Dart dNext = map.phi1(dRoof) ;
Dart dPrev = map.phi2(map.phi_1(dRoof)) ;
map.collapseEdge(dNext) ;
map.collapseEdge(dPrev) ;
break ;
}
case 2 :
{
dRoof = extrudeFaceAndMark<PFP>(map, position, dRoof, buildingMark, height / 3) ;
Dart dNext = map.phi1(dRoof) ;
Dart dPrev = map.phi2(map.phi_1(dRoof)) ;
typename PFP::VEC3 mid1 = (position[dNext] + position[map.phi1(dNext)]) / 2.0f ;
typename PFP::VEC3 mid2 = (position[dPrev]