zoomedit: C++ized Line & Rectangle

This commit is contained in:
neoraider 2007-09-16 20:59:04 +00:00
parent 5ea7f0464e
commit 96e9d04527
12 changed files with 253 additions and 173 deletions

View file

@ -2,11 +2,42 @@
#include <math.h> #include <math.h>
int lineIntersection(const LINE *la, const LINE *lb, Vertex *v) { bool Line::contains(const Vertex &v) const {
double xa1 = la->v1.getX(), ya1 = la->v1.getY(); if(v1.getX() == v2.getX() && v1.getY() == v2.getY()) {
double xa2 = la->v2.getX(), ya2 = la->v2.getY(); if(v1.getX() == v.getX() && v1.getY() == v.getY())
double xb1 = lb->v1.getX(), yb1 = lb->v1.getY(); return true;
double xb2 = lb->v2.getX(), yb2 = lb->v2.getY(); else
return false;
}
if(v1.getX() == v2.getX()) {
if(v1.getX() != v.getX())
return false;
else if(v.getY() >= fmin(v1.getY(), v2.getY()) && v.getY() <= fmax(v1.getY(), v2.getY()))
return true;
else
return false;
}
if(v1.getY() == v2.getY()) {
if(v1.getY() != v.getY())
return false;
else if(v.getX() >= fmin(v1.getX(), v2.getX()) && v.getX() <= fmax(v1.getX(), v2.getX()))
return true;
else
return false;
}
if((v.getX()-v1.getX())/(v2.getX()-v1.getX()) - (v.getY()-v1.getY())/(v2.getY()-v1.getY()) == 0)
return true;
else
return false;
}
int Line::intersects(const Line &l, Vertex *v) const {
double xa1 = v1.getX(), ya1 = v1.getY();
double xa2 = v2.getX(), ya2 = v2.getY();
double xb1 = l.v1.getX(), yb1 = l.v1.getY();
double xb2 = l.v2.getX(), yb2 = l.v2.getY();
double temp; double temp;
int switched = 0; int switched = 0;
Vertex v2; Vertex v2;

34
Line.h
View file

@ -2,6 +2,7 @@
#define LINE_H_ #define LINE_H_
#include "Vertex.h" #include "Vertex.h"
#include <math.h>
#define INTERSECTION_ERROR -1 #define INTERSECTION_ERROR -1
@ -13,11 +14,34 @@
#define INTERSECTION_SEGMENT_LINE 6 #define INTERSECTION_SEGMENT_LINE 6
#define INTERSECTION_SEGMENT_SEGMENT 7 #define INTERSECTION_SEGMENT_SEGMENT 7
typedef struct _LINE { class Line {
Vertex v1, v2; private:
} LINE; Vertex v1, v2;
public:
Line() {}
Line(const Vertex& v1, const Vertex& v2) {
this->v1 = v1; this->v2 = v2;
}
Line(double x1, double y1, double x2, double y2) {
v1.setLocation(x1, y1);
v2.setLocation(x2, y2);
}
Vertex &getVertex1() {return v1;}
const Vertex &getVertex1() const {return v1;}
void setVertex1(const Vertex &v) {v1 = v;}
Vertex &getVertex2() {return v2;}
const Vertex &getVertex2() const {return v2;}
void setVertex2(const Vertex &v) {v2 = v;}
double lengthSq() const {return v1.distanceSq(v2);}
double length() const {return sqrt(lengthSq());}
bool contains(const Vertex &v) const;
int intersects(const Line &l, Vertex *v) const;
};
int lineIntersection(const LINE *la, const LINE *lb, Vertex *v);
#endif /*LINE_H_*/ #endif /*LINE_H_*/

View file

@ -1,4 +1,4 @@
bin_PROGRAMS = zoomedit bin_PROGRAMS = zoomedit
zoomedit_SOURCES = zoomedit.cpp window.cpp ui.cpp draw.cpp level.cpp geometry.cpp edit.cpp Vertex.cpp Line.cpp Polygon.cpp zoomedit_SOURCES = zoomedit.cpp window.cpp ui.cpp draw.cpp level.cpp geometry.cpp edit.cpp Vertex.cpp Line.cpp Polygon.cpp Rectangle.cpp
zoomedit_CPPFLAGS = @GTK_CFLAGS@ zoomedit_CPPFLAGS = @GTK_CFLAGS@
zoomedit_LDADD = @GTK_LIBS@ zoomedit_LDADD = @GTK_LIBS@

View file

@ -53,7 +53,7 @@ am_zoomedit_OBJECTS = zoomedit-zoomedit.$(OBJEXT) \
zoomedit-draw.$(OBJEXT) zoomedit-level.$(OBJEXT) \ zoomedit-draw.$(OBJEXT) zoomedit-level.$(OBJEXT) \
zoomedit-geometry.$(OBJEXT) zoomedit-edit.$(OBJEXT) \ zoomedit-geometry.$(OBJEXT) zoomedit-edit.$(OBJEXT) \
zoomedit-Vertex.$(OBJEXT) zoomedit-Line.$(OBJEXT) \ zoomedit-Vertex.$(OBJEXT) zoomedit-Line.$(OBJEXT) \
zoomedit-Polygon.$(OBJEXT) zoomedit-Polygon.$(OBJEXT) zoomedit-Rectangle.$(OBJEXT)
zoomedit_OBJECTS = $(am_zoomedit_OBJECTS) zoomedit_OBJECTS = $(am_zoomedit_OBJECTS)
zoomedit_DEPENDENCIES = zoomedit_DEPENDENCIES =
DEFAULT_INCLUDES = -I.@am__isrc@ DEFAULT_INCLUDES = -I.@am__isrc@
@ -171,7 +171,7 @@ sysconfdir = @sysconfdir@
target_alias = @target_alias@ target_alias = @target_alias@
top_builddir = @top_builddir@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
zoomedit_SOURCES = zoomedit.cpp window.cpp ui.cpp draw.cpp level.cpp geometry.cpp edit.cpp Vertex.cpp Line.cpp Polygon.cpp zoomedit_SOURCES = zoomedit.cpp window.cpp ui.cpp draw.cpp level.cpp geometry.cpp edit.cpp Vertex.cpp Line.cpp Polygon.cpp Rectangle.cpp
zoomedit_CPPFLAGS = @GTK_CFLAGS@ zoomedit_CPPFLAGS = @GTK_CFLAGS@
zoomedit_LDADD = @GTK_LIBS@ zoomedit_LDADD = @GTK_LIBS@
all: config.h all: config.h
@ -264,6 +264,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Line.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Line.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Polygon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Polygon.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Rectangle.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Vertex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-Vertex.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-draw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-draw.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-edit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoomedit-edit.Po@am__quote@
@ -427,6 +428,20 @@ zoomedit-Polygon.obj: Polygon.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoomedit-Polygon.obj `if test -f 'Polygon.cpp'; then $(CYGPATH_W) 'Polygon.cpp'; else $(CYGPATH_W) '$(srcdir)/Polygon.cpp'; fi` @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoomedit-Polygon.obj `if test -f 'Polygon.cpp'; then $(CYGPATH_W) 'Polygon.cpp'; else $(CYGPATH_W) '$(srcdir)/Polygon.cpp'; fi`
zoomedit-Rectangle.o: Rectangle.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zoomedit-Rectangle.o -MD -MP -MF $(DEPDIR)/zoomedit-Rectangle.Tpo -c -o zoomedit-Rectangle.o `test -f 'Rectangle.cpp' || echo '$(srcdir)/'`Rectangle.cpp
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/zoomedit-Rectangle.Tpo $(DEPDIR)/zoomedit-Rectangle.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Rectangle.cpp' object='zoomedit-Rectangle.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoomedit-Rectangle.o `test -f 'Rectangle.cpp' || echo '$(srcdir)/'`Rectangle.cpp
zoomedit-Rectangle.obj: Rectangle.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT zoomedit-Rectangle.obj -MD -MP -MF $(DEPDIR)/zoomedit-Rectangle.Tpo -c -o zoomedit-Rectangle.obj `if test -f 'Rectangle.cpp'; then $(CYGPATH_W) 'Rectangle.cpp'; else $(CYGPATH_W) '$(srcdir)/Rectangle.cpp'; fi`
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/zoomedit-Rectangle.Tpo $(DEPDIR)/zoomedit-Rectangle.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='Rectangle.cpp' object='zoomedit-Rectangle.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(zoomedit_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o zoomedit-Rectangle.obj `if test -f 'Rectangle.cpp'; then $(CYGPATH_W) 'Rectangle.cpp'; else $(CYGPATH_W) '$(srcdir)/Rectangle.cpp'; fi`
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \ unique=`for i in $$list; do \

View file

@ -38,11 +38,11 @@ int Polygon::quadrant(const Vertex &v) const {
} }
bool Polygon::contains(const Vertex &v) const { bool Polygon::contains(const Vertex &v) const {
const Line d1(-1, -1, 1, 1);
const Line d2(-1, 1, 1, -1);
int d = 0; int d = 0;
int q, ql, q2; int q, ql, q2;
LINE d1 = {Vertex(-1, -1), Vertex(1, 1)}; Line l;
LINE d2 = {Vertex(-1, 1), Vertex(1, -1)};
LINE l;
Vertex v2; Vertex v2;
@ -73,11 +73,11 @@ bool Polygon::contains(const Vertex &v) const {
d--; d--;
break; break;
default: default:
l.v1 = ((it == begin()) ? back() : *(it-1)) - v; l.setVertex1(((it == begin()) ? back() : *(it-1)) - v);
l.v2 = v2; l.setVertex2(v2);
if(q == 1 || q == 3) { if(q == 1 || q == 3) {
if(!(lineIntersection(&l, &d2, &v2) & INTERSECTION_LINE)) return false; if(!(l.intersects(d2, &v2) & INTERSECTION_LINE)) return false;
q2 = quadrant(v2); q2 = quadrant(v2);
if(q2 == 0) return true; if(q2 == 0) return true;
@ -86,7 +86,7 @@ bool Polygon::contains(const Vertex &v) const {
else d += 2; else d += 2;
} }
else { else {
if(!(lineIntersection(&l, &d1, &v2) & INTERSECTION_LINE)) return false; if(!(l.intersects(d1, &v2) & INTERSECTION_LINE)) return false;
q2 = quadrant(v2); q2 = quadrant(v2);
if(q2 == 0) return true; if(q2 == 0) return true;
@ -100,17 +100,17 @@ bool Polygon::contains(const Vertex &v) const {
return (d != 0); return (d != 0);
} }
bool Polygon::intersects(const LINE *l) const { bool Polygon::intersects(const Line &l) const {
LINE line; Line line;
for(Polygon::const_iterator it = begin(); it != end(); it++) { for(Polygon::const_iterator it = begin(); it != end(); it++) {
Polygon::const_iterator it2 = it+1; Polygon::const_iterator it2 = it+1;
if(it2 == end()) it2 = begin(); if(it2 == end()) it2 = begin();
line.v1 = *it; line.setVertex1(*it);
line.v2 = *it2; line.setVertex2(*it2);
if(lineIntersection(l, &line, NULL) == INTERSECTION_SEGMENT_SEGMENT) if(l.intersects(line, NULL) == INTERSECTION_SEGMENT_SEGMENT)
return true; return true;
} }

View file

@ -13,7 +13,7 @@ class Polygon : public std::vector<Vertex> {
double perimeter() const; double perimeter() const;
bool contains(const Vertex &v) const; bool contains(const Vertex &v) const;
bool intersects(const LINE *l) const; bool intersects(const Line &l) const;
}; };
#endif /*POLYGON_H_*/ #endif /*POLYGON_H_*/

50
Rectangle.cpp Normal file
View file

@ -0,0 +1,50 @@
#include "Rectangle.h"
bool Rectangle::contains(const Vertex &v) const {
return (edges(v) == EDGE_NONE);
}
int Rectangle::edges(const Vertex &v) const {
int ret = EDGE_NONE;
if(v.getX() < v1.getX()) ret |= EDGE_LEFT;
else if(v.getX() >= v2.getX()) ret |= EDGE_RIGHT;
if(v.getY() < v1.getY()) ret |= EDGE_TOP;
else if(v.getY() >= v2.getY()) ret |= EDGE_BOTTOM;
return ret;
}
int Rectangle::intersects(const Line &l, Vertex *v, int edge) const {
const Line top(v1.getX(), v1.getY(), v2.getX(), v1.getY());
const Line bottom(v1.getX(), v2.getY(), v2.getX(), v2.getY());
const Line left(v1.getX(), v1.getY(), v1.getX(), v2.getY());
const Line right(v2.getX(), v1.getY(), v2.getX(), v2.getY());
if(edge == EDGE_NONE) edge = edges(l.getVertex1());
if((edge & EDGE_TOP) && (top.intersects(l, v) == INTERSECTION_SEGMENT_SEGMENT))
return EDGE_TOP;
if((edge & EDGE_BOTTOM) && (bottom.intersects(l, v) == INTERSECTION_SEGMENT_SEGMENT))
return EDGE_BOTTOM;
if((edge & EDGE_LEFT) && (left.intersects(l, v) == INTERSECTION_SEGMENT_SEGMENT))
return EDGE_LEFT;
if((edge & EDGE_RIGHT) && (right.intersects(l, v) == INTERSECTION_SEGMENT_SEGMENT))
return EDGE_RIGHT;
v->setLocation(0, 0);
return EDGE_NONE;
}
int Rectangle::intersects(const Line &l, Vertex *v1, Vertex *v2, int edge) const {
int ret = EDGE_NONE;
if(edge == EDGE_NONE) edge = edges(l.getVertex1());
ret |= intersects(l, v1, edge);
ret |= intersects(l, v2, EDGE_ALL^edge);
return ret;
}

54
Rectangle.h Normal file
View file

@ -0,0 +1,54 @@
#ifndef RECTANGLE_H_
#define RECTANGLE_H_
#include "Vertex.h"
#include "Line.h"
#include <math.h>
#define EDGE_NONE 0
#define EDGE_LEFT (1<<0)
#define EDGE_RIGHT (1<<1)
#define EDGE_TOP (1<<2)
#define EDGE_BOTTOM (1<<3)
#define EDGE_ALL (EDGE_LEFT|EDGE_RIGHT|EDGE_TOP|EDGE_BOTTOM)
class Rectangle {
private:
Vertex v1, v2;
public:
Rectangle() {}
Rectangle(const Vertex& v1, const Vertex& v2) {
this->v1 = v1; this->v2 = v2;
}
Rectangle(double x, double y, double width, double height) {
v1.setLocation(x, y);
v2.setLocation(x+width, y+height);
}
Vertex &getVertex1() {return v1;}
const Vertex &getVertex1() const {return v1;}
void setVertex1(const Vertex &v) {v1 = v;}
Vertex &getVertex2() {return v2;}
const Vertex &getVertex2() const {return v2;}
void setVertex2(const Vertex &v) {v2 = v;}
double getWidth() const {return v2.getX()-v1.getX();}
void setWidth(double width) {v2.setX(v1.getX()+width);}
double getHeight() const {return v2.getY()-v1.getY();}
void setHeight(double height) {v2.setY(v1.getY()+height);}
double area() const {return getWidth()*getHeight();}
bool contains(const Vertex &v) const;
int edges(const Vertex &v) const;
int intersects(const Line &l, Vertex *v, int edge = EDGE_NONE) const;
int intersects(const Line &l, Vertex *v1, Vertex *v2, int edge = EDGE_NONE) const;
};
#endif /*RECTANGLE_H_*/

View file

@ -13,13 +13,15 @@ static double xTranslate = 0.0, yTranslate = 0.0;
static gboolean repaint = FALSE; static gboolean repaint = FALSE;
static void drawGrid(cairo_t *cr, const RECTANGLE *rect) { static void drawGrid(cairo_t *cr, const Rectangle *rect) {
double depth = log10(scale)-0.75; double depth = log10(scale)-0.75;
double depth2 = floor(depth); double depth2 = floor(depth);
double step = pow(0.1, depth2); double step = pow(0.1, depth2);
double d; double d;
int i; int i;
gchar *string; gchar *string;
double x1 = rect->getVertex1().getX(), y1 = rect->getVertex1().getY();
double x2 = rect->getVertex2().getX(), y2 = rect->getVertex2().getY();
cairo_set_font_size(cr, 10.0/scale); cairo_set_font_size(cr, 10.0/scale);
@ -28,9 +30,9 @@ static void drawGrid(cairo_t *cr, const RECTANGLE *rect) {
d = MIN(0.4*(depth-depth2+i), 0.5); d = MIN(0.4*(depth-depth2+i), 0.5);
cairo_set_source_rgb(cr, d, d, d); cairo_set_source_rgb(cr, d, d, d);
for(d = rect->x - fmod(rect->x, step) - step; d <= rect->x+rect->width; d+=step) { for(d = x1 - fmod(x1, step) - step; d <= x2; d+=step) {
cairo_move_to(cr, d, rect->y); cairo_move_to(cr, d, y1);
cairo_line_to(cr, d, rect->y+rect->height); cairo_line_to(cr, d, y2);
if(step > 0.005) { if(step > 0.005) {
if(step > 0.5) if(step > 0.5)
@ -38,16 +40,16 @@ static void drawGrid(cairo_t *cr, const RECTANGLE *rect) {
else else
string = g_strdup_printf("%.*f", -(int)floor(log10(step*1.1)), d+step/10); string = g_strdup_printf("%.*f", -(int)floor(log10(step*1.1)), d+step/10);
cairo_move_to(cr, d+1/scale, rect->y+11/scale); cairo_move_to(cr, d+1/scale, y1+11/scale);
cairo_show_text(cr, string); cairo_show_text(cr, string);
g_free(string); g_free(string);
} }
} }
for(d = rect->y - fmod(rect->y, step) - step; d <= rect->y+rect->height; d+=step) { for(d = y1 - fmod(y1, step) - step; d <= y2; d+=step) {
cairo_move_to(cr, rect->x, d); cairo_move_to(cr, x1, d);
cairo_line_to(cr, rect->x+rect->width, d); cairo_line_to(cr, x2, d);
if(step > 0.005) { if(step > 0.005) {
if(step > 0.5) if(step > 0.5)
@ -55,7 +57,7 @@ static void drawGrid(cairo_t *cr, const RECTANGLE *rect) {
else else
string = g_strdup_printf("%.*f", -(int)floor(log10(step*1.1)), d+step/10); string = g_strdup_printf("%.*f", -(int)floor(log10(step*1.1)), d+step/10);
cairo_move_to(cr, rect->x+3/scale, d+11/scale); cairo_move_to(cr, x1+3/scale, d+11/scale);
cairo_show_text(cr, string); cairo_show_text(cr, string);
g_free(string); g_free(string);
@ -68,7 +70,7 @@ static void drawGrid(cairo_t *cr, const RECTANGLE *rect) {
} }
} }
static void polygon2path(cairo_t *cr, const Polygon *polygon, const RECTANGLE *rect, gboolean close) { static void polygon2path(cairo_t *cr, const Polygon *polygon, const Rectangle *rect, gboolean close) {
Polygon polygon2; Polygon polygon2;
// no vertices // no vertices
@ -94,7 +96,7 @@ static void polygon2path(cairo_t *cr, const Polygon *polygon, const RECTANGLE *r
gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) { gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
cairo_t *cr; cairo_t *cr;
Vertex v1(-1, -1), v2(widget->allocation.width+1, widget->allocation.height+1); Vertex v1(-1, -1), v2(widget->allocation.width+1, widget->allocation.height+1);
RECTANGLE rect; Rectangle rect;
gboolean vertexOk; gboolean vertexOk;
static GdkPixmap *pixmap = NULL; static GdkPixmap *pixmap = NULL;
static double lastImageWidth = 0.0, lastImageHeight = 0.0; static double lastImageWidth = 0.0, lastImageHeight = 0.0;
@ -108,10 +110,8 @@ gboolean drawTopView(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
viewToImage(&v1); viewToImage(&v1);
viewToImage(&v2); viewToImage(&v2);
rect.x = v1.getX(); rect.setVertex1(v1);
rect.y = v1.getY(); rect.setVertex2(v2);
rect.width = v2.getX()-v1.getX();
rect.height = v2.getY()-v1.getY();
if(pixmap == NULL || fabs(lastImageWidth - getImageWidth()) >= 0.000001 || fabs(lastImageHeight - getImageHeight()) >= 0.000001 || if(pixmap == NULL || fabs(lastImageWidth - getImageWidth()) >= 0.000001 || fabs(lastImageHeight - getImageHeight()) >= 0.000001 ||
lastWidth != widget->allocation.width || lastHeight != widget->allocation.height || lastEditMode != getEditMode() || repaint) lastWidth != widget->allocation.width || lastHeight != widget->allocation.height || lastEditMode != getEditMode() || repaint)

View file

@ -75,28 +75,28 @@ ROOM *getHoveredRoom() {
return hoveredRoom; return hoveredRoom;
} }
static bool isLineOk(LINE *l) { static bool isLineOk(Line *l) {
LEVEL *lvl = getLevel(); LEVEL *lvl = getLevel();
LINE l2; Line l2;
if(activeRoom) { if(activeRoom) {
for(int i = 0; i+2 < activeRoom->polygon.size(); i++) { for(int i = 0; i+2 < activeRoom->polygon.size(); i++) {
l2.v1 = activeRoom->polygon[i]; l2.setVertex1(activeRoom->polygon[i]);
l2.v2 = activeRoom->polygon[i+1]; l2.setVertex2(activeRoom->polygon[i+1]);
if(lineIntersection(l, &l2, NULL) == INTERSECTION_SEGMENT_SEGMENT) return false; if(l->intersects(l2, NULL) == INTERSECTION_SEGMENT_SEGMENT) return false;
} }
if(activeRoom->polygon.size() > 1) { if(activeRoom->polygon.size() > 1) {
l2.v1 = activeRoom->polygon[activeRoom->polygon.size()-2]; l2.setVertex1(activeRoom->polygon[activeRoom->polygon.size()-2]);
l2.v2 = activeRoom->polygon.back(); l2.setVertex2(activeRoom->polygon.back());
if(vertexOnLine(&l->v2, &l2)) return false; if(l2.contains(l->getVertex2())) return false;
} }
} }
for(int i = 0; i < lvl->nRooms; i++) { for(int i = 0; i < lvl->nRooms; i++) {
if(lvl->rooms[i].polygon.intersects(l)) if(lvl->rooms[i].polygon.intersects(*l))
return false; return false;
} }
@ -105,7 +105,7 @@ static bool isLineOk(LINE *l) {
bool isVertexOk(Vertex *v) { bool isVertexOk(Vertex *v) {
LEVEL *lvl = getLevel(); LEVEL *lvl = getLevel();
LINE l; Line l;
int i; int i;
@ -116,8 +116,8 @@ bool isVertexOk(Vertex *v) {
if(!(getActiveRoom() && !getActiveRoom()->polygon.empty())) if(!(getActiveRoom() && !getActiveRoom()->polygon.empty()))
return true; return true;
l.v1 = getActiveRoom()->polygon.back(); l.setVertex1(getActiveRoom()->polygon.back());
l.v2 = *v; l.setVertex2(*v);
return isLineOk(&l); return isLineOk(&l);
} }
@ -126,7 +126,7 @@ bool isVertexOk(Vertex *v) {
bool isPolygonOk(Polygon *polygon) { bool isPolygonOk(Polygon *polygon) {
LEVEL *lvl = getLevel(); LEVEL *lvl = getLevel();
LINE l, l2; Line l, l2;
if(polygon->empty()) return false; if(polygon->empty()) return false;
@ -147,11 +147,11 @@ bool isPolygonOk(Polygon *polygon) {
Polygon::const_iterator it2 = it+1; Polygon::const_iterator it2 = it+1;
if(it2 == polygon->end()) it2 = polygon->begin(); if(it2 == polygon->end()) it2 = polygon->begin();
l.v1 = *it; l.setVertex1(*it);
l.v2 = *it2; l.setVertex2(*it2);
for(int i = 0; i < lvl->nRooms; i++) { for(int i = 0; i < lvl->nRooms; i++) {
if(lvl->rooms[i].polygon.intersects(&l)) if(lvl->rooms[i].polygon.intersects(l))
return false; return false;
} }
@ -162,10 +162,10 @@ bool isPolygonOk(Polygon *polygon) {
if(it == polygon->begin() && it4 == polygon->begin()) continue; if(it == polygon->begin() && it4 == polygon->begin()) continue;
l2.v1 = *it3; l2.setVertex1(*it3);
l2.v2 = *it4; l2.setVertex2(*it4);
if(lineIntersection(&l, &l2, NULL) == INTERSECTION_SEGMENT_SEGMENT) if(l.intersects(l2, NULL) == INTERSECTION_SEGMENT_SEGMENT)
return false; return false;
} }
} }

View file

@ -1,108 +1,37 @@
#include "geometry.h" #include "geometry.h"
#include <math.h>
#include <stdlib.h>
#include <gtk/gtk.h>
int vertexOnLine(const Vertex *v, const LINE *l) { static void edgeVertex(Vertex *v, int edge, const Rectangle *rect) {
if(l->v1.getX() == l->v2.getX() && l->v1.getY() == l->v2.getY()) {
if(l->v1.getX() == v->getX() && l->v1.getY() == v->getY()) return 1;
else return 0;
}
if(l->v1.getX() == l->v2.getX()) {
if(l->v1.getX() != v->getX()) return 0;
else if(v->getY() >= MIN(l->v1.getY(), l->v2.getY()) && v->getY() <= MAX(l->v1.getY(), l->v2.getY())) return 1;
else return 1;
}
if(l->v1.getY() == l->v2.getY()) {
if(l->v1.getY() != v->getY()) return 0;
else if(v->getX() >= MIN(l->v1.getX(), l->v2.getX()) && v->getX() <= MAX(l->v1.getX(), l->v2.getX())) return 1;
else return 1;
}
if((v->getX()-l->v1.getX())/(l->v2.getX()-l->v1.getX()) - (v->getY()-l->v1.getY())/(l->v2.getY()-l->v1.getY()) == 0) return 1;
else return 0;
}
int vertexInRect(const Vertex *v, const RECTANGLE *rect) {
int ret = EDGE_NONE;
if(v->getX() < rect->x) ret |= EDGE_LEFT;
else if(v->getX() >= rect->x+rect->width) ret |= EDGE_RIGHT;
if(v->getY() < rect->y) ret |= EDGE_TOP;
else if(v->getY() >= rect->y+rect->height) ret |= EDGE_BOTTOM;
return ret;
}
int lineRectIntersection(const LINE *l, const RECTANGLE *rect, int edge, Vertex *v) {
const double minX = rect->x, maxX = rect->x+rect->width;
const double minY = rect->y, maxY = rect->y+rect->height;
const LINE top = {Vertex(minX, minY), Vertex(maxX, minY)};
const LINE bottom = {Vertex(minX, maxY), Vertex(maxX, maxY)};
const LINE left = {Vertex(minX, minY), Vertex(minX, maxY)};
const LINE right = {Vertex(maxX, minY), Vertex(maxX, maxY)};
if((edge & EDGE_TOP) && (lineIntersection(&top, l, v) == INTERSECTION_SEGMENT_SEGMENT))
return EDGE_TOP;
if((edge & EDGE_BOTTOM) && (lineIntersection(&bottom, l, v) == INTERSECTION_SEGMENT_SEGMENT))
return EDGE_BOTTOM;
if((edge & EDGE_LEFT) && (lineIntersection(&left, l, v) == INTERSECTION_SEGMENT_SEGMENT))
return EDGE_LEFT;
if((edge & EDGE_RIGHT) && (lineIntersection(&right, l, v) == INTERSECTION_SEGMENT_SEGMENT))
return EDGE_RIGHT;
v->setLocation(0, 0);
return EDGE_NONE;
}
int lineRectIntersections(const LINE *line, const RECTANGLE *rect, int edge, Vertex *v1, Vertex *v2) {
int ret = EDGE_NONE;
ret |= lineRectIntersection(line, rect, edge, v1);
ret |= lineRectIntersection(line, rect, EDGE_ALL^edge, v2);
return ret;
}
static void edgeVertex(Vertex *v, int edge, const RECTANGLE *rect) {
if(edge == EDGE_NONE) if(edge == EDGE_NONE)
edge = vertexInRect(v, rect); edge = rect->edges(*v);
if(edge & EDGE_LEFT) v->setX(rect->x); if(edge & EDGE_LEFT) v->setX(rect->getVertex1().getX());
else if(edge & EDGE_RIGHT) v->setX(rect->x+rect->width); else if(edge & EDGE_RIGHT) v->setX(rect->getVertex2().getX());
if(edge & EDGE_TOP) v->setY(rect->y); if(edge & EDGE_TOP) v->setY(rect->getVertex1().getY());
else if(edge & EDGE_BOTTOM) v->setY(rect->y+rect->height); else if(edge & EDGE_BOTTOM) v->setY(rect->getVertex2().getY());
} }
static int simplifyVertex(Vertex *v, const Vertex *to, const RECTANGLE *rect) { static int simplifyVertex(Vertex *v, const Vertex *to, const Rectangle *rect) {
LINE l = {*v, *to}; Line l(*v, *to);
int edge, edge2; int edge, edge2;
edge = vertexInRect(v, rect); edge = rect->edges(*v);
if(edge == EDGE_NONE) return EDGE_NONE; if(edge == EDGE_NONE) return EDGE_NONE;
edge2 = lineRectIntersection(&l, rect, edge, v); edge2 = rect->intersects(l, v, edge);
if(edge2 != EDGE_NONE) return edge2; if(edge2 != EDGE_NONE) return edge2;
edgeVertex(v, edge, rect); edgeVertex(v, edge, rect);
return edge; return edge;
} }
static void addSimplifiedLine(const Vertex *v1, const Vertex *v2, const Rectangle *rect, int last, Polygon *out) {
const Line d1(rect->getVertex1(), rect->getVertex2());
static void addSimplifiedLine(const Vertex *v1, const Vertex *v2, const RECTANGLE *rect, int last, Polygon *out) { const Line d2(rect->getVertex1().getX(), rect->getVertex2().getY(), rect->getVertex2().getX(), rect->getVertex1().getY());
const LINE d1 = {Vertex(rect->x, rect->y), Vertex(rect->x+rect->width, rect->y+rect->height)};
const LINE d2 = {Vertex(rect->x, rect->y+rect->height), Vertex(rect->x+rect->width, rect->y)};
LINE l = {*v1, *v2}; Line l(*v1, *v2);
Vertex v, vi; Vertex v, vi;
int edge1, edge2; int edge1, edge2;
@ -115,11 +44,11 @@ static void addSimplifiedLine(const Vertex *v1, const Vertex *v2, const RECTANGL
edge2 = simplifyVertex(&v, v1, rect); edge2 = simplifyVertex(&v, v1, rect);
if(edge1 != EDGE_NONE && edge2 != EDGE_NONE && !(edge1 & edge2)) { if(edge1 != EDGE_NONE && edge2 != EDGE_NONE && !(edge1 & edge2)) {
if(lineIntersection(&l, &d1, &vi) == INTERSECTION_SEGMENT_LINE) { if(l.intersects(d1, &vi) == INTERSECTION_SEGMENT_LINE) {
edgeVertex(&vi, 0, rect); edgeVertex(&vi, 0, rect);
out->push_back(vi); out->push_back(vi);
} }
else if(lineIntersection(&l, &d2, &vi) == INTERSECTION_SEGMENT_LINE) { else if(l.intersects(d1, &vi) == INTERSECTION_SEGMENT_LINE) {
edgeVertex(&vi, 0, rect); edgeVertex(&vi, 0, rect);
out->push_back(vi); out->push_back(vi);
} }
@ -129,7 +58,7 @@ static void addSimplifiedLine(const Vertex *v1, const Vertex *v2, const RECTANGL
out->push_back(v); out->push_back(v);
} }
void simplifyPolygon(const Polygon *in, const RECTANGLE *rect, Polygon *out) { void simplifyPolygon(const Polygon *in, const Rectangle *rect, Polygon *out) {
Vertex v; Vertex v;
if(in->empty()) return; if(in->empty()) return;

View file

@ -2,33 +2,10 @@
#define GEOMETRY_H_ #define GEOMETRY_H_
#include "Vertex.h"
#include "Polygon.h" #include "Polygon.h"
#include "Line.h" #include "Rectangle.h"
#include <glib.h>
#define EDGE_NONE 0
#define EDGE_LEFT (1<<0)
#define EDGE_RIGHT (1<<1)
#define EDGE_TOP (1<<2)
#define EDGE_BOTTOM (1<<3)
#define EDGE_ALL (EDGE_LEFT|EDGE_RIGHT|EDGE_TOP|EDGE_BOTTOM)
void simplifyPolygon(const Polygon *in, const Rectangle *rect, Polygon *out);
typedef struct _RECTANGLE {
double x, y, width, height;
} RECTANGLE;
int vertexOnLine(const Vertex *v, const LINE *l);
int vertexInRect(const Vertex *v, const RECTANGLE *rect);
int lineRectIntersection(const LINE *l, const RECTANGLE *rect, int edge, Vertex *v);
int lineRectIntersections(const LINE *line, const RECTANGLE *rect, int edge, Vertex *v1, Vertex *v2);
//gboolean linePolygonIntersection(const LINE *l, const POLYGON *p);
void simplifyPolygon(const Polygon *in, const RECTANGLE *rect, Polygon *out);
#endif /*GEOMETRY_H_*/ #endif /*GEOMETRY_H_*/