@@ -34,7 +34,9 @@ void DrawInterlacing::drawGeometries(Gen::AxisId axisIndex) const
3434 || guides.interlacings == false )
3535 return ;
3636
37- auto orientation = !+axisIndex;
37+ auto otherWeights = getInterlacingWeights (!axisIndex);
38+ auto &&otherInterlacingColor =
39+ *parent.rootStyle .plot .getAxis (!axisIndex).interlacing .color ;
3840
3941 parent.painter .setPolygonToCircleFactor (0 );
4042 parent.painter .setPolygonStraightFactor (0 );
@@ -48,30 +50,42 @@ void DrawInterlacing::drawGeometries(Gen::AxisId axisIndex) const
4850 1.0 ,
4951 Math::Floating::less)
5052 - clippedBottom;
51- auto rect = Geom::Rect{
52- Geom::Point::Coord (orientation, 0.0 , clippedBottom),
53- {Geom::Size::Coord (orientation, 1.0 , clippedSize)}};
54-
55- auto interlacingColor =
56- *axisStyle.interlacing .color
57- * Math::FuzzyBool::And<double >(interval.weight ,
58- interval.isSecond ,
59- guides.interlacings );
60-
61- auto &canvas = parent.canvas ;
62- canvas.save ();
63- canvas.setLineColor (Gfx::Color::Transparent ());
64- canvas.setBrushColor (interlacingColor);
65- if (auto &&eventTarget =
66- Events::Targets::axisInterlacing (axisIndex);
67- parent.rootEvents .draw .plot .axis .interlacing ->invoke (
68- Events::OnRectDrawEvent (*eventTarget,
69- {rect, true }))) {
70- parent.painter .drawPolygon (rect.points ());
71- parent.renderedChart .emplace (Rect{rect, true },
72- std::move (eventTarget));
53+
54+ auto rect = [&, orientation = +axisIndex](const double &from,
55+ const double &to)
56+ {
57+ return Geom::Rect{
58+ Geom::Point::Coord (orientation, clippedBottom, from),
59+ {Geom::Size::Coord (orientation,
60+ clippedSize,
61+ to - from)}};
62+ };
63+
64+ auto weight = Math::FuzzyBool::And<double >(interval.weight ,
65+ interval.isSecond ,
66+ guides.interlacings );
67+ auto interlacingColor = *axisStyle.interlacing .color * weight;
68+
69+ for (auto first = otherWeights.begin (),
70+ next = std::next (first),
71+ last = otherWeights.end ();
72+ next != last;
73+ ++next, ++first) {
74+ if (Math::Floating::is_zero (first->second ))
75+ drawInterlacing (axisIndex,
76+ interlacingColor,
77+ rect (first->first , next->first ));
78+ else if (axisIndex == Gen::AxisId::y) {
79+ drawInterlacing (first->second > weight ? !axisIndex
80+ : axisIndex,
81+ getCrossingInterlacingColor (
82+ *axisStyle.interlacing .color ,
83+ weight,
84+ otherInterlacingColor,
85+ first->second ),
86+ rect (first->first , next->first ));
87+ }
7388 }
74- canvas.restore ();
7589 }
7690}
7791
@@ -119,6 +133,26 @@ void DrawInterlacing::drawTexts(Gen::AxisId axisIndex) const
119133 }
120134}
121135
136+ void DrawInterlacing::drawInterlacing (Gen::AxisId axisIndex,
137+ const Gfx::Color &interlacingColor,
138+ const Geom::Rect &rect) const
139+ {
140+ auto &canvas = parent.canvas ;
141+ canvas.save ();
142+ canvas.setLineColor (Gfx::Color::Transparent ());
143+ canvas.setLineWidth (0 );
144+ canvas.setBrushColor (interlacingColor);
145+ if (auto &&eventTarget =
146+ Events::Targets::axisInterlacing (axisIndex);
147+ parent.rootEvents .draw .plot .axis .interlacing ->invoke (
148+ Events::OnRectDrawEvent (*eventTarget, {rect, true }))) {
149+ parent.painter .drawPolygon (rect.points ());
150+ parent.renderedChart .emplace (Rect{rect, true },
151+ std::move (eventTarget));
152+ }
153+ canvas.restore ();
154+ }
155+
122156void DrawInterlacing::drawDataLabel (
123157 const ::Anim::Interpolated<bool > &axisEnabled,
124158 Gen::AxisId axisIndex,
@@ -226,4 +260,61 @@ void DrawInterlacing::drawSticks(double tickLength,
226260 canvas.restore ();
227261}
228262
263+ std::map<double , double > DrawInterlacing::getInterlacingWeights (
264+ Gen::AxisId axisIndex) const
265+ {
266+ std::map<double , double > weights{{0.0 , 0.0 }, {1.0 , 0.0 }};
267+
268+ auto &&guides = parent.plot ->guides .at (axisIndex);
269+ auto &&axisStyle = parent.rootStyle .plot .getAxis (axisIndex);
270+ if (axisStyle.interlacing .color ->isTransparent ()
271+ || guides.interlacings == false )
272+ return weights;
273+
274+ for (auto &&interval : parent.getIntervals (axisIndex)) {
275+ if (Math::Floating::is_zero (interval.isSecond )) continue ;
276+ auto min = std::max (interval.range .getMin (), 0.0 );
277+ auto max = std::min (interval.range .getMax (), 1.0 );
278+ auto mprev = std::prev (weights.upper_bound (min));
279+ auto mnext = weights.lower_bound (max);
280+
281+ if (mprev->first < min)
282+ mprev = weights.try_emplace (mprev, min, mprev->second );
283+ if (mnext->first > max)
284+ mnext = weights.try_emplace (mnext,
285+ max,
286+ std::prev (mnext)->second );
287+
288+ while (mprev != mnext)
289+ mprev++->second +=
290+ Math::FuzzyBool::And<double >(interval.weight ,
291+ interval.isSecond ,
292+ guides.interlacings );
293+ }
294+ return weights;
295+ }
296+
297+ Gfx::Color DrawInterlacing::getCrossingInterlacingColor (
298+ const Gfx::Color &mainColor,
299+ double mainWeight,
300+ const Gfx::Color &otherColor,
301+ double otherWeight)
302+ {
303+ auto color = mainColor * mainWeight + otherColor * otherWeight;
304+
305+ color.alpha = 1
306+ - (1 - mainColor.alpha * mainWeight)
307+ * (1 - otherColor.alpha * otherWeight);
308+
309+ if (mainWeight + otherWeight > 1.0 )
310+ color = Math::Niebloid::interpolate (color,
311+ color
312+ * std::max ({std::abs (mainColor.red - otherColor.red ),
313+ std::abs (mainColor.green - otherColor.green ),
314+ std::abs (mainColor.blue - otherColor.blue )}),
315+ mainWeight + otherWeight - 1.0 );
316+
317+ return color;
318+ }
319+
229320}
0 commit comments