Skip to content

Commit

Permalink
VLine, HLine and Polygon layers (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
ISeleznev-HORIS committed Sep 13, 2019
1 parent 6a792de commit 07b9d5a
Show file tree
Hide file tree
Showing 10 changed files with 389 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package jetbrains.livemap.demo
import jetbrains.datalore.base.values.Color
import jetbrains.datalore.visualization.base.canvas.CanvasControl
import jetbrains.livemap.LiveMapSpec
import jetbrains.livemap.api.layers
import jetbrains.livemap.api.paths
import jetbrains.livemap.api.points
import jetbrains.livemap.api.*
import jetbrains.livemap.demo.model.Cities.BOSTON
import jetbrains.livemap.demo.model.Cities.MOSCOW
import jetbrains.livemap.demo.model.Cities.SPB
import jetbrains.livemap.demo.model.GeoObject

Expand All @@ -31,6 +30,29 @@ class FeaturesDemoModel(canvasControl: CanvasControl): DemoModelBase(canvasContr
strokeWidth = 1.0
}
}

polygons {
polygon {
coordinates = listOf(BOSTON, SPB, MOSCOW).map(GeoObject::geoCoord)
fillColor = Color.LIGHT_CYAN
}
}

hLines {
line {
lon = MOSCOW.lon
lat = MOSCOW.lat
lineDash = listOf(8.0, 8.0)
}
}

