Merge lp:~inkscape.dev/inkscape/pathVectorSatellites into lp:~inkscape.dev/inkscape/trunk
- pathVectorSatellites
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 15666 |
Proposed branch: | lp:~inkscape.dev/inkscape/pathVectorSatellites |
Merge into: | lp:~inkscape.dev/inkscape/trunk |
Diff against target: |
4168 lines (+2029/-1667) 20 files modified
po/POTFILES.in (+1/-1) src/helper/CMakeLists.txt (+4/-0) src/helper/geom-pathvectorsatellites.cpp (+244/-0) src/helper/geom-pathvectorsatellites.h (+58/-0) src/helper/geom-satellite.cpp (+245/-0) src/helper/geom-satellite.h (+110/-0) src/knotholder.h (+3/-2) src/live_effects/CMakeLists.txt (+2/-2) src/live_effects/effect.cpp (+1/-1) src/live_effects/lpe-fillet-chamfer.cpp (+466/-543) src/live_effects/lpe-fillet-chamfer.h (+29/-35) src/live_effects/parameter/array.cpp (+40/-4) src/live_effects/parameter/array.h (+38/-1) src/live_effects/parameter/filletchamferpointarray.cpp (+0/-873) src/live_effects/parameter/filletchamferpointarray.h (+0/-123) src/live_effects/parameter/satellitesarray.cpp (+583/-0) src/live_effects/parameter/satellitesarray.h (+114/-0) src/ui/dialog/lpe-fillet-chamfer-properties.cpp (+63/-52) src/ui/dialog/lpe-fillet-chamfer-properties.h (+28/-22) src/ui/tool/path-manipulator.cpp (+0/-8) |
To merge this branch: | bzr merge lp:~inkscape.dev/inkscape/pathVectorSatellites |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jabiertxof | Needs Resubmitting | ||
Krzysztof Kosinski | Needs Fixing | ||
Review via email: mp+254724@code.launchpad.net |
Commit message
Description of the change
Add pointwise class to manage "satellite" data in nodes and a add a refactor of fillet-chamfer LPE using it.
- 13704. By Jabiertxof <email address hidden>
-
change pointwise comment
- 13705. By Jabiertxof <email address hidden>
-
Remove active desktop calls from LPE
- 13706. By Jabiertxof <email address hidden>
-
fixed hide knots and removed unused headers
- 13707. By Jabiertxof <email address hidden>
-
removed code comments
Jabiertxof (jabiertxof) wrote : | # |
Hi Krzysztof thanks for the fast review.
I try to improve all.
Regards.
- 13708. By Jabiertxof <email address hidden>
-
Move 2Geom work to a intermediate positon -helper-
Removed dependency to helper/geom.h
Now use a simple vector, not a vector of pairs of size_t and Satellite
Getters and setters on Satellite removed
Update store parameter to a more friendly string, like powerstroke
Todo:
Documentation and Fix coding style. - 13709. By Jabiertxof <email address hidden>
-
More cleanup of code structure.
TODO: Documentation
TODO: Fit code guidelines of Inkscape - 13710. By Jabiertxof <email address hidden>
-
add documentation
- 13711. By Jabiertxof <email address hidden>
-
Added documentation and fix to coding style.
- 13712. By Jabiertxof <email address hidden>
-
update to trunk
- 13713. By Jabiertxof <email address hidden>
-
Now open -without conversion- old fillet chamfer objects
- 13714. By Jabiertxof <email address hidden>
-
add move knots when move nodes pointed by su_v
- 13715. By Jabiertxof <email address hidden>
-
Adding suport for duplicate nodes
Allow degenrate curves
Show helper path whith original path - 13716. By Jabiertxof <email address hidden>
-
update to trunk
- 13717. By Jabiertxof <email address hidden>
-
Update pathinfo class to allow piecewise and pathvector as input.
Add a method on pointwise to allow update if degenerated curves in new path, not noticed by piecewises - 13718. By Jabiertxof <email address hidden>
-
Updated Pathinfo to discrimine degenerate curves optionaly.
Fixed redundant data in are_near from pointwise
Fixed Fillet-Chamfer lpe to allow duplicate nodes - 13719. By Jabiertxof <email address hidden>
-
Fix a bug in pathinfo
- 13720. By Jabiertxof <email address hidden>
-
update to trunk
- 13721. By Jabiertxof <email address hidden>
-
fixing bug on closed paths
- 13722. By Jabiertxof <email address hidden>
-
Fixed bug on closed paths, Clenup of pathinfo
Jabiertxof (jabiertxof) wrote : | # |
Hi Krzysztof, could you review again the branch?
Thanks very much, Jabier.
- 13723. By Jabiertxof <email address hidden>
-
rename pathinfo function
- 13724. By Jabiertxof <email address hidden>
-
Adding and renaming methofs to pathinfo
- 13725. By Jabiertxof <email address hidden>
-
added comment
- 13726. By Jabiertxof <email address hidden>
-
update to trunk
- 13727. By Jabiertxof <email address hidden>
-
adding suport to full path reverse
- 13728. By Jabiertxof <email address hidden>
-
update to trunk
- 13729. By Jabiertxof <email address hidden>
-
prevent overflow index on a pathinfo function
Krzysztof Kosinski (tweenk) wrote : | # |
There are still a lot of issues that need to be fixed.
I am not sure about the class Pathinfo. I think these functions could be added directly to PathVector, but I'm not sure yet what Pathinfo does.
You should spend some time on writing comments what your code wants to do, it will be easier to review.
Jabiertxof (jabiertxof) wrote : | # |
Thanks for the review Krzysztof. I take it soon.
- 13730. By Jabiertxof <email address hidden>
-
update to trunk
- 13731. By Jabiertxof <email address hidden>
-
fixing review
- 13732. By Jabiertxof <email address hidden>
-
fixing review
- 13733. By Jabiertxof <email address hidden>
-
update to trunk
- 13734. By Jabiertxof <email address hidden>
-
Working on Krzysztof review. Seems to be all fixed.
TODO: double check review and comment - 13735. By Jabiertxof <email address hidden>
-
Added some comments
- 13736. By Jabiertxof <email address hidden>
-
some comments and pointwise related refactor
Jabiertxof (jabiertxof) wrote : | # |
Hi Krzysztof, could you review again the branch?
Thanks very much, Jabier.
- 13737. By Jabiertxof <email address hidden>
-
fix a minor bug calculating max time
- 13738. By Jabiertxof <email address hidden>
-
update to trunk
- 13739. By Jabiertxof <email address hidden>
-
update to trunk
- 13740. By Jabiertxof <email address hidden>
-
attemp to handle reverse path
- 13741. By Jabiertxof <email address hidden>
-
update to trunk
- 13742. By Jabiertxof <email address hidden>
-
removed reverse path, commented why
- 13743. By Jabiertxof <email address hidden>
-
update to trunk
Krzysztof Kosinski (tweenk) wrote : | # |
This looks better, but I think I understand what Pathinfo does now, and the whole class is unnecessary. The number of nodes in a Geom::Path is equal to size_closed(), you don't need to reimplement it and you don't need the active attribute in satellites.
I only reviewed a portion of the code - I will try to continue the review during this weekend.
Jabiertxof (jabiertxof) wrote : | # |
Thanks Krzysztof for the review. A great new i can use your last work on 2Geom inside Inkscape trunk! Go to fix!
Jabiertxof (jabiertxof) wrote : | # |
One question Krzysztof, whats the best way to know the first and last subpath curve index on a pathvector?
Krzysztof Kosinski (tweenk) wrote : | # |
The first subpath is always at index 0. The last one is at size_default() - 1. The number of nodes is always equal to std::max(
Jabiertxof (jabiertxof) wrote : | # |
> The first subpath is always at index 0. The last one is at size_default() - 1.
> The number of nodes is always equal to std::max(
> that has no segments contains only a naked moveto, and thus has one node. Hope
> this helps.
Thanks Krzysztof for the quick reply!
Seems I ask bad the question, i want to know the index of start and end index in a intermediate "subpath" not at full pathvector.
Maybe PathVectorTime can also return this value when retrive the value of pathvector index from PathVector-
Sorry for my bad english.
Jabiertxof (jabiertxof) wrote : | # |
More, Krzysztof:
I have a new commit with pathinfo class removed. Is working except a small function that need the index of first and last subpath.
Think is better commit it or wait to you to full review current branch?
Krzysztof Kosinski (tweenk) wrote : | # |
You can commit your new code to this branch and I will try to review both the new code and the parts I didn't review yet.
- 13744. By Jabiertxof <email address hidden>
-
update to trunk
- 13745. By Jabiertxof <email address hidden>
-
fix to compile on Krzysztof merge previous to fix the improvements in the merge request
- 13746. By Jabiertxof <email address hidden>
-
Fix a bug displaying arcs
- 13747. By Jabiertxof <email address hidden>
-
Fixes from branch review
- 13748. By Jabiertxof <email address hidden>
-
update to trunk
- 13749. By Jabiertxof <email address hidden>
-
pointwise tweak
- 13750. By Jabiertxof <email address hidden>
-
astyle
Jabiertxof (jabiertxof) wrote : | # |
> You can commit your new code to this branch and I will try to review both the
> new code and the parts I didn't review yet.
Commited. Thanks for your time!
- 13751. By Jabiertxof <email address hidden>
-
update to trunk
- 13752. By Jabiertxof <email address hidden>
-
Not sure about this changes :(
- 13753. By Jabiertxof <email address hidden>
-
update to trunk
- 13754. By Jabiertxof <email address hidden>
-
remove couts
- 13755. By Jabiertxof <email address hidden>
-
satellites in curves
- 13756. By Jabiertxof <email address hidden>
-
Cached some functions
- 13757. By Jabiertxof <email address hidden>
-
addes cache and log to a function, result of the test, no diference so remove cache on next commit
- 13758. By Jabiertxof <email address hidden>
-
Removed cache work :(
- 13759. By Jabiertxof <email address hidden>
-
add 'little' comment
- 13760. By Jabiertxof <email address hidden>
-
update to trunk
- 13761. By Jabiertxof <email address hidden>
-
astyle code
- 13762. By Jabiertxof <email address hidden>
-
update to trunk
- 13763. By Jabiertxof <email address hidden>
-
Update to limit options to radius = 0, radious > 0 or both
- 13764. By Jabiertxof <email address hidden>
-
Update to trunk
- 13765. By Jabiertxof <email address hidden>
-
Fixed bugs post merge
- 13766. By Jabiertxof <email address hidden>
-
update to trunk
- 13767. By Jabiertxof <email address hidden>
-
update to trunk
- 13768. By Jabiertxof <email address hidden>
-
Remove advertaising buttons of old version
- 13769. By Jabiertxof <email address hidden>
-
update to trunk
- 13770. By Jabiertxof
-
update to trunk
- 13771. By Jabiertxof
-
remove a waring on compile
Krzysztof Kosinski (tweenk) wrote : | # |
This is a little better, but it needs two major changes.
1. Opening a dialog by shift-clicking on a node is completely crazy. There must another way.
2. The doEffect function must be broken down into smaller functions so I can have any hope of understanding what it does.
Moreover, please consider using a vector of vectors for storing satellites. You would not need flat indexing of curves in pathvectors, which is error prone, and your code would be a lot simpler.
- 13772. By Jabiertxof
-
update to trunk
- 13773. By Jabiertxof
-
First attempt to make fixed tweenk review
- 13774. By Jabiertxof
-
update to trunk
- 13775. By Jabiertxof
-
Working with path updates
- 13776. By Jabiertxof
-
update to trunk
- 13777. By Jabiertxof
-
pre-remove of subpath update satellites
- 13778. By Jabiertxof
-
Fiximg pointwise
- 13779. By Jabiertxof
-
update to trunk
- 13780. By Jabiertxof
-
Fixing pointwise
- 13781. By Jabiertxof
-
update to trunk
- 13782. By Jabiertxof
-
Fixing pointwise
- 13783. By Jabiertxof
-
update to trunk
- 13784. By Jabiertxof
-
Update to refresh knots
- 13785. By Jabiertxof
-
update to trunk
- 13786. By Jabiertxof
-
Fixing pointwise
- 13787. By Jabiertxof
-
update to trunk
- 13788. By Jabiertxof
-
Fixing pointwise
- 13789. By Jabiertxof
-
update to trunk
- 13790. By Jabiertxof
-
Rename branch
- 13791. By Jabiertxof
-
Fixing satellites bug on erase
- 13792. By Jabiertxof
-
update to trunk
- 13793. By Jabiertxof
-
Fix the bug deleting satellites
- 13794. By Jabiertxof
-
update to trunk
- 13795. By Jabiertxof
-
Handle path add and remove nodes
- 13796. By Jabiertxof
-
update to trunk
- 13797. By Jabiertxof
-
Fix bug consecutive nodes at same position
- 13798. By Jabiertxof
-
update to trunk
- 13799. By Jabiertxof
-
Handle both directions on knot reposition
- 13800. By Jabiertxof
-
Fix 90% of tweenk review
- 13801. By Jabiertxof
-
update to trunk
- 13802. By Jabiertxof
-
Add snap to origin in double direction knots
- 13803. By Jabiertxof
-
update to trunk
- 13804. By Jabiertxof
-
attemp to simplify doeffect code on fillet chamfer
- 13805. By Jabiertxof
-
update to trunk
- 13806. By Jabiertxof
-
Pre fixing selected points
- 13807. By Jabiertxof
-
fixing bug moving nodes
- 13808. By Jabiertxof
-
Fixes when moves a path
- 13809. By Jabiertxof
-
Organize doeffect function
Jabiertxof (jabiertxof) wrote : | # |
Fix Krzysztof Kosinski review.
Target 0.93
- 13810. By Jabiertxof <jtx@jtx>
-
Update to trunk
- 13811. By Jabiertxof <jtx@jtx>
-
Update to new code in trunk
- 13812. By Jabiertxof <jtx@jtx>
-
Update to trunk
- 13813. By Jabiertxof
-
update to trunk
- 13814. By Jabiertxof
-
update to trunk
- 13815. By Jabiertxof <jtx@jtx>
-
Update to trunk
- 13816. By Jabiertxof <jtx@jtx>
-
Remove some warnings
- 13817. By Jabiertxof <jtx@jtx>
-
Remove some warnings
- 13818. By Jabiertxof <jtx@jtx>
-
Update to trunk
Jabiertxof (jabiertxof) wrote : | # |
Just updated to trunk. Code on trunk about fillet/chamfer need to be replaced by this branch. This is the cause this LPE is not on 0.92.
- 13819. By Jabiertxof
-
Update to trunk
- 13820. By Jabiertxof <jtx@jtx>
-
Update to trunk
- 13821. By Jabiertxof <jtx@jtx>
-
Updating code to trunk
- 13822. By Jabiertxof <jtx@jtx>
-
Pre merge fixing
Jabiertxof (jabiertxof) wrote : | # |
Merged on r.15666
Preview Diff
1 | === modified file 'po/POTFILES.in' |
2 | --- po/POTFILES.in 2016-12-27 15:49:22 +0000 |
3 | +++ po/POTFILES.in 2017-05-06 17:46:29 +0000 |
4 | @@ -153,7 +153,7 @@ |
5 | src/live_effects/lpe-vonkoch.cpp |
6 | src/live_effects/parameter/bool.cpp |
7 | src/live_effects/parameter/enum.h |
8 | -src/live_effects/parameter/filletchamferpointarray.cpp |
9 | +src/live_effects/parameter/satellitearray.cpp |
10 | src/live_effects/parameter/fontbutton.cpp |
11 | src/live_effects/parameter/originalpath.cpp |
12 | src/live_effects/parameter/originalpatharray.cpp |
13 | |
14 | === modified file 'src/helper/CMakeLists.txt' |
15 | --- src/helper/CMakeLists.txt 2015-03-19 01:41:26 +0000 |
16 | +++ src/helper/CMakeLists.txt 2017-05-06 17:46:29 +0000 |
17 | @@ -14,6 +14,8 @@ |
18 | geom.cpp |
19 | geom-nodetype.cpp |
20 | geom-pathstroke.cpp |
21 | + geom-pathvectorsatellites.cpp |
22 | + geom-satellite.cpp |
23 | gnome-utils.cpp |
24 | pixbuf-ops.cpp |
25 | png-write.cpp |
26 | @@ -32,6 +34,8 @@ |
27 | geom-curves.h |
28 | geom-nodetype.h |
29 | geom-pathstroke.h |
30 | + geom-pathvectorsatellites.h |
31 | + geom-satellite.h |
32 | geom.h |
33 | gnome-utils.h |
34 | mathfns.h |
35 | |
36 | === added file 'src/helper/geom-pathvectorsatellites.cpp' |
37 | --- src/helper/geom-pathvectorsatellites.cpp 1970-01-01 00:00:00 +0000 |
38 | +++ src/helper/geom-pathvectorsatellites.cpp 2017-05-06 17:46:29 +0000 |
39 | @@ -0,0 +1,244 @@ |
40 | +/** |
41 | + * \file |
42 | + * \brief PathVectorSatellites a class to manage satellites -per node extra data- in a pathvector |
43 | + */ /* |
44 | + * Authors: |
45 | + * Jabiertxof |
46 | + * Nathan Hurst |
47 | + * Johan Engelen |
48 | + * Josh Andler |
49 | + * suv |
50 | + * Mc- |
51 | + * Liam P. White |
52 | + * Krzysztof Kosiński |
53 | + * This code is in public domain |
54 | + */ |
55 | + |
56 | +#include <helper/geom-pathvectorsatellites.h> |
57 | +#include "util/units.h" |
58 | + |
59 | +Geom::PathVector PathVectorSatellites::getPathVector() const |
60 | +{ |
61 | + return _pathvector; |
62 | +} |
63 | + |
64 | +void PathVectorSatellites::setPathVector(Geom::PathVector pathv) |
65 | +{ |
66 | + _pathvector = pathv; |
67 | +} |
68 | + |
69 | +Satellites PathVectorSatellites::getSatellites() |
70 | +{ |
71 | + return _satellites; |
72 | +} |
73 | + |
74 | +void PathVectorSatellites::setSatellites(Satellites satellites) |
75 | +{ |
76 | + _satellites = satellites; |
77 | +} |
78 | + |
79 | +size_t PathVectorSatellites::getTotalSatellites() |
80 | +{ |
81 | + size_t counter = 0; |
82 | + for (size_t i = 0; i < _satellites.size(); ++i) { |
83 | + for (size_t j = 0; j < _satellites[i].size(); ++j) { |
84 | + counter++; |
85 | + } |
86 | + } |
87 | + return counter; |
88 | +} |
89 | + |
90 | +std::pair<size_t, size_t> PathVectorSatellites::getIndexData(size_t index) |
91 | +{ |
92 | + size_t counter = 0; |
93 | + for (size_t i = 0; i < _satellites.size(); ++i) { |
94 | + for (size_t j = 0; j < _satellites[i].size(); ++j) { |
95 | + if (index == counter) { |
96 | + return std::make_pair(i,j); |
97 | + } |
98 | + counter++; |
99 | + } |
100 | + } |
101 | + return std::make_pair(0,0); |
102 | +} |
103 | + |
104 | +void PathVectorSatellites::setSelected(std::vector<size_t> selected) |
105 | +{ |
106 | + size_t counter = 0; |
107 | + for (size_t i = 0; i < _satellites.size(); ++i) { |
108 | + for (size_t j = 0; j < _satellites[i].size(); ++j) { |
109 | + if (find (selected.begin(), selected.end(), counter) != selected.end()) { |
110 | + _satellites[i][j].setSelected(true); |
111 | + } else { |
112 | + _satellites[i][j].setSelected(false); |
113 | + } |
114 | + counter++; |
115 | + } |
116 | + } |
117 | +} |
118 | + |
119 | +void PathVectorSatellites::updateSteps(size_t steps, bool apply_no_radius, bool apply_with_radius, bool only_selected) |
120 | +{ |
121 | + for (size_t i = 0; i < _satellites.size(); ++i) { |
122 | + for (size_t j = 0; j < _satellites[i].size(); ++j) { |
123 | + if ((!apply_no_radius && _satellites[i][j].amount == 0) || |
124 | + (!apply_with_radius && _satellites[i][j].amount != 0)) |
125 | + { |
126 | + continue; |
127 | + } |
128 | + if (only_selected) { |
129 | + if (_satellites[i][j].selected) { |
130 | + _satellites[i][j].steps = steps; |
131 | + } |
132 | + } else { |
133 | + _satellites[i][j].steps = steps; |
134 | + } |
135 | + } |
136 | + } |
137 | +} |
138 | + |
139 | +void PathVectorSatellites::updateAmount(double radius, bool apply_no_radius, bool apply_with_radius, bool only_selected, |
140 | + bool use_knot_distance, bool flexible) |
141 | +{ |
142 | + double power = 0; |
143 | + if (!flexible) { |
144 | + power = radius; |
145 | + } else { |
146 | + power = radius / 100; |
147 | + } |
148 | + for (size_t i = 0; i < _satellites.size(); ++i) { |
149 | + for (size_t j = 0; j < _satellites[i].size(); ++j) { |
150 | + boost::optional<size_t> previous_index = boost::none; |
151 | + if (j == 0 && _pathvector[i].closed()) { |
152 | + previous_index = _pathvector[i].size() - 1; |
153 | + } else if (!_pathvector[i].closed() || j != 0) { |
154 | + previous_index = j - 1; |
155 | + } |
156 | + if (!_pathvector[i].closed() && j == 0) { |
157 | + _satellites[i][j].amount = 0; |
158 | + continue; |
159 | + } |
160 | + if (_pathvector[i].size() == j) { |
161 | + continue; |
162 | + } |
163 | + if ((!apply_no_radius && _satellites[i][j].amount == 0) || |
164 | + (!apply_with_radius && _satellites[i][j].amount != 0)) |
165 | + { |
166 | + continue; |
167 | + } |
168 | + |
169 | + Geom::Point satellite_point = _pathvector[i].pointAt(j); |
170 | + if (_satellites[i][j].selected || !only_selected) { |
171 | + if (!use_knot_distance && !flexible) { |
172 | + if (previous_index) { |
173 | + _satellites[i][j].amount = _satellites[i][j].radToLen(power, _pathvector[i][*previous_index], _pathvector[i][j]); |
174 | + if (power && !_satellites[i][j].amount) { |
175 | + g_warning("Seems a too high radius value"); |
176 | + } |
177 | + } else { |
178 | + _satellites[i][j].amount = 0.0; |
179 | + } |
180 | + } else { |
181 | + _satellites[i][j].amount = power; |
182 | + } |
183 | + } |
184 | + } |
185 | + } |
186 | +} |
187 | + |
188 | +void PathVectorSatellites::convertUnit(Glib::ustring in, Glib::ustring to, bool apply_no_radius, bool apply_with_radius) |
189 | +{ |
190 | + for (size_t i = 0; i < _satellites.size(); ++i) { |
191 | + for (size_t j = 0; j < _satellites[i].size(); ++j) { |
192 | + if (!_pathvector[i].closed() && j == 0) { |
193 | + _satellites[i][j].amount = 0; |
194 | + continue; |
195 | + } |
196 | + if (_pathvector[i].size() == j) { |
197 | + continue; |
198 | + } |
199 | + if ((!apply_no_radius && _satellites[i][j].amount == 0) || |
200 | + (!apply_with_radius && _satellites[i][j].amount != 0)) |
201 | + { |
202 | + continue; |
203 | + } |
204 | + _satellites[i][j].amount = Inkscape::Util::Quantity::convert(_satellites[i][j].amount, in.c_str(), to.c_str()); |
205 | + } |
206 | + } |
207 | +} |
208 | + |
209 | +void PathVectorSatellites::updateSatelliteType(SatelliteType satellitetype, bool apply_no_radius, bool apply_with_radius, |
210 | + bool only_selected) |
211 | +{ |
212 | + for (size_t i = 0; i < _satellites.size(); ++i) { |
213 | + for (size_t j = 0; j < _satellites[i].size(); ++j) { |
214 | + if ((!apply_no_radius && _satellites[i][j].amount == 0) || |
215 | + (!apply_with_radius && _satellites[i][j].amount != 0)) |
216 | + { |
217 | + continue; |
218 | + } |
219 | + if (_pathvector[i].size() == j) { |
220 | + if (!only_selected) { |
221 | + _satellites[i][j].satellite_type = satellitetype; |
222 | + } |
223 | + continue; |
224 | + } |
225 | + if (only_selected) { |
226 | + Geom::Point satellite_point = _pathvector[i].pointAt(j); |
227 | + if (_satellites[i][j].selected) { |
228 | + _satellites[i][j].satellite_type = satellitetype; |
229 | + } |
230 | + } else { |
231 | + _satellites[i][j].satellite_type = satellitetype; |
232 | + } |
233 | + } |
234 | + } |
235 | +} |
236 | + |
237 | +void PathVectorSatellites::recalculateForNewPathVector(Geom::PathVector const pathv, Satellite const S) |
238 | +{ |
239 | + Satellites satellites; |
240 | + bool found = false; |
241 | + //TODO evaluate fix on nodes at same position |
242 | + size_t number_nodes = pathv.nodes().size(); |
243 | + size_t previous_number_nodes = _pathvector.nodes().size(); |
244 | + for (size_t i = 0; i < pathv.size(); i++) { |
245 | + std::vector<Satellite> path_satellites; |
246 | + for (size_t j = 0; j < pathv[i].size_closed(); j++) { |
247 | + found = false; |
248 | + for (size_t k = 0; k < _pathvector.size(); k++) { |
249 | + for (size_t l = 0; l < _pathvector[k].size_closed(); l++) { |
250 | + if (Geom::are_near(_pathvector[k][l].initialPoint(), pathv[i][j].initialPoint())) |
251 | + { |
252 | + path_satellites.push_back(_satellites[k][l]); |
253 | + found = true; |
254 | + break; |
255 | + } |
256 | + } |
257 | + if (found) { |
258 | + break; |
259 | + } |
260 | + } |
261 | + |
262 | + if (!found && previous_number_nodes < number_nodes) { |
263 | + path_satellites.push_back(S); |
264 | + } |
265 | + } |
266 | + satellites.push_back(path_satellites); |
267 | + } |
268 | + setPathVector(pathv); |
269 | + setSatellites(satellites); |
270 | +} |
271 | + |
272 | +/* |
273 | + Local Variables: |
274 | + mode:c++ |
275 | + c-file-style:"stroustrup" |
276 | + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) |
277 | + indent-tabs-mode:nil |
278 | + fill-column:99 |
279 | + End: |
280 | +*/ |
281 | +// vim: |
282 | +// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 |
283 | +// : |
284 | |
285 | === added file 'src/helper/geom-pathvectorsatellites.h' |
286 | --- src/helper/geom-pathvectorsatellites.h 1970-01-01 00:00:00 +0000 |
287 | +++ src/helper/geom-pathvectorsatellites.h 2017-05-06 17:46:29 +0000 |
288 | @@ -0,0 +1,58 @@ |
289 | +/** |
290 | + * \file |
291 | + * \brief PathVectorSatellites a class to manage satellites -per node extra data- in a pathvector |
292 | + */ /* |
293 | + * Authors: |
294 | + * Jabiertxof |
295 | + * Nathan Hurst |
296 | + * Johan Engelen |
297 | + * Josh Andler |
298 | + * suv |
299 | + * Mc- |
300 | + * Liam P. White |
301 | + * Krzysztof Kosiński |
302 | + * This code is in public domain |
303 | + */ |
304 | + |
305 | +#ifndef SEEN_PATHVECTORSATELLITES_H |
306 | +#define SEEN_PATHVECTORSATELLITES_H |
307 | + |
308 | +#include <helper/geom-satellite.h> |
309 | +#include <2geom/path.h> |
310 | +#include <2geom/pathvector.h> |
311 | + |
312 | +typedef std::vector<std::vector<Satellite> > Satellites; |
313 | +///@brief PathVectorSatellites a class to manage satellites in a pathvector |
314 | +class PathVectorSatellites { |
315 | +public: |
316 | + Geom::PathVector getPathVector() const; |
317 | + void setPathVector(Geom::PathVector pathv); |
318 | + Satellites getSatellites(); |
319 | + void setSatellites(Satellites satellites); |
320 | + size_t getTotalSatellites(); |
321 | + void setSelected(std::vector<size_t> selected); |
322 | + void updateSteps(size_t steps, bool apply_no_radius, bool apply_with_radius, bool only_selected); |
323 | + void updateAmount(double radius, bool apply_no_radius, bool apply_with_radius, bool only_selected, |
324 | + bool use_knot_distance, bool flexible); |
325 | + void convertUnit(Glib::ustring in, Glib::ustring to, bool apply_no_radius, bool apply_with_radius); |
326 | + void updateSatelliteType(SatelliteType satellitetype, bool apply_no_radius, bool apply_with_radius, bool only_selected); |
327 | + std::pair<size_t, size_t> getIndexData(size_t index); |
328 | + void recalculateForNewPathVector(Geom::PathVector const pathv, Satellite const S); |
329 | +private: |
330 | + Geom::PathVector _pathvector; |
331 | + Satellites _satellites; |
332 | +}; |
333 | + |
334 | +#endif //SEEN_PATHVECTORSATELLITES_H |
335 | +/* |
336 | + Local Variables: |
337 | + mode:c++ |
338 | + c-file-style:"stroustrup" |
339 | + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) |
340 | + indent-tabs-mode:nil |
341 | + fill-column:99 |
342 | + End: |
343 | +*/ |
344 | +// vim: |
345 | +// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 |
346 | +// : |
347 | |
348 | === added file 'src/helper/geom-satellite.cpp' |
349 | --- src/helper/geom-satellite.cpp 1970-01-01 00:00:00 +0000 |
350 | +++ src/helper/geom-satellite.cpp 2017-05-06 17:46:29 +0000 |
351 | @@ -0,0 +1,245 @@ |
352 | +/** |
353 | + * \file |
354 | + * \brief Satellite a per node holder of data. |
355 | + */ /* |
356 | + * Authors: |
357 | + * 2015 Jabier Arraiza Cenoz<jabier.arraiza@marker.es> |
358 | + * |
359 | + * This code is in public domain |
360 | + */ |
361 | + |
362 | +#include <helper/geom-satellite.h> |
363 | +#include <2geom/curve.h> |
364 | +#include <2geom/nearest-time.h> |
365 | +#include <2geom/path-intersection.h> |
366 | +#include <2geom/sbasis-to-bezier.h> |
367 | +#include <2geom/ray.h> |
368 | +#include <boost/optional.hpp> |
369 | +//log cache |
370 | +#ifdef _WIN32 |
371 | +#include <Windows.h> |
372 | +#else |
373 | +#include <sys/time.h> |
374 | +#include <ctime> |
375 | +#endif |
376 | + |
377 | +///@brief Satellite a per node holder of data. |
378 | +Satellite::Satellite() {} |
379 | + |
380 | + |
381 | +Satellite::Satellite(SatelliteType satellite_type) |
382 | + : satellite_type(satellite_type), |
383 | + is_time(false), |
384 | + selected(false), |
385 | + has_mirror(false), |
386 | + hidden(true), |
387 | + amount(0.0), |
388 | + angle(0.0), |
389 | + steps(0) |
390 | +{} |
391 | + |
392 | +Satellite::~Satellite() {} |
393 | + |
394 | +///Calculate the time in curve_in with a size of A |
395 | +//TODO: find a better place to it |
396 | +double timeAtArcLength(double const A, Geom::Curve const &curve_in) |
397 | +{ |
398 | + if ( A == 0 || curve_in.isDegenerate()) { |
399 | + return 0; |
400 | + } |
401 | + |
402 | + Geom::D2<Geom::SBasis> d2_in = curve_in.toSBasis(); |
403 | + double t = 0; |
404 | + double length_part = curve_in.length(); |
405 | + if (A >= length_part || curve_in.isLineSegment()) { |
406 | + if (length_part != 0) { |
407 | + t = A / length_part; |
408 | + } |
409 | + } else if (!curve_in.isLineSegment()) { |
410 | + std::vector<double> t_roots = roots(Geom::arcLengthSb(d2_in) - A); |
411 | + if (!t_roots.empty()) { |
412 | + t = t_roots[0]; |
413 | + } |
414 | + } |
415 | + return t; |
416 | +} |
417 | + |
418 | +///Calculate the size in curve_in with a point at A |
419 | +//TODO: find a better place to it |
420 | +double arcLengthAt(double const A, Geom::Curve const &curve_in) |
421 | +{ |
422 | + if ( A == 0 || curve_in.isDegenerate()) { |
423 | + return 0; |
424 | + } |
425 | + |
426 | + double s = 0; |
427 | + double length_part = curve_in.length(); |
428 | + if (A > length_part || curve_in.isLineSegment()) { |
429 | + s = (A * length_part); |
430 | + } else if (!curve_in.isLineSegment()) { |
431 | + Geom::Curve *curve = curve_in.portion(0.0, A); |
432 | + s = curve->length(); |
433 | + delete curve; |
434 | + } |
435 | + return s; |
436 | +} |
437 | + |
438 | +///Convert a arc radius of a fillet/chamfer to his satellite length -point position where fillet/chamfer knot be on original curve |
439 | +double Satellite::radToLen( |
440 | + double const A, Geom::Curve const &curve_in, |
441 | + Geom::Curve const &curve_out) const |
442 | +{ |
443 | + double len = 0; |
444 | + Geom::D2<Geom::SBasis> d2_in = curve_in.toSBasis(); |
445 | + Geom::D2<Geom::SBasis> d2_out = curve_out.toSBasis(); |
446 | + Geom::Piecewise<Geom::D2<Geom::SBasis> > offset_curve0 = |
447 | + Geom::Piecewise<Geom::D2<Geom::SBasis> >(d2_in) + |
448 | + rot90(unitVector(derivative(d2_in))) * (A); |
449 | + Geom::Piecewise<Geom::D2<Geom::SBasis> > offset_curve1 = |
450 | + Geom::Piecewise<Geom::D2<Geom::SBasis> >(d2_out) + |
451 | + rot90(unitVector(derivative(d2_out))) * (A); |
452 | + Geom::Path p0 = path_from_piecewise(offset_curve0, 0.1)[0]; |
453 | + Geom::Path p1 = path_from_piecewise(offset_curve1, 0.1)[0]; |
454 | + Geom::Crossings cs = Geom::crossings(p0, p1); |
455 | + if (cs.size() > 0) { |
456 | + Geom::Point cp = p0(cs[0].ta); |
457 | + double p0pt = nearest_time(cp, curve_out); |
458 | + len = arcLengthAt(p0pt, curve_out); |
459 | + } else { |
460 | + if (A > 0) { |
461 | + len = radToLen(A * -1, curve_in, curve_out); |
462 | + } |
463 | + } |
464 | + return len; |
465 | +} |
466 | + |
467 | +///Convert a satelite length -point position where fillet/chamfer knot be on original curve- to a arc radius of fillet/chamfer |
468 | +double Satellite::lenToRad( |
469 | + double const A, Geom::Curve const &curve_in, |
470 | + Geom::Curve const &curve_out, |
471 | + Satellite const previousSatellite) const |
472 | +{ |
473 | + double time_in = (previousSatellite).time(A, true, curve_in); |
474 | + double time_out = timeAtArcLength(A, curve_out); |
475 | + Geom::Point start_arc_point = curve_in.pointAt(time_in); |
476 | + Geom::Point end_arc_point = curve_out.pointAt(time_out); |
477 | + Geom::Curve *knot_curve1 = curve_in.portion(0, time_in); |
478 | + Geom::Curve *knot_curve2 = curve_out.portion(time_out, 1); |
479 | + Geom::CubicBezier const *cubic1 = dynamic_cast<Geom::CubicBezier const *>(&*knot_curve1); |
480 | + Geom::Ray ray1(start_arc_point, curve_in.pointAt(1)); |
481 | + if (cubic1) { |
482 | + ray1.setPoints((*cubic1)[2], start_arc_point); |
483 | + } |
484 | + Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*knot_curve2); |
485 | + Geom::Ray ray2(curve_out.pointAt(0), end_arc_point); |
486 | + if (cubic2) { |
487 | + ray2.setPoints(end_arc_point, (*cubic2)[1]); |
488 | + } |
489 | + bool ccw_toggle = cross(curve_in.pointAt(1) - start_arc_point, |
490 | + end_arc_point - start_arc_point) < 0; |
491 | + double distance_arc = |
492 | + Geom::distance(start_arc_point, middle_point(start_arc_point, end_arc_point)); |
493 | + double angle = angle_between(ray1, ray2, ccw_toggle); |
494 | + double divisor = std::sin(angle / 2.0); |
495 | + if (divisor > 0) { |
496 | + return distance_arc / divisor; |
497 | + } |
498 | + return 0; |
499 | +} |
500 | + |
501 | +///Get the time position of the satellite in curve_in |
502 | +double Satellite::time(Geom::Curve const &curve_in, bool inverse) const |
503 | +{ |
504 | + double t = amount; |
505 | + if (!is_time) { |
506 | + t = time(t, inverse, curve_in); |
507 | + } else if (inverse) { |
508 | + t = 1-t; |
509 | + } |
510 | + if (t > 1) { |
511 | + t = 1; |
512 | + } |
513 | + return t; |
514 | +} |
515 | + |
516 | +///Get the time from a length A in other curve, a bolean inverse gived to reverse time |
517 | +double Satellite::time(double A, bool inverse, |
518 | + Geom::Curve const &curve_in) const |
519 | +{ |
520 | + if (A == 0 && inverse) { |
521 | + return 1; |
522 | + } |
523 | + if (A == 0 && !inverse) { |
524 | + return 0; |
525 | + } |
526 | + if (!inverse) { |
527 | + return timeAtArcLength(A, curve_in); |
528 | + } |
529 | + double length_part = curve_in.length(); |
530 | + A = length_part - A; |
531 | + return timeAtArcLength(A, curve_in); |
532 | +} |
533 | + |
534 | +///Get the length of the satellite in curve_in |
535 | +double Satellite::arcDistance(Geom::Curve const &curve_in) const |
536 | +{ |
537 | + double s = amount; |
538 | + if (is_time) { |
539 | + s = arcLengthAt(s, curve_in); |
540 | + } |
541 | + return s; |
542 | +} |
543 | + |
544 | +///Get the point position of the satellite |
545 | +Geom::Point Satellite::getPosition(Geom::Curve const &curve_in, bool inverse) const |
546 | +{ |
547 | + double t = time(curve_in, inverse); |
548 | + return curve_in.pointAt(t); |
549 | +} |
550 | + |
551 | +///Set the position of the satellite from a gived point P |
552 | +void Satellite::setPosition(Geom::Point const p, Geom::Curve const &curve_in, bool inverse) |
553 | +{ |
554 | + Geom::Curve * curve = const_cast<Geom::Curve *>(&curve_in); |
555 | + if (inverse) { |
556 | + curve = curve->reverse(); |
557 | + } |
558 | + double A = Geom::nearest_time(p, *curve); |
559 | + if (!is_time) { |
560 | + A = arcLengthAt(A, *curve); |
561 | + } |
562 | + amount = A; |
563 | +} |
564 | + |
565 | + |
566 | +///Map a satellite type with gchar |
567 | +void Satellite::setSatelliteType(gchar const *A) |
568 | +{ |
569 | + std::map<std::string, SatelliteType> gchar_map_to_satellite_type = |
570 | + boost::assign::map_list_of("F", FILLET)("IF", INVERSE_FILLET)("C", CHAMFER)("IC", INVERSE_CHAMFER)("KO", INVALID_SATELLITE); |
571 | + std::map<std::string, SatelliteType>::iterator it = gchar_map_to_satellite_type.find(std::string(A)); |
572 | + if (it != gchar_map_to_satellite_type.end()) { |
573 | + satellite_type = it->second; |
574 | + } |
575 | +} |
576 | + |
577 | +///Map a gchar with satelliteType |
578 | +gchar const *Satellite::getSatelliteTypeGchar() const |
579 | +{ |
580 | + std::map<SatelliteType, gchar const *> satellite_type_to_gchar_map = |
581 | + boost::assign::map_list_of(FILLET, "F")(INVERSE_FILLET, "IF")(CHAMFER, "C")(INVERSE_CHAMFER, "IC")(INVALID_SATELLITE, "KO"); |
582 | + return satellite_type_to_gchar_map.at(satellite_type); |
583 | +} |
584 | + |
585 | +/* |
586 | + Local Variables: |
587 | + mode:c++ |
588 | + c-file-style:"stroustrup" |
589 | + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) |
590 | + indent-tabs-mode:nil |
591 | + fill-column:99 |
592 | + End: |
593 | +*/ |
594 | +// vim: |
595 | +// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 |
596 | +// : |
597 | |
598 | === added file 'src/helper/geom-satellite.h' |
599 | --- src/helper/geom-satellite.h 1970-01-01 00:00:00 +0000 |
600 | +++ src/helper/geom-satellite.h 2017-05-06 17:46:29 +0000 |
601 | @@ -0,0 +1,110 @@ |
602 | +/** |
603 | + * \file |
604 | + * \brief Satellite a per node holder of data. |
605 | + */ /* |
606 | + * Authors: |
607 | + * 2015 Jabier Arraiza Cenoz<jabier.arraiza@marker.es> |
608 | + * |
609 | + * This code is in public domain |
610 | + */ |
611 | + |
612 | +#ifndef SEEN_SATELLITE_H |
613 | +#define SEEN_SATELLITE_H |
614 | + |
615 | +#include <map> |
616 | +#include <boost/assign.hpp> |
617 | +#include <2geom/sbasis-geometric.h> |
618 | +#include "util/enums.h" |
619 | + |
620 | + |
621 | +enum SatelliteType { |
622 | + FILLET = 0, //Fillet |
623 | + INVERSE_FILLET, //Inverse Fillet |
624 | + CHAMFER, //Chamfer |
625 | + INVERSE_CHAMFER, //Inverse Chamfer |
626 | + INVALID_SATELLITE // Invalid Satellite |
627 | +}; |
628 | +/** |
629 | + * @brief Satellite a per node holder of data. |
630 | + */ |
631 | + |
632 | +class Satellite { |
633 | +public: |
634 | + |
635 | + Satellite(); |
636 | + Satellite(SatelliteType satellite_type); |
637 | + |
638 | + virtual ~Satellite(); |
639 | + void setIsTime(bool set_is_time) |
640 | + { |
641 | + is_time = set_is_time; |
642 | + } |
643 | + void setSelected(bool set_selected) |
644 | + { |
645 | + selected = set_selected; |
646 | + } |
647 | + void setHasMirror(bool set_has_mirror) |
648 | + { |
649 | + has_mirror = set_has_mirror; |
650 | + } |
651 | + void setHidden(bool set_hidden) |
652 | + { |
653 | + hidden = set_hidden; |
654 | + } |
655 | + void setAmount(bool set_amount) |
656 | + { |
657 | + amount = set_amount; |
658 | + } |
659 | + void setAngle(bool set_angle) |
660 | + { |
661 | + angle = set_angle; |
662 | + } |
663 | + void setSteps(bool set_steps) |
664 | + { |
665 | + steps = set_steps; |
666 | + } |
667 | + double lenToRad(double const A, Geom::Curve const &curve_in, |
668 | + Geom::Curve const &curve_out, |
669 | + Satellite const previousSatellite) const; |
670 | + double radToLen(double const A, Geom::Curve const &curve_in, |
671 | + Geom::Curve const &curve_out) const; |
672 | + |
673 | + double time(Geom::Curve const &curve_in, bool inverse = false) const; |
674 | + double time(double A, bool inverse, Geom::Curve const &curve_in) const; |
675 | + double arcDistance(Geom::Curve const &curve_in) const; |
676 | + |
677 | + void setPosition(Geom::Point const p, Geom::Curve const &curve_in, bool inverse = false); |
678 | + Geom::Point getPosition(Geom::Curve const &curve_in, bool inverse = false) const; |
679 | + |
680 | + void setSatelliteType(gchar const *A); |
681 | + gchar const *getSatelliteTypeGchar() const; |
682 | + SatelliteType satellite_type; |
683 | + //The value stored could be a time value of the satellite in the curve or a lenght of distance to the node from the satellite |
684 | + //"is_time" tell is if is a time or lenght value |
685 | + bool is_time; |
686 | + bool selected; |
687 | + bool has_mirror; |
688 | + bool hidden; |
689 | + //in "amount" we store the time or distance used in the satellite |
690 | + double amount; |
691 | + double angle; |
692 | + size_t steps; |
693 | +}; |
694 | + |
695 | +double timeAtArcLength(double const A, Geom::Curve const &curve_in); |
696 | +double arcLengthAt(double const A, Geom::Curve const &curve_in); |
697 | + |
698 | +#endif // SEEN_SATELLITE_H |
699 | + |
700 | +/* |
701 | + Local Variables: |
702 | + mode:c++ |
703 | + c-file-style:"stroustrup" |
704 | + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) |
705 | + indent-tabs-mode:nil |
706 | + fill-column:99 |
707 | + End: |
708 | +*/ |
709 | +// vim: |
710 | +// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 |
711 | +// : |
712 | |
713 | === modified file 'src/knotholder.h' |
714 | --- src/knotholder.h 2016-07-30 17:04:34 +0000 |
715 | +++ src/knotholder.h 2017-05-06 17:46:29 +0000 |
716 | @@ -30,7 +30,8 @@ |
717 | } |
718 | namespace LivePathEffect { |
719 | class PowerStrokePointArrayParamKnotHolderEntity; |
720 | -class FilletPointArrayParamKnotHolderEntity; |
721 | +class SatellitesArrayParam; |
722 | +class FilletChamferKnotHolderEntity; |
723 | } |
724 | } |
725 | |
726 | @@ -63,7 +64,7 @@ |
727 | |
728 | friend class Inkscape::UI::ShapeEditor; // FIXME why? |
729 | friend class Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity; // why? |
730 | - friend class Inkscape::LivePathEffect::FilletPointArrayParamKnotHolderEntity; // why? |
731 | + friend class Inkscape::LivePathEffect::FilletChamferKnotHolderEntity; // why? |
732 | |
733 | protected: |
734 | |
735 | |
736 | === modified file 'src/live_effects/CMakeLists.txt' |
737 | --- src/live_effects/CMakeLists.txt 2017-01-24 09:44:10 +0000 |
738 | +++ src/live_effects/CMakeLists.txt 2017-05-06 17:46:29 +0000 |
739 | @@ -59,7 +59,6 @@ |
740 | |
741 | parameter/array.cpp |
742 | parameter/bool.cpp |
743 | - parameter/filletchamferpointarray.cpp |
744 | parameter/item-reference.cpp |
745 | parameter/item.cpp |
746 | parameter/originalitem.cpp |
747 | @@ -70,6 +69,7 @@ |
748 | parameter/path.cpp |
749 | parameter/point.cpp |
750 | parameter/powerstrokepointarray.cpp |
751 | + parameter/satellitesarray.cpp |
752 | parameter/random.cpp |
753 | parameter/text.cpp |
754 | parameter/fontbutton.cpp |
755 | @@ -144,7 +144,6 @@ |
756 | parameter/array.h |
757 | parameter/bool.h |
758 | parameter/enum.h |
759 | - parameter/filletchamferpointarray.h |
760 | parameter/item.h |
761 | parameter/item-reference.h |
762 | parameter/originalitem.h |
763 | @@ -155,6 +154,7 @@ |
764 | parameter/path.h |
765 | parameter/point.h |
766 | parameter/powerstrokepointarray.h |
767 | + parameter/satellitesarray.h |
768 | parameter/random.h |
769 | parameter/text.h |
770 | parameter/fontbutton.h |
771 | |
772 | === modified file 'src/live_effects/effect.cpp' |
773 | --- src/live_effects/effect.cpp 2017-05-05 14:45:16 +0000 |
774 | +++ src/live_effects/effect.cpp 2017-05-06 17:46:29 +0000 |
775 | @@ -101,7 +101,6 @@ |
776 | {RECURSIVE_SKELETON, N_("Recursive skeleton"), "recursive_skeleton"}, |
777 | {TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"}, |
778 | {TEXT_LABEL, N_("Text label"), "text_label"}, |
779 | - {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet_chamfer"}, |
780 | #endif |
781 | /* 0.46 */ |
782 | {BEND_PATH, N_("Bend"), "bend_path"}, |
783 | @@ -142,6 +141,7 @@ |
784 | {BOUNDING_BOX, N_("Bounding Box"), "bounding_box"}, |
785 | /* 9.93 */ |
786 | {MEASURE_LINE, N_("Measure Line"), "measure_line"}, |
787 | + {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet_chamfer"}, |
788 | }; |
789 | const Util::EnumDataConverter<EffectType> LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData)); |
790 | |
791 | |
792 | === modified file 'src/live_effects/lpe-fillet-chamfer.cpp' |
793 | --- src/live_effects/lpe-fillet-chamfer.cpp 2017-04-28 19:42:36 +0000 |
794 | +++ src/live_effects/lpe-fillet-chamfer.cpp 2017-05-06 17:46:29 +0000 |
795 | @@ -4,86 +4,131 @@ |
796 | * |
797 | * Copyright (C) 2014 Author(s) |
798 | * |
799 | - * Special thanks to Johan Engelen for the base of the effect -powerstroke- |
800 | - * Also to ScislaC for point me to the idea |
801 | - * Also su_v for his construvtive feedback and time |
802 | - * Also to Mc- (IRC nick) for his important contribution to find real time |
803 | - * values based on |
804 | - * and finaly to Liam P. White for his big help on coding, that save me a lot of hours |
805 | * |
806 | * Released under GNU GPL, read the file 'COPYING' for more information |
807 | */ |
808 | + |
809 | #include "live_effects/lpe-fillet-chamfer.h" |
810 | - |
811 | -#include <2geom/sbasis-to-bezier.h> |
812 | -#include <2geom/elliptical-arc.h> |
813 | - |
814 | +#include "helper/geom.h" |
815 | #include "display/curve.h" |
816 | -#include "helper/geom-nodetype.h" |
817 | #include "helper/geom-curves.h" |
818 | -#include "helper/geom.h" |
819 | +#include "helper/geom-satellite.h" |
820 | +#include <2geom/elliptical-arc.h> |
821 | +#include "knotholder.h" |
822 | +#include <boost/optional.hpp> |
823 | |
824 | -// for programmatically updating knots |
825 | -#include "ui/tools-switch.h" |
826 | // TODO due to internal breakage in glibmm headers, this must be last: |
827 | #include <glibmm/i18n.h> |
828 | |
829 | -using namespace Geom; |
830 | namespace Inkscape { |
831 | namespace LivePathEffect { |
832 | |
833 | -static const Util::EnumData<FilletMethod> FilletMethodData[FM_END] = { |
834 | - { FM_AUTO, N_("Auto"), "auto" }, |
835 | +static const Util::EnumData<Filletmethod> FilletmethodData[] = { |
836 | + { FM_AUTO, N_("Auto"), "auto" }, |
837 | { FM_ARC, N_("Force arc"), "arc" }, |
838 | { FM_BEZIER, N_("Force bezier"), "bezier" } |
839 | }; |
840 | -static const Util::EnumDataConverter<FilletMethod> |
841 | -FMConverter(FilletMethodData, FM_END); |
842 | - |
843 | -const double tolerance = 0.001; |
844 | -const double gapHelper = 0.00001; |
845 | - |
846 | -LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) : |
847 | - Effect(lpeobject), |
848 | - fillet_chamfer_values(_("Fillet point"), _("Fillet point"), "fillet_chamfer_values", &wr, this), |
849 | - hide_knots(_("Hide knots"), _("Hide knots"), "hide_knots", &wr, this, false), |
850 | - ignore_radius_0(_("Ignore 0 radius knots"), _("Ignore 0 radius knots"), "ignore_radius_0", &wr, this, false), |
851 | - only_selected(_("Change only selected nodes"), _("Change only selected nodes"), "only_selected", &wr, this, false), |
852 | - flexible(_("Flexible radius size (%)"), _("Flexible radius size (%)"), "flexible", &wr, this, false), |
853 | - use_knot_distance(_("Use knots distance instead radius"), _("Use knots distance instead radius"), "use_knot_distance", &wr, this, false), |
854 | - method(_("Method:"), _("Fillets methods"), "method", FMConverter, &wr, this, FM_AUTO), |
855 | - radius(_("Radius (unit or %):"), _("Radius, in unit or %"), "radius", &wr, this, 0.), |
856 | - chamfer_steps(_("Chamfer steps:"), _("Chamfer steps"), "chamfer_steps", &wr, this, 0), |
857 | - |
858 | - helper_size(_("Helper size with direction:"), _("Helper size with direction"), "helper_size", &wr, this, 0) |
859 | +static const Util::EnumDataConverter<Filletmethod> FMConverter(FilletmethodData, FM_END); |
860 | + |
861 | +LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) |
862 | + : Effect(lpeobject), |
863 | + unit(_("Unit"), _("Unit"), "unit", &wr, this, "px"), |
864 | + satellites_param("Satellites_param", "Satellites_param", |
865 | + "satellites_param", &wr, this), |
866 | + method(_("Method:"), _("Methods to calculate the fillet or chamfer"), |
867 | + "method", FMConverter, &wr, this, FM_AUTO), |
868 | + radius(_("Radius (unit or %):"), _("Radius, in unit or %"), "radius", &wr, |
869 | + this, 0.0), |
870 | + chamfer_steps(_("Chamfer steps:"), _("Chamfer steps"), "chamfer_steps", |
871 | + &wr, this, 1), |
872 | + flexible(_("Flexible radius size (%)"), _("Flexible radius size (%)"), |
873 | + "flexible", &wr, this, false), |
874 | + mirror_knots(_("Mirror Knots"), _("Mirror Knots"), "mirror_knots", &wr, |
875 | + this, true), |
876 | + only_selected(_("Change only selected nodes"), |
877 | + _("Change only selected nodes"), "only_selected", &wr, this, |
878 | + false), |
879 | + use_knot_distance(_("Use knots distance instead radius"), |
880 | + _("Use knots distance instead radius"), |
881 | + "use_knot_distance", &wr, this, false), |
882 | + hide_knots(_("Hide knots"), _("Hide knots"), "hide_knots", &wr, this, |
883 | + false), |
884 | + apply_no_radius(_("Apply changes if radius = 0"), _("Apply changes if radius = 0"), "apply_no_radius", &wr, this, true), |
885 | + apply_with_radius(_("Apply changes if radius > 0"), _("Apply changes if radius > 0"), "apply_with_radius", &wr, this, true), |
886 | + helper_size(_("Helper path size with direction to node:"), |
887 | + _("Helper path size with direction to node"), "helper_size", &wr, this, 0), |
888 | + _pathvector_satellites(NULL), |
889 | + _degenerate_hide(false) |
890 | { |
891 | - registerParameter(&fillet_chamfer_values); |
892 | + registerParameter(&satellites_param); |
893 | + registerParameter(&unit); |
894 | registerParameter(&method); |
895 | registerParameter(&radius); |
896 | registerParameter(&chamfer_steps); |
897 | registerParameter(&helper_size); |
898 | registerParameter(&flexible); |
899 | registerParameter(&use_knot_distance); |
900 | - registerParameter(&ignore_radius_0); |
901 | + registerParameter(&mirror_knots); |
902 | + registerParameter(&apply_no_radius); |
903 | + registerParameter(&apply_with_radius); |
904 | registerParameter(&only_selected); |
905 | registerParameter(&hide_knots); |
906 | |
907 | - radius.param_set_range(0., infinity()); |
908 | + radius.param_set_range(0.0, Geom::infinity()); |
909 | radius.param_set_increments(1, 1); |
910 | radius.param_set_digits(4); |
911 | radius.param_overwrite_widget(true); |
912 | chamfer_steps.param_set_range(1, 999); |
913 | chamfer_steps.param_set_increments(1, 1); |
914 | chamfer_steps.param_set_digits(0); |
915 | - chamfer_steps.param_overwrite_widget(true); |
916 | - helper_size.param_set_range(0, infinity()); |
917 | + helper_size.param_set_range(0, 999); |
918 | helper_size.param_set_increments(5, 5); |
919 | helper_size.param_set_digits(0); |
920 | - helper_size.param_overwrite_widget(true); |
921 | - fillet_chamfer_values.set_chamfer_steps(3); |
922 | + _provides_knotholder_entities = true; |
923 | } |
924 | |
925 | -LPEFilletChamfer::~LPEFilletChamfer() {} |
926 | +void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem) |
927 | +{ |
928 | + SPLPEItem *splpeitem = const_cast<SPLPEItem *>(lpeItem); |
929 | + SPShape *shape = dynamic_cast<SPShape *>(splpeitem); |
930 | + if (shape) { |
931 | + Geom::PathVector const pathv = pathv_to_linear_and_cubic_beziers(shape->getCurve()->get_pathvector()); |
932 | + Satellites satellites; |
933 | + for (Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { |
934 | + if (path_it->empty()) { |
935 | + continue; |
936 | + } |
937 | + std::vector<Satellite> subpath_satellites; |
938 | + for (Geom::Path::const_iterator curve_it = path_it->begin(); curve_it != path_it->end(); ++curve_it) { |
939 | + //Maybe we want this satellites... |
940 | + //if (curve_it->isDegenerate()) { |
941 | + // continue |
942 | + //} |
943 | + Satellite satellite(FILLET); |
944 | + satellite.setSteps(chamfer_steps); |
945 | + subpath_satellites.push_back(satellite); |
946 | + } |
947 | + //we add the last satellite on open path because _pathvector_satellites is related to nodes, not curves |
948 | + //so maybe in the future we can need this last satellite in other effects |
949 | + //dont remove for this effect because _pathvector_satellites class has methods when the path is modiffied |
950 | + //and we want one method for all uses |
951 | + if (!path_it->closed()) { |
952 | + Satellite satellite(FILLET); |
953 | + satellite.setSteps(chamfer_steps); |
954 | + subpath_satellites.push_back(satellite); |
955 | + } |
956 | + satellites.push_back(subpath_satellites); |
957 | + } |
958 | + _pathvector_satellites = new PathVectorSatellites(); |
959 | + _pathvector_satellites->setPathVector(pathv); |
960 | + _pathvector_satellites->setSatellites(satellites); |
961 | + satellites_param.setPathVectorSatellites(_pathvector_satellites); |
962 | + } else { |
963 | + g_warning("LPE Fillet/Chamfer can only be applied to shapes (not groups)."); |
964 | + SPLPEItem *item = const_cast<SPLPEItem *>(lpeItem); |
965 | + item->removeCurrentPathEffect(false); |
966 | + } |
967 | +} |
968 | |
969 | Gtk::Widget *LPEFilletChamfer::newWidget() |
970 | { |
971 | @@ -94,54 +139,50 @@ |
972 | vbox->set_border_width(5); |
973 | vbox->set_homogeneous(false); |
974 | vbox->set_spacing(2); |
975 | - Gtk::HBox *advertaising = Gtk::manage(new Gtk::HBox(true, 0)); |
976 | - Gtk::Button *advert = Gtk::manage(new Gtk::Button(Glib::ustring(_("IMPORTANT! New version soon...")))); |
977 | - advertaising->pack_start(*advert, true, true, 2); |
978 | - vbox->pack_start(*advertaising, true, true, 2); |
979 | - Gtk::HBox *advertaising2 = Gtk::manage(new Gtk::HBox(true, 0)); |
980 | - Gtk::Button *advert2 = Gtk::manage(new Gtk::Button(Glib::ustring(_("Not compatible. Convert to path after.")))); |
981 | - advertaising2->pack_start(*advert2, true, true, 2); |
982 | - vbox->pack_start(*advertaising2, true, true, 2); |
983 | std::vector<Parameter *>::iterator it = param_vector.begin(); |
984 | while (it != param_vector.end()) { |
985 | if ((*it)->widget_is_visible) { |
986 | Parameter *param = *it; |
987 | Gtk::Widget *widg = param->param_newWidget(); |
988 | if (param->param_key == "radius") { |
989 | - Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg)); |
990 | - widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::updateFillet)); |
991 | - widg = widgRegistered; |
992 | + Inkscape::UI::Widget::Scalar *widg_registered = |
993 | + Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg)); |
994 | + widg_registered->signal_value_changed().connect( |
995 | + sigc::mem_fun(*this, &LPEFilletChamfer::updateAmount)); |
996 | + widg = widg_registered; |
997 | if (widg) { |
998 | - Gtk::HBox *scalarParameter = dynamic_cast<Gtk::HBox *>(widg); |
999 | - std::vector<Gtk::Widget *> childList = scalarParameter->get_children(); |
1000 | - Gtk::Entry *entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]); |
1001 | - entryWidg->set_width_chars(6); |
1002 | + Gtk::HBox *scalar_parameter = dynamic_cast<Gtk::HBox *>(widg); |
1003 | + std::vector<Gtk::Widget *> childList = scalar_parameter->get_children(); |
1004 | + Gtk::Entry *entry_widget = dynamic_cast<Gtk::Entry *>(childList[1]); |
1005 | + entry_widget->set_width_chars(6); |
1006 | } |
1007 | +// } else if (param->param_key == "unit") { |
1008 | +// Inkscape::UI::Widget::RegisteredUnitMenu* widg_registered = |
1009 | +// Gtk::manage(dynamic_cast< Inkscape::UI::Widget::RegisteredUnitMenu *>(widg)); |
1010 | +// widg_registered->setUnit(unit.get_abbreviation()); |
1011 | +// widg_registered->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change unit parameter")); |
1012 | +// widg_registered->getUnitMenu()->signal_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::convertUnit)); |
1013 | +// widg = widg_registered; |
1014 | } else if (param->param_key == "chamfer_steps") { |
1015 | - Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg)); |
1016 | - widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamferSubdivisions)); |
1017 | - widg = widgRegistered; |
1018 | + Inkscape::UI::Widget::Scalar *widg_registered = |
1019 | + Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg)); |
1020 | + widg_registered->signal_value_changed().connect( |
1021 | + sigc::mem_fun(*this, &LPEFilletChamfer::updateChamferSteps)); |
1022 | + widg = widg_registered; |
1023 | if (widg) { |
1024 | - Gtk::HBox *scalarParameter = dynamic_cast<Gtk::HBox *>(widg); |
1025 | - std::vector<Gtk::Widget *> childList = scalarParameter->get_children(); |
1026 | - Gtk::Entry *entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]); |
1027 | - entryWidg->set_width_chars(3); |
1028 | + Gtk::HBox *scalar_parameter = dynamic_cast<Gtk::HBox *>(widg); |
1029 | + std::vector<Gtk::Widget *> childList = scalar_parameter->get_children(); |
1030 | + Gtk::Entry *entry_widget = dynamic_cast<Gtk::Entry *>(childList[1]); |
1031 | + entry_widget->set_width_chars(3); |
1032 | } |
1033 | - } else if (param->param_key == "flexible") { |
1034 | - Gtk::CheckButton *widgRegistered = Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg)); |
1035 | - widgRegistered->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::toggleFlexFixed)); |
1036 | } else if (param->param_key == "helper_size") { |
1037 | - Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg)); |
1038 | - widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::refreshKnots)); |
1039 | - } else if (param->param_key == "hide_knots") { |
1040 | - Gtk::CheckButton *widgRegistered = Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg)); |
1041 | - widgRegistered->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::toggleHide)); |
1042 | + Inkscape::UI::Widget::Scalar *widg_registered = |
1043 | + Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg)); |
1044 | + widg_registered->signal_value_changed().connect( |
1045 | + sigc::mem_fun(*this, &LPEFilletChamfer::refreshKnots)); |
1046 | } else if (param->param_key == "only_selected") { |
1047 | Gtk::manage(widg); |
1048 | - } else if (param->param_key == "ignore_radius_0") { |
1049 | - Gtk::manage(widg); |
1050 | } |
1051 | - |
1052 | Glib::ustring *tip = param->param_getTooltip(); |
1053 | if (widg) { |
1054 | vbox->pack_start(*widg, true, true, 2); |
1055 | @@ -153,504 +194,386 @@ |
1056 | } |
1057 | } |
1058 | } |
1059 | - |
1060 | ++it; |
1061 | } |
1062 | - Gtk::HBox *filletContainer = Gtk::manage(new Gtk::HBox(true, 0)); |
1063 | - Gtk::Button *fillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Fillet")))); |
1064 | - fillet->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::fillet)); |
1065 | - |
1066 | - filletContainer->pack_start(*fillet, true, true, 2); |
1067 | - Gtk::Button *inverseFillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse fillet")))); |
1068 | - inverseFillet->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::inverseFillet)); |
1069 | - filletContainer->pack_start(*inverseFillet, true, true, 2); |
1070 | - |
1071 | - Gtk::HBox *chamferContainer = Gtk::manage(new Gtk::HBox(true, 0)); |
1072 | + |
1073 | + Gtk::HBox *fillet_container = Gtk::manage(new Gtk::HBox(true, 0)); |
1074 | + Gtk::Button *fillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Fillet")))); |
1075 | + fillet->signal_clicked() |
1076 | + .connect(sigc::bind<SatelliteType>(sigc::mem_fun(*this, &LPEFilletChamfer::updateSatelliteType),FILLET)); |
1077 | + |
1078 | + fillet_container->pack_start(*fillet, true, true, 2); |
1079 | + Gtk::Button *inverse_fillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse fillet")))); |
1080 | + inverse_fillet->signal_clicked() |
1081 | + .connect(sigc::bind<SatelliteType>(sigc::mem_fun(*this, &LPEFilletChamfer::updateSatelliteType),INVERSE_FILLET)); |
1082 | + fillet_container->pack_start(*inverse_fillet, true, true, 2); |
1083 | + |
1084 | + Gtk::HBox *chamfer_container = Gtk::manage(new Gtk::HBox(true, 0)); |
1085 | Gtk::Button *chamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Chamfer")))); |
1086 | - chamfer->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamfer)); |
1087 | - |
1088 | - chamferContainer->pack_start(*chamfer, true, true, 2); |
1089 | - Gtk::Button *inverseChamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse chamfer")))); |
1090 | - inverseChamfer->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::inverseChamfer)); |
1091 | - chamferContainer->pack_start(*inverseChamfer, true, true, 2); |
1092 | - |
1093 | - vbox->pack_start(*filletContainer, true, true, 2); |
1094 | - vbox->pack_start(*chamferContainer, true, true, 2); |
1095 | + chamfer->signal_clicked() |
1096 | + .connect(sigc::bind<SatelliteType>(sigc::mem_fun(*this, &LPEFilletChamfer::updateSatelliteType),CHAMFER)); |
1097 | + |
1098 | + chamfer_container->pack_start(*chamfer, true, true, 2); |
1099 | + Gtk::Button *inverse_chamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse chamfer")))); |
1100 | + inverse_chamfer->signal_clicked() |
1101 | + .connect(sigc::bind<SatelliteType>(sigc::mem_fun(*this, &LPEFilletChamfer::updateSatelliteType),INVERSE_CHAMFER)); |
1102 | + chamfer_container->pack_start(*inverse_chamfer, true, true, 2); |
1103 | + |
1104 | + vbox->pack_start(*fillet_container, true, true, 2); |
1105 | + vbox->pack_start(*chamfer_container, true, true, 2); |
1106 | |
1107 | return vbox; |
1108 | } |
1109 | |
1110 | -void LPEFilletChamfer::toggleHide() |
1111 | -{ |
1112 | - std::vector<Point> filletChamferData = fillet_chamfer_values.data(); |
1113 | - std::vector<Geom::Point> result; |
1114 | - for (std::vector<Point>::const_iterator point_it = filletChamferData.begin(); |
1115 | - point_it != filletChamferData.end(); ++point_it) { |
1116 | - if (hide_knots) { |
1117 | - result.push_back(Point((*point_it)[X], std::abs((*point_it)[Y]) * -1)); |
1118 | - } else { |
1119 | - result.push_back(Point((*point_it)[X], std::abs((*point_it)[Y]))); |
1120 | - } |
1121 | - } |
1122 | - fillet_chamfer_values.param_set_and_write_new_value(result); |
1123 | - refreshKnots(); |
1124 | -} |
1125 | - |
1126 | -void LPEFilletChamfer::toggleFlexFixed() |
1127 | -{ |
1128 | - std::vector<Point> filletChamferData = fillet_chamfer_values.data(); |
1129 | - std::vector<Geom::Point> result; |
1130 | - unsigned int i = 0; |
1131 | - for (std::vector<Point>::const_iterator point_it = filletChamferData.begin(); |
1132 | - point_it != filletChamferData.end(); ++point_it) { |
1133 | - if (flexible) { |
1134 | - result.push_back(Point(fillet_chamfer_values.to_time(i, (*point_it)[X]), |
1135 | - (*point_it)[Y])); |
1136 | - } else { |
1137 | - result.push_back(Point(fillet_chamfer_values.to_len(i, (*point_it)[X]), |
1138 | - (*point_it)[Y])); |
1139 | - } |
1140 | - i++; |
1141 | - } |
1142 | - if (flexible) { |
1143 | - radius.param_set_range(0., 100); |
1144 | - radius.param_set_value(0); |
1145 | - } else { |
1146 | - radius.param_set_range(0., infinity()); |
1147 | - radius.param_set_value(0); |
1148 | - } |
1149 | - fillet_chamfer_values.param_set_and_write_new_value(result); |
1150 | -} |
1151 | - |
1152 | -void LPEFilletChamfer::updateFillet() |
1153 | -{ |
1154 | - double power = 0; |
1155 | +void LPEFilletChamfer::refreshKnots() |
1156 | +{ |
1157 | + if (satellites_param._knoth) { |
1158 | + satellites_param._knoth->update_knots(); |
1159 | + } |
1160 | +} |
1161 | + |
1162 | +void LPEFilletChamfer::updateAmount() |
1163 | +{ |
1164 | + setSelected(_pathvector_satellites); |
1165 | + double power = radius; |
1166 | if (!flexible) { |
1167 | - power = radius * -1; |
1168 | - } else { |
1169 | - power = radius; |
1170 | - } |
1171 | - Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); |
1172 | - doUpdateFillet(path_from_piecewise(pwd2, tolerance), power); |
1173 | - DocumentUndo::done(getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change scalar parameter")); |
1174 | -} |
1175 | - |
1176 | -void LPEFilletChamfer::fillet() |
1177 | -{ |
1178 | - Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); |
1179 | - doChangeType(path_from_piecewise(pwd2, tolerance), 1); |
1180 | - DocumentUndo::done(getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Convert to fillet")); |
1181 | -} |
1182 | - |
1183 | -void LPEFilletChamfer::inverseFillet() |
1184 | -{ |
1185 | - Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); |
1186 | - doChangeType(path_from_piecewise(pwd2, tolerance), 2); |
1187 | - DocumentUndo::done(getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Convert to inverse fillet")); |
1188 | -} |
1189 | - |
1190 | -void LPEFilletChamfer::chamferSubdivisions() |
1191 | -{ |
1192 | - fillet_chamfer_values.set_chamfer_steps(chamfer_steps); |
1193 | - Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); |
1194 | - doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 5000); |
1195 | - DocumentUndo::done(getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change scalar parameter")); |
1196 | -} |
1197 | - |
1198 | -void LPEFilletChamfer::chamfer() |
1199 | -{ |
1200 | - fillet_chamfer_values.set_chamfer_steps(chamfer_steps); |
1201 | - Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); |
1202 | - doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 3000); |
1203 | - DocumentUndo::done(getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Convert to chamfer")); |
1204 | -} |
1205 | - |
1206 | -void LPEFilletChamfer::inverseChamfer() |
1207 | -{ |
1208 | - fillet_chamfer_values.set_chamfer_steps(chamfer_steps); |
1209 | - Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); |
1210 | - doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 4000); |
1211 | - DocumentUndo::done(getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Convert to inverse fillet")); |
1212 | -} |
1213 | - |
1214 | -void LPEFilletChamfer::refreshKnots() |
1215 | -{ |
1216 | - Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2(); |
1217 | - fillet_chamfer_values.recalculate_knots(pwd2); |
1218 | - SPDesktop *desktop = SP_ACTIVE_DESKTOP; |
1219 | - if (tools_isactive(desktop, TOOLS_NODES)) { |
1220 | - tools_switch(desktop, TOOLS_SELECT); |
1221 | - tools_switch(desktop, TOOLS_NODES); |
1222 | - } |
1223 | - DocumentUndo::done(getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Knots and helper paths refreshed")); |
1224 | -} |
1225 | - |
1226 | -void LPEFilletChamfer::doUpdateFillet(Geom::PathVector const &original_pathv, double power) |
1227 | -{ |
1228 | - std::vector<Point> filletChamferData = fillet_chamfer_values.data(); |
1229 | - std::vector<Geom::Point> result; |
1230 | - Geom::PathVector original_pathv_processed = pathv_to_linear_and_cubic_beziers(original_pathv); |
1231 | - int counter = 0; |
1232 | - for (PathVector::const_iterator path_it = original_pathv_processed.begin(); |
1233 | - path_it != original_pathv_processed.end(); ++path_it) { |
1234 | - if (path_it->empty()) |
1235 | - continue; |
1236 | - |
1237 | - Geom::Path::const_iterator curve_it1 = path_it->begin(); |
1238 | - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); |
1239 | - Geom::Path::const_iterator curve_endit = path_it->end_default(); |
1240 | - if (path_it->closed() && path_it->back_closed().isDegenerate()) { |
1241 | - const Curve &closingline = path_it->back_closed(); |
1242 | - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { |
1243 | - curve_endit = path_it->end_open(); |
1244 | - } |
1245 | - } |
1246 | - double powerend = 0; |
1247 | - while (curve_it1 != curve_endit) { |
1248 | - powerend = power; |
1249 | - if (power < 0 && !use_knot_distance) { |
1250 | - powerend = fillet_chamfer_values.rad_to_len(counter,powerend); |
1251 | - } |
1252 | - if (power > 0) { |
1253 | - powerend = counter + (power / 100); |
1254 | - } |
1255 | - if (ignore_radius_0 && (filletChamferData[counter][X] == 0 || |
1256 | - filletChamferData[counter][X] == counter)) { |
1257 | - powerend = filletChamferData[counter][X]; |
1258 | - } |
1259 | - if (filletChamferData[counter][Y] == 0) { |
1260 | - powerend = filletChamferData[counter][X]; |
1261 | - } |
1262 | - if (only_selected && !isNodePointSelected(curve_it1->initialPoint())) { |
1263 | - powerend = filletChamferData[counter][X]; |
1264 | - } |
1265 | - result.push_back(Point(powerend, filletChamferData[counter][Y])); |
1266 | - ++curve_it1; |
1267 | - ++curve_it2; |
1268 | - counter++; |
1269 | - } |
1270 | - } |
1271 | - fillet_chamfer_values.param_set_and_write_new_value(result); |
1272 | -} |
1273 | - |
1274 | -void LPEFilletChamfer::doChangeType(Geom::PathVector const &original_pathv, int type) |
1275 | -{ |
1276 | - std::vector<Point> filletChamferData = fillet_chamfer_values.data(); |
1277 | - std::vector<Geom::Point> result; |
1278 | - Geom::PathVector original_pathv_processed = pathv_to_linear_and_cubic_beziers(original_pathv); |
1279 | - int counter = 0; |
1280 | - for (PathVector::const_iterator path_it = original_pathv_processed.begin(); path_it != original_pathv_processed.end(); ++path_it) { |
1281 | - int pathCounter = 0; |
1282 | - if (path_it->empty()) |
1283 | - continue; |
1284 | - |
1285 | - Geom::Path::const_iterator curve_it1 = path_it->begin(); |
1286 | - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); |
1287 | - Geom::Path::const_iterator curve_endit = path_it->end_default(); |
1288 | - if (path_it->closed() && path_it->back_closed().isDegenerate()) { |
1289 | - const Curve &closingline = path_it->back_closed(); |
1290 | - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { |
1291 | - curve_endit = path_it->end_open(); |
1292 | - } |
1293 | - } |
1294 | - while (curve_it1 != curve_endit) { |
1295 | - bool toggle = true; |
1296 | - if (filletChamferData[counter][Y] == 0 || |
1297 | - (ignore_radius_0 && (filletChamferData[counter][X] == 0 || |
1298 | - filletChamferData[counter][X] == counter)) || |
1299 | - (only_selected && !isNodePointSelected(curve_it1->initialPoint()))) { |
1300 | - toggle = false; |
1301 | - } |
1302 | - if (toggle) { |
1303 | - if(type >= 5000){ |
1304 | - if(filletChamferData[counter][Y] >= 3000 && filletChamferData[counter][Y] < 4000){ |
1305 | - type = type - 2000; |
1306 | - } else if (filletChamferData[counter][Y] >= 4000 && filletChamferData[counter][Y] < 5000){ |
1307 | - type = type - 1000; |
1308 | - } |
1309 | - } |
1310 | - result.push_back(Point(filletChamferData[counter][X], type)); |
1311 | + SPDocument * document = SP_ACTIVE_DOCUMENT; |
1312 | + SPNamedView *nv = sp_document_namedview(document, NULL); |
1313 | + Glib::ustring display_unit = nv->display_units->abbr; |
1314 | + power = Inkscape::Util::Quantity::convert(power, unit.get_abbreviation(), display_unit.c_str()); |
1315 | + } |
1316 | + _pathvector_satellites->updateAmount(power, apply_no_radius, apply_with_radius, only_selected, |
1317 | + use_knot_distance, flexible); |
1318 | + satellites_param.setPathVectorSatellites(_pathvector_satellites); |
1319 | +} |
1320 | + |
1321 | +//void LPEFilletChamfer::convertUnit() |
1322 | +//{ |
1323 | +// SPDocument * document = SP_ACTIVE_DOCUMENT; |
1324 | +// SPNamedView *nv = sp_document_namedview(document, NULL); |
1325 | +// Glib::ustring display_unit = nv->display_units->abbr; |
1326 | +// _pathvector_satellites->convertUnit(unit.get_abbreviation(), display_unit, apply_no_radius, apply_with_radius); |
1327 | +// satellites_param.setPathVectorSatellites(_pathvector_satellites); |
1328 | +//} |
1329 | + |
1330 | +void LPEFilletChamfer::updateChamferSteps() |
1331 | +{ |
1332 | + setSelected(_pathvector_satellites); |
1333 | + _pathvector_satellites->updateSteps(chamfer_steps, apply_no_radius, apply_with_radius, only_selected); |
1334 | + satellites_param.setPathVectorSatellites(_pathvector_satellites); |
1335 | +} |
1336 | + |
1337 | +void LPEFilletChamfer::updateSatelliteType(SatelliteType satellitetype) |
1338 | +{ |
1339 | + setSelected(_pathvector_satellites); |
1340 | + _pathvector_satellites->updateSatelliteType(satellitetype, apply_no_radius, apply_with_radius, only_selected); |
1341 | + satellites_param.setPathVectorSatellites(_pathvector_satellites); |
1342 | +} |
1343 | + |
1344 | +void LPEFilletChamfer::setSelected(PathVectorSatellites *_pathvector_satellites){ |
1345 | + Geom::PathVector const pathv = _pathvector_satellites->getPathVector(); |
1346 | + Satellites satellites = _pathvector_satellites->getSatellites(); |
1347 | + for (size_t i = 0; i < satellites.size(); ++i) { |
1348 | + for (size_t j = 0; j < satellites[i].size(); ++j) { |
1349 | + Geom::Curve const &curve_in = pathv[i][j]; |
1350 | + if (only_selected && isNodePointSelected(curve_in.initialPoint()) ){ |
1351 | + satellites[i][j].setSelected(true); |
1352 | } else { |
1353 | - result.push_back(filletChamferData[counter]); |
1354 | - } |
1355 | - ++curve_it1; |
1356 | - if (curve_it2 != curve_endit) { |
1357 | - ++curve_it2; |
1358 | - } |
1359 | - counter++; |
1360 | - pathCounter++; |
1361 | - } |
1362 | - } |
1363 | - fillet_chamfer_values.param_set_and_write_new_value(result); |
1364 | -} |
1365 | - |
1366 | -void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem) |
1367 | -{ |
1368 | - if (SP_IS_SHAPE(lpeItem)) { |
1369 | - std::vector<Point> point; |
1370 | - PathVector const &original_pathv = pathv_to_linear_and_cubic_beziers(SP_SHAPE(lpeItem)->_curve->get_pathvector()); |
1371 | - Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(original_pathv); |
1372 | - for (PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { |
1373 | - if (path_it->empty()) |
1374 | - continue; |
1375 | - |
1376 | - Geom::Path::const_iterator curve_it1 = path_it->begin(); |
1377 | - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); |
1378 | - Geom::Path::const_iterator curve_endit = path_it->end_default(); |
1379 | - if (path_it->closed()) { |
1380 | - const Geom::Curve &closingline = path_it->back_closed(); |
1381 | - // the closing line segment is always of type |
1382 | - // Geom::LineSegment. |
1383 | - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { |
1384 | - // closingline.isDegenerate() did not work, because it only checks for |
1385 | - // *exact* zero length, which goes wrong for relative coordinates and |
1386 | - // rounding errors... |
1387 | - // the closing line segment has zero-length. So stop before that one! |
1388 | - curve_endit = path_it->end_open(); |
1389 | - } |
1390 | - } |
1391 | - int counter = 0; |
1392 | - while (curve_it1 != curve_endit) { |
1393 | - std::pair<std::size_t, std::size_t> positions = fillet_chamfer_values.get_positions(counter, original_pathv); |
1394 | - Geom::NodeType nodetype; |
1395 | - if (positions.second == 0) { |
1396 | - if (path_it->closed()) { |
1397 | - Piecewise<D2<SBasis> > u; |
1398 | - u.push_cut(0); |
1399 | - u.push(pwd2_in[fillet_chamfer_values.last_index(counter, original_pathv)], 1); |
1400 | - Geom::Curve const * A = path_from_piecewise(u, 0.1)[0][0].duplicate(); |
1401 | - nodetype = get_nodetype(*A, *curve_it1); |
1402 | - } else { |
1403 | - nodetype = NODE_NONE; |
1404 | - } |
1405 | - } else { |
1406 | - nodetype = get_nodetype((*path_it)[counter - 1], *curve_it1); |
1407 | - } |
1408 | - if (nodetype == NODE_CUSP) { |
1409 | - point.push_back(Point(0, 1)); |
1410 | - } else { |
1411 | - point.push_back(Point(0, 0)); |
1412 | - } |
1413 | - ++curve_it1; |
1414 | - if (curve_it2 != curve_endit) { |
1415 | - ++curve_it2; |
1416 | - } |
1417 | - counter++; |
1418 | - } |
1419 | - } |
1420 | - fillet_chamfer_values.param_set_and_write_new_value(point); |
1421 | - } else { |
1422 | - g_warning("LPE Fillet can only be applied to shapes (not groups)."); |
1423 | - SPLPEItem * item = const_cast<SPLPEItem*>(lpeItem); |
1424 | - item->removeCurrentPathEffect(false); |
1425 | - } |
1426 | + satellites[i][j].setSelected(false); |
1427 | + } |
1428 | + } |
1429 | + } |
1430 | + _pathvector_satellites->setSatellites(satellites); |
1431 | } |
1432 | |
1433 | void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) |
1434 | { |
1435 | - if (SP_IS_SHAPE(lpeItem)) { |
1436 | - if(hide_knots){ |
1437 | - fillet_chamfer_values.set_helper_size(0); |
1438 | - } else { |
1439 | - fillet_chamfer_values.set_helper_size(helper_size); |
1440 | - } |
1441 | - fillet_chamfer_values.set_use_distance(use_knot_distance); |
1442 | - SPCurve *c = SP_IS_PATH(lpeItem) ? static_cast<SPPath const *>(lpeItem) |
1443 | - ->get_original_curve() |
1444 | - : SP_SHAPE(lpeItem)->getCurve(); |
1445 | - std::vector<Point> filletChamferData = fillet_chamfer_values.data(); |
1446 | - if (!filletChamferData.empty() && getKnotsNumber(c) != (int) |
1447 | - filletChamferData.size()) { |
1448 | - PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(c->get_pathvector()); |
1449 | - Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(original_pathv); |
1450 | - fillet_chamfer_values.recalculate_controlpoints_for_new_pwd2(pwd2_in); |
1451 | - } |
1452 | + if (sp_curve) { |
1453 | + //fillet chamfer specific calls |
1454 | + satellites_param.setUseDistance(use_knot_distance); |
1455 | + satellites_param.setCurrentZoom(current_zoom); |
1456 | + //mandatory call |
1457 | + satellites_param.setEffectType(effectType()); |
1458 | + Geom::PathVector const pathv = pathv_to_linear_and_cubic_beziers(sp_curve->get_pathvector()); |
1459 | + //if are diferent sizes call to recalculate |
1460 | + //TODO: Update the satellite data in paths modified, |
1461 | + Satellites satellites = satellites_param.data(); |
1462 | + if (satellites.empty()) { |
1463 | + doOnApply(lpeItem); |
1464 | + satellites = satellites_param.data(); |
1465 | + } |
1466 | + if (_pathvector_satellites) { |
1467 | + size_t number_nodes = pathv.nodes().size(); |
1468 | + size_t previous_number_nodes = _pathvector_satellites->getTotalSatellites(); |
1469 | + if (number_nodes != previous_number_nodes) { |
1470 | + Satellite satellite(FILLET); |
1471 | + satellite.setIsTime(flexible); |
1472 | + satellite.setHasMirror(mirror_knots); |
1473 | + satellite.setHidden(hide_knots); |
1474 | + _pathvector_satellites->recalculateForNewPathVector(pathv, satellite); |
1475 | + satellites = _pathvector_satellites->getSatellites(); |
1476 | + } |
1477 | + } |
1478 | + if (_degenerate_hide) { |
1479 | + satellites_param.setGlobalKnotHide(true); |
1480 | + } else { |
1481 | + satellites_param.setGlobalKnotHide(false); |
1482 | + } |
1483 | + if (hide_knots) { |
1484 | + satellites_param.setHelperSize(0); |
1485 | + } else { |
1486 | + satellites_param.setHelperSize(helper_size); |
1487 | + } |
1488 | + for (size_t i = 0; i < satellites.size(); ++i) { |
1489 | + for (size_t j = 0; j < satellites[i].size(); ++j) { |
1490 | + Geom::Curve const &curve_in = pathv[i][j]; |
1491 | + if (satellites[i][j].is_time != flexible) { |
1492 | + satellites[i][j].is_time = flexible; |
1493 | + double amount = satellites[i][j].amount; |
1494 | + if (pathv[i].size() == j) { |
1495 | + continue; |
1496 | + } |
1497 | + if (satellites[i][j].is_time) { |
1498 | + double time = timeAtArcLength(amount, curve_in); |
1499 | + satellites[i][j].amount = time; |
1500 | + } else { |
1501 | + double size = arcLengthAt(amount, curve_in); |
1502 | + satellites[i][j].amount = size; |
1503 | + } |
1504 | + } |
1505 | + if (satellites[i][j].has_mirror != mirror_knots) { |
1506 | + satellites[i][j].has_mirror = mirror_knots; |
1507 | + } |
1508 | + satellites[i][j].hidden = hide_knots; |
1509 | + if (only_selected && isNodePointSelected(curve_in.initialPoint()) ){ |
1510 | + satellites[i][j].setSelected(true); |
1511 | + } |
1512 | + } |
1513 | + } |
1514 | + if (!_pathvector_satellites) { |
1515 | + _pathvector_satellites = new PathVectorSatellites(); |
1516 | + } |
1517 | + _pathvector_satellites->setPathVector(pathv); |
1518 | + _pathvector_satellites->setSatellites(satellites); |
1519 | + satellites_param.setPathVectorSatellites(_pathvector_satellites, false); |
1520 | + refreshKnots(); |
1521 | } else { |
1522 | g_warning("LPE Fillet can only be applied to shapes (not groups)."); |
1523 | } |
1524 | } |
1525 | |
1526 | -int LPEFilletChamfer::getKnotsNumber(SPCurve const *c) |
1527 | +void |
1528 | +LPEFilletChamfer::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) |
1529 | { |
1530 | - int nKnots = c->nodes_in_path(); |
1531 | - PathVector const pv = pathv_to_linear_and_cubic_beziers(c->get_pathvector()); |
1532 | - for (Geom::PathVector::const_iterator path_it = pv.begin(); |
1533 | - path_it != pv.end(); ++path_it) { |
1534 | - if (!(*path_it).closed()) { |
1535 | - nKnots--; |
1536 | - } |
1537 | - } |
1538 | - return nKnots; |
1539 | + hp_vec.push_back(_hp); |
1540 | } |
1541 | |
1542 | void |
1543 | -LPEFilletChamfer::adjustForNewPath(Geom::PathVector const &path_in) |
1544 | +LPEFilletChamfer::addChamferSteps(Geom::Path &tmp_path, Geom::Path path_chamfer, Geom::Point end_arc_point, size_t steps) |
1545 | { |
1546 | - if (!path_in.empty()) { |
1547 | - fillet_chamfer_values.recalculate_controlpoints_for_new_pwd2(pathv_to_linear_and_cubic_beziers(path_in)[0].toPwSb()); |
1548 | + setSelected(_pathvector_satellites); |
1549 | + double path_subdivision = 1.0 / steps; |
1550 | + for (size_t i = 1; i < steps; i++) { |
1551 | + Geom::Point chamfer_step = path_chamfer.pointAt(path_subdivision * i); |
1552 | + tmp_path.appendNew<Geom::LineSegment>(chamfer_step); |
1553 | } |
1554 | + tmp_path.appendNew<Geom::LineSegment>(end_arc_point); |
1555 | } |
1556 | |
1557 | Geom::PathVector |
1558 | LPEFilletChamfer::doEffect_path(Geom::PathVector const &path_in) |
1559 | { |
1560 | - Geom::PathVector pathvector_out; |
1561 | - Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(pathv_to_linear_and_cubic_beziers(path_in)); |
1562 | - pwd2_in = remove_short_cuts(pwd2_in, .01); |
1563 | - Piecewise<D2<SBasis> > der = derivative(pwd2_in); |
1564 | - Piecewise<D2<SBasis> > n = rot90(unitVector(der)); |
1565 | - fillet_chamfer_values.set_pwd2(pwd2_in, n); |
1566 | - std::vector<Point> filletChamferData = fillet_chamfer_values.data(); |
1567 | - unsigned int counter = 0; |
1568 | + const double GAP_HELPER = 0.00001; |
1569 | + Geom::PathVector path_out; |
1570 | + size_t path = 0; |
1571 | const double K = (4.0 / 3.0) * (sqrt(2.0) - 1.0); |
1572 | - Geom::PathVector path_in_processed = pathv_to_linear_and_cubic_beziers(path_in); |
1573 | - for (PathVector::const_iterator path_it = path_in_processed.begin(); |
1574 | - path_it != path_in_processed.end(); ++path_it) { |
1575 | - if (path_it->empty()) |
1576 | - continue; |
1577 | - Geom::Path path_out; |
1578 | - Geom::Path::const_iterator curve_it1 = path_it->begin(); |
1579 | - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); |
1580 | - Geom::Path::const_iterator curve_endit = path_it->end_default(); |
1581 | + _degenerate_hide = false; |
1582 | + Geom::PathVector const pathv = pathv_to_linear_and_cubic_beziers(path_in); |
1583 | + Satellites satellites = _pathvector_satellites->getSatellites(); |
1584 | + for (Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { |
1585 | + if (path_it->empty()) { |
1586 | + continue; |
1587 | + } |
1588 | + Geom::Path tmp_path; |
1589 | + if (path_it->size() == 1) { |
1590 | + path++; |
1591 | + tmp_path.start(path_it[0].pointAt(0)); |
1592 | + tmp_path.append(path_it[0]); |
1593 | + path_out.push_back(tmp_path); |
1594 | + continue; |
1595 | + } |
1596 | + double time0 = 0; |
1597 | + size_t curve = 0; |
1598 | + for (Geom::Path::const_iterator curve_it1 = path_it->begin(); curve_it1 != path_it->end(); ++curve_it1) { |
1599 | + size_t next_index = curve + 1; |
1600 | + if (curve == pathv[path].size() - 1 && pathv[path].closed()) { |
1601 | + next_index = 0; |
1602 | + } |
1603 | + //append last extreme of paths on open paths |
1604 | + if (curve == pathv[path].size() -1 && !pathv[path].closed()) { //the path is open and we are at end of path |
1605 | + if (time0 != 1) { //Previous satellite not at 100% amount |
1606 | + Geom::Curve *last_curve = curve_it1->portion(time0, 1); |
1607 | + last_curve->setInitial(tmp_path.finalPoint()); |
1608 | + tmp_path.append(*last_curve); |
1609 | + } |
1610 | + continue; |
1611 | + } |
1612 | + Geom::Curve const &curve_it2 = pathv[path][next_index]; |
1613 | + Satellite satellite = satellites[path][next_index]; |
1614 | + if (Geom::are_near((*curve_it1).initialPoint(), (*curve_it1).finalPoint())) { |
1615 | + _degenerate_hide = true; |
1616 | + g_warning("Knots hidded if consecutive nodes has the same position."); |
1617 | + return path_in; |
1618 | + } |
1619 | + if (!curve) { //curve == 0 |
1620 | + if (!path_it->closed()) { |
1621 | + time0 = 0; |
1622 | + } else { |
1623 | + time0 = satellites[path][0].time(*curve_it1); |
1624 | + } |
1625 | + } |
1626 | + double s = satellite.arcDistance(curve_it2); |
1627 | + double time1 = satellite.time(s, true, (*curve_it1)); |
1628 | + double time2 = satellite.time(curve_it2); |
1629 | + if (time1 <= time0) { |
1630 | + time1 = time0; |
1631 | + } |
1632 | + if (time2 > 1) { |
1633 | + time2 = 1; |
1634 | + } |
1635 | + Geom::Curve *knot_curve_1 = curve_it1->portion(time0, time1); |
1636 | + Geom::Curve *knot_curve_2 = curve_it2.portion(time2, 1); |
1637 | + if (curve > 0) { |
1638 | + knot_curve_1->setInitial(tmp_path.finalPoint()); |
1639 | + } else { |
1640 | + tmp_path.start((*curve_it1).pointAt(time0)); |
1641 | + } |
1642 | + |
1643 | + Geom::Point start_arc_point = knot_curve_1->finalPoint(); |
1644 | + Geom::Point end_arc_point = curve_it2.pointAt(time2); |
1645 | + //add a gap helper |
1646 | + if (time2 == 1) { |
1647 | + end_arc_point = curve_it2.pointAt(time2 - GAP_HELPER); |
1648 | + } |
1649 | + if (time1 == time0) { |
1650 | + start_arc_point = curve_it1->pointAt(time1 + GAP_HELPER); |
1651 | + } |
1652 | + |
1653 | + double k1 = distance(start_arc_point, curve_it1->finalPoint()) * K; |
1654 | + double k2 = distance(curve_it2.initialPoint(), end_arc_point) * K; |
1655 | + Geom::CubicBezier const *cubic_1 = dynamic_cast<Geom::CubicBezier const *>(&*knot_curve_1); |
1656 | + Geom::CubicBezier const *cubic_2 = dynamic_cast<Geom::CubicBezier const *>(&*knot_curve_2); |
1657 | + Geom::Ray ray_1(start_arc_point, curve_it1->finalPoint()); |
1658 | + Geom::Ray ray_2(curve_it2.initialPoint(), end_arc_point); |
1659 | + if (cubic_1) { |
1660 | + ray_1.setPoints((*cubic_1)[2], start_arc_point); |
1661 | + } |
1662 | + if (cubic_2) { |
1663 | + ray_2.setPoints(end_arc_point, (*cubic_2)[1]); |
1664 | + } |
1665 | + bool ccw_toggle = cross(curve_it1->finalPoint() - start_arc_point, end_arc_point - start_arc_point) < 0; |
1666 | + double angle = angle_between(ray_1, ray_2, ccw_toggle); |
1667 | + double handle_angle_1 = ray_1.angle() - angle; |
1668 | + double handle_angle_2 = ray_2.angle() + angle; |
1669 | + if (ccw_toggle) { |
1670 | + handle_angle_1 = ray_1.angle() + angle; |
1671 | + handle_angle_2 = ray_2.angle() - angle; |
1672 | + } |
1673 | + Geom::Point handle_1 = Geom::Point::polar(ray_1.angle(), k1) + start_arc_point; |
1674 | + Geom::Point handle_2 = end_arc_point - Geom::Point::polar(ray_2.angle(), k2); |
1675 | + Geom::Point inverse_handle_1 = Geom::Point::polar(handle_angle_1, k1) + start_arc_point; |
1676 | + Geom::Point inverse_handle_2 = end_arc_point - Geom::Point::polar(handle_angle_2, k2); |
1677 | + if (time0 == 1) { |
1678 | + handle_1 = start_arc_point; |
1679 | + inverse_handle_1 = start_arc_point; |
1680 | + } |
1681 | + //remove gap helper |
1682 | + if (time2 == 1) { |
1683 | + end_arc_point = curve_it2.pointAt(time2); |
1684 | + } |
1685 | + if (time1 == time0) { |
1686 | + start_arc_point = curve_it1->pointAt(time0); |
1687 | + } |
1688 | + if (time1 != 1) { |
1689 | + if (time1 != time0 || (time1 == 1 && time0 == 1)) { |
1690 | + if (!knot_curve_1->isDegenerate()) { |
1691 | + tmp_path.append(*knot_curve_1); |
1692 | + } |
1693 | + } |
1694 | + SatelliteType type = satellite.satellite_type; |
1695 | + size_t steps = satellite.steps; |
1696 | + if (!steps) steps = 1; |
1697 | + Geom::Line const x_line(Geom::Point(0, 0), Geom::Point(1, 0)); |
1698 | + Geom::Line const angled_line(start_arc_point, end_arc_point); |
1699 | + double arc_angle = Geom::angle_between(x_line, angled_line); |
1700 | + double radius = Geom::distance(start_arc_point, middle_point(start_arc_point, end_arc_point)) / |
1701 | + sin(angle / 2.0); |
1702 | + Geom::Coord rx = radius; |
1703 | + Geom::Coord ry = rx; |
1704 | + bool eliptical = (is_straight_curve(*curve_it1) && |
1705 | + is_straight_curve(curve_it2) && method != FM_BEZIER) || |
1706 | + method == FM_ARC; |
1707 | + switch (type) { |
1708 | + case CHAMFER: |
1709 | + { |
1710 | + Geom::Path path_chamfer; |
1711 | + path_chamfer.start(tmp_path.finalPoint()); |
1712 | + if (eliptical) { |
1713 | + ccw_toggle = ccw_toggle ? 0 : 1; |
1714 | + path_chamfer.appendNew<Geom::EllipticalArc>(rx, ry, arc_angle, 0, ccw_toggle, end_arc_point); |
1715 | + } else { |
1716 | + path_chamfer.appendNew<Geom::CubicBezier>(handle_1, handle_2, end_arc_point); |
1717 | + } |
1718 | + addChamferSteps(tmp_path, path_chamfer, end_arc_point, steps); |
1719 | + } |
1720 | + break; |
1721 | + case INVERSE_CHAMFER: |
1722 | + { |
1723 | + Geom::Path path_chamfer; |
1724 | + path_chamfer.start(tmp_path.finalPoint()); |
1725 | + if (eliptical) { |
1726 | + path_chamfer.appendNew<Geom::EllipticalArc>(rx, ry, arc_angle, 0, ccw_toggle, end_arc_point); |
1727 | + } else { |
1728 | + path_chamfer.appendNew<Geom::CubicBezier>(inverse_handle_1, inverse_handle_2, end_arc_point); |
1729 | + } |
1730 | + addChamferSteps(tmp_path, path_chamfer, end_arc_point, steps); |
1731 | + } |
1732 | + break; |
1733 | + case INVERSE_FILLET: |
1734 | + { |
1735 | + if (eliptical) { |
1736 | + tmp_path.appendNew<Geom::EllipticalArc>(rx, ry, arc_angle, 0, ccw_toggle, end_arc_point); |
1737 | + } else { |
1738 | + tmp_path.appendNew<Geom::CubicBezier>(inverse_handle_1, inverse_handle_2, end_arc_point); |
1739 | + } |
1740 | + } |
1741 | + break; |
1742 | + default: //fillet |
1743 | + { |
1744 | + if (eliptical) { |
1745 | + ccw_toggle = ccw_toggle ? 0 : 1; |
1746 | + tmp_path.appendNew<Geom::EllipticalArc>(rx, ry, arc_angle, 0, ccw_toggle, end_arc_point); |
1747 | + } else { |
1748 | + tmp_path.appendNew<Geom::CubicBezier>(handle_1, handle_2, end_arc_point); |
1749 | + } |
1750 | + } |
1751 | + break; |
1752 | + } |
1753 | + } else { |
1754 | + if (!knot_curve_1->isDegenerate()) { |
1755 | + tmp_path.append(*knot_curve_1); |
1756 | + } |
1757 | + } |
1758 | + curve++; |
1759 | + time0 = time2; |
1760 | + } |
1761 | if (path_it->closed()) { |
1762 | - const Geom::Curve &closingline = path_it->back_closed(); |
1763 | - // the closing line segment is always of type |
1764 | - // Geom::LineSegment. |
1765 | - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { |
1766 | - // closingline.isDegenerate() did not work, because it only checks for |
1767 | - // *exact* zero length, which goes wrong for relative coordinates and |
1768 | - // rounding errors... |
1769 | - // the closing line segment has zero-length. So stop before that one! |
1770 | - curve_endit = path_it->end_open(); |
1771 | - } |
1772 | - } |
1773 | - unsigned int counterCurves = 0; |
1774 | - while (curve_it1 != curve_endit) { |
1775 | - Curve *curve_it2Fixed = (*path_it->begin()).duplicate(); |
1776 | - if(!path_it->closed() || curve_it2 != curve_endit){ |
1777 | - curve_it2Fixed = (*curve_it2).duplicate(); |
1778 | - } |
1779 | - bool last = curve_it2 == curve_endit; |
1780 | - std::vector<double> times = fillet_chamfer_values.get_times(counter, path_in, last); |
1781 | - Curve *knotCurve1 = curve_it1->portion(times[0], times[1]); |
1782 | - if (counterCurves > 0) { |
1783 | - knotCurve1->setInitial(path_out.finalPoint()); |
1784 | - } else { |
1785 | - path_out.start((*curve_it1).pointAt(times[0])); |
1786 | - } |
1787 | - Curve *knotCurve2 = curve_it2Fixed->portion(times[2], 1); |
1788 | - Point startArcPoint = knotCurve1->finalPoint(); |
1789 | - Point endArcPoint = curve_it2Fixed->pointAt(times[2]); |
1790 | - double k1 = distance(startArcPoint, curve_it1->finalPoint()) * K; |
1791 | - double k2 = distance(endArcPoint, curve_it1->finalPoint()) * K; |
1792 | - Geom::CubicBezier const *cubic1 = dynamic_cast<Geom::CubicBezier const *>(&*knotCurve1); |
1793 | - Ray ray1(startArcPoint, curve_it1->finalPoint()); |
1794 | - if (cubic1) { |
1795 | - ray1.setPoints((*cubic1)[2], startArcPoint); |
1796 | - } |
1797 | - Point handle1 = Point::polar(ray1.angle(),k1) + startArcPoint; |
1798 | - Geom::CubicBezier const *cubic2 = |
1799 | - dynamic_cast<Geom::CubicBezier const *>(&*knotCurve2); |
1800 | - Ray ray2(curve_it1->finalPoint(), endArcPoint); |
1801 | - if (cubic2) { |
1802 | - ray2.setPoints(endArcPoint, (*cubic2)[1]); |
1803 | - } |
1804 | - Point handle2 = endArcPoint - Point::polar(ray2.angle(),k2); |
1805 | - bool ccwToggle = cross(curve_it1->finalPoint() - startArcPoint, endArcPoint - startArcPoint) > 0; |
1806 | - double angle = angle_between(ray1, ray2, ccwToggle); |
1807 | - double handleAngle = ray1.angle() - angle; |
1808 | - if (ccwToggle) { |
1809 | - handleAngle = ray1.angle() + angle; |
1810 | - } |
1811 | - Point inverseHandle1 = Point::polar(handleAngle,k1) + startArcPoint; |
1812 | - handleAngle = ray2.angle() + angle; |
1813 | - if (ccwToggle) { |
1814 | - handleAngle = ray2.angle() - angle; |
1815 | - } |
1816 | - Point inverseHandle2 = endArcPoint - Point::polar(handleAngle,k2); |
1817 | - //straigth lines arc based |
1818 | - Line const x_line(Geom::Point(0,0),Geom::Point(1,0)); |
1819 | - Line const angled_line(startArcPoint,endArcPoint); |
1820 | - double angleArc = Geom::angle_between( x_line,angled_line); |
1821 | - double radius = Geom::distance(startArcPoint,middle_point(startArcPoint,endArcPoint))/sin(angle/2.0); |
1822 | - Coord rx = radius; |
1823 | - Coord ry = rx; |
1824 | - |
1825 | - if (times[1] != 1) { |
1826 | - if (times[1] != gapHelper && times[1] != times[0] + gapHelper) { |
1827 | - path_out.append(*knotCurve1); |
1828 | - } |
1829 | - int type = 0; |
1830 | - if(path_it->closed() && last){ |
1831 | - type = std::abs(filletChamferData[counter - counterCurves][Y]); |
1832 | - } else if (!path_it->closed() && last){ |
1833 | - //0 |
1834 | - } else { |
1835 | - type = std::abs(filletChamferData[counter + 1][Y]); |
1836 | - } |
1837 | - if(are_near(middle_point(startArcPoint,endArcPoint),curve_it1->finalPoint(), 0.0001)){ |
1838 | - path_out.appendNew<Geom::LineSegment>(endArcPoint); |
1839 | - } else if (type >= 3000 && type < 4000) { |
1840 | - unsigned int chamferSubs = type-3000; |
1841 | - Geom::Path path_chamfer; |
1842 | - path_chamfer.start(path_out.finalPoint()); |
1843 | - if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ |
1844 | - path_chamfer.appendNew<EllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); |
1845 | - } else { |
1846 | - path_chamfer.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint); |
1847 | - } |
1848 | - double chamfer_stepsTime = 1.0/chamferSubs; |
1849 | - for(unsigned int i = 1; i < chamferSubs; i++){ |
1850 | - Geom::Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i); |
1851 | - path_out.appendNew<Geom::LineSegment>(chamferStep); |
1852 | - } |
1853 | - path_out.appendNew<Geom::LineSegment>(endArcPoint); |
1854 | - } else if (type >= 4000 && type < 5000) { |
1855 | - unsigned int chamferSubs = type-4000; |
1856 | - Geom::Path path_chamfer; |
1857 | - path_chamfer.start(path_out.finalPoint()); |
1858 | - if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ |
1859 | - ccwToggle = ccwToggle?0:1; |
1860 | - path_chamfer.appendNew<EllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); |
1861 | - }else{ |
1862 | - path_chamfer.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint); |
1863 | - } |
1864 | - double chamfer_stepsTime = 1.0/chamferSubs; |
1865 | - for(unsigned int i = 1; i < chamferSubs; i++){ |
1866 | - Geom::Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i); |
1867 | - path_out.appendNew<Geom::LineSegment>(chamferStep); |
1868 | - } |
1869 | - path_out.appendNew<Geom::LineSegment>(endArcPoint); |
1870 | - } else if (type == 2) { |
1871 | - if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ |
1872 | - ccwToggle = ccwToggle?0:1; |
1873 | - path_out.appendNew<EllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); |
1874 | - }else{ |
1875 | - path_out.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint); |
1876 | - } |
1877 | - } else if (type == 1){ |
1878 | - if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ |
1879 | - path_out.appendNew<EllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); |
1880 | - } else { |
1881 | - path_out.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint); |
1882 | - } |
1883 | - } |
1884 | - } else { |
1885 | - path_out.append(*knotCurve1); |
1886 | - } |
1887 | - if (path_it->closed() && last) { |
1888 | - path_out.close(); |
1889 | - } |
1890 | - ++curve_it1; |
1891 | - if (curve_it2 != curve_endit) { |
1892 | - ++curve_it2; |
1893 | - } |
1894 | - counter++; |
1895 | - counterCurves++; |
1896 | - } |
1897 | - pathvector_out.push_back(path_out); |
1898 | + tmp_path.close(); |
1899 | + } |
1900 | + path++; |
1901 | + path_out.push_back(tmp_path); |
1902 | } |
1903 | - return pathvector_out; |
1904 | + return path_out; |
1905 | } |
1906 | |
1907 | }; //namespace LivePathEffect |
1908 | |
1909 | === modified file 'src/live_effects/lpe-fillet-chamfer.h' |
1910 | --- src/live_effects/lpe-fillet-chamfer.h 2015-07-24 18:50:50 +0000 |
1911 | +++ src/live_effects/lpe-fillet-chamfer.h 2017-05-06 17:46:29 +0000 |
1912 | @@ -7,25 +7,22 @@ |
1913 | * |
1914 | * Copyright (C) 2014 Author(s) |
1915 | * |
1916 | - * Special thanks to Johan Engelen for the base of the effect -powerstroke- |
1917 | - * Also to ScislaC for point me to the idea |
1918 | - * Also su_v for his construvtive feedback and time |
1919 | - * and finaly to Liam P. White for his big help on coding, that save me a lot of hours |
1920 | + * Jabiertxof:Thanks to all people help me |
1921 | * |
1922 | * Released under GNU GPL, read the file 'COPYING' for more information |
1923 | */ |
1924 | |
1925 | #include "live_effects/parameter/enum.h" |
1926 | -#include "live_effects/parameter/bool.h" |
1927 | +#include "live_effects/parameter/satellitesarray.h" |
1928 | +#include "live_effects/effect.h" |
1929 | #include "live_effects/parameter/unit.h" |
1930 | - |
1931 | -#include "live_effects/parameter/filletchamferpointarray.h" |
1932 | -#include "live_effects/effect.h" |
1933 | +#include "helper/geom-pathvectorsatellites.h" |
1934 | +#include "helper/geom-satellite.h" |
1935 | |
1936 | namespace Inkscape { |
1937 | namespace LivePathEffect { |
1938 | |
1939 | -enum FilletMethod { |
1940 | +enum Filletmethod { |
1941 | FM_AUTO, |
1942 | FM_ARC, |
1943 | FM_BEZIER, |
1944 | @@ -35,41 +32,38 @@ |
1945 | class LPEFilletChamfer : public Effect { |
1946 | public: |
1947 | LPEFilletChamfer(LivePathEffectObject *lpeobject); |
1948 | - virtual ~LPEFilletChamfer(); |
1949 | - |
1950 | + virtual void doBeforeEffect(SPLPEItem const *lpeItem); |
1951 | virtual Geom::PathVector doEffect_path(Geom::PathVector const &path_in); |
1952 | - |
1953 | virtual void doOnApply(SPLPEItem const *lpeItem); |
1954 | - virtual void doBeforeEffect(SPLPEItem const *lpeItem); |
1955 | - virtual void adjustForNewPath(Geom::PathVector const &path_in); |
1956 | - virtual Gtk::Widget* newWidget(); |
1957 | - |
1958 | - int getKnotsNumber(SPCurve const *c); |
1959 | - void toggleHide(); |
1960 | - void toggleFlexFixed(); |
1961 | - void chamfer(); |
1962 | - void chamferSubdivisions(); |
1963 | - void inverseChamfer(); |
1964 | - void fillet(); |
1965 | - void inverseFillet(); |
1966 | - void updateFillet(); |
1967 | - void doUpdateFillet(Geom::PathVector const& original_pathv, double power); |
1968 | - void doChangeType(Geom::PathVector const& original_pathv, int type); |
1969 | + virtual Gtk::Widget *newWidget(); |
1970 | + Geom::Ray getRay(Geom::Point start, Geom::Point end, Geom::Curve *curve, bool reverse); |
1971 | + void addChamferSteps(Geom::Path &tmp_path, Geom::Path path_chamfer, Geom::Point end_arc_point, size_t steps); |
1972 | + void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec); |
1973 | + void updateSatelliteType(SatelliteType satellitetype); |
1974 | + void setSelected(PathVectorSatellites *_pathvector_satellites); |
1975 | + //void convertUnit(); |
1976 | + void updateChamferSteps(); |
1977 | + void updateAmount(); |
1978 | void refreshKnots(); |
1979 | |
1980 | - FilletChamferPointArrayParam fillet_chamfer_values; |
1981 | + SatellitesArrayParam satellites_param; |
1982 | |
1983 | private: |
1984 | - |
1985 | - BoolParam hide_knots; |
1986 | - BoolParam ignore_radius_0; |
1987 | + UnitParam unit; |
1988 | + EnumParam<Filletmethod> method; |
1989 | + ScalarParam radius; |
1990 | + ScalarParam chamfer_steps; |
1991 | + BoolParam flexible; |
1992 | + BoolParam mirror_knots; |
1993 | BoolParam only_selected; |
1994 | - BoolParam flexible; |
1995 | BoolParam use_knot_distance; |
1996 | - EnumParam<FilletMethod> method; |
1997 | - ScalarParam radius; |
1998 | - ScalarParam chamfer_steps; |
1999 | + BoolParam hide_knots; |
2000 | + BoolParam apply_no_radius; |
2001 | + BoolParam apply_with_radius; |
2002 | ScalarParam helper_size; |
2003 | + bool _degenerate_hide; |
2004 | + PathVectorSatellites *_pathvector_satellites; |
2005 | + Geom::PathVector _hp; |
2006 | |
2007 | LPEFilletChamfer(const LPEFilletChamfer &); |
2008 | LPEFilletChamfer &operator=(const LPEFilletChamfer &); |
2009 | |
2010 | === modified file 'src/live_effects/parameter/array.cpp' |
2011 | --- src/live_effects/parameter/array.cpp 2014-03-27 01:33:44 +0000 |
2012 | +++ src/live_effects/parameter/array.cpp 2017-05-06 17:46:29 +0000 |
2013 | @@ -5,10 +5,7 @@ |
2014 | */ |
2015 | |
2016 | #include "live_effects/parameter/array.h" |
2017 | - |
2018 | -#include "svg/svg.h" |
2019 | -#include "svg/stringstream.h" |
2020 | - |
2021 | +#include "helper-fns.h" |
2022 | #include <2geom/coord.h> |
2023 | #include <2geom/point.h> |
2024 | |
2025 | @@ -49,6 +46,45 @@ |
2026 | return Geom::Point(Geom::infinity(),Geom::infinity()); |
2027 | } |
2028 | |
2029 | + |
2030 | +template <> |
2031 | +std::vector<Satellite> |
2032 | +ArrayParam<std::vector<Satellite > >::readsvg(const gchar * str) |
2033 | +{ |
2034 | + std::vector<Satellite> subpath_satellites; |
2035 | + if (!str) { |
2036 | + return subpath_satellites; |
2037 | + } |
2038 | + gchar ** strarray = g_strsplit(str, "@", 0); |
2039 | + gchar ** iter = strarray; |
2040 | + while (*iter != NULL) { |
2041 | + gchar ** strsubarray = g_strsplit(*iter, ",", 8); |
2042 | + if (*strsubarray[7]) {//steps always > 0 |
2043 | + Satellite *satellite = new Satellite(); |
2044 | + satellite->setSatelliteType(g_strstrip(strsubarray[0])); |
2045 | + satellite->is_time = strncmp(strsubarray[1],"1",1) == 0; |
2046 | + satellite->selected = strncmp(strsubarray[2],"1",1) == 0; |
2047 | + satellite->has_mirror = strncmp(strsubarray[3],"1",1) == 0; |
2048 | + satellite->hidden = strncmp(strsubarray[4],"1",1) == 0; |
2049 | + double amount,angle; |
2050 | + float stepsTmp; |
2051 | + sp_svg_number_read_d(strsubarray[5], &amount); |
2052 | + sp_svg_number_read_d(strsubarray[6], &angle); |
2053 | + sp_svg_number_read_f(g_strstrip(strsubarray[7]), &stepsTmp); |
2054 | + unsigned int steps = (unsigned int)stepsTmp; |
2055 | + satellite->amount = amount; |
2056 | + satellite->angle = angle; |
2057 | + satellite->steps = steps; |
2058 | + subpath_satellites.push_back(*satellite); |
2059 | + } |
2060 | + g_strfreev (strsubarray); |
2061 | + iter++; |
2062 | + } |
2063 | + g_strfreev (strarray); |
2064 | + return subpath_satellites; |
2065 | +} |
2066 | + |
2067 | + |
2068 | } /* namespace LivePathEffect */ |
2069 | |
2070 | } /* namespace Inkscape */ |
2071 | |
2072 | === modified file 'src/live_effects/parameter/array.h' |
2073 | --- src/live_effects/parameter/array.h 2017-04-29 00:01:22 +0000 |
2074 | +++ src/live_effects/parameter/array.h 2017-05-06 17:46:29 +0000 |
2075 | @@ -15,6 +15,7 @@ |
2076 | |
2077 | #include "live_effects/parameter/parameter.h" |
2078 | |
2079 | +#include "helper/geom-satellite.h" |
2080 | #include "svg/svg.h" |
2081 | #include "svg/stringstream.h" |
2082 | |
2083 | @@ -93,7 +94,43 @@ |
2084 | // separate items with pipe symbol |
2085 | str << " | "; |
2086 | } |
2087 | - str << vector[i]; |
2088 | + writesvgData(str,vector[i]); |
2089 | + } |
2090 | + } |
2091 | + |
2092 | + void writesvgData(SVGOStringStream &str, float const &vector_data) const { |
2093 | + str << vector_data; |
2094 | + } |
2095 | + |
2096 | + void writesvgData(SVGOStringStream &str, double const &vector_data) const { |
2097 | + str << vector_data; |
2098 | + } |
2099 | + |
2100 | + void writesvgData(SVGOStringStream &str, Geom::Point const &vector_data) const { |
2101 | + str << vector_data; |
2102 | + } |
2103 | + |
2104 | + void writesvgData(SVGOStringStream &str, std::vector<Satellite> const &vector_data) const { |
2105 | + for (size_t i = 0; i < vector_data.size(); ++i) { |
2106 | + if (i != 0) { |
2107 | + // separate items with @ symbol ¿Any other? |
2108 | + str << " @ "; |
2109 | + } |
2110 | + str << vector_data[i].getSatelliteTypeGchar(); |
2111 | + str << ","; |
2112 | + str << vector_data[i].is_time; |
2113 | + str << ","; |
2114 | + str << vector_data[i].selected; |
2115 | + str << ","; |
2116 | + str << vector_data[i].has_mirror; |
2117 | + str << ","; |
2118 | + str << vector_data[i].hidden; |
2119 | + str << ","; |
2120 | + str << vector_data[i].amount; |
2121 | + str << ","; |
2122 | + str << vector_data[i].angle; |
2123 | + str << ","; |
2124 | + str << vector_data[i].steps; |
2125 | } |
2126 | } |
2127 | |
2128 | |
2129 | === removed file 'src/live_effects/parameter/filletchamferpointarray.cpp' |
2130 | --- src/live_effects/parameter/filletchamferpointarray.cpp 2016-12-19 20:54:42 +0000 |
2131 | +++ src/live_effects/parameter/filletchamferpointarray.cpp 1970-01-01 00:00:00 +0000 |
2132 | @@ -1,873 +0,0 @@ |
2133 | -/* |
2134 | - * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es> |
2135 | - * Special thanks to Johan Engelen for the base of the effect -powerstroke- |
2136 | - * Also to ScislaC for point me to the idea |
2137 | - * Also su_v for his construvtive feedback and time |
2138 | - * and finaly to Liam P. White for his big help on coding, that save me a lot of |
2139 | - * hours |
2140 | - * Released under GNU GPL, read the file 'COPYING' for more information |
2141 | - */ |
2142 | - |
2143 | -#include <2geom/piecewise.h> |
2144 | -#include <2geom/sbasis-to-bezier.h> |
2145 | -#include <2geom/sbasis-geometric.h> |
2146 | -#include <2geom/line.h> |
2147 | -#include <2geom/path-intersection.h> |
2148 | - |
2149 | -#include "ui/dialog/lpe-fillet-chamfer-properties.h" |
2150 | -#include "live_effects/parameter/filletchamferpointarray.h" |
2151 | -#include "live_effects/effect.h" |
2152 | -#include "svg/svg.h" |
2153 | -#include "svg/stringstream.h" |
2154 | -#include "knotholder.h" |
2155 | -#include "sp-lpe-item.h" |
2156 | -#include "selection.h" |
2157 | - |
2158 | -// needed for on-canvas editting: |
2159 | -#include "live_effects/lpeobject.h" |
2160 | -#include "helper/geom-nodetype.h" |
2161 | -#include "helper/geom-curves.h" |
2162 | -#include "ui/tools/node-tool.h" |
2163 | - |
2164 | -// TODO due to internal breakage in glibmm headers, |
2165 | -// this has to be included last. |
2166 | -#include <glibmm/i18n.h> |
2167 | - |
2168 | - |
2169 | -using namespace Geom; |
2170 | - |
2171 | -namespace Inkscape { |
2172 | - |
2173 | -namespace LivePathEffect { |
2174 | - |
2175 | -FilletChamferPointArrayParam::FilletChamferPointArrayParam( |
2176 | - const Glib::ustring &label, const Glib::ustring &tip, |
2177 | - const Glib::ustring &key, Inkscape::UI::Widget::Registry *wr, |
2178 | - Effect *effect) |
2179 | - : ArrayParam<Point>(label, tip, key, wr, effect, 0) |
2180 | -{ |
2181 | - knot_shape = SP_KNOT_SHAPE_DIAMOND; |
2182 | - knot_mode = SP_KNOT_MODE_XOR; |
2183 | - knot_color = 0x00ff0000; |
2184 | -} |
2185 | - |
2186 | -FilletChamferPointArrayParam::~FilletChamferPointArrayParam() {} |
2187 | - |
2188 | -Gtk::Widget *FilletChamferPointArrayParam::param_newWidget() |
2189 | -{ |
2190 | - return NULL; |
2191 | - /* |
2192 | - Inkscape::UI::Widget::RegisteredTransformedPoint * pointwdg = |
2193 | - Gtk::manage( |
2194 | - new Inkscape::UI::Widget::RegisteredTransformedPoint( |
2195 | - param_label, |
2196 | - param_tooltip, |
2197 | - param_key, |
2198 | - *param_wr, |
2199 | - param_effect->getRepr(), |
2200 | - param_effect->getSPDoc() |
2201 | - ) ); |
2202 | - // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP) |
2203 | - SPDesktop *desktop = SP_ACTIVE_DESKTOP; |
2204 | - Affine transf = desktop->doc2dt(); |
2205 | - pointwdg->setTransform(transf); |
2206 | - pointwdg->setValue( *this ); |
2207 | - pointwdg->clearProgrammatically(); |
2208 | - pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, |
2209 | - _("Change point parameter")); |
2210 | - |
2211 | - Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() ); |
2212 | - static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true); |
2213 | - static_cast<Gtk::HBox*>(hbox)->show_all_children(); |
2214 | - |
2215 | - return dynamic_cast<Gtk::Widget *> (hbox); |
2216 | - */ |
2217 | -} |
2218 | - |
2219 | -void |
2220 | -FilletChamferPointArrayParam::param_transform_multiply(Affine const &postmul, |
2221 | - bool /*set*/) |
2222 | -{ |
2223 | - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
2224 | - |
2225 | - if (prefs->getBool("/options/transform/rectcorners", true) && |
2226 | - _vector[1][X] <= 0) { |
2227 | - std::vector<Geom::Point> result; |
2228 | - for (std::vector<Point>::const_iterator point_it = _vector.begin(); |
2229 | - point_it != _vector.end(); ++point_it) { |
2230 | - Coord A = |
2231 | - (*point_it)[X] * ((postmul.expansionX() + postmul.expansionY()) / 2); |
2232 | - result.push_back(Point(A, (*point_it)[Y])); |
2233 | - } |
2234 | - param_set_and_write_new_value(result); |
2235 | - } |
2236 | - |
2237 | - // param_set_and_write_new_value( (*this) * postmul ); |
2238 | -} |
2239 | - |
2240 | -/** call this method to recalculate the controlpoints such that they stay at the |
2241 | - * same location relative to the new path. Useful after adding/deleting nodes to |
2242 | - * the path.*/ |
2243 | -void FilletChamferPointArrayParam::recalculate_controlpoints_for_new_pwd2( |
2244 | - Piecewise<D2<SBasis> > const &pwd2_in) |
2245 | -{ |
2246 | - if (!last_pwd2.empty()) { |
2247 | - PathVector const pathv = |
2248 | - path_from_piecewise(remove_short_cuts(pwd2_in, 0.1), 0.001); |
2249 | - PathVector last_pathv = |
2250 | - path_from_piecewise(remove_short_cuts(last_pwd2, 0.1), 0.001); |
2251 | - std::vector<Point> result; |
2252 | - unsigned long counter = 0; |
2253 | - unsigned long counterPaths = 0; |
2254 | - unsigned long counterCurves = 0; |
2255 | - long offset = 0; |
2256 | - long offsetPaths = 0; |
2257 | - Geom::NodeType nodetype; |
2258 | - for (PathVector::const_iterator path_it = pathv.begin(); |
2259 | - path_it != pathv.end(); ++path_it) { |
2260 | - if (path_it->empty()) { |
2261 | - counterPaths++; |
2262 | - counter++; |
2263 | - continue; |
2264 | - } |
2265 | - Geom::Path::const_iterator curve_it1 = path_it->begin(); |
2266 | - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); |
2267 | - Geom::Path::const_iterator curve_endit = path_it->end_default(); |
2268 | - if (path_it->closed() && path_it->back_closed().isDegenerate()) { |
2269 | - const Curve &closingline = path_it->back_closed(); |
2270 | - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { |
2271 | - curve_endit = path_it->end_open(); |
2272 | - } |
2273 | - } |
2274 | - counterCurves = 0; |
2275 | - while (curve_it1 != curve_endit) { |
2276 | - //if start a path get node type |
2277 | - if (counterCurves == 0) { |
2278 | - if (path_it->closed()) { |
2279 | - if (path_it->back_closed().isDegenerate()) { |
2280 | - nodetype = get_nodetype(path_it->back_open(), *curve_it1); |
2281 | - } else { |
2282 | - nodetype = get_nodetype(path_it->back_closed(), *curve_it1); |
2283 | - } |
2284 | - } else { |
2285 | - nodetype = NODE_NONE; |
2286 | - } |
2287 | - } else { |
2288 | - //check node type also whith straight lines because get_nodetype |
2289 | - //return non cusp node in a node inserted inside a straight line |
2290 | - //todo: if the path remove some nodes whith the result of a straight |
2291 | - //line but with handles, the node inserted into dont fire the knot |
2292 | - // because is not handle as cusp node by get_nodetype function |
2293 | - bool next_is_line = is_straight_curve(*curve_it1); |
2294 | - bool this_is_line = is_straight_curve((*path_it)[counterCurves - 1]); |
2295 | - nodetype = get_nodetype((*path_it)[counterCurves - 1], *curve_it1); |
2296 | - if (this_is_line || next_is_line) { |
2297 | - nodetype = NODE_CUSP; |
2298 | - } |
2299 | - } |
2300 | - if (last_pathv.size() > pathv.size() || |
2301 | - (last_pathv.size() > counterPaths && |
2302 | - last_pathv[counterPaths].size() > counter - offset && |
2303 | - !are_near(curve_it1->initialPoint(), |
2304 | - last_pathv[counterPaths][counter - offset].initialPoint(), |
2305 | - 0.1))) { |
2306 | - if ( curve_it2 == curve_endit) { |
2307 | - if (last_pathv[counterPaths].size() != pathv[counterPaths].size()) { |
2308 | - offset = (last_pathv[counterPaths].size() - pathv[counterPaths].size()) * -1; |
2309 | - } else { |
2310 | - offset = 0; |
2311 | - } |
2312 | - offsetPaths += offset; |
2313 | - offset = offsetPaths; |
2314 | - } else if (counterCurves == 0 && last_pathv.size() <= pathv.size() && |
2315 | - counter - offset <= last_pathv[counterPaths].size() && |
2316 | - are_near(curve_it1->initialPoint(), |
2317 | - last_pathv[counterPaths].finalPoint(), 0.1) && |
2318 | - !last_pathv[counterPaths].closed()) { |
2319 | - long e = counter - offset + 1; |
2320 | - std::vector<Point> tmp = _vector; |
2321 | - for (unsigned long i = |
2322 | - last_pathv[counterPaths].size() + counter - offset; |
2323 | - i > counterCurves - offset + 1; i--) { |
2324 | - |
2325 | - if (tmp[i - 1][X] > 0) { |
2326 | - double fractpart, intpart; |
2327 | - fractpart = modf(tmp[i - 1][X], &intpart); |
2328 | - _vector[e] = Point(e + fractpart, tmp[i - 1][Y]); |
2329 | - } else { |
2330 | - _vector[e] = Point(tmp[i - 1][X], tmp[i - 1][Y]); |
2331 | - } |
2332 | - e++; |
2333 | - } |
2334 | - //delete temp vector |
2335 | - std::vector<Point>().swap(tmp); |
2336 | - if (last_pathv.size() > counterPaths) { |
2337 | - last_pathv[counterPaths] = last_pathv[counterPaths].reversed(); |
2338 | - } |
2339 | - } else { |
2340 | - if (last_pathv.size() > counterPaths) { |
2341 | - if (last_pathv[counterPaths].size() < |
2342 | - pathv[counterPaths].size()) { |
2343 | - offset++; |
2344 | - } else if (last_pathv[counterPaths].size() > |
2345 | - pathv[counterPaths].size()) { |
2346 | - offset--; |
2347 | - continue; |
2348 | - } |
2349 | - } else { |
2350 | - offset++; |
2351 | - } |
2352 | - } |
2353 | - double xPos = 0; |
2354 | - if (_vector[1][X] > 0) { |
2355 | - xPos = nearest_time(curve_it1->initialPoint(), pwd2_in); |
2356 | - } |
2357 | - if (nodetype == NODE_CUSP) { |
2358 | - result.push_back(Point(xPos, 1)); |
2359 | - } else { |
2360 | - result.push_back(Point(xPos, 0)); |
2361 | - } |
2362 | - } else { |
2363 | - double xPos = _vector[counter - offset][X]; |
2364 | - if (_vector.size() <= (unsigned)(counter - offset)) { |
2365 | - if (_vector[1][X] > 0) { |
2366 | - xPos = nearest_time(curve_it1->initialPoint(), pwd2_in); |
2367 | - } else { |
2368 | - xPos = 0; |
2369 | - } |
2370 | - } |
2371 | - if (nodetype == NODE_CUSP) { |
2372 | - double vectorY = _vector[counter - offset][Y]; |
2373 | - if (_vector.size() <= (unsigned)(counter - offset) || vectorY == 0) { |
2374 | - vectorY = 1; |
2375 | - } |
2376 | - result.push_back(Point(xPos, vectorY)); |
2377 | - } else { |
2378 | - if (_vector[1][X] < 0) { |
2379 | - xPos = 0; |
2380 | - } |
2381 | - result.push_back(Point(floor(xPos), 0)); |
2382 | - } |
2383 | - } |
2384 | - ++curve_it1; |
2385 | - if (curve_it2 != curve_endit) { |
2386 | - ++curve_it2; |
2387 | - } |
2388 | - counter++; |
2389 | - counterCurves++; |
2390 | - } |
2391 | - counterPaths++; |
2392 | - } |
2393 | - _vector = result; |
2394 | - write_to_SVG(); |
2395 | - } |
2396 | -} |
2397 | - |
2398 | -void FilletChamferPointArrayParam::recalculate_knots( |
2399 | - Piecewise<D2<SBasis> > const &pwd2_in) |
2400 | -{ |
2401 | - bool change = false; |
2402 | - if(_vector.size() == 0){ |
2403 | - return; |
2404 | - } |
2405 | - PathVector pathv = path_from_piecewise(pwd2_in, 0.001); |
2406 | - if (!pathv.empty()) { |
2407 | - std::vector<Point> result; |
2408 | - int counter = 0; |
2409 | - int counterCurves = 0; |
2410 | - Geom::NodeType nodetype; |
2411 | - for (PathVector::const_iterator path_it = pathv.begin(); |
2412 | - path_it != pathv.end(); ++path_it) { |
2413 | - if (path_it->empty()) { |
2414 | - counter++; |
2415 | - continue; |
2416 | - } |
2417 | - Geom::Path::const_iterator curve_it1 = path_it->begin(); |
2418 | - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); |
2419 | - Geom::Path::const_iterator curve_endit = path_it->end_default(); |
2420 | - if (path_it->closed() && path_it->back_closed().isDegenerate()) { |
2421 | - const Curve &closingline = path_it->back_closed(); |
2422 | - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { |
2423 | - curve_endit = path_it->end_open(); |
2424 | - } |
2425 | - } |
2426 | - counterCurves = 0; |
2427 | - while (curve_it1 != curve_endit) { |
2428 | - //if start a path get node type |
2429 | - if (counterCurves == 0) { |
2430 | - if (path_it->closed()) { |
2431 | - if (path_it->back_closed().isDegenerate()) { |
2432 | - nodetype = get_nodetype(path_it->back_open(), *curve_it1); |
2433 | - } else { |
2434 | - nodetype = get_nodetype(path_it->back_closed(), *curve_it1); |
2435 | - } |
2436 | - } else { |
2437 | - nodetype = NODE_NONE; |
2438 | - } |
2439 | - } else { |
2440 | - bool next_is_line = is_straight_curve(*curve_it1); |
2441 | - bool this_is_line = is_straight_curve((*path_it)[counterCurves - 1]); |
2442 | - nodetype = get_nodetype((*path_it)[counterCurves - 1], *curve_it1); |
2443 | - if (this_is_line || next_is_line) { |
2444 | - nodetype = NODE_CUSP; |
2445 | - } |
2446 | - } |
2447 | - if (nodetype == NODE_CUSP) { |
2448 | - double vectorY = _vector[counter][Y]; |
2449 | - if (vectorY == 0) { |
2450 | - vectorY = 1; |
2451 | - change = true; |
2452 | - } |
2453 | - result.push_back(Point(_vector[counter][X], vectorY)); |
2454 | - } else { |
2455 | - double xPos = floor(_vector[counter][X]); |
2456 | - if (_vector[1][X] < 0) { |
2457 | - xPos = 0; |
2458 | - } |
2459 | - double vectorY = _vector[counter][Y]; |
2460 | - if (vectorY != 0) { |
2461 | - change = true; |
2462 | - } |
2463 | - result.push_back(Point(xPos, 0)); |
2464 | - } |
2465 | - ++curve_it1; |
2466 | - counter++; |
2467 | - if (curve_it2 != curve_endit) { |
2468 | - ++curve_it2; |
2469 | - } |
2470 | - counterCurves++; |
2471 | - } |
2472 | - } |
2473 | - if (change) { |
2474 | - _vector = result; |
2475 | - write_to_SVG(); |
2476 | - } |
2477 | - } |
2478 | -} |
2479 | - |
2480 | -void FilletChamferPointArrayParam::set_pwd2( |
2481 | - Piecewise<D2<SBasis> > const &pwd2_in, |
2482 | - Piecewise<D2<SBasis> > const &pwd2_normal_in) |
2483 | -{ |
2484 | - last_pwd2 = pwd2_in; |
2485 | - last_pwd2_normal = pwd2_normal_in; |
2486 | -} |
2487 | - |
2488 | -void FilletChamferPointArrayParam::set_helper_size(int hs) |
2489 | -{ |
2490 | - helper_size = hs; |
2491 | -} |
2492 | - |
2493 | -void FilletChamferPointArrayParam::set_chamfer_steps(int value_chamfer_steps) |
2494 | -{ |
2495 | - chamfer_steps = value_chamfer_steps; |
2496 | -} |
2497 | - |
2498 | -void FilletChamferPointArrayParam::set_use_distance(bool use_knot_distance ) |
2499 | -{ |
2500 | - use_distance = use_knot_distance; |
2501 | -} |
2502 | - |
2503 | -void FilletChamferPointArrayParam::updateCanvasIndicators() |
2504 | -{ |
2505 | - std::vector<Point> ts = data(); |
2506 | - hp.clear(); |
2507 | - unsigned int i = 0; |
2508 | - for (std::vector<Point>::const_iterator point_it = ts.begin(); |
2509 | - point_it != ts.end(); ++point_it) { |
2510 | - double Xvalue = to_time(i, (*point_it)[X]) -i; |
2511 | - if (Xvalue == 0) { |
2512 | - i++; |
2513 | - continue; |
2514 | - } |
2515 | - Geom::Point ptA = last_pwd2[i].valueAt(Xvalue); |
2516 | - Geom::Point derivA = unit_vector(derivative(last_pwd2[i]).valueAt(Xvalue)); |
2517 | - Geom::Rotate rot(Geom::Rotate::from_degrees(-90)); |
2518 | - derivA = derivA * rot; |
2519 | - Geom::Point C = ptA - derivA * helper_size; |
2520 | - Geom::Point D = ptA + derivA * helper_size; |
2521 | - Geom::Ray ray1(C, D); |
2522 | - char const * svgd = "M 1,0.25 0.5,0 1,-0.25 M 1,0.5 0,0 1,-0.5"; |
2523 | - Geom::PathVector pathv = sp_svg_read_pathv(svgd); |
2524 | - Geom::Affine aff = Geom::Affine(); |
2525 | - aff *= Geom::Scale(helper_size); |
2526 | - aff *= Geom::Rotate(ray1.angle() - rad_from_deg(270)); |
2527 | - aff *= Geom::Translate(last_pwd2[i].valueAt(Xvalue)); |
2528 | - pathv *= aff; |
2529 | - hp.push_back(pathv[0]); |
2530 | - hp.push_back(pathv[1]); |
2531 | - i++; |
2532 | - } |
2533 | -} |
2534 | - |
2535 | -void FilletChamferPointArrayParam::addCanvasIndicators( |
2536 | - SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) |
2537 | -{ |
2538 | - hp_vec.push_back(hp); |
2539 | -} |
2540 | - |
2541 | -double FilletChamferPointArrayParam::rad_to_len(int index, double rad) |
2542 | -{ |
2543 | - double len = 0; |
2544 | - Geom::PathVector subpaths = path_from_piecewise(last_pwd2, 0.1); |
2545 | - std::pair<std::size_t, std::size_t> positions = get_positions(index, subpaths); |
2546 | - D2<SBasis> A = last_pwd2[last_index(index, subpaths)]; |
2547 | - if(positions.second != 0){ |
2548 | - A = last_pwd2[index-1]; |
2549 | - }else{ |
2550 | - if(!subpaths[positions.first].closed()){ |
2551 | - return len; |
2552 | - } |
2553 | - } |
2554 | - D2<SBasis> B = last_pwd2[index]; |
2555 | - Piecewise<D2<SBasis> > offset_curve0 = Piecewise<D2<SBasis> >(A)+rot90(unitVector(derivative(A)))*(rad); |
2556 | - Piecewise<D2<SBasis> > offset_curve1 = Piecewise<D2<SBasis> >(B)+rot90(unitVector(derivative(B)))*(rad); |
2557 | - Geom::Path p0 = path_from_piecewise(offset_curve0, 0.1)[0]; |
2558 | - Geom::Path p1 = path_from_piecewise(offset_curve1, 0.1)[0]; |
2559 | - Geom::Crossings cs = Geom::crossings(p0, p1); |
2560 | - if(cs.size() > 0){ |
2561 | - Point cp =p0(cs[0].ta); |
2562 | - double p0pt = nearest_time(cp, B); |
2563 | - len = time_to_len(index,p0pt); |
2564 | - } else { |
2565 | - if(rad < 0){ |
2566 | - len = rad_to_len(index, rad * -1); |
2567 | - } |
2568 | - } |
2569 | - return len; |
2570 | -} |
2571 | - |
2572 | -double FilletChamferPointArrayParam::len_to_rad(int index, double len) |
2573 | -{ |
2574 | - double rad = 0; |
2575 | - double tmp_len = _vector[index][X]; |
2576 | - _vector[index] = Geom::Point(len,_vector[index][Y]); |
2577 | - Geom::PathVector subpaths = path_from_piecewise(last_pwd2, 0.1); |
2578 | - std::pair<std::size_t, std::size_t> positions = get_positions(index, subpaths); |
2579 | - Piecewise<D2<SBasis> > u; |
2580 | - u.push_cut(0); |
2581 | - u.push(last_pwd2[last_index(index, subpaths)], 1); |
2582 | - Geom::Curve * A = path_from_piecewise(u, 0.1)[0][0].duplicate(); |
2583 | - Geom::Curve * B = subpaths[positions.first][positions.second].duplicate(); |
2584 | - std::vector<double> times; |
2585 | - if(positions.second != 0){ |
2586 | - A = subpaths[positions.first][positions.second-1].duplicate(); |
2587 | - times = get_times(index-1, subpaths, false); |
2588 | - }else{ |
2589 | - if(!subpaths[positions.first].closed()){ |
2590 | - return rad; |
2591 | - } |
2592 | - times = get_times(last_index(index, subpaths), subpaths, true); |
2593 | - } |
2594 | - _vector[index] = Geom::Point(tmp_len,_vector[index][Y]); |
2595 | - Geom::Point startArcPoint = A->toSBasis().valueAt(times[1]); |
2596 | - Geom::Point endArcPoint = B->toSBasis().valueAt(times[2]); |
2597 | - Curve *knotCurve1 = A->portion(times[0], times[1]); |
2598 | - Curve *knotCurve2 = B->portion(times[2], 1); |
2599 | - Geom::CubicBezier const *cubic1 = dynamic_cast<Geom::CubicBezier const *>(knotCurve1); |
2600 | - Ray ray1(startArcPoint, A->finalPoint()); |
2601 | - if (cubic1) { |
2602 | - ray1.setPoints((*cubic1)[2], startArcPoint); |
2603 | - } |
2604 | - Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(knotCurve2); |
2605 | - Ray ray2(B->initialPoint(), endArcPoint); |
2606 | - if (cubic2) { |
2607 | - ray2.setPoints(endArcPoint, (*cubic2)[1]); |
2608 | - } |
2609 | - bool ccwToggle = cross(A->finalPoint() - startArcPoint, endArcPoint - startArcPoint) > 0; |
2610 | - double distanceArc = Geom::distance(startArcPoint,middle_point(startArcPoint,endArcPoint)); |
2611 | - double angleBetween = angle_between(ray1, ray2, ccwToggle); |
2612 | - rad = distanceArc/sin(angleBetween/2.0); |
2613 | - return rad * -1; |
2614 | -} |
2615 | - |
2616 | -std::vector<double> FilletChamferPointArrayParam::get_times(int index, Geom::PathVector subpaths, bool last) |
2617 | -{ |
2618 | - const double tolerance = 0.001; |
2619 | - const double gapHelper = 0.00001; |
2620 | - std::pair<std::size_t, std::size_t> positions = get_positions(index, subpaths); |
2621 | - Curve *curve_it1; |
2622 | - curve_it1 = subpaths[positions.first][positions.second].duplicate(); |
2623 | - Coord it1_length = (*curve_it1).length(tolerance); |
2624 | - double time_it1, time_it2, time_it1_B, intpart; |
2625 | - if (static_cast<int>(_vector.size()) <= index){ |
2626 | - std::vector<double> out; |
2627 | - out.push_back(0); |
2628 | - out.push_back(1); |
2629 | - out.push_back(0); |
2630 | - return out; |
2631 | - } |
2632 | - time_it1 = modf(to_time(index, _vector[index][X]), &intpart); |
2633 | - if (_vector[index][Y] == 0) { |
2634 | - time_it1 = 0; |
2635 | - } |
2636 | - double resultLenght = 0; |
2637 | - if (subpaths[positions.first].closed() && last) { |
2638 | - time_it2 = modf(to_time(index - positions.second , _vector[index - positions.second ][X]), &intpart); |
2639 | - resultLenght = it1_length + to_len(index - positions.second, _vector[index - positions.second ][X]); |
2640 | - } else if (!subpaths[positions.first].closed() && last){ |
2641 | - time_it2 = 0; |
2642 | - resultLenght = 0; |
2643 | - } else { |
2644 | - time_it2 = modf(to_time(index + 1, _vector[index + 1][X]), &intpart); |
2645 | - resultLenght = it1_length + to_len( index + 1, _vector[index + 1][X]); |
2646 | - } |
2647 | - if (resultLenght > 0 && time_it2 != 0) { |
2648 | - time_it1_B = modf(to_time(index, -resultLenght), &intpart); |
2649 | - } else { |
2650 | - if (time_it2 == 0) { |
2651 | - time_it1_B = 1; |
2652 | - } else { |
2653 | - time_it1_B = gapHelper; |
2654 | - } |
2655 | - } |
2656 | - |
2657 | - if ((subpaths[positions.first].closed() && last && _vector[index - positions.second][Y] == 0) || (subpaths[positions.first].size() > positions.second + 1 && _vector[index + 1][Y] == 0)) { |
2658 | - time_it1_B = 1; |
2659 | - time_it2 = 0; |
2660 | - } |
2661 | - if (time_it1_B < time_it1) { |
2662 | - time_it1_B = time_it1 + gapHelper; |
2663 | - } |
2664 | - std::vector<double> out; |
2665 | - out.push_back(time_it1); |
2666 | - out.push_back(time_it1_B); |
2667 | - out.push_back(time_it2); |
2668 | - return out; |
2669 | -} |
2670 | - |
2671 | -std::pair<std::size_t, std::size_t> FilletChamferPointArrayParam::get_positions(int index, Geom::PathVector subpaths) |
2672 | -{ |
2673 | - int counter = -1; |
2674 | - std::size_t first = 0; |
2675 | - std::size_t second = 0; |
2676 | - for (PathVector::const_iterator path_it = subpaths.begin(); path_it != subpaths.end(); ++path_it) { |
2677 | - if (path_it->empty()) |
2678 | - continue; |
2679 | - Geom::Path::const_iterator curve_it1 = path_it->begin(); |
2680 | - Geom::Path::const_iterator curve_endit = path_it->end_default(); |
2681 | - if (path_it->closed()) { |
2682 | - const Geom::Curve &closingline = path_it->back_closed(); |
2683 | - // the closing line segment is always of type |
2684 | - // Geom::LineSegment. |
2685 | - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { |
2686 | - // closingline.isDegenerate() did not work, because it only checks for |
2687 | - // *exact* zero length, which goes wrong for relative coordinates and |
2688 | - // rounding errors... |
2689 | - // the closing line segment has zero-length. So stop before that one! |
2690 | - curve_endit = path_it->end_open(); |
2691 | - } |
2692 | - } |
2693 | - first++; |
2694 | - second = 0; |
2695 | - while (curve_it1 != curve_endit) { |
2696 | - counter++; |
2697 | - second++; |
2698 | - if(counter == index){ |
2699 | - break; |
2700 | - } |
2701 | - ++curve_it1; |
2702 | - } |
2703 | - if(counter == index){ |
2704 | - break; |
2705 | - } |
2706 | - } |
2707 | - first--; |
2708 | - second--; |
2709 | - std::pair<std::size_t, std::size_t> out(first, second); |
2710 | - return out; |
2711 | -} |
2712 | - |
2713 | -int FilletChamferPointArrayParam::last_index(int index, Geom::PathVector subpaths) |
2714 | -{ |
2715 | - int counter = -1; |
2716 | - bool inSubpath = false; |
2717 | - for (PathVector::const_iterator path_it = subpaths.begin(); path_it != subpaths.end(); ++path_it) { |
2718 | - if (path_it->empty()) |
2719 | - continue; |
2720 | - Geom::Path::const_iterator curve_it1 = path_it->begin(); |
2721 | - Geom::Path::const_iterator curve_endit = path_it->end_default(); |
2722 | - if (path_it->closed()) { |
2723 | - const Geom::Curve &closingline = path_it->back_closed(); |
2724 | - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { |
2725 | - curve_endit = path_it->end_open(); |
2726 | - } |
2727 | - } |
2728 | - while (curve_it1 != curve_endit) { |
2729 | - counter++; |
2730 | - if(counter == index){ |
2731 | - inSubpath = true; |
2732 | - } |
2733 | - ++curve_it1; |
2734 | - } |
2735 | - if(inSubpath){ |
2736 | - break; |
2737 | - } |
2738 | - } |
2739 | - if(!inSubpath){ |
2740 | - counter = -1; |
2741 | - } |
2742 | - return counter; |
2743 | -} |
2744 | - |
2745 | - |
2746 | -double FilletChamferPointArrayParam::len_to_time(int index, double len) |
2747 | -{ |
2748 | - double t = 0; |
2749 | - if (last_pwd2.size() > (unsigned) index) { |
2750 | - if (len != 0) { |
2751 | - if (last_pwd2[index][0].degreesOfFreedom() != 2) { |
2752 | - Piecewise<D2<SBasis> > u; |
2753 | - u.push_cut(0); |
2754 | - u.push(last_pwd2[index], 1); |
2755 | - std::vector<double> t_roots = roots(arcLengthSb(u) - std::abs(len)); |
2756 | - if (t_roots.size() > 0) { |
2757 | - t = t_roots[0]; |
2758 | - } |
2759 | - } else { |
2760 | - double lenghtPart = 0; |
2761 | - if (last_pwd2.size() > (unsigned) index) { |
2762 | - lenghtPart = length(last_pwd2[index], EPSILON); |
2763 | - } |
2764 | - if (std::abs(len) < lenghtPart && lenghtPart != 0) { |
2765 | - t = std::abs(len) / lenghtPart; |
2766 | - } |
2767 | - } |
2768 | - } |
2769 | - t = double(index) + t; |
2770 | - } else { |
2771 | - t = double(last_pwd2.size() - 1); |
2772 | - } |
2773 | - |
2774 | - return t; |
2775 | -} |
2776 | - |
2777 | -double FilletChamferPointArrayParam::time_to_len(int index, double time) |
2778 | -{ |
2779 | - double intpart; |
2780 | - double len = 0; |
2781 | - time = modf(time, &intpart); |
2782 | - double lenghtPart = 0; |
2783 | - if (last_pwd2.size() <= (unsigned) index || time == 0) { |
2784 | - return len; |
2785 | - } |
2786 | - if (last_pwd2[index][0].degreesOfFreedom() != 2) { |
2787 | - Piecewise<D2<SBasis> > u; |
2788 | - u.push_cut(0); |
2789 | - u.push(last_pwd2[index], 1); |
2790 | - u = portion(u, 0, time); |
2791 | - return length(u, 0.001) * -1; |
2792 | - } |
2793 | - lenghtPart = length(last_pwd2[index], EPSILON); |
2794 | - return (time * lenghtPart) * -1; |
2795 | -} |
2796 | - |
2797 | -double FilletChamferPointArrayParam::to_time(int index, double A) |
2798 | -{ |
2799 | - if (A > 0) { |
2800 | - return A; |
2801 | - } else { |
2802 | - return len_to_time(index, A); |
2803 | - } |
2804 | -} |
2805 | - |
2806 | -double FilletChamferPointArrayParam::to_len(int index, double A) |
2807 | -{ |
2808 | - if (A > 0) { |
2809 | - return time_to_len(index, A); |
2810 | - } else { |
2811 | - return A; |
2812 | - } |
2813 | -} |
2814 | - |
2815 | -void FilletChamferPointArrayParam::set_oncanvas_looks(SPKnotShapeType shape, |
2816 | - SPKnotModeType mode, |
2817 | - guint32 color) |
2818 | -{ |
2819 | - knot_shape = shape; |
2820 | - knot_mode = mode; |
2821 | - knot_color = color; |
2822 | -} |
2823 | - |
2824 | -FilletChamferPointArrayParamKnotHolderEntity:: |
2825 | -FilletChamferPointArrayParamKnotHolderEntity( |
2826 | - FilletChamferPointArrayParam *p, unsigned int index) |
2827 | - : _pparam(p), _index(index) {} |
2828 | - |
2829 | -void FilletChamferPointArrayParamKnotHolderEntity::knot_set(Point const &p, |
2830 | - Point const &/*origin*/, |
2831 | - guint state) |
2832 | -{ |
2833 | - using namespace Geom; |
2834 | - |
2835 | - if (!valid_index(_index)) { |
2836 | - return; |
2837 | - } |
2838 | - Piecewise<D2<SBasis> > const &pwd2 = _pparam->get_pwd2(); |
2839 | - double t = nearest_time(p, pwd2[_index]); |
2840 | - Geom::Point const s = snap_knot_position(pwd2[_index].valueAt(t), state); |
2841 | - t = nearest_time(s, pwd2[_index]); |
2842 | - if (t == 1) { |
2843 | - t = 0.9999; |
2844 | - } |
2845 | - t += _index; |
2846 | - |
2847 | - if (_pparam->_vector.at(_index)[X] <= 0) { |
2848 | - _pparam->_vector.at(_index) = |
2849 | - Point(_pparam->time_to_len(_index, t), _pparam->_vector.at(_index)[Y]); |
2850 | - } else { |
2851 | - _pparam->_vector.at(_index) = Point(t, _pparam->_vector.at(_index)[Y]); |
2852 | - } |
2853 | - sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); |
2854 | -} |
2855 | - |
2856 | -Point FilletChamferPointArrayParamKnotHolderEntity::knot_get() const |
2857 | -{ |
2858 | - using namespace Geom; |
2859 | - |
2860 | - if (!valid_index(_index)) { |
2861 | - return Point(infinity(), infinity()); |
2862 | - } |
2863 | - |
2864 | - Piecewise<D2<SBasis> > const &pwd2 = _pparam->get_pwd2(); |
2865 | - |
2866 | - double time_it = _pparam->to_time(_index, _pparam->_vector.at(_index)[X]); |
2867 | - Point canvas_point = pwd2.valueAt(time_it); |
2868 | - |
2869 | - _pparam->updateCanvasIndicators(); |
2870 | - return canvas_point; |
2871 | - |
2872 | -} |
2873 | - |
2874 | -void FilletChamferPointArrayParamKnotHolderEntity::knot_click(guint state) |
2875 | -{ |
2876 | - if (state & GDK_CONTROL_MASK) { |
2877 | - if (state & GDK_MOD1_MASK) { |
2878 | - _pparam->_vector.at(_index) = Point(_index, _pparam->_vector.at(_index)[Y]); |
2879 | - _pparam->param_set_and_write_new_value(_pparam->_vector); |
2880 | - sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); |
2881 | - }else{ |
2882 | - using namespace Geom; |
2883 | - int type = (int)_pparam->_vector.at(_index)[Y]; |
2884 | - if (type >=3000 && type < 4000){ |
2885 | - type = 3; |
2886 | - } |
2887 | - if (type >=4000 && type < 5000){ |
2888 | - type = 4; |
2889 | - } |
2890 | - switch(type){ |
2891 | - case 1: |
2892 | - type = 2; |
2893 | - break; |
2894 | - case 2: |
2895 | - type = _pparam->chamfer_steps + 3000; |
2896 | - break; |
2897 | - case 3: |
2898 | - type = _pparam->chamfer_steps + 4000; |
2899 | - break; |
2900 | - default: |
2901 | - type = 1; |
2902 | - break; |
2903 | - } |
2904 | - _pparam->_vector.at(_index) = Point(_pparam->_vector.at(_index)[X], (double)type); |
2905 | - _pparam->param_set_and_write_new_value(_pparam->_vector); |
2906 | - sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); |
2907 | - const gchar *tip; |
2908 | - if (type >=3000 && type < 4000){ |
2909 | - tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toggle type, " |
2910 | - "<b>Shift+Click</b> open dialog, " |
2911 | - "<b>Ctrl+Alt+Click</b> reset"); |
2912 | - } else if (type >=4000 && type < 5000) { |
2913 | - tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toggle type, " |
2914 | - "<b>Shift+Click</b> open dialog, " |
2915 | - "<b>Ctrl+Alt+Click</b> reset"); |
2916 | - } else if (type == 2) { |
2917 | - tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toggle type, " |
2918 | - "<b>Shift+Click</b> open dialog, " |
2919 | - "<b>Ctrl+Alt+Click</b> reset"); |
2920 | - } else { |
2921 | - tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toggle type, " |
2922 | - "<b>Shift+Click</b> open dialog, " |
2923 | - "<b>Ctrl+Alt+Click</b> reset"); |
2924 | - } |
2925 | - this->knot->tip = g_strdup(tip); |
2926 | - this->knot->show(); |
2927 | - } |
2928 | - } else if (state & GDK_SHIFT_MASK) { |
2929 | - double xModified = _pparam->_vector.at(_index).x(); |
2930 | - if(xModified < 0 && !_pparam->use_distance){ |
2931 | - xModified = _pparam->len_to_rad(_index, _pparam->_vector.at(_index).x()); |
2932 | - } |
2933 | - Geom::PathVector subpaths = path_from_piecewise(_pparam->last_pwd2, 0.1); |
2934 | - std::pair<std::size_t, std::size_t> positions = _pparam->get_positions(_index, subpaths); |
2935 | - D2<SBasis> A = _pparam->last_pwd2[_pparam->last_index(_index, subpaths)]; |
2936 | - if(positions.second != 0){ |
2937 | - A = _pparam->last_pwd2[_index-1]; |
2938 | - } |
2939 | - D2<SBasis> B = _pparam->last_pwd2[_index]; |
2940 | - bool aprox = (A[0].degreesOfFreedom() != 2 || B[0].degreesOfFreedom() != 2) && !_pparam->use_distance?true:false; |
2941 | - Geom::Point offset = Geom::Point(xModified, _pparam->_vector.at(_index).y()); |
2942 | - Inkscape::UI::Dialogs::FilletChamferPropertiesDialog::showDialog( |
2943 | - this->desktop, offset, this, _pparam->use_distance, aprox); |
2944 | - } |
2945 | - |
2946 | -} |
2947 | - |
2948 | -void FilletChamferPointArrayParamKnotHolderEntity::knot_set_offset( |
2949 | - Geom::Point offset) |
2950 | -{ |
2951 | - double xModified = offset.x(); |
2952 | - if(xModified < 0 && !_pparam->use_distance){ |
2953 | - xModified = _pparam->rad_to_len(_index, offset.x()); |
2954 | - } |
2955 | - _pparam->_vector.at(_index) = Geom::Point(xModified, offset.y()); |
2956 | - this->parent_holder->knot_ungrabbed_handler(this->knot, 0); |
2957 | -} |
2958 | - |
2959 | -void FilletChamferPointArrayParam::addKnotHolderEntities(KnotHolder *knotholder, SPItem *item) { |
2960 | - recalculate_knots(get_pwd2()); |
2961 | - for (unsigned int i = 0; i < _vector.size(); ++i) { |
2962 | - if (_vector[i][Y] <= 0) { |
2963 | - continue; |
2964 | - } |
2965 | - const gchar *tip; |
2966 | - if (_vector[i][Y] >=3000 && _vector[i][Y] < 4000){ |
2967 | - tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toggle type, " |
2968 | - "<b>Shift+Click</b> open dialog, " |
2969 | - "<b>Ctrl+Alt+Click</b> reset"); |
2970 | - } else if (_vector[i][Y] >=4000 && _vector[i][Y] < 5000) { |
2971 | - tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toggle type, " |
2972 | - "<b>Shift+Click</b> open dialog, " |
2973 | - "<b>Ctrl+Alt+Click</b> reset"); |
2974 | - } else if (_vector[i][Y] == 2) { |
2975 | - tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toggle type, " |
2976 | - "<b>Shift+Click</b> open dialog, " |
2977 | - "<b>Ctrl+Alt+Click</b> reset"); |
2978 | - } else { |
2979 | - tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toggle type, " |
2980 | - "<b>Shift+Click</b> open dialog, " |
2981 | - "<b>Ctrl+Alt+Click</b> reset"); |
2982 | - } |
2983 | - FilletChamferPointArrayParamKnotHolderEntity *e = |
2984 | - new FilletChamferPointArrayParamKnotHolderEntity(this, i); |
2985 | - e->create(NULL, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, _(tip), |
2986 | - knot_shape, knot_mode, knot_color); |
2987 | - knotholder->add(e); |
2988 | - } |
2989 | - updateCanvasIndicators(); |
2990 | -} |
2991 | - |
2992 | -} /* namespace LivePathEffect */ |
2993 | - |
2994 | -} /* namespace Inkscape */ |
2995 | - |
2996 | -/* |
2997 | - Local Variables: |
2998 | - mode:c++ |
2999 | - c-file-style:"stroustrup" |
3000 | - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) |
3001 | - indent-tabs-mode:nil |
3002 | - fill-column:99 |
3003 | - End: |
3004 | -*/ |
3005 | -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : |
3006 | |
3007 | === removed file 'src/live_effects/parameter/filletchamferpointarray.h' |
3008 | --- src/live_effects/parameter/filletchamferpointarray.h 2017-04-29 00:01:22 +0000 |
3009 | +++ src/live_effects/parameter/filletchamferpointarray.h 1970-01-01 00:00:00 +0000 |
3010 | @@ -1,123 +0,0 @@ |
3011 | -#ifndef INKSCAPE_LIVEPATHEFFECT_FILLET_CHAMFER_POINT_ARRAY_H |
3012 | -#define INKSCAPE_LIVEPATHEFFECT_FILLET_CHAMFER_POINT_ARRAY_H |
3013 | - |
3014 | -/* |
3015 | - * Inkscape::LivePathEffectParameters |
3016 | - * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es> |
3017 | - * Special thanks to Johan Engelen for the base of the effect -powerstroke- |
3018 | - * Also to ScislaC for point me to the idea |
3019 | - * Also su_v for his construvtive feedback and time |
3020 | - * and finaly to Liam P. White for his big help on coding, that save me a lot of |
3021 | - * hours |
3022 | - * Released under GNU GPL, read the file 'COPYING' for more information |
3023 | - */ |
3024 | - |
3025 | -#include <glib.h> |
3026 | -#include <2geom/point.h> |
3027 | - |
3028 | -#include "live_effects/parameter/array.h" |
3029 | - |
3030 | -#include "knot-holder-entity.h" |
3031 | - |
3032 | -namespace Inkscape { |
3033 | - |
3034 | -namespace LivePathEffect { |
3035 | - |
3036 | -class FilletChamferPointArrayParamKnotHolderEntity; |
3037 | - |
3038 | -class FilletChamferPointArrayParam : public ArrayParam<Geom::Point> { |
3039 | -public: |
3040 | - FilletChamferPointArrayParam(const Glib::ustring &label, |
3041 | - const Glib::ustring &tip, |
3042 | - const Glib::ustring &key, |
3043 | - Inkscape::UI::Widget::Registry *wr, |
3044 | - Effect *effect); |
3045 | - virtual ~FilletChamferPointArrayParam(); |
3046 | - |
3047 | - virtual Gtk::Widget *param_newWidget(); |
3048 | - |
3049 | - virtual void param_transform_multiply(Geom::Affine const &postmul, |
3050 | - bool /*set*/); |
3051 | - |
3052 | - void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, |
3053 | - guint32 color); |
3054 | - virtual double to_time(int index, double A); |
3055 | - virtual double to_len(int index, double A); |
3056 | - virtual double rad_to_len(int index, double rad); |
3057 | - virtual double len_to_rad(int index, double len); |
3058 | - virtual double len_to_time(int index, double len); |
3059 | - virtual double time_to_len(int index, double time); |
3060 | - virtual std::pair<std::size_t, std::size_t> get_positions(int index, Geom::PathVector subpaths); |
3061 | - virtual int last_index(int index, Geom::PathVector subpaths); |
3062 | - std::vector<double> get_times(int index, Geom::PathVector subpaths, bool last); |
3063 | - virtual void set_helper_size(int hs); |
3064 | - virtual void set_use_distance(bool use_knot_distance); |
3065 | - virtual void set_chamfer_steps(int value_chamfer_steps); |
3066 | - virtual void addCanvasIndicators(SPLPEItem const *lpeitem, |
3067 | - std::vector<Geom::PathVector> &hp_vec); |
3068 | - virtual void param_update_default(const gchar * default_value){}; |
3069 | - virtual bool providesKnotHolderEntities() const { |
3070 | - return true; |
3071 | - } |
3072 | - virtual void updateCanvasIndicators(); |
3073 | - virtual void addKnotHolderEntities(KnotHolder *knotholder, SPItem *item); |
3074 | - |
3075 | - void set_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in, |
3076 | - Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_normal_in); |
3077 | - Geom::Piecewise<Geom::D2<Geom::SBasis> > const &get_pwd2() const { |
3078 | - return last_pwd2; |
3079 | - } |
3080 | - Geom::Piecewise<Geom::D2<Geom::SBasis> > const &get_pwd2_normal() const { |
3081 | - return last_pwd2_normal; |
3082 | - } |
3083 | - |
3084 | - void recalculate_controlpoints_for_new_pwd2( |
3085 | - Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in); |
3086 | - void recalculate_knots( |
3087 | - Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in); |
3088 | - friend class FilletChamferPointArrayParamKnotHolderEntity; |
3089 | - |
3090 | -private: |
3091 | - FilletChamferPointArrayParam(const FilletChamferPointArrayParam &); |
3092 | - FilletChamferPointArrayParam &operator=(const FilletChamferPointArrayParam &); |
3093 | - |
3094 | - SPKnotShapeType knot_shape; |
3095 | - SPKnotModeType knot_mode; |
3096 | - guint32 knot_color; |
3097 | - int helper_size; |
3098 | - int chamfer_steps; |
3099 | - bool use_distance; |
3100 | - Geom::PathVector hp; |
3101 | - |
3102 | - Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2; |
3103 | - Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2_normal; |
3104 | -}; |
3105 | - |
3106 | -class FilletChamferPointArrayParamKnotHolderEntity : public KnotHolderEntity { |
3107 | -public: |
3108 | - FilletChamferPointArrayParamKnotHolderEntity(FilletChamferPointArrayParam *p, |
3109 | - unsigned int index); |
3110 | - virtual ~FilletChamferPointArrayParamKnotHolderEntity() {} |
3111 | - |
3112 | - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, |
3113 | - guint state); |
3114 | - virtual Geom::Point knot_get() const; |
3115 | - virtual void knot_click(guint state); |
3116 | - virtual void knot_set_offset(Geom::Point offset); |
3117 | - |
3118 | - /*Checks whether the index falls within the size of the parameter's vector*/ |
3119 | - bool valid_index(unsigned int index) const { |
3120 | - return (_pparam->_vector.size() > index); |
3121 | - } |
3122 | - ; |
3123 | - |
3124 | -private: |
3125 | - FilletChamferPointArrayParam *_pparam; |
3126 | - unsigned int _index; |
3127 | -}; |
3128 | - |
3129 | -} //namespace LivePathEffect |
3130 | - |
3131 | -} //namespace Inkscape |
3132 | - |
3133 | -#endif |
3134 | |
3135 | === added file 'src/live_effects/parameter/satellitesarray.cpp' |
3136 | --- src/live_effects/parameter/satellitesarray.cpp 1970-01-01 00:00:00 +0000 |
3137 | +++ src/live_effects/parameter/satellitesarray.cpp 2017-05-06 17:46:29 +0000 |
3138 | @@ -0,0 +1,583 @@ |
3139 | +/* |
3140 | + * Author(s): |
3141 | + * Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es> |
3142 | + * |
3143 | + * Copyright (C) 2014 Author(s) |
3144 | + * Released under GNU GPL, read the file 'COPYING' for more information |
3145 | + */ |
3146 | + |
3147 | +#include "knotholder.h" |
3148 | +#include "ui/dialog/lpe-fillet-chamfer-properties.h" |
3149 | +#include "live_effects/parameter/satellitesarray.h" |
3150 | +#include "live_effects/effect.h" |
3151 | +#include "sp-lpe-item.h" |
3152 | +#include "inkscape.h" |
3153 | +#include <preferences.h> |
3154 | +// TODO due to internal breakage in glibmm headers, |
3155 | +// this has to be included last. |
3156 | +#include <glibmm/i18n.h> |
3157 | + |
3158 | +namespace Inkscape { |
3159 | + |
3160 | +namespace LivePathEffect { |
3161 | + |
3162 | +SatellitesArrayParam::SatellitesArrayParam(const Glib::ustring &label, |
3163 | + const Glib::ustring &tip, |
3164 | + const Glib::ustring &key, |
3165 | + Inkscape::UI::Widget::Registry *wr, |
3166 | + Effect *effect) |
3167 | + : ArrayParam<std::vector<Satellite> >(label, tip, key, wr, effect, 0), _knoth(NULL) |
3168 | +{ |
3169 | + _knot_shape = SP_KNOT_SHAPE_DIAMOND; |
3170 | + _knot_mode = SP_KNOT_MODE_XOR; |
3171 | + _knot_color = 0xAAFF8800; |
3172 | + _helper_size = 0; |
3173 | + _use_distance = false; |
3174 | + _global_knot_hide = false; |
3175 | + _current_zoom = 0; |
3176 | + _effectType = FILLET_CHAMFER; |
3177 | + _last_pathvector_satellites = NULL; |
3178 | +} |
3179 | + |
3180 | + |
3181 | +void SatellitesArrayParam::set_oncanvas_looks(SPKnotShapeType shape, |
3182 | + SPKnotModeType mode, |
3183 | + guint32 color) |
3184 | +{ |
3185 | + _knot_shape = shape; |
3186 | + _knot_mode = mode; |
3187 | + _knot_color = color; |
3188 | +} |
3189 | + |
3190 | +void SatellitesArrayParam::setPathVectorSatellites(PathVectorSatellites *pathVectorSatellites, bool write) |
3191 | +{ |
3192 | + _last_pathvector_satellites = pathVectorSatellites; |
3193 | + if (write) { |
3194 | + param_set_and_write_new_value(_last_pathvector_satellites->getSatellites()); |
3195 | + } else { |
3196 | + param_setValue(_last_pathvector_satellites->getSatellites()); |
3197 | + } |
3198 | +} |
3199 | + |
3200 | +void SatellitesArrayParam::setUseDistance(bool use_knot_distance) |
3201 | +{ |
3202 | + _use_distance = use_knot_distance; |
3203 | +} |
3204 | + |
3205 | +void SatellitesArrayParam::setCurrentZoom(double current_zoom) |
3206 | +{ |
3207 | + _current_zoom = current_zoom; |
3208 | +} |
3209 | + |
3210 | +void SatellitesArrayParam::setGlobalKnotHide(bool global_knot_hide) |
3211 | +{ |
3212 | + _global_knot_hide = global_knot_hide; |
3213 | +} |
3214 | +void SatellitesArrayParam::setEffectType(EffectType et) |
3215 | +{ |
3216 | + _effectType = et; |
3217 | +} |
3218 | + |
3219 | +void SatellitesArrayParam::setHelperSize(int hs) |
3220 | +{ |
3221 | + _helper_size = hs; |
3222 | + updateCanvasIndicators(); |
3223 | +} |
3224 | + |
3225 | +void SatellitesArrayParam::updateCanvasIndicators(bool mirror) |
3226 | +{ |
3227 | + if (!_last_pathvector_satellites) { |
3228 | + return; |
3229 | + } |
3230 | + |
3231 | + if (!_hp.empty()) { |
3232 | + _hp.clear(); |
3233 | + } |
3234 | + Geom::PathVector pathv = _last_pathvector_satellites->getPathVector(); |
3235 | + if (pathv.empty()) { |
3236 | + return; |
3237 | + } |
3238 | + if (mirror == true) { |
3239 | + _hp.clear(); |
3240 | + } |
3241 | + if (_effectType == FILLET_CHAMFER) { |
3242 | + for (size_t i = 0; i < _vector.size(); ++i) { |
3243 | + for (size_t j = 0; j < _vector[i].size(); ++j) { |
3244 | + if (_vector[i][j].hidden || //Ignore if hidden |
3245 | + (!_vector[i][j].has_mirror && mirror == true) || //Ignore if not have mirror and we are in mirror loop |
3246 | + _vector[i][j].amount == 0 || //no helper in 0 value |
3247 | + pathv[i].size() == j || //ignore last satellite in open paths with fillet chamfer effect |
3248 | + (!pathv[i].closed() && j == 0)) //ignore first satellites on open paths |
3249 | + { |
3250 | + continue; |
3251 | + } |
3252 | + Geom::Curve *curve_in = pathv[i][j].duplicate(); |
3253 | + double pos = 0; |
3254 | + bool overflow = false; |
3255 | + double size_out = _vector[i][j].arcDistance(*curve_in); |
3256 | + double lenght_out = curve_in->length(); |
3257 | + gint previous_index = j - 1; //Always are previous index because we skip first satellite on open paths |
3258 | + if (j == 0 && pathv[i].closed()) { |
3259 | + previous_index = pathv[i].size() - 1; |
3260 | + } |
3261 | + if ( previous_index < 0 ) { |
3262 | + return; |
3263 | + } |
3264 | + double lenght_in = pathv.curveAt(previous_index).length(); |
3265 | + if (mirror) { |
3266 | + curve_in = const_cast<Geom::Curve *>(&pathv.curveAt(previous_index)); |
3267 | + pos = _vector[i][j].time(size_out, true, *curve_in); |
3268 | + if (lenght_out < size_out) { |
3269 | + overflow = true; |
3270 | + } |
3271 | + } else { |
3272 | + pos = _vector[i][j].time(*curve_in); |
3273 | + if (lenght_in < size_out) { |
3274 | + overflow = true; |
3275 | + } |
3276 | + } |
3277 | + if (pos <= 0 || pos >= 1) { |
3278 | + continue; |
3279 | + } |
3280 | + Geom::Point point_a = curve_in->pointAt(pos); |
3281 | + Geom::Point deriv_a = unit_vector(derivative(curve_in->toSBasis()).pointAt(pos)); |
3282 | + Geom::Rotate rot(Geom::Rotate::from_degrees(-90)); |
3283 | + deriv_a = deriv_a * rot; |
3284 | + Geom::Point point_c = point_a - deriv_a * _helper_size; |
3285 | + Geom::Point point_d = point_a + deriv_a * _helper_size; |
3286 | + Geom::Ray ray_1(point_c, point_d); |
3287 | + char const *svgd = "M 1,0.25 0.5,0 1,-0.25 M 1,0.5 0,0 1,-0.5"; |
3288 | + Geom::PathVector pathv = sp_svg_read_pathv(svgd); |
3289 | + Geom::Affine aff = Geom::Affine(); |
3290 | + aff *= Geom::Scale(_helper_size); |
3291 | + if (mirror) { |
3292 | + aff *= Geom::Rotate(ray_1.angle() - Geom::rad_from_deg(90)); |
3293 | + } else { |
3294 | + aff *= Geom::Rotate(ray_1.angle() - Geom::rad_from_deg(270)); |
3295 | + } |
3296 | + aff *= Geom::Translate(curve_in->pointAt(pos)); |
3297 | + pathv *= aff; |
3298 | + _hp.push_back(pathv[0]); |
3299 | + _hp.push_back(pathv[1]); |
3300 | + if (overflow) { |
3301 | + double diameter = _helper_size; |
3302 | + if (_helper_size == 0) { |
3303 | + diameter = 15; |
3304 | + char const *svgd; |
3305 | + svgd = "M 0.7,0.35 A 0.35,0.35 0 0 1 0.35,0.7 0.35,0.35 0 0 1 0,0.35 " |
3306 | + "0.35,0.35 0 0 1 0.35,0 0.35,0.35 0 0 1 0.7,0.35 Z"; |
3307 | + Geom::PathVector pathv = sp_svg_read_pathv(svgd); |
3308 | + aff = Geom::Affine(); |
3309 | + aff *= Geom::Scale(diameter); |
3310 | + aff *= Geom::Translate(point_a - Geom::Point(diameter * 0.35, diameter * 0.35)); |
3311 | + pathv *= aff; |
3312 | + _hp.push_back(pathv[0]); |
3313 | + } else { |
3314 | + char const *svgd; |
3315 | + svgd = "M 0 -1.32 A 1.32 1.32 0 0 0 -1.32 0 A 1.32 1.32 0 0 0 0 1.32 A " |
3316 | + "1.32 1.32 0 0 0 1.18 0.59 L 0 0 L 1.18 -0.59 A 1.32 1.32 0 0 0 " |
3317 | + "0 -1.32 z"; |
3318 | + Geom::PathVector pathv = sp_svg_read_pathv(svgd); |
3319 | + aff = Geom::Affine(); |
3320 | + aff *= Geom::Scale(_helper_size / 2.0); |
3321 | + if (mirror) { |
3322 | + aff *= Geom::Rotate(ray_1.angle() - Geom::rad_from_deg(90)); |
3323 | + } else { |
3324 | + aff *= Geom::Rotate(ray_1.angle() - Geom::rad_from_deg(270)); |
3325 | + } |
3326 | + aff *= Geom::Translate(curve_in->pointAt(pos)); |
3327 | + pathv *= aff; |
3328 | + _hp.push_back(pathv[0]); |
3329 | + } |
3330 | + } |
3331 | + } |
3332 | + } |
3333 | + } |
3334 | + if (!_knot_reset_helper.empty()) { |
3335 | + _hp.insert(_hp.end(), _knot_reset_helper.begin(), _knot_reset_helper.end() ); |
3336 | + } |
3337 | + if (mirror) { |
3338 | + updateCanvasIndicators(false); |
3339 | + } |
3340 | +} |
3341 | +void SatellitesArrayParam::updateCanvasIndicators() |
3342 | +{ |
3343 | + updateCanvasIndicators(true); |
3344 | +} |
3345 | + |
3346 | +void SatellitesArrayParam::addCanvasIndicators( |
3347 | + SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) |
3348 | +{ |
3349 | + hp_vec.push_back(_hp); |
3350 | +} |
3351 | + |
3352 | +void SatellitesArrayParam::param_transform_multiply(Geom::Affine const &postmul, bool /*set*/) |
3353 | +{ |
3354 | + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
3355 | + |
3356 | + if (prefs->getBool("/options/transform/rectcorners", true)) { |
3357 | + for (size_t i = 0; i < _vector.size(); ++i) { |
3358 | + for (size_t j = 0; j < _vector[i].size(); ++j) { |
3359 | + if (!_vector[i][j].is_time && _vector[i][j].amount > 0) { |
3360 | + _vector[i][j].amount = _vector[i][j].amount * ((postmul.expansionX() + postmul.expansionY()) / 2); |
3361 | + } |
3362 | + } |
3363 | + } |
3364 | + param_set_and_write_new_value(_vector); |
3365 | + } |
3366 | +} |
3367 | + |
3368 | +void SatellitesArrayParam::addKnotHolderEntities(KnotHolder *knotholder, |
3369 | + SPItem *item, |
3370 | + bool mirror) |
3371 | +{ |
3372 | + if (!_last_pathvector_satellites) { |
3373 | + return; |
3374 | + } |
3375 | + Geom::PathVector pathv = _last_pathvector_satellites->getPathVector(); |
3376 | + size_t index = 0; |
3377 | + for (size_t i = 0; i < _vector.size(); ++i) { |
3378 | + for (size_t j = 0; j < _vector[i].size(); ++j) { |
3379 | + if (!_vector[i][j].has_mirror && mirror) { |
3380 | + continue; |
3381 | + } |
3382 | + SatelliteType type = _vector[i][j].satellite_type; |
3383 | + if (mirror && i == 0 && j == 0) { |
3384 | + index = index + _last_pathvector_satellites->getTotalSatellites(); |
3385 | + } |
3386 | + using namespace Geom; |
3387 | + //If is for filletChamfer effect... |
3388 | + if (_effectType == FILLET_CHAMFER) { |
3389 | + const gchar *tip; |
3390 | + if (type == CHAMFER) { |
3391 | + tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toggles type, " |
3392 | + "<b>Shift+Click</b> open dialog, " |
3393 | + "<b>Ctrl+Alt+Click</b> reset"); |
3394 | + } else if (type == INVERSE_CHAMFER) { |
3395 | + tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toggles type, " |
3396 | + "<b>Shift+Click</b> open dialog, " |
3397 | + "<b>Ctrl+Alt+Click</b> reset"); |
3398 | + } else if (type == INVERSE_FILLET) { |
3399 | + tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toggles type, " |
3400 | + "<b>Shift+Click</b> open dialog, " |
3401 | + "<b>Ctrl+Alt+Click</b> reset"); |
3402 | + } else { |
3403 | + tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toggles type, " |
3404 | + "<b>Shift+Click</b> open dialog, " |
3405 | + "<b>Ctrl+Alt+Click</b> reset"); |
3406 | + } |
3407 | + FilletChamferKnotHolderEntity *e = new FilletChamferKnotHolderEntity(this, index); |
3408 | + e->create(NULL, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, _(tip),_knot_shape, _knot_mode, _knot_color); |
3409 | + knotholder->add(e); |
3410 | + } |
3411 | + index++; |
3412 | + } |
3413 | + } |
3414 | + if (mirror) { |
3415 | + addKnotHolderEntities(knotholder, item, false); |
3416 | + } |
3417 | +} |
3418 | + |
3419 | +void SatellitesArrayParam::addKnotHolderEntities(KnotHolder *knotholder, |
3420 | + SPItem *item) |
3421 | +{ |
3422 | + _knoth = knotholder; |
3423 | + addKnotHolderEntities(knotholder, item, true); |
3424 | +} |
3425 | + |
3426 | +FilletChamferKnotHolderEntity::FilletChamferKnotHolderEntity( |
3427 | + SatellitesArrayParam *p, size_t index) |
3428 | + : _pparam(p), _index(index) {} |
3429 | + |
3430 | +void FilletChamferKnotHolderEntity::knot_set(Geom::Point const &p, |
3431 | + Geom::Point const &/*origin*/, |
3432 | + guint state) |
3433 | +{ |
3434 | + if (!_pparam->_last_pathvector_satellites) { |
3435 | + return; |
3436 | + } |
3437 | + size_t total_satellites = _pparam->_last_pathvector_satellites->getTotalSatellites(); |
3438 | + bool is_mirror = false; |
3439 | + size_t index = _index; |
3440 | + if (_index >= total_satellites) { |
3441 | + index = _index - total_satellites; |
3442 | + is_mirror = true; |
3443 | + } |
3444 | + std::pair<size_t, size_t> index_data = _pparam->_last_pathvector_satellites->getIndexData(index); |
3445 | + size_t path_index = index_data.first; |
3446 | + size_t curve_index = index_data.second; |
3447 | + |
3448 | + Geom::Point s = snap_knot_position(p, state); |
3449 | + if (!valid_index(path_index, curve_index)) { |
3450 | + return; |
3451 | + } |
3452 | + Satellite satellite = _pparam->_vector[path_index][curve_index]; |
3453 | + Geom::PathVector pathv = _pparam->_last_pathvector_satellites->getPathVector(); |
3454 | + if (satellite.hidden || |
3455 | + (!pathv[path_index].closed() && curve_index == 0) ||//ignore first satellites on open paths |
3456 | + pathv[path_index].size() == curve_index) //ignore last satellite in open paths with fillet chamfer effect |
3457 | + { |
3458 | + return; |
3459 | + } |
3460 | + gint previous_index = curve_index - 1; |
3461 | + if (curve_index == 0 && pathv[path_index].closed()) { |
3462 | + previous_index = pathv[path_index].size() - 1; |
3463 | + } |
3464 | + if ( previous_index < 0 ) { |
3465 | + return; |
3466 | + } |
3467 | + Geom::Curve const &curve_in = pathv[path_index][previous_index]; |
3468 | + double mirror_time = Geom::nearest_time(s, curve_in); |
3469 | + Geom::Point mirror = curve_in.pointAt(mirror_time); |
3470 | + double normal_time = Geom::nearest_time(s, pathv[path_index][curve_index]); |
3471 | + Geom::Point normal = pathv[path_index][curve_index].pointAt(normal_time); |
3472 | + double distance_mirror = Geom::distance(mirror,s); |
3473 | + double distance_normal = Geom::distance(normal,s); |
3474 | + if (Geom::are_near(s, pathv[path_index][curve_index].initialPoint(), 1.5 / _pparam->_current_zoom)) { |
3475 | + satellite.amount = 0; |
3476 | + } else if (distance_mirror < distance_normal) { |
3477 | + double time_start = 0; |
3478 | + Satellites satellites = _pparam->_last_pathvector_satellites->getSatellites(); |
3479 | + time_start = satellites[path_index][previous_index].time(curve_in); |
3480 | + if (time_start > mirror_time) { |
3481 | + mirror_time = time_start; |
3482 | + } |
3483 | + double size = arcLengthAt(mirror_time, curve_in); |
3484 | + double amount = curve_in.length() - size; |
3485 | + if (satellite.is_time) { |
3486 | + amount = timeAtArcLength(amount, pathv[path_index][curve_index]); |
3487 | + } |
3488 | + satellite.amount = amount; |
3489 | + } else { |
3490 | + satellite.setPosition(s, pathv[path_index][curve_index]); |
3491 | + } |
3492 | + _pparam->_knot_reset_helper.clear(); |
3493 | + if (satellite.amount == 0) { |
3494 | + char const *svgd; |
3495 | + svgd = "M -5.39,8.78 -9.13,5.29 -10.38,10.28 Z M -7.22,7.07 -3.43,3.37 m -1.95,-12.16 -3.74,3.5 -1.26,-5 z " |
3496 | + "m -1.83,1.71 3.78,3.7 M 5.24,8.78 8.98,5.29 10.24,10.28 Z " |
3497 | + "M 7.07,7.07 3.29,3.37 M 5.24,-8.78 l 3.74,3.5 1.26,-5 z M 7.07,-7.07 3.29,-3.37"; |
3498 | + _pparam->_knot_reset_helper = sp_svg_read_pathv(svgd); |
3499 | + _pparam->_knot_reset_helper *= Geom::Affine(_pparam->_helper_size * 0.1,0,0,_pparam->_helper_size * 0.1,0,0) * Geom::Translate(pathv[path_index][curve_index].initialPoint()); |
3500 | + } |
3501 | + _pparam->_vector[path_index][curve_index] = satellite; |
3502 | + sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); |
3503 | +} |
3504 | + |
3505 | +Geom::Point FilletChamferKnotHolderEntity::knot_get() const |
3506 | +{ |
3507 | + if (!_pparam->_last_pathvector_satellites || _pparam->_global_knot_hide) { |
3508 | + return Geom::Point(Geom::infinity(), Geom::infinity()); |
3509 | + } |
3510 | + Geom::Point tmp_point; |
3511 | + size_t total_satellites = _pparam->_last_pathvector_satellites->getTotalSatellites(); |
3512 | + bool is_mirror = false; |
3513 | + size_t index = _index; |
3514 | + if (_index >= total_satellites) { |
3515 | + index = _index - total_satellites; |
3516 | + is_mirror = true; |
3517 | + } |
3518 | + std::pair<size_t, size_t> index_data = _pparam->_last_pathvector_satellites->getIndexData(index); |
3519 | + size_t path_index = index_data.first; |
3520 | + size_t curve_index = index_data.second; |
3521 | + if (!valid_index(path_index, curve_index)) { |
3522 | + return Geom::Point(Geom::infinity(), Geom::infinity()); |
3523 | + } |
3524 | + Satellite satellite = _pparam->_vector[path_index][curve_index]; |
3525 | + Geom::PathVector pathv = _pparam->_last_pathvector_satellites->getPathVector(); |
3526 | + if (satellite.hidden || |
3527 | + (!pathv[path_index].closed() && curve_index == 0) ||//ignore first satellites on open paths |
3528 | + pathv[path_index].size() == curve_index) //ignore last satellite in open paths with fillet chamfer effect |
3529 | + { |
3530 | + return Geom::Point(Geom::infinity(), Geom::infinity()); |
3531 | + } |
3532 | + this->knot->show(); |
3533 | + if (is_mirror) { |
3534 | + gint previous_index = curve_index - 1; |
3535 | + if (curve_index == 0 && pathv[path_index].closed()) { |
3536 | + previous_index = pathv[path_index].size() - 1; |
3537 | + } |
3538 | + if ( previous_index < 0 ) { |
3539 | + return Geom::Point(Geom::infinity(), Geom::infinity()); |
3540 | + } |
3541 | + Geom::Curve const &curve_in = pathv[path_index][previous_index]; |
3542 | + double s = satellite.arcDistance(pathv[path_index][curve_index]); |
3543 | + double t = satellite.time(s, true, curve_in); |
3544 | + if (t > 1) { |
3545 | + t = 1; |
3546 | + } |
3547 | + if (t < 0) { |
3548 | + t = 0; |
3549 | + } |
3550 | + double time_start = 0; |
3551 | + time_start = _pparam->_last_pathvector_satellites->getSatellites()[path_index][previous_index].time(curve_in); |
3552 | + if (time_start > t) { |
3553 | + t = time_start; |
3554 | + } |
3555 | + tmp_point = (curve_in).pointAt(t); |
3556 | + } else { |
3557 | + tmp_point = satellite.getPosition(pathv[path_index][curve_index]); |
3558 | + } |
3559 | + Geom::Point const canvas_point = tmp_point; |
3560 | + _pparam->updateCanvasIndicators(); |
3561 | + return canvas_point; |
3562 | +} |
3563 | + |
3564 | +void FilletChamferKnotHolderEntity::knot_click(guint state) |
3565 | +{ |
3566 | + if (!_pparam->_last_pathvector_satellites) { |
3567 | + return; |
3568 | + } |
3569 | + size_t total_satellites = _pparam->_last_pathvector_satellites->getTotalSatellites(); |
3570 | + bool is_mirror = false; |
3571 | + size_t index = _index; |
3572 | + if (_index >= total_satellites) { |
3573 | + index = _index - total_satellites; |
3574 | + is_mirror = true; |
3575 | + } |
3576 | + std::pair<size_t, size_t> index_data = _pparam->_last_pathvector_satellites->getIndexData(index); |
3577 | + size_t path_index = index_data.first; |
3578 | + size_t curve_index = index_data.second; |
3579 | + if (!valid_index(path_index, curve_index)) { |
3580 | + return; |
3581 | + } |
3582 | + Geom::PathVector pathv = _pparam->_last_pathvector_satellites->getPathVector(); |
3583 | + if ((!pathv[path_index].closed() && curve_index == 0) ||//ignore first satellites on open paths |
3584 | + pathv[path_index].size() == curve_index) //ignore last satellite in open paths with fillet chamfer effect |
3585 | + { |
3586 | + return; |
3587 | + } |
3588 | + if (state & GDK_CONTROL_MASK) { |
3589 | + if (state & GDK_MOD1_MASK) { |
3590 | + _pparam->_vector[path_index][curve_index].amount = 0.0; |
3591 | + sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); |
3592 | + } else { |
3593 | + using namespace Geom; |
3594 | + SatelliteType type = _pparam->_vector[path_index][curve_index].satellite_type; |
3595 | + switch (type) { |
3596 | + case FILLET: |
3597 | + type = INVERSE_FILLET; |
3598 | + break; |
3599 | + case INVERSE_FILLET: |
3600 | + type = CHAMFER; |
3601 | + break; |
3602 | + case CHAMFER: |
3603 | + type = INVERSE_CHAMFER; |
3604 | + break; |
3605 | + default: |
3606 | + type = FILLET; |
3607 | + break; |
3608 | + } |
3609 | + _pparam->_vector[path_index][curve_index].satellite_type = type; |
3610 | + sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); |
3611 | + const gchar *tip; |
3612 | + if (type == CHAMFER) { |
3613 | + tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toggles type, " |
3614 | + "<b>Shift+Click</b> open dialog, " |
3615 | + "<b>Ctrl+Alt+Click</b> resets"); |
3616 | + } else if (type == INVERSE_CHAMFER) { |
3617 | + tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toggles type, " |
3618 | + "<b>Shift+Click</b> open dialog, " |
3619 | + "<b>Ctrl+Alt+Click</b> resets"); |
3620 | + } else if (type == INVERSE_FILLET) { |
3621 | + tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toggles type, " |
3622 | + "<b>Shift+Click</b> open dialog, " |
3623 | + "<b>Ctrl+Alt+Click</b> resets"); |
3624 | + } else { |
3625 | + tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toggles type, " |
3626 | + "<b>Shift+Click</b> open dialog, " |
3627 | + "<b>Ctrl+Alt+Click</b> resets"); |
3628 | + } |
3629 | + this->knot->tip = g_strdup(tip); |
3630 | + this->knot->show(); |
3631 | + } |
3632 | + } else if (state & GDK_SHIFT_MASK) { |
3633 | + double amount = _pparam->_vector[path_index][curve_index].amount; |
3634 | + gint previous_index = curve_index - 1; |
3635 | + if (curve_index == 0 && pathv[path_index].closed()) { |
3636 | + previous_index = pathv[path_index].size() - 1; |
3637 | + } |
3638 | + if ( previous_index < 0 ) { |
3639 | + return; |
3640 | + } |
3641 | + if (!_pparam->_use_distance && !_pparam->_vector[path_index][curve_index].is_time) { |
3642 | + amount = _pparam->_vector[path_index][curve_index].lenToRad(amount, pathv[path_index][previous_index], pathv[path_index][curve_index], _pparam->_vector[path_index][previous_index]); |
3643 | + } |
3644 | + bool aprox = false; |
3645 | + Geom::D2<Geom::SBasis> d2_out = pathv[path_index][curve_index].toSBasis(); |
3646 | + Geom::D2<Geom::SBasis> d2_in = pathv[path_index][previous_index].toSBasis(); |
3647 | + aprox = ((d2_in)[0].degreesOfFreedom() != 2 || |
3648 | + d2_out[0].degreesOfFreedom() != 2) && |
3649 | + !_pparam->_use_distance |
3650 | + ? true |
3651 | + : false; |
3652 | + Inkscape::UI::Dialogs::FilletChamferPropertiesDialog::showDialog( |
3653 | + this->desktop, amount, this, _pparam->_use_distance, |
3654 | + aprox, _pparam->_vector[path_index][curve_index]); |
3655 | + |
3656 | + } |
3657 | +} |
3658 | + |
3659 | +void FilletChamferKnotHolderEntity::knot_set_offset(Satellite satellite) |
3660 | +{ |
3661 | + if (!_pparam->_last_pathvector_satellites) { |
3662 | + return; |
3663 | + } |
3664 | + size_t total_satellites = _pparam->_last_pathvector_satellites->getTotalSatellites(); |
3665 | + bool is_mirror = false; |
3666 | + size_t index = _index; |
3667 | + if (_index >= total_satellites) { |
3668 | + index = _index - total_satellites; |
3669 | + is_mirror = true; |
3670 | + } |
3671 | + std::pair<size_t, size_t> index_data = _pparam->_last_pathvector_satellites->getIndexData(index); |
3672 | + size_t path_index = index_data.first; |
3673 | + size_t curve_index = index_data.second; |
3674 | + if (!valid_index(path_index, curve_index)) { |
3675 | + return; |
3676 | + } |
3677 | + Geom::PathVector pathv = _pparam->_last_pathvector_satellites->getPathVector(); |
3678 | + if (satellite.hidden || |
3679 | + (!pathv[path_index].closed() && curve_index == 0) ||//ignore first satellites on open paths |
3680 | + pathv[path_index].size() == curve_index) //ignore last satellite in open paths with fillet chamfer effect |
3681 | + { |
3682 | + return; |
3683 | + } |
3684 | + double amount = satellite.amount; |
3685 | + double max_amount = amount; |
3686 | + if (!_pparam->_use_distance && !satellite.is_time) { |
3687 | + gint previous_index = curve_index - 1; |
3688 | + if (curve_index == 0 && pathv[path_index].closed()) { |
3689 | + previous_index = pathv[path_index].size() - 1; |
3690 | + } |
3691 | + if ( previous_index < 0 ) { |
3692 | + return; |
3693 | + } |
3694 | + amount = _pparam->_vector[path_index][curve_index].radToLen(amount, pathv[path_index][previous_index], pathv[path_index][curve_index]); |
3695 | + if (max_amount > 0 && amount == 0) { |
3696 | + amount = _pparam->_vector[path_index][curve_index].amount; |
3697 | + } |
3698 | + } |
3699 | + satellite.amount = amount; |
3700 | + _pparam->_vector[path_index][curve_index] = satellite; |
3701 | + this->parent_holder->knot_ungrabbed_handler(this->knot, 0); |
3702 | + SPLPEItem *splpeitem = dynamic_cast<SPLPEItem *>(item); |
3703 | + if (splpeitem) { |
3704 | + sp_lpe_item_update_patheffect(splpeitem, false, false); |
3705 | + } |
3706 | +} |
3707 | + |
3708 | +} /* namespace LivePathEffect */ |
3709 | + |
3710 | +} /* namespace Inkscape */ |
3711 | + |
3712 | +/* |
3713 | + Local Variables: |
3714 | + mode:c++ |
3715 | + c-file-style:"stroustrup" |
3716 | + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) |
3717 | + indent-tabs-mode:nil |
3718 | + fill-column:99 |
3719 | + End: |
3720 | +*/ |
3721 | +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : |
3722 | |
3723 | === added file 'src/live_effects/parameter/satellitesarray.h' |
3724 | --- src/live_effects/parameter/satellitesarray.h 1970-01-01 00:00:00 +0000 |
3725 | +++ src/live_effects/parameter/satellitesarray.h 2017-05-06 17:46:29 +0000 |
3726 | @@ -0,0 +1,114 @@ |
3727 | +#ifndef INKSCAPE_LIVEPATHEFFECT_SATELLITES_ARRAY_H |
3728 | +#define INKSCAPE_LIVEPATHEFFECT_SATELLITES_ARRAY_H |
3729 | + |
3730 | +/* |
3731 | + * Inkscape::LivePathEffectParameters |
3732 | + * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es> |
3733 | + * Special thanks to Johan Engelen for the base of the effect -powerstroke- |
3734 | + * Also to ScislaC for point me to the idea |
3735 | + * Also su_v for his construvtive feedback and time |
3736 | + * To Nathan Hurst for his review and help on refactor |
3737 | + * and finaly to Liam P. White for his big help on coding, that save me a lot of |
3738 | + * hours |
3739 | + * |
3740 | + * |
3741 | + * This parameter act as bridge from pathVectorSatellites class to serialize it as a LPE |
3742 | + * parameter |
3743 | + * |
3744 | + * Released under GNU GPL, read the file 'COPYING' for more information |
3745 | + */ |
3746 | + |
3747 | +#include "live_effects/parameter/array.h" |
3748 | +#include "live_effects/effect-enum.h" |
3749 | +#include "helper/geom-pathvectorsatellites.h" |
3750 | +#include "knot-holder-entity.h" |
3751 | +#include <glib.h> |
3752 | + |
3753 | +namespace Inkscape { |
3754 | + |
3755 | +namespace LivePathEffect { |
3756 | + |
3757 | +class FilletChamferKnotHolderEntity; |
3758 | + |
3759 | +class SatellitesArrayParam : public ArrayParam<std::vector<Satellite> > { |
3760 | +public: |
3761 | + SatellitesArrayParam(const Glib::ustring &label, const Glib::ustring &tip, |
3762 | + const Glib::ustring &key, |
3763 | + Inkscape::UI::Widget::Registry *wr, Effect *effect); |
3764 | + |
3765 | + virtual Gtk::Widget *param_newWidget() |
3766 | + { |
3767 | + return NULL; |
3768 | + } |
3769 | + virtual void setHelperSize(int hs); |
3770 | + virtual void addKnotHolderEntities(KnotHolder *knotholder, SPItem *item); |
3771 | + virtual void addKnotHolderEntities(KnotHolder *knotholder, SPItem *item, bool mirror); |
3772 | + virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); |
3773 | + virtual void updateCanvasIndicators(); |
3774 | + virtual void updateCanvasIndicators(bool mirror); |
3775 | + virtual bool providesKnotHolderEntities() const |
3776 | + { |
3777 | + return true; |
3778 | + } |
3779 | + void param_transform_multiply(Geom::Affine const &postmul, bool /*set*/); |
3780 | + void setUseDistance(bool use_knot_distance); |
3781 | + void setCurrentZoom(double current_zoom); |
3782 | + void setGlobalKnotHide(bool global_knot_hide); |
3783 | + void setEffectType(EffectType et); |
3784 | + void setPathVectorSatellites(PathVectorSatellites *pathVectorSatellites, bool write = true); |
3785 | + void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); |
3786 | + |
3787 | + friend class FilletChamferKnotHolderEntity; |
3788 | + friend class LPEFilletChamfer; |
3789 | + |
3790 | +protected: |
3791 | + KnotHolder *_knoth; |
3792 | + |
3793 | +private: |
3794 | + SatellitesArrayParam(const SatellitesArrayParam &); |
3795 | + SatellitesArrayParam &operator=(const SatellitesArrayParam &); |
3796 | + |
3797 | + SPKnotShapeType _knot_shape; |
3798 | + SPKnotModeType _knot_mode; |
3799 | + guint32 _knot_color; |
3800 | + Geom::PathVector _hp; |
3801 | + Geom::PathVector _knot_reset_helper; |
3802 | + int _helper_size; |
3803 | + bool _use_distance; |
3804 | + bool _global_knot_hide; |
3805 | + double _current_zoom; |
3806 | + EffectType _effectType; |
3807 | + PathVectorSatellites *_last_pathvector_satellites; |
3808 | + |
3809 | +}; |
3810 | + |
3811 | +class FilletChamferKnotHolderEntity : public KnotHolderEntity { |
3812 | +public: |
3813 | + FilletChamferKnotHolderEntity(SatellitesArrayParam *p, size_t index); |
3814 | + virtual ~FilletChamferKnotHolderEntity() |
3815 | + { |
3816 | + _pparam->_knoth = NULL; |
3817 | + } |
3818 | + |
3819 | + virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, |
3820 | + guint state); |
3821 | + virtual Geom::Point knot_get() const; |
3822 | + virtual void knot_click(guint state); |
3823 | + void knot_set_offset(Satellite); |
3824 | + /** Checks whether the index falls within the size of the parameter's vector |
3825 | + */ |
3826 | + bool valid_index(size_t index,size_t subindex) const |
3827 | + { |
3828 | + return (_pparam->_vector.size() > index && _pparam->_vector[index].size() > subindex); |
3829 | + }; |
3830 | + |
3831 | +private: |
3832 | + SatellitesArrayParam *_pparam; |
3833 | + size_t _index; |
3834 | +}; |
3835 | + |
3836 | +} //namespace LivePathEffect |
3837 | + |
3838 | +} //namespace Inkscape |
3839 | + |
3840 | +#endif |
3841 | |
3842 | === modified file 'src/ui/dialog/lpe-fillet-chamfer-properties.cpp' |
3843 | --- src/ui/dialog/lpe-fillet-chamfer-properties.cpp 2017-03-12 13:45:15 +0000 |
3844 | +++ src/ui/dialog/lpe-fillet-chamfer-properties.cpp 2017-05-06 17:46:29 +0000 |
3845 | @@ -43,7 +43,6 @@ |
3846 | //todo: get tha max aloable infinity freeze the widget |
3847 | _fillet_chamfer_position_numeric.set_range(0., SCALARPARAM_G_MAXDOUBLE); |
3848 | _fillet_chamfer_position_numeric.set_hexpand(); |
3849 | - |
3850 | _fillet_chamfer_position_label.set_label(_("Radius (pixels):")); |
3851 | _fillet_chamfer_position_label.set_alignment(1.0, 0.5); |
3852 | |
3853 | @@ -54,7 +53,6 @@ |
3854 | //todo: get tha max aloable infinity freeze the widget |
3855 | _fillet_chamfer_chamfer_subdivisions.set_range(0, SCALARPARAM_G_MAXDOUBLE); |
3856 | _fillet_chamfer_chamfer_subdivisions.set_hexpand(); |
3857 | - |
3858 | _fillet_chamfer_chamfer_subdivisions_label.set_label(_("Chamfer subdivisions:")); |
3859 | _fillet_chamfer_chamfer_subdivisions_label.set_alignment(1.0, 0.5); |
3860 | |
3861 | @@ -104,23 +102,26 @@ |
3862 | FilletChamferPropertiesDialog::~FilletChamferPropertiesDialog() |
3863 | { |
3864 | |
3865 | - _set_desktop(NULL); |
3866 | + _setDesktop(NULL); |
3867 | } |
3868 | |
3869 | void FilletChamferPropertiesDialog::showDialog( |
3870 | - SPDesktop *desktop, Geom::Point knotpoint, |
3871 | + SPDesktop *desktop, |
3872 | + double _amount, |
3873 | const Inkscape::LivePathEffect:: |
3874 | - FilletChamferPointArrayParamKnotHolderEntity *pt, |
3875 | - bool use_distance, |
3876 | - bool aprox_radius) |
3877 | + FilletChamferKnotHolderEntity *pt, |
3878 | + bool _use_distance, |
3879 | + bool _aprox_radius, |
3880 | + Satellite _satellite) |
3881 | { |
3882 | FilletChamferPropertiesDialog *dialog = new FilletChamferPropertiesDialog(); |
3883 | |
3884 | - dialog->_set_desktop(desktop); |
3885 | - dialog->_set_use_distance(use_distance); |
3886 | - dialog->_set_aprox(aprox_radius); |
3887 | - dialog->_set_knot_point(knotpoint); |
3888 | - dialog->_set_pt(pt); |
3889 | + dialog->_setDesktop(desktop); |
3890 | + dialog->_setUseDistance(_use_distance); |
3891 | + dialog->_setAprox(_aprox_radius); |
3892 | + dialog->_setAmount(_amount); |
3893 | + dialog->_setSatellite(_satellite); |
3894 | + dialog->_setPt(pt); |
3895 | |
3896 | dialog->set_title(_("Modify Fillet-Chamfer")); |
3897 | dialog->_apply_button.set_label(_("_Modify")); |
3898 | @@ -135,34 +136,38 @@ |
3899 | |
3900 | void FilletChamferPropertiesDialog::_apply() |
3901 | { |
3902 | - double d_width; |
3903 | + |
3904 | double d_pos = _fillet_chamfer_position_numeric.get_value(); |
3905 | - if (d_pos) { |
3906 | + if (d_pos >= 0) { |
3907 | if (_fillet_chamfer_type_fillet.get_active() == true) { |
3908 | - d_width = 1; |
3909 | + _satellite.satellite_type = FILLET; |
3910 | } else if (_fillet_chamfer_type_inverse_fillet.get_active() == true) { |
3911 | - d_width = 2; |
3912 | + _satellite.satellite_type = INVERSE_FILLET; |
3913 | } else if (_fillet_chamfer_type_inverse_chamfer.get_active() == true) { |
3914 | - d_width = _fillet_chamfer_chamfer_subdivisions.get_value() + 4000; |
3915 | + _satellite.satellite_type = INVERSE_CHAMFER; |
3916 | } else { |
3917 | - d_width = _fillet_chamfer_chamfer_subdivisions.get_value() + 3000; |
3918 | + _satellite.satellite_type = CHAMFER; |
3919 | } |
3920 | if (_flexible) { |
3921 | if (d_pos > 99.99999 || d_pos < 0) { |
3922 | d_pos = 0; |
3923 | } |
3924 | - d_pos = _index + (d_pos / 100); |
3925 | - } else { |
3926 | - d_pos = d_pos * -1; |
3927 | - } |
3928 | - _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width)); |
3929 | + d_pos = d_pos / 100; |
3930 | + } |
3931 | + _satellite.amount = d_pos; |
3932 | + size_t steps = (size_t)_fillet_chamfer_chamfer_subdivisions.get_value(); |
3933 | + if (steps < 1) { |
3934 | + steps = 1; |
3935 | + } |
3936 | + _satellite.steps = steps; |
3937 | + _knotpoint->knot_set_offset(_satellite); |
3938 | } |
3939 | _close(); |
3940 | } |
3941 | |
3942 | void FilletChamferPropertiesDialog::_close() |
3943 | { |
3944 | - _set_desktop(NULL); |
3945 | + _setDesktop(NULL); |
3946 | destroy_(); |
3947 | Glib::signal_idle().connect( |
3948 | sigc::bind_return( |
3949 | @@ -184,62 +189,68 @@ |
3950 | } |
3951 | } |
3952 | |
3953 | -void FilletChamferPropertiesDialog::_set_knot_point(Geom::Point knotpoint) |
3954 | +void FilletChamferPropertiesDialog::_setSatellite(Satellite satellite) |
3955 | { |
3956 | double position; |
3957 | std::string distance_or_radius = std::string(_("Radius")); |
3958 | - if(aprox){ |
3959 | + if (_aprox) { |
3960 | distance_or_radius = std::string(_("Radius approximated")); |
3961 | } |
3962 | - if(use_distance){ |
3963 | + if (_use_distance) { |
3964 | distance_or_radius = std::string(_("Knot distance")); |
3965 | } |
3966 | - if (knotpoint.x() > 0) { |
3967 | - double intpart; |
3968 | - position = modf(knotpoint[Geom::X], &intpart) * 100; |
3969 | + if (satellite.is_time) { |
3970 | + position = _amount * 100; |
3971 | _flexible = true; |
3972 | - _index = intpart; |
3973 | _fillet_chamfer_position_label.set_label(_("Position (%):")); |
3974 | } else { |
3975 | _flexible = false; |
3976 | std::string posConcat = Glib::ustring::compose (_("%1:"), distance_or_radius); |
3977 | _fillet_chamfer_position_label.set_label(_(posConcat.c_str())); |
3978 | - position = knotpoint[Geom::X] * -1; |
3979 | + position = _amount; |
3980 | } |
3981 | _fillet_chamfer_position_numeric.set_value(position); |
3982 | - if (knotpoint.y() == 1) { |
3983 | + _fillet_chamfer_chamfer_subdivisions.set_value(satellite.steps); |
3984 | + if (satellite.satellite_type == FILLET) { |
3985 | _fillet_chamfer_type_fillet.set_active(true); |
3986 | - } else if (knotpoint.y() == 2) { |
3987 | + } else if (satellite.satellite_type == INVERSE_FILLET) { |
3988 | _fillet_chamfer_type_inverse_fillet.set_active(true); |
3989 | - } else if (knotpoint.y() >= 3000 && knotpoint.y() < 4000) { |
3990 | - _fillet_chamfer_chamfer_subdivisions.set_value(knotpoint.y() - 3000); |
3991 | + } else if (satellite.satellite_type == CHAMFER) { |
3992 | _fillet_chamfer_type_chamfer.set_active(true); |
3993 | - } else if (knotpoint.y() >= 4000 && knotpoint.y() < 5000) { |
3994 | - _fillet_chamfer_chamfer_subdivisions.set_value(knotpoint.y() - 4000); |
3995 | + } else if (satellite.satellite_type == INVERSE_CHAMFER) { |
3996 | _fillet_chamfer_type_inverse_chamfer.set_active(true); |
3997 | } |
3998 | + _satellite = satellite; |
3999 | } |
4000 | |
4001 | -void FilletChamferPropertiesDialog::_set_pt( |
4002 | +void FilletChamferPropertiesDialog::_setPt( |
4003 | const Inkscape::LivePathEffect:: |
4004 | - FilletChamferPointArrayParamKnotHolderEntity *pt) |
4005 | + FilletChamferKnotHolderEntity *pt) |
4006 | { |
4007 | _knotpoint = const_cast< |
4008 | - Inkscape::LivePathEffect::FilletChamferPointArrayParamKnotHolderEntity *>( |
4009 | + Inkscape::LivePathEffect::FilletChamferKnotHolderEntity *>( |
4010 | pt); |
4011 | } |
4012 | |
4013 | -void FilletChamferPropertiesDialog::_set_use_distance(bool use_knot_distance) |
4014 | -{ |
4015 | - use_distance = use_knot_distance; |
4016 | -} |
4017 | - |
4018 | -void FilletChamferPropertiesDialog::_set_aprox(bool aprox_radius) |
4019 | -{ |
4020 | - aprox = aprox_radius; |
4021 | -} |
4022 | - |
4023 | -void FilletChamferPropertiesDialog::_set_desktop(SPDesktop *desktop) |
4024 | + |
4025 | +void FilletChamferPropertiesDialog::_setAmount(double amount) |
4026 | +{ |
4027 | + _amount = amount; |
4028 | +} |
4029 | + |
4030 | + |
4031 | + |
4032 | +void FilletChamferPropertiesDialog::_setUseDistance(bool use_knot_distance) |
4033 | +{ |
4034 | + _use_distance = use_knot_distance; |
4035 | +} |
4036 | + |
4037 | +void FilletChamferPropertiesDialog::_setAprox(bool _aprox_radius) |
4038 | +{ |
4039 | + _aprox = _aprox_radius; |
4040 | +} |
4041 | + |
4042 | +void FilletChamferPropertiesDialog::_setDesktop(SPDesktop *desktop) |
4043 | { |
4044 | if (desktop) { |
4045 | Inkscape::GC::anchor(desktop); |
4046 | |
4047 | === modified file 'src/ui/dialog/lpe-fillet-chamfer-properties.h' |
4048 | --- src/ui/dialog/lpe-fillet-chamfer-properties.h 2017-03-12 13:37:33 +0000 |
4049 | +++ src/ui/dialog/lpe-fillet-chamfer-properties.h 2017-05-06 17:46:29 +0000 |
4050 | @@ -10,7 +10,7 @@ |
4051 | |
4052 | #include <2geom/point.h> |
4053 | #include <gtkmm.h> |
4054 | -#include "live_effects/parameter/filletchamferpointarray.h" |
4055 | +#include "live_effects/parameter/satellitesarray.h" |
4056 | |
4057 | class SPDesktop; |
4058 | |
4059 | @@ -23,20 +23,22 @@ |
4060 | FilletChamferPropertiesDialog(); |
4061 | virtual ~FilletChamferPropertiesDialog(); |
4062 | |
4063 | - Glib::ustring getName() const { |
4064 | + Glib::ustring getName() const |
4065 | + { |
4066 | return "LayerPropertiesDialog"; |
4067 | } |
4068 | |
4069 | - static void showDialog(SPDesktop *desktop, Geom::Point knotpoint, |
4070 | + static void showDialog(SPDesktop *desktop, double _amount, |
4071 | const Inkscape::LivePathEffect:: |
4072 | - FilletChamferPointArrayParamKnotHolderEntity *pt, |
4073 | - bool use_distance, |
4074 | - bool aprox_radius); |
4075 | + FilletChamferKnotHolderEntity *pt, |
4076 | + bool _use_distance, |
4077 | + bool _aprox_radius, |
4078 | + Satellite _satellite); |
4079 | |
4080 | protected: |
4081 | |
4082 | SPDesktop *_desktop; |
4083 | - Inkscape::LivePathEffect::FilletChamferPointArrayParamKnotHolderEntity * |
4084 | + Inkscape::LivePathEffect::FilletChamferKnotHolderEntity * |
4085 | _knotpoint; |
4086 | |
4087 | Gtk::Label _fillet_chamfer_position_label; |
4088 | @@ -51,36 +53,40 @@ |
4089 | |
4090 | Gtk::Grid _layout_table; |
4091 | bool _position_visible; |
4092 | - double _index; |
4093 | |
4094 | Gtk::Button _close_button; |
4095 | Gtk::Button _apply_button; |
4096 | |
4097 | sigc::connection _destroy_connection; |
4098 | |
4099 | - static FilletChamferPropertiesDialog &_instance() { |
4100 | + static FilletChamferPropertiesDialog &_instance() |
4101 | + { |
4102 | static FilletChamferPropertiesDialog instance; |
4103 | return instance; |
4104 | } |
4105 | |
4106 | - void _set_desktop(SPDesktop *desktop); |
4107 | - void _set_pt(const Inkscape::LivePathEffect:: |
4108 | - FilletChamferPointArrayParamKnotHolderEntity *pt); |
4109 | - void _set_use_distance(bool use_knot_distance); |
4110 | - void _set_aprox(bool aprox_radius); |
4111 | + void _setDesktop(SPDesktop *desktop); |
4112 | + void _setPt(const Inkscape::LivePathEffect:: |
4113 | + FilletChamferKnotHolderEntity *pt); |
4114 | + void _setUseDistance(bool use_knot_distance); |
4115 | + void _setAprox(bool aprox_radius); |
4116 | + void _setAmount(double amount); |
4117 | + void _setSatellite(Satellite satellite); |
4118 | + void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row); |
4119 | + |
4120 | + bool _handleKeyEvent(GdkEventKey *event); |
4121 | + void _handleButtonEvent(GdkEventButton *event); |
4122 | + |
4123 | void _apply(); |
4124 | void _close(); |
4125 | bool _flexible; |
4126 | - bool use_distance; |
4127 | - bool aprox; |
4128 | - void _set_knot_point(Geom::Point knotpoint); |
4129 | - void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row); |
4130 | - |
4131 | - bool _handleKeyEvent(GdkEventKey *event); |
4132 | - void _handleButtonEvent(GdkEventButton *event); |
4133 | + Satellite _satellite; |
4134 | + bool _use_distance; |
4135 | + double _amount; |
4136 | + bool _aprox; |
4137 | |
4138 | friend class Inkscape::LivePathEffect:: |
4139 | - FilletChamferPointArrayParamKnotHolderEntity; |
4140 | + FilletChamferKnotHolderEntity; |
4141 | |
4142 | private: |
4143 | FilletChamferPropertiesDialog( |
4144 | |
4145 | === modified file 'src/ui/tool/path-manipulator.cpp' |
4146 | --- src/ui/tool/path-manipulator.cpp 2016-12-06 21:22:02 +0000 |
4147 | +++ src/ui/tool/path-manipulator.cpp 2017-05-06 17:46:29 +0000 |
4148 | @@ -12,7 +12,6 @@ |
4149 | |
4150 | #include "live_effects/lpe-powerstroke.h" |
4151 | #include "live_effects/lpe-bspline.h" |
4152 | -#include "live_effects/lpe-fillet-chamfer.h" |
4153 | #include <2geom/bezier-utils.h> |
4154 | #include <2geom/path-sink.h> |
4155 | #include "ui/tool/path-manipulator.h" |
4156 | @@ -1364,13 +1363,6 @@ |
4157 | lpe_pwr->adjustForNewPath(pathv); |
4158 | } |
4159 | } |
4160 | - this_effect = _path->getPathEffectOfType(Inkscape::LivePathEffect::FILLET_CHAMFER); |
4161 | - if(this_effect){ |
4162 | - LivePathEffect::LPEFilletChamfer *lpe_fll = dynamic_cast<LivePathEffect::LPEFilletChamfer*>(this_effect->getLPEObj()->get_lpe()); |
4163 | - if (lpe_fll) { |
4164 | - lpe_fll->adjustForNewPath(pathv); |
4165 | - } |
4166 | - } |
4167 | } |
4168 | } |
4169 |
- 2Geom is a separate library, not part of Inkscape. It should only contain code which is useful outside of Inkscape, and the changes should be submitted to 2Geom.
- 2geom/pointwise.h has a dependency on helper/geom.h, which is unacceptable.
- The Pointwise and Satellite classes are poorly undocumented - I don't understand what they are supposed to do. Are they supposed to some store per-node data? Their interface is rather unintelligible.
- The computational complexity comments are misleading. This code is obviously O(N) in the number of satellites and should either use a map or a simple vector, not a vector of pairs of size_t and Satellite. What is the intended purpose?
- The coding style does not match Inkscape's and is in fact inconsistent even within this patchset (some methods are in snake_case, some local variables are in lowerCamelCase, invalid indent in class definitions, etc.)
- The getters and setters on Satellite are pointless, they could simply be replaced by public fields.
- The way the satellite parameters are stored is very un-XML. I possible, each of the boolean parameters should be a separate attribute.