Как создать объект Area с помощью PathIterator?

Здесь я явно упускаю важную концепцию. Я написал код, использующий события мыши, чтобы нарисовать границу (многоугольник) на существующем BufferedImage. Вот соответствующий раздел:

public void paintComponent(Graphics g) 
{
    super.paintComponent(g);  //Paint parent's background

    //G3 displays the BufferedImage "Drawing" with each paint
    Graphics2D G3 = (Graphics2D)g;
    G3.drawImage(this.Drawing, 0, 0, null);
    G3.dispose();
} 

public void updateDrawing()
{               
    int x0, y0, x1, y1; // Vertex coordinates
    Line2D.Float seg;
    // grafix is painting the mouse drawing to the BufferedImage "Drawing"     
    if (this.pts.size() > 0)
    {                   
        for(int ip = 0; ip < pts.size(); ip++)
        {
            x0 = (int)this.pts.get(ip).x;
            y0 = (int)this.pts.get(ip).y;
            this.grafix.drawRect(x0 - this.sqw/2, y0 - this.sqh/2, + this.sqw, this.sqh);
            if (ip > 0)
            {
                x1 = (int)this.pts.get(ip-1).x;
                y1 = (int)this.pts.get(ip-1).y; 
                this.grafix.drawLine(x1, y1, x0, y0);
                seg = new Line2D.Float(x1, y1, x0, y0);
                this.segments.add(seg);
            }
        }
    }
    repaint();
}

Следующие две процедуры вызываются событиями мыши: щелчок левой кнопкой мыши приводит к следующей точке, а щелчок правой кнопкой мыши закрывает область.

public void getNextPoint(Point2D p)
{
    this.isDrawing = true;
    Point2D.Float next = new Point2D.Float();
    next.x = (float) p.getX();
    next.y = (float) p.getY();
    this.pts.add(next);
    updateDrawing();
}

public void closeBoundary()
{
    //Connects the last point to the first point to close the loop
    Point2D.Float next = new Point2D.Float(this.pts.get(0).x, this.pts.get(0).y);
    this.pts.add(next);
    this.isDrawing = false;
    updateDrawing();
}

Все работает нормально, и я могу сохранить изображение с моим рисунком: изображение с рисунком Список вершин (точек) и линейных сегментов (сегментов) - это все, что описывает область / форму / многоугольник. Я хочу извлечь из исходного изображения только ту область, которая находится внутри границы. То есть я планирую создать новое изображение BufferedImage, перемещаясь по всем пикселям, проверяя, попадают ли они в фигуру, и сохраняю их, если они попадают. Итак, я хочу создать ОБЛАСТЬ из точек и сегментов, которые я собрал при рисовании фигуры. Все говорит: создайте переменную AREA и "getPathIterator". Но на какой форме? Моя переменная AREA будет пустой. Как итератор пути получает доступ к точкам в моем списке?

Я просмотрел всю литературу и этот сайт. Я что-то упускаю.

Сохраните все свои точки во время рисования, затем создайте Polygon из точек. При необходимости создайте из него Area (new Area(polygon)). Но вы также можете создать PathIterator прямо из Polygon. Хотя трудно сказать точно, почему вы этого хотите ... Может быть, вам поможет какой-нибудь псевдокод того, что вы пытаетесь сделать.

Harald K 10.05.2018 07:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
180
1

Ответы 1

Спасибо haraldK за ваше предложение. Еще до того, как я увидел ваш пост, я пришел к аналогичному выводу: Используя Arraylist вершин из операции рисования, я заполнил объект «Path2D.Float» под названием «contour», пройдя цикл по списку точек, который был создан во время операции «рисования». Используя этот «контурный» объект, я создал объект Area, называемый «интерферограммой». Чтобы проверить свою работу, я создал еще один PathIterator, «PI», из Area и разложил Area, «интерферограмму» на «сегменты», отправив результаты на консоль. Я показываю код ниже:

private void mnuitmKeepInsideActionPerformed(java.awt.event.ActionEvent evt)                                                 
{                                                     
    // Keeps the inner area of interest
    // Vertices is the "pts" list from Class MouseDrawing (mask)
    // It is already a closed path
    ArrayList<Point2D.Float> vertices = 
            new ArrayList<>(this.mask.getVertices()); 
    this.contour = new Path2D.Float(Path2D.WIND_NON_ZERO);

    // Read the vertices into the Path2D variable "contour"
    this.contour.moveTo((float)vertices.get(0).getX(), 
        (float)vertices.get(0).getY()); //Starting location

    for(int ivertex = 1; ivertex < vertices.size(); ivertex++)
    {
        this.contour.lineTo((float)vertices.get(ivertex).getX(), 
            (float)vertices.get(ivertex).getY());                           
    }      
    this.interferogram = new Area(this.contour);        
    PathIterator PI = this.interferogram.getPathIterator(null);

    //Test print out the segment types and vertices for debug
    float[] p = new float[6];
    int icount = 0;
    while( !PI.isDone())
    {
        int type = PI.currentSegment(p);
        System.out.print(icount);
        System.out.print(" Type " + type);
        System.out.print(" X " + p[0]);
        System.out.println(" Y " + p[1]);
        icount++;
        PI.next();
    }

    BufferedImage masked = Mask(this.image_out, this.interferogram);
    // Write image to file for debug
    String dir;
    dir = System.getProperty("user.dir");
    dir = dir + "\\00masked.png";
    writeImage(masked, dir, "PNG");

}                                                

Затем я применил маску к изображению, проверяя каждый пиксель на предмет включения в область, используя приведенный ниже код:

public BufferedImage Mask(BufferedImage BIM, Area area)
{
    /** Loop through the pixels in the image and test each one for inclusion
    *   within the area.
    *   Change the colors of those outside
    **/

    Point2D p = new Point2D.Double(0,0);
    // rgb should be white
    int rgb = (255 << 24);
    for (int row = 0; row < BIM.getWidth(); row++)
    {
        for (int col = 0; col < BIM.getHeight(); col++)
        {
            p.setLocation(col, row);
            if (!area.contains(p))
            {
                BIM.setRGB(col, row, rgb);
            }
        }
    }
    return BIM;
}
public static BufferedImage deepCopy(BufferedImage B2M) 
{
    ColorModel cm = B2M.getColorModel();
    boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
    WritableRaster raster = B2M.copyData(B2M.getRaster()
            .createCompatibleWritableRaster());
    return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}

Это сработало прекрасно (я был удивлен!), За исключением одной небольшой детали: линии области появлялись снаружи замаскированного изображения. Чтобы исправить это, я скопировал исходное изображение (с измененным размером) перед операцией рисования. Большое спасибо user1050755 (ноябрь 2014 г.) за подпрограмму deepCopy, которую я нашел на этом сайте. Применение моей маски к скопированному изображению привело к тому, что часть исходного изображения, которую я хотел, была без линий маски. Результат показан на прилагаемой картинке. Я в восторге! замаскированное изображение

Другие вопросы по теме