www.mikrocontroller.net

Forum: PC-Programmierung C++ Kurve darstellen


Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Xenu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es auch eine einfachere Variante?

Autor: Devil (Gast)
Datum:

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

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

Autor: arc (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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#
void UserControl_Paint(object sender, PaintEventArgs e) {
  // falls notwendig Hintergrund füllen
  e.Graphics.FillRectangle(SystemBrushes.Control, ClientRectangle)

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

  // values ist hier ein Array mit PointF
  // die Strichbbreite des Pens müsste eigentlich auch skaliert werden
  for (int i = 0; i < NUMPOINTS - 1; i++) {
      e.Graphics.DrawLine(Pens.Black, values[i], values[i + 1]);
  }
}

Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

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

Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich nehm immer PlotLab: http://www.mitov.com/html/plotlab.html

Autor: arc (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?????

Autor: arc (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: etsmart (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
//Dateiname: GraphOut.h

#include <math.h>
///////////////////////////////////////////////////////////////
// Funktionsplotter aus array Daten
//  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])));
///////////////////////////////////////////////////////////////
class GraphOut
{
protected:
  int width;
  int height;
  int resolution;

public:
  Graph_Background(CDC* pDC);
  d2Graph(CDC* pDC, double data[],int dataSize);
};


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

  // Konstruktor
  double xmin=width*0.1;
  double xmax=width*0.9;
  double ymin=height*0.1;
  double ymax=height*0.9;
  pDC->MoveTo(xmin,ymin+(ymax-ymin)/2);

  double DataValueMax = 0.0;
  double DataValueMin = 0.0;
  for(int x=0;x<=dataSize;x++)
  {
    if(data[x]>DataValueMax)
    {
      DataValueMax=data[x];
    }
  
    if(data[x]<DataValueMin)
    {
      DataValueMin=data[x];
    }
  }

  CPen PenRedSolid;
  PenRedSolid.CreatePen(PS_SOLID,2,RGB(255,0,0));
  pDC->SelectObject(&PenRedSolid);
  for(x=0;x<=dataSize;x++)
  {
    pDC->LineTo(
      (xmin+x*(xmax-xmin)/dataSize),
      (ymin+(ymax-ymin)/2-data[x]*(ymax-ymin)/(DataValueMax-DataValueMin)));
  }

  CString ValMax,ValMin;
  CRect rect_topleft(xmin*0.0,ymin*0.85,xmin*0.95,ymin*2);
  CRect rect_bottomleft(xmin*0.0,ymax*0.97,xmin*0.95,ymax*1.1);
  
  ValMax.Format("%f",DataValueMax);
  ValMin.Format("%f",DataValueMin);

  pDC->DrawText(
    ValMax,
    rect_topleft,
    DT_RIGHT);
  pDC->DrawText(
    ValMin,
    rect_bottomleft,
    DT_RIGHT);
  
}

GraphOut::Graph_Background(CDC* pDC)
{
  // Draw Background Tektronix Style
  /////////////////////////
  // Fenstergröße ermitteln (getWindowRect)
  // Koordinatensystem anpassen
  // Zeichnen
  /////////////////////////

  CPen PenBlackSolid;
  CPen PenBlackShortDash;
  CPen PenRedSolid;
  PenBlackSolid.CreatePen(PS_SOLID,5,RGB(0,0,0));
  PenBlackShortDash.CreatePen(PS_DOT,1,RGB(0,0,0));
  PenRedSolid.CreatePen(PS_SOLID,2,RGB(255,0,0));

  CRect r;
  HWND hWnd;
  hWnd = GetActiveWindow();
  GetClientRect(hWnd, &r);

  width = r.right;
  height = r.bottom;

  int xmin = r.left;
  int xmax = r.right;
  int ymin = r.top;
  int ymax = r.bottom;

  // Rahmen
  pDC->SelectObject(&PenBlackSolid);
  pDC->MoveTo((int)width*0.1,(int)height*0.1);
  pDC->LineTo((int)width*0.9,(int)height*0.1);
  pDC->LineTo((int)width*0.9,(int)height*0.9);
  pDC->LineTo((int)width*0.1,(int)height*0.9);
  pDC->LineTo((int)width*0.1,(int)height*0.1);

  // Skala
  pDC->SelectObject(&PenBlackShortDash);
  pDC->MoveTo((int)width*0.1,(int)height*0.5);
  pDC->LineTo((int)width*0.9,(int)height*0.5);
  pDC->MoveTo((int)width*0.5,(int)height*0.1);
  pDC->LineTo((int)width*0.5,(int)height*0.9);

}

Autor: Devil (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void NameView::OnDraw(CDC* pDC)
{
  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])));

}

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/...

Autor: Devil (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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])));

}

Autor: etsmart (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Archie (Gast)
Datum:

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

Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: Devil (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: arc (Gast)
Datum:

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

  

Autor: Devil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: C++ (Gast)
Datum:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.