@@ -655,7 +655,8 @@ static void CatmullRomInterpolate(const TThickPoint &P0, const TThickPoint &P1,
655
655
656
656
// --------------------------------------------------------------------------------------------------
657
657
658
- static void Smooth (std::vector<TThickPoint> &points, int radius) {
658
+ static void Smooth (std::vector<TThickPoint> &points, const int radius,
659
+ const int readIndex, const int level) {
659
660
int n = (int )points.size ();
660
661
if (radius < 1 || n < 3 ) {
661
662
return ;
@@ -665,7 +666,10 @@ static void Smooth(std::vector<TThickPoint> &points, int radius) {
665
666
666
667
float d = 1 .0f / (radius * 2 + 1 );
667
668
668
- for (int i = 1 ; i < n - 1 ; ++i) {
669
+ int endSamples = 10 ;
670
+ int startId = std::max (readIndex - endSamples * 3 - radius * level, 1 );
671
+
672
+ for (int i = startId; i < n - 1 ; ++i) {
669
673
int lower = i - radius;
670
674
int upper = i + radius;
671
675
@@ -692,21 +696,23 @@ static void Smooth(std::vector<TThickPoint> &points, int radius) {
692
696
result.push_back (total);
693
697
}
694
698
695
- for (int i = 1 ; i < n - 1 ; ++i) {
696
- points[i].x = result[i - 1 ].x ;
697
- points[i].y = result[i - 1 ].y ;
698
- points[i].thick = result[i - 1 ].thick ;
699
+ auto result_itr = result.begin ();
700
+ for (int i = startId; i < n - 1 ; ++i, ++result_itr) {
701
+ points[i].x = (*result_itr).x ;
702
+ points[i].y = (*result_itr).y ;
703
+ points[i].thick = (*result_itr).thick ;
699
704
}
700
705
701
706
if (points.size () >= 3 ) {
702
707
std::vector<TThickPoint> pts;
703
- CatmullRomInterpolate (points[0 ], points[0 ], points[1 ], points[2 ], 10 , pts);
708
+ CatmullRomInterpolate (points[0 ], points[0 ], points[1 ], points[2 ],
709
+ endSamples, pts);
704
710
std::vector<TThickPoint>::iterator it = points.begin () + 1 ;
705
711
points.insert (it, pts.begin (), pts.end ());
706
712
707
713
pts.clear ();
708
714
CatmullRomInterpolate (points[n - 3 ], points[n - 2 ], points[n - 1 ],
709
- points[n - 1 ], 10 , pts);
715
+ points[n - 1 ], endSamples , pts);
710
716
it = points.begin ();
711
717
it += n - 1 ;
712
718
points.insert (it, pts.begin (), pts.end ());
@@ -721,6 +727,8 @@ void SmoothStroke::beginStroke(int smooth) {
721
727
m_readIndex = -1 ;
722
728
m_rawPoints.clear ();
723
729
m_outputPoints.clear ();
730
+ m_resampledIndex = 0 ;
731
+ m_resampledPoints.clear ();
724
732
}
725
733
726
734
// --------------------------------------------------------------------------------------------------
@@ -749,6 +757,8 @@ void SmoothStroke::clearPoints() {
749
757
m_readIndex = -1 ;
750
758
m_outputPoints.clear ();
751
759
m_rawPoints.clear ();
760
+ m_resampledIndex = 0 ;
761
+ m_resampledPoints.clear ();
752
762
}
753
763
754
764
// --------------------------------------------------------------------------------------------------
@@ -781,26 +791,40 @@ void SmoothStroke::generatePoints() {
781
791
return ;
782
792
}
783
793
784
- std::vector<TThickPoint> smoothedPoints;
794
+ std::vector<TThickPoint> smoothedPoints = m_resampledPoints ;
785
795
// Add more stroke samples before applying the smoothing
786
796
// This is because the raw inputs points are too few to support smooth result,
787
797
// especially on stroke ends
788
- smoothedPoints.push_back (m_rawPoints.front ());
789
- for (int i = 1 ; i < n; ++i) {
790
- const TThickPoint &p1 = m_rawPoints[i - 1 ];
791
- const TThickPoint &p2 = m_rawPoints[i];
792
- const TThickPoint &p0 = i - 2 >= 0 ? m_rawPoints[i - 2 ] : p1;
793
- const TThickPoint &p3 = i + 1 < n ? m_rawPoints[i + 1 ] : p2;
794
-
795
- int samples = 8 ;
796
- CatmullRomInterpolate (p0, p1, p2, p3, samples, smoothedPoints);
797
- smoothedPoints.push_back (p2);
798
+
799
+ int resampleStartId = m_resampledIndex;
800
+ for (int i = resampleStartId; i < n - 1 ; ++i) {
801
+ const TThickPoint &p1 = m_rawPoints[i];
802
+ const TThickPoint &p2 = m_rawPoints[i + 1 ];
803
+ const TThickPoint &p0 = i - 1 >= 0 ? m_rawPoints[i - 1 ] : p1;
804
+ const TThickPoint &p3 = i + 2 < n ? m_rawPoints[i + 2 ] : p2;
805
+
806
+ std::vector<TThickPoint> tmpResampled;
807
+ tmpResampled.push_back (p1);
808
+ // define subsample amount according to distance between points
809
+ int samples = std::min ((int )tdistance (p1, p2), 8 );
810
+ if (samples >= 1 )
811
+ CatmullRomInterpolate (p0, p1, p2, p3, samples, tmpResampled);
812
+
813
+ if (i + 2 < n) {
814
+ m_resampledIndex = i + 1 ;
815
+ std::copy (tmpResampled.begin (), tmpResampled.end (),
816
+ std::back_inserter (m_resampledPoints));
817
+ }
818
+ std::copy (tmpResampled.begin (), tmpResampled.end (),
819
+ std::back_inserter (smoothedPoints));
798
820
}
821
+ smoothedPoints.push_back (m_rawPoints.back ());
799
822
// Apply the 1D box filter
800
823
// Multiple passes result in better quality and fix the stroke ends break
801
824
// issue
802
- for (int i = 0 ; i < 3 ; ++i) {
803
- Smooth (smoothedPoints, m_smooth);
825
+ // level is passed to define range where the points are smoothed
826
+ for (int level = 2 ; level >= 0 ; --level) {
827
+ Smooth (smoothedPoints, m_smooth, m_readIndex, level);
804
828
}
805
829
// Compare the new smoothed stroke with old one
806
830
// Enable the output for unchanged parts
0 commit comments