C++ Kurve darstellen

Gast #509978
Lesenswert?

Linux oder Windows?

Am einfachsten gehts mit Gnuplot. Zuerst Werte in Datei schreiben und 
dann Gnuplot mit 'ner Kommandodatei aufrufen.

Für Windows gibts mehrere Open-Source-Projekte, z.B.:

http://www.codeproject.com/miscctrl/pgllib.asp

Auf der Seite gibts noch mehr.

Falls Du die Qt-Bibliothek benutzen willst kannst Du Dir das mal 
anschauen:

http://qwt.sourceforge.net/
http://www.slac.stanford.edu/grp/ek/hippodraw/index.html
Gast #510309
Lesenswert?

Danke Xenu,

ich möchte das ganze unter Windows XP machen.
Ich verwende als Programmiertool Microsoft Visual C++ .NET 2003 bzw. 
2005.
Hast du das ganze mal zum laufen gebracht?
Wie müsste ich den Code z.B. in meine WinForms-Anwendung (.NET) 
einbinden?
Gast #510576
Lesenswert?

Mit GDI+ lässt sich das ganze auch ziemlich einfach ohne zusätzliche 
Komponenten erledigen
(das ganze am besten in einem eigenen UserControl)
Beispiel ist C#
1
void UserControl_Paint(object sender, PaintEventArgs e) {
2
  // falls notwendig Hintergrund füllen
3
  e.Graphics.FillRectangle(SystemBrushes.Control, ClientRectangle)
4

5
  // Transformationen
6
  // Ursprung in die linke untere Ecke
7
  e.Graphics.TranslateTransform(0.0f, ClientSize.Height)
8
  // Breite und Höhe passend zu den Daten skalieren und spiegeln
9
  e.Graphics.ScaleTransform(ClientSize.Width / NUMPOINTS, 
10
     -ClientSize.Height / MAXTEMP);
11

12
  // values ist hier ein Array mit PointF
13
  // die Strichbbreite des Pens müsste eigentlich auch skaliert werden
14
  for (int i = 0; i < NUMPOINTS - 1; i++) {
15
      e.Graphics.DrawLine(Pens.Black, values[i], values[i + 1]);
16
  }
17
}
Gast #511099
Lesenswert?

Danke ich habs mir mal heruntergeladen.
Aber leider weiss ich nicht wie ich das ganze einbinden könnte.
So ein misst seit ein paar Tagen sitze ich vor dem PC und suche im Netz 
geeignete Sachen, mit dem ich eine Temperaturkurve oder z.B. 
luftdruckkurve auf dem PC darstellen lassen kann.
Irgendwie gibt es für Borland builder C++ bzw. Visual C++ .NET nix 
gescheites. Für jede weitere Anregung bin ich sehr dankbar!
Gast #511284
Lesenswert?

