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
d3605f6a
Commit
d3605f6a
authored
Feb 09, 2026
by
Numanoglu
Browse files
remove metadata
parent
e087346b
Changes
377
Hide whitespace changes
Inline
Side-by-side
.metadata/.plugins/org.eclipse.core.resources/.history/37/d0f5b8b52699001017e0d034282fa54d
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
/*-
*
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
deleted
100644 → 0
View file @
e087346b
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
…
19
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