diff --git a/VEdge.h b/VEdge.h index 04b8b0c..930d651 100644 --- a/VEdge.h +++ b/VEdge.h @@ -1,69 +1,69 @@ -#ifndef VEdge_h -#define VEdge_h - -#include "Vpoint.h" -#include - -/* - A class that stores an edge in Voronoi diagram - - start : pointer to start point - end : pointer to end point - left : pointer to Voronoi place on the left side of edge - right : pointer to Voronoi place on the right side of edge - - neighbour : some edges consist of two parts, so we add the pointer to another part to connect them at the end of an algorithm - - direction : directional vector, from "start", points to "end", normal of |left, right| - f, g : directional coeffitients satisfying equation y = f*x + g (edge lies on this line) -*/ - -class VEdge -{ -public: - - VPoint * start; - VPoint * end; - VPoint * direction; - VPoint * left; - VPoint * right; - - double f; - double g; - - VEdge * neighbour; - - /* - Constructor of the class - - s : pointer to start - a : pointer to left place - b : pointer to right place - */ - - VEdge(VPoint * s, VPoint * a, VPoint * b) - { - start = s; - left = a; - right = b; - neighbour = 0; - end = 0; - - f = (b->x - a->x) / (a->y - b->y) ; - g = s->y - f * s->x ; - direction = new VPoint(b->y - a->y, -(b->x - a->x)); - } - - /* - Destructor of the class - direction belongs only to the current edge, other pointers can be shared by other edges - */ - - ~VEdge() - { - delete direction ; - } - -}; - +#ifndef VEdge_h +#define VEdge_h + +#include "Vpoint.h" +#include + +/* + A class that stores an edge in Voronoi diagram + + start : pointer to start point + end : pointer to end point + left : pointer to Voronoi place on the left side of edge + right : pointer to Voronoi place on the right side of edge + + neighbour : some edges consist of two parts, so we add the pointer to another part to connect them at the end of an algorithm + + direction : directional vector, from "start", points to "end", normal of |left, right| + f, g : directional coeffitients satisfying equation y = f*x + g (edge lies on this line) +*/ + +class VEdge +{ +public: + + VPoint * start; + VPoint * end; + VPoint * direction; + VPoint * left; + VPoint * right; + + double f; + double g; + + VEdge * neighbour; + + /* + Constructor of the class + + s : pointer to start + a : pointer to left place + b : pointer to right place + */ + + VEdge(VPoint * s, VPoint * a, VPoint * b) + { + start = s; + left = a; + right = b; + neighbour = 0; + end = 0; + + f = (b->x - a->x) / (a->y - b->y) ; + g = s->y - f * s->x ; + direction = new VPoint(b->y - a->y, -(b->x - a->x)); + } + + /* + Destructor of the class + direction belongs only to the current edge, other pointers can be shared by other edges + */ + + ~VEdge() + { + delete direction ; + } + +}; + #endif \ No newline at end of file diff --git a/VEvent.h b/VEvent.h index 9414aab..b104d48 100644 --- a/VEvent.h +++ b/VEvent.h @@ -1,50 +1,50 @@ -#ifndef VEvent_h -#define VEvent_h - -#include -#include "VPoint.h" -#include "VParabola.h" - -/* - The class for storing place / circle event in event queue. - - point : the point at which current event occurs (top circle point for circle event, focus point for place event) - pe : whether it is a place event or not - y : y coordinate of "point", events are sorted by this "y" - arch : if "pe", it is an arch above which the event occurs -*/ - -class VEvent -{ -public: - VPoint * point; - bool pe; - double y; - VParabola * arch; - - /* - Constructor for the class - - p : point, at which the event occurs - pev : whether it is a place event or not - */ - - VEvent(VPoint * p, bool pev) - { - point = p; - pe = pev; - y = p->y; - arch = 0; - } - - /* - function for comparing two events (by "y" property) - */ - - struct CompareEvent : public std::binary_function - { - bool operator()(const VEvent* l, const VEvent* r) const { return (l->y < r->y); } - }; -}; - -#endif +#ifndef VEvent_h +#define VEvent_h + +#include +#include "VPoint.h" +#include "VParabola.h" + +/* + The class for storing place / circle event in event queue. + + point : the point at which current event occurs (top circle point for circle event, focus point for place event) + pe : whether it is a place event or not + y : y coordinate of "point", events are sorted by this "y" + arch : if "pe", it is an arch above which the event occurs +*/ + +class VEvent +{ +public: + VPoint * point; + bool pe; + double y; + VParabola * arch; + + /* + Constructor for the class + + p : point, at which the event occurs + pev : whether it is a place event or not + */ + + VEvent(VPoint * p, bool pev) + { + point = p; + pe = pev; + y = p->y; + arch = 0; + } + + /* + function for comparing two events (by "y" property) + */ + + struct CompareEvent : public std::binary_function + { + bool operator()(const VEvent* l, const VEvent* r) const { return (l->y < r->y); } + }; +}; + +#endif diff --git a/VParabola.cpp b/VParabola.cpp index b24fef0..1cf34c9 100644 --- a/VParabola.cpp +++ b/VParabola.cpp @@ -1,80 +1,80 @@ -#include "VParabola.h" -#include "VPoint.h" - -/* - Constructors -*/ - -VParabola::VParabola() -{ - site = 0; - isLeaf = false; - cEvent = 0; - edge = 0; - parent = 0; -} - -VParabola::VParabola(VPoint * s) -{ - site = s; - isLeaf = true; - cEvent = 0; - edge = 0; - parent = 0; -} - -/* - Tree operations (described in the header file) -*/ - -VParabola * VParabola::GetLeft (VParabola * p) -{ - return GetLeftChild(GetLeftParent(p)); -} - - -VParabola * VParabola::GetRight (VParabola * p) -{ - return GetRightChild(GetRightParent(p)); -} - -VParabola * VParabola::GetLeftParent (VParabola * p) -{ - VParabola * par = p->parent; - VParabola * pLast = p; - while(par->Left() == pLast) - { - if(!par->parent) return 0; - pLast = par; - par = par->parent; - } - return par; -} - -VParabola * VParabola::GetRightParent (VParabola * p) -{ - VParabola * par = p->parent; - VParabola * pLast = p; - while(par->Right() == pLast) - { - if(!par->parent) return 0; - pLast = par; par = par->parent; - } - return par; -} - -VParabola * VParabola::GetLeftChild (VParabola * p) -{ - if(!p) return 0; - VParabola * par = p->Left(); - while(!par->isLeaf) par = par->Right(); - return par; -} - -VParabola * VParabola::GetRightChild (VParabola * p) -{ - if(!p) return 0; - VParabola * par = p->Right(); - while(!par->isLeaf) par = par->Left(); - return par; -} +#include "VParabola.h" +#include "VPoint.h" + +/* + Constructors +*/ + +VParabola::VParabola() +{ + site = 0; + isLeaf = false; + cEvent = 0; + edge = 0; + parent = 0; +} + +VParabola::VParabola(VPoint * s) +{ + site = s; + isLeaf = true; + cEvent = 0; + edge = 0; + parent = 0; +} + +/* + Tree operations (described in the header file) +*/ + +VParabola * VParabola::GetLeft (VParabola * p) +{ + return GetLeftChild(GetLeftParent(p)); +} + + +VParabola * VParabola::GetRight (VParabola * p) +{ + return GetRightChild(GetRightParent(p)); +} + +VParabola * VParabola::GetLeftParent (VParabola * p) +{ + VParabola * par = p->parent; + VParabola * pLast = p; + while(par->Left() == pLast) + { + if(!par->parent) return 0; + pLast = par; + par = par->parent; + } + return par; +} + +VParabola * VParabola::GetRightParent (VParabola * p) +{ + VParabola * par = p->parent; + VParabola * pLast = p; + while(par->Right() == pLast) + { + if(!par->parent) return 0; + pLast = par; par = par->parent; + } + return par; +} + +VParabola * VParabola::GetLeftChild (VParabola * p) +{ + if(!p) return 0; + VParabola * par = p->Left(); + while(!par->isLeaf) par = par->Right(); + return par; +} + +VParabola * VParabola::GetRightChild (VParabola * p) +{ + if(!p) return 0; + VParabola * par = p->Right(); + while(!par->isLeaf) par = par->Left(); + return par; +} diff --git a/VParabola.h b/VParabola.h index 9c26f7a..78b2788 100644 --- a/VParabola.h +++ b/VParabola.h @@ -1,78 +1,78 @@ -#ifndef VParabola_h -#define VParabola_h - -#include "VPoint.h" -#include "VEdge.h" - -/* - Parabolas and events have pointers to each other, so we declare class VEvent, which will be defined later. -*/ - -class VEvent; - -/* - A class that stores information about an item in beachline sequence (see Fortune's algorithm). - It can represent an arch of parabola or an intersection between two archs (which defines an edge). - In my implementation I build a binary tree with them (internal nodes are edges, leaves are archs). -*/ - -class VParabola -{ -public: - - /* - isLeaf : flag whether the node is Leaf or internal node - site : pointer to the focus point of parabola (when it is parabola) - edge : pointer to the edge (when it is an edge) - cEvent : pointer to the event, when the arch disappears (circle event) - parent : pointer to the parent node in tree - */ - - bool isLeaf; - VPoint * site; - VEdge * edge; - VEvent * cEvent; - VParabola * parent; - - /* - Constructors of the class (empty for edge, with focus parameter for an arch). - */ - - VParabola (); - VParabola (VPoint * s); - - /* - Access to the children (in tree). - */ - - void SetLeft (VParabola * p) {_left = p; p->parent = this;} - void SetRight(VParabola * p) {_right = p; p->parent = this;} - - VParabola * Left () { return _left; } - VParabola * Right() { return _right; } - - /* - Some useful tree operations - - GetLeft : returns the closest left leave of the tree - GetRight : returns the closest right leafe of the tree - GetLeftParent : returns the closest parent which is on the left - GetLeftParent : returns the closest parent which is on the right - GetLeftChild : returns the closest leave which is on the left of current node - GetRightChild : returns the closest leave which is on the right of current node - */ - - static VParabola * GetLeft (VParabola * p); - static VParabola * GetRight (VParabola * p); - static VParabola * GetLeftParent (VParabola * p); - static VParabola * GetRightParent (VParabola * p); - static VParabola * GetLeftChild (VParabola * p); - static VParabola * GetRightChild (VParabola * p); - -private: - - VParabola * _left; - VParabola * _right; -}; - +#ifndef VParabola_h +#define VParabola_h + +#include "VPoint.h" +#include "VEdge.h" + +/* + Parabolas and events have pointers to each other, so we declare class VEvent, which will be defined later. +*/ + +class VEvent; + +/* + A class that stores information about an item in beachline sequence (see Fortune's algorithm). + It can represent an arch of parabola or an intersection between two archs (which defines an edge). + In my implementation I build a binary tree with them (internal nodes are edges, leaves are archs). +*/ + +class VParabola +{ +public: + + /* + isLeaf : flag whether the node is Leaf or internal node + site : pointer to the focus point of parabola (when it is parabola) + edge : pointer to the edge (when it is an edge) + cEvent : pointer to the event, when the arch disappears (circle event) + parent : pointer to the parent node in tree + */ + + bool isLeaf; + VPoint * site; + VEdge * edge; + VEvent * cEvent; + VParabola * parent; + + /* + Constructors of the class (empty for edge, with focus parameter for an arch). + */ + + VParabola (); + VParabola (VPoint * s); + + /* + Access to the children (in tree). + */ + + void SetLeft (VParabola * p) {_left = p; p->parent = this;} + void SetRight(VParabola * p) {_right = p; p->parent = this;} + + VParabola * Left () { return _left; } + VParabola * Right() { return _right; } + + /* + Some useful tree operations + + GetLeft : returns the closest left leave of the tree + GetRight : returns the closest right leafe of the tree + GetLeftParent : returns the closest parent which is on the left + GetLeftParent : returns the closest parent which is on the right + GetLeftChild : returns the closest leave which is on the left of current node + GetRightChild : returns the closest leave which is on the right of current node + */ + + static VParabola * GetLeft (VParabola * p); + static VParabola * GetRight (VParabola * p); + static VParabola * GetLeftParent (VParabola * p); + static VParabola * GetRightParent (VParabola * p); + static VParabola * GetLeftChild (VParabola * p); + static VParabola * GetRightChild (VParabola * p); + +private: + + VParabola * _left; + VParabola * _right; +}; + #endif \ No newline at end of file diff --git a/VPoint.h b/VPoint.h index 84b40ed..fac70f5 100644 --- a/VPoint.h +++ b/VPoint.h @@ -1,25 +1,25 @@ -#ifndef VPoint_h -#define VPoint_h - -/* - A structure that stores 2D point -*/ - -struct VPoint -{ -public: - - double x, y; - - /* - Constructor for structure; x, y - coordinates - */ - - VPoint(double nx, double ny) - { - x = nx; - y = ny; - } -}; - +#ifndef VPoint_h +#define VPoint_h + +/* + A structure that stores 2D point +*/ + +struct VPoint +{ +public: + + double x, y; + + /* + Constructor for structure; x, y - coordinates + */ + + VPoint(double nx, double ny) + { + x = nx; + y = ny; + } +}; + #endif \ No newline at end of file diff --git a/Voronoi.cpp b/Voronoi.cpp index 8acd978..9137ce2 100644 --- a/Voronoi.cpp +++ b/Voronoi.cpp @@ -1,284 +1,284 @@ - -#include "Voronoi.h" -#include -#include -#include - -using namespace vor; - -Voronoi::Voronoi() -{ - edges = 0; -} - -Edges * Voronoi::GetEdges(Vertices * v, int w, int h) -{ - places = v; - width = w; - height = h; - root = 0; - - if(!edges) edges = new Edges(); - else - { - for(Vertices::iterator i = points.begin(); i != points.end(); ++i) delete (*i); - for(Edges::iterator i = edges->begin(); i != edges->end(); ++i) delete (*i); - points.clear(); - edges->clear(); - } - - for(Vertices::iterator i = places->begin(); i!=places->end(); ++i) - { - queue.push(new VEvent( *i, true)); - } - - VEvent * e; - while(!queue.empty()) - { - e = queue.top(); - queue.pop(); - ly = e->point->y; - if(deleted.find(e) != deleted.end()) { delete(e); deleted.erase(e); continue;} - if(e->pe) InsertParabola(e->point); - else RemoveParabola(e); - delete(e); - } - - FinishEdge(root); - - for(Edges::iterator i = edges->begin(); i != edges->end(); ++i) - { - if( (*i)->neighbour) - { - (*i)->start = (*i)->neighbour->end; - delete (*i)->neighbour; - } - } - - return edges; -} - -void Voronoi::InsertParabola(VPoint * p) -{ - if(!root){root = new VParabola(p); return;} - - if(root->isLeaf && root->site->y - p->y < 1) // degenerovaný případ - obě spodní místa ve stejné výšce - { - VPoint * fp = root->site; - root->isLeaf = false; - root->SetLeft( new VParabola(fp) ); - root->SetRight(new VParabola(p) ); - VPoint * s = new VPoint((p->x + fp->x)/2, height); // začátek hrany uprostřed míst - points.push_back(s); - if(p->x > fp->x) root->edge = new VEdge(s, fp, p); // rozhodnu, který vlevo, který vpravo - else root->edge = new VEdge(s, p, fp); - edges->push_back(root->edge); - return; - } - - VParabola * par = GetParabolaByX(p->x); - - if(par->cEvent) - { - deleted.insert(par->cEvent); - par->cEvent = 0; - } - - VPoint * start = new VPoint(p->x, GetY(par->site, p->x)); - points.push_back(start); - - VEdge * el = new VEdge(start, par->site, p); - VEdge * er = new VEdge(start, p, par->site); - - el->neighbour = er; - edges->push_back(el); - - // přestavuju strom .. vkládám novou parabolu - par->edge = er; - par->isLeaf = false; - - VParabola * p0 = new VParabola(par->site); - VParabola * p1 = new VParabola(p); - VParabola * p2 = new VParabola(par->site); - - par->SetRight(p2); - par->SetLeft(new VParabola()); - par->Left()->edge = el; - - par->Left()->SetLeft(p0); - par->Left()->SetRight(p1); - - CheckCircle(p0); - CheckCircle(p2); -} - -void Voronoi::RemoveParabola(VEvent * e) -{ - VParabola * p1 = e->arch; - - VParabola * xl = VParabola::GetLeftParent(p1); - VParabola * xr = VParabola::GetRightParent(p1); - - VParabola * p0 = VParabola::GetLeftChild(xl); - VParabola * p2 = VParabola::GetRightChild(xr); - - if(p0 == p2) std::cout << "chyba - pravá a levá parabola má stejné ohnisko!\n"; - - if(p0->cEvent){ deleted.insert(p0->cEvent); p0->cEvent = 0; } - if(p2->cEvent){ deleted.insert(p2->cEvent); p2->cEvent = 0; } - - VPoint * p = new VPoint(e->point->x, GetY(p1->site, e->point->x)); - points.push_back(p); - - xl->edge->end = p; - xr->edge->end = p; - - VParabola * higher; - VParabola * par = p1; - while(par != root) - { - par = par->parent; - if(par == xl) higher = xl; - if(par == xr) higher = xr; - } - higher->edge = new VEdge(p, p0->site, p2->site); - edges->push_back(higher->edge); - - VParabola * gparent = p1->parent->parent; - if(p1->parent->Left() == p1) - { - if(gparent->Left() == p1->parent) gparent->SetLeft ( p1->parent->Right() ); - if(gparent->Right() == p1->parent) gparent->SetRight( p1->parent->Right() ); - } - else - { - if(gparent->Left() == p1->parent) gparent->SetLeft ( p1->parent->Left() ); - if(gparent->Right() == p1->parent) gparent->SetRight( p1->parent->Left() ); - } - - delete p1->parent; - delete p1; - - CheckCircle(p0); - CheckCircle(p2); -} - -void Voronoi::FinishEdge(VParabola * n) -{ - if(n->isLeaf) {delete n; return;} - double mx; - if(n->edge->direction->x > 0.0) mx = std::max(width, n->edge->start->x + 10 ); - else mx = std::min(0.0, n->edge->start->x - 10); - - VPoint * end = new VPoint(mx, mx * n->edge->f + n->edge->g); - n->edge->end = end; - points.push_back(end); - - FinishEdge(n->Left() ); - FinishEdge(n->Right()); - delete n; -} - -double Voronoi::GetXOfEdge(VParabola * par, double y) -{ - VParabola * left = VParabola::GetLeftChild(par); - VParabola * right= VParabola::GetRightChild(par); - - VPoint * p = left->site; - VPoint * r = right->site; - - double dp = 2.0 * (p->y - y); - double a1 = 1.0 / dp; - double b1 = -2.0 * p->x / dp; - double c1 = y + dp / 4 + p->x * p->x / dp; - - dp = 2.0 * (r->y - y); - double a2 = 1.0 / dp; - double b2 = -2.0 * r->x/dp; - double c2 = ly + dp / 4 + r->x * r->x / dp; - - double a = a1 - a2; - double b = b1 - b2; - double c = c1 - c2; - - double disc = b*b - 4 * a * c; - double x1 = (-b + std::sqrt(disc)) / (2*a); - double x2 = (-b - std::sqrt(disc)) / (2*a); - - double ry; - if(p->y < r->y ) ry = std::max(x1, x2); - else ry = std::min(x1, x2); - - return ry; -} - -VParabola * Voronoi::GetParabolaByX(double xx) -{ - VParabola * par = root; - double x = 0.0; - - while(!par->isLeaf) // projdu stromem dokud nenarazím na vhodný list - { - x = GetXOfEdge(par, ly); - if(x>xx) par = par->Left(); - else par = par->Right(); - } - return par; -} - -double Voronoi::GetY(VPoint * p, double x) // ohnisko, x-souřadnice -{ - double dp = 2 * (p->y - ly); - double a1 = 1 / dp; - double b1 = -2 * p->x / dp; - double c1 = ly + dp / 4 + p->x * p->x / dp; - - return(a1*x*x + b1*x + c1); -} - -void Voronoi::CheckCircle(VParabola * b) -{ - VParabola * lp = VParabola::GetLeftParent (b); - VParabola * rp = VParabola::GetRightParent(b); - - VParabola * a = VParabola::GetLeftChild (lp); - VParabola * c = VParabola::GetRightChild(rp); - - if(!a || !c || a->site == c->site) return; - - VPoint * s = 0; - s = GetEdgeIntersection(lp->edge, rp->edge); - if(s == 0) return; - - double dx = a->site->x - s->x; - double dy = a->site->y - s->y; - - double d = std::sqrt( (dx * dx) + (dy * dy) ); - - if(s->y - d >= ly) { return;} - - VEvent * e = new VEvent(new VPoint(s->x, s->y - d), false); - points.push_back(e->point); - b->cEvent = e; - e->arch = b; - queue.push(e); -} - -VPoint * Voronoi::GetEdgeIntersection(VEdge * a, VEdge * b) -{ - double x = (b->g-a->g) / (a->f - b->f); - double y = a->f * x + a->g; - - if((x - a->start->x)/a->direction->x < 0) return 0; - if((y - a->start->y)/a->direction->y < 0) return 0; - - if((x - b->start->x)/b->direction->x < 0) return 0; - if((y - b->start->y)/b->direction->y < 0) return 0; - - VPoint * p = new VPoint(x, y); - points.push_back(p); - return p; -} - - + +#include "Voronoi.h" +#include +#include +#include + +using namespace vor; + +Voronoi::Voronoi() +{ + edges = 0; +} + +Edges * Voronoi::GetEdges(Vertices * v, int w, int h) +{ + places = v; + width = w; + height = h; + root = 0; + + if(!edges) edges = new Edges(); + else + { + for(Vertices::iterator i = points.begin(); i != points.end(); ++i) delete (*i); + for(Edges::iterator i = edges->begin(); i != edges->end(); ++i) delete (*i); + points.clear(); + edges->clear(); + } + + for(Vertices::iterator i = places->begin(); i!=places->end(); ++i) + { + queue.push(new VEvent( *i, true)); + } + + VEvent * e; + while(!queue.empty()) + { + e = queue.top(); + queue.pop(); + ly = e->point->y; + if(deleted.find(e) != deleted.end()) { delete(e); deleted.erase(e); continue;} + if(e->pe) InsertParabola(e->point); + else RemoveParabola(e); + delete(e); + } + + FinishEdge(root); + + for(Edges::iterator i = edges->begin(); i != edges->end(); ++i) + { + if( (*i)->neighbour) + { + (*i)->start = (*i)->neighbour->end; + delete (*i)->neighbour; + } + } + + return edges; +} + +void Voronoi::InsertParabola(VPoint * p) +{ + if(!root){root = new VParabola(p); return;} + + if(root->isLeaf && root->site->y - p->y < 1) // degenerovaný případ - obě spodní místa ve stejné výšce + { + VPoint * fp = root->site; + root->isLeaf = false; + root->SetLeft( new VParabola(fp) ); + root->SetRight(new VParabola(p) ); + VPoint * s = new VPoint((p->x + fp->x)/2, height); // začátek hrany uprostřed míst + points.push_back(s); + if(p->x > fp->x) root->edge = new VEdge(s, fp, p); // rozhodnu, který vlevo, který vpravo + else root->edge = new VEdge(s, p, fp); + edges->push_back(root->edge); + return; + } + + VParabola * par = GetParabolaByX(p->x); + + if(par->cEvent) + { + deleted.insert(par->cEvent); + par->cEvent = 0; + } + + VPoint * start = new VPoint(p->x, GetY(par->site, p->x)); + points.push_back(start); + + VEdge * el = new VEdge(start, par->site, p); + VEdge * er = new VEdge(start, p, par->site); + + el->neighbour = er; + edges->push_back(el); + + // přestavuju strom .. vkládám novou parabolu + par->edge = er; + par->isLeaf = false; + + VParabola * p0 = new VParabola(par->site); + VParabola * p1 = new VParabola(p); + VParabola * p2 = new VParabola(par->site); + + par->SetRight(p2); + par->SetLeft(new VParabola()); + par->Left()->edge = el; + + par->Left()->SetLeft(p0); + par->Left()->SetRight(p1); + + CheckCircle(p0); + CheckCircle(p2); +} + +void Voronoi::RemoveParabola(VEvent * e) +{ + VParabola * p1 = e->arch; + + VParabola * xl = VParabola::GetLeftParent(p1); + VParabola * xr = VParabola::GetRightParent(p1); + + VParabola * p0 = VParabola::GetLeftChild(xl); + VParabola * p2 = VParabola::GetRightChild(xr); + + if(p0 == p2) std::cout << "chyba - pravá a levá parabola má stejné ohnisko!\n"; + + if(p0->cEvent){ deleted.insert(p0->cEvent); p0->cEvent = 0; } + if(p2->cEvent){ deleted.insert(p2->cEvent); p2->cEvent = 0; } + + VPoint * p = new VPoint(e->point->x, GetY(p1->site, e->point->x)); + points.push_back(p); + + xl->edge->end = p; + xr->edge->end = p; + + VParabola * higher; + VParabola * par = p1; + while(par != root) + { + par = par->parent; + if(par == xl) higher = xl; + if(par == xr) higher = xr; + } + higher->edge = new VEdge(p, p0->site, p2->site); + edges->push_back(higher->edge); + + VParabola * gparent = p1->parent->parent; + if(p1->parent->Left() == p1) + { + if(gparent->Left() == p1->parent) gparent->SetLeft ( p1->parent->Right() ); + if(gparent->Right() == p1->parent) gparent->SetRight( p1->parent->Right() ); + } + else + { + if(gparent->Left() == p1->parent) gparent->SetLeft ( p1->parent->Left() ); + if(gparent->Right() == p1->parent) gparent->SetRight( p1->parent->Left() ); + } + + delete p1->parent; + delete p1; + + CheckCircle(p0); + CheckCircle(p2); +} + +void Voronoi::FinishEdge(VParabola * n) +{ + if(n->isLeaf) {delete n; return;} + double mx; + if(n->edge->direction->x > 0.0) mx = std::max(width, n->edge->start->x + 10 ); + else mx = std::min(0.0, n->edge->start->x - 10); + + VPoint * end = new VPoint(mx, mx * n->edge->f + n->edge->g); + n->edge->end = end; + points.push_back(end); + + FinishEdge(n->Left() ); + FinishEdge(n->Right()); + delete n; +} + +double Voronoi::GetXOfEdge(VParabola * par, double y) +{ + VParabola * left = VParabola::GetLeftChild(par); + VParabola * right= VParabola::GetRightChild(par); + + VPoint * p = left->site; + VPoint * r = right->site; + + double dp = 2.0 * (p->y - y); + double a1 = 1.0 / dp; + double b1 = -2.0 * p->x / dp; + double c1 = y + dp / 4 + p->x * p->x / dp; + + dp = 2.0 * (r->y - y); + double a2 = 1.0 / dp; + double b2 = -2.0 * r->x/dp; + double c2 = ly + dp / 4 + r->x * r->x / dp; + + double a = a1 - a2; + double b = b1 - b2; + double c = c1 - c2; + + double disc = b*b - 4 * a * c; + double x1 = (-b + std::sqrt(disc)) / (2*a); + double x2 = (-b - std::sqrt(disc)) / (2*a); + + double ry; + if(p->y < r->y ) ry = std::max(x1, x2); + else ry = std::min(x1, x2); + + return ry; +} + +VParabola * Voronoi::GetParabolaByX(double xx) +{ + VParabola * par = root; + double x = 0.0; + + while(!par->isLeaf) // projdu stromem dokud nenarazím na vhodný list + { + x = GetXOfEdge(par, ly); + if(x>xx) par = par->Left(); + else par = par->Right(); + } + return par; +} + +double Voronoi::GetY(VPoint * p, double x) // ohnisko, x-souřadnice +{ + double dp = 2 * (p->y - ly); + double a1 = 1 / dp; + double b1 = -2 * p->x / dp; + double c1 = ly + dp / 4 + p->x * p->x / dp; + + return(a1*x*x + b1*x + c1); +} + +void Voronoi::CheckCircle(VParabola * b) +{ + VParabola * lp = VParabola::GetLeftParent (b); + VParabola * rp = VParabola::GetRightParent(b); + + VParabola * a = VParabola::GetLeftChild (lp); + VParabola * c = VParabola::GetRightChild(rp); + + if(!a || !c || a->site == c->site) return; + + VPoint * s = 0; + s = GetEdgeIntersection(lp->edge, rp->edge); + if(s == 0) return; + + double dx = a->site->x - s->x; + double dy = a->site->y - s->y; + + double d = std::sqrt( (dx * dx) + (dy * dy) ); + + if(s->y - d >= ly) { return;} + + VEvent * e = new VEvent(new VPoint(s->x, s->y - d), false); + points.push_back(e->point); + b->cEvent = e; + e->arch = b; + queue.push(e); +} + +VPoint * Voronoi::GetEdgeIntersection(VEdge * a, VEdge * b) +{ + double x = (b->g-a->g) / (a->f - b->f); + double y = a->f * x + a->g; + + if((x - a->start->x)/a->direction->x < 0) return 0; + if((y - a->start->y)/a->direction->y < 0) return 0; + + if((x - b->start->x)/b->direction->x < 0) return 0; + if((y - b->start->y)/b->direction->y < 0) return 0; + + VPoint * p = new VPoint(x, y); + points.push_back(p); + return p; +} + + \ No newline at end of file diff --git a/Voronoi.h b/Voronoi.h index 4b2f351..955aa59 100644 --- a/Voronoi.h +++ b/Voronoi.h @@ -1,101 +1,101 @@ -#ifndef Voronoi_h -#define Voronoi_h - -#include -#include -#include - -#include "VPoint.h" -#include "VEdge.h" -#include "VParabola.h" -#include "VEvent.h" -#include - - -namespace vor -{ - /* - Useful data containers for Vertices (places) and Edges of Voronoi diagram - */ - - typedef std::list Vertices ; - typedef std::list Edges ; - - /* - Class for generating the Voronoi diagram - */ - - class Voronoi - { - public: - - /* - Constructor - without any parameters - */ - - Voronoi(); - - /* - The only public function for generating a diagram - - input: - v : Vertices - places for drawing a diagram - w : width of the result (top left corner is (0, 0)) - h : height of the result - output: - pointer to list of edges - - All the data structures are managed by this class - */ - - Edges * GetEdges(Vertices * v, int w, int h); - - private: - - /* - places : container of places with which we work - edges : container of edges which will be teh result - width : width of the diagram - height : height of the diagram - root : the root of the tree, that represents a beachline sequence - ly : current "y" position of the line (see Fortune's algorithm) - */ - - Vertices * places; - Edges * edges; - double width, height; - VParabola * root; - double ly; - - /* - deleted : set of deleted (false) Events (since we can not delete from PriorityQueue - points : list of all new points that were created during the algorithm - queue : priority queue with events to process - */ - - std::set deleted; - std::list points; - std::priority_queue, VEvent::CompareEvent> queue; - - /* - InsertParabola : processing the place event - RemoveParabola : processing the circle event - FinishEdge : recursively finishes all infinite edges in the tree - GetXOfEdge : returns the current x position of an intersection point of left and right parabolas - GetParabolaByX : returns the Parabola that is under this "x" position in the current beachline - CheckCircle : checks the circle event (disappearing) of this parabola - GetEdgeInterse - */ - - void InsertParabola(VPoint * p); - void RemoveParabola(VEvent * e); - void FinishEdge(VParabola * n); - double GetXOfEdge(VParabola * par, double y); - VParabola * GetParabolaByX(double xx); - double GetY(VPoint * p, double x); - void CheckCircle(VParabola * b); - VPoint * GetEdgeIntersection(VEdge * a, VEdge * b); - }; -} - +#ifndef Voronoi_h +#define Voronoi_h + +#include +#include +#include + +#include "VPoint.h" +#include "VEdge.h" +#include "VParabola.h" +#include "VEvent.h" +#include + + +namespace vor +{ + /* + Useful data containers for Vertices (places) and Edges of Voronoi diagram + */ + + typedef std::list Vertices ; + typedef std::list Edges ; + + /* + Class for generating the Voronoi diagram + */ + + class Voronoi + { + public: + + /* + Constructor - without any parameters + */ + + Voronoi(); + + /* + The only public function for generating a diagram + + input: + v : Vertices - places for drawing a diagram + w : width of the result (top left corner is (0, 0)) + h : height of the result + output: + pointer to list of edges + + All the data structures are managed by this class + */ + + Edges * GetEdges(Vertices * v, int w, int h); + + private: + + /* + places : container of places with which we work + edges : container of edges which will be teh result + width : width of the diagram + height : height of the diagram + root : the root of the tree, that represents a beachline sequence + ly : current "y" position of the line (see Fortune's algorithm) + */ + + Vertices * places; + Edges * edges; + double width, height; + VParabola * root; + double ly; + + /* + deleted : set of deleted (false) Events (since we can not delete from PriorityQueue + points : list of all new points that were created during the algorithm + queue : priority queue with events to process + */ + + std::set deleted; + std::list points; + std::priority_queue, VEvent::CompareEvent> queue; + + /* + InsertParabola : processing the place event + RemoveParabola : processing the circle event + FinishEdge : recursively finishes all infinite edges in the tree + GetXOfEdge : returns the current x position of an intersection point of left and right parabolas + GetParabolaByX : returns the Parabola that is under this "x" position in the current beachline + CheckCircle : checks the circle event (disappearing) of this parabola + GetEdgeInterse + */ + + void InsertParabola(VPoint * p); + void RemoveParabola(VEvent * e); + void FinishEdge(VParabola * n); + double GetXOfEdge(VParabola * par, double y); + VParabola * GetParabolaByX(double xx); + double GetY(VPoint * p, double x); + void CheckCircle(VParabola * b); + VPoint * GetEdgeIntersection(VEdge * a, VEdge * b); + }; +} + #endif \ No newline at end of file diff --git a/main.cpp b/main.cpp index 61f13a5..c11ef5f 100644 --- a/main.cpp +++ b/main.cpp @@ -1,153 +1,153 @@ -#include // Include the GLEW header file -#include // Include the GLUT header file -#include -#include -#include -#include - - -#include "Voronoi.h" -#include "VPoint.h" - -void display (void); -void onEF (int n); -void reshape (int width, int height); - -vor::Voronoi * v; -vor::Vertices * ver; // vrcholy -vor::Vertices * dir; // směry, kterými se pohybují -vor::Edges * edg; // hrany diagramu - -double w = 10000; - -int main (int argc, char **argv) -{ - using namespace vor; - - v = new Voronoi(); - ver = new Vertices(); - dir = new Vertices(); - - srand ( time(NULL) ); - - for(int i=0; i<50; i++) - { - - ver->push_back(new VPoint( w * (double)rand()/(double)RAND_MAX , w * (double)rand()/(double)RAND_MAX )); - dir->push_back(new VPoint( (double)rand()/(double)RAND_MAX - 0.5, (double)rand()/(double)RAND_MAX - 0.5)); - } - - edg = v->GetEdges(ver, w, w); - std::cout << "voronois done!\n"; - - for(vor::Edges::iterator i = edg->begin(); i!= edg->end(); ++i) - { - if( (*i)->start == 0 ) - { - std::cout << "chybi zacatek hrany!\n"; - continue; - } - if( (*i)->end == 0 ) - { - std::cout << "chybi konec hrany!\n"; - continue; - } - } - - glutInit(&argc, argv); // Initialize GLUT - glutInitDisplayMode (GLUT_SINGLE); // Set up a basic display buffer (only single buffered for now) - glutInitWindowSize (600, 600); // Set the width and height of the window - glutInitWindowPosition (100, 100); // Set the position of the window - glutCreateWindow ("You’re first OpenGL Window"); // Set the title for the window - - glutTimerFunc(100, onEF, 0); - glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering - - glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for reshaping - - //glutKeyboardFunc(keyPressed); // Tell GLUT to use the method "keyPressed" for key presses - //glutKeyboardUpFunc(keyUp); // Tell GLUT to use the method "keyUp" for key up events - - glutMainLoop(); // Enter GLUT's main loop - - return 0; -} - -void drawVoronoi() -{ - - vor::Vertices::iterator j = dir->begin(); - for(vor::Vertices::iterator i = ver->begin(); i != ver->end(); ++i) - { - (*i)->x += (*j)->x * w/50; - (*i)->y += (*j)->y * w/50; - if( (*i)->x > w ) (*j)->x *= -1; - if( (*i)->x < 0 ) (*j)->x *= -1; - - if( (*i)->y > w ) (*j)->y *= -1; - if( (*i)->y < 0 ) (*j)->y *= -1; - ++j; - } - - - edg = v->GetEdges(ver, w, w); - //std::cout << "voronoi done"; - for(vor::Vertices::iterator i = ver->begin(); i!= ver->end(); ++i) - { - glBegin(GL_QUADS); - //std::cout << (*i)->x << "\n"; - glVertex2f( -1+2*(*i)->x/w -0.01, -1+2*(*i)->y/w - 0.01); - glVertex2f( -1+2*(*i)->x/w +0.01, -1+2*(*i)->y/w - 0.01); - glVertex2f( -1+2*(*i)->x/w +0.01, -1+2*(*i)->y/w + 0.01); - glVertex2f( -1+2*(*i)->x/w -0.01, -1+2*(*i)->y/w + 0.01); - glEnd(); - } - - - for(vor::Edges::iterator i = edg->begin(); i!= edg->end(); ++i) - { - /* - glBegin(GL_LINES); - glVertex2f( -1+2*(*i)->left->x/w, -1+2*(*i)->left->y/w); - glVertex2f( -1+2*(*i)->right->x/w, -1+2*(*i)->right->y/w); - glEnd(); - */ - glBegin(GL_LINES); - glVertex2f( -1+2*(*i)->start->x/w, -1+2*(*i)->start->y/w); - glVertex2f( -1+2*(*i)->end->x/w, -1+2*(*i)->end->y/w); - glEnd(); - - } -} - -void display (void) -{ - std::cout << "display\n"; - glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations - glTranslatef(0.0f, 0.0f, -5.0f); - - glFlush(); -} - - -void onEF(int n) -{ - - glutTimerFunc(20, onEF, 0); - glClear(GL_COLOR_BUFFER_BIT);//Clear the screen - glClearColor(0.0f, 0.0f, 0.2f, 1.0f); // Clear the background of our window to red - - drawVoronoi(); - glutSwapBuffers(); - //Draw everything to the screen -} - -void reshape (int width, int height) -{ - - glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window - glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed - glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up) - gluPerspective(22.5, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes - glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly +#include // Include the GLEW header file +#include // Include the GLUT header file +#include +#include +#include +#include + + +#include "Voronoi.h" +#include "VPoint.h" + +void display (void); +void onEF (int n); +void reshape (int width, int height); + +vor::Voronoi * v; +vor::Vertices * ver; // vrcholy +vor::Vertices * dir; // směry, kterými se pohybují +vor::Edges * edg; // hrany diagramu + +double w = 10000; + +int main (int argc, char **argv) +{ + using namespace vor; + + v = new Voronoi(); + ver = new Vertices(); + dir = new Vertices(); + + srand ( time(NULL) ); + + for(int i=0; i<50; i++) + { + + ver->push_back(new VPoint( w * (double)rand()/(double)RAND_MAX , w * (double)rand()/(double)RAND_MAX )); + dir->push_back(new VPoint( (double)rand()/(double)RAND_MAX - 0.5, (double)rand()/(double)RAND_MAX - 0.5)); + } + + edg = v->GetEdges(ver, w, w); + std::cout << "voronois done!\n"; + + for(vor::Edges::iterator i = edg->begin(); i!= edg->end(); ++i) + { + if( (*i)->start == 0 ) + { + std::cout << "chybi zacatek hrany!\n"; + continue; + } + if( (*i)->end == 0 ) + { + std::cout << "chybi konec hrany!\n"; + continue; + } + } + + glutInit(&argc, argv); // Initialize GLUT + glutInitDisplayMode (GLUT_SINGLE); // Set up a basic display buffer (only single buffered for now) + glutInitWindowSize (600, 600); // Set the width and height of the window + glutInitWindowPosition (100, 100); // Set the position of the window + glutCreateWindow ("You’re first OpenGL Window"); // Set the title for the window + + glutTimerFunc(100, onEF, 0); + glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering + + glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for reshaping + + //glutKeyboardFunc(keyPressed); // Tell GLUT to use the method "keyPressed" for key presses + //glutKeyboardUpFunc(keyUp); // Tell GLUT to use the method "keyUp" for key up events + + glutMainLoop(); // Enter GLUT's main loop + + return 0; +} + +void drawVoronoi() +{ + + vor::Vertices::iterator j = dir->begin(); + for(vor::Vertices::iterator i = ver->begin(); i != ver->end(); ++i) + { + (*i)->x += (*j)->x * w/50; + (*i)->y += (*j)->y * w/50; + if( (*i)->x > w ) (*j)->x *= -1; + if( (*i)->x < 0 ) (*j)->x *= -1; + + if( (*i)->y > w ) (*j)->y *= -1; + if( (*i)->y < 0 ) (*j)->y *= -1; + ++j; + } + + + edg = v->GetEdges(ver, w, w); + //std::cout << "voronoi done"; + for(vor::Vertices::iterator i = ver->begin(); i!= ver->end(); ++i) + { + glBegin(GL_QUADS); + //std::cout << (*i)->x << "\n"; + glVertex2f( -1+2*(*i)->x/w -0.01, -1+2*(*i)->y/w - 0.01); + glVertex2f( -1+2*(*i)->x/w +0.01, -1+2*(*i)->y/w - 0.01); + glVertex2f( -1+2*(*i)->x/w +0.01, -1+2*(*i)->y/w + 0.01); + glVertex2f( -1+2*(*i)->x/w -0.01, -1+2*(*i)->y/w + 0.01); + glEnd(); + } + + + for(vor::Edges::iterator i = edg->begin(); i!= edg->end(); ++i) + { + /* + glBegin(GL_LINES); + glVertex2f( -1+2*(*i)->left->x/w, -1+2*(*i)->left->y/w); + glVertex2f( -1+2*(*i)->right->x/w, -1+2*(*i)->right->y/w); + glEnd(); + */ + glBegin(GL_LINES); + glVertex2f( -1+2*(*i)->start->x/w, -1+2*(*i)->start->y/w); + glVertex2f( -1+2*(*i)->end->x/w, -1+2*(*i)->end->y/w); + glEnd(); + + } +} + +void display (void) +{ + std::cout << "display\n"; + glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations + glTranslatef(0.0f, 0.0f, -5.0f); + + glFlush(); +} + + +void onEF(int n) +{ + + glutTimerFunc(20, onEF, 0); + glClear(GL_COLOR_BUFFER_BIT);//Clear the screen + glClearColor(0.0f, 0.0f, 0.2f, 1.0f); // Clear the background of our window to red + + drawVoronoi(); + glutSwapBuffers(); + //Draw everything to the screen +} + +void reshape (int width, int height) +{ + + glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window + glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed + glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up) + gluPerspective(22.5, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes + glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly } \ No newline at end of file diff --git a/main_old.cpp b/main_old.cpp index eef72ab..7c316e2 100644 --- a/main_old.cpp +++ b/main_old.cpp @@ -1,141 +1,141 @@ -#include // Include the GLEW header file -#include // Include the GLUT header file -#include -#include -#include - -#define PI 3.14159265 -#define gd 10 -#define gr 6 -#define fn 3000 - - -int tim = 0; - -struct sf // snowflake -{ - float size, rot, x, y, z; - sf() - { - size = 0.3 + 0.7*rand()/RAND_MAX; - x = 8.0 * rand()/RAND_MAX - 4; - y = 4.0 * rand()/RAND_MAX - 2; - z = 4.0 * rand()/RAND_MAX - 2; - rot = 0; - } - void iterate() - { - y -= gd * 0.0005; - x += gr * 0.0005; - if(y<-2) y = 2 + 0.3*rand()/RAND_MAX; - if(x>4) x = -4 + 0.3*rand()/RAND_MAX; - rot -= 0.03; - } - bool operator < (sf & a) { return z < a.z; } - -} flakes [fn]; - -void dl(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); -void dc(GLfloat x, GLfloat y, float r); -void df(sf & f); - -void display (void) -{ - std::cout << "display\n"; - glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations - glTranslatef(0.0f, 0.0f, -5.0f); -} - -void onEF(int n) -{ - glutTimerFunc(5, onEF, 0); - glClear(GL_COLOR_BUFFER_BIT);//Clear the screen - glClearColor(0.0f, 0.0f, 0.2f, 1.0f); // Clear the background of our window to red - tim ++; - - glHint (GL_POLYGON_SMOOTH, GL_DONT_CARE); - glLineWidth (1.5); - - double c; - for(int i=0; i // Include the GLEW header file +#include // Include the GLUT header file +#include +#include +#include + +#define PI 3.14159265 +#define gd 10 +#define gr 6 +#define fn 3000 + + +int tim = 0; + +struct sf // snowflake +{ + float size, rot, x, y, z; + sf() + { + size = 0.3 + 0.7*rand()/RAND_MAX; + x = 8.0 * rand()/RAND_MAX - 4; + y = 4.0 * rand()/RAND_MAX - 2; + z = 4.0 * rand()/RAND_MAX - 2; + rot = 0; + } + void iterate() + { + y -= gd * 0.0005; + x += gr * 0.0005; + if(y<-2) y = 2 + 0.3*rand()/RAND_MAX; + if(x>4) x = -4 + 0.3*rand()/RAND_MAX; + rot -= 0.03; + } + bool operator < (sf & a) { return z < a.z; } + +} flakes [fn]; + +void dl(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +void dc(GLfloat x, GLfloat y, float r); +void df(sf & f); + +void display (void) +{ + std::cout << "display\n"; + glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations + glTranslatef(0.0f, 0.0f, -5.0f); +} + +void onEF(int n) +{ + glutTimerFunc(5, onEF, 0); + glClear(GL_COLOR_BUFFER_BIT);//Clear the screen + glClearColor(0.0f, 0.0f, 0.2f, 1.0f); // Clear the background of our window to red + tim ++; + + glHint (GL_POLYGON_SMOOTH, GL_DONT_CARE); + glLineWidth (1.5); + + double c; + for(int i=0; i -#include "vmath.h" - -quat_t quat_rotate(quat_t q, float angle, float x, float y, float z) -{ - quat_t rq; - float half_angle = angle * 0.5f; - float sin_half = (float)sin(half_angle); - - rq.w = (float)cos(half_angle); - rq.x = x * sin_half; - rq.y = y * sin_half; - rq.z = z * sin_half; - - return quat_mul(q, rq); -} +#include +#include "vmath.h" + +quat_t quat_rotate(quat_t q, float angle, float x, float y, float z) +{ + quat_t rq; + float half_angle = angle * 0.5f; + float sin_half = (float)sin(half_angle); + + rq.w = (float)cos(half_angle); + rq.x = x * sin_half; + rq.y = y * sin_half; + rq.z = z * sin_half; + + return quat_mul(q, rq); +} diff --git a/vmath.h b/vmath.h index 249a504..ba9dc17 100644 --- a/vmath.h +++ b/vmath.h @@ -1,38 +1,38 @@ -#ifndef VMATH_H_ -#define VMATH_H_ - -#if defined(WIN32) -#define INLINE -#else -#define INLINE inline -#endif - - -typedef struct { float x, y, z; } vec3_t; -typedef struct { float x, y, z, w; } vec4_t; - -typedef vec4_t quat_t; - -typedef float mat4_t[4][4]; - -/* vector functions */ -static INLINE vec3_t v3_cons(float x, float y, float z); -static INLINE float v3_dot(vec3_t v1, vec3_t v2); - -/* quaternion functions */ -static INLINE quat_t quat_cons(float s, float x, float y, float z); -static INLINE vec3_t quat_vec(quat_t q); -static INLINE quat_t quat_mul(quat_t q1, quat_t q2); -static INLINE void quat_to_mat(mat4_t res, quat_t q); -quat_t quat_rotate(quat_t q, float angle, float x, float y, float z); - -/* matrix functions */ -static INLINE void m4_cons(mat4_t m, - float m11, float m12, float m13, float m14, - float m21, float m22, float m23, float m24, - float m31, float m32, float m33, float m34, - float m41, float m42, float m43, float m44); - -#include "vmath.inl" - -#endif /* VMATH_H_ */ +#ifndef VMATH_H_ +#define VMATH_H_ + +#if defined(WIN32) +#define INLINE +#else +#define INLINE inline +#endif + + +typedef struct { float x, y, z; } vec3_t; +typedef struct { float x, y, z, w; } vec4_t; + +typedef vec4_t quat_t; + +typedef float mat4_t[4][4]; + +/* vector functions */ +static INLINE vec3_t v3_cons(float x, float y, float z); +static INLINE float v3_dot(vec3_t v1, vec3_t v2); + +/* quaternion functions */ +static INLINE quat_t quat_cons(float s, float x, float y, float z); +static INLINE vec3_t quat_vec(quat_t q); +static INLINE quat_t quat_mul(quat_t q1, quat_t q2); +static INLINE void quat_to_mat(mat4_t res, quat_t q); +quat_t quat_rotate(quat_t q, float angle, float x, float y, float z); + +/* matrix functions */ +static INLINE void m4_cons(mat4_t m, + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44); + +#include "vmath.inl" + +#endif /* VMATH_H_ */