Skip to content

Commit 79c64de

Browse files
committed
Merge branch 'master' into tutorial
Conflicts: geoscript/build.sbt geoscript/src/test/scala/GeoHashTest.scala geoscript/src/test/scala/UsageTests.scala geoscript/src/test/scala/org/geoscript/geometry/SerializationSpec.scala geoscript/src/test/scala/org/geoscript/workspaces/MemorySpec.scala project/Build.scala
2 parents 09ec724 + 2ac5c93 commit 79c64de

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1427
-2040
lines changed

dummy/build.sbt

Lines changed: 0 additions & 8 deletions
This file was deleted.

geocss/build.sbt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ libraryDependencies <++= gtVersion { v =>
77
)
88
}
99

10-
libraryDependencies +=
11-
"org.specs2" %% "specs2" % "1.7.1" % "test"
10+
libraryDependencies ++= Seq(
11+
"org.scala-tools.testing" %% "scalacheck" % "1.9" % "test",
12+
"org.scalatest" %% "scalatest" % "1.8" % "test")
1213

1314
initialCommands += """
1415
import org.{ geotools => gt }

geocss/src/main/java/org/geoscript/geocss/CSS2SLD.java renamed to geocss/src/main/java/org/geoscript/geocss/compat/CSS2SLD.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,7 @@
55
import org.geotools.styling.Style;
66

77
public final class CSS2SLD {
8-
static abstract class Converter {
9-
public abstract Style convert(Reader input);
10-
public abstract Style convert(Reader input, URL baseURL);
11-
}
12-
13-
protected static Converter impl;
14-
15-
static {
16-
impl = new Impl();
17-
}
8+
protected static final Converter impl = new Converter();
189

1910
private CSS2SLD() throws Exception {
2011
throw new Exception("You shouldn't be instantiating this class");

geocss/src/main/scala/org/geoscript/geocss/CssOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ object CssOps {
298298
def unapply(value: Value): Option[String] = value match {
299299
case Function("rgb", Seq(Literal(r), Literal(g), Literal(b))) =>
300300
val channels = Seq(r, g, b)
301-
val hex = "#%2x%2x%2x"
301+
val hex = "#%02x%02x%02x"
302302
def validInt(x: String) =
303303
try { x.toInt; true } catch { case _ => false }
304304

geocss/src/main/scala/org/geoscript/geocss/Translator.scala

Lines changed: 101 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,9 @@ class Translator(val baseURL: Option[java.net.URL]) {
541541
Seq(polySyms, lineSyms, pointSyms, textSyms).flatten
542542
}
543543

544+
type StyleSheet = Seq[Rule]
545+
type ZIndex = Double
546+
544547
/**
545548
* Convert a list of tokens (as generated by CssParser.parse) into a GeoTools
546549
* Style object. This works by creating individual rules for every possible
@@ -550,91 +553,111 @@ class Translator(val baseURL: Option[java.net.URL]) {
550553
* @see org.geotools.styling.SLDTransformer if you want to serialize the
551554
* resultant Style object to an XML file
552555
*/
553-
def css2sld(styleSheet: Seq[Rule]): gt.Style = {
554-
val sld = styles.createStyle
555-
556-
val rules = stableSort(styleSheet, Specificity.order _).reverse
557-
558-
def extractTypeName(rule: Rule): Option[String] =
559-
flatten(And(rule.selectors)).collect {
560-
case Typename(typename) => typename
561-
} headOption
562-
563-
def extractScaleRanges(rule: Rule): Seq[Pair[Option[Double], Option[Double]]] = {
564-
val scales =
565-
flatten(And(rule.selectors))
566-
.collect {
567-
case PseudoSelector("scale", _, d) => d.toDouble
568-
case Not(PseudoSelector("scale", _, d)) => d.toDouble
569-
}
570-
.sorted
571-
.distinct
572-
573-
val limits = None +: (scales map (Some(_))) :+ None
574-
limits zip limits.tail
575-
}
556+
def css2sld(s: StyleSheet): gt.Style = {
557+
val sorted: StyleSheet = sort(s)
558+
val byType: Seq[(Option[String], StyleSheet)] = splitOnType(sorted)
559+
val resolved: Seq[(Option[String], StyleSheet)] =
560+
for ((t, rs) <- byType) yield (t, cascading2exclusive(rs))
561+
val withSymbolizers: Seq[(Option[String], Seq[(ZIndex, Rule, Seq[Symbolizer])])] =
562+
for ((t, rs) <- resolved) yield (t, interpret(rs))
563+
val gtRules: Seq[(Option[String], Seq[Seq[gt.Rule]])] =
564+
for ((t, rs) <- withSymbolizers) yield (t, createSLDRuleLayers(rs))
565+
val featureTypeStyles: Seq[gt.FeatureTypeStyle] =
566+
gtRules.flatMap(createFeatureTypeStyles)
567+
createStyle(featureTypeStyles)
568+
}
569+
570+
def sort(s: StyleSheet): StyleSheet =
571+
stableSort(s, (x: Rule, y: Rule) => Specificity.order(y, x))
572+
573+
def splitOnType(s: StyleSheet): Seq[(Option[String], StyleSheet)] = {
574+
def isForTypename(t: Option[String])(r: Rule): Boolean =
575+
t.forall(name => reduce(allOf(Typename(name) +: r.selectors)) != Exclude)
576576

577-
def isForTypename(typename: Option[String])(rule: Rule): Boolean =
578-
typename map { t =>
579-
reduce(allOf(Typename(t) +: rule.selectors)) != Exclude
580-
} getOrElse true
577+
def extractTypename(r: Rule): Option[String] =
578+
flatten(And(r.selectors)).collectFirst { case Typename(t) => t }
581579

582-
def stripTypenames(rule: Rule): Rule =
583-
rule.copy(selectors = rule.selectors map {
580+
def stripTypenames(r: Rule): Rule = {
581+
val selectors0 = r.selectors.map {
584582
case Typename(_) => Accept
585583
case selector => selector
586-
})
587-
588-
val typenames = (rules map extractTypeName) distinct
589-
590-
val styleRules =
591-
for (name <- typenames) yield (name, rules filter isForTypename(name) map stripTypenames)
592-
593-
for ((typename, overlays) <- styleRules) {
594-
val zGroups: Seq[Seq[(Double, Rule, Seq[gt.Symbolizer])]] =
595-
for (rule <- cascading2exclusive(overlays)) yield
596-
for ((z, syms) <- groupByZ(symbolize(rule))) yield
597-
(z, rule, syms)
598-
599-
for ((_, group) <- flattenByZ(zGroups.flatten)) {
600-
val fts = styles.createFeatureTypeStyle
601-
typename.foreach { t => fts.featureTypeNames.add(new NameImpl(t)) }
602-
for ((rule, syms) <- group if !syms.isEmpty) {
603-
val sldRule = styles.createRule()
604-
val ranges = extractScaleRanges(rule)
605-
606-
for (range @ (min, max) <- ranges) {
607-
val minSelector = min.map(x => PseudoSelector("scale", ">", x.toString))
608-
val maxSelector = max.map(x => PseudoSelector("scale", "<", x.toString))
609-
val restricted =
610-
reduce(allOf(rule.selectors ++ minSelector ++ maxSelector))
611-
612-
if (restricted != Exclude) {
613-
val sldRule = styles.createRule()
614-
615-
for (m <- min) sldRule.setMinScaleDenominator(m)
616-
for (m <- max) sldRule.setMaxScaleDenominator(m)
617-
for (title <- rule.description.title)
618-
sldRule.getDescription().setTitle(title)
619-
for (abstrakt <- rule.description.abstrakt)
620-
sldRule.getDescription().setAbstract(abstrakt)
621-
622-
val filter = realize(restricted)
623-
624-
for (f <- filter)
625-
sldRule.setFilter(f)
626-
for (sym <- syms)
627-
sldRule.symbolizers.add(sym)
628-
629-
fts.rules.add(sldRule)
630-
}
631-
}
632-
}
633-
sld.featureTypeStyles.add(fts)
634584
}
585+
586+
r.copy(selectors = selectors0)
635587
}
636588

637-
return sld
589+
val typenames = (s map extractTypename).distinct
590+
591+
for (t <- typenames)
592+
yield (t, s.filter(isForTypename(t)).map(stripTypenames))
593+
}
594+
595+
def extractScaleRanges(rule: Rule): Seq[Pair[Option[Double], Option[Double]]] = {
596+
val scales =
597+
flatten(And(rule.selectors))
598+
.collect {
599+
case PseudoSelector("scale", _, d) => d.toDouble
600+
case Not(PseudoSelector("scale", _, d)) => d.toDouble
601+
}
602+
.sorted
603+
.distinct
604+
605+
val limits = None +: (scales map (Some(_))) :+ None
606+
limits zip limits.tail
607+
}
608+
609+
def interpret(s: StyleSheet): Seq[(ZIndex, Rule, Seq[Symbolizer])] =
610+
for {
611+
r <- cascading2exclusive(s)
612+
(z, syms) <- groupByZ(symbolize(r))
613+
} yield (z, r, syms)
614+
615+
def createSLDRuleLayers(rs: Seq[(ZIndex, Rule, Seq[Symbolizer])]): Seq[Seq[gt.Rule]] =
616+
for ((_, group) <- flattenByZ(rs)) yield createSLDRuleLayer(group)
617+
618+
def createSLDRuleLayer(group: Seq[(Rule, Seq[Symbolizer])]): Seq[gt.Rule] =
619+
for {
620+
(rule, syms) <- group if syms.nonEmpty
621+
range @ (min, max) <- extractScaleRanges(rule)
622+
minSelector = min.map(x => PseudoSelector("scale", ">", x.toString))
623+
maxSelector = max.map(x => PseudoSelector("scale", "<", x.toString))
624+
filter = reduce(allOf(rule.selectors ++ minSelector ++ maxSelector))
625+
if (filter != Exclude)
626+
} yield createSLDRule(min, max, realize(filter), rule.description.title, rule.description.abstrakt, syms)
627+
628+
def createSLDRule(
629+
min: Option[Double],
630+
max: Option[Double],
631+
filter: Option[org.opengis.filter.Filter],
632+
title: Option[String],
633+
`abstract`: Option[String],
634+
symbolizers: Seq[gt.Symbolizer]): gt.Rule =
635+
{
636+
val rule = styles.createRule()
637+
min.foreach { rule.setMinScaleDenominator }
638+
max.foreach { rule.setMaxScaleDenominator }
639+
filter.foreach { rule.setFilter }
640+
title.foreach { t => rule.getDescription().setTitle(t) }
641+
`abstract`.foreach { a => rule.getDescription().setAbstract(a) }
642+
symbolizers.foreach { rule.symbolizers.add }
643+
rule
644+
}
645+
646+
def createFeatureTypeStyles(spec: (Option[String], Seq[Seq[gt.Rule]])): Seq[gt.FeatureTypeStyle] =
647+
spec._2.map { createFeatureTypeStyle(spec._1, _) }
648+
649+
def createFeatureTypeStyle(spec: (Option[String], Seq[gt.Rule])): gt.FeatureTypeStyle = {
650+
val (typename, rules) = spec
651+
val ftStyle = styles.createFeatureTypeStyle()
652+
typename.foreach { t => ftStyle.featureTypeNames().add(new NameImpl(t)) }
653+
rules.foreach { ftStyle.rules.add }
654+
ftStyle
655+
}
656+
657+
def createStyle(fts: Seq[gt.FeatureTypeStyle]): gt.Style = {
658+
val style = styles.createStyle()
659+
fts.foreach { style.featureTypeStyles.add }
660+
style
638661
}
639662

640663
private def flattenByZ[R, S](zGroups: Seq[(Double, R, Seq[S])])

geocss/src/main/scala/org/geoscript/geocss/compat/Impl.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import org.geotools.styling.Style
44
import sys.error
55

66
package compat {
7-
class Impl extends CSS2SLD.Converter {
8-
override def convert(input: java.io.Reader): Style =
7+
class Converter protected[compat]() {
8+
def convert(input: java.io.Reader): Style =
99
CssParser.parse(input) match {
1010
case CssParser.Success(style, _) => (new Translator).css2sld(style)
1111
case (ns: CssParser.NoSuccess) => error(ns.toString)
1212
}
1313

14-
override def convert(input: java.io.Reader, baseURL: java.net.URL): Style =
14+
def convert(input: java.io.Reader, baseURL: java.net.URL): Style =
1515
CssParser.parse(input) match {
1616
case CssParser.Success(style, _) => (new Translator(Some(baseURL))).css2sld(style)
1717
case (ns: CssParser.NoSuccess) => error(ns.toString)

support/src/main/scala/org/geoscript/support/interval/Interval.scala renamed to geocss/src/main/scala/org/geoscript/support/interval/Interval.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ object Interval {
4343
: Interval[T] =
4444
(a, b) match {
4545
case (`empty`, _) | (_, `empty`) => Empty
46-
case (a: NonEmpty[T], b: NonEmpty[T]) =>
46+
case (NonEmpty(aMin, aMax), NonEmpty(bMin, bMax)) =>
4747
val min =
48-
(for (x <- a.min; y <- b.min) yield join(evidence.gt _)(x, y)) orElse
49-
a.min orElse
50-
b.min
48+
(for (x <- aMin; y <- bMin) yield join(evidence.gt _)(x, y)) orElse
49+
aMin orElse
50+
bMin
5151
val max =
52-
(for (x <- a.max; y <- b.max) yield join(evidence.lt _)(x, y)) orElse
53-
a.max orElse
54-
b.max
52+
(for (x <- aMax; y <- bMax) yield join(evidence.lt _)(x, y)) orElse
53+
aMax orElse
54+
bMax
5555
val emptyOpt =
5656
for (mn <- min; mx <- max) yield
5757
(mn, mx) match {

0 commit comments

Comments
 (0)