Also das .NET ist so ein kompilzierter Scheiss.
Vor ein paar Jahren habe ich alles mit dem Borland Builder C++ 
realisiert.
Ich brauch nur mal ein kleines Beispiel mit dem ich eine Temperaturkurve 
darstellen lassen kann. Ich verwende WinForms (C#,C++). Also KEIN MFC.
Gast #513592
Lesenswert?

Willst was ganz einfaches ... brauchst du MFC
Wie im Folgenden zu sehen ist, wird ganz einfach ein array mit 
Verbindungslinie LineTo(..) gezeichnet. Die Skala werden mit der größten 
und kleinsten Zahl beschriftet.

Ich habe mal gelesen, dass sich auch irgendwie die plot-Funktion von 
Matlab als Bibl. in C++ einbinden lassen. Stimmt das, oder hab ich was 
falsch verstanden.
1
//Dateiname: GraphOut.h
2

3
#include <math.h>
4
///////////////////////////////////////////////////////////////
5
// Funktionsplotter aus array Daten
6
//  double data[]={0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1,0,4,6,7,8,7};
7
//
8
//
9
//  GraphOut Graph1;
10
//  Graph1.Graph_Background(pDC);
11
//  Graph1.d2Graph(pDC,data,(sizeof(data)/sizeof(data[0])));
12
///////////////////////////////////////////////////////////////
13
class GraphOut
14
{
15
protected:
16
  int width;
17
  int height;
18
  int resolution;
19

20
public:
21
  Graph_Background(CDC* pDC);
22
  d2Graph(CDC* pDC, double data[],int dataSize);
23
};
24

25

26
GraphOut::d2Graph(CDC* pDC, double data[],int dataSize)
27
{
28

29
  // Konstruktor
30
  double xmin=width*0.1;
31
  double xmax=width*0.9;
32
  double ymin=height*0.1;
33
  double ymax=height*0.9;
34
  pDC->MoveTo(xmin,ymin+(ymax-ymin)/2);
35

36
  double DataValueMax = 0.0;
37
  double DataValueMin = 0.0;
38
  for(int x=0;x<=dataSize;x++)
39
  {
40
    if(data[x]>DataValueMax)
41
    {
42
      DataValueMax=data[x];
43
    }
44
  
45
    if(data[x]<DataValueMin)
46
    {
47
      DataValueMin=data[x];
48
    }
49
  }
50

51
  CPen PenRedSolid;
52
  PenRedSolid.CreatePen(PS_SOLID,2,RGB(255,0,0));
53
  pDC->SelectObject(&PenRedSolid);
54
  for(x=0;x<=dataSize;x++)
55
  {
56
    pDC->LineTo(
57
      (xmin+x*(xmax-xmin)/dataSize),
58
      (ymin+(ymax-ymin)/2-data[x]*(ymax-ymin)/(DataValueMax-DataValueMin)));
59
  }
60

61
  CString ValMax,ValMin;
62
  CRect rect_topleft(xmin*0.0,ymin*0.85,xmin*0.95,ymin*2);
63
  CRect rect_bottomleft(xmin*0.0,ymax*0.97,xmin*0.95,ymax*1.1);
64
  
65
  ValMax.Format("%f",DataValueMax);
66
  ValMin.Format("%f",DataValueMin);
67

68
  pDC->DrawText(
69
    ValMax,
70
    rect_topleft,
71
    DT_RIGHT);
72
  pDC->DrawText(
73
    ValMin,
74
    rect_bottomleft,
75
    DT_RIGHT);
76
  
77
}
78

79
GraphOut::Graph_Background(CDC* pDC)
80
{
81
  // Draw Background Tektronix Style
82
  /////////////////////////
83
  // Fenstergröße ermitteln (getWindowRect)
84
  // Koordinatensystem anpassen
85
  // Zeichnen
86
  /////////////////////////
87

88
  CPen PenBlackSolid;
89
  CPen PenBlackShortDash;
90
  CPen PenRedSolid;
91
  PenBlackSolid.CreatePen(PS_SOLID,5,RGB(0,0,0));
92
  PenBlackShortDash.CreatePen(PS_DOT,1,RGB(0,0,0));
93
  PenRedSolid.CreatePen(PS_SOLID,2,RGB(255,0,0));
94

95
  CRect r;
96
  HWND hWnd;
97
  hWnd = GetActiveWindow();
98
  GetClientRect(hWnd, &r);
99

100
  width = r.right;
101
  height = r.bottom;
102

103
  int xmin = r.left;
104
  int xmax = r.right;
105
  int ymin = r.top;
106
  int ymax = r.bottom;
107

108
  // Rahmen
109
  pDC->SelectObject(&PenBlackSolid);
110
  pDC->MoveTo((int)width*0.1,(int)height*0.1);
111
  pDC->LineTo((int)width*0.9,(int)height*0.1);
112
  pDC->LineTo((int)width*0.9,(int)height*0.9);
113
  pDC->LineTo((int)width*0.1,(int)height*0.9);
114
  pDC->LineTo((int)width*0.1,(int)height*0.1);
115

116
  // Skala
117
  pDC->SelectObject(&PenBlackShortDash);
118
  pDC->MoveTo((int)width*0.1,(int)height*0.5);
119
  pDC->LineTo((int)width*0.9,(int)height*0.5);
120
  pDC->MoveTo((int)width*0.5,(int)height*0.1);
121
  pDC->LineTo((int)width*0.5,(int)height*0.9);
122

123
}
Gast #513654
Lesenswert?

1
void NameView::OnDraw(CDC* pDC)
2
{
3
  NameDoc* pDoc = GetDocument();
4
  ASSERT_VALID(pDoc);
5

6
  // ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten hinzufügen
7

8
  double data[]={0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1,0,4,6,7,8,7};
9

10
  GraphOut Graph1;
11
  Graph1.Graph_Background(pDC);
12
  Graph1.d2Graph(pDC,data,(sizeof(data)/sizeof(data[0])));
13

14
}

du kannst/musst diesen Befehl in OnDraw ausführen. pDC ist das Ziel wo 
gezeichnet wird.
NameView - Name ist der Name deines Projektes - View ist festgelegt

data wird als Zeiger übergeben. Deshalb wird die Größe 
sizeof(data)/sizeof(data[0]) als weiterer Parameter übergeben.

Ich empfehle erst einmal
http://www.uni-trier.de/urt/user/baltes/docs/vcpp/vcpp6/vcpp6.pdf
Gast #513674
Lesenswert?

Jetzt erscheint diese Fehlermeldung.
Ich habe es so gemacht :

{
  NameDoc* pDoc = GetDocument();
  ASSERT_VALID(pDoc);

  // ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten 
hinzufügen

  double data[]={0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1,0,4,6,7,8,7};

  GraphOut Graph1;
  Graph1.Graph_Background(pDC);
  Graph1.d2Graph(pDC,data,(sizeof(data)/sizeof(data[0])));

}
Angehängte Dateien:
Gast #513692
Lesenswert?

Schau mal
//Dateiname: GraphOut.h
Du kopierst den Code von oben in eine header Datei.
Dann bindest du die ein. Dadurch wird die Klasse vor dem eigentlichen 
Quellcode eingefügt.

error C2065: 'GraphOut' : nichtdeklarierter Bezeichner
GraphOut ist nicht deklariert, weil keine header Datei eingebunden in 
der das deklariert ist

error C2146: Syntaxfehler : Fehlendes ';' vor Bezeichner 'Graph1'
resultiert aus vorherigem Fehler. Ansonsten wäre GraphOut die Klasse und 
Graph1 erbt halt alles aus GraphOut -> Objektorientiert

error C2065: 'Graph1' : nichtdeklarierter Bezeichner
Graph1 wurde durch vorhergehende beide Fehler nicht erzeugt

und so weiter

Aber ich vermute, dass du nicht die notwendige Erfahrung in Sachen 
OOP,MFC u.ä. hast. Dieses Uni-Trier Skript scheint ganz brauchbar
Gast #514760
Lesenswert?

Danke für den Link.
Ich habe jetzt mal ein neues Projekt erstellt.

Dieser Code befindet sich in meiner Test.cpp Datei.
Ich habe auf meinem Formular ein Button plaziert.
Wenn ich den Button drücke, dann soll OnDraw ausgeführt werden.
Wie rufe ich dies in der Button Routine aus?

void CView::OnDraw(CDC* pDC)
{

  double data[]={0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1,0,4,6,7,8,7};

  GraphOut Graph1;
  Graph1.Graph_Background(pDC);
  Graph1.d2Graph(pDC,data,(sizeof(data)/sizeof(data[0])));
  CView* t;
  //t->OnDraw
}



void CTestDlg::OnButton1()
{
  // TODO: Code für die Behandlungsroutine der 
Steuerelement-Benachrichtigung hier einfügen
  //MessageBox("Test","Info", MB_ICONEXCLAMATION);


}

Brauche ich eigentlich dies hier?
  NameDoc* pDoc = GetDocument();
  ASSERT_VALID(pDoc);
Persönliche Seite #514800
Lesenswert?

Ich glaube, du musst erstmal verstehen, wass es mit Objektorientierter 
Programmierung auf sich hat...

Um auf deine "eigene" Klasse "GraphOut" zugreifen zu können, musst du 
sie deklarieren. (Wie oben gezeigt)
Anschließend musst du sie in die .cpp datei einbinden. Entweder 
'reinkopieren, oder per .h Datei.


>Wenn ich den Button drücke, dann soll OnDraw ausgeführt werden.
Und hier wiederum solltest du ersteinmal nachvollziehen, wie die Windows 
Programmierung per MFC abläuft. (Zugegebenermaßen ist das nicht grad 
sehr einfach, aber, soweit ich das richtig verstanden hab, das 
einfachste zur Zeit um Windows-Programme schreiben zu können).

"On..." Methoden (Funktionen...) kannst du nicht aufrufen. Bzw, du 
solltest es nicht tun.
Diese Methoden werden mit Windows-Messages verknüpft (Nachrichten, die 
Windows an dein Programm schickt) und somit aufgerufen, wenn die 
passende Windows-Message eintrifft.

Wird dein Programmfenster zum Beispiel verschoben, oder maximiert, so 
wird OnDraw aufgerufen, um die komplette Fenster"oberfläche" zu 
zeichnen.

Als Hinweis: Es ist dennoch möglich, ein neues Zeichnen der Oberfläche 
zu erzwingen. Die Klasse CView (wovon "NameView" in deinem Falle 
abgeleitet ist) hat hierfür die Methode "Invalidate();". Da du dich 
privat in der CView Klasse, bzw in einer Ableitung der CView Klasse 
befindest, reicht ein einfaches "Invalidate();" um ein erneutes Zeichnen 
zu erzwingen.

PS: Habe selber gerade erst angefangen, mir die MFC anzueignen, also 
Nachsicht bitte ;)
Gast #516779
Lesenswert?

