#include "GeomTest.h" Pointf LineCross(Pointf a, Pointf a1, Pointf b, Pointf b1) { Pointf A = a1 - a; Pointf B = b1 - b; double d = A.y * B.x - B.y * A.x; if(d == 0) return Null; double tb = (A.x * (b.y - a.y) + A.y * (a.x - b.x)) / d; if(tb <= 0 || tb >= 1) return Null; double ta = (B.x * tb + b.x - a.x) / A.x; return ta > 0 && ta < 1 ? B * tb + b : Null; } static int sCrosses(Pointf a, double y0, Pointf b, Pointf b1, double y1) { double By = b1.y - b.y; if(By == 0) return (y0 < b.y && b.y < y1 || y0 > b.y && b.y > y1) && (a.y == b.y && a.x < b.x)/* || (a.y == b1.y && a.x < b1.x)*/; if(a.y == b.y) return (y0 < b.y && b.y < b1.y || y0 > b.y && b.y > b1.y) && b.x > a.x; if(a.y == b1.y) return 0; // return (b.y < b1.y && b1.y < y2 || b.y > b1.y && b1.y > y2) && b1.x > a.x; double tb = (a.y - b.y) / By; return tb >= 0 && tb < 1 && (b1.x - b.x) * tb + b.x - a.x > 0; } bool InPolygon(Pointf p, const Vector& polygon) { int q = 0; if(polygon.GetCount() < 2) return false; int n = polygon.GetCount(); for(int i = 0; i < polygon.GetCount(); i++) q += sCrosses(p, polygon[(i + n - 1) % n].y, polygon[i], polygon[(i + 1) % n], polygon[(i + 2) % n].y); return q & 1; } void GeomTest::LeftDown(Point p, dword flags) { p = 4 * p / 4; if(flags & K_ALT) { paintin = !paintin; Refresh(); return; } if(flags & K_CTRL) polygon.Clear(); polygon.Add(p); Refresh(); } void GeomTest::MouseMove(Point p, dword) { point = p; Refresh(); } void GeomTest::Paint(Draw& w) { Size sz = GetSize(); w.DrawRect(sz, SWhite); if(polygon.GetCount() == 0) return; if(polygon.GetCount() == 1) { w.DrawRect((int)polygon[0].x, (int)polygon[0].y, 1, 1, SBlack); return; } for(int i = 0; i < polygon.GetCount() - 1; i++) w.DrawLine(polygon[i], polygon[i + 1]); w.DrawLine(polygon[i], polygon[0]); // if(paintin) for(int i = 0; i < polygon.GetCount(); i++) { int y = polygon[i].y; for(int x = 0; x < sz.cx; x++) if(InPolygon(Pointf(x, y), polygon)) w.DrawRect(x, y, 1, 1, SLtCyan); } if(InPolygon(point, polygon)) w.DrawText(0, 0, "IN", Arial(20).Bold()); } GeomTest::GeomTest() { BackPaint(); paintin = false; polygon.Add(Pointf(100, 100)); polygon.Add(Pointf(200, 100)); polygon.Add(Pointf(150, 150)); polygon.Add(Pointf(250, 150)); } GUI_APP_MAIN { GeomTest().Run(); }