Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
9.2.2023: Due to updates GitLab will be unavailable for some minutes between 9:00 and 11:00.
Open sidebar
vadere
vadere
Commits
3a6093c1
Commit
3a6093c1
authored
Oct 18, 2018
by
Stefan Schuhbaeck
Browse files
refactor groupSpawn to use a polygon as source shape
parent
75c7c2b3
Changes
8
Hide whitespace changes
Inline
Side-by-side
VadereGui/src/org/vadere/gui/renderer/agent/AgentRender.java
View file @
3a6093c1
...
...
@@ -59,6 +59,8 @@ public class AgentRender implements Renderer {
}
private
void
renderGroup
(
Pedestrian
ped
,
Graphics2D
g
)
{
g
.
setColor
(
Color
.
DARK_GRAY
);
g
.
fill
(
ped
.
getShape
());
g
.
setColor
(
getGroupColor
(
ped
));
DefaultRenderer
.
fill
(
getShape
(
ped
),
g
);
}
...
...
VadereSimulator/src/org/vadere/simulator/control/GroupSourceController.java
View file @
3a6093c1
...
...
@@ -5,7 +5,8 @@ import org.vadere.simulator.models.groups.GroupModel;
import
org.vadere.state.attributes.scenario.AttributesDynamicElement
;
import
org.vadere.state.scenario.Source
;
import
org.vadere.state.scenario.Topography
;
import
org.vadere.state.util.SpawnArray
;
import
org.vadere.state.util.GroupSpawnArray
;
import
org.vadere.util.geometry.PointPositioned
;
import
org.vadere.util.geometry.shapes.VPoint
;
import
org.vadere.util.geometry.shapes.VRectangle
;
...
...
@@ -13,12 +14,13 @@ import java.util.Iterator;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Random
;
import
java.util.stream.Collectors
;
public
class
GroupSourceController
extends
SourceController
{
private
final
GroupModel
groupModel
;
private
LinkedList
<
Integer
>
groupsToSpawn
;
protected
final
SpawnArray
spawnArray
;
protected
final
Group
SpawnArray
spawnArray
;
public
GroupSourceController
(
Topography
scenario
,
Source
source
,
DynamicElementFactory
dynamicElementFactory
,
...
...
@@ -30,8 +32,9 @@ public class GroupSourceController extends SourceController {
VRectangle
elementBound
=
new
VRectangle
(
dynamicElementFactory
.
getDynamicElementRequiredPlace
(
new
VPoint
(
0
,
0
)).
getBounds2D
());
this
.
spawnArray
=
new
SpawnArray
(
new
VRectangle
(
source
.
getShape
().
getBounds2D
()),
new
VRectangle
(
0
,
0
,
elementBound
.
getWidth
()
,
elementBound
.
getHeight
()
));
this
.
spawnArray
=
new
GroupSpawnArray
(
source
.
getShape
(),
new
VRectangle
(
0
,
0
,
elementBound
.
getWidth
()
,
elementBound
.
getHeight
()),
dynamicElementFactory:
:
getDynamicElementRequiredPlace
);
}
...
...
@@ -47,7 +50,14 @@ public class GroupSourceController extends SourceController {
Iterator
<
Integer
>
iter
=
groupsToSpawn
.
iterator
();
while
(
iter
.
hasNext
())
{
int
groupSize
=
iter
.
next
();
List
<
VPoint
>
newGroup
=
spawnArray
.
getNextFreeGroup
(
groupSize
,
random
,
getDynElementsAtSource
());
List
<
VPoint
>
newGroup
=
spawnArray
.
getNextFreeGroup
(
groupSize
,
random
,
getDynElementsAtSource
().
stream
()
.
map
(
PointPositioned:
:
getPosition
)
.
map
(
dynamicElementFactory:
:
getDynamicElementRequiredPlace
)
.
collect
(
Collectors
.
toList
())
);
if
(
newGroup
.
size
()
>
0
)
{
// add immediately to Scenario to update DynElementsAtSource
addElementToScenario
(
newGroup
);
...
...
@@ -60,7 +70,14 @@ public class GroupSourceController extends SourceController {
Iterator
<
Integer
>
iter
=
groupsToSpawn
.
iterator
();
while
(
iter
.
hasNext
())
{
int
groupSize
=
iter
.
next
();
List
<
VPoint
>
newGroup
=
spawnArray
.
getNextGroup
(
groupSize
,
random
,
getDynElementsAtSource
());
List
<
VPoint
>
newGroup
=
spawnArray
.
getNextGroup
(
groupSize
,
random
,
getDynElementsAtSource
().
stream
()
.
map
(
PointPositioned:
:
getPosition
)
.
map
(
dynamicElementFactory:
:
getDynamicElementRequiredPlace
)
.
collect
(
Collectors
.
toList
())
);
if
(
newGroup
.
isEmpty
())
throw
new
RuntimeException
(
"Cannot spawn new Group. Source "
+
source
.
getId
()
+
" is set "
+
"to useFreeSpaceOnly == false but no space is left to spawn group without exactly"
+
...
...
@@ -77,7 +94,13 @@ public class GroupSourceController extends SourceController {
Iterator
<
Integer
>
iter
=
groupsToSpawn
.
iterator
();
while
(
iter
.
hasNext
())
{
int
groupSize
=
iter
.
next
();
List
<
VPoint
>
newGroup
=
spawnArray
.
getNextFreeGroup
(
groupSize
,
getDynElementsAtSource
());
List
<
VPoint
>
newGroup
=
spawnArray
.
getNextFreeGroup
(
groupSize
,
getDynElementsAtSource
().
stream
()
.
map
(
PointPositioned:
:
getPosition
)
.
map
(
dynamicElementFactory:
:
getDynamicElementRequiredPlace
)
.
collect
(
Collectors
.
toList
())
);
if
(
newGroup
!=
null
&&
!
newGroup
.
isEmpty
())
{
// add immediately to Scenario to update DynElementsAtSource
addElementToScenario
(
newGroup
);
...
...
@@ -90,7 +113,13 @@ public class GroupSourceController extends SourceController {
Iterator
<
Integer
>
iter
=
groupsToSpawn
.
iterator
();
while
(
iter
.
hasNext
())
{
int
groupSize
=
iter
.
next
();
List
<
VPoint
>
newGroup
=
spawnArray
.
getNextGroup
(
groupSize
,
getDynElementsAtSource
());
List
<
VPoint
>
newGroup
=
spawnArray
.
getNextGroup
(
groupSize
,
getDynElementsAtSource
().
stream
()
.
map
(
PointPositioned:
:
getPosition
)
.
map
(
dynamicElementFactory:
:
getDynamicElementRequiredPlace
)
.
collect
(
Collectors
.
toList
())
);
if
(
newGroup
==
null
||
newGroup
.
isEmpty
())
throw
new
RuntimeException
(
"Cannot spawn new Group. Source "
+
source
.
getId
()
+
" is set "
+
"to useFreeSpaceOnly == false but no space is left to spawn group without exactly"
+
...
...
VadereSimulator/src/org/vadere/simulator/control/SingleSourceController.java
View file @
3a6093c1
package
org.vadere.simulator.control
;
import
org.jetbrains.annotations.NotNull
;
import
org.lwjgl.system.CallbackI
;
import
org.vadere.simulator.models.DynamicElementFactory
;
import
org.vadere.state.attributes.scenario.AttributesDynamicElement
;
import
org.vadere.state.scenario.Obstacle
;
import
org.vadere.state.scenario.Source
;
import
org.vadere.state.scenario.Topography
;
import
org.vadere.state.util.SingleSourceSpawnArray
;
import
org.vadere.state.util.SpawnArray
;
import
org.vadere.util.geometry.PointPositioned
;
import
org.vadere.util.geometry.shapes.VPoint
;
import
org.vadere.util.geometry.shapes.VRectangle
;
import
org.vadere.util.geometry.shapes.VShape
;
import
java.awt.*
;
import
java.awt.geom.Rectangle2D
;
import
java.util.ArrayList
;
import
java.util.LinkedList
;
...
...
@@ -22,7 +19,6 @@ import java.util.List;
import
java.util.Optional
;
import
java.util.Random
;
import
java.util.stream.Collectors
;
import
java.util.stream.IntStream
;
public
class
SingleSourceController
extends
SourceController
{
...
...
@@ -37,7 +33,6 @@ public class SingleSourceController extends SourceController {
AttributesDynamicElement
attributesDynamicElement
,
Random
random
)
{
super
(
scenario
,
source
,
dynamicElementFactory
,
attributesDynamicElement
,
random
);
this
.
dynamicElementFactory
=
dynamicElementFactory
;
VRectangle
elementBound
=
new
VRectangle
(
dynamicElementFactory
.
getDynamicElementRequiredPlace
(
new
VPoint
(
0
,
0
)).
getBounds2D
());
this
.
spawnArray
=
new
SingleSourceSpawnArray
(
source
.
getShape
(),
new
VRectangle
(
0
,
0
,
elementBound
.
getWidth
(),
elementBound
.
getHeight
()),
...
...
@@ -106,7 +101,7 @@ public class SingleSourceController extends SourceController {
List
<
VPoint
>
positions
=
new
ArrayList
<>(
numberToSpawn
);
for
(
int
i
=
0
;
i
<
numberToSpawn
;
i
++)
{
Optional
<
VPoint
>
optPosition
=
getNextPosition
(
blockPedestrianShapes
,
spawnArray
.
getSpawnPoints
());
Optional
<
VPoint
>
optPosition
=
getNextPosition
(
blockPedestrianShapes
,
spawnArray
.
get
Allowed
SpawnPoints
());
if
(
optPosition
.
isPresent
())
{
VPoint
position
=
optPosition
.
get
();
...
...
VadereSimulator/src/org/vadere/simulator/control/SourceController.java
View file @
3a6093c1
...
...
@@ -2,7 +2,6 @@ package org.vadere.simulator.control;
import
org.apache.commons.math3.distribution.RealDistribution
;
import
org.vadere.simulator.models.DynamicElementFactory
;
import
org.vadere.state.attributes.scenario.AttributesAgent
;
import
org.vadere.state.attributes.scenario.AttributesDynamicElement
;
import
org.vadere.state.attributes.scenario.AttributesSource
;
import
org.vadere.state.scenario.Agent
;
...
...
@@ -12,11 +11,8 @@ import org.vadere.state.scenario.DynamicElement;
import
org.vadere.state.scenario.Pedestrian
;
import
org.vadere.state.scenario.Source
;
import
org.vadere.state.scenario.Topography
;
import
org.vadere.state.util.SpawnArray
;
import
org.vadere.util.geometry.LinkedCellsGrid
;
import
org.vadere.util.geometry.shapes.VCircle
;
import
org.vadere.util.geometry.shapes.VPoint
;
import
org.vadere.util.geometry.shapes.VRectangle
;
import
java.awt.geom.Rectangle2D
;
import
java.util.LinkedList
;
...
...
@@ -29,7 +25,7 @@ public abstract class SourceController {
// public static final double SPAWN_BUFFER_SIZE = 0.03;
protected
final
Source
source
;
pr
ivate
final
DynamicElementFactory
dynamicElementFactory
;
pr
otected
final
DynamicElementFactory
dynamicElementFactory
;
private
final
Topography
topography
;
protected
final
Random
random
;
...
...
VadereState/src/org/vadere/state/util/AbstractSpawnArray.java
0 → 100644
View file @
3a6093c1
package
org.vadere.state.util
;
import
org.apache.log4j.LogManager
;
import
org.apache.log4j.Logger
;
import
org.vadere.util.geometry.shapes.VPoint
;
import
org.vadere.util.geometry.shapes.VRectangle
;
import
org.vadere.util.geometry.shapes.VShape
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.function.Function
;
public
abstract
class
AbstractSpawnArray
{
private
static
Logger
logger
=
LogManager
.
getLogger
(
AbstractSpawnArray
.
class
);
protected
final
VRectangle
spawnElementBound
;
protected
final
VRectangle
bound
;
// number of spawn elements in x and y Dimension.
protected
int
xDim
;
protected
int
yDim
;
protected
final
ArrayList
<
VPoint
>
allowedSpawnPoints
;
protected
VPoint
firstSpawnPoint
;
protected
double
eX
,
eY
;
// map valid boundGrid coordinates to #allowedSpawnPoints ArrayList index.
protected
HashMap
<
Integer
,
Integer
>
validSpawnPointMapInBoundShape
;
protected
Function
<
VPoint
,
VShape
>
shapeProducer
;
public
AbstractSpawnArray
(
final
VShape
boundShape
,
final
VRectangle
spawnElementBound
,
Function
<
VPoint
,
VShape
>
shapeProducer
)
{
this
.
spawnElementBound
=
spawnElementBound
;
this
.
bound
=
new
VRectangle
(
boundShape
.
getBounds2D
());
this
.
shapeProducer
=
shapeProducer
;
xDim
=
(
int
)
(
bound
.
width
/
spawnElementBound
.
width
);
yDim
=
(
int
)
(
bound
.
height
/
spawnElementBound
.
height
);
if
(
xDim
*
yDim
<=
0
)
{
xDim
=
(
xDim
==
0
)
?
1
:
xDim
;
yDim
=
(
yDim
==
0
)
?
1
:
yDim
;
allowedSpawnPoints
=
new
ArrayList
<>(
xDim
*
yDim
);
//offset left upper corner to center point.
eX
=
(
xDim
==
1
)
?
bound
.
getCenterX
()
:
spawnElementBound
.
x
+
spawnElementBound
.
width
/
2
;
eY
=
(
yDim
==
1
)
?
bound
.
getCenterY
()
:
spawnElementBound
.
y
+
spawnElementBound
.
height
/
2
;
logger
.
info
(
String
.
format
(
"Dimension of Source is to small for at least one dimension to contain designated spawnElement with Bound (%.2f x %.2f) Set to (%d x %d)"
,
spawnElementBound
.
width
,
spawnElementBound
.
height
,
xDim
,
yDim
));
}
else
{
allowedSpawnPoints
=
new
ArrayList
<>(
xDim
*
yDim
);
//offset left upper corner to center point.
eX
=
spawnElementBound
.
x
+
spawnElementBound
.
width
/
2
;
eY
=
spawnElementBound
.
y
+
spawnElementBound
.
height
/
2
;
}
firstSpawnPoint
=
new
VPoint
(
bound
.
x
+
eX
,
bound
.
y
+
eY
);
validSpawnPointMapInBoundShape
=
new
HashMap
<>();
int
validIndex
=
0
;
for
(
int
i
=
0
;
i
<
(
xDim
*
yDim
);
i
++)
{
VPoint
candidatePoint
=
firstSpawnPoint
.
add
(
new
VPoint
(
2
*
eX
*
(
i
%
xDim
),
2
*
eY
*
(
i
/
xDim
)));
VShape
candidateShape
=
shapeProducer
.
apply
(
candidatePoint
);
if
(
boundShape
.
containsShape
(
candidateShape
))
{
validSpawnPointMapInBoundShape
.
put
(
i
,
validIndex
);
allowedSpawnPoints
.
add
(
candidatePoint
);
validIndex
++;
}
}
allowedSpawnPoints
.
trimToSize
();
}
public
List
<
VPoint
>
getAllowedSpawnPoints
(){
return
allowedSpawnPoints
;
}
}
VadereState/src/org/vadere/state/util/GroupPlacementHelper.java
View file @
3a6093c1
package
org.vadere.state.util
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
/**
* Simplifies placement of a group within a
{@link SpawnArray}.
There are two placement strategies
* Simplifies placement of a group within a There are two placement strategies
* supported.
* <li>NoneOverlapping:</li>
* With this strategy a group spawns do not overlap. E.g The first 2x2 Group will start at (0,0) and
...
...
@@ -13,8 +17,8 @@ package org.vadere.state.util;
*/
public
class
GroupPlacementHelper
{
private
final
int
xB
ound
;
private
final
int
yB
ound
;
private
final
int
b
ound
edShapeGridCellsX
;
private
final
int
b
ound
edShapeGridCellsY
;
private
final
int
groupSize
;
private
final
int
groupDimX
;
...
...
@@ -23,97 +27,96 @@ public class GroupPlacementHelper {
private
final
int
noneOverlapXGroupCount
;
private
final
int
noneOverlapYGroupCount
;
private
final
int
overlapXGroup
Count
;
private
final
int
overlapYGroup
Count
;
private
final
int
groupPlacement
Count
X
;
private
final
int
groupPlacement
Count
Y
;
private
ArrayList
<
Integer
>
validSpawnPointsForGroupInBound
;
public
GroupPlacementHelper
(
int
xBound
,
int
yBound
,
int
groupSize
)
{
if
(
groupSize
>
xBound
*
yBound
)
public
GroupPlacementHelper
(
int
boundedShapeGridCellsX
,
int
boundedShapeGridCellsY
,
int
groupSize
,
HashMap
<
Integer
,
Integer
>
validSpawnPointMapInBoundShape
)
{
if
(
groupSize
>
boundedShapeGridCellsX
*
boundedShapeGridCellsY
)
throw
new
IndexOutOfBoundsException
(
"GroupSize: "
+
groupSize
+
"to big for given Bound "
+
xB
ound
+
" x "
+
yB
ound
);
+
"to big for given Bound "
+
b
ound
edShapeGridCellsX
+
" x "
+
b
ound
edShapeGridCellsY
);
this
.
xB
ound
=
xB
ound
;
this
.
yB
ound
=
yB
ound
;
this
.
b
ound
edShapeGridCellsX
=
b
ound
edShapeGridCellsX
;
this
.
b
ound
edShapeGridCellsY
=
b
ound
edShapeGridCellsY
;
this
.
groupSize
=
groupSize
;
int
dimGx
,
dimGy
;
// dimension of smallest square contain a group of size groupSize
dimGx
=
(
int
)
Math
.
ceil
(
Math
.
sqrt
(
groupSize
));
dimGx
=
(
dimGx
>
xB
ound
)
?
xB
ound
:
dimGx
;
dimGx
=
(
dimGx
>
b
ound
edShapeGridCellsX
)
?
b
ound
edShapeGridCellsX
:
dimGx
;
// dimGy set to minimize lost space in resulting rectangle (or square if groupSize is a square number)
dimGy
=
dimGx
*
(
dimGx
-
1
)
<
groupSize
?
dimGx
:
dimGx
-
1
;
this
.
groupDimX
=
dimGx
;
this
.
groupDimY
=
dimGy
;
this
.
noneOverlapXGroupCount
=
xB
ound
/
dimGx
;
this
.
noneOverlapYGroupCount
=
yB
ound
/
dimGy
;
this
.
noneOverlapXGroupCount
=
b
ound
edShapeGridCellsX
/
dimGx
;
this
.
noneOverlapYGroupCount
=
b
ound
edShapeGridCellsY
/
dimGy
;
this
.
overlapXGroupCount
=
xBound
-
(
dimGx
-
1
);
this
.
overlapYGroup
Count
=
yB
ound
-
(
dimG
y
-
1
);
}
//
this
.
groupPlacement
Count
X
=
b
ound
edShapeGridCellsX
-
(
dimG
x
-
1
);
this
.
groupPlacementCountY
=
boundedShapeGridCellsY
-
(
dimGy
-
1
);
/**
* @param groupNumber zero-Based number of group of groupSize with the noneOverlapping strategy
* @return zero-Based index within {@link SpawnArray} corresponding to start index of
* groupNumber.
*/
public
int
getNoneOverlappingStart
(
int
groupNumber
)
{
return
(
groupNumber
%
noneOverlapXGroupCount
)
*
groupDimX
+
// offset in x
(
groupNumber
/
noneOverlapXGroupCount
)
*
xBound
*
groupDimY
;
// offset in y
validSpawnPointsForGroupInBound
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
getOverlappingGroupCount
();
i
++){
// i group spawn location
if
(
isGridCellWithinSource
(
validSpawnPointMapInBoundShape
,
i
)){
validSpawnPointsForGroupInBound
.
add
(
i
);
}
}
}
/**
* NoneOverlapping strategy
*
* @param groupNumber zero-Based number of group
* @param i zero-Based index within group. Must be smaller than groupSize
* @return zero-Based index within {@link SpawnArray} corresponding to groupNumber and index
* i
* @param validSpawnPointMapInBoundShape mapping of rectangular bound grid to valid coordinates
* within the source shape
* @param groupIndex groupIndex specifying the first ped within one group.
* @return true if all positions within the group are contained
* within the source shape.
*/
public
int
getNoneOverlappingIndex
(
int
groupNumber
,
int
i
)
{
assert
i
<
groupSize
;
int
start
=
getNoneOverlappingStart
(
groupNumber
);
return
start
+
(
i
%
groupDimX
)
+
(
i
/
groupDimX
)
*
xBound
;
boolean
isGridCellWithinSource
(
HashMap
<
Integer
,
Integer
>
validSpawnPointMapInBoundShape
,
int
groupIndex
){
for
(
int
pedIndexInGroup
=
0
;
pedIndexInGroup
<
groupSize
;
pedIndexInGroup
++){
boolean
isValid
=
validSpawnPointMapInBoundShape
.
containsKey
(
getOverlappingIndex
(
groupIndex
,
pedIndexInGroup
));
if
(!
isValid
){
return
false
;
}
}
return
true
;
}
public
int
nextNoneOverlappingGroupNumber
(
int
oldGroupNumber
)
{
return
(
oldGroupNumber
+
1
)
%
(
noneOverlapXGroupCount
*
noneOverlapYGroupCount
);
}
/**
* @return Number of groups based on noneOverlapping strategy
*/
public
int
getNoneOverlappingGroupCount
()
{
return
noneOverlapXGroupCount
*
noneOverlapYGroupCount
;
}
/**
* @param groupNumber zero-Based number of group of groupSize with the overlapping strategy
* @return zero-Based index within {@link SpawnArray} corresponding to groupNumber and index i
* @return zero-Based index within {@link
Group
SpawnArray} corresponding to groupNumber and index i
*/
public
int
getOverlappingStart
(
int
groupNumber
)
{
return
(
groupNumber
%
overlapXGroup
Count
)
+
// offset in x
(
groupNumber
/
overlapXGroup
Count
)
*
xB
ound
;
// offset in y (groupDimY not needed)
return
(
groupNumber
%
groupPlacement
Count
X
)
+
// offset in x
(
groupNumber
/
groupPlacement
Count
X
)
*
b
ound
edShapeGridCellsX
;
// offset in y (groupDimY not needed)
}
/**
* Overlapping strategy
*
* @param groupNumber zero-Based number of group
* @param groupNumber
InBound
zero-Based number of group
* @param i zero-Based index within group. Must be smaller than groupSize
* @return zero-Based index within {@link SpawnArray} corresponding to groupNumber and index
* @return zero-Based index within {@link
Group
SpawnArray} corresponding to groupNumber and index
* i
*/
public
int
getOverlappingIndex
(
int
groupNumber
,
int
i
)
{
public
int
getOverlappingIndex
(
int
groupNumber
InBound
,
int
i
)
{
assert
i
<
groupSize
;
int
start
=
getOverlappingStart
(
groupNumber
);
return
start
+
(
i
%
groupDimX
)
+
(
i
/
groupDimX
)
*
xB
ound
;
int
start
=
getOverlappingStart
(
groupNumber
InBound
);
return
start
+
(
i
%
groupDimX
)
+
(
i
/
groupDimX
)
*
b
ound
edShapeGridCellsX
;
}
public
int
getOverlappingGroupCount
()
{
return
overlapXGroupCount
*
overlapYGroupCount
;
return
groupPlacementCountX
*
groupPlacementCountY
;
}
public
ArrayList
<
Integer
>
getValidSpawnPointsForGroupInBound
(){
return
validSpawnPointsForGroupInBound
;
}
public
int
getGroupSize
()
{
...
...
VadereState/src/org/vadere/state/util/SpawnArray.java
→
VadereState/src/org/vadere/state/util/
Group
SpawnArray.java
View file @
3a6093c1
package
org.vadere.state.util
;
import
org.apache.log4j.LogManager
;
import
org.apache.log4j.Logger
;
import
com.oracle.jrockit.jfr.Producer
;
import
org.jetbrains.annotations.NotNull
;
import
org.vadere.state.scenario.DynamicElement
;
import
org.vadere.util.geometry.shapes.VPoint
;
import
org.vadere.util.geometry.shapes.VRectangle
;
import
org.vadere.util.geometry.shapes.VShape
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
...
...
@@ -15,36 +16,12 @@ import java.util.List;
import
java.util.ListIterator
;
import
java.util.Random
;
import
java.util.function.BiFunction
;
import
java.util.function.Consumer
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
import
java.util.stream.IntStream
;
/**
* <h1>Single Pedestrians</h1>
*
* The single spawn algorithm divides the source in a grid based on the width of the pedestrians.
* This grid is used to place newly spawn pedestrians. These points are called spawnPoints and
* are saved as an 1D-array. Based on the Source Attribute values one of the four functions will
* be used to select the next spawnPoints.
*
* <h2>{@link #getNextSpawnPoints(int, List)}</h2>
* use the next free spawn point in order (0..n) to place the next pedestrian. This function will
* try to place up to maxPoints pedestrian an will wrap around to spawnPoint 0 if needed. Also this
* function will allow overlapping pedestrians a complete overlap is not allowed due to numerical
* problems in OE-solvers.
*
* <h2>{@link #getNextRandomSpawnPoints(int, Random, List)}</h2>
* same as above but the spawn points will be shuffled prior to iteration.
*
* <h2>{@link #getNextFreeSpawnPoints(int, List)}</h2>
* same as above but it will be ensured that the new pedestrian does not overlap with any part of
* an existing pedestrian.
*
* <h2>{@link #getNextFreeRandomSpawnPoints(int, Random, List)}</h2>
* sam es above but the spawn points will be shuffled prior to iteration and overlapping will be
* tested.
*
*
* <h1>Groups</h1>
*
* Groups are spawn as a rectangle (axb) with the smallest possible deviation of a and b. The
...
...
@@ -77,255 +54,100 @@ import java.util.stream.IntStream;
* same as above but it will use a Randomize groupNumber Iterator.
*
*/
public
class
SpawnArray
{
public
class
GroupSpawnArray
extends
Abstract
SpawnArray
{
private
static
Logger
logger
=
LogManager
.
getLogger
(
SpawnArray
.
class
);
public
static
final
double
OVERLAPP_EPSILON
=
0.4
;
private
final
VPoint
[]
spawnPoints
;
private
final
VRectangle
spawnElementBound
;
// number of spawn elements in x and y Dimension.
private
int
xDim
;
private
int
yDim
;
private
int
nextIndex
;
// not an index put a way to calculate the index 1..n where n is the number of possible ways to place a given group
// key: groupSize
// value: number of next group.
private
HashMap
<
Integer
,
Integer
>
nextGroupPos
;
private
HashMap
<
Integer
,
GroupPlacementHelper
>
groupPlacementHelpers
;
public
SpawnArray
(
VRectangle
bound
,
VRectangle
spawnElementBound
)
{
xDim
=
(
int
)
(
bound
.
width
/
spawnElementBound
.
width
);
yDim
=
(
int
)
(
bound
.
height
/
spawnElementBound
.
height
);
this
.
spawnElementBound
=
spawnElementBound
;
// System.out.printf("SpawnElement: %f | %f %n", spawnElementBound.width, spawnElementBound.height);
double
eX
,
eY
;
if
(
xDim
*
yDim
<=
0
)
{
xDim
=
(
xDim
==
0
)
?
1
:
xDim
;
yDim
=
(
yDim
==
0
)
?
1
:
yDim
;
public
GroupSpawnArray
(
final
VShape
boundShape
,
final
VRectangle
spawnElementBound
,
Function
<
VPoint
,
VShape
>
shapeProducer
)
{
super
(
boundShape
,
spawnElementBound
,
shapeProducer
);
spawnPoints
=
new
VPoint
[
xDim
*
yDim
];
//offset left upper corner to center point.
eX
=
(
xDim
==
1
)
?
bound
.
getCenterX
()
:
spawnElementBound
.
x
+
spawnElementBound
.
width
/
2
;
eY
=
(
yDim
==
1
)
?
bound
.
getCenterY
()
:
spawnElementBound
.
y
+
spawnElementBound
.
height
/
2
;
logger
.
info
(
String
.
format
(
"Dimension of Source is to small for at least one dimension to contain designated spawnElement with Bound (%.2f x %.2f) Set to (%d x %d)"
,
spawnElementBound
.
width
,
spawnElementBound
.
height
,
xDim
,
yDim
));
}
else
{
spawnPoints
=
new
VPoint
[
xDim
*
yDim
];
//offset left upper corner to center point.
eX
=
spawnElementBound
.
x
+
spawnElementBound
.
width
/
2
;
eY
=
spawnElementBound
.
y
+
spawnElementBound
.
height
/
2
;
}
VPoint
firstSpawnPoint
=
new
VPoint
(
bound
.
x
+
eX
,
bound
.
y
+
eY
);
for
(
int
i
=
0
;
i
<
spawnPoints
.
length
;
i
++)
{
spawnPoints
[
i
]
=
firstSpawnPoint
.
add
(
new
VPoint
(
2
*
eX
*
(
i
%
xDim
),
2
*
eY
*
(
i
/
xDim
)));
}
nextIndex
=
0
;
nextGroupPos
=
new
HashMap
<>();
groupPlacementHelpers
=
new
HashMap
<>();
}
/**
* @return maximum dimension of element. If VCircle or square it is the same in x and y. For
* other shapes the bounding box is used and from this the biggest dimension.
*/
public
double
getMaxElementDim
()
{
return
spawnElementBound
.
width
>
spawnElementBound
.
height
?
spawnElementBound
.
width
:
spawnElementBound
.
height
;
}
/**
* @return next SpawnPointIndex used to spawn underling spawnElementBound
*/
public
int
getNextSpawnPointIndex
()
{
return
nextIndex
;
}
/**
* @return copy of spawnPoint used for underling source shape.
*/
public
VPoint
[]
getSpawnPoints
()
{
return
Arrays
.
copyOf
(
spawnPoints
,
spawnPoints
.
length
);
}
// spawn without checking for free space does not make sense.
// Check here for a complete overlap (With epsilon) and use different cell in this case
// caller must handle return null.
@Deprecated
public
LinkedList
<
VPoint
>
getNextSpawnPoints
(
int
maxPoints
,
final
List
<
DynamicElement
>
neighbours
)
{
return
spawnPoints
(
maxPoints
,
neighbours
,
(
n
,
p
)
->
n
.
getShape
().
getCentroid
().
equals
(
p
,
OVERLAPP_EPSILON
)
,
len
->
startWith
(
nextIndex
,
len
));
// define spawn order (use next index)
}
// spawn without checking for free space does not make sense.
// Check here for a complete overlap (With epsilon) and use different cell in this case
// caller must handle return null.
@Deprecated
public
LinkedList
<
VPoint
>
getNextRandomSpawnPoints
(
int
maxPoints
,
Random
rnd
,
final
List
<
DynamicElement
>
neighbours
)
{
return
spawnPoints
(