Fehler Mehrdeutiger Bezeichner

Also nur Debug. Naja.

Wiedermal, es ist wirklich nicht nötig, die Dateien in die Compilerverzeichnisse zu kopieren.
Da, wo deine start.cpp ist, reicht.

Jetzt öffnest du in VS die Projekteinstellungen - Linker
Dort gibt es irgendwo "Zusätzliche Abhängigkeiten" (oder so ähnlich).
Da kommen die ganzen lib-Dateinamen rein.
 
Jetzt meckert er
Code:
1>------ Erstellen gestartet: Projekt: grafik_c++, Konfiguration: Debug Win32 ------
1>LINK : fatal error LNK1104: Datei "flktkformsd.lib" kann nicht geöffnet werden.
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
, aber fltkformsd.lib ist im Verzeichnis vorhanden.
 
Zuletzt bearbeitet:
@sheel: Du wurschtelst da am falschen Problem herum.

1. Ja, es ist unnötig die Dateien ins Compilerverzeichnis zu packen. Besser ist es diese irgendwo anders zu "installieren" und diesen Pfad dann als "zusätzlichen Linkerpfad" in den Projekteinstellungen anzugeben.

2. es gab nie ein Problem mit den fltk Bibliotheken.

3. der Fehler ist immer noch das die Implementierung fehlt. Diese findet sich in der Simple_Window.cpp welche in dem Buch dabei ist. Diese muß mit ins Projekt. Das gleiche gilt für die Graph.cpp usw.

Gruß
 
Ich habe nun die angesprochenen Dateien eingebunden
C++:
//
// This is example code from Chapter 12.3 "A first example" of
// "Programming -- Principles and Practice Using C++" by Bjarne Stroustrup
//

#include "Simple_window.h"    // get access to our window library
#include "Graph.h"            // get access to our graphics library facilities
#include "Simple_window.cpp"
#include "Graph.cpp"

//------------------------------------------------------------------------------

int main()
{
    using namespace Graph_lib;   // our graphics facilities are in Graph_lib

    Point tl(100,100);           // to become top left  corner of window

    Simple_window win(tl,600,400,"Canvas");    // make a simple window

    Graph_lib::Polygon poly;                // make a shape (a polygon)

    poly.add(Point(300,200));    // add a point
    poly.add(Point(350,100));    // add another point
    poly.add(Point(400,200));    // add a third point 

    poly.set_color(Color::red);  // adjust properties of poly

    win.attach (poly);           // connect poly to the window

    win.wait_for_button();        // give control to the display engine
}

//------------------------------------------------------------------------------

Hierauf erscheint nun dieser Fehlerbericht.

