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/9a/30233d5b506d0010133f8119b8e960f2
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
healer
.
aabb
.
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
TestHouseAABB
{
private
static
ConcretePolygon
createTrianglePolygon
(
Point
p1
,
Point
p2
,
Point
p3
)
{
ConcretePolygon
poly
=
new
ConcretePolygon
();
LinearRing
ring
=
new
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
(
p1
.
getX
(),
p1
.
getY
(),
p1
.
getZ
()));
//
Ring
schlie
ß
en
poly
.
setExteriorRing
(
ring
);
return
poly
;
}
private
static
ConcretePolygon
createQuadPolygon
(
Point
p1
,
Point
p2
,
Point
p3
,
Point
p4
)
{
ConcretePolygon
poly
=
new
ConcretePolygon
();
LinearRing
ring
=
new
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
()));
//
Ring
schlie
ß
en
poly
.
setExteriorRing
(
ring
);
return
poly
;
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/9a/70c98d9652e900101245d5e14ea95888
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
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
;
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/a/507e361753e900101245d5e14ea95888
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/a/50b5266078ea0010125ad88dcc4485e5
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
.
Map
;
import
java
.
util
.
Set
;
import
Jama
.
EigenvalueDecomposition
;
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
.
Requirement
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
RequirementType
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
ResultStatus
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
DegeneratedRingError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
PointTouchesEdgeError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
check
.
error
.
RingEdgeIntersectionError
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
Checks
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
util
.
CollectionUtils
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BoundingBox
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Edge
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Geometry
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Vertex
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
math
.
CovarianceMatrix
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
math
.
DistanceResult
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
math
.
Matrix3x3d
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
math
.
OrthogonalRegressionPlane
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
math
.
Segment3d
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
math
.
Vector3d
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
parser
.
ParserConfiguration
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
.
AABB
;
/**
*
Checks
whether
a
ring
self
intersects
.
Also
checks
if
a
point
is
too
close
to
*
an
edge
of
the
ring
.
*
*
Axis
Aligned
Boundin
Box
Early
-
Out
-
Version
of
Matthias
Betz
's Check
* @author Baris Numanoglu
*/
public class RingSelfIntCheckAABB extends Check {
private static final String EPSILON_NAME = "minVertexDistance";
// check requirement class for default parameters
private double degeneratedRingTolerance = 0.01;
private double epsilon = Checks.MIN_VERTEX_DISTANCE_DEFAULT;
private static final List<CheckId> dependencies;
static {
ArrayList<CheckId> deps = new ArrayList<>();
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);
dependencies = Collections.unmodifiableList(deps);
}
@Override
public void init(Map<String, String> parameters, ParserConfiguration config) {
String epsilonString = parameters.get(EPSILON_NAME);
if (epsilonString != null) {
epsilon = Double.parseDouble(epsilonString);
}
if (parameters.containsKey(Requirement.DEGENERATED_RING_TOLERANCE)) {
degeneratedRingTolerance = Double.parseDouble(parameters.get(Requirement.DEGENERATED_RING_TOLERANCE));
}
}
@Override
public void check(LinearRing lr) {
checkRingJava(lr);
}
private void checkRingJava(LinearRing lr) {
// keep original behavior (tiny/degenerate detection first)
List<Vertex> vertices = lr.getVertices();
Vector3d centroid = CovarianceMatrix.getCentroid(vertices);
EigenvalueDecomposition ed = OrthogonalRegressionPlane.decompose(vertices, centroid);
if (checkEigenvalues(lr, vertices, ed)) {
return; // error added, stop here
}
List<Edge> edges = getEdgesForRing(lr);
// --- NEW: Broad-phase AABB for "point touches edge" test ---
// Precompute padded AABBs for all edges (padding = epsilon)
List<EdgeBox> edgeBoxes = new ArrayList<>(edges.size());
for (Edge e : edges) {
edgeBoxes.add(new EdgeBox(e, edgeAabb(e.getFrom(), e.getTo(), epsilon)));
}
// Optimized "point touches edge": first filter by padded edge AABB
for (EdgeBox eb : edgeBoxes) {
if (checkForPointsTouchingEdgeBroadPhase(lr, eb)) {
return;
}
}
// --- Original pairwise edge test, now with AABB early-out ---
for (int i = 0; i < edges.size() - 1; i++) {
Edge e1 = edges.get(i);
EdgeBox eb1 = edgeBoxes.get(i);
for (int j = i + 1; j < edges.size(); j++) {
Edge e2 = edges.get(j);
// share a vertex? skip
if (e1.getConnectionPoint(e2) != null) {
continue;
}
//skip if AABBs don'
t
overlap
EdgeBox
eb2
=
edgeBoxes
.
get
(
j
);
if
(
!overlaps(eb1.box, eb2.box)) {
continue
;
}
//
Narrow
-
phase
distance
test
(
unchanged
)
Segment3d
s1
=
new
Segment3d
(
e1
.
getFrom
(),
e1
.
getTo
());
Segment3d
s2
=
new
Segment3d
(
e2
.
getFrom
(),
e2
.
getTo
());
DistanceResult
dr
=
s1
.
getDistanceResult
(
s2
);
if
(
dr
.
distance
()
<
epsilon
)
{
CheckError
err
=
new
RingEdgeIntersectionError
(
lr
,
e1
,
e2
,
dr
.
point1
());
CheckResult
cr
=
new
CheckResult
(
this
,
ResultStatus
.
ERROR
,
err
);
lr
.
addCheckResult
(
cr
);
return
;
}
}
}
//
no
errors
detected
CheckResult
cr
=
new
CheckResult
(
this
,
ResultStatus
.
OK
,
null
);
lr
.
addCheckResult
(
cr
);
}
private
boolean
checkEigenvalues
(
LinearRing
lr
,
List
<
Vertex
>
points
,
EigenvalueDecomposition
ed
)
{
Matrix3x3d
mat
=
new
Matrix3x3d
(
ed
.
getV
().
getArray
());
List
<
Vector3d
>
rotatedVertices
=
new
ArrayList
<>();
for
(
Vertex
v
:
points
)
{
rotatedVertices
.
add
(
mat
.
mult
(
v
));
}
BoundingBox
bbox
=
BoundingBox
.
ofPoints
(
rotatedVertices
);
int
nrOfEigenvaluesBelowTolerance
=
0
;
if
(
bbox
.
getWidth
()
<
degeneratedRingTolerance
)
{
nrOfEigenvaluesBelowTolerance
++;
}
if
(
bbox
.
getHeight
()
<
degeneratedRingTolerance
)
{
nrOfEigenvaluesBelowTolerance
++;
}
if
(
bbox
.
getDepth
()
<
degeneratedRingTolerance
)
{
nrOfEigenvaluesBelowTolerance
++;
}
if
(
nrOfEigenvaluesBelowTolerance
>=
2
)
{
CheckError
err
=
new
DegeneratedRingError
(
lr
);
lr
.
addCheckResult
(
new
CheckResult
(
this
,
ResultStatus
.
ERROR
,
err
));
return
true
;
}
return
false
;
}
/**
*
Original
narrow
-
phase
"point near edge"
with
a
broad
-
phase
AABB
filter
.
*/
private
boolean
checkForPointsTouchingEdgeBroadPhase
(
LinearRing
lr
,
EdgeBox
eb
)
{
Segment3d
seg
=
new
Segment3d
(
eb
.
edge
.
getFrom
(),
eb
.
edge
.
getTo
());
for
(
Vertex
v
:
lr
.
getVertices
())
{
//
skip
endpoints
if
(
v
==
eb
.
edge
.
getFrom
()
||
v
==
eb
.
edge
.
getTo
())
{
continue
;
}
//
Broad
-
phase
:
reject
if
vertex
is
outside
padded
edge
AABB
if
(
!eb.box.encloses(v.getX(), v.getY(), v.getZ())) {
continue
;
}
//
Narrow
-
phase
:
exact
segment
-
point
distance
if
(
seg
.
getDistance
(
v
)
<
epsilon
)
{
CheckError
err
=
new
PointTouchesEdgeError
(
lr
,
eb
.
edge
,
v
);
CheckResult
cr
=
new
CheckResult
(
this
,
ResultStatus
.
ERROR
,
err
);
lr
.
addCheckResult
(
cr
);
return
true
;
}
}
return
false
;
}
private
List
<
Edge
>
getEdgesForRing
(
LinearRing
lr
)
{
List
<
Edge
>
edges
=
new
ArrayList
<>();
Geometry
geom
=
lr
.
getParent
().
getParent
();
for
(
int
i
=
0
;
i
<
lr
.
getVertices
().
size
()
-
1
;
i
++)
{
Vertex
v1
=
lr
.
getVertices
().
get
(
i
);
Vertex
v2
=
lr
.
getVertices
().
get
(
i
+
1
);
Edge
e
=
geom
.
getEdge
(
v1
,
v2
);
if
(
e
==
null
)
{
throw
new
IllegalStateException
(
"Edge between v1="
+
v1
+
" to v2="
+
v2
+
" is missing"
);
}
edges
.
add
(
e
);
}
return
edges
;
}
@
Override
public
List
<
CheckId
>
getDependencies
()
{
return
dependencies
;
}
@
Override
public
Set
<
Requirement
>
appliesToRequirements
()
{
return
CollectionUtils
.
singletonSet
(
Requirement
.
R_GE_R_SELF_INTERSECTION
);
}
@
Override
public
RequirementType
getType
()
{
return
RequirementType
.
GEOMETRY
;
}
@
Override
public
Check
createNewInstance
()
{
return
new
RingSelfIntCheckAABB
();
}
@
Override
public
CheckId
getCheckId
()
{
return
CheckId
.
C_GE_R_SELF_INTERSECTION
;
}
//
TODO
AUSLAGERN
!!!
/*
========
AABB
helpers
(
broad
-
phase
)
========
*/
private
static
final
class
EdgeBox
{
final
Edge
edge
;
final
AABB
box
;
EdgeBox
(
Edge
edge
,
AABB
box
)
{
this
.
edge
=
edge
;
this
.
box
=
box
;
}
}
/**
Builds
a
padded
AABB
around
a
segment
(
two
vertices
).
*/
private
static
AABB
edgeAabb
(
Vertex
a
,
Vertex
b
,
double
pad
)
{
double
minX
=
Math
.
min
(
a
.
getX
(),
b
.
getX
())
-
pad
;
double
minY
=
Math
.
min
(
a
.
getY
(),
b
.
getY
())
-
pad
;
double
minZ
=
Math
.
min
(
a
.
getZ
(),
b
.
getZ
())
-
pad
;
double
maxX
=
Math
.
max
(
a
.
getX
(),
b
.
getX
())
+
pad
;
double
maxY
=
Math
.
max
(
a
.
getY
(),
b
.
getY
())
+
pad
;
double
maxZ
=
Math
.
max
(
a
.
getZ
(),
b
.
getZ
())
+
pad
;
return
new
AABB
(
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
);
}
/**
Returns
true
if
two
AABBs
overlap
(
inclusive
).
*/
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/a3/40d4c0da7cea0010125ad88dcc4485e5
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
;
}
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/a9/f0bc3f46f1e800101776afd2c6cb3760
deleted
100644 → 0
View file @
e087346b
<?xml version="1.0" encoding="utf-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
de.hft.stuttgart
</groupId>
<artifactId>
CityDoctorParent
</artifactId>
<version>
3.17.2
</version>
</parent>
<properties>
<versionString>
${project.version}-${git.commit.id.abbrev}
</versionString>
</properties>
<artifactId>
CityDoctorModel
</artifactId>
<name>
CityDoctorModel
</name>
<dependencies>
<dependency>
<groupId>
org.citygml4j
</groupId>
<artifactId>
citygml4j-core
</artifactId>
</dependency>
<dependency>
<groupId>
org.citygml4j
</groupId>
<artifactId>
citygml4j-xml
</artifactId>
</dependency>
<dependency>
<groupId>
de.hft.stuttgart
</groupId>
<artifactId>
citygml4j-quality-ade
</artifactId>
</dependency>
<dependency>
<groupId>
gov.nist.math
</groupId>
<artifactId>
jama
</artifactId>
</dependency>
<dependency>
<groupId>
org.jogamp.gluegen
</groupId>
<artifactId>
gluegen-rt-main
</artifactId>
</dependency>
<dependency>
<groupId>
org.jogamp.jogl
</groupId>
<artifactId>
jogl-all-main
</artifactId>
</dependency>
<dependency>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.apache.logging.log4j
</groupId>
<artifactId>
log4j-api
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.logging.log4j
</groupId>
<artifactId>
log4j-core
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.yaml
</groupId>
<artifactId>
snakeyaml
</artifactId>
</dependency>
<dependency>
<groupId>
org.locationtech.proj4j
</groupId>
<artifactId>
proj4j
</artifactId>
</dependency>
<dependency>
<groupId>
org.locationtech.proj4j
</groupId>
<artifactId>
proj4j-epsg
</artifactId>
</dependency>
<dependency>
<groupId>
commons-io
</groupId>
<artifactId>
commons-io
</artifactId>
<scope>
compile
</scope>
</dependency>
<dependency>
<groupId>
org.locationtech.jts
</groupId>
<artifactId>
jts-core
</artifactId>
</dependency>
<dependency>
<groupId>
io.github.earcut4j
</groupId>
<artifactId>
earcut4j
</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>
src/main/resources
</directory>
<filtering>
true
</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>
pl.project13.maven
</groupId>
<artifactId>
git-commit-id-plugin
</artifactId>
<version>
4.9.10
</version>
<executions>
<execution>
<id>
get-the-git-infos
</id>
<goals>
<goal>
revision
</goal>
</goals>
</execution>
</executions>
<configuration>
<dotGitDirectory>
${project.basedir}/../../.git
</dotGitDirectory>
<prefix>
git
</prefix>
<verbose>
false
</verbose>
<generateGitPropertiesFile>
true
</generateGitPropertiesFile>
<generateGitPropertiesFilename>
${project.build.outputDirectory}/git.properties
</generateGitPropertiesFilename>
<gitDescribe>
<skip>
false
</skip>
<always>
false
</always>
</gitDescribe>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
.metadata/.plugins/org.eclipse.core.resources/.history/ab/c07a27be71e900101245d5e14ea95888
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
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
.
healing
.*;
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
=
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/ae/300a0879f1e700101110d31642d3da88
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
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/af/80f574e75fea0010125ad88dcc4485e5
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/b5/605de4fbf0e700101110d31642d3da88
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
;
import
java
.
util
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.
AABB
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.
BVHStructures
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.
Point
;
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
TestDummyAABB
{
/**
*
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/b5/d04bfe656bea0010125ad88dcc4485e5
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Vertex
;
import
java
.
util
.*;
//
import
java
.
util
.
List
;
/**
*
@
author
Baris
Numanoglu
*
*
Utility
class
providing
AABB
-
related
helper
methods
.
*
*
Contains
functionality
for
computing
axis
-
aligned
bounding
boxes
(
AABBs
)
*
from
geometric
data
structures
such
as
{@
link
ConcretePolygon
}
or
{@
link
LinearRing
}.
*
*
All
methods
are
static
.
*/
public
class
AABBUtils
{
public
static
AABB
getAABB
(
ConcretePolygon
poly
)
{
LinearRing
ring
=
poly
.
getExteriorRing
();
if
(
ring
==
null
)
return
null
;
return
computeAABBFromRing
(
ring
);
}
/**
*
Computes
an
AABB
from
a
LinearRing
by
iterating
over
its
vertices
.
*
*
@
param
ring
the
LinearRing
whose
vertices
define
the
AABB
*
@
return
AABB
enclosing
the
ring
;
returns
an
empty
AABB
if
the
ring
has
no
vertices
*/
public
static
AABB
computeAABBFromRing
(
LinearRing
ring
)
{
if
(
ring
==
null
||
ring
.
getVertices
()
==
null
||
ring
.
getVertices
().
isEmpty
())
{
return
new
AABB
(
Double
.
POSITIVE_INFINITY
,
Double
.
POSITIVE_INFINITY
,
Double
.
POSITIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
);
}
double
minX
=
Double
.
POSITIVE_INFINITY
;
double
minY
=
Double
.
POSITIVE_INFINITY
;
double
minZ
=
Double
.
POSITIVE_INFINITY
;
double
maxX
=
Double
.
NEGATIVE_INFINITY
;
double
maxY
=
Double
.
NEGATIVE_INFINITY
;
double
maxZ
=
Double
.
NEGATIVE_INFINITY
;
for
(
Vertex
v
:
ring
.
getVertices
())
{
double
x
=
v
.
getX
();
double
y
=
v
.
getY
();
double
z
=
v
.
getZ
();
minX
=
Math
.
min
(
minX
,
x
);
minY
=
Math
.
min
(
minY
,
y
);
minZ
=
Math
.
min
(
minZ
,
z
);
maxX
=
Math
.
max
(
maxX
,
x
);
maxY
=
Math
.
max
(
maxY
,
y
);
maxZ
=
Math
.
max
(
maxZ
,
z
);
}
return
new
AABB
(
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
);
}
/**
*
PREMORDIAL
:
substitutes
the
earlier
semantic
of
AABB
-
Point
-
Init
.
*
Computes
the
min
and
max
bounds
(
6
doubles
)
from
two
points
.
*
*
@
param
p1
the
first
point
*
@
param
p2
the
second
point
*
@
return
an
array
of
6
doubles
:
[
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
]
*/
public
static
double
[]
extractBoundsFromPoints
(
Point
p1
,
Point
p2
)
{
double
minX
=
Math
.
min
(
p1
.
getX
(),
p2
.
getX
());
double
minY
=
Math
.
min
(
p1
.
getY
(),
p2
.
getY
());
double
minZ
=
Math
.
min
(
p1
.
getZ
(),
p2
.
getZ
());
double
maxX
=
Math
.
max
(
p1
.
getX
(),
p2
.
getX
());
double
maxY
=
Math
.
max
(
p1
.
getY
(),
p2
.
getY
());
double
maxZ
=
Math
.
max
(
p1
.
getZ
(),
p2
.
getZ
());
return
new
double
[]
{
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
};
}
////////////////////////////////////////////////////////////////////////////////////////////
/**
*
Computes
an
AABB
for
a
single
vertex
(
degenerate
AABB
with
min
=
max
=
vertex
coordinates
).
*
*
@
param
vertex
the
vertex
to
wrap
in
an
AABB
*
@
return
AABB
centered
at
the
vertex
position
*/
public
static
AABB
computeAABBFromVertex
(
Vertex
vertex
)
{
if
(
vertex
==
null
)
{
//
Return
a
degenerate
AABB
with
infinite
bounds
if
vertex
is
null
return
new
AABB
(
Double
.
POSITIVE_INFINITY
,
Double
.
POSITIVE_INFINITY
,
Double
.
POSITIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
);
}
double
x
=
vertex
.
getX
();
double
y
=
vertex
.
getY
();
double
z
=
vertex
.
getZ
();
//
AABB
is
degenerate
here
:
min
=
max
=(
x
,
y
,
z
)
return
new
AABB
(
x
,
y
,
z
,
x
,
y
,
z
);
}
/**
Returns
true
if
the
AABB
is
(
nearly
)
flat
in
at
least
two
axes
.
*/
public
static
boolean
isDegenerate
(
AABB
aabb
,
double
tol
)
{
double
dx
=
aabb
.
getMaxX
()
-
aabb
.
getMinX
();
double
dy
=
aabb
.
getMaxY
()
-
aabb
.
getMinY
();
double
dz
=
aabb
.
getMaxZ
()
-
aabb
.
getMinZ
();
int
flatAxes
=
0
;
if
(
dx
<=
tol
)
flatAxes
++;
if
(
dy
<=
tol
)
flatAxes
++;
if
(
dz
<=
tol
)
flatAxes
++;
return
flatAxes
>=
2
;
//
cannot
host
3
distinct
points
in
3
D
}
/**
*
Counts
distinct
vertices
of
a
ring
using
a
tolerance
.
*
Implementation
:
uniform
quantization
(
grid
hashing
)
for
speed
and
determinism
.
*/
public
static
int
countDistinctVertices
(
LinearRing
ring
,
double
tol
)
{
if
(
ring
==
null
||
ring
.
getVertices
()
==
null
)
return
0
;
//
Use
a
quantization
resolution
based
on
tol
(
avoid
div
by
zero
).
final
double
q
=
(
tol
>
0
)
?
tol
:
1e-9
;
//
Hash
set
of
quantized
integer
triplets
"ix|iy|iz"
Set
<
Long
>
buckets
=
new
HashSet
<>(
ring
.
getVertices
().
size
()
*
2
);
for
(
Vertex
v
:
ring
.
getVertices
())
{
long
ix
=
Math
.
round
(
v
.
getX
()
/
q
);
long
iy
=
Math
.
round
(
v
.
getY
()
/
q
);
long
iz
=
Math
.
round
(
v
.
getZ
()
/
q
);
//
pack
into
a
64
-
bit
key
(
simple
mixing
;
safe
if
ranges
are
reasonable
)
long
key
=
mix3
(
ix
,
iy
,
iz
);
buckets
.
add
(
key
);
}
return
buckets
.
size
();
}
//
TODO
replace
with
older
hash
functions
from
project
//
Simple
3
D
integer
mix
to
a
64
-
bit
key
(
Xorshift
-
ish
)
from
JavaDoc
private
static
long
mix3
(
long
x
,
long
y
,
long
z
)
{
long
h
=
x
*
73856093L
^
y
*
19349663L
^
z
*
83492791L
;
//
final
avalanche
h
^=
(
h
>>>
33
);
h
*=
0xff51afd7ed558ccdL
;
h
^=
(
h
>>>
33
);
h
*=
0xc4ceb9fe1a85ec53L
;
h
^=
(
h
>>>
33
);
return
h
;
}
/*
COMING
SOON
*/
}
.metadata/.plugins/org.eclipse.core.resources/.history/b6/80ee5ae452e900101245d5e14ea95888
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/b7/30af50337eea0010125ad88dcc4485e5
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
import
java
.
io
.
PrintStream
;
//
TODO
:
Change
Point
-
Init
semantics
to
Double
-
Init
/**
*
Represents
a
3
D
line
segment
defined
by
a
start
and
end
point
.
*
Useful
for
geometric
computations
like
intersection
tests
,
*
ray
casting
,
or
clipping
against
bounding
volumes
such
as
AABBs
.
*/
public
class
Line
{
private
Point
start
;
private
Point
end
;
public
Line
()
{
this
.
start
=
new
Point
();
this
.
end
=
new
Point
();
}
public
Line
(
Point
start
,
Point
end
)
{
this
.
start
=
start
;
this
.
end
=
end
;
}
public
Point
getStart
()
{
return
start
;
}
public
Point
getEnd
()
{
return
end
;
}
//
Calculates
Bounding
Box
for
this
Line
public
AABB
getAABB
()
{
//
return
new
AABB
(
start
,
end
)
return
new
AABB
(
start
.
getX
(),
start
.
getY
(),
start
.
getZ
(),
end
.
getX
(),
end
.
getY
(),
end
.
getZ
());
}
/*
*
calculates
the
square
of
length
of
the
line
*
to
avoid
squarerooth
-
operation
*
*/
public
double
getLengthSquared
()
{
double
dx
=
end
.
getX
()
-
start
.
getX
();
double
dy
=
end
.
getY
()
-
start
.
getY
();
double
dz
=
end
.
getZ
()
-
start
.
getZ
();
return
dx
*
dx
+
dy
*
dy
+
dz
*
dz
;
}
//
Direction
vector
public
Point
getDir
()
{
return
new
Point
(
end
.
getX
()
-
start
.
getX
(),
end
.
getY
()
-
start
.
getY
(),
end
.
getZ
()
-
start
.
getZ
()
);
}
//
Normal
vector
public
Point
getNormDir
()
{
double
length
=
Math
.
sqrt
(
getLengthSquared
());
if
(
length
==
0
)
{
return
new
Point
(
0
,
0
,
0
);
}
return
new
Point
(
(
end
.
getX
()
-
start
.
getX
())
/
length
,
(
end
.
getY
()
-
start
.
getY
())
/
length
,
(
end
.
getZ
()
-
start
.
getZ
())
/
length
);
}
public
void
print
()
{
System
.
out
.
println
(
"Line from "
+
start
+
" to "
+
end
);
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/bc/305422177eea0010125ad88dcc4485e5
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
bht
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Vertex
;
import
java
.
util
.
Arrays
;
import
java
.
util
.
List
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
geometry
.*;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.*;
//<-
evtl
*
geomCheks
hier
verlagern
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.*;
/**
*
Manual
test
runner
for
basic
geometry
checks
with
AABB
involvement
.
*
Without
JUnit
:
prints
results
directly
to
the
console
.
*/
public
class
GeometryChecksWithAABBTest
{
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
"=== Geometry Checks with AABB – Manual Test Runner ==="
);
//
testTooFewPoints
();
testNestedRings
();
testRingSelfIntersection
();
testSolidSelfIntersection
();
System
.
out
.
println
(
"
\n
=== Test run finished ==="
);
}
//
--------------------------------------------------------------
//
NestedRingsCheck
//
--------------------------------------------------------------
private
static
void
testNestedRings
()
{
System
.
out
.
println
(
"
\n
[TEST] NestedRingsCheck"
);
//
outer
ring
LinearRing
outer
=
new
LinearRing
(
LinearRing
.
LinearRingType
.
EXTERIOR
);
outer
.
addAllVertices
(
Arrays
.
asList
(
new
Vertex
(
0
,
0
,
0
),
new
Vertex
(
1
,
0
,
0
),
new
Vertex
(
1
,
1
,
0
),
new
Vertex
(
0
,
1
,
0
),
new
Vertex
(
0
,
0
,
0
)
));
ConcretePolygon
p
=
new
ConcretePolygon
();
p
.
setExteriorRing
(
outer
);
//
inner
ring
1
LinearRing
inner1
=
new
LinearRing
(
LinearRing
.
LinearRingType
.
INTERIOR
);
inner1
.
addAllVertices
(
Arrays
.
asList
(
new
Vertex
(
0.2
,
0.2
,
0
),
new
Vertex
(
0.8
,
0.2
,
0
),
new
Vertex
(
0.8
,
0.8
,
0
),
new
Vertex
(
0.2
,
0.8
,
0
),
new
Vertex
(
0.2
,
0.2
,
0
)
));
//
inner
ring
2
inside
inner
ring
1
LinearRing
inner2
=
new
LinearRing
(
LinearRing
.
LinearRingType
.
INTERIOR
);
inner2
.
addAllVertices
(
Arrays
.
asList
(
new
Vertex
(
0.4
,
0.4
,
0
),
new
Vertex
(
0.6
,
0.4
,
0
),
new
Vertex
(
0.6
,
0.6
,
0
),
new
Vertex
(
0.4
,
0.6
,
0
),
new
Vertex
(
0.4
,
0.4
,
0
)
));
p
.
addInteriorRing
(
inner1
);
p
.
addInteriorRing
(
inner2
);
NestedRingsCheckAABB
check
=
new
NestedRingsCheckAABB
();
check
.
check
(
p
);
System
.
out
.
println
(
" - Should detect nested rings: "
+
p
.
containsAnyError
());
}
//
--------------------------------------------------------------
//
RingSelfIntCheck
//
--------------------------------------------------------------
private
static
void
testRingSelfIntersection
()
{
System
.
out
.
println
(
"
\n
[TEST] RingSelfIntCheck"
);
LinearRing
ring
=
new
LinearRing
(
LinearRing
.
LinearRingType
.
EXTERIOR
);
ring
.
addAllVertices
(
Arrays
.
asList
(
new
Vertex
(
0
,
0
,
0
),
new
Vertex
(
1
,
1
,
0
),
new
Vertex
(
1
,
0
,
0
),
new
Vertex
(
0
,
1
,
0
),
new
Vertex
(
0
,
0
,
0
)
));
ConcretePolygon
p
=
new
ConcretePolygon
();
p
.
setExteriorRing
(
ring
);
Geometry
g
=
new
Geometry
(
GeometryType
.
SOLID
,
Lod
.
LOD2
);
g
.
addPolygon
(
p
);
//
ensures
parent
links
exist
g
.
updateEdgesAndVertices
();
RingSelfIntCheckAABB
check
=
new
RingSelfIntCheckAABB
();
check
.
check
(
ring
);
System
.
out
.
println
(
" - Should detect self-intersection: "
+
ring
.
containsAnyError
());
}
//
--------------------------------------------------------------
//
SolidSelfIntCheck
//
--------------------------------------------------------------
private
static
void
testSolidSelfIntersection
()
{
System
.
out
.
println
(
"
\n
[TEST] SolidSelfIntCheck"
);
//
first
triangle
ConcretePolygon
p1
=
new
ConcretePolygon
();
LinearRing
r1
=
new
LinearRing
(
LinearRing
.
LinearRingType
.
EXTERIOR
);
r1
.
addAllVertices
(
Arrays
.
asList
(
new
Vertex
(
0
,
0
,
0
),
new
Vertex
(
1
,
0
,
0
),
new
Vertex
(
1
,
1
,
0
),
new
Vertex
(
0
,
0
,
0
)
));
p1
.
setExteriorRing
(
r1
);
//
second
triangle
overlapping
the
first
ConcretePolygon
p2
=
new
ConcretePolygon
();
LinearRing
r2
=
new
LinearRing
(
LinearRing
.
LinearRingType
.
EXTERIOR
);
r2
.
addAllVertices
(
Arrays
.
asList
(
new
Vertex
(
0
,
0
,
0
),
new
Vertex
(
1
,
1
,
0
),
new
Vertex
(
0
,
1
,
0
),
new
Vertex
(
0
,
0
,
0
)
));
p2
.
setExteriorRing
(
r2
);
Geometry
solid
=
new
Geometry
(
GeometryType
.
SOLID
,
Lod
.
LOD2
);
solid
.
getPolygons
().
addAll
(
List
.
of
(
p1
,
p2
));
SolidSelfIntCheckAABB
check
=
new
SolidSelfIntCheckAABB
();
check
.
check
(
solid
);
System
.
out
.
println
(
" - Should detect solid self-intersection: "
+
solid
.
containsAnyError
());
}
}
.metadata/.plugins/org.eclipse.core.resources/.history/bc/906d2f05d5e700101110d31642d3da88
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
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/c/70da4f49f1e700101110d31642d3da88
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/c0/6091b0b52699001017e0d034282fa54d
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"
;
//
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/c1/7096723af4e700101110d31642d3da88
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
import
java
.
util
.*;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.
AABB
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.
BVHStructures
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
checks
.
aabb
.
Point
;
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
TestDummyAABB
{
/**
*
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/c3/f0ac3dad7cea0010125ad88dcc4485e5
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
bht
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
ConcretePolygon
;
//
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Edge
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
LinearRing
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Vertex
;
import
de
.
hft
.
stuttgart
.
citydoctor2
.
math
.
Vector3d
;
import
java
.
util
.*;
//
import
java
.
util
.
List
;
/**
*
@
author
Baris
Numanoglu
*
*
Utility
class
providing
AABB
-
related
helper
methods
.
*
*
Contains
functionality
for
computing
axis
-
aligned
bounding
boxes
(
AABBs
)
*
from
geometric
data
structures
such
as
{@
link
ConcretePolygon
}
or
{@
link
LinearRing
}.
*
*
All
methods
are
static
.
*/
public
class
AABBUtils
{
public
static
AABB
getAABB
(
ConcretePolygon
poly
)
{
LinearRing
ring
=
poly
.
getExteriorRing
();
if
(
ring
==
null
)
return
null
;
return
computeAABBFromRing
(
ring
);
}
/**
*
Computes
an
AABB
from
a
LinearRing
by
iterating
over
its
vertices
.
*
*
@
param
ring
the
LinearRing
whose
vertices
define
the
AABB
*
@
return
AABB
enclosing
the
ring
;
returns
an
empty
AABB
if
the
ring
has
no
vertices
*/
public
static
AABB
computeAABBFromRing
(
LinearRing
ring
)
{
if
(
ring
==
null
||
ring
.
getVertices
()
==
null
||
ring
.
getVertices
().
isEmpty
())
{
return
new
AABB
(
Double
.
POSITIVE_INFINITY
,
Double
.
POSITIVE_INFINITY
,
Double
.
POSITIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
);
}
double
minX
=
Double
.
POSITIVE_INFINITY
;
double
minY
=
Double
.
POSITIVE_INFINITY
;
double
minZ
=
Double
.
POSITIVE_INFINITY
;
double
maxX
=
Double
.
NEGATIVE_INFINITY
;
double
maxY
=
Double
.
NEGATIVE_INFINITY
;
double
maxZ
=
Double
.
NEGATIVE_INFINITY
;
for
(
Vertex
v
:
ring
.
getVertices
())
{
double
x
=
v
.
getX
();
double
y
=
v
.
getY
();
double
z
=
v
.
getZ
();
minX
=
Math
.
min
(
minX
,
x
);
minY
=
Math
.
min
(
minY
,
y
);
minZ
=
Math
.
min
(
minZ
,
z
);
maxX
=
Math
.
max
(
maxX
,
x
);
maxY
=
Math
.
max
(
maxY
,
y
);
maxZ
=
Math
.
max
(
maxZ
,
z
);
}
return
new
AABB
(
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
);
}
/**
*
PREMORDIAL
:
substitutes
the
earlier
semantic
of
AABB
-
Point
-
Init
.
*
Computes
the
min
and
max
bounds
(
6
doubles
)
from
two
points
.
*
*
@
param
p1
the
first
point
*
@
param
p2
the
second
point
*
@
return
an
array
of
6
doubles
:
[
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
]
*/
public
static
double
[]
extractBoundsFromPoints
(
Point
p1
,
Point
p2
)
{
double
minX
=
Math
.
min
(
p1
.
getX
(),
p2
.
getX
());
double
minY
=
Math
.
min
(
p1
.
getY
(),
p2
.
getY
());
double
minZ
=
Math
.
min
(
p1
.
getZ
(),
p2
.
getZ
());
double
maxX
=
Math
.
max
(
p1
.
getX
(),
p2
.
getX
());
double
maxY
=
Math
.
max
(
p1
.
getY
(),
p2
.
getY
());
double
maxZ
=
Math
.
max
(
p1
.
getZ
(),
p2
.
getZ
());
return
new
double
[]
{
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
};
}
//
NOTE
:
May
replaced
later
:
double
[]
extractBoundsFromPoints
(
List
<?
extends
Point
>
points
)??
public
static
AABB
aabbFromVector3d
(
List
<?
extends
Vector3d
>
points
)
{
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
(
Vector3d
p
:
points
)
{
minX
=
Math
.
min
(
minX
,
p
.
getX
());
minY
=
Math
.
min
(
minY
,
p
.
getY
());
minZ
=
Math
.
min
(
minZ
,
p
.
getZ
());
maxX
=
Math
.
max
(
maxX
,
p
.
getX
());
maxY
=
Math
.
max
(
maxY
,
p
.
getY
());
maxZ
=
Math
.
max
(
maxZ
,
p
.
getZ
());
}
return
new
AABB
(
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
);
}
/**
*
Computes
an
AABB
for
a
single
vertex
(
degenerate
AABB
with
min
=
max
=
vertex
coordinates
).
*
*
@
param
vertex
the
vertex
to
wrap
in
an
AABB
*
@
return
AABB
centered
at
the
vertex
position
*/
public
static
AABB
computeAABBFromVertex
(
Vertex
vertex
)
{
if
(
vertex
==
null
)
{
//
Return
a
degenerate
AABB
with
infinite
bounds
if
vertex
is
null
return
new
AABB
(
Double
.
POSITIVE_INFINITY
,
Double
.
POSITIVE_INFINITY
,
Double
.
POSITIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
);
}
double
x
=
vertex
.
getX
();
double
y
=
vertex
.
getY
();
double
z
=
vertex
.
getZ
();
//
AABB
is
degenerate
here
:
min
=
max
=(
x
,
y
,
z
)
return
new
AABB
(
x
,
y
,
z
,
x
,
y
,
z
);
}
/**
Returns
true
if
the
AABB
is
(
nearly
)
flat
in
at
least
two
axes
.
*/
public
static
boolean
isDegenerate
(
AABB
aabb
,
double
tol
)
{
double
dx
=
aabb
.
getMaxX
()
-
aabb
.
getMinX
();
double
dy
=
aabb
.
getMaxY
()
-
aabb
.
getMinY
();
double
dz
=
aabb
.
getMaxZ
()
-
aabb
.
getMinZ
();
int
flatAxes
=
0
;
if
(
dx
<=
tol
)
flatAxes
++;
if
(
dy
<=
tol
)
flatAxes
++;
if
(
dz
<=
tol
)
flatAxes
++;
return
flatAxes
>=
2
;
//
cannot
host
3
distinct
points
in
3
D
}
/**
*
Counts
distinct
vertices
of
a
ring
using
a
tolerance
.
*
Implementation
:
uniform
quantization
(
grid
hashing
)
for
speed
and
determinism
.
*/
public
static
int
countDistinctVertices
(
LinearRing
ring
,
double
tol
)
{
if
(
ring
==
null
||
ring
.
getVertices
()
==
null
)
return
0
;
//
Use
a
quantization
resolution
based
on
tol
(
avoid
div
by
zero
).
final
double
q
=
(
tol
>
0
)
?
tol
:
1e-9
;
//
Hash
set
of
quantized
integer
triplets
"ix|iy|iz"
Set
<
Long
>
buckets
=
new
HashSet
<>(
ring
.
getVertices
().
size
()
*
2
);
for
(
Vertex
v
:
ring
.
getVertices
())
{
long
ix
=
Math
.
round
(
v
.
getX
()
/
q
);
long
iy
=
Math
.
round
(
v
.
getY
()
/
q
);
long
iz
=
Math
.
round
(
v
.
getZ
()
/
q
);
//
pack
into
a
64
-
bit
key
(
simple
mixing
;
safe
if
ranges
are
reasonable
)
long
key
=
mix3
(
ix
,
iy
,
iz
);
buckets
.
add
(
key
);
}
return
buckets
.
size
();
}
//
Simple
3
D
integer
mix
to
a
64
-
bit
key
(
Xorshift
-
ish
)
from
JavaDoc
private
static
long
mix3
(
long
x
,
long
y
,
long
z
)
{
long
h
=
x
*
73856093L
^
y
*
19349663L
^
z
*
83492791L
;
//
final
avalanche
h
^=
(
h
>>>
33
);
h
*=
0xff51afd7ed558ccdL
;
h
^=
(
h
>>>
33
);
h
*=
0xc4ceb9fe1a85ec53L
;
h
^=
(
h
>>>
33
);
return
h
;
}
/**
Returns
true
if
'outer'
fully
contains
'inner'
(
inclusive
)
in
axis
-
aligned
sense
.
*/
public
static
boolean
containsAabb
(
AABB
outer
,
AABB
inner
)
{
return
outer
.
getMinX
()
<=
inner
.
getMinX
()
&&
outer
.
getMinY
()
<=
inner
.
getMinY
()
&&
outer
.
getMinZ
()
<=
inner
.
getMinZ
()
&&
outer
.
getMaxX
()
>=
inner
.
getMaxX
()
&&
outer
.
getMaxY
()
>=
inner
.
getMaxY
()
&&
outer
.
getMaxZ
()
>=
inner
.
getMaxZ
();
}
/**
Builds
a
padded
AABB
around
a
segment
(
two
vertices
).
*/
public
static
AABB
edgeAabb
(
Vertex
a
,
Vertex
b
,
double
pad
)
{
double
minX
=
Math
.
min
(
a
.
getX
(),
b
.
getX
())
-
pad
;
double
minY
=
Math
.
min
(
a
.
getY
(),
b
.
getY
())
-
pad
;
double
minZ
=
Math
.
min
(
a
.
getZ
(),
b
.
getZ
())
-
pad
;
double
maxX
=
Math
.
max
(
a
.
getX
(),
b
.
getX
())
+
pad
;
double
maxY
=
Math
.
max
(
a
.
getY
(),
b
.
getY
())
+
pad
;
double
maxZ
=
Math
.
max
(
a
.
getZ
(),
b
.
getZ
())
+
pad
;
return
new
AABB
(
minX
,
minY
,
minZ
,
maxX
,
maxY
,
maxZ
);
}
/**
Returns
true
if
two
AABBs
overlap
(
inclusive
).
*/
public
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/c8/7080726371e900101245d5e14ea95888
deleted
100644 → 0
View file @
e087346b
package
de
.
hft
.
stuttgart
.
citydoctor2
.
healing
.
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
7
…
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