Mit Microsoft Visual Studio 2005 C++ .NET habe ich mal ein kleines 
Projekt angefangen. Mit DrawLine möchte ich den Temperaturverlauf in 
einem pictureBox darstellen.
Deiser DrawLine Funktion muss ich ja einen Anfangswert für X und Y 
eintragen und einen Endwert für X und Y. Irgendwie haut das bei mir 
nicht so hin.
Angehängte Dateien:
Gast #516794
Lesenswert?

Wenn
1
for(x=0;x<=dataSize;x++) { 
2
  g->DrawLine(System::Drawing::Pens::Black,x,data[x],x+1,data[x]);
3
}
z.B. mit data[] = { 1, 2, 3, 4 } verwendet wird kommt
1
statt \    sowas  -     raus      
2
       \           -
3
        \           -
4
         \           -
Zweites Problem (ausser data ist als int data[101] definiert) ist die 
Schleifenbedingung <= statt <
1
for(x=0; x < dataSize - 1; x++) {     
2
  g->DrawLine(System::Drawing::Pens::Black, x, data[x], x + 1, data[x + 1]);
3
}

  
Gast #516813
Lesenswert?

Der Nullpunkt ist ja links oben. Wenn ich einen Temperaturverlauf 
anzeigen lassen möchte,
dann muss ich ja links unten anfangen. Wie kann ich dies mit DrawLine 
realisieren. Ich komme mit dieser DrawLine Funktion durcheinander.
Kann ich eigentlich nur ein PIXEL anzeigen lassen? Wie geht das?

(C°)
|
|       .
|      . .
|  ....   .
|.         .....
-----------------> (time)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren