From 971ef4214070c37a0a09d7bc9e194fd94279e5c3 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 17 Jun 2012 00:24:54 -0700 Subject: Removed unneeded header style filename #defines (bzr r11503) --- src/helper/geom.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/helper/geom.cpp') diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp index 585d2b8a5..3e63df1ac 100644 --- a/src/helper/geom.cpp +++ b/src/helper/geom.cpp @@ -1,5 +1,3 @@ -#define INKSCAPE_HELPER_GEOM_CPP - /* * Specific geometry functions for Inkscape, not provided my lib2geom. * -- cgit v1.2.3 From e298aeb969151e2a523d3aaef737ac04b6e5b0e8 Mon Sep 17 00:00:00 2001 From: David Mathog <> Date: Fri, 8 Mar 2013 09:27:50 +0100 Subject: changes_2013_02_25a.patch New: WMF import/export implements WMF (Windows Metafile) read and write. Inkscape previously supported that through uniconverter, which was not very good with WMF files. The new version now has a complete wmf-print/wmf-inout implementation, analogous to the previous emf-print/emf-inout. This handles images, patterns, and various other goodies to the extent that WMF does. WMF is a bit primitive, many fields are only 16 bits, so it even more resolution sapping issues than does EMF. Given the choice, always use the latter format. (bzr r11668.1.52) --- src/helper/geom.cpp | 310 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) (limited to 'src/helper/geom.cpp') diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp index 3e63df1ac..a0a440308 100644 --- a/src/helper/geom.cpp +++ b/src/helper/geom.cpp @@ -21,6 +21,7 @@ #include <2geom/coord.h> #include <2geom/sbasis-to-bezier.h> #include +#include // for M_PI using Geom::X; using Geom::Y; @@ -491,6 +492,315 @@ pathv_to_linear_and_cubic_beziers( Geom::PathVector const &pathv ) return output; } +/* + * Converts all segments in all paths to Geom::LineSegment. There is an intermediate + * stage where some may be converted to beziers. maxdisp is the maximum displacement from + * the line segment to the bezier curve. + * + * This is NOT a terribly fast method, but it should give a solution close to the one with the + * fewest points. + */ +Geom::PathVector +pathv_to_linear( Geom::PathVector const &pathv, double maxdisp) +{ + Geom::PathVector output; + Geom::PathVector tmppath = pathv_to_linear_and_cubic_beziers(pathv); + + // Now all path segments are either already lines, or they are beziers. + + for (Geom::PathVector::const_iterator pit = tmppath.begin(); pit != tmppath.end(); ++pit) { + output.push_back( Geom::Path() ); + output.back().start( pit->initialPoint() ); + output.back().close( pit->closed() ); + + for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit) { + if (is_straight_curve(*cit)) { + Geom::LineSegment ls(cit->initialPoint(), cit->finalPoint()); + output.back().append(ls); + } + else { /* all others must be Bezier curves */ + Geom::BezierCurve const *curve = dynamic_cast(&*cit); + Geom::CubicBezier b((*curve)[0], (*curve)[1], (*curve)[2], (*curve)[3]); + std::vector bzrpoints = b.points(); + Geom::Point A = bzrpoints[0]; + Geom::Point B = bzrpoints[1]; + Geom::Point C = bzrpoints[2]; + Geom::Point D = bzrpoints[3]; + std::vector pointlist; + pointlist.push_back(A); + recursive_bezier4( + A[X], A[Y], + B[X], B[Y], + C[X], C[Y], + D[X], D[Y], + pointlist, + 0); + pointlist.push_back(D); + Geom::Point r0; + Geom::Point r1 = pointlist[0]; + for (unsigned int i=1; i &m_points, + int level) + { + // some of these should be parameters, but do it this way for now. + const double curve_collinearity_epsilon = 1e-30; + const double curve_angle_tolerance_epsilon = 0.01; + double m_cusp_limit = 0.0; + double m_angle_tolerance = 0.0; + double m_approximation_scale = 1.0; + double m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; + enum curve_recursion_limit_e { curve_recursion_limit = 32 }; +#define calc_sq_distance(A,B,C,D) ((A-C)*(A-C) + (B-D)*(B-D)) + + if(level > curve_recursion_limit) + { + return; + } + + + // Calculate all the mid-points of the line segments + //---------------------- + double x12 = (x1 + x2) / 2; + double y12 = (y1 + y2) / 2; + double x23 = (x2 + x3) / 2; + double y23 = (y2 + y3) / 2; + double x34 = (x3 + x4) / 2; + double y34 = (y3 + y4) / 2; + double x123 = (x12 + x23) / 2; + double y123 = (y12 + y23) / 2; + double x234 = (x23 + x34) / 2; + double y234 = (y23 + y34) / 2; + double x1234 = (x123 + x234) / 2; + double y1234 = (y123 + y234) / 2; + + + // Try to approximate the full cubic curve by a single straight line + //------------------ + double dx = x4-x1; + double dy = y4-y1; + + double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx)); + double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx)); + double da1, da2, k; + + switch((int(d2 > curve_collinearity_epsilon) << 1) + + int(d3 > curve_collinearity_epsilon)) + { + case 0: + // All collinear OR p1==p4 + //---------------------- + k = dx*dx + dy*dy; + if(k == 0) + { + d2 = calc_sq_distance(x1, y1, x2, y2); + d3 = calc_sq_distance(x4, y4, x3, y3); + } + else + { + k = 1 / k; + da1 = x2 - x1; + da2 = y2 - y1; + d2 = k * (da1*dx + da2*dy); + da1 = x3 - x1; + da2 = y3 - y1; + d3 = k * (da1*dx + da2*dy); + if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1) + { + // Simple collinear case, 1---2---3---4 + // We can leave just two endpoints + return; + } + if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1); + else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4); + else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy); + + if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1); + else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4); + else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy); + } + if(d2 > d3) + { + if(d2 < m_distance_tolerance_square) + { + m_points.push_back(Geom::Point(x2, y2)); + return; + } + } + else + { + if(d3 < m_distance_tolerance_square) + { + m_points.push_back(Geom::Point(x3, y3)); + return; + } + } + break; + + case 1: + // p1,p2,p4 are collinear, p3 is significant + //---------------------- + if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.push_back(Geom::Point(x23, y23)); + return; + } + + // Angle Condition + //---------------------- + da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2)); + if(da1 >= M_PI) da1 = 2*M_PI - da1; + + if(da1 < m_angle_tolerance) + { + m_points.push_back(Geom::Point(x2, y2)); + m_points.push_back(Geom::Point(x3, y3)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.push_back(Geom::Point(x3, y3)); + return; + } + } + } + break; + + case 2: + // p1,p3,p4 are collinear, p2 is significant + //---------------------- + if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.push_back(Geom::Point(x23, y23)); + return; + } + + // Angle Condition + //---------------------- + da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); + if(da1 >= M_PI) da1 = 2*M_PI - da1; + + if(da1 < m_angle_tolerance) + { + m_points.push_back(Geom::Point(x2, y2)); + m_points.push_back(Geom::Point(x3, y3)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.push_back(Geom::Point(x2, y2)); + return; + } + } + } + break; + + case 3: + // Regular case + //----------------- + if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.push_back(Geom::Point(x23, y23)); + return; + } + + // Angle & Cusp Condition + //---------------------- + k = atan2(y3 - y2, x3 - x2); + da1 = fabs(k - atan2(y2 - y1, x2 - x1)); + da2 = fabs(atan2(y4 - y3, x4 - x3) - k); + if(da1 >= M_PI) da1 = 2*M_PI - da1; + if(da2 >= M_PI) da2 = 2*M_PI - da2; + + if(da1 + da2 < m_angle_tolerance) + { + // Finally we can stop the recursion + //---------------------- + m_points.push_back(Geom::Point(x23, y23)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.push_back(Geom::Point(x2, y2)); + return; + } + + if(da2 > m_cusp_limit) + { + m_points.push_back(Geom::Point(x3, y3)); + return; + } + } + } + break; + } + + // Continue subdivision + //---------------------- + recursive_bezier4(x1, y1, x12, y12, x123, y123, x1234, y1234, m_points, level + 1); + recursive_bezier4(x1234, y1234, x234, y234, x34, y34, x4, y4, m_points, level + 1); +} + /** * rounds all corners of the rectangle 'outwards', i.e. x0 and y0 are floored, x1 and y1 are ceiled. -- cgit v1.2.3 From d6b24c1540e9a7f388dd1500c762f73586119280 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 26 Mar 2013 23:46:08 +0000 Subject: Stop using top-level glibmm header (bzr r12251) --- src/helper/geom.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/helper/geom.cpp') diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp index 3e63df1ac..077344380 100644 --- a/src/helper/geom.cpp +++ b/src/helper/geom.cpp @@ -9,6 +9,7 @@ * Released under GNU GPL */ +#include #include "helper/geom.h" #include "helper/geom-curves.h" #include @@ -20,7 +21,6 @@ #include <2geom/rect.h> #include <2geom/coord.h> #include <2geom/sbasis-to-bezier.h> -#include using Geom::X; using Geom::Y; @@ -275,18 +275,18 @@ geom_cubic_bbox_wind_distance (Geom::Coord x000, Geom::Coord y000, if (bbox) cubic_bbox (x000, y000, x001, y001, x011, y011, x111, y111, *bbox); - x0 = MIN (x000, x001); - x0 = MIN (x0, x011); - x0 = MIN (x0, x111); - y0 = MIN (y000, y001); - y0 = MIN (y0, y011); - y0 = MIN (y0, y111); - x1 = MAX (x000, x001); - x1 = MAX (x1, x011); - x1 = MAX (x1, x111); - y1 = MAX (y000, y001); - y1 = MAX (y1, y011); - y1 = MAX (y1, y111); + x0 = std::min (x000, x001); + x0 = std::min (x0, x011); + x0 = std::min (x0, x111); + y0 = std::min (y000, y001); + y0 = std::min (y0, y011); + y0 = std::min (y0, y111); + x1 = std::min (x000, x001); + x1 = std::min (x1, x011); + x1 = std::min (x1, x111); + y1 = std::min (y000, y001); + y1 = std::min (y1, y011); + y1 = std::min (y1, y111); if (best) { /* Quickly adjust to endpoints */ -- cgit v1.2.3 From dc325db99e4e1b17293fac9ecb6de9da00bd30da Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Thu, 4 Apr 2013 08:55:13 +0200 Subject: Fix for Bug #1163759 (Mouse selection ignores transform). (bzr r12265) --- src/helper/geom.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/helper/geom.cpp') diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp index 077344380..879026521 100644 --- a/src/helper/geom.cpp +++ b/src/helper/geom.cpp @@ -281,12 +281,12 @@ geom_cubic_bbox_wind_distance (Geom::Coord x000, Geom::Coord y000, y0 = std::min (y000, y001); y0 = std::min (y0, y011); y0 = std::min (y0, y111); - x1 = std::min (x000, x001); - x1 = std::min (x1, x011); - x1 = std::min (x1, x111); - y1 = std::min (y000, y001); - y1 = std::min (y1, y011); - y1 = std::min (y1, y111); + x1 = std::max (x000, x001); + x1 = std::max (x1, x011); + x1 = std::max (x1, x111); + y1 = std::max (y000, y001); + y1 = std::max (y1, y011); + y1 = std::max (y1, y111); if (best) { /* Quickly adjust to endpoints */ -- cgit v1.2.3 From 0adad6cc5da5e601747f3311485532a342d4a164 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Wed, 8 Jan 2014 22:04:22 +0100 Subject: fix warning, update comments (bzr r12896) --- src/helper/geom.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/helper/geom.cpp') diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp index df0e4fcf2..c9148a634 100644 --- a/src/helper/geom.cpp +++ b/src/helper/geom.cpp @@ -495,13 +495,13 @@ pathv_to_linear_and_cubic_beziers( Geom::PathVector const &pathv ) /* * Converts all segments in all paths to Geom::LineSegment. There is an intermediate * stage where some may be converted to beziers. maxdisp is the maximum displacement from - * the line segment to the bezier curve. + * the line segment to the bezier curve; ** maxdisp is not used at this moment **. * * This is NOT a terribly fast method, but it should give a solution close to the one with the * fewest points. */ Geom::PathVector -pathv_to_linear( Geom::PathVector const &pathv, double maxdisp) +pathv_to_linear( Geom::PathVector const &pathv, double /*maxdisp*/) { Geom::PathVector output; Geom::PathVector tmppath = pathv_to_linear_and_cubic_beziers(pathv); @@ -536,12 +536,11 @@ pathv_to_linear( Geom::PathVector const &pathv, double maxdisp) pointlist, 0); pointlist.push_back(D); - Geom::Point r0; Geom::Point r1 = pointlist[0]; for (unsigned int i=1; i