[mapguide-commits] r1353 - trunk/MgDev/Common/Stylization
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Thu Mar 22 21:54:26 EDT 2007
Author: jasonnogar
Date: 2007-03-22 21:54:26 -0400 (Thu, 22 Mar 2007)
New Revision: 1353
Added:
trunk/MgDev/Common/Stylization/SE_LineStorage.cpp
trunk/MgDev/Common/Stylization/SE_LineStorage.h
Modified:
trunk/MgDev/Common/Stylization/Makefile.am
trunk/MgDev/Common/Stylization/SE_IdentityJoin.cpp
trunk/MgDev/Common/Stylization/SE_IdentityJoin.h
trunk/MgDev/Common/Stylization/SE_MiterJoin.cpp
trunk/MgDev/Common/Stylization/SE_MiterJoin.h
trunk/MgDev/Common/Stylization/SE_PiecewiseTransform.h
trunk/MgDev/Common/Stylization/Stylization.vcproj
Log:
Symbology:
* Rewrite of the Join classes
* Now supporting arbitrary # of joins on one symbol
* Transform of entire linebuffers
* Improved design.
* Added to vcproj
* SE_LineStorage
* Moved out of LineBuffer.cpp into a separate file
Modified: trunk/MgDev/Common/Stylization/Makefile.am
===================================================================
--- trunk/MgDev/Common/Stylization/Makefile.am 2007-03-23 00:43:55 UTC (rev 1352)
+++ trunk/MgDev/Common/Stylization/Makefile.am 2007-03-23 01:54:26 UTC (rev 1353)
@@ -20,6 +20,7 @@
SE_MiterJoin.cpp \
SE_ExpressionBase.cpp \
SE_LineBuffer.cpp \
+ SE_LineStorage.cpp \
SE_PositioningAlgorithms.cpp \
SE_Renderer.cpp \
SE_StyleVisitor.cpp \
@@ -78,6 +79,7 @@
SE_SymbolDefProxies.h \
SE_RenderProxies.h \
SE_LineBuffer.h \
+ SE_LineStorage.h \
SE_Matrix.h \
SE_PositioningAlgorithms.h \
SE_Renderer.h \
Modified: trunk/MgDev/Common/Stylization/SE_IdentityJoin.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_IdentityJoin.cpp 2007-03-23 00:43:55 UTC (rev 1352)
+++ trunk/MgDev/Common/Stylization/SE_IdentityJoin.cpp 2007-03-23 01:54:26 UTC (rev 1353)
@@ -16,78 +16,123 @@
//
#include "SE_IdentityJoin.h"
+#include "SE_LineStorage.h"
#include <float.h>
-SE_IdentityJoin::SE_IdentityJoin(RS_Bounds& bounds, double chop, bool end) :
- m_chop(chop),
- m_end(end),
- m_identity_region(),
- m_xf_bounds()
+SE_IdentityJoin::SE_IdentityJoin(RS_Bounds& bounds, double offset, const RS_F_Point& pt0, const RS_F_Point& pt1) :
+ m_xf_bounds(DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX),
+ m_xform()
{
- if (end)
+ RS_F_Point dp(pt1.x - pt0.x, pt1.y - pt0.y);
+ double len = sqrt(dp.x*dp.x + dp.y*dp.y);
+ double invlen = 1.0/len;
+ dp.x *= invlen;
+ dp.y *= invlen;
+
+ /* Rotate around leading edge */
+ m_xform.translateX(-bounds.minx);
+ m_xform.rotate(dp.y, dp.x);
+ dp.x *= offset;
+ dp.y *= offset;
+ /* Position left edge offset pixels along the line from pt0 */
+ m_xform.translate(pt0.x + dp.x, pt0.y + dp.y);
+
+ m_bounds = bounds;
+ double underreach = len - bounds.width() - offset;
+ if (offset < 0)
{
- m_identity_region.minx = -DBL_MAX;
- m_identity_region.maxx = bounds.maxx - chop;
- m_xf_bounds.maxx = m_identity_region.maxx;
- m_xf_bounds.minx = bounds.minx;
+ m_bounds.minx -= offset;
+ m_chop_start = m_bounds.minx;
}
- else
+ if (underreach < 0)
{
- m_identity_region.maxx = DBL_MAX;
- m_identity_region.minx = bounds.minx + chop;
- m_xf_bounds.minx = m_identity_region.minx;
- m_xf_bounds.maxx = bounds.maxx;
+ m_bounds.maxx += underreach;
+ m_chop_end = m_bounds.maxx;
}
-
- m_identity_region.miny = -DBL_MAX;
- m_identity_region.maxy = DBL_MAX;
- m_xf_bounds.miny = bounds.miny;
- m_xf_bounds.maxy = bounds.maxy;
}
-RS_Bounds* SE_IdentityJoin::GetIdentityRegions(int &length)
-{
- length = 1;
- return &m_identity_region;
-}
-
RS_F_Point* SE_IdentityJoin::GetDiscontinuities(int &length)
{
length = 0;
return NULL;
}
-RS_Bounds* SE_IdentityJoin::GetNonlinearRegions(int &length)
+RS_Bounds& SE_IdentityJoin::GetTransformedBounds()
{
- length = 0;
- return NULL;
+ if (!m_xf_bounds.IsValid() && m_bounds.IsValid())
+ {
+ RS_F_Point xfpt;
+
+ xfpt.x = m_bounds.minx;
+ xfpt.y = m_bounds.miny;
+ m_xform.transform(xfpt.x, xfpt.y);
+ m_xf_bounds.add_point(xfpt);
+
+ xfpt.x = m_bounds.minx;
+ xfpt.y = m_bounds.maxy;
+ m_xform.transform(xfpt.x, xfpt.y);
+ m_xf_bounds.add_point(xfpt);
+
+ xfpt.x = m_bounds.maxx;
+ xfpt.y = m_bounds.miny;
+ m_xform.transform(xfpt.x, xfpt.y);
+ m_xf_bounds.add_point(xfpt);
+
+ xfpt.x = m_bounds.maxx;
+ xfpt.y = m_bounds.maxy;
+ m_xform.transform(xfpt.x, xfpt.y);
+ m_xf_bounds.add_point(xfpt);
+ }
+
+ return m_xf_bounds;
}
-RS_Bounds& SE_IdentityJoin::GetTransformedBounds()
+void SE_IdentityJoin::GetXChop(double& startx, double& endx)
{
- return m_xf_bounds;
+ startx = m_chop_start;
+ endx = m_chop_end;
}
-double SE_IdentityJoin::GetXChop(bool &chopEnd)
+RS_F_Point* SE_IdentityJoin::Transform(const RS_F_Point& pt0, const RS_F_Point& pt1, int& length)
{
- chopEnd = m_end;
- return m_chop;
+ length = 2;
+ m_xform.transform(pt0.x, pt0.y, m_points[0].x, m_points[0].y);
+ m_xform.transform(pt1.x, pt1.y, m_points[1].x, m_points[1].y);
+ return m_points;
}
-void SE_IdentityJoin::Transform(double& /*x*/, double& /*y*/, SE_TransformInfo* info)
+void SE_IdentityJoin::Transform(SE_LineStorage* source, SE_LineStorage* dest, bool closed)
{
- if (info)
- {
- info->dXdx = 1.0;
- info->dYdy = 1.0;
- info->dYdx = 0.0;
- info->dXdy = 0.0;
- info->d2Xdx2 = 0.0;
- info->d2Ydx2 = 0.0;
- info->d2Xdy2 = 0.0;
- info->d2Ydy2 = 0.0;
- info->d2Xdxdy = 0.0;
- info->d2Ydxdy = 0.0;
+ const RS_Bounds& bounds = source->bounds();
+ if (bounds.minx < m_chop_start || bounds.maxx > m_chop_end)
+ { /* Chopping may be required */
+ dest->SetChopInfo(m_chop_start, m_chop_end, closed);
+
+ int n_cntrs = source->cntr_count();
+ int* contours = source->cntrs();
+ double* src = source->points();
+
+ for (int i = 0; i < n_cntrs; i++)
+ {
+ double x, y;
+ double* last = src + 2*contours[i];
+ x = *src++;
+ y = *src++;
+ dest->EnsureContours(1);
+ dest->EnsurePoints(1);
+ dest->_MoveTo(x, y);
+
+ while (src < last)
+ {
+ x = *src++;
+ y = *src++;
+ dest->EnsurePoints(1);
+ dest->_LineTo(x, y);
+ }
+ }
+ dest->Transform(m_xform);
}
+ else
+ dest->SetToTransform(m_xform, source);
}
Modified: trunk/MgDev/Common/Stylization/SE_IdentityJoin.h
===================================================================
--- trunk/MgDev/Common/Stylization/SE_IdentityJoin.h 2007-03-23 00:43:55 UTC (rev 1352)
+++ trunk/MgDev/Common/Stylization/SE_IdentityJoin.h 2007-03-23 01:54:26 UTC (rev 1353)
@@ -19,30 +19,37 @@
#define SE_IDENTITYJOIN_H
#include "SE_PiecewiseTransform.h"
+#include "SE_Matrix.h"
class SE_IdentityJoin : public SE_PiecewiseTransform
{
public:
/* bounds: The bounds of the symbol.
- * chop: The amount to remove in pixel units
- * end: The symbol is truncated backwards from maxx if true, or forwards from minx if not
+ * offset: The distance along the line in pixels from pt0 to the beginning of the symbol
+ * pt0: The start point of the line segment
+ * pt1: The end point of the line segment
*/
- SE_IdentityJoin(RS_Bounds& bounds, double chop, bool end);
+ SE_IdentityJoin(RS_Bounds& bounds, double offset, const RS_F_Point& pt0, const RS_F_Point& pt1);
virtual RS_F_Point* GetDiscontinuities(int &length);
- virtual RS_Bounds* GetIdentityRegions(int &length);
- virtual RS_Bounds* GetNonlinearRegions(int &length);
virtual RS_Bounds& GetTransformedBounds();
- virtual double GetXChop(bool &chopEnd);
+ virtual void GetXChop(double& startx, double& endx);
- virtual void Transform(double& x, double &y, SE_TransformInfo* info);
+ virtual RS_F_Point* Transform(const RS_F_Point& pt0, const RS_F_Point& pt1, int& length);
+ virtual void Transform(SE_LineStorage* src, SE_LineStorage* dst, bool closed);
+
private:
- double m_chop;
- bool m_end;
- RS_Bounds m_identity_region;
+ double m_chop_start;
+ double m_chop_end;
+
+ RS_F_Point m_points[2];
+
+ SE_Matrix m_xform;
+
RS_Bounds m_xf_bounds;
+ RS_Bounds m_bounds;
};
#endif // SE_IDENTITYJOIN_H
Added: trunk/MgDev/Common/Stylization/SE_LineStorage.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_LineStorage.cpp (rev 0)
+++ trunk/MgDev/Common/Stylization/SE_LineStorage.cpp 2007-03-23 01:54:26 UTC (rev 1353)
@@ -0,0 +1,208 @@
+//
+// Copyright (C) 2007 by Autodesk, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of version 2.1 of the GNU Lesser
+// General Public License as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#include "SE_LineStorage.h"
+#include "stdafx.h"
+
+void SE_LineStorage::_MoveTo(double x, double y)
+{
+ if (m_do_chop && (x < m_chop_start || x > m_chop_end))
+ {
+ m_chop_x = x;
+ m_chop_y = y;
+ m_chopped = true;
+ return;
+ }
+
+ m_types[m_cur_types++] = (unsigned char)stMoveTo;
+ m_pts[m_cur_pts++] = x;
+ m_pts[m_cur_pts++] = y;
+
+ m_last_x = x;
+ m_last_y = y;
+
+ m_cntrs[++m_cur_cntr] = 1;
+}
+
+void SE_LineStorage::_LineTo(double x, double y)
+{
+ if (m_do_chop)
+ {
+ bool chopStart = x < m_chop_start;
+ if (chopStart || x > m_chop_end)
+ {
+ m_chop_x = x;
+ m_chop_y = y;
+ if (m_chopped)
+ return;
+
+ double lastx, lasty;
+ lastx = m_pts[m_cur_pts-2];
+ lasty = m_pts[m_cur_pts-1];
+ m_cross_x = chopStart ? m_chop_start : m_chop_end;
+ m_cross_y = lasty + (y - lasty)*(m_cross_x - lastx)/(x - lastx);
+ m_chopped = m_crossed = true;
+ x = m_cross_x;
+ y = m_cross_y;
+ }
+ else if (m_chopped)
+ {
+ double sy = m_chop_y + (y - m_chop_y)*(m_cross_x - m_chop_x)/(x - m_chop_x);
+ if (!m_close_chops || !m_crossed)
+ {
+ if (m_crossed)
+ EnsureContours(1);
+ _MoveTo(m_cross_x, sy);
+ }
+ else
+ {
+ m_types[m_cur_types++] = (unsigned char)stLineTo;
+ m_pts[m_cur_pts++] = m_cross_x;
+ m_pts[m_cur_pts++] = sy;
+ m_cntrs[m_cur_cntr]++;
+ }
+ m_chopped = false;
+ if (x == m_cross_x)
+ return;
+ EnsurePoints(1);
+ }
+ }
+
+ m_types[m_cur_types++] = (unsigned char)stLineTo;
+ m_pts[m_cur_pts++] = x;
+ m_pts[m_cur_pts++] = y;
+
+ m_cntrs[m_cur_cntr]++;
+}
+
+void SE_LineStorage::SetToTransform(const SE_Matrix& xform, LineBuffer* lb)
+{
+ EnsurePoints(lb->point_count());
+ EnsureContours(lb->cntr_count());
+
+ int n_cntrs = lb->cntr_count();
+ int* contours = lb->cntrs();
+ double* src = lb->points();
+ double* dst = m_pts;
+
+ for (int i = 0; i < n_cntrs; i++)
+ {
+ double sx, sy, *tx, *ty;
+ double* last = src + 2*contours[i];
+ sx = *src++;
+ sy = *src++;
+ xform.transform(sx, sy, m_last_x, m_last_y);
+ *dst++ = m_last_x;
+ *dst++ = m_last_y;
+
+ while (src < last)
+ {
+ sx = *src++;
+ sy = *src++;
+ tx = dst++;
+ ty = dst++;
+ xform.transform(sx, sy, *tx, *ty);
+ }
+ }
+
+ memcpy(m_types, lb->types(), lb->point_count());
+ memcpy(m_cntrs, lb->cntrs(), sizeof(int)*lb->cntr_count());
+
+ m_cur_types = lb->point_count();
+ m_cur_pts = m_cur_types*2;
+ m_cur_cntr = lb->cntr_count() - 1;
+
+ m_geom_type = lb->geom_type();
+ xform.transform(m_last_x, m_last_y);
+}
+
+void SE_LineStorage::SetToCopy(SE_LineStorage* src)
+{
+ m_do_chop = src->m_do_chop;
+ m_chopped = src->m_chopped;
+ m_close_chops = src->m_close_chops;
+ m_crossed = src->m_crossed;
+ m_chop_start = src->m_chop_start;
+ m_chop_end = src->m_chop_end;
+ m_cross_x = src->m_cross_x;
+ m_cross_y = src->m_cross_y;
+ m_chop_x = src->m_chop_x;
+ m_chop_y = src->m_chop_y;
+ m_last_x = src->_LastX();
+ m_last_y = src->_LastY();
+ m_bounds = src->bounds();
+ m_geom_type = src->geom_type();
+ int grow_types = src->point_count() - m_types_len;
+ if (grow_types > 0)
+ EnsurePoints(m_types_len + grow_types);
+ int grow_cntrs = src->cntr_count() - m_cntrs_len;
+ if (grow_cntrs > 0)
+ EnsureContours(m_cntrs_len + grow_cntrs);
+ memcpy(m_pts, src->points(), sizeof(double)*2*src->point_count());
+ memcpy(m_types, src->types(), src->point_count());
+ memcpy(m_cntrs, src->cntrs(), sizeof(int)*src->cntr_count());
+ m_cur_pts = src->point_count()*2;
+ m_cur_types = src->point_count();
+ m_cur_cntr = src->cntr_count() - 1;
+}
+
+void SE_LineStorage::Transform(const SE_Matrix& xform)
+{
+ double* cur = m_pts;
+ double* end = m_pts + m_cur_pts;
+ double *x, *y;
+
+ while (cur < end)
+ {
+ x = cur++;
+ y = cur++;
+ xform.transform(*x, *y);
+ }
+}
+
+void SE_LineStorage::_ResizePoints(int n)
+{
+ int len = 2*m_pts_len;
+ if (len - m_pts_len < 2*n)
+ len += 2*n;
+
+ double* tempPts = new double[len];
+ memcpy(tempPts, m_pts, sizeof(double)*m_pts_len);
+ delete[] m_pts;
+ m_pts = tempPts;
+ m_pts_len = len;
+
+ len /= 2;
+ unsigned char* tempTypes = new unsigned char[len];
+ memcpy(tempTypes, m_types, sizeof(unsigned char) * m_types_len);
+ delete[] m_types;
+ m_types = tempTypes;
+ m_types_len = len;
+}
+
+void SE_LineStorage::_ResizeContours(int n)
+{
+ int len = 2*m_cntrs_len;
+ if (len - m_pts_len < n)
+ len += n;
+
+ int* tempCntrs = new int[len];
+ memcpy(tempCntrs, m_cntrs, sizeof(int)*m_cntrs_len);
+ delete[] m_cntrs;
+ m_cntrs = tempCntrs;
+ m_cntrs_len = len;
+}
Added: trunk/MgDev/Common/Stylization/SE_LineStorage.h
===================================================================
--- trunk/MgDev/Common/Stylization/SE_LineStorage.h (rev 0)
+++ trunk/MgDev/Common/Stylization/SE_LineStorage.h 2007-03-23 01:54:26 UTC (rev 1353)
@@ -0,0 +1,141 @@
+//
+// Copyright (C) 2007 by Autodesk, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of version 2.1 of the GNU Lesser
+// General Public License as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#ifndef SE_LINESTORAGE_H
+#define SE_LINESTORAGE_H
+
+#include "LineBuffer.h"
+#include "SE_Matrix.h"
+#include "SE_Bounds.h"
+
+class SE_LineStorage : public LineBuffer
+{
+public:
+ SE_INLINE SE_LineStorage(int size);
+ SE_INLINE void EnsurePoints(int n);
+ SE_INLINE void EnsureContours(int n);
+ SE_INLINE void SetBounds(double minx, double miny, double maxx, double maxy);
+ SE_INLINE void SetBounds(SE_Bounds* bounds);
+ SE_INLINE void SetChopInfo(double startx, double endx, bool closeChops);
+ SE_INLINE void Reset();
+
+ SE_INLINE void _MoveToNoChop(double x, double y);
+ SE_INLINE void _LineToNoChop(double x, double y);
+
+ void _MoveTo(double x, double y);
+ void _LineTo(double x, double y);
+
+ /* Both of these methods invalidate the bounds. SetBounds must be called manually to restore them. */
+ void SetToTransform(const SE_Matrix& xform, LineBuffer* src);
+ void SetToCopy(SE_LineStorage* src);
+ void Transform(const SE_Matrix& xform);
+
+private:
+ SE_INLINE double& _LastX() { return m_last_x; }
+ SE_INLINE double& _LastY() { return m_last_y; }
+ void _ResizePoints(int n);
+ void _ResizeContours(int n);
+
+ bool m_do_chop;
+ bool m_chopped;
+
+ bool m_close_chops;
+ bool m_crossed;
+ double m_chop_start;
+ double m_chop_end;
+ double m_cross_x;
+ double m_cross_y;
+ double m_chop_x;
+ double m_chop_y;
+};
+
+/* Inline Functions */
+
+SE_LineStorage::SE_LineStorage(int size) :
+ LineBuffer(size),
+ m_do_chop(false),
+ m_chopped(false),
+ m_crossed(false)
+{
+}
+
+void SE_LineStorage::EnsurePoints(int n)
+{
+ if (m_cur_pts + 2*n >= m_pts_len)
+ _ResizePoints(n);
+}
+
+void SE_LineStorage::EnsureContours(int n)
+{
+ if (m_cur_cntr + 2 + n > m_cntrs_len)
+ _ResizeContours(n);
+}
+
+void SE_LineStorage::SetBounds(double minx, double miny, double maxx, double maxy)
+{
+ m_bounds.minx = minx;
+ m_bounds.miny = miny;
+ m_bounds.maxx = maxx;
+ m_bounds.maxy = maxy;
+}
+
+void SE_LineStorage::SetBounds(SE_Bounds* bounds)
+{
+ m_bounds.minx = bounds->min[0];
+ m_bounds.miny = bounds->min[1];
+ m_bounds.maxx = bounds->max[0];
+ m_bounds.maxy = bounds->max[1];
+}
+
+void SE_LineStorage::SetChopInfo(double startx, double endx, bool closeChops)
+{
+ m_do_chop = true;
+ m_chop_start = startx;
+ m_chop_end = endx;
+ m_close_chops = closeChops;
+}
+
+void SE_LineStorage::Reset()
+{
+ m_do_chop = false;
+ m_chopped = false;
+ m_crossed = false;
+ LineBuffer::Reset();
+}
+
+void SE_LineStorage::_MoveToNoChop(double x, double y)
+{
+ m_types[m_cur_types++] = (unsigned char)stMoveTo;
+ m_pts[m_cur_pts++] = x;
+ m_pts[m_cur_pts++] = y;
+
+ m_last_x = x;
+ m_last_y = y;
+
+ m_cntrs[++m_cur_cntr] = 1;
+}
+
+void SE_LineStorage::_LineToNoChop(double x, double y)
+{
+ m_types[m_cur_types++] = (unsigned char)stLineTo;
+ m_pts[m_cur_pts++] = x;
+ m_pts[m_cur_pts++] = y;
+
+ m_cntrs[m_cur_cntr]++;
+}
+
+#endif // SE_LINESTORAGE_H
Modified: trunk/MgDev/Common/Stylization/SE_MiterJoin.cpp
===================================================================
--- trunk/MgDev/Common/Stylization/SE_MiterJoin.cpp 2007-03-23 00:43:55 UTC (rev 1352)
+++ trunk/MgDev/Common/Stylization/SE_MiterJoin.cpp 2007-03-23 01:54:26 UTC (rev 1353)
@@ -16,230 +16,472 @@
//
#include "SE_MiterJoin.h"
+#include "SE_LineBuffer.h"
#include "stdafx.h"
-/* TODO: use vectors instead of sAng, eAng */
+
SE_MiterJoin::SE_MiterJoin
( double limit,
RS_Bounds& bounds,
double vertexOffset,
- double sAng,
- double eAng,
- double dx,
- double dy,
- double chopOffset )
+ const RS_F_Point& prev,
+ const RS_F_Point& vert,
+ const RS_F_Point& next,
+ bool noTransform ) :
+ m_sRot(),
+ m_eRot(),
+ m_j_bounds(),
+ m_xf_bounds(DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX)
{
- double V; /* The location of the vertex in symbol coordinates */
- double wn; /* The height of the symbol below the line (inside the join) */
- double wp; /* The height of the symbol above the line (outside the join) */
- double jn; /* The length of the join above the line */
- double jp; /* The length of the join below the line */
- double h; /* The half-angle between the segments */
- double t; /* The tangent of the half-angle */
- double c; /* The cosine of the half-angle */
- double s; /* The sine of the half-angle */
- double mmax; /* The length of the miter before the miter limit is applied */
- double mlen; /* The miter length (the miter limit times the outside line thickness) */
- double movr; /* The length of the portion of the miter that exceeds the miter length */
-
- m_sAng = sAng;
- m_eAng = eAng;
-
- wn = bounds.miny < 0.0 ? -bounds.miny : 0.0;
- wp = bounds.maxy > 0.0 ? bounds.maxy : 0.0;
+ double V; /* The location of the vertex in symbol coordinates */
+ double wp; /* The height of the positive portion of the symbol (above the centerline) */
+ double wn; /* The height of the negative portion of the symbol (below the centerline) */
+ double wb; /* The height of the beveled portion of the symbol */
+ double w; /* The height of the join above or below the line (symmetrical) */
+ double jo; /* The x distance from the vertex to the end of the outside join */
+ double ji; /* The x distance from the vertex to the end of the inside join */
+ double t; /* The tangent of the half-angle */
+ double ca; /* The cosine of the angle */
+ double ch; /* The cosine of the half-angle */
+ double sa; /* The sine of the angle */
+ double mmax; /* The length of the miter before the miter limit is applied */
+ double mmin; /* The minimum miter limit (at which a flat bevel is possible) */
+ double mlen; /* The miter length (the miter limit times the outside line thickness) */
+ double movr; /* The length of the portion of the miter that exceeds the miter length */
+ double imprev; /* The inverse magnitude of the (vert - prev) vector */
+ double imnext; /* The invserse magnitude of the (next - vert) vector */
+ RS_F_Point nprev; /* The normalized (vert - prev) vector */
+ RS_F_Point nnext; /* The normalized (next - vert) vector */
+ bool clockwise; /* If true, then the positive portion of the symbol is on the inside of the join */
+ bool rtl; /* If true, then the line moves negatively in x */
- /* If t is negative, then jn will become the miter length and jp will become the inside length */
- h = (eAng - sAng)/2.0;
- s = sin(h);
- c = cos(h);
- t = s/c; /* The calculations will be stable even if the tangent is INF or 0 (assuming a reasonable miter limit) */
V = bounds.minx - vertexOffset;
-
- /* Rotation should occur about the vertex */
- m_sRot.translateX(V);
- m_sRot.rotate(sAng);
- m_sRot.translate(dx - V, dy);
- m_eRot.translateX(V);
- m_eRot.rotate(eAng);
- m_eRot.translate(dx - V, dy);
+ clockwise = PointLeft(prev.x, prev.y, vert.x, vert.y, next.x, next.y);
+ rtl = next.x < prev.x;
+
+ nnext.x = next.x - vert.x;
+ nnext.y = next.y - vert.y;
+ imnext = 1.0/sqrt(nnext.x*nnext.x + nprev.y*nprev.y);
+ nnext.x *= imnext;
+ nnext.y *= imnext;
- /* the tangent of the half angle is equal to the upper height over the upper join width */
- jn = wn/t;
+ nprev.x = vert.x - prev.x;
+ nprev.y = vert.y - prev.y;
+ imprev = 1.0/sqrt(nprev.x*nprev.x + nprev.y*nprev.y);
+ nprev.x *= imprev;
+ nprev.y *= imprev;
- /* the tangent of the half angle is equal to the lower height over the lower join width */
- jp = wp/t;
-
- if (t < 0.0)
- { /* The positive portion of the symbol is inside the join */
- mmax = sqrt(wn*wn + jn*jn);
- mlen = wn*limit;
- if ((movr = mmax - mlen) > 0) /* the miter limit forces a bevel */
+ m_j_bounds.minx = vertexOffset; /* bounds.minx - V */
+ m_j_bounds.maxx = bounds.maxx - V;
+
+ if (noTransform)
+ {
+ m_eRot.translate(-vert.x, -vert.y);
+ m_eRot.rotate(-nprev.y, nprev.x); /* Undo leading segment rotation */
+
+ m_w2j.translate(-vert.x, -vert.y);
+ m_w2j.rotate(-nprev.y, nprev.x); /* rotate by -angle */
+ if (clockwise)
+ { /* Flip across the line so we don't have to worry about this stuff */
+ m_w2j.scaleY(-1.0);
+ m_j2w.scaleY(-1.0);
+ m_j_bounds.miny = -bounds.maxy;
+ m_j_bounds.maxy = -bounds.miny;
+ }
+ else
{
- /* the cosine of the half angle is equal to the chopped length / the truncation of j */
- jn -= movr/c;
- jn = (jn < 0) ? 0.0 : jn;
+ m_j_bounds.miny = bounds.miny;
+ m_j_bounds.maxy = bounds.maxy;
}
- m_y_max_len = jn;
- m_y_max = wn;
- m_y_min_len = jp;
- m_y_min = wp;
+ if (rtl)
+ {
+ m_w2j.scaleX(-1.0);
+ m_j2w.scaleX(-1.0);
+ }
+ m_j2w.rotate(nprev.y, nprev.x);
+ m_j2w.translate(vert.x, vert.y);
}
else
- { /* The negative portion of the symbol is inside the join */
- mmax = sqrt(wp*wp + jp*jp);
- mlen = wp*limit;
- if ((movr = mmax - mlen) > 0)
+ {
+ m_sRot.translateX(-V); /* translate by vert-(V,0), then by -vert */
+ m_sRot.rotate(nprev.y, nprev.x);
+ m_sRot.translate(vert.x, vert.y);
+ m_w2j.translateX(-V);
+ if (clockwise)
{
- jp -= movr/c;
- jp = (jp < 0) ? 0.0 : jp;
+ m_w2j.scaleY(-1.0);
+ m_j2w.scaleY(-1.0);
}
- m_y_max_len = jp;
- m_y_max = wp;
- m_y_min_len = jn;
- m_y_min = wn;
+ if (rtl)
+ {
+ m_w2j.scaleX(-1.0);
+ m_j2w.scaleX(-1.0);
+ }
+ m_w2j.translateX(V);
+ m_eRot.translateX(-V);
}
+
+ /* Rotation should occur about the vertex */
+ m_eRot.rotate(nnext.y, nnext.x);
+ m_eRot.translate(vert.x, vert.y);
- if (V + chopOffset < bounds.maxx)
- m_chop = V + chopOffset;
- else
- m_chop = DBL_MAX;
+ m_eRot.postmultiply(m_j2w);
+ m_sRot.postmultiply(m_j2w);
- /* The widest part of the transform is cosine of the half angle times the actual miter length.
- * If there is no bevel, m_y_mid will be equal to m_y_max.
- * Despite this mathemtical certainty, using an if ensures that m_y_mid == m_y_max in fp math */
+ wn = bounds.miny < 0.0 ? -bounds.miny : 0.0;
+ wp = bounds.maxy > 0.0 ? bounds.maxy : 0.0;
+ double hw = (wn > wp) ? wn : wp;
+ w = 2.0 * hw;
+
+ ca = -nprev.x*nnext.x - nprev.y*nnext.y; /* <-nprev, nnext> */
+ sa = fabs(-nprev.x*nnext.y + nprev.y*nnext.x); /* |-nprev X nnext| */
+ t = (1 - ca)/sa; /* From half angle identity: tan(x/2) = (1 - cos(x))/sin(x) */
+
+ /* the tangent of the half angle is equal to w/j */
+ jo = ji = hw/t;
+ mmax = sqrt(jo*jo + hw*hw);
+
+ /* Derivation of mmin:
+ * Let A be the area of the minimum bevel filled in between segments with no join
+ * Let theta be the angle between the two segments
+ *
+ * A = w*w*sin(pi - theta) from the sine formula for the area of a triangle
+ * A = w*w*sin(theta) from identity sin(pi - theta) = sin(theta)
+ *
+ * A/2 = w*mmin*sin(pi/2 - theta/2) from applying the same formula to one half of the (isoceles) triangle
+ * A/2 = w*mmin*cos(theta/2) from identity sin(pi/2 - theta) = cos(theta)
+ * A/2 = w*mmin*sqrt((1 + cos(theta))/2) from cos(theta/2) = +/- sqrt((1 + cos(theta)/2), and theta/2 < pi/2, so positive
+ * w*w*sin(theta)/2 = w*wmin*sqrt((1 + cos(theta))/2)
+ * w*sa/2 = wmin*sqrt((1+ca)/2)
+ * wmin = hw*sa/sqrt((1+ca)/2)
+ */
+ ch = sqrt((1 + ca) / 2.0);
+ mmin = sa / ch;
+ mlen = hw * (limit < mmin ? mmin : limit);
+ movr = mmax - mlen;
+
if (movr > 0)
{
- m_y_mid_len = (mmax < mlen ? mmax : mlen)*c;
- m_y_mid = m_y_mid_len*t;
+ /* Todo: limit cannot go to zero */
+ double reduction = movr/mmax;
+ jo *= 1.0 - reduction;
+ wb = hw * reduction;
+ m_bevel_width = mlen * ch;
+ m_bevel_scale = (m_bevel_width - jo) / wb;
}
else
{
- m_y_mid_len = m_y_max_len;
- m_y_mid = m_y_max;
+ wb = 0.0;
+ m_bevel_width = jo;
}
- m_x_vert = V;
-
+
+ m_height = hw;
+ m_width = ji;
+ m_top_width = jo;
+ m_bevel = hw - wb;
+ m_miter_scale = m_width * (m_bevel_width + m_width) / (m_bevel + m_height);
+
m_n_discontinuities = -1;
- m_n_identity_regions = -1;
- m_bounds = bounds;
-
- /* Factor used in miter calculations (see comments in Transform) */
- m_miter_scale = m_y_min_len*(m_y_mid_len + m_y_min_len)/(m_y_mid - m_y_min);
- m_bevel_scale = (m_y_max - m_y_mid)*(m_y_mid_len - m_y_max_len);
-
}
RS_F_Point* SE_MiterJoin::GetDiscontinuities(int &length)
{
if (m_n_discontinuities == -1) /* Lazily initialize */
{
- m_first_discontinuity = NULL;
- double minx = m_x_vert - m_y_min_len;
- double maxx = m_x_vert + m_y_min_len;
- if (m_bounds.minx < m_x_vert && m_y_mid != m_y_max)
+ m_n_discontinuities = 0;
+ int index = 0;
+
+ if (m_j_bounds.minx < -m_width)
{
- m_first_discontinuity = m_discontinuities;
m_n_discontinuities++;
- m_discontinuities[0].x = (minx > m_bounds.minx) ? minx : m_bounds.minx;
- m_discontinuities[0].y = m_y_mid;
- m_discontinuities[1].x = (m_bounds.maxx < m_x_vert) ? m_bounds.maxx : m_x_vert;
- m_discontinuities[1].y = m_y_mid;
+ m_discontinuities[index].x = -m_width;
+ m_discontinuities[index].y = -m_height;
+ m_j2w.transform(m_discontinuities[index].x, m_discontinuities[index].y);
+ index++;
+ m_discontinuities[index].x = -m_width;
+ m_discontinuities[index].y = m_height;
+ m_j2w.transform(m_discontinuities[index].x, m_discontinuities[index].y);
}
- if (m_bounds.minx < m_x_vert && m_bounds.maxx > m_x_vert)
+ if (m_bevel > 0.0 && m_j_bounds.maxy > m_bevel)
{
- if (m_first_discontinuity == NULL)
- m_first_discontinuity = m_discontinuities + 2;
m_n_discontinuities++;
- m_discontinuities[2].x = m_x_vert;
- m_discontinuities[2].y = m_y_max;
- m_discontinuities[3].x = m_x_vert;
- m_discontinuities[3].y = m_y_min;
+ m_discontinuities[index].x = -m_width;
+ m_discontinuities[index].y = m_bevel;
+ m_j2w.transform(m_discontinuities[index].x, m_discontinuities[index].y);
+ index++;
+ m_discontinuities[index].x = 0.0;
+ m_discontinuities[index].y = m_bevel;
+ m_j2w.transform(m_discontinuities[index].x, m_discontinuities[index].y);
+ index++;
+
+ m_n_discontinuities++;
+ m_discontinuities[index].x = 0.0;
+ m_discontinuities[index].y = m_bevel;
+ m_j2w.transform(m_discontinuities[index].x, m_discontinuities[index].y);
+ index++;
+ m_discontinuities[index].x = m_width;
+ m_discontinuities[index].y = m_bevel;
+ m_j2w.transform(m_discontinuities[index].x, m_discontinuities[index].y);
+ index++;
}
- if (m_bounds.maxx > m_x_vert && m_y_mid != m_y_max)
+ if (m_j_bounds.minx < 0 && m_j_bounds.maxx > 0)
{
- if (m_first_discontinuity == NULL)
- m_first_discontinuity = m_discontinuities + 4;
m_n_discontinuities++;
- m_discontinuities[4].x = (maxx < m_bounds.maxx) ? maxx : m_bounds.maxx;
- m_discontinuities[4].y = m_y_mid;
- m_discontinuities[5].x = (m_bounds.minx > m_x_vert) ? m_bounds.minx : m_x_vert;
- m_discontinuities[5].y = m_y_mid;
+ m_discontinuities[index].x = 0;
+ m_discontinuities[index].y = -m_height;
+ m_j2w.transform(m_discontinuities[index].x, m_discontinuities[index].y);
+ index++;
+ m_discontinuities[index].x = 0;
+ m_discontinuities[index].y = m_height;
+ m_j2w.transform(m_discontinuities[index].x, m_discontinuities[index].y);
}
+
+ if (m_j_bounds.maxx > m_width)
+ {
+ m_n_discontinuities++;
+ m_discontinuities[index].x = m_width;
+ m_discontinuities[index].y = -m_height;
+ m_j2w.transform(m_discontinuities[index].x, m_discontinuities[index].y);
+ index++;
+ m_discontinuities[index].x = m_width;
+ m_discontinuities[index].y = m_height;
+ m_j2w.transform(m_discontinuities[index].x, m_discontinuities[index].y);
+ }
}
length = m_n_discontinuities;
- return m_first_discontinuity;
+ return m_discontinuities;
}
-RS_Bounds* SE_MiterJoin::GetIdentityRegions(int &length)
+RS_Bounds& SE_MiterJoin::GetTransformedBounds()
{
- if (m_n_identity_regions == -1) /* Lazily initialize */
+ if (!m_xf_bounds.IsValid())
{
- m_first_identity_region = NULL;
- m_n_identity_regions = 0;
+ RS_F_Point xfpt;
- if (m_bounds.minx < m_x_vert - m_y_min_len)
- {
- m_first_identity_region = m_identity_region;
- m_n_identity_regions++;
- m_identity_region[0].minx = m_bounds.minx;
- m_identity_region[0].maxx = m_x_vert - m_y_min_len;
- m_identity_region[0].miny = m_bounds.miny;
- m_identity_region[0].maxy = m_bounds.maxy;
- }
+ xfpt.x = m_j_bounds.minx;
+ xfpt.y = m_j_bounds.miny;
+ _Transform(xfpt);
+ m_xf_bounds.add_point(xfpt);
- if (m_bounds.maxx > m_x_vert + m_y_min_len && m_chop > m_x_vert + m_y_min_len)
- {
- if (m_first_identity_region == NULL)
- m_first_identity_region = m_identity_region + 1;
- m_n_identity_regions++;
- m_identity_region[1].minx = m_x_vert + m_y_min_len;
- m_identity_region[1].maxx = m_bounds.maxx > m_chop ? m_chop : m_bounds.maxx;
- m_identity_region[1].miny = m_bounds.miny;
- m_identity_region[1].maxy = m_bounds.maxy;
- }
+ xfpt.x = m_j_bounds.maxx;
+ xfpt.y = m_j_bounds.maxy;
+ _Transform(xfpt);
+ m_xf_bounds.add_point(xfpt);
+
+ xfpt.x = 0.0;
+ xfpt.y = m_j_bounds.maxy;
+ _Transform(xfpt);
+ m_xf_bounds.add_point(xfpt);
+
+ xfpt.x = 0.0;
+ xfpt.y = m_j_bounds.miny;
+ _Transform(xfpt);
+ m_xf_bounds.add_point(xfpt);
+
+ xfpt.x = m_j_bounds.minx;
+ xfpt.y = m_j_bounds.maxy;
+ _Transform(xfpt);
+ m_xf_bounds.add_point(xfpt);
+
+ xfpt.x = m_j_bounds.maxx;
+ xfpt.y = m_j_bounds.miny;
+ _Transform(xfpt);
+ m_xf_bounds.add_point(xfpt);
}
- length = m_n_identity_regions;
- return m_first_identity_region;
+ return m_xf_bounds;
}
-RS_Bounds* SE_MiterJoin::GetNonlinearRegions(int &length)
+void SE_MiterJoin::GetXChop(double& startx, double& endx)
{
- length = 0;
- return NULL;
+ startx = -DBL_MAX;
+ endx = DBL_MAX;
}
-RS_Bounds& SE_MiterJoin::GetTransformedBounds()
+RS_F_Point* SE_MiterJoin::Transform(const RS_F_Point& pt0, const RS_F_Point& pt1, int& length)
{
- /* TODO: initialize, lazily */
- return m_xf_bounds;
+ RS_F_Point head, tail;
+
+ m_w2j.transform(pt0.x, pt0.y, head.x, head.y);
+ m_w2j.transform(pt1.x, pt1.y, tail.x, tail.y);
+
+ if (head.x > tail.x) /* Swap 'em--the head comes first! */
+ {
+ m_points[0] = tail;
+ tail = head;
+ head = m_points[0];
+ }
+
+ _Explode(head, tail, length);
+
+ for (int i = 0; i < length; i++)
+ _Transform(m_points[i]);
+ return m_points;
}
-double SE_MiterJoin::GetXChop(bool &chopEnd)
+void SE_MiterJoin::Transform(SE_LineStorage* src, SE_LineStorage* dst, bool /*closed*/)
{
- chopEnd = true;
- return m_chop;
+ int n_cntrs = src->cntr_count();
+ int* contours = src->cntrs();
+ double* pts = src->points();
+ RS_F_Point head, tail;
+ int length;
+
+ for (int i = 0; i < n_cntrs; i++)
+ {
+ double x, y, lx, ly;
+ double* last = pts + 2*contours[i];
+ dst->EnsureContours(1);
+ lx = *pts++;
+ ly = *pts++;
+ m_w2j.transform(lx, ly);
+ bool first = true;
+ bool noswap;
+
+ while (pts < last)
+ {
+ x = *pts++;
+ y = *pts++;
+ m_w2j.transform(x, y);
+
+ head.x = x;
+ head.y = y;
+ tail.x = lx;
+ tail.y = ly;
+
+ if (noswap = head.x > tail.x) /* Swap 'em--the head comes first! */
+ {
+ m_points[0] = tail;
+ tail = head;
+ head = m_points[0];
+ }
+
+ _Explode(head, tail, length);
+ dst->EnsurePoints(length);
+
+ int index, inc;
+ if (noswap)
+ {
+ index = 0;
+ inc = 1;
+ }
+ else
+ {
+ index = length - 1;
+ inc = -1;
+ }
+
+ if (first)
+ {
+ first = false;
+ _Transform(m_points[index]);
+ dst->_MoveToNoChop(m_points[index].x, m_points[index].y);
+ }
+
+ index += inc;
+
+ for (i = 1; i < length; i++)
+ {
+ RS_F_Point& pt = m_points[index];
+ index += inc;
+ _Transform(pt);
+ dst->_LineToNoChop(pt.x, pt.y);
+ }
+ lx = x;
+ ly = y;
+ }
+ }
}
-void SE_MiterJoin::Transform(double& x, double &y, SE_TransformInfo* info)
+void SE_MiterJoin::_Explode(const RS_F_Point& head, const RS_F_Point& tail, int& length)
{
- /* By using these, max will always be > min */
- bool start = x < m_x_vert;
- double x_min = start ? m_x_vert - m_y_min_len : m_x_vert + m_y_min_len;
- double dXdx, dXdy, d2Xdxdy;
+ RS_F_Point bevel, zero;
+ bool addBevel = false, addZero = false;
- if (x >= m_x_vert - m_y_min_len && x <= m_x_vert + m_y_min_len)
+ length = 0;
+ double slope = (tail.y - head.y) / (tail.x - head.x);
+
+ m_points[length++] = head;
+
+ if (head.x < -m_width && tail.x > -m_width) /* Line crosses the beginning of the transform */
{
- if (y > m_y_mid && y <= m_y_max)
+ m_points[length].x = -m_width;
+ m_points[length++].y = head.y - slope * (m_width + head.x);
+ }
+
+ if ( (head.y < m_bevel && tail.y > m_bevel) || (head.y > m_bevel && tail.y < m_bevel) )
+ {
+ bevel.x = head.x + (m_bevel - head.y) / slope;
+ bevel.y = m_bevel;
+ addBevel = true;
+ }
+
+ if (head.x < 0.0 && tail.x > 0.0)
+ {
+ zero.y = head.y - slope * head.x;
+ zero.x = 0.0;
+ /* If, by some chance, the line crosses the bevel at x=0, don't add the point twice */
+ addZero = !addBevel || zero.x != bevel.x || zero.y != bevel.y;
+ }
+
+ if (addBevel && addZero)
+ {
+ if (bevel.x < zero.x)
{
+ m_points[length++] = bevel;
+ m_points[length++] = zero;
+ }
+ else
+ {
+ m_points[length++] = zero;
+ m_points[length++] = bevel;
+ }
+ }
+ else if (addBevel)
+ m_points[length++] = bevel;
+ else if (addZero)
+ m_points[length++] = zero;
+
+ if (head.x < m_width && tail.x > m_width) /* Line crosses the end of the transform */
+ {
+ m_points[length].x = m_width;
+ m_points[length++].y = head.y + slope * (m_width - head.x);
+ }
+
+ m_points[length++] = tail;
+}
+
+/* Argument: point in join space
+ * Returns: point in input space
+ */
+void SE_MiterJoin::_Transform(RS_F_Point& pt)
+{
+ double x_min;
+ SE_Matrix* postxf;
+
+ if (pt.x <= 0)
+ {
+ x_min = -m_width;
+ postxf = &m_sRot;
+ }
+ else
+ {
+ x_min = m_width;
+ postxf = &m_eRot;
+ }
+
+ if (fabs(pt.x) <= m_width)
+ {
+ if (pt.y > m_bevel && pt.y <= m_height)
+ {
/* The bevel transform can be described by the following function:
- * X(x,y) = x_min + (x - x_min) * (y_max_len + (y_max - y) * (y_mid_len - y_max_len) / (y_max - y_mid)
+ * X(x,y) = x_min + (x - x_min) * (m_top_width + (m_height - y) * (m_bevel_width - m_top_width) / (m_height - m_bevel)
* |------------- m_bevel_scale -------------|
* where:
- * dX/dx = y_max_len + (y_max - y) * scale
+ * dX/dx = m_top_width + (m_height - y) * scale
* dX/dy = - (x - x_min) * scale
* d2X/dx2 = 0
* d2X/dy2 = 0
@@ -248,22 +490,19 @@
* The transform is constant over Y, so
* Y(x,y) = y
*/
- double dy = m_y_max - y;
- double dx = x - x_min;
+ double dy = m_height - pt.y;
+ double dx = pt.x - x_min;
- x = x_min + dx * (m_y_max_len + dy * m_bevel_scale);
- dXdx = m_y_max_len + dy * m_bevel_scale;
- dXdy = dx * m_bevel_scale;
- d2Xdxdy = -m_bevel_scale;
+ pt.x = x_min + dx * (m_top_width + dy * m_bevel_scale);
}
- else if (y <= m_y_mid && y >= m_y_min)
+ else if (pt.y <= m_bevel && pt.y >= -m_height)
{
/* The miter transform can be described by the following function:
- * X(x,y) = x_min + (x - x_min) * (y - y_min) * y_min_len * (y_mid_len + y_min_len) / (y_mid - y_min)
+ * X(x,y) = x_min + (x - x_min) * (y + m_height) * m_width * (m_bevel_width + m_width) / (m_bevel + m_height)
* |------------------- m_miter_scale -------------------|
* where:
- * dX/dx = (y - y_min) * scale
+ * dX/dx = (y + m_height) * scale
* dX/dy = (x - x_min) * scale
* d2X/dx2 = 0
* d2X/dy2 = 0
@@ -272,44 +511,12 @@
* The transform is constant over Y, so
* Y(x,y) = y
*/
- double dx = x - x_min;
- double dy = y - m_y_min;
+ double dx = pt.x - x_min;
+ double dy = pt.y + m_height;
- x = x_min + dx * dy * m_miter_scale;
- dXdx = dy * m_miter_scale;
- dXdy = dx * m_miter_scale;
- d2Xdxdy = m_miter_scale;
+ pt.x = x_min + dx * dy * m_miter_scale;
}
- else
- {
- dXdx = 1.0;
- dXdy = 0.0;
- d2Xdxdy = 0.0;
- }
}
- else
- {
- dXdx = 1.0;
- dXdy = 0.0;
- d2Xdxdy = 0.0;
- }
- if (info)
- {
- info->dXdx = dXdx;
- info->dXdy = dXdy;
- info->dYdx = 0.0;
- info->dYdy = 1.0;
- info->d2Xdx2 = 0.0;
- info->d2Ydx2 = 0.0;
- info->d2Xdy2 = 0.0;
- info->d2Ydy2 = 0.0;
- info->d2Xdxdy = d2Xdxdy;
- info->d2Ydxdy = 0.0;
- }
-
- if (start)
- m_sRot.transform(x,y);
- else
- m_eRot.transform(x, y);
+ postxf->transform(pt.x, pt.y);
}
Modified: trunk/MgDev/Common/Stylization/SE_MiterJoin.h
===================================================================
--- trunk/MgDev/Common/Stylization/SE_MiterJoin.h 2007-03-23 00:43:55 UTC (rev 1352)
+++ trunk/MgDev/Common/Stylization/SE_MiterJoin.h 2007-03-23 01:54:26 UTC (rev 1353)
@@ -25,57 +25,53 @@
class SE_MiterJoin : public SE_PiecewiseTransform
{
public:
- SE_MiterJoin(double limit, /* The miter limit of the join. */
- RS_Bounds& bounds, /* The bounds of the unoriented symbol in pixel units. */
+ SE_MiterJoin(double limit, /* The miter limit of the join */
+ RS_Bounds& bounds, /* The bounds of the unoriented symbol in pixel units */
double vertexOffset, /* The distance along the line (in pixels) from the
beginning of the symbol to the vertex of the join
(the value will be negative if the symbol starts before
- the join, and positive if it starts after the join). */
- double sAng, /* The angle of the first line segment. */
- double eAng, /* The angle of the second line segment. */
- double dx, /* The x offset of the origin of the symbol */
- double dy, /* The y offset of the origin of the symbol */
- double chopOffset = DBL_MAX); /* The distance after the vertex at which to truncate the symbol */
+ the join, and positive if it starts after the join) */
+ const RS_F_Point& prev, /* The point preceeding the vertex of the join in screen space */
+ const RS_F_Point& vert, /* The vertex of the join in screen space */
+ const RS_F_Point& next, /* The point following the vertex of the join in screen space */
+ bool noTransform = true); /* True if the symbol is already oriented appropriately along the leading segment */
virtual RS_F_Point* GetDiscontinuities(int &length);
- virtual RS_Bounds* GetIdentityRegions(int &length);
- virtual RS_Bounds* GetNonlinearRegions(int &length);
virtual RS_Bounds& GetTransformedBounds();
- virtual double GetXChop(bool &chopEnd);
+ virtual void GetXChop(double& startx, double& endx);
- /* Transform will apply the join transform, as well as the appropriate rotation */
- virtual void Transform(double& x, double& y, SE_TransformInfo* info);
+ /* Transform will apply the join transform, as well as the appropriate orientation in screen space */
+ virtual RS_F_Point* Transform(const RS_F_Point& pt0, const RS_F_Point& pt1, int& length);
+ virtual void Transform(SE_LineStorage* src, SE_LineStorage* dst, bool closed);
private:
- double m_y_max;
- double m_y_max_len;
- double m_y_mid;
- double m_y_mid_len;
- double m_y_min;
- double m_y_min_len;
+ void _Transform(RS_F_Point& pt);
+ void _Explode(const RS_F_Point& head, const RS_F_Point& tail, int& length);
- double m_x_vert;
- double m_miter_scale;
+ double m_height; /* Height on each side from the center (ignoring bevel) in join space */
+ double m_bevel; /* Height of the bevel in join space */
+ double m_width; /* Distance from the center on each side that is transformed in join space*/
+ double m_bevel_width; /* Maximum transformed size of m_width */
+ double m_top_width; /* Transformed size of m_width at m_height */
+
double m_bevel_scale;
- double m_sAng;
- double m_eAng;
+ double m_miter_scale;
+
+ SE_Matrix m_w2j; /* World space to join space transform */
+ SE_Matrix m_j2w; /* Join space to world space transform */
+
+ RS_F_Point m_points[6];
int m_n_discontinuities;
- RS_F_Point* m_first_discontinuity;
- RS_F_Point m_discontinuities[6];
+ RS_F_Point m_discontinuities[10];
- int m_n_identity_regions;
- RS_Bounds* m_first_identity_region;
- RS_Bounds m_identity_region[2];
-
RS_Bounds m_bounds;
+ RS_Bounds m_j_bounds;
RS_Bounds m_xf_bounds;
SE_Matrix m_sRot;
SE_Matrix m_eRot;
-
- double m_chop;
};
#endif // SE_MITERJOIN_H
Modified: trunk/MgDev/Common/Stylization/SE_PiecewiseTransform.h
===================================================================
--- trunk/MgDev/Common/Stylization/SE_PiecewiseTransform.h 2007-03-23 00:43:55 UTC (rev 1352)
+++ trunk/MgDev/Common/Stylization/SE_PiecewiseTransform.h 2007-03-23 01:54:26 UTC (rev 1353)
@@ -20,19 +20,8 @@
#include "Bounds.h"
-struct SE_TransformInfo
-{
- double dXdx;
- double dYdx;
- double dXdy;
- double dYdy;
- double d2Xdx2;
- double d2Ydx2;
- double d2Xdy2;
- double d2Ydy2;
- double d2Xdxdy;
- double d2Ydxdy;
-};
+class SE_LineStorage;
+class SE_LineBufferStorage;
class SE_PiecewiseTransform
@@ -41,17 +30,16 @@
/* Returned in the format pt00, pt01, pt10, pt11 etc. where each pair of points represents
* the endpoints of a line along which the the transform is not smooth */
virtual RS_F_Point* GetDiscontinuities(int &length) = 0;
- /* Regions that are not transformed (other than rotation) */
- virtual RS_Bounds* GetIdentityRegions(int &length) = 0;
- /* Regions where simple linear of transformed points is insufficient */
- virtual RS_Bounds* GetNonlinearRegions(int &length) = 0;
+ /* Transformed bounds take chop into account */
virtual RS_Bounds& GetTransformedBounds() = 0;
- /* Applying the chop is left to the caller */
- virtual double GetXChop(bool &chopEnd) = 0;
+ /* Applying the chop is left to the caller. Chop the symbol before startx and after endx. */
+ virtual void GetXChop(double& startx, double& endx) = 0;
- /* The transform function is not aware of the chop value */
- virtual void Transform(double& x, double& y, SE_TransformInfo* info) = 0;
+ /* This transform function is not aware of the chop value */
+ virtual RS_F_Point* Transform(const RS_F_Point& pt0, const RS_F_Point& pt1, int& length) = 0;
+ /* This transform function handles the chop as well */
+ virtual void Transform(SE_LineStorage* src, SE_LineStorage* dst, bool closed) = 0;
};
#endif // SE_PIECEWISETRANSFORM_H
Modified: trunk/MgDev/Common/Stylization/Stylization.vcproj
===================================================================
--- trunk/MgDev/Common/Stylization/Stylization.vcproj 2007-03-23 00:43:55 UTC (rev 1352)
+++ trunk/MgDev/Common/Stylization/Stylization.vcproj 2007-03-23 01:54:26 UTC (rev 1353)
@@ -677,6 +677,14 @@
>
</File>
<File
+ RelativePath=".\SE_IdentityJoin.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SE_IdentityJoin.h"
+ >
+ </File>
+ <File
RelativePath=".\SE_LineBuffer.cpp"
>
</File>
@@ -685,10 +693,30 @@
>
</File>
<File
+ RelativePath=".\SE_LineStorage.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SE_LineStorage.h"
+ >
+ </File>
+ <File
RelativePath=".\SE_Matrix.h"
>
</File>
<File
+ RelativePath=".\SE_MiterJoin.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SE_MiterJoin.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SE_PiecewiseTransform.h"
+ >
+ </File>
+ <File
RelativePath=".\SE_PositioningAlgorithms.cpp"
>
</File>
More information about the mapguide-commits
mailing list