Package org.geomajas.plugin.printing.component.impl

Source Code of org.geomajas.plugin.printing.component.impl.VectorLayerComponentImpl$MapToUserFilter

/*
* 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.plugin.printing.component.impl;

import java.awt.Color;
import java.awt.Font;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.geomajas.configuration.FeatureStyleInfo;
import org.geomajas.configuration.LabelStyleInfo;
import org.geomajas.configuration.NamedStyleInfo;
import org.geomajas.configuration.SymbolInfo;
import org.geomajas.configuration.VectorLayerInfo;
import org.geomajas.configuration.client.ClientMapInfo;
import org.geomajas.layer.VectorLayerService;
import org.geomajas.layer.feature.InternalFeature;
import org.geomajas.plugin.printing.component.LayoutConstraint;
import org.geomajas.plugin.printing.component.PdfContext;
import org.geomajas.plugin.printing.component.PrintComponentVisitor;
import org.geomajas.plugin.printing.component.dto.VectorLayerComponentInfo;
import org.geomajas.plugin.printing.component.service.PrintConfigurationService;
import org.geomajas.service.FilterService;
import org.geomajas.service.GeoService;
import org.opengis.filter.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.lowagie.text.Rectangle;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateFilter;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;

/**
* Internal implementation of {@link org.geomajas.plugin.printing.component.BaseLayerComponent}.
*
* @author Jan De Moerloose
*/
@Component()
@Scope(value = "prototype")
public class VectorLayerComponentImpl extends BaseLayerComponentImpl<VectorLayerComponentInfo> {

  /** Style for this layer. */
  private NamedStyleInfo styleInfo;

  /** CQL filter */
  private String filter;

  /** Array of selected feature id's for this layer. */
  private String[] selectedFeatureIds = new String[0];

  /** True if labels are visible. */
  private boolean labelsVisible;

  /** The calculated bounds */
  @XStreamOmitField
  protected Envelope bbox;

  /** List of the features */
  @XStreamOmitField
  protected List<InternalFeature> features = new ArrayList<InternalFeature>();

  /** A sorted set of selected feature ids */
  @XStreamOmitField
  protected Set<String> selectedFeatures = new TreeSet<String>();

  @XStreamOmitField
  private final Logger log = LoggerFactory.getLogger(VectorLayerComponentImpl.class);

  // length of the connector line for symbols
  private static final float SYMBOL_CONNECT_LENGTH = 15;

  @Autowired
  @XStreamOmitField
  private GeoService geoService;

  @Autowired
  @XStreamOmitField
  private FilterService filterService;

  @Autowired
  @XStreamOmitField
  private VectorLayerService layerService;

  @Autowired
  @XStreamOmitField
  private PrintConfigurationService configurationService;

  public VectorLayerComponentImpl() {

    // stretch to map
    getConstraint().setAlignmentX(LayoutConstraint.JUSTIFIED);
    getConstraint().setAlignmentY(LayoutConstraint.JUSTIFIED);
  }

  /**
   * Call back visitor.
   *
   * @param visitor visitor
   */
  public void accept(PrintComponentVisitor visitor) {
    // nothing to do
  }

  @Override
  public void render(PdfContext context) {
    if (isVisible()) {
      bbox = createBbox();
      Collections.addAll(selectedFeatures, getSelectedFeatureIds());
      // Fetch features
      try {
        ClientMapInfo map = configurationService.getMapInfo(getMap().getMapId(), getMap().getApplicationId());

        // If MapCRS does not equal LayerCRS then instantiate
        // the CrsTransform which will be used for transforming the bbox
        VectorLayerInfo layerInfo = configurationService.getVectorLayerInfo(getLayerId());
        String mapCrs = map.getCrs();
        String layerCrs = layerInfo.getCrs();
        Envelope layerBbox = bbox;
        if (!mapCrs.equals(layerCrs)) {
          layerBbox = geoService.transform(layerBbox, mapCrs, layerCrs);
        }

        String geomName = layerInfo.getFeatureInfo().getGeometryType().getName();

        // If the transform is null then just use the bbox for the filter
        // Else if the transform is not null then transform the bbox for the filter
        Filter filter = filterService.createBboxFilter(layerCrs, layerBbox, geomName);

        if (getFilter() != null) {
          filter = filterService.createAndFilter(filterService.parseFilter(getFilter()), filter);
        }

        features = layerService.getFeatures(getLayerId(), geoService.getCrs2(map.getCrs()), filter, styleInfo,
            VectorLayerService.FEATURE_INCLUDE_ALL);

      } catch (Exception e) {
        log.error("Error getting features", e);
      }
     
      // order features, selected last
      List<InternalFeature> orderedFeatures = new ArrayList<InternalFeature>();
      for (InternalFeature feature : features) {
        if (selectedFeatures.contains(feature.getId())) {
          orderedFeatures.add(feature);
        } else {
          orderedFeatures.add(0, feature);
        }
      }

      for (InternalFeature f : orderedFeatures) {
        drawFeature(context, f);
      }
      if (isLabelsVisible()) {
        for (InternalFeature f : orderedFeatures) {
          drawLabel(context, f);
        }
      }
    }
  }

