Forum: PC-Programmierung C++ Kurve darstellen


von Devil (Gast)


Lesenswert?

Hallo,

ich suche ein Beispiel in C++, womit man die Daten von der RS232
auf dem PC grafisch darstellen lassen kann.
z.B. Temperaturmesswert von einem Controller.
Die Y-Achse Temperaturwerte und X-Achse Zeit.
Hat jemand schon mal so etwas gemacht?

von Xenu (Gast)


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

von Devil (Gast)


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?

von Devil (Gast)


Lesenswert?

Ich habe mir mal den Code heruntergeladen:
>>http://www.codeproject.com/miscctrl/pgllib.asp

Also ich kann da keine Grafik sehen. Ich habe das ganze mal mit Visual 
C++ 2005 .NET ausgeführt.

von Devil (Gast)


Lesenswert?

Gibt es auch eine einfachere Variante?

von Devil (Gast)


Lesenswert?

Im Netz habe iich diesen Link gefunden.
>>http://www.fred.net/brv/chart/

Hat jemand damit schon mal was in WIndows (C++) gemacht?

von arc (Gast)


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
}

von Devil (Gast)


Lesenswert?

Gibt es eine C++ Klasse bzw. Projekt mit dem man sowohl in Borland 
Builder C++ als auch in Visual Studio ein 2D plot zeichnen lassen kann?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

gnuplot müsste sich mit beiden übersetzen lassen, weiß aber nicht, ob 
das überhaupt C++ und nicht gar nur simples C ist.

von Devil (Gast)


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!

von Devil (Gast)


Lesenswert?

Ich habe mir den Source Code 
>>http://www.codeproject.com/miscctrl/pgllib.asp
ja heruntergeladen und mit Visual Studio C++ 2005 .NET gestartet.
Das funktioniert ja überhaupt nicht. Gibt es hier in diesem Forum jemand 
der dieses Projekt zum laufen gebracht hat?
Ich verzweifle noch. Egal was ich mache es tut nichts.

von Devil (Gast)


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.

von Christian R. (supachris)


Lesenswert?

Ich nehm immer PlotLab: http://www.mitov.com/html/plotlab.html

von arc (Gast)


Lesenswert?

> Also das .NET ist so ein kompilzierter Scheiss.
Das o.a. Beispiel ist .NET (fehlt nur noch die Beschriftung, Achsen 
etc., die aber ebenso einfach erstellt werden können)

von Devil (Gast)


Lesenswert?

Hallo arc, welche Beispiel meinst du?
Das hier >>http://www.codeproject.com/miscctrl/pgllib.asp
Wenn ja weisst du wie man das ganze in die WinForms Umgebung einbinden 
kann?
Also ich habe mit C++ .NET eine WinForms Anwendung erstellt. Wenn ich 
zum Beispiel einen Button da drücke, dann soll mir erst mal die Grafik 
erscheinen.
Wie binde ich das ganze ein?????

von arc (Gast)


Lesenswert?

Wenn's kein eigenes UserControl werden soll, würde ich statt des 
genannten eher eine reine .NET-Komponente nehmen.
http://www.codeproject.com/csharp/ZedGraph.asp
bzw.
http://zedgraph.org/wiki/index.php?title=Main_Page

von etsmart (Gast)


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
}

von Devil (Gast)


Angehängte Dateien:

Lesenswert?

Hallo etsmart,

danke für den Code. Ich habe diesen gleich mal mit Visual C++ 6.0 (MFC) 
getestet. Es erscheint immer eine Fehlermeldung:
pDC --> nicht deklarierter Bezeichner

von Ich (Gast)


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

von Devil (Gast)


Angehängte Dateien:

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])));

}

von etsmart (Gast)


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

von Archie (Gast)


Lesenswert?

Hier findest du eine simple Anleitung:
http://www.functionx.com/visualc/gdi/lines.htm

von Devil (Gast)


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);

von Simon K. (simon) Benutzerseite


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 ;)

von Devil (Gast)


Angehängte Dateien:

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.

von arc (Gast)


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
}

  

von Devil (Gast)


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)

von C++ (Gast)


Lesenswert?

Hier steht doch schon alles:
http://www.functionx.com/visualc/gdi/lines.htm

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.