You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I want to implement StepLineSeries' step-drawing inversion. For example, for two points of the same data source, now the X-axis line is drawn first and then the Y-axis line, can you add an attribute to control the Y-axis line first and then the X-axis line when drawing.
I add an attribute 'IsReverse ',then I modified part of the code in the function Invalidate to reverse the order of the coordinate sequence,This will achieve the effect I want.
` private bool _isReverse = false;
///
/// Reverse step line
///
public bool IsReverse { get => _isReverse; set => SetProperty(ref _isReverse, value); }
///
public override void Invalidate(Chart chart)
{
var cartesianChart = (CartesianChart)chart;
var primaryAxis = cartesianChart.YAxes[ScalesYAt];
var secondaryAxis = cartesianChart.XAxes[ScalesXAt];
var drawLocation = cartesianChart.DrawMarginLocation;
var drawMarginSize = cartesianChart.DrawMarginSize;
var secondaryScale = secondaryAxis.GetNextScaler(cartesianChart);
var primaryScale = primaryAxis.GetNextScaler(cartesianChart);
var actualSecondaryScale = secondaryAxis.GetActualScaler(cartesianChart);
var actualPrimaryScale = primaryAxis.GetActualScaler(cartesianChart);
var gs = _geometrySize;
var hgs = gs / 2f;
var sw = Stroke?.StrokeThickness ?? 0;
var p = primaryScale.ToPixels(pivot);
// see note #240222
var segments = _enableNullSplitting
? Fetch(cartesianChart).SplitByNullGaps(point => DeleteNullPoint(point, secondaryScale, primaryScale))
: [Fetch(cartesianChart)];
var stacker = (SeriesProperties & SeriesProperties.Stacked) == SeriesProperties.Stacked
? cartesianChart.SeriesContext.GetStackPosition(this, GetStackGroup())
: null;
var actualZIndex = ZIndex == 0 ? ((ISeries)this).SeriesId : ZIndex;
var clipping = GetClipRectangle(cartesianChart);
if (stacker is not null)
{
// see note #010621
actualZIndex = 1000 - stacker.Position;
if (Fill is not null) Fill.ZIndex = actualZIndex;
if (Stroke is not null) Stroke.ZIndex = actualZIndex;
}
var dls = (float)DataLabelsSize;
var segmentI = 0;
var pointsCleanup = ChartPointCleanupContext.For(everFetched);
if (!_strokePathHelperDictionary.TryGetValue(chart.Canvas.Sync, out var strokePathHelperContainer))
{
strokePathHelperContainer = [];
_strokePathHelperDictionary[chart.Canvas.Sync] = strokePathHelperContainer;
}
if (!_fillPathHelperDictionary.TryGetValue(chart.Canvas.Sync, out var fillPathHelperContainer))
{
fillPathHelperContainer = [];
_fillPathHelperDictionary[chart.Canvas.Sync] = fillPathHelperContainer;
}
var uwx = secondaryScale.MeasureInPixels(secondaryAxis.UnitWidth);
uwx = uwx < gs ? gs : uwx;
var hasSvg = this.HasVariableSvgGeometry();
var isFirstDraw = !chart._drawnSeries.Contains(((ISeries)this).SeriesId);
foreach (var segment in segments)
{
var hasPaths = false;
var isSegmentEmpty = true;
VectorManager<StepLineSegment, TDrawingContext>? strokeVector = null, fillVector = null;
double previousPrimary = 0, previousSecondary = 0;
**//Reverse cooordinate for step line
List<ChartPoint> Reversepoint = new();
foreach (var point in segment)
{
Reversepoint.Add(point);
}
if (_isReverse)
{
Reversepoint.Reverse();
}
// foreach (var point in segment) //old code
foreach (var point in Reversepoint)**
{
if (!hasPaths)
{
hasPaths = true;
var fillLookup = GetSegmentVisual(segmentI, fillPathHelperContainer, VectorClosingMethod.CloseToPivot);
var strokeLookup = GetSegmentVisual(segmentI, strokePathHelperContainer, VectorClosingMethod.NotClosed);
if (fillLookup.Path.Commands.Count == 1)
{
Fill?.RemoveGeometryFromPainTask(cartesianChart.Canvas, fillLookup.Path);
fillLookup.Path.Commands.Clear();
fillPathHelperContainer.RemoveAt(segmentI);
fillLookup = GetSegmentVisual(segmentI, fillPathHelperContainer, VectorClosingMethod.CloseToPivot);
}
if (strokeLookup.Path.Commands.Count == 1)
{
Stroke?.RemoveGeometryFromPainTask(cartesianChart.Canvas, strokeLookup.Path);
strokeLookup.Path.Commands.Clear();
strokePathHelperContainer.RemoveAt(segmentI);
strokeLookup = GetSegmentVisual(segmentI, strokePathHelperContainer, VectorClosingMethod.NotClosed);
}
var isNew = fillLookup.IsNew || strokeLookup.IsNew;
var fillPath = fillLookup.Path;
var strokePath = strokeLookup.Path;
strokeVector = new VectorManager<StepLineSegment, TDrawingContext>(strokePath);
fillVector = new VectorManager<StepLineSegment, TDrawingContext>(fillPath);
if (Fill is not null)
{
Fill.AddGeometryToPaintTask(cartesianChart.Canvas, fillPath);
cartesianChart.Canvas.AddDrawableTask(Fill);
Fill.ZIndex = actualZIndex + 0.1;
Fill.SetClipRectangle(cartesianChart.Canvas, clipping);
fillPath.Pivot = p;
if (isNew)
{
fillPath.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed);
}
}
if (Stroke is not null)
{
Stroke.AddGeometryToPaintTask(cartesianChart.Canvas, strokePath);
cartesianChart.Canvas.AddDrawableTask(Stroke);
Stroke.ZIndex = actualZIndex + 0.2;
Stroke.SetClipRectangle(cartesianChart.Canvas, clipping);
strokePath.Pivot = p;
if (isNew)
{
strokePath.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed);
}
}
strokePath.Opacity = IsVisible ? 1 : 0;
fillPath.Opacity = IsVisible ? 1 : 0;
}
var coordinate = point.Coordinate;
isSegmentEmpty = false;
var s = 0d;
if (stacker is not null)
s = coordinate.PrimaryValue > 0
? stacker.GetStack(point).Start
: stacker.GetStack(point).NegativeStart;
var visual = (StepLineVisualPoint<TDrawingContext, TVisual>?)point.Context.AdditionalVisuals;
var dp = coordinate.PrimaryValue + s - previousPrimary;
var ds = coordinate.SecondaryValue - previousSecondary;
if (!IsVisible)
{
if (visual is not null)
{
visual.Geometry.X = secondaryScale.ToPixels(coordinate.SecondaryValue);
visual.Geometry.Y = p;
visual.Geometry.Opacity = 0;
visual.Geometry.RemoveOnCompleted = true;
visual.StepSegment.Xi = secondaryScale.ToPixels(coordinate.SecondaryValue - ds);
visual.StepSegment.Xj = secondaryScale.ToPixels(coordinate.SecondaryValue);
visual.StepSegment.Yi = p;
visual.StepSegment.Yj = p;
point.Context.Visual = null;
}
pointsCleanup.Clean(point);
continue;
}
if (visual is null)
{
var v = new StepLineVisualPoint<TDrawingContext, TVisual>();
visual = v;
if (isFirstDraw)
{
v.Geometry.X = secondaryScale.ToPixels(coordinate.SecondaryValue);
v.Geometry.Y = p;
v.Geometry.Width = 0;
v.Geometry.Height = 0;
//v.StepSegment.Xi = secondaryScale.ToPixels(coordinate.SecondaryValue - ds);
//v.StepSegment.Xj = secondaryScale.ToPixels(coordinate.SecondaryValue);
//v.StepSegment.Yi = p;
//v.StepSegment.Yj = p;
v.StepSegment.Yi = primaryScale.ToPixels(coordinate.PrimaryValue + s - dp);
v.StepSegment.Yj = primaryScale.ToPixels(coordinate.PrimaryValue + s);
v.StepSegment.Xi = p;
v.StepSegment.Xj = p;
}
point.Context.Visual = v.Geometry;
point.Context.AdditionalVisuals = v;
OnPointCreated(point);
}
visual.Geometry.Opacity = 1;
if (hasSvg)
{
var svgVisual = (IVariableSvgPath<TDrawingContext>)visual.Geometry;
if (_geometrySvgChanged || svgVisual.SVGPath is null)
svgVisual.SVGPath = GeometrySvg ?? throw new Exception("svg path is not defined");
}
_ = everFetched.Add(point);
GeometryFill?.AddGeometryToPaintTask(cartesianChart.Canvas, visual.Geometry);
GeometryStroke?.AddGeometryToPaintTask(cartesianChart.Canvas, visual.Geometry);
visual.StepSegment.Id = point.Context.Entity.MetaData!.EntityIndex;
if (Fill is not null) fillVector!.AddConsecutiveSegment(visual.StepSegment, !isFirstDraw);
if (Stroke is not null) strokeVector!.AddConsecutiveSegment(visual.StepSegment, !isFirstDraw);
visual.StepSegment.Xi = secondaryScale.ToPixels(coordinate.SecondaryValue - ds);
visual.StepSegment.Xj = secondaryScale.ToPixels(coordinate.SecondaryValue);
visual.StepSegment.Yi = primaryScale.ToPixels(coordinate.PrimaryValue + s - dp);
visual.StepSegment.Yj = primaryScale.ToPixels(coordinate.PrimaryValue + s);
var x = secondaryScale.ToPixels(coordinate.SecondaryValue);
var y = primaryScale.ToPixels(coordinate.PrimaryValue + s);
visual.Geometry.MotionProperties[nameof(visual.Geometry.X)]
.CopyFrom(visual.StepSegment.MotionProperties[nameof(visual.StepSegment.Xj)]);
visual.Geometry.MotionProperties[nameof(visual.Geometry.Y)]
.CopyFrom(visual.StepSegment.MotionProperties[nameof(visual.StepSegment.Yj)]);
visual.Geometry.TranslateTransform = new LvcPoint(-hgs, -hgs);
visual.Geometry.Width = gs;
visual.Geometry.Height = gs;
visual.Geometry.RemoveOnCompleted = false;
visual.FillPath = fillVector!.AreaGeometry;
visual.StrokePath = strokeVector!.AreaGeometry;
var hags = gs < 8 ? 8 : gs;
if (point.Context.HoverArea is not RectangleHoverArea ha)
point.Context.HoverArea = ha = new RectangleHoverArea();
_ = ha
.SetDimensions(x - uwx * 0.5f, y - hgs, uwx, gs)
.CenterXToolTip();
_ = coordinate.PrimaryValue >= pivot
? ha.StartYToolTip()
: ha.EndYToolTip().IsLessThanPivot();
pointsCleanup.Clean(point);
if (DataLabelsPaint is not null)
{
var label = (TLabel?)point.Context.Label;
if (label is null)
{
var l = new TLabel { X = x - hgs, Y = p - hgs, RotateTransform = (float)DataLabelsRotation, MaxWidth = (float)DataLabelsMaxWidth };
l.Animate(EasingFunction ?? cartesianChart.EasingFunction, AnimationsSpeed ?? cartesianChart.AnimationsSpeed);
label = l;
point.Context.Label = l;
}
DataLabelsPaint.AddGeometryToPaintTask(cartesianChart.Canvas, label);
label.Text = DataLabelsFormatter(new ChartPoint<TModel, TVisual, TLabel>(point));
label.TextSize = dls;
label.Padding = DataLabelsPadding;
if (isFirstDraw)
label.CompleteTransition(
nameof(label.TextSize), nameof(label.X), nameof(label.Y), nameof(label.RotateTransform));
var m = label.Measure(DataLabelsPaint);
var labelPosition = GetLabelPosition(
x - hgs, y - hgs, gs, gs, m, DataLabelsPosition,
SeriesProperties, coordinate.PrimaryValue > Pivot, drawLocation, drawMarginSize);
if (DataLabelsTranslate is not null) label.TranslateTransform =
new LvcPoint(m.Width * DataLabelsTranslate.Value.X, m.Height * DataLabelsTranslate.Value.Y);
label.X = labelPosition.X;
label.Y = labelPosition.Y;
}
OnPointMeasured(point);
previousPrimary = coordinate.PrimaryValue + s;
previousSecondary = coordinate.SecondaryValue;
}
strokeVector?.End();
fillVector?.End();
if (GeometryFill is not null)
{
cartesianChart.Canvas.AddDrawableTask(GeometryFill);
GeometryFill.SetClipRectangle(cartesianChart.Canvas, clipping);
GeometryFill.ZIndex = actualZIndex + 0.3;
}
if (GeometryStroke is not null)
{
cartesianChart.Canvas.AddDrawableTask(GeometryStroke);
GeometryStroke.SetClipRectangle(cartesianChart.Canvas, clipping);
GeometryStroke.ZIndex = actualZIndex + 0.4;
}
if (!isSegmentEmpty) segmentI++;
}
var maxSegment = fillPathHelperContainer.Count > strokePathHelperContainer.Count
? fillPathHelperContainer.Count
: strokePathHelperContainer.Count;
for (var i = maxSegment - 1; i >= segmentI; i--)
{
if (i < fillPathHelperContainer.Count)
{
var segmentFill = fillPathHelperContainer[i];
Fill?.RemoveGeometryFromPainTask(cartesianChart.Canvas, segmentFill);
segmentFill.Commands.Clear();
fillPathHelperContainer.RemoveAt(i);
}
if (i < strokePathHelperContainer.Count)
{
var segmentStroke = strokePathHelperContainer[i];
Stroke?.RemoveGeometryFromPainTask(cartesianChart.Canvas, segmentStroke);
segmentStroke.Commands.Clear();
strokePathHelperContainer.RemoveAt(i);
}
}
if (DataLabelsPaint is not null)
{
cartesianChart.Canvas.AddDrawableTask(DataLabelsPaint);
DataLabelsPaint.SetClipRectangle(cartesianChart.Canvas, clipping);
DataLabelsPaint.ZIndex = actualZIndex + 0.5;
}
pointsCleanup.CollectPoints(
everFetched, cartesianChart.View, primaryScale, secondaryScale, SoftDeleteOrDisposePoint);
_geometrySvgChanged = false;
}
`
The text was updated successfully, but these errors were encountered:
I want to implement StepLineSeries' step-drawing inversion. For example, for two points of the same data source, now the X-axis line is drawn first and then the Y-axis line, can you add an attribute to control the Y-axis line first and then the X-axis line when drawing.
I add an attribute 'IsReverse ',then I modified part of the code in the function Invalidate to reverse the order of the coordinate sequence,This will achieve the effect I want.
` private bool _isReverse = false;
///
/// Reverse step line
///
public bool IsReverse { get => _isReverse; set => SetProperty(ref _isReverse, value); }
///
public override void Invalidate(Chart chart)
{
var cartesianChart = (CartesianChart)chart;
var primaryAxis = cartesianChart.YAxes[ScalesYAt];
var secondaryAxis = cartesianChart.XAxes[ScalesXAt];
}
`
The text was updated successfully, but these errors were encountered: