From 9b64e857339762adc446d0856c88cb3d8a0efdc2 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Wed, 18 Nov 2015 22:07:04 +0100 Subject: [PATCH] [DEV] change list point generation methode ==> separate files --- esvg/Path.cpp | 274 ++---------------------------------------- esvg/render/Path.cpp | 213 ++++++++++++++++++++++++++++++++ esvg/render/Path.h | 2 + esvg/render/Point.cpp | 0 esvg/render/Point.h | 63 ++++++++++ lutin_esvg.py | 5 +- 6 files changed, 294 insertions(+), 263 deletions(-) create mode 100644 esvg/render/Point.cpp create mode 100644 esvg/render/Point.h diff --git a/esvg/Path.cpp b/esvg/Path.cpp index e0b5a0d..47927ef 100644 --- a/esvg/Path.cpp +++ b/esvg/Path.cpp @@ -377,106 +377,8 @@ bool sortXPosFunction(const std::pair& _e1, const std::pair& listPoints) { - SVG_VERBOSE(" Display list of points : size=" << listPoints.size()); - for (int32_t iii=0; - iii < listPoints.size(); - ++iii) { - switch (listPoints[iii].m_type) { - case PointRender::typePoint_single: - SVG_VERBOSE(" [" << iii << "] Find Single " << listPoints[iii].m_pos); - break; - case PointRender::typePoint_start: - SVG_VERBOSE(" [" << iii << "] Find Start " << listPoints[iii].m_pos); - break; - case PointRender::typePoint_stop: - SVG_VERBOSE(" [" << iii << "] Find Stop " << listPoints[iii].m_pos); - break; - case PointRender::typePoint_interpolation: - SVG_VERBOSE(" [" << iii << "] Find interpolation " << listPoints[iii].m_pos); - break; - case PointRender::typePoint_join: - SVG_VERBOSE(" [" << iii << "] Find Join " << listPoints[iii].m_pos); - break; - } - } -} - -void interpolateCubicBezier(std::vector& _listPoint, - int32_t _recurtionMax, - float _threshold, - vec2 _pos1, - vec2 _pos2, - vec2 _pos3, - vec2 _pos4, - int32_t _level, - enum PointRender::typePoint _type) { - if (_level > _recurtionMax) { - return; - } - vec2 pos12 = (_pos1+_pos2)*0.5f; - vec2 pos23 = (_pos2+_pos3)*0.5f; - vec2 pos34 = (_pos3+_pos4)*0.5f; - - vec2 delta = _pos4 - _pos1; - float distance2 = std::abs(((_pos2.x() - _pos4.x()) * delta.y() - (_pos2.y() - _pos4.y()) * delta.x() )); - float distance3 = std::abs(((_pos3.x() - _pos4.x()) * delta.y() - (_pos3.y() - _pos4.y()) * delta.x() )); - - if ((distance2 + distance3)*(distance2 + distance3) < _threshold * delta.length2()) { - _listPoint.push_back(PointRender(_pos4, _type) ); - return; - } - vec2 pos123 = (pos12+pos23)*0.5f; - vec2 pos234 = (pos23+pos34)*0.5f; - vec2 pos1234 = (pos123+pos234)*0.5f; - - interpolateCubicBezier(_listPoint, _recurtionMax, _threshold, _pos1, pos12, pos123, pos1234, _level+1, PointRender::typePoint_interpolation); - interpolateCubicBezier(_listPoint, _recurtionMax, _threshold, pos1234, pos234, pos34, _pos4, _level+1, _type); -} - -void addSegment(std::vector& _seg, const PointRender& _pos0, const PointRender& _pos1) { +void addSegment(std::vector& _seg, const esvg::render::Point& _pos0, const esvg::render::Point& _pos1) { // Skip horizontal Segments if (_pos0.m_pos.y() == _pos1.m_pos.y()) { // remove /0 operation @@ -485,7 +387,7 @@ void addSegment(std::vector& _seg, const PointRender& _pos0, const Poin _seg.push_back(Segment(_pos0.m_pos, _pos1.m_pos)); } -std::vector createSegmentList(const std::vector& _listPoint) { +std::vector createSegmentList(const std::vector& _listPoint) { std::vector out; // Build Segments for (int32_t iii=0, jjj=_listPoint.size()-1; @@ -498,7 +400,7 @@ std::vector createSegmentList(const std::vector& _listPoin return out; } -std::vector createSegmentListStroke(std::vector& _listPoint) { +std::vector createSegmentListStroke(std::vector& _listPoint) { std::vector out; // generate for every point all the orthogonal elements @@ -518,8 +420,8 @@ std::vector createSegmentListStroke(std::vector& _listPoin for (int32_t idPevious=-1, idCurrent=0, idNext=1; idCurrent < _listPoint.size(); idPevious++, idCurrent++, idNext++) { - if ( _listPoint[idCurrent].m_type == PointRender::typePoint_join - || _listPoint[idCurrent].m_type == PointRender::typePoint_interpolation) { + if ( _listPoint[idCurrent].m_type == esvg::render::Point::type_join + || _listPoint[idCurrent].m_type == esvg::render::Point::type_interpolation) { if (idPevious < 0 ) { SVG_ERROR("an error occure a previous ID is < 0.... "); continue; @@ -540,11 +442,11 @@ std::vector createSegmentListStroke(std::vector& _listPoin vecC.safeNormalize(); _listPoint[idCurrent].m_miterAxe = vecC; } - } else if (_listPoint[idCurrent].m_type == PointRender::typePoint_start) { + } else if (_listPoint[idCurrent].m_type == esvg::render::Point::type_start) { vec2 vecB = _listPoint[idNext].m_pos - _listPoint[idCurrent].m_pos; vecB.safeNormalize(); _listPoint[idCurrent].m_miterAxe = vec2(vecB.y(), vecB.x()); - } else if (_listPoint[idCurrent].m_type == PointRender::typePoint_stop) { + } else if (_listPoint[idCurrent].m_type == esvg::render::Point::type_stop) { if (idPevious < 0 ) { SVG_ERROR("an error occure a previous ID is < 0.... "); continue; @@ -565,11 +467,11 @@ std::vector createSegmentListStroke(std::vector& _listPoin iii < _listPoint.size(); ++iii) { switch (_listPoint[iii].m_type) { - case PointRender::typePoint_single: + case esvg::render::Point::type_single: // just do nothing .... SVG_VERBOSE("[" << iii << "] Find Single " << _listPoint[iii].m_pos); break; - case PointRender::typePoint_start: + case esvg::render::Point::type_start: { SVG_VERBOSE("[" << iii << "] Find Start " << _listPoint[iii].m_pos); if (haveStartLine == true) { @@ -587,7 +489,7 @@ std::vector createSegmentListStroke(std::vector& _listPoin SVG_VERBOSE(" segment :" << leftPoint << " -> " << rightPoint); } break; - case PointRender::typePoint_stop: + case esvg::render::Point::type_stop: { SVG_VERBOSE("[" << iii << "] Find Stop " << _listPoint[iii].m_pos); if (haveStartLine == true) { @@ -612,7 +514,7 @@ std::vector createSegmentListStroke(std::vector& _listPoin SVG_VERBOSE(" segment :" << rightPoint << " -> " << leftPoint); } break; - case PointRender::typePoint_interpolation: + case esvg::render::Point::type_interpolation: { SVG_VERBOSE("[" << iii << "] Find interpolation " << _listPoint[iii].m_pos); // TODO : Calculate intersection ... (now we do a simple fast test of path display ...) @@ -629,7 +531,7 @@ std::vector createSegmentListStroke(std::vector& _listPoin rightPoint = right; } break; - case PointRender::typePoint_join: + case esvg::render::Point::type_join: { SVG_VERBOSE("[" << iii << "] Find Join " << _listPoint[iii].m_pos); // TODO : Calculate intersection ... (now we do a simple fast test of path display ...) @@ -740,159 +642,9 @@ Weighter createWeighter(ivec2 _size, int32_t _subSamplingCount, const std::vecto void esvg::Path::draw(esvg::Renderer& _myRenderer, mat2& _basicTrans, int32_t _level) { SVG_VERBOSE(spacingDist(_level) << "DRAW esvg::Path"); - vec2 lastPosition(0.0f, 0.0f); - std::vector listPoints; - int32_t lastPointId = -1; - bool PathStart = false; int32_t recurtionMax = 10; float threshold = 0.25f; - // Foreach element, we move in the path: - for(int32_t iii=0; iii listPoints = m_listElement.generateListPoints(_level, recurtionMax, threshold); mat2 mtx = m_transformMatrix; mtx *= _basicTrans; diff --git a/esvg/render/Path.cpp b/esvg/render/Path.cpp index 7ebc1dd..d7f377c 100644 --- a/esvg/render/Path.cpp +++ b/esvg/render/Path.cpp @@ -103,3 +103,216 @@ void esvg::render::Path::display(int32_t _spacing) { } } + +void interpolateCubicBezier(std::vector& _listPoint, + int32_t _recurtionMax, + float _threshold, + vec2 _pos1, + vec2 _pos2, + vec2 _pos3, + vec2 _pos4, + int32_t _level, + enum esvg::render::Point::type _type) { + if (_level > _recurtionMax) { + return; + } + vec2 pos12 = (_pos1+_pos2)*0.5f; + vec2 pos23 = (_pos2+_pos3)*0.5f; + vec2 pos34 = (_pos3+_pos4)*0.5f; + + vec2 delta = _pos4 - _pos1; + float distance2 = std::abs(((_pos2.x() - _pos4.x()) * delta.y() - (_pos2.y() - _pos4.y()) * delta.x() )); + float distance3 = std::abs(((_pos3.x() - _pos4.x()) * delta.y() - (_pos3.y() - _pos4.y()) * delta.x() )); + + if ((distance2 + distance3)*(distance2 + distance3) < _threshold * delta.length2()) { + _listPoint.push_back(esvg::render::Point(_pos4, _type) ); + return; + } + vec2 pos123 = (pos12+pos23)*0.5f; + vec2 pos234 = (pos23+pos34)*0.5f; + vec2 pos1234 = (pos123+pos234)*0.5f; + + interpolateCubicBezier(_listPoint, _recurtionMax, _threshold, _pos1, pos12, pos123, pos1234, _level+1, esvg::render::Point::type_interpolation); + interpolateCubicBezier(_listPoint, _recurtionMax, _threshold, pos1234, pos234, pos34, _pos4, _level+1, _type); +} + +void diplayRenderPoints(const std::vector& listPoints) { + SVG_VERBOSE(" Display list of points : size=" << listPoints.size()); + for (int32_t iii=0; + iii < listPoints.size(); + ++iii) { + switch (listPoints[iii].m_type) { + case esvg::render::Point::type_single: + SVG_VERBOSE(" [" << iii << "] Find Single " << listPoints[iii].m_pos); + break; + case esvg::render::Point::type_start: + SVG_VERBOSE(" [" << iii << "] Find Start " << listPoints[iii].m_pos); + break; + case esvg::render::Point::type_stop: + SVG_VERBOSE(" [" << iii << "] Find Stop " << listPoints[iii].m_pos); + break; + case esvg::render::Point::type_interpolation: + SVG_VERBOSE(" [" << iii << "] Find interpolation " << listPoints[iii].m_pos); + break; + case esvg::render::Point::type_join: + SVG_VERBOSE(" [" << iii << "] Find Join " << listPoints[iii].m_pos); + break; + } + } +} + +std::vector esvg::render::Path::generateListPoints(int32_t _level, int32_t _recurtionMax, float _threshold) { + SVG_VERBOSE(spacingDist(_level) << "Generate List Points ... from a path"); + std::vector out; + vec2 lastPosition(0.0f, 0.0f); + int32_t lastPointId = -1; + bool PathStart = false; + // Foreach element, we move in the path: + for(auto &it : m_listElement) { + switch (it.getType()) { + case esvg::render::path_stop: + SVG_VERBOSE(spacingDist(_level+1) << " Draw : esvg::render::path_stop"); + // TODO : Check if the z value mean that the path will cycle ... + if (out.size() != 0) { + if (PathStart == false) { + SVG_WARNING(spacingDist(_level+1) << " Request path stop of not starting path ..."); + } else { + out.back().setEndPath(); + PathStart = false; + } + } + // nothing alse to do ... + break; + case esvg::render::path_moveTo: + SVG_VERBOSE(spacingDist(_level+1) << " Draw : esvg::render::path_moveTo"); + // stop last path + if (out.size() != 0) { + if (PathStart == true) { + out.back().setEndPath(); + PathStart = false; + } + } + PathStart = true; + // create a new one + if (it.getRelative() == false) { + lastPosition = vec2(0.0f, 0.0f); + } + lastPosition += it.getPos(); + out.push_back(esvg::render::Point(lastPosition, esvg::render::Point::type_start)); + break; + case esvg::render::path_lineTo: + SVG_VERBOSE(spacingDist(_level+1) << " Draw : esvg::render::path_lineTo"); + // If no previous point, we need to create the last point has start ... + if (PathStart == false) { + out.push_back(esvg::render::Point(lastPosition, esvg::render::Point::type_join)); + PathStart = true; + } + if (it.getRelative() == false) { + lastPosition = vec2(0.0f, 0.0f); + } + lastPosition += it.getPos(); + out.push_back(esvg::render::Point(lastPosition, esvg::render::Point::type_start)); + break; + case esvg::render::path_lineToH: + SVG_VERBOSE(spacingDist(_level+1) << " Draw : esvg::render::path_lineToH"); + // If no previous point, we need to create the last point has start ... + if (PathStart == false) { + out.push_back(esvg::render::Point(lastPosition, esvg::render::Point::type_join)); + PathStart = true; + } + if (it.getRelative() == false) { + lastPosition = vec2(0.0f, 0.0f); + } + lastPosition += it.getPos(); + out.push_back(esvg::render::Point(lastPosition, esvg::render::Point::type_start)); + break; + case esvg::render::path_lineToV: + SVG_VERBOSE(spacingDist(_level+1) << " Draw : esvg::render::path_lineToV"); + // If no previous point, we need to create the last point has start ... + if (PathStart == false) { + out.push_back(esvg::render::Point(lastPosition, esvg::render::Point::type_join)); + PathStart = true; + } + if (it.getRelative() == false) { + lastPosition = vec2(0.0f, 0.0f); + } + lastPosition += it.getPos(); + out.push_back(esvg::render::Point(lastPosition, esvg::render::Point::type_start)); + break; + case esvg::render::path_curveTo: + SVG_VERBOSE(spacingDist(_level+1) << " Draw : esvg::render::path_curveTo"); + // If no previous point, we need to create the last point has start ... + if (PathStart == false) { + out.push_back(esvg::render::Point(lastPosition, esvg::render::Point::type_join)); + PathStart = true; + } + { + vec2 lastPosStore(lastPosition); + if (it.getRelative() == false) { + lastPosition = vec2(0.0f, 0.0f); + } + vec2 pos1 = lastPosition + it.getPos1();; + vec2 pos2 = lastPosition + it.getPos2();; + vec2 pos = lastPosition + it.getPos();; + interpolateCubicBezier(out, + _recurtionMax, + _threshold, + lastPosStore, + pos1, + pos2, + pos, + 0, + esvg::render::Point::type_join); + lastPosition = pos; + } + break; + case esvg::render::path_smoothCurveTo: + SVG_TODO(spacingDist(_level+1) << " Draw : esvg::render::path_smoothCurveTo"); + /* + path.curve4SmoothTo(it.getRelative(), + vec2(it.m_element[0], + it.m_element[1]), + vec2(it.m_element[2], + it.m_element[3]) ); + */ + break; + case esvg::render::path_bezierCurveTo: + SVG_TODO(spacingDist(_level+1) << " Draw : esvg::render::path_bezierCurveTo"); + /* + path.curve3To(it.getRelative(), + vec2(it.m_element[0], + it.m_element[1]), + vec2(it.m_element[2], + it.m_element[3]) ); + */ + break; + case esvg::render::path_bezierSmoothCurveTo: + SVG_TODO(spacingDist(_level+1) << " Draw : esvg::render::path_bezierSmoothCurveTo"); + /* + path.curve3SmoothTo(it.getRelative(), + vec2(it.m_element[0], + it.m_element[1]) ); + */ + break; + case esvg::render::path_elliptic: + /* + SVG_VERBOSE(spacingDist(_level+1) << " Draw : esvg::render::path_elliptic"); + path.ellipticTo(it.getRelative(), + it.m_element[0], + it.m_element[1], + it.m_element[2], + it.m_element[3], + it.m_element[4], + it.m_element[5], + it.m_element[6] ); + */ + SVG_TODO(spacingDist(_level+1) << " Draw : esvg::render::path_elliptic"); + break; + default: + SVG_ERROR(spacingDist(_level+1) << " Unknow PATH commant (internal error)"); + break; + } + } + diplayRenderPoints(out); + return out; +} \ No newline at end of file diff --git a/esvg/render/Path.h b/esvg/render/Path.h index bd1b799..8a43c27 100644 --- a/esvg/render/Path.h +++ b/esvg/render/Path.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace esvg { namespace render { @@ -38,6 +39,7 @@ namespace esvg { void bezierSmoothCurveTo(bool _relative, const vec2& _pos); void ellipticTo(bool _relative, float _val0, float _val1, float _val2, float _val3, float _val4, float _val5, float _val6); void display(int32_t _spacing); + std::vector generateListPoints(int32_t _level, int32_t _recurtionMax = 10, float _threshold = 0.25f); }; } } diff --git a/esvg/render/Point.cpp b/esvg/render/Point.cpp new file mode 100644 index 0000000..e69de29 diff --git a/esvg/render/Point.h b/esvg/render/Point.h new file mode 100644 index 0000000..1df8602 --- /dev/null +++ b/esvg/render/Point.h @@ -0,0 +1,63 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license APACHE v2.0 (see license file) + */ + +#ifndef __ESVG_RENDER_POINT_H__ +#define __ESVG_RENDER_POINT_H__ + +#include +#include +#include + +namespace esvg { + namespace render { + class Point { + public: + enum type { + type_single, //!< Point type is single, this mean that it start and stop of a path + type_start, //!< Point type is starting of a path + type_stop, //!< Point type is stoping of a path + type_join, //!< Point type in an user point provided inside a path + type_interpolation, //!< This point is dynamicly calculated to create an interpolation + }; + public: + vec2 m_pos; //!< position of the point + enum esvg::render::Point::type m_type; + vec2 m_miterAxe; + vec2 m_delta; + float m_len; + Point(const vec2& _pos, enum esvg::render::Point::type _type = esvg::render::Point::type_join) : + m_pos(_pos), + m_type(_type) { + // nothing to do ... + } + void setEndPath() { + if (m_type == esvg::render::Point::type_interpolation) { + SVG_WARNING("Request stop path of an interpolate Point"); + m_type = esvg::render::Point::type_stop; + return; + } + if (m_type == esvg::render::Point::type_stop) { + SVG_WARNING("Request stop path of an STOP Point"); + return; + } + if (m_type == esvg::render::Point::type_start) { + m_type = esvg::render::Point::type_single; + return; + } + m_type = esvg::render::Point::type_stop; + } + void normalize(const vec2& _nextPoint) { + m_delta = _nextPoint - m_pos; + m_len = m_delta.length(); + } + }; + } +} + +#endif + diff --git a/lutin_esvg.py b/lutin_esvg.py index b972837..cd543e0 100644 --- a/lutin_esvg.py +++ b/lutin_esvg.py @@ -70,7 +70,6 @@ def create(target, module_name): 'esvg/Renderer.h', 'esvg/Stroking.h', 'esvg/Text.h', - 'esvg/render/Path.h', 'esvg/render/Element.h', 'esvg/render/ElementStop.h', 'esvg/render/ElementMoveTo.h', @@ -81,7 +80,9 @@ def create(target, module_name): 'esvg/render/ElementSmoothCurveTo.h', 'esvg/render/ElementBezierCurveTo.h', 'esvg/render/ElementBezierSmoothCurveTo.h', - 'esvg/render/ElementElliptic.h' + 'esvg/render/ElementElliptic.h', + 'esvg/render/Path.h', + 'esvg/render/Point.h' ]) my_module.add_path(tools.get_current_path(__file__))