Code:
1>------ Erstellen gestartet: Projekt: grafik_c++, Konfiguration: Debug Win32 ------
1>  start.cpp
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.h(45): warning C4305: 'Initialisierung': Verkürzung von 'Graph_lib::Color::Transparency' in 'char'
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.h(45): warning C4309: 'Initialisierung': Verkürzung eines konstanten Wertes
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.h(47): warning C4305: 'Initialisierung': Verkürzung von 'Graph_lib::Color::Transparency' in 'char'
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.h(47): warning C4309: 'Initialisierung': Verkürzung eines konstanten Wertes
1>c:\program files\microsoft visual studio 10.0\vc\include\gui.h(107): warning C4018: '<': Konflikt zwischen 'signed' und 'unsigned'
1>c:\program files\microsoft visual studio 10.0\vc\include\gui.h(112): warning C4018: '<': Konflikt zwischen 'signed' und 'unsigned'
1>c:\program files\microsoft visual studio 10.0\vc\include\gui.h(117): warning C4018: '<': Konflikt zwischen 'signed' und 'unsigned'
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.cpp(64): warning C4018: '<': Konflikt zwischen 'signed' und 'unsigned'
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.cpp(130): warning C4244: '=': Konvertierung von 'double' in 'int', möglicher Datenverlust
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.cpp(131): warning C4244: '=': Konvertierung von 'double' in 'int', möglicher Datenverlust
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.cpp(371): warning C4800: 'void *': Variable wird auf booleschen Wert ('True' oder 'False') gesetzt (Auswirkungen auf Leistungsverhalten möglich)
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.cpp(396): warning C4018: '>=': Konflikt zwischen 'signed' und 'unsigned'
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.h(130): warning C4018: '<': Konflikt zwischen 'signed' und 'unsigned'
1>          c:\program files\microsoft visual studio 10.0\vc\include\graph.h(130): Bei der Kompilierung der  Klassen-template der Graph_lib::Vector_ref<T>::~Vector_ref(void)-Memberfunktion
1>          with
1>          [
1>              T=Graph_lib::Button
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\gui.h(99): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "Graph_lib::Vector_ref<T>".
1>          with
1>          [
1>              T=Graph_lib::Button
1>          ]
1>start.obj : error LNK2005: "public: __thiscall Simple_window::Simple_window(struct Point,int,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (****0Simple_window@@QAE@UPoint@@HHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) ist bereits in Simple_window.obj definiert.
1>start.obj : error LNK2005: "public: bool __thiscall Simple_window::wait_for_button(void)" (?wait_for_button@Simple_window@@QAE_NXZ) ist bereits in Simple_window.obj definiert.
1>start.obj : error LNK2005: "private: static void __cdecl Simple_window::cb_next(void *,void *)" (?cb_next@Simple_window@@CAXPAX0@Z) ist bereits in Simple_window.obj definiert.
1>start.obj : error LNK2005: "private: void __thiscall Simple_window::next(void)" (?next@Simple_window@@AAEXXZ) ist bereits in Simple_window.obj definiert.
1>start.obj : error LNK2005: "protected: __thiscall Graph_lib::Shape::Shape(void)" (****0Shape@Graph_lib@@IAE@XZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "protected: void __thiscall Graph_lib::Shape::add(struct Point)" (?add@Shape@Graph_lib@@IAEXUPoint@@@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "protected: void __thiscall Graph_lib::Shape::set_point(int,struct Point)" (?set_point@Shape@Graph_lib@@IAEXHUPoint@@@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "protected: virtual void __thiscall Graph_lib::Shape::draw_lines(void)const " (?draw_lines@Shape@Graph_lib@@MBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: void __thiscall Graph_lib::Shape::draw(void)const " (?draw@Shape@Graph_lib@@QBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Shape::move(int,int)" (?move@Shape@Graph_lib@@UAEXHH@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: __thiscall Graph_lib::Line::Line(struct Point,struct Point)" (****0Line@Graph_lib@@QAE@UPoint@@0@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: void __thiscall Graph_lib::Lines::add(struct Point,struct Point)" (?add@Lines@Graph_lib@@QAEXUPoint@@0@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Lines::draw_lines(void)const " (?draw_lines@Lines@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "bool __cdecl Graph_lib::line_segment_intersect(struct Point,struct Point,struct Point,struct Point,struct Point &)" (?line_segment_intersect@Graph_lib@@YA_NUPoint@@000AAU2@@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: void __thiscall Graph_lib::Polygon::add(struct Point)" (?add@Polygon@Graph_lib@@QAEXUPoint@@@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Polygon::draw_lines(void)const " (?draw_lines@Polygon@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Open_polyline::draw_lines(void)const " (?draw_lines@Open_polyline@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Closed_polyline::draw_lines(void)const " (?draw_lines@Closed_polyline@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "void __cdecl Graph_lib::draw_mark(struct Point,char)" (?draw_mark@Graph_lib@@YAXUPoint@@D@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Marked_polyline::draw_lines(void)const " (?draw_lines@Marked_polyline@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Rectangle::draw_lines(void)const " (?draw_lines@Rectangle@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: __thiscall Graph_lib::Circle::Circle(struct Point,int)" (****0Circle@Graph_lib@@QAE@UPoint@@H@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: struct Point __thiscall Graph_lib::Circle::center(void)const " (?center@Circle@Graph_lib@@QBE?AUPoint@@XZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Circle::draw_lines(void)const " (?draw_lines@Circle@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Ellipse::draw_lines(void)const " (?draw_lines@Ellipse@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Text::draw_lines(void)const " (?draw_lines@Text@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: __thiscall Graph_lib::Axis::Axis(enum Graph_lib::Axis::Orientation,struct Point,int,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (****0Axis@Graph_lib@@QAE@W4Orientation@01@UPoint@@HHV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Axis::draw_lines(void)const " (?draw_lines@Axis@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: void __thiscall Graph_lib::Axis::set_color(struct Graph_lib::Color)" (?set_color@Axis@Graph_lib@@QAEXUColor@2@@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Axis::move(int,int)" (?move@Axis@Graph_lib@@UAEXHH@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: __thiscall Graph_lib::Function::Function(double (__cdecl*)(double),double,double,struct Point,int,double,double)" (****0Function@Graph_lib@@QAE@P6ANN@ZNNUPoint@@HNN@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "bool __cdecl Graph_lib::can_open(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?can_open@Graph_lib@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "enum Graph_lib::Suffix::Encoding __cdecl Graph_lib::get_encoding(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?get_encoding@Graph_lib@@YA?AW4Encoding@Suffix@1@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: __thiscall Graph_lib::Image::Image(struct Point,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,enum Graph_lib::Suffix::Encoding)" (****0Image@Graph_lib@@QAE@UPoint@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@W4Encoding@Suffix@1@@Z) ist bereits in Graph.obj definiert.
1>start.obj : error LNK2005: "public: virtual void __thiscall Graph_lib::Image::draw_lines(void)const " (?draw_lines@Image@Graph_lib@@UBEXXZ) ist bereits in Graph.obj definiert.
1>Simple_window.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall Graph_lib::Window::attach(class Graph_lib::Widget &)" (?attach@Window@Graph_lib@@QAEXAAVWidget@2@@Z)" in Funktion ""public: __thiscall Simple_window::Simple_window(struct Point,int,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (****0Simple_window@@QAE@UPoint@@HHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)".
1>start.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: void __thiscall Graph_lib::Window::attach(class Graph_lib::Widget &)" (?attach@Window@Graph_lib@@QAEXAAVWidget@2@@Z)".
1>Simple_window.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: __thiscall Graph_lib::Window::Window(struct Point,int,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (****0Window@Graph_lib@@QAE@UPoint@@HHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)" in Funktion ""public: __thiscall Simple_window::Simple_window(struct Point,int,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (****0Simple_window@@QAE@UPoint@@HHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)".
1>start.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: __thiscall Graph_lib::Window::Window(struct Point,int,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (****0Window@Graph_lib@@QAE@UPoint@@HHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)".
1>Simple_window.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""protected: virtual void __thiscall Graph_lib::Window::draw(void)" (?draw@Window@Graph_lib@@MAEXXZ)".
1>start.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""protected: virtual void __thiscall Graph_lib::Window::draw(void)" (?draw@Window@Graph_lib@@MAEXXZ)".
1>Simple_window.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual void __thiscall Graph_lib::Button::attach(class Graph_lib::Window &)" (?attach@Button@Graph_lib@@UAEXAAVWindow@2@@Z)".
1>start.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual void __thiscall Graph_lib::Button::attach(class Graph_lib::Window &)" (?attach@Button@Graph_lib@@UAEXAAVWindow@2@@Z)".
1>C:\Users\Markus\Documents\Visual Studio 2010\Projects\grafik_c++\Debug\grafik_c++.exe : fatal error LNK1120: 4 nicht aufgelöste externe Verweise.
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
 
Nein, Du solltst die Dateien zu deinem Visual Studio Projekt hinzufügen.

.cpp werden nicht mit include eingebunden, weil sonst nämlich Linkerfehler auftreten... ;-]

Gruß
 
Wenn ich sie rausnehme (die Includes) erscheint diese Meldung:
Code:
1>------ Erstellen gestartet: Projekt: grafik_c++, Konfiguration: Debug Win32 ------
1>  start.cpp
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.h(45): warning C4305: 'Initialisierung': Verkürzung von 'Graph_lib::Color::Transparency' in 'char'
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.h(45): warning C4309: 'Initialisierung': Verkürzung eines konstanten Wertes
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.h(47): warning C4305: 'Initialisierung': Verkürzung von 'Graph_lib::Color::Transparency' in 'char'
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.h(47): warning C4309: 'Initialisierung': Verkürzung eines konstanten Wertes
1>c:\program files\microsoft visual studio 10.0\vc\include\gui.h(107): warning C4018: '<': Konflikt zwischen 'signed' und 'unsigned'
1>c:\program files\microsoft visual studio 10.0\vc\include\gui.h(112): warning C4018: '<': Konflikt zwischen 'signed' und 'unsigned'
1>c:\program files\microsoft visual studio 10.0\vc\include\gui.h(117): warning C4018: '<': Konflikt zwischen 'signed' und 'unsigned'
1>c:\program files\microsoft visual studio 10.0\vc\include\graph.h(130): warning C4018: '<': Konflikt zwischen 'signed' und 'unsigned'
1>          c:\program files\microsoft visual studio 10.0\vc\include\graph.h(130): Bei der Kompilierung der  Klassen-template der Graph_lib::Vector_ref<T>::~Vector_ref(void)-Memberfunktion
1>          with
1>          [
1>              T=Graph_lib::Button
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\gui.h(99): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "Graph_lib::Vector_ref<T>".
1>          with
1>          [
1>              T=Graph_lib::Button
1>          ]
1>Simple_window.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall Graph_lib::Window::attach(class Graph_lib::Widget &)" (?attach@Window@Graph_lib@@QAEXAAVWidget@2@@Z)" in Funktion ""public: __thiscall Simple_window::Simple_window(struct Point,int,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (****0Simple_window@@QAE@UPoint@@HHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)".
1>Simple_window.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: __thiscall Graph_lib::Window::Window(struct Point,int,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (****0Window@Graph_lib@@QAE@UPoint@@HHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)" in Funktion ""public: __thiscall Simple_window::Simple_window(struct Point,int,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (****0Simple_window@@QAE@UPoint@@HHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)".
1>Simple_window.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""protected: virtual void __thiscall Graph_lib::Window::draw(void)" (?draw@Window@Graph_lib@@MAEXXZ)".
1>start.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""protected: virtual void __thiscall Graph_lib::Window::draw(void)" (?draw@Window@Graph_lib@@MAEXXZ)".
1>Simple_window.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual void __thiscall Graph_lib::Button::attach(class Graph_lib::Window &)" (?attach@Button@Graph_lib@@UAEXAAVWindow@2@@Z)".
1>C:\Users\Markus\Documents\Visual Studio 2010\Projects\grafik_c++\Debug\grafik_c++.exe : fatal error LNK1120: 4 nicht aufgelöste externe Verweise.
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
 
Zuletzt bearbeitet:
Ich hatte Graph.cpp und Simple_window.cpp hinzugefügt und in meinen Materialen existiert keine Graph_lib.cpp.
Ach, ich sehe gerade anhand der Warnungen, die Graph_lib Methoden sollten in der Graph.cpp definiert sein. Sicher, dass du die dem Projekt hinzugefügt hast?

Und schau doch einfach nach, ob die fehlenden Methoden dort drin sind.

Ohne den relevanten Code können wir auch nur raten...

Gruß
 
Der Code von Graph.cpp
C++:
//
// This is a GUI support code to the chapters 12-16 of the book
// "Programming -- Principles and Practice Using C++" by Bjarne Stroustrup
//

#include <FL/Fl_GIF_Image.H>
#include <FL/Fl_JPEG_Image.H>
#include "Graph.h"

//------------------------------------------------------------------------------

namespace Graph_lib {

//------------------------------------------------------------------------------

Shape::Shape() : 
    lcolor(fl_color()),      // default color for lines and characters
    ls(0),                   // default style
    fcolor(Color::invisible) // no fill
{}

//------------------------------------------------------------------------------

void Shape::add(Point p)     // protected
{
    points.push_back(p);
}

//------------------------------------------------------------------------------

void Shape::set_point(int i,Point p)        // not used; not necessary so far
{
    points[i] = p;
}

//------------------------------------------------------------------------------

void Shape::draw_lines() const
{
    if (color().visibility() && 1<points.size())    // draw sole pixel?
        for (unsigned int i=1; i<points.size(); ++i)
            fl_line(points[i-1].x,points[i-1].y,points[i].x,points[i].y);
}

//------------------------------------------------------------------------------

void Shape::draw() const
{
    Fl_Color oldc = fl_color();
    // there is no good portable way of retrieving the current style
    fl_color(lcolor.as_int());            // set color
    fl_line_style(ls.style(),ls.width()); // set style
    draw_lines();
    fl_color(oldc);      // reset color (to previous)
    fl_line_style(0);    // reset line style to default
}

//------------------------------------------------------------------------------


void Shape::move(int dx, int dy)    // move the shape +=dx and +=dy
{
    for (int i = 0; i<points.size(); ++i) {
        points[i].x+=dx;
        points[i].y+=dy;
    }
}

//------------------------------------------------------------------------------

Line::Line(Point p1, Point p2)    // construct a line from two points
{
    add(p1);    // add p1 to this shape
    add(p2);    // add p2 to this shape
}

//------------------------------------------------------------------------------

void Lines::add(Point p1, Point p2)
{
    Shape::add(p1);
    Shape::add(p2);
}

//------------------------------------------------------------------------------

// draw lines connecting pairs of points
void Lines::draw_lines() const
{
    if (color().visibility())
        for (int i=1; i<number_of_points(); i+=2)
            fl_line(point(i-1).x,point(i-1).y,point(i).x,point(i).y);
}

//------------------------------------------------------------------------------

// does two lines (p1,p2) and (p3,p4) intersect?
// if se return the distance of the intersect point as distances from p1
inline pair<double,double> line_intersect(Point p1, Point p2, Point p3, Point p4, bool& parallel) 
{
    double x1 = p1.x;
    double x2 = p2.x;
    double x3 = p3.x;
    double x4 = p4.x;
    double y1 = p1.y;
    double y2 = p2.y;
    double y3 = p3.y;
    double y4 = p4.y;

    double denom = ((y4 - y3)*(x2-x1) - (x4-x3)*(y2-y1));
    if (denom == 0){
        parallel= true;
        return pair<double,double>(0,0);
    }
    parallel = false;
    return pair<double,double>( ((x4-x3)*(y1-y3) - (y4-y3)*(x1-x3))/denom,
                                ((x2-x1)*(y1-y3) - (y2-y1)*(x1-x3))/denom);
}

//------------------------------------------------------------------------------

//intersection between two line segments
//Returns true if the two segments intersect,
//in which case intersection is set to the point of intersection
bool line_segment_intersect(Point p1, Point p2, Point p3, Point p4, Point& intersection){
   bool parallel;
   pair<double,double> u = line_intersect(p1,p2,p3,p4,parallel);
   if (parallel || u.first < 0 || u.first > 1 || u.second < 0 || u.second > 1) return false;
   intersection.x = p1.x + u.first*(p2.x - p1.x);
   intersection.y = p1.y + u.first*(p2.y - p1.y);
   return true;
}

//------------------------------------------------------------------------------

void Polygon::add(Point p)
{
    int np = number_of_points();

    if (1<np) {    // check that thenew line isn't parallel to the previous one
        if (p==point(np-1)) error("polygon point equal to previous point");
        bool parallel;
        line_intersect(point(np-1),p,point(np-2),point(np-1),parallel);
        if (parallel)
            error("two polygon points lie in a straight line");
    }

    for (int i = 1; i<np-1; ++i) {    // check that new segment doesn't interset and old point
        Point ignore(0,0);
        if (line_segment_intersect(point(np-1),p,point(i-1),point(i),ignore))
            error("intersect in polygon");
    }
    

    Closed_polyline::add(p);
}

//------------------------------------------------------------------------------

void Polygon::draw_lines() const
{
    if (number_of_points() < 3) error("less than 3 points in a Polygon");
    Closed_polyline::draw_lines();
}

//------------------------------------------------------------------------------

void Open_polyline::draw_lines() const
{
    if (fill_color().visibility()) {
        fl_color(fill_color().as_int());
        fl_begin_complex_polygon();
        for(int i=0; i<number_of_points(); ++i){
            fl_vertex(point(i).x, point(i).y);
        }
        fl_end_complex_polygon();
        fl_color(color().as_int());    // reset color
    }
    
    if (color().visibility())
        Shape::draw_lines();
}

//------------------------------------------------------------------------------

void Closed_polyline::draw_lines() const
{
    Open_polyline::draw_lines();    // first draw the "open poly line part"
    // then draw closing line:
    if (color().visibility())
        fl_line(point(number_of_points()-1).x, 
        point(number_of_points()-1).y,
        point(0).x,
        point(0).y);
}

//------------------------------------------------------------------------------

void draw_mark(Point xy, char c)
{
    static const int dx = 4;
    static const int dy = 4;

    string m(1,c);
    fl_draw(m.c_str(),xy.x-dx,xy.y+dy);
}

//------------------------------------------------------------------------------

void Marked_polyline::draw_lines() const
{
    Open_polyline::draw_lines();
    for (int i=0; i<number_of_points(); ++i) 
        draw_mark(point(i),mark[i%mark.size()]);
}

//------------------------------------------------------------------------------

void Rectangle::draw_lines() const
{
    if (fill_color().visibility()) {    // fill
        fl_color(fill_color().as_int());
        fl_rectf(point(0).x,point(0).y,w,h);
        fl_color(color().as_int());    // reset color
    }

    if (color().visibility()) {    // lines on top of fill
        fl_color(color().as_int());
        fl_rect(point(0).x,point(0).y,w,h);
    }
}

//------------------------------------------------------------------------------

Circle::Circle(Point p, int rr)    // center and radius
:r(rr)
{
    add(Point(p.x-r,p.y-r));       // store top-left corner
}

//------------------------------------------------------------------------------

Point Circle::center() const
{
    return Point(point(0).x+r, point(0).y+r);
}

//------------------------------------------------------------------------------

void Circle::draw_lines() const
{
  	if (fill_color().visibility()) {	// fill
		fl_color(fill_color().as_int());
		fl_pie(point(0).x,point(0).y,r+r-1,r+r-1,0,360);
		fl_color(color().as_int());	// reset color
	}

	if (color().visibility()) {
		fl_color(color().as_int());
		fl_arc(point(0).x,point(0).y,r+r,r+r,0,360);
	}
}

//------------------------------------------------------------------------------

void Ellipse::draw_lines() const
{
   if (fill_color().visibility()) {	// fill
		fl_color(fill_color().as_int());
		fl_pie(point(0).x,point(0).y,w+w-1,h+h-1,0,360);
		fl_color(color().as_int());	// reset color
	}

	if (color().visibility()) {
		fl_color(color().as_int());
		fl_arc(point(0).x,point(0).y,w+w,h+h,0,360);
	}
}

//------------------------------------------------------------------------------

void Text::draw_lines() const
{
    int ofnt = fl_font();
    int osz = fl_size();
    fl_font(fnt.as_int(),fnt_sz);
    fl_draw(lab.c_str(),point(0).x,point(0).y);
    fl_font(ofnt,osz);
}

//------------------------------------------------------------------------------

Axis::Axis(Orientation d, Point xy, int length, int n, string lab) :
    label(Point(0,0),lab)
{
    if (length<0) error("bad axis length");
    switch (d){
    case Axis::x:
    {
        Shape::add(xy); // axis line
        Shape::add(Point(xy.x+length,xy.y));

        if (0<n) {      // add notches
            int dist = length/n;
            int x = xy.x+dist;
            for (int i = 0; i<n; ++i) {
                notches.add(Point(x,xy.y),Point(x,xy.y-5));
                x += dist;
            }
        }
        // label under the line
        label.move(length/3,xy.y+20);
        break;
    }
    case Axis::y:
    {
        Shape::add(xy); // a y-axis goes up
        Shape::add(Point(xy.x,xy.y-length));

        if (0<n) {      // add notches
            int dist = length/n;
            int y = xy.y-dist;
            for (int i = 0; i<n; ++i) {
                notches.add(Point(xy.x,y),Point(xy.x+5,y));
                y -= dist;
            }
        }
        // label at top
        label.move(xy.x-10,xy.y-length-10);
        break;
    }
    case Axis::z:
        error("z axis not implemented");
    }
}

//------------------------------------------------------------------------------

void Axis::draw_lines() const
{
    Shape::draw_lines();
    notches.draw();  // the notches may have a different color from the line
    label.draw();    // the label may have a different color from the line
}

//------------------------------------------------------------------------------

void Axis::set_color(Color c)
{
    Shape::set_color(c);
    notches.set_color(c);
    label.set_color(c);
}

//------------------------------------------------------------------------------

void Axis::move(int dx, int dy)
{
    Shape::move(dx,dy);
    notches.move(dx,dy);
    label.move(dx,dy);
}

//------------------------------------------------------------------------------

Function::Function(Fct f, double r1, double r2, Point xy,
                   int count, double xscale, double yscale)
// graph f(x) for x in [r1:r2) using count line segments with (0,0) displayed at xy
// x coordinates are scaled by xscale and y coordinates scaled by yscale
{
    if (r2-r1<=0) error("bad graphing range");
    if (count <=0) error("non-positive graphing count");
    double dist = (r2-r1)/count;
    double r = r1;
    for (int i = 0; i<count; ++i) {
        add(Point(xy.x+int(r*xscale),xy.y-int(f(r)*yscale)));
        r += dist;
    }
}

//------------------------------------------------------------------------------

bool can_open(const string& s)
// check if a file named s exists and can be opened for reading
{
    ifstream ff(s.c_str());
    return ff;
}

//------------------------------------------------------------------------------

#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))

Suffix::Encoding get_encoding(const string& s)
{
    struct SuffixMap 
    { 
        const char*      extension;
        Suffix::Encoding suffix;
    };

    static SuffixMap smap[] = {
        {".jpg",  Suffix::jpg},
        {".jpeg", Suffix::jpg},
        {".gif",  Suffix::gif},
    };

    for (int i = 0, n = ARRAY_SIZE(smap); i < n; i++)
    {
        int len = strlen(smap[i].extension);

        if (s.length() >= len && s.substr(s.length()-len, len) == smap[i].extension)
            return smap[i].suffix;
    }

    return Suffix::none;
}

//------------------------------------------------------------------------------

// somewhat over-elaborate constructor
// because errors related to image files can be such a pain to debug
Image::Image(Point xy, string s, Suffix::Encoding e)
    :w(0), h(0), fn(xy,"")
{
    add(xy);

    if (!can_open(s)) {    // can we open s?
        fn.set_label("cannot open \""+s+'\"');
        p = new Bad_image(30,20);    // the "error image"
        return;
    }

    if (e == Suffix::none) e = get_encoding(s);

    switch(e) {        // check if it is a known encoding
    case Suffix::jpg:
        p = new Fl_JPEG_Image(s.c_str());
        break;
    case Suffix::gif:
        p = new Fl_GIF_Image(s.c_str());
        break;
    default:    // Unsupported image encoding
        fn.set_label("unsupported file type \""+s+'\"');
        p = new Bad_image(30,20);    // the "error image"
    }
}

//------------------------------------------------------------------------------

void Image::draw_lines() const
{
    if (fn.label()!="") fn.draw_lines();

    if (w&&h)
        p->draw(point(0).x,point(0).y,w,h,cx,cy);
    else
        p->draw(point(0).x,point(0).y);
}

//------------------------------------------------------------------------------

} // of namespace Graph_lib
Der Code von Graph.h
C++:
//
// This is a GUI support code to the chapters 12-16 of the book
// "Programming -- Principles and Practice Using C++" by Bjarne Stroustrup
//

#ifndef GRAPH_GUARD
#define GRAPH_GUARD 1

#include <FL/fl_draw.H>
#include <FL/Fl_Image.H>
#include "Point.h"
#include "std_lib_facilities.h"


namespace Graph_lib {

// defense against ill-behaved Linux macros:
#undef major
#undef minor

//------------------------------------------------------------------------------

// Color is the type we use to represent color. We can use Color like this:
//    grid.set_color(Color::red);
struct Color {
    enum Color_type {
        red=FL_RED,
        blue=FL_BLUE,
        green=FL_GREEN,
        yellow=FL_YELLOW,
        white=FL_WHITE,
        black=FL_BLACK,
        magenta=FL_MAGENTA,
        cyan=FL_CYAN,
        dark_red=FL_DARK_RED,
        dark_green=FL_DARK_GREEN,
        dark_yellow=FL_DARK_YELLOW,
        dark_blue=FL_DARK_BLUE,
        dark_magenta=FL_DARK_MAGENTA,
        dark_cyan=FL_DARK_CYAN
    };

    enum Transparency { invisible = 0, visible=255 };

    Color(Color_type cc) :c(Fl_Color(cc)), v(visible) { }
    Color(Color_type cc, Transparency vv) :c(Fl_Color(cc)), v(vv) { }
    Color(int cc) :c(Fl_Color(cc)), v(visible) { }
    Color(Transparency vv) :c(Fl_Color()), v(vv) { }    // default color

    int as_int() const { return c; }

    char visibility() const { return v; } 
    void set_visibility(Transparency vv) { v=vv; }
private:
    char v;    // invisible and visible for now
    Fl_Color c;
};

//------------------------------------------------------------------------------

struct Line_style {
    enum Line_style_type {
        solid=FL_SOLID,            // -------
        dash=FL_DASH,              // - - - -
        dot=FL_DOT,                // ....... 
        dashdot=FL_DASHDOT,        // - . - . 
        dashdotdot=FL_DASHDOTDOT,  // -..-..
    };

    Line_style(Line_style_type ss) :s(ss), w(0) { }
    Line_style(Line_style_type lst, int ww) :s(lst), w(ww) { }
    Line_style(int ss) :s(ss), w(0) { }

    int width() const { return w; }
    int style() const { return s; }
private:
    int s;
    int w;
};

//------------------------------------------------------------------------------

class Font {
public:
    enum Font_type {
        helvetica=FL_HELVETICA,
        helvetica_bold=FL_HELVETICA_BOLD,
        helvetica_italic=FL_HELVETICA_ITALIC,
        helvetica_bold_italic=FL_HELVETICA_BOLD_ITALIC,
        courier=FL_COURIER,
        courier_bold=FL_COURIER_BOLD,
        courier_italic=FL_COURIER_ITALIC,
        courier_bold_italic=FL_COURIER_BOLD_ITALIC,
        times=FL_TIMES,
        times_bold=FL_TIMES_BOLD,
        times_italic=FL_TIMES_ITALIC,
        times_bold_italic=FL_TIMES_BOLD_ITALIC,
        symbol=FL_SYMBOL,
        screen=FL_SCREEN,
        screen_bold=FL_SCREEN_BOLD,
        zapf_dingbats=FL_ZAPF_DINGBATS
    };

    Font(Font_type ff) :f(ff) { }
    Font(int ff) :f(ff) { }

    int as_int() const { return f; }
private:
    int f;
};

//------------------------------------------------------------------------------

template<class T> class Vector_ref {
    vector<T*> v;
    vector<T*> owned;
public:
    Vector_ref() {}
    Vector_ref(T& a) { push_back(a); }
    Vector_ref(T& a, T& b);
    Vector_ref(T& a, T& b, T& c);
    Vector_ref(T* a, T* b = 0, T* c = 0, T* d = 0)
    {
        if (a) push_back(a);
        if (b) push_back(b);
        if (c) push_back(c);
        if (d) push_back(d);
    }

    ~Vector_ref() { for (int i=0; i<owned.size(); ++i) delete owned[i]; }

    void push_back(T& s) { v.push_back(&s); }
    void push_back(T* p) { v.push_back(p); owned.push_back(p); }

    T& operator[](int i) { return *v[i]; }
    const T& operator[](int i) const { return *v[i]; }

    int size() const { return v.size(); }
};

//------------------------------------------------------------------------------

typedef double Fct(double);

class Shape  {        // deals with color and style, and holds sequence of lines 
public:
    void draw() const;                 // deal with color and draw lines
    virtual void move(int dx, int dy); // move the shape +=dx and +=dy

    void set_color(Color col) { lcolor = col; }
    Color color() const { return lcolor; }
    void set_style(Line_style sty) { ls = sty; }
    Line_style style() const { return ls; }
    void set_fill_color(Color col) { fcolor = col; }
    Color fill_color() const { return fcolor; }

    Point point(int i) const { return points[i]; } // read only access to points
    int number_of_points() const { return int(points.size()); }

    virtual ~Shape() { }
protected:
    Shape();    
    virtual void draw_lines() const;   // draw the appropriate lines
    void add(Point p);                 // add p to points
    void set_point(int i,Point p);     // points[i]=p;
private:
    vector<Point> points;              // not used by all shapes
    Color lcolor;                      // color for lines and characters
    Line_style ls; 
    Color fcolor;                      // fill color

    Shape(const Shape&);               // prevent copying
    Shape& operator=(const Shape&);
};

//------------------------------------------------------------------------------

struct Function : Shape {
    // the function parameters are not stored
    Function(Fct f, double r1, double r2, Point orig,
        int count = 100, double xscale = 25, double yscale = 25);    
};

//------------------------------------------------------------------------------

struct Line : Shape {            // a Line is a Shape defined by two Points
    Line(Point p1, Point p2);    // construct a line from two points
};

//------------------------------------------------------------------------------

struct Rectangle : Shape {

    Rectangle(Point xy, int ww, int hh) : w(ww), h(hh)
    {
        add(xy);
        if (h<=0 || w<=0) error("Bad rectangle: non-positive side");
    }

    Rectangle(Point x, Point y) : w(y.x-x.x), h(y.y-x.y)
    {
        add(x);
        if (h<=0 || w<=0) error("Bad rectangle: non-positive width or height");
    }
    void draw_lines() const;

    int height() const { return h; }
    int width() const { return w; }
private:
    int h;    // height
    int w;    // width
};

//------------------------------------------------------------------------------

struct Open_polyline : Shape {         // open sequence of lines
    void add(Point p) { Shape::add(p); }
    void draw_lines() const;
};

//------------------------------------------------------------------------------

struct Closed_polyline : Open_polyline { // closed sequence of lines
    void draw_lines() const;
};

//------------------------------------------------------------------------------

struct Polygon : Closed_polyline {    // closed sequence of non-intersecting lines
    void add(Point p);
    void draw_lines() const;
};

//------------------------------------------------------------------------------

struct Lines : Shape {                 // related lines
    void draw_lines() const;
    void add(Point p1, Point p2);      // add a line defined by two points
};

//------------------------------------------------------------------------------

struct Text : Shape {
    // the point is the bottom left of the first letter
    Text(Point x, const string& s) : lab(s), fnt(fl_font()), fnt_sz(fl_size()) { add(x); }

    void draw_lines() const;

    void set_label(const string& s) { lab = s; }
    string label() const { return lab; }

    void set_font(Font f) { fnt = f; }
    Font font() const { return Font(fnt); }

    void set_font_size(int s) { fnt_sz = s; }
    int font_size() const { return fnt_sz; }
private:
    string lab;    // label
    Font fnt;
    int fnt_sz;
};

//------------------------------------------------------------------------------

struct Axis : Shape {
    enum Orientation { x, y, z };
    Axis(Orientation d, Point xy, int length,
        int number_of_notches=0, string label = "");

    void draw_lines() const;
    void move(int dx, int dy);
    void set_color(Color c);

    Text label;
    Lines notches;
};

//------------------------------------------------------------------------------

struct Circle : Shape {
    Circle(Point p, int rr);    // center and radius

    void draw_lines() const;

    Point center() const ; 
    int radius() const { return r; }
    void set_radius(int rr) { r=rr; }
private:
    int r;
};

//------------------------------------------------------------------------------

struct Ellipse : Shape {
    Ellipse(Point p, int w, int h)    // center, min, and max distance from center
        : w(w), h(h)
    { 
        add(Point(p.x-w,p.y-h));
    }

    void draw_lines() const;

    Point center() const { return Point(point(0).x+w,point(0).y+h); }
    Point focus1() const { return Point(center().x+int(sqrt(double(w*w-h*h))),center().y); }
    Point focus2() const { return Point(center().x-int(sqrt(double(w*w-h*h))),center().y); }

    void set_major(int ww) { w=ww; }
    int major() const { return w; }
    void set_minor(int hh) { h=hh; }
    int minor() const { return h; }
private:
    int w;
    int h;
};

//------------------------------------------------------------------------------

struct Marked_polyline : Open_polyline {
    Marked_polyline(const string& m) :mark(m) { }
    void draw_lines() const;
private:
    string mark;
};

//------------------------------------------------------------------------------

struct Marks : Marked_polyline {
    Marks(const string& m) :Marked_polyline(m)
    {
        set_color(Color(Color::invisible));
    }
};

//------------------------------------------------------------------------------

struct Mark : Marks {
    Mark(Point xy, char c) : Marks(string(1,c))
    {
        add(xy);
    }
};

//------------------------------------------------------------------------------

struct Suffix {
    enum Encoding { none, jpg, gif  };
};

Suffix::Encoding get_encoding(const string& s);

//------------------------------------------------------------------------------

struct Image : Shape {
    Image(Point xy, string file_name, Suffix::Encoding e = Suffix::none);
    ~Image() { delete p; }
    void draw_lines() const;
    void set_mask(Point xy, int ww, int hh) { w=ww; h=hh; cx=xy.x; cy=xy.y; }
private:
    int w,h;  // define "masking box" within image relative to position (cx,cy)
    int cx,cy; 
    Fl_Image* p;
    Text fn;
};

//------------------------------------------------------------------------------

struct Bad_image : Fl_Image {
    Bad_image(int h, int w) : Fl_Image(h,w,0) { }
    void draw(int x,int y, int, int, int, int) { draw_empty(x,y); }
};

//------------------------------------------------------------------------------

} // of namespace Graph_lib

#endif
 
Zurück