Problem: polymorphe Datenverwaltung (Element1.DoIt(Element2);)
-
mh .... kleiner Fehler:
class CA; class CB; class CBasis { public: virtual ~CBasis() {} virtual int Klasse() {return 0;} virtual void DoIt(CA* Element) {} virtual void DoIt(CB* Element) {} }; class CA : public CBasis { public: virtual ~CA() {} virtual int Klasse() {return 1;} virtual void DoIt(CA* Element) {} virtual void DoIt(CB* Element) {} }; class CB : public CBasis { public: virtual ~CB() {} virtual int Klasse() {return 2;} virtual void DoIt(CA* Element) {} virtual void DoIt(CB* Element) {} }; class CObjekt { public: void funk() { CA E1 = CA(); CB E2 = CB(); CBasis* Element1 = &E1; CBasis* Element2 = &E2; if (Element2->Klasse() == 1) Element1->DoIt( (CA *)Element2 ); if (Element2->Klasse() == 2) Element1->DoIt( (CB *)Element2 ); } };
-
Hallo!
Jede Implementierung mit Forward-Deklarationen ist erstmal zweifelhaft. Das löst per se eine zyklische Abhängigkeit auf, und zyklische Abhängigkeit ist so ziemlich das genaue Gagenteil von loser Kopplung.
Es mag Beispiele geben, wo es sinnvoll oder besonders effizient ist, aber ich bezweifle, dass so etwas hier vorliegt.Das Problem "Uberschneidungen feststellen" ist ein sehr komplexes, wird hier aber nur auf eine Funktion abgebildet. Eine angemessene Modellierung könnte eine Verbungsschnittstelle ("protected") aufweisen damit die Polymorphie zur Problemlösung beitragen kann. Das Problem ist nur dann zufriedenstellend zu lösen wenn Du etwas über den Algorithmus, der sich wohl in DoIt() verbirgt, erzähltst.
=> Also, wie sieht der Algorithmus aus ? <=
Btw Klasse() ist redundant; für sowas gibt's typeid und typename.
Grüsse
*this
-
Also ich weiß nicht wozu das von relevanz sein sollte.
Die besagte Funktion bekommt eine Figur als ersten Parameter übergeben und als zweiten eine Liste. Sollte eine Schnittmenge zwischen den beiden Körpern existieren, so wird diese ermittelt. Alle Schnittpunkte wertden in die Liste gespeichert und der Wert TRUE wird zurückgegeben. Sollte keine Schnittmenge existieren, so bleibt die Liste leer und es wird der Wert FALSE zurückgegeben.
Btw Klasse() ist redundant; für sowas gibt's typeid und typename.
Was ist hiermit genau gemeint?
Vielen Dank & Liebe Grüße!
-
A88 schrieb:
Also ich weiß nicht wozu das von relevanz sein sollte.
Zum Auffinden einer besseren Modelierung, wie bereits erklärt.
A88 schrieb:
Die besagte Funktion bekommt eine Figur als ersten Parameter übergeben und als zweiten eine Liste. Sollte eine Schnittmenge zwischen den beiden Körpern existieren, so wird diese ermittelt. Alle Schnittpunkte wertden in die Liste gespeichert und der Wert TRUE wird zurückgegeben. Sollte keine Schnittmenge existieren, so bleibt die Liste leer und es wird der Wert FALSE zurückgegeben.
Wichtig ist wie "Figur" repräsentiert wird. Auch als Punktmenge?
A88 schrieb:
Btw Klasse() ist redundant; für sowas gibt's typeid und typename.
Was ist hiermit genau gemeint?
Such mal nach "RTTI" ("Run Time Type Information").
Grüsse
*this
-
Figur besteht aus einen Mittelpunkt und einen Radius.
Die abgeleiteten Klassen (CDreieck, etc.) haben dann verschiedene Punkte. Z.B. Dreieck hat drei Punkte, Kreis keine, Ellipse 2, Viereck 4, usw.Ich hoffe das beantwortet deine Frage!
Vielen Dank & Liebe Grüße
-
A88 schrieb:
Also ich weiß nicht wozu das von relevanz sein sollte.
Die besagte Funktion bekommt eine Figur als ersten Parameter übergeben und als zweiten eine Liste. Sollte eine Schnittmenge zwischen den beiden Körpern existieren, so wird diese ermittelt. Alle Schnittpunkte wertden in die Liste gespeichert und der Wert TRUE wird zurückgegeben. Sollte keine Schnittmenge existieren, so bleibt die Liste leer und es wird der Wert FALSE zurückgegeben.
*grübelt* Das klingt ganz stark nach "double dispatching" (noch etwas, wonach du suchen kannst)
Btw, abgesehen von der Punktezahl dürfte die Berechnung zumindest für alle Polygone identisch sein - das vereinfacht die Aufgabe sicher schon etwas. (nur der Schnitt Kreis-Polygon und Kreis-Kreis muß noch gesondert behandelt werden)
PS: Wozu hat ein Polygon eigentlich einen Mittelpunkt und Radius? Diese Angaben dürften doch spezifisch für einen Kreis sein.
-
A88 schrieb:
Ich hoffe das beantwortet deine Frage!
???
Von solcher Rhetorik solltest Du Abstand nehmen ween Du willst dass Dir geholfen wird. Nur damit da nichts durcheinanderkommt: Du hast ein Problem mit Deiner Modellierung.Grüsse
*this
P.S.: Jetzt hast Du den ADT, nicht aber den Algorithmus beschrieben.
-
Hallihallo!
PS: Wozu hat ein Polygon eigentlich einen Mittelpunkt und Radius? Diese Angaben dürften doch spezifisch für einen Kreis sein.
Die Notwendigkeit ist eigentlich leicht zu begründen. Der Kreis soll symbolisch für eine Hülle des Polygons stehen. Es ist sehr viel einfacher, zwei Kreise auf Überschneidung zu prüfen. Speziell, wenn mehrere Schnittmengen pro Sekunde berechnet werden sollen, so ist es von Vorteil solche Vereinfachungen vorzunehmen.
*grübelt* Das klingt ganz stark nach "double dispatching" (noch etwas, wonach du suchen kannst)
Danke - werde danach suchen.
???
Von solcher Rhetorik solltest Du Abstand nehmen ween Du willst dass Dir geholfen wird. Nur damit da nichts durcheinanderkommt: Du hast ein Problem mit Deiner Modellierung.Hallo???
Komm mal runter!
Fühlst du dich angegriffen? Wenn ja - wodurch?
Durch meine Hoffnung, deine Frage beantworten zu können? Interpretierst du da Ironie/Hass rein? Wie dass? Bist du der einzige Mensch, der anhand von Phrasen die Sprache - gar das Wesen - eines Menschen analysieren kann? Wenn ja - Hut ab! Ich kann sowas nicht. Sprache - besonder Komunikation - ist sehrviel mehr als nur >Text<. Zur Sprache gehören Gestik, Mimik, die zwischenmenschliche Beziehung und noch einiges mehr. Die genannten Elemente der Komunikation können in diesem Umfang nicht in Worte/Phrasen gekleidet werden. Wenn ich dir sage, das mein Forumname ein Stellvertreter für Anarchie88 ist, weiß ich wie du aller Wahrscheinlichkeit urteilst. Anarchie ... heißt Tot und Zerstörung ... heißt Caos ... hm ... 88 ... was ist denn das fürn Typ ... ein rachtradikales Schwein ... brauner Abschaum! ... tja ... dann tut es mir leid! ... ich kann nicht nachvollziehen, wie es möglich sein soll, Menschen zu beurteilen, die man nicht kennt ... sollten sie etwa einfach in eine Schublade fallen? ... leider ist das die Realität, in der wir leben
Also ich weiß echt nicht was du hast!? Ist es verboten offen und ehrlich zu sein - zu sagen, was man denkt? Ich finde Offenheit
ist eine dringende Notwendigkeit für kontroverse, konstruktive Fortschritte und Problemlösungen.Noch was speziell an Gast++: Ich bin mir definitiv bewusst, dass ich ein Problem habe. Daher nehme ich auch eindeutig eine unterwürfige Position ein. Ich war stehts freundlich und habe mich für jede Beantwortung meiner Frage bedankt! Und das war alles ehrlich uznd nicht gespielt!
Nochwas: Du hast einen Fragenden keinerlei Verpflichtungen bezüglich der Beantwortung seiner Fragen!Aber zurück zum eigentlichen (wichtigeren) Thema!
P.S.: Jetzt hast Du den ADT, nicht aber den Algorithmus beschrieben.
Das ist der Algorithmus ... sicherlich nicht perfekt!
bool coll(CLinie *L, TList *coll_Pkt) { if ((M - L->M).Betrag() > r + L->r) return false; CVektor2D p = A; CVektor2D u = B - p; CVektor2D q = L->A; CVektor2D v = L->B - q; float D = v[0]*u[1] - v[1]*u[0]; if (D*D > 0.0001) { float r = (CVektor2D(-v[1],v[0]) * (q - p)) / D; float s = (CVektor2D(-u[1],u[0]) * (q - p)) / D; if (r>=0 && r<=1 && s>=0 && s<=1) { coll_Pkt->Add( new CVektor2D(p + r*u) ); return true; } } else if (CVektor2D(-v[1],v[0]) * (q - p)<0.0001) { float s1 = (p - q)*v/(v*v); float s2 = (p + u - q)*v/(v*v); if (s1>s2) {float h = s1; s1 = s2; s2 = h;} if (s1>1 || s2<0) return; if (s1 == 0 || s2 == 0) if (s1 == 1) coll_Pkt->Add( new CVektor2D(p+u) ); else coll_Pkt->Add( new CVektor2D(p) ); else { if (s2>0) coll_Pkt->Add( new CVektor2D(p+u) ); else coll_Pkt->Add( new CVektor2D(p) ); if (s1<1) coll_Pkt->Add( new CVektor2D(p + s1*u) ); else coll_Pkt->Add( new CVektor2D(p + u) ); } return true; } return false; };Analog Linie-Kreis, Linie-Dreieck, etc ...
[quote]Btw, abgesehen von der Punktezahl dürfte die Berechnung zumindest für alle Polygone identisch sein - das vereinfacht die Aufgabe sicher schon etwas. (nur der Schnitt Kreis-Polygon und Kreis-Kreis muß noch gesondert behandelt werden)[quote]
Das habe ich mir auch schon überlegt! Mann könnte ja Kreise auch nährungsweise mit Linien nachbilden ... genau, wie jede Figur ... darauf wollte ich jedoch verzichten, da die Berechnung - je nach Detailgenauigkeit - sehr komplex werden kann ... mittlerweile favorisiere ich jedoch auch diesen Vorschlag, da ich an der Schnittpunktfindung Ellipse-Ellipse verzweifelt bin. Da auch die Nachbildung beliebig geformter Figuren mit hilfe der Linien-Liste Methode möglich ist - jedoch nicht mit der Vorgabe von fertig modellierten Figuren.
Von daher bin ich echt am überlegen, mein Programm wie gesagt zu ändern. Denn auch mein Problem, was mich veranlasste, mich an diese Forum zu wenden würde dann nicht länger existent sein.Natürlich würde ich mich über eine Problemlösung des eingangs gestellten Problems sehr freuen.
Vielen Dank & Liebe Grüße
-
A88 schrieb:
[...]Anarchie88 [...]
Dazu kann ich leider nichts sagen; 1988 hatte ich noch nicht in C++ programmiert...
Das ist jetzt ein Algorithmus für "CLine"; und wie ich sehe prüfst Du anfangs ob sich die Umkreise überschneiden. Ein Kreis ist ja nur ein Sonderfall einer Ellipse ( die ihrerseits ein auch ein Kegelschnitts ist).2D-Polygone lassen sich Mengen von 2D Vektoren darstellen.
Wie wäre es wenn Du in der Basisklasse eine Methode intersect(oder wie auch immer benannt) schaffst die sich von den Kindklassen (die sie noch nicht zu kennen braucht solche Vektormengen liefern lässt? Effiziente Parameterübergabe beachte ich hier mal nicht; das hängt u.a. von der Implementierung der CBasis-Kindklassen ab
/* * For surrounding Ellipse only */ class _CEllipse { //... public: bool intersects (const _CEllipse* that); }; class CBasis { //... protected: virtual std::vector<Vector2D> getVectors() = 0; virtual const _CEllipse* getEllipse() = 0; bool vectorCompare(std::vector<Vector2D> other,Tlist& result); public: bool intersect(const CBasis* that,TList& result) { bool fRetVal; if( this->getEllipse()->intersects(that->getEllipse()) { fRetVal = this->vectorCompare(that->getVectors(),result); } else { result.setEmpty(); fRetVal = false; } return fRetVal; }; };In den Kindklassen kapseltst Du dann die Erzeugung des Vektorzuges und verwendst in CBasis::vectorCompare(...) den Algorithmus für CLine für alle Teilstrecken des Polygonzuges. Das wird allerdings n*m für Vergleiche eines n mit einem m Polygons!
Die Überschneidung von Ellipsen lässt sich analytisch mittels der Ellipsengleichung lösen; CEllipse und CCircle selbst übergeben geweils leere Polygonzüge in getVectors()!
Na, wie sieht das aus?
Du kannst auch aus Performancsgründen den Ellipsentest zum Kreistest degenerieren (bei gleichen Halbachsen). Das ganze ist nur eine Form; wohin Du jetzt was delegierst ist vor allem eine Performancefrage.
Ein Problem seh ich aber noch - was ist wenn eine Figur komplett in eine andere fällt?
Grüsse
*this
-
Ersteinmal herzlichen Dank!
Mir gefällt dein Lösungsvorschlag gut. Wenn ich nichts missverstanden habe, favorisierst du die von CStoll angeschnittene "Linienzug - Methode".
Wo du es sagst ... wenn die Figur in einer anderen liegt ... das macht mir gerade dolle Sorgen! Wäre es nicht vorteilhaft, alle Eckpunkte eines Polygons, welche in einem anderen Polygon liegen, mit in die Liste zu schreiben?
Vielen Dank & Liebe Grüße!
-
A88 schrieb:
Wo du es sagst ... wenn die Figur in einer anderen liegt ... das macht mir gerade dolle Sorgen! Wäre es nicht vorteilhaft, alle Eckpunkte eines Polygons, welche in einem anderen Polygon liegen, mit in die Liste zu schreiben?
Vielen Dank & Liebe Grüße!Bei regelmässigen Polygonen müsste ja imo gelten
(A liegt ganz in
=> ( M(A) liegt in Umkreis(B) ) && ( Schnittmenge ist leer )Für "<=>" müsste man noch mit S (Schnittpunkt von Strecke(M(A),M(B)) mit B )
und |S-M(A)|, |S-M(B)| und |M(A)-M(B)| sich was ausdenken, falls sich A zwischen B und Umkreis(B) schnittpunktfrei "reinquetscht".Grüsse
*this