Προς το περιεχόμενο

Πρόβλημα σε Java (επανασχεδίαση πολυγώνων)


SpirosG86

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπέρα :-)

 

Προσπαθώ να φτιάξω μια εφαρμογή σε Java, όπου μέσα από ένα παράθυρο σχεδίασης με ένα προσχεδιασμένο από την εφαρμογή "κουτάκι" θα μπορεί να γίνει αποκοπή των πολυγώνων που σχεδιάζει ο χρήστης με το πάτημα ενός κουμπιού "Cut" και να μένει μόνο ότι υπάρχει μέσα στο κουτάκι.

 

Πρόκειται στην ουσία για την υλοποίηση του αλγορίθμου Sutherland - Hodgeman, για όσους γνωρίζουν.

 

Αυτό που θέλω να κάνω τώρα είναι να αποκόπτω ότι βρίσκεται δεξιά από την δεξιά πλευρά του παραθύρου αποκοπής ( ότι έχει συντεταγμένες Χ > rightEdgeX, όπου rightEdgeX = το Χ της δεξιάς πλευράς του παραθύρου αποκοπής).

 

Ωστόσο δεν μπορώ να καταλάβω τί λάθος υπάρχει στον κώδικα, και θα ήθελα την βοήθεια σας!

 

Παραθέτω το κομμάτι του κώδικα του JFrame που καλεί την κλάση putClippedPolygon(η οποία εκτελεί τη διαδικασία αποκοπής:

 

>
...
	    if (source == Cut ){
	    	new putClippedPolygon();
	    	cut = true;
	    	Display.pointCt = putClippedPolygon.ClippedPolygonX.length;
	    	new Display();
	    	cut = false;
	    }
...

 

Έτσι, όταν πατάμε το κουμπί Cut εκτελείται η κλάση putClippedPolygon().

Η κλάση putClippedPolygon λειτουργεί ως εξής: αποθηκεύει σε 2 arrays τις συντεταγμένες Χ και Υ των σημείων του πολυγώνου και ελέγχει για το καθένα αν βρίσκεται αριστερά ή δεξιά από το rightEdgeX, και αποθηκεύει τα σημεία που βρίσκονται αριστερά (σε γενικές γραμμές), ενώ προσαρμόζει στο όριο τα σημεία που βρίσκονται δεξιά.

Τις καινούριες συντεταγμένες(του αποκοπούντος :mrgreen: πολυγώνου) τις αποθηκεύει σε 2 νέες Arrays X και Y (ClippedPolygonX/Y)

 

Η κλάση putClippedPolygon παρατίθεται παρακάτω:

>


public class putClippedPolygon {

private int		rightEdgeX = Display.Xmax,
				j = 0,
				i;
private int[]	polXCoord = Display.xCoord,
                     polYCoord = Display.yCoord;

public static int[]	ClippedPolygonX;
public static int[]     ClippedPolygonY;


public putClippedPolygon()	{
      
	ClippedPolygonX = new int[1000];
	ClippedPolygonY = new int[1000];
			
	//start process
	ClippedPolygonX[0] = polXCoord[0];
	ClippedPolygonY[0] = polYCoord[0];
	j++;
	for ( i = 0; i < polXCoord.length-1; i++ ) {
		if (( polXCoord[i] <= rightEdgeX ) && ( polXCoord[i+1] <= rightEdgeX )) {
			ClippedPolygonX[j] = polXCoord[i+1];
			ClippedPolygonY[j] = polYCoord[i+1];
			j++;
		}
		else if (( polXCoord[i] <= rightEdgeX ) && ( polXCoord[i+1] > rightEdgeX )) {
			ClippedPolygonX[j] = rightEdgeX;
			//finding clipped point's Y???
			//ClippedPolygonY[j] = Line[i,i+1] cuts (Edge);
			//proswrina:
			ClippedPolygonY[j] = polYCoord[i];
			j++;
		}
		else if (( polXCoord[i] > rightEdgeX ) && ( polXCoord[i+1] > rightEdgeX )) {
			//do nothing
		}
		else if (( polXCoord[i] > rightEdgeX ) && ( polXCoord[i+1] <= rightEdgeX )) {
			ClippedPolygonX[j] = rightEdgeX;
			ClippedPolygonY[j] = polYCoord[i];
			ClippedPolygonX[j+1] = polXCoord[i+1];
			ClippedPolygonY[j+1] = polYCoord[i+1];
			j += 2;
		}
	}

}
}

 

Έπειτα, τίθεται η τιμή "true" στον boolean int cut, αντικαθίσταται ο "μετρητής" των κλικ στην οθόνη από το μήκος της Array των συντεταγμένων του καινούριου πολυγώνου και καλείται εκ νέου η κλάση Display(new Display()), η οποία είναι το παράθυρο σχεδιασμού. Η κλάση αυτή κανονικά περιμένει να κάνεις κλικ στην περιοχή σχεδίασης και να σχεδιάσεις με το ποντίκι, όμως με τη συνθήκη που περιέχεται στον κώδικά της

 

>
...
 if ( JPanels.cut == true ) {
   	  xCoord = putClippedPolygon.ClippedPolygonX;
   	  yCoord = putClippedPolygon.ClippedPolygonY;
     }
     else {
                 addMouseListener(this);
   	  	  xCoord = new int[500];
   	  	  yCoord = new int[500];
     }
...
         g.setColor(polColor);
         g.fillPolygon(xCoord, yCoord, pointCt);
   	  g.setColor(linColor);
   	  g.drawPolygon(xCoord, yCoord, pointCt);

 

και δεδομένου ότι το cut έχει πάρει την τιμή true, τα xCoord και yCoord από τα οποία δημιουργείται το πολύγωνο παίρνουν τις τιμές των αποκομένων πολυγώνων(και το pointCt έχει πάρει την τιμή του μήκους της Array του νέου πολυγώνου) και κανονικά θα έπρεπε να σχεδιάζονται αυτόματα(ή τουλάχιστον έτσι νομίζω)!

 

Αντ'αυτού δεν κάνει καμμιά επανασχεδίαση και όλα μένουν ως έχει! Δεν ξέρω αν τα σχεδιάζει αλλα δεν φαίνονται επειδή τα καλύπτει το παλιό πολύγωνο, αλλά αν δοκιμάσω το repaint() εξαφανίζονται τα πάντα!

 

Ελπίζω να έχετε καταλάβει μέχρι τώρα ότι είμαι απελπισμένος :cry: και χρειάζομαι τη βοήθειά σας! 2 βδομάδες την παλεύω αυτή την εργασία και είναι κρίμα να μην την παραδώσω τελικά....

Δημοσ.

Να σου πω την αλήθεια δεν έχω καταλάβει τι ακριβώς θέλεις να κάνεις. Μπορείς να μας δώσει ένα μικρό παράδειγμα που να μπορούμε να το κάνουμε compile και να αντιπροσωπεύει το πρόβλημα;

Δημοσ.

Το έκανα όσο πιο απλό μπόρεσα.:-)

 

Παρατήρησα ότι, αφού φτιάξω ένα πολύγωνο, όταν πατήσω το πλήκτρο Cut δεν γίνεται τίποτα, αλλά μόλις πατήσω δεξί κλικ γίνεται κάποιου είδους αποκοπή(Edit: αυτό τελικά γίνεται αν το πολυγωνο δεν έχει ολοκληρωθεί ακόμα και πατήσω το Cut), η επιθυμητή μεν, αλλά με άκυρες συντεταγμένες. Τις σωστές θα τις βρω, αυτό που με νοιάζει είναι στο "demo" που παραθέτω να δημιουργείται το αποκομμένο πολύγωνο με το πάτημα του κουμπιού Cut (όχι να πρέπει να πατήσω και δεξί κλικ), καθώς και να εξαφανίζεται το προηγούμενο.

Αν το κάνω αυτό έχω λύσει το τρέχον πρόβλημα.

 

Παραθέτω το "demo":

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

public class JPanels extends JFrame implements ActionListener{

public static boolean cut = false;	
private JButton Cut = new JButton("Cut");

   JPanel 			controlArea = new JPanel(new GridLayout(5, 1));
   
 public JPanels() {
  
super("Line and Polygon Design with Clipping Box");

Cut.addActionListener(this);
   controlArea.add(Cut);
   Container content = getContentPane();
   content.setBackground(Color.lightGray);
   content.add(controlArea, BorderLayout.EAST);
   content.add(new Display(), BorderLayout.WEST);
   pack();
   setVisible(true);  
 	}
   
public void actionPerformed(ActionEvent evt) {
	 Object source = evt.getSource();
	    if (source == Cut ){
	    	new putClippedPolygon();
	    	cut = true;
	    	new Display();
	    	cut = false;
	    }
}

public static void main(String[] args) {
    new JPanels();
  }
}

 

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


  public class Display extends JPanel implements MouseListener {
       
/* Variables for implementing polygon input. */
   
  public static int[] xCoord, yCoord;  // Arrays containing the points of 
                                 //   the polygon.  Up to 500 points 
                                 //   are allowed.
  
  public static int pointCt;  // The number of points that have been input.
  public static int Xmin, Xmax, Ymin, Ymax; //The clipping box's coordinates.
  
  public Display() {
     setBackground(Color.white);
     
     if (JPanels.cut == true) {
   	  pointCt = putClippedPolygon.ClippedPolygonX.length;
   	  xCoord = putClippedPolygon.ClippedPolygonX;
   	  yCoord = putClippedPolygon.ClippedPolygonY;
     }
     else if (JPanels.cut == false) {
         	  addMouseListener(this);
   	  	  xCoord = new int[500];
   	  	  yCoord = new int[500];
     }
     setPreferredSize(new Dimension(600,0));
  }


  public void paintComponent(Graphics g) {

        // The paintComponent() routine just draws a 1-pixel black 
        // border around the panel.  Polygons drawn on the panel
        // are not permanent.

     super.paintComponent(g); // Fills with background color.
     setBackground(Color.white);
  	  g.setColor(Color.black);
     g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
     g.drawRect(1, 1, getWidth() - 3, getHeight() - 3);
     Xmin = getWidth()/2 - 100;
     Xmax = getWidth()/2 + 100;
     Ymin = getHeight()/2 - 100;
     Ymax = getHeight()/2 + 100;
     //Drawing clipping box
     g.drawRect(Xmin, Ymin, 200, 200);
     
     //Checking whether to display polygon
     if (JPanels.cut == true) {
   	  putPolygon();
     }
     new Display();

  }


  private void putLine(int x1, int y1, int x2, int y2) {
      Graphics g = getGraphics();
  	   g.setColor(Color.black);
      g.drawLine(x1,y1,x2,y2);
      g.dispose();
  }


  private void putPolygon() {
   if (pointCt < 2) {
         return;
         }
      Graphics g = getGraphics();
      if (pointCt == 2) {
   	  g.setColor(Color.black);
         g.drawLine(xCoord[0], yCoord[0], xCoord[1], yCoord[1]);
         }
      else {
         g.setColor(Color.red);
         g.fillPolygon(xCoord, yCoord, pointCt);
   	  g.setColor(Color.black);
   	  g.drawPolygon(xCoord, yCoord, pointCt);
      }
      g.dispose();
      new Display();
  }
  
  public void mousePressed(MouseEvent evt) {
        // Process a user mouse-click.
     if ( pointCt > 0 && (Math.abs(xCoord[0] - evt.getX()) <= 2)
                         && (Math.abs(yCoord[0] - evt.getY()) <= 2)) {
            // User has clicked near the starting point.
            // Draw the polygon and reset pointCt so that the 
            // user can start a new polygon.
        putPolygon();
        pointCt = 0;
     }
     else if (evt.isMetaDown() || pointCt == 500) {
            // Draw the polygon and reset pointCt so that the 
            // user can start a new polygon.  Note that there
            // is a limit of 500 points for one polygon.
        putPolygon();
        pointCt = 0;
     }
     else {
            // Add the point where the user clicked to the list of
            // points in the polygon, and draw a line between the
            // previous point and the current point.  A line can
            // only be drawn if there are at least two points.
        xCoord[pointCt] = evt.getX();
        yCoord[pointCt] = evt.getY();
        pointCt++;
        if (pointCt >= 2) {
           putLine(xCoord[pointCt-2], yCoord[pointCt-2], 
                        xCoord[pointCt-1], yCoord[pointCt-1]); 
        }
     }

  } // end mousePressed()

  public void mouseReleased(MouseEvent evt) { }
  public void mouseClicked(MouseEvent evt) { }
  public void mouseEntered(MouseEvent evt) { }
  public void mouseExited(MouseEvent evt) { }
       
} // end class Display

 

