ingo@1115: /*
ingo@1115: * Copyright (c) 2010 by Intevation GmbH
ingo@1115: *
ingo@1115: * This program is free software under the LGPL (>=v2.1)
ingo@1115: * Read the file LGPL.txt coming with the software for details
ingo@1115: * or visit http://www.gnu.org/licenses/ if it does not exist.
ingo@1115: */
ingo@1115:
sascha@437: package de.intevation.gnv.raster;
sascha@437:
sascha@779: import de.intevation.gnv.jfreechart.CompactXYItems;
sascha@779: import de.intevation.gnv.jfreechart.PolygonSeries;
sascha@779:
sascha@779: import de.intevation.gnv.math.IJKey;
sascha@779:
sascha@779: import de.intevation.gnv.raster.Vectorizer.Edge;
sascha@779:
sascha@779: import gnu.trove.TDoubleArrayList;
sascha@779: import gnu.trove.TIntObjectHashMap;
sascha@779:
sascha@437: import java.util.ArrayList;
sascha@437: import java.util.Collection;
sascha@437:
sascha@447: import org.apache.log4j.Logger;
sascha@447:
sascha@437: /**
sascha@802: * Vectorizer backend to generate iso lines which are able to be visualized
sascha@802: * via {@link de.intevation.gnv.jfreechart.PolygonPlot} as line strings
sascha@802: * and custom labels on the chart.
sascha@802: *
sascha@780: * @author Sascha L. Teichmann
sascha@437: */
sascha@437: public class IsoPolygonSeriesProducer
sascha@465: extends IsoProducer
sascha@437: {
sascha@448: private static Logger log = Logger.getLogger(
sascha@448: IsoPolygonSeriesProducer.class);
sascha@447:
sascha@802: /**
sascha@802: * The line width of the line string used in the chart.
sascha@802: */
sascha@802: public static final Float LINE_WIDTH = Float.valueOf(0.1f);
sascha@447:
sascha@802: /**
sascha@802: * Constructor to create an IsoPolygonSeriesProducer with a
sascha@802: * given world bounding box.
sascha@802: * @param minX Min x coord of the world.
sascha@802: * @param minY Min y coord of the world.
sascha@802: * @param maxX Max x coord of the world.
sascha@802: * @param maxY Max y coord of the world.
sascha@802: */
sascha@437: public IsoPolygonSeriesProducer(
sascha@437: double minX, double minY,
sascha@437: double maxX, double maxY
sascha@437: ) {
sascha@465: super(minX, minY, maxX, maxY);
sascha@437: }
sascha@437:
sascha@802: /**
sascha@802: * Returns a collection of series with line strings
sascha@802: * with no AttributeGenerator.
sascha@802: * @return The collection with line strings.
sascha@802: */
sascha@437: public Collection getSeries() {
sascha@437: return getSeries(null);
sascha@437: }
sascha@437:
sascha@802: /**
sascha@802: * Returns a collection of series with line strings.
sascha@802: * The label attributes are generated with a given generator.
sascha@802: * @param attributeGenerator The attribute generator. Maybe null
sascha@802: * if no attributes should be generated.
sascha@802: * @return The collection with the line strings.
sascha@802: */
sascha@448: public Collection getSeries(
sascha@448: AttributeGenerator attributeGenerator
sascha@448: ) {
sascha@437: ArrayList series = new ArrayList();
sascha@447:
sascha@437: double b1 = minX;
sascha@437: double m1 = width != 1
sascha@437: ? (maxX - minX)/(width-1)
sascha@437: : 0d;
sascha@437:
sascha@437: double b2 = minY;
sascha@437: double m2 = height != 1
sascha@437: ? (maxY - minY)/(height-1)
sascha@437: : 0d;
sascha@437:
sascha@437: TDoubleArrayList vertices = new TDoubleArrayList();
sascha@437:
sascha@465: for (IJKey key: joinPairs()) {
sascha@437: PolygonSeries ps = new PolygonSeries();
sascha@437:
sascha@437: // process complete
sascha@437: ArrayList completeList = complete.get(key);
sascha@437: if (completeList != null) {
sascha@437: for (Edge head: completeList) {
sascha@437: Edge current = head;
sascha@437: do {
sascha@437: vertices.add(m1*(current.a % width) + b1);
sascha@437: vertices.add(m2*(current.a / width) + b2);
sascha@437: }
sascha@437: while ((current = current.next) != head);
sascha@447: // add head again to close shape
sascha@447: vertices.add(m1*(head.a % width) + b1);
sascha@447: vertices.add(m2*(head.a / width) + b2);
sascha@437: ps.addRing(new CompactXYItems(vertices.toNativeArray()));
sascha@521: vertices.reset();
sascha@437: }
sascha@437: }
sascha@437:
sascha@437: // process open
sascha@437: TIntObjectHashMap map = commonOpen.get(key);
sascha@447:
sascha@437: if (map != null) {
sascha@465: for (Edge head: headList(map)) {
sascha@447:
sascha@437: head = Vectorizer.simplify(head, width);
sascha@437: Edge current = head, last = head;
sascha@437: do {
sascha@437: vertices.add(m1*(current.a % width) + b1);
sascha@437: vertices.add(m2*(current.a / width) + b2);
sascha@437: last = current;
sascha@437: }
sascha@437: while ((current = current.next) != null);
sascha@437: // add b from tail
sascha@437: vertices.add(m1*(last.b % width) + b1);
sascha@437: vertices.add(m2*(last.b / width) + b2);
sascha@437: ps.addRing(new CompactXYItems(vertices.toNativeArray()));
sascha@521: vertices.reset();
sascha@437: } // for all in common open
sascha@437: } // if map defined for key
sascha@447:
sascha@801: if (ps.getItemCount() > 0) {
sascha@801: series.add(ps);
sascha@801: if (attributeGenerator != null) {
sascha@448: Object attribute = attributeGenerator
sascha@448: .generateAttribute(key.i, key.j);
sascha@448:
sascha@448: if (attribute != null) {
sascha@448: ps.setAttribute("label", attribute);
sascha@801: }
sascha@801: }
sascha@801: ps.setAttribute("line.width", LINE_WIDTH);
sascha@801: }
sascha@437: } // for all pairs
sascha@437:
sascha@437: return series;
sascha@437: }
sascha@437: }
sascha@798: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :