All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.cloudfarming.client.geoviewer.render.ShapeStroke Maven / Gradle / Ivy

Go to download

AgroSense geoviewer render - contains classes for rendering of various geo objects

The newest version!
/**
 * Copyright (C) 2008-2012 AgroSense Foundation.
 *
 * AgroSense is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * There are special exceptions to the terms and conditions of the GPLv3 as it is applied to
 * this software, see the FLOSS License Exception
 * .
 *
 * AgroSense is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AgroSense.  If not, see .
 */
package nl.cloudfarming.client.geoviewer.render;

import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.FlatteningPathIterator;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;

/**
 *
 * @author Timon Veenstra 
 */

public class ShapeStroke implements Stroke {
	private Shape shapes[];
	private float advance;
	private boolean stretchToFit = false;
	private boolean repeat = true;
	private AffineTransform t = new AffineTransform();
	private static final float FLATNESS = 1;

	public ShapeStroke( Shape shapes, float advance ) {
		this( new Shape[] { shapes }, advance );
	}

	public ShapeStroke( Shape shapes[], float advance ) {
		this.advance = advance;
		this.shapes = new Shape[shapes.length];

		for ( int i = 0; i < this.shapes.length; i++ ) {
			Rectangle2D bounds = shapes[i].getBounds2D();
			t.setToTranslation( -bounds.getCenterX(), -bounds.getCenterY() );
			this.shapes[i] = t.createTransformedShape( shapes[i] );
		}
	}

	public Shape createStrokedShape( Shape shape ) {
		GeneralPath result = new GeneralPath();
		PathIterator it = new FlatteningPathIterator( shape.getPathIterator( null ), FLATNESS );
		float points[] = new float[6];
		float moveX = 0, moveY = 0;
		float lastX = 0, lastY = 0;
		float thisX = 0, thisY = 0;
		int type = 0;
		boolean first = false;
		float next = 0;
		int currentShape = 0;
		int length = shapes.length;

		float factor = 1;

		while ( currentShape < length && !it.isDone() ) {
			type = it.currentSegment( points );
			switch( type ){
			case PathIterator.SEG_MOVETO:
				moveX = lastX = points[0];
				moveY = lastY = points[1];
				result.moveTo( moveX, moveY );
				first = true;
				next = 0;
				break;

			case PathIterator.SEG_CLOSE:
				points[0] = moveX;
				points[1] = moveY;
				// Fall into....

			case PathIterator.SEG_LINETO:
				thisX = points[0];
				thisY = points[1];
				float dx = thisX-lastX;
				float dy = thisY-lastY;
				float distance = (float)Math.sqrt( dx*dx + dy*dy );
				if ( distance >= next ) {
					float r = 1.0f/distance;
					float angle = (float)Math.atan2( dy, dx );
					while ( currentShape < length && distance >= next ) {
						float x = lastX + next*dx*r;
						float y = lastY + next*dy*r;
						t.setToTranslation( x, y );
						t.rotate( angle );
						result.append( t.createTransformedShape( shapes[currentShape] ), false );
						next += advance;
						currentShape++;
						if ( repeat )
							currentShape %= length;
					}
				}
				next -= distance;
				first = false;
				lastX = thisX;
				lastY = thisY;
				break;
			}
			it.next();
		}

		return result;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy