Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
rrs
viewer
log-segmentation
Commits
342fea6f
Unverified
Commit
342fea6f
authored
Nov 19, 2022
by
Juon Kawakami
🥗
Browse files
init
parent
54f6cedf
Changes
419
Hide whitespace changes
Inline
Side-by-side
Too many changes to show.
To preserve performance only
20 of 419+
files are displayed.
Plain diff
Email patch
modules/maps/src/maps/osm/OSMBuilding.java
0 → 100644
View file @
342fea6f
package
maps.osm
;
import
java.util.List
;
/**
A building in OSM space.
*/
public
class
OSMBuilding
extends
OSMWay
{
/**
Construct an OSMBuilding.
@param id The ID of the building.
@param ids The IDs of the apex nodes of the building.
*/
public
OSMBuilding
(
Long
id
,
List
<
Long
>
ids
)
{
super
(
id
,
ids
);
}
@Override
public
String
toString
()
{
return
"OSMBuilding: id "
+
getID
();
}
}
modules/maps/src/maps/osm/OSMException.java
0 → 100644
View file @
342fea6f
package
maps.osm
;
/**
Exceptions related to OpenStreetMap.
*/
public
class
OSMException
extends
Exception
{
/**
Construct an OSMException with no error message.
*/
public
OSMException
()
{
super
();
}
/**
Construct an OSMException with an error message.
@param msg The error message.
*/
public
OSMException
(
String
msg
)
{
super
(
msg
);
}
/**
Construct an OSMException with an underlying cause.
@param cause The cause.
*/
public
OSMException
(
Throwable
cause
)
{
super
(
cause
);
}
/**
Construct an OSMException with an error message and underlying cause.
@param msg The error message.
@param cause The cause.
*/
public
OSMException
(
String
msg
,
Throwable
cause
)
{
super
(
msg
,
cause
);
}
}
modules/maps/src/maps/osm/OSMMap.java
0 → 100644
View file @
342fea6f
package
maps.osm
;
import
org.dom4j.Document
;
import
org.dom4j.DocumentHelper
;
import
org.dom4j.DocumentException
;
import
org.dom4j.Element
;
import
org.dom4j.io.SAXReader
;
import
java.util.HashSet
;
import
java.util.Map
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Iterator
;
import
java.io.File
;
import
java.io.IOException
;
/**
An OpenStreetMap map.
*/
public
class
OSMMap
{
private
static
final
Collection
<
String
>
ROAD_MARKERS
=
new
HashSet
<
String
>();
static
{
ROAD_MARKERS
.
add
(
"motorway"
);
ROAD_MARKERS
.
add
(
"motorway_link"
);
ROAD_MARKERS
.
add
(
"trunk"
);
ROAD_MARKERS
.
add
(
"trunk_link"
);
ROAD_MARKERS
.
add
(
"primary"
);
ROAD_MARKERS
.
add
(
"primary_link"
);
ROAD_MARKERS
.
add
(
"secondary"
);
ROAD_MARKERS
.
add
(
"secondary_link"
);
ROAD_MARKERS
.
add
(
"tertiary"
);
ROAD_MARKERS
.
add
(
"unclassified"
);
ROAD_MARKERS
.
add
(
"road"
);
ROAD_MARKERS
.
add
(
"residential"
);
ROAD_MARKERS
.
add
(
"living_street"
);
ROAD_MARKERS
.
add
(
"service"
);
ROAD_MARKERS
.
add
(
"track"
);
ROAD_MARKERS
.
add
(
"services"
);
ROAD_MARKERS
.
add
(
"pedestrian"
);
}
private
Map
<
Long
,
OSMNode
>
nodes
;
private
Map
<
Long
,
OSMRoad
>
roads
;
private
Map
<
Long
,
OSMBuilding
>
buildings
;
private
boolean
boundsCalculated
;
private
double
minLat
;
private
double
maxLat
;
private
double
minLon
;
private
double
maxLon
;
/**
Construct an empty map.
*/
public
OSMMap
()
{
boundsCalculated
=
false
;
nodes
=
new
HashMap
<
Long
,
OSMNode
>();
roads
=
new
HashMap
<
Long
,
OSMRoad
>();
buildings
=
new
HashMap
<
Long
,
OSMBuilding
>();
}
/**
Construct a map from an XML document.
@param doc The document to read.
*/
public
OSMMap
(
Document
doc
)
throws
OSMException
{
this
();
read
(
doc
);
}
/**
Construct a map from an XML file.
@param file The file to read.
*/
public
OSMMap
(
File
file
)
throws
OSMException
,
DocumentException
,
IOException
{
this
();
SAXReader
reader
=
new
SAXReader
();
Document
doc
=
reader
.
read
(
file
);
read
(
doc
);
}
/**
Construct a copy of an OSMMap over a bounded area.
@param other The map to copy.
@param minLat The minimum latitude of the new map.
@param minLon The minimum longitude of the new map.
@param maxLat The maximum latitude of the new map.
@param maxLon The maximum longitude of the new map.
*/
public
OSMMap
(
OSMMap
other
,
double
minLat
,
double
minLon
,
double
maxLat
,
double
maxLon
)
{
this
.
minLat
=
minLat
;
this
.
minLon
=
minLon
;
this
.
maxLat
=
maxLat
;
this
.
maxLon
=
maxLon
;
boundsCalculated
=
true
;
nodes
=
new
HashMap
<
Long
,
OSMNode
>();
roads
=
new
HashMap
<
Long
,
OSMRoad
>();
buildings
=
new
HashMap
<
Long
,
OSMBuilding
>();
// Copy all nodes inside the bounds
for
(
OSMNode
next
:
other
.
nodes
.
values
())
{
double
lat
=
next
.
getLatitude
();
double
lon
=
next
.
getLongitude
();
long
id
=
next
.
getID
();
if
(
lat
>=
minLat
&&
lat
<=
maxLat
&&
lon
>=
minLon
&&
lon
<=
maxLon
)
{
this
.
nodes
.
put
(
id
,
new
OSMNode
(
id
,
lat
,
lon
));
}
}
// Now copy the bits of roads and buildings that do not have missing nodes
for
(
OSMRoad
next
:
other
.
roads
.
values
())
{
List
<
Long
>
ids
=
new
ArrayList
<
Long
>(
next
.
getNodeIDs
());
for
(
Iterator
<
Long
>
it
=
ids
.
iterator
();
it
.
hasNext
();)
{
Long
nextID
=
it
.
next
();
if
(!
nodes
.
containsKey
(
nextID
))
{
it
.
remove
();
}
}
if
(!
ids
.
isEmpty
())
{
roads
.
put
(
next
.
getID
(),
new
OSMRoad
(
next
.
getID
(),
ids
));
}
}
for
(
OSMBuilding
next
:
other
.
buildings
.
values
())
{
boolean
allFound
=
true
;
for
(
Long
nextID
:
next
.
getNodeIDs
())
{
if
(!
nodes
.
containsKey
(
nextID
))
{
allFound
=
false
;
}
}
if
(
allFound
)
{
buildings
.
put
(
next
.
getID
(),
new
OSMBuilding
(
next
.
getID
(),
new
ArrayList
<
Long
>(
next
.
getNodeIDs
())));
}
}
}
/**
Read an XML document and populate this map.
@param doc The document to read.
*/
public
void
read
(
Document
doc
)
throws
OSMException
{
boundsCalculated
=
false
;
nodes
=
new
HashMap
<
Long
,
OSMNode
>();
roads
=
new
HashMap
<
Long
,
OSMRoad
>();
buildings
=
new
HashMap
<
Long
,
OSMBuilding
>();
Element
root
=
doc
.
getRootElement
();
if
(!
"osm"
.
equals
(
root
.
getName
()))
{
throw
new
OSMException
(
"Invalid map file: root element must be 'osm', not "
+
root
.
getName
());
}
for
(
Object
next
:
root
.
elements
(
"node"
))
{
Element
e
=
(
Element
)
next
;
OSMNode
node
=
processNode
(
e
);
}
for
(
Object
next
:
root
.
elements
(
"way"
))
{
Element
e
=
(
Element
)
next
;
processWay
(
e
);
}
}
/**
Turn this map into XML.
@return A new XML document.
*/
public
Document
toXML
()
{
Element
root
=
DocumentHelper
.
createElement
(
"osm"
);
Element
bounds
=
root
.
addElement
(
"bounds"
);
calculateBounds
();
bounds
.
addAttribute
(
"minlat"
,
String
.
valueOf
(
minLat
));
bounds
.
addAttribute
(
"maxlat"
,
String
.
valueOf
(
maxLat
));
bounds
.
addAttribute
(
"minlon"
,
String
.
valueOf
(
minLon
));
bounds
.
addAttribute
(
"maxlon"
,
String
.
valueOf
(
maxLon
));
for
(
OSMNode
next
:
nodes
.
values
())
{
Element
node
=
root
.
addElement
(
"node"
);
node
.
addAttribute
(
"id"
,
String
.
valueOf
(
next
.
getID
()));
node
.
addAttribute
(
"lat"
,
String
.
valueOf
(
next
.
getLatitude
()));
node
.
addAttribute
(
"lon"
,
String
.
valueOf
(
next
.
getLongitude
()));
}
for
(
OSMRoad
next
:
roads
.
values
())
{
Element
node
=
root
.
addElement
(
"way"
);
node
.
addAttribute
(
"id"
,
String
.
valueOf
(
next
.
getID
()));
for
(
Long
nextID
:
next
.
getNodeIDs
())
{
node
.
addElement
(
"nd"
).
addAttribute
(
"ref"
,
String
.
valueOf
(
nextID
));
}
node
.
addElement
(
"tag"
).
addAttribute
(
"k"
,
"highway"
).
addAttribute
(
"v"
,
"primary"
);
}
for
(
OSMBuilding
next
:
buildings
.
values
())
{
Element
node
=
root
.
addElement
(
"way"
);
node
.
addAttribute
(
"id"
,
String
.
valueOf
(
next
.
getID
()));
for
(
Long
nextID
:
next
.
getNodeIDs
())
{
node
.
addElement
(
"nd"
).
addAttribute
(
"ref"
,
String
.
valueOf
(
nextID
));
}
node
.
addElement
(
"tag"
).
addAttribute
(
"k"
,
"building"
).
addAttribute
(
"v"
,
"yes"
);
}
return
DocumentHelper
.
createDocument
(
root
);
}
/**
Get the minimum longitude in this map.
@return The minimum longitude.
*/
public
double
getMinLongitude
()
{
calculateBounds
();
return
minLon
;
}
/**
Get the maximum longitude in this map.
@return The maximum longitude.
*/
public
double
getMaxLongitude
()
{
calculateBounds
();
return
maxLon
;
}
/**
Get the centre longitude in this map.
@return The centre longitude.
*/
public
double
getCentreLongitude
()
{
calculateBounds
();
return
(
maxLon
+
minLon
)
/
2
;
}
/**
Get the minimum latitude in this map.
@return The minimum latitude.
*/
public
double
getMinLatitude
()
{
calculateBounds
();
return
minLat
;
}
/**
Get the maximum latitude in this map.
@return The maximum latitude.
*/
public
double
getMaxLatitude
()
{
calculateBounds
();
return
maxLat
;
}
/**
Get the centre latitude in this map.
@return The centre latitude.
*/
public
double
getCentreLatitude
()
{
calculateBounds
();
return
(
maxLat
+
minLat
)
/
2
;
}
/**
Get all nodes in the map.
@return All nodes.
*/
public
Collection
<
OSMNode
>
getNodes
()
{
return
new
HashSet
<
OSMNode
>(
nodes
.
values
());
}
/**
Remove a node.
@param node The node to remove.
*/
public
void
removeNode
(
OSMNode
node
)
{
nodes
.
remove
(
node
.
getID
());
}
/**
Get a node by ID.
@param id The ID of the node.
@return The node with the given ID or null.
*/
public
OSMNode
getNode
(
Long
id
)
{
return
nodes
.
get
(
id
);
}
/**
Get the nearest node to a point.
@param lat The latitude of the point.
@param lon The longitude of the point.
@return The nearest node.
*/
public
OSMNode
getNearestNode
(
double
lat
,
double
lon
)
{
double
smallest
=
Double
.
MAX_VALUE
;
OSMNode
best
=
null
;
for
(
OSMNode
next
:
nodes
.
values
())
{
double
d1
=
next
.
getLatitude
()
-
lat
;
double
d2
=
next
.
getLongitude
()
-
lon
;
double
d
=
(
d1
*
d1
)
+
(
d2
*
d2
);
if
(
d
<
smallest
)
{
best
=
next
;
smallest
=
d
;
}
}
return
best
;
}
/**
Replace a node and update all references.
@param old The node to replace.
@param replacement The replacement node.
*/
public
void
replaceNode
(
OSMNode
old
,
OSMNode
replacement
)
{
for
(
OSMRoad
r
:
roads
.
values
())
{
r
.
replace
(
old
.
getID
(),
replacement
.
getID
());
}
for
(
OSMBuilding
b
:
buildings
.
values
())
{
b
.
replace
(
old
.
getID
(),
replacement
.
getID
());
}
removeNode
(
old
);
}
/**
Get all roads.
@return All roads.
*/
public
Collection
<
OSMRoad
>
getRoads
()
{
return
new
HashSet
<
OSMRoad
>(
roads
.
values
());
}
/**
Remove a road.
@param road The road to remove.
*/
public
void
removeRoad
(
OSMRoad
road
)
{
roads
.
remove
(
road
.
getID
());
}
/**
Get all buildings.
@return All buildings.
*/
public
Collection
<
OSMBuilding
>
getBuildings
()
{
return
new
HashSet
<
OSMBuilding
>(
buildings
.
values
());
}
/**
Remove a building.
@param building The building to remove.
*/
public
void
removeBuilding
(
OSMBuilding
building
)
{
buildings
.
remove
(
building
.
getID
());
}
private
void
calculateBounds
()
{
if
(
boundsCalculated
)
{
return
;
}
minLat
=
Double
.
POSITIVE_INFINITY
;
maxLat
=
Double
.
NEGATIVE_INFINITY
;
minLon
=
Double
.
POSITIVE_INFINITY
;
maxLon
=
Double
.
NEGATIVE_INFINITY
;
for
(
OSMNode
node
:
nodes
.
values
())
{
minLat
=
Math
.
min
(
minLat
,
node
.
getLatitude
());
maxLat
=
Math
.
max
(
maxLat
,
node
.
getLatitude
());
minLon
=
Math
.
min
(
minLon
,
node
.
getLongitude
());
maxLon
=
Math
.
max
(
maxLon
,
node
.
getLongitude
());
}
boundsCalculated
=
true
;
}
private
OSMNode
processNode
(
Element
e
)
{
long
id
=
Long
.
parseLong
(
e
.
attributeValue
(
"id"
));
double
lat
=
Double
.
parseDouble
(
e
.
attributeValue
(
"lat"
));
double
lon
=
Double
.
parseDouble
(
e
.
attributeValue
(
"lon"
));
OSMNode
node
=
new
OSMNode
(
id
,
lat
,
lon
);
nodes
.
put
(
id
,
node
);
return
node
;
}
private
void
processWay
(
Element
e
)
{
long
id
=
Long
.
parseLong
(
e
.
attributeValue
(
"id"
));
List
<
Long
>
ids
=
new
ArrayList
<
Long
>();
for
(
Object
next
:
e
.
elements
(
"nd"
))
{
Element
nd
=
(
Element
)
next
;
Long
nextID
=
Long
.
parseLong
(
nd
.
attributeValue
(
"ref"
));
ids
.
add
(
nextID
);
}
// Is this way a road or a building?
boolean
road
=
false
;
boolean
building
=
false
;
for
(
Object
next
:
e
.
elements
(
"tag"
))
{
Element
tag
=
(
Element
)
next
;
building
=
building
||
tagSignifiesBuilding
(
tag
);
road
=
road
||
tagSignifiesRoad
(
tag
);
}
if
(
building
)
{
buildings
.
put
(
id
,
new
OSMBuilding
(
id
,
ids
));
}
else
if
(
road
)
{
roads
.
put
(
id
,
new
OSMRoad
(
id
,
ids
));
}
}
private
boolean
tagSignifiesRoad
(
Element
tag
)
{
String
key
=
tag
.
attributeValue
(
"k"
);
String
value
=
tag
.
attributeValue
(
"v"
);
if
(!
"highway"
.
equals
(
key
))
{
return
false
;
}
return
ROAD_MARKERS
.
contains
(
value
);
}
private
boolean
tagSignifiesBuilding
(
Element
tag
)
{
String
key
=
tag
.
attributeValue
(
"k"
);
String
value
=
tag
.
attributeValue
(
"v"
);
if
(
"building"
.
equals
(
key
))
{
return
"yes"
.
equals
(
value
);
}
if
(
"rcr:building"
.
equals
(
key
))
{
return
"1"
.
equals
(
value
);
}
return
false
;
}
}
modules/maps/src/maps/osm/OSMMapExtractor.java
0 → 100644
View file @
342fea6f
package
maps.osm
;
import
javax.swing.JFrame
;
import
javax.swing.JComponent
;
import
java.awt.Point
;
import
java.awt.Insets
;
import
java.awt.Graphics
;
import
java.awt.Color
;
import
java.awt.Dimension
;
import
java.awt.event.MouseEvent
;
import
java.awt.event.MouseAdapter
;
import
java.io.Writer
;
import
java.io.File
;
import
java.io.FileWriter
;
import
org.dom4j.Document
;
import
org.dom4j.io.XMLWriter
;
import
org.dom4j.io.OutputFormat
;
/**
This class extracts a portion of an OSMMap.
*/
public
class
OSMMapExtractor
extends
MouseAdapter
{
private
static
final
int
VIEWER_SIZE
=
500
;
private
static
final
Color
DRAG_COLOUR
=
new
Color
(
128
,
128
,
128
,
64
);
private
JComponent
glass
;
private
Point
press
;
private
Point
drag
;
private
Point
release
;
private
OSMMap
map
;
private
OSMMapViewer
viewer
;
private
Writer
out
;
/**
Construct an OSMMapExtractor.
@param map The map.
@param viewer The viewer.
@param out The writer to write extracted data to.
*/
public
OSMMapExtractor
(
OSMMap
map
,
OSMMapViewer
viewer
,
Writer
out
)
{
this
.
map
=
map
;
this
.
viewer
=
viewer
;
this
.
out
=
out
;
this
.
glass
=
new
DragGlass
();
}
/**
Start the OSMMapExtractor.
@param args Command line arguments: source target.
*/
public
static
void
main
(
String
[]
args
)
{
try
{
OSMMap
map
=
new
OSMMap
(
new
File
(
args
[
0
]));
Writer
out
=
new
FileWriter
(
new
File
(
args
[
1
]));
OSMMapViewer
viewer
=
new
OSMMapViewer
(
map
);
OSMMapExtractor
extractor
=
new
OSMMapExtractor
(
map
,
viewer
,
out
);
viewer
.
addMouseListener
(
extractor
);
viewer
.
setPreferredSize
(
new
Dimension
(
VIEWER_SIZE
,
VIEWER_SIZE
));
JFrame
frame
=
new
JFrame
();
frame
.
setGlassPane
(
extractor
.
getGlass
());
frame
.
setContentPane
(
viewer
);
frame
.
pack
();
frame
.
setVisible
(
true
);
frame
.
setDefaultCloseOperation
(
JFrame
.
EXIT_ON_CLOSE
);
}
// CHECKSTYLE:OFF:IllegalCatch
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
// CHECKSTYLE:ON:IllegalCatch
}
/**
Get a glass component for drawing the selection overlay.
@return A glass component.
*/
public
JComponent
getGlass
()
{
return
glass
;
}
@Override
public
void
mousePressed
(
MouseEvent
e
)
{
if
(
e
.
getButton
()
==
MouseEvent
.
BUTTON3
)
{
Point
p
=
e
.
getPoint
();
Insets
insets
=
viewer
.
getInsets
();
p
.
translate
(-
insets
.
left
,
-
insets
.
top
);
press
=
new
Point
(
p
);
}
}
@Override
public
void
mouseDragged
(
MouseEvent
e
)
{
if
(
e
.
getButton
()
==
MouseEvent
.
BUTTON3
)
{
Point
p
=
e
.
getPoint
();
Insets
insets
=
viewer
.
getInsets
();
p
.
translate
(-
insets
.
left
,
-
insets
.
top
);
drag
=
new
Point
(
p
);
glass
.
repaint
();
}
}
@Override
public
void
mouseReleased
(
MouseEvent
e
)
{
if
(
e
.
getButton
()
==
MouseEvent
.
BUTTON3
)
{
Point
p
=
e
.
getPoint
();
Insets
insets
=
viewer
.
getInsets
();
p
.
translate
(-
insets
.
left
,
-
insets
.
top
);
release
=
new
Point
(
p
);
drag
=
null
;
write
();
}
}
private
void
write
()
{
double
pressLat
=
viewer
.
getLatitude
(
press
.
y
);
double
pressLon
=
viewer
.
getLongitude
(
press
.
x
);
double
releaseLat
=
viewer
.
getLatitude
(
release
.
y
);
double
releaseLon
=
viewer
.
getLongitude
(
release
.
x
);
try
{
OSMMap
newMap
=
new
OSMMap
(
map
,
Math
.
min
(
pressLat
,
releaseLat
),
Math
.
min
(
pressLon
,
releaseLon
),
Math
.
max
(
pressLat
,
releaseLat
),
Math
.
max
(
pressLon
,
releaseLon
));
Document
d
=
newMap
.
toXML
();
XMLWriter
writer
=
new
XMLWriter
(
out
,
OutputFormat
.
createPrettyPrint
());
writer
.
write
(
d
);
writer
.
flush
();
writer
.
close
();
System
.
out
.
println
(
"Wrote map"
);
}
// CHECKSTYLE:OFF:IllegalCatch
catch
(
Exception
ex
)
{
ex
.
printStackTrace
();
}
// CHECKSTYLE:ON:IllegalCatch
}
private
class
DragGlass
extends
JComponent
{
public
void
paintComponent
(
Graphics
g
)
{
if
(
drag
==
null
)
{
return
;
}
g
.
setColor
(
DRAG_COLOUR
);
int
x
=
Math
.
min
(
press
.
x
,
drag
.
x
);
int
y
=
Math
.
max
(
press
.
y
,
drag
.
y
);
int
width
=
(
int
)
Math
.
abs
(
press
.
x
-
drag
.
x
);
int
height
=
(
int
)
Math
.
abs
(
press
.
y
-
drag
.
y
);
g
.
fillRect
(
x
,
y
,
width
,
height
);
}
}
}
modules/maps/src/maps/osm/OSMMapViewer.java
0 → 100644
View file @
342fea6f
package
maps.osm
;
import
java.awt.Graphics
;
import
java.awt.Graphics2D
;
import
java.awt.Color
;
import
java.awt.Insets
;
import
java.awt.Point
;
import
java.awt.event.MouseAdapter
;
import
java.awt.event.MouseEvent
;
import
javax.swing.JComponent
;
import
rescuecore2.misc.gui.ScreenTransform
;
import
rescuecore2.misc.gui.PanZoomListener
;
/**
A component for viewing OSM maps.
*/
public
class
OSMMapViewer
extends
JComponent
{
private
OSMMap
map
;
private
ScreenTransform
transform
;
private
PanZoomListener
panZoom
;
/**
Create an OSMMapViewer.
*/
public
OSMMapViewer
()
{
this
(
null
);
}
/**
Create an OSMMapViewer.
@param map The map to view.
*/
public
OSMMapViewer
(
final
OSMMap
map
)
{
panZoom
=
new
PanZoomListener
(
this
);
setMap
(
map
);
addMouseListener
(
new
MouseAdapter
()
{
public
void
mouseClicked
(
MouseEvent
e
)
{
if
(
e
.
getButton
()
==
MouseEvent
.
BUTTON1
)
{
Point
p
=
e
.
getPoint
();
double
lon
=
transform
.
screenToX
(
p
.
x
);
double
lat
=
transform
.
screenToY
(
p
.
y
);
OSMNode
node
=
map
.
getNearestNode
(
lat
,
lon
);
System
.
out
.
println
(
"Click at "
+
lat
+
", "
+
lon
);
System
.
out
.
println
(
"Nearest node: "
+
node
);
}
}
});
}
/**
Set the map.
@param map The new map to view.
*/
public
void
setMap
(
OSMMap
map
)
{
this
.
map
=
map
;
transform
=
null
;
if
(
map
!=
null
)
{
transform
=
new
ScreenTransform
(
map
.
getMinLongitude
(),
map
.
getMinLatitude
(),
map
.
getMaxLongitude
(),
map
.
getMaxLatitude
());
}
panZoom
.
setScreenTransform
(
transform
);
}
/**
Get the latitude of a screen coordinate.
@param y The screen coordinate.
@return The latitude at that coordinate.
*/
public
double
getLatitude
(
int
y
)
{
return
transform
.
screenToY
(
y
);
}
/**
Get the longitude of a screen coordinate.
@param x The screen coordinate.
@return The longitude at that coordinate.
*/
public
double
getLongitude
(
int
x
)
{
return
transform
.
screenToX
(
x
);
}
@Override
public
void
paintComponent
(
Graphics
graphics
)
{
super
.
paintComponent
(
graphics
);
if
(
map
==
null
)
{
return
;
}
Insets
insets
=
getInsets
();
int
width
=
getWidth
()
-
insets
.
left
-
insets
.
right
;
int
height
=
getHeight
()
-
insets
.
top
-
insets
.
bottom
;
Graphics2D
g
=
(
Graphics2D
)
graphics
.
create
(
insets
.
left
,
insets
.
top
,
width
+
1
,
height
+
1
);
transform
.
rescale
(
width
,
height
);
g
.
setColor
(
Color
.
black
);
for
(
OSMNode
next
:
map
.
getNodes
())
{
int
x
=
transform
.
xToScreen
(
next
.
getLongitude
());
int
y
=
transform
.
yToScreen
(
next
.
getLatitude
());
g
.
drawLine
(
x
-
1
,
y
-
1
,
x
+
1
,
y
+
1
);
g
.
drawLine
(
x
+
1
,
y
-
1
,
x
-
1
,
y
+
1
);
}
for
(
OSMRoad
next
:
map
.
getRoads
())
{
int
lastX
=
-
1
;
int
lastY
=
-
1
;
for
(
Long
nodeID
:
next
.
getNodeIDs
())
{
OSMNode
node
=
map
.
getNode
(
nodeID
);
int
x
=
transform
.
xToScreen
(
node
.
getLongitude
());
int
y
=
transform
.
yToScreen
(
node
.
getLatitude
());
if
(
lastX
!=
-
1
)
{
g
.
drawLine
(
lastX
,
lastY
,
x
,
y
);
}
lastX
=
x
;
lastY
=
y
;
}
}
g
.
setColor
(
Color
.
blue
);
for
(
OSMBuilding
next
:
map
.
getBuildings
())
{
int
lastX
=
-
1
;
int
lastY
=
-
1
;
for
(
Long
nodeID
:
next
.
getNodeIDs
())
{
OSMNode
node
=
map
.
getNode
(
nodeID
);
int
x
=
transform
.
xToScreen
(
node
.
getLongitude
());
int
y
=
transform
.
yToScreen
(
node
.
getLatitude
());
if
(
lastX
!=
-
1
)
{
g
.
drawLine
(
lastX
,
lastY
,
x
,
y
);
}
lastX
=
x
;
lastY
=
y
;
}
}
}
}
modules/maps/src/maps/osm/OSMNode.java
0 → 100644
View file @
342fea6f
package
maps.osm
;
/**
An OpenStreetMap node.
*/
public
class
OSMNode
extends
OSMObject
{
private
double
lat
;
private
double
lon
;
/**
Construct an OSMNode.
@param id The ID of the node.
@param lat The latitude of the node.
@param lon The longitude of the node.
*/
public
OSMNode
(
long
id
,
double
lat
,
double
lon
)
{
super
(
id
);
this
.
lat
=
lat
;
this
.
lon
=
lon
;
}
/**
Get the latitude of this node in degrees.
@return The latitude in degrees.
*/
public
double
getLatitude
()
{
return
lat
;
}
/**
Get the longitude of this node in degrees.
@return The longitude in degrees.
*/
public
double
getLongitude
()
{
return
lon
;
}
@Override
public
String
toString
()
{
return
"OSMNode ("
+
getID
()
+
") at lat "
+
lat
+
", lon "
+
lon
;
}
}
modules/maps/src/maps/osm/OSMObject.java
0 → 100644
View file @
342fea6f
package
maps.osm
;
/**
Abstract base class for OpenStreetMap objects.
*/
public
abstract
class
OSMObject
{
private
long
id
;
/**
Construct an OSMObject.
@param id The ID of the object.
*/
public
OSMObject
(
long
id
)
{
this
.
id
=
id
;
}
/**
Get the ID of this object.
@return The ID of the object.
*/
public
long
getID
()
{
return
id
;
}
}
modules/maps/src/maps/osm/OSMRoad.java
0 → 100644
View file @
342fea6f
package
maps.osm
;
import
java.util.List
;
/**
An OpenStreetMap road.
*/
public
class
OSMRoad
extends
OSMWay
{
/**
Construct an OSMRoad.
@param id The ID of the road.
@param ids The IDs of the apex nodes of the road.
*/
public
OSMRoad
(
Long
id
,
List
<
Long
>
ids
)
{
super
(
id
,
ids
);
}
}
modules/maps/src/maps/osm/OSMWay.java
0 → 100644
View file @
342fea6f
package
maps.osm
;
import
java.util.List
;
import
java.util.ArrayList
;
import
java.util.Collections
;
/**
An OSM way.
*/
public
abstract
class
OSMWay
extends
OSMObject
{
private
List
<
Long
>
ids
;
/**
Construct an OSMWay.
@param id The ID of the way.
@param ids The IDs of the nodes of the way.
*/
public
OSMWay
(
Long
id
,
List
<
Long
>
ids
)
{
super
(
id
);
this
.
ids
=
ids
;
}
/**
Get the IDs of the way nodes.
@return The IDs of the nodes of this way.
*/
public
List
<
Long
>
getNodeIDs
()
{
return
new
ArrayList
<
Long
>(
ids
);
}
/**
Set the IDs of the way nodes.
@param newIDs The new IDs of the nodes of this way.
*/
public
void
setNodeIDs
(
List
<
Long
>
newIDs
)
{
ids
=
newIDs
;
}
/**
Replace a node ID in this way.
@param oldID The old node ID.
@param newID The new node ID.
*/
public
void
replace
(
Long
oldID
,
Long
newID
)
{
Collections
.
replaceAll
(
ids
,
oldID
,
newID
);
}
}
modules/maps/src/maps/osm/debug/OSMWayShapeInfo.java
0 → 100644
View file @
342fea6f
package
maps.osm.debug
;
import
java.awt.Color
;
import
java.awt.Shape
;
import
java.awt.Polygon
;
import
java.awt.Graphics2D
;
import
java.awt.geom.Rectangle2D
;
import
java.util.List
;
import
rescuecore2.misc.gui.ScreenTransform
;
import
rescuecore2.misc.gui.ShapeDebugFrame
;
import
rescuecore2.misc.gui.DrawingTools
;
import
maps.osm.OSMWay
;
import
maps.osm.OSMMap
;
import
maps.osm.OSMNode
;
/**
A ShapeInfo that knows how to draw OSMWays.
*/
public
class
OSMWayShapeInfo
extends
ShapeDebugFrame
.
ShapeInfo
{
private
OSMWay
way
;
private
OSMMap
map
;
private
Color
colour
;
private
boolean
drawEdgeDirections
;
private
Rectangle2D
bounds
;
/**
Create a new OSMWayShapeInfo.
@param way The way to draw.
@param map The map the way is part of.
@param name The name of the way.
@param colour The colour to draw the way.
@param drawEdgeDirections Whether to draw edge directions or not.
*/
public
OSMWayShapeInfo
(
OSMWay
way
,
OSMMap
map
,
String
name
,
Color
colour
,
boolean
drawEdgeDirections
)
{
super
(
way
,
name
);
this
.
way
=
way
;
this
.
map
=
map
;
this
.
colour
=
colour
;
this
.
drawEdgeDirections
=
drawEdgeDirections
;
if
(
way
!=
null
)
{
bounds
=
findBounds
();
}
}
@Override
public
Shape
paint
(
Graphics2D
g
,
ScreenTransform
transform
)
{
if
(
way
==
null
)
{
return
null
;
}
List
<
Long
>
points
=
way
.
getNodeIDs
();
int
n
=
points
.
size
();
int
[]
xs
=
new
int
[
n
];
int
[]
ys
=
new
int
[
n
];
int
i
=
0
;
for
(
long
next
:
points
)
{
xs
[
i
]
=
transform
.
xToScreen
(
map
.
getNode
(
next
).
getLongitude
());
ys
[
i
]
=
transform
.
yToScreen
(
map
.
getNode
(
next
).
getLatitude
());
++
i
;
}
Polygon
p
=
new
Polygon
(
xs
,
ys
,
n
);
if
(
colour
!=
null
)
{
g
.
setColor
(
colour
);
g
.
draw
(
p
);
if
(
drawEdgeDirections
)
{
for
(
i
=
1
;
i
<
n
;
++
i
)
{
DrawingTools
.
drawArrowHeads
(
xs
[
i
-
1
],
ys
[
i
-
1
],
xs
[
i
],
ys
[
i
],
g
);
}
}
}
return
p
;
}
@Override
public
void
paintLegend
(
Graphics2D
g
,
int
width
,
int
height
)
{
if
(
colour
!=
null
)
{
g
.
setColor
(
colour
);
g
.
drawRect
(
0
,
0
,
width
-
1
,
height
-
1
);
}
}
@Override
public
Rectangle2D
getBoundsShape
()
{
return
bounds
;
}
@Override
public
java
.
awt
.
geom
.
Point2D
getBoundsPoint
()
{
return
null
;
}
private
Rectangle2D
findBounds
()
{
double
xMin
=
Double
.
POSITIVE_INFINITY
;
double
xMax
=
Double
.
NEGATIVE_INFINITY
;
double
yMin
=
Double
.
POSITIVE_INFINITY
;
double
yMax
=
Double
.
NEGATIVE_INFINITY
;
for
(
long
next
:
way
.
getNodeIDs
())
{
OSMNode
n
=
map
.
getNode
(
next
);
xMin
=
Math
.
min
(
xMin
,
n
.
getLongitude
());
xMax
=
Math
.
max
(
xMax
,
n
.
getLongitude
());
yMin
=
Math
.
min
(
yMin
,
n
.
getLatitude
());
yMax
=
Math
.
max
(
yMax
,
n
.
getLatitude
());
}
return
new
Rectangle2D
.
Double
(
xMin
,
yMin
,
xMax
-
xMin
,
yMax
-
yMin
);
}
}
modules/maps/src/maps/validate/GMLConnectivityValidator.java
0 → 100644
View file @
342fea6f
package
maps.validate
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Queue
;
import
java.util.Set
;
import
maps.gml.GMLBuilding
;
import
maps.gml.GMLDirectedEdge
;
import
maps.gml.GMLMap
;
import
maps.gml.GMLRoad
;
import
maps.gml.GMLShape
;
/**
* Checks if a GML map is fully connected and if all individual shaped are
* correctly connected to each other (i.e. there are no dangling or no one-way
* connections).
*/
public
class
GMLConnectivityValidator
implements
MapValidator
<
GMLMap
>
{
private
GMLMap
map
=
null
;
@Override
public
Collection
<
ValidationError
>
validate
(
GMLMap
mmap
)
{
this
.
map
=
mmap
;
List
<
ValidationError
>
errors
=
new
LinkedList
<
ValidationError
>();
// Check if all shapes are connected correctly (no dangling connections,
// etc...)
Set
<
GMLShape
>
toBeChecked
=
new
HashSet
<
GMLShape
>();
for
(
GMLShape
shape
:
map
.
getAllShapes
())
{
errors
.
addAll
(
validateShape
(
shape
));
if
(
shape
instanceof
GMLBuilding
||
shape
instanceof
GMLRoad
)
{
toBeChecked
.
add
(
shape
);
}
}
Queue
<
GMLShape
>
open
=
new
LinkedList
<
GMLShape
>();
GMLShape
first
=
toBeChecked
.
iterator
().
next
();
open
.
add
(
first
);
// check for connectivity (only simple connectivity needs to be checked,
// as
// we made sure that there are no one-way connections
while
(!
open
.
isEmpty
())
{
GMLShape
next
=
open
.
remove
();
toBeChecked
.
remove
(
next
);
for
(
GMLShape
n
:
getNeigbours
(
next
))
{
if
(
toBeChecked
.
contains
(
n
))
{
open
.
add
(
n
);
}
if
(!(
n
instanceof
GMLBuilding
||
n
instanceof
GMLRoad
))
{
String
message
=
"Can reach non-building, non-road shape "
+
n
.
getID
();
errors
.
add
(
new
ValidationError
(
next
.
getID
(),
message
));
}
}
}
if
(!
toBeChecked
.
isEmpty
())
{
for
(
GMLShape
unreachable
:
toBeChecked
)
{
String
message
=
"The map is not fully connected. Shape cannot be reached from "
+
first
.
getID
();
errors
.
add
(
new
ValidationError
(
unreachable
.
getID
(),
message
));
}
}
return
errors
;
}
/**
* Check if all connections to neighbours are reflexive.
*
* @param shape
* @return
*/
private
Collection
<
ValidationError
>
validateShape
(
GMLShape
shape
)
{
List
<
ValidationError
>
errors
=
new
LinkedList
<
ValidationError
>();
for
(
GMLDirectedEdge
e
:
shape
.
getEdges
())
{
if
(
shape
.
hasNeighbour
(
e
))
{
int
nId
=
shape
.
getNeighbour
(
e
);
GMLShape
neighbour
=
map
.
getShape
(
nId
);
if
(
neighbour
==
null
)
{
String
message
=
"Connection to nonexisting id "
+
nId
+
" via Edge "
+
e
.
getEdge
().
getID
();
errors
.
add
(
new
ValidationError
(
shape
.
getID
(),
message
));
}
else
if
(
neighbour
==
shape
)
{
String
message
=
"Shape is connected to itself via Edge"
+
e
.
getEdge
().
getID
();
errors
.
add
(
new
ValidationError
(
shape
.
getID
(),
message
));
}
else
{
GMLShape
backRef
=
null
;
try
{
if
(
neighbour
.
hasNeighbour
(
e
.
getEdge
()))
{
backRef
=
map
.
getShape
(
neighbour
.
getNeighbour
(
e
.
getEdge
()));
}
if
(
backRef
!=
shape
)
{
String
message
=
"Connection to "
+
neighbour
.
getID
()
+
" via Edge "
+
e
.
getEdge
().
getID
()
+
" is not reflexive."
;
errors
.
add
(
new
ValidationError
(
shape
.
getID
(),
message
));
}
}
catch
(
IllegalArgumentException
ex
)
{
String
message
=
"Neigbour "
+
neighbour
.
getID
()
+
" does not share Edge "
+
e
.
getEdge
().
getID
();
errors
.
add
(
new
ValidationError
(
shape
.
getID
(),
message
));
}
}
}
}
return
errors
;
}
/**
* Get all shapes that a shape is connected to.
* @param shape
* @return
*/
private
Collection
<
GMLShape
>
getNeigbours
(
GMLShape
shape
)
{
Collection
<
GMLShape
>
result
=
new
ArrayList
<
GMLShape
>();
for
(
GMLDirectedEdge
edge
:
shape
.
getEdges
())
{
if
(
shape
.
hasNeighbour
(
edge
))
{
GMLShape
n
=
map
.
getShape
(
shape
.
getNeighbour
(
edge
));
if
(
n
!=
null
)
{
result
.
add
(
n
);
}
}
}
return
result
;
}
}
modules/maps/src/maps/validate/GMLMapValidator.java
0 → 100644
View file @
342fea6f
package
maps.validate
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.List
;
import
maps.MapException
;
import
maps.MapReader
;
import
maps.gml.GMLMap
;
/**
* Load a map and check it for errors.
*
*/
public
final
class
GMLMapValidator
{
private
static
List
<
MapValidator
<
GMLMap
>>
validators
;
static
{
validators
=
new
ArrayList
<
MapValidator
<
GMLMap
>>();
validators
.
add
(
new
GMLConnectivityValidator
());
validators
.
add
(
new
GMLShapeValidator
());
validators
.
add
(
new
GMLTraversabilityValidator
());
}
private
GMLMapValidator
()
{}
/**
* Returns a list of default MapValidators to use for GML maps.
@return List of default MapValidators.
*/
public
static
List
<
MapValidator
<
GMLMap
>>
getDefaultValidators
()
{
return
new
ArrayList
<
MapValidator
<
GMLMap
>>(
validators
);
}
/**
* @param args The command line arguments.
*/
public
static
void
main
(
String
[]
args
)
{
try
{
GMLMap
map
=
(
GMLMap
)
MapReader
.
readMap
(
args
[
0
]);
boolean
hasErrors
=
true
;
for
(
MapValidator
<
GMLMap
>
val
:
validators
)
{
Collection
<
ValidationError
>
errors
=
val
.
validate
(
map
);
for
(
ValidationError
e
:
errors
)
{
System
.
err
.
println
(
e
);
hasErrors
=
true
;
}
}
if
(!
hasErrors
)
{
System
.
out
.
println
(
"No errors have been found."
);
}
}
catch
(
MapException
e
)
{
e
.
printStackTrace
();
}
}
}
modules/maps/src/maps/validate/GMLShapeValidator.java
0 → 100644
View file @
342fea6f
package
maps.validate
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.List
;
import
maps.gml.GMLMap
;
import
maps.gml.GMLShape
;
import
com.vividsolutions.jts.geom.Geometry
;
/**
Validate the correctness of basic shape properties.
@author goebelbe
*/
public
class
GMLShapeValidator
implements
MapValidator
<
GMLMap
>
{
@Override
public
Collection
<
ValidationError
>
validate
(
GMLMap
map
)
{
List
<
ValidationError
>
errors
=
new
ArrayList
<
ValidationError
>();
List
<
Geometry
>
polygons
=
new
ArrayList
<
Geometry
>();
List
<
GMLShape
>
shapes
=
new
ArrayList
<
GMLShape
>(
map
.
getAllShapes
());
for
(
GMLShape
shape
:
shapes
)
{
try
{
Geometry
polygon
=
checkShape
(
shape
);
polygons
.
add
(
polygon
);
}
catch
(
ValidationException
e
)
{
errors
.
add
(
e
.
getError
());
polygons
.
add
(
null
);
}
}
for
(
int
i
=
0
;
i
<
polygons
.
size
();
i
++)
{
Geometry
s1
=
polygons
.
get
(
i
);
if
(
s1
==
null
)
{
continue
;
}
for
(
int
j
=
i
+
1
;
j
<
polygons
.
size
();
j
++)
{
Geometry
s2
=
polygons
.
get
(
j
);
if
(
s2
!=
null
&&
s1
.
intersects
(
s2
)
&&
!
s1
.
touches
(
s2
))
{
int
s1Id
=
shapes
.
get
(
i
).
getID
();
int
s2Id
=
shapes
.
get
(
j
).
getID
();
String
message
=
" Shape overlaps with shape "
+
s2Id
;
errors
.
add
(
new
ValidationError
(
s1Id
,
message
));
}
}
}
return
errors
;
}
/**
Check if the given shape is correct.
@param shape
@return
*/
private
static
Geometry
checkShape
(
GMLShape
shape
)
throws
ValidationException
{
Geometry
polygon
=
JTSTools
.
shapeToPolygon
(
shape
);
if
(!
polygon
.
isValid
())
{
throw
new
ValidationException
(
shape
.
getID
(),
"invalid shape"
);
}
if
(!
polygon
.
contains
(
polygon
.
getCentroid
()))
{
throw
new
ValidationException
(
shape
.
getID
(),
"Shape doesn't contain centroid."
);
}
return
polygon
;
}
}
modules/maps/src/maps/validate/GMLTraversabilityValidator.java
0 → 100644
View file @
342fea6f
package
maps.validate
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.List
;
import
maps.gml.GMLDirectedEdge
;
import
maps.gml.GMLMap
;
import
maps.gml.GMLRoad
;
import
maps.gml.GMLShape
;
import
com.vividsolutions.jts.geom.Coordinate
;
import
com.vividsolutions.jts.geom.Geometry
;
import
com.vividsolutions.jts.geom.LineString
;
import
com.vividsolutions.jts.operation.linemerge.LineSequencer
;
/**
* Validator to check if the shapes of the map are traversable.
*
* For all shaped we check if they can be entered via their entrances.
*
* For road we also check if each entrance can reach the other ones via this
* road.
*
*/
public
class
GMLTraversabilityValidator
implements
MapValidator
<
GMLMap
>
{
private
static
final
double
MIN_ROAD_WIDTH
=
1.0
;
private
static
final
double
SHAPE_PADDING
=
0.01
;
@Override
public
Collection
<
ValidationError
>
validate
(
GMLMap
map
)
{
Collection
<
ValidationError
>
errors
=
new
ArrayList
<
ValidationError
>();
for
(
GMLShape
shape
:
map
.
getRoads
())
{
ValidationError
error
=
checkTraversability
(
shape
,
MIN_ROAD_WIDTH
);
if
(
error
!=
null
)
{
errors
.
add
(
error
);
}
}
for
(
GMLShape
shape
:
map
.
getBuildings
())
{
ValidationError
error
=
checkTraversability
(
shape
,
MIN_ROAD_WIDTH
);
if
(
error
!=
null
)
{
errors
.
add
(
error
);
}
}
return
errors
;
}
/**
* Check if this shape can be traversed by an agent of width
* <tt>minWidth</tt>.
*
* @param shape
* @param agentWidth
* @return
*/
private
ValidationError
checkTraversability
(
GMLShape
shape
,
double
minWidth
)
{
// To check for traversability, we shrink the non-traversable edges
// of the shape by the radius of the agent.
// We then check, if all entrance edges are part of the same part
// of the resulting polygon
try
{
Geometry
polygon
=
JTSTools
.
shapeToPolygon
(
shape
);
if
(!
polygon
.
isValid
())
{
return
new
ValidationError
(
shape
.
getID
(),
"invalid shape"
);
}
Geometry
boundary
=
impassableLines
(
shape
);
Geometry
buffer
=
boundary
.
buffer
(((
double
)
minWidth
)
/
2
);
Geometry
result
=
polygon
.
difference
(
buffer
);
// make sure the intersection tests succeed
result
=
result
.
buffer
(
SHAPE_PADDING
);
Coordinate
centroid
=
JTSTools
.
pointToCoordinate
(
shape
.
getCentroid
());
// Build list of adjacent entrance edges
List
<
GMLDirectedEdge
>
edges
=
shape
.
getEdges
();
List
<
List
<
GMLDirectedEdge
>>
entrances
=
new
ArrayList
<
List
<
GMLDirectedEdge
>>();
List
<
GMLDirectedEdge
>
entrance
=
new
ArrayList
<
GMLDirectedEdge
>();
for
(
GMLDirectedEdge
e
:
edges
)
{
if
(
shape
.
hasNeighbour
(
e
))
{
entrance
.
add
(
e
);
//Check if we have a line of sight to the centroid
LineString
edge
=
JTSTools
.
edgeToLine
(
e
);
Coordinate
edgeCenter
=
edge
.
getCentroid
().
getCoordinate
();
Coordinate
[]
coords
=
new
Coordinate
[]{
centroid
,
edgeCenter
};
LineString
lineOfSight
=
JTSTools
.
getFactory
().
createLineString
(
coords
);
if
(
lineOfSight
.
intersects
(
boundary
))
{
String
message
=
"Edge "
+
e
.
getEdge
().
getID
()
+
" has no line of sight to shape center."
;
return
new
ValidationError
(
shape
.
getID
(),
message
);
}
}
else
{
if
(!
entrance
.
isEmpty
())
{
entrances
.
add
(
entrance
);
}
entrance
=
new
ArrayList
<
GMLDirectedEdge
>();
}
}
if
(!
entrance
.
isEmpty
())
{
// Merge first and last sequences if neccessary
if
(
shape
.
hasNeighbour
(
edges
.
get
(
0
))
&&
!
entrances
.
isEmpty
())
{
entrances
.
get
(
0
).
addAll
(
entrance
);
}
else
{
entrances
.
add
(
entrance
);
}
}
// Check in which part of the polygon the entrances lie
GMLDirectedEdge
firstEdge
=
null
;
int
firstPolygon
=
-
1
;
for
(
List
<
GMLDirectedEdge
>
etr
:
entrances
)
{
int
polyIndex
=
-
1
;
for
(
GMLDirectedEdge
e
:
etr
)
{
polyIndex
=
findPolygonPartOfEdge
(
e
,
result
);
if
(
polyIndex
!=
-
1
)
{
break
;
}
}
if
(
polyIndex
==
-
1
)
{
// Entrance edge no longer in polygon
String
message
=
"Edge is too narrow to pass through."
;
return
new
ValidationError
(
etr
.
get
(
0
).
getEdge
().
getID
(),
message
);
}
if
(
firstEdge
==
null
)
{
firstEdge
=
etr
.
get
(
0
);
firstPolygon
=
polyIndex
;
}
else
if
(
firstPolygon
!=
polyIndex
&&
(
shape
instanceof
GMLRoad
))
{
// Only check traversability for roads
String
message
=
"Can't reach edge "
+
firstEdge
.
getEdge
().
getID
()
+
" from "
+
etr
.
get
(
0
).
getEdge
().
getID
();
return
new
ValidationError
(
shape
.
getID
(),
message
);
}
}
return
null
;
}
catch
(
ValidationException
e
)
{
return
e
.
getError
();
}
}
/**
* Find the index of the subgeometry the given edge is part of. Return -1 if
* the edge is not contained in the geometry at all.
* @param edge
* @param geom
* @return
*/
private
static
int
findPolygonPartOfEdge
(
GMLDirectedEdge
edge
,
Geometry
geom
)
{
for
(
int
i
=
0
;
i
<
geom
.
getNumGeometries
();
i
++)
{
if
(
edgePartOfPolygon
(
edge
,
geom
.
getGeometryN
(
i
)))
{
return
i
;
}
}
return
-
1
;
}
/**
* Checks if an edge is part (i.e intersects) of a given polygon.
* @param edge
* @param polygon
* @return
*/
private
static
boolean
edgePartOfPolygon
(
GMLDirectedEdge
edge
,
Geometry
polygon
)
{
// No idea if this works...
return
polygon
.
intersects
(
JTSTools
.
edgeToLine
(
edge
));
}
/**
* Return a LineString or MultiLineString of the impassable edges of a
* shape.
* @param shape
* @return
*/
private
static
Geometry
impassableLines
(
GMLShape
shape
)
{
LineSequencer
seq
=
new
LineSequencer
();
for
(
GMLDirectedEdge
e
:
shape
.
getEdges
())
{
if
(!
shape
.
hasNeighbour
(
e
))
{
Coordinate
[]
coord
=
new
Coordinate
[
2
];
coord
[
0
]
=
JTSTools
.
nodeToCoordinate
(
e
.
getStartNode
());
coord
[
1
]
=
JTSTools
.
nodeToCoordinate
(
e
.
getEndNode
());
seq
.
add
(
JTSTools
.
getFactory
().
createLineString
(
coord
));
}
}
return
seq
.
getSequencedLineStrings
();
}
}
modules/maps/src/maps/validate/JTSTools.java
0 → 100644
View file @
342fea6f
package
maps.validate
;
import
maps.gml.GMLDirectedEdge
;
import
maps.gml.GMLNode
;
import
maps.gml.GMLShape
;
import
rescuecore2.misc.geometry.Point2D
;
import
com.vividsolutions.jts.geom.Coordinate
;
import
com.vividsolutions.jts.geom.CoordinateList
;
import
com.vividsolutions.jts.geom.Geometry
;
import
com.vividsolutions.jts.geom.GeometryFactory
;
import
com.vividsolutions.jts.geom.LineString
;
import
com.vividsolutions.jts.geom.LinearRing
;
import
com.vividsolutions.jts.operation.linemerge.LineSequencer
;
import
com.vividsolutions.jts.util.AssertionFailedException
;
/**
* This class provides some conversion functions from GML map classes to JTS
* Geometry classes.
*/
public
final
class
JTSTools
{
private
static
GeometryFactory
geomFactory
=
new
GeometryFactory
();
private
JTSTools
()
{
};
/**
* Create a LineString from a GMLDirectedEdge.
* @param edge
* The edge to convert.
* @return LineString or MultLineString.
*/
public
static
LineString
edgeToLine
(
GMLDirectedEdge
edge
)
{
Coordinate
[]
coord
=
new
Coordinate
[
2
];
coord
[
0
]
=
nodeToCoordinate
(
edge
.
getStartNode
());
coord
[
1
]
=
nodeToCoordinate
(
edge
.
getEndNode
());
return
geomFactory
.
createLineString
(
coord
);
}
/**
* Create a JTS Polygon form a GMLShape.
* @param shape
* The shape to convert.
* @return Polygon geometry.
* @throws ValidationException
*/
public
static
Geometry
shapeToPolygon
(
GMLShape
shape
)
throws
ValidationException
{
LineSequencer
seq
=
new
LineSequencer
();
for
(
GMLDirectedEdge
e
:
shape
.
getEdges
())
{
Coordinate
[]
coord
=
new
Coordinate
[
2
];
coord
[
0
]
=
nodeToCoordinate
(
e
.
getStartNode
());
coord
[
1
]
=
nodeToCoordinate
(
e
.
getEndNode
());
if
(
coord
[
0
].
equals
(
coord
[
1
]))
{
throw
new
ValidationException
(
e
.
getEdge
().
getID
(),
"Zero length edge."
);
}
seq
.
add
(
geomFactory
.
createLineString
(
coord
));
}
try
{
if
(!
seq
.
isSequenceable
())
{
throw
new
ValidationException
(
shape
.
getID
(),
"Outline is not a single line."
);
}
}
catch
(
AssertionFailedException
e
)
{
throw
new
ValidationException
(
shape
.
getID
(),
"Could not get outline: "
+
e
.
getMessage
());
}
Geometry
line
=
seq
.
getSequencedLineStrings
();
CoordinateList
coord
=
new
CoordinateList
(
line
.
getCoordinates
());
coord
.
closeRing
();
// CHECKSTYLE:OFF:MagicNumber
if
(
coord
.
size
()
<
4
)
{
// CHECKSTYLE:ON:MagicNumber
throw
new
ValidationException
(
shape
.
getID
(),
"Degenerate Shape"
);
}
Geometry
ring
=
geomFactory
.
createLinearRing
(
coord
.
toCoordinateArray
());
return
geomFactory
.
createPolygon
((
LinearRing
)
ring
,
null
);
}
/**
* Create a Coordinate from a GMLNode.
* @param node
* Node to convert.
* @return Coordinate object.
*/
public
static
Coordinate
nodeToCoordinate
(
GMLNode
node
)
{
return
new
Coordinate
(
node
.
getX
(),
node
.
getY
());
}
/**
* Create a Coordinate from a Point2D.
* @param point
* Point to convert.
* @return Coordinate object.
*/
public
static
Coordinate
pointToCoordinate
(
Point2D
point
)
{
return
new
Coordinate
(
point
.
getX
(),
point
.
getY
());
}
/**
* Get the default GeometryFactory.
* @return The default GeometryFactory.
*/
public
static
GeometryFactory
getFactory
()
{
return
geomFactory
;
}
}
modules/maps/src/maps/validate/MapValidator.java
0 → 100644
View file @
342fea6f
package
maps.validate
;
import
java.util.Collection
;
import
maps.Map
;
/**
* Interface for classes that can validate maps.
*
* @param <T>
*/
public
interface
MapValidator
<
T
extends
Map
>
{
/**
* Check if the given map is valid. If not, return a collection of errors.
* @param map Map that should be checked.
* @return Collection of errors.
*/
Collection
<
ValidationError
>
validate
(
T
map
);
}
modules/maps/src/maps/validate/ValidationError.java
0 → 100644
View file @
342fea6f
package
maps.validate
;
/**
* This class encapsulates a validation error. It contains the object id and an
* error message.
*/
public
class
ValidationError
{
private
int
id
;
private
String
message
;
/**
* Create a new ValidationError object.
* @param id The id of the GMLObject containing the error.
* @param message The error message.
*/
public
ValidationError
(
int
id
,
String
message
)
{
this
.
id
=
id
;
this
.
message
=
message
;
}
/**
* Get the id of the object this error refers to.
* @return The id of the GMLObject containing the error.
*/
public
int
getId
()
{
return
id
;
}
/**
* Get the error message of this ValidationError.
* @return The error message.
*/
public
String
getMessage
()
{
return
message
;
}
@Override
public
String
toString
()
{
return
"Error in object "
+
id
+
": "
+
message
;
}
}
modules/maps/src/maps/validate/ValidationException.java
0 → 100644
View file @
342fea6f
package
maps.validate
;
/**
* Exception that is raised when an error in a map is detected during
* validation.
*
*/
public
class
ValidationException
extends
Exception
{
private
ValidationError
error
;
/**
* Create a new ValidationException.
* @param id The id of the GMLObject containing the error.
* @param message The error message.
*/
public
ValidationException
(
int
id
,
String
message
)
{
super
(
message
);
error
=
new
ValidationError
(
id
,
message
);
}
/**
* Get the underlying ValidationError for this exception.
* @return The ValidationError causing this exception.
*/
public
ValidationError
getError
()
{
return
error
;
}
}
modules/misc/src/misc/DamageType.java
0 → 100755
View file @
342fea6f
package
misc
;
import
rescuecore2.config.Config
;
import
java.util.Random
;
import
org.uncommons.maths.random.GaussianGenerator
;
import
org.uncommons.maths.number.NumberGenerator
;
/**
Container for information about different damage types.
*/
/*
* Implementation of Refuge Bed Capacity
* @author Farshid Faraji
* May 2020 During Covid-19 :-)))
* */
public
class
DamageType
{
private
String
type
;
private
double
k
;
private
double
l
;
private
NumberGenerator
<
Double
>
noise
;
private
double
damage
;
/**
Construct a DamageType.
@param type The name of this type.
@param config The system configuration.
@param Random sequence proprietary.
*/
public
DamageType
(
String
type
,
Config
config
,
Random
random
)
{
this
.
type
=
type
;
k
=
config
.
getFloatValue
(
"misc.injury."
+
type
+
".k"
);
l
=
config
.
getFloatValue
(
"misc.injury."
+
type
+
".l"
);
double
mean
=
config
.
getFloatValue
(
"misc.injury."
+
type
+
".noise.mean"
);
double
sd
=
config
.
getFloatValue
(
"misc.injury."
+
type
+
".noise.sd"
);
noise
=
new
GaussianGenerator
(
mean
,
sd
,
random
);
damage
=
0
;
}
/**
Get the type name.
@return The type name.
*/
public
String
getType
()
{
return
type
;
}
/**
Compute damage progression for this type.
@return The new damage.
*/
public
double
progress
()
{
if
(
damage
<=
0
)
{
return
damage
;
}
double
n
=
noise
.
nextValue
();
damage
=
damage
+
(
k
*
damage
*
damage
)
+
l
+
n
;
return
damage
;
}
public
double
progressInRefuge
()
{
if
(
damage
<=
0
)
{
return
damage
;
}
double
n
=
noise
.
nextValue
();
damage
=
damage
-
(
k
*
damage
*
damage
)
-
l
-
(
2
*
n
);
return
damage
;
}
/**
Get the current damage.
@return The current damage.
*/
public
double
getDamage
()
{
return
damage
;
}
/**
Set the current damage.
@param d The current damage.
*/
public
void
setDamage
(
double
d
)
{
damage
=
d
;
}
/**
Add some damage.
@param d The amount to add.
*/
public
void
addDamage
(
double
d
)
{
damage
+=
d
;
}
}
modules/misc/src/misc/HumanAttributes.java
0 → 100755
View file @
342fea6f
package
misc
;
import
rescuecore2.config.Config
;
import
rescuecore2.worldmodel.EntityID
;
import
rescuecore2.standard.entities.Human
;
import
java.util.Random
;
/**
Class for holding information about humans.
*/
/*
* Implementation of Refuge Bed Capacity
* @author Farshid Faraji
* May 2020 During Covid-19 :-)))
* */
public
class
HumanAttributes
{
private
Human
human
;
private
EntityID
id
;
private
DamageType
damageFire
;
private
DamageType
damageCollapse
;
private
DamageType
damageBury
;
private
Random
random
;
/**
Construct a HumanAttributes object that wraps a Human.
@param h The Human to wrap.
@param config The system configuration.
*/
public
HumanAttributes
(
Human
h
,
Config
config
)
{
this
.
human
=
h
;
this
.
id
=
h
.
getID
();
// Generate Random for each Human
this
.
random
=
new
Random
(
config
.
getRandom
().
nextLong
());
damageFire
=
new
DamageType
(
"fire"
,
config
,
random
);
damageCollapse
=
new
DamageType
(
"collapse"
,
config
,
random
);
damageBury
=
new
DamageType
(
"bury"
,
config
,
random
);
}
/**
Get the ID of the wrapped human.
@return The human ID.
*/
public
EntityID
getID
()
{
return
id
;
}
/**
Get the wrapped human.
@return The wrapped human.
*/
public
Human
getHuman
()
{
return
human
;
}
/**
Get the random sequence of the wrapped human.
@return The random sequence.
*/
public
Random
getRandom
(){
return
random
;
}
/**
Add some collapse damage.
@param d The amount of damage to add.
*/
public
void
addCollapseDamage
(
double
d
)
{
damageCollapse
.
addDamage
(
d
);
}
/**
Get the amount of collapse damage this human has.
@return The amount of collapse damage.
*/
public
double
getCollapseDamage
()
{
return
damageCollapse
.
getDamage
();
}
/**
Set the amount of collapse damage this human has.
@param d The new collapse damage.
*/
public
void
setCollapseDamage
(
double
d
)
{
damageCollapse
.
setDamage
(
d
);
}
/**
Add some buriedness damage.
@param d The amount of damage to add.
*/
public
void
addBuriednessDamage
(
double
d
)
{
damageBury
.
addDamage
(
d
);
}
/**
Get the amount of buriedness damage this human has.
@return The amount of buriedness damage.
*/
public
double
getBuriednessDamage
()
{
return
damageBury
.
getDamage
();
}
/**
Set the amount of buriedness damage this human has.
@param d The new buriedness damage.
*/
public
void
setBuriednessDamage
(
double
d
)
{
damageBury
.
setDamage
(
d
);
}
/**
Add some fire damage.
@param d The amount of damage to add.
*/
public
void
addFireDamage
(
double
d
)
{
damageFire
.
addDamage
(
d
);
}
/**
Get the amount of fire damage this human has.
@return The amount of fire damage.
*/
public
double
getFireDamage
()
{
return
damageFire
.
getDamage
();
}
/**
Set the amount of fire damage this human has.
@param d The new fire damage.
*/
public
void
setFireDamage
(
double
d
)
{
damageFire
.
setDamage
(
d
);
}
/**
Get the total damage of this human, rounded to the nearest integer.
@return The total damage.
*/
public
int
getTotalDamage
()
{
return
(
int
)
Math
.
round
(
damageCollapse
.
getDamage
()
+
damageFire
.
getDamage
()
+
damageBury
.
getDamage
());
}
/**
Progress all damage types.
*/
public
void
progressDamage
()
{
damageCollapse
.
progress
();
damageFire
.
progress
();
damageBury
.
progress
();
}
public
void
progressDamageInRefuge
()
{
//int damage = getTotalDamage();
damageCollapse
.
progressInRefuge
();
damageFire
.
progressInRefuge
();
damageBury
.
progressInRefuge
();
}
/**
Clear all damage.
*/
public
void
clearDamage
()
{
damageCollapse
.
setDamage
(
0
);
damageBury
.
setDamage
(
0
);
damageFire
.
setDamage
(
0
);
}
}
Prev
1
…
9
10
11
12
13
14
15
16
17
…
21
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment