I wrote a blog post about this a while back, 1st you need to override org.geotools.grid.GridFeatureBuilder
to add the X or Y values to the lines (so you can draw them later):
package com.ianturton.cookbook.utilities.gridsupport;
import java.text.Format;
import java.util.Map;
import org.geotools.grid.GridElement;
import org.geotools.grid.GridFeatureBuilder;
import org.geotools.grid.ortholine.LineOrientation;
import org.geotools.grid.ortholine.OrthoLine;
import org.geotools.measure.CoordinateFormat;
import org.locationtech.jts.geom.Coordinate;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.cs.CoordinateSystem;
public class LineFeatureBuilder extends GridFeatureBuilder {
/** Default feature TYPE name: "linegrid" */
public static final String DEFAULT_TYPE_NAME = "linegrid";
/** Name used for the integer id attribute: "id" */
public static final String ID_ATTRIBUTE_NAME = "id";
/**
* Name of the Integer level attribute ("level")
*/
public static final String LEVEL_ATTRIBUTE_NAME = "level";
/**
* Name of the Object value attribute ("value")
*/
public static final String VALUE_ATTRIBUTE_NAME = "value";
public static final String VALUE_LABEL_NAME = "label";
protected int id;
private SimpleFeatureType type;
private CoordinateFormat formatter;
private Format xFormat;
private Format yFormat;
private String xUnit;
private String yUnit;
public LineFeatureBuilder(SimpleFeatureType type2) {
super(type2);
this.type = type2;
formatter = new CoordinateFormat();
formatter.setNumberPattern("##0.00");
formatter.setAnglePattern("DD.dd");
formatter.setCoordinateReferenceSystem(type.getCoordinateReferenceSystem());
xFormat = formatter.getFormat(0);
yFormat = formatter.getFormat(1);
CoordinateSystem coordinateSystem = type.getCoordinateReferenceSystem().getCoordinateSystem();
xUnit = "" + coordinateSystem.getAxis(0).getUnit().toString();
yUnit = "" + coordinateSystem.getAxis(1).getUnit().toString();
}
@Override
public void setAttributes(GridElement el, Map<String, Object> attributes) {
if (el instanceof OrthoLine) {
OrthoLine orthoLine = (OrthoLine) el;
attributes.put(ID_ATTRIBUTE_NAME, ++id);
attributes.put(LEVEL_ATTRIBUTE_NAME, orthoLine.getLevel());
Coordinate v0 = orthoLine.getVertices()[0];
Double value = null;
String label = "";
if (orthoLine.getOrientation() == LineOrientation.HORIZONTAL) {
value = v0.y;
label = yFormat.format(v0.y) + yUnit;
} else {
value = v0.x;
label = xFormat.format(v0.x) + xUnit;
}
attributes.put(VALUE_ATTRIBUTE_NAME, value);
attributes.put(VALUE_LABEL_NAME, label);
} else {
throw new IllegalArgumentException("Expected an instance of OrthoLine");
}
}
}
Then you can create the "grid" using something like:
ReferencedEnvelope bounds = ReferencedEnvelope.create(new Envelope(xMin, xMax, yMin, yMax),
coordinateReferenceSystem);
SimpleFeatureType type = (SimpleFeatureType) GridUtilities.buildType(coordinateReferenceSystem);
List<OrthoLineDef> lineDefs = Arrays.asList(
// vertical (longitude) lines
new OrthoLineDef(LineOrientation.VERTICAL, 2, xStep),
// horizontal (latitude) lines
new OrthoLineDef(LineOrientation.HORIZONTAL, 2, yStep));
// Specify vertex spacing to get "densified" polygons
double vertexSpacing = 0.1;
grid = Lines.createOrthoLines(bounds, lineDefs, vertexSpacing, new LineFeatureBuilder(type));
The final trick is to make the style draw the labels as well as the lines:
Style red = SLD.createLineStyle(Color.red, 1.0f);
((LineSymbolizer)red.featureTypeStyles().get(0).rules()
.get(0).symbolizers().get(0)).getStroke().setOpacity(ff.literal(0.5));
layer = new FeatureLayer(featureSource, style);
layer.getBounds().getCoordinateReferenceSystem();
ReferencedEnvelope gridBounds = layer.getBounds();
StyleBuilder sb = new StyleBuilder();
java.awt.Font font = java.awt.Font.decode("Arial");
TextSymbolizer text = sb.createTextSymbolizer(Color.red,
sb.createFont(font), "label");
LabelPlacement lp = sb.createLinePlacement(ff.literal(4));
text.setLabelPlacement(lp);
red.featureTypeStyles().get(0).rules().get(0).symbolizers().add(text);
Layer gridLayer = new FeatureLayer(grid, red);
Then add gridLayer
to your map with all your other layers.
Update
Gridutilities.buildType
:
private static FeatureType buildType(CoordinateReferenceSystem crs) {
SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
tb.setName("grid");
tb.add(LineFeatureBuilder.DEFAULT_GEOMETRY_ATTRIBUTE_NAME, LineString.class, crs);
tb.add(LineFeatureBuilder.ID_ATTRIBUTE_NAME, Integer.class);
tb.add(LineFeatureBuilder.LEVEL_ATTRIBUTE_NAME, Integer.class);
tb.add(LineFeatureBuilder.VALUE_LABEL_NAME, String.class);
tb.add(LineFeatureBuilder.VALUE_ATTRIBUTE_NAME, Double.class);
return tb.buildFeatureType();
}