# Polygonsize durch das umliegende Reckteck verändern inJava2D



## Diablo68 (8. Okt 2007)

Hallo,

erstmal sorry an die Homepage Admins, dass ich den gleichen Inhalt zum zweiten Mal poste. Leider war es beim ersten Versuch in der falschen Rubrik gelandet, auf die ich wahrscheinlich deswegen kein Feedback bekommen habe.


Ich habe ein Tool geschrieben, mit der man mit Hilfe der Maus Polygone erstellen und in einem Vector abspeichern kann. Wenn man auf das jeweilige Polygon klickt, erscheint ein Reckteck um das Polygon herum. Ich möchte, dass sich das Polygon an die Rechteckgröße anpasst, wenn ich es vertikal, horizontal oder auch diagonal ändere. Das Rechteck kann man schon mit der Maus in beliebiger Richtung ändern, nur das Polygon bleibt statisch. 

Wie kann ich vorgehen ?

Gruss

Diablo


----------



## Evil-Devil (8. Okt 2007)

Wir wär's wenn du einfach ausrechnest um wieviel sich die Größe des Rechteckes verändert hat und diese Änderung entsprechend auf dein Polygon überträgst?


----------



## diablo68 (8. Okt 2007)

Hi Evil, 

danke für den Feedback..

Mit dem u.a Code funktioniert es :


```
// Linke Seite tranformieren
else if (aendereMinX && e.isMetaDown() == false) {	
int abs = zF.polyRect.x - (last_x + e.getX());
				
				zF.polyRect.setRect(last_x + e.getX(), zF.polyRect.y, 
						zF.polyRect.width + abs, zF.polyRect.height);
								
				for (int i = 0; i < p.npoints; i++) {
					int x = p.xpoints[i];
					boundsMaxX = Math.max(boundsMaxX, x);
					if (p.xpoints[i] < boundsMaxX) {
						p.xpoints[i] -= abs;
					}
				}
			}
```


----------



## Guest (8. Okt 2007)

diablo68 hat gesagt.:
			
		

> Hi Evil,
> 
> danke für den Feedback..
> 
> ...


----------



## Marco13 (8. Okt 2007)

Wie Evil-Devil es schon angedeutet hat.


```
Rectanlge oldRect = Rechteck VOR der Größenänderung
Rectanlge newRect = Rechteck NACH der Größenänderung

for (alle Punkte p des Polygons)
{
    float relX = (float)(p.x - oldRect.x) / oldRect.width;
    float relY = (float)(p.y - oldRect.y) / oldRect.height;

    p.x = (int)(newRect.x + relX * newRect.width);
    p.y = (int)(newRect.y + relY * newRect.height);
}
```

EDIT: Ginge auch effizienter, aber so ist es vmlt. nachvollziehbarer...


----------



## Guest (8. Okt 2007)

Hallo nochmals,

also habe mein Code habe ich folgendermaßen geändert :


```
// Linke Seite tranformieren
else if (aendereMinX && e.isMetaDown() == false) {	
			
  int abs = zF.polyRect.x - (last_x + e.getX());
				
  zF.polyRect.setRect(last_x + e.getX(), zF.polyRect.y, 
	zF.polyRect.width + abs, zF.polyRect.height);
				
   for (int i = 0; i < p.npoints; i++) {
	float relX = (float)(p.xpoints[i] - old.x) / old.width;			    
	p.xpoints[i] = (int)((zF.polyRect.x + relX * zF.polyRect.width));
   } 
}
```

Also, das mit dem Skalieren des Polygons funktioniert wunderbar, aber es passt sich nicht an das Rechteck an.
Skaliert sehr schnell, dass er nicht mehr auf dem Monitor zusehen ist. Scheint an dem Skalierungswert zulegen. 

Wo kann ich es ändern ?

Gruss

Celal


----------



## Marco13 (8. Okt 2007)

Lass mich raten: Das ganze "schnurrt" irgendwie zusammen, wenn man die Maus bewegt!? Vermutlich gibt es noch ein Problem, weil ja immer auf int zurückgecastet werden muss - es gehen dabei während der Mausbewegung ständig Informationen verloren. Du solltest evtl. das ursprüngliche Polygon speichern, und immer auf den gleichen Anfangsdaten rechnen (bis MouseReleased kommt). Hab' da gerade mal was zum Testen hingehackt:

