1

Following Label coordinate position of Grid lines explanations I was able to create latitude lines every 10 degrees with labels. The values of the latitudes are drawn following the prime meridian (0 longitude).

Is there a way to display the labels along meridians 30W and 30E without displaying them at the prime meridian?

How could I label latitudes every 30 degrees starting at 0 while keeping the latitude lines (parallels) drawn every 10 degrees?

I have looked in various articles about filters and rules, but I have not been able to find the answer to my questions.

New version of code creating lat/lon graticule and labeling :

public Layer getGraticuleLayer(MapContent map, ReferencedEnvelope bounds) {
          CoordinateReferenceSystem crs1 = map.getCoordinateReferenceSystem();
          SimpleFeatureType type = (SimpleFeatureType) GridUtilities.buildType(crs1);
                List<OrthoLineDef> lineDefs = Arrays.asList(
                        new OrthoLineDef(LineOrientation.VERTICAL, 2, 10.0),
                        new OrthoLineDef(LineOrientation.HORIZONTAL, 2,10.0));
                double vertexSpacing = 0.1;
                SimpleFeatureSource grid = 
             Lines.createOrthoLines(bounds, lineDefs, vertexSpacing, 
                new LineFeatureBuilder(type));
                Style blueStyle = SLD.createLineStyle(Color.blue, 1.0f);
                ((LineSymbolizer)blueStyle.featureTypeStyles().get(0).rules()
                        .get(0).symbolizers().get(0)).getStroke().setOpacity(ff.literal(0.5));
             FeatureLayer layer = new FeatureLayer(grid, blueStyle);
             ReferencedEnvelope gridBounds = layer.getBounds();
             StyleBuilder sb = new StyleBuilder();
             java.awt.Font font = java.awt.Font.decode("Arial");
             TextSymbolizer text = sb.createTextSymbolizer(Color.white,
                        sb.createFont(font), "label");
                // every 30 instead of 10
             String localElement = "element";
             for (OrthoLineDef lineDef : lineDefs) {
                 switch (lineDef.getOrientation()) {
                     case HORIZONTAL:
                         Rule rule = blueStyle.featureTypeStyles().get(0).rules().get(0);
                         Function startPoint = ff.function("startPoint", ff.property(localElement)); // name = localName var in orig code
                         Function endPoint = ff.function("endPoint", ff.property(localElement));  // name = localName var in orig code.
                         text.setGeometry(endPoint);
                         Filter filter = ff.and(ff.equals(ff.function("getY", startPoint), ff.function("getY", endPoint)), ff.equals(ff.function("IEEEremainder", ff.function("parseDouble", ff.property("value")), ff.literal(30)),
                                 ff.literal(0)));
                         rule.setFilter(filter);
                         LabelPlacement lp = sb.createPointPlacement(.5, .5, 0, -10, 0);
                         text.setLabelPlacement(lp);
                         rule.symbolizers().add(text);
                         break;
                     case VERTICAL:
                         Rule ruleLon = blueStyle.featureTypeStyles().get(0).rules().get(0);
                         startPoint = ff.function("startPoint", ff.property(localElement));
                         endPoint = ff.function("endPoint", ff.property(localElement));
                         text.setGeometry(endPoint);
                         filter = ff.and(ff.equals(ff.function("getX", startPoint), ff.function("getX", endPoint)), ff.equals(ff.function("IEEEremainder", ff.function("parseDouble", ff.property("value")), ff.literal(30)),
                                 ff.literal(0)));
                         ruleLon.setFilter(filter);
                         // text.setLabelPlacement(lp);
                         lp = sb.createPointPlacement(.5, .5, -10, 0, 90.0);
                         text.setLabelPlacement(lp);
                         ruleLon.symbolizers().add(text);
                         break;
                 }
             }
             Layer gridLayer = new FeatureLayer(grid, blueStyle);

             return gridLayer;

        }

UPDATED CODE

        FeatureTypeStyle featureTypeStyle = sf.createFeatureTypeStyle();
        String geometryName = LineFeatureBuilder.DEFAULT_GEOMETRY_ATTRIBUTE_NAME;
         String labelName = LineFeatureBuilder.VALUE_LABEL_NAME;
         String valueName = LineFeatureBuilder.VALUE_ATTRIBUTE_NAME;

         Function startPoint = ff.function("startPoint", ff.property(geometryName));
         Function endPoint = ff.function("endPoint", ff.property(geometryName));
// Set up how the labels are drawn
         TextSymbolizer htext = sb.createTextSymbolizer(Color.red, sb.createFont(font), labelName);
         TextSymbolizer vtext = sb.createTextSymbolizer(Color.red, sb.createFont(font), labelName);
         htext.setGeometry(endPoint);
         vtext.setGeometry(endPoint);
         LabelPlacement hlp = sb.createPointPlacement(.5, .5, 10, 0, 0);
         LabelPlacement vlp = sb.createPointPlacement(.5, .5, 0, -50, 0);
         htext.setLabelPlacement(hlp);
         vtext.setLabelPlacement(vlp);

