Abbildungsmodus



  • Halloo Leute,

    Zur Zeit bin ich gerade dran eine Koordinatensystem zu programmieren.
    Es soll mittig ausgerichtet sein und die Achsen sollen geanuso verlaufen wie
    wir von der Mathemaik gewohnt sind. Ich benutze den Abbildungsmodus
    ANISOTROPIC und da habe ich Verständnissprobleme mit Befehlen wie z.B
    LPtoDP. Denn wenn ich die Achsenskalierung programmiere kommt Müll raus.
    Ich verstehe also nicht was diese Funktion genau macht.

    Am besten gebe ich mein Code mal auch an, es ist ja nicht lang:

    void C1QuadrantDlg::Plot1CoordinateLinear(long yMIN, long yMAX, long xMIN, long xMAX, long DELTA)
    {
       long xExtension = xMAX - xMIN;
       long yExtension = yMAX - yMIN;
    
       CPaintDC dc(this);
    
       CRect ClientRect;
       CRect Coordinate;
    
       GetClientRect(&ClientRect);   //Größe des Ausgabebereichs ermitteln 
       GetClientRect(&Coordinate);    //soll die Größe des 1. Quadranten
                                             aufnehmen 
    
       CPoint Border(ClientRect.Width()/10,ClientRect.Height()/10); //Randgröße
    
       Coordinate.DeflateRect(Border.x,Border.y);    //Größe des 1.Quadrantes  
    
           //Größe der Striche die zur Achsenaufteilung dienen    
            CPoint Strich(Coordinate.Width()/100,Coordinate.Height()/100);
    
           //verschieben des Ursprunges  
       dc.SetViewportOrg(Border.x,ClientRect.Height()-Border.y);
    
       dc.SetMapMode(MM_ANISOTROPIC);
    
       dc.SetWindowExt(xExtension,yExtension);
    
            //Ausrichtung der Achse Y so daß pos. Werte nach oben gehen
            dc.SetViewportExt(Coordinate.Width(),-Coordinate.Height());
    
       //Umwandlung der festgelegten Werte in log. Koordinaten
            dc.DPtoLP(&Border);
       dc.DPtoLP(&Strich);
       dc.DPtoLP(&Coordinate);
    
       dc.Rectangle(0,0,1000,1000);
       //dc.Rectangle(Coordinate);
       //dc.Ellipse(0,0,xExtension,yExtension);
    
            //Achsenaufteilung zeichnen
       for(int i=1;i<5;i++)
       {
       dc.MoveTo(0,DELTA*i);
       dc.LineTo(Strich.x,DELTA*i);
       }
    
       for(int j=1;j<5;j++)
       {
       dc.MoveTo(DELTA*j,0);
       dc.LineTo(DELTA*j,Strich.y);
       }
    

    Edit by Moderator. Bitte Codetag nicht vergessen.

    Vielen Dank für Antworten Bolilein

    [ Dieser Beitrag wurde am 11.12.2002 um 14:05 Uhr von Unix-Tom editiert. ]



  • Hi,
    also, ich kenne mich zwar mit "ANISOTROPIC" nicht aus,
    aber ich schreibe gerade selber eine Dialogfeldanwendung, bei
    der ein Koordinatensystem verwendet wird.
    Hier einfach mal der Code:

    void CGraphDlg::OnCkoordinatensystem() 
    {
        UpdateData(TRUE);
    
        CClientDC dc(this);
        CPen Pen;
    
        if(m_bKoordinatenSystem)                                    // Wenn Koordinatensystem erwünscht
        {
            Pen.CreatePen(PS_SOLID,1,RGB(0,0,0));                   // schwarzer Stift
        }
        else
        {
            Pen.CreatePen(PS_SOLID,1,DLG_BACKGROUND);       // Stift mit der Hintergrundfarbe
        }
        dc.SelectObject(&Pen);                                  // Stift verwenden
        dc.MoveTo(Rect.CenterPoint().x,Rect.BottomRight().y);   // "Kreuz" zeichnen // Rect ist eine CRect Variable mit der Größe des Zeichenbereiches
        dc.LineTo(Rect.CenterPoint().x,0);
        dc.MoveTo(Rect.TopLeft().x,Rect.CenterPoint().y);
        dc.LineTo(Rect.BottomRight().x,Rect.CenterPoint().y);
        for(int x = Rect.CenterPoint().x;x <= Rect.right;x += 10)    // x Striche alle 10 Punkte zeichnen
        {
            dc.MoveTo(x,Rect.CenterPoint().y+5);        // folgende 2: positiver Bereich
            dc.LineTo(x,Rect.CenterPoint().y-5);
            dc.MoveTo(Rect.CenterPoint().x - (x - Rect.CenterPoint().x),Rect.CenterPoint().y+5);    // negativer Bereich
            dc.LineTo(Rect.CenterPoint().x - (x - Rect.CenterPoint().x),Rect.CenterPoint().y-5);
            }
        for(int y = Rect.CenterPoint().y;y <= Rect.bottom;y += 10)   // y Striche alle 10 Punkte zeichnen
            {
            dc.MoveTo(Rect.CenterPoint().x+5,y);
            dc.LineTo(Rect.CenterPoint().x-5,y);
            dc.MoveTo(Rect.CenterPoint().x+5,Rect.CenterPoint().y - (y - Rect.CenterPoint().y));
            dc.LineTo(Rect.CenterPoint().x-5,Rect.CenterPoint().y - (y - Rect.CenterPoint().y));
        }
        if(!m_bKoordinatenSystem)RePaintDC();
    }
    

    Ich hoffe, dass das dir weiterhilft.

    mfg takeiteasy



  • @Bolilein
    Jo, has Du wirklich falsch verstanden .. wie ich sehe, setzt Du überall clientrect ein, egal, ob für Viewport oder Window! Das ist falsch.

    ----------------------------------- ClientWindow
    |WindowOrg  (Border)              |
    | ------------------------------- |
    | |                             | |
    | |         WindowExt           | |
    | |                             | |
    | |                             | |
    | ------------------------------- |
    |                                 |
    -----------------------------------
    

    Du setzt also mit SetWindowOrg den Rahmen, mit SetWindowExt die Grösse des Bereichs des Koordinatensystems in Device-Koordinaten.

    Jetzt kannst Du mit SetViewportExt die Dimension von WindowExt für Dich bestimmen, z.B. WindowExt( 200, 100) -> ViewportExt( 2000, 200)
    Wenn Du nun SetPixel( 1000, 100) aufrufst, wird der Pixel umgerechnet in Fensterkoordinaten bzw. DevicePoints und auf Punkt(100, 50) gesetzt.
    Du musst also DPtoLP nicht aufrufen, um zu zeichnen.
    Andersrum, wenn Du mit der Maus reinklickst, bekommst Du die Device-Koordinaten. Um diese auf Deine Koordinatensystemkoordinaten umzurechnen, musst Du nun DPtoLP aufrufen!
    Soweit verständlich?



  • Hallo René

    Ich denke ich habe deine Ausführungen noch nicht verstanden.
    Daher versuche ich mal darzustellen wie ich die Sache verstanden habe.

    Also es gibt die sogennanten logische Koordinatenraum. Das ist der Koordinatensystem die ich einfach nur vorstelle und dessen Ursprung und Ausdehnung ich mit SetWindowOrg()und SetWindowExt() festlege.
    So, und dann gibt es die sogenannte physikalische Koordinatensystem die den tatsächlichen Ausgabebereich (Client-bereich) darstellt in Pixeln (**standardmäßig).
    Es werden grundsätzlich die logischen Koordinaten ins physikalische Koordinaten
    abgebildet (umgerechnet).

    Also z.B bei SetWindowsExt(100,100) -> SetViewportExt(1000,1000)
    wird mit dem Aufruf Rectangle(50,50) ein Rechteck mit 500 Pixel Seitenlänge gezeichnet.

    Nach mein Verständniss ist also alles was mit viewport zu tun hat der physikalische Bereich;also das was ich am Bildschirm tatsächlich sehe; das ist also der sichtbare Dialog oder irgendein Fenster.
    Und der logische Koordinatenraum ist nur ein ´gedachte´ Koordinatenraum. Dessen Ursprung und Größe lege ich mit SetWindowOrg() und SetWindowExt() fest.

    Also nochmal : Ich sage ich will ein Koordinatensystem darstellen mit der Ausdehnung
    100 Einheiten nach oben und rechts. Also SetWindowExt(100,100).
    Dann ermittel´ ich die Größe des wirklichen Ausgabebereiches mit
    GetClientRect(&ClientRect) in Pixeln. Dann kann ich mit
    SetviewportExt(&ClientRect) erreichen ,daß wenn ich irgendein
    Zeichnen-Funktion (100,100) übergebe, dann der gesammte
    Ausgabebereich ausgefüllt wird (z.B bei Rectangle()) .

    Jetzt bin ich mal gespannt ob ich immer noch voll auf dem Holzweg bin.
    Ich habe zum diesen Thema schon 3 Bücher gelesen und irgendwie ist es nicht 100% klar.

    Vielen Dank im voraus und have a nice day .... bolilein**



  • Ja, so habe ich das bisher immer gemacht und hat auch funktioniert .. bei meiner obigen Erklärung habe ich leider die Befehle SetViewportExt und SetWindowExt verwechselt, hoffe, Du verzeihst mir das ...

    Das erste, was ich nicht verstehe, ist, dass Du Deine Strichbreite und Border abhängig vom ClientRect machst, kann mir nicht vorstellen, dass diese 80Px breit sein sollen, wenn das Rect 800 breit ist.

    Als zweites verwendest Du CPaintDC, dieses darf aber nur innerhalb des OnPaint-Befehls stehen. Bei Deiner Funktion müsstest Du CClientDC verwenden.

    Als 3. wäre es gut, wenn Du ein Beispiel angibst, wo Du LPtoDP verwendest. In Deinem Codebeispiel verwendest Du nur DPtoLP und dass scheint zu funktionieren, ausser dass Du nur 5 Striche für die Skalierung zeichnen willst, was ich aber abhängig von Min<->Max machen würde.



  • Hallo René

    Dank für Antwort

    1. Ich mache den Rand von Fenstergröße abhängig da mein Ausgabefenster in der
    Größe änderbar sein soll.
    Den Rand habe ich definiert damit ich meine Koordinatensystem (nur 1.Quadrant!!) mittig im Ausgabefenster positionieren kann.

    Ich richte also mein Koordinatensystem so aus wie ich von Mathe aus gewohnt bin.
    Y nach oben X nach rechts. Dazu verschiebe ich den Ursprung um "Rand" nach rechts und Ausgabefensterhöhe-"Rand".

    2. Ja ich habe auch schon gelesen daß ich eigentlich CClientDC benutzen sollte aber wenn ich das mache dann flackert es wild und ich weiß nicht warum. Das müßte ich aber nochmal probieren (ich weiß es nicht mehr genau).

    3. nach diesen Befehl DPtoLP bzw. LPtoD habe ich deshalb gefragt, weil der irgendwie (glaub ich) auch die Achsenausrichtungen mit berücksichtigt. Nur ich habe keine ahnung wie. Zumindest kriege ich meine Achsenstriche mit dem Befehl nicht hin. Nur wenn ich diese konvertierung sein lasse dann kommt ein akzeptabler Ergebniss raus. nach meine Logik müßte ich aber die Konvertierung DPtoLP vornehmen. Na ja ich weiß nicht ....

    Danke danke ,und falls du noch was für mich hast freue ich mich
    Gruß bolilein


Anmelden zum Antworten