Как обрезать Path2D?

Есть ли способ привязать Path2D к области/другому экземпляру path2D?

Простой пример (я ищу что-то, что будет работать в общем случае, когда пути могут включать в себя квадраты или кубики и могут быть или не быть единственными):

У меня есть отрезок (0,10) -> (30,10), который я хотел бы обрезать внутри треугольника (10,0), (20,20), (20,0), в идеале получая отрезок (15 ,10) -> (20,10)

Я могу преобразовать Path2D в область, используя «новую область (форму);» а затем обрезать, используя «Area.intersect(area)», но это вернет пустую область, если путь не закрыт.

Я могу обрезать область рисования, используя «Graphics2D.clip(Shape)», но я хочу иметь возвращенную форму (есть случаи, когда я хочу выполнить дальнейшие операции перед фактическим рендерингом)

Изучив документацию API, я не могу найти способ сделать это напрямую. Я что-то упускаю?


person tofarr    schedule 16.02.2011    source источник


Ответы (1)


Причина, по которой вы не можете обрезать контур с помощью области, заключается в том, что объект Path2D имеет нулевую площадь. Ширина пути не определена. Класс Area предназначен исключительно для использования с объектами, имеющими площадь.

Вы можете обрезать рисунок, потому что вы определили ширину штриха, которая используется для определения области контура.

Итак, если вы хотите обрезать путь, вам нужно создать обведенную фигуру из пути, используя Stroke.createStrokedShape(Shape)

Вот пример:

public static void main(String[] args) throws IOException {

    String imgFormat = "PNG";

    Path2D path = new Path2D.Double();
    BasicStroke pathStroke = 
        new BasicStroke( 2 );


    // Create the path to be clipped:       
    int pathPoints[] = { 0, 10, 30, 10 };
    path.moveTo( pathPoints[ 0 ], pathPoints[1] );
    for( int i = 2; i < pathPoints.length; i+=2 ) {
        path.lineTo( pathPoints[ i ], pathPoints[ i+1 ] );
    }
    // Create the shape representing the clip area
    Polygon clipShape = new Polygon();
    int triPoints[] = { 10, 0, 20, 20, 20, 0 };
    for( int i = 0; i < triPoints.length; i+=2 ) {
        clipShape.addPoint( triPoints[i], triPoints[i+1] );
    }
    // Create the path with area using the stroke
    Shape clippedPath = pathStroke.createStrokedShape( path );

    // Apply a scale so the image is easier to see
    int scale = 10;
    AffineTransform at = AffineTransform.getScaleInstance( scale, scale );
    Shape sPath = at.createTransformedShape( path );
    Shape sClip = at.createTransformedShape( clipShape );

    // Create the Area shape that represents the path that is clipped by the clipShape
    Area clipArea = new Area( sClip );
    clipArea.intersect( new Area( at.createTransformedShape( clippedPath ) ) );


    int bbox = 10;
    Rectangle rect = sPath.getBounds();
    rect.add( sClip.getBounds() );
    // Expand the drawing area      
    rect.width += bbox;
    rect.height += bbox;
    rect.x -= bbox/2;
    rect.y -= bbox/2;
    BufferedImage img = new BufferedImage( rect.width, rect.height, BufferedImage.TYPE_INT_ARGB  );
    Graphics2D g2 = img.createGraphics();

    g2.setStroke( pathStroke );
    g2.setColor( Color.black );
    g2.draw( sPath );

    g2.setColor( Color.red );
    g2.draw( sClip );

    g2.setColor( Color.green );
    g2.draw( clipArea );

    g2.finalize();

    File img1 = new File( "/tmp/img1.png" );
    ImageIO.write( img, imgFormat, img1 );
}
person James    schedule 23.02.2011
comment
Спасибо за ответ. В некоторых случаях сначала преобразование линий в области с помощью обводки будет работать нормально, хотя у меня было несколько случаев, когда я писал некоторый код пользовательской геометрии. - person tofarr; 28.02.2011