@@ -11,6 +11,7 @@ import org.geotools.styling.{
11
11
LineSymbolizer ,
12
12
PointSymbolizer ,
13
13
PolygonSymbolizer ,
14
+ RasterSymbolizer ,
14
15
Symbolizer ,
15
16
TextSymbolizer ,
16
17
TextSymbolizer2 ,
@@ -179,12 +180,9 @@ class Translator(val baseURL: Option[java.net.URL]) {
179
180
case _ => None
180
181
}
181
182
182
- def getZIndex (xs : Seq [Value ]): Option [Double ] =
183
- keyword(xs) flatMap { text =>
184
- try Some (text.toDouble)
185
- catch {
186
- case (_ : NumberFormatException ) => None
187
- }
183
+ def getLiteralDouble (xs : Seq [Value ]): Option [Double ] =
184
+ Some (xs) collect {
185
+ case Seq (Literal (Double (z))) => z
188
186
}
189
187
190
188
def scale (s : String ): Float = {
@@ -230,10 +228,90 @@ class Translator(val baseURL: Option[java.net.URL]) {
230
228
}).toArray
231
229
}
232
230
233
- // implicit def stringToFilter(literal: String): org.opengis.filter.Filter = {
234
- // val cql = literal.substring(1, literal.length - 1)
235
- // org.geotools.filter.text.ecql.ECQL.toFilter(cql)
236
- // }
231
+ def channelSelection (xs : Seq [Value ]): gt.ChannelSelection = {
232
+ object Channel {
233
+ def unapply (v : Value ): Option [gt.SelectedChannelType ] =
234
+ v match {
235
+ case Literal (" auto" ) => None
236
+ case Literal (text) =>
237
+ Some (styles.createSelectedChannelType(
238
+ text, null : gt.ContrastEnhancement ))
239
+ case _ => None
240
+ }
241
+ }
242
+
243
+ val channels =
244
+ Some (xs) collect {
245
+ case Seq (Channel (grey)) => Array (grey)
246
+ case Seq (Channel (r), Channel (g), Channel (b)) => Array (r, g, b)
247
+ }
248
+
249
+ channels.map(styles.createChannelSelection).orNull // TODO: return Option[ChannelSelection] instead.
250
+ }
251
+
252
+ object Double {
253
+ def unapply (s : String ): Option [Double ] =
254
+ try
255
+ Some (s.toDouble)
256
+ catch {
257
+ case (_ : NumberFormatException ) => None
258
+ }
259
+ }
260
+
261
+ def colorMap (rampType : Option [Int ])(xs : Seq [Value ]): Option [gt.ColorMap ] = {
262
+ def getColorMapEntry (c : OGCExpression , v : Double , o : Double ) = {
263
+ val e = styles.createColorMapEntry
264
+ e.setColor(c)
265
+ e.setQuantity(filters.literal(v))
266
+ e.setOpacity(filters.literal(o))
267
+ e
268
+ }
269
+ def getColorMap (entries : Seq [gt.ColorMapEntry ]) = {
270
+ val m = styles.createColorMap
271
+ rampType.foreach(m.setType)
272
+ entries.foreach(m.addColorMapEntry)
273
+ m
274
+ }
275
+ def tryEntry (v : Value ): Option [gt.ColorMapEntry ] =
276
+ Some (v) collect {
277
+ case Function (" color-map-entry" , Seq (Color (c), Literal (Double (v)))) =>
278
+ getColorMapEntry(c, v, 1 )
279
+ case Function (" color-map-entry" , Seq (Color (c), Literal (Double (v)), Literal (Double (o)))) =>
280
+ getColorMapEntry(c, v, o)
281
+ }
282
+
283
+ def sequence [A ](as : Seq [Option [A ]]): Option [Seq [A ]] =
284
+ (as foldRight (Some (Nil ): Option [Seq [A ]])) {
285
+ (aOpt, accum) => for (a <- aOpt; res <- accum) yield a +: res
286
+ }
287
+
288
+ sequence(xs map tryEntry).map(getColorMap)
289
+ }
290
+
291
+ def getOverlapBehavior (xs : Seq [Value ]): Option [org.opengis.style.OverlapBehavior ] = {
292
+ import scala .util .control .Exception .catching
293
+ xs.headOption flatMap {
294
+ case Literal (name) =>
295
+ catching(classOf [IllegalArgumentException ]).opt {
296
+ org.opengis.style.OverlapBehavior .valueOf(name)
297
+ }
298
+ case _ => None
299
+ }
300
+ }
301
+
302
+ def getContrastMethod (xs : Seq [Value ]): Option [org.opengis.style.ContrastMethod ] =
303
+ xs.headOption collect {
304
+ case Literal (" none" ) => org.opengis.style.ContrastMethod .NONE
305
+ case Literal (" normalize" ) => org.opengis.style.ContrastMethod .NORMALIZE
306
+ case Literal (" histogram" ) => org.opengis.style.ContrastMethod .HISTOGRAM
307
+ }
308
+
309
+ def getColorMapType (xs : Seq [Value ]): Option [Int ] =
310
+ xs.headOption collect {
311
+ case Literal (" ramp" ) => org.geotools.styling.ColorMap .TYPE_RAMP
312
+ case Literal (" intervals" ) => org.geotools.styling.ColorMap .TYPE_INTERVALS
313
+ case Literal (" values" ) => org.geotools.styling.ColorMap .TYPE_VALUES
314
+ }
237
315
238
316
def valToExpression (v : Value ): Option [OGCExpression ] =
239
317
v match {
@@ -349,7 +427,7 @@ class Translator(val baseURL: Option[java.net.URL]) {
349
427
val geom =
350
428
props.get(" stroke-geometry" ) orElse props.get(" geometry" ) flatMap expression
351
429
val zIndex : Double =
352
- props.get(" stroke-z-index" ) orElse props.get(" z-index" ) flatMap getZIndex getOrElse(0d )
430
+ props.get(" stroke-z-index" ) orElse props.get(" z-index" ) flatMap getLiteralDouble getOrElse(0d )
353
431
354
432
val graphic = buildGraphic(" stroke" , props, markProps)
355
433
@@ -388,7 +466,7 @@ class Translator(val baseURL: Option[java.net.URL]) {
388
466
val geom =
389
467
props.get(" fill-geometry" ) orElse props.get(" geometry" ) flatMap expression
390
468
val zIndex : Double =
391
- props.get(" fill-z-index" ) orElse props.get(" z-index" ) flatMap getZIndex getOrElse(0d )
469
+ props.get(" fill-z-index" ) orElse props.get(" z-index" ) flatMap getLiteralDouble getOrElse(0d )
392
470
393
471
val graphic = buildGraphic(" fill" , props, markProps)
394
472
@@ -413,7 +491,7 @@ class Translator(val baseURL: Option[java.net.URL]) {
413
491
val geom = (props.get(" mark-geometry" ) orElse props.get(" geometry" ))
414
492
.flatMap(expression)
415
493
val zIndex : Double =
416
- props.get(" mark-z-index" ) orElse props.get(" z-index" ) flatMap getZIndex getOrElse(0d )
494
+ props.get(" mark-z-index" ) orElse props.get(" z-index" ) flatMap getLiteralDouble getOrElse(0d )
417
495
418
496
val graphic = buildGraphic(" mark" , props, markProps)
419
497
@@ -437,7 +515,7 @@ class Translator(val baseURL: Option[java.net.URL]) {
437
515
val geom = (props.get(" label-geometry" ) orElse props.get(" geometry" ))
438
516
.flatMap(expression)
439
517
val zIndex : Double =
440
- props.get(" label-z-index" ) orElse props.get(" z-index" ) flatMap(getZIndex ) getOrElse 0d
518
+ props.get(" label-z-index" ) orElse props.get(" z-index" ) flatMap(getLiteralDouble ) getOrElse 0d
441
519
442
520
val font = fontFamily.getOrElse(Nil ).flatMap(valToExpression).map { familyName => {
443
521
val fontStyle =
@@ -531,7 +609,52 @@ class Translator(val baseURL: Option[java.net.URL]) {
531
609
(zIndex, sym)
532
610
}
533
611
534
- Seq (polySyms, lineSyms, pointSyms, textSyms).flatten
612
+ val rasterSyms : Seq [(Double , RasterSymbolizer )] =
613
+ (expand(properties, " raster-channels" ).toStream zip
614
+ (Stream .from(1 ) map { orderedMarkRules(" outline" , _) })
615
+ ).map { case (props, outlineProps) =>
616
+ val geom =
617
+ (props get " raster-geometry" )
618
+ .orElse(props get " geometry" )
619
+ .flatMap(expression)
620
+ val opacity =
621
+ (props get " raster-opacity" ) flatMap expression
622
+ val channels =
623
+ (props get " raster-channels" ) map channelSelection
624
+ val overlap = (props get " raster-overlap-behavior" ) flatMap getOverlapBehavior
625
+ val colorMapType = (props get " raster-color-map-type" ) flatMap getColorMapType
626
+ val colorMapEntries =
627
+ (props get " raster-color-map" ) flatMap colorMap(colorMapType)
628
+ val contrastMethod =
629
+ (props get " raster-contrast-enhancement" ) flatMap getContrastMethod
630
+ val gamma =
631
+ (props get " raster-gamma" ) flatMap getLiteralDouble
632
+ val relief = (null : org.geotools.styling.ShadedRelief )
633
+ val outline = (null : Symbolizer )
634
+ val zIndex : Double =
635
+ (props get " raster-z-index" )
636
+ .orElse(props get " z-index" )
637
+ .flatMap(getLiteralDouble)
638
+ .getOrElse(0d )
639
+
640
+ val contrastEnhancement = styles.createContrastEnhancement()
641
+ contrastMethod.foreach(contrastEnhancement.setMethod)
642
+ gamma.foreach(g => contrastEnhancement.setGammaValue(filters.literal(g)))
643
+
644
+ val sym = styles.createRasterSymbolizer(
645
+ null , // This should be the geometry property, but it only accepts a string so we use setGeometry() after creation to pass an expression.
646
+ opacity.orNull,
647
+ channels.orNull,
648
+ overlap.map(filters.literal).orNull,
649
+ colorMapEntries.orNull,
650
+ contrastEnhancement,
651
+ relief,
652
+ outline)
653
+ sym.setGeometry(geom.orNull)
654
+ (zIndex, sym)
655
+ }
656
+
657
+ Seq (polySyms, lineSyms, pointSyms, textSyms, rasterSyms).flatten
535
658
}
536
659
537
660
type StyleSheet = Seq [Rule ]
0 commit comments