ultimatepp/uppsrc/Geom/geometry.cpp
rylek 5daee1fcff .Sql: added 'binary' flag to SqlColumnInfo to check for binary columns
.OleDB: fixed logic for fetching multiple BLOB columns from a rowset
.OleDB: fixed BLOB update logic based on SqlRaw
.Geom/Draw: removed assembly variant of matrix-vector multiplication

git-svn-id: svn://ultimatepp.org/upp/trunk@3322 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2011-04-03 23:04:30 +00:00

269 lines
6.9 KiB
C++

#include "Geom.h"
NAMESPACE_UPP
Pointf Length(const Pointf& p, double length)
{
double l = max(Length(p), AbsMax(p));
Pointf out = p;
if(l)
out *= length / l;
return out;
}
Sizef Length(const Sizef& p, double length)
{
double l = max(Length(p), AbsMax(p));
Sizef out = p;
if(l)
out *= length / l;
return out;
}
Pointf Project(const Pointf& p, const Pointf& A, const Pointf& B)
{
Pointf AB = B - A;
double length = Squared(AB);
if(length == 0)
return A;
return A + AB * ((AB ^ (p - A)) / length);
}
/* TRC 09/04/22: moved to Core by CXL
double Bearing(const Pointf& 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;
}
*/
Pointf Bezier2(const Pointf& a, const Pointf& b, const Pointf& c, double t)
{
Pointf ab = b - a, bc = c - b;
return a + (ab * (2 * t) + (bc - ab) * (t * t));
}
double Bezier2Length(const Pointf& a, const Pointf& b, const Pointf& c, double t)
{
Pointf v = b - a, w = (c - b) - v;
v *= 2;
double w2 = Squared(w);
if(fabs(w2) <= 1e-100)
return t * Distance(c, a);
double k = ScalarProduct(Sizef(v), Sizef(w)) / (2 * w2);
double d = fabs(VectorProduct(Sizef(v), Sizef(w))) / (2 * w2);
double wl = sqrt(w2);
double x = t + k;
if(fabs(d) <= 1e-100)
return wl * x * fabs(x) / 2;
return wl * (x * hypot(x, d) + (d * d) * argsinh(x / d));
}
Sizef Bezier2Tangent(const Pointf& a, const Pointf& b, const Pointf& c, double t)
{
Sizef ab = b - a, bc = c - b;
return 2.0 * (ab + t * (bc - ab));
}
Sizef Orthogonal(const Sizef& v, const Sizef& against)
{
return v - against * ((v ^ against) / Squared(against));
}
Sizef Orthonormal(const Sizef& v, const Sizef& against)
{
return Unit(Orthogonal(v, against));
}
Sizef GetFarthestAxis(const Sizef& v)
{
return fabs(v.cx) <= fabs(v.cy) ? Sizef(1, 0) : Sizef(0, 1);
}
double Distance(const Rectf& rc, const Pointf& pt)
{
double dx = (pt.x >= rc.right ? pt.x - rc.right : pt.x <= rc.left ? pt.x - rc.left : 0);
double dy = (pt.y >= rc.bottom ? pt.y - rc.bottom : pt.y <= rc.top ? pt.y - rc.top : 0);
if(dx == 0)
return fabs(dy);
if(dy == 0)
return fabs(dx);
return hypot(dx, dy);
}
Rectf& SetUnion(Rectf& rc, const Pointf& pt)
{
if(IsNull(pt))
return rc;
if(IsNull(rc))
{
rc.left = rc.right = pt.x;
rc.top = rc.bottom = pt.y;
return rc;
}
if(pt.x < rc.left) rc.left = pt.x;
if(pt.x > rc.right) rc.right = pt.x;
if(pt.y < rc.top) rc.top = pt.y;
if(pt.y > rc.bottom) rc.bottom = pt.y;
return rc;
}
Rectf GetUnion(const Array<Pointf>& pt)
{
if(pt.IsEmpty())
return Null;
Rectf rc = PointfRectf(pt[0]);
for(int i = 1; i < pt.GetCount(); i++)
rc |= pt[i];
return rc;
}
Rectf& SetMinMaxMove(Rectf& rc, const Rectf& outer_rc)
{
if(IsNull(rc))
return rc;
if(IsNull(outer_rc))
return rc = Null;
if(rc.right > outer_rc.right) rc.OffsetHorz(outer_rc.right - rc.right);
if(rc.bottom > outer_rc.bottom) rc.OffsetVert(outer_rc.bottom - rc.bottom);
if(rc.left < outer_rc.left) rc.OffsetHorz(outer_rc.left - rc.left);
if(rc.top < outer_rc.top) rc.OffsetVert(outer_rc.top - rc.top);
rc &= outer_rc;
return rc;
}
const Matrixf& Matrixf_0() { static Matrixf m(0, 0, 0, 0, 0, 0); return m; }
const Matrixf& Matrixf_1() { static Matrixf m(1, 0, 0, 1, 0, 0); return m; }
const Matrixf& Matrixf_Null() { static Matrixf m(Null, Null, Null, Null, Null, Null); return m; }
const Matrixf& Matrixf_MirrorX() { static Matrixf m(1, 0, 0, -1, 0, 0); return m; }
const Matrixf& Matrixf_MirrorY() { static Matrixf m(-1, 0, 0, 1, 0, 0); return m; }
Matrixf MatrixfMove(Pointf vector)
{
return Matrixf(1, 0, 0, 1, vector.x, vector.y);
}
Matrixf MatrixfRotate(double angle, Pointf f)
{
Pointf temp = PolarPointf(angle);
Matrixf out(temp, Left(temp));
out.Fix(f);
return out;
}
Matrixf MatrixfScale(double scale, Pointf f)
{
Matrixf out(Pointf(scale, 0), Pointf(0, scale));
out.Fix(f);
return out;
}
Matrixf MatrixfScale(Pointf scale, Pointf f)
{
Matrixf out(Pointf(scale.x, 0), Pointf(0, scale.y));
out.Fix(f);
return out;
}
Matrixf MatrixfScale(const Rectf& src, const Rectf& dest)
{
Matrixf result(Pointf(dest.Width() / src.Width(), 0), Pointf(0, dest.Height() / src.Height()));
result.a = dest.TopLeft() - src.TopLeft() * result;
return result;
}
Matrixf MatrixfMirror(Pointf A, Pointf B)
{
Pointf V = B - A;
double vx2 = sqr(V.x);
double vy2 = sqr(V.y);
double det = vx2 + vy2;
double dif = (vx2 - vy2) / det;
double mul = 2 * V.x * V.y / det;
Matrixf out(Pointf(vx2 - vy2, mul), Pointf(mul, vy2 - vx2));
out.Fix(A);
return out;
}
Matrixf MatrixfAffine (Pointf src1, Pointf dest1, Pointf src2, Pointf dest2)
{
return MatrixfAffine(src1, dest1, src2, dest2, src1 + Right(src2 - src1), dest1 + Right(dest2 - dest1));
}
Matrixf MatrixfAffine (Pointf src1, Pointf dest1, Pointf src2, Pointf dest2, Pointf src3, Pointf dest3)
{
Matrixf rev(src2 - src1, src3 - src1, src1);
if(fabs(Determinant(rev)) <= 1e-100)
return MatrixfMove((dest1 - src1 + dest2 - src2 + dest3 - src3) / 3.0);
return MatrixfInverse(rev) * Matrixf(dest2 - dest1, dest3 - dest1, dest1);
}
Matrixf& Matrixf::operator *= (const Matrixf& m)
{
double xx = m.x.x * x.x + m.y.x * x.y;
double xy = m.x.x * y.x + m.y.x * y.y;
double yx = m.x.y * x.x + m.y.y * x.y;
double yy = m.x.y * y.x + m.y.y * y.y;
x = Pointf(xx, yx);
y = Pointf(xy, yy);
a *= m;
return *this;
}
Pointf operator * (Pointf point, const Matrixf& matrix)
{
return Pointf(
point.x * matrix.x.x + point.y * matrix.y.x + matrix.a.x,
point.x * matrix.x.y + point.y * matrix.y.y + matrix.a.y);
}
Pointf operator / (Pointf point, const Matrixf& matrix)
{
return point * MatrixfInverse(matrix);
}
Rectf operator * (const Rectf& rect, const Matrixf& matrix)
{
if(IsNull(rect))
return Null;
double xl = min(rect.left, rect.right), xh = max(rect.left, rect.right);
double yl = min(rect.top, rect.bottom), yh = max(rect.top, rect.bottom);
Rectf out;
out.left = matrix.x.x * (matrix.x.x >= 0 ? xl : xh) + matrix.y.x * (matrix.y.x >= 0 ? yl : yh) + matrix.a.x;
out.top = matrix.x.y * (matrix.x.y >= 0 ? xl : xh) + matrix.y.y * (matrix.y.y >= 0 ? yl : yh) + matrix.a.y;
out.right = matrix.x.x * (matrix.x.x >= 0 ? xh : xl) + matrix.y.x * (matrix.y.x >= 0 ? yh : yl) + matrix.a.x;
out.bottom = matrix.x.y * (matrix.x.y >= 0 ? xh : xl) + matrix.y.y * (matrix.y.y >= 0 ? yh : yl) + matrix.a.y;
return out;
}
Rectf operator / (const Rectf& rect, const Matrixf& matrix)
{
return rect * MatrixfInverse(matrix);
}
double MatrixfMeasure(const Matrixf& mx)
{
double det = Determinant(mx);
return (det >= 0 ? +1 : -1) * sqrt(fabs(det));
}
Matrixf MatrixfInverse(const Matrixf& mx)
{
double det = Determinant(mx);
Matrixf m(Pointf(mx.y.y, -mx.x.y) / det, Pointf(-mx.y.x, mx.x.x) / det);
m.a = -mx.a % m;
return m;
}
String Matrixf::ToString() const
{
return String().Cat() << "[x = " << x << ", y = " << y << ", a = " << a << "]";
}
END_UPP_NAMESPACE