// create a rule for Horizontal Labels
         Rule rule = sb.createRule(htext);
         Filter hFilter = ff.and(ff.equals(ff.function("getY", startPoint), ff.function("getY", endPoint)), ff.equals(
                 ff.function("IEEEremainder", ff.function("parseInt", ff.property(valueName)), ff.literal(30)), ff.literal(0)));
         rule.setFilter(hFilter);
         featureTypeStyle.rules().add(rule);

         Filter vFilter = ff.and(ff.equals(ff.function("getX", startPoint), ff.function("getX", endPoint)), ff.equals(
                 ff.function("IEEEremainder", ff.function("parseInt", ff.property(valueName)), ff.literal(30)), ff.literal(0)));

         Rule ruleLon = sb.createRule(vtext);
         ruleLon.setFilter(vFilter);
         featureTypeStyle.rules().add(ruleLon);
//         blueStyle.featureTypeStyles().get(0).rules().get(0).symbolizers().add(text);  // replaced by rule.symbolizers(text)
         **blueStyle.featureTypeStyles().add(featureTypeStyle);**
         Layer gridLayer = new FeatureLayer(grid, blueStyle);

1 Answer 1

2

You would need to add a filter to your style that checked if the line was horizontal or vertical and if it is evenly divisible by 30.

So something like this (which is psuedocode):

y(startPoint("element")) == y(endPoint("element") and IEEERemainder("value",30) == 0 

which becomes something like:

  Rule rule = red.featureTypeStyles().get(0).rules().get(0);
  Function startPoint = ff.function("startPoint", ff.property(localName));
  Function endPoint = ff.function("endPoint", ff.property(localName));
  text.setGeometry(endPoint);
  Filter filter = ff.and(ff.equals(ff.function("getY", startPoint), ff.function("getY", endPoint)),

      ff.equals(ff.function("IEEEremainder", ff.function("parseDouble", ff.property("value")), ff.literal(30)),
          ff.literal(0)));
  rule.setFilter(filter);
  // LabelPlacement lp = sb.createLinePlacement(ff.literal(4));
  // text.setLabelPlacement(lp);
  LabelPlacement lp = sb.createPointPlacement(.5, .5, 0, -10, 0);
  text.setLabelPlacement(lp);
  rule.symbolizers().add(text);

To give:

enter image description here

You need to create a 2nd Rule for the vertical grid lines and repeat the process for those.

Update

It seems that the lines may not always be at the exact value I expected so 30.00000000000008 mod 30 is not 0, the answer to this is to use parseInt instead of parseDouble in the filters.

Also you need two text symbolizers and two rules (or otherwise the horizontal display changes when you set up the vertical one). So I came up with something like, though I still don't get the latitude labels until I move the map down and I'm not sure why:

String geometryName = LineFeatureBuilder.DEFAULT_GEOMETRY_ATTRIBUTE_NAME; // element
String labelName = LineFeatureBuilder.VALUE_LABEL_NAME; //label
String valueName = LineFeatureBuilder.VALUE_ATTRIBUTE_NAME; //value

Function startPoint = ff.function("startPoint", ff.property(geometryName));
Function endPoint = ff.function("endPoint", ff.property(geometryName));
// Set up how the labels are drawn
TextSymbolizer htext = sb.createTextSymbolizer(Color.red, sb.createFont(font), labelName);
TextSymbolizer vtext = sb.createTextSymbolizer(Color.red, sb.createFont(font), labelName);
htext.setGeometry(endPoint);
vtext.setGeometry(endPoint);
LabelPlacement hlp = sb.createPointPlacement(.5, .5, 10, 0, 0);
LabelPlacement vlp = sb.createPointPlacement(.5, .5, 0, -50, 0);
htext.setLabelPlacement(hlp);
vtext.setLabelPlacement(vlp);

// create a rule for Horizontal Labels
Rule rule = sb.createRule(htext);
Filter hFilter = ff.and(ff.equals(ff.function("getY", startPoint), ff.function("getY", endPoint)), ff.equals(
    ff.function("IEEEremainder", ff.function("parseInt", ff.property(valueName)), ff.literal(30)), ff.literal(0)));
rule.setFilter(hFilter);
featureTypeStyle.rules().add(rule);

Filter vFilter = ff.and(ff.equals(ff.function("getX", startPoint), ff.function("getX", endPoint)), ff.equals(
    ff.function("IEEEremainder", ff.function("parseInt", ff.property(valueName)), ff.literal(30)), ff.literal(0)));

Rule ruleLon = sb.createRule(vtext);
ruleLon.setFilter(vFilter);
featureTypeStyle.rules().add(ruleLon);

//writeStyle(blueStyle);
Layer gridLayer = new FeatureLayer(grid, blueStyle);

enter image description here

12
  • no latitude labels appear. After code above I have: redStyle.featureTypeStyles().get(0).rules().get(0).symbolizers().add(text); Layer gridLayer = new FeatureLayer(grid, redStyle); What am I missing?
    – Isidora
    Commented Apr 17, 2020 at 22:54
  • rule.symbolizers().add(text); replaces redStyle.featureTypeStyles().get(0).rules().get(0).symbolizers().add(text);
    – Ian Turton
    Commented Apr 18, 2020 at 8:47
  • That did not do it. I think the issue is with "localName" variable used in Functions startPoint and endPoint. What should be that set to exactly?
    – Isidora
    Commented Apr 20, 2020 at 18:01
  • String localName = "element";
    – Ian Turton
    Commented Apr 21, 2020 at 7:50
  • 1
    please edit the question to add your code
    – Ian Turton
    Commented Apr 21, 2020 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.