Mehrdimensionales Array sortieren

Dantesa

Grünschnabel
Hallo,

Ich will ein mehrdimensionales Array der Größe [20][3] sortieren.
In diesem stehen unter data[i][0] die jeweiligen x Werte und unter data[i][1] die jeweiligen y werte!

Dies hat folgende Bewandnis:

Es werden über Opengl im Fenster Punkte definiert, die hinterher ein Polygon ergeben sollen. Die Punkte sollen so angeordnet werden, dass sich keine Linie schneidet.

Ich habe mir ausgedacht, die Punkte nach den Winkeln zu sortieren,
also ich vergleiche :
Code:
acos(data[i][0]) < acos(data[i+1][0]

Nur leider will dies nicht klappen ! :-/


Hier mein Code :


Code:
void sortieren(GLfloat p[][3]){

            for(int h=0; h<i; h++)    //i = Anzahl der Punkte in Data
                {
        
                        for (int j=h; j<i; j++)        
                        {           
            
                                if (acos(p[j][0])<acos(p[j+1][0]))            
                                { // Tauschen erforderlich
                
									GLfloat *temp;
									temp = new GLfloat[1];

                                        temp[0] = p[j][0];
										temp[1] = p[j][1];										
                                        p[j][0] = p[j+1][0];  
										p[j][1] = p[j+1][1];
										p[j+1][0] = temp[0];  
										p[j+1][1] = temp[1];
            
                                }            
        
                        }
    
                }

                
}

aufruf : sortieren(data);


Wo liegt der Fehler ?

Vielen Dank für eure Hilfe !
 
Es werden über Opengl im Fenster Punkte definiert, die hinterher ein Polygon ergeben sollen. Die Punkte sollen so angeordnet werden, dass sich keine Linie schneidet.

Ich habe mir ausgedacht, die Punkte nach den Winkeln zu sortieren,
also ich vergleiche :
Code:
acos(data[i][0]) < acos(data[i+1][0]
Mal abgesehen davon, dass diese Sortiervorschrift keinen Sinn ergibt (die reelle acos-Funktion ist nur für den Bereich [-1,1] definiert)… hier deine Fehler im Einzelnen:

  1. Zeile 9: p[j+1][0] ist undefiniert, wenn j gleich i-1 ist (Zugriff außerhalb des Arrays). Gleiches gilt für die Zugriffe in den Zeilen 17–20.
  2. Zeile 13: Wieso new GLfloat[1]? Deine Punkte bestehen doch aus 3 Komponenten. Das gibt einen Speicherzugriffsfehler in den Zeilen, 16 und 20.
  3. Zeile 22: Spätestens hier solltest du den reservierten Speicher für temp wieder freigeben, sonst hast du ein Speicherleck. Zu jedem new gehört ein delete (in diesem Fall delete[])!
  4. Schlussendlich ist das ganze kein Sortieralgorithmus. So einen musst du auch überhaupt nicht per Hand implementieren, verwende stattdessen qsort (falls du in C programmierst) oder std::sort (C++).

\edit: Hier noch eine Übersicht von Algorithmen, mit denen du dein Problem lösen könntest: http://www.geometrylab.de/RandomPolygon/index.html

Grüße,
Matthias
 
Zuletzt bearbeitet:
Du hast natürlich vollkommen recht, war unsinn :D

Hab hier nun die überarbeitete Version, alle Problem sind behoben und nun gehts in die nächste Phase, zeichnen der Bezierkurve über die per Maus definierten Kontrollpunkte !
Ich habe mehrfach alles kontrolliert, aber ich finde meinen Fehler einfach nicht !

Ich definiere zuerst den Evaluator : glMap1f
Dann das eindimensionale Punktegitter : glMapGrid1f
und dann will ich die Kurve zeichnen : glEvalMesh1

Habe auch schon überprüft, ob die richtigen Koordinaten in der draw funktion ankommen !
Alles hilft nix, der macht nur müll !


Code:
#include "stdafx.h"
# include <iostream>
# include <string >
using namespace std ;
#include <fstream>
#include <gl\glut.h>
#include <math.h>

typedef GLfloat T;
GLfloat PI = 3.1415;
GLdouble wx,wy,wz;
bool curve = true; //Zeichne Kurve
bool in = false;   // Maus auf Punk 
bool showkh = false; //Zeige Konvexe Hülle
bool showp = true;   // Zeige Punkte

struct Node {  

	T x;
	T y;
	T ax;
	T gew;
	Node * next;

};

struct List{  //Speichern der Punkte in Liste 

	Node * front,*back;
	int size;
};

Node * ind = NULL; //Zeiger auf den Knoten des ausgewählten Punktes

List q;

void initialize(List &);
void push (List &, T , T , T);


void initialize(List & q){

	q.front = q.back = NULL;
}

void push(List & q, T x , T y , T ax){

	if(!q.front) {

		q.front = q.back = new Node;
		q.back->x = x ;
		q.back->y = y ;
		q.back->ax = ax ;
		q.back->next = NULL;
		q.size = 1;
		q.back->gew = 1;

	}

	else {
		Node * temp = q.back;
		q.back = q.back->next = new Node ;
		q.back->x = x;
		q.back->y = y;
		q.back->ax = ax;
		q.back->next = NULL;
		q.back->gew = 1;
		q.size = q.size +1;


	}

}

void increase(){ //Gewicht der Kontrollpunkte erhöhen

	if(in) ind->gew++;

}  

void decrease(){	//Gewicht der Kontrollpunkte reduzieren
		
	if(in && (ind->gew > 1)) ind->gew--;

}

void new_controll_points(GLfloat ** & a) //Berechnung der gewichteten Kontrollpunkte
{
	Node *temp = q.front;
  for (int i=0; i<q.size; i++){

	  a[i][0] = temp->x * temp->gew;
	  a[i][1] = temp->y * temp->gew;
	  a[i][2] = 1 * temp->gew;
	  a[i][3] = 1 ;
	  temp = temp->next;

  }
  
}

void draw_curve(GLfloat **p) //Zeichnen der Kurve
{
   glPushMatrix();
   glColor3f(1.0, 0.0, 0.0);
   Node *temp = q.front;
  // for(int i = 0;i<q.size;i++){

	 //  	cout<<"X werte in curve = "<< i+1<<" : " <<p[i][0]<<endl;
	 //   cout<<"Y werte in curve = "<< i+1<<" : " <<p[i][1]<<endl;
		//cout<<"Gewicht = "<< i+1<<" : " <<p[i][3]<<endl;
  // }
   glMap1f(GL_MAP1_VERTEX_4, 0,1, 4, q.size, &p[0][0]);
   glMapGrid1f(40,0.0, 1.0);
   glEvalMesh1(GL_LINE, 0, 40);   // Darstellung der Kurve   
   glPopMatrix();
}




void bezier(){ //Belegung des Array der Koordinaten/Gewichte über Liste

	if(q.size > 1){
		
		GLfloat **gewp = new GLfloat*[q.size];
		Node * temp = q.front;
		GLfloat * _gewicht = new GLfloat[q.size];

		for(int i = 0;i<q.size;i++){

			_gewicht[i] = temp->gew;			
			gewp[i] = new GLfloat[4];
			temp = temp->next;
		}
		//int k=0;
		//for(Node *temp = q.front;temp;temp=temp->next){

		//	
		//	cout<<"X werte = "<< k+1<<" : " <<temp->x<<endl;
		//	cout<<"Y werte = "<< k+1<<" : " <<temp->y<<endl;
		//	cout<<"Gewicht = "<< k+1<<" : "<<temp->gew<<endl;
		//	k++;
		//}
		
		new_controll_points(gewp);

		//   for(int i = 0;i<q.size;i++){

	 //  	cout<<"X werte nach gew= "<< i+1<<" : " <<gewp[i][0]<<endl;
	 //   cout<<"Y werte nach gew= "<< i+1<<" : " <<gewp[i][1]<<endl;
		//cout<<"Gewicht = "<< i+1<<" : " <<_gewicht[i]<<endl;
  // }

		draw_curve(gewp); //Zeichnen der Bezierkurve


		delete [] *gewp ;
		delete [] gewp;
		delete temp;
		delete [] _gewicht;
	}
}



void sort(){ //Sortieren der Punkte CCW ("Bubblesort")

	Node* tmp1 = q.front;
	Node* tmp2 = q.front;

	while(tmp1 != NULL){

		while(tmp2 != NULL){

			if(tmp2->ax >= tmp1->ax){         //vertausche

				GLfloat tauschax = tmp2->ax;
                GLfloat tauschx = tmp2->x;
				GLfloat tauschy = tmp2->y;

				tmp2->ax = tmp1->ax;
				tmp1->ax = tauschax;

				tmp2->x = tmp1->x;
				tmp1->x = tauschx;

				tmp2->y = tmp1->y;
				tmp1->y = tauschy;

			}

			tmp2 = tmp2->next;

		}

		tmp2 = q.front;  //Zaehler 2 wieder reseten

		tmp1 = tmp1->next; //Zaehler 1 um 1 element weiterschalten

	}


}




void liste (void) //Zeichen der Punkte bzw konvexe Hülle (wird noch ausgelagert)
{

	Node *l = q.front ;
	glPolygonMode(GL_FRONT,GL_LINE);
        if(showp){
            glPointSize(5);

            glBegin(GL_POINTS);
            while(l){
                    glVertex3f(l->x,l->y,0);
                    l=l->next;
            }
            glEnd();
        }

	if(showkh){
		glPolygonMode(GL_BACK,GL_LINE);
		l=q.front;

		glBegin(GL_POLYGON);
		while(l){
			glVertex3f(l->x,l->y,0);
			l=l->next;
		}
		glEnd();
	}

}



//Einstellung einiger OpenGL-Zustaende
void init_opengl(void)
{
   glClearColor(0,0,0,0);
   glEnableClientState(GL_VERTEX_ARRAY);
   glLineWidth(2);
   glPointSize(4);
   glEnable(GL_MAP1_VERTEX_4);
}


//Darstellung der Szene
void display(void)
{
   
   
   glClear(GL_COLOR_BUFFER_BIT);
   glLoadIdentity();
   glColor3f(1.0, 0.0, 0.0);
   liste();
   glPolygonMode(GL_FRONT,GL_FILL);   
   if(curve) bezier();
   glFinish();
   glutSwapBuffers();
}

void reshape(int w, int h)
{
   GLfloat aspect_1 = (GLfloat)h / (GLfloat)w;
   GLfloat aspect_2 = (GLfloat)w / (GLfloat)h;
   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   if (w <= h)
       glOrtho(-4.0, 4.0, -4.0 * aspect_1, 4.0 * aspect_1, -4.0, 4.0);
   else
       glOrtho(-4.0 * aspect_2, 4.0 * aspect_2, -4.0, 4.0, -4.0, 4.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}
// Tastaturabfragen
void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      //glutmainloop() beenden
      case 27:                       // Escape-Taste
         exit(0);
         break;

//	  case 'c' : bezier();break;
	  case 's' : curve = !curve;break;
	  case '+' : increase();break;
	  case '-' : decrease();break;
	  case 'k' : showkh = !showkh;break;
      case 'p' : showp = !showp;break;
   }
   glutPostRedisplay();
}



bool punkt(GLfloat x, GLfloat y) //Zeigt die Maus auf einen Punkt ?
{

	Node * tempo = q.front;
	while(tempo)
	{
		if((x < (tempo->x + 0.07)) && (x > (tempo->x - 0.07)) && (y < (tempo->y + 0.07))
			&& (y > (tempo->y - 0.07)))
		{
			ind = tempo;
			return true;
		}
		tempo=tempo->next;
	}
	return false;
}

GLfloat arc(GLfloat x,GLfloat y){ //Berechnung der Winkel zum sortieren


	GLfloat temp = atan(y/x);

	if(((x <= 0) && (y>= 0)) || ((x<= 0) && (y < 0))) temp += PI;

	else if((x > 0) && (y< 0)) temp +=2*PI;

	return temp;

}


void maus(int button, int state, int x, int y) //Beim drücken der linken Maustaste wird ein neuer Punkt generiert
{
   GLint viewport[4];                    // Speicherplatz fuer akt. Viewport
   GLdouble mvmatrix[16], projmatrix[16];// Speicherplatz fuer akt. Matrizen
   GLint realy;                          // Korrigierte y Koordinate


   //
   switch (button) {
      case GLUT_LEFT_BUTTON:             // Linke Maustaste
         if (state == GLUT_DOWN) {       // Taste gedrueckt
            glGetIntegerv (GL_VIEWPORT, viewport);
            glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
            glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
            realy = viewport[3] - (GLint) y - 1;
            gluUnProject ((GLdouble) x, (GLdouble) realy, 0.0,
               mvmatrix, projmatrix, viewport, &wx, &wy, &wz);

			in = punkt(wx,wy);

			if(!in ){

				GLfloat arct = arc(wx,wy);
				push(q,wx,wy,arct);
				sort();
			}

         }

         if(state == GLUT_UP) sort(); //Wird ein Punkt gezogen, werden beim loslassen der Maustaste die Punkte neu sortiert

         break;



	  case GLUT_RIGHT_BUTTON:                 // Rechte Maustaste

		  if (state == GLUT_DOWN)
			  exit(0);
		  break;

   }

   glutPostRedisplay();
}

void mausbewegung(int x,int y){ //Mausbewegung bei gedrückter linker Maustaste



	GLint viewport[4];                    // Speicherplatz fuer akt. Viewport
	GLdouble mvmatrix[16], projmatrix[16];// Speicherplatz fuer akt. Matrizen
	GLint realy;
	glGetIntegerv (GL_VIEWPORT, viewport);
	glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
	glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
	realy = viewport[3] - (GLint) y - 1;
	gluUnProject ((GLdouble) x, (GLdouble) realy, 0.0,
		mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
        if(GLUT_LEFT_BUTTON == GLUT_DOWN){
            if(ind){

                    ind->x = wx;
                    ind->y = wy;
            ind->ax = arc(wx,wy);
            }

        }



        glutPostRedisplay();

}


int main(int argc, char** argv)
{
   glutInit(&argc, argv);             // Initialisierung der GLUT
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
   glutInitWindowSize (1000, 1000);
   glutCreateWindow (argv[0]);
   init_opengl();
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutMouseFunc(maus);
   glutMotionFunc(mausbewegung);    
   glutKeyboardFunc (keyboard);
   //Nun beginnt es;
   glutMainLoop();
   return 0;
}


Ich bin aufjedenfall mit meinem Latein am Ende .. :-/
 
Zurück