diff --git a/uppdev/GeomTest/GeomTest.upp b/uppdev/GeomTest/GeomTest.upp index 2a7586f10..68ed2aebf 100644 --- a/uppdev/GeomTest/GeomTest.upp +++ b/uppdev/GeomTest/GeomTest.upp @@ -1,12 +1,11 @@ -uses - CtrlLib; - -file - "GeomTest.h" - , main.cpp - - -; - -mainconfig - "" = "GUI ST"; +uses + CtrlLib, + Geom; + +file + GeomTest.h, + main.cpp; + +mainconfig + "" = "GUI ST"; + diff --git a/uppdev/GeomTest/init b/uppdev/GeomTest/init new file mode 100644 index 000000000..0c8115e1e --- /dev/null +++ b/uppdev/GeomTest/init @@ -0,0 +1,5 @@ +#ifndef _GeomTest_icpp_init_stub +#define _GeomTest_icpp_init_stub +#include "CtrlLib/init" +#include "Geom/init" +#endif diff --git a/uppdev/Mirrors/main.cpp b/uppdev/Mirrors/main.cpp index bf728c468..956e7cf93 100644 --- a/uppdev/Mirrors/main.cpp +++ b/uppdev/Mirrors/main.cpp @@ -40,14 +40,14 @@ GUI_APP_MAIN for(int i = 0; i < 10; i++) { int a, b; do { - a = Random(20) + 1; - b = Random(20) + 1; + a = Random(35) + 1; + b = Random(35) + 1; } while(a + b < 0 || a + b > 20); r.DrawText(10, 10 + isz.cy * 2 * i, Format("%d + %d = ", a, b), fnt); do { - a = Random(20) + 1; - b = Random(20) + 1; + a = Random(35) + 1; + b = Random(35) + 1; } while(a - b < 0); r.DrawText(2000, 10 + isz.cy * 2 * i, Format("%d - %d = ", a, b), fnt); diff --git a/uppdev/ScanLine/Bezier.cpp b/uppdev/ScanLine/Bezier.cpp index 990cc125e..385bf2827 100644 --- a/uppdev/ScanLine/Bezier.cpp +++ b/uppdev/ScanLine/Bezier.cpp @@ -1,16 +1,7 @@ #include "ScanLine.h" -double SquareDist(Pointf p1, Pointf p2) -{ - return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y); -} - -Pointf Mid(Pointf a, Pointf b) -{ - return (a + b) / 2; -} - -static void sQuadratic(VertexTarget& t, Pointf p1, Pointf p2, Pointf p3, double qt, int lvl) +static void sQuadratic(VertexTarget& t, const Pointf& p1, const Pointf& p2, const Pointf& p3, + double qt, int lvl) { if(lvl < 32) { Pointf d = p3 - p1; @@ -31,14 +22,16 @@ static void sQuadratic(VertexTarget& t, Pointf p1, Pointf p2, Pointf p3, double t.Line(p3); } -void ApproximateQuadratic(VertexTarget& t, Pointf p1, Pointf p2, Pointf p3, double tolerance) +void ApproximateQuadratic(VertexTarget& t, const Pointf& p1, const Pointf& p2, const Pointf& p3, + double tolerance) { sQuadratic(t, p1, p2, p3, tolerance * tolerance, 0); t.Line(p3); } -static void sCubic(VertexTarget& t, Pointf p1, Pointf p2, Pointf p3, Pointf p4, double qt, - int lvl) +static void sCubic(VertexTarget& t, + const Pointf& p1, const Pointf& p2, const Pointf& p3, const Pointf& p4, + double qt, int lvl) { if(lvl < 32) { Pointf d = p4 - p1; @@ -66,7 +59,9 @@ static void sCubic(VertexTarget& t, Pointf p1, Pointf p2, Pointf p3, Pointf p4, t.Line(p4); } -void ApproximateCubic(VertexTarget& t, Pointf p1, Pointf p2, Pointf p3, Pointf p4, double tolerance) +void ApproximateCubic(VertexTarget& t, + const Pointf& p1, const Pointf& p2, const Pointf& p3, const Pointf& p4, + double tolerance) { sCubic(t, p1, p2, p3, p4, tolerance * tolerance, 0); t.Line(p4); diff --git a/uppdev/ScanLine/Math.cpp b/uppdev/ScanLine/Math.cpp new file mode 100644 index 000000000..0f4065390 --- /dev/null +++ b/uppdev/ScanLine/Math.cpp @@ -0,0 +1,51 @@ +#include "ScanLine.h" + +double SquareDist(const Pointf& p1, const Pointf& p2) +{ + return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y); +} + +Pointf Mid(const Pointf& a, const Pointf& b) +{ + return (a + b) / 2; +} + +Pointf Ortogonal(const Pointf& p) +{ + return Pointf(-p.y, p.x); +} + +double SquareLength(const Pointf& p) +{ + return p.x * p.x + p.y * p.y; +} + +double Length(const Pointf& p) +{ + return sqrt(SquareLength(p)); +} + +double Bearing(const Pointf& p) +{ + return atan2(p.y, p.x); +} + +double Distance(const Pointf& p1, const Pointf& p2) +{ + return Length(p1 - p2); +} + +double SquareDistance(const Pointf& p1, const Pointf& p2) +{ + return SquareLength(p1 - p2); +} + +Pointf PolarPointf(double a) +{ + return Pointf(cos(a), sin(a)); +} + +Pointf Polar(const Pointf& p, double r, double a) +{ + return p + r * PolarPointf(a); +} diff --git a/uppdev/ScanLine/RasterizerClip.cpp b/uppdev/ScanLine/RasterizerClip.cpp index 1bf3c7133..c8fea7754 100644 --- a/uppdev/ScanLine/RasterizerClip.cpp +++ b/uppdev/ScanLine/RasterizerClip.cpp @@ -8,7 +8,7 @@ void Rasterizer::Move(double x, double y) inline int Cv(double x) { - return int(x * 256 + 0.5); + return fround(x * 256); } void Rasterizer::CvLine(double x1, double y1, double x2, double y2) diff --git a/uppdev/ScanLine/ScanLine.h b/uppdev/ScanLine/ScanLine.h index 149e629cd..c43dc1ff0 100644 --- a/uppdev/ScanLine/ScanLine.h +++ b/uppdev/ScanLine/ScanLine.h @@ -65,28 +65,66 @@ struct ScanLine { void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color, bool evenodd); +double SquareDist(const Pointf& p1, const Pointf& p2); +Pointf Mid(const Pointf& a, const Pointf& b); +Pointf Ortogonal(const Pointf& p); +double SquareLength(const Pointf& p); +double Length(const Pointf& p); +double Bearing(const Pointf& p); +double Distance(const Pointf& p1, const Pointf& p2); +double SquareDistance(const Pointf& p1, const Pointf& p2); +Pointf PolarPointf(double a); +Pointf Polar(const Pointf& p, double r, double a); + struct VertexTarget { - virtual void Move(Pointf p) = 0; - virtual void Line(Pointf p) = 0; + virtual void Move(const Pointf& p) = 0; + virtual void Line(const Pointf& p) = 0; virtual void End() = 0; }; struct VertexProcessor : VertexTarget { VertexTarget *target; + + void PutMove(const Pointf& p) { target->Move(p); } + void PutLine(const Pointf& p) { target->Line(p); } + void PutEnd() { target->End(); } + + VertexProcessor& operator|(VertexProcessor& b) { target = &b; return b; } + void operator|(VertexTarget& b) { target = &b; } }; -class Stroker : VertexProcessor { -public: - virtual void Move(double x, double y); - virtual void Line(double x, double y); - virtual void End(); +enum { + LINECAP_BUTT, + LINECAP_SQUARE, + LINECAP_ROUND, + + LINEJOIN_MITER, + LINEJOIN_ROUND, + LINEJOIN_BEVEL, }; -class Dasher : VertexProcessor { +class Stroker : public VertexProcessor { + double w2; + double qmiter; + double fid; + + Pointf p0, v0, o0, a0, b0; + Pointf p1, v1, o1, a1, b1; + Pointf p2; + int linecap; + int linejoin; + + void Finish(); + void Round(const Pointf& p, const Pointf& v1, const Pointf& v2, double r); + void Cap(const Pointf& p0, const Pointf& v0, const Pointf& o0, + const Pointf& a0, const Pointf& b0); + public: - virtual void Move(double x, double y); - virtual void Line(double x, double y); + virtual void Move(const Pointf& p); + virtual void Line(const Pointf& p); virtual void End(); + + Stroker(double width, double miterlimit, double tolerance, int linecap, int linejoin); }; class Transformer : VertexProcessor { @@ -96,10 +134,8 @@ public: virtual void End(); }; -double SquareDist(Pointf p1, Pointf p2); - -void ApproximateQuadratic(VertexTarget& t, Pointf p1, Pointf p2, Pointf p3, double tolerance); -void ApproximateCubic(VertexTarget& t, Pointf x0, Pointf x1, Pointf x2, Pointf x, double tolerance); +void ApproximateQuadratic(VertexTarget& t, const Pointf& p1, const Pointf& p2, const Pointf& p3, double tolerance); +void ApproximateCubic(VertexTarget& t, const Pointf& x0, const Pointf& x1, const Pointf& x2, const Pointf& x, double tolerance); #define Painter NewPainter diff --git a/uppdev/ScanLine/ScanLine.upp b/uppdev/ScanLine/ScanLine.upp index 0861ea228..3c1123762 100644 --- a/uppdev/ScanLine/ScanLine.upp +++ b/uppdev/ScanLine/ScanLine.upp @@ -14,7 +14,9 @@ file Rasterizer3.h, Rasterizer3.cpp, RasterizerClip.cpp, + Math.cpp, Bezier.cpp, + Stroker.cpp, Path.cpp, help.txt, Lion.cpp, diff --git a/uppdev/ScanLine/Stroker.cpp b/uppdev/ScanLine/Stroker.cpp new file mode 100644 index 000000000..183ba8933 --- /dev/null +++ b/uppdev/ScanLine/Stroker.cpp @@ -0,0 +1,150 @@ +#include "ScanLine.h" + +Stroker::Stroker(double width, double miterlimit, double tolerance, int linecap, int linejoin) +: linecap(linecap), + linejoin(linejoin) +{ + w2 = width / 2; + qmiter = miterlimit * w2; + qmiter *= qmiter; + fid = acos(1 - tolerance / w2); + p0 = p1 = p2 = Null; +} + +void Stroker::Move(const Pointf& p) +{ + Finish(); + p1 = p; + p0 = p2 = Null; +} + +void Stroker::Round(const Pointf& p, const Pointf& v1, const Pointf& v2, double r) +{ + double tolerance = 0.3; + double a1 = Bearing(v1); + double a2 = Bearing(v2); + if(a1 < a2) + a1 += 2 * M_PI; + while(a1 > a2) { + PutLine(Polar(p, r, a1)); + a1 -= fid; + } +} + +void Stroker::Line(const Pointf& p3) +{ + if(p3 == p2) + return; + if(IsNull(p1)) { + Move(p3); + return; + } + if(IsNull(p2)) { + p2 = p3; + v1 = p2 - p1; + o1 = Ortogonal(v1) * w2 / Length(v1); + a1 = p1 + o1; + b1 = p1 - o1; + if(IsNull(p0)) { + p0 = p1; + v0 = v1; + o0 = o1; + a0 = a1; + b0 = b1; + } + return; + } + + Pointf v2 = p3 - p2; + Pointf o2 = Ortogonal(v2) * w2 / Length(v2); + Pointf a2 = p2 + o2; + Pointf b2 = p2 - o2; + + double d = v1.y * v2.x - v2.y * v1.x; + if(d > 1e-30) { + Pointf ts = a1 + v1 * (v2.y * (a1.x - a2.x) - v2.x * (a1.y - a2.y)) / d; + PutMove(a1); + if(linejoin != LINEJOIN_MITER || SquareDistance(ts, p2) > qmiter) { + PutLine(a1 + v1); + if(linejoin == LINEJOIN_ROUND) + Round(p2, o1, o2, w2); + } + else + PutLine(ts); + PutLine(a2); + PutMove(b2); + PutLine(p2); + PutLine(b1 + v1); + PutLine(b1); + } + else + if(d < -1e-30) { + Pointf ts = b2 + v2 * (v1.y * (a2.x - a1.x) - v1.x * (a2.y - a1.y)) / d; + PutMove(b2); + if(linejoin != LINEJOIN_MITER || SquareDistance(ts, p2) > qmiter) { + if(linejoin == LINEJOIN_ROUND) + Round(p2, -o2, -o1, w2); + PutLine(b1 + v1); + } + else + PutLine(ts); + PutLine(b1); + PutMove(a1); + PutLine(a1 + v1); + PutLine(p2); + PutLine(a2); + } + else { + PutMove(a1); + PutLine(a1 + v1); + if(linejoin == LINEJOIN_ROUND) + Round(p2, o1, o2, w2); + PutLine(a2); + PutMove(b2); + PutLine(b1 + v1); + PutLine(b1); + } + p1 = p2; + v1 = v2; + o1 = o2; + a1 = a2; + b1 = b2; + p2 = p3; +} + +void Stroker::Cap(const Pointf& p, const Pointf& v, const Pointf& o, + const Pointf& a, const Pointf& b) +{ + PutMove(a); + if(linecap == LINECAP_SQUARE) { + Pointf nv = Ortogonal(o); + PutLine(a + nv); + PutLine(b + nv); + } + if(linecap == LINECAP_ROUND) + Round(p, -o, o, w2); + PutLine(b); +} + +void Stroker::Finish() +{ + if(IsNull(p1) || IsNull(p2)) + return; + if(p2 == p0) + Line(p0 + v0); + else { + PutMove(a1); + PutLine(a1 + v1); + PutMove(b1 + v1); + PutLine(b1); + Cap(p0, v0, o0, b0, a0); + Cap(p2, -v1, -o1, a1 + v1, b1 + v1); + } + p1 = p2 = Null; + PutEnd(); +} + +void Stroker::End() +{ + Finish(); +} diff --git a/uppdev/ScanLine/main.cpp b/uppdev/ScanLine/main.cpp index f4f9fc24f..22dafcbda 100644 --- a/uppdev/ScanLine/main.cpp +++ b/uppdev/ScanLine/main.cpp @@ -14,6 +14,8 @@ struct Raget : VertexTarget { struct App : TopWindow { double x1, y1, x2, y2, x3, y3; + + Pointf p1, p2, p3, p4; String Text() { return Format("r.Move(%f, %f);\nr.Line(%f, %f);\nr.Line(%f, %f);\nr.Line(%f, %f);\n", x1, y1, x2, y2, x3, y3, x1, y1); @@ -21,30 +23,24 @@ struct App : TopWindow { virtual void LeftDown(Point p, dword keyflags) { - x1 = p.x; - y1 = p.y; + (keyflags & K_ALT ? p4 : p1) = p; Refresh(); - ClearClipboard(); - AppendClipboardText(Text()); } virtual void RightDown(Point p, dword) { - x2 = p.x; - y2 = p.y; + p2 = p; Refresh(); - ClearClipboard(); - AppendClipboardText(Text()); } virtual void MouseMove(Point p, dword keyflags) { - x3 = p.x; - y3 = p.y; + p2 = p; Refresh(); - ClearClipboard(); - AppendClipboardText(Text()); } + virtual Image CursorImage(Point p, dword keyflags) { return Image::Cross(); } - virtual void Paint(Draw& w) { + virtual void Paint(Draw& w); + + virtual void Paint1(Draw& w) { ImageBuffer ib(600, 600); Fill(~ib, White(), ib.GetLength()); /* Apply(ib[20], 100, Black(), a); @@ -72,15 +68,14 @@ struct App : TopWindow { r.Line(x1, y1); #endif - Raget q(r); #if 1 r.Move(200, 300); - ApproximateQuadratic(q, Pointf(200, 300), Pointf(400, 50), Pointf(600, 300), 0.3); +// ApproximateQuadratic(q, Pointf(200, 300), Pointf(400, 50), Pointf(600, 300), 0.3); r.Line(200, 300); Render(ib, r, Red(), false); #endif r.Move(100, 200); - ApproximateCubic(q, Pointf(100, 200), Pointf(100, 100), Pointf(250, 100), Pointf(250, 200), 2); +// ApproximateCubic(q, Pointf(100, 200), Pointf(100, 100), Pointf(250, 100), Pointf(250, 200), 2); r.Line(150, 400); r.Line(100, 200); Render(ib, r, Blue(), false); @@ -99,10 +94,87 @@ struct App : TopWindow { } App() { - x1 = y1 = x2 = y2 = 0; + p1 = p4 = Pointf(100, 100); + p2 = Pointf(200, 100); + p3 = Pointf(150, 200); } }; +struct RasterizerTarget : VertexTarget { + Rasterizer& r; + ImageBuffer& ib; + + virtual void Line(const Pointf& p) + { + r.Line(p.x, p.y); + } + virtual void Move(const Pointf& p) + { + r.Move(p.x, p.y); + } + virtual void End() + { + Render(ib, r, Black(), false); + } + + RasterizerTarget(ImageBuffer& ib, Rasterizer& r) : ib(ib), r(r) {} +}; + +#if 1 +void App::Paint(Draw& w) +{ + Size sz = GetSize(); + ImageBuffer ib(sz.cx, sz.cy); + Rasterizer r(sz.cx, sz.cy); + Fill(~ib, White(), ib.GetLength()); + RasterizerTarget tgt(ib, r); + + Stroker s(20, 4, 0.3, LINECAP_ROUND, LINEJOIN_ROUND); + + s|tgt; + + s.Move(p1); + s.Line(p2); +// s.Line(p3); +// s.Line(p4); + s.End(); + + w.DrawImage(0, 0, ib); +} + +#else +struct LineTarget : VertexTarget { + Draw& w; + Pointf p; + + virtual void Line(const Pointf& p1) + { + w.DrawLine(p.x, p.y, p1.x, p1.y); + p = p1; + } + virtual void Move(const Pointf& p1) + { + p = p1; + } + virtual void End() {} + + LineTarget(Draw& w) : w(w) {} +}; + +void App::Paint(Draw& w) +{ + w.DrawRect(GetSize(), White()); + LineTarget ltg(w); + Stroker s(20, 4, 0.3, LINECAP_ROUND, LINEJOIN_ROUND); + s|ltg; + s.Move(p1); + s.Line(p2); +// s.Line(p3); +// s.Line(p4); + s.End(); +} +#endif + GUI_APP_MAIN { App().Run(); #ifdef _DEBUG diff --git a/uppdev/Stroke/init b/uppdev/Stroke/init index b73050e95..d2be6ee9b 100644 --- a/uppdev/Stroke/init +++ b/uppdev/Stroke/init @@ -2,4 +2,5 @@ #define _Stroke_icpp_init_stub #include "CtrlLib/init" #include "Painter/init" +#include "Geom/init" #endif diff --git a/uppdev/Stroke/main.cpp b/uppdev/Stroke/main.cpp index 2a6086fec..480956963 100644 --- a/uppdev/Stroke/main.cpp +++ b/uppdev/Stroke/main.cpp @@ -7,12 +7,14 @@ struct App : TopWindow { Pointf p1; Pointf p2; Pointf p3; + bool round; virtual void LeftDown(Point p, dword keyflags); virtual void MouseMove(Point p, dword keyflags); virtual void Paint(Draw& w); + virtual Image CursorImage(Point p, dword keyflags) { return Image::Cross(); } - App() { BackPaint(); p2 = p3 = Pointf(0.0, 0.0); p1 = Pointf(300.0, 300.0); } + App() { BackPaint(); p2 = Pointf(1195, 300); p3 = Pointf(500.0, 300.0); p1 = Pointf(300.0, 300.0); round = true; } }; Pointf Ortogonal(Pointf p) @@ -20,41 +22,26 @@ Pointf Ortogonal(Pointf p) return Pointf(-p.y, p.x); } +double SquareLength(Pointf p) +{ + return p.x * p.x + p.y * p.y; +} + double Length(Pointf p) { - return sqrt(p.x * p.x + p.y * p.y); + return sqrt(SquareLength(p)); } -double Intersection0(Pointf p1, Pointf v1, Pointf p2, Pointf v2) +double Bearing(Pointf p) { -// p1.x + v1.x * t1 = p2.x + v2.x * t2; -// p1.y + v1.y * t1 = p2.y + v2.y * t2; -// t2 = (p1.x + v1.x * t1 - p2.x) / v2.x -// m2 = v2.y / v2.x; -// p1.y + v1.y * t1 = p2.y + v2.y * (p1.x + v1.x * t1 - p2.x) / v2.x; -// p1.y + v1.y * t1 = p2.y + m2 * p1.x + m2 * v1.x * t1 - m2 * p2.x; - -// p1.y + v1.y * t1 = ; -// v1.y * t1 - m2 * v1.x * t1 = p2.y + m2 * p1.x - m2 * p2.x - p1.y; -// t1 = (p2.y + m2 * p1.x - m2 * p2.x - p1.y) / (v1.y - m2 * v1.x) - double m2 = v2.y / v2.x; - return (p2.y - p1.y + m2 * (p1.x - p2.x)) / (v1.y - m2 * v1.x); -} - -Pointf Swapped(Pointf p) -{ - return Pointf(p.y, p.x); -} - -double Intersection(Pointf p1, Pointf v1, Pointf p2, Pointf v2) -{ - return v2.x < 1e-30 ? Intersection0(Swapped(p1), Swapped(v1), Swapped(p2), Swapped(v2)) - : Intersection0(p1, v1, p2, v2); -} - -Pointf Mirror(Pointf c, Pointf p) -{ - return 2 * c - p; + if(p.y == 0) + return (p.x >= 0 ? 0 : M_PI); + if(p.x == 0) + return (p.y >= 0 ? M_PI_2 : 3 * M_PI_2); + double b = atan2(p.y, p.x); + if(b < 0) + b += 2 * M_PI; + return b; } double Distance(Pointf p1, Pointf p2) @@ -62,6 +49,14 @@ double Distance(Pointf p1, Pointf p2) return Length(p1 - p2); } +double SquareDistance(Pointf p1, Pointf p2) +{ + return SquareLength(p1 - p2); +} + +Pointf PolarPointf(double a) { return Pointf(cos(a), sin(a)); } +Pointf Polar(Pointf p, double r, double a) { return p + r * PolarPointf(a) ; } + void App::LeftDown(Point p, dword keyflags) { p3 = p; @@ -74,79 +69,125 @@ void App::MouseMove(Point p, dword keyflags) Refresh(); } +void Round(Painter& sw, Pointf p, Pointf v1, Pointf v2, double r) +{ + double tolerance = 0.3; + double a1 = Bearing(v1); + double a2 = Bearing(v2); + double df = acos(1 - tolerance / r); + if(a1 < a2) + a1 += 2 * M_PI; + while(a1 > a2) { + sw.Line(Polar(p, r, a1)); + a1 -= df; + } +} + void App::Paint(Draw& w) { ImageBuffer ib(GetSize()); BufferPainter sw(ib); sw.Clear(White()); - sw.Move(p1.x, p1.y).Line(p2.x, p2.y).Line(p3.x, p3.y); - sw.Stroke(40, Gray()); - sw.Stroke(2, LtRed()); + + int join = 0; +// sw.Move(p1.x, p1.y).Line(p2.x, p2.y).Line(p3.x, p3.y); +// sw.Stroke(40, Gray()); +// sw.Stroke(2, LtRed()); sw.Circle(p2.x, p2.y, 3).Fill(White()).Stroke(1, Black()); - + double w2 = 20; - double miterlimit = 4 * w2; + double qmiterlimit = 16 * w2 * w2; Pointf v1 = p2 - p1; - Pointf o1 = Ortogonal(v1); - double l1 = Length(v1); - double u1 = w2 / l1; + Pointf o1 = Ortogonal(v1) * w2 / Length(v1); - Pointf t1 = p1 + u1 * o1; - Pointf b1 = p1 - u1 * o1; + Pointf t1 = p1 + o1; + Pointf b1 = p1 - o1; Pointf v2 = p3 - p2; - Pointf o2 = Ortogonal(v2); - double l2 = Length(v2); - double u2 = w2 / l2; + Pointf o2 = Ortogonal(v2) * w2 / Length(v2); - Pointf t2 = p2 + u2 * o2; - Pointf b2 = p2 - u2 * o2; -// DrawPoint(w, t2); -// DrawPoint(w, b2); - - double s1 = Intersection(t1, v1, t2, v2); + Pointf t2 = p2 + o2; + Pointf b2 = p2 - o2; - Pointf ts = t1 + s1 * v1; - Pointf bs = Mirror(p2, ts); - - Pointf t3 = p3 + u2 * o2; - Pointf b3 = p3 - u2 * o2; - - if(s1 < 1) { - Swap(t1, b1); - Swap(t2, b2); - Swap(ts, bs); - Swap(t3, b3); - u1 = -u1; - u2 = -u2; + Color c; + double d = join == 1 ? 0 : v1.y * v2.x - v2.y * v1.x; + if(d > 1e-30) { + Pointf ts = t1 + v1 * (v2.y * (t1.x - t2.x) - v2.x * (t1.y - t2.y)) / d; + sw.Move(t1); + if(join || SquareDistance(ts, p2) > qmiterlimit) { + sw.Line(t1 + v1); + if(join == 2) + Round(sw, p2, o1, o2, w2); + sw.Line(t2); + } + else + sw.Line(ts); + sw.Line(t2 + v2); + sw.Move(b2 + v2); + sw.Line(b2); + sw.Line(p2); + sw.Line(b1 + v1); + sw.Line(b1); + c = LtBlue(); } - - if(Distance(ts, p2) > miterlimit) { - Pointf bevel1 = p2 + u1 * o1; - Pointf bevel2 = p2 + u2 * o2; - sw.Move(t1.x, t1.y); - sw.Line(bevel1.x, bevel1.y); - sw.Line(bevel2.x, bevel2.y); - sw.Line(t3.x, t3.y); + else + if(d < -1e-30) { + Pointf ts = b2 + v2 * (v1.y * (t2.x - t1.x) - v1.x * (t2.y - t1.y)) / d; + sw.Move(b2 + v2); + if(join || SquareDistance(ts, p2) > qmiterlimit) { + sw.Line(b2); + if(join == 2) + Round(sw, p2, -o2, -o1, w2); + sw.Line(b1 + v1); + } + else + sw.Line(ts); + sw.Line(b1); + sw.Move(t1); + sw.Line(t1 + v1); + sw.Line(p2); + sw.Line(t2); + sw.Line(t2 + v2); + c = LtGreen(); } else { - sw.Move(t1.x, t1.y); - sw.Line(ts.x, ts.y); - sw.Line(t3.x, t3.y); + sw.Move(t1); + sw.Line(t1 + v1); + if(round) + Round(sw, p2, o1, o2, w2); + sw.Line(t2); + sw.Line(t2 + v2); + sw.Move(b2 + v2); + sw.Line(b2); + sw.Line(b1 + v1); + sw.Line(b1); + c = LtRed(); } - - sw.Move(b1.x, b1.y); - sw.Line(bs.x, bs.y); - sw.Line(b3.x, b3.y); - sw.Stroke(1, LtRed()); + + + sw.Move(b1); + sw.Line(t1); + + sw.Move(p3 - o2); + sw.Line(p3 + o2); + +#if 0 + sw.EvenOdd(true); + sw.Fill(c); +#else + sw.Stroke(1, c); +#endif w.DrawImage(0, 0, ib); + + String s; + s << p1 << " - " << p2 << " - " << p3 << ", D=" << d; + w.DrawText(0, 0, s); } GUI_APP_MAIN { App().Run(); } - diff --git a/uppdev/benchsin/benchsin.cpp b/uppdev/benchsin/benchsin.cpp new file mode 100644 index 000000000..62aeb4600 --- /dev/null +++ b/uppdev/benchsin/benchsin.cpp @@ -0,0 +1,40 @@ +#include + +using namespace Upp; + +CONSOLE_APP_MAIN +{ + double h = 0; + { + RTIMING("sin"); + for(double x = 0; x < 1000000; x += 0.1) + h += sin(x); + } + { + RTIMING("asin"); + for(double x = 0; x < 1000000; x += 0.1) + h += asin(x); + } + { + RTIMING("acos"); + for(double x = 0; x < 1000000; x += 0.1) + h += acos(x); + } + { + RTIMING("add"); + for(double x = 0; x < 1000000; x += 0.1) + h += x; + } + { + RTIMING("mul"); + for(double x = 0; x < 1000000; x += 0.1) + h *= x; + } + { + RTIMING("sqrt"); + for(double x = 0; x < 1000000; x += 0.1) + h += sqrt(x); + } + RDUMP(h); +} + diff --git a/uppdev/benchsin/benchsin.upp b/uppdev/benchsin/benchsin.upp new file mode 100644 index 000000000..565fb4a0d --- /dev/null +++ b/uppdev/benchsin/benchsin.upp @@ -0,0 +1,10 @@ +uses + Core; + +file + benchsin.cpp; + +mainconfig + "" = "SSE2", + "" = ""; + diff --git a/uppdev/benchsin/init b/uppdev/benchsin/init new file mode 100644 index 000000000..6c9f451ec --- /dev/null +++ b/uppdev/benchsin/init @@ -0,0 +1,4 @@ +#ifndef _benchsin_icpp_init_stub +#define _benchsin_icpp_init_stub +#include "Core/init" +#endif