vLines {
line {
lon = BOSTON.lon
lat = BOSTON.lat
lineDash = listOf(8.0, 8.0)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package jetbrains.livemap.demo

import jetbrains.datalore.base.values.Color
import jetbrains.livemap.api.PathBuilder
import jetbrains.livemap.api.Paths
import jetbrains.livemap.api.PointBuilder
import jetbrains.livemap.api.Points
import jetbrains.livemap.api.*
import jetbrains.livemap.demo.model.GeoObject

fun Points.point(block: PointBuilder.() -> Unit) {
Expand Down Expand Up @@ -51,6 +48,41 @@ fun Paths.path(block: PathBuilder.() -> Unit) {
)
}

fun Polygons.polygon(block: PolygonsBuilder.() -> Unit) {
items.add(
PolygonsBuilder().apply {
index = 0
mapId = ""
regionId = ""

lineDash = emptyList()
strokeColor = Color.BLACK
strokeWidth = 0.0
fillColor = Color.GREEN
coordinates = emptyList()
}
.apply(block)
.build()
)
}

fun Lines.line(block: LineBuilder.() -> Unit) {
items.add(
LineBuilder().apply {
index = 0
mapId = ""
regionId = ""

lineDash = emptyList()
strokeColor = Color.BLACK
strokeWidth = 1.0

}
.apply(block)
.build()
)
}

fun PointBuilder.coord(geoObj: GeoObject) {
lon = geoObj.lon
lat = geoObj.lat
Expand Down
6 changes: 3 additions & 3 deletions livemap/src/commonMain/kotlin/jetbrains/livemap/LiveMap.kt
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,11 @@ class LiveMap(
when(kind) {
MapLayerKind.POINT -> mapObject2Entity.processPoint(mapObjects)
MapLayerKind.PATH -> mapObject2Entity.processPath(mapObjects)
//MapLayerKind.POLYGON -> mapObject2Entity.processPolygon(mapObjects)
MapLayerKind.POLYGON -> mapObject2Entity.processPolygon(mapObjects)
//MapLayerKind.BAR -> mapObject2Entity.processBar(mapObjects)
//MapLayerKind.PIE -> mapObject2Entity.processPie(mapObjects)
//MapLayerKind.H_LINE -> mapObject2Entity.processLine(mapObjects, true, myMapProjection.mapRect)
//MapLayerKind.V_LINE -> mapObject2Entity.processLine(mapObjects, false, myMapProjection.mapRect)
MapLayerKind.H_LINE -> mapObject2Entity.processLine(mapObjects, true)
MapLayerKind.V_LINE -> mapObject2Entity.processLine(mapObjects, false)
//MapLayerKind.TEXT -> mapObject2Entity.processText(
//mapObjects,
//TextSpec.createMeasurer(context.mapRenderContext.canvasProvider.createCanvas(Vector.ZERO).context2d)
Expand Down
79 changes: 77 additions & 2 deletions livemap/src/commonMain/kotlin/jetbrains/livemap/api/Builder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ import jetbrains.livemap.LiveMapSpec
import jetbrains.livemap.MapLocation
import jetbrains.livemap.entities.geometry.LonLatGeometry
import jetbrains.livemap.mapobjects.MapLayer
import jetbrains.livemap.mapobjects.MapLayerKind.PATH
import jetbrains.livemap.mapobjects.MapLayerKind.POINT
import jetbrains.livemap.mapobjects.MapLayerKind.*
import jetbrains.livemap.mapobjects.MapLine
import jetbrains.livemap.mapobjects.MapPoint
import jetbrains.livemap.mapobjects.MapPolygon
import jetbrains.livemap.projections.ProjectionType
import jetbrains.livemap.projections.createArcPath

Expand Down Expand Up @@ -110,6 +111,16 @@ class Paths {
val items = ArrayList<MapPath>()
}

@LiveMapDsl
class Polygons {
val items = ArrayList<MapPolygon>()
}

@LiveMapDsl
class Lines {
val items = ArrayList<MapLine>()
}

@LiveMapDsl
class PointBuilder {
var animation: Int? = null
Expand Down Expand Up @@ -174,6 +185,58 @@ class PathBuilder {
}
}



@LiveMapDsl
class PolygonsBuilder {
var index: Int? = null
var mapId: String? = null
var regionId: String? = null

var lineDash: List<Double>? = null
var strokeColor: Color? = null
var strokeWidth: Double? = null
var fillColor: Color? = null
var coordinates: List<DoubleVector>? = null

fun build(): MapPolygon {

return MapPolygon(
index!!, mapId, regionId,
lineDash!!, strokeColor!!, strokeWidth!!,
fillColor!!,
coordinates!!
.run(::Ring)
.run(::Polygon)
.run(::MultiPolygon)
.run(LonLatGeometry.Companion::create)
)
}
}

@LiveMapDsl
class LineBuilder {
var index: Int? = null
var mapId: String? = null
var regionId: String? = null

var lon: Double? = null
var lat: Double? = null
var lineDash: List<Double>? = null
var strokeColor: Color? = null
var strokeWidth: Double? = null


fun build(): MapLine {

return MapLine(
index!!, mapId, regionId,
lineDash!!, strokeColor!!, strokeWidth!!,
DoubleVector(lon!!, lat!!)
)
}
}

@LiveMapDsl
class Location {
var name: String? = null
Expand Down Expand Up @@ -228,6 +291,18 @@ fun LayersBuilder.paths(block: Paths.() -> Unit) {
items.add(MapLayer(PATH, Paths().apply(block).items))
}

fun LayersBuilder.polygons(block: Polygons.() -> Unit) {
items.add(MapLayer(POLYGON, Polygons().apply(block).items))
}

fun LayersBuilder.hLines(block: Lines.() -> Unit) {
items.add(MapLayer(H_LINE, Lines().apply(block).items))
}

fun LayersBuilder.vLines(block: Lines.() -> Unit) {
items.add(MapLayer(V_LINE, Lines().apply(block).items))
}

fun point(block: PointBuilder.() -> Unit) = PointBuilder().apply(block)

fun path(block: PathBuilder.() -> Unit) = PathBuilder().apply(block)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ class StyleComponent : EcsComponent {
fun StyleComponent.setLineDash(lineDash: List<Double>) { this.lineDash = lineDash.toDoubleArray() }
fun StyleComponent.setFillColor(fillColor: Color) { this.fillColor = fillColor.toCssColor() }
fun StyleComponent.setStrokeColor(strokeColor: Color) { this.strokeColor = strokeColor.toCssColor() }
fun StyleComponent.setStrokeWidth(strokeWidth: Double) { this.strokeWidth = strokeWidth }
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package jetbrains.livemap.mapobjects

import jetbrains.datalore.base.geometry.DoubleVector
import jetbrains.datalore.base.values.Color

class MapLine(
index: Int,
mapId: String?,
regionId: String?,

val lineDash: List<Double>,
val strokeColor: Color,
val strokeWidth: Double,
val point: DoubleVector
) : MapObject(index, mapId, regionId)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package jetbrains.livemap.mapobjects

import jetbrains.datalore.base.values.Color
import jetbrains.livemap.entities.geometry.LonLatGeometry

class MapPolygon(
index: Int,
mapId: String?,
regionId: String?,

val lineDash: List<Double>,
val strokeColor: Color,
val strokeWidth: Double,
val fillColor: Color,
val geometry: LonLatGeometry?

) : MapObject(index, mapId, regionId)
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package jetbrains.livemap.obj2entity

import jetbrains.datalore.base.geometry.DoubleRectangle
import jetbrains.datalore.base.geometry.DoubleVector
import jetbrains.datalore.base.projectionGeometry.MultiPolygon
import jetbrains.datalore.base.projectionGeometry.Polygon
import jetbrains.datalore.base.projectionGeometry.Ring
import jetbrains.datalore.maps.livemap.entities.geometry.Renderers
import jetbrains.datalore.maps.livemap.entities.geometry.WorldGeometryComponent
import jetbrains.livemap.core.ecs.EcsComponentManager
import jetbrains.livemap.core.rendering.layers.LayerManager
import jetbrains.livemap.entities.Entities
import jetbrains.livemap.entities.geometry.WorldGeometry
import jetbrains.livemap.entities.placement.Components
import jetbrains.livemap.entities.rendering.*
import jetbrains.livemap.mapobjects.MapLine
import jetbrains.livemap.mapobjects.MapObject
import jetbrains.livemap.projections.MapProjection
import jetbrains.livemap.projections.WorldPoint
import jetbrains.livemap.projections.toWorldPoint

class MapLineProcessor internal constructor(
componentManager: EcsComponentManager,
layerManager: LayerManager,
private val myMapProjection: MapProjection
) {

private val myLayerEntitiesComponent = LayerEntitiesComponent()
private val myFactory: Entities.MapEntityFactory

init {
val layerEntity = componentManager
.createEntity("map_layer_line")
.addComponent(layerManager.createRenderLayerComponent("geom_line"))
.addComponent(myLayerEntitiesComponent)
myFactory = Entities.MapEntityFactory(layerEntity)
}

internal fun process(mapObjects: List<MapObject>, horizontal: Boolean) {
createEntities(mapObjects, horizontal)
}

private fun createEntities(mapObjects: List<MapObject>, horizontal: Boolean) {
for (obj in mapObjects) {
val mapLine = obj as MapLine
val worldPoint = myMapProjection.project(mapLine.point).toWorldPoint()
val geometry = createLineGeometry(worldPoint, horizontal, myMapProjection.mapRect)
val bbox = createLineBBox(worldPoint, mapLine.strokeWidth, horizontal, myMapProjection.mapRect)

val lineEntity = myFactory
.createMapEntity(bbox.origin.toWorldPoint(), SIMPLE_RENDERER, "map_ent_line")
.addComponent(WorldGeometryComponent().apply { this.geometry = geometry })
.addComponent(Components.WorldDimensionComponent(bbox.dimension.toWorldPoint()))
.addComponent(
StyleComponent().apply {
setStrokeColor(mapLine.strokeColor)
setStrokeWidth(mapLine.strokeWidth)
setLineDash(mapLine.lineDash)
}
)

myLayerEntitiesComponent.add(lineEntity.id)
}
}

companion object {
private val SIMPLE_RENDERER = Renderers.PathRenderer()

private fun createLineGeometry(point: WorldPoint, horizontal: Boolean, mapRect: DoubleRectangle): WorldGeometry {
return if (horizontal) {
listOf(
DoubleVector(mapRect.left, point.y),
DoubleVector(mapRect.right, point.y)
)
} else {
listOf(
DoubleVector(point.x, mapRect.top),
DoubleVector(point.x, mapRect.bottom)
)
}
.run(::Ring)
.run(::Polygon)
.run(::MultiPolygon)
.run(WorldGeometry.Companion::create)
}

private fun createLineBBox(
point: WorldPoint,
strokeWidth: Double,
horizontal: Boolean,
mapRect: DoubleRectangle
): DoubleRectangle {
val origin: DoubleVector
val dimension: DoubleVector
if (horizontal) {
origin = DoubleVector(mapRect.left, point.y - strokeWidth / 2)
dimension = DoubleVector(mapRect.width, strokeWidth)
} else {
origin = DoubleVector(point.x - strokeWidth / 2, mapRect.top)
dimension = DoubleVector(strokeWidth, mapRect.height)
}
return DoubleRectangle(origin, dimension)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ class MapObject2Entity(
MapPathProcessor(myComponentManager, myLayerManager, myMapProjection).process(mapObjects)
}

/*
fun processLine(mapObjects: List<MapObject>, horizontal: Boolean) {
MapLineProcessor(myComponentManager, myLayerManager, myMapProjection).process(mapObjects, horizontal)
}

fun processPolygon(mapObjects: List<MapObject>) {
MapPolygonProcessor(myComponentManager, myLayerManager).process(mapObjects)
MapPolygonProcessor(myComponentManager, myLayerManager, myMapProjection).process(mapObjects)
}


/*
fun processBar(mapObjects: List<MapObject>) {
MapBarProcessor(myComponentManager, myLayerManager).process(mapObjects)
}
Expand All @@ -35,10 +41,6 @@ class MapObject2Entity(
MapPieProcessor(myComponentManager, myLayerManager).process(mapObjects)
}
fun processLine(mapObjects: List<MapObject>, horizontal: Boolean, mapRect: DoubleRectangle) {
MapLineProcessor(myComponentManager, myLayerManager, mapRect).process(mapObjects, horizontal)
}
fun processText(mapObjects: List<MapObject>, textMeasurer: TextMeasurer) {
MapTextProcessor(myComponentManager, myLayerManager, textMeasurer).process(mapObjects)
}
Expand Down

0 comments on commit 07b9d5a

Please sign in to comment.