>
public class putClippedPolygon {

//for now just right Edge		
private int		rightEdgeX = Display.Xmax,
				j = 0,
				i;
private int[]	polXCoord = Display.xCoord,
				polYCoord = Display.yCoord;

public static int[]	ClippedPolygonX;
public static int[] ClippedPolygonY;


public putClippedPolygon()	{
      
	ClippedPolygonX = new int[1000];
	ClippedPolygonY = new int[1000];
			
	//start process
	ClippedPolygonX[0] = polXCoord[0];
	ClippedPolygonY[0] = polYCoord[0];
	j++;
	for ( i = 0; i < polXCoord.length-1; i++ ) {
		if (( polXCoord[i] <= rightEdgeX ) && ( polXCoord[i+1] <= rightEdgeX )) {
			ClippedPolygonX[j] = polXCoord[i+1];
			ClippedPolygonY[j] = polYCoord[i+1];
			j++;
		}
		else if (( polXCoord[i] <= rightEdgeX ) && ( polXCoord[i+1] > rightEdgeX )) {
			ClippedPolygonX[j] = rightEdgeX;
			ClippedPolygonY[j] = polYCoord[i];
			j++;
		}
		else if (( polXCoord[i] > rightEdgeX ) && ( polXCoord[i+1] > rightEdgeX )) {
			//do nothing
		}
		else if (( polXCoord[i] > rightEdgeX ) && ( polXCoord[i+1] <= rightEdgeX )) {
			ClippedPolygonX[j] = rightEdgeX;
			ClippedPolygonY[j] = polYCoord[i];
			ClippedPolygonX[j+1] = polXCoord[i+1];
			ClippedPolygonY[j+1] = polYCoord[i+1];
			j += 2;
		}
	}

}
}

 

