Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
CityDoctor
CityDoctor2
Commits
c67a5961
Commit
c67a5961
authored
Jan 09, 2026
by
Numanoglu
Browse files
Bring over AABB bht work (model + validation + healer tests) from cf200f0
parent
8536ec35
Pipeline
#12312
failed with stage
in 1 minute and 41 seconds
Changes
423
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
.metadata/.plugins/org.eclipse.core.resources/.history/37/d0f5b8b52699001017e0d034282fa54d
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
bht
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
healer
.
aabb
.
bht
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.*;
import
java
.
io
.
IOException
;
import
java
.
util
.*;
//
src
/
test
/
java
/.../
TestCityGmlAABB
.
java
import
java
.
net
.
URL
;
import
java
.
nio
.
file
.
Paths
;
public
class
TestCityGmlAABB
{
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"=== CityGML AABB Test ==="
);
//
---
1
)
Ask
user
which
test
case
to
run
---
Scanner
sc
=
new
Scanner
(
System
.
in
);
System
.
out
.
print
(
"Enter TestCase ID (e.g. PO_TWO_INNERS, SO_WRONG_POLY_ORIENTATION_SINGLE) "
+
"or press Enter for default: "
);
//
String
testcase
=
sc
.
nextLine
().
trim
();
//
Default
path
if
nothing
entered
//
String
path
=
TestPaths
.
PO_TWO_INNERS
;
//
default
example
/*
*
*
*
*
*
*/
//
//
DEBUG
:
relative
path
problems
String
path
=
"src/test/resources/bht/TestBuilding_SelfInt.gml"
;
//
not
just
SelfInt
errors
/*
*
TODO
:
class
Testmodel
.
getTestPath
();
getName
()
etc
.
pp
*
*
*
*/
String
id
=
sc
.
nextLine
().
trim
();
//
Default
w
ä
hlen
(
eine
deiner
Konstanten
)
String
resourcePath
=
TestPaths
.
PO_TWO_INNERS
;
if
(
!id.isEmpty()) {
try
{
//
Holt
z
.
B
.
TestPaths
.
SO_NOT_WATERTIGHT
per
Reflection
resourcePath
=
(
String
)
TestPaths
.
class
.
getField
(
id
).
get
(
null
);
}
catch
(
ReflectiveOperationException
ex
)
{
System
.
out
.
println
(
"Unknown testcase: "
+
id
+
" (using default)"
);
}
}
String
filePathForParser
=
resolveResourceOnClasspath
(
resourcePath
);
System
.
out
.
println
(
"Using file: "
+
filePathForParser
);
//
---
2
)
Load
CityGML
model
---
ValidationConfiguration
config
=
ValidationConfiguration
.
loadStandardValidationConfig
();
//
TODO
:
import
package
CityDoctorModel
model
=
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
TestUtil
.
loadCityModel
(
filePathForParser
,
config
);
System
.
out
.
println
(
"Model loaded successfully.
\n
"
);
List
<
Building
>
buildings
=
model
.
getBuildings
();
//
---
3
)
Menu
:
choose
granularity
---
System
.
out
.
println
(
"
\n
Choose granularity:"
);
System
.
out
.
println
(
" 1) Polygon-level (broad-phase)"
);
System
.
out
.
println
(
" 2) Ring-level (EXTERIOR)"
);
System
.
out
.
println
(
" 3) Ring-level (INTERIOR)"
);
System
.
out
.
println
(
" 4) Vertex-level (fine-phase)"
);
System
.
out
.
println
(
" 5) All of the above"
);
System
.
out
.
print
(
"Your choice [1-5]: "
);
int
choice
=
readChoice
(
sc
,
1
,
5
);
boolean
doPolygon
=
(
choice
==
1
||
choice
==
5
);
boolean
doExtRing
=
(
choice
==
2
||
choice
==
5
);
boolean
doIntRing
=
(
choice
==
3
||
choice
==
5
);
boolean
doVertex
=
(
choice
==
4
||
choice
==
5
);
//
---
4
)
Run
the
selected
modes
---
if
(
doPolygon
)
runPolygonMode
(
buildings
);
if
(
doExtRing
)
runRingMode
(
buildings
,
true
);
if
(
doIntRing
)
runRingMode
(
buildings
,
false
);
if
(
doVertex
)
runVertexMode
(
buildings
);
System
.
out
.
println
(
"
\n
=== Done ==="
);
}
//
----------
Modes
----------
private
static
void
runPolygonMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Polygon-level AABB (broad-phase)"
);
Set
<
ConcretePolygon
>
polys
=
collectAllPolygons
(
buildings
);
AABBTree
<
ConcretePolygon
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
polys
),
AABBUtils
::
getAABB
);
System
.
out
.
println
(
"Polygons: "
+
polys
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runRingMode
(
List
<
Building
>
buildings
,
boolean
exterior
)
{
String
label
=
exterior
?
"EXTERIOR"
:
"INTERIOR"
;
System
.
out
.
println
(
"
\n
> Ring-level AABB ("
+
label
+
")"
);
Set
<
LinearRing
>
rings
=
exterior
?
collectExteriorRings
(
buildings
)
:
collectInteriorRings
(
buildings
);
AABBTree
<
LinearRing
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
rings
),
AABBUtils
::
computeAABBFromRing
);
System
.
out
.
println
(
label
+
" rings: "
+
rings
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runVertexMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Vertex-level AABB (fine-phase)"
);
Set
<
Vertex
>
verts
=
collectAllVertices
(
buildings
);
AABBTree
<
Vertex
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
verts
),
AABBUtils
::
computeAABBFromVertex
);
System
.
out
.
println
(
"Vertices: "
+
verts
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
//
----------
Collectors
----------
/**
Collects
all
ConcretePolygons
(
unique
)
via
visitor
.
*/
private
static
Set
<
ConcretePolygon
>
collectAllPolygons
(
List
<
Building
>
buildings
)
{
Set
<
ConcretePolygon
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
set
.
add
(
poly
.
getOriginal
());
}
});
}
return
set
;
}
/**
Collects
all
EXTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectExteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
LinearRing
ext
=
poly
.
getOriginal
().
getExteriorRing
();
if
(
ext
!= null) set.add(ext);
}
});
}
return
set
;
}
/**
Collects
all
INTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectInteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
List
<
LinearRing
>
inner
=
poly
.
getOriginal
().
getInnerRings
();
if
(
inner
!= null && !inner.isEmpty()) {
set
.
addAll
(
inner
);
}
}
});
}
return
set
;
}
/**
Collects
all
vertices
(
unique
)
from
both
exterior
and
interior
rings
.
*/
private
static
Set
<
Vertex
>
collectAllVertices
(
List
<
Building
>
buildings
)
{
Set
<
Vertex
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
ConcretePolygon
cp
=
poly
.
getOriginal
();
LinearRing
ext
=
cp
.
getExteriorRing
();
if
(
ext
!= null) set.addAll(ext.getVertices());
List
<
LinearRing
>
inner
=
cp
.
getInnerRings
();
if
(
inner
!= null) {
for
(
LinearRing
lr
:
inner
)
set
.
addAll
(
lr
.
getVertices
());
}
}
});
}
return
set
;
}
//
----------
Utils
----------
/*
Helper
method
reads
choice
of
the
user
*/
private
static
int
readChoice
(
Scanner
sc
,
int
min
,
int
max
)
{
while
(
true
)
{
String
s
=
sc
.
nextLine
().
trim
();
try
{
int
v
=
Integer
.
parseInt
(
s
);
if
(
v
>=
min
&&
v
<=
max
)
return
v
;
}
catch
(
NumberFormatException
ignored
)
{}
System
.
out
.
print
(
"Please enter a number between "
+
min
+
" and "
+
max
+
": "
);
}
}
/*
Helper
method
Pathfinder
*/
private
static
String
resolveResourceOnClasspath
(
String
resourcePath
)
{
String
rp
=
normalizeResourcePath
(
resourcePath
);
//
1
)
Klassenpfad
via
Class
.
getResource
URL
url
=
TestCityGmlAABB
.
class
.
getResource
(
rp
);
//
2
)
Klassenpfad
via
Context
-
ClassLoader
if
(
url
==
null
)
{
ClassLoader
cl
=
Thread
.
currentThread
().
getContextClassLoader
();
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
url
=
cl
.
getResource
(
noSlash
);
}
//
3
)
Wenn
gefunden
:
in
Pfad
umwandeln
if
(
url
!= null) {
try
{
return
Paths
.
get
(
url
.
toURI
()).
toString
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Konnte Resource-URI nicht auflösen: "
+
url
,
e
);
}
}
//
4
)
Fallbacks
:
Projekt
-
relative
Kandidaten
pr
ü
fen
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
String
[]
candidates
=
{
"src/test/resources/"
+
noSlash
,
"src/main/resources/"
+
noSlash
,
resourcePath
//
falls
bereits
ein
echter
Dateipfad
ü
bergeben
wurde
};
for
(
String
cand
:
candidates
)
{
java
.
nio
.
file
.
Path
p
=
java
.
nio
.
file
.
Paths
.
get
(
cand
);
if
(
java
.
nio
.
file
.
Files
.
exists
(
p
))
{
return
p
.
toAbsolutePath
().
toString
();
}
}
throw
new
IllegalArgumentException
(
"Pap:Resource nicht im Klassenpfad gefunden: "
+
resourcePath
+
" (versucht als: "
+
rp
+
")"
);
}
//
F
Ü
R
ALLE
F
Ä
LLE
Corrections
via
string
manip
GERADE
ws
REDUNDAD
private
static
String
normalizeResourcePath
(
String
path
)
{
String
p
=
path
.
replace
(
'\\'
,
'/'
);
//
Quellordner
-
Pr
ä
fixe
entfernen
,
falls
mit
ü
bergeben
if
(
p
.
startsWith
(
"src/test/resources/"
))
{
p
=
p
.
substring
(
"src/test/resources/"
.
length
());
}
else
if
(
p
.
startsWith
(
"src/main/resources/"
))
{
p
=
p
.
substring
(
"src/main/resources/"
.
length
());
}
//
F
ü
r
Class
.
getResource
:
f
ü
hrenden
Slash
setzen
if
(
!p.startsWith("/")) p = "/" + p;
return
p
;
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/43/002745ad7cea0010125ad88dcc4485e5
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
Comparator
;
import
java
.
util
.
List
;
import
java
.
util
.
function
.
Function
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
public
class
BVHStructures
{
/**
*
Generic
node
used
in
BVH
tree
*/
public
static
class
Node
<
E
>
{
public
List
<
Node
<
E
>>
children
=
new
ArrayList
<>();
public
AABB
aabb
;
public
E
element
;
public
Node
()
{
//
Anchor
-
3
DPoint
given
by
means
of
its
coords
double
zeroX
=
0
;
double
zeroY
=
0
;
double
zeroZ
=
0
;
this
.
aabb
=
new
AABB
(
zeroX
,
zeroY
,
zeroZ
,
zeroX
,
zeroY
,
zeroZ
);
this
.
element
=
null
;
}
public
boolean
isLeaf
()
{
return
children
.
isEmpty
()
&&
element
!= null;
}
}
/**
*
Represents
a
pair
of
geometry
lists
resulting
from
a
split
*/
public
static
class
SplitStruct
<
E
>
{
public
List
<
E
>
list1
=
new
ArrayList
<>();
public
List
<
E
>
list2
=
new
ArrayList
<>();
}
/**
*
Stack
element
used
during
recursive
BVH
tree
construction
*/
public
static
class
StackElement
<
E
>
{
public
int
level
;
public
Node
<
E
>
node
;
public
List
<
E
>
elements
=
new
ArrayList
<>();
public
StackElement
(
int
level
,
Node
<
E
>
node
,
List
<
E
>
elements
)
{
this
.
level
=
level
;
this
.
node
=
node
;
this
.
elements
=
elements
;
}
}
/**
*
Pair
of
AABBs
and
polygon
lists
used
during
splitting
*/
public
static
class
SplitStructB
<
E
>
{
public
AABB
box1
,
box2
;
public
List
<
E
>
list1
=
new
ArrayList
<>();
public
List
<
E
>
list2
=
new
ArrayList
<>();
}
/**
*
Generic
array
-
based
BVH
node
.
*
Stores
an
AABB
and
an
associated
element
(
typically
a
leaf
object
).
*/
public
static
class
NodeB_Ar
<
E
>
{
public
AABB
aabb
;
public
E
element
;
public
NodeB_Ar
(
AABB
aabb
,
E
element
)
{
this
.
aabb
=
aabb
;
this
.
element
=
element
;
}
}
/**
*
Stack
element
used
for
array
-
based
BVH
construction
*/
public
static
class
StackElementAr
{
public
int
arrayIndex
;
public
int
level
;
public
AABB
aabb
;
public
List
<
ConcretePolygon
>
polygons
=
new
ArrayList
<>();
public
StackElementAr
(
int
arrayIndex
,
int
level
,
AABB
aabb
,
List
<
ConcretePolygon
>
polygons
)
{
this
.
arrayIndex
=
arrayIndex
;
this
.
level
=
level
;
this
.
aabb
=
aabb
;
this
.
polygons
=
polygons
;
}
}
/**
*
Creates
a
comparator
to
sort
elements
by
their
AABB
center
X
coordinate
.
*/
public
static
<
E
>
Comparator
<
E
>
compareCenterX
(
Function
<
E
,
AABB
>
aabbGetter
)
{
return
Comparator
.
comparingDouble
(
e
->
{
AABB
box
=
aabbGetter
.
apply
(
e
);
return
(
box
.
getMinX
()
+
box
.
getMaxX
())
/
2.0
;
});
}
/**
*
Creates
a
comparator
to
sort
elements
by
their
AABB
center
Y
coordinate
.
*/
public
static
<
E
>
Comparator
<
E
>
compareCenterY
(
Function
<
E
,
AABB
>
aabbGetter
)
{
return
Comparator
.
comparingDouble
(
e
->
{
AABB
box
=
aabbGetter
.
apply
(
e
);
return
(
box
.
getMinY
()
+
box
.
getMaxY
())
/
2.0
;
});
}
/**
*
Creates
a
comparator
to
sort
elements
by
their
AABB
center
Z
coordinate
.
*/
public
static
<
E
>
Comparator
<
E
>
compareCenterZ
(
Function
<
E
,
AABB
>
aabbGetter
)
{
return
Comparator
.
comparingDouble
(
e
->
{
AABB
box
=
aabbGetter
.
apply
(
e
);
return
(
box
.
getMinZ
()
+
box
.
getMaxZ
())
/
2.0
;
});
}
/**
*
Sorts
elements
by
AABB
center
along
specified
axis
.
*
*
@
param
elements
the
list
to
sort
*
@
param
axis
0
=
X
,
1
=
Y
,
2
=
Z
*
@
param
aabbGetter
a
function
to
extract
the
AABB
from
an
element
*/
public
static
<
E
>
void
sortElementsByCenterAxis
(
List
<
E
>
elements
,
int
axis
,
Function
<
E
,
AABB
>
aabbGetter
)
{
switch
(
axis
)
{
case
0
->
elements
.
sort
(
compareCenterX
(
aabbGetter
));
case
1
->
elements
.
sort
(
compareCenterY
(
aabbGetter
));
case
2
->
elements
.
sort
(
compareCenterZ
(
aabbGetter
));
default
->
throw
new
IllegalArgumentException
(
"Invalid axis index: "
+
axis
);
}
}
/**
*
Returns
the
index
of
the
longest
axis
in
the
AABB
*/
public
static
int
findLongestAxis
(
AABB
aabb
)
{
double
x
=
aabb
.
getMaxX
()
-
aabb
.
getMinX
();
double
y
=
aabb
.
getMaxY
()
-
aabb
.
getMinY
();
double
z
=
aabb
.
getMaxZ
()
-
aabb
.
getMinZ
();
if
(
x
>
y
&&
x
>
z
)
return
0
;
if
(
y
>
x
&&
y
>
z
)
return
1
;
return
2
;
}
/**
*
SOON
OBSOLETE
:
Generic
Version
all
ready
exists
*
Calculates
the
smallest
AABB
that
encloses
all
given
polygons
*/
public
static
AABB
getAggregateAABB
(
List
<
ConcretePolygon
>
polygons
)
{
if
(
polygons
.
size
()
==
1
)
{
return
AABBUtils
.
getAABB
(
polygons
.
get
(
0
));
}
double
minX
=
Double
.
MAX_VALUE
,
minY
=
Double
.
MAX_VALUE
,
minZ
=
Double
.
MAX_VALUE
;
double
maxX
=
-
Double
.
MAX_VALUE
,
maxY
=
-
Double
.
MAX_VALUE
,
maxZ
=
-
Double
.
MAX_VALUE
;
for
(
ConcretePolygon
p
:
polygons
)
{
AABB
aabb
=
AABBUtils
.
getAABB
(
p
);
minX
=
Math
.
min
(
minX
,
aabb
.
getMinX
());
minY
=
Math
.
min
(
minY
,
aabb
.
getMinY
());
minZ
=
Math
.
min
(
minZ
,
aabb
.
getMinZ
());
maxX
=
Math
.
max
(
maxX
,
aabb
.
getMaxX
());
maxY
=
Math
.
max
(
maxY
,
aabb
.
getMaxY
());
maxZ
=
Math
.
max
(
maxZ
,
aabb
.
getMaxZ
());
}
return
new
AABB
(
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
);
}
public
static
<
E
>
AABB
getAggregateAABB
(
List
<
E
>
elements
,
Function
<
E
,
AABB
>
aabbFunc
)
{
double
minX
=
Double
.
POSITIVE_INFINITY
,
minY
=
Double
.
POSITIVE_INFINITY
,
minZ
=
Double
.
POSITIVE_INFINITY
;
double
maxX
=
Double
.
NEGATIVE_INFINITY
,
maxY
=
Double
.
NEGATIVE_INFINITY
,
maxZ
=
Double
.
NEGATIVE_INFINITY
;
for
(
E
e
:
elements
)
{
AABB
aabb
=
aabbFunc
.
apply
(
e
);
minX
=
Math
.
min
(
minX
,
aabb
.
getMinX
());
minY
=
Math
.
min
(
minY
,
aabb
.
getMinY
());
minZ
=
Math
.
min
(
minZ
,
aabb
.
getMinZ
());
maxX
=
Math
.
max
(
maxX
,
aabb
.
getMaxX
());
maxY
=
Math
.
max
(
maxY
,
aabb
.
getMaxY
());
maxZ
=
Math
.
max
(
maxZ
,
aabb
.
getMaxZ
());
}
return
new
AABB
(
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
);
}
}
\ No newline at end of file
.metadata/.plugins/org.eclipse.core.resources/.history/4f/002aed923899001017e0d034282fa54d
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
bht
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
healer
.
aabb
.
bht
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.*;
import
java
.
io
.
IOException
;
import
java
.
util
.*;
//
src
/
test
/
java
/.../
TestCityGmlAABB
.
java
import
java
.
net
.
URL
;
import
java
.
nio
.
file
.
Paths
;
public
class
TestCityGmlAABB
{
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"=== CityGML AABB Test ==="
);
//
---
1
)
Ask
user
which
test
case
to
run
---
Scanner
sc
=
new
Scanner
(
System
.
in
);
System
.
out
.
print
(
"Enter TestCase ID (e.g. PO_TWO_INNERS, SO_WRONG_POLY_ORIENTATION_SINGLE) "
+
"or press Enter for default: "
);
String
id
=
sc
.
nextLine
().
trim
();
//
Default
w
ä
hlen
(
eine
deiner
Konstanten
)
String
resourcePath
=
TestPaths
.
PO_TWO_INNERS
;
if
(
!id.isEmpty()) {
try
{
//
Holt
z
.
B
.
TestPaths
.
SO_NOT_WATERTIGHT
per
Reflection
resourcePath
=
(
String
)
TestPaths
.
class
.
getField
(
id
).
get
(
null
);
}
catch
(
ReflectiveOperationException
ex
)
{
System
.
out
.
println
(
"Unknown testcase: "
+
id
+
" (using default)"
);
}
}
String
filePathForParser
=
resolveResourceOnClasspath
(
resourcePath
);
System
.
out
.
println
(
"Using file: "
+
filePathForParser
);
//
---
2
)
Load
CityGML
model
---
ValidationConfiguration
config
=
ValidationConfiguration
.
loadStandardValidationConfig
();
//
TODO
:
Study
class
model
CityDoctorModel
model
=
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
TestUtil
.
loadCityModel
(
filePathForParser
,
config
);
System
.
out
.
println
(
"Model loaded successfully.
\n
"
);
List
<
Building
>
buildings
=
model
.
getBuildings
();
//
---
3
)
Menu
:
choose
granularity
---
System
.
out
.
println
(
"
\n
Choose granularity:"
);
System
.
out
.
println
(
" 1) Polygon-level (broad-phase)"
);
System
.
out
.
println
(
" 2) Ring-level (EXTERIOR)"
);
System
.
out
.
println
(
" 3) Ring-level (INTERIOR)"
);
System
.
out
.
println
(
" 4) Vertex-level (fine-phase)"
);
System
.
out
.
println
(
" 5) All of the above"
);
System
.
out
.
print
(
"Your choice [1-5]: "
);
int
choice
=
readChoice
(
sc
,
1
,
5
);
boolean
doPolygon
=
(
choice
==
1
||
choice
==
5
);
boolean
doExtRing
=
(
choice
==
2
||
choice
==
5
);
boolean
doIntRing
=
(
choice
==
3
||
choice
==
5
);
boolean
doVertex
=
(
choice
==
4
||
choice
==
5
);
//
---
4
)
Run
the
selected
modes
---
if
(
doPolygon
)
runPolygonMode
(
buildings
);
if
(
doExtRing
)
runRingMode
(
buildings
,
true
);
if
(
doIntRing
)
runRingMode
(
buildings
,
false
);
if
(
doVertex
)
runVertexMode
(
buildings
);
System
.
out
.
println
(
"
\n
=== Done ==="
);
}
//
----------
Modes
----------
private
static
void
runPolygonMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Polygon-level AABB (broad-phase)"
);
Set
<
ConcretePolygon
>
polys
=
collectAllPolygons
(
buildings
);
AABBTree
<
ConcretePolygon
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
polys
),
AABBUtils
::
getAABB
);
System
.
out
.
println
(
"Polygons: "
+
polys
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runRingMode
(
List
<
Building
>
buildings
,
boolean
exterior
)
{
String
label
=
exterior
?
"EXTERIOR"
:
"INTERIOR"
;
System
.
out
.
println
(
"
\n
> Ring-level AABB ("
+
label
+
")"
);
Set
<
LinearRing
>
rings
=
exterior
?
collectExteriorRings
(
buildings
)
:
collectInteriorRings
(
buildings
);
AABBTree
<
LinearRing
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
rings
),
AABBUtils
::
computeAABBFromRing
);
System
.
out
.
println
(
label
+
" rings: "
+
rings
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runVertexMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Vertex-level AABB (fine-phase)"
);
Set
<
Vertex
>
verts
=
collectAllVertices
(
buildings
);
AABBTree
<
Vertex
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
verts
),
AABBUtils
::
computeAABBFromVertex
);
System
.
out
.
println
(
"Vertices: "
+
verts
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
//
----------
Collectors
----------
/**
Collects
all
ConcretePolygons
(
unique
)
via
visitor
.
*/
private
static
Set
<
ConcretePolygon
>
collectAllPolygons
(
List
<
Building
>
buildings
)
{
Set
<
ConcretePolygon
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
set
.
add
(
poly
.
getOriginal
());
}
});
}
return
set
;
}
/**
Collects
all
EXTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectExteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
LinearRing
ext
=
poly
.
getOriginal
().
getExteriorRing
();
if
(
ext
!= null) set.add(ext);
}
});
}
return
set
;
}
/**
Collects
all
INTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectInteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
List
<
LinearRing
>
inner
=
poly
.
getOriginal
().
getInnerRings
();
if
(
inner
!= null && !inner.isEmpty()) {
set
.
addAll
(
inner
);
}
}
});
}
return
set
;
}
/**
Collects
all
vertices
(
unique
)
from
both
exterior
and
interior
rings
.
*/
private
static
Set
<
Vertex
>
collectAllVertices
(
List
<
Building
>
buildings
)
{
Set
<
Vertex
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
ConcretePolygon
cp
=
poly
.
getOriginal
();
LinearRing
ext
=
cp
.
getExteriorRing
();
if
(
ext
!= null) set.addAll(ext.getVertices());
List
<
LinearRing
>
inner
=
cp
.
getInnerRings
();
if
(
inner
!= null) {
for
(
LinearRing
lr
:
inner
)
set
.
addAll
(
lr
.
getVertices
());
}
}
});
}
return
set
;
}
//
----------
Utils
----------
/*
Helper
method
reads
choice
of
the
user
*/
private
static
int
readChoice
(
Scanner
sc
,
int
min
,
int
max
)
{
while
(
true
)
{
String
s
=
sc
.
nextLine
().
trim
();
try
{
int
v
=
Integer
.
parseInt
(
s
);
if
(
v
>=
min
&&
v
<=
max
)
return
v
;
}
catch
(
NumberFormatException
ignored
)
{}
System
.
out
.
print
(
"Please enter a number between "
+
min
+
" and "
+
max
+
": "
);
}
}
/*
Helper
method
Pathfinder
*/
private
static
String
resolveResourceOnClasspath
(
String
resourcePath
)
{
String
rp
=
normalizeResourcePath
(
resourcePath
);
//
1
)
Klassenpfad
via
Class
.
getResource
URL
url
=
TestCityGmlAABB
.
class
.
getResource
(
rp
);
//
2
)
Klassenpfad
via
Context
-
ClassLoader
:
if
(
url
==
null
)
{
ClassLoader
cl
=
Thread
.
currentThread
().
getContextClassLoader
();
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
url
=
cl
.
getResource
(
noSlash
);
}
//
3
)
Wenn
gefunden
:
in
Pfad
umwandeln
if
(
url
!= null) {
try
{
return
Paths
.
get
(
url
.
toURI
()).
toString
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Konnte Resource-URI nicht auflösen: "
+
url
,
e
);
}
}
//
4
)
Fallbacks
:
Projekt
-
relative
Kandidaten
pr
ü
fen
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
String
[]
candidates
=
{
"src/test/resources/"
+
noSlash
,
"src/main/resources/"
+
noSlash
,
resourcePath
//
falls
bereits
ein
echter
Dateipfad
ü
bergeben
wurde
};
for
(
String
cand
:
candidates
)
{
java
.
nio
.
file
.
Path
p
=
java
.
nio
.
file
.
Paths
.
get
(
cand
);
if
(
java
.
nio
.
file
.
Files
.
exists
(
p
))
{
return
p
.
toAbsolutePath
().
toString
();
}
}
throw
new
IllegalArgumentException
(
"Resource nicht im Klassenpfad gefunden: "
+
resourcePath
+
" (versucht als: "
+
rp
+
")"
);
}
//
F
Ü
R
ALLE
F
Ä
LLE
zur
Zeit
REDUNDAD
private
static
String
normalizeResourcePath
(
String
path
)
{
String
p
=
path
.
replace
(
'\\'
,
'/'
);
//
Quellordner
-
Pr
ä
fixe
entfernen
,
falls
mit
ü
bergeben
if
(
p
.
startsWith
(
"src/test/resources/"
))
{
p
=
p
.
substring
(
"src/test/resources/"
.
length
());
}
else
if
(
p
.
startsWith
(
"src/main/resources/"
))
{
p
=
p
.
substring
(
"src/main/resources/"
.
length
());
}
//
F
ü
r
Class
.
getResource
:
f
ü
hrenden
Slash
setzen
if
(
!p.startsWith("/")) p = "/" + p;
return
p
;
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/4f/80969c9652e900101245d5e14ea95888
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
import
java
.
io
.
IOException
;
//
import
java
.
io
.
InputStream
;
//
new
import
java
.
util
.
ArrayList
;
import
java
.
util
.
HashMap
;
import
java
.
util
.
HashSet
;
import
java
.
util
.
List
;
import
java
.
util
.
Map
;
import
java
.
util
.
Set
;
import
java
.
util
.
Scanner
;
//
new
import
org
.
junit
.
Test
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckableUtilsVisitor
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckableVisitor
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Check
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
ValidationConfiguration
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Building
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
CityDoctorModel
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
CityObject
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Geometry
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Polygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
.
LinearRingType
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Vertex
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
exceptions
.
CityDoctorWriteException
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
TestUtil
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
CityGmlParseException
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
InvalidGmlFileException
;
public
class
TestExample
{
//
InputStream
inStream
=
getClass
().
getClassLoader
().
getResourceAsStream
(
"SimpleSolid_SrefBS.gml"
);
//
new
//
//
if
you
want
to
load
a
src
/
test
/
resources
file
out
of
a
different
package
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"Start TestExample...
\n
"
);
//
new
//
String
path
=
args
[
0
];
//
String
path
=
"src/test/resources/SimpleSolid_SrefBS.gml"
;
//
new
valid
LoD2
model
//
String
path
=
"src/test/resources/TestBuilding1.gml"
;
//
new
block
model
//
new
valid
model
with
inner
rings
String
path
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml"
;
//
too
big
,
main
gets
terminated
//
String
path
=
"src/test/resources/bht/KreishausFeuerwache.gml"
;
//
String
path
=
"src/test/resources/bht/TestBuilding_SelfInt.gml"
;
ValidationConfiguration
config
=
ValidationConfiguration
.
loadStandardValidationConfig
();
CityDoctorModel
model
=
TestUtil
.
loadCityModel
(
path
,
config
);
System
.
out
.
println
(
"
\n
Model has been loaded..."
);
//
new
//
visitor
//
filter
duplicate
polygons
out
Set
<
ConcretePolygon
>
allBuildingPolygons
=
new
HashSet
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
public
void
check
(
Polygon
poly
)
{
allBuildingPolygons
.
add
(
poly
.
getOriginal
());
}
});
}
System
.
out
.
println
(
"
\n
Polygons via visitor:"
+
allBuildingPolygons
);
//
new
//
//
for
loop
List
<
Polygon
>
allBuildingPolygons2
=
new
ArrayList
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
for
(
Geometry
geom
:
b
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
allBuildingPolygons2
.
add
(
p
);
allBuildingPolygons2
.
add
(
p
.
getOriginal
());
//
new
}
}
}
System
.
out
.
println
(
"
\n
Polygon List:"
+
allBuildingPolygons2
);
//
new
//
new
:
LinearRings
//
visitor
//
filter
duplicate
linear
rings
out
Set
<
LinearRing
>
allBuildingLinearRings
=
new
HashSet
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
public
void
check
(
LinearRing
ring
)
{
allBuildingLinearRings
.
add
(
ring
);
}
});
}
System
.
out
.
println
(
"
\n
LinearRings via visitor:"
+
allBuildingLinearRings
);
//
new
//
new
:
ExteriorRings
//
visitor
//
filter
duplicate
exterior
rings
out
Set
<
LinearRing
>
allBuildingExteriorRings
=
new
HashSet
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
public
void
check
(
LinearRing
ring
)
{
allBuildingExteriorRings
.
add
(
ring
.
getParent
().
getExteriorRing
());
//
ACHTUNG
getParent
}
});
}
System
.
out
.
println
(
"
\n
ExteriorRings via visitor:"
+
allBuildingExteriorRings
);
//
new
//
//
new
:
ExteriorRings
(
List
)
//
//
for
loop
//
List
<
LinearRing
>
allBuildingExteriorRings2
=
new
ArrayList
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
for
(
Geometry
geom
:
b
.
getGeometries
())
{
//
for
(
Polygon
p
:
geom
.
getPolygons
())
{
//
allBuildingExteriorRings2
.
add
(
p
.
getOriginal
().
getExteriorRing
());
//
}
//
}
//
}
//
System
.
out
.
println
(
"
\n
ExteriorRing List:"
+
allBuildingExteriorRings2
);
//
new
//
new
:
InnerRings
//
visitor
//
filter
duplicate
inner
rings
out
Set
<
LinearRing
>
allBuildingInnerRings
=
new
HashSet
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
public
void
check
(
Polygon
poly
)
{
allBuildingInnerRings
.
addAll
(
poly
.
getOriginal
().
getInnerRings
());//
ACHTUNG
getOriginal
}
});
}
System
.
out
.
println
(
"
\n
InnerRings via visitor:"
+
allBuildingInnerRings
);
//
new
//
//
new
:
InnerRings
(
List
)
//
//
for
loop
//
List
<
LinearRing
>
allBuildingInnerRings2
=
new
ArrayList
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
for
(
Geometry
geom
:
b
.
getGeometries
())
{
//
for
(
Polygon
p
:
geom
.
getPolygons
())
{
//
for
(
LinearRing
lr
:
p
.
getInnerRings
())
{
//
allBuildingInnerRings2
.
add
(
lr
);
//
}
//
//
}
//
}
//
}
//
System
.
out
.
println
(
"
\n
InnerRing List:"
+
allBuildingInnerRings2
);
//
new
//
//
get
Vertices
for
LinearRing
,
ExteriorRing
and
InteriorRing
//
//
new
:
LinearRingVertices
//
//
visitor
//
//
filter
duplicate
linear
rings
out
//
Set
<
Vertex
>
allBuildingLinearRingVertices
=
new
HashSet
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
b
.
accept
(
new
CheckableUtilsVisitor
()
{
//
public
void
check
(
LinearRing
ring
)
{
//
allBuildingLinearRingVertices
.
addAll
(
ring
.
getVertices
());
//
}
//
//
});
//
}
//
System
.
out
.
println
(
"
\n
LinearRingVertices via visitor:"
+
allBuildingLinearRingVertices
);
//
new
//
//
new
:
ExteriorRingVertices
//
//
visitor
//
//
filter
duplicate
exterior
rings
out
//
Set
<
Vertex
>
allBuildingExteriorRingVertices
=
new
HashSet
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
b
.
accept
(
new
CheckableUtilsVisitor
()
{
//
public
void
check
(
LinearRing
ring
)
{
//
allBuildingExteriorRingVertices
.
addAll
(
ring
.
getParent
().
getOriginal
().
getExteriorRing
().
getVertices
());
//
}
//
//
});
//
}
//
System
.
out
.
println
(
"
\n
ExteriorRingVertices via visitor:"
+
allBuildingExteriorRingVertices
);
//
new
//
//
new
:
ExteriorRingVertices
(
List
)
//
//
for
loop
//
List
<
Vertex
>
allBuildingExteriorRingVertices2
=
new
ArrayList
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
for
(
Geometry
geom
:
b
.
getGeometries
())
{
//
for
(
Polygon
p
:
geom
.
getPolygons
())
{
//
for
(
Vertex
v
:
p
.
getOriginal
().
getExteriorRing
().
getVertices
())
{
//
allBuildingExteriorRingVertices2
.
add
(
v
);
//
}
//
}
//
}
//
}
//
System
.
out
.
println
(
"
\n
ExteriorRingVertices List:"
+
allBuildingExteriorRingVertices2
);
//
new
//
//
new
:
InnerRingVertices
//
//
visitor
//
//
filter
duplicate
linear
vertices
out
//
Set
<
Vertex
>
allBuildingInnerRingVertices
=
new
HashSet
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
b
.
accept
(
new
CheckableUtilsVisitor
()
{
//
public
void
check
(
Polygon
poly
)
{
//
poly
.
getOriginal
().
getInnerRings
().
forEach
(
ring
->
allBuildingInnerRingVertices
.
addAll
(
ring
.
getVertices
()));
//
}
//
});
//
}
//
System
.
out
.
println
(
"
\n
InnerRingVertices via visitor:"
+
allBuildingInnerRingVertices
);
//
new
//
//
new
:
InnerRingVertices
(
List
)
//
//
for
loop
//
List
<
Vertex
>
allInnerRingVertices2
=
new
ArrayList
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
for
(
Geometry
geom
:
b
.
getGeometries
())
{
//
for
(
Polygon
p
:
geom
.
getPolygons
())
{
//
for
(
LinearRing
lr
:
p
.
getInnerRings
())
{
//
for
(
Vertex
v
:
lr
.
getVertices
())
{
//
allInnerRingVertices2
.
add
(
v
);
//
}
//
}
//
//
}
//
}
//
}
//
System
.
out
.
println
(
"
\n
InnerRingVertices List:"
+
allInnerRingVertices2
);
//
new
//
//
TODO
:
HashMap
to
show
Ring
and
gmlId
//
Map
<
LinearRing
,
Set
<
Vertex
>>
test
=
new
HashMap
<>();
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/4f/b0813fad7cea0010125ad88dcc4485e5
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
import
java
.
io
.
PrintStream
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
List
;
/**
*
Represents
an
Axis
-
Aligned
Bounding
Box
(
AABB
)
using
six
double
values
.
*/
public
class
AABB
{
private
double
minX
,
minY
,
minZ
;
private
double
maxX
,
maxY
,
maxZ
;
/**
*
Default
constructor
initializing
to
a
zero
-
sized
box
at
origin
.
*/
/**
*
Constructs
an
AABB
from
explicit
min
and
max
coordinates
.
*/
public
AABB
(
double
minX
,
double
minY
,
double
minZ
,
double
maxX
,
double
maxY
,
double
maxZ
)
{
this
.
minX
=
Math
.
min
(
minX
,
maxX
);
this
.
minY
=
Math
.
min
(
minY
,
maxY
);
this
.
minZ
=
Math
.
min
(
minZ
,
maxZ
);
this
.
maxX
=
Math
.
max
(
minX
,
maxX
);
this
.
maxY
=
Math
.
max
(
minY
,
maxY
);
this
.
maxZ
=
Math
.
max
(
minZ
,
maxZ
);
}
public
double
getMinX
()
{
return
minX
;
}
public
double
getMinY
()
{
return
minY
;
}
public
double
getMinZ
()
{
return
minZ
;
}
public
double
getMaxX
()
{
return
maxX
;
}
public
double
getMaxY
()
{
return
maxY
;
}
public
double
getMaxZ
()
{
return
maxZ
;
}
public
double
getCenterX
()
{
return
(
minX
+
maxX
)
/
2.0
;
}
public
double
getCenterY
()
{
return
(
minY
+
maxY
)
/
2.0
;
}
public
double
getCenterZ
()
{
return
(
minZ
+
maxZ
)
/
2.0
;
}
/**
*
Returns
the
center
point
of
the
AABB
as
a
double
array
[
x
,
y
,
z
].
*
*
@
return
the
center
coordinates
*/
public
double
[]
getCenter
()
{
double
centerX
=
(
minX
+
maxX
)
/
2.0
;
double
centerY
=
(
minY
+
maxY
)
/
2.0
;
double
centerZ
=
(
minZ
+
maxZ
)
/
2.0
;
return
new
double
[]
{
centerX
,
centerY
,
centerZ
};
}
/**
*
PREMORDIAL
CHEAT
TODO
correct
!
*
Returns
the
8
corner
points
of
the
AABB
as
list
of
double
[
3
]
arrays
.
*/
public
List
<
double
[]>
getCornerPoints
()
{
List
<
double
[]>
points
=
new
ArrayList
<>(
8
);
points
.
add
(
new
double
[]{
minX
,
minY
,
minZ
});
points
.
add
(
new
double
[]{
minX
,
minY
,
maxZ
});
points
.
add
(
new
double
[]{
minX
,
maxY
,
minZ
});
points
.
add
(
new
double
[]{
minX
,
maxY
,
maxZ
});
points
.
add
(
new
double
[]{
maxX
,
minY
,
minZ
});
points
.
add
(
new
double
[]{
maxX
,
minY
,
maxZ
});
points
.
add
(
new
double
[]{
maxX
,
maxY
,
minZ
});
points
.
add
(
new
double
[]{
maxX
,
maxY
,
maxZ
});
return
points
;
}
/**
*
Checks
whether
a
point
lies
inside
or
on
the
surface
of
the
AABB
.
*/
public
boolean
encloses
(
double
x
,
double
y
,
double
z
)
{
return
minX
<=
x
&&
x
<=
maxX
&&
minY
<=
y
&&
y
<=
maxY
&&
minZ
<=
z
&&
z
<=
maxZ
;
}
/**
*
Checks
if
this
and
other
boxes
intersect
*/
public
boolean
intersects
(
AABB
other
)
{
return
!(other.maxX < this.minX || other.minX > this.maxX ||
other
.
maxY
<
this
.
minY
||
other
.
minY
>
this
.
maxY
||
other
.
maxZ
<
this
.
minZ
||
other
.
minZ
>
this
.
maxZ
);
}
@
Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
!(obj instanceof AABB other)) return false;
return
minX
==
other
.
minX
&&
minY
==
other
.
minY
&&
minZ
==
other
.
minZ
&&
maxX
==
other
.
maxX
&&
maxY
==
other
.
maxY
&&
maxZ
==
other
.
maxZ
;
}
@
Override
public
int
hashCode
()
{
return
Double
.
hashCode
(
minX
)
^
Double
.
hashCode
(
maxX
)
^
Double
.
hashCode
(
minY
)
^
Double
.
hashCode
(
maxY
)
^
Double
.
hashCode
(
minZ
)
^
Double
.
hashCode
(
maxZ
);
}
public
void
print
()
{
System
.
out
.
printf
(
"min: %.2f, %.2f, %.2f%n"
,
minX
,
minY
,
minZ
);
System
.
out
.
printf
(
"max: %.2f, %.2f, %.2f%n"
,
maxX
,
maxY
,
maxZ
);
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/56/706753d8efe700101110d31642d3da88
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
bht
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.*;
import
java
.
io
.
IOException
;
import
java
.
util
.*;
//
src
/
test
/
java
/.../
TestCityGmlAABB
.
java
import
java
.
net
.
URL
;
import
java
.
nio
.
file
.
Paths
;
public
class
TestCityGmlAABB
{
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"=== CityGML AABB Test ==="
);
//
---
1
)
Ask
user
which
test
case
to
run
---
Scanner
sc
=
new
Scanner
(
System
.
in
);
System
.
out
.
print
(
"Enter TestCase ID (e.g. PO_TWO_INNERS, SO_WRONG_POLY_ORIENTATION_SINGLE) "
+
"or press Enter for default: "
);
String
id
=
sc
.
nextLine
().
trim
();
//
Default
w
ä
hlen
String
resourcePath
=
TestPaths
.
PO_TWO_INNERS
;
if
(
!id.isEmpty()) {
try
{
//
Holt
TestPaths
per
Reflection
resourcePath
=
(
String
)
TestPaths
.
class
.
getField
(
id
).
get
(
null
);
}
catch
(
ReflectiveOperationException
ex
)
{
System
.
out
.
println
(
"Unknown testcase: "
+
id
+
" (using default)"
);
}
}
String
filePathForParser
=
resolveResourceOnClasspath
(
resourcePath
);
System
.
out
.
println
(
"Using file: "
+
filePathForParser
);
//
---
2
)
Load
CityGML
model
---
ValidationConfiguration
config
=
ValidationConfiguration
.
loadStandardValidationConfig
();
//
TODO
:
Study
class
model
CityDoctorModel
model
=
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
TestUtil
.
loadCityModel
(
filePathForParser
,
config
);
System
.
out
.
println
(
"Model loaded successfully.
\n
"
);
List
<
Building
>
buildings
=
model
.
getBuildings
();
//
---
3
)
Menu
:
choose
granularity
---
System
.
out
.
println
(
"
\n
Choose granularity:"
);
System
.
out
.
println
(
" 1) Polygon-level (broad-phase)"
);
System
.
out
.
println
(
" 2) Ring-level (EXTERIOR)"
);
System
.
out
.
println
(
" 3) Ring-level (INTERIOR)"
);
System
.
out
.
println
(
" 4) Vertex-level (fine-phase)"
);
System
.
out
.
println
(
" 5) All of the above"
);
System
.
out
.
print
(
"Your choice [1-5]: "
);
int
choice
=
readChoice
(
sc
,
1
,
5
);
boolean
doPolygon
=
(
choice
==
1
||
choice
==
5
);
boolean
doExtRing
=
(
choice
==
2
||
choice
==
5
);
boolean
doIntRing
=
(
choice
==
3
||
choice
==
5
);
boolean
doVertex
=
(
choice
==
4
||
choice
==
5
);
//
---
4
)
Run
the
selected
modes
---
if
(
doPolygon
)
runPolygonMode
(
buildings
);
if
(
doExtRing
)
runRingMode
(
buildings
,
true
);
if
(
doIntRing
)
runRingMode
(
buildings
,
false
);
if
(
doVertex
)
runVertexMode
(
buildings
);
System
.
out
.
println
(
"
\n
=== Done ==="
);
}
//
----------
Modes
----------
private
static
void
runPolygonMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Polygon-level AABB (broad-phase)"
);
Set
<
ConcretePolygon
>
polys
=
collectAllPolygons
(
buildings
);
AABBTree
<
ConcretePolygon
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
polys
),
AABBUtils
::
getAABB
);
System
.
out
.
println
(
"Polygons: "
+
polys
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runRingMode
(
List
<
Building
>
buildings
,
boolean
exterior
)
{
String
label
=
exterior
?
"EXTERIOR"
:
"INTERIOR"
;
System
.
out
.
println
(
"
\n
> Ring-level AABB ("
+
label
+
")"
);
Set
<
LinearRing
>
rings
=
exterior
?
collectExteriorRings
(
buildings
)
:
collectInteriorRings
(
buildings
);
AABBTree
<
LinearRing
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
rings
),
AABBUtils
::
computeAABBFromRing
);
System
.
out
.
println
(
label
+
" rings: "
+
rings
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runVertexMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Vertex-level AABB (fine-phase)"
);
Set
<
Vertex
>
verts
=
collectAllVertices
(
buildings
);
AABBTree
<
Vertex
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
verts
),
AABBUtils
::
computeAABBFromVertex
);
System
.
out
.
println
(
"Vertices: "
+
verts
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
//
----------
Collectors
----------
/**
Collects
all
ConcretePolygons
(
unique
)
via
visitor
.
*/
private
static
Set
<
ConcretePolygon
>
collectAllPolygons
(
List
<
Building
>
buildings
)
{
Set
<
ConcretePolygon
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
set
.
add
(
poly
.
getOriginal
());
}
});
}
return
set
;
}
/**
Collects
all
EXTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectExteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
LinearRing
ext
=
poly
.
getOriginal
().
getExteriorRing
();
if
(
ext
!= null) set.add(ext);
}
});
}
return
set
;
}
/**
Collects
all
INTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectInteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
List
<
LinearRing
>
inner
=
poly
.
getOriginal
().
getInnerRings
();
if
(
inner
!= null && !inner.isEmpty()) {
set
.
addAll
(
inner
);
}
}
});
}
return
set
;
}
/**
Collects
all
vertices
(
unique
)
from
both
exterior
and
interior
rings
.
*/
private
static
Set
<
Vertex
>
collectAllVertices
(
List
<
Building
>
buildings
)
{
Set
<
Vertex
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
ConcretePolygon
cp
=
poly
.
getOriginal
();
LinearRing
ext
=
cp
.
getExteriorRing
();
if
(
ext
!= null) set.addAll(ext.getVertices());
List
<
LinearRing
>
inner
=
cp
.
getInnerRings
();
if
(
inner
!= null) {
for
(
LinearRing
lr
:
inner
)
set
.
addAll
(
lr
.
getVertices
());
}
}
});
}
return
set
;
}
//
----------
Utils
----------
/*
Helper
method
reads
choice
of
the
user
*/
private
static
int
readChoice
(
Scanner
sc
,
int
min
,
int
max
)
{
while
(
true
)
{
String
s
=
sc
.
nextLine
().
trim
();
try
{
int
v
=
Integer
.
parseInt
(
s
);
if
(
v
>=
min
&&
v
<=
max
)
return
v
;
}
catch
(
NumberFormatException
ignored
)
{}
System
.
out
.
print
(
"Please enter a number between "
+
min
+
" and "
+
max
+
": "
);
}
}
/*
Helper
method
Pathfinder
*/
private
static
String
resolveResourceOnClasspath
(
String
resourcePath
)
{
String
rp
=
normalizeResourcePath
(
resourcePath
);
//
1
)
Klassenpfad
via
Class
.
getResource
URL
url
=
TestCityGmlAABB
.
class
.
getResource
(
rp
);
//
2
)
Klassenpfad
via
Context
-
ClassLoader
:
if
(
url
==
null
)
{
ClassLoader
cl
=
Thread
.
currentThread
().
getContextClassLoader
();
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
url
=
cl
.
getResource
(
noSlash
);
}
//
3
)
Wenn
gefunden
:
in
Pfad
umwandeln
if
(
url
!= null) {
try
{
return
Paths
.
get
(
url
.
toURI
()).
toString
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Konnte Resource-URI nicht auflösen: "
+
url
,
e
);
}
}
//
4
)
Fallbacks
:
Projekt
-
relative
Kandidaten
pr
ü
fen
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
String
[]
candidates
=
{
"src/test/resources/"
+
noSlash
,
"src/main/resources/"
+
noSlash
,
resourcePath
//
falls
bereits
ein
echter
Dateipfad
ü
bergeben
wurde
};
for
(
String
cand
:
candidates
)
{
java
.
nio
.
file
.
Path
p
=
java
.
nio
.
file
.
Paths
.
get
(
cand
);
if
(
java
.
nio
.
file
.
Files
.
exists
(
p
))
{
return
p
.
toAbsolutePath
().
toString
();
}
}
throw
new
IllegalArgumentException
(
"Resource nicht im Klassenpfad gefunden: "
+
resourcePath
+
" (versucht als: "
+
rp
+
")"
);
}
//*
//
F
Ü
R
ALLE
F
Ä
LLE
zur
Zeit
REDUNDAD
private
static
String
normalizeResourcePath
(
String
path
)
{
String
p
=
path
.
replace
(
'\\'
,
'/'
);
//
Quellordner
-
Pr
ä
fixe
entfernen
,
falls
mit
ü
bergeben
if
(
p
.
startsWith
(
"src/test/resources/"
))
{
p
=
p
.
substring
(
"src/test/resources/"
.
length
());
}
else
if
(
p
.
startsWith
(
"src/main/resources/"
))
{
p
=
p
.
substring
(
"src/main/resources/"
.
length
());
}
//
F
ü
r
Class
.
getResource
:
f
ü
hrenden
Slash
setzen
if
(
!p.startsWith("/")) p = "/" + p;
return
p
;
}
//*/
}
.metadata/.plugins/org.eclipse.core.resources/.history/5c/20528fdeefe700101110d31642d3da88
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
import
java
.
util
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Vertex
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
.
LinearRingType
;
public
class
Main
{
/**
*
Entry
point
for
AABB
testing
*/
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
"=== AABB TEST ==="
);
ConcretePolygon
polygon
=
new
ConcretePolygon
();
LinearRing
exterior
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
exterior
.
addVertex
(
new
Vertex
(
0
,
0
,
0
));
exterior
.
addVertex
(
new
Vertex
(
1
,
0
,
0
));
exterior
.
addVertex
(
new
Vertex
(
0
,
1
,
0
));
exterior
.
addVertex
(
new
Vertex
(
0
,
0
,
0
));
polygon
.
setExteriorRing
(
exterior
);
//
Define
points
of
a
tetrahedron
Point
p1
=
new
Point
(
0
,
0
,
0
);
Point
p2
=
new
Point
(
1
,
0
,
0
);
Point
p3
=
new
Point
(
0.5
,
1
,
0
);
Point
p4
=
new
Point
(
0.5
,
0.5
,
1
);
//
Define
triangle
faces
of
the
tetrahedron
ConcretePolygon
base
=
new
ConcretePolygon
();
LinearRing
baseRing
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
baseRing
.
addVertex
(
new
Vertex
(
p1
.
getX
(),
p1
.
getY
(),
p1
.
getZ
()));
baseRing
.
addVertex
(
new
Vertex
(
p2
.
getX
(),
p2
.
getY
(),
p2
.
getZ
()));
baseRing
.
addVertex
(
new
Vertex
(
p3
.
getX
(),
p3
.
getY
(),
p3
.
getZ
()));
baseRing
.
addVertex
(
new
Vertex
(
p1
.
getX
(),
p1
.
getY
(),
p1
.
getZ
()));
base
.
setExteriorRing
(
baseRing
);
ConcretePolygon
side1
=
new
ConcretePolygon
();
LinearRing
ring1
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
ring1
.
addVertex
(
new
Vertex
(
p1
.
getX
(),
p1
.
getY
(),
p1
.
getZ
()));
ring1
.
addVertex
(
new
Vertex
(
p2
.
getX
(),
p2
.
getY
(),
p2
.
getZ
()));
ring1
.
addVertex
(
new
Vertex
(
p4
.
getX
(),
p4
.
getY
(),
p4
.
getZ
()));
ring1
.
addVertex
(
new
Vertex
(
p1
.
getX
(),
p1
.
getY
(),
p1
.
getZ
()));
side1
.
setExteriorRing
(
ring1
);
ConcretePolygon
side2
=
new
ConcretePolygon
();
LinearRing
ring2
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
ring2
.
addVertex
(
new
Vertex
(
p2
.
getX
(),
p2
.
getY
(),
p2
.
getZ
()));
ring2
.
addVertex
(
new
Vertex
(
p3
.
getX
(),
p3
.
getY
(),
p3
.
getZ
()));
ring2
.
addVertex
(
new
Vertex
(
p4
.
getX
(),
p4
.
getY
(),
p4
.
getZ
()));
ring2
.
addVertex
(
new
Vertex
(
p2
.
getX
(),
p2
.
getY
(),
p2
.
getZ
()));
side2
.
setExteriorRing
(
ring2
);
ConcretePolygon
side3
=
new
ConcretePolygon
();
LinearRing
ring3
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
ring3
.
addVertex
(
new
Vertex
(
p3
.
getX
(),
p3
.
getY
(),
p3
.
getZ
()));
ring3
.
addVertex
(
new
Vertex
(
p1
.
getX
(),
p1
.
getY
(),
p1
.
getZ
()));
ring3
.
addVertex
(
new
Vertex
(
p4
.
getX
(),
p4
.
getY
(),
p4
.
getZ
()));
ring3
.
addVertex
(
new
Vertex
(
p3
.
getX
(),
p3
.
getY
(),
p3
.
getZ
()));
side3
.
setExteriorRing
(
ring3
);
List
<
ConcretePolygon
>
poly
=
Arrays
.
asList
(
base
,
side1
,
side2
,
side3
);
AABB
aabb
=
BVHStructures
.
getAggregateAABB
(
poly
);
System
.
out
.
println
(
"
\n
Computed AABB:"
);
aabb
.
print
();
/***
3
D
-
Point
-
coords
with
Test
Properties
***/
//
Inside
laying
Point
double
testInsideX
=
0.5
;
double
testInsideY
=
0.5
;
double
testInsideZ
=
0.3
;
//
Outside
laying
Point
double
testOutsideX
=
2.0
;
double
testOutsideY
=
2.0
;
double
testOutsideZ
=
2.0
;
//
On
edge
laying
Point
double
testOnEdgeX
=
1.0
;
double
testOnEdgeY
=
1.0
;
double
testOnEdgeZ
=
0.0
;
System
.
out
.
println
(
"
\n
Test point (inside): "
+
testInsideX
+
" "
+
testInsideY
+
" "
+
testInsideZ
);
System
.
out
.
println
(
"-> contained?: "
+
aabb
.
encloses
(
testInsideX
,
testInsideY
,
testInsideZ
));
System
.
out
.
println
(
"
\n
Test point (outside): "
+
testOutsideX
+
" "
+
testOutsideY
+
" "
+
testOutsideZ
);
System
.
out
.
println
(
"-> contained?: "
+
aabb
.
encloses
(
testOutsideX
,
testOutsideY
,
testOutsideZ
));
System
.
out
.
println
(
"
\n
Test point (on edge): "
+
testOnEdgeX
+
" "
+
testOnEdgeY
+
" "
+
testOnEdgeZ
);
System
.
out
.
println
(
"-> contained?: "
+
aabb
.
encloses
(
testOnEdgeX
,
testOnEdgeY
,
testOnEdgeZ
));
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/5e/1053381753e900101245d5e14ea95888
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
/**
*
Central
collection
of
CityGML
test
file
paths
used
for
AABB
/
healing
experiments
.
*
Files
are
located
under
{@
code
src
/
test
/
resources
}
or
{@
code
src
/
test
/
resources
/
bht
/}
*
ACHTUNG
:
mit
'!!!'
markierte
Objekte
haben
einen
falschen
Pfad
*/
public
final
class
TestPaths
{
private
TestPaths
()
{
//
utility
class
}
//
==================================================
//
Schematron
/
Validation
tests
//
==================================================
/**
!!! Not XSD valid, namespaces removed, for schematron experiments. */
public
static
final
String
SCHEMATRON
=
"CityDoctorParent/CityDoctorValidation/target/test-classes/SimpleSolid_SrefBS-Schematron-Test.gml"
;
//
CityDoctorParent
//
"src/test/resources/bht/SimpleSolid_SrefBS-Schematron-Test.gml"
;
//
==================================================
//
LinearRing
(
LR
)
test
cases
//
==================================================
/**
1
LinearRing
has
only
2
points
.
*/
public
static
final
String
LR_2POINTS
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0001-T0001.gml"
;
/**
2
LinearRing
has
3
points
but
is
not
closed
.
*/
public
static
final
String
LR_NOTCLOSED
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0001-T0002.gml"
;
/**
3
LinearRing
has
consecutive
duplicate
vertices
.
*/
public
static
final
String
LR_DUPLICATE_CONSEC
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0001.gml"
;
/**
4
LinearRing
has
non
-
consecutive
duplicate
vertices
.
*/
public
static
final
String
LR_DUPLICATE_NONCONSEC
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0002.gml"
;
/**
added
5
LinearRing
points
form
a
straight
line
.
*/
public
static
final
String
LR_LINE
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0003.gml"
;
/**
added
6
LinearRing
has
consecutive
points
closer
than
0.1
.
*/
public
static
final
String
LR_TOO_CLOSE
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0004.gml"
;
/**
added
7
LinearRing
has
too
few
points
and
duplicate
points
.
*/
public
static
final
String
LR_TOO_FEW_DUP
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0005.gml"
;
/**
8
LinearRing
is
not
closed
.
*/
public
static
final
String
LR_NOTCLOSED_2
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0003-T0001.gml"
;
/**
added
9
LinearRing
is
closed
but
with
point
distance
<
0.1
.
*/
public
static
final
String
LR_CLOSED_SMALLDIST
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0003-T0002.gml"
;
/**
10
LinearRing
has
a
loop
.
*/
public
static
final
String
LR_LOOP
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0004.gml"
;
/**
11
LinearRing
point
touches
edge
with
distance
<
0.1
.
*/
public
static
final
String
LR_TOUCH_EDGE
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0005.gml"
;
//
==================================================
//
Polygon
(
PO
)
test
cases
//
==================================================
/**
12
Inner
ring
intersects
outer
ring
.
*/
public
static
final
String
PO_INTERSECT_OUTER
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0001.gml"
;
/**
13
Polygon
has
2
inner
rings
.
*/
public
static
final
String
PO_TWO_INNERS
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml"
;
/**
14
Polygon
has
2
intersecting
inner
rings
.
*/
public
static
final
String
PO_INNER_INTERSECT
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0003.gml"
;
/**
15
Polygon
has
2
inner
rings
;
one
vertex
too
far
from
the
plane
.
*/
public
static
final
String
PO_INNER_OFF_PLANE
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0002-T0001.gml"
;
/**
added
16
Polygon
has
normal
deviation
error
.
*/
public
static
final
String
PO_NORMAL_ERROR
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0002-T0002.gml"
;
/**
17
Polygon
has
disconnected
interior
surface
.
*/
public
static
final
String
PO_DISCONNECTED_INTERIOR_1
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0001.gml"
;
/**
added
18
Polygon
has
disconnected
interior
surface
due
to
two
inner
rings
.
*/
public
static
final
String
PO_DISCONNECTED_INTERIOR_2
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0002.gml"
;
/**
added
19
Inner
ring
completely
outside
the
outer
ring
.
*/
public
static
final
String
PO_INNER_OUTSIDE
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0004-T0001.gml"
;
/**
added
20
Inner
ring
completely
inside
another
inner
ring
.
*/
public
static
final
String
PO_INNER_INSIDE_ANOTHER
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0005-T0001.gml"
;
/**
21
Two
inner
rings
with
wrong
orientation
.
*/
public
static
final
String
PO_TWO_INNERS_WRONG_ORIENT
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0006-T0001.gml"
;
//
==================================================
//
Solid
(
SO
)
test
cases
//
==================================================
/**
added
22
Solid
consists
of
only
3
polygons
.
*/
public
static
final
String
SO_TOO_FEW_POLYGONS
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0001-T0001.gml"
;
/**
added
23
Shell
is
not
watertight
.
*/
public
static
final
String
SO_NOT_WATERTIGHT
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0002-T0001.gml"
;
/**
24
Two
buildings
connected
only
by
a
single
point
.
*/
public
static
final
String
SO_CONNECTED_BY_POINT
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0003-T0001.gml"
;
/**
25
Roof
point
slightly
deviates
(
e
.
g
.,
10.0
14.95
2.95
vs
10.0
15.0
3.0
).
*/
public
static
final
String
SO_ROOF_COORD_DEVIATION_1
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0004-T0001.gml"
;
/**
25
Missing
polygon
.
*/
public
static
final
String
SO_MISSING_POLYGON
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0004-T0002.gml"
;
/*
*
*
komplex
Data
from
NRW
;
whole
Quartier
*
*/
/**
26
added
EXTRA
Whole
Church
forum
.
*/
public
static
final
String
CHURCH_FORUM
=
"src/test/resources/bht/LoD2_32_344_5675_1_NW.gml"
;
/*
LOST
DATA
/**
Slight
coordinate
deviations
on
multiple
roof
polygons
(
CityGML
2.0
only
).
public
static
final
String
SO_ROOF_COORD_DEVIATION_2
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0004-T0003.gml"
;
*/
/**
added
27
Solid
geometry
actually
contains
two
buildings
.
*/
public
static
final
String
SO_TWO_BUILDINGS_IN_ONE
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0005-T0001.gml"
;
//
//
Falsches
Datei
!!!!
/**
!!! 28 Self-intersecting geometry. */
public
static
final
String
SO_SELF_INTERSECTING
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0003-T0001.gml"
;
//
ACHTUNG
FALSCHES
LABEL
/**
29
Polygon
with
wrong
orientation
.
*/
public
static
final
String
ENTER_LABEL1
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0001.gml"
;
/**
30
Polygon
with
wrong
orientation
.
ACHTUNG
FALSCHES
LABEL
*/
public
static
final
String
ENTER_LABEL2
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0002.gml"
;
/**
31
Polygon
with
wrong
orientation
.
ACHTUNG
FALSCHES
LABEL
*/
public
static
final
String
ENTER_LABEL3
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0003.gml"
;
//
/**
LOST
! 33 All polygons have wrong orientation. */
public
static
final
String
SO_WRONG_POLY_ORIENTATION_ALL
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0008-T0001.gml"
;
}
.metadata/.plugins/org.eclipse.core.resources/.history/6/50ae66e452e900101245d5e14ea95888
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
bht
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyBoolean
;
import
java
.
io
.
IOException
;
//
import
java
.
io
.
InputStream
;
//
new
import
java
.
util
.
ArrayList
;
import
java
.
util
.
Arrays
;
import
java
.
util
.
HashMap
;
import
java
.
util
.
HashSet
;
import
java
.
util
.
List
;
import
java
.
util
.
Map
;
import
java
.
util
.
Set
;
import
java
.
util
.
stream
.
Collectors
;
import
java
.
util
.
Scanner
;
//
new
import
org
.
junit
.
Test
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckableUtilsVisitor
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckableVisitor
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Checker
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
ErrorId
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
ResultStatus
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Check
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckId
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckResult
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Checkable
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
ValidationConfiguration
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
DegeneratedRingError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
PointTouchesEdgeError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
RingDuplicatePointError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
RingEdgeIntersectionError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
geometry
.
SolidSelfIntCheck
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Building
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BoundingBox
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
CityDoctorModel
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
CityObject
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Geometry
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
GeometryType
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
GmlElement
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Polygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Lod
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
.
LinearRingType
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Vertex
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
exceptions
.
CityDoctorWriteException
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
gui
.
table
.
ErrorStat
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
gui
.
tree
.
ErrorItemVisitor
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
gui
.
tree
.
Renderable
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
gui
.
tree
.
node
.
ErrorNode
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
TestUtil
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
math
.
Vector3d
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
CityGmlParseException
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
CityGmlParser
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
InvalidGmlFileException
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
utils
.
BoundingBoxCalculator
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
utils
.
visitors
.
CheckableErrorCollector
;
import
javafx
.
scene
.
control
.
TreeItem
;
public
class
TestExampleAABB
{
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"Start TestExampleAABB..."
);
//
new
//
String
path
=
args
[
0
];
//
String
path
=
"src/test/resources/TestBuilding1.gml"
;
//
new
block
model
String
path
=
"src/test/resources/bht/TestBuilding_SelfInt.gml"
;
//
not
just
SelfInt
errors
//
String
path
=
"src/test/resources/bht/SolidSelfIntTest1.gml"
;
//
valid
model
//
String
path
=
"src/test/resources/bht/DorstenGartenstrasse_SelfInt.gml"
;
//
SelfInt
and
NotClosed
errors
////
Info
:
if
test
model
doesn
't include the desired error, use:
//// addCheckResult(new CheckResult(CheckId.C_GE_S_SELF_INTERSECTION), ResultStatus.ERROR, Mockito.mock(CheckError.class)) hinzufügen
System.out.println("\nModel has been loaded...\n"); //new
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
// CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/bht/SolidSelfIntTest1.gml", config.getParserConfiguration());
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Building building = model.getBuildings().get(0);
// assertFalse(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// assertEquals(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// assertNotNull(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// System.out.println("\n" + building + " contains " + CheckId.C_GE_S_SELF_INTERSECTION); //new
List<CheckError> errors = new ArrayList<>();
building.collectContainedErrors(errors);
//features of errors containing CheckId.C_GE_R_SELF_INTERSECTION
// errors.get(0).getFeature().containsError(CheckId.C_GE_R_SELF_INTERSECTION);
// System.out.println("\n" + building + " contains the Errors " + errors ); //shows list of unknown check errors
//Check for Unknown Errors
// List<CheckError> AllErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.UNKNOWN_ERROR)).collect(Collectors.toList()); // returns UnknownCheckError
// System.out.println("\n" + building + " contains the Errors " + AllErrors ); //shows list of unknown check errors
//Check for Solid SelfIntersection
// List<CheckError> selfIntSolidErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.GE_S_SELF_INTERSECTION)).collect(Collectors.toList());
// System.out.println("\n" + building + " contains the Solid Errors " + selfIntSolidErrors ); //shows list of solid selfInt
//Check for Ring SelfIntersection
List<CheckError> selfIntRingErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.GE_R_SELF_INTERSECTION)).collect(Collectors.toList());
System.out.println("\n" + building + " contains the Ring Errors " + selfIntRingErrors ); //shows list of ring selfInt
//Get Vertices and BoundingBox of LinearRing(s) with SelfIntErrors
for (CheckError error : errors) {
if (error instanceof PointTouchesEdgeError err1) {
System.out.println("\nVertices of PointTouchesEdgeError: " + err1.getRing().getVertices());
BoundingBox bbox1 = BoundingBox.ofPoints(err1.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox1.getBox()));
}
if (error instanceof RingEdgeIntersectionError err2) {
System.out.println("\nVertices of RingEdgeIntersectionError: " + err2.getRing().getVertices());
BoundingBox bbox2 = BoundingBox.ofPoints(err2.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox2.getBox()));
}
if (error instanceof RingDuplicatePointError err3) {
System.out.println("\nVertices of RingDuplicatePointError: " + err3.getRing().getVertices());
BoundingBox bbox3 = BoundingBox.ofPoints(err3.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox3.getBox()));
}
if (error instanceof DegeneratedRingError err4) {
System.out.println("\nVertices of DegeneratedRingError: " + err4.getRing().getVertices());
BoundingBox bbox4 = BoundingBox.ofPoints(err4.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox4.getBox()));
}
}
// //Get BoundingBoxes out of Vertices
// // Test: edge from vertex v1 to vertex v2
// List<Vector3d> v3d = new ArrayList<>();
// Vector3d v1 = new Vector3d(375755.655, 5718919.166, 72.052);
// Vector3d v2 = new Vector3d(375755.655, 5718919.166, 67.772);
// v3d.add(v1);
// v3d.add(v2);
// System.out.println("\nVector Array: " + v3d);
// BoundingBox vbox = BoundingBox.ofPoints(v3d);
// System.out.println("\nBounding Box: " + Arrays.toString(vbox.getBox()));
//
// BoundingBox box = BoundingBox.of(new Vector3d[]{new Vector3d(375755.655, 5718919.166, 72.052), new Vector3d(375755.655, 5718919.166, 67.772)});
// System.out.println("\nBounding Box: " + Arrays.toString(box.getBox()));
//Other available informations for BoundingBox
// System.out.println("\nCenter of Bounding Box: " + box.getCenter());
// System.out.println("\nDiagonal of Bounding Box: " + box.getDiagonal());
// System.out.println("\nVolume of Bounding Box: " + box.getVolume());
// System.out.println("\nHeight of Bounding Box: " + box.getHeight());
// System.out.println("\nWidth of Bounding Box: " + box.getWidth());
}
}
\ No newline at end of file
.metadata/.plugins/org.eclipse.core.resources/.history/67/f0de0979f1e700101110d31642d3da88
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
bht
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.*;
import
java
.
io
.
IOException
;
import
java
.
util
.*;
//
src
/
test
/
java
/.../
TestCityGmlAABB
.
java
import
java
.
net
.
URL
;
import
java
.
nio
.
file
.
Paths
;
public
class
TestCityGmlAABB
{
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"=== CityGML AABB Test ==="
);
//
---
1
)
Ask
user
which
test
case
to
run
---
Scanner
sc
=
new
Scanner
(
System
.
in
);
System
.
out
.
print
(
"Enter TestCase ID (e.g. PO_TWO_INNERS, SO_WRONG_POLY_ORIENTATION_SINGLE) "
+
"or press Enter for default: "
);
String
id
=
sc
.
nextLine
().
trim
();
//
Default
w
ä
hlen
String
resourcePath
=
TestPaths
.
PO_TWO_INNERS
;
if
(
!id.isEmpty()) {
try
{
//
Holt
TestPaths
per
Reflection
resourcePath
=
(
String
)
TestPaths
.
class
.
getField
(
id
).
get
(
null
);
}
catch
(
ReflectiveOperationException
ex
)
{
System
.
out
.
println
(
"Unknown testcase: "
+
id
+
" (using default)"
);
}
}
String
filePathForParser
=
resolveResourceOnClasspath
(
resourcePath
);
System
.
out
.
println
(
"Using file: "
+
filePathForParser
);
//
---
2
)
Load
CityGML
model
---
ValidationConfiguration
config
=
ValidationConfiguration
.
loadStandardValidationConfig
();
//
TODO
:
Study
class
model
CityDoctorModel
model
=
TestUtil
.
loadCityModel
(
filePathForParser
,
config
);
System
.
out
.
println
(
"Model loaded successfully.
\n
"
);
List
<
Building
>
buildings
=
model
.
getBuildings
();
//
---
3
)
Menu
:
choose
granularity
---
System
.
out
.
println
(
"
\n
Choose granularity:"
);
System
.
out
.
println
(
" 1) Polygon-level (broad-phase)"
);
System
.
out
.
println
(
" 2) Ring-level (EXTERIOR)"
);
System
.
out
.
println
(
" 3) Ring-level (INTERIOR)"
);
System
.
out
.
println
(
" 4) Vertex-level (fine-phase)"
);
System
.
out
.
println
(
" 5) All of the above"
);
System
.
out
.
print
(
"Your choice [1-5]: "
);
int
choice
=
readChoice
(
sc
,
1
,
5
);
boolean
doPolygon
=
(
choice
==
1
||
choice
==
5
);
boolean
doExtRing
=
(
choice
==
2
||
choice
==
5
);
boolean
doIntRing
=
(
choice
==
3
||
choice
==
5
);
boolean
doVertex
=
(
choice
==
4
||
choice
==
5
);
//
---
4
)
Run
the
selected
modes
---
if
(
doPolygon
)
runPolygonMode
(
buildings
);
if
(
doExtRing
)
runRingMode
(
buildings
,
true
);
if
(
doIntRing
)
runRingMode
(
buildings
,
false
);
if
(
doVertex
)
runVertexMode
(
buildings
);
System
.
out
.
println
(
"
\n
=== Done ==="
);
}
//
----------
Modes
----------
private
static
void
runPolygonMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Polygon-level AABB (broad-phase)"
);
Set
<
ConcretePolygon
>
polys
=
collectAllPolygons
(
buildings
);
AABBTree
<
ConcretePolygon
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
polys
),
AABBUtils
::
getAABB
);
System
.
out
.
println
(
"Polygons: "
+
polys
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runRingMode
(
List
<
Building
>
buildings
,
boolean
exterior
)
{
String
label
=
exterior
?
"EXTERIOR"
:
"INTERIOR"
;
System
.
out
.
println
(
"
\n
> Ring-level AABB ("
+
label
+
")"
);
Set
<
LinearRing
>
rings
=
exterior
?
collectExteriorRings
(
buildings
)
:
collectInteriorRings
(
buildings
);
AABBTree
<
LinearRing
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
rings
),
AABBUtils
::
computeAABBFromRing
);
System
.
out
.
println
(
label
+
" rings: "
+
rings
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runVertexMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Vertex-level AABB (fine-phase)"
);
Set
<
Vertex
>
verts
=
collectAllVertices
(
buildings
);
AABBTree
<
Vertex
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
verts
),
AABBUtils
::
computeAABBFromVertex
);
System
.
out
.
println
(
"Vertices: "
+
verts
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
//
----------
Collectors
----------
/**
Collects
all
ConcretePolygons
(
unique
)
via
visitor
.
*/
private
static
Set
<
ConcretePolygon
>
collectAllPolygons
(
List
<
Building
>
buildings
)
{
Set
<
ConcretePolygon
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
set
.
add
(
poly
.
getOriginal
());
}
});
}
return
set
;
}
/**
Collects
all
EXTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectExteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
LinearRing
ext
=
poly
.
getOriginal
().
getExteriorRing
();
if
(
ext
!= null) set.add(ext);
}
});
}
return
set
;
}
/**
Collects
all
INTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectInteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
List
<
LinearRing
>
inner
=
poly
.
getOriginal
().
getInnerRings
();
if
(
inner
!= null && !inner.isEmpty()) {
set
.
addAll
(
inner
);
}
}
});
}
return
set
;
}
/**
Collects
all
vertices
(
unique
)
from
both
exterior
and
interior
rings
.
*/
private
static
Set
<
Vertex
>
collectAllVertices
(
List
<
Building
>
buildings
)
{
Set
<
Vertex
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
ConcretePolygon
cp
=
poly
.
getOriginal
();
LinearRing
ext
=
cp
.
getExteriorRing
();
if
(
ext
!= null) set.addAll(ext.getVertices());
List
<
LinearRing
>
inner
=
cp
.
getInnerRings
();
if
(
inner
!= null) {
for
(
LinearRing
lr
:
inner
)
set
.
addAll
(
lr
.
getVertices
());
}
}
});
}
return
set
;
}
//
----------
Utils
----------
/*
Helper
method
reads
choice
of
the
user
*/
private
static
int
readChoice
(
Scanner
sc
,
int
min
,
int
max
)
{
while
(
true
)
{
String
s
=
sc
.
nextLine
().
trim
();
try
{
int
v
=
Integer
.
parseInt
(
s
);
if
(
v
>=
min
&&
v
<=
max
)
return
v
;
}
catch
(
NumberFormatException
ignored
)
{}
System
.
out
.
print
(
"Please enter a number between "
+
min
+
" and "
+
max
+
": "
);
}
}
/*
Helper
method
Pathfinder
*/
private
static
String
resolveResourceOnClasspath
(
String
resourcePath
)
{
String
rp
=
normalizeResourcePath
(
resourcePath
);
//
1
)
Klassenpfad
via
Class
.
getResource
URL
url
=
TestCityGmlAABB
.
class
.
getResource
(
rp
);
//
2
)
Klassenpfad
via
Context
-
ClassLoader
:
if
(
url
==
null
)
{
ClassLoader
cl
=
Thread
.
currentThread
().
getContextClassLoader
();
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
url
=
cl
.
getResource
(
noSlash
);
}
//
3
)
Wenn
gefunden
:
in
Pfad
umwandeln
if
(
url
!= null) {
try
{
return
Paths
.
get
(
url
.
toURI
()).
toString
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Konnte Resource-URI nicht auflösen: "
+
url
,
e
);
}
}
//
4
)
Fallbacks
:
Projekt
-
relative
Kandidaten
pr
ü
fen
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
String
[]
candidates
=
{
"src/test/resources/"
+
noSlash
,
"src/main/resources/"
+
noSlash
,
resourcePath
//
falls
bereits
ein
echter
Dateipfad
ü
bergeben
wurde
};
for
(
String
cand
:
candidates
)
{
java
.
nio
.
file
.
Path
p
=
java
.
nio
.
file
.
Paths
.
get
(
cand
);
if
(
java
.
nio
.
file
.
Files
.
exists
(
p
))
{
return
p
.
toAbsolutePath
().
toString
();
}
}
throw
new
IllegalArgumentException
(
"Resource nicht im Klassenpfad gefunden: "
+
resourcePath
+
" (versucht als: "
+
rp
+
")"
);
}
//*
//
F
Ü
R
ALLE
F
Ä
LLE
zur
Zeit
REDUNDAD
private
static
String
normalizeResourcePath
(
String
path
)
{
String
p
=
path
.
replace
(
'\\'
,
'/'
);
//
Quellordner
-
Pr
ä
fixe
entfernen
,
falls
mit
ü
bergeben
if
(
p
.
startsWith
(
"src/test/resources/"
))
{
p
=
p
.
substring
(
"src/test/resources/"
.
length
());
}
else
if
(
p
.
startsWith
(
"src/main/resources/"
))
{
p
=
p
.
substring
(
"src/main/resources/"
.
length
());
}
//
F
ü
r
Class
.
getResource
:
f
ü
hrenden
Slash
setzen
if
(
!p.startsWith("/")) p = "/" + p;
return
p
;
}
//*/
}
.metadata/.plugins/org.eclipse.core.resources/.history/6b/d002f0fe79ea0010125ad88dcc4485e5
0 → 100644
View file @
c67a5961
/*-
*
Copyright
2020
Beuth
Hochschule
f
ü
r
Technik
Berlin
,
Hochschule
f
ü
r
Technik
Stuttgart
*
*
This
file
is
part
of
CityDoctor2
.
*
*
CityDoctor2
is
free
software
:
you
can
redistribute
it
and
/
or
modify
*
it
under
the
terms
of
the
GNU
Lesser
General
Public
License
as
published
by
*
the
Free
Software
Foundation
,
either
version
3
of
the
License
,
or
*
(
at
your
option
)
any
later
version
.
*
*
CityDoctor2
is
distributed
in
the
hope
that
it
will
be
useful
,
*
but
WITHOUT
ANY
WARRANTY
;
without
even
the
implied
warranty
of
*
MERCHANTABILITY
or
FITNESS
FOR
A
PARTICULAR
PURPOSE
.
See
the
*
GNU
Lesser
General
Public
License
for
more
details
.
*
*
You
should
have
received
a
copy
of
the
GNU
Lesser
General
Public
License
*
along
with
CityDoctor2
.
If
not
,
see
<
https
://
www
.
gnu
.
org
/
licenses
/>.
*/
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
bht
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
Collections
;
import
java
.
util
.
List
;
import
java
.
util
.
Set
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Check
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckId
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckResult
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
GeometrySelfIntersection
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Requirement
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
RequirementType
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
ResultStatus
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
SolidSelfIntError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
util
.
CollectionUtils
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
util
.
SelfIntersectionUtil
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Geometry
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
GeometryType
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Polygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
utils
.
PolygonIntersection
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
.
AABB
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
.
AABBUtils
;
/**
*
Check
for
self
intersecting
solids
*
*
@
author
Baris
Numanoglu
*/
public
class
SolidSelfIntCheckAABB
extends
Check
{
private
static
final
List
<
CheckId
>
dependencies
;
static
{
ArrayList
<
CheckId
>
deps
=
new
ArrayList
<>();
dependencies
=
Collections
.
unmodifiableList
(
deps
);
deps
.
add
(
CheckId
.
C_GE_R_TOO_FEW_POINTS
);
deps
.
add
(
CheckId
.
C_GE_R_NOT_CLOSED
);
deps
.
add
(
CheckId
.
C_GE_R_DUPLICATE_POINT
);
deps
.
add
(
CheckId
.
C_GE_R_SELF_INTERSECTION
);
deps
.
add
(
CheckId
.
C_GE_P_HOLE_OUTSIDE
);
deps
.
add
(
CheckId
.
C_GE_P_INNER_RINGS_NESTED
);
deps
.
add
(
CheckId
.
C_GE_P_INTERIOR_DISCONNECTED
);
deps
.
add
(
CheckId
.
C_GE_P_INTERSECTING_RINGS
);
deps
.
add
(
CheckId
.
C_GE_P_ORIENTATION_RINGS_SAME
);
deps
.
add
(
CheckId
.
C_GE_P_NON_PLANAR
);
deps
.
add
(
CheckId
.
C_GE_S_TOO_FEW_POLYGONS
);
deps
.
add
(
CheckId
.
C_GE_S_MULTIPLE_CONNECTED_COMPONENTS
);
deps
.
add
(
CheckId
.
C_GE_S_NON_MANIFOLD_EDGE
);
deps
.
add
(
CheckId
.
C_GE_S_NON_MANIFOLD_VERTEX
);
deps
.
add
(
CheckId
.
C_GE_S_POLYGON_WRONG_ORIENTATION
);
}
@
Override
public
void
check
(
Geometry
g
)
{
if
(
g
.
getType
()
!= GeometryType.SOLID && g.getType() != GeometryType.COMPOSITE_SURFACE) {
return
;
}
//
---
cheap
broad
-
phase
using
per
-
polygon
AABBs
---
List
<
Polygon
>
polys
=
g
.
getPolygons
();
if
(
polys
==
null
||
polys
.
size
()
<=
1
)
{
g
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
));
return
;
}
//
Build
AABBs
once
AABB
[]
boxes
=
new
AABB
[
polys
.
size
()];
for
(
int
i
=
0
;
i
<
polys
.
size
();
i
++)
{
ConcretePolygon
cp
=
polys
.
get
(
i
).
getOriginal
();
boxes
[
i
]
=
AABBUtils
.
getAABB
(
cp
);
}
//
If
no
AABB
pair
overlaps
,
self
-
intersection
is
impossible
if
(
!anyOverlap(boxes)) {
g
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
));
return
;
}
//
---
---
CheckResult
cr
;
List
<
PolygonIntersection
>
intersections
=
SelfIntersectionUtil
.
calculateSolidSelfIntersection
(
g
);
if
(
intersections
.
isEmpty
())
{
cr
=
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
);
}
else
{
CheckError
e
=
new
SolidSelfIntError
(
g
,
intersections
);
cr
=
new
CheckResult
(
this
,
ResultStatus
.
ERROR
,
e
);
}
g
.
addCheckResult
(
cr
);
}
@
SuppressWarnings
(
"unused"
)
private
CheckResult
oldIntersectionAlgorithm
(
Geometry
g
)
{
CheckResult
cr
;
GeometrySelfIntersection
intersect
=
SelfIntersectionUtil
.
doesSolidSelfIntersect
(
g
);
if
(
intersect
!= null) {
cr
=
new
CheckResult
(
this
,
ResultStatus
.
ERROR
,
null
);
}
else
{
cr
=
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
);
}
return
cr
;
}
@
Override
public
List
<
CheckId
>
getDependencies
()
{
return
dependencies
;
}
@
Override
public
Set
<
Requirement
>
appliesToRequirements
()
{
return
CollectionUtils
.
singletonSet
(
Requirement
.
R_GE_S_SELF_INTERSECTION
);
}
@
Override
public
RequirementType
getType
()
{
return
RequirementType
.
GEOMETRY
;
}
@
Override
public
Check
createNewInstance
()
{
return
new
SolidSelfIntCheckAABB
();
}
@
Override
public
CheckId
getCheckId
()
{
return
CheckId
.
C_GE_S_SELF_INTERSECTION
;
}
/*
----------------
AABB
helpers
(
broad
-
phase
)
----------------
*/
/**
Returns
true
if
there
exists
any
overlapping
AABB
pair
.
*/
private
static
boolean
anyOverlap
(
AABB
[]
boxes
)
{
for
(
int
i
=
0
;
i
<
boxes
.
length
-
1
;
i
++)
{
AABB
a
=
boxes
[
i
];
for
(
int
j
=
i
+
1
;
j
<
boxes
.
length
;
j
++)
{
AABB
b
=
boxes
[
j
];
if
(
overlaps
(
a
,
b
))
return
true
;
}
}
return
false
;
}
/**
Helper
:
AABB
overlap
test
.
*/
private
static
boolean
overlaps
(
AABB
a
,
AABB
b
)
{
return
!(a.getMaxX() < b.getMinX() ||
a
.
getMinX
()
>
b
.
getMaxX
()
||
a
.
getMaxY
()
<
b
.
getMinY
()
||
a
.
getMinY
()
>
b
.
getMaxY
()
||
a
.
getMaxZ
()
<
b
.
getMinZ
()
||
a
.
getMinZ
()
>
b
.
getMaxZ
());
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/7/008846f47dea0010125ad88dcc4485e5
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.*;
import
java
.
io
.
IOException
;
import
java
.
util
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Vertex
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
CityGmlParseException
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
InvalidGmlFileException
;
public
class
TestHouseAABB
{
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"===TestHouseAABB==="
);
/*
*
3
D
House
of
St
.
Niclas
*
*
*/
//
Haus
-
Basis
:
W
ü
rfelgr
öß
e
2
x2x2
,
Dachh
ö
he
+
1
double
baseSize
=
2.0
;
double
height
=
2.0
;
double
roofHeight
=
1.0
;
//
Bodenpunkte
(
unten
)
Point
b1
=
new
Point
(
0
,
0
,
0
);
Point
b2
=
new
Point
(
baseSize
,
0
,
0
);
Point
b3
=
new
Point
(
baseSize
,
baseSize
,
0
);
Point
b4
=
new
Point
(
0
,
baseSize
,
0
);
//
Deckpunkte
(
oben
)
Point
t1
=
new
Point
(
0
,
0
,
height
);
Point
t2
=
new
Point
(
baseSize
,
0
,
height
);
Point
t3
=
new
Point
(
baseSize
,
baseSize
,
height
);
Point
t4
=
new
Point
(
0
,
baseSize
,
height
);
//
Dachspitze
(
Prisma
in
Mitte
der
oberen
Fl
ä
che
)
Point
roofPeak1
=
new
Point
(
baseSize
/
2
,
-
0.2
,
height
+
roofHeight
);
//
vorne
Point
roofPeak2
=
new
Point
(
baseSize
/
2
,
baseSize
+
0.2
,
height
+
roofHeight
);
//
hinten
List
<
ConcretePolygon
>
house
=
new
ArrayList
<>();
//
Boden
(
b1
,
b2
,
b3
,
b4
)
house
.
add
(
createQuadPolygon
(
b1
,
b2
,
b3
,
b4
));
//
W
ä
nde
house
.
add
(
createQuadPolygon
(
b1
,
b2
,
t2
,
t1
));
//
vorne
house
.
add
(
createQuadPolygon
(
b2
,
b3
,
t3
,
t2
));
//
rechts
house
.
add
(
createQuadPolygon
(
b3
,
b4
,
t4
,
t3
));
//
hinten
house
.
add
(
createQuadPolygon
(
b4
,
b1
,
t1
,
t4
));
//
links
//
Decke
unter
Dach
house
.
add
(
createQuadPolygon
(
t1
,
t2
,
t3
,
t4
));
//
Dach
:
zwei
Dreiecksseiten
(
links
/
rechts
)
house
.
add
(
createTrianglePolygon
(
t1
,
t2
,
roofPeak1
));
house
.
add
(
createTrianglePolygon
(
t4
,
t3
,
roofPeak2
));
//
Dach
:
Vorder
-
und
R
ü
ckfl
ä
che
(
Prisma
)
house
.
add
(
createQuadPolygon
(
t2
,
t3
,
roofPeak2
,
roofPeak1
));
house
.
add
(
createQuadPolygon
(
t1
,
t4
,
roofPeak2
,
roofPeak1
));
//
AABB
houseAABB
=
BVHStructures
.
getAggregateAABB
(
house
);
houseAABB
.
print
();
//
Define
test
points
PS
wegen
lesbarkeit
als
Liste
von
Koord
.
vorerst
double
[]
insidePoint
=
{
1.0
,
1.0
,
1.0
};
//
clearly
inside
(
center
of
the
base
cube
)
double
[]
roofPoint
=
{
1.0
,
1.0
,
2.8
};
//
inside
roof
area
but
near
the
top
double
[]
outsidePoint
=
{
3.0
,
3.0
,
3.0
};
//
clearly
outside
double
[]
edgePoint
=
{
2.0
,
2.0
,
2.0
};
//
exactly
on
the
upper
cube
corner
//
Test
containment
System
.
out
.
println
(
"
\n
Test point (inside): "
+
Arrays
.
toString
(
insidePoint
));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
encloses
(
insidePoint
[
0
],
insidePoint
[
1
],
insidePoint
[
2
]));
System
.
out
.
println
(
"
\n
Test point (on roof): "
+
Arrays
.
toString
(
roofPoint
));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
encloses
(
roofPoint
[
0
],
roofPoint
[
1
],
roofPoint
[
2
]));
System
.
out
.
println
(
"
\n
Test point (outside): "
+
Arrays
.
toString
(
outsidePoint
));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
encloses
(
outsidePoint
[
0
],
outsidePoint
[
1
],
outsidePoint
[
2
]));
System
.
out
.
println
(
"
\n
Test point (on edge): "
+
Arrays
.
toString
(
edgePoint
));
System
.
out
.
println
(
"-> contained? "
+
houseAABB
.
encloses
(
edgePoint
[
0
],
edgePoint
[
1
],
edgePoint
[
2
]));
}
/**
Creates
a
triangular
polygon
from
three
points
*/
private
static
ConcretePolygon
createTrianglePolygon
(
Point
p1
,
Point
p2
,
Point
p3
)
{
//
alocate
poly
ConcretePolygon
poly
=
new
ConcretePolygon
();
//
alocate
ring
LinearRing
ring
=
new
LinearRing
(
LinearRing
.
LinearRingType
.
EXTERIOR
);
//
vertices
of
triangle
ring
.
addVertex
(
new
Vertex
(
p1
.
getX
(),
p1
.
getY
(),
p1
.
getZ
()));
ring
.
addVertex
(
new
Vertex
(
p2
.
getX
(),
p2
.
getY
(),
p2
.
getZ
()));
ring
.
addVertex
(
new
Vertex
(
p3
.
getX
(),
p3
.
getY
(),
p3
.
getZ
()));
ring
.
addVertex
(
new
Vertex
(
p1
.
getX
(),
p1
.
getY
(),
p1
.
getZ
()));
//
Close
ring
//
poly
.
setExteriorRing
(
ring
);
return
poly
;
}
/**
Creates
a
quadrilateral
polygon
from
four
points
*/
private
static
ConcretePolygon
createQuadPolygon
(
Point
p1
,
Point
p2
,
Point
p3
,
Point
p4
)
{
ConcretePolygon
poly
=
new
ConcretePolygon
();
LinearRing
ring
=
new
LinearRing
(
LinearRing
.
LinearRingType
.
EXTERIOR
);
ring
.
addVertex
(
new
Vertex
(
p1
.
getX
(),
p1
.
getY
(),
p1
.
getZ
()));
ring
.
addVertex
(
new
Vertex
(
p2
.
getX
(),
p2
.
getY
(),
p2
.
getZ
()));
ring
.
addVertex
(
new
Vertex
(
p3
.
getX
(),
p3
.
getY
(),
p3
.
getZ
()));
ring
.
addVertex
(
new
Vertex
(
p4
.
getX
(),
p4
.
getY
(),
p4
.
getZ
()));
ring
.
addVertex
(
new
Vertex
(
p1
.
getX
(),
p1
.
getY
(),
p1
.
getZ
()));
//
Close
ring
poly
.
setExteriorRing
(
ring
);
return
poly
;
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/76/30bde8923899001017e0d034282fa54d
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
bht
;
/**
*
Central
collection
of
CityGML
test
file
paths
used
for
AABB
/
healing
experiments
.
*
Files
are
located
under
{@
code
src
/
test
/
resources
}
or
{@
code
src
/
test
/
resources
/
bht
/}
*
ACHTUNG
:
mit
'!!!'
markierte
Objekte
haben
einen
falschen
Pfad
*/
public
final
class
TestPaths
{
private
TestPaths
()
{
//
utility
class
}
//
==================================================
//
Schematron
/
Validation
tests
//
==================================================
/**
!!! Not XSD valid, namespaces removed, for schematron experiments. */
public
static
final
String
SCHEMATRON
=
"CityDoctorParent/CityDoctorValidation/target/test-classes/SimpleSolid_SrefBS-Schematron-Test.gml"
;
//
CityDoctorParent
//
"src/test/resources/bht/SimpleSolid_SrefBS-Schematron-Test.gml"
;
//
==================================================
//
LinearRing
(
LR
)
test
cases
//
==================================================
/**
1
LinearRing
has
only
2
points
.
*/
public
static
final
String
LR_2POINTS
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0001-T0001.gml"
;
/**
2
LinearRing
has
3
points
but
is
not
closed
.
*/
public
static
final
String
LR_NOTCLOSED
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0001-T0002.gml"
;
/**
3
LinearRing
has
consecutive
duplicate
vertices
.
*/
public
static
final
String
LR_DUPLICATE_CONSEC
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0001.gml"
;
/**
4
LinearRing
has
non
-
consecutive
duplicate
vertices
.
*/
public
static
final
String
LR_DUPLICATE_NONCONSEC
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0002-T0002.gml"
;
/**
added
5
LinearRing
points
form
a
straight
line
.
*/
public
static
final
String
LR_LINE
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0003.gml"
;
/**
added
6
LinearRing
has
consecutive
points
closer
than
0.1
.
*/
public
static
final
String
LR_TOO_CLOSE
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0004.gml"
;
/**
added
7
LinearRing
has
too
few
points
and
duplicate
points
.
*/
public
static
final
String
LR_TOO_FEW_DUP
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0002-T0005.gml"
;
/**
8
LinearRing
is
not
closed
.
*/
public
static
final
String
LR_NOTCLOSED_2
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0003-T0001.gml"
;
/**
added
9
LinearRing
is
closed
but
with
point
distance
<
0.1
.
*/
public
static
final
String
LR_CLOSED_SMALLDIST
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-LR-0003-T0002.gml"
;
/**
10
LinearRing
has
a
loop
.
*/
public
static
final
String
LR_LOOP
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0004.gml"
;
/**
11
LinearRing
point
touches
edge
with
distance
<
0.1
.
*/
public
static
final
String
LR_TOUCH_EDGE
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-LR-0004-T0005.gml"
;
//
==================================================
//
Polygon
(
PO
)
test
cases
//
==================================================
/**
12
Inner
ring
intersects
outer
ring
.
*/
public
static
final
String
PO_INTERSECT_OUTER
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0001.gml"
;
/**
13
Polygon
has
2
inner
rings
.
*/
public
static
final
String
PO_TWO_INNERS
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml"
;
/**
14
Polygon
has
2
intersecting
inner
rings
.
*/
public
static
final
String
PO_INNER_INTERSECT
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0003.gml"
;
/**
15
Polygon
has
2
inner
rings
;
one
vertex
too
far
from
the
plane
.
*/
public
static
final
String
PO_INNER_OFF_PLANE
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0002-T0001.gml"
;
/**
added
16
Polygon
has
normal
deviation
error
.
*/
public
static
final
String
PO_NORMAL_ERROR
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0002-T0002.gml"
;
/**
17
Polygon
has
disconnected
interior
surface
.
*/
public
static
final
String
PO_DISCONNECTED_INTERIOR_1
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0001.gml"
;
/**
added
18
Polygon
has
disconnected
interior
surface
due
to
two
inner
rings
.
*/
public
static
final
String
PO_DISCONNECTED_INTERIOR_2
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0003-T0002.gml"
;
/**
added
19
Inner
ring
completely
outside
the
outer
ring
.
*/
public
static
final
String
PO_INNER_OUTSIDE
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0004-T0001.gml"
;
/**
added
20
Inner
ring
completely
inside
another
inner
ring
.
*/
public
static
final
String
PO_INNER_INSIDE_ANOTHER
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0005-T0001.gml"
;
/**
21
Two
inner
rings
with
wrong
orientation
.
*/
public
static
final
String
PO_TWO_INNERS_WRONG_ORIENT
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-PO-0006-T0001.gml"
;
//
==================================================
//
Solid
(
SO
)
test
cases
//
==================================================
/**
added
22
Solid
consists
of
only
3
polygons
.
*/
public
static
final
String
SO_TOO_FEW_POLYGONS
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0001-T0001.gml"
;
/**
added
23
Shell
is
not
watertight
.
*/
public
static
final
String
SO_NOT_WATERTIGHT
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0002-T0001.gml"
;
/**
24
Two
buildings
connected
only
by
a
single
point
.
*/
public
static
final
String
SO_CONNECTED_BY_POINT
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0003-T0001.gml"
;
/**
25
Roof
point
slightly
deviates
(
e
.
g
.,
10.0
14.95
2.95
vs
10.0
15.0
3.0
).
*/
public
static
final
String
SO_ROOF_COORD_DEVIATION_1
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0004-T0001.gml"
;
/**
25
Missing
polygon
.
*/
public
static
final
String
SO_MISSING_POLYGON
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0004-T0002.gml"
;
/**
LOST
! 26 Slight coordinate deviations on multiple roof polygons (CityGML 2.0 only). */
public
static
final
String
SO_ROOF_COORD_DEVIATION_2
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0004-T0003.gml"
;
/**
added
27
Solid
geometry
actually
contains
two
buildings
.
*/
public
static
final
String
SO_TWO_BUILDINGS_IN_ONE
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0005-T0001.gml"
;
/**
added
EXTRA
Whole
Churchforum
.
*/
public
static
final
String
CHURCH_FORUM
=
"src/test/resources/bht/LoD2_32_344_5675_1_NW.gml"
;
//
//
Falsches
Datei
!!!!
/**
!!! 28 Self-intersecting geometry. */
public
static
final
String
SO_SELF_INTERSECTING
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0003-T0001.gml"
;
//
ACHTUNG
FALSCHES
LABEL
/**
29
Polygon
with
wrong
orientation
.
*/
public
static
final
String
ENTER_LABEL1
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0001.gml"
;
/**
30
Polygon
with
wrong
orientation
.
ACHTUNG
FALSCHES
LABEL
*/
public
static
final
String
ENTER_LABEL2
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0002.gml"
;
/**
31
Polygon
with
wrong
orientation
.
ACHTUNG
FALSCHES
LABEL
*/
public
static
final
String
ENTER_LABEL3
=
"src/test/resources/SimpleSolid_SrefBS-GE-gml-SO-0007-T0003.gml"
;
//
/**
LOST
! 33 All polygons have wrong orientation. */
public
static
final
String
SO_WRONG_POLY_ORIENTATION_ALL
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-SO-0008-T0001.gml"
;
}
.metadata/.plugins/org.eclipse.core.resources/.history/7a/e0f656e452e900101245d5e14ea95888
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
bht
;
import
java
.
io
.
IOException
;
//
import
java
.
io
.
InputStream
;
//
new
import
java
.
util
.
ArrayList
;
import
java
.
util
.
HashMap
;
import
java
.
util
.
HashSet
;
import
java
.
util
.
List
;
import
java
.
util
.
Map
;
import
java
.
util
.
Set
;
import
java
.
util
.
Scanner
;
//
new
import
org
.
junit
.
Test
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckableUtilsVisitor
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckableVisitor
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Check
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
ValidationConfiguration
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Building
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
CityDoctorModel
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
CityObject
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Geometry
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Polygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
.
LinearRingType
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Vertex
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
exceptions
.
CityDoctorWriteException
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
TestUtil
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
CityGmlParseException
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
InvalidGmlFileException
;
public
class
TestExample
{
//
InputStream
inStream
=
getClass
().
getClassLoader
().
getResourceAsStream
(
"SimpleSolid_SrefBS.gml"
);
//
new
//
//
if
you
want
to
load
a
src
/
test
/
resources
file
out
of
a
different
package
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"Start TestExample...
\n
"
);
//
new
//
String
path
=
args
[
0
];
//
String
path
=
"src/test/resources/SimpleSolid_SrefBS.gml"
;
//
new
valid
LoD2
model
//
String
path
=
"src/test/resources/TestBuilding1.gml"
;
//
new
block
model
//
new
valid
model
with
inner
rings
String
path
=
"src/test/resources/bht/SimpleSolid_SrefBS-GE-gml-PO-0001-T0002.gml"
;
//
too
big
,
main
gets
terminated
//
String
path
=
"src/test/resources/bht/KreishausFeuerwache.gml"
;
//
String
path
=
"src/test/resources/bht/TestBuilding_SelfInt.gml"
;
ValidationConfiguration
config
=
ValidationConfiguration
.
loadStandardValidationConfig
();
CityDoctorModel
model
=
TestUtil
.
loadCityModel
(
path
,
config
);
System
.
out
.
println
(
"
\n
Model has been loaded..."
);
//
new
//
visitor
//
filter
duplicate
polygons
out
Set
<
ConcretePolygon
>
allBuildingPolygons
=
new
HashSet
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
public
void
check
(
Polygon
poly
)
{
allBuildingPolygons
.
add
(
poly
.
getOriginal
());
}
});
}
System
.
out
.
println
(
"
\n
Polygons via visitor:"
+
allBuildingPolygons
);
//
new
//
//
for
loop
List
<
Polygon
>
allBuildingPolygons2
=
new
ArrayList
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
for
(
Geometry
geom
:
b
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
allBuildingPolygons2
.
add
(
p
);
allBuildingPolygons2
.
add
(
p
.
getOriginal
());
//
new
}
}
}
System
.
out
.
println
(
"
\n
Polygon List:"
+
allBuildingPolygons2
);
//
new
//
new
:
LinearRings
//
visitor
//
filter
duplicate
linear
rings
out
Set
<
LinearRing
>
allBuildingLinearRings
=
new
HashSet
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
public
void
check
(
LinearRing
ring
)
{
allBuildingLinearRings
.
add
(
ring
);
}
});
}
System
.
out
.
println
(
"
\n
LinearRings via visitor:"
+
allBuildingLinearRings
);
//
new
//
new
:
ExteriorRings
//
visitor
//
filter
duplicate
exterior
rings
out
Set
<
LinearRing
>
allBuildingExteriorRings
=
new
HashSet
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
public
void
check
(
LinearRing
ring
)
{
allBuildingExteriorRings
.
add
(
ring
.
getParent
().
getExteriorRing
());
//
ACHTUNG
getParent
}
});
}
System
.
out
.
println
(
"
\n
ExteriorRings via visitor:"
+
allBuildingExteriorRings
);
//
new
//
//
new
:
ExteriorRings
(
List
)
//
//
for
loop
//
List
<
LinearRing
>
allBuildingExteriorRings2
=
new
ArrayList
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
for
(
Geometry
geom
:
b
.
getGeometries
())
{
//
for
(
Polygon
p
:
geom
.
getPolygons
())
{
//
allBuildingExteriorRings2
.
add
(
p
.
getOriginal
().
getExteriorRing
());
//
}
//
}
//
}
//
System
.
out
.
println
(
"
\n
ExteriorRing List:"
+
allBuildingExteriorRings2
);
//
new
//
new
:
InnerRings
//
visitor
//
filter
duplicate
inner
rings
out
Set
<
LinearRing
>
allBuildingInnerRings
=
new
HashSet
<>();
for
(
Building
b
:
model
.
getBuildings
())
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
public
void
check
(
Polygon
poly
)
{
allBuildingInnerRings
.
addAll
(
poly
.
getOriginal
().
getInnerRings
());//
ACHTUNG
getOriginal
}
});
}
System
.
out
.
println
(
"
\n
InnerRings via visitor:"
+
allBuildingInnerRings
);
//
new
//
//
new
:
InnerRings
(
List
)
//
//
for
loop
//
List
<
LinearRing
>
allBuildingInnerRings2
=
new
ArrayList
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
for
(
Geometry
geom
:
b
.
getGeometries
())
{
//
for
(
Polygon
p
:
geom
.
getPolygons
())
{
//
for
(
LinearRing
lr
:
p
.
getInnerRings
())
{
//
allBuildingInnerRings2
.
add
(
lr
);
//
}
//
//
}
//
}
//
}
//
System
.
out
.
println
(
"
\n
InnerRing List:"
+
allBuildingInnerRings2
);
//
new
//
//
get
Vertices
for
LinearRing
,
ExteriorRing
and
InteriorRing
//
//
new
:
LinearRingVertices
//
//
visitor
//
//
filter
duplicate
linear
rings
out
//
Set
<
Vertex
>
allBuildingLinearRingVertices
=
new
HashSet
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
b
.
accept
(
new
CheckableUtilsVisitor
()
{
//
public
void
check
(
LinearRing
ring
)
{
//
allBuildingLinearRingVertices
.
addAll
(
ring
.
getVertices
());
//
}
//
//
});
//
}
//
System
.
out
.
println
(
"
\n
LinearRingVertices via visitor:"
+
allBuildingLinearRingVertices
);
//
new
//
//
new
:
ExteriorRingVertices
//
//
visitor
//
//
filter
duplicate
exterior
rings
out
//
Set
<
Vertex
>
allBuildingExteriorRingVertices
=
new
HashSet
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
b
.
accept
(
new
CheckableUtilsVisitor
()
{
//
public
void
check
(
LinearRing
ring
)
{
//
allBuildingExteriorRingVertices
.
addAll
(
ring
.
getParent
().
getOriginal
().
getExteriorRing
().
getVertices
());
//
}
//
//
});
//
}
//
System
.
out
.
println
(
"
\n
ExteriorRingVertices via visitor:"
+
allBuildingExteriorRingVertices
);
//
new
//
//
new
:
ExteriorRingVertices
(
List
)
//
//
for
loop
//
List
<
Vertex
>
allBuildingExteriorRingVertices2
=
new
ArrayList
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
for
(
Geometry
geom
:
b
.
getGeometries
())
{
//
for
(
Polygon
p
:
geom
.
getPolygons
())
{
//
for
(
Vertex
v
:
p
.
getOriginal
().
getExteriorRing
().
getVertices
())
{
//
allBuildingExteriorRingVertices2
.
add
(
v
);
//
}
//
}
//
}
//
}
//
System
.
out
.
println
(
"
\n
ExteriorRingVertices List:"
+
allBuildingExteriorRingVertices2
);
//
new
//
//
new
:
InnerRingVertices
//
//
visitor
//
//
filter
duplicate
linear
vertices
out
//
Set
<
Vertex
>
allBuildingInnerRingVertices
=
new
HashSet
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
b
.
accept
(
new
CheckableUtilsVisitor
()
{
//
public
void
check
(
Polygon
poly
)
{
//
poly
.
getOriginal
().
getInnerRings
().
forEach
(
ring
->
allBuildingInnerRingVertices
.
addAll
(
ring
.
getVertices
()));
//
}
//
});
//
}
//
System
.
out
.
println
(
"
\n
InnerRingVertices via visitor:"
+
allBuildingInnerRingVertices
);
//
new
//
//
new
:
InnerRingVertices
(
List
)
//
//
for
loop
//
List
<
Vertex
>
allInnerRingVertices2
=
new
ArrayList
<>();
//
for
(
Building
b
:
model
.
getBuildings
())
{
//
for
(
Geometry
geom
:
b
.
getGeometries
())
{
//
for
(
Polygon
p
:
geom
.
getPolygons
())
{
//
for
(
LinearRing
lr
:
p
.
getInnerRings
())
{
//
for
(
Vertex
v
:
lr
.
getVertices
())
{
//
allInnerRingVertices2
.
add
(
v
);
//
}
//
}
//
//
}
//
}
//
}
//
System
.
out
.
println
(
"
\n
InnerRingVertices List:"
+
allInnerRingVertices2
);
//
new
//
//
TODO
:
HashMap
to
show
Ring
and
gmlId
//
Map
<
LinearRing
,
Set
<
Vertex
>>
test
=
new
HashMap
<>();
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/8/30bf331753e900101245d5e14ea95888
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
/**
*
Represents
a
CityGML
test
model
with
metadata
for
easier
handling
in
tests
.
*/
public
class
TestModel
{
/**
A
short
unique
ID
(
e
.
g
.
"PO_TWO_INNERS"
,
"SO_NOT_WATERTIGHT"
).
*/
private
final
String
id
;
/**
Path
to
the
GML
file
(
classpath
or
relative
path
under
src
/
test
/
resources
).
*/
private
final
String
resourcePath
;
/**
Human
-
readable
description
of
the
test
case
.
*/
private
final
String
description
;
/**
Category
of
test
(
e
.
g
.
"PO"
=
polygon
,
"SO"
=
solid
,
"LR"
=
linear
ring
).
*/
private
final
String
category
;
/**
Optional
:
Author
or
source
of
the
model
(
if
useful
for
tracing
).
*/
private
final
String
source
;
/**
Optional
:
Known
type
of
geometry
error
(
e
.
g
.
"ring not closed"
,
"not watertight"
).
*/
private
final
String
errorType
;
//
---
Constructor
---
public
TestModel
(
String
id
,
String
resourcePath
,
String
description
,
String
category
,
String
source
,
String
errorType
)
{
this
.
id
=
id
;
this
.
resourcePath
=
resourcePath
;
this
.
description
=
description
;
this
.
category
=
category
;
this
.
source
=
source
;
this
.
errorType
=
errorType
;
}
//
---
Getters
---
public
String
getId
()
{
return
id
;
}
public
String
getResourcePath
()
{
return
resourcePath
;
}
public
String
getDescription
()
{
return
description
;
}
public
String
getCategory
()
{
return
category
;
}
public
String
getSource
()
{
return
source
;
}
public
String
getErrorType
()
{
return
errorType
;
}
@
Override
public
String
toString
()
{
return
"["
+
id
+
"] "
+
description
+
" ("
+
resourcePath
+
")"
;
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/84/0092c4bdf7e700101110d31642d3da88
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
healer
.
aabb
.
bht
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.*;
import
java
.
io
.
IOException
;
import
java
.
util
.*;
//
src
/
test
/
java
/.../
TestCityGmlAABB
.
java
import
java
.
net
.
URL
;
import
java
.
nio
.
file
.
Paths
;
public
class
TestCityGmlAABB
{
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"=== CityGML AABB Test ==="
);
//
---
1
)
Ask
user
which
test
case
to
run
---
Scanner
sc
=
new
Scanner
(
System
.
in
);
System
.
out
.
print
(
"Enter TestCase ID (e.g. PO_TWO_INNERS, SO_WRONG_POLY_ORIENTATION_SINGLE) "
+
"or press Enter for default: "
);
String
id
=
sc
.
nextLine
().
trim
();
//
Default
w
ä
hlen
String
resourcePath
=
TestPaths
.
PO_TWO_INNERS
;
if
(
!id.isEmpty()) {
try
{
//
Holt
TestPaths
per
Reflection
resourcePath
=
(
String
)
TestPaths
.
class
.
getField
(
id
).
get
(
null
);
}
catch
(
ReflectiveOperationException
ex
)
{
System
.
out
.
println
(
"Unknown testcase: "
+
id
+
" (using default)"
);
}
}
String
filePathForParser
=
resolveResourceOnClasspath
(
resourcePath
);
System
.
out
.
println
(
"Using file: "
+
filePathForParser
);
//
---
2
)
Load
CityGML
model
---
ValidationConfiguration
config
=
ValidationConfiguration
.
loadStandardValidationConfig
();
//
TODO
:
Study
class
model
CityDoctorModel
model
=
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
TestUtil
.
loadCityModel
(
filePathForParser
,
config
);
System
.
out
.
println
(
"Model loaded successfully.
\n
"
);
List
<
Building
>
buildings
=
model
.
getBuildings
();
//
---
3
)
Menu
:
choose
granularity
---
System
.
out
.
println
(
"
\n
Choose granularity:"
);
System
.
out
.
println
(
" 1) Polygon-level (broad-phase)"
);
System
.
out
.
println
(
" 2) Ring-level (EXTERIOR)"
);
System
.
out
.
println
(
" 3) Ring-level (INTERIOR)"
);
System
.
out
.
println
(
" 4) Vertex-level (fine-phase)"
);
System
.
out
.
println
(
" 5) All of the above"
);
System
.
out
.
print
(
"Your choice [1-5]: "
);
int
choice
=
readChoice
(
sc
,
1
,
5
);
boolean
doPolygon
=
(
choice
==
1
||
choice
==
5
);
boolean
doExtRing
=
(
choice
==
2
||
choice
==
5
);
boolean
doIntRing
=
(
choice
==
3
||
choice
==
5
);
boolean
doVertex
=
(
choice
==
4
||
choice
==
5
);
//
---
4
)
Run
the
selected
modes
---
if
(
doPolygon
)
runPolygonMode
(
buildings
);
if
(
doExtRing
)
runRingMode
(
buildings
,
true
);
if
(
doIntRing
)
runRingMode
(
buildings
,
false
);
if
(
doVertex
)
runVertexMode
(
buildings
);
System
.
out
.
println
(
"
\n
=== Done ==="
);
}
//
----------
Modes
----------
private
static
void
runPolygonMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Polygon-level AABB (broad-phase)"
);
Set
<
ConcretePolygon
>
polys
=
collectAllPolygons
(
buildings
);
AABBTree
<
ConcretePolygon
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
polys
),
AABBUtils
::
getAABB
);
System
.
out
.
println
(
"Polygons: "
+
polys
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runRingMode
(
List
<
Building
>
buildings
,
boolean
exterior
)
{
String
label
=
exterior
?
"EXTERIOR"
:
"INTERIOR"
;
System
.
out
.
println
(
"
\n
> Ring-level AABB ("
+
label
+
")"
);
Set
<
LinearRing
>
rings
=
exterior
?
collectExteriorRings
(
buildings
)
:
collectInteriorRings
(
buildings
);
AABBTree
<
LinearRing
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
rings
),
AABBUtils
::
computeAABBFromRing
);
System
.
out
.
println
(
label
+
" rings: "
+
rings
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runVertexMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Vertex-level AABB (fine-phase)"
);
Set
<
Vertex
>
verts
=
collectAllVertices
(
buildings
);
AABBTree
<
Vertex
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
verts
),
AABBUtils
::
computeAABBFromVertex
);
System
.
out
.
println
(
"Vertices: "
+
verts
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
//
----------
Collectors
----------
/**
Collects
all
ConcretePolygons
(
unique
)
via
visitor
.
*/
private
static
Set
<
ConcretePolygon
>
collectAllPolygons
(
List
<
Building
>
buildings
)
{
Set
<
ConcretePolygon
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
set
.
add
(
poly
.
getOriginal
());
}
});
}
return
set
;
}
/**
Collects
all
EXTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectExteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
LinearRing
ext
=
poly
.
getOriginal
().
getExteriorRing
();
if
(
ext
!= null) set.add(ext);
}
});
}
return
set
;
}
/**
Collects
all
INTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectInteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
List
<
LinearRing
>
inner
=
poly
.
getOriginal
().
getInnerRings
();
if
(
inner
!= null && !inner.isEmpty()) {
set
.
addAll
(
inner
);
}
}
});
}
return
set
;
}
/**
Collects
all
vertices
(
unique
)
from
both
exterior
and
interior
rings
.
*/
private
static
Set
<
Vertex
>
collectAllVertices
(
List
<
Building
>
buildings
)
{
Set
<
Vertex
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
ConcretePolygon
cp
=
poly
.
getOriginal
();
LinearRing
ext
=
cp
.
getExteriorRing
();
if
(
ext
!= null) set.addAll(ext.getVertices());
List
<
LinearRing
>
inner
=
cp
.
getInnerRings
();
if
(
inner
!= null) {
for
(
LinearRing
lr
:
inner
)
set
.
addAll
(
lr
.
getVertices
());
}
}
});
}
return
set
;
}
//
----------
Utils
----------
/*
Helper
method
reads
choice
of
the
user
*/
private
static
int
readChoice
(
Scanner
sc
,
int
min
,
int
max
)
{
while
(
true
)
{
String
s
=
sc
.
nextLine
().
trim
();
try
{
int
v
=
Integer
.
parseInt
(
s
);
if
(
v
>=
min
&&
v
<=
max
)
return
v
;
}
catch
(
NumberFormatException
ignored
)
{}
System
.
out
.
print
(
"Please enter a number between "
+
min
+
" and "
+
max
+
": "
);
}
}
/*
Helper
method
Pathfinder
*/
private
static
String
resolveResourceOnClasspath
(
String
resourcePath
)
{
String
rp
=
normalizeResourcePath
(
resourcePath
);
//
1
)
Klassenpfad
via
Class
.
getResource
URL
url
=
TestCityGmlAABB
.
class
.
getResource
(
rp
);
//
2
)
Klassenpfad
via
Context
-
ClassLoader
:
if
(
url
==
null
)
{
ClassLoader
cl
=
Thread
.
currentThread
().
getContextClassLoader
();
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
url
=
cl
.
getResource
(
noSlash
);
}
//
3
)
Wenn
gefunden
:
in
Pfad
umwandeln
if
(
url
!= null) {
try
{
return
Paths
.
get
(
url
.
toURI
()).
toString
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Konnte Resource-URI nicht auflösen: "
+
url
,
e
);
}
}
//
4
)
Fallbacks
:
Projekt
-
relative
Kandidaten
pr
ü
fen
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
String
[]
candidates
=
{
"src/test/resources/"
+
noSlash
,
"src/main/resources/"
+
noSlash
,
resourcePath
//
falls
bereits
ein
echter
Dateipfad
ü
bergeben
wurde
};
for
(
String
cand
:
candidates
)
{
java
.
nio
.
file
.
Path
p
=
java
.
nio
.
file
.
Paths
.
get
(
cand
);
if
(
java
.
nio
.
file
.
Files
.
exists
(
p
))
{
return
p
.
toAbsolutePath
().
toString
();
}
}
throw
new
IllegalArgumentException
(
"Resource nicht im Klassenpfad gefunden: "
+
resourcePath
+
" (versucht als: "
+
rp
+
")"
);
}
//
F
Ü
R
ALLE
F
Ä
LLE
zur
Zeit
REDUNDAD
private
static
String
normalizeResourcePath
(
String
path
)
{
String
p
=
path
.
replace
(
'\\'
,
'/'
);
//
Quellordner
-
Pr
ä
fixe
entfernen
,
falls
mit
ü
bergeben
if
(
p
.
startsWith
(
"src/test/resources/"
))
{
p
=
p
.
substring
(
"src/test/resources/"
.
length
());
}
else
if
(
p
.
startsWith
(
"src/main/resources/"
))
{
p
=
p
.
substring
(
"src/main/resources/"
.
length
());
}
//
F
ü
r
Class
.
getResource
:
f
ü
hrenden
Slash
setzen
if
(
!p.startsWith("/")) p = "/" + p;
return
p
;
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/8d/e02d969652e900101245d5e14ea95888
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyBoolean
;
import
java
.
io
.
IOException
;
//
import
java
.
io
.
InputStream
;
//
new
import
java
.
util
.
ArrayList
;
import
java
.
util
.
Arrays
;
import
java
.
util
.
HashMap
;
import
java
.
util
.
HashSet
;
import
java
.
util
.
List
;
import
java
.
util
.
Map
;
import
java
.
util
.
Set
;
import
java
.
util
.
stream
.
Collectors
;
import
java
.
util
.
Scanner
;
//
new
import
org
.
junit
.
Test
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckableUtilsVisitor
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckableVisitor
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Checker
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
ErrorId
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
ResultStatus
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Check
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckId
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
CheckResult
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
Checkable
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
ValidationConfiguration
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
DegeneratedRingError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
PointTouchesEdgeError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
RingDuplicatePointError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
RingEdgeIntersectionError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
geometry
.
SolidSelfIntCheck
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Building
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BoundingBox
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
CityDoctorModel
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
CityObject
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Geometry
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
GeometryType
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
GmlElement
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Polygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Lod
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
.
LinearRingType
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Vertex
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
exceptions
.
CityDoctorWriteException
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
gui
.
table
.
ErrorStat
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
gui
.
tree
.
ErrorItemVisitor
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
gui
.
tree
.
Renderable
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
gui
.
tree
.
node
.
ErrorNode
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
TestUtil
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
math
.
Vector3d
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
CityGmlParseException
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
CityGmlParser
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
InvalidGmlFileException
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
utils
.
BoundingBoxCalculator
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
utils
.
visitors
.
CheckableErrorCollector
;
import
javafx
.
scene
.
control
.
TreeItem
;
public
class
TestExampleAABB
{
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"Start TestExampleAABB..."
);
//
new
//
String
path
=
args
[
0
];
//
String
path
=
"src/test/resources/TestBuilding1.gml"
;
//
new
block
model
String
path
=
"src/test/resources/bht/TestBuilding_SelfInt.gml"
;
//
not
just
SelfInt
errors
//
String
path
=
"src/test/resources/bht/SolidSelfIntTest1.gml"
;
//
valid
model
//
String
path
=
"src/test/resources/bht/DorstenGartenstrasse_SelfInt.gml"
;
//
SelfInt
and
NotClosed
errors
////
Info
:
if
test
model
doesn
't include the desired error, use:
//// addCheckResult(new CheckResult(CheckId.C_GE_S_SELF_INTERSECTION), ResultStatus.ERROR, Mockito.mock(CheckError.class)) hinzufügen
System.out.println("\nModel has been loaded...\n"); //new
ValidationConfiguration config = ValidationConfiguration.loadStandardValidationConfig();
config.setSchematronFilePathInGlobalParameters(null);
// CityDoctorModel model = CityGmlParser.parseCityGmlFile("src/test/resources/bht/SolidSelfIntTest1.gml", config.getParserConfiguration());
CityDoctorModel model = TestUtil.loadCityModel(path, config);
Checker c = new Checker(config, model);
c.runChecks();
Building building = model.getBuildings().get(0);
// assertFalse(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// assertEquals(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// assertNotNull(building.containsError(CheckId.C_GE_S_SELF_INTERSECTION));
// System.out.println("\n" + building + " contains " + CheckId.C_GE_S_SELF_INTERSECTION); //new
List<CheckError> errors = new ArrayList<>();
building.collectContainedErrors(errors);
//features of errors containing CheckId.C_GE_R_SELF_INTERSECTION
// errors.get(0).getFeature().containsError(CheckId.C_GE_R_SELF_INTERSECTION);
// System.out.println("\n" + building + " contains the Errors " + errors ); //shows list of unknown check errors
//Check for Unknown Errors
// List<CheckError> AllErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.UNKNOWN_ERROR)).collect(Collectors.toList()); // returns UnknownCheckError
// System.out.println("\n" + building + " contains the Errors " + AllErrors ); //shows list of unknown check errors
//Check for Solid SelfIntersection
// List<CheckError> selfIntSolidErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.GE_S_SELF_INTERSECTION)).collect(Collectors.toList());
// System.out.println("\n" + building + " contains the Solid Errors " + selfIntSolidErrors ); //shows list of solid selfInt
//Check for Ring SelfIntersection
List<CheckError> selfIntRingErrors = errors.stream().filter(checkError -> checkError.getErrorId().equals(ErrorId.GE_R_SELF_INTERSECTION)).collect(Collectors.toList());
System.out.println("\n" + building + " contains the Ring Errors " + selfIntRingErrors ); //shows list of ring selfInt
//Get Vertices and BoundingBox of LinearRing(s) with SelfIntErrors
for (CheckError error : errors) {
if (error instanceof PointTouchesEdgeError err1) {
System.out.println("\nVertices of PointTouchesEdgeError: " + err1.getRing().getVertices());
BoundingBox bbox1 = BoundingBox.ofPoints(err1.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox1.getBox()));
}
if (error instanceof RingEdgeIntersectionError err2) {
System.out.println("\nVertices of RingEdgeIntersectionError: " + err2.getRing().getVertices());
BoundingBox bbox2 = BoundingBox.ofPoints(err2.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox2.getBox()));
}
if (error instanceof RingDuplicatePointError err3) {
System.out.println("\nVertices of RingDuplicatePointError: " + err3.getRing().getVertices());
BoundingBox bbox3 = BoundingBox.ofPoints(err3.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox3.getBox()));
}
if (error instanceof DegeneratedRingError err4) {
System.out.println("\nVertices of DegeneratedRingError: " + err4.getRing().getVertices());
BoundingBox bbox4 = BoundingBox.ofPoints(err4.getRing().getVertices());
System.out.println("\nBoundingBox: " + Arrays.toString(bbox4.getBox()));
}
}
// //Get BoundingBoxes out of Vertices
// // Test: edge from vertex v1 to vertex v2
// List<Vector3d> v3d = new ArrayList<>();
// Vector3d v1 = new Vector3d(375755.655, 5718919.166, 72.052);
// Vector3d v2 = new Vector3d(375755.655, 5718919.166, 67.772);
// v3d.add(v1);
// v3d.add(v2);
// System.out.println("\nVector Array: " + v3d);
// BoundingBox vbox = BoundingBox.ofPoints(v3d);
// System.out.println("\nBounding Box: " + Arrays.toString(vbox.getBox()));
//
// BoundingBox box = BoundingBox.of(new Vector3d[]{new Vector3d(375755.655, 5718919.166, 72.052), new Vector3d(375755.655, 5718919.166, 67.772)});
// System.out.println("\nBounding Box: " + Arrays.toString(box.getBox()));
//Other available informations for BoundingBox
// System.out.println("\nCenter of Bounding Box: " + box.getCenter());
// System.out.println("\nDiagonal of Bounding Box: " + box.getDiagonal());
// System.out.println("\nVolume of Bounding Box: " + box.getVolume());
// System.out.println("\nHeight of Bounding Box: " + box.getHeight());
// System.out.println("\nWidth of Bounding Box: " + box.getWidth());
}
}
\ No newline at end of file
.metadata/.plugins/org.eclipse.core.resources/.history/8e/4029143bd6e700101110d31642d3da88
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
bht
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.*;
import
java
.
io
.
IOException
;
import
java
.
util
.*;
//
src
/
test
/
java
/.../
TestCityGmlAABB
.
java
import
java
.
net
.
URL
;
import
java
.
nio
.
file
.
Paths
;
public
class
TestCityGmlAABB
{
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"=== CityGML AABB Test ==="
);
//
---
1
)
Ask
user
which
test
case
to
run
---
Scanner
sc
=
new
Scanner
(
System
.
in
);
System
.
out
.
print
(
"Enter TestCase ID (e.g. PO_TWO_INNERS, SO_WRONG_POLY_ORIENTATION_SINGLE) "
+
"or press Enter for default: "
);
String
id
=
sc
.
nextLine
().
trim
();
//
Default
w
ä
hlen
String
resourcePath
=
TestPaths
.
PO_TWO_INNERS
;
if
(
!id.isEmpty()) {
try
{
//
Holt
TestPaths
per
Reflection
resourcePath
=
(
String
)
TestPaths
.
class
.
getField
(
id
).
get
(
null
);
}
catch
(
ReflectiveOperationException
ex
)
{
System
.
out
.
println
(
"Unknown testcase: "
+
id
+
" (using default)"
);
}
}
String
filePathForParser
=
resolveResourceOnClasspath
(
resourcePath
);
System
.
out
.
println
(
"Using file: "
+
filePathForParser
);
//
---
2
)
Load
CityGML
model
---
ValidationConfiguration
config
=
ValidationConfiguration
.
loadStandardValidationConfig
();
//
TODO
:
Study
class
model
CityDoctorModel
model
=
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
TestUtil
.
loadCityModel
(
filePathForParser
,
config
);
System
.
out
.
println
(
"Model loaded successfully.
\n
"
);
List
<
Building
>
buildings
=
model
.
getBuildings
();
//
---
3
)
Menu
:
choose
granularity
---
System
.
out
.
println
(
"
\n
Choose granularity:"
);
System
.
out
.
println
(
" 1) Polygon-level (broad-phase)"
);
System
.
out
.
println
(
" 2) Ring-level (EXTERIOR)"
);
System
.
out
.
println
(
" 3) Ring-level (INTERIOR)"
);
System
.
out
.
println
(
" 4) Vertex-level (fine-phase)"
);
System
.
out
.
println
(
" 5) All of the above"
);
System
.
out
.
print
(
"Your choice [1-5]: "
);
int
choice
=
readChoice
(
sc
,
1
,
5
);
boolean
doPolygon
=
(
choice
==
1
||
choice
==
5
);
boolean
doExtRing
=
(
choice
==
2
||
choice
==
5
);
boolean
doIntRing
=
(
choice
==
3
||
choice
==
5
);
boolean
doVertex
=
(
choice
==
4
||
choice
==
5
);
//
---
4
)
Run
the
selected
modes
---
if
(
doPolygon
)
runPolygonMode
(
buildings
);
if
(
doExtRing
)
runRingMode
(
buildings
,
true
);
if
(
doIntRing
)
runRingMode
(
buildings
,
false
);
if
(
doVertex
)
runVertexMode
(
buildings
);
System
.
out
.
println
(
"
\n
=== Done ==="
);
}
//
----------
Modes
----------
private
static
void
runPolygonMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Polygon-level AABB (broad-phase)"
);
Set
<
ConcretePolygon
>
polys
=
collectAllPolygons
(
buildings
);
AABBTree
<
ConcretePolygon
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
polys
),
AABBUtils
::
getAABB
);
System
.
out
.
println
(
"Polygons: "
+
polys
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runRingMode
(
List
<
Building
>
buildings
,
boolean
exterior
)
{
String
label
=
exterior
?
"EXTERIOR"
:
"INTERIOR"
;
System
.
out
.
println
(
"
\n
> Ring-level AABB ("
+
label
+
")"
);
Set
<
LinearRing
>
rings
=
exterior
?
collectExteriorRings
(
buildings
)
:
collectInteriorRings
(
buildings
);
AABBTree
<
LinearRing
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
rings
),
AABBUtils
::
computeAABBFromRing
);
System
.
out
.
println
(
label
+
" rings: "
+
rings
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runVertexMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Vertex-level AABB (fine-phase)"
);
Set
<
Vertex
>
verts
=
collectAllVertices
(
buildings
);
AABBTree
<
Vertex
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
verts
),
AABBUtils
::
computeAABBFromVertex
);
System
.
out
.
println
(
"Vertices: "
+
verts
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
//
----------
Collectors
----------
/**
Collects
all
ConcretePolygons
(
unique
)
via
visitor
.
*/
private
static
Set
<
ConcretePolygon
>
collectAllPolygons
(
List
<
Building
>
buildings
)
{
Set
<
ConcretePolygon
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
set
.
add
(
poly
.
getOriginal
());
}
});
}
return
set
;
}
/**
Collects
all
EXTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectExteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
LinearRing
ext
=
poly
.
getOriginal
().
getExteriorRing
();
if
(
ext
!= null) set.add(ext);
}
});
}
return
set
;
}
/**
Collects
all
INTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectInteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
List
<
LinearRing
>
inner
=
poly
.
getOriginal
().
getInnerRings
();
if
(
inner
!= null && !inner.isEmpty()) {
set
.
addAll
(
inner
);
}
}
});
}
return
set
;
}
/**
Collects
all
vertices
(
unique
)
from
both
exterior
and
interior
rings
.
*/
private
static
Set
<
Vertex
>
collectAllVertices
(
List
<
Building
>
buildings
)
{
Set
<
Vertex
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
ConcretePolygon
cp
=
poly
.
getOriginal
();
LinearRing
ext
=
cp
.
getExteriorRing
();
if
(
ext
!= null) set.addAll(ext.getVertices());
List
<
LinearRing
>
inner
=
cp
.
getInnerRings
();
if
(
inner
!= null) {
for
(
LinearRing
lr
:
inner
)
set
.
addAll
(
lr
.
getVertices
());
}
}
});
}
return
set
;
}
//
----------
Utils
----------
/*
Helper
method
reads
choice
of
the
user
*/
private
static
int
readChoice
(
Scanner
sc
,
int
min
,
int
max
)
{
while
(
true
)
{
String
s
=
sc
.
nextLine
().
trim
();
try
{
int
v
=
Integer
.
parseInt
(
s
);
if
(
v
>=
min
&&
v
<=
max
)
return
v
;
}
catch
(
NumberFormatException
ignored
)
{}
System
.
out
.
print
(
"Please enter a number between "
+
min
+
" and "
+
max
+
": "
);
}
}
/*
Helper
method
Pathfinder
*/
private
static
String
resolveResourceOnClasspath
(
String
resourcePath
)
{
String
rp
=
normalizeResourcePath
(
resourcePath
);
//
1
)
Klassenpfad
via
Class
.
getResource
URL
url
=
TestCityGmlAABB
.
class
.
getResource
(
rp
);
//
2
)
Klassenpfad
via
Context
-
ClassLoader
:
if
(
url
==
null
)
{
ClassLoader
cl
=
Thread
.
currentThread
().
getContextClassLoader
();
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
url
=
cl
.
getResource
(
noSlash
);
}
//
3
)
Wenn
gefunden
:
in
Pfad
umwandeln
if
(
url
!= null) {
try
{
return
Paths
.
get
(
url
.
toURI
()).
toString
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Konnte Resource-URI nicht auflösen: "
+
url
,
e
);
}
}
//
4
)
Fallbacks
:
Projekt
-
relative
Kandidaten
pr
ü
fen
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
String
[]
candidates
=
{
"src/test/resources/"
+
noSlash
,
"src/main/resources/"
+
noSlash
,
resourcePath
//
falls
bereits
ein
echter
Dateipfad
ü
bergeben
wurde
};
for
(
String
cand
:
candidates
)
{
java
.
nio
.
file
.
Path
p
=
java
.
nio
.
file
.
Paths
.
get
(
cand
);
if
(
java
.
nio
.
file
.
Files
.
exists
(
p
))
{
return
p
.
toAbsolutePath
().
toString
();
}
}
throw
new
IllegalArgumentException
(
"Resource nicht im Klassenpfad gefunden: "
+
resourcePath
+
" (versucht als: "
+
rp
+
")"
);
}
/*
//
F
Ü
R
ALLE
F
Ä
LLE
zur
Zeit
REDUNDAD
private
static
String
normalizeResourcePath
(
String
path
)
{
String
p
=
path
.
replace
(
'\\'
,
'/'
);
//
Quellordner
-
Pr
ä
fixe
entfernen
,
falls
mit
ü
bergeben
if
(
p
.
startsWith
(
"src/test/resources/"
))
{
p
=
p
.
substring
(
"src/test/resources/"
.
length
());
}
else
if
(
p
.
startsWith
(
"src/main/resources/"
))
{
p
=
p
.
substring
(
"src/main/resources/"
.
length
());
}
//
F
ü
r
Class
.
getResource
:
f
ü
hrenden
Slash
setzen
if
(
!p.startsWith("/")) p = "/" + p;
return
p
;
}
*/
}
.metadata/.plugins/org.eclipse.core.resources/.history/9/70170b79f1e700101110d31642d3da88
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
bht
;
/**
*
Represents
a
CityGML
test
model
with
metadata
for
easier
handling
in
tests
.
*/
public
class
TestModel
{
/**
A
short
unique
ID
(
e
.
g
.
"PO_TWO_INNERS"
,
"SO_NOT_WATERTIGHT"
).
*/
private
final
String
id
;
/**
Path
to
the
GML
file
(
classpath
or
relative
path
under
src
/
test
/
resources
).
*/
private
final
String
resourcePath
;
/**
Human
-
readable
description
of
the
test
case
.
*/
private
final
String
description
;
/**
Category
of
test
(
e
.
g
.
"PO"
=
polygon
,
"SO"
=
solid
,
"LR"
=
linear
ring
).
*/
private
final
String
category
;
/**
Optional
:
Author
or
source
of
the
model
(
if
useful
for
tracing
).
*/
private
final
String
source
;
/**
Optional
:
Known
type
of
geometry
error
(
e
.
g
.
"ring not closed"
,
"not watertight"
).
*/
private
final
String
errorType
;
//
---
Constructor
---
public
TestModel
(
String
id
,
String
resourcePath
,
String
description
,
String
category
,
String
source
,
String
errorType
)
{
this
.
id
=
id
;
this
.
resourcePath
=
resourcePath
;
this
.
description
=
description
;
this
.
category
=
category
;
this
.
source
=
source
;
this
.
errorType
=
errorType
;
}
//
---
Getters
---
public
String
getId
()
{
return
id
;
}
public
String
getResourcePath
()
{
return
resourcePath
;
}
public
String
getDescription
()
{
return
description
;
}
public
String
getCategory
()
{
return
category
;
}
public
String
getSource
()
{
return
source
;
}
public
String
getErrorType
()
{
return
errorType
;
}
@
Override
public
String
toString
()
{
return
"["
+
id
+
"] "
+
description
+
" ("
+
resourcePath
+
")"
;
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/93/40a561e452e900101245d5e14ea95888
0 → 100644
View file @
c67a5961
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
bht
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
systemtest
.
TestUtil
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.*;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.*;
import
java
.
io
.
IOException
;
import
java
.
util
.*;
//
src
/
test
/
java
/.../
TestCityGmlAABB
.
java
import
java
.
net
.
URL
;
import
java
.
nio
.
file
.
Paths
;
public
class
TestCityGmlAABB
{
public
static
void
main
(
String
[]
args
)
throws
CityGmlParseException
,
IOException
,
InvalidGmlFileException
{
System
.
out
.
println
(
"=== CityGML AABB Test ==="
);
//
---
1
)
Ask
user
which
test
case
to
run
---
Scanner
sc
=
new
Scanner
(
System
.
in
);
System
.
out
.
print
(
"Enter TestCase ID (e.g. PO_TWO_INNERS, SO_WRONG_POLY_ORIENTATION_SINGLE) "
+
"or press Enter for default: "
);
String
id
=
sc
.
nextLine
().
trim
();
//
Default
w
ä
hlen
String
resourcePath
=
TestPaths
.
PO_TWO_INNERS
;
if
(
!id.isEmpty()) {
try
{
//
Holt
TestPaths
per
Reflection
resourcePath
=
(
String
)
TestPaths
.
class
.
getField
(
id
).
get
(
null
);
}
catch
(
ReflectiveOperationException
ex
)
{
System
.
out
.
println
(
"Unknown testcase: "
+
id
+
" (using default)"
);
}
}
String
filePathForParser
=
resolveResourceOnClasspath
(
resourcePath
);
System
.
out
.
println
(
"Using file: "
+
filePathForParser
);
//
---
2
)
Load
CityGML
model
---
ValidationConfiguration
config
=
ValidationConfiguration
.
loadStandardValidationConfig
();
//
TODO
:
Study
class
model
CityDoctorModel
model
=
TestUtil
.
loadCityModel
(
filePathForParser
,
config
);
System
.
out
.
println
(
"Model loaded successfully.
\n
"
);
List
<
Building
>
buildings
=
model
.
getBuildings
();
//
---
3
)
Menu
:
choose
granularity
---
System
.
out
.
println
(
"
\n
Choose granularity:"
);
System
.
out
.
println
(
" 1) Polygon-level (broad-phase)"
);
System
.
out
.
println
(
" 2) Ring-level (EXTERIOR)"
);
System
.
out
.
println
(
" 3) Ring-level (INTERIOR)"
);
System
.
out
.
println
(
" 4) Vertex-level (fine-phase)"
);
System
.
out
.
println
(
" 5) All of the above"
);
System
.
out
.
print
(
"Your choice [1-5]: "
);
int
choice
=
readChoice
(
sc
,
1
,
5
);
boolean
doPolygon
=
(
choice
==
1
||
choice
==
5
);
boolean
doExtRing
=
(
choice
==
2
||
choice
==
5
);
boolean
doIntRing
=
(
choice
==
3
||
choice
==
5
);
boolean
doVertex
=
(
choice
==
4
||
choice
==
5
);
//
---
4
)
Run
the
selected
modes
---
if
(
doPolygon
)
runPolygonMode
(
buildings
);
if
(
doExtRing
)
runRingMode
(
buildings
,
true
);
if
(
doIntRing
)
runRingMode
(
buildings
,
false
);
if
(
doVertex
)
runVertexMode
(
buildings
);
System
.
out
.
println
(
"
\n
=== Done ==="
);
}
//
----------
Modes
----------
private
static
void
runPolygonMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Polygon-level AABB (broad-phase)"
);
Set
<
ConcretePolygon
>
polys
=
collectAllPolygons
(
buildings
);
AABBTree
<
ConcretePolygon
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
polys
),
AABBUtils
::
getAABB
);
System
.
out
.
println
(
"Polygons: "
+
polys
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runRingMode
(
List
<
Building
>
buildings
,
boolean
exterior
)
{
String
label
=
exterior
?
"EXTERIOR"
:
"INTERIOR"
;
System
.
out
.
println
(
"
\n
> Ring-level AABB ("
+
label
+
")"
);
Set
<
LinearRing
>
rings
=
exterior
?
collectExteriorRings
(
buildings
)
:
collectInteriorRings
(
buildings
);
AABBTree
<
LinearRing
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
rings
),
AABBUtils
::
computeAABBFromRing
);
System
.
out
.
println
(
label
+
" rings: "
+
rings
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
private
static
void
runVertexMode
(
List
<
Building
>
buildings
)
{
System
.
out
.
println
(
"
\n
> Vertex-level AABB (fine-phase)"
);
Set
<
Vertex
>
verts
=
collectAllVertices
(
buildings
);
AABBTree
<
Vertex
>
bvh
=
new
AABBTree
<>(
new
ArrayList
<>(
verts
),
AABBUtils
::
computeAABBFromVertex
);
System
.
out
.
println
(
"Vertices: "
+
verts
.
size
());
if
(
bvh
.
getRoot
()
!= null) {
System
.
out
.
print
(
"Root AABB: "
);
bvh
.
getRoot
().
aabb
.
print
();
}
}
//
----------
Collectors
----------
/**
Collects
all
ConcretePolygons
(
unique
)
via
visitor
.
*/
private
static
Set
<
ConcretePolygon
>
collectAllPolygons
(
List
<
Building
>
buildings
)
{
Set
<
ConcretePolygon
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
set
.
add
(
poly
.
getOriginal
());
}
});
}
return
set
;
}
/**
Collects
all
EXTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectExteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
LinearRing
ext
=
poly
.
getOriginal
().
getExteriorRing
();
if
(
ext
!= null) set.add(ext);
}
});
}
return
set
;
}
/**
Collects
all
INTERIOR
rings
(
unique
).
*/
private
static
Set
<
LinearRing
>
collectInteriorRings
(
List
<
Building
>
buildings
)
{
Set
<
LinearRing
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
List
<
LinearRing
>
inner
=
poly
.
getOriginal
().
getInnerRings
();
if
(
inner
!= null && !inner.isEmpty()) {
set
.
addAll
(
inner
);
}
}
});
}
return
set
;
}
/**
Collects
all
vertices
(
unique
)
from
both
exterior
and
interior
rings
.
*/
private
static
Set
<
Vertex
>
collectAllVertices
(
List
<
Building
>
buildings
)
{
Set
<
Vertex
>
set
=
new
HashSet
<>();
for
(
Building
b
:
buildings
)
{
b
.
accept
(
new
CheckableUtilsVisitor
()
{
@
Override
public
void
check
(
Polygon
poly
)
{
ConcretePolygon
cp
=
poly
.
getOriginal
();
LinearRing
ext
=
cp
.
getExteriorRing
();
if
(
ext
!= null) set.addAll(ext.getVertices());
List
<
LinearRing
>
inner
=
cp
.
getInnerRings
();
if
(
inner
!= null) {
for
(
LinearRing
lr
:
inner
)
set
.
addAll
(
lr
.
getVertices
());
}
}
});
}
return
set
;
}
//
----------
Utils
----------
/*
Helper
method
reads
choice
of
the
user
*/
private
static
int
readChoice
(
Scanner
sc
,
int
min
,
int
max
)
{
while
(
true
)
{
String
s
=
sc
.
nextLine
().
trim
();
try
{
int
v
=
Integer
.
parseInt
(
s
);
if
(
v
>=
min
&&
v
<=
max
)
return
v
;
}
catch
(
NumberFormatException
ignored
)
{}
System
.
out
.
print
(
"Please enter a number between "
+
min
+
" and "
+
max
+
": "
);
}
}
/*
Helper
method
Pathfinder
*/
private
static
String
resolveResourceOnClasspath
(
String
resourcePath
)
{
String
rp
=
normalizeResourcePath
(
resourcePath
);
//
1
)
Klassenpfad
via
Class
.
getResource
URL
url
=
TestCityGmlAABB
.
class
.
getResource
(
rp
);
//
2
)
Klassenpfad
via
Context
-
ClassLoader
:
if
(
url
==
null
)
{
ClassLoader
cl
=
Thread
.
currentThread
().
getContextClassLoader
();
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
url
=
cl
.
getResource
(
noSlash
);
}
//
3
)
Wenn
gefunden
:
in
Pfad
umwandeln
if
(
url
!= null) {
try
{
return
Paths
.
get
(
url
.
toURI
()).
toString
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Konnte Resource-URI nicht auflösen: "
+
url
,
e
);
}
}
//
4
)
Fallbacks
:
Projekt
-
relative
Kandidaten
pr
ü
fen
String
noSlash
=
rp
.
startsWith
(
"/"
)
?
rp
.
substring
(
1
)
:
rp
;
String
[]
candidates
=
{
"src/test/resources/"
+
noSlash
,
"src/main/resources/"
+
noSlash
,
resourcePath
//
falls
bereits
ein
echter
Dateipfad
ü
bergeben
wurde
};
for
(
String
cand
:
candidates
)
{
java
.
nio
.
file
.
Path
p
=
java
.
nio
.
file
.
Paths
.
get
(
cand
);
if
(
java
.
nio
.
file
.
Files
.
exists
(
p
))
{
return
p
.
toAbsolutePath
().
toString
();
}
}
throw
new
IllegalArgumentException
(
"Resource nicht im Klassenpfad gefunden: "
+
resourcePath
+
" (versucht als: "
+
rp
+
")"
);
}
//
F
Ü
R
ALLE
F
Ä
LLE
zur
Zeit
REDUNDAD
private
static
String
normalizeResourcePath
(
String
path
)
{
String
p
=
path
.
replace
(
'\\'
,
'/'
);
//
Quellordner
-
Pr
ä
fixe
entfernen
,
falls
mit
ü
bergeben
if
(
p
.
startsWith
(
"src/test/resources/"
))
{
p
=
p
.
substring
(
"src/test/resources/"
.
length
());
}
else
if
(
p
.
startsWith
(
"src/main/resources/"
))
{
p
=
p
.
substring
(
"src/main/resources/"
.
length
());
}
//
F
ü
r
Class
.
getResource
:
f
ü
hrenden
Slash
setzen
if
(
!p.startsWith("/")) p = "/" + p;
return
p
;
}
}
Prev
1
2
3
4
5
6
…
22
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