Author: dblasby Date: 2005-11-27 03:32:29 -0800 (Sun, 27 Nov 2005) New Revision: 17008 Modified: geotools/branches/2.1.x/module/main/src/org/geotools/renderer/lite/Lab= elCacheDefault.java geotools/branches/2.1.x/module/main/src/org/geotools/renderer/style/SL= DStyleFactory.java geotools/branches/2.1.x/module/main/src/org/geotools/renderer/style/Te= xtStyle2D.java geotools/branches/2.1.x/module/migrate/src/org/geotools/renderer/j2d/S= tyledShapePainter.java Log: (1) stylefactory/textstyle2d changes to reflect lineplacement option (2) depricated useage of absolutelineplacement (see inline comments) (3) added a bunch of changes to labeler to make it more robust, powerful,= and ogc compliant. Modified: geotools/branches/2.1.x/module/main/src/org/geotools/renderer/l= ite/LabelCacheDefault.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- geotools/branches/2.1.x/module/main/src/org/geotools/renderer/lite/La= belCacheDefault.java 2005-11-27 11:28:08 UTC (rev 17007) +++ geotools/branches/2.1.x/module/main/src/org/geotools/renderer/lite/La= belCacheDefault.java 2005-11-27 11:32:29 UTC (rev 17008) @@ -124,7 +124,7 @@ /** non-grouped labels get thrown in here**/ protected ArrayList labelCacheNonGrouped =3D new ArrayList(); =09 - public boolean DEFAULT_GROUP=3Dtrue; //what to do if there's no groupin= g option + public boolean DEFAULT_GROUP=3Dfalse; //what to do if there's no groupi= ng option public int DEFAULT_SPACEAROUND =3D 0; =09 =09 @@ -547,6 +547,17 @@ return line; } =20 + /** + * This handles point and line placement. + *=20 + * 1. lineplacement -- calculate a rotation and location (and does the= perp offset) + * 2. pointplacement -- reduce line to a point and ignore the calculate= d rotation + *=20 + * @param glyphVector + * @param line + * @param textStyle + * @param tempTransform + */ private void paintLineStringLabel(GlyphVector glyphVector, LineString l= ine, TextStyle2D textStyle, AffineTransform tempTransform)=20 { =09 Point start =3D line.getStartPoint(); @@ -558,30 +569,44 @@ double rotation=3Dtheta; =09 =09 + =09 + =09 Rectangle2D textBounds =3D glyphVector.getVisualBounds(); Point centroid=3DmiddleLine(line,0.5); //DJB: changed from centroid to= "middle point" -- see middleLine() dox //DJB: this is also where you could do "voting" and looking at other l= ocations on the line to label (ie. 0.33,0.66) tempTransform.translate(centroid.getX(), centroid.getY()); double displacementX =3D 0; double displacementY =3D 0; - if (textStyle.isAbsoluteLineDisplacement()) { - double offset =3D textStyle.getDisplacementY(); - - if (offset > 0.0) { // to the left of the line - displacementY =3D -offset; - } else if (offset < 0) { - displacementY =3D -offset + textBounds.getHeight(); - } else { - displacementY =3D textBounds.getHeight() / 2; - } - - displacementX =3D -textBounds.getWidth() / 2; - } else { // DJB: this now does "centering" - displacementX =3D (textStyle.getAnchorX() + (-textBounds.getWidth(= )/2.0)) - + textStyle.getDisplacementX(); - displacementY =3D (textStyle.getAnchorY() + (textBounds.getHeight(= )/2.0)) - - textStyle.getDisplacementY(); + =09 + // DJB: this now does "centering" + // displacementX =3D (textStyle.getAnchorX() + (-textBounds.getWidt= h()/2.0)) + // + textStyle.getDisplacementX(); + // displacementY =3D (textStyle.getAnchorY() + (textBounds.getHeigh= t()/2.0)) + // - textStyle.getDisplacementY(); + =09 + double anchorX =3D textStyle.getAnchorX(); + double anchorY =3D textStyle.getAnchorY(); + =09 + // undo the above if its point placement! + if (textStyle.isPointPlacement()) + { + rotation =3D textStyle.getRotation(); // use the one the user supplie= d! } + else //lineplacement + { + displacementY -=3D textStyle.getPerpendicularOffset(); // move it off= the line + anchorX =3D 0.5; // centered + anchorY =3D 0.5; // centered, sitting on line + } + =09 + displacementX =3D ( anchorX* (-textBounds.getWidth())) + + textStyle.getDisplacementX(); + displacementY =3D (anchorY * (textBounds.getHeight())) + - textStyle.getDisplacementY(); + =20 + =20 + =09 + =09 if (rotation !=3D rotation) // IEEE def'n x=3Dx for all x except when = x is NaN rotation =3D 0.0; if (Double.isInfinite(rotation)) @@ -608,31 +633,34 @@ tempTransform.translate(point.getX(), point.getY()); double displacementX =3D 0; double displacementY =3D 0; - if (textStyle.isAbsoluteLineDisplacement()) { - double offset =3D textStyle.getDisplacementY(); - - if (offset > 0.0) { // to the left of the line - displacementY =3D -offset; - } else if (offset < 0) { - displacementY =3D -offset + textBounds.getHeight(); - } else { - displacementY =3D textBounds.getHeight() / 2; - } - - displacementX =3D -textBounds.getWidth() / 2; - } else { //DJB: this probably isnt doing what you think its doing - s= ee others + =09 + //DJB: this probably isnt doing what you think its doing - = see others displacementX =3D (textStyle.getAnchorX() * (-textBounds.getWidth(= ))) + textStyle.getDisplacementX(); displacementY =3D (textStyle.getAnchorY() * (textBounds.getHeight(= ))) - textStyle.getDisplacementY(); - } - tempTransform.rotate(textStyle.getRotation()); - tempTransform.translate(displacementX, displacementY); + =09 + if (!textStyle.isPointPlacement()) + { + //lineplacement. We're cheating here, since we cannot line l= abel a point + displacementY -=3D textStyle.getPerpendicularOffset(); // just= move it up (yes, its cheating) + } + =20 + double rotation =3D textStyle.getRotation(); + if (rotation !=3D rotation) // IEEE def'n x=3Dx for all x except when= x is NaN + rotation =3D 0.0; + if (Double.isInfinite(rotation)) + rotation =3D 0; //weird number + =09 + tempTransform.rotate(rotation); + tempTransform.translate(displacementX, displacementY); return point; } =09 /** * returns the representative geometry (for further processing) + *=20 + * TODO: handle lineplacement for a polygon (perhaps we're supposed to= grab the outside line and label it, but spec is unclear) */ private Geometry paintPolygonLabel(GlyphVector glyphVector, LabelCacheI= tem labelItem, AffineTransform tempTransform, Geometry displayGeom)=20 { @@ -669,29 +697,30 @@ tempTransform.translate(centroid.getX(), centroid.getY()); double displacementX =3D 0; double displacementY =3D 0; - if (textStyle.isAbsoluteLineDisplacement()) { - double offset =3D textStyle.getDisplacementY(); + =09 =20 - if (offset > 0.0) { // to the left of the line - displacementY =3D -offset; - } else if (offset < 0) { - displacementY =3D -offset + textBounds.getHeight(); - } else { - displacementY =3D textBounds.getHeight() / 2; - } - - displacementX =3D -textBounds.getWidth() / 2; - } else { + =09 =09 // DJB: this now does "centering" - =09 - =09 - displacementX =3D (textStyle.getAnchorX() + (-textBounds.getWidth(= )/2.0)) - + textStyle.getDisplacementX(); - displacementY =3D (textStyle.getAnchorY() + (textBounds.getHeight(= )/2.0)) - - textStyle.getDisplacementY(); - } - tempTransform.rotate(textStyle.getRotation()); + displacementX =3D (textStyle.getAnchorX() * (-textBounds.getWidth())) + + textStyle.getDisplacementX(); + displacementY =3D (textStyle.getAnchorY() * (textBounds.getHeigh= t())) + - textStyle.getDisplacementY(); + =20 + if (!textStyle.isPointPlacement()) + { + //lineplacement. We're cheating here, since we've reduced the= polygon to a point, when we should be trying to do something + // a little smarter (like find its median axis!= ) + displacementY -=3D textStyle.getPerpendicularOffset(); // just = move it up (yes, its cheating) + } + =20 + double rotation =3D textStyle.getRotation(); + if (rotation !=3D rotation) // IEEE def'n x=3Dx for all x except when = x is NaN + rotation =3D 0.0; + if (Double.isInfinite(rotation)) + rotation =3D 0; //weird number + =09 + tempTransform.rotate(rotation); tempTransform.translate(displacementX, displacementY); return geom; =20 } Modified: geotools/branches/2.1.x/module/main/src/org/geotools/renderer/s= tyle/SLDStyleFactory.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- geotools/branches/2.1.x/module/main/src/org/geotools/renderer/style/S= LDStyleFactory.java 2005-11-27 11:28:08 UTC (rev 17007) +++ geotools/branches/2.1.x/module/main/src/org/geotools/renderer/style/S= LDStyleFactory.java 2005-11-27 11:32:29 UTC (rev 17008) @@ -89,10 +89,47 @@ =20 =20 /** - * Factory object that converts SLD style into rendered styles + * Factory object that converts SLD style into rendered styles. + *=20 + * DJB: I've made a few changes to this. + * The old behavior was for this class to convert <LinePlacement> = tags to <PointPlacement> tags. + * (ie. there never was a LinePlacement option) + * This is *certainly* not the correct place to do this, and it wa= s doing a very poor job of it too, + * and the renderer was not expecting it to be doing it! + *=20 + * I added support in TextStyle3D for this and had this class corr= ectly set Line/Point placement selection. + * NOTE: PointPlacement is the default if not present. * * @author aaime + * @author dblasby */ + +/* + * orginal message on the subject: + *=20 + * I was attempting to write documentation for label placement (plus fix +all the inconsistencies with the spec), and I noticed some problems +with the SLDStyleFactory and TextStyle2D. + +It turns out the SLDStyleFactory is actually trying to do [poor] label +placement (see around line 570)! This also results in a loss of +information if you're using a <LinePlacement> element in your SLD. + + +1. remove the placement code from SLDStyleFactory! +2. get rid of the "AbsoluteLineDisplacement" stuff and replace it with +something that represents <PointPlacement>/<LinePlacement> elements in +the TextSymbolizer. + +The current implementation seems to try to convert a <LinePlacement> and +an actual line into a <PointPlacement> (and setting the +AbsoluteLineDisplacement flag)!! This should be done by the real +labeling code. + +This change could affect the j2d renderer as it appears to use the +"AbsoluteLineDisplacement" flag. +*/ +=20 public class SLDStyleFactory { /** The logger for the rendering module. */ private static final Logger LOGGER =3D Logger.getLogger("org.geotool= s.rendering"); @@ -542,7 +579,8 @@ double dispX =3D 0; double dispY =3D 0; =20 - if (placement instanceof PointPlacement) { + if (placement instanceof PointPlacement)=20 + { if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer("setting pointPlacement"); } @@ -558,27 +596,18 @@ // rotation rotation =3D ((Number) p.getRotation().getValue(feature)).do= ubleValue(); rotation *=3D (Math.PI / 180.0); - } else if (placement instanceof LinePlacement && geom instanceof= LineString) { - // @TODO: if the geometry is a ring or a polygon try to find= out - // some "axis" to follow in the label placement - if (LOGGER.isLoggable(Level.FINER)) { - LOGGER.finer("setting line placement"); + ts2d.setPointPlacement(true); + }=20 + else if (placement instanceof LinePlacement)=20 + { + // this code used to really really really really suck, so I r= emoved it! + if (LOGGER.isLoggable(Level.FINER)) { + LOGGER.finer("setting pointPlacement"); } - - LineString ls =3D (LineString) geom; - Coordinate s =3D ls.getStartPoint().getCoordinate(); - Coordinate e =3D ls.getEndPoint().getCoordinate(); - double dx =3D e.x - s.x; - double dy =3D e.y - s.y; - - double offset =3D ((Number) ((LinePlacement) placement).getP= erpendicularOffset().getValue(feature)) - .doubleValue(); - rotation =3D Math.atan2(dx, dy) - (Math.PI / 2.0); - anchorX =3D -0.5; - anchorY =3D -0.5; - dispX =3D 0; - dispY =3D offset; - ts2d.setAbsoluteLineDisplacement(true); + ts2d.setPointPlacement(false); + LinePlacement p =3D (LinePlacement) placement; + int displace =3D ((Number) p.getPerpendicularOffset().getVa= lue(feature)).intValue(); + ts2d.setPerpendicularOffset( displace ); } =20 ts2d.setAnchorX(anchorX); Modified: geotools/branches/2.1.x/module/main/src/org/geotools/renderer/s= tyle/TextStyle2D.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- geotools/branches/2.1.x/module/main/src/org/geotools/renderer/style/T= extStyle2D.java 2005-11-27 11:28:08 UTC (rev 17007) +++ geotools/branches/2.1.x/module/main/src/org/geotools/renderer/style/T= extStyle2D.java 2005-11-27 11:32:29 UTC (rev 17008) @@ -30,17 +30,57 @@ =20 /** * Style used to represent labels over lines, polygons and points + *=20 * * @author Andrea Aime + * @author dblasby * @version $Id$ */ + +/** DJB: + *=20 + * This class was fundamentally wrong - it tried to convert <LinePlace= ment> into <PointPlacement>.=20 + * Not only was it doing a really crappy job, but its fundamentally t= he wrong place to do it. + *=20 + * The SLD spec defines a <PointPlacement> as: + * <xsd:sequence> + * <xsd:element ref=3D"sld:AnchorPoint" minOccurs=3D"0"/> + * <xsd:element ref=3D"sld:Displacement" minOccurs=3D"0"/> + * <xsd:element ref=3D"sld:Rotation" minOccurs=3D"0"/> + * </xsd:sequence> + *=20 + * and <LinePlacement> as: + * <xsd:sequence> + * <xsd:element ref=3D"sld:PerpendicularOffset "minOccurs=3D"0"/> + * </xsd:sequence> + *=20 + * its annotated as: + * A "PerpendicularOffset" gives the perpendicular distance away from a= line to draw a label. + * which is a bit vague, but there's a little more details here: + *=20 + * The PerpendicularOffset element of a LinePlacement gives the perp= endicular distance away from a line to draw a label. ... + * The distance is in pixels and is positive to the left-hand. + *=20 + * Left hand/right hand for perpendicularOffset is just crap - I'm = assuming them mean +ive --> "up" and -ive --> "down". + * See the actual label code for how it deals with this. + *=20 + * I've removed all the absoluteLineDisplacement stuff and replaced= it with + * isPointPlacement() (true) --> render normally (PointPlacement= Attributes) + * isPointPlacement() (false) --> render LinePlacement=20 + *=20 + * This replaces the old behavior which converted a LinePlacement = -> pointplacement and set the absoluteLineDisplacement flag! + *=20 + * */ + =20 public class TextStyle2D extends Style2D { GlyphVector textGlyphVector; Shape haloShape; String label; Font font; double rotation; - boolean absoluteLineDisplacement; + /** yes =3D <PointPlacement> no =3D <LinePlacement> default =3D y= es**/ + boolean pointPlacement =3D true; + int perpendicularOffset =3D0; // only valid when using a LinePla= cement double anchorX; double anchorY; double displacementX; @@ -191,17 +231,17 @@ } =20 /** - * @return Returns the absoluteLineDisplacement. + * @return Returns the pointPlacement (true =3D> point placement, fa= lse =3D> line placement) */ - public boolean isAbsoluteLineDisplacement() { - return absoluteLineDisplacement; + public boolean isPointPlacement() { + return pointPlacement; } =20 /** - * @param absoluteLineDisplacement The absoluteLineDisplacement to s= et. + * @param pointPlacement (true =3D> point placement, false =3D> line= placement.) */ - public void setAbsoluteLineDisplacement(boolean absoluteLineDisplace= ment) { - this.absoluteLineDisplacement =3D absoluteLineDisplacement; + public void setPointPlacement(boolean pointPlacement) { + this.pointPlacement =3D pointPlacement; } =20 /** @@ -249,6 +289,26 @@ public void setFill(Paint fill) { this.fill =3D fill; } + =20 + /** + * only valid for a isPointPlacement=3Dfalse (ie. a lineplacement) + * @param displace in pixels + */ + public void setPerpendicularOffset(int displace) + { + perpendicularOffset =3D displace; + } + =20 + /** + * only valid for a isPointPlacement=3Dfalse (ie. a lineplacement) + * @return displacement in pixels + */ + public int getPerpendicularOffset() + { + return perpendicularOffset; + } +=09 +=09 =20 /** * Getter for property composite. Modified: geotools/branches/2.1.x/module/migrate/src/org/geotools/rendere= r/j2d/StyledShapePainter.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- geotools/branches/2.1.x/module/migrate/src/org/geotools/renderer/j2d/= StyledShapePainter.java 2005-11-27 11:28:08 UTC (rev 17007) +++ geotools/branches/2.1.x/module/migrate/src/org/geotools/renderer/j2d/= StyledShapePainter.java 2005-11-27 11:32:29 UTC (rev 17008) @@ -22,6 +22,11 @@ import org.geotools.renderer.style.PolygonStyle2D; import org.geotools.renderer.style.Style2D; import org.geotools.renderer.style.TextStyle2D; +import org.geotools.styling.LinePlacement; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.LineString; + import java.awt.AlphaComposite; import java.awt.Canvas; import java.awt.Graphics2D; @@ -136,7 +141,40 @@ double x =3D 0; double y =3D 0; =20 - if (ts2d.isAbsoluteLineDisplacement()) { + /* DJB: this used to be ts2d.isAbsoluteLineDisplacement() + * but was changed to false because the TextStyle2D no= longer does supports that. + * That code was buggy and highly likly to never actua= lly execute (unless you were using actual LINESTRING(..)) . + * It also didnt support static styles! + * Its also really rare to see a LinePlacement in an S= LD document anyways. + *=20 + * HERE IS THE ORIGNAL CODE IN SLDStyleFactory: + *=20 + *=20 + if (placement instanceof LinePlacement && geom instanceof= LineString) { + // @TODO: if the geometry is a ring or a polygon try to f= ind out + // some "axis" to follow in the label placement + if (LOGGER.isLoggable(Level.FINER)) { + LOGGER.finer("setting line placement"); + } + =09 + LineString ls =3D (LineString) geom; + Coordinate s =3D ls.getStartPoint().getCoordinate(); + Coordinate e =3D ls.getEndPoint().getCoordinate(); + double dx =3D e.x - s.x; + double dy =3D e.y - s.y; + =09 + double offset =3D ((Number) ((LinePlacement) placement).g= etPerpendicularOffset().getValue(feature)) + .doubleValue(); + rotation =3D Math.atan2(dx, dy) - (Math.PI / 2.0); + anchorX =3D -0.5; + anchorY =3D -0.5; + dispX =3D 0; + dispY =3D offset; + ts2d.setAbsoluteLineDisplacement(true); + } + =20 + */ + if (false) { double offset =3D ts2d.getDisplacementY(); =20 if (offset > 0.0) { // to the left of the line |