Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Mayer
CircularGreenSimCity
Commits
690d78b9
Commit
690d78b9
authored
Feb 24, 2023
by
Matthias Betz
Browse files
initial commit for osm data enricher
parent
fb3bf74b
Changes
10
Expand all
Show whitespace changes
Inline
Side-by-side
enrich-citygml-with-greenarea/.gitignore
0 → 100644
View file @
690d78b9
# Created by https://www.gitignore.io/api/java,maven,macos,linux,eclipse,windows,netbeans,intellij
# Edit at https://www.gitignore.io/?templates=java,maven,macos,linux,eclipse,windows,netbeans,intellij
# User specific
.sonarlint/
Servers/
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
### Eclipse Patch ###
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Annotation Processing
.apt_generated
.sts4-cache/
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/sonarlint
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
### NetBeans ###
**/nbproject/private/
**/nbproject/Makefile-*.mk
**/nbproject/Package-*.bash
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
### Windows ###
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# End of https://www.gitignore.io/api/java,maven,macos,linux,eclipse,windows,netbeans,intellij
enrich-citygml-with-greenarea/pom.xml
0 → 100644
View file @
690d78b9
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
de.hft.stuttgart
</groupId>
<artifactId>
enrich-citygml-with-osm
</artifactId>
<version>
0.0.1-SNAPSHOT
</version>
<properties>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
<maven.compiler.source>
17
</maven.compiler.source>
<maven.compiler.target>
17
</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>
org.junit.jupiter
</groupId>
<artifactId>
junit-jupiter-api
</artifactId>
<version>
5.9.2
</version>
<scope>
test
</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.citygml4j/citygml4j-core -->
<dependency>
<groupId>
org.citygml4j
</groupId>
<artifactId>
citygml4j-core
</artifactId>
<version>
3.0.0-rc.5
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.locationtech.proj4j/proj4j -->
<dependency>
<groupId>
org.locationtech.proj4j
</groupId>
<artifactId>
proj4j
</artifactId>
<version>
1.1.4
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.locationtech.jts/jts-core -->
<dependency>
<groupId>
org.locationtech.jts
</groupId>
<artifactId>
jts-core
</artifactId>
<version>
1.19.0
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.citygml4j/citygml4j-xml -->
<dependency>
<groupId>
org.citygml4j
</groupId>
<artifactId>
citygml4j-xml
</artifactId>
<version>
3.0.0-rc.5
</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/GreenArea.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
org.locationtech.jts.geom.Polygon
;
public
class
GreenArea
{
private
Polygon
area
;
public
GreenArea
()
{
}
public
GreenArea
(
Polygon
area
)
{
this
.
area
=
area
;
}
public
void
setArea
(
Polygon
area
)
{
this
.
area
=
area
;
}
public
Polygon
getArea
()
{
return
area
;
}
@Override
public
String
toString
()
{
return
"GreenArea [area="
+
area
+
"]"
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/GreenEnricher.java
0 → 100644
View file @
690d78b9
This diff is collapsed.
Click to expand it.
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/OsmData.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.locationtech.jts.geom.Polygon
;
public
class
OsmData
{
private
Polygon
boundingBox
;
private
List
<
TreePoint
>
treePoints
=
new
ArrayList
<>();
private
List
<
GreenArea
>
greenAreas
=
new
ArrayList
<>();
private
List
<
TreeRow
>
treeRows
=
new
ArrayList
<>();
private
List
<
Waterway
>
waterways
=
new
ArrayList
<>();
private
List
<
WaterArea
>
waterAreas
=
new
ArrayList
<>();
public
void
setBoundingBox
(
Polygon
boundingBox
)
{
this
.
boundingBox
=
boundingBox
;
}
public
List
<
WaterArea
>
getWaterAreas
()
{
return
waterAreas
;
}
public
List
<
Waterway
>
getWaterways
()
{
return
waterways
;
}
public
Polygon
getBoundingBox
()
{
return
boundingBox
;
}
public
List
<
GreenArea
>
getGreenAreas
()
{
return
greenAreas
;
}
public
List
<
TreePoint
>
getTreePoints
()
{
return
treePoints
;
}
public
List
<
TreeRow
>
getTreeRows
()
{
return
treeRows
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/TreeGenerator.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
org.locationtech.jts.geom.Coordinate
;
import
org.locationtech.jts.geom.Polygon
;
import
org.xmlobjects.gml.model.geometry.aggregates.MultiSurface
;
import
org.xmlobjects.gml.model.geometry.primitives.SurfaceProperty
;
public
class
TreeGenerator
{
private
static
final
double
TRUNK_INCREASE_FACTOR
=
1.2
;
public
static
MultiSurface
generateTree
(
Coordinate
point
,
double
trunkRadius
,
double
trunkHeight
,
double
crownXRadius
,
double
crownYRadius
,
double
crownHeight
)
{
List
<
Coordinate
>
trunkWestCoordinateList
=
new
ArrayList
<>();
trunkWestCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
double
drawTrunkHeight
=
trunkHeight
*
TRUNK_INCREASE_FACTOR
;
trunkWestCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
drawTrunkHeight
));
trunkWestCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
+
trunkRadius
,
drawTrunkHeight
));
trunkWestCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
+
trunkRadius
,
0
));
trunkWestCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
Polygon
trunkWestPolygon
=
convertPolygon
(
trunkWestCoordinateList
);
var
trunkWestConvertedPolygon
=
GreenEnricher
.
convertToCityGmlPoly
(
trunkWestPolygon
);
MultiSurface
ms
=
new
MultiSurface
();
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
trunkWestConvertedPolygon
));
List
<
Coordinate
>
trunkEastCoordinateList
=
new
ArrayList
<>();
trunkEastCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
trunkEastCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
+
trunkRadius
,
0
));
trunkEastCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
+
trunkRadius
,
drawTrunkHeight
));
trunkEastCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
-
trunkRadius
,
drawTrunkHeight
));
trunkEastCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
Polygon
trunkEastPolygon
=
convertPolygon
(
trunkEastCoordinateList
);
var
trunkEastConvertedPolygon
=
GreenEnricher
.
convertToCityGmlPoly
(
trunkEastPolygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
trunkEastConvertedPolygon
));
List
<
Coordinate
>
trunkSouthCoordinateList
=
new
ArrayList
<>();
trunkSouthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
trunkSouthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
trunkSouthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
-
trunkRadius
,
drawTrunkHeight
));
trunkSouthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
drawTrunkHeight
));
trunkSouthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
-
trunkRadius
,
0
));
Polygon
trunkSouthPolygon
=
convertPolygon
(
trunkSouthCoordinateList
);
var
trunkSouthConvertedPolygon
=
GreenEnricher
.
convertToCityGmlPoly
(
trunkSouthPolygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
trunkSouthConvertedPolygon
));
List
<
Coordinate
>
trunkNorthCoordinateList
=
new
ArrayList
<>();
trunkNorthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
+
trunkRadius
,
0
));
trunkNorthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
+
trunkRadius
,
drawTrunkHeight
));
trunkNorthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
+
trunkRadius
,
drawTrunkHeight
));
trunkNorthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
+
trunkRadius
,
point
.
y
+
trunkRadius
,
0
));
trunkNorthCoordinateList
.
add
(
new
Coordinate
(
point
.
x
-
trunkRadius
,
point
.
y
+
trunkRadius
,
0
));
Polygon
trunkNorthPolygon
=
convertPolygon
(
trunkNorthCoordinateList
);
var
trunkNorthConvertedPolygon
=
GreenEnricher
.
convertToCityGmlPoly
(
trunkNorthPolygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
trunkNorthConvertedPolygon
));
/*-
* Spheroid formula:
* x = a * sin(thetha) * cos(phi)
* y = b * sin(thetha) * sin(phi)
* z = c * cos(thetha)
*
* 0 <= theta <= pi
* 0 <= phi < 2 pi
*/
// create crown
// divide by 2 to get radius, height is diameter
double
c
=
crownHeight
/
2
D
;
double
a
=
crownXRadius
;
double
b
=
crownYRadius
;
int
numberOfThetaRings
=
5
;
int
numberOfPhiRings
=
10
;
double
thetaDelta
=
Math
.
PI
/
(
numberOfThetaRings
-
1
);
double
phiDelta
=
Math
.
PI
*
2
/
numberOfPhiRings
;
List
<
List
<
Coordinate
>>
ringCoordinates
=
new
ArrayList
<>();
// top point triangles
Coordinate
topPoint
=
new
Coordinate
(
point
.
x
,
point
.
y
,
point
.
z
+
c
+
trunkHeight
+
c
);
ringCoordinates
.
add
(
Collections
.
singletonList
(
topPoint
));
for
(
int
i
=
1
;
i
<
numberOfThetaRings
-
1
;
i
++)
{
double
theta
=
i
*
thetaDelta
;
List
<
Coordinate
>
coords
=
new
ArrayList
<>();
ringCoordinates
.
add
(
coords
);
for
(
int
j
=
0
;
j
<
numberOfPhiRings
;
j
++)
{
double
phi
=
j
*
phiDelta
;
double
x
=
a
*
Math
.
sin
(
theta
)
*
Math
.
cos
(
phi
)
+
point
.
x
;
double
y
=
b
*
Math
.
sin
(
theta
)
*
Math
.
sin
(
phi
)
+
point
.
y
;
double
z
=
c
*
Math
.
cos
(
theta
)
+
point
.
z
+
trunkHeight
+
c
;
Coordinate
p1
=
new
Coordinate
(
x
,
y
,
z
);
coords
.
add
(
p1
);
}
}
Coordinate
bottomPoint
=
new
Coordinate
(
point
.
x
,
point
.
y
,
point
.
z
+
trunkHeight
);
ringCoordinates
.
add
(
Collections
.
singletonList
(
bottomPoint
));
List
<
Coordinate
>
secondRing
=
ringCoordinates
.
get
(
1
);
for
(
int
i
=
0
;
i
<
secondRing
.
size
();
i
++)
{
Coordinate
[]
coordArray
=
new
Coordinate
[]
{
topPoint
,
secondRing
.
get
(
i
),
secondRing
.
get
((
i
+
1
)
%
secondRing
.
size
()),
topPoint
};
Polygon
polygon
=
GreenEnricher
.
geomFactory
.
createPolygon
(
coordArray
);
var
convertedPoly
=
GreenEnricher
.
convertToCityGmlPoly
(
polygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
convertedPoly
));
}
for
(
int
i
=
1
;
i
<
ringCoordinates
.
size
()
-
2
;
i
++)
{
List
<
Coordinate
>
topRing
=
ringCoordinates
.
get
(
i
);
List
<
Coordinate
>
bottomRing
=
ringCoordinates
.
get
(
i
+
1
);
for
(
int
j
=
0
;
j
<
topRing
.
size
();
j
++)
{
int
nextRingIndex
=
(
j
+
1
)
%
topRing
.
size
();
Coordinate
p1
=
topRing
.
get
(
j
);
Coordinate
p2
=
topRing
.
get
(
nextRingIndex
);
Coordinate
p3
=
bottomRing
.
get
(
j
);
Coordinate
p4
=
bottomRing
.
get
(
nextRingIndex
);
Coordinate
[]
coordArray
=
new
Coordinate
[]
{
p1
,
p3
,
p4
,
p2
,
p1
};
Polygon
polygon
=
GreenEnricher
.
geomFactory
.
createPolygon
(
coordArray
);
var
convertedPoly
=
GreenEnricher
.
convertToCityGmlPoly
(
polygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
convertedPoly
));
}
}
// bottom point triangles
List
<
Coordinate
>
bottomRing
=
ringCoordinates
.
get
(
ringCoordinates
.
size
()
-
2
);
for
(
int
i
=
0
;
i
<
bottomRing
.
size
();
i
++)
{
int
nextRingIndex
=
(
i
+
1
)
%
bottomRing
.
size
();
Coordinate
p1
=
bottomRing
.
get
(
i
);
Coordinate
p2
=
bottomRing
.
get
(
nextRingIndex
);
Coordinate
[]
coordArray
=
new
Coordinate
[]
{
p2
,
p1
,
bottomPoint
,
p2
};
Polygon
polygon
=
GreenEnricher
.
geomFactory
.
createPolygon
(
coordArray
);
var
convertedPoly
=
GreenEnricher
.
convertToCityGmlPoly
(
polygon
);
ms
.
getSurfaceMember
().
add
(
new
SurfaceProperty
(
convertedPoly
));
}
return
ms
;
}
private
static
Polygon
convertPolygon
(
List
<
Coordinate
>
trunkWestCoordinateList
)
{
return
GreenEnricher
.
geomFactory
.
createPolygon
(
trunkWestCoordinateList
.
toArray
(
new
Coordinate
[
trunkWestCoordinateList
.
size
()]));
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/TreePoint.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
org.locationtech.jts.geom.Point
;
public
class
TreePoint
{
private
Point
point
;
public
TreePoint
()
{
}
public
TreePoint
(
Point
point
)
{
this
.
point
=
point
;
}
public
void
setPoint
(
Point
point
)
{
this
.
point
=
point
;
}
public
Point
getPoint
()
{
return
point
;
}
@Override
public
String
toString
()
{
return
"TreePoint [point="
+
point
+
"]"
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/TreeRow.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
org.locationtech.jts.geom.LineString
;
public
class
TreeRow
{
private
LineString
line
;
public
TreeRow
()
{
}
public
TreeRow
(
LineString
line
)
{
this
.
line
=
line
;
}
public
LineString
getLine
()
{
return
line
;
}
public
void
setLine
(
LineString
line
)
{
this
.
line
=
line
;
}
@Override
public
String
toString
()
{
return
"TreeRow [line="
+
line
+
"]"
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/WaterArea.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
org.locationtech.jts.geom.Polygon
;
public
class
WaterArea
{
private
Polygon
area
;
public
WaterArea
()
{
}
public
WaterArea
(
Polygon
area
)
{
this
.
area
=
area
;
}
public
void
setArea
(
Polygon
area
)
{
this
.
area
=
area
;
}
public
Polygon
getArea
()
{
return
area
;
}
@Override
public
String
toString
()
{
return
"WaterArea [area="
+
area
+
"]"
;
}
}
enrich-citygml-with-greenarea/src/main/java/de/hft/stuttgart/citygml/green/osm/Waterway.java
0 → 100644
View file @
690d78b9
package
de.hft.stuttgart.citygml.green.osm
;
import
org.locationtech.jts.geom.LineString
;
public
class
Waterway
{
private
LineString
line
;
public
Waterway
()
{
}
public
Waterway
(
LineString
line
)
{
super
();
this
.
line
=
line
;
}
public
void
setLine
(
LineString
line
)
{
this
.
line
=
line
;
}
public
LineString
getLine
()
{
return
line
;
}
@Override
public
String
toString
()
{
return
"Waterway [line="
+
line
+
"]"
;
}
}
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