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 :