Below is an example to rotate labels individually along a contour line.
Some specifics:
DATA:
The example force feeds 4 lines of data.
The first set of data is for +90 to -90
ROTATION CONVERSION:
angle calculation of line:
int angle = (int)Math.round(Math.atan2((y2-y1), (x2-x1)) *180 / Math.PI);
If values are not in the +90 to -90 the opposite sign is taken and the value is
adjusted oposite by 90
ie +135 would be:
-1*(135-90)=-45
otherwise rotation is over extended
ATTRIBUTE NAMES:
182 attribute names are defined
90+ pos90
..
..
0
0
..
..
90- neg90
ATTRIBUTE VALUE SETTING:
When getting x1,y1 and x2,y2 the attribute name is set to pos45 or neg45 and
the other attribute name is given an empty string otherwise they are doing
duplicate when redrawn.
STYLE CREATION RULES (private static Style createLineStyle()):
182 rules are defined at style creation with mapping to pos90 to neg90
each rule has a TextSymbolizer
This is a handy example I think for manipulating labels at a more granular
level data.
If there is anything I can do better let me know.... Thanks, Oliver
OUTPUT:
x1: 10.0 y1: 10.0 x2: 20.0 y2: 20.0
angle=45
x1: 20.0 y1: 20.0 x2: 30.0 y2: 10.0
angle=-45
x1: 30.0 y1: 10.0 x2: 40.0 y2: 20.0
angle=45
x1: 40.0 y1: 20.0 x2: 50.0 y2: 10.0
angle=-45
CODE:
package org.geotools.demo;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureCollections;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.map.DefaultMapContext;
import org.geotools.map.MapContext;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.styling.AnchorPoint;
import org.geotools.styling.Displacement;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.Fill;
import org.geotools.styling.Font;
import org.geotools.styling.Graphic;
import org.geotools.styling.LabelPlacement;
import org.geotools.styling.LineSymbolizer;
import org.geotools.styling.Mark;
import org.geotools.styling.PointSymbolizer;
import org.geotools.styling.Rule;
import org.geotools.styling.Stroke;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.TextSymbolizer;
import org.geotools.swing.JMapFrame;
import java.awt.Color;
import java.util.*;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.FilterFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateArrays;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
public class LabelRotate {
static StyleFactory styleFactory =
CommonFactoryFinder.getStyleFactory(null);
static FilterFactory filterFactory =
CommonFactoryFinder.getFilterFactory(null);
static final CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84;
static final int MAX_NAME_LENGTH = 20;
public static void main(String[] args) throws Exception {
SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
typeBuilder.setName("mytype");
typeBuilder.setCRS(crs);
typeBuilder.add("route", LineString.class);
for(int degree=0; degree<=90; degree++){
if(degree>0){
typeBuilder.length(MAX_NAME_LENGTH).add("pos"+degree, String.class);
typeBuilder.length(MAX_NAME_LENGTH).add("neg"+degree, String.class);
}
}
final SimpleFeatureType TYPE = typeBuilder.buildFeatureType();
FeatureCollection<SimpleFeatureType, SimpleFeature> collection =
FeatureCollections.newCollection();
double x[][] = {{10, 20}, {20, 30}, {30, 40}, {40, 50}};
double y[][] = {{10, 20}, {20, 10}, {10, 20}, {20, 10}};
//double x[][] = {{20, 10}, {30, 20}, {40, 30}, {50, 40}};
//double y[][] = {{20, 10}, {10, 20}, {20, 10}, {10, 20}};
String[] names = {"L1", "L2", "L3", "L4" };
GeometryFactory factory = JTSFactoryFinder.getGeometryFactory(null);
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
ArrayList<Coordinate> coordList = new ArrayList<Coordinate>();
for (int line = 0; line < x.length; line++) {
double y1=0;
double y2=0;
double x1=0;
double x2=0;
for (int i = 0; i < x[line].length; i++) {
coordList.add(new Coordinate(x[line][i], y[line][i]));
if(i==0){
y1=y[line][i];
x1=x[line][i];
} else if(i==1){
y2=y[line][i];
x2=x[line][i];
}
}
System.out.println("x1: "+x1+" y1: "+y1+" x2: "+x2+" y2: "+y2);
int angle = (int)Math.round(Math.atan2((y2-y1), (x2-x1)) *180 /
Math.PI);
boolean flag90=false;
if(angle>90){
angle=-1*(angle-90);
flag90=true;
}
if(angle<-90){
angle=-1*(angle+90);
flag90=true;
}
System.out.println("angle="+angle);
Coordinate[] coords = CoordinateArrays.toCoordinateArray(coordList);
LineString lineString = factory.createLineString(coords);
//setting attributes to a variable name
featureBuilder.add(lineString);
if(flag90==false){
if(y2>y1){
featureBuilder.set("neg"+Math.abs(angle), names[line]);
featureBuilder.set("pos"+Math.abs(angle), "");
} else if(y2<y1){
featureBuilder.set("pos"+Math.abs(angle), names[line]);
featureBuilder.set("neg"+Math.abs(angle), "");
}
} else {
if(y1>y2){
featureBuilder.set("neg"+Math.abs(angle), names[line]);
featureBuilder.set("pos"+Math.abs(angle), "");
} else if(y1<y2){
featureBuilder.set("pos"+Math.abs(angle), names[line]);
featureBuilder.set("neg"+Math.abs(angle), "");
}
}
collection.add(featureBuilder.buildFeature(null));
coordList.clear();
}
MapContext map = new DefaultMapContext();
map.setTitle("My Contour following Labels");
map.addLayer(collection, createLineStyle());
// Now display the map
JMapFrame.showMap(map);
}
/**
* Create a Style to draw line features as thin blue lines
*/
private static Style createLineStyle() {
Stroke stroke = styleFactory.createStroke(
filterFactory.literal(Color.BLUE),
filterFactory.literal(1));
/*
* Setting the geometryPropertyName arg to null signals that we want to
* draw the default geomettry of features
*/
LineSymbolizer sym = styleFactory.createLineSymbolizer(stroke, null);
Rule rule = styleFactory.createRule();
for(int degree=0;degree<=90;degree++){
//Label Formatting
String labelField="pos"+degree;
Fill labelFill =
styleFactory.createFill(filterFactory.literal(Color.BLACK));
AnchorPoint anchor =
styleFactory.createAnchorPoint(filterFactory.literal(-0.5),
filterFactory.literal(0));
Displacement disp =
styleFactory.createDisplacement(filterFactory.literal(0),
filterFactory.literal(-10));
LabelPlacement placement = styleFactory.createPointPlacement(anchor,
disp, filterFactory.literal(degree));
//line rule applied
rule.symbolizers().add(sym);
Font font = styleFactory.getDefaultFont();
font=styleFactory.createFont(filterFactory.literal("Arial"),
filterFactory.literal("italic"), filterFactory.literal(10),
filterFactory.literal(10));
TextSymbolizer textSym = styleFactory.createTextSymbolizer(
labelFill, new Font[]{font}, null,
filterFactory.property(labelField),
placement, null);
//Label Formatting Again
labelField="neg"+degree;
labelFill =
styleFactory.createFill(filterFactory.literal(Color.black));
anchor =
styleFactory.createAnchorPoint(filterFactory.literal(-0.5),
filterFactory.literal(0));
disp = styleFactory.createDisplacement(filterFactory.literal(0),
filterFactory.literal(2));
placement = styleFactory.createPointPlacement(anchor, disp,
filterFactory.literal(-1*degree));
font = styleFactory.getDefaultFont();
font=styleFactory.createFont(filterFactory.literal("Arial"),
filterFactory.literal("italic"), filterFactory.literal(10),
filterFactory.literal(10));
TextSymbolizer textSym2 = styleFactory.createTextSymbolizer(
labelFill, new Font[]{font}, null,
filterFactory.property(labelField),
placement, null);
rule.symbolizers().add(textSym);
rule.symbolizers().add(textSym2);
}
FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(new
Rule[]{rule});
Style style = styleFactory.createStyle();
style.featureTypeStyles().add(fts);
return style;
}
}
------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev
_______________________________________________
Geotools-gt2-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-gt2-users