Κάπου στο Display, ή στο ActionPerformed του JPanels είναι το πρόβλημα...

Ευχαριστώ πολύ όποιον ασχοληθεί και βοηθήσει!:-)

Δημοσ.

Καλησπέρα και πάλι :-)

Οι μέρες παιρνούν και εγω είμαι κολλημένος στο ίδιο πρόβλημα :fear:

Ανασχεδίασα το πλάνο της εφαρμογής ωστέ να αποφύγω τα προαναφερθέντα προβλήματα, ωστόσο έχω ένα μεγάλο πρόβλημα που δεν μπορώ να το λύσω με τίποτα...

 

Όταν χρωματίζεται το πολύγωνο, προσθέτει στις γωνίες μία ακόμα με συντεταγμένες (0,0) και έχω τρελαθεί γιατι δεν μπορω να βρω με τίποτα γιατί!! Με τίποτα!!!

Ίσως "πηδάει" κάποιον δείκτη της array με αποτέλεσμα να μείνει κενός και του θέτει την τιμή (0,0) αυτόματα, ίσως ο Pointer της στοίβας προσθέτει μια επιπλέον τιμή (κενή), έχω δοκιμάσει ΤΑ ΠΑΝΤΑ, ΔΕΝ ΜΠΟΡΩ ΝΑ ΚΑΤΑΛΑΒΩ ΤΙ ΦΤΑΙΕΙ και πώς να το λύσω!!

 

Πραγματικά.. ΒΟΗΘΕΙΑ! :cry::cry::cry:

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...