下面列出了怎么用java.awt.geom.FlatteningPathIterator的API类实例代码及写法,或者点击链接到github查看源代码。
@Override public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g.create();
g2.translate(x, y);
g2.setPaint(Color.BLACK);
g2.draw(shape);
g2.setPaint(Color.RED);
PathIterator i = new FlatteningPathIterator(shape.getPathIterator(null), 1d);
double[] coords = new double[6];
while (!i.isDone()) {
i.currentSegment(coords);
g2.fillRect((int) (coords[0] - .5), (int) (coords[1] - .5), 2, 2);
i.next();
}
g2.dispose();
}
public static Polygon convertShape2Polygon(Shape s) {
PathIterator i = new FlatteningPathIterator(s.getPathIterator(null), 1d);
Polygon polygon = new Polygon();
float[] coords = new float[6];
while (!i.isDone()) {
i.currentSegment(coords);
polygon.addPoint((int) coords[0], (int) coords[1]);
i.next();
}
return polygon;
}
@Override
public PathIterator getPathIterator(AffineTransform at, double flatness) {
return new FlatteningPathIterator(getPathIterator(at), flatness);
}
public PathIterator getPathIterator(AffineTransform at, double flatness) {
return new FlatteningPathIterator(getPathIterator(at), flatness);
}
/**
* @{inheritDoc}
*/
public PathIterator getPathIterator(AffineTransform at, double flatness) {
return new FlatteningPathIterator(getPathIterator(at), flatness);
}
@Override
public Shape createStrokedShape(Shape shape) {
// rand.setSeed(seed);
GeneralPath result = new GeneralPath();
shape = new BasicStroke(basicStrokeWidth).createStrokedShape(shape);
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;
while (!it.isDone()) {
type = it.currentSegment(points);
switch (type) {
case SEG_MOVETO:
moveX = lastX = randomize(points[0]);
moveY = lastY = randomize(points[1]);
result.moveTo(moveX, moveY);
// first = true;
next = 0;
break;
case SEG_CLOSE:
points[0] = moveX;
points[1] = moveY;
// fall through
case SEG_LINETO:
thisX = randomize(points[0]);
thisY = randomize(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 (distance >= next) {
float x = lastX + next * dx * r;
float y = lastY + next * dy * r;
result.lineTo(randomize(x), randomize(y));
next += detail;
}
}
next -= distance;
// first = false;
lastX = thisX;
lastY = thisY;
break;
}
it.next();
}
return result;
}
@Override
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;
float next = 0;
int currentShape = 0;
int length = shapes.length;
while (currentShape < length && !it.isDone()) {
type = it.currentSegment(points);
switch (type) {
case SEG_MOVETO:
moveX = lastX = points[0];
moveY = lastY = points[1];
result.moveTo(moveX, moveY);
next = 0;
break;
case SEG_CLOSE:
points[0] = moveX;
points[1] = moveY;
// fall through
case 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;
lastX = thisX;
lastY = thisY;
break;
}
it.next();
}
return result;
}
@Override
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;
float next = 0;
int phase = 0;
while (!it.isDone()) {
type = it.currentSegment(points);
switch (type) {
case SEG_MOVETO:
moveX = lastX = points[0];
moveY = lastY = points[1];
result.moveTo(moveX, moveY);
next = wavelength / 2;
break;
case SEG_CLOSE:
points[0] = moveX;
points[1] = moveY;
// fall through
case 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 (distance >= next) {
float x = lastX + next * dx * r;
float y = lastY + next * dy * r;
// float tx = amplitude*dy*r;
// float ty = amplitude*dx*r;
if ((phase & 1) == 0) {
result.lineTo(x + amplitude * dy * r, y - amplitude * dx * r);
} else {
result.lineTo(x - amplitude * dy * r, y + amplitude * dx * r);
}
next += wavelength;
phase++;
}
}
next -= distance;
lastX = thisX;
lastY = thisY;
if (type == SEG_CLOSE) {
result.closePath();
}
break;
}
it.next();
}
return stroke.createStrokedShape(result);
}
private void doTrace(Drawable dr, Shape shape) {
View view = dr.getComp().getView();
PPoint startingPoint = null;
var fpi = new FlatteningPathIterator(
shape.getPathIterator(null), 1.0);
// MeasuredShape[] subpaths = MeasuredShape.getSubpaths(shape, 3.0f);
// GeneralPath gp = new GeneralPath();
// subpaths[0].writeShape(new GeneralPathWriter(gp));
// PathIterator fpi = gp.getPathIterator(null);
boolean brushStrokePrepared = false;
float[] coords = new float[2];
int subPathIndex = -1;
while (!fpi.isDone()) {
int type = fpi.currentSegment(coords);
double x = coords[0];
double y = coords[1];
PPoint p = PPoint.lazyFromIm(x, y, view);
affectedArea.updateWith(p);
switch (type) {
case SEG_MOVETO:
// we can get here more than once if there are multiple subpaths!
subPathIndex++;
startingPoint = p;
if (!brushStrokePrepared) {
// TODO this should not be here, and it should not need
// a point argument, but it is here because some hacks
// in the clone and smudge tools need that point
prepareProgrammaticBrushStroke(dr, p);
brushStrokePrepared = true;
}
if (subPathIndex != 0) {
brush.finishBrushStroke();
}
brush.startAt(p);
break;
case SEG_LINETO:
brush.continueTo(p);
break;
case SEG_CLOSE:
brush.continueTo(startingPoint);
break;
default:
throw new IllegalArgumentException("type = " + type);
}
fpi.next();
}
}
/**
* Convert AWT shape to image map coordinates.
*
* @param shape
* @return
*/
private String shape2polyCoords( Shape shape )
{
if ( shape == null )
{
return null;
}
ArrayList<Double> al = new ArrayList<Double>( );
FlatteningPathIterator pitr = new FlatteningPathIterator( shape.getPathIterator( null ),
1 );
double[] data = new double[6];
while ( !pitr.isDone( ) )
{
int type = pitr.currentSegment( data );
switch ( type )
{
case PathIterator.SEG_MOVETO :
al.add( new Double( data[0] ) );
al.add( new Double( data[1] ) );
break;
case PathIterator.SEG_LINETO :
al.add( new Double( data[0] ) );
al.add( new Double( data[1] ) );
break;
case PathIterator.SEG_QUADTO :
al.add( new Double( data[0] ) );
al.add( new Double( data[1] ) );
al.add( new Double( data[2] ) );
al.add( new Double( data[3] ) );
break;
case PathIterator.SEG_CUBICTO :
al.add( new Double( data[0] ) );
al.add( new Double( data[1] ) );
al.add( new Double( data[2] ) );
al.add( new Double( data[3] ) );
al.add( new Double( data[4] ) );
al.add( new Double( data[5] ) );
break;
case PathIterator.SEG_CLOSE :
break;
}
pitr.next( );
}
if ( al.size( ) == 0 )
{
return null;
}
StringBuffer sb = new StringBuffer( );
for ( int i = 0; i < al.size( ); i++ )
{
Double db = al.get( i );
if ( i > 0 )
{
sb.append( "," ); //$NON-NLS-1$
}
sb.append( (int) translateCoor( db.doubleValue( ) ) );
}
return sb.toString( );
}
private int[] shape2polyCoords( Shape shape )
{
if ( shape == null )
{
return null;
}
ArrayList<Integer> al = new ArrayList<Integer>( );
FlatteningPathIterator pitr = new FlatteningPathIterator( shape.getPathIterator( null ),
1 );
double[] data = new double[6];
while ( !pitr.isDone( ) )
{
int type = pitr.currentSegment( data );
switch ( type )
{
case PathIterator.SEG_MOVETO :
al.add( (int) data[0] );
al.add( (int) data[1] );
break;
case PathIterator.SEG_LINETO :
al.add( (int) data[0] );
al.add( (int) data[1] );
break;
case PathIterator.SEG_QUADTO :
al.add( (int) data[0] );
al.add( (int) data[1] );
al.add( (int) data[2] );
al.add( (int) data[3] );
break;
case PathIterator.SEG_CUBICTO :
al.add( (int) data[0] );
al.add( (int) data[1] );
al.add( (int) data[2] );
al.add( (int) data[3] );
al.add( (int) data[4] );
al.add( (int) data[5] );
break;
case PathIterator.SEG_CLOSE :
break;
}
pitr.next( );
}
if ( al.size( ) == 0 )
{
return null;
}
int[] coords = new int[al.size( )];
for ( int i = 0; i < al.size( ); i++ )
{
coords[i] = al.get( i );
}
return coords;
}
@Override
public Shape createStrokedShape ( Shape shape )
{
final GeneralPath result = new GeneralPath ();
shape = new BasicStroke ( 10 ).createStrokedShape ( shape );
final PathIterator it = new FlatteningPathIterator ( shape.getPathIterator ( null ), FLATNESS );
final float[] points = new float[ 6 ];
float moveX = 0;
float moveY = 0;
float lastX = 0;
float lastY = 0;
float thisX;
float thisY;
int type;
float next = 0;
while ( !it.isDone () )
{
type = it.currentSegment ( points );
switch ( type )
{
case PathIterator.SEG_MOVETO:
moveX = lastX = randomize ( points[ 0 ] );
moveY = lastY = randomize ( points[ 1 ] );
result.moveTo ( moveX, moveY );
next = 0;
break;
case PathIterator.SEG_CLOSE:
points[ 0 ] = moveX;
points[ 1 ] = moveY;
// Fall into....
case PathIterator.SEG_LINETO:
thisX = randomize ( points[ 0 ] );
thisY = randomize ( points[ 1 ] );
final float dx = thisX - lastX;
final float dy = thisY - lastY;
final float distance = ( float ) Math.sqrt ( dx * dx + dy * dy );
if ( distance >= next )
{
final float r = 1.0f / distance;
while ( distance >= next )
{
final float x = lastX + next * dx * r;
final float y = lastY + next * dy * r;
result.lineTo ( randomize ( x ), randomize ( y ) );
next += detail;
}
}
next -= distance;
lastX = thisX;
lastY = thisY;
break;
}
it.next ();
}
return result;
}
@Override
public Shape createStrokedShape ( final Shape shape )
{
final GeneralPath result = new GeneralPath ();
final PathIterator it = new FlatteningPathIterator ( shape.getPathIterator ( null ), FLATNESS );
final float[] points = new float[ 6 ];
float moveX = 0;
float moveY = 0;
float lastX = 0;
float lastY = 0;
float thisX;
float thisY;
int type;
float next = 0;
int phase = 0;
while ( !it.isDone () )
{
type = it.currentSegment ( points );
switch ( type )
{
case PathIterator.SEG_MOVETO:
moveX = lastX = points[ 0 ];
moveY = lastY = points[ 1 ];
result.moveTo ( moveX, moveY );
next = wavelength / 2;
break;
case PathIterator.SEG_CLOSE:
points[ 0 ] = moveX;
points[ 1 ] = moveY;
// Fall into....
case PathIterator.SEG_LINETO:
thisX = points[ 0 ];
thisY = points[ 1 ];
final float dx = thisX - lastX;
final float dy = thisY - lastY;
final float distance = ( float ) Math.sqrt ( dx * dx + dy * dy );
if ( distance >= next )
{
final float r = 1.0f / distance;
while ( distance >= next )
{
final float x = lastX + next * dx * r;
final float y = lastY + next * dy * r;
if ( ( phase & 1 ) == 0 )
{
result.lineTo ( x + amplitude * dy * r, y - amplitude * dx * r );
}
else
{
result.lineTo ( x - amplitude * dy * r, y + amplitude * dx * r );
}
next += wavelength;
phase++;
}
}
next -= distance;
lastX = thisX;
lastY = thisY;
if ( type == PathIterator.SEG_CLOSE )
{
result.closePath ();
}
break;
}
it.next ();
}
return stroke.createStrokedShape ( result );
}
public void arcTo(GeoPoint pivot, double widthMeters, double heightMeters, double leftAzimuthDegrees,
double rightAzimuthDegrees) {
Path2D newPath = new Path2D.Double();
Arc2D arc;
if (leftAzimuthDegrees > rightAzimuthDegrees) {
arc = new Arc2D.Double(-widthMeters / 2, -heightMeters / 2, widthMeters, heightMeters,
leftAzimuthDegrees - 90, Math.abs((360 - leftAzimuthDegrees) + rightAzimuthDegrees), Arc2D.OPEN);
} else {
arc = new Arc2D.Double(-widthMeters / 2, -heightMeters / 2, widthMeters, heightMeters,
leftAzimuthDegrees - 90, Math.abs(leftAzimuthDegrees - rightAzimuthDegrees), Arc2D.OPEN);
}
GeoPoint point = null;
if (pivot != null) {
PathIterator it = new FlatteningPathIterator(arc.getPathIterator(null), flatnessDistanceMeters, limit);
while (!it.isDone()) {
// Add a point to the list for each segment flattened from the curve
double[] strokePoints = new double[6];
int type = it.currentSegment(strokePoints);
double x = strokePoints[0];
double y = strokePoints[1];
double azimuth = Angle.toDegrees(Math.atan2(x, y));
GlobalCoordinates coord = new GlobalCoordinates(pivot.getLatitude(), pivot.getLongitude());
GlobalCoordinates c = geoCalc.calculateEndingGlobalCoordinates(REFERENCE_ELLIPSOID, coord, azimuth,
new Point2D.Double().distance(x, y));
switch (type) {
case PathIterator.SEG_MOVETO:
newPath.moveTo(c.getLongitude(), c.getLatitude());
GeoPoint startPoint = new GeoPoint(c.getLongitude(), c.getLatitude());
if (toPoints.size() > 0 && !startPoint.equals(toPoints.get(toPoints.size() - 1))) {
lineTo(startPoint);
}
break;
case PathIterator.SEG_LINETO:
newPath.lineTo(c.getLongitude(), c.getLatitude());
point = new GeoPoint(c.getLongitude(), c.getLatitude());
break;
}
it.next();
}
}
path.append(newPath, true);
toPoints.add(point);
}
/**
* @see java.awt.Stroke#createStrokedShape(java.awt.Shape)
*/
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;
float next = 0;
int phase = 0;
while (!it.isDone()) {
type = it.currentSegment(points);
switch (type) {
case PathIterator.SEG_MOVETO:
moveX = lastX = points[0];
moveY = lastY = points[1];
result.moveTo(moveX, moveY);
next = wavelength / 2;
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;
while (distance >= next) {
float x = lastX + next * dx * r;
float y = lastY + next * dy * r;
if ((phase & 1) == 0)
result.lineTo(x + amplitude * dy * r, y - amplitude * dx * r);
else
result.lineTo(x - amplitude * dy * r, y + amplitude * dx * r);
next += wavelength;
phase++;
}
}
next -= distance;
lastX = thisX;
lastY = thisY;
if (type == PathIterator.SEG_CLOSE) result.closePath();
break;
}
it.next();
}
return new BasicStroke(getWidth(), BasicStroke.CAP_SQUARE, getJoin()).createStrokedShape(result);
}
/**
* @see java.awt.Stroke#createStrokedShape(java.awt.Shape)
*/
public Shape createStrokedShape (Shape shape) {
GeneralPath result = new GeneralPath();
shape = new BasicStroke(getWidth(), BasicStroke.CAP_SQUARE, getJoin()).createStrokedShape(shape);
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;
float next = 0;
while (!it.isDone()) {
type = it.currentSegment(points);
switch (type) {
case PathIterator.SEG_MOVETO:
moveX = lastX = randomize(points[0]);
moveY = lastY = randomize(points[1]);
result.moveTo(moveX, moveY);
next = 0;
break;
case PathIterator.SEG_CLOSE:
points[0] = moveX;
points[1] = moveY;
// Fall into....
case PathIterator.SEG_LINETO:
thisX = randomize(points[0]);
thisY = randomize(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;
while (distance >= next) {
float x = lastX + next * dx * r;
float y = lastY + next * dy * r;
result.lineTo(randomize(x), randomize(y));
next += detail;
}
}
next -= distance;
lastX = thisX;
lastY = thisY;
break;
}
it.next();
}
return result;
}
/**
* Creates a <code>PathIterator</code> for the flattened outline of this
* <code>AreaX</code> object. Only uncurved path segments represented by the
* SEG_MOVETO, SEG_LINETO, and SEG_CLOSE point types are returned by the
* iterator. This <code>AreaX</code> object is unchanged.
*
* @param at
* an optional <code>AffineTransform</code> to be applied to the
* coordinates as they are returned in the iteration, or
* <code>null</code> if untransformed coordinates are desired
* @param flatness
* the maximum amount that the control points for a given curve
* can vary from colinear before a subdivided curve is replaced
* by a straight line connecting the end points
* @return the <code>PathIterator</code> object that returns the geometry of
* the outline of this <code>AreaX</code>, one segment at a time.
*/
public synchronized PathIterator getPathIterator(AffineTransform at,
double flatness) {
return new FlatteningPathIterator(getPathIterator(at), flatness);
}