Package org.geomajas.internal.rendering.painter.tile

Source Code of org.geomajas.internal.rendering.painter.tile.StringContentTilePainter

/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2011 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/

package org.geomajas.internal.rendering.painter.tile;

import java.awt.geom.AffineTransform;
import java.io.StringWriter;
import java.util.Collections;

import org.geomajas.configuration.LabelStyleInfo;
import org.geomajas.configuration.NamedStyleInfo;
import org.geomajas.global.ExceptionCode;
import org.geomajas.internal.layer.feature.InternalFeatureImpl;
import org.geomajas.internal.layer.tile.InternalTileImpl;
import org.geomajas.internal.rendering.DefaultSvgDocument;
import org.geomajas.internal.rendering.DefaultVmlDocument;
import org.geomajas.internal.rendering.writer.svg.SvgFeatureWriter;
import org.geomajas.internal.rendering.writer.svg.SvgLabelTileWriter;
import org.geomajas.internal.rendering.writer.svg.SvgTileWriter;
import org.geomajas.internal.rendering.writer.vml.VmlFeatureWriter;
import org.geomajas.internal.rendering.writer.vml.VmlLabelTileWriter;
import org.geomajas.internal.rendering.writer.vml.VmlTileWriter;
import org.geomajas.layer.VectorLayer;
import org.geomajas.layer.tile.InternalTile;
import org.geomajas.layer.tile.TileMetadata;
import org.geomajas.rendering.GraphicsDocument;
import org.geomajas.rendering.RenderException;
import org.geomajas.rendering.painter.tile.TilePainter;
import org.geomajas.service.GeoService;
import org.geomajas.service.TextService;
import org.geotools.geometry.jts.GeometryCoordinateSequenceTransformer;
import org.geotools.referencing.operation.transform.ProjectiveTransform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vividsolutions.jts.geom.Coordinate;

/**
* <p>
* TilePainter implementation for {@link InternalTile} objects.
* </p>
*
* @author Pieter De Graef
*/
public class StringContentTilePainter implements TilePainter {

  private final Logger log = LoggerFactory.getLogger(StringContentTilePainter.class);

  /**
   * The maximum number of allowed fraction digits.
   */
  protected static final int MAXIMUM_FRACTION_DIGITS = 0;

  /**
   * Should this painter paint a feature's geometries or not?
   */
  private boolean paintGeometries = true;

  /**
   * Should this painter paint a feature's labels or not?
   */
  private boolean paintLabels;

  /**
   * The layer wherein the tiles lie.
   */
  private VectorLayer layer;

  /**
   * The layer style.
   */
  private NamedStyleInfo style;

  /**
   * Rendering output type. This can be either "SVG" or "VML". This depends on what the client requests.
   */
  private String renderer;

  /**
   * The tile to render.
   */
  private InternalTile tile;

  /**
   * The current client-side scale.
   */
  private double scale;

  /**
   * Transformer that transforms the feature's geometries from world to view space.
   */
  private GeometryCoordinateSequenceTransformer unitToPixel;

  /**
   * A DOM document for parsing the tile's features.
   */
  private GraphicsDocument featureDocument;

  /**
   * A DOM document for parsing the tile's labels.
   */
  private GraphicsDocument labelDocument;

  /**
   * The current origin may differ, depending on whether or not the client has been panning.
   */
  private Coordinate panOrigin;

  private GeoService geoService;

  private TextService textService;
  // -------------------------------------------------------------------------
  // Constructors:
  // -------------------------------------------------------------------------

  /**
   * Initialize this painter with all the info it needs.
   *
   * @param layer
   *            The vector layer wherein the tiles lie.
   * @param style
   *            The rendering style.
   * @param renderer
   *            Rendering output type: "SVG" or "VML".
   * @param scale
   *            The current client-side scale. Needed for creating the world to view space coordinate transformer.
   * @param panOrigin
   *            The current origin may differ, depending on whether or not the client has been panning.Needed for
   *            creating the world to view space coordinate transformer.
   * @param geoService
   *            geo service for geometry conversions
   * @param textService
   *            text service for string sizes
   */
  public StringContentTilePainter(VectorLayer layer, NamedStyleInfo style, String renderer, double scale,
      Coordinate panOrigin, GeoService geoService, TextService textService) {
    this.layer = layer;
    // @todo: duplicate code, can we just depend on the VectorLayerService ?
    if (style == null) {
      // no style specified, take the first
      style = layer.getLayerInfo().getNamedStyleInfos().get(0);
    } else if (style.getFeatureStyles().isEmpty()) {
      // only name specified, find it
      style = layer.getLayerInfo().getNamedStyleInfo(style.getName());
    }

    this.style = style;
    this.renderer = renderer;
    this.scale = scale;
    this.panOrigin = panOrigin;
    this.geoService = geoService;
    this.textService = textService;
  }

  // -------------------------------------------------------------------------
  // TilePainter implementation:
  // -------------------------------------------------------------------------

  /**
   * Paint the tile! The tile must be an instance of {@link InternalTile}. This function will create 2 DOM documents
   * for geometries and labels. In case the renderer says "SVG" these documents will be of the type
   * {@link org.geomajas.internal.rendering.DefaultSvgDocument}, otherwise
   * {@link org.geomajas.internal.rendering.DefaultVmlDocument}. These documents in turn are built using
   * {@link org.geomajas.internal.rendering.writer.GraphicsWriter} classes.
   *
   * @param tileToPaint
   *            The instance of {@link InternalTile}. Using the DOM documents, the tile's "featureFragment" and
   *            "labelFragment" will be created.
   * @return Returns a fully rendered vector tile.
   */
  public InternalTile paint(InternalTile tileToPaint) throws RenderException {
    if (tileToPaint != null && null != tileToPaint.getFeatures()) {
      tile = tileToPaint;
      Collections.sort(tile.getFeatures()); // make sure features are sorted by style, needed for grouping

      // Create the SVG / VML feature fragment:
      if (paintGeometries && featureDocument == null) {
        StringWriter writer = new StringWriter();
        try {
          featureDocument = createFeatureDocument(writer);
          featureDocument.setRootId(layer.getId());
          featureDocument.writeObject(tile, false);
          featureDocument.flush();
        } catch (RenderException e) {
          log.error("Unable to write this tile's feature fragment", e);
        }
        tile.setFeatureContent(writer.toString());
      }

      // Create the SVG / VML label fragment:
      if (paintLabels && labelDocument == null) {
        StringWriter writer = new StringWriter();
        try {
          labelDocument = createLabelDocument(writer, style.getLabelStyle());
          labelDocument.setRootId(layer.getId());
          labelDocument.writeObject(tileToPaint, false);
          labelDocument.flush();
        } catch (RenderException e) {
          log.error("Unable to write this tile's label fragment", e);
        }
        tile.setLabelContent(writer.toString());
      }
      return tile;
    }

    return tileToPaint;
  }

  /**
   * Enables or disabled the use of painter that paint the geometries of the features in the tile.
   *
   * @param paintGeometries
   *            true or false.
   */
  public void setPaintGeometries(boolean paintGeometries) {
    this.paintGeometries = paintGeometries;
  }

  /**
   * Enables or disabled the use of painter that paint the labels of the features in the tile.
   *
   * @param paintLabels
   *            true or false.
   */
  public void setPaintLabels(boolean paintLabels) {
    this.paintLabels = paintLabels;
  }

  // -------------------------------------------------------------------------
  // Private functions:
  // -------------------------------------------------------------------------

  /**
   * Create a document that parses the tile's featureFragment, using GraphicsWriter classes.
   *
   * @param writer
   *            writer
   * @return document
   * @throws RenderException
   *             oops
   */
  private GraphicsDocument createFeatureDocument(StringWriter writer) throws RenderException {
    if (TileMetadata.PARAM_SVG_RENDERER.equalsIgnoreCase(renderer)) {
      DefaultSvgDocument document = new DefaultSvgDocument(writer, false);
      document.setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);
      document.registerWriter(InternalFeatureImpl.class, new SvgFeatureWriter(getTransformer()));
      document.registerWriter(InternalTileImpl.class, new SvgTileWriter());
      return document;
    } else if (TileMetadata.PARAM_VML_RENDERER.equalsIgnoreCase(renderer)) {
      DefaultVmlDocument document = new DefaultVmlDocument(writer);
      int coordWidth = tile.getScreenWidth();
      int coordHeight = tile.getScreenHeight();
      document.registerWriter(InternalFeatureImpl.class, new VmlFeatureWriter(getTransformer(), coordWidth,
          coordHeight));
      document.registerWriter(InternalTileImpl.class, new VmlTileWriter(coordWidth, coordHeight));
      document.setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);
      return document;
    } else {
      throw new RenderException(ExceptionCode.RENDERER_TYPE_NOT_SUPPORTED, renderer);
    }
  }

  /**
   * Create a document that parses the tile's labelFragment, using GraphicsWriter classes.
   *
   * @param writer
   *            writer
   * @param labelStyleInfo
   *            label style info
   * @return graphics document
   * @throws RenderException
   *             cannot render
   */
  private GraphicsDocument createLabelDocument(StringWriter writer, LabelStyleInfo labelStyleInfo)
      throws RenderException {

    if (TileMetadata.PARAM_SVG_RENDERER.equalsIgnoreCase(renderer)) {
      DefaultSvgDocument document = new DefaultSvgDocument(writer, false);
      document.setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);
      document.registerWriter(InternalTileImpl.class, new SvgLabelTileWriter(getTransformer(), labelStyleInfo,
          geoService, textService));
      return document;
    } else if (TileMetadata.PARAM_VML_RENDERER.equalsIgnoreCase(renderer)) {
      DefaultVmlDocument document = new DefaultVmlDocument(writer);
      int coordWidth = tile.getScreenWidth();
      int coordHeight = tile.getScreenHeight();
      document.registerWriter(InternalFeatureImpl.class, new VmlFeatureWriter(getTransformer(), coordWidth,
          coordHeight));
      document.registerWriter(InternalTileImpl.class, new VmlLabelTileWriter(coordWidth, coordHeight,
          getTransformer(), labelStyleInfo, geoService, textService));
      document.setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);
      return document;
    } else {
      throw new RenderException(ExceptionCode.RENDERER_TYPE_NOT_SUPPORTED, renderer);
    }
  }

  /**
   * Get transformer to use.
   *
   * @return transformation to apply
   */
  private GeometryCoordinateSequenceTransformer getTransformer() {
    if (unitToPixel == null) {
      unitToPixel = new GeometryCoordinateSequenceTransformer();
      unitToPixel.setMathTransform(ProjectiveTransform.create(new AffineTransform(scale, 0, 0, -scale, -scale
          * panOrigin.x, scale * panOrigin.y)));
    }
    return unitToPixel;
  }

}
TOP

Related Classes of org.geomajas.internal.rendering.painter.tile.StringContentTilePainter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.