cadman Geschrieben 6. Februar 2011 Teilen Geschrieben 6. Februar 2011 Hallo, habe folgendes Problem: Ich habe eine Gerade und eine Polylinie (mehrgliedrige Linie) an eine Funktion zu übergeben. Die Funktion soll mir die Schnittpunkte in einem 2-dimensionalem array zurückgeben. Da ich zu Anfang nicht weiß, ob und wieviele Schnittpunkte es gibt muss das Rückgabearray irgendwie dynamisch arbeiten. Ich habe mir schon malloc angesehen. Aber die Beispiele bestanden nur aus 1-dimensionalen arrays. wat nu ? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 6. Februar 2011 Teilen Geschrieben 6. Februar 2011 Wie wäre es mit einem Vector von std::pair oder einer geeigneten Struktur? In C++ sollte man eigentlich um rohe Zeiger einen weiten Bogen machen Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
cadman Geschrieben 7. Februar 2011 Autor Teilen Geschrieben 7. Februar 2011 ... struktur ? du meinst so eine art klasse mit einer methode für x, eine für y und eine für den fehlercode, wenn kein schnittpunkt vorhanden ? aber x und y müssten dann ja dynamisch funktionieren und da liegt das problem Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 7. Februar 2011 Teilen Geschrieben 7. Februar 2011 ... struktur ? du meinst so eine art klasse mit einer methode für x, eine für y und eine für den fehlercode, wenn kein schnittpunkt vorhanden ?Nein, eine einfache Struktur, die einen Schnittpunkt darstellt: struct Punkt { double x; double y; };[/code] Unter der Annahme, dass dein Koordinatentyp double ist. Und davon gibt deine Funktion einen vector zurück: [code]std::vector<Punkt> deinefunktion(params) Einen eigenen Fehlercode für "keinen Schnittpunkt" brauchst du nicht. In dem Fall kannst du ja einfach einen leeren Vector zurückgeben. In der Funktion legst du einen Vector an, und immer, wenn du einen Schnittpunkt gefunden hast, hängst du den hinten an den Vector an: std::vector<Punkt> deinefunktion(params) { std::vector<Punkt> ergebnis; // ... Schnittpunkt suchen ... Punkt p; p.x = bla; p.y = blubb; ergebnis.push_back(p); // Punkt p an Vector ergebnis anhängen // ... weitersuchen ... return ergebnis; }[/code] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
cadman Geschrieben 8. Februar 2011 Autor Teilen Geschrieben 8. Februar 2011 danke, probier' ich mal aus Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
cadman Geschrieben 10. Februar 2011 Autor Teilen Geschrieben 10. Februar 2011 habe folgende funktion, aber das mit dem realloc funktioniert nicht: // Schnittpunkt einer Geraden mit einer Polylinie berechnen // epx1, epy1,zpx1, zpy1 -> Koordinaten der 1. Geraden // f -> =1 Gerade unendlich lang // double poly [][2] -> Koordinatenfeld der Polylinie (1. Punkt = letzter Punkt) // int orianzep -> Anzahl der Eckpunkte // f1 -> wenn f1=1 wird die 1. Gerade unendlich verlängert // f2 -> wenn f2=1 wird die 2. Gerade unendlich verlängert // rueckgabe -> punktfeld mit schnittpunkten: double (*rueckgabe) [2] = new double [anzeckp][2]; // fehler -> =-1 keine Schnittp4n2te gefunden void fc_calc_sp_g1_poly (double epx1, double epy1,double zpx1, double zpy1, int f, double poly [][2], int orianzep, double rueckgabe[][2], int fehler) { //fehlerpuffer fehler=-1; //Zähler zum Durchlauf der Polylinie int z; //Zwischenpuffer für Schnittpunkt double r1[3]; //Zähler für Schnittpunkte int spz=0; //Rückgabepuffer "rueckgabe" wird erst beim 1 Fund initialisiert double **matrix; // int i; //Alle Punkte der Polylinie durchlaufen for (z=0;z<(orianzep-1);z+=1) { //funktion sucht schnittpunkt fc_calc_sp_g1_g2 (epx1,epy1,zpx1,zpy1, poly [z][0],poly [z][1],poly [z+1][0],poly [z+1][1], f,0,r1); //wenn schnittpunkt gefunden if (r1[2]==1) { fehler=1; //wenn noch kein schnittpunkt gefunden if (spz==0) { cout << "\nmalloc !"; //Zeile matrix = (double **) malloc (1*sizeof(double *)); //Spalte matrix[0] = (double *) malloc (2*sizeof(double)); } //für weitere schnittpunkte if (spz>0) { cout << "\nrealloc !"; //Zeile matrix = (double **) realloc (matrix, (spz+1)*sizeof(double *)); //Spalte matrix[spz] = (double *) realloc (matrix, 2*sizeof(double)); } cout << "\nSchnittpunkt gefunden !"; cout << "\nspz: " << spz; cout << "\n" << z << "\t" << r1[0] << "\t" << r1[1]; matrix[spz][0]=r1[0]; matrix[spz][1]=r1[1]; spz++; } } cout << "\nspeicher freigeben !"; if (spz>0) { for (i=0;i<spz;i++) {free (matrix[i]);} free (matrix); } } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 10. Februar 2011 Teilen Geschrieben 10. Februar 2011 das mit dem realloc funktioniert nicht:"Funktioniert nicht" ist keine ausreichende Fehlerbeschreibung Für matrix[spz] darfst du natürlich nicht realloc benutzen. Das ist ja ein ganz neuer, uninitialisierter Zeiger, der nie mit malloc belegt wurde. Aber warum plagst du dich in C++ mit malloc & Co. ab? Hast du Einfluss auf die Signatur dieser Funktionen? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
cadman Geschrieben 11. Februar 2011 Autor Teilen Geschrieben 11. Februar 2011 hallo, aus matrix[spz] = (double *) realloc (matrix, 2*sizeof(double)); matrix[spz] = (double *) malloc (2*sizeof(double)); dann geht es ! Danke ! Ob ich EInfluss auf die Signatur der Funktion habe ? Was meinst Du damit ? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 11. Februar 2011 Teilen Geschrieben 11. Februar 2011 Ob ich EInfluss auf die Signatur der Funktion habe ? Was meinst Du damit ? Kannst du die Parametertypen von fc_calc_sp_g1_poly und fc_calc_sp_g1_g2 ändern, oder ist das vorgegeben? Dein Code sieht nämlich bis auf cin/cout wie C aus. In C++ würde man das anders lösen. Dazu müsste man aber die Parametertypen ein wenig ändern. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
cadman Geschrieben 11. Februar 2011 Autor Teilen Geschrieben 11. Februar 2011 die funktionen fc_calc_sp_g1_poly und fc_calc_sp_g1_g2 kann ich ändern wie ich will, da ich nur privat ein bißchen programmieren lernen möchte bin so ein selbsternannter informatiker im 2. bildungsweg :bimei Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 11. Februar 2011 Teilen Geschrieben 11. Februar 2011 Dein Code zeigt, wie man dieses Problem in C lösen würde (wenn man mal von cin/cout absieht). In C++ kann man das zwar genauso machen, man tut es aber normalerweise nicht. C++ biete viele Möglichkeiten, wie man sich hier das Leben vereinfachen kann. Man muss dazu auch nicht sofort alles auf Objektorientierung umstellen. So könnte das aussehen: // Struktur für einen 2D-Punkt struct punkt { double x; double y; }; vector<punkt> fc_calc_sp_g1_poly (punkt ep, punkt zp, int f, vector<punkt> const& poly) { vector<punkt> rueckgabe; //Alle Punkte der Polylinie durchlaufen for (size_t z=0; z<poly.size()-1; ++z) { punkt r; //funktion sucht schnittpunkt if( fc_calc_sp_g1_g2 (ep, zp, poly[z], poly[z+1], f, 0, r) ) { rueckgabe.push_back(r); cout << "\nSchnittpunkt gefunden !"; cout << "\nspz: " << matrix.size(); cout << "\n" << z << '\t' << r.x << '\t' << r.y; } } return rueckgabe; }[/code] Der Code ist damit übersichtlicher und gleichzeitig ausnahmesicher. Er enthält kein lästiges Speichermanagement mehr, darum kümmert sich die Vector-Klasse. fc_calc_sp_g1_g2 müsste natürlich ähnlich angepasst werden. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
cadman Geschrieben 11. Februar 2011 Autor Teilen Geschrieben 11. Februar 2011 habe jetzt eine funktion auf die vector geschichte umgestellt. rueckgabe ist eine punkt struktur wie stelle ich es denn an, dass die aufrufende funktion merkt, dass kein punkt gefunden wurde ? fc_point fc_calc_sp_g1_g2 (fc_point ep1, fc_point zp1, fc_point ep2, fc_point zp2, int f1, int f2) { fc_point rueckgabe; int fehler=1; fc_point schnittp; // Felder für transformierte Endpunkte double tep1[2],tzp1[2],tep2[2],tzp2[2]; // Daten der 1. Geraden im Originalzustand double l1=pow(pow((ep1.x-zp1.x),2) + pow((ep1.y-zp1.y),2),0.5); double alpha1=acos((zp1.x-ep1.x)/l1); // Die Koordinatensystem wird so gedreht, dass der Anfangspunkt der 1. Geraden // horizontal durch den Ursprung verläuft fc_calc_coortrans_point(ep1.x,ep1.y,ep1.x,ep1.y,alpha1,tep1); fc_calc_coortrans_point(zp1.x,zp1.y,ep1.x,ep1.y,alpha1,tzp1); fc_calc_coortrans_point(ep2.x,ep2.y,ep1.x,ep1.y,alpha1,tep2); fc_calc_coortrans_point(zp2.x,zp2.y,ep1.x,ep1.y,alpha1,tzp2); // Ist auch die 2. Gerade horizontal ? Dann Fehler = -1 setzen if (tep2[1]==tzp2[1]) { //cout << "\nDie Linien sind parallel !"; fehler = -1; if (tep1[1]==tep2[1]) { //cout << "\nDie Linien liegen übereinander !"; } } if (fehler==1) { // Zweite Gerade senkrecht ? if (tep2[0]==tzp2[0]) { schnittp.x=tep2[0]; schnittp.y=0.0; } else { schnittp.x=tep2[0]+(tzp2[0]-tep2[0])*(-tep2[1])/(tzp2[1]-tep2[1]); schnittp.y=0.0; } // Bei entsprechender Einstellung (f1,f2) muss der Schnittpunkt auf denn Geraden liegen // Bedingung f1 prüfen if (f1!=1) { if (schnittp.x<0.0 || schnittp.x>tzp1[0]) { fehler=-1; }} // Bedingung f2 prüfen, wenn kein Fehler if (fehler==1) { if (f2!=1) { if ((schnittp.y-tep2[1])/(tzp2[1]-tep2[1])<0.0 || (schnittp.y-tep2[1])/(tzp2[1]-tep2[1])>1.0) {fehler=-1;} } } // Rücktransformation double tmp[2],bcs[2]; fc_calc_coortrans_point(0.0,0.0,ep1.x,ep1.y,alpha1,bcs); fc_calc_coortrans_point(schnittp.x,schnittp.y,bcs[0],bcs[1],-alpha1,tmp); rueckgabe.x=tmp[0]; rueckgabe.y=tmp[1]; } return rueckgabe; } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
lilith2k3 Geschrieben 11. Februar 2011 Teilen Geschrieben 11. Februar 2011 Ohne jetzt detailliert den Code gelesen zu haben ... wie stelle ich es denn an, dass die aufrufende funktion merkt, dass kein punkt gefunden wurde ? vector<punkt> rueckgabe; return rueckgabe; [/PHP] Der Vector enthält schlimmstenfalls eben 0 Elemente. vector::size Returns the number of elements in the vector container. Wenn Dich die Größe interessiert. [PHP]for ( it=myvector.begin() ; it < myvector.end(); it++) Und so iterierst Du über alle Elemente. Wenn Du dann 0 Elemente hast, ist die For-Schleife eben schnell beendet vector - C++ Reference Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
cadman Geschrieben 11. Februar 2011 Autor Teilen Geschrieben 11. Februar 2011 das ist der datentyp von rueckgabe: structure fc_point { double x; double y; } ist KEIN vector Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
lilith2k3 Geschrieben 12. Februar 2011 Teilen Geschrieben 12. Februar 2011 Wenn ich Klotzis Beipsiel nehme: vector<punkt> fc_calc_sp_g1_poly (punkt ep, punkt zp, int f, vector<punkt> const& poly)[/PHP] So ist bei dem Beispiel [PHP]vector<punkt> der Rückgabetyp. Ohne jetzt im Einzelnen zu wissen, was die Funktion macht: if( fc_calc_sp_g1_g2 (ep, zp, poly[z], poly[z+1], f, 0, r) ) sollte die Abfrage sicherstellen, ob ein Schnittpunkt existiert oder nicht und rueckgabe.push_back(r); sorgt dafür, dass "r" -welches den zurückgegebenen Punkt enthält- an's Ende des Vectors angefügt wird. In jedem Falle wird nach durchlaufen der for-Schleife der Vector zurückgegeben. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 12. Februar 2011 Teilen Geschrieben 12. Februar 2011 das ist der datentyp von rueckgabe: structure fc_point { double x; double y; } ist KEIN vectorDas kannst du nicht als Rückgabetyp benutzen, weil eben auch die Möglichkeit besteht, dass es keinen Schnittpunkt gibt. Du könntest einen std::auto_ptr<fc_point> zurückgeben, der kann gegebenenfalls auch einen Nullzeiger kapseln. Alternativ kannst du das Ergebnis über einen Referenzparameter zurückgeben und über den Rückgabewert, beispielsweise true oder false, anzeigen, ob es einen Schnittpunkt gibt. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.