Wie kann man das eleganter machen?



  • Hallo!

    Ich hab ein Problem. Der folgende Code soll alle Kombinationen von Werten von Variablen durchgehen. Bei jedem aufruf zählt der folgende Code eine variable hoch. Wenn diese das maximum erreicht hat, wird sie zurückgesetzt und die nächste um eins hochgezählt. und so weiter.

    Der Code funzt, aber er sieht schrecklich aus. Wie ginge das besser? Ich habe ja für jede variable eine if-abfrage.

    if(!m_HasStarted)
    {
    	m_currTrans = -m_trRange;
    	m_currSc = -m_scRange;
    	m_currRot = -m_rotRange;
    }
    else
    {
    	m_currRot += m_rotStep;
    	if(m_currRot > m_rotRange)
    	{
    		m_currRot = -m_rotRange;
    		m_currSc += m_scStep;
    		if(m_currSc > m_scRange)
    		{
    			m_currSc = -m_scRange;
    			m_currTrans.x += m_trStep;
    			if(m_currTrans.x > m_trRange.x)
    			{
    				m_currTrans.y += m_trStep;
    				if(m_currTrans.y > m_trRange.y)
    				{
    					m_HasNext = false;
    					return false;
    				}
    			}
    		}
            }
    }
    

    Ich sehe leider keine möglichkeit, da was zu machen (oder nur ziemlich performance-schlechte sachen). Sobald ich eine neue variable dazu machen will, muss ich noch ne if-abfrage machen und so.

    Habt ihr ne bessere idee?

    Gruß, Maxi



  • Hallo Maxi,

    wie wär's damit - so im Prinzip

    using namespace std;
        enum { Rot = 0, Sc = 1, Trans = 2 };
        vector< int > m_curr( 3, 0 );
        vector< int > m_Range( 3 );
        m_Range[Rot] = 10;
        m_Range[Sc] = 20;
        m_Range[Trans] = 30;
        vector< int > m_step( 3 );
        m_step[Rot] = 5;
        m_step[Sc] = 2;
        m_step[Trans] = 4;
    
        // -- um 1 Hochzählen
        for( size_t i = 0; i < m_curr.size(); ++i )
        {
            m_curr[i] += m_step[i];
            if( m_curr[i] > m_Range[i] )
            {
                // Überlauf
                m_curr[i] -= m_Range[i];
            }
            else
                break;
        }
    

    Gruß
    Werner



  • Hallo!

    An sowas in der Art hatte ich auch schon gedacht, quasi die möglichen Werte auf natürliche zahlen mappen und dann wie ne normale zahl hochzählen. Aber das Problem dabei ist, dass nicht alle Parameter den selben Typ haben, manche sind vektoren, manche einache floats etc.

    Und die vektoren jetzt in einzelne floats aufspalten fände ich nicht so toll.



  • Gib uns doch mal den Kontext, also das eigentliche Problem, das du damit loesen wolltest. Vielleicht gibts einen anderen Ansatz, der das ganze etwas weniger umstaendlich macht.



  • Abstrakt gesehen funktioniert das wohl wie eine Uhr mit vier Zeigern, wo ein Zeiger immer weitergesetzt wird und wenn dieser einen bestimmten Punkt überschreitet das gleiche mit dem nächsten geschieht.

    Würde ich eine Klasse draus machen, in etwa:

    class Dial{
    public:
      // Konstruktor
      void setInnerDial(Dial *d){ mInnerDial = d; }
      void step(){
        mCurrent += mStep;
        if (mCurrent > mRange){
          mCurrent = -mRange;
          if (mInnerDial){
            mInnerDial->step();
          }
        }
      }
    
    private:
      int mCurrent;
      int mRange;
      int mStep;
    
      Dial *mInnerDial;
    
    }
    

    ... so in etwa. Dials erstellen, verknüpfen und fertig.

    EDIT: Macht man aus den Membervariablen auch Pointer die auf externe Variablen verweisen passt das sogar nahtlos in jede Implementierung.



  • Fellhuhn: Du machst das ganze rekursiv in der Art ginge auch sicherlich. Müsst ich mir mal überlegen, weil man da mit templates auch verschiedene datentypen zusammenklammern kann.
    Das Beispiel mit der Uhr is aber genau das was ich meine.

    pumuckl:
    Es geht darum: Ein Bild soll mit allen möglichen Transformationen transformiert werden. Die Transformationen sind durch Translation, Rotation und skalierung beschrieben. Trans und scale sind vector2d, rot ist float. die step-weiten geben an, wie viele zwischenschritte zwischen den Grenzen der einzelnen parameter gemacht werden sollen.



  • Skalierung durch einen 2D-Vector ausgedrueckt? Verzerrst du das Bild in eine bestimmte Richtung? Sonst wuerde eine einfache Skalierung durch einen einzigen (float-) Parameter beschrieben.

    Dein Problem wuerde ich folgendermassen angehen: Da du vermutlich deine if-Kaskadierung in einer Schleife durchlaeufst, bis hasNext false ist, hat das den selben Effekt, wie wenn du 4 geschachtelte for-Schleifen durchlaeufst:

    for(m_currTrans.y = - m_trRange.y; m_currTrans.y <= m_trRange.y; m_currTrans.y += m_trStep)
      for(m_currTrans.x = - m_trRange.x; m_currTrans.x <= m_trRange.x; m_currTrans.x += m_trStep)
        for (...)
          for (...)
    


  • Dann hätte man aber Schleifen an Stellen wo man evtl. keine haben will.

    Eine saubere Trennung der Logiken ist dann nicht mehr möglich. zB wenn man das bei mehreren Objekten parallel mit unterschiedlichen Werten haben will etc.



  • pumuckl: So wie du hatte ich es vorher. Dadurch hatte ich eine irre verschachtelungstiefe, sah total hässlich aus und man hat schwer durchgesehn. Jetzt wo ich das nochmal überarbeite will ich das da nichtmehr dabei haben. Außerdem greift Fellhuhns argument 🙂

    Ja, ich verzerre das Bild auch, also x und y-skalierung muss nciht gleich sein, deswegen vector2d

    Ich glaube, ich werde es jetzt machen, so wie Fellhuhn es vorgeschlagen hat, das sieht mir am elegantesten aus, man kann es auch leicht um weitere parameter erweitern etc.


Anmelden zum Antworten