  private void drawLabel(PdfContext context, InternalFeature f) {
    LabelStyleInfo labelType = styleInfo.getLabelStyle();
    String label = f.getLabel();
    if (label != null) {
      Font font = new Font("Helvetica", Font.ITALIC, 10);
      Color fontColor = Color.black;
      if (labelType.getFontStyle() != null) {
        fontColor = context
            .getColor(labelType.getFontStyle().getColor(), labelType.getFontStyle().getOpacity());
      }
      Rectangle rect = calculateLabelRect(context, f, label, font);
      Color bgColor = Color.white;
      if (labelType.getBackgroundStyle() != null) {
        bgColor = context.getColor(labelType.getBackgroundStyle().getFillColor(), labelType
            .getBackgroundStyle().getFillOpacity());
      }
      context.fillRoundRectangle(rect, bgColor, 3);
      Color borderColor = Color.black;
      if (labelType.getBackgroundStyle() != null) {
        borderColor = context.getColor(labelType.getBackgroundStyle().getStrokeColor(), labelType
            .getBackgroundStyle().getStrokeOpacity());
      }
      float linewidth = 0.5f;
      if (labelType.getBackgroundStyle() != null) {
        linewidth = labelType.getBackgroundStyle().getStrokeWidth();
      }
      context.strokeRoundRectangle(rect, borderColor, linewidth, 3);
      context.drawText(label, font, rect, fontColor);
      if (f.getGeometry() instanceof Point) {
        context.drawLine(0.5f * (rect.getLeft() + rect.getRight()), rect.getBottom(),
            0.5f * (rect.getLeft() + rect.getRight()), rect.getBottom() - SYMBOL_CONNECT_LENGTH,
            borderColor, linewidth);
      }
    }
  }

  private float getSymbolHeight(InternalFeature f) {
    SymbolInfo info = f.getStyleInfo().getSymbol();
    if (info.getCircle() != null) {
      return 2 * info.getCircle().getR();
    } else {
      return info.getRect().getH();
    }
  }

  private Rectangle calculateLabelRect(PdfContext context, InternalFeature f, String label, Font font) {
    Rectangle textSize = context.getTextSize(label, font);
    float margin = 0.25f * font.getSize();
    Rectangle rect = new Rectangle(textSize.getWidth() + 2 * margin, textSize.getHeight() + 2 * margin);
    Coordinate labelPosition = geoService.calcDefaultLabelPosition(f);
    context.moveRectangleTo(rect, (float) labelPosition.x - rect.getWidth() / 2f,
        (float) labelPosition.y - rect.getHeight() / 2f);
    if (f.getGeometry() instanceof Point) {
      float shiftHeight = 0.5f * (rect.getHeight() + getSymbolHeight(f));
      // move up 15 pixels to make the symbol visible
      context.moveRectangleTo(rect, rect.getLeft(), rect.getBottom() + shiftHeight + SYMBOL_CONNECT_LENGTH);
    }
    if (rect.getLeft() < 0) {
      context.moveRectangleTo(rect, 10, rect.getBottom());
    }
    if (rect.getBottom() < 0) {
      context.moveRectangleTo(rect, rect.getLeft(), 10);
    }
    if (rect.getTop() > getBounds().getHeight()) {
      context.moveRectangleTo(rect, rect.getLeft(), getBounds().getHeight() - rect.getHeight() - 10);
    }
    if (rect.getRight() > getBounds().getWidth()) {
      context.moveRectangleTo(rect, getBounds().getWidth() - rect.getWidth() - 10, rect.getBottom());
    }
    return rect;
  }

  private void drawFeature(PdfContext context, InternalFeature f) {
    FeatureStyleInfo style = f.getStyleInfo();

    // Color, transparency, dash
    Color fillColor = context.getColor(style.getFillColor(), style.getFillOpacity());
    Color strokeColor = context.getColor(style.getStrokeColor(), style.getStrokeOpacity());
    float[] dashArray = context.getDashArray(style.getDashArray());

    // check if the feature is selected
    ClientMapInfo map = configurationService.getMapInfo(getMap().getMapId(), getMap().getApplicationId());
    if (selectedFeatures.contains(f.getId())) {
      if (f.getGeometry() instanceof MultiPolygon || f.getGeometry() instanceof Polygon) {
        style = mergeStyle(style, map.getPolygonSelectStyle());
        fillColor = context.getColor(style.getFillColor(), style.getFillOpacity());
        strokeColor = context.getColor(style.getStrokeColor(), style.getStrokeOpacity());
      } else if (f.getGeometry() instanceof MultiLineString || f.getGeometry() instanceof LineString) {
        style = mergeStyle(style, map.getLineSelectStyle());
        strokeColor = context.getColor(style.getStrokeColor(), style.getStrokeOpacity());
      } else if (f.getGeometry() instanceof MultiPoint || f.getGeometry() instanceof Point) {
        style = mergeStyle(style, map.getPointSelectStyle());
        strokeColor = context.getColor(style.getStrokeColor(), style.getStrokeOpacity());
      }
    }

    float lineWidth = style.getStrokeWidth();

    SymbolInfo symbol = null;
    if (f.getGeometry() instanceof MultiPoint || f.getGeometry() instanceof Point) {
      symbol = style.getSymbol();
    }
    // transform to user space
    f.getGeometry().apply(new MapToUserFilter());
    // notify geometry change !!!
    f.getGeometry().geometryChanged();
    // now draw
    context.drawGeometry(f.getGeometry(), symbol, fillColor, strokeColor, lineWidth, dashArray, getSize());
  }

  private FeatureStyleInfo mergeStyle(FeatureStyleInfo base, FeatureStyleInfo extension) {
    FeatureStyleInfo merged = new FeatureStyleInfo();
    merged.setDashArray(extension.getDashArray() != null ? extension.getDashArray() : base.getDashArray());
    merged.setFillColor(extension.getFillColor() != null ? extension.getFillColor() : base.getFillColor());
    merged.setFillOpacity(extension.getFillOpacity() != -1 ? extension.getFillOpacity() : base.getFillOpacity());
    merged.setStrokeColor(extension.getStrokeColor() != null ? extension.getStrokeColor() : base.getStrokeColor());
    merged.setStrokeOpacity(extension.getStrokeOpacity() != -1 ? extension.getStrokeOpacity() : base
        .getStrokeOpacity());
    merged.setSymbol(extension.getSymbol() != null ? extension.getSymbol() : base.getSymbol());
    merged.setStrokeWidth(extension.getStrokeWidth() != -1 ? extension.getStrokeWidth() : base.getStrokeWidth());
    return merged;
  }

  /**
   * ???
   */
  private final class MapToUserFilter implements CoordinateFilter {

    public void filter(Coordinate coordinate) {
      coordinate.x = (coordinate.x - bbox.getMinX()) * getMap().getPpUnit();
      coordinate.y = (coordinate.y - bbox.getMinY()) * getMap().getPpUnit();
    }
  }

  public void setStyleInfo(NamedStyleInfo styleInfo) {
    this.styleInfo = styleInfo;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.geomajas.plugin.printing.component.impl.VectorLayerComponent#getSelectedFeatureIds()
   */
  public String[] getSelectedFeatureIds() {
    return selectedFeatureIds;
  }

  public void setSelectedFeatureIds(String[] selectedFeatureIds) {
    this.selectedFeatureIds = selectedFeatureIds;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.geomajas.plugin.printing.component.impl.VectorLayerComponent#getFilter()
   */
  public String getFilter() {
    return filter;
  }

  public void setFilter(String filter) {
    this.filter = filter;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.geomajas.plugin.printing.component.impl.VectorLayerComponent#isLabelsVisible()
   */
  public boolean isLabelsVisible() {
    return labelsVisible;
  }

  public void setLabelsVisible(boolean labelsVisible) {
    this.labelsVisible = labelsVisible;
  }

  public void fromDto(VectorLayerComponentInfo vectorLayerInfo) {
    super.fromDto(vectorLayerInfo);
    setLabelsVisible(vectorLayerInfo.isLabelsVisible());
    setSelectedFeatureIds(vectorLayerInfo.getSelectedFeatureIds());
    setStyleInfo(vectorLayerInfo.getStyleInfo());
    setFilter(vectorLayerInfo.getFilter());
  }

}
TOP

Related Classes of org.geomajas.plugin.printing.component.impl.VectorLayerComponentImpl$MapToUserFilter

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.