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
2d57794b
Commit
2d57794b
authored
Mar 25, 2025
by
Beuster
Browse files
Merge remote-tracking branch 'origin/dev' into dev_cpp_code_conversion
parents
040af2d2
660255ab
Pipeline
#11013
passed with stage
in 1 minute and 38 seconds
Changes
241
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TopLevelTransportFeature.java
0 → 100644
View file @
2d57794b
package
de.hft.stuttgart.citydoctor2.datastructure
;
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.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
org.citygml4j.core.model.deprecated.transportation.TransportationComplex
;
import
org.citygml4j.core.model.transportation.Railway
;
import
org.citygml4j.core.model.transportation.Road
;
import
org.citygml4j.core.model.transportation.Square
;
import
org.citygml4j.core.model.transportation.Track
;
import
org.citygml4j.core.model.transportation.Waterway
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
import
java.util.ArrayList
;
import
java.util.List
;
public
class
TopLevelTransportFeature
extends
TransportationSpace
{
private
final
List
<
TransportSection
>
sections
=
new
ArrayList
<>();
private
final
List
<
TransportSection
>
intersections
=
new
ArrayList
<>();
public
static
TopLevelTransportFeature
from
(
Track
t
)
{
TopLevelTransportFeature
top
=
new
TopLevelTransportFeature
(
TransportationType
.
TRACK
);
top
.
setGmlObject
(
t
);
return
top
;
}
public
static
TopLevelTransportFeature
from
(
Road
r
)
{
TopLevelTransportFeature
top
=
new
TopLevelTransportFeature
(
TransportationType
.
ROAD
);
top
.
setGmlObject
(
r
);
return
top
;
}
public
static
TopLevelTransportFeature
from
(
Waterway
w
)
{
TopLevelTransportFeature
top
=
new
TopLevelTransportFeature
(
TransportationType
.
WATERWAY
);
top
.
setGmlObject
(
w
);
return
top
;
}
public
static
TopLevelTransportFeature
from
(
Railway
r
)
{
TopLevelTransportFeature
top
=
new
TopLevelTransportFeature
(
TransportationType
.
RAILWAY
);
top
.
setGmlObject
(
r
);
return
top
;
}
public
static
TopLevelTransportFeature
from
(
Square
s
)
{
TopLevelTransportFeature
top
=
new
TopLevelTransportFeature
(
TransportationType
.
SQUARE
);
top
.
setGmlObject
(
s
);
return
top
;
}
public
static
TopLevelTransportFeature
from
(
TransportationComplex
tc
)
{
TopLevelTransportFeature
top
=
new
TopLevelTransportFeature
(
TransportationType
.
TRANSPORTATION_COMPLEX
);
top
.
setGmlObject
(
tc
);
return
top
;
}
private
TopLevelTransportFeature
(
TransportationType
type
)
{
super
(
type
);
}
public
void
addSection
(
TransportSection
section
)
{
sections
.
add
(
section
);
}
public
void
addIntersection
(
TransportSection
section
)
{
intersections
.
add
(
section
);
}
public
List
<
TransportSection
>
getSections
()
{
return
sections
;
}
public
List
<
TransportSection
>
getIntersections
()
{
return
intersections
;
}
@Override
public
void
reCreateGeometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
super
.
reCreateGeometries
(
factory
,
config
);
for
(
TransportSection
section
:
sections
)
{
section
.
reCreateGeometries
(
factory
,
config
);
}
for
(
TransportSection
section
:
intersections
)
{
section
.
reCreateGeometries
(
factory
,
config
);
}
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
for
(
TransportSection
section
:
sections
)
{
if
(
section
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
for
(
TransportSection
section
:
intersections
)
{
if
(
section
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
return
false
;
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearAllContainedCheckResults
();
for
(
TransportSection
section
:
sections
)
{
section
.
clearAllContainedCheckResults
();
}
for
(
TransportSection
section
:
intersections
)
{
section
.
clearAllContainedCheckResults
();
}
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
for
(
TransportSection
section
:
sections
)
{
section
.
collectContainedErrors
(
errors
);
}
for
(
TransportSection
section
:
intersections
)
{
section
.
collectContainedErrors
(
errors
);
}
}
@Override
public
boolean
containsAnyError
()
{
boolean
hasError
=
super
.
containsAnyError
();
if
(
hasError
)
{
return
true
;
}
for
(
TransportSection
section
:
sections
)
{
if
(
section
.
containsAnyError
())
{
return
true
;
}
}
for
(
TransportSection
section
:
intersections
)
{
if
(
section
.
containsAnyError
())
{
return
true
;
}
}
return
false
;
}
@Override
public
void
accept
(
Check
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
}
for
(
TransportSection
section
:
sections
)
{
section
.
accept
(
c
);
}
for
(
TransportSection
section
:
intersections
)
{
section
.
accept
(
c
);
}
}
@Override
public
void
unsetGmlGeometries
()
{
super
.
unsetGmlGeometries
();
for
(
TransportSection
section
:
sections
)
{
section
.
unsetGmlGeometries
();
}
for
(
TransportSection
section
:
intersections
)
{
section
.
unsetGmlGeometries
();
}
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
this
;
}
@Override
public
String
toString
()
{
return
"TopLevelTransportFeature [id="
+
getGmlId
()
+
"]"
;
}
@Override
public
void
prepareForChecking
()
{
super
.
prepareForChecking
();
for
(
TransportSection
section
:
sections
)
{
section
.
prepareForChecking
();
}
for
(
TransportSection
section
:
intersections
)
{
section
.
prepareForChecking
();
}
}
@Override
public
void
clearMetaInformation
()
{
super
.
clearMetaInformation
();
for
(
TransportSection
section
:
sections
)
{
section
.
clearMetaInformation
();
}
for
(
TransportSection
section
:
intersections
)
{
section
.
clearMetaInformation
();
}
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
for
(
TransportSection
section
:
sections
)
{
section
.
collectInstances
(
handler
);
}
for
(
TransportSection
section
:
intersections
)
{
section
.
collectInstances
(
handler
);
}
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
TransportationObject
originalTo
=
(
TransportationObject
)
original
;
for
(
TransportSection
section
:
sections
)
{
section
.
fillValues
(
originalTo
,
handler
);
}
for
(
TransportSection
section
:
intersections
)
{
section
.
fillValues
(
originalTo
,
handler
);
}
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
TopLevelTransportFeature
(
type
);
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TrafficAreaObject.java
0 → 100644
View file @
2d57794b
package
de.hft.stuttgart.citydoctor2.datastructure
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CityGmlUtils
;
import
org.citygml4j.core.model.transportation.AuxiliaryTrafficArea
;
import
org.citygml4j.core.model.transportation.TrafficArea
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurface
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty
;
public
class
TrafficAreaObject
extends
TransportationObject
{
public
enum
TrafficAreaType
{
TRAFFIC_AREA
,
AUXILIARY_TRAFFIC_AREA
}
public
TrafficAreaObject
(
TrafficAreaType
trafficAreaType
)
{
if
(
trafficAreaType
==
TrafficAreaType
.
TRAFFIC_AREA
)
{
setType
(
TransportationType
.
TRAFFIC_AREA
);
}
else
{
setType
(
TransportationType
.
AUXILLIARY_TRAFFIC_AREA
);
}
}
@Override
public
void
reCreateGeometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
for
(
Geometry
geom
:
getGeometries
())
{
if
(
geom
instanceof
ImplicitGeometryHolder
)
{
continue
;
}
if
(
geom
.
getType
()
==
GeometryType
.
MULTI_SURFACE
)
{
MultiSurface
ms
=
CityGmlUtils
.
createMultiSurface
(
geom
,
factory
,
config
);
switch
(
type
)
{
case
TRAFFIC_AREA:
TrafficArea
ta
=
(
TrafficArea
)
super
.
getGmlObject
();
setMultiSurfaceAccordingToLod
(
ta
,
ms
,
geom
.
getLod
());
break
;
case
AUXILLIARY_TRAFFIC_AREA:
AuxiliaryTrafficArea
ata
=
(
AuxiliaryTrafficArea
)
super
.
getGmlObject
();
setMultiSurfaceAccordingToLod
(
ata
,
ms
,
geom
.
getLod
());
break
;
}
}
else
{
throw
new
IllegalStateException
(
"Geometry in TransportationObject cannot be of type "
+
geom
.
getType
()
+
". Only MultiSurface allowed"
);
}
}
}
private
void
setMultiSurfaceAccordingToLod
(
AuxiliaryTrafficArea
ata
,
MultiSurface
ms
,
Lod
lod
)
{
switch
(
lod
)
{
case
LOD0:
ata
.
setLod0MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD1:
ata
.
setLod1MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD2:
ata
.
setLod2MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD3:
ata
.
setLod3MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD4:
ata
.
getDeprecatedProperties
().
setLod4MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
default
:
throw
new
IllegalStateException
(
"cannot set geometry with LOD for AuxiliaryTrafficArea: "
+
lod
);
}
}
private
void
setMultiSurfaceAccordingToLod
(
TrafficArea
ta
,
MultiSurface
ms
,
Lod
lod
)
{
switch
(
lod
)
{
case
LOD0:
ta
.
setLod0MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD1:
ta
.
setLod1MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD2:
ta
.
setLod2MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD3:
ta
.
setLod3MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD4:
ta
.
getDeprecatedProperties
().
setLod4MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
default
:
throw
new
IllegalStateException
(
"cannot set geometry with LOD for TrafficArea: "
+
lod
);
}
}
@Override
public
void
unsetGmlGeometries
()
{
switch
(
type
)
{
case
TRAFFIC_AREA:
TrafficArea
ta
=
(
TrafficArea
)
super
.
getGmlObject
();
ta
.
setLod2MultiSurface
(
null
);
ta
.
setLod3MultiSurface
(
null
);
ta
.
getDeprecatedProperties
().
setLod4MultiSurface
(
null
);
break
;
case
AUXILLIARY_TRAFFIC_AREA:
AuxiliaryTrafficArea
ata
=
(
AuxiliaryTrafficArea
)
super
.
getGmlObject
();
ata
.
setLod0MultiSurface
(
null
);
ata
.
setLod1MultiSurface
(
null
);
ata
.
setLod2MultiSurface
(
null
);
ata
.
setLod3MultiSurface
(
null
);
ata
.
getDeprecatedProperties
().
setLod4MultiSurface
(
null
);
break
;
}
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
this
;
}
@Override
public
String
toString
()
{
return
"TrafficArea [id="
+
getGmlId
()
+
"]"
;
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TrafficSpaceObject.java
0 → 100644
View file @
2d57794b
package
de.hft.stuttgart.citydoctor2.datastructure
;
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.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CityGmlUtils
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
org.citygml4j.core.model.core.AbstractSpace
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurface
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty
;
import
java.util.ArrayList
;
import
java.util.List
;
public
class
TrafficSpaceObject
extends
TransportationObject
{
private
final
List
<
TrafficAreaObject
>
trafficAreas
=
new
ArrayList
<>();
public
enum
TrafficSpaceType
{
TRAFFIC_SPACE
,
AUXILIARY_TRAFFIC_SPACE
}
public
TrafficSpaceObject
(
TrafficSpaceType
trafficSpaceType
)
{
if
(
trafficSpaceType
==
TrafficSpaceType
.
TRAFFIC_SPACE
)
{
super
.
setType
(
TransportationType
.
TRAFFIC_SPACE
);
}
else
{
super
.
setType
(
TransportationType
.
AUXILLIARY_TRAFFIC_SPACE
);
}
}
public
List
<
TrafficAreaObject
>
getTrafficAreas
()
{
return
trafficAreas
;
}
public
void
addTrafficArea
(
TrafficAreaObject
trafficAreaObject
)
{
trafficAreas
.
add
(
trafficAreaObject
);
}
@Override
public
void
reCreateGeometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
for
(
Geometry
geom
:
getGeometries
())
{
if
(
geom
instanceof
ImplicitGeometryHolder
)
{
continue
;
}
MultiSurface
ms
=
CityGmlUtils
.
createMultiSurface
(
geom
,
factory
,
config
);
AbstractSpace
ats
=
(
AbstractSpace
)
super
.
getGmlObject
();
setMultiSurfaceAccordingToLod
(
ats
,
ms
,
geom
.
getLod
());
}
for
(
TrafficAreaObject
tao
:
trafficAreas
)
{
tao
.
reCreateGeometries
(
factory
,
config
);
}
}
private
void
setMultiSurfaceAccordingToLod
(
AbstractSpace
ats
,
MultiSurface
ms
,
Lod
lod
)
{
switch
(
lod
)
{
case
LOD0:
ats
.
setLod0MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD2:
ats
.
setLod2MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD3:
ats
.
setLod3MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
default
:
throw
new
IllegalStateException
(
"cannot set geometry with LOD for AuxiliaryTrafficSpace: "
+
lod
);
}
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
for
(
TrafficAreaObject
tao
:
trafficAreas
)
{
if
(
tao
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
return
false
;
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearAllContainedCheckResults
();
for
(
TrafficAreaObject
tao
:
trafficAreas
)
{
tao
.
clearAllContainedCheckResults
();
}
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
for
(
TrafficAreaObject
tao
:
trafficAreas
)
{
tao
.
collectContainedErrors
(
errors
);
}
}
@Override
public
boolean
containsAnyError
()
{
boolean
hasError
=
super
.
containsAnyError
();
if
(
hasError
)
{
return
true
;
}
for
(
TrafficAreaObject
tao
:
trafficAreas
)
{
if
(
tao
.
containsAnyError
())
{
return
true
;
}
}
return
false
;
}
@Override
public
void
accept
(
Check
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
}
for
(
TrafficAreaObject
tao
:
trafficAreas
)
{
tao
.
accept
(
c
);
}
}
@Override
public
void
unsetGmlGeometries
()
{
AbstractSpace
ats
=
(
AbstractSpace
)
super
.
getGmlObject
();
ats
.
setLod0MultiSurface
(
null
);
ats
.
setLod2MultiSurface
(
null
);
ats
.
setLod3MultiSurface
(
null
);
for
(
TrafficAreaObject
tao
:
trafficAreas
)
{
tao
.
unsetGmlGeometries
();
}
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
this
;
}
@Override
public
String
toString
()
{
return
"TransportationSpaceObject [id="
+
getGmlId
()
+
"]"
;
}
@Override
public
void
prepareForChecking
()
{
super
.
prepareForChecking
();
for
(
TrafficAreaObject
tao
:
trafficAreas
)
{
tao
.
prepareForChecking
();
}
}
@Override
public
void
clearMetaInformation
()
{
super
.
clearMetaInformation
();
for
(
TrafficAreaObject
tao
:
trafficAreas
)
{
tao
.
clearMetaInformation
();
}
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
for
(
TrafficAreaObject
tao
:
trafficAreas
)
{
handler
.
addInstance
(
tao
);
}
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
TrafficSpaceObject
originalTao
=
(
TrafficSpaceObject
)
original
;
for
(
TrafficAreaObject
tao
:
originalTao
.
trafficAreas
)
{
trafficAreas
.
add
(
handler
.
getCopyInstance
(
tao
));
}
super
.
setGmlObject
(
originalTao
.
getGmlObject
());
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
TrafficSpaceObject
(
null
);
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TransportSection.java
0 → 100644
View file @
2d57794b
package
de.hft.stuttgart.citydoctor2.datastructure
;
public
class
TransportSection
extends
TransportationSpace
{
public
enum
SectionType
{
SECTION
,
INTERSECTION
}
public
TransportSection
(
SectionType
sectionType
)
{
super
(
TransportationType
.
SECTION
);
if
(
sectionType
==
SectionType
.
INTERSECTION
)
{
super
.
setType
(
TransportationType
.
INTERSECTION
);
}
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TransportationObject.java
View file @
2d57794b
...
...
@@ -43,190 +43,33 @@ import java.util.List;
*
* @author Matthias Betz
*/
public
class
TransportationObject
extends
CityObject
{
public
abstract
class
TransportationObject
extends
CityObject
{
@Serial
private
static
final
long
serialVersionUID
=
-
2698907271726700390L
;
public
enum
TransportationType
{
ROAD
,
TRACK
,
RAILWAY
,
TRAFFIC_AREA
,
AUXILLIARY_TRAFFIC_AREA
,
TRANSPORTATION_COMPLEX
,
SQUARE
,
AUXILLIARY_TRAFFIC_SPACE
,
TRAFFIC_SPACE
ROAD
,
TRACK
,
RAILWAY
,
TRAFFIC_AREA
,
AUXILLIARY_TRAFFIC_AREA
,
TRANSPORTATION_COMPLEX
,
SQUARE
,
AUXILLIARY_TRAFFIC_SPACE
,
TRAFFIC_SPACE
,
WATERWAY
,
SECTION
,
INTERSECTION
}
private
AbstractCityObject
ato
;
private
final
List
<
TransportationObject
>
composesOf
=
new
ArrayList
<>(
1
);
private
final
TransportationType
type
;
protected
TransportationType
type
;
public
TransportationObject
(
TransportationType
type
)
{
this
.
type
=
type
;
}
@Override
public
FeatureType
getFeatureType
()
{
return
FeatureType
.
TRANSPORTATION
;
}
@Override
public
void
reCreateGeometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
for
(
Geometry
geom
:
getGeometries
())
{
if
(
geom
instanceof
ImplicitGeometryHolder
)
{
continue
;
}
if
(
geom
.
getType
()
==
GeometryType
.
MULTI_SURFACE
)
{
MultiSurface
ms
=
CityGmlUtils
.
createMultiSurface
(
geom
,
factory
,
config
);
switch
(
type
)
{
case
ROAD
,
TRACK
,
RAILWAY
,
SQUARE
,
TRANSPORTATION_COMPLEX:
AbstractTransportationSpace
tc
=
(
AbstractTransportationSpace
)
ato
;
setMultiSurfaceAccordingToLod
(
tc
,
ms
,
geom
.
getLod
());
break
;
case
TRAFFIC_AREA:
TrafficArea
ta
=
(
TrafficArea
)
ato
;
setMultiSurfaceAccordingToLod
(
ta
,
ms
,
geom
.
getLod
());
break
;
case
AUXILLIARY_TRAFFIC_AREA:
AuxiliaryTrafficArea
ata
=
(
AuxiliaryTrafficArea
)
ato
;
setMultiSurfaceAccordingToLod
(
ata
,
ms
,
geom
.
getLod
());
break
;
case
AUXILLIARY_TRAFFIC_SPACE
,
TRAFFIC_SPACE:
AbstractSpace
ats
=
(
AbstractSpace
)
ato
;
setMultiSurfaceAccordingToLod
(
ats
,
ms
,
geom
.
getLod
());
break
;
}
}
else
{
throw
new
IllegalStateException
(
"Geometry in TransportationObject cannot be of type "
+
geom
.
getType
()
+
". Only MultiSurface allowed"
);
}
}
for
(
TransportationObject
children
:
composesOf
)
{
children
.
reCreateGeometries
(
factory
,
config
);
}
}
private
void
setMultiSurfaceAccordingToLod
(
AbstractSpace
ats
,
MultiSurface
ms
,
Lod
lod
)
{
switch
(
lod
)
{
case
LOD0:
ats
.
setLod0MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD2:
ats
.
setLod2MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD3:
ats
.
setLod3MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
default
:
throw
new
IllegalStateException
(
"cannot set geometry with LOD for AuxiliaryTrafficSpace: "
+
lod
);
}
}
private
void
setMultiSurfaceAccordingToLod
(
AbstractTransportationSpace
tc
,
MultiSurface
ms
,
Lod
lod
)
{
switch
(
lod
)
{
case
LOD1:
tc
.
getDeprecatedProperties
().
setLod1MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD2:
tc
.
setLod2MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD3:
tc
.
setLod3MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD4:
tc
.
getDeprecatedProperties
().
setLod4MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
default
:
throw
new
IllegalStateException
(
"cannot set geometry with LOD for TransportationComplex: "
+
lod
);
}
}
private
void
setMultiSurfaceAccordingToLod
(
AuxiliaryTrafficArea
ata
,
MultiSurface
ms
,
Lod
lod
)
{
switch
(
lod
)
{
case
LOD0:
ata
.
setLod0MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD1:
ata
.
setLod1MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD2:
ata
.
setLod2MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD3:
ata
.
setLod3MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD4:
ata
.
getDeprecatedProperties
().
setLod4MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
default
:
throw
new
IllegalStateException
(
"cannot set geometry with LOD for AuxiliaryTrafficArea: "
+
lod
);
}
}
private
void
setMultiSurfaceAccordingToLod
(
TrafficArea
ta
,
MultiSurface
ms
,
Lod
lod
)
{
switch
(
lod
)
{
case
LOD2:
ta
.
setLod2MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD3:
ta
.
setLod3MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD4:
ta
.
getDeprecatedProperties
().
setLod4MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
default
:
throw
new
IllegalStateException
(
"cannot set geometry with LOD for TrafficArea: "
+
lod
);
}
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
for
(
TransportationObject
to
:
composesOf
)
{
if
(
to
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
return
false
;
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearAllContainedCheckResults
();
for
(
TransportationObject
to
:
composesOf
)
{
to
.
clearAllContainedCheckResults
();
}
protected
TransportationObject
()
{
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
for
(
TransportationObject
to
:
composesOf
)
{
to
.
collectContainedErrors
(
errors
);
}
}
@Override
public
boolean
containsAnyError
()
{
boolean
hasError
=
super
.
containsAnyError
();
if
(
hasError
)
{
return
true
;
}
for
(
TransportationObject
to
:
composesOf
)
{
if
(
to
.
containsAnyError
())
{
return
true
;
}
}
return
false
;
void
setType
(
TransportationType
type
)
{
this
.
type
=
type
;
}
@Override
public
void
accept
(
Check
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
}
for
(
TransportationObject
to
:
composesOf
)
{
to
.
accept
(
c
);
}
public
FeatureType
getFeatureType
()
{
return
FeatureType
.
TRANSPORTATION
;
}
@Override
...
...
@@ -234,50 +77,11 @@ public class TransportationObject extends CityObject {
return
ato
;
}
@Override
public
void
unsetGmlGeometries
()
{
switch
(
type
)
{
case
ROAD
,
TRACK
,
RAILWAY
,
SQUARE
,
TRANSPORTATION_COMPLEX:
AbstractTransportationSpace
tc
=
(
AbstractTransportationSpace
)
ato
;
tc
.
getDeprecatedProperties
().
setLod1MultiSurface
(
null
);
tc
.
setLod2MultiSurface
(
null
);
tc
.
setLod3MultiSurface
(
null
);
tc
.
getDeprecatedProperties
().
setLod4MultiSurface
(
null
);
break
;
case
TRAFFIC_AREA:
TrafficArea
ta
=
(
TrafficArea
)
ato
;
ta
.
setLod2MultiSurface
(
null
);
ta
.
setLod3MultiSurface
(
null
);
ta
.
getDeprecatedProperties
().
setLod4MultiSurface
(
null
);
break
;
case
AUXILLIARY_TRAFFIC_AREA:
AuxiliaryTrafficArea
ata
=
(
AuxiliaryTrafficArea
)
ato
;
ata
.
setLod0MultiSurface
(
null
);
ata
.
setLod1MultiSurface
(
null
);
ata
.
setLod2MultiSurface
(
null
);
ata
.
setLod3MultiSurface
(
null
);
ata
.
getDeprecatedProperties
().
setLod4MultiSurface
(
null
);
break
;
case
AUXILLIARY_TRAFFIC_SPACE
,
TRAFFIC_SPACE:
AbstractSpace
ats
=
(
AbstractSpace
)
ato
;
ats
.
setLod0MultiSurface
(
null
);
ats
.
setLod2MultiSurface
(
null
);
ats
.
setLod3MultiSurface
(
null
);
break
;
}
}
public
void
setGmlObject
(
AbstractCityObject
tc
)
{
ato
=
tc
;
}
public
void
addChild
(
TransportationObject
subTrans
)
{
composesOf
.
add
(
subTrans
);
}
public
List
<
TransportationObject
>
getChildren
()
{
return
composesOf
;
}
public
TransportationType
getTransportationType
()
{
return
type
;
...
...
@@ -288,43 +92,17 @@ public class TransportationObject extends CityObject {
return
"TransportationObject [id="
+
getGmlId
()
+
"]"
;
}
@Override
public
void
prepareForChecking
()
{
super
.
prepareForChecking
();
for
(
TransportationObject
child
:
composesOf
)
{
child
.
prepareForChecking
();
}
}
@Override
public
void
clearMetaInformation
()
{
super
.
clearMetaInformation
();
for
(
TransportationObject
child
:
composesOf
)
{
child
.
clearMetaInformation
();
}
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
for
(
TransportationObject
to
:
composesOf
)
{
handler
.
addInstance
(
to
);
}
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
TransportationObject
originalTo
=
(
TransportationObject
)
original
;
for
(
TransportationObject
to
:
originalTo
.
composesOf
)
{
composesOf
.
add
(
handler
.
getCopyInstance
(
to
));
}
ato
=
originalTo
.
ato
;
}
@Override
public
Copyable
createCopyInstance
()
{
return
n
ew
TransportationObject
(
type
)
;
return
n
ull
;
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TransportationSpace.java
0 → 100644
View file @
2d57794b
package
de.hft.stuttgart.citydoctor2.datastructure
;
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.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.CityGmlUtils
;
import
de.hft.stuttgart.citydoctor2.utils.CopyHandler
;
import
de.hft.stuttgart.citydoctor2.utils.Copyable
;
import
org.citygml4j.core.model.core.AbstractSpace
;
import
org.citygml4j.core.model.transportation.AbstractTransportationSpace
;
import
org.citygml4j.core.util.geometry.GeometryFactory
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurface
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurfaceProperty
;
import
java.util.ArrayList
;
import
java.util.List
;
public
abstract
class
TransportationSpace
extends
TransportationObject
{
private
final
List
<
TrafficSpaceObject
>
trafficSpaces
=
new
ArrayList
<>();
private
final
List
<
TrafficSpaceObject
>
auxTrafficSpaces
=
new
ArrayList
<>();
protected
TransportationSpace
(
TransportationType
type
)
{
super
(
type
);
}
public
List
<
TrafficSpaceObject
>
getTrafficSpaces
()
{
return
trafficSpaces
;
}
public
List
<
TrafficSpaceObject
>
getAuxTrafficSpaces
()
{
return
auxTrafficSpaces
;
}
public
void
addTrafficSpace
(
TrafficSpaceObject
t
)
{
trafficSpaces
.
add
(
t
);
}
public
void
addAuxTrafficSpace
(
TrafficSpaceObject
t
)
{
auxTrafficSpaces
.
add
(
t
);
}
@Override
public
void
reCreateGeometries
(
GeometryFactory
factory
,
ParserConfiguration
config
)
{
for
(
Geometry
geom
:
getGeometries
())
{
if
(
geom
instanceof
ImplicitGeometryHolder
)
{
continue
;
}
if
(
geom
.
getType
()
==
GeometryType
.
MULTI_SURFACE
)
{
MultiSurface
ms
=
CityGmlUtils
.
createMultiSurface
(
geom
,
factory
,
config
);
if
(
super
.
getGmlObject
()
instanceof
AbstractTransportationSpace
ats
)
{
setMultiSurfaceAccordingToLod
(
ats
,
ms
,
geom
.
getLod
());
}
else
{
AbstractSpace
as
=
(
AbstractSpace
)
super
.
getGmlObject
();
setMultiSurfaceAccordingToLod
(
as
,
ms
,
geom
.
getLod
());
}
}
else
{
throw
new
IllegalStateException
(
"Geometry in TransportationObject cannot be of type "
+
geom
.
getType
()
+
". Only MultiSurface allowed"
);
}
}
for
(
TrafficSpaceObject
spaces
:
trafficSpaces
)
{
spaces
.
reCreateGeometries
(
factory
,
config
);
}
for
(
TrafficSpaceObject
spaces
:
auxTrafficSpaces
)
{
spaces
.
reCreateGeometries
(
factory
,
config
);
}
}
private
void
setMultiSurfaceAccordingToLod
(
AbstractTransportationSpace
ats
,
MultiSurface
ms
,
Lod
lod
)
{
switch
(
lod
)
{
case
LOD0
->
ats
.
setLod0MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
case
LOD1
->
ats
.
getDeprecatedProperties
().
setLod1MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
case
LOD2
->
ats
.
setLod2MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
case
LOD3
->
ats
.
setLod3MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
case
LOD4
->
ats
.
getDeprecatedProperties
().
setLod4MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
default
->
throw
new
IllegalStateException
(
"cannot set geometry with LOD for AuxiliaryTrafficSpace: "
+
lod
);
}
}
private
void
setMultiSurfaceAccordingToLod
(
AbstractSpace
as
,
MultiSurface
ms
,
Lod
lod
)
{
switch
(
lod
)
{
case
LOD0:
as
.
setLod0MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD2:
as
.
setLod2MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
case
LOD3:
as
.
setLod3MultiSurface
(
new
MultiSurfaceProperty
(
ms
));
break
;
default
:
throw
new
IllegalStateException
(
"cannot set geometry with LOD for AuxiliaryTrafficSpace: "
+
lod
);
}
}
@Override
public
boolean
containsError
(
CheckId
checkIdentifier
)
{
boolean
hasError
=
super
.
containsError
(
checkIdentifier
);
if
(
hasError
)
{
return
true
;
}
for
(
TrafficSpaceObject
to
:
trafficSpaces
)
{
if
(
to
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
for
(
TrafficSpaceObject
to
:
auxTrafficSpaces
)
{
if
(
to
.
containsError
(
checkIdentifier
))
{
return
true
;
}
}
return
false
;
}
@Override
public
void
clearAllContainedCheckResults
()
{
super
.
clearAllContainedCheckResults
();
for
(
TrafficSpaceObject
to
:
trafficSpaces
)
{
to
.
clearAllContainedCheckResults
();
}
for
(
TrafficSpaceObject
to
:
auxTrafficSpaces
)
{
to
.
clearAllContainedCheckResults
();
}
}
@Override
public
void
collectContainedErrors
(
List
<
CheckError
>
errors
)
{
super
.
collectContainedErrors
(
errors
);
for
(
TrafficSpaceObject
to
:
trafficSpaces
)
{
to
.
collectContainedErrors
(
errors
);
}
for
(
TrafficSpaceObject
to
:
auxTrafficSpaces
)
{
to
.
collectContainedErrors
(
errors
);
}
}
@Override
public
boolean
containsAnyError
()
{
boolean
hasError
=
super
.
containsAnyError
();
if
(
hasError
)
{
return
true
;
}
for
(
TrafficSpaceObject
to
:
trafficSpaces
)
{
if
(
to
.
containsAnyError
())
{
return
true
;
}
}
for
(
TrafficSpaceObject
to
:
auxTrafficSpaces
)
{
if
(
to
.
containsAnyError
())
{
return
true
;
}
}
return
false
;
}
@Override
public
void
accept
(
Check
c
)
{
super
.
accept
(
c
);
if
(
c
.
canExecute
(
this
))
{
c
.
check
(
this
);
}
for
(
TrafficSpaceObject
to
:
trafficSpaces
)
{
to
.
accept
(
c
);
}
for
(
TrafficSpaceObject
to
:
auxTrafficSpaces
)
{
to
.
accept
(
c
);
}
}
@Override
public
void
unsetGmlGeometries
()
{
AbstractSpace
ats
=
(
AbstractSpace
)
super
.
getGmlObject
();
ats
.
setLod0MultiSurface
(
null
);
ats
.
setLod2MultiSurface
(
null
);
ats
.
setLod3MultiSurface
(
null
);
for
(
TrafficSpaceObject
to
:
trafficSpaces
)
{
to
.
unsetGmlGeometries
();
}
for
(
TrafficSpaceObject
to
:
auxTrafficSpaces
)
{
to
.
unsetGmlGeometries
();
}
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
this
;
}
@Override
public
String
toString
()
{
return
"TransportationSpace [id="
+
getGmlId
()
+
"]"
;
}
@Override
public
void
prepareForChecking
()
{
super
.
prepareForChecking
();
for
(
TrafficSpaceObject
to
:
trafficSpaces
)
{
to
.
prepareForChecking
();
}
for
(
TrafficSpaceObject
to
:
auxTrafficSpaces
)
{
to
.
prepareForChecking
();
}
}
@Override
public
void
clearMetaInformation
()
{
super
.
clearMetaInformation
();
for
(
TrafficSpaceObject
to
:
trafficSpaces
)
{
to
.
clearMetaInformation
();
}
for
(
TrafficSpaceObject
to
:
auxTrafficSpaces
)
{
to
.
clearMetaInformation
();
}
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
for
(
TrafficSpaceObject
to
:
trafficSpaces
)
{
to
.
collectInstances
(
handler
);
}
for
(
TrafficSpaceObject
to
:
auxTrafficSpaces
)
{
to
.
collectInstances
(
handler
);
}
}
@Override
public
void
fillValues
(
Copyable
original
,
CopyHandler
handler
)
{
super
.
fillValues
(
original
,
handler
);
TransportationObject
originalTo
=
(
TransportationObject
)
original
;
for
(
TrafficSpaceObject
to
:
trafficSpaces
)
{
to
.
fillValues
(
originalTo
,
handler
);
}
for
(
TrafficSpaceObject
to
:
auxTrafficSpaces
)
{
to
.
fillValues
(
originalTo
,
handler
);
}
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Tunnel.java
View file @
2d57794b
...
...
@@ -34,6 +34,11 @@ public class Tunnel extends AbstractTunnel {
}
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
this
;
}
@Override
public
void
accept
(
Check
c
)
{
super
.
accept
(
c
);
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TunnelConstructiveElement.java
View file @
2d57794b
...
...
@@ -31,12 +31,20 @@ public class TunnelConstructiveElement extends CityObject {
private
final
org
.
citygml4j
.
core
.
model
.
tunnel
.
TunnelConstructiveElement
gmlTunnelElement
;
private
final
List
<
BoundarySurface
>
boundarySurfaceList
=
new
ArrayList
<>();
private
AbstractTunnel
parent
;
public
TunnelConstructiveElement
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
TunnelConstructiveElement
gmlObject
)
{
this
.
gmlTunnelElement
=
gmlObject
;
}
public
void
setParent
(
AbstractTunnel
parent
)
{
this
.
parent
=
parent
;
}
public
AbstractTunnel
getParent
()
{
return
parent
;
}
@Override
public
Copyable
createCopyInstance
()
{
return
new
TunnelConstructiveElement
(
gmlTunnelElement
);
...
...
@@ -60,6 +68,8 @@ public class TunnelConstructiveElement extends CityObject {
MultiSurface
ms
=
CityGmlUtils
.
createMultiSurface
(
geom
,
factory
,
config
);
setMultiSurfaceAccordingToLod
(
geom
,
ms
);
break
;
case
COMPOSITE_SURFACE:
throw
new
IllegalStateException
(
"Tunnel constructive element cannot have a composite surface geometry"
);
}
}
for
(
BoundarySurface
bs
:
boundarySurfaceList
)
{
...
...
@@ -186,6 +196,11 @@ public class TunnelConstructiveElement extends CityObject {
}
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
getParent
().
getTopLevelCityObject
();
}
@Override
public
FeatureType
getFeatureType
()
{
return
FeatureType
.
TUNNEL_CONSTRUCTION_ELEMENT
;
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TunnelHollow.java
View file @
2d57794b
...
...
@@ -43,6 +43,11 @@ public class TunnelHollow extends AbstractRoom {
parent
=
handler
.
getCopyInstance
(
oHollow
.
getParent
());
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
getParent
().
getTopLevelCityObject
();
}
@Override
public
void
collectInstances
(
CopyHandler
handler
)
{
super
.
collectInstances
(
handler
);
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/TunnelPart.java
View file @
2d57794b
...
...
@@ -22,6 +22,11 @@ public class TunnelPart extends AbstractTunnel {
return
parent
;
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
getParent
().
getTopLevelCityObject
();
}
@Override
public
FeatureType
getFeatureType
()
{
return
FeatureType
.
TUNNEL_PART
;
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/Vegetation.java
View file @
2d57794b
...
...
@@ -198,6 +198,11 @@ public class Vegetation extends CityObject {
}
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
this
;
}
public
void
setGmlObject
(
AbstractVegetationObject
avo
)
{
citygmlVegetation
=
avo
;
}
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/WaterObject.java
View file @
2d57794b
...
...
@@ -106,6 +106,11 @@ public class WaterObject extends CityObject {
gmlWater
.
getDeprecatedProperties
().
setLod1MultiSurface
(
null
);
}
@Override
public
CityObject
getTopLevelCityObject
()
{
return
this
;
}
public
void
setGmlObject
(
WaterBody
waterBody
)
{
gmlWater
=
waterBody
;
}
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3FeatureMapper.java
View file @
2d57794b
...
...
@@ -27,15 +27,14 @@ import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import
de.hft.stuttgart.citydoctor2.datastructure.BuildingRoom
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.BridgeObject.BridgeType
;
import
de.hft.stuttgart.citydoctor2.datastructure.TunnelConstructiveElement
;
import
de.hft.stuttgart.citydoctor2.datastructure.TunnelFurniture
;
import
de.hft.stuttgart.citydoctor2.datastructure.TunnelPart
;
import
de.hft.stuttgart.citydoctor2.datastructure.TransportationObject.TransportationType
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vegetation.VegetationType
;
import
de.hft.stuttgart.citydoctor2.math.graph.KDTree
;
import
de.hft.stuttgart.citydoctor2.parser.ParserConfiguration
;
import
de.hft.stuttgart.citydoctor2.utils.Localization
;
import
de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
import
org.citygml4j.core.model.CityGMLVersion
;
...
...
@@ -72,705 +71,794 @@ import java.util.Map;
public
class
Citygml3FeatureMapper
extends
ObjectWalker
{
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
Citygml3FeatureMapper
.
class
);
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
Citygml3FeatureMapper
.
class
);
private
final
CityDoctorModel
model
;
private
final
ParserConfiguration
config
;
private
final
Path
directory
;
private
final
CityDoctorModel
model
;
private
final
ParserConfiguration
config
;
private
final
Path
directory
;
private
final
CityGmlZipEntry
zipEntry
;
private
final
double
neighborDistance
;
private
Map
<
String
,
ConcretePolygon
>
polygonMap
=
new
HashMap
<>();
private
Map
<
String
,
CompositeCollection
>
compositeMap
=
new
HashMap
<>();
private
List
<
ResolvableReference
>
references
=
new
ArrayList
<>();
private
Map
<
Vertex
,
Vertex
>
vertexMap
=
new
HashMap
<>();
private
Map
<
String
,
ConcretePolygon
>
polygonMap
=
new
HashMap
<>();
private
Map
<
String
,
CompositeCollection
>
compositeMap
=
new
HashMap
<>();
private
List
<
ResolvableReference
>
references
=
new
ArrayList
<>();
private
Map
<
Vertex
,
Vertex
>
vertexMap
=
new
HashMap
<>();
public
Citygml3FeatureMapper
(
ParserConfiguration
config
,
Path
path
)
{
this
.
config
=
config
;
this
.
directory
=
path
.
getParent
();
model
=
new
CityDoctorModel
(
config
,
path
.
toFile
());
neighborDistance
=
1.8d
/
Math
.
pow
(
10
,
config
.
getNumberOfRoundingPlaces
());
zipEntry
=
null
;
}
public
static
void
parseId
(
AbstractGML
gml
,
GmlElement
gmlElement
)
{
String
id
=
gml
.
getId
();
if
(
id
!=
null
)
{
gmlElement
.
setGmlId
(
new
GmlId
(
id
));
}
}
@Override
public
void
visit
(
AbstractSpace
space
)
{
// if we are here, an AbstractSpace thing was read that is not handled in the
// other methods
}
@Override
public
void
visit
(
org
.
citygml4j
.
core
.
model
.
cityfurniture
.
CityFurniture
gmlCityFurniture
)
{
CityFurniture
cf
=
new
CityFurniture
();
cf
.
setGmlObject
(
gmlCityFurniture
);
mapAbstractOccupiedSpace
(
gmlCityFurniture
,
cf
);
resolveAndClearReferences
();
cf
.
unsetGmlGeometries
();
updateEdgesAndVertices
(
cf
);
model
.
addCityFurniture
(
cf
);
}
@Override
public
void
visit
(
org
.
citygml4j
.
core
.
model
.
generics
.
GenericOccupiedSpace
gos
)
{
GenericCityObject
gco
=
new
GenericCityObject
();
gco
.
setGmlObject
(
gos
);
GeometryProperty
<?>
agLod1
=
gos
.
getDeprecatedProperties
().
getLod1Geometry
();
GeometryProperty
<?>
agLod4
=
gos
.
getDeprecatedProperties
().
getLod4Geometry
();
if
(
agLod1
!=
null
&&
agLod1
.
getObject
()
!=
null
&&
agLod1
.
getObject
()
instanceof
MultiSurface
ms
)
{
gco
.
addGeometry
(
parseMultiSurface
(
ms
,
Lod
.
LOD1
));
}
if
(
agLod4
!=
null
&&
agLod4
.
getObject
()
!=
null
)
{
if
(
agLod4
.
getObject
()
instanceof
MultiSurface
ms
)
{
gco
.
addGeometry
(
parseMultiSurface
(
ms
,
Lod
.
LOD4
));
}
else
if
(
agLod4
.
getObject
()
instanceof
AbstractSolid
solid
)
{
gco
.
addGeometry
(
parseSolid
(
solid
,
Lod
.
LOD4
));
}
}
mapAbstractOccupiedSpace
(
gos
,
gco
);
resolveAndClearReferences
();
gco
.
unsetGmlGeometries
();
updateEdgesAndVertices
(
gco
);
model
.
addGenericCityObject
(
gco
);
}
@Override
public
void
visit
(
org
.
citygml4j
.
core
.
model
.
building
.
Building
gmlBuilding
)
{
Building
cdBuilding
=
new
Building
();
readAbstractBuilding
(
gmlBuilding
,
cdBuilding
);
for
(
BuildingPartProperty
bpProp
:
gmlBuilding
.
getBuildingParts
())
{
if
(!
bpProp
.
isSetObject
())
{
continue
;
}
BuildingPart
part
=
new
BuildingPart
(
cdBuilding
);
readAbstractBuilding
(
bpProp
.
getObject
(),
part
);
}
model
.
addBuilding
(
cdBuilding
);
}
@Override
public
void
visit
(
WaterBody
waterBody
)
{
WaterObject
wo
=
new
WaterObject
();
wo
.
setGmlObject
(
waterBody
);
mapAbstractOccupiedSpace
(
waterBody
,
wo
);
parseAndAddMultiSurface
(
waterBody
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
wo
);
parseAndAddSolid
(
waterBody
.
getDeprecatedProperties
().
getLod4Solid
(),
Lod
.
LOD4
,
wo
);
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
waterBody
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
wo
.
addBoundarySurface
(
bs
);
}
resolveAndClearReferences
();
wo
.
unsetGmlGeometries
();
updateEdgesAndVertices
(
wo
);
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
updateEdgesAndVertices
(
bs
);
}
model
.
addWater
(
wo
);
}
@Override
public
void
visit
(
LandUse
landUse
)
{
LandObject
lo
=
new
LandObject
(
landUse
);
mapAbstractThematicSurface
(
landUse
,
lo
);
finishCityObjectConstruction
(
lo
);
model
.
addLand
(
lo
);
}
@Override
public
void
visit
(
PlantCover
plantCover
)
{
Vegetation
veg
=
new
Vegetation
(
VegetationType
.
PLANT_COVER
);
veg
.
setGmlObject
(
plantCover
);
mapAbstractVegetationObject
(
plantCover
,
veg
);
parseAndAddMultiSurface
(
plantCover
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
veg
);
parseAndAddMultiSurface
(
plantCover
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
veg
);
finishCityObjectConstruction
(
veg
);
model
.
addVegetation
(
veg
);
}
@Override
public
void
visit
(
SolitaryVegetationObject
solitaryVegetationObject
)
{
Vegetation
veg
=
new
Vegetation
(
VegetationType
.
SOLITARY_VEGETATION_OBJECT
);
veg
.
setGmlObject
(
solitaryVegetationObject
);
mapAbstractVegetationObject
(
solitaryVegetationObject
,
veg
);
parseAndAddAbstractGeometry
(
solitaryVegetationObject
.
getDeprecatedProperties
().
getLod1Geometry
(),
Lod
.
LOD1
,
veg
);
parseAndAddAbstractGeometry
(
solitaryVegetationObject
.
getDeprecatedProperties
().
getLod2Geometry
(),
Lod
.
LOD2
,
veg
);
parseAndAddAbstractGeometry
(
solitaryVegetationObject
.
getDeprecatedProperties
().
getLod3Geometry
(),
Lod
.
LOD3
,
veg
);
parseAndAddAbstractGeometry
(
solitaryVegetationObject
.
getDeprecatedProperties
().
getLod4Geometry
(),
Lod
.
LOD4
,
veg
);
finishCityObjectConstruction
(
veg
);
model
.
addVegetation
(
veg
);
}
private
void
mapAbstractVegetationObject
(
AbstractVegetationObject
avo
,
Vegetation
veg
)
{
mapAbstractOccupiedSpace
(
avo
,
veg
);
}
private
void
mapAbstractOccupiedSpace
(
AbstractOccupiedSpace
aos
,
CityObject
co
)
{
mapAbstractPhysicalSpace
(
aos
,
co
);
parseImplicitGeometry
(
aos
,
co
);
}
private
void
mapAbstractPhysicalSpace
(
AbstractPhysicalSpace
aps
,
CityObject
co
)
{
mapAbstractSpace
(
aps
,
co
);
}
private
void
mapAbstractSpace
(
AbstractSpace
as
,
CityObject
co
)
{
mapAbstractFeature
(
as
,
co
);
parseAndAddMultiSurface
(
as
.
getLod0MultiSurface
(),
Lod
.
LOD0
,
co
);
parseAndAddMultiSurface
(
as
.
getLod2MultiSurface
(),
Lod
.
LOD2
,
co
);
parseAndAddMultiSurface
(
as
.
getLod3MultiSurface
(),
Lod
.
LOD3
,
co
);
parseAndAddSolid
(
as
.
getLod1Solid
(),
Lod
.
LOD1
,
co
);
parseAndAddSolid
(
as
.
getLod2Solid
(),
Lod
.
LOD2
,
co
);
parseAndAddSolid
(
as
.
getLod3Solid
(),
Lod
.
LOD3
,
co
);
parseAndAddGenericAttributes
(
as
,
co
);
}
private
void
parseAndAddGenericAttributes
(
AbstractSpace
as
,
CityObject
co
)
{
for
(
AbstractGenericAttributeProperty
aga
:
as
.
getGenericAttributes
())
{
co
.
addGenericAttribute
(
new
GenericAttribute
(
aga
));
}
}
@Override
public
void
visit
(
Bridge
bridge
)
{
BridgeObject
bo
=
new
BridgeObject
(
BridgeType
.
BRIDGE
,
bridge
);
// parse deprecated geometries
parseAndAddMultiSurface
(
bridge
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
bo
);
parseAndAddMultiSurface
(
bridge
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
bo
);
parseAndAddSolid
(
bridge
.
getDeprecatedProperties
().
getLod4Solid
(),
Lod
.
LOD4
,
bo
);
mapAbstractBridge
(
bridge
,
bo
);
for
(
BridgePartProperty
bPartProperty
:
bridge
.
getBridgeParts
())
{
if
(!
bPartProperty
.
isSetObject
())
{
continue
;
}
BridgePart
gmlBridgePart
=
bPartProperty
.
getObject
();
BridgeObject
bPart
=
new
BridgeObject
(
BridgeType
.
BRIDGE_PART
,
gmlBridgePart
);
mapAbstractBridge
(
gmlBridgePart
,
bPart
);
bo
.
addBridgePart
(
bPart
);
}
resolveAndClearReferences
();
updateEdgesAndVertices
(
bo
);
for
(
BridgeObject
part
:
bo
.
getParts
())
{
updateEdgesAndVertices
(
part
);
}
for
(
BridgeConstructiveElement
ele
:
bo
.
getConstructiveElements
())
{
updateEdgesAndVertices
(
ele
);
for
(
BoundarySurface
bs
:
ele
.
getBoundarySurfaces
())
{
updateEdgesAndVertices
(
bs
);
}
}
for
(
Installation
bi
:
bo
.
getBridgeInstallations
())
{
updateEdgesAndVertices
(
bi
);
for
(
BoundarySurface
bs
:
bi
.
getBoundarySurfaces
())
{
updateEdgesAndVertices
(
bs
);
}
}
model
.
addBridge
(
bo
);
}
private
void
mapAbstractBridge
(
AbstractBridge
ab
,
BridgeObject
bo
)
{
mapAbstractConstruction
(
ab
,
bo
);
for
(
BridgeConstructiveElementProperty
eleProp
:
ab
.
getBridgeConstructiveElements
())
{
if
(!
eleProp
.
isSetObject
())
{
continue
;
}
org
.
citygml4j
.
core
.
model
.
bridge
.
BridgeConstructiveElement
constructiveElement
=
eleProp
.
getObject
();
BridgeConstructiveElement
cdEle
=
new
BridgeConstructiveElement
(
constructiveElement
);
mapConstructiveElement
(
constructiveElement
,
cdEle
);
bo
.
addConstructiveElement
(
cdEle
);
}
List
<
BridgeInstallationProperty
>
bridgeInstallations
=
ab
.
getBridgeInstallations
();
for
(
BridgeInstallationProperty
installationProp
:
bridgeInstallations
)
{
var
gmlBi
=
installationProp
.
getObject
();
if
(
gmlBi
==
null
)
{
// ignore empty properties
continue
;
}
Installation
bi
=
mapBridgeInstallation
(
gmlBi
);
bo
.
addBridgeInstallation
(
bi
);
}
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
ab
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
updatePartOfSurface
(
bo
,
surfaceMapper
);
for
(
BoundarySurface
bs
:
bo
.
getBoundarySurfaces
())
{
updateEdgesAndVertices
(
bs
);
}
bo
.
unsetGmlGeometries
();
}
private
Installation
mapBridgeInstallation
(
BridgeInstallation
gmlBi
)
{
Installation
bi
=
new
Installation
();
bi
.
setGmlObject
(
gmlBi
);
mapAbstractOccupiedSpace
(
gmlBi
,
bi
);
GeometryProperty
<?>
lod2Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod2Geometry
();
parseAndAddAbstractGeometry
(
lod2Prop
,
Lod
.
LOD2
,
bi
);
GeometryProperty
<?>
lod3Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod3Geometry
();
parseAndAddAbstractGeometry
(
lod3Prop
,
Lod
.
LOD3
,
bi
);
GeometryProperty
<?>
lod4Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod4Geometry
();
parseAndAddAbstractGeometry
(
lod4Prop
,
Lod
.
LOD4
,
bi
);
bi
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlBi
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bi
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
p
.
setPartOfInstallation
(
bi
);
}
}
}
for
(
Geometry
geom
:
bi
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfInstallation
(
bi
);
}
}
return
bi
;
}
@Override
public
void
visit
(
Tunnel
tunnel
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Tunnel
tu
=
new
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Tunnel
();
for
(
TunnelPartProperty
tPartProperty
:
tunnel
.
getTunnelParts
())
{
if
(!
tPartProperty
.
isSetObject
())
{
continue
;
}
org
.
citygml4j
.
core
.
model
.
tunnel
.
TunnelPart
gmlTunnelPart
=
tPartProperty
.
getObject
();
TunnelPart
tPart
=
new
TunnelPart
(
tu
);
readAbstractTunnel
(
gmlTunnelPart
,
tPart
);
tu
.
addTunnelPart
(
tPart
);
}
readAbstractTunnel
(
tunnel
,
tu
);
resolveAndClearReferences
();
updateEdgesAndVertices
(
tu
);
for
(
TunnelPart
part
:
tu
.
getTunnelParts
())
{
updateEdgesAndVertices
(
part
);
}
model
.
addTunnel
(
tu
);
}
private
void
readAbstractTunnel
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
AbstractTunnel
gmlTunnel
,
AbstractTunnel
cdTunnel
)
{
mapAbstractOccupiedSpace
(
gmlTunnel
,
cdTunnel
);
cdTunnel
.
setGmlObject
(
gmlTunnel
);
// parse deprecated geometries
parseAndAddMultiSurface
(
gmlTunnel
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
cdTunnel
);
parseAndAddMultiSurface
(
gmlTunnel
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
cdTunnel
);
parseAndAddSolid
(
gmlTunnel
.
getDeprecatedProperties
().
getLod4Solid
(),
Lod
.
LOD4
,
cdTunnel
);
for
(
TunnelInstallationProperty
tiProp
:
gmlTunnel
.
getTunnelInstallations
())
{
var
gmlTi
=
tiProp
.
getObject
();
if
(
gmlTi
==
null
)
{
// ignore empty properties
continue
;
}
Installation
ti
=
mapTunnelInstallation
(
gmlTi
);
cdTunnel
.
addTunnelInstallation
(
ti
);
}
for
(
HollowSpaceProperty
thProp
:
gmlTunnel
.
getHollowSpaces
())
{
var
gmlTh
=
thProp
.
getObject
();
if
(
gmlTh
==
null
)
{
continue
;
}
TunnelHollow
br
=
mapTunnelHollow
(
gmlTh
);
cdTunnel
.
addTunnelHollow
(
br
);
}
for
(
Installation
ti
:
cdTunnel
.
getTunnelInstallations
())
{
updateEdgesAndVertices
(
ti
);
for
(
BoundarySurface
bs
:
ti
.
getBoundarySurfaces
())
{
updateEdgesAndVertices
(
bs
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
updateEdgesAndVertices
(
o
);
}
}
}
for
(
TunnelFurnitureProperty
tfProp
:
gmlTunnel
.
getTunnelFurniture
())
{
var
gmlTf
=
tfProp
.
getObject
();
if
(
gmlTf
==
null
)
{
continue
;
}
TunnelFurniture
tf
=
mapTunnelFurniture
(
gmlTf
);
cdTunnel
.
addTunnelFurniture
(
tf
);
}
for
(
TunnelConstructiveElementProperty
teProp
:
gmlTunnel
.
getTunnelConstructiveElements
())
{
var
gmlTc
=
teProp
.
getObject
();
if
(
gmlTc
==
null
)
{
continue
;
}
TunnelConstructiveElement
tc
=
mapTunnelConstructiveElement
(
gmlTc
);
cdTunnel
.
addTunnelConstructiveElement
(
tc
);
}
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlTunnel
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
updateEdgesAndVertices
(
bs
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
updateEdgesAndVertices
(
o
);
}
}
cdTunnel
.
unsetGmlGeometries
();
resolveAndClearReferences
();
updateEdgesAndVertices
(
cdTunnel
);
}
private
Installation
mapTunnelInstallation
(
TunnelInstallation
gmlTi
)
{
Installation
ti
=
new
Installation
();
ti
.
setGmlObject
(
gmlTi
);
mapAbstractOccupiedSpace
(
gmlTi
,
ti
);
GeometryProperty
<?>
lod2Prop
=
gmlTi
.
getDeprecatedProperties
().
getLod2Geometry
();
parseAndAddAbstractGeometry
(
lod2Prop
,
Lod
.
LOD2
,
ti
);
GeometryProperty
<?>
lod3Prop
=
gmlTi
.
getDeprecatedProperties
().
getLod3Geometry
();
parseAndAddAbstractGeometry
(
lod3Prop
,
Lod
.
LOD3
,
ti
);
GeometryProperty
<?>
lod4Prop
=
gmlTi
.
getDeprecatedProperties
().
getLod4Geometry
();
parseAndAddAbstractGeometry
(
lod4Prop
,
Lod
.
LOD4
,
ti
);
ti
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlTi
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
ti
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
p
.
setPartOfInstallation
(
ti
);
}
}
}
for
(
Geometry
geom
:
ti
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfInstallation
(
ti
);
}
}
return
ti
;
}
private
TunnelHollow
mapTunnelHollow
(
HollowSpace
gmlHo
)
{
TunnelHollow
tHollow
=
new
TunnelHollow
();
tHollow
.
setGmlObject
(
gmlHo
);
mapAbstractUnoccupiedSpace
(
gmlHo
,
tHollow
);
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlHo
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
tHollow
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
for
(
TunnelInstallationProperty
tiProp
:
gmlHo
.
getTunnelInstallations
())
{
var
gmlTi
=
tiProp
.
getObject
();
if
(
gmlTi
==
null
)
{
// ignore empty properties
continue
;
}
Installation
bi
=
mapTunnelInstallation
(
gmlTi
);
tHollow
.
addRoomInstallation
(
bi
);
}
for
(
TunnelFurnitureProperty
tfProp
:
gmlHo
.
getTunnelFurniture
())
{
var
gmlHref
=
tfProp
.
getHref
();
if
(
gmlHref
==
null
)
{
continue
;
}
tHollow
.
addFurnitureRef
(
tfProp
);
}
return
tHollow
;
}
private
TunnelFurniture
mapTunnelFurniture
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
TunnelFurniture
gmlTf
)
{
TunnelFurniture
tf
=
new
TunnelFurniture
();
tf
.
setGmlObject
(
gmlTf
);
mapAbstractOccupiedSpace
(
gmlTf
,
tf
);
tf
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlTf
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
tf
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
return
tf
;
}
private
TunnelConstructiveElement
mapTunnelConstructiveElement
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
TunnelConstructiveElement
gmlTe
)
{
TunnelConstructiveElement
te
=
new
TunnelConstructiveElement
(
gmlTe
);
mapAbstractOccupiedSpace
(
gmlTe
,
te
);
te
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlTe
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
te
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
return
te
;
}
private
void
updatePartOfSurface
(
BridgeObject
bo
,
SurfaceMapper
surfaceMapper
)
{
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bo
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
}
private
void
mapConstructiveElement
(
org
.
citygml4j
.
core
.
model
.
bridge
.
BridgeConstructiveElement
ele
,
BridgeConstructiveElement
bce
)
{
mapAbstractConstructiveElement
(
ele
,
bce
);
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
ele
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bce
.
addBoundarySurface
(
bs
);
}
}
private
void
mapAbstractConstructiveElement
(
org
.
citygml4j
.
core
.
model
.
bridge
.
BridgeConstructiveElement
ele
,
BridgeConstructiveElement
bce
)
{
mapAbstractOccupiedSpace
(
ele
,
bce
);
}
private
void
mapAbstractConstruction
(
AbstractConstruction
ac
,
BridgeObject
bo
)
{
mapAbstractOccupiedSpace
(
ac
,
bo
);
}
@Override
public
void
visit
(
AuxiliaryTrafficArea
ata
)
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
AUXILLIARY_TRAFFIC_AREA
);
mapAbstractThematicSurface
(
ata
,
to
);
finishTransportationMapping
(
to
);
}
@Override
public
void
visit
(
TrafficArea
ta
)
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_AREA
);
mapAbstractThematicSurface
(
ta
,
to
);
finishTransportationMapping
(
to
);
}
@Override
public
void
visit
(
Road
road
)
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
ROAD
);
mapAbstractTransportationSpace
(
road
,
to
);
finishTransportationMapping
(
to
);
}
private
void
mapAbstractThematicSurface
(
AbstractThematicSurface
ats
,
CityObject
co
)
{
mapAbstractSpaceBoundary
(
ats
,
co
);
parseAndAddMultiSurface
(
ats
.
getLod0MultiSurface
(),
Lod
.
LOD0
,
co
);
parseAndAddMultiSurface
(
ats
.
getLod1MultiSurface
(),
Lod
.
LOD1
,
co
);
parseAndAddMultiSurface
(
ats
.
getLod2MultiSurface
(),
Lod
.
LOD2
,
co
);
parseAndAddMultiSurface
(
ats
.
getLod3MultiSurface
(),
Lod
.
LOD3
,
co
);
parseAndAddMultiSurface
(
ats
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
co
);
}
private
void
mapAbstractSpaceBoundary
(
AbstractSpaceBoundary
asb
,
CityObject
co
)
{
mapAbstractCityObject
(
asb
,
co
);
}
private
void
mapAbstractCityObject
(
AbstractCityObject
aco
,
CityObject
to
)
{
mapAbstractFeatureWithLifespan
(
aco
,
to
);
}
private
void
mapAbstractFeatureWithLifespan
(
AbstractFeatureWithLifespan
afwl
,
CityObject
to
)
{
mapAbstractFeature
(
afwl
,
to
);
}
private
void
mapAbstractFeature
(
AbstractFeature
af
,
CityObject
to
)
{
mapAbstractGML
(
af
,
to
);
}
private
void
mapAbstractGML
(
AbstractGML
ag
,
CityObject
to
)
{
parseId
(
ag
,
to
);
}
@Override
public
void
visit
(
Railway
railway
)
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
RAILWAY
);
mapAbstractTransportationSpace
(
railway
,
to
);
finishTransportationMapping
(
to
);
}
@Override
public
void
visit
(
Square
square
)
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
SQUARE
);
mapAbstractTransportationSpace
(
square
,
to
);
finishTransportationMapping
(
to
);
}
@Override
public
void
visit
(
Track
track
)
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRACK
);
mapAbstractTransportationSpace
(
track
,
to
);
finishTransportationMapping
(
to
);
}
@Override
public
void
visit
(
TransportationComplex
transportationComplex
)
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
TRANSPORTATION_COMPLEX
);
mapAbstractTransportationSpace
(
transportationComplex
,
to
);
finishTransportationMapping
(
to
);
}
private
void
finishTransportationMapping
(
TransportationObject
to
)
{
finishCityObjectConstruction
(
to
);
model
.
addTransportation
(
to
);
}
private
void
finishCityObjectConstruction
(
CityObject
co
)
{
co
.
unsetGmlGeometries
();
resolveAndClearReferences
();
updateEdgesAndVertices
(
co
);
}
private
void
mapAbstractTransportationSpace
(
AbstractTransportationSpace
ats
,
TransportationObject
to
)
{
to
.
setGmlObject
(
ats
);
parseAbstractTransportationSpaceGeometries
(
ats
,
to
);
for
(
TrafficSpaceProperty
tsp
:
ats
.
getTrafficSpaces
())
{
if
(
tsp
.
isSetObject
())
{
TransportationObject
trafficSpace
=
new
TransportationObject
(
TransportationType
.
TRAFFIC_SPACE
);
mapTrafficSpace
(
tsp
.
getObject
(),
trafficSpace
);
finishTransportationMapping
(
trafficSpace
);
to
.
getChildren
().
add
(
trafficSpace
);
}
}
for
(
AuxiliaryTrafficSpaceProperty
auxTrafficProp
:
ats
.
getAuxiliaryTrafficSpaces
())
{
if
(
auxTrafficProp
.
isSetObject
())
{
TransportationObject
trafficSpace
=
parseAuxiliaryTrafficSpace
(
auxTrafficProp
.
getObject
());
finishTransportationMapping
(
trafficSpace
);
to
.
addChild
(
trafficSpace
);
}
}
}
private
void
mapTrafficSpace
(
TrafficSpace
ts
,
TransportationObject
to
)
{
mapAbstractUnoccupiedSpace
(
ts
,
to
);
}
private
void
mapAbstractUnoccupiedSpace
(
AbstractUnoccupiedSpace
aus
,
CityObject
co
)
{
mapAbstractPhysicalSpace
(
aus
,
co
);
}
private
TransportationObject
parseAuxiliaryTrafficSpace
(
AuxiliaryTrafficSpace
ats
)
{
TransportationObject
to
=
new
TransportationObject
(
TransportationType
.
AUXILLIARY_TRAFFIC_SPACE
);
parseAbstractSpaceGeometries
(
ats
,
to
);
finishCityObjectConstruction
(
to
);
return
to
;
}
private
void
parseAbstractTransportationSpaceGeometries
(
AbstractTransportationSpace
space
,
CityObject
co
)
{
parseAndAddMultiSurface
(
space
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
co
);
parseAndAddMultiSurface
(
space
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
co
);
public
Citygml3FeatureMapper
(
ParserConfiguration
config
,
CityGmlZipEntry
entry
)
{
this
.
config
=
config
;
this
.
directory
=
null
;
this
.
zipEntry
=
entry
;
model
=
new
CityDoctorModel
(
config
,
Path
.
of
(
entry
.
getEntrySubPath
()).
toFile
());
neighborDistance
=
1.8d
/
Math
.
pow
(
10
,
config
.
getNumberOfRoundingPlaces
());
}
private
void
parseAbstractSpaceGeometries
(
AbstractSpace
as
,
CityObject
co
)
{
parseAndAddMultiSurface
(
as
.
getLod0MultiSurface
(),
Lod
.
LOD0
,
co
);
parseAndAddMultiSurface
(
as
.
getLod2MultiSurface
(),
Lod
.
LOD2
,
co
);
parseAndAddMultiSurface
(
as
.
getLod3MultiSurface
(),
Lod
.
LOD3
,
co
);
parseAndAddSolid
(
as
.
getLod1Solid
(),
Lod
.
LOD1
,
co
);
parseAndAddSolid
(
as
.
getLod2Solid
(),
Lod
.
LOD2
,
co
);
parseAndAddSolid
(
as
.
getLod3Solid
(),
Lod
.
LOD3
,
co
);
}
private
void
parseAndAddMultiSurface
(
MultiSurfaceProperty
msp
,
Lod
lod
,
CityObject
co
)
{
if
(
msp
==
null
||
msp
.
getObject
()
==
null
)
{
return
;
}
Geometry
geom
=
parseMultiSurface
(
msp
.
getObject
(),
lod
);
co
.
addGeometry
(
geom
);
}
public
static
void
parseId
(
AbstractGML
gml
,
GmlElement
gmlElement
)
{
String
id
=
gml
.
getId
();
if
(
id
!=
null
)
{
gmlElement
.
setGmlId
(
new
GmlId
(
id
));
}
}
@Override
public
void
visit
(
AbstractSpace
space
)
{
// if we are here, an AbstractSpace thing was read that is not handled in the
// other methods
}
@Override
public
void
visit
(
org
.
citygml4j
.
core
.
model
.
cityfurniture
.
CityFurniture
gmlCityFurniture
)
{
CityFurniture
cf
=
new
CityFurniture
();
cf
.
setGmlObject
(
gmlCityFurniture
);
mapAbstractOccupiedSpace
(
gmlCityFurniture
,
cf
);
resolveAndClearReferences
();
cf
.
unsetGmlGeometries
();
updateEdgesAndVertices
(
cf
);
model
.
addCityFurniture
(
cf
);
}
@Override
public
void
visit
(
org
.
citygml4j
.
core
.
model
.
generics
.
GenericOccupiedSpace
gos
)
{
GenericCityObject
gco
=
new
GenericCityObject
();
gco
.
setGmlObject
(
gos
);
GeometryProperty
<?>
agLod1
=
gos
.
getDeprecatedProperties
().
getLod1Geometry
();
GeometryProperty
<?>
agLod4
=
gos
.
getDeprecatedProperties
().
getLod4Geometry
();
if
(
agLod1
!=
null
&&
agLod1
.
getObject
()
!=
null
&&
agLod1
.
getObject
()
instanceof
MultiSurface
ms
)
{
gco
.
addGeometry
(
parseMultiSurface
(
ms
,
Lod
.
LOD1
));
}
if
(
agLod4
!=
null
&&
agLod4
.
getObject
()
!=
null
)
{
if
(
agLod4
.
getObject
()
instanceof
MultiSurface
ms
)
{
gco
.
addGeometry
(
parseMultiSurface
(
ms
,
Lod
.
LOD4
));
}
else
if
(
agLod4
.
getObject
()
instanceof
AbstractSolid
solid
)
{
gco
.
addGeometry
(
parseSolid
(
solid
,
Lod
.
LOD4
));
}
}
mapAbstractOccupiedSpace
(
gos
,
gco
);
resolveAndClearReferences
();
gco
.
unsetGmlGeometries
();
updateEdgesAndVertices
(
gco
);
model
.
addGenericCityObject
(
gco
);
}
@Override
public
void
visit
(
org
.
citygml4j
.
core
.
model
.
building
.
Building
gmlBuilding
)
{
Building
cdBuilding
=
new
Building
();
readAbstractBuilding
(
gmlBuilding
,
cdBuilding
);
for
(
BuildingPartProperty
bpProp
:
gmlBuilding
.
getBuildingParts
())
{
if
(!
bpProp
.
isSetObject
())
{
continue
;
}
BuildingPart
part
=
new
BuildingPart
(
cdBuilding
);
readAbstractBuilding
(
bpProp
.
getObject
(),
part
);
}
model
.
addBuilding
(
cdBuilding
);
}
@Override
public
void
visit
(
WaterBody
waterBody
)
{
WaterObject
wo
=
new
WaterObject
();
wo
.
setGmlObject
(
waterBody
);
mapAbstractOccupiedSpace
(
waterBody
,
wo
);
parseAndAddMultiSurface
(
waterBody
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
wo
);
parseAndAddSolid
(
waterBody
.
getDeprecatedProperties
().
getLod4Solid
(),
Lod
.
LOD4
,
wo
);
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
waterBody
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
wo
.
addBoundarySurface
(
bs
);
}
resolveAndClearReferences
();
wo
.
unsetGmlGeometries
();
updateEdgesAndVertices
(
wo
);
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
updateEdgesAndVertices
(
bs
);
}
model
.
addWater
(
wo
);
}
@Override
public
void
visit
(
LandUse
landUse
)
{
LandObject
lo
=
new
LandObject
(
landUse
);
mapAbstractThematicSurface
(
landUse
,
lo
);
finishCityObjectConstruction
(
lo
);
model
.
addLand
(
lo
);
}
@Override
public
void
visit
(
PlantCover
plantCover
)
{
Vegetation
veg
=
new
Vegetation
(
VegetationType
.
PLANT_COVER
);
veg
.
setGmlObject
(
plantCover
);
mapAbstractVegetationObject
(
plantCover
,
veg
);
parseAndAddMultiSurface
(
plantCover
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
veg
);
parseAndAddMultiSurface
(
plantCover
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
veg
);
finishCityObjectConstruction
(
veg
);
model
.
addVegetation
(
veg
);
}
@Override
public
void
visit
(
SolitaryVegetationObject
solitaryVegetationObject
)
{
Vegetation
veg
=
new
Vegetation
(
VegetationType
.
SOLITARY_VEGETATION_OBJECT
);
veg
.
setGmlObject
(
solitaryVegetationObject
);
mapAbstractVegetationObject
(
solitaryVegetationObject
,
veg
);
parseAndAddAbstractGeometry
(
solitaryVegetationObject
.
getDeprecatedProperties
().
getLod1Geometry
(),
Lod
.
LOD1
,
veg
);
parseAndAddAbstractGeometry
(
solitaryVegetationObject
.
getDeprecatedProperties
().
getLod2Geometry
(),
Lod
.
LOD2
,
veg
);
parseAndAddAbstractGeometry
(
solitaryVegetationObject
.
getDeprecatedProperties
().
getLod3Geometry
(),
Lod
.
LOD3
,
veg
);
parseAndAddAbstractGeometry
(
solitaryVegetationObject
.
getDeprecatedProperties
().
getLod4Geometry
(),
Lod
.
LOD4
,
veg
);
finishCityObjectConstruction
(
veg
);
model
.
addVegetation
(
veg
);
}
private
void
mapAbstractVegetationObject
(
AbstractVegetationObject
avo
,
Vegetation
veg
)
{
mapAbstractOccupiedSpace
(
avo
,
veg
);
}
private
void
mapAbstractOccupiedSpace
(
AbstractOccupiedSpace
aos
,
CityObject
co
)
{
mapAbstractPhysicalSpace
(
aos
,
co
);
parseImplicitGeometry
(
aos
,
co
);
}
private
void
mapAbstractPhysicalSpace
(
AbstractPhysicalSpace
aps
,
CityObject
co
)
{
mapAbstractSpace
(
aps
,
co
);
}
private
void
mapAbstractSpace
(
AbstractSpace
as
,
CityObject
co
)
{
mapAbstractFeature
(
as
,
co
);
parseAndAddMultiSurface
(
as
.
getLod0MultiSurface
(),
Lod
.
LOD0
,
co
);
parseAndAddMultiSurface
(
as
.
getLod2MultiSurface
(),
Lod
.
LOD2
,
co
);
parseAndAddMultiSurface
(
as
.
getLod3MultiSurface
(),
Lod
.
LOD3
,
co
);
parseAndAddSolid
(
as
.
getLod1Solid
(),
Lod
.
LOD1
,
co
);
parseAndAddSolid
(
as
.
getLod2Solid
(),
Lod
.
LOD2
,
co
);
parseAndAddSolid
(
as
.
getLod3Solid
(),
Lod
.
LOD3
,
co
);
parseAndAddGenericAttributes
(
as
,
co
);
}
private
void
parseAndAddGenericAttributes
(
AbstractSpace
as
,
CityObject
co
)
{
for
(
AbstractGenericAttributeProperty
aga
:
as
.
getGenericAttributes
())
{
co
.
addGenericAttribute
(
new
GenericAttribute
(
aga
));
}
}
@Override
public
void
visit
(
Bridge
bridge
)
{
BridgeObject
bo
=
new
BridgeObject
(
bridge
);
// parse deprecated geometries
parseAndAddMultiSurface
(
bridge
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
bo
);
parseAndAddMultiSurface
(
bridge
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
bo
);
parseAndAddSolid
(
bridge
.
getDeprecatedProperties
().
getLod4Solid
(),
Lod
.
LOD4
,
bo
);
mapAbstractBridge
(
bridge
,
bo
);
for
(
BridgePartProperty
bPartProperty
:
bridge
.
getBridgeParts
())
{
if
(!
bPartProperty
.
isSetObject
())
{
continue
;
}
BridgePart
gmlBridgePart
=
bPartProperty
.
getObject
();
BridgeObject
bPart
=
new
BridgeObject
(
gmlBridgePart
,
bo
);
mapAbstractBridge
(
gmlBridgePart
,
bPart
);
bo
.
addBridgePart
(
bPart
);
}
resolveAndClearReferences
();
updateEdgesAndVertices
(
bo
);
for
(
BridgeObject
part
:
bo
.
getParts
())
{
updateEdgesAndVertices
(
part
);
}
for
(
BridgeConstructiveElement
ele
:
bo
.
getConstructiveElements
())
{
updateEdgesAndVertices
(
ele
);
for
(
BoundarySurface
bs
:
ele
.
getBoundarySurfaces
())
{
updateEdgesAndVertices
(
bs
);
}
}
for
(
Installation
bi
:
bo
.
getBridgeInstallations
())
{
updateEdgesAndVertices
(
bi
);
for
(
BoundarySurface
bs
:
bi
.
getBoundarySurfaces
())
{
updateEdgesAndVertices
(
bs
);
}
}
model
.
addBridge
(
bo
);
}
private
void
mapAbstractBridge
(
AbstractBridge
ab
,
BridgeObject
bo
)
{
mapAbstractConstruction
(
ab
,
bo
);
for
(
BridgeConstructiveElementProperty
eleProp
:
ab
.
getBridgeConstructiveElements
())
{
if
(!
eleProp
.
isSetObject
())
{
continue
;
}
org
.
citygml4j
.
core
.
model
.
bridge
.
BridgeConstructiveElement
constructiveElement
=
eleProp
.
getObject
();
BridgeConstructiveElement
cdEle
=
new
BridgeConstructiveElement
(
constructiveElement
);
mapConstructiveElement
(
constructiveElement
,
cdEle
);
bo
.
addConstructiveElement
(
cdEle
);
}
List
<
BridgeInstallationProperty
>
bridgeInstallations
=
ab
.
getBridgeInstallations
();
for
(
BridgeInstallationProperty
installationProp
:
bridgeInstallations
)
{
var
gmlBi
=
installationProp
.
getObject
();
if
(
gmlBi
==
null
)
{
// ignore empty properties
continue
;
}
Installation
bi
=
mapBridgeInstallation
(
gmlBi
);
bo
.
addBridgeInstallation
(
bi
);
}
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
ab
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
updatePartOfSurface
(
bo
,
surfaceMapper
);
for
(
BoundarySurface
bs
:
bo
.
getBoundarySurfaces
())
{
updateEdgesAndVertices
(
bs
);
}
bo
.
unsetGmlGeometries
();
}
private
Installation
mapBridgeInstallation
(
BridgeInstallation
gmlBi
)
{
Installation
bi
=
new
Installation
();
bi
.
setGmlObject
(
gmlBi
);
mapAbstractOccupiedSpace
(
gmlBi
,
bi
);
GeometryProperty
<?>
lod2Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod2Geometry
();
parseAndAddAbstractGeometry
(
lod2Prop
,
Lod
.
LOD2
,
bi
);
GeometryProperty
<?>
lod3Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod3Geometry
();
parseAndAddAbstractGeometry
(
lod3Prop
,
Lod
.
LOD3
,
bi
);
GeometryProperty
<?>
lod4Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod4Geometry
();
parseAndAddAbstractGeometry
(
lod4Prop
,
Lod
.
LOD4
,
bi
);
bi
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlBi
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bi
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
p
.
setPartOfInstallation
(
bi
);
}
}
}
for
(
Geometry
geom
:
bi
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfInstallation
(
bi
);
}
}
return
bi
;
}
@Override
public
void
visit
(
Tunnel
tunnel
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Tunnel
tu
=
new
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Tunnel
();
for
(
TunnelPartProperty
tPartProperty
:
tunnel
.
getTunnelParts
())
{
if
(!
tPartProperty
.
isSetObject
())
{
continue
;
}
org
.
citygml4j
.
core
.
model
.
tunnel
.
TunnelPart
gmlTunnelPart
=
tPartProperty
.
getObject
();
TunnelPart
tPart
=
new
TunnelPart
(
tu
);
readAbstractTunnel
(
gmlTunnelPart
,
tPart
);
tu
.
addTunnelPart
(
tPart
);
}
readAbstractTunnel
(
tunnel
,
tu
);
resolveAndClearReferences
();
updateEdgesAndVertices
(
tu
);
for
(
TunnelPart
part
:
tu
.
getTunnelParts
())
{
updateEdgesAndVertices
(
part
);
}
model
.
addTunnel
(
tu
);
}
private
void
readAbstractTunnel
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
AbstractTunnel
gmlTunnel
,
AbstractTunnel
cdTunnel
)
{
mapAbstractOccupiedSpace
(
gmlTunnel
,
cdTunnel
);
cdTunnel
.
setGmlObject
(
gmlTunnel
);
// parse deprecated geometries
parseAndAddMultiSurface
(
gmlTunnel
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
cdTunnel
);
parseAndAddMultiSurface
(
gmlTunnel
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
cdTunnel
);
parseAndAddSolid
(
gmlTunnel
.
getDeprecatedProperties
().
getLod4Solid
(),
Lod
.
LOD4
,
cdTunnel
);
parseTunnelInstallations
(
gmlTunnel
,
cdTunnel
);
parseHollowSpaces
(
gmlTunnel
,
cdTunnel
);
parseTunnelFurniture
(
gmlTunnel
,
cdTunnel
);
parseTunnelConstructiveElements
(
gmlTunnel
,
cdTunnel
);
parseTunnelBoundarySurfaces
(
gmlTunnel
);
for
(
Installation
ti
:
cdTunnel
.
getTunnelInstallations
())
{
updateEdgesAndVertices
(
ti
);
for
(
BoundarySurface
bs
:
ti
.
getBoundarySurfaces
())
{
updateEdgesAndVertices
(
bs
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
updateEdgesAndVertices
(
o
);
}
}
}
cdTunnel
.
unsetGmlGeometries
();
resolveAndClearReferences
();
updateEdgesAndVertices
(
cdTunnel
);
}
private
void
parseTunnelBoundarySurfaces
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
AbstractTunnel
gmlTunnel
)
{
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlTunnel
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
updateEdgesAndVertices
(
bs
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
updateEdgesAndVertices
(
o
);
}
}
}
private
void
parseTunnelConstructiveElements
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
AbstractTunnel
gmlTunnel
,
AbstractTunnel
cdTunnel
)
{
for
(
TunnelConstructiveElementProperty
teProp
:
gmlTunnel
.
getTunnelConstructiveElements
())
{
var
gmlTc
=
teProp
.
getObject
();
if
(
gmlTc
==
null
)
{
continue
;
}
TunnelConstructiveElement
tc
=
mapTunnelConstructiveElement
(
gmlTc
);
cdTunnel
.
addTunnelConstructiveElement
(
tc
);
}
}
private
void
parseTunnelFurniture
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
AbstractTunnel
gmlTunnel
,
AbstractTunnel
cdTunnel
)
{
for
(
TunnelFurnitureProperty
tfProp
:
gmlTunnel
.
getTunnelFurniture
())
{
var
gmlTf
=
tfProp
.
getObject
();
if
(
gmlTf
==
null
)
{
continue
;
}
TunnelFurniture
tf
=
mapTunnelFurniture
(
gmlTf
);
cdTunnel
.
addTunnelFurniture
(
tf
);
}
}
private
void
parseHollowSpaces
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
AbstractTunnel
gmlTunnel
,
AbstractTunnel
cdTunnel
)
{
for
(
HollowSpaceProperty
thProp
:
gmlTunnel
.
getHollowSpaces
())
{
var
gmlTh
=
thProp
.
getObject
();
if
(
gmlTh
==
null
)
{
continue
;
}
TunnelHollow
br
=
mapTunnelHollow
(
gmlTh
);
cdTunnel
.
addTunnelHollow
(
br
);
}
}
private
void
parseTunnelInstallations
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
AbstractTunnel
gmlTunnel
,
AbstractTunnel
cdTunnel
)
{
for
(
TunnelInstallationProperty
tiProp
:
gmlTunnel
.
getTunnelInstallations
())
{
var
gmlTi
=
tiProp
.
getObject
();
if
(
gmlTi
==
null
)
{
// ignore empty properties
continue
;
}
Installation
ti
=
mapTunnelInstallation
(
gmlTi
);
cdTunnel
.
addTunnelInstallation
(
ti
);
}
}
private
Installation
mapTunnelInstallation
(
TunnelInstallation
gmlTi
)
{
Installation
ti
=
new
Installation
();
ti
.
setGmlObject
(
gmlTi
);
mapAbstractOccupiedSpace
(
gmlTi
,
ti
);
GeometryProperty
<?>
lod2Prop
=
gmlTi
.
getDeprecatedProperties
().
getLod2Geometry
();
parseAndAddAbstractGeometry
(
lod2Prop
,
Lod
.
LOD2
,
ti
);
GeometryProperty
<?>
lod3Prop
=
gmlTi
.
getDeprecatedProperties
().
getLod3Geometry
();
parseAndAddAbstractGeometry
(
lod3Prop
,
Lod
.
LOD3
,
ti
);
GeometryProperty
<?>
lod4Prop
=
gmlTi
.
getDeprecatedProperties
().
getLod4Geometry
();
parseAndAddAbstractGeometry
(
lod4Prop
,
Lod
.
LOD4
,
ti
);
ti
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlTi
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
ti
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
p
.
setPartOfInstallation
(
ti
);
}
}
}
for
(
Geometry
geom
:
ti
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfInstallation
(
ti
);
}
}
return
ti
;
}
private
TunnelHollow
mapTunnelHollow
(
HollowSpace
gmlHo
)
{
TunnelHollow
tHollow
=
new
TunnelHollow
();
tHollow
.
setGmlObject
(
gmlHo
);
mapAbstractUnoccupiedSpace
(
gmlHo
,
tHollow
);
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlHo
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
tHollow
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
for
(
TunnelInstallationProperty
tiProp
:
gmlHo
.
getTunnelInstallations
())
{
var
gmlTi
=
tiProp
.
getObject
();
if
(
gmlTi
==
null
)
{
// ignore empty properties
continue
;
}
Installation
bi
=
mapTunnelInstallation
(
gmlTi
);
tHollow
.
addRoomInstallation
(
bi
);
}
for
(
TunnelFurnitureProperty
tfProp
:
gmlHo
.
getTunnelFurniture
())
{
var
gmlHref
=
tfProp
.
getHref
();
if
(
gmlHref
==
null
)
{
continue
;
}
tHollow
.
addFurnitureRef
(
tfProp
);
}
return
tHollow
;
}
private
TunnelFurniture
mapTunnelFurniture
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
TunnelFurniture
gmlTf
)
{
TunnelFurniture
tf
=
new
TunnelFurniture
();
tf
.
setGmlObject
(
gmlTf
);
mapAbstractOccupiedSpace
(
gmlTf
,
tf
);
tf
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlTf
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
tf
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
return
tf
;
}
private
TunnelConstructiveElement
mapTunnelConstructiveElement
(
org
.
citygml4j
.
core
.
model
.
tunnel
.
TunnelConstructiveElement
gmlTe
)
{
TunnelConstructiveElement
te
=
new
TunnelConstructiveElement
(
gmlTe
);
mapAbstractOccupiedSpace
(
gmlTe
,
te
);
te
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlTe
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
te
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
return
te
;
}
private
void
updatePartOfSurface
(
BridgeObject
bo
,
SurfaceMapper
surfaceMapper
)
{
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bo
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
}
private
void
mapConstructiveElement
(
org
.
citygml4j
.
core
.
model
.
bridge
.
BridgeConstructiveElement
ele
,
BridgeConstructiveElement
bce
)
{
mapAbstractConstructiveElement
(
ele
,
bce
);
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
ele
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bce
.
addBoundarySurface
(
bs
);
}
}
private
void
mapAbstractConstructiveElement
(
org
.
citygml4j
.
core
.
model
.
bridge
.
BridgeConstructiveElement
ele
,
BridgeConstructiveElement
bce
)
{
mapAbstractOccupiedSpace
(
ele
,
bce
);
}
private
void
mapAbstractConstruction
(
AbstractConstruction
ac
,
BridgeObject
bo
)
{
mapAbstractOccupiedSpace
(
ac
,
bo
);
}
@Override
public
void
visit
(
Track
track
)
{
TopLevelTransportFeature
top
=
TopLevelTransportFeature
.
from
(
track
);
mapSectionsAndIntersections
(
track
.
getSections
(),
track
.
getIntersections
(),
top
);
mapAbstractTransportationSpace
(
track
,
top
);
finishTransportationMapping
(
top
);
}
@Override
public
void
visit
(
Road
road
)
{
TopLevelTransportFeature
top
=
TopLevelTransportFeature
.
from
(
road
);
mapSectionsAndIntersections
(
road
.
getSections
(),
road
.
getIntersections
(),
top
);
mapAbstractTransportationSpace
(
road
,
top
);
finishTransportationMapping
(
top
);
}
@Override
public
void
visit
(
Waterway
waterway
)
{
TopLevelTransportFeature
top
=
TopLevelTransportFeature
.
from
(
waterway
);
mapSectionsAndIntersections
(
waterway
.
getSections
(),
waterway
.
getIntersections
(),
top
);
mapAbstractTransportationSpace
(
waterway
,
top
);
finishTransportationMapping
(
top
);
}
@Override
public
void
visit
(
Railway
railway
)
{
TopLevelTransportFeature
top
=
TopLevelTransportFeature
.
from
(
railway
);
mapSectionsAndIntersections
(
railway
.
getSections
(),
railway
.
getIntersections
(),
top
);
mapAbstractTransportationSpace
(
railway
,
top
);
finishTransportationMapping
(
top
);
}
@Override
public
void
visit
(
Square
square
)
{
TopLevelTransportFeature
top
=
TopLevelTransportFeature
.
from
(
square
);
mapAbstractTransportationSpace
(
square
,
top
);
finishTransportationMapping
(
top
);
}
@Override
public
void
visit
(
TransportationComplex
tc
)
{
TopLevelTransportFeature
top
=
TopLevelTransportFeature
.
from
(
tc
);
mapAbstractTransportationSpace
(
tc
,
top
);
finishTransportationMapping
(
top
);
}
private
void
mapAbstractThematicSurface
(
AbstractThematicSurface
ats
,
CityObject
co
)
{
mapAbstractSpaceBoundary
(
ats
,
co
);
parseAndAddMultiSurface
(
ats
.
getLod0MultiSurface
(),
Lod
.
LOD0
,
co
);
parseAndAddMultiSurface
(
ats
.
getLod1MultiSurface
(),
Lod
.
LOD1
,
co
);
parseAndAddMultiSurface
(
ats
.
getLod2MultiSurface
(),
Lod
.
LOD2
,
co
);
parseAndAddMultiSurface
(
ats
.
getLod3MultiSurface
(),
Lod
.
LOD3
,
co
);
parseAndAddMultiSurface
(
ats
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
co
);
}
private
void
mapAbstractSpaceBoundary
(
AbstractSpaceBoundary
asb
,
CityObject
co
)
{
mapAbstractCityObject
(
asb
,
co
);
}
private
void
mapAbstractCityObject
(
AbstractCityObject
aco
,
CityObject
to
)
{
mapAbstractFeatureWithLifespan
(
aco
,
to
);
}
private
void
mapAbstractFeatureWithLifespan
(
AbstractFeatureWithLifespan
afwl
,
CityObject
to
)
{
mapAbstractFeature
(
afwl
,
to
);
}
private
void
mapAbstractFeature
(
AbstractFeature
af
,
CityObject
to
)
{
mapAbstractGML
(
af
,
to
);
}
private
void
mapAbstractGML
(
AbstractGML
ag
,
CityObject
to
)
{
parseId
(
ag
,
to
);
}
private
void
finishTransportationMapping
(
TransportationObject
to
)
{
finishCityObjectConstruction
(
to
);
model
.
addTransportation
(
to
);
}
private
void
finishCityObjectConstruction
(
CityObject
co
)
{
co
.
unsetGmlGeometries
();
resolveAndClearReferences
();
updateEdgesAndVertices
(
co
);
}
private
void
mapAbstractTransportationSpace
(
AbstractTransportationSpace
ats
,
TransportationSpace
trsp
)
{
parseAbstractTransportationSpaceGeometries
(
ats
,
trsp
);
for
(
TrafficSpaceProperty
tsp
:
ats
.
getTrafficSpaces
())
{
if
(
tsp
.
isSetObject
())
{
TrafficSpaceObject
tso
=
new
TrafficSpaceObject
(
TrafficSpaceObject
.
TrafficSpaceType
.
TRAFFIC_SPACE
);
mapTrafficSpace
(
tsp
.
getObject
(),
tso
);
trsp
.
addTrafficSpace
(
tso
);
}
}
for
(
AuxiliaryTrafficSpaceProperty
atsp
:
ats
.
getAuxiliaryTrafficSpaces
())
{
if
(
atsp
.
isSetObject
())
{
TrafficSpaceObject
atso
=
new
TrafficSpaceObject
(
TrafficSpaceObject
.
TrafficSpaceType
.
AUXILIARY_TRAFFIC_SPACE
);
mapAuxiliaryTrafficSpace
(
atsp
.
getObject
(),
atso
);
trsp
.
addTrafficSpace
(
atso
);
}
}
}
private
void
mapSectionsAndIntersections
(
List
<
SectionProperty
>
sectionProps
,
List
<
IntersectionProperty
>
intersectionProps
,
TopLevelTransportFeature
top
)
{
for
(
SectionProperty
sectionProp
:
sectionProps
)
{
if
(
sectionProp
.
isSetObject
())
{
TransportSection
sect
=
new
TransportSection
(
TransportSection
.
SectionType
.
SECTION
);
sect
.
setGmlObject
(
sectionProp
.
getObject
());
mapAbstractTransportationSpace
(
sectionProp
.
getObject
(),
sect
);
finishCityObjectConstruction
(
sect
);
top
.
addSection
(
sect
);
}
}
for
(
IntersectionProperty
intersectionProp
:
intersectionProps
)
{
if
(
intersectionProp
.
isSetObject
())
{
TransportSection
isect
=
new
TransportSection
(
TransportSection
.
SectionType
.
INTERSECTION
);
isect
.
setGmlObject
(
intersectionProp
.
getObject
());
mapAbstractTransportationSpace
(
intersectionProp
.
getObject
(),
isect
);
finishCityObjectConstruction
(
isect
);
top
.
addIntersection
(
isect
);
}
}
}
private
void
mapTrafficSpace
(
TrafficSpace
ts
,
TrafficSpaceObject
tso
)
{
tso
.
setGmlObject
(
ts
);
mapAbstractUnoccupiedSpace
(
ts
,
tso
);
for
(
AbstractSpaceBoundaryProperty
boundary
:
ts
.
getBoundaries
())
{
if
(
boundary
.
isSetObject
())
{
TrafficArea
area
=
(
TrafficArea
)
boundary
.
getObject
();
TrafficAreaObject
tao
=
new
TrafficAreaObject
(
TrafficAreaObject
.
TrafficAreaType
.
TRAFFIC_AREA
);
mapTrafficArea
(
area
,
tao
);
tso
.
addTrafficArea
(
tao
);
}
}
finishCityObjectConstruction
(
tso
);
}
private
void
mapAuxiliaryTrafficSpace
(
AuxiliaryTrafficSpace
ats
,
TrafficSpaceObject
tso
)
{
tso
.
setGmlObject
(
ats
);
mapAbstractUnoccupiedSpace
(
ats
,
tso
);
for
(
AbstractSpaceBoundaryProperty
boundary
:
ats
.
getBoundaries
())
{
if
(
boundary
.
isSetObject
())
{
AuxiliaryTrafficArea
area
=
(
AuxiliaryTrafficArea
)
boundary
.
getObject
();
TrafficAreaObject
tao
=
new
TrafficAreaObject
(
TrafficAreaObject
.
TrafficAreaType
.
AUXILIARY_TRAFFIC_AREA
);
mapAuxiliaryTrafficArea
(
area
,
tao
);
tso
.
addTrafficArea
(
tao
);
}
}
finishCityObjectConstruction
(
tso
);
}
private
void
mapTrafficArea
(
TrafficArea
ta
,
TrafficAreaObject
tao
)
{
tao
.
setGmlObject
(
ta
);
parseAndAddMultiSurface
(
ta
.
getLod0MultiSurface
(),
Lod
.
LOD0
,
tao
);
parseAndAddMultiSurface
(
ta
.
getLod1MultiSurface
(),
Lod
.
LOD1
,
tao
);
parseAndAddMultiSurface
(
ta
.
getLod2MultiSurface
(),
Lod
.
LOD2
,
tao
);
parseAndAddMultiSurface
(
ta
.
getLod3MultiSurface
(),
Lod
.
LOD3
,
tao
);
parseAndAddMultiSurface
(
ta
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
tao
);
finishCityObjectConstruction
(
tao
);
}
private
void
mapAuxiliaryTrafficArea
(
AuxiliaryTrafficArea
ats
,
TrafficAreaObject
tao
)
{
tao
.
setGmlObject
(
ats
);
parseAndAddMultiSurface
(
ats
.
getLod0MultiSurface
(),
Lod
.
LOD0
,
tao
);
parseAndAddMultiSurface
(
ats
.
getLod1MultiSurface
(),
Lod
.
LOD1
,
tao
);
parseAndAddMultiSurface
(
ats
.
getLod2MultiSurface
(),
Lod
.
LOD2
,
tao
);
parseAndAddMultiSurface
(
ats
.
getLod3MultiSurface
(),
Lod
.
LOD3
,
tao
);
parseAndAddMultiSurface
(
ats
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
tao
);
finishCityObjectConstruction
(
tao
);
}
private
void
mapAbstractUnoccupiedSpace
(
AbstractUnoccupiedSpace
aus
,
CityObject
co
)
{
mapAbstractPhysicalSpace
(
aus
,
co
);
}
private
void
parseAbstractTransportationSpaceGeometries
(
AbstractTransportationSpace
space
,
CityObject
co
)
{
parseAndAddMultiSurface
(
space
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
co
);
parseAndAddMultiSurface
(
space
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
co
);
}
private
void
parseAbstractSpaceGeometries
(
AbstractSpace
as
,
CityObject
co
)
{
parseAndAddMultiSurface
(
as
.
getLod0MultiSurface
(),
Lod
.
LOD0
,
co
);
parseAndAddMultiSurface
(
as
.
getLod2MultiSurface
(),
Lod
.
LOD2
,
co
);
parseAndAddMultiSurface
(
as
.
getLod3MultiSurface
(),
Lod
.
LOD3
,
co
);
parseAndAddSolid
(
as
.
getLod1Solid
(),
Lod
.
LOD1
,
co
);
parseAndAddSolid
(
as
.
getLod2Solid
(),
Lod
.
LOD2
,
co
);
parseAndAddSolid
(
as
.
getLod3Solid
(),
Lod
.
LOD3
,
co
);
}
private
void
parseAndAddMultiSurface
(
MultiSurfaceProperty
msp
,
Lod
lod
,
CityObject
co
)
{
if
(
msp
==
null
||
msp
.
getObject
()
==
null
)
{
return
;
}
Geometry
geom
=
parseMultiSurface
(
msp
.
getObject
(),
lod
);
co
.
addGeometry
(
geom
);
}
private
void
parseAndAddSolid
(
SolidProperty
sp
,
Lod
lod
,
CityObject
co
)
{
if
(
sp
==
null
||
sp
.
getObject
()
==
null
)
{
...
...
@@ -782,477 +870,489 @@ public class Citygml3FeatureMapper extends ObjectWalker {
}
}
private
void
parseAndAddCompositeSurface
(
MultiSurfaceProperty
ms
,
Lod
lod
,
CityObject
co
)
{
if
(
ms
==
null
||
ms
.
getObject
()
==
null
)
{
return
;
}
List
<
SurfaceProperty
>
surfaces
=
ms
.
getObject
().
getSurfaceMember
();
for
(
SurfaceProperty
surface
:
surfaces
)
{
if
(
surface
.
getObject
()
instanceof
CompositeSurface
cs
)
{
Geometry
geom
=
parseCompositeSurface
(
cs
,
lod
);
if
(
geom
!=
null
)
{
co
.
addGeometry
(
geom
);
}
}
}
}
private
void
parseImplicitGeometry
(
AbstractOccupiedSpace
aos
,
CityObject
co
)
{
for
(
int
i
=
1
;
i
<=
3
;
i
++)
{
if
(
aos
.
getImplicitRepresentation
(
i
)
==
null
)
{
continue
;
}
if
(
aos
.
getImplicitRepresentation
(
i
).
getObject
()
!=
null
)
{
ImplicitGeometry
impGeom
=
aos
.
getImplicitRepresentation
(
i
).
getObject
();
ImplicitGeometryHolder
igh
=
resolveImplicitGeometry
(
impGeom
,
i
);
if
(
igh
!=
null
)
{
co
.
addGeometry
(
igh
);
}
}
else
if
(
aos
.
getImplicitRepresentation
(
i
).
getHref
()
!=
null
)
{
// Hrefs of ImplicitGeometries point to its RelativeGeometry.
// Can be ignored for CD since the Href is only used for repeating the RelativeGeometry at different LODs
}
}
}
private
ImplicitGeometryHolder
resolveImplicitGeometry
(
ImplicitGeometry
ig
,
int
lodInt
)
{
ImplicitGeometryHolder
igh
=
null
;
if
(
ig
.
getLibraryObject
()
!=
null
)
{
Path
libraryObjectPath
=
directory
.
resolve
(
ig
.
getLibraryObject
());
LibraryObject
libObj
=
LibraryObject
.
of
(
libraryObjectPath
,
config
);
if
(
libObj
!=
null
)
{
igh
=
new
ImplicitGeometryHolder
(
ig
,
libObj
);
}
}
else
if
(
ig
.
getRelativeGeometry
()
!=
null
)
{
AbstractGeometry
aGeom
=
ig
.
getRelativeGeometry
().
getObject
();
Geometry
geom
=
null
;
Lod
lod
=
Lod
.
values
()[
lodInt
];
RelativeGeometry
relGeo
=
null
;
if
(
aGeom
instanceof
MultiSurface
ms
)
{
geom
=
parseMultiSurface
(
ms
,
lod
);
}
else
if
(
aGeom
instanceof
Solid
s
)
{
geom
=
parseSolid
(
s
,
lod
);
}
else
if
(
aGeom
instanceof
CompositeSurface
cs
)
{
geom
=
parseCompositeSurface
(
cs
,
lod
);
}
if
(
geom
!=
null
)
{
relGeo
=
RelativeGeometry
.
of
(
geom
);
igh
=
new
ImplicitGeometryHolder
(
ig
,
relGeo
);
}
}
else
{
logger
.
error
(
String
.
format
(
"Implicit geometry of GML-ID %s has no referenced geometry."
,
ig
.
getId
()));
}
return
igh
;
}
private
void
resolveAndClearReferences
()
{
for
(
ResolvableReference
ref
:
references
)
{
String
href
=
ref
.
href
();
if
(
href
.
startsWith
(
"#"
))
{
href
=
href
.
substring
(
1
);
}
Geometry
geom
=
ref
.
geometry
();
CompositeCollection
comp
=
compositeMap
.
get
(
href
);
if
(
comp
!=
null
)
{
comp
.
getCompositeMembers
().
forEach
(
geom:
:
addPolygon
);
}
else
{
ConcretePolygon
concPoly
=
polygonMap
.
get
(
href
);
if
(
concPoly
==
null
)
{
if
(
logger
.
isWarnEnabled
())
{
logger
.
warn
(
Localization
.
getText
(
"FeatureMapper.polygonUnreferenced"
),
href
);
}
}
else
{
LinkedPolygon
lPoly
=
new
LinkedPolygon
(
concPoly
,
geom
);
if
(
geom
.
getParent
()
instanceof
BoundarySurface
bs
)
{
lPoly
.
setPartOfSurface
(
bs
);
if
(
bs
.
getParent
()
instanceof
Installation
bi
)
{
lPoly
.
setPartOfInstallation
(
bi
);
}
}
geom
.
addPolygon
(
lPoly
);
}
}
}
// clear storage for polygons and vertices
// probably faster than .clear() ?
references
=
new
ArrayList
<>();
vertexMap
=
new
HashMap
<>();
polygonMap
=
new
HashMap
<>();
}
private
void
readAbstractBuilding
(
org
.
citygml4j
.
core
.
model
.
building
.
AbstractBuilding
gmlAb
,
AbstractBuilding
cdBuilding
)
{
mapAbstractOccupiedSpace
(
gmlAb
,
cdBuilding
);
cdBuilding
.
setGmlObject
(
gmlAb
);
// parse deprecated geometries
parseAndAddMultiSurface
(
gmlAb
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
cdBuilding
);
parseAndAddMultiSurface
(
gmlAb
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
cdBuilding
);
parseAndAddSolid
(
gmlAb
.
getDeprecatedProperties
().
getLod4Solid
(),
Lod
.
LOD4
,
cdBuilding
);
for
(
BuildingInstallationProperty
biProp
:
gmlAb
.
getBuildingInstallations
())
{
var
gmlBi
=
biProp
.
getObject
();
if
(
gmlBi
==
null
)
{
// ignore empty properties
continue
;
}
Installation
bi
=
mapBuildingInstallation
(
gmlBi
);
cdBuilding
.
addBuildingInstallation
(
bi
);
}
for
(
BuildingRoomProperty
brProp
:
gmlAb
.
getBuildingRooms
())
{
var
gmlBr
=
brProp
.
getObject
();
if
(
gmlBr
==
null
)
{
continue
;
}
BuildingRoom
br
=
mapBuildingRoom
(
gmlBr
);
cdBuilding
.
addBuildingRoom
(
br
);
}
for
(
AbstractBuildingSubdivisionProperty
abs
:
gmlAb
.
getBuildingSubdivisions
())
{
var
gmlABS
=
abs
.
getObject
();
if
(
gmlABS
==
null
)
{
continue
;
}
if
(
gmlABS
instanceof
Storey
gmlStorey
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Storey
storey
=
mapBuildingStorey
(
gmlStorey
);
cdBuilding
.
addStorey
(
storey
);
}
else
if
(
gmlABS
instanceof
BuildingUnit
gmlBU
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BuildingUnit
bu
=
mapBuildingUnit
(
gmlBU
);
cdBuilding
.
addBuildingUnit
(
bu
);
}
}
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlAb
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
updatePartOfSurface
(
cdBuilding
,
surfaceMapper
);
cdBuilding
.
unsetGmlGeometries
();
resolveAndClearReferences
();
updateEdgesAndVertices
(
cdBuilding
);
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
updateEdgesAndVertices
(
bs
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
updateEdgesAndVertices
(
o
);
}
}
for
(
Installation
bi
:
cdBuilding
.
getBuildingInstallations
())
{
updateEdgesAndVertices
(
bi
);
for
(
BoundarySurface
bs
:
bi
.
getBoundarySurfaces
())
{
updateEdgesAndVertices
(
bs
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
updateEdgesAndVertices
(
o
);
}
}
}
for
(
BuildingFurnitureProperty
bfProp
:
gmlAb
.
getBuildingFurniture
())
{
var
gmlBf
=
bfProp
.
getObject
();
if
(
gmlBf
==
null
)
{
continue
;
}
BuildingRoomFurniture
bf
=
mapBuildingFurniture
(
gmlBf
);
cdBuilding
.
addBuildingRoomFurniture
(
bf
);
}
}
private
BuildingRoom
mapBuildingRoom
(
org
.
citygml4j
.
core
.
model
.
building
.
BuildingRoom
gmlBr
)
{
BuildingRoom
br
=
new
BuildingRoom
();
br
.
setGmlObject
(
gmlBr
);
mapAbstractUnoccupiedSpace
(
gmlBr
,
br
);
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlBr
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
br
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
for
(
BuildingInstallationProperty
biProp
:
gmlBr
.
getBuildingInstallations
())
{
var
gmlBi
=
biProp
.
getObject
();
if
(
gmlBi
==
null
)
{
// ignore empty properties
continue
;
}
Installation
bi
=
mapBuildingInstallation
(
gmlBi
);
br
.
addRoomInstallation
(
bi
);
}
for
(
BuildingFurnitureProperty
bfProp
:
gmlBr
.
getBuildingFurniture
())
{
var
gmlHref
=
bfProp
.
getHref
();
if
(
gmlHref
==
null
)
{
continue
;
}
br
.
addFurnitureRef
(
bfProp
);
}
return
br
;
}
private
BuildingRoomFurniture
mapBuildingFurniture
(
BuildingFurniture
gmlAF
)
{
BuildingRoomFurniture
bf
=
new
BuildingRoomFurniture
();
bf
.
setGmlObject
(
gmlAF
);
mapAbstractOccupiedSpace
(
gmlAF
,
bf
);
bf
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlAF
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bf
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
return
bf
;
}
private
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Storey
mapBuildingStorey
(
Storey
gmlStorey
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Storey
storey
=
new
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Storey
();
storey
.
setGmlObject
(
gmlStorey
);
mapAbstractSpace
(
gmlStorey
,
storey
);
storey
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlStorey
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
storey
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
return
storey
;
}
private
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BuildingUnit
mapBuildingUnit
(
BuildingUnit
gmlBU
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BuildingUnit
bu
=
new
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BuildingUnit
();
bu
.
setGmlObject
(
gmlBU
);
mapAbstractSpace
(
gmlBU
,
bu
);
bu
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlBU
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bu
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
return
bu
;
}
private
void
updatePartOfSurface
(
AbstractBuilding
cdBuilding
,
SurfaceMapper
surfaceMapper
)
{
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
cdBuilding
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
}
private
Installation
mapBuildingInstallation
(
org
.
citygml4j
.
core
.
model
.
building
.
BuildingInstallation
gmlBi
)
{
Installation
bi
=
new
Installation
();
bi
.
setGmlObject
(
gmlBi
);
mapAbstractOccupiedSpace
(
gmlBi
,
bi
);
GeometryProperty
<?>
lod2Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod2Geometry
();
parseAndAddAbstractGeometry
(
lod2Prop
,
Lod
.
LOD2
,
bi
);
GeometryProperty
<?>
lod3Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod3Geometry
();
parseAndAddAbstractGeometry
(
lod3Prop
,
Lod
.
LOD3
,
bi
);
GeometryProperty
<?>
lod4Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod4Geometry
();
parseAndAddAbstractGeometry
(
lod4Prop
,
Lod
.
LOD4
,
bi
);
bi
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlBi
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bi
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
p
.
setPartOfInstallation
(
bi
);
}
}
}
for
(
Geometry
geom
:
bi
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfInstallation
(
bi
);
}
}
return
bi
;
}
private
void
parseAndAddAbstractGeometry
(
GeometryProperty
<?>
geomProp
,
Lod
lod
,
CityObject
co
)
{
if
(
geomProp
==
null
||
geomProp
.
getObject
()
==
null
)
{
return
;
}
AbstractGeometry
abstractGeometry
=
geomProp
.
getObject
();
if
(
abstractGeometry
instanceof
MultiSurface
ms
)
{
Geometry
geom
=
parseMultiSurface
(
ms
,
lod
);
co
.
addGeometry
(
geom
);
}
else
if
(
abstractGeometry
instanceof
Solid
solid
)
{
Geometry
geom
=
parseSolid
(
solid
,
lod
);
if
(
geom
!=
null
)
{
co
.
addGeometry
(
geom
);
}
}
else
{
logger
.
warn
(
"Cannot handle geometry type {}, ignoring"
,
abstractGeometry
.
getClass
().
getSimpleName
());
}
}
private
Geometry
parseSolid
(
AbstractSolid
abstractSolid
,
Lod
lod
)
{
if
(
abstractSolid
instanceof
Solid
s
)
{
return
handleSolidGeometry
(
s
,
lod
);
}
else
{
logger
.
warn
(
"Cannot handle solid class {}, can only process pure solids"
,
abstractSolid
.
getClass
().
getSimpleName
());
return
null
;
}
}
private
Geometry
handleSolidGeometry
(
Solid
solid
,
Lod
lod
)
{
ShellProperty
exteriorProperty
=
solid
.
getExterior
();
if
(
exteriorProperty
==
null
||
exteriorProperty
.
getObject
()
==
null
)
{
logger
.
warn
(
"Found solid {} without exterior hull, ignoring"
,
solid
.
getId
());
return
null
;
}
Geometry
geom
=
new
Geometry
(
GeometryType
.
SOLID
,
lod
);
Shell
exterior
=
solid
.
getExterior
().
getObject
();
Citygml3GeometryMapper
geometryMapper
=
new
Citygml3GeometryMapper
(
config
,
vertexMap
);
readSurfaceMember
(
geom
,
geometryMapper
,
exterior
.
getSurfaceMembers
());
return
geom
;
}
private
Geometry
parseMultiSurface
(
MultiSurface
ms
,
Lod
lod
)
{
Geometry
geom
=
new
Geometry
(
GeometryType
.
MULTI_SURFACE
,
lod
);
Citygml3GeometryMapper
geometryMapper
=
new
Citygml3GeometryMapper
(
config
,
vertexMap
);
readSurfaceMember
(
geom
,
geometryMapper
,
ms
.
getSurfaceMember
());
return
geom
;
}
private
void
readSurfaceMember
(
Geometry
geom
,
Citygml3GeometryMapper
geometryMapper
,
List
<
SurfaceProperty
>
surfaceMember
)
{
for
(
SurfaceProperty
prop
:
surfaceMember
)
{
if
(
prop
.
getHref
()
!=
null
)
{
references
.
add
(
new
ResolvableReference
(
prop
.
getHref
(),
geom
));
continue
;
}
if
(
prop
.
getObject
()
!=
null
)
{
AbstractSurface
as
=
prop
.
getObject
();
as
.
accept
(
geometryMapper
);
}
}
List
<
ConcretePolygon
>
polygons
=
geometryMapper
.
getPolygons
();
for
(
ConcretePolygon
concretePoly
:
polygons
)
{
geom
.
addPolygon
(
concretePoly
);
if
(
concretePoly
.
hasExistingGmlId
())
{
polygonMap
.
put
(
concretePoly
.
getGmlId
().
getGmlString
(),
concretePoly
);
}
}
}
private
Geometry
parseCompositeSurface
(
CompositeSurface
cs
,
Lod
lod
)
{
Geometry
geom
=
new
Geometry
(
GeometryType
.
COMPOSITE_SURFACE
,
lod
);
Citygml3GeometryMapper
geometryMapper
=
new
Citygml3GeometryMapper
(
config
,
vertexMap
);
readSurfaceMember
(
geom
,
geometryMapper
,
cs
.
getSurfaceMembers
());
return
geom
;
}
private
void
updateEdgesAndVertices
(
CityObject
co
)
{
// searching for neighboring vertices, replacing them with one single vertex to
// avoid later problems with edges and manifold problems
for
(
Geometry
geom
:
co
.
getGeometries
())
{
KDTree
tree
=
new
KDTree
();
for
(
Polygon
poly
:
geom
.
getPolygons
())
{
LinearRing
lr
=
poly
.
getExteriorRing
();
updateRing
(
tree
,
lr
);
for
(
LinearRing
innerRing
:
poly
.
getInnerRings
())
{
updateRing
(
tree
,
innerRing
);
}
}
if
(!
config
.
useLowMemoryConsumption
())
{
// no low memory consumption mode meaning create all meta information in
// geometry
geom
.
updateEdgesAndVertices
();
}
}
}
private
void
updateRing
(
KDTree
tree
,
LinearRing
lr
)
{
for
(
int
i
=
0
;
i
<
lr
.
getVertices
().
size
();
i
++)
{
Vertex
v
=
lr
.
getVertices
().
get
(
i
);
List
<
Vertex
>
nodesInRange
=
tree
.
getNodesInRange
(
v
,
neighborDistance
);
if
(
nodesInRange
.
isEmpty
())
{
tree
.
add
(
v
);
private
void
parseImplicitGeometry
(
AbstractOccupiedSpace
aos
,
CityObject
co
)
{
for
(
int
i
=
1
;
i
<=
3
;
i
++)
{
if
(
aos
.
getImplicitRepresentation
(
i
)
==
null
)
{
continue
;
}
if
(
aos
.
getImplicitRepresentation
(
i
).
getObject
()
!=
null
)
{
ImplicitGeometry
impGeom
=
aos
.
getImplicitRepresentation
(
i
).
getObject
();
ImplicitGeometryHolder
igh
=
resolveImplicitGeometry
(
impGeom
,
i
);
if
(
igh
!=
null
)
{
co
.
addGeometry
(
igh
);
}
}
else
if
(
aos
.
getImplicitRepresentation
(
i
).
getHref
()
!=
null
)
{
// Hrefs of ImplicitGeometries point to its RelativeGeometry.
// Can be ignored for CD since the Href is only used for repeating the
// RelativeGeometry at different LODs
}
}
}
private
ImplicitGeometryHolder
resolveImplicitGeometry
(
ImplicitGeometry
ig
,
int
lodInt
)
{
ImplicitGeometryHolder
igh
=
null
;
if
(
ig
.
getLibraryObject
()
!=
null
)
{
LibraryObject
libObj
=
null
;
if
(
directory
!=
null
){
Path
libraryObjectPath
=
directory
.
resolve
(
ig
.
getLibraryObject
());
libObj
=
LibraryObject
.
of
(
libraryObjectPath
,
config
);
}
else
{
// replace other vertex with any neighboring one
Vertex
original
=
nodesInRange
.
get
(
0
);
lr
.
setVertex
(
i
,
original
);
}
}
}
public
void
setCityModel
(
CityModel
cModel
)
{
model
.
setCityModel
(
cModel
);
}
public
CityDoctorModel
getModel
()
{
return
model
;
}
public
void
setCityGMLVersion
(
CityGMLVersion
cityGMLVersion
)
{
model
.
setParsedCityGMLVersion
(
cityGMLVersion
);
}
String
libraryObjectPath
=
ig
.
getLibraryObject
();
Path
loPath
=
zipEntry
.
resolveLibraryObjectPath
(
libraryObjectPath
);
CityGmlZipEntry
libEntry
=
zipEntry
.
getArchive
().
getEntry
(
loPath
.
toString
());
libObj
=
LibraryObject
.
of
(
libEntry
,
config
);
}
if
(
libObj
!=
null
)
{
igh
=
new
ImplicitGeometryHolder
(
ig
,
libObj
);
}
}
else
if
(
ig
.
getRelativeGeometry
()
!=
null
)
{
AbstractGeometry
aGeom
=
ig
.
getRelativeGeometry
().
getObject
();
Geometry
geom
=
null
;
Lod
lod
=
Lod
.
values
()[
lodInt
];
RelativeGeometry
relGeo
=
null
;
if
(
aGeom
instanceof
MultiSurface
ms
)
{
geom
=
parseMultiSurface
(
ms
,
lod
);
}
else
if
(
aGeom
instanceof
Solid
s
)
{
geom
=
parseSolid
(
s
,
lod
);
}
else
if
(
aGeom
instanceof
CompositeSurface
cs
)
{
geom
=
parseCompositeSurface
(
cs
,
lod
);
}
if
(
geom
!=
null
)
{
relGeo
=
RelativeGeometry
.
of
(
geom
);
igh
=
new
ImplicitGeometryHolder
(
ig
,
relGeo
);
}
}
else
{
logger
.
error
(
"Implicit geometry of GML-ID {} has no referenced geometry."
,
ig
.
getId
());
}
return
igh
;
}
private
void
resolveAndClearReferences
()
{
for
(
ResolvableReference
ref
:
references
)
{
String
href
=
ref
.
href
();
if
(
href
.
startsWith
(
"#"
))
{
href
=
href
.
substring
(
1
);
}
Geometry
geom
=
ref
.
geometry
();
CompositeCollection
comp
=
compositeMap
.
get
(
href
);
if
(
comp
!=
null
)
{
// composite collection, add each containing polygon to the geometry
comp
.
getCompositeMembers
().
forEach
(
geom:
:
addPolygon
);
}
else
{
handlePolygonReference
(
href
,
geom
);
}
}
// clear storage for polygons and vertices
references
=
new
ArrayList
<>();
vertexMap
=
new
HashMap
<>();
polygonMap
=
new
HashMap
<>();
}
private
void
handlePolygonReference
(
String
href
,
Geometry
geom
)
{
ConcretePolygon
concPoly
=
polygonMap
.
get
(
href
);
if
(
concPoly
==
null
)
{
if
(
logger
.
isWarnEnabled
())
{
logger
.
warn
(
Localization
.
getText
(
"FeatureMapper.polygonUnreferenced"
),
href
);
}
}
else
{
LinkedPolygon
lPoly
=
new
LinkedPolygon
(
concPoly
,
geom
);
if
(
geom
.
getParent
()
instanceof
BoundarySurface
bs
)
{
lPoly
.
setPartOfSurface
(
bs
);
if
(
bs
.
getParent
()
instanceof
Installation
bi
)
{
lPoly
.
setPartOfInstallation
(
bi
);
}
}
geom
.
addPolygon
(
lPoly
);
}
}
private
void
readAbstractBuilding
(
org
.
citygml4j
.
core
.
model
.
building
.
AbstractBuilding
gmlAb
,
AbstractBuilding
cdBuilding
)
{
mapAbstractOccupiedSpace
(
gmlAb
,
cdBuilding
);
cdBuilding
.
setGmlObject
(
gmlAb
);
// parse deprecated geometries
parseAndAddMultiSurface
(
gmlAb
.
getDeprecatedProperties
().
getLod1MultiSurface
(),
Lod
.
LOD1
,
cdBuilding
);
parseAndAddMultiSurface
(
gmlAb
.
getDeprecatedProperties
().
getLod4MultiSurface
(),
Lod
.
LOD4
,
cdBuilding
);
parseAndAddSolid
(
gmlAb
.
getDeprecatedProperties
().
getLod4Solid
(),
Lod
.
LOD4
,
cdBuilding
);
parseBuildingInstallations
(
gmlAb
,
cdBuilding
);
parseBuildingRooms
(
gmlAb
,
cdBuilding
);
parseBuildingSubdivisions
(
gmlAb
,
cdBuilding
);
parseBoundarySurfaces
(
gmlAb
,
cdBuilding
);
parseBuildingFurniture
(
gmlAb
,
cdBuilding
);
}
private
void
parseBuildingFurniture
(
org
.
citygml4j
.
core
.
model
.
building
.
AbstractBuilding
gmlAb
,
AbstractBuilding
cdBuilding
)
{
for
(
BuildingFurnitureProperty
bfProp
:
gmlAb
.
getBuildingFurniture
())
{
var
gmlBf
=
bfProp
.
getObject
();
if
(
gmlBf
==
null
)
{
continue
;
}
BuildingRoomFurniture
bf
=
mapBuildingFurniture
(
gmlBf
);
cdBuilding
.
addBuildingRoomFurniture
(
bf
);
}
}
private
void
parseBoundarySurfaces
(
org
.
citygml4j
.
core
.
model
.
building
.
AbstractBuilding
gmlAb
,
AbstractBuilding
cdBuilding
)
{
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlAb
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
updatePartOfSurface
(
cdBuilding
,
surfaceMapper
);
cdBuilding
.
unsetGmlGeometries
();
resolveAndClearReferences
();
updateEdgesAndVertices
(
cdBuilding
);
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
updateEdgesAndVertices
(
bs
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
updateEdgesAndVertices
(
o
);
}
}
}
private
void
parseBuildingSubdivisions
(
org
.
citygml4j
.
core
.
model
.
building
.
AbstractBuilding
gmlAb
,
AbstractBuilding
cdBuilding
)
{
for
(
AbstractBuildingSubdivisionProperty
abs
:
gmlAb
.
getBuildingSubdivisions
())
{
var
gmlABS
=
abs
.
getObject
();
if
(
gmlABS
==
null
)
{
continue
;
}
if
(
gmlABS
instanceof
Storey
gmlStorey
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Storey
storey
=
mapBuildingStorey
(
gmlStorey
);
cdBuilding
.
addStorey
(
storey
);
}
else
if
(
gmlABS
instanceof
BuildingUnit
gmlBU
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BuildingUnit
bu
=
mapBuildingUnit
(
gmlBU
);
cdBuilding
.
addBuildingUnit
(
bu
);
}
}
}
private
void
parseBuildingRooms
(
org
.
citygml4j
.
core
.
model
.
building
.
AbstractBuilding
gmlAb
,
AbstractBuilding
cdBuilding
)
{
for
(
BuildingRoomProperty
brProp
:
gmlAb
.
getBuildingRooms
())
{
var
gmlBr
=
brProp
.
getObject
();
if
(
gmlBr
==
null
)
{
continue
;
}
BuildingRoom
br
=
mapBuildingRoom
(
gmlBr
);
cdBuilding
.
addBuildingRoom
(
br
);
}
}
private
void
parseBuildingInstallations
(
org
.
citygml4j
.
core
.
model
.
building
.
AbstractBuilding
gmlAb
,
AbstractBuilding
cdBuilding
)
{
for
(
BuildingInstallationProperty
biProp
:
gmlAb
.
getBuildingInstallations
())
{
var
gmlBi
=
biProp
.
getObject
();
if
(
gmlBi
==
null
)
{
// ignore empty properties
continue
;
}
Installation
bi
=
mapBuildingInstallation
(
gmlBi
);
cdBuilding
.
addBuildingInstallation
(
bi
);
}
for
(
Installation
bi
:
cdBuilding
.
getBuildingInstallations
())
{
updateEdgesAndVertices
(
bi
);
for
(
BoundarySurface
bs
:
bi
.
getBoundarySurfaces
())
{
updateEdgesAndVertices
(
bs
);
for
(
Opening
o
:
bs
.
getOpenings
())
{
updateEdgesAndVertices
(
o
);
}
}
}
}
private
BuildingRoom
mapBuildingRoom
(
org
.
citygml4j
.
core
.
model
.
building
.
BuildingRoom
gmlBr
)
{
BuildingRoom
br
=
new
BuildingRoom
();
br
.
setGmlObject
(
gmlBr
);
mapAbstractUnoccupiedSpace
(
gmlBr
,
br
);
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlBr
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
br
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
for
(
BuildingInstallationProperty
biProp
:
gmlBr
.
getBuildingInstallations
())
{
var
gmlBi
=
biProp
.
getObject
();
if
(
gmlBi
==
null
)
{
// ignore empty properties
continue
;
}
Installation
bi
=
mapBuildingInstallation
(
gmlBi
);
br
.
addRoomInstallation
(
bi
);
}
for
(
BuildingFurnitureProperty
bfProp
:
gmlBr
.
getBuildingFurniture
())
{
var
gmlHref
=
bfProp
.
getHref
();
if
(
gmlHref
==
null
)
{
continue
;
}
br
.
addFurnitureRef
(
bfProp
);
}
return
br
;
}
private
BuildingRoomFurniture
mapBuildingFurniture
(
BuildingFurniture
gmlAF
)
{
BuildingRoomFurniture
bf
=
new
BuildingRoomFurniture
();
bf
.
setGmlObject
(
gmlAF
);
mapAbstractOccupiedSpace
(
gmlAF
,
bf
);
bf
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlAF
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bf
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
return
bf
;
}
private
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Storey
mapBuildingStorey
(
Storey
gmlStorey
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Storey
storey
=
new
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
Storey
();
storey
.
setGmlObject
(
gmlStorey
);
mapAbstractSpace
(
gmlStorey
,
storey
);
storey
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlStorey
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
storey
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
return
storey
;
}
private
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BuildingUnit
mapBuildingUnit
(
BuildingUnit
gmlBU
)
{
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BuildingUnit
bu
=
new
de
.
hft
.
stuttgart
.
citydoctor2
.
datastructure
.
BuildingUnit
();
bu
.
setGmlObject
(
gmlBU
);
mapAbstractSpace
(
gmlBU
,
bu
);
bu
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlBU
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bu
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
return
bu
;
}
private
void
updatePartOfSurface
(
AbstractBuilding
cdBuilding
,
SurfaceMapper
surfaceMapper
)
{
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
cdBuilding
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
}
}
}
}
private
Installation
mapBuildingInstallation
(
org
.
citygml4j
.
core
.
model
.
building
.
BuildingInstallation
gmlBi
)
{
Installation
bi
=
new
Installation
();
bi
.
setGmlObject
(
gmlBi
);
mapAbstractOccupiedSpace
(
gmlBi
,
bi
);
GeometryProperty
<?>
lod2Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod2Geometry
();
parseAndAddAbstractGeometry
(
lod2Prop
,
Lod
.
LOD2
,
bi
);
GeometryProperty
<?>
lod3Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod3Geometry
();
parseAndAddAbstractGeometry
(
lod3Prop
,
Lod
.
LOD3
,
bi
);
GeometryProperty
<?>
lod4Prop
=
gmlBi
.
getDeprecatedProperties
().
getLod4Geometry
();
parseAndAddAbstractGeometry
(
lod4Prop
,
Lod
.
LOD4
,
bi
);
bi
.
unsetGmlGeometries
();
SurfaceMapper
surfaceMapper
=
new
SurfaceMapper
(
polygonMap
,
references
,
compositeMap
,
vertexMap
,
config
);
for
(
AbstractSpaceBoundaryProperty
surfaceProp
:
gmlBi
.
getBoundaries
())
{
if
(!
surfaceProp
.
isSetObject
())
{
continue
;
}
AbstractSpaceBoundary
surface
=
surfaceProp
.
getObject
();
surface
.
accept
(
surfaceMapper
);
}
for
(
BoundarySurface
bs
:
surfaceMapper
.
getSurfaces
())
{
bi
.
addBoundarySurface
(
bs
);
for
(
Geometry
geom
:
bs
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfSurface
(
bs
);
p
.
setPartOfInstallation
(
bi
);
}
}
}
for
(
Geometry
geom
:
bi
.
getGeometries
())
{
for
(
Polygon
p
:
geom
.
getPolygons
())
{
p
.
setPartOfInstallation
(
bi
);
}
}
return
bi
;
}
private
void
parseAndAddAbstractGeometry
(
GeometryProperty
<?>
geomProp
,
Lod
lod
,
CityObject
co
)
{
if
(
geomProp
==
null
||
geomProp
.
getObject
()
==
null
)
{
return
;
}
AbstractGeometry
abstractGeometry
=
geomProp
.
getObject
();
if
(
abstractGeometry
instanceof
MultiSurface
ms
)
{
Geometry
geom
=
parseMultiSurface
(
ms
,
lod
);
co
.
addGeometry
(
geom
);
}
else
if
(
abstractGeometry
instanceof
Solid
solid
)
{
Geometry
geom
=
parseSolid
(
solid
,
lod
);
if
(
geom
!=
null
)
{
co
.
addGeometry
(
geom
);
}
}
else
{
logger
.
warn
(
"Cannot handle geometry type {}, ignoring"
,
abstractGeometry
.
getClass
().
getSimpleName
());
}
}
private
Geometry
parseSolid
(
AbstractSolid
abstractSolid
,
Lod
lod
)
{
if
(
abstractSolid
instanceof
Solid
s
)
{
return
handleSolidGeometry
(
s
,
lod
);
}
else
{
logger
.
warn
(
"Cannot handle solid class {}, can only process pure solids"
,
abstractSolid
.
getClass
().
getSimpleName
());
return
null
;
}
}
private
Geometry
handleSolidGeometry
(
Solid
solid
,
Lod
lod
)
{
ShellProperty
exteriorProperty
=
solid
.
getExterior
();
if
(
exteriorProperty
==
null
||
exteriorProperty
.
getObject
()
==
null
)
{
logger
.
warn
(
"Found solid {} without exterior hull, ignoring"
,
solid
.
getId
());
return
null
;
}
Geometry
geom
=
new
Geometry
(
GeometryType
.
SOLID
,
lod
);
Shell
exterior
=
solid
.
getExterior
().
getObject
();
Citygml3GeometryMapper
geometryMapper
=
new
Citygml3GeometryMapper
(
config
,
vertexMap
);
readSurfaceMember
(
geom
,
geometryMapper
,
exterior
.
getSurfaceMembers
());
return
geom
;
}
private
Geometry
parseMultiSurface
(
MultiSurface
ms
,
Lod
lod
)
{
Geometry
geom
=
new
Geometry
(
GeometryType
.
MULTI_SURFACE
,
lod
);
Citygml3GeometryMapper
geometryMapper
=
new
Citygml3GeometryMapper
(
config
,
vertexMap
);
readSurfaceMember
(
geom
,
geometryMapper
,
ms
.
getSurfaceMember
());
return
geom
;
}
private
void
readSurfaceMember
(
Geometry
geom
,
Citygml3GeometryMapper
geometryMapper
,
List
<
SurfaceProperty
>
surfaceMember
)
{
for
(
SurfaceProperty
prop
:
surfaceMember
)
{
if
(
prop
.
getHref
()
!=
null
)
{
references
.
add
(
new
ResolvableReference
(
prop
.
getHref
(),
geom
));
continue
;
}
if
(
prop
.
getObject
()
!=
null
)
{
AbstractSurface
as
=
prop
.
getObject
();
as
.
accept
(
geometryMapper
);
}
}
List
<
ConcretePolygon
>
polygons
=
geometryMapper
.
getPolygons
();
for
(
ConcretePolygon
concretePoly
:
polygons
)
{
geom
.
addPolygon
(
concretePoly
);
if
(
concretePoly
.
hasExistingGmlId
())
{
polygonMap
.
put
(
concretePoly
.
getGmlId
().
getGmlString
(),
concretePoly
);
}
}
}
private
Geometry
parseCompositeSurface
(
CompositeSurface
cs
,
Lod
lod
)
{
Geometry
geom
=
new
Geometry
(
GeometryType
.
COMPOSITE_SURFACE
,
lod
);
Citygml3GeometryMapper
geometryMapper
=
new
Citygml3GeometryMapper
(
config
,
vertexMap
);
readSurfaceMember
(
geom
,
geometryMapper
,
cs
.
getSurfaceMembers
());
return
geom
;
}
private
void
updateEdgesAndVertices
(
CityObject
co
)
{
// searching for neighboring vertices, replacing them with one single vertex to
// avoid later problems with edges and manifold problems
for
(
Geometry
geom
:
co
.
getGeometries
())
{
KDTree
tree
=
new
KDTree
();
for
(
Polygon
poly
:
geom
.
getPolygons
())
{
LinearRing
lr
=
poly
.
getExteriorRing
();
updateRing
(
tree
,
lr
);
for
(
LinearRing
innerRing
:
poly
.
getInnerRings
())
{
updateRing
(
tree
,
innerRing
);
}
}
if
(!
config
.
useLowMemoryConsumption
())
{
// no low memory consumption mode meaning create all meta information in
// geometry
geom
.
updateEdgesAndVertices
();
}
}
}
private
void
updateRing
(
KDTree
tree
,
LinearRing
lr
)
{
for
(
int
i
=
0
;
i
<
lr
.
getVertices
().
size
();
i
++)
{
Vertex
v
=
lr
.
getVertices
().
get
(
i
);
List
<
Vertex
>
nodesInRange
=
tree
.
getNodesInRange
(
v
,
neighborDistance
);
if
(
nodesInRange
.
isEmpty
())
{
tree
.
add
(
v
);
}
else
{
// replace other vertex with any neighboring one
Vertex
original
=
nodesInRange
.
get
(
0
);
lr
.
setVertex
(
i
,
original
);
}
}
}
public
void
setCityModel
(
CityModel
cModel
)
{
model
.
setCityModel
(
cModel
);
}
public
CityDoctorModel
getModel
()
{
return
model
;
}
public
void
setCityGMLVersion
(
CityGMLVersion
cityGMLVersion
)
{
model
.
setParsedCityGMLVersion
(
cityGMLVersion
);
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/mapper/citygml3/Citygml3GeometryMapper.java
View file @
2d57794b
...
...
@@ -59,10 +59,55 @@ public class Citygml3GeometryMapper extends GeometryWalker {
public
void
visit
(
Polygon
polygon
)
{
parsePolygon
(
polygon
.
getId
(),
polygon
.
getExterior
(),
polygon
.
getInterior
());
if
(
polygon
.
getExterior
()
==
null
)
{
logger
.
warn
(
String
.
format
(
"No exterior:
%s
"
,
polygon
.
getId
())
)
;
logger
.
warn
(
"No exterior:
{}
"
,
polygon
.
getId
());
}
}
@Override
public
void
visit
(
Surface
surface
)
{
if
(
surface
.
getPatches
()
!=
null
&&
!
surface
.
getPatches
().
isSetObjects
())
{
logger
.
warn
(
"Surface {} has no PolygonPatches."
,
surface
.
getId
());
return
;
}
PatchCollection
patchCollection
=
new
PatchCollection
();
GeometryWalker
patchCollector
=
new
GeometryWalker
()
{
@Override
public
void
visit
(
PolygonPatch
patch
)
{
parsePolygonPatch
(
patch
,
patchCollection
);
}
};
surface
.
getPatches
().
getObjects
().
forEach
(
abstractSurfacePatch
->
abstractSurfacePatch
.
accept
(
patchCollector
));
}
private
void
parsePolygonPatch
(
PolygonPatch
patch
,
PatchCollection
collection
)
{
AbstractRingProperty
exterior
=
patch
.
getExterior
();
List
<
AbstractRingProperty
>
interior
=
patch
.
getInterior
();
if
(
exterior
==
null
||
exterior
.
getObject
()
==
null
)
{
if
(
logger
.
isWarnEnabled
())
{
logger
.
warn
(
Localization
.
getText
(
"GeometryMapper.emptyPolygon"
));
}
return
;
}
ConcretePolygon
conc
=
new
ConcretePolygon
();
polygons
.
add
(
conc
);
currentRing
=
new
LinearRing
(
LinearRingType
.
EXTERIOR
);
exterior
.
getObject
().
accept
(
this
);
conc
.
setExteriorRing
(
currentRing
);
for
(
AbstractRingProperty
interiorGmlRing
:
interior
)
{
AbstractRing
gmlRing
=
interiorGmlRing
.
getObject
();
if
(
gmlRing
==
null
)
{
continue
;
}
currentRing
=
new
LinearRing
(
LinearRingType
.
INTERIOR
);
gmlRing
.
accept
(
this
);
conc
.
addInteriorRing
(
currentRing
);
}
collection
.
addPatchMember
(
conc
);
polygons
.
add
(
conc
);
}
private
void
parsePolygon
(
String
id
,
AbstractRingProperty
exterior
,
List
<
AbstractRingProperty
>
interior
)
{
if
(
exterior
==
null
||
exterior
.
getObject
()
==
null
)
{
if
(
logger
.
isWarnEnabled
())
{
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/MovedPolygon.java
View file @
2d57794b
...
...
@@ -39,6 +39,25 @@ public class MovedPolygon {
private
MovedRing
exteriorRing
;
private
List
<
MovedRing
>
innerRings
;
/**
* Moves the polygon by the first exterior vertex. The center of the polygon
* will not me the origin, the polygon will just be near the origin. This can
* eliviate numeric issues in large calculations.
*
* @param p the polygon that is moved to the center.
* @return the moved polygon.
*/
public
static
MovedPolygon
ofPolygon
(
Polygon
p
)
{
Vector3d
movedBy
=
p
.
getExteriorRing
().
getVertices
().
get
(
0
);
MovedPolygon
indPoly
=
new
MovedPolygon
();
indPoly
.
original
=
p
;
indPoly
.
exteriorRing
=
MovedRing
.
ofRing
(
p
.
getExteriorRing
(),
movedBy
);
for
(
LinearRing
inner
:
p
.
getInnerRings
())
{
indPoly
.
addInnerRing
(
MovedRing
.
ofRing
(
inner
,
movedBy
));
}
return
indPoly
;
}
public
static
MovedPolygon
ofPolygon
(
Polygon
p
,
Vector3d
movedBy
)
{
MovedPolygon
indPoly
=
new
MovedPolygon
();
indPoly
.
original
=
p
;
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Polygon2d.java
View file @
2d57794b
...
...
@@ -40,6 +40,11 @@ public class Polygon2d {
ProjectionAxis
axis
=
ProjectionAxis
.
of
(
poly
);
return
projectTo2D
(
poly
,
axis
);
}
public
static
Polygon2d
withProjection
(
MovedPolygon
poly
)
{
ProjectionAxis
axis
=
ProjectionAxis
.
of
(
poly
.
getOriginal
());
return
projectTo2D
(
poly
,
axis
);
}
public
static
Polygon2d
withProjection
(
MovedPolygon
poly
,
ProjectionAxis
projectionAxis
)
{
return
projectTo2D
(
poly
,
projectionAxis
);
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/ProjectionAxis.java
View file @
2d57794b
...
...
@@ -34,7 +34,7 @@ import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
*
*/
public
class
ProjectionAxis
{
private
static
final
String
DIVISOR_IS_0
=
"Divisor is 0"
;
private
final
int
[]
axis
;
...
...
@@ -87,20 +87,36 @@ public class ProjectionAxis {
this
.
axis
=
axis
;
}
/**
* This will write the two coordinates determined in this projection axis into a
* given array at the startIndex location. The array has to have at least a
* length of startIndex + 1.
*
* @param v the vector from which the coordinates are taken.
* @param array the array that is written to.
* @param startIndex the start location in the array.
*/
public
void
writeCoordinatesOfVectorInArray
(
Vector3d
v
,
double
[]
array
,
int
startIndex
)
{
array
[
startIndex
]
=
v
.
getCoordinate
(
axis
[
0
]);
array
[
startIndex
+
1
]
=
v
.
getCoordinate
(
axis
[
1
]);
}
public
Vector2d
project
(
Vector3d
v
)
{
return
new
Vector2d
(
v
.
getCoordinate
(
axis
[
0
]),
v
.
getCoordinate
(
axis
[
1
]));
}
/**
* calculates the missing coordinate for 3d vector from the plane and this axis.
*
* @return the projected 3d point.
*/
public
Vector3d
projectToPlane
(
Plane
plane
,
Vector2d
v
)
{
return
projectToPlane
(
plane
,
v
.
getX
(),
v
.
getY
());
}
/**
* calculates the missing coordinate for 3d vector from the plane and this axis.
*
* @return the projected 3d point.
*/
public
Vector3d
projectToPlane
(
Plane
plane
,
double
vectorX
,
double
vectorY
)
{
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/math/Vector3d.java
View file @
2d57794b
...
...
@@ -22,6 +22,8 @@ import java.io.Serial;
import
java.io.Serializable
;
import
java.util.Arrays
;
import
org.locationtech.jts.geom.Coordinate
;
/**
* A three dimensional vector
*
...
...
@@ -44,6 +46,17 @@ public class Vector3d implements Serializable {
public
Vector3d
()
{
this
(
0
d
,
0
d
,
0
d
);
}
/**
* Convert JTS Coordinate class to Vector3d.
* @param coord JTS Coordinate
*/
public
Vector3d
(
Coordinate
coord
)
{
coords
=
new
double
[
3
];
coords
[
0
]
=
coord
.
getX
();
coords
[
1
]
=
coord
.
getY
();
coords
[
2
]
=
coord
.
getZ
();
}
public
Vector3d
(
double
x
,
double
y
,
double
z
)
{
coords
=
new
double
[
3
];
...
...
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/parser/CityGmlParser.java
View file @
2d57794b
/*-
* Copyright 2022 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
...
...
@@ -18,30 +18,16 @@
*/
package
de.hft.stuttgart.citydoctor2.parser
;
import
java.io.BufferedInputStream
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
javax.xml.XMLConstants
;
import
javax.xml.namespace.QName
;
import
javax.xml.parsers.ParserConfigurationException
;
import
javax.xml.parsers.SAXParser
;
import
javax.xml.parsers.SAXParserFactory
;
import
javax.xml.transform.Source
;
import
javax.xml.transform.stream.StreamSource
;
import
javax.xml.validation.Schema
;
import
javax.xml.validation.SchemaFactory
;
import
javax.xml.validation.Validator
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.mapper.citygml3.Citygml3FeatureMapper
;
import
de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler
;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
de.hft.stuttgart.citydoctor2.utils.Localization
;
import
de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntry
;
import
de.hft.stuttgart.citydoctor2.zip.CityGmlZipEntryFile
;
import
de.hft.stuttgart.quality.QualityADEContext
;
import
de.hft.stuttgart.quality.QualityADEModule
;
import
org.apache.logging.log4j.Level
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.Logger
;
...
...
@@ -69,454 +55,648 @@ import org.locationtech.proj4j.BasicCoordinateTransform;
import
org.locationtech.proj4j.CRSFactory
;
import
org.locationtech.proj4j.CoordinateReferenceSystem
;
import
org.locationtech.proj4j.ProjCoordinate
;
import
org.locationtech.proj4j.io.Proj4FileReader
;
import
org.locationtech.proj4j.proj.Projection
;
import
org.locationtech.proj4j.units.Units
;
import
org.xml.sax.InputSource
;
import
org.xml.sax.SAXException
;
import
org.xml.sax.SAXNotRecognizedException
;
import
org.xml.sax.SAXNotSupportedException
;
import
org.xml.sax.SAXParseException
;
import
org.xmlobjects.schema.SchemaHandler
;
import
org.xmlobjects.schema.SchemaHandlerException
;
import
org.xmlobjects.stream.XMLReader
;
import
org.xmlobjects.stream.XMLReaderFactory
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel
;
import
de.hft.stuttgart.citydoctor2.datastructure.CityObject
;
import
de.hft.stuttgart.citydoctor2.mapper.citygml3.Citygml3FeatureMapper
;
import
de.hft.stuttgart.citydoctor2.mapper.citygml3.GMLValidationHandler
;
import
de.hft.stuttgart.citydoctor2.math.Vector3d
;
import
de.hft.stuttgart.citydoctor2.utils.Localization
;
import
de.hft.stuttgart.quality.QualityADEContext
;
import
de.hft.stuttgart.quality.QualityADEModule
;
import
javax.xml.XMLConstants
;
import
javax.xml.namespace.QName
;
import
javax.xml.parsers.ParserConfigurationException
;
import
javax.xml.parsers.SAXParser
;
import
javax.xml.parsers.SAXParserFactory
;
import
javax.xml.transform.Source
;
import
javax.xml.transform.stream.StreamSource
;
import
javax.xml.validation.Schema
;
import
javax.xml.validation.SchemaFactory
;
import
javax.xml.validation.Validator
;
import
java.io.BufferedInputStream
;
import
java.io.ByteArrayInputStream
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
/**
* Utility class to parse CityGML files.
*
* @author Matthias Betz
*
* @author Matthias Betz
*/
public
class
CityGmlParser
{
private
static
final
String
CITY_OBJECT_MEMBER
=
"cityObjectMember"
;
private
static
final
String
WGS_84
=
"EPSG:4326"
;
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
CityGmlParser
.
class
);
private
static
final
CRSFactory
CRS_FACTORY
=
new
CRSFactory
();
// EPSG:31467
private
static
final
Pattern
P_EPSG
=
Pattern
.
compile
(
"^(EPSG:\\d+)$"
);
// urn:ogc:def:crs,crs:EPSG:6.12:31467,crs:EPSG:6.12:5783
// or
// urn:ogc:def:crs,crs:EPSG::28992
private
static
final
Pattern
P_OGC
=
Pattern
.
compile
(
"urn:ogc:def:crs,crs:EPSG:[\\d\\.]*:([\\d]+)\\D*"
);
private
static
final
Pattern
P_OGC2
=
Pattern
.
compile
(
"urn:ogc:def:crs:EPSG:[\\d\\.]*:([\\d]+)\\D*"
);
// urn:adv:crs:DE_DHDN_3GK3*DE_DHHN92_NH
// urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH
private
static
final
Pattern
P_URN
=
Pattern
.
compile
(
"urn:adv:crs:([^\\*]+)"
);
private
static
final
SAXParserFactory
FACTORY
;
private
static
CityGMLContext
context
;
private
static
List
<
QName
>
chunkProperties
=
new
ArrayList
<>();
// Toggle to suppress logger output for parsing of libraryObjects
private
static
boolean
gagged
=
false
;
static
{
System
.
setProperty
(
"javax.xml.transform.TransformerFactory"
,
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"
);
FACTORY
=
SAXParserFactory
.
newInstance
();
try
{
FACTORY
.
setFeature
(
XMLConstants
.
FEATURE_SECURE_PROCESSING
,
false
);
}
catch
(
SAXNotRecognizedException
|
SAXNotSupportedException
|
ParserConfigurationException
e
)
{
logger
.
catching
(
e
);
}
chunkProperties
.
add
(
new
QName
(
CityGMLConstants
.
CITYGML_1_0_CORE_NAMESPACE
,
CITY_OBJECT_MEMBER
));
chunkProperties
.
add
(
new
QName
(
CityGMLConstants
.
CITYGML_2_0_CORE_NAMESPACE
,
CITY_OBJECT_MEMBER
));
chunkProperties
.
add
(
new
QName
(
CityGMLConstants
.
CITYGML_3_0_CORE_NAMESPACE
,
CITY_OBJECT_MEMBER
));
}
private
CityGmlParser
()
{
}
public
static
synchronized
CityGMLContext
getContext
()
{
if
(
context
==
null
)
{
try
{
context
=
CityGMLContext
.
newInstance
(
CityGmlParser
.
class
.
getClassLoader
());
// also setup ades
ADERegistry
adeRegistry
=
ADERegistry
.
getInstance
();
adeRegistry
.
loadADE
(
new
QualityADEContext
());
}
catch
(
CityGMLContextException
e
)
{
logger
.
fatal
(
"Unable to create citygml4j context"
,
e
);
throw
new
IllegalStateException
(
"Unable to create citygml4j context"
);
}
catch
(
ADEException
e
)
{
logger
.
fatal
(
"Unable to add ADE plugins to citygml4j"
,
e
);
throw
new
IllegalStateException
(
"Unable to add ADE plugins to citygml4j"
);
}
}
return
context
;
}
public
static
CityDoctorModel
parseCityGmlFile
(
String
file
,
ParserConfiguration
config
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
return
parseCityGmlFile
(
file
,
config
,
null
,
null
);
}
public
static
CityDoctorModel
parseCityGmlFile
(
String
file
,
ParserConfiguration
config
,
ProgressListener
l
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
return
parseCityGmlFile
(
file
,
config
,
l
,
null
);
}
public
static
CityDoctorModel
parseCityGmlFile
(
String
filePath
,
ParserConfiguration
config
,
ProgressListener
l
,
GMLValidationHandler
handler
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
CityGMLContext
context
=
getContext
();
Path
file
=
Paths
.
get
(
filePath
);
if
(
config
.
getValidate
())
{
List
<
String
>
messages
=
validateFile
(
context
,
handler
,
file
);
if
(!
messages
.
isEmpty
())
{
throw
new
InvalidGmlFileException
(
"Invalid GML File. First error: \n"
+
messages
.
get
(
0
));
}
}
try
{
parseEpsgCodeFromFile
(
file
,
config
);
CityGMLInputFactory
in
=
context
.
createCityGMLInputFactory
()
.
withChunking
(
ChunkOptions
.
chunkByProperties
(
chunkProperties
).
skipCityModel
(
false
));
try
(
ObservedInputStream
ois
=
new
ObservedInputStream
(
file
.
toFile
()))
{
if
(
l
!=
null
)
{
ois
.
addListener
(
l:
:
updateProgress
);
}
return
readAndKeepFeatures
(
config
,
file
,
in
,
ois
);
}
}
catch
(
CityGMLReadException
|
IOException
e
)
{
throw
new
CityGmlParseException
(
"Failed to read CityGML file"
,
e
);
}
}
public
static
void
streamCityGml
(
String
file
,
ParserConfiguration
config
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGmlParseException
{
Path
f
=
Paths
.
get
(
file
);
streamCityGml
(
f
,
config
,
null
,
cityObjectConsumer
,
outputFile
);
}
public
static
void
streamCityGml
(
File
file
,
ParserConfiguration
parserConfig
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGmlParseException
{
streamCityGml
(
file
.
toPath
(),
parserConfig
,
null
,
cityObjectConsumer
,
outputFile
);
}
public
static
void
streamCityGml
(
Path
file
,
ParserConfiguration
config
,
ProgressListener
l
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGmlParseException
{
parseEpsgCodeFromFile
(
file
,
config
);
startReadingCityGml
(
file
,
config
,
l
,
cityObjectConsumer
,
outputFile
);
}
public
static
CityModel
parseOnlyCityModel
(
File
inputFile
)
throws
CityGmlParseException
{
try
{
CityGMLInputFactory
inputFactory
=
context
.
createCityGMLInputFactory
()
.
withChunking
(
ChunkOptions
.
chunkByProperties
(
chunkProperties
).
skipCityModel
(
false
));
try
(
CityGMLReader
reader
=
inputFactory
.
createCityGMLReader
(
inputFile
))
{
while
(
reader
.
hasNext
())
{
AbstractFeature
chunk
=
reader
.
next
();
if
(
chunk
instanceof
CityModel
cModel
)
{
cModel
.
setCityObjectMembers
(
null
);
return
cModel
;
}
}
}
}
catch
(
CityGMLReadException
e
)
{
throw
new
CityGmlParseException
(
e
);
}
throw
new
CityGmlParseException
(
"Did not find any CityModel in CityGML file"
);
}
private
static
void
startReadingCityGml
(
Path
file
,
ParserConfiguration
config
,
ProgressListener
l
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
{
try
(
ObservedInputStream
ois
=
new
ObservedInputStream
(
file
.
toFile
()))
{
if
(
l
!=
null
)
{
ois
.
addListener
(
l:
:
updateProgress
);
}
readAndDiscardFeatures
(
file
,
config
,
ois
,
cityObjectConsumer
,
outputFile
);
}
catch
(
IOException
|
CityGMLReadException
e
)
{
logger
.
error
(
Localization
.
getText
(
"CityGmlParser.errorReadingGmlFile"
),
e
.
getMessage
());
logger
.
catching
(
Level
.
ERROR
,
e
);
}
}
private
static
void
readAndDiscardFeatures
(
Path
file
,
ParserConfiguration
config
,
ObservedInputStream
ois
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGMLReadException
{
getContext
();
CityGMLInputFactory
inputFactory
=
context
.
createCityGMLInputFactory
()
.
withChunking
(
ChunkOptions
.
chunkByProperties
(
chunkProperties
).
skipCityModel
(
false
));
CityGMLChunkWriter
writer
=
null
;
try
(
CityGMLReader
reader
=
inputFactory
.
createCityGMLReader
(
ois
))
{
Citygml3FeatureMapper
mapper
=
new
Citygml3FeatureMapper
(
config
,
file
);
CityDoctorModel
model
=
mapper
.
getModel
();
boolean
isInitialized
=
false
;
while
(
reader
.
hasNext
())
{
AbstractFeature
chunk
=
reader
.
next
();
if
(
writer
==
null
)
{
writer
=
createCityModelWriter
(
outputFile
,
reader
);
}
if
(!
isInitialized
&&
writer
!=
null
&&
reader
.
getParentInfo
()
!=
null
&&
reader
.
getParentInfo
().
getTypeName
().
getLocalPart
().
equals
(
"CityModel"
))
{
FeatureInfo
parentInfo
=
reader
.
getParentInfo
();
writer
.
withCityModelInfo
(
parentInfo
);
isInitialized
=
true
;
}
if
(
chunk
instanceof
AbstractCityObject
ag
)
{
ag
.
accept
(
mapper
);
drainCityModel
(
model
,
cityObjectConsumer
);
writeAbstractCityObject
(
writer
,
ag
);
}
else
if
(
chunk
instanceof
CityModel
cModel
)
{
cModel
.
setCityObjectMembers
(
null
);
mapper
.
setCityModel
(
cModel
);
cityObjectConsumer
.
accept
(
cModel
);
writeCityModel
(
writer
,
cModel
);
}
else
if
(
writer
!=
null
)
{
writer
.
writeMember
(
chunk
);
}
}
// end of stream
logger
.
debug
(
"End of gml file stream"
);
}
catch
(
CityGMLReadException
e
)
{
logger
.
error
(
Localization
.
getText
(
"CityGmlParser.errorReadingGmlFile"
),
e
.
getMessage
(),
e
);
}
catch
(
CityGMLWriteException
e
)
{
logger
.
error
(
Localization
.
getText
(
"CityGmlParser.errorWritingGmlFile"
),
e
.
getMessage
(),
e
);
}
finally
{
if
(
writer
!=
null
)
{
try
{
writer
.
close
();
}
catch
(
CityGMLWriteException
e
)
{
// ignore
}
}
}
}
private
static
void
writeCityModel
(
CityGMLChunkWriter
writer
,
CityModel
cModel
)
{
if
(
writer
!=
null
)
{
for
(
ADEProperty
genEle
:
cModel
.
getADEProperties
())
{
writer
.
getCityModelInfo
().
addADEProperty
(
genEle
);
}
}
}
private
static
void
writeAbstractCityObject
(
CityGMLChunkWriter
writer
,
AbstractCityObject
ag
)
throws
CityGMLWriteException
{
if
(
writer
!=
null
)
{
writer
.
writeMember
(
ag
);
}
}
private
static
CityGMLChunkWriter
createCityModelWriter
(
String
outputFile
,
CityGMLReader
reader
)
throws
CityGMLWriteException
{
if
(
outputFile
==
null
)
{
return
null
;
}
CityGMLContext
gmlContext
=
CityGmlParser
.
getContext
();
CityGMLVersion
version
=
CityGMLModules
.
getCityGMLVersion
(
reader
.
getName
().
getNamespaceURI
());
CityGMLOutputFactory
factory
=
gmlContext
.
createCityGMLOutputFactory
(
version
);
CityGMLChunkWriter
writer
=
factory
.
createCityGMLChunkWriter
(
new
File
(
outputFile
),
StandardCharsets
.
UTF_8
.
name
());
writer
.
withPrefix
(
"qual"
,
QualityADEModule
.
NAMESPACE_URI
);
writer
.
withSchemaLocation
(
QualityADEModule
.
NAMESPACE_URI
,
QualityADEModule
.
NAMESPACE_URI
+
"/qualityAde.xsd"
);
writer
.
withIndent
(
" "
);
writer
.
withDefaultPrefixes
();
writer
.
withDefaultSchemaLocations
();
return
writer
;
}
/**
* Suppresses logger output of {@link #readAndKeepFeatures} for the next parse.
* Used to prevent logging spam while resolving implicit geometries.
*/
public
static
void
gagLogger
(
boolean
value
){
gagged
=
value
;
}
private
static
CityDoctorModel
readAndKeepFeatures
(
ParserConfiguration
config
,
Path
file
,
CityGMLInputFactory
inputFactory
,
ObservedInputStream
ois
)
throws
CityGMLReadException
{
try
(
CityGMLReader
reader
=
inputFactory
.
createCityGMLReader
(
ois
))
{
Citygml3FeatureMapper
mapper
=
new
Citygml3FeatureMapper
(
config
,
file
);
CityGMLVersion
version
=
null
;
// model is read in chunked mode
// object members are replaced by href in model
// need to remove the refs and re-add unparsed objects
List
<
AbstractCityObject
>
acos
=
new
ArrayList
<>();
while
(
reader
.
hasNext
())
{
AbstractFeature
chunk
=
reader
.
next
();
version
=
CityGMLModules
.
getCityGMLVersion
(
reader
.
getName
().
getNamespaceURI
());
if
(
chunk
instanceof
CityModel
cModel
)
{
cModel
.
setCityObjectMembers
(
null
);
mapper
.
setCityModel
(
cModel
);
mapper
.
setCityGMLVersion
(
version
);
}
else
if
(
chunk
instanceof
AbstractCityObject
aco
)
{
acos
.
add
(
aco
);
aco
.
accept
(
mapper
);
}
}
if
(
mapper
.
getModel
().
getCityModel
()
==
null
)
{
// file does not contain a city model?
// create it for now
mapper
.
setCityModel
(
new
CityModel
());
}
CityModel
cModel
=
mapper
.
getModel
().
getCityModel
();
// remove those that should have been parsed
List
<
AbstractCityObject
>
parsedCityObjects
=
mapper
.
getModel
().
createFeatureStream
()
.
map
(
CityObject:
:
getGmlObject
).
toList
();
acos
.
removeAll
(
parsedCityObjects
);
// re-add all not parsed objects
for
(
AbstractCityObject
aco
:
acos
)
{
cModel
.
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
aco
));
}
if
(
logger
.
isInfoEnabled
()
&&
!
gagged
)
{
logger
.
info
(
Localization
.
getText
(
"CityGmlParser.parsedObjects"
),
mapper
.
getModel
().
getNumberOfFeatures
());
}
else
if
(
gagged
){
// Remove gag
gagged
=
false
;
}
mapper
.
setCityGMLVersion
(
version
);
return
mapper
.
getModel
();
}
}
private
static
void
parseEpsgCodeFromFile
(
Path
file
,
ParserConfiguration
config
)
throws
CityGmlParseException
{
try
(
BufferedInputStream
bis
=
new
BufferedInputStream
(
new
FileInputStream
(
file
.
toFile
())))
{
parseEpsgCodeFromStream
(
bis
,
config
);
}
catch
(
ParserConfigurationException
|
SAXException
|
IOException
e
)
{
throw
new
CityGmlParseException
(
"Failed to read CityGML file"
,
e
);
}
}
private
static
void
parseEpsgCodeFromStream
(
InputStream
is
,
ParserConfiguration
config
)
throws
ParserConfigurationException
,
SAXException
{
SAXParser
parser
=
FACTORY
.
newSAXParser
();
CityGmlHandler
handler
=
new
CityGmlHandler
();
try
{
parser
.
parse
(
new
InputSource
(
is
),
handler
);
}
catch
(
EnvelopeFoundException
e
)
{
try
{
parseCoordinateSystem
(
config
,
handler
);
}
catch
(
Exception
e2
)
{
logger
.
debug
(
"Exception while parsing for EPSG code"
,
e2
);
if
(
logger
.
isWarnEnabled
())
{
logger
.
warn
(
Localization
.
getText
(
"CityGmlParser.noEPSG"
));
}
}
}
catch
(
Exception
e
)
{
logger
.
debug
(
"Exception while parsing for EPSG code"
,
e
);
if
(
logger
.
isWarnEnabled
())
{
logger
.
warn
(
Localization
.
getText
(
"CityGmlParser.noEPSG"
));
}
}
}
private
static
void
parseCoordinateSystem
(
ParserConfiguration
config
,
CityGmlHandler
handler
)
{
if
(
handler
.
getEpsg
()
==
null
)
{
return
;
}
CoordinateReferenceSystem
crs
=
crsFromSrsName
(
handler
.
getEpsg
());
if
(
crs
==
null
)
{
// could not find a coordinate system for srsName
// assuming metric system
return
;
}
if
(
crs
.
getProjection
().
getUnits
()
==
Units
.
METRES
)
{
// coordinate system is in meters, do not convert
if
(
logger
.
isInfoEnabled
())
{
logger
.
info
(
Localization
.
getText
(
"CityGmlParser.noConversionNeeded"
));
}
return
;
}
parseMeterConversion
(
config
,
crs
);
Vector3d
low
=
handler
.
getLowerCorner
();
Vector3d
up
=
handler
.
getUpperCorner
();
double
centerLong
=
low
.
getX
()
+
((
up
.
getX
()
-
low
.
getX
())
/
2
);
double
centerLat
=
low
.
getY
()
+
((
up
.
getY
()
-
low
.
getY
())
/
2
);
if
(!
crs
.
getName
().
equals
(
WGS_84
))
{
// need to convert coordinates first to WGS84, then find UTM Zone
CoordinateReferenceSystem
wgs84
=
crsFromSrsName
(
WGS_84
);
ProjCoordinate
p1
=
new
ProjCoordinate
();
p1
.
setValue
(
centerLong
,
centerLat
);
ProjCoordinate
p2
=
new
ProjCoordinate
();
BasicCoordinateTransform
bct
=
new
BasicCoordinateTransform
(
crs
,
wgs84
);
bct
.
transform
(
p1
,
p2
);
centerLong
=
p2
.
x
;
centerLat
=
p2
.
y
;
}
int
zone
=
(
int
)
(
31
+
Math
.
round
(
centerLong
/
6
));
CoordinateReferenceSystem
utm
;
if
(
centerLat
<
0
)
{
// south
logger
.
info
(
"Converting coordiante system to UTM zone {}S"
,
zone
);
utm
=
CRS_FACTORY
.
createFromParameters
(
"UTM"
,
"+proj=utm +ellps=WGS84 +units=m +zone="
+
zone
+
" +south"
);
}
else
{
// north
logger
.
info
(
"Converting coordiante system to UTM zone {}N"
,
zone
);
utm
=
CRS_FACTORY
.
createFromParameters
(
"UTM"
,
"+proj=utm +ellps=WGS84 +units=m +zone="
+
zone
);
}
config
.
setCoordinateSystem
(
crs
,
utm
);
}
private
static
void
parseMeterConversion
(
ParserConfiguration
config
,
CoordinateReferenceSystem
crs
)
{
Projection
projection
=
crs
.
getProjection
();
double
fromMetres
=
projection
.
getFromMetres
();
if
(
fromMetres
>
0
)
{
// also transform height information
config
.
setFromMeters
(
fromMetres
);
}
else
{
config
.
setFromMeters
(
1.0
);
}
}
/**
* The srsName (The name by which this reference system is identified) inside
* the CityGML file can have multiple formats. This method tries to parse the
* string and detect the corresponding reference system. If it is found, it
* returns a proj4j.CoordinateReferenceSystem. It throws an
* IllegalArgumentException otherwise.
*
* This method should be able to parse any EPSG id : e.g. "EPSG:1234". German
* Citygmls might also have "DE_DHDN_3GK3" or "ETRS89_UTM32" as srsName, so
* those are also included. It isn't guaranteed that those formats are correctly
* parsed, though.
*
* The EPSG ids and parameters are defined in resources ('nad/epsg') inside
* proj4j-0.1.0.jar. Some EPSG ids are missing though, e.g. 7415
*
* @param srsName
* @return CoordinateReferenceSystem
*/
private
static
CoordinateReferenceSystem
crsFromSrsName
(
String
srsName
)
{
srsName
=
srsName
.
trim
();
Matcher
mEPSG
=
P_EPSG
.
matcher
(
srsName
);
if
(
mEPSG
.
find
())
{
if
(
"EPSG:4979"
.
contentEquals
(
srsName
))
{
srsName
=
"EPSG:4236"
;
}
else
if
(
"EPSG:7415"
.
contentEquals
(
srsName
))
{
return
CRS_FACTORY
.
createFromParameters
(
"EPSG:7415"
,
"+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.417,50.3319,465.552,-0.398957,0.343988,-1.8774,4.0725 +units=m +no_defs"
);
}
return
CRS_FACTORY
.
createFromName
(
srsName
);
}
Matcher
mOGC
=
P_OGC
.
matcher
(
srsName
);
if
(
mOGC
.
find
())
{
return
CRS_FACTORY
.
createFromName
(
"EPSG:"
+
mOGC
.
group
(
1
));
}
Matcher
mOGC2
=
P_OGC2
.
matcher
(
srsName
);
if
(
mOGC2
.
find
())
{
return
CRS_FACTORY
.
createFromName
(
"EPSG:"
+
mOGC2
.
group
(
1
));
}
Matcher
mURN
=
P_URN
.
matcher
(
srsName
);
// NOTE: Could use a HashMap if the switch/case becomes too long.
if
(
mURN
.
find
())
{
private
static
final
String
CITY_OBJECT_MEMBER
=
"cityObjectMember"
;
private
static
final
String
WGS_84
=
"EPSG:4326"
;
private
static
final
Logger
logger
=
LogManager
.
getLogger
(
CityGmlParser
.
class
);
private
static
final
CRSFactory
CRS_FACTORY
=
new
CRSFactory
();
// EPSG:31467
private
static
final
Pattern
P_EPSG
=
Pattern
.
compile
(
"^(EPSG:\\d+)$"
);
// urn:ogc:def:crs,crs:EPSG:6.12:31467,crs:EPSG:6.12:5783
// or
// urn:ogc:def:crs,crs:EPSG::28992
private
static
final
Pattern
P_OGC
=
Pattern
.
compile
(
"urn:ogc:def:crs,crs:EPSG:[\\d\\.]*:([\\d]+)\\D*"
);
private
static
final
Pattern
P_OGC2
=
Pattern
.
compile
(
"urn:ogc:def:crs:EPSG:[\\d\\.]*:([\\d]+)\\D*"
);
// urn:adv:crs:DE_DHDN_3GK3*DE_DHHN92_NH
// urn:adv:crs:ETRS89_UTM32*DE_DHHN92_NH
private
static
final
Pattern
P_URN
=
Pattern
.
compile
(
"urn:adv:crs:([^\\*]+)"
);
private
static
final
SAXParserFactory
FACTORY
;
private
static
Proj4FileReader
csReader
=
new
Proj4FileReader
();
private
static
final
Pattern
P_VUNITS
=
Pattern
.
compile
(
"^\\+vunits=.+"
);
private
static
final
Pattern
P_GEOIDGRID
=
Pattern
.
compile
(
"^\\+geoidgrid=.+"
);
private
static
CityGMLContext
context
;
private
static
List
<
QName
>
chunkProperties
=
new
ArrayList
<>();
static
{
System
.
setProperty
(
"javax.xml.transform.TransformerFactory"
,
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"
);
FACTORY
=
SAXParserFactory
.
newInstance
();
try
{
FACTORY
.
setFeature
(
XMLConstants
.
FEATURE_SECURE_PROCESSING
,
false
);
}
catch
(
SAXNotRecognizedException
|
SAXNotSupportedException
|
ParserConfigurationException
e
)
{
logger
.
catching
(
e
);
}
chunkProperties
.
add
(
new
QName
(
CityGMLConstants
.
CITYGML_1_0_CORE_NAMESPACE
,
CITY_OBJECT_MEMBER
));
chunkProperties
.
add
(
new
QName
(
CityGMLConstants
.
CITYGML_2_0_CORE_NAMESPACE
,
CITY_OBJECT_MEMBER
));
chunkProperties
.
add
(
new
QName
(
CityGMLConstants
.
CITYGML_3_0_CORE_NAMESPACE
,
CITY_OBJECT_MEMBER
));
}
private
CityGmlParser
()
{
}
public
static
synchronized
CityGMLContext
getContext
()
{
if
(
context
==
null
)
{
try
{
context
=
CityGMLContext
.
newInstance
(
CityGmlParser
.
class
.
getClassLoader
());
// also setup ades
ADERegistry
adeRegistry
=
ADERegistry
.
getInstance
();
adeRegistry
.
loadADE
(
new
QualityADEContext
());
}
catch
(
CityGMLContextException
e
)
{
logger
.
fatal
(
"Unable to create citygml4j context"
,
e
);
throw
new
IllegalStateException
(
"Unable to create citygml4j context"
);
}
catch
(
ADEException
e
)
{
logger
.
fatal
(
"Unable to add ADE plugins to citygml4j"
,
e
);
throw
new
IllegalStateException
(
"Unable to add ADE plugins to citygml4j"
);
}
}
return
context
;
}
public
static
CityDoctorModel
parseCityGmlFileSilently
(
String
file
,
ParserConfiguration
config
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
return
parseCityGmlFile
(
file
,
config
,
null
,
null
,
false
);
}
public
static
CityDoctorModel
parseCityGmlFile
(
String
file
,
ParserConfiguration
config
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
return
parseCityGmlFile
(
file
,
config
,
null
,
null
,
true
);
}
public
static
CityDoctorModel
parseCityGmlFile
(
String
file
,
ParserConfiguration
config
,
ProgressListener
l
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
return
parseCityGmlFile
(
file
,
config
,
l
,
null
,
true
);
}
public
static
CityDoctorModel
parseCityGmlFile
(
String
filePath
,
ParserConfiguration
config
,
ProgressListener
l
,
GMLValidationHandler
handler
,
boolean
verbose
)
throws
CityGmlParseException
,
InvalidGmlFileException
{
CityGMLContext
context
=
getContext
();
Path
file
=
Paths
.
get
(
filePath
);
if
(
config
.
getValidate
())
{
List
<
String
>
messages
=
validateFile
(
context
,
handler
,
file
);
if
(!
messages
.
isEmpty
())
{
throw
new
InvalidGmlFileException
(
"Invalid GML File. First error: \n"
+
messages
.
get
(
0
));
}
}
try
{
parseEpsgCodeFromFile
(
file
,
config
);
CityGMLInputFactory
in
=
context
.
createCityGMLInputFactory
()
.
withChunking
(
ChunkOptions
.
chunkByProperties
(
chunkProperties
).
skipCityModel
(
false
));
try
(
ObservedInputStream
ois
=
new
ObservedInputStream
(
file
.
toFile
()))
{
if
(
l
!=
null
)
{
ois
.
addListener
(
l:
:
updateProgress
);
}
return
readAndKeepFeatures
(
config
,
file
,
in
,
ois
,
verbose
);
}
}
catch
(
CityGMLReadException
|
IOException
e
)
{
throw
new
CityGmlParseException
(
"Failed to read CityGML file"
,
e
);
}
}
public
static
CityDoctorModel
parseCityGmlZipEntry
(
CityGmlZipEntry
entry
,
ParserConfiguration
config
)
throws
CityGmlParseException
,
InvalidGmlFileException
,
IOException
{
return
parseCityGmlZipEntry
(
entry
,
config
,
null
);
}
public
static
CityDoctorModel
parseCityGmlZipEntry
(
CityGmlZipEntry
entry
,
ParserConfiguration
config
,
ProgressListener
l
)
throws
CityGmlParseException
,
InvalidGmlFileException
,
IOException
{
CityGMLContext
context
=
getContext
();
if
(
config
.
getValidate
())
{
try
(
CityGmlZipEntryFile
entryFile
=
new
CityGmlZipEntryFile
(
entry
))
{
List
<
String
>
messages
=
validateStream
(
entryFile
.
getInputStream
(),
context
);
if
(!
messages
.
isEmpty
())
{
throw
new
InvalidGmlFileException
(
"Invalid GML File. First error: \n"
+
messages
.
get
(
0
));
}
}
catch
(
Exception
e
)
{
throw
new
CityGmlParseException
(
e
);
}
}
return
decompressAndParseCityGmlEntry
(
entry
,
config
,
l
,
context
);
}
public
static
CityDoctorModel
decompressAndParseCityGmlEntry
(
CityGmlZipEntry
entry
,
ParserConfiguration
config
,
CityGMLContext
context
)
throws
CityGmlParseException
{
return
decompressAndParseCityGmlEntry
(
entry
,
config
,
null
,
context
);
}
public
static
CityDoctorModel
decompressAndParseCityGmlEntry
(
CityGmlZipEntry
entry
,
ParserConfiguration
config
,
ProgressListener
l
,
CityGMLContext
context
)
throws
CityGmlParseException
{
try
(
CityGmlZipEntryFile
entryFile
=
new
CityGmlZipEntryFile
(
entry
))
{
BufferedInputStream
bis
=
new
BufferedInputStream
(
entryFile
.
getInputStream
());
readEpsgCodeFromInputStream
(
bis
,
config
);
CityGMLInputFactory
in
=
context
.
createCityGMLInputFactory
()
.
withChunking
(
ChunkOptions
.
chunkByProperties
(
chunkProperties
).
skipCityModel
(
false
));
try
(
ObservedInputStream
ois
=
new
ObservedInputStream
(
bis
,
bis
.
available
()))
{
if
(
l
!=
null
)
{
ois
.
addListener
(
l:
:
updateProgress
);
}
return
readAndKeepFeatures
(
config
,
entry
,
in
,
ois
,
false
);
}
}
catch
(
CityGMLReadException
|
IOException
e
)
{
throw
new
CityGmlParseException
(
"Failed to read CityGML file"
,
e
);
}
catch
(
Exception
e
)
{
throw
new
CityGmlParseException
(
e
);
}
}
private
static
CityDoctorModel
readAndKeepFeatures
(
ParserConfiguration
config
,
CityGmlZipEntry
entry
,
CityGMLInputFactory
inputFactory
,
ObservedInputStream
ois
,
boolean
verbose
)
throws
CityGMLReadException
{
return
readAndKeepModel
(
new
Citygml3FeatureMapper
(
config
,
entry
),
inputFactory
,
ois
,
verbose
);
}
private
static
List
<
String
>
validateStream
(
InputStream
vis
,
CityGMLContext
context
)
throws
CityGmlParseException
{
GMLValidationHandler
handler
=
new
GMLValidationHandler
();
try
{
BufferedInputStream
bis
=
new
BufferedInputStream
(
vis
);
SchemaHandler
schemaHandler
=
new
ValidationSchemaHandler
(
context
.
getDefaultSchemaHandler
());
readAdditionalSchemaDefinitions
(
context
,
bis
,
schemaHandler
);
Source
[]
schemas
=
schemaHandler
.
getSchemas
();
SchemaFactory
schemaFactory
=
SchemaFactory
.
newInstance
(
XMLConstants
.
W3C_XML_SCHEMA_NS_URI
);
schemaFactory
.
setFeature
(
"http://apache.org/xml/features/disallow-doctype-decl"
,
true
);
Schema
schema
=
schemaFactory
.
newSchema
(
schemas
);
Validator
validator
=
schema
.
newValidator
();
validator
.
setErrorHandler
(
handler
);
validator
.
validate
(
new
StreamSource
(
bis
));
return
handler
.
getMessages
();
}
catch
(
SchemaHandlerException
|
SAXException
|
IOException
e
)
{
throw
new
CityGmlParseException
(
"Failed to validate CityGML file"
,
e
);
}
}
private
static
void
readAdditionalSchemaDefinitions
(
CityGMLContext
context
,
BufferedInputStream
bis
,
SchemaHandler
schemaHandler
)
throws
CityGmlParseException
{
bis
.
mark
(
Integer
.
MAX_VALUE
);
try
(
XMLReader
reader
=
XMLReaderFactory
.
newInstance
(
context
.
getXMLObjects
())
.
withSchemaHandler
(
schemaHandler
)
.
createReader
(
bis
))
{
reader
.
nextTag
();
bis
.
reset
();
}
catch
(
Exception
e
)
{
throw
new
CityGmlParseException
(
"Failed to read Schema from stream."
,
e
);
}
}
private
static
void
readEpsgCodeFromInputStream
(
BufferedInputStream
bis
,
ParserConfiguration
config
)
throws
CityGmlParseException
{
try
{
// Mark start position of GML-"file"
bis
.
mark
(
Integer
.
MAX_VALUE
);
// Buffer the first 10000 chars of the Stream, EPSG/envelope info should be found within that range
int
peekingWidth
=
Math
.
min
(
10000
,
bis
.
available
());
byte
[]
buf
=
new
byte
[
peekingWidth
];
bis
.
read
(
buf
,
0
,
peekingWidth
);
bis
.
reset
();
parseEpsgCodeFromBuffer
(
buf
,
config
);
}
catch
(
ParserConfigurationException
|
SAXException
|
IOException
e
)
{
throw
new
CityGmlParseException
(
"Failed to read CityGML file"
,
e
);
}
}
public
static
void
streamCityGml
(
CityGmlZipEntry
entry
,
ParserConfiguration
config
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGmlParseException
,
IOException
{
try
(
CityGmlZipEntryFile
entryFile
=
new
CityGmlZipEntryFile
(
entry
))
{
parseEpsgCodeFromStream
(
entryFile
.
getInputStream
(),
config
);
startReadingCityGmlZipEntry
(
entry
,
config
,
null
,
cityObjectConsumer
,
outputFile
);
}
catch
(
ParserConfigurationException
|
SAXException
|
IOException
e
)
{
throw
new
CityGmlParseException
(
"Failed to read CityGML stream"
,
e
);
}
}
public
static
void
streamCityGml
(
String
file
,
ParserConfiguration
config
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGmlParseException
{
Path
f
=
Paths
.
get
(
file
);
streamCityGml
(
f
,
config
,
null
,
cityObjectConsumer
,
outputFile
);
}
public
static
void
streamCityGml
(
File
file
,
ParserConfiguration
parserConfig
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGmlParseException
{
streamCityGml
(
file
.
toPath
(),
parserConfig
,
null
,
cityObjectConsumer
,
outputFile
);
}
public
static
void
streamCityGml
(
Path
file
,
ParserConfiguration
config
,
ProgressListener
l
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGmlParseException
{
parseEpsgCodeFromFile
(
file
,
config
);
startReadingCityGmlFile
(
file
,
config
,
l
,
cityObjectConsumer
,
outputFile
);
}
public
static
CityModel
parseOnlyCityModel
(
File
inputFile
)
throws
CityGmlParseException
{
try
{
CityGMLInputFactory
inputFactory
=
context
.
createCityGMLInputFactory
()
.
withChunking
(
ChunkOptions
.
chunkByProperties
(
chunkProperties
).
skipCityModel
(
false
));
try
(
CityGMLReader
reader
=
inputFactory
.
createCityGMLReader
(
inputFile
))
{
while
(
reader
.
hasNext
())
{
AbstractFeature
chunk
=
reader
.
next
();
if
(
chunk
instanceof
CityModel
cModel
)
{
cModel
.
setCityObjectMembers
(
null
);
return
cModel
;
}
}
}
}
catch
(
CityGMLReadException
e
)
{
throw
new
CityGmlParseException
(
e
);
}
throw
new
CityGmlParseException
(
"Did not find any CityModel in CityGML file"
);
}
private
static
void
startReadingCityGmlFile
(
Path
file
,
ParserConfiguration
config
,
ProgressListener
l
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
{
try
(
ObservedInputStream
ois
=
new
ObservedInputStream
(
file
.
toFile
()))
{
if
(
l
!=
null
)
{
ois
.
addListener
(
l:
:
updateProgress
);
}
readAndDiscardFeatures
(
file
,
config
,
ois
,
cityObjectConsumer
,
outputFile
);
}
catch
(
IOException
|
CityGMLReadException
e
)
{
logger
.
error
(
Localization
.
getText
(
"CityGmlParser.errorReadingGmlFile"
),
e
.
getMessage
());
logger
.
catching
(
Level
.
ERROR
,
e
);
}
}
private
static
void
readAndDiscardFeatures
(
Path
file
,
ParserConfiguration
config
,
ObservedInputStream
ois
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGMLReadException
{
Citygml3FeatureMapper
mapper
=
new
Citygml3FeatureMapper
(
config
,
file
);
readAndDiscardModel
(
mapper
,
ois
,
cityObjectConsumer
,
outputFile
);
}
private
static
void
startReadingCityGmlZipEntry
(
CityGmlZipEntry
entry
,
ParserConfiguration
config
,
ProgressListener
l
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
{
try
(
CityGmlZipEntryFile
entryFile
=
new
CityGmlZipEntryFile
(
entry
);
ObservedInputStream
ois
=
new
ObservedInputStream
(
entryFile
.
getInputStream
(),
entry
.
getFileSize
()))
{
if
(
l
!=
null
)
{
ois
.
addListener
(
l:
:
updateProgress
);
}
streamAndDiscardFeatures
(
entry
,
config
,
ois
,
cityObjectConsumer
,
outputFile
);
}
catch
(
IOException
|
CityGMLReadException
e
)
{
logger
.
error
(
Localization
.
getText
(
"CityGmlParser.errorReadingGmlFile"
),
e
.
getMessage
());
logger
.
catching
(
Level
.
ERROR
,
e
);
}
}
private
static
void
streamAndDiscardFeatures
(
CityGmlZipEntry
entry
,
ParserConfiguration
config
,
ObservedInputStream
ois
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGMLReadException
{
Citygml3FeatureMapper
mapper
=
new
Citygml3FeatureMapper
(
config
,
entry
);
readAndDiscardModel
(
mapper
,
ois
,
cityObjectConsumer
,
outputFile
);
}
private
static
void
readAndDiscardModel
(
Citygml3FeatureMapper
mapper
,
ObservedInputStream
ois
,
CityGmlConsumer
cityObjectConsumer
,
String
outputFile
)
throws
CityGMLReadException
{
getContext
();
CityGMLInputFactory
inputFactory
=
context
.
createCityGMLInputFactory
()
.
withChunking
(
ChunkOptions
.
chunkByProperties
(
chunkProperties
).
skipCityModel
(
false
));
CityGMLChunkWriter
writer
=
null
;
try
(
CityGMLReader
reader
=
inputFactory
.
createCityGMLReader
(
ois
))
{
CityDoctorModel
model
=
mapper
.
getModel
();
boolean
isInitialized
=
false
;
while
(
reader
.
hasNext
())
{
AbstractFeature
chunk
=
reader
.
next
();
if
(
writer
==
null
)
{
writer
=
createCityModelWriter
(
outputFile
,
reader
);
}
if
(!
isInitialized
&&
writer
!=
null
&&
reader
.
getParentInfo
()
!=
null
&&
reader
.
getParentInfo
().
getTypeName
().
getLocalPart
().
equals
(
"CityModel"
))
{
FeatureInfo
parentInfo
=
reader
.
getParentInfo
();
writer
.
withCityModelInfo
(
parentInfo
);
isInitialized
=
true
;
}
if
(
chunk
instanceof
AbstractCityObject
ag
)
{
ag
.
accept
(
mapper
);
drainCityModel
(
model
,
cityObjectConsumer
);
writeAbstractCityObject
(
writer
,
ag
);
}
else
if
(
chunk
instanceof
CityModel
cModel
)
{
cModel
.
setCityObjectMembers
(
null
);
mapper
.
setCityModel
(
cModel
);
cityObjectConsumer
.
accept
(
cModel
);
writeCityModel
(
writer
,
cModel
);
}
else
if
(
writer
!=
null
)
{
writer
.
writeMember
(
chunk
);
}
}
// end of stream
logger
.
debug
(
"End of gml file stream"
);
}
catch
(
CityGMLReadException
e
)
{
logger
.
error
(
Localization
.
getText
(
"CityGmlParser.errorReadingGmlFile"
),
e
.
getMessage
(),
e
);
}
catch
(
CityGMLWriteException
e
)
{
logger
.
error
(
Localization
.
getText
(
"CityGmlParser.errorWritingGmlFile"
),
e
.
getMessage
(),
e
);
}
finally
{
if
(
writer
!=
null
)
{
try
{
writer
.
close
();
}
catch
(
CityGMLWriteException
e
)
{
// ignore
}
}
}
}
private
static
void
writeCityModel
(
CityGMLChunkWriter
writer
,
CityModel
cModel
)
{
if
(
writer
!=
null
)
{
for
(
ADEProperty
genEle
:
cModel
.
getADEProperties
())
{
writer
.
getCityModelInfo
().
addADEProperty
(
genEle
);
}
}
}
private
static
void
writeAbstractCityObject
(
CityGMLChunkWriter
writer
,
AbstractCityObject
ag
)
throws
CityGMLWriteException
{
if
(
writer
!=
null
)
{
writer
.
writeMember
(
ag
);
}
}
private
static
CityGMLChunkWriter
createCityModelWriter
(
String
outputFile
,
CityGMLReader
reader
)
throws
CityGMLWriteException
{
if
(
outputFile
==
null
)
{
return
null
;
}
CityGMLContext
gmlContext
=
CityGmlParser
.
getContext
();
CityGMLVersion
version
=
CityGMLModules
.
getCityGMLVersion
(
reader
.
getName
().
getNamespaceURI
());
CityGMLOutputFactory
factory
=
gmlContext
.
createCityGMLOutputFactory
(
version
);
CityGMLChunkWriter
writer
=
factory
.
createCityGMLChunkWriter
(
new
File
(
outputFile
),
StandardCharsets
.
UTF_8
.
name
());
writer
.
withPrefix
(
"qual"
,
QualityADEModule
.
NAMESPACE_URI
);
writer
.
withSchemaLocation
(
QualityADEModule
.
NAMESPACE_URI
,
QualityADEModule
.
NAMESPACE_URI
+
"/qualityAde.xsd"
);
writer
.
withIndent
(
" "
);
writer
.
withDefaultPrefixes
();
writer
.
withDefaultSchemaLocations
();
return
writer
;
}
private
static
CityDoctorModel
readAndKeepFeatures
(
ParserConfiguration
config
,
Path
file
,
CityGMLInputFactory
inputFactory
,
ObservedInputStream
ois
,
boolean
verbose
)
throws
CityGMLReadException
{
return
readAndKeepModel
(
new
Citygml3FeatureMapper
(
config
,
file
),
inputFactory
,
ois
,
verbose
);
}
private
static
CityDoctorModel
readAndKeepModel
(
Citygml3FeatureMapper
mapper
,
CityGMLInputFactory
inputFactory
,
ObservedInputStream
ois
,
boolean
verbose
)
throws
CityGMLReadException
{
try
(
CityGMLReader
reader
=
inputFactory
.
createCityGMLReader
(
ois
))
{
CityGMLVersion
version
=
null
;
// model is read in chunked mode
// object members are replaced by href in model
// need to remove the refs and re-add unparsed objects
List
<
AbstractCityObject
>
acos
=
new
ArrayList
<>();
while
(
reader
.
hasNext
())
{
AbstractFeature
chunk
=
reader
.
next
();
version
=
CityGMLModules
.
getCityGMLVersion
(
reader
.
getName
().
getNamespaceURI
());
if
(
chunk
instanceof
CityModel
cModel
)
{
cModel
.
setCityObjectMembers
(
null
);
mapper
.
setCityModel
(
cModel
);
mapper
.
setCityGMLVersion
(
version
);
}
else
if
(
chunk
instanceof
AbstractCityObject
aco
)
{
acos
.
add
(
aco
);
aco
.
accept
(
mapper
);
}
}
if
(
mapper
.
getModel
().
getCityModel
()
==
null
)
{
// file does not contain a city model?
// create it for now
mapper
.
setCityModel
(
new
CityModel
());
}
CityModel
cModel
=
mapper
.
getModel
().
getCityModel
();
// remove those that should have been parsed
List
<
AbstractCityObject
>
parsedCityObjects
=
mapper
.
getModel
().
createFeatureStream
()
.
map
(
CityObject:
:
getGmlObject
).
toList
();
acos
.
removeAll
(
parsedCityObjects
);
// re-add all not parsed objects
for
(
AbstractCityObject
aco
:
acos
)
{
cModel
.
getCityObjectMembers
().
add
(
new
AbstractCityObjectProperty
(
aco
));
}
if
(
logger
.
isInfoEnabled
()
&&
verbose
)
{
logger
.
info
(
Localization
.
getText
(
"CityGmlParser.parsedObjects"
),
mapper
.
getModel
().
getNumberOfFeatures
());
}
mapper
.
setCityGMLVersion
(
version
);
return
mapper
.
getModel
();
}
}
private
static
void
parseEpsgCodeFromFile
(
Path
file
,
ParserConfiguration
config
)
throws
CityGmlParseException
{
try
(
BufferedInputStream
bis
=
new
BufferedInputStream
(
new
FileInputStream
(
file
.
toFile
())))
{
parseEpsgCodeFromStream
(
bis
,
config
);
}
catch
(
ParserConfigurationException
|
SAXException
|
IOException
e
)
{
throw
new
CityGmlParseException
(
"Failed to read CityGML file"
,
e
);
}
}
private
static
void
parseEpsgCodeFromStream
(
InputStream
is
,
ParserConfiguration
config
)
throws
ParserConfigurationException
,
SAXException
{
SAXParser
parser
=
FACTORY
.
newSAXParser
();
CityGmlHandler
handler
=
new
CityGmlHandler
();
try
{
parser
.
parse
(
new
InputSource
(
is
),
handler
);
}
catch
(
EnvelopeFoundException
e
)
{
try
{
parseCoordinateSystem
(
config
,
handler
);
}
catch
(
Exception
e2
)
{
logEpsgParseError
(
e2
);
}
}
catch
(
Exception
e
)
{
logEpsgParseError
(
e
);
}
if
(
handler
.
getEpsg
()
==
null
&&
logger
.
isInfoEnabled
())
{
logger
.
info
(
Localization
.
getText
(
"CityGmlParser.missingEPSGCode"
));
}
}
private
static
void
parseEpsgCodeFromBuffer
(
byte
[]
buffer
,
ParserConfiguration
config
)
throws
ParserConfigurationException
,
SAXException
{
InputStream
is
=
new
ByteArrayInputStream
(
buffer
);
SAXParser
parser
=
FACTORY
.
newSAXParser
();
CityGmlHandler
handler
=
new
CityGmlHandler
();
try
{
parser
.
parse
(
new
InputSource
(
is
),
handler
);
}
catch
(
EnvelopeFoundException
e
)
{
try
{
parseCoordinateSystem
(
config
,
handler
);
}
catch
(
Exception
e2
)
{
logEpsgParseError
(
e2
);
}
}
catch
(
SAXParseException
spe
)
{
// suppress XML document structure warning
if
(!
spe
.
getMessage
().
matches
(
"XML document structures must start and end within the same entity."
))
{
logEpsgParseError
(
spe
);
}
}
catch
(
Exception
e
)
{
logEpsgParseError
(
e
);
}
if
(
handler
.
getEpsg
()
==
null
&&
logger
.
isInfoEnabled
())
{
logger
.
info
(
Localization
.
getText
(
"CityGmlParser.missingEPSGCode"
));
}
}
private
static
void
logEpsgParseError
(
Exception
e
)
{
logger
.
debug
(
"Exception while parsing for EPSG code"
,
e
);
if
(
logger
.
isWarnEnabled
())
{
logger
.
warn
(
Localization
.
getText
(
"CityGmlParser.failedEPSGParse"
));
}
}
private
static
void
parseCoordinateSystem
(
ParserConfiguration
config
,
CityGmlHandler
handler
)
{
if
(
handler
.
getEpsg
()
==
null
)
{
return
;
}
CoordinateReferenceSystem
crs
=
crsFromSrsName
(
handler
.
getEpsg
());
if
(
crs
==
null
)
{
// could not find a coordinate system for srsName
// assuming metric system
if
(
logger
.
isInfoEnabled
())
{
logger
.
info
(
Localization
.
getText
(
"CityGmlParser.missingEPSGCode"
));
}
return
;
}
if
(
crs
.
getProjection
().
getUnits
()
==
Units
.
METRES
)
{
// coordinate system is in meters, do not convert
if
(
logger
.
isInfoEnabled
())
{
logger
.
info
(
Localization
.
getText
(
"CityGmlParser.noConversionNeeded"
));
}
return
;
}
parseMeterConversion
(
config
,
crs
);
Vector3d
low
=
handler
.
getLowerCorner
();
Vector3d
up
=
handler
.
getUpperCorner
();
double
centerLong
=
low
.
getX
()
+
((
up
.
getX
()
-
low
.
getX
())
/
2
);
double
centerLat
=
low
.
getY
()
+
((
up
.
getY
()
-
low
.
getY
())
/
2
);
if
(!
crs
.
getName
().
equals
(
WGS_84
))
{
// need to convert coordinates first to WGS84, then find UTM Zone
CoordinateReferenceSystem
wgs84
=
crsFromSrsName
(
WGS_84
);
ProjCoordinate
p1
=
new
ProjCoordinate
();
p1
.
setValue
(
centerLong
,
centerLat
);
ProjCoordinate
p2
=
new
ProjCoordinate
();
BasicCoordinateTransform
bct
=
new
BasicCoordinateTransform
(
crs
,
wgs84
);
bct
.
transform
(
p1
,
p2
);
centerLong
=
p2
.
x
;
centerLat
=
p2
.
y
;
}
int
zone
=
(
int
)
(
31
+
Math
.
round
(
centerLong
/
6
));
CoordinateReferenceSystem
utm
;
if
(
centerLat
<
0
)
{
// south
logger
.
info
(
"Converting coordiante system to UTM zone {}S"
,
zone
);
utm
=
CRS_FACTORY
.
createFromParameters
(
"UTM"
,
"+proj=utm +ellps=WGS84 +units=m +zone="
+
zone
+
" +south"
);
}
else
{
// north
logger
.
info
(
"Converting coordiante system to UTM zone {}N"
,
zone
);
utm
=
CRS_FACTORY
.
createFromParameters
(
"UTM"
,
"+proj=utm +ellps=WGS84 +units=m +zone="
+
zone
);
}
config
.
setCoordinateSystem
(
crs
,
utm
);
}
private
static
void
parseMeterConversion
(
ParserConfiguration
config
,
CoordinateReferenceSystem
crs
)
{
Projection
projection
=
crs
.
getProjection
();
double
fromMetres
=
projection
.
getFromMetres
();
if
(
fromMetres
>
0
)
{
// also transform height information
config
.
setFromMeters
(
fromMetres
);
}
else
{
config
.
setFromMeters
(
1.0
);
}
}
/**
* The srsName (The name by which this reference system is identified) inside
* the CityGML file can have multiple formats. This method tries to parse the
* string and detect the corresponding reference system. If it is found, it
* returns a proj4j.CoordinateReferenceSystem. It throws an
* IllegalArgumentException otherwise.
* <p>
* This method should be able to parse any EPSG id : e.g. "EPSG:1234". German
* Citygmls might also have "DE_DHDN_3GK3" or "ETRS89_UTM32" as srsName, so
* those are also included. It isn't guaranteed that those formats are correctly
* parsed, though.
* <p>
* The EPSG ids and parameters are defined in resources ('nad/epsg') inside
* proj4j-0.1.0.jar. Some EPSG ids are missing though, e.g. 7415
*
* @param srsName
* @return CoordinateReferenceSystem
*/
private
static
CoordinateReferenceSystem
crsFromSrsName
(
String
srsName
)
{
srsName
=
srsName
.
trim
();
Matcher
mEPSG
=
P_EPSG
.
matcher
(
srsName
);
if
(
mEPSG
.
find
())
{
if
(
"EPSG:4979"
.
contentEquals
(
srsName
))
{
srsName
=
"EPSG:4236"
;
}
else
if
(
"EPSG:7415"
.
contentEquals
(
srsName
))
{
return
CRS_FACTORY
.
createFromParameters
(
"EPSG:7415"
,
"+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.417,50.3319,465.552,-0.398957,0.343988,-1.8774,4.0725 +units=m +no_defs"
);
}
return
CRS_FACTORY
.
createFromName
(
srsName
);
}
Matcher
mOGC
=
P_OGC
.
matcher
(
srsName
);
if
(
mOGC
.
find
())
{
return
getCrsFromOGCSrsCode
(
mOGC
.
group
(
1
));
}
Matcher
mOGC2
=
P_OGC2
.
matcher
(
srsName
);
if
(
mOGC2
.
find
())
{
return
getCrsFromOGCSrsCode
(
mOGC2
.
group
(
1
));
}
Matcher
mURN
=
P_URN
.
matcher
(
srsName
);
// NOTE: Could use a HashMap if the switch/case becomes too long.
if
(
mURN
.
find
())
{
return
switch
(
mURN
.
group
(
1
))
{
case
"DE_DHDN_3GK2"
->
CRS_FACTORY
.
createFromName
(
"EPSG:31466"
);
case
"DE_DHDN_3GK3"
->
CRS_FACTORY
.
createFromName
(
"EPSG:31467"
);
...
...
@@ -525,59 +705,70 @@ public class CityGmlParser {
case
"ETRS89_UTM32"
->
CRS_FACTORY
.
createFromName
(
"EPSG:25832"
);
default
->
null
;
};
}
if
(
srsName
.
equals
(
"http://www.opengis.net/def/crs/EPSG/0/6697"
))
{
return
CRS_FACTORY
.
createFromParameters
(
"EPSG:6697"
,
"+proj=longlat +ellps=GRS80 +no_defs +axis=neu"
);
}
return
null
;
}
private
static
List
<
String
>
validateFile
(
CityGMLContext
context
,
GMLValidationHandler
handler
,
Path
file
)
throws
CityGmlParseException
{
if
(
handler
==
null
)
{
handler
=
new
GMLValidationHandler
();
}
try
{
SchemaHandler
schemaHandler
=
new
ValidationSchemaHandler
(
context
.
getDefaultSchemaHandler
());
}
if
(
srsName
.
equals
(
"http://www.opengis.net/def/crs/EPSG/0/6697"
))
{
return
CRS_FACTORY
.
createFromParameters
(
"EPSG:6697"
,
"+proj=longlat +ellps=GRS80 +no_defs +axis=neu"
);
}
return
null
;
}
private
static
CoordinateReferenceSystem
getCrsFromOGCSrsCode
(
String
srsCode
)
{
String
crsName
=
"EPSG:"
+
srsCode
;
List
<
String
>
params
=
new
ArrayList
<>(
Arrays
.
stream
(
csReader
.
getParameters
(
crsName
)).
toList
());
params
.
removeIf
(
P_VUNITS
.
asPredicate
());
params
.
removeIf
(
P_GEOIDGRID
.
asPredicate
());
return
CRS_FACTORY
.
createFromParameters
(
crsName
,
params
.
toArray
(
new
String
[
0
]));
}
private
static
List
<
String
>
validateFile
(
CityGMLContext
context
,
GMLValidationHandler
handler
,
Path
file
)
throws
CityGmlParseException
{
if
(
handler
==
null
)
{
handler
=
new
GMLValidationHandler
();
}
try
{
SchemaHandler
schemaHandler
=
new
ValidationSchemaHandler
(
context
.
getDefaultSchemaHandler
());
readAdditionalSchemaDefinitions
(
context
,
file
,
schemaHandler
);
Source
[]
schemas
=
schemaHandler
.
getSchemas
();
SchemaFactory
schemaFactory
=
SchemaFactory
.
newInstance
(
XMLConstants
.
W3C_XML_SCHEMA_NS_URI
);
schemaFactory
.
setFeature
(
"http://apache.org/xml/features/disallow-doctype-decl"
,
true
);
Schema
schema
=
schemaFactory
.
newSchema
(
schemas
);
Validator
validator
=
schema
.
newValidator
();
validator
.
setErrorHandler
(
handler
);
validator
.
validate
(
new
StreamSource
(
file
.
toFile
()));
return
handler
.
getMessages
();
}
catch
(
SchemaHandlerException
|
SAXException
|
IOException
e
)
{
throw
new
CityGmlParseException
(
"Failed to validate CityGML file"
,
e
);
}
}
private
static
void
readAdditionalSchemaDefinitions
(
CityGMLContext
context
,
Path
file
,
SchemaHandler
schemaHandler
)
throws
CityGmlParseException
{
try
(
XMLReader
reader
=
XMLReaderFactory
.
newInstance
(
context
.
getXMLObjects
())
.
withSchemaHandler
(
schemaHandler
)
.
createReader
(
file
))
{
reader
.
nextTag
();
}
catch
(
Exception
e
)
{
throw
new
CityGmlParseException
(
"Failed to read file "
+
file
.
toAbsolutePath
()
+
"."
,
e
);
}
}
private
static
void
drainCityModel
(
CityDoctorModel
model
,
CityGmlConsumer
cityObjectConsumer
)
{
drainCityObjectList
(
model
.
getBuildings
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getBridges
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getVegetation
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getLand
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getTransportation
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getWater
(),
cityObjectConsumer
);
}
private
static
void
drainCityObjectList
(
List
<?
extends
CityObject
>
objects
,
CityGmlConsumer
cityObjectConsumer
)
{
for
(
CityObject
co
:
objects
)
{
cityObjectConsumer
.
accept
(
co
);
}
objects
.
clear
();
}
Source
[]
schemas
=
schemaHandler
.
getSchemas
();
SchemaFactory
schemaFactory
=
SchemaFactory
.
newInstance
(
XMLConstants
.
W3C_XML_SCHEMA_NS_URI
);
schemaFactory
.
setFeature
(
"http://apache.org/xml/features/disallow-doctype-decl"
,
true
);
Schema
schema
=
schemaFactory
.
newSchema
(
schemas
);
Validator
validator
=
schema
.
newValidator
();
validator
.
setErrorHandler
(
handler
);
validator
.
validate
(
new
StreamSource
(
file
.
toFile
()));
return
handler
.
getMessages
();
}
catch
(
SchemaHandlerException
|
SAXException
|
IOException
e
)
{
throw
new
CityGmlParseException
(
"Failed to validate CityGML file"
,
e
);
}
}
private
static
void
readAdditionalSchemaDefinitions
(
CityGMLContext
context
,
Path
file
,
SchemaHandler
schemaHandler
)
throws
CityGmlParseException
{
try
(
XMLReader
reader
=
XMLReaderFactory
.
newInstance
(
context
.
getXMLObjects
())
.
withSchemaHandler
(
schemaHandler
)
.
createReader
(
file
))
{
reader
.
nextTag
();
}
catch
(
Exception
e
)
{
throw
new
CityGmlParseException
(
"Failed to read file "
+
file
.
toAbsolutePath
()
+
"."
,
e
);
}
}
private
static
void
drainCityModel
(
CityDoctorModel
model
,
CityGmlConsumer
cityObjectConsumer
)
{
drainCityObjectList
(
model
.
getBuildings
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getBridges
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getVegetation
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getLand
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getTransportation
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getWater
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getTunnels
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getCityFurniture
(),
cityObjectConsumer
);
drainCityObjectList
(
model
.
getGenericCityObjects
(),
cityObjectConsumer
);
}
private
static
void
drainCityObjectList
(
List
<?
extends
CityObject
>
objects
,
CityGmlConsumer
cityObjectConsumer
)
{
for
(
CityObject
co
:
objects
)
{
cityObjectConsumer
.
accept
(
co
);
}
objects
.
clear
();
}
}
CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/tesselation/EarcutTesselator.java
0 → 100644
View file @
2d57794b
package
de.hft.stuttgart.citydoctor2.tesselation
;
import
java.util.ArrayList
;
import
java.util.List
;
import
de.hft.stuttgart.citydoctor2.datastructure.LinearRing
;
import
de.hft.stuttgart.citydoctor2.datastructure.Polygon
;
import
de.hft.stuttgart.citydoctor2.datastructure.Vertex
;
import
de.hft.stuttgart.citydoctor2.math.ProjectionAxis
;
import
de.hft.stuttgart.citydoctor2.math.Triangle3d
;
import
earcut4j.Earcut
;
/**
* Tesselator to create triangles out of polygons. Uses earcut4j implementation.
*
* @author Matthias Betz
*
*/
public
class
EarcutTesselator
{
public
static
TesselatedPolygon
tesselatePolygon
(
Polygon
p
)
{
// sum number of vertices, don't use duplicate last point
// assume polygons are closed
int
nrOfVertices
=
p
.
getExteriorRing
().
getVertices
().
size
()
-
1
;
int
[]
holeStart
=
null
;
if
(!
p
.
getInnerRings
().
isEmpty
())
{
holeStart
=
new
int
[
p
.
getInnerRings
().
size
()];
List
<
LinearRing
>
innerRings
=
p
.
getInnerRings
();
for
(
int
i
=
0
;
i
<
innerRings
.
size
();
i
++)
{
LinearRing
r
=
innerRings
.
get
(
i
);
holeStart
[
i
]
=
nrOfVertices
;
nrOfVertices
+=
r
.
getVertices
().
size
()
-
1
;
}
}
// collect vertices
// find most dominant projection axis for 2d projection
ProjectionAxis
axis
=
ProjectionAxis
.
of
(
p
);
double
[]
vertices
=
new
double
[
nrOfVertices
*
2
];
List
<
Vertex
>
vertexObjects
=
new
ArrayList
<>();
addVerticesToList
(
p
.
getExteriorRing
(),
vertexObjects
);
for
(
LinearRing
innerRing
:
p
.
getInnerRings
())
{
addVerticesToList
(
innerRing
,
vertexObjects
);
}
// write the vector data according to the projection axis into the array
int
start
=
addRingToArray
(
p
.
getExteriorRing
(),
vertices
,
0
,
axis
);
for
(
LinearRing
innerRing
:
p
.
getInnerRings
())
{
start
=
addRingToArray
(
innerRing
,
vertices
,
start
,
axis
);
}
// triangulation
List
<
Integer
>
indices
=
Earcut
.
earcut
(
vertices
,
holeStart
,
2
);
List
<
Triangle3d
>
triangles
=
new
ArrayList
<>();
if
(
indices
.
size
()
%
3
!=
0
)
{
throw
new
IllegalStateException
();
}
for
(
int
i
=
0
;
i
<
indices
.
size
();
i
=
i
+
3
)
{
Triangle3d
t
=
new
Triangle3d
(
vertexObjects
.
get
(
indices
.
get
(
i
+
0
)),
vertexObjects
.
get
(
indices
.
get
(
i
+
1
)),
vertexObjects
.
get
(
indices
.
get
(
i
+
2
)));
triangles
.
add
(
t
);
}
return
new
TesselatedPolygon
(
triangles
,
p
);
}
private
static
void
addVerticesToList
(
LinearRing
ring
,
List
<
Vertex
>
vertexObjects
)
{
List
<
Vertex
>
vertices
=
ring
.
getVertices
();
for
(
int
i
=
0
;
i
<
vertices
.
size
()
-
1
;
i
++)
{
Vertex
v
=
vertices
.
get
(
i
);
vertexObjects
.
add
(
v
);
}
}
private
static
int
addRingToArray
(
LinearRing
ring
,
double
[]
vertices
,
int
start
,
ProjectionAxis
axis
)
{
List
<
Vertex
>
ringVertices
=
ring
.
getVertices
();
for
(
int
i
=
0
;
i
<
ringVertices
.
size
()
-
1
;
i
++)
{
Vertex
v
=
ringVertices
.
get
(
i
);
axis
.
writeCoordinatesOfVectorInArray
(
v
,
vertices
,
start
);
start
=
start
+
2
;
}
return
start
;
}
private
EarcutTesselator
()
{
}
}
Prev
1
2
3
4
5
6
7
…
13
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