```
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class PolygonPanel extends JPanel implements MouseListener, MouseMotionListener
{
    private Polygon polygon;
    private Rectangle rectangle;

    private Polygon editingPolygon;
    private Rectangle editingRectangle;

    public PolygonPanel()
    {
        int xpoints[] = new int[] { 200, 300, 200, 200, 100 };
        int ypoints[] = new int[] { 300, 200, 100, 200, 200 };
        polygon = new Polygon(xpoints, ypoints, xpoints.length);

        rectangle = new Rectangle(100,100,200,200);

        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public void paintComponent(Graphics gr)
    {
        Graphics2D g = (Graphics2D)gr;

        g.setColor(Color.WHITE);
        g.fillRect(0,0,getWidth(),getHeight());


        g.setColor(Color.BLACK);
        g.fill(polygon);
        g.draw(rectangle);

        g.setColor(Color.RED);
        if (editingRectangle != null) g.draw(editingRectangle);
        if (editingPolygon != null) g.draw(editingPolygon);

    }

    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}
    public void mousePressed(MouseEvent e)
    {
        // Neues Polygon für die Dauer des Editierens erstellen
        int xp[] = polygon.xpoints.clone();
        int yp[] = polygon.ypoints.clone();
        editingPolygon = new Polygon(xp, yp, polygon.xpoints.length);
        editingRectangle = (Rectangle)rectangle.clone();
        repaint();
    }

    public void mouseReleased(MouseEvent e)
    {
        // Daten aus dem editier-Polygon in das "richtige" Polygon kopieren
        // (hack: Eigentlich nicht klonen, sondern einfach rüberkopieren!)
        int xp[] = editingPolygon.xpoints.clone();
        int yp[] = editingPolygon.ypoints.clone();
        polygon = new Polygon(xp, yp, editingPolygon.xpoints.length);
        rectangle = (Rectangle)editingRectangle.clone();
        editingPolygon = null;
        editingRectangle = null;
        repaint();
    }
    public void mouseClicked(MouseEvent e){}

    public void mouseMoved(MouseEvent e){}
    public void mouseDragged(MouseEvent e)
    {
        Rectangle oldRect = rectangle;
        Rectangle newRect = editingRectangle;
        editingRectangle.width = e.getX() - editingRectangle.x;
        editingRectangle.height = e.getY() - editingRectangle.y;

        // Berechne die Koordinaten des NEUEN Polygons auf
        // Basis der Informationen aus dem ALTEN Polygon
        // und des alten+neuen Rectangles
        for (int i=0; i<editingPolygon.xpoints.length; i++)
        {
            Point p = new Point(polygon.xpoints[i], polygon.ypoints[i]);

            float relX = (float)(p.x - oldRect.x) / oldRect.width;
            float relY = (float)(p.y - oldRect.y) / oldRect.height;

            p.x = (int)(newRect.x + relX * newRect.width);
            p.y = (int)(newRect.y + relY * newRect.height);

            editingPolygon.xpoints[i] = p.x;
            editingPolygon.ypoints[i] = p.y;
        }
        repaint();
    }
}


class RectangleTest extends JFrame
{
    public static void main(String args[])
    {
        new RectangleTest();
    }

    public RectangleTest()
    {
        setSize(400, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().add(new PolygonPanel());
        setVisible(true);
    }
}
```
Genaugenommen ist das aber auch noch suboptimal: Wenn man "oft" die Größe ändert, macht sich auch der Effekt bemerkbar, dass Informationen durch das casten nach 'int' verlorengehen, und das Polygon "verzerrt" wird. Besser wäre es für solche Zwecke, das Polygon als eigene Klasse auf Basis von float-Daten zu speichern, und/oder sich IMMER das Originalpolygon aufzuheben, und den aktuellen Zustand (d.h. das skalierte Polgon) NUR zu _zeichnen_. Im Moment kannst du es nämlich drehen und wenden, wie du willst: Sobald das Polygon einmal auf "Breite 0" zusammengeschoben wurde, kriegt man es nie mehr auseinander......


----------

