public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata) { for (int i = _innerList.Count - 1; i >= 0; i--) { this[i].Paint(g, layer, pdata); } }
/// <summary> /// Prepares a new substyle (one that is not already in the collection) for becoming member of the collection. The substyle will get /// all distributes group properties (local only) of this style collection. /// </summary> /// <param name="newSubStyle">Sub style to prepare.</param> /// <param name="layer"></param> /// <param name="pdata"></param> public void PrepareNewSubStyle(IG2DPlotStyle newSubStyle, IPlotArea layer, Processed2DPlotData pdata) { PlotGroupStyleCollection externGroup = new PlotGroupStyleCollection(); PlotGroupStyleCollection localGroup = new PlotGroupStyleCollection(); // because we don't step, the order is essential only for PrepareStyles for (int i = 0; i < _innerList.Count; i++) { this[i].CollectLocalGroupStyles(externGroup, localGroup); } newSubStyle.CollectLocalGroupStyles(externGroup, localGroup); // prepare for (int i = 0; i < Count; i++) { this[i].PrepareGroupStyles(externGroup, localGroup, layer, pdata); } newSubStyle.PrepareGroupStyles(externGroup, localGroup, layer, pdata); // apply for (int i = 0; i < Count; i++) { this[i].ApplyGroupStyles(externGroup, localGroup); } newSubStyle.ApplyGroupStyles(externGroup, localGroup); }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { // adjust the skip frequency if it was not set appropriate if (_skipFrequency <= 0) { _skipFrequency = 1; } if (_independentOnShiftingGroupStyles) { _cachedLogicalShiftX = _cachedLogicalShiftY = 0; } PlotRangeList rangeList = pdata.RangeList; if (_ignoreMissingDataPoints) { // in case we ignore the missing points, all ranges can be plotted // as one range, i.e. continuously // for this, we create the totalRange, which contains all ranges var totalRange = new PlotRangeCompound(rangeList); PaintOneRange(g, layer, totalRange, pdata); } else // we not ignore missing points, so plot all ranges separately { for (int i = 0; i < rangeList.Count; i++) { PaintOneRange(g, layer, rangeList[i], pdata); } } }
/// <summary> /// Template to get a fill path. /// </summary> /// <param name="gp">Graphics path to fill with data.</param> /// <param name="pdata">The plot data. Don't use the Range property of the pdata, since it is overriden by the next argument.</param> /// <param name="range">The plot range to use.</param> /// <param name="layer">Graphics layer.</param> /// <param name="fillDirection">Designates a bound to fill to.</param> /// <param name="linePoints">The points that mark the line.</param> /// <param name="connectCircular">If true, a circular connection is drawn.</param> private void FillOneRange_PreprocessedPoints( GraphicsPath gp, Processed2DPlotData pdata, IPlotRange range, IPlotArea layer, CSPlaneID fillDirection, PointF[] linePoints, bool connectCircular, double logicalShiftX, double logicalShiftY ) { if (connectCircular) { gp.AddBeziers(linePoints); gp.CloseFigure(); } else { Logical3D r0 = layer.GetLogical3D(pdata, range.OriginalFirstPoint); r0.RX += logicalShiftX; r0.RY += logicalShiftY; layer.CoordinateSystem.GetIsolineFromPlaneToPoint(gp, fillDirection, r0); gp.AddBeziers(linePoints); Logical3D r1 = layer.GetLogical3D(pdata, range.GetOriginalRowIndexFromPlotPointIndex(range.LowerBound + linePoints.Length - 1)); r1.RX += logicalShiftX; r1.RY += logicalShiftY; layer.CoordinateSystem.GetIsolineFromPointToPlane(gp, r1, fillDirection); layer.CoordinateSystem.GetIsolineOnPlane(gp, fillDirection, r1, r0); gp.CloseFigure(); } }
public void PaintChild(System.Drawing.Graphics g, IPaintContext paintContext, IPlotArea layer, PlotItemCollection coll, int indexOfChild) { var plotDataDict = paintContext.GetValueOrDefault <Dictionary <G2DPlotItem, Processed2DPlotData> >(this); if (null == plotDataDict) // if initializing this dict was not successfull, then make a normal plot { coll[indexOfChild].Paint(g, paintContext, layer, indexOfChild == coll.Count - 1 ? null : coll[indexOfChild + 1], indexOfChild == 0 ? null : coll[indexOfChild - 1]); return; } Processed2DPlotData prevPlotData = null; Processed2DPlotData nextPlotData = null; if ((indexOfChild + 1) < coll.Count && (coll[indexOfChild + 1] is G2DPlotItem)) { prevPlotData = plotDataDict[coll[indexOfChild + 1] as G2DPlotItem]; } if (indexOfChild > 0 && (coll[indexOfChild - 1] is G2DPlotItem)) { nextPlotData = plotDataDict[coll[indexOfChild - 1] as G2DPlotItem]; } if (coll[indexOfChild] is G2DPlotItem) { var gpi = coll[indexOfChild] as G2DPlotItem; gpi.Paint(g, layer, plotDataDict[gpi], prevPlotData, nextPlotData); } else { coll[indexOfChild].Paint(g, paintContext, layer, null, null); } }
public override void PrepareGroupStyles(PlotGroupStyleCollection externalGroups, IPlotArea layer) { Processed2DPlotData pdata = GetRangesAndPoints(layer); if (null == _localGroups) { _localGroups = new PlotGroupStyleCollection() { ParentObject = this } } ; using (var suspendToken = _localGroups.SuspendGetToken()) { _localGroups.Clear(); // first add missing local group styles _plotStyles.CollectLocalGroupStyles(externalGroups, _localGroups); // for the newly created group styles BeginPrepare must be called _localGroups.BeginPrepare(); // now prepare the groups _plotStyles.PrepareGroupStyles(externalGroups, _localGroups, layer, pdata); // for the group styles in the local group, PrepareStep and EndPrepare must be called, _localGroups.PrepareStep(); _localGroups.EndPrepare(); suspendToken.ResumeSilently(); // we are not interested in changes in the _localGroup } }
/// <summary>Adds the y-values of a plot item to an array of y-values..</summary> /// <param name="yArray">The y array to be added to. If null, a new array will be allocated (and filled with the y-values of the plot item).</param> /// <param name="pdata">The pdata.</param> /// <returns>If the parameter <paramref name="yArray"/> was not null, then that <paramref name="yArray"/> is returned. Otherwise the newly allocated array is returned.</returns> public static AltaxoVariant[] AddUp(AltaxoVariant[] yArray, Processed2DPlotData pdata) { if (null == pdata) { throw new ArgumentNullException(nameof(pdata)); } if (yArray == null) { yArray = new AltaxoVariant[pdata.RangeList.PlotPointCount]; int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; yArray[j] = pdata.GetYPhysical(originalIndex); } } else // this is not the first item { int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; yArray[j] += pdata.GetYPhysical(originalIndex); } } return(yArray); }
public void GetFillPath(GraphicsPath gp, IPlotArea layer, Processed2DPlotData pdata, CSPlaneID fillDirection) { PointF[] plotPositions = pdata.PlotPointsInAbsoluteLayerCoordinates; if (0 != _cachedLogicalShiftX || 0 != _cachedLogicalShiftY) { plotPositions = Processed2DPlotData.GetPlotPointsInAbsoluteLayerCoordinatesWithShift(pdata, layer, _cachedLogicalShiftX, _cachedLogicalShiftY); } PlotRangeList rangeList = pdata.RangeList; fillDirection = layer.UpdateCSPlaneID(fillDirection); int rangelistlen = rangeList.Count; if (_ignoreMissingDataPoints) { // in case we ignore the missing points, all ranges can be plotted // as one range, i.e. continuously // for this, we create the totalRange, which contains all ranges var totalRange = new PlotRange(rangeList[0].LowerBound, rangeList[rangelistlen - 1].UpperBound); _connectionStyle.FillOneRange(gp, pdata, totalRange, layer, fillDirection, _ignoreMissingDataPoints, _connectCircular, plotPositions, _cachedLogicalShiftX, _cachedLogicalShiftY); } else // we not ignore missing points, so plot all ranges separately { for (int i = 0; i < rangelistlen; i++) { _connectionStyle.FillOneRange(gp, pdata, rangeList[i], layer, fillDirection, _ignoreMissingDataPoints, _connectCircular, plotPositions, _cachedLogicalShiftX, _cachedLogicalShiftY); } } }
/// <summary> /// Distibute changes made to one group style of the collection (at index <c>pivot</c> to all other members of the collection. /// </summary> /// <param name="pivot">Index of the group style that was changed. This style keeps it's properties.</param> /// <param name="layer"></param> /// <param name="pdata"></param> public void DistributeSubStyleChange(int pivot, IPlotArea layer, Processed2DPlotData pdata) { PlotGroupStyleCollection externGroup = new PlotGroupStyleCollection(); PlotGroupStyleCollection localGroup = new PlotGroupStyleCollection(); // because we don't step, the order is essential only for PrepareStyles for (int i = 0; i < _innerList.Count; i++) { CollectLocalGroupStyles(externGroup, localGroup); } // prepare this[pivot].PrepareGroupStyles(externGroup, localGroup, layer, pdata); for (int i = 0; i < Count; i++) { if (i != pivot) { this[i].PrepareGroupStyles(externGroup, localGroup, layer, pdata); } } // apply this[pivot].ApplyGroupStyles(externGroup, localGroup); for (int i = 0; i < Count; i++) { if (i != pivot) { this[i].ApplyGroupStyles(externGroup, localGroup); } } }
public void MergeYBoundsInto(IPlotArea layer, IPhysicalBoundaries pb, PlotItemCollection coll) { var pbclone = (IPhysicalBoundaries)pb.Clone(); // before we can use CanUseStyle, we have to give physical y boundaries template CoordinateTransformingStyleBase.MergeYBoundsInto(pbclone, coll); if (!CanUseStyle(layer, coll, out var plotDataList)) { pb.Add(pbclone); return; } // we put zero into the y-Boundaries, since the addition starts with that value pb.Add(new AltaxoVariant(0.0)); AltaxoVariant[] ySumArray = null; int idx = -1; foreach (IGPlotItem pi in coll) { if (pi is G2DPlotItem) { idx++; var gpi = (G2DPlotItem)pi; Processed2DPlotData pdata = plotDataList[gpi]; if (null != pdata) { // Note: we can not use AddUp function here, since // when we have positive/negative items, the intermediate bounds // might be wider than the bounds of the end result if (ySumArray == null) { ySumArray = new AltaxoVariant[pdata.RangeList.PlotPointCount]; int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; ySumArray[j] = pdata.GetYPhysical(originalIndex); pb.Add(ySumArray[j]); } } else // this is not the first item { int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; ySumArray[j] += pdata.GetYPhysical(originalIndex); pb.Add(ySumArray[j]); } } } } } }
/// <summary> /// Needed for coordinate transforming styles to plot the data. /// </summary> /// <param name="g">Graphics context.</param> /// <param name="layer">The plot layer.</param> /// <param name="plotdata">The plot data. Since the data are transformed, you should not /// rely that the physical values in this item correspond to the area coordinates.</param> public virtual void Paint(Graphics g, IPlotArea layer, Processed2DPlotData plotdata) { if (null != this._plotStyles) { _plotStyles.Paint(g, layer, plotdata); } _cachedPlotDataUsedForPainting = plotdata; }
public override void Paint(Graphics g, IPlotArea layer) { Processed2DPlotData pdata = GetRangesAndPoints(layer); if (pdata != null) { Paint(g, layer, GetRangesAndPoints(layer)); } }
public Processed2DPlotData GetPlotData(IPlotArea layer) { if (_cachedPlotDataUsedForPainting == null) { _cachedPlotDataUsedForPainting = GetRangesAndPoints(layer); } return(_cachedPlotDataUsedForPainting); }
/// <summary> /// Needed for coordinate transforming styles to plot the data. /// </summary> /// <param name="g">Graphics context.</param> /// <param name="layer">The plot layer.</param> /// <param name="plotdata">The plot data. Since the data are transformed, you should not rely that the physical values in this item correspond to the area coordinates.</param> /// <param name="prevPlotData">Plot data of the previous plot item.</param> /// <param name="nextPlotData">Plot data of the next plot item.</param> public virtual void Paint(Graphics g, IPlotArea layer, Processed2DPlotData plotdata, Processed2DPlotData prevPlotData, Processed2DPlotData nextPlotData) { _cachedPlotDataUsedForPainting = plotdata ?? throw new ArgumentNullException(nameof(plotdata)); if (null != _plotStyles) { _plotStyles.Paint(g, layer, plotdata, prevPlotData, nextPlotData); } }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { if (_connectionStyle is LineConnectionStyles.NoConnection) { return; } PointF[] plotPositions = pdata.PlotPointsInAbsoluteLayerCoordinates; if (_independentOnShiftingGroupStyles) { _cachedLogicalShiftX = _cachedLogicalShiftY = 0; } if (0 != _cachedLogicalShiftX || 0 != _cachedLogicalShiftY) { plotPositions = Processed2DPlotData.GetPlotPointsInAbsoluteLayerCoordinatesWithShift(pdata, layer, _cachedLogicalShiftX, _cachedLogicalShiftY); } // ensure that brush and pen are cached if (null != _framePen) { _framePen.Cached = true; } if (null != _fillBrush) { _fillBrush.SetEnvironment(new RectangleD2D(PointD2D.Empty, layer.Size), BrushX.GetEffectiveMaximumResolution(g, 1)); } _fillDirection = layer.UpdateCSPlaneID(_fillDirection); var gp = new GraphicsPath(); PlotRangeList rangeList = pdata.RangeList; if (_ignoreMissingDataPoints) { // in case we ignore the missing points, all ranges can be plotted // as one range, i.e. continuously // for this, we create the totalRange, which contains all ranges IPlotRange totalRange = new PlotRangeCompound(rangeList); _connectionStyle.FillOneRange(gp, pdata, totalRange, layer, _fillDirection, _ignoreMissingDataPoints, _connectCircular, plotPositions, _cachedLogicalShiftX, _cachedLogicalShiftY); } else // we not ignore missing points, so plot all ranges separately { for (int i = 0; i < rangeList.Count; i++) { _connectionStyle.FillOneRange(gp, pdata, rangeList[i], layer, _fillDirection, _ignoreMissingDataPoints, _connectCircular, plotPositions, _cachedLogicalShiftX, _cachedLogicalShiftY); } } g.FillPath(_fillBrush, gp); g.DrawPath(_framePen, gp); }
public void Paint(System.Drawing.Graphics g, IPlotArea layer, PlotItemCollection coll) { System.Drawing.Region[] clippingColl = new System.Drawing.Region[coll.Count]; Processed2DPlotData[] plotDataColl = new Processed2DPlotData[coll.Count]; double[] xincColl = new double[coll.Count]; double[] yincColl = new double[coll.Count]; int idx = -1; Processed2DPlotData previousPlotData = null; for (int i = 0; i < coll.Count; i++) { if (coll[i] is G2DPlotItem) { idx++; double currxinc = xincColl[i] = idx * _xinc * _scaleXInc; double curryinc = yincColl[i] = idx * _yinc * _scaleYInc; G2DPlotItem gpi = coll[i] as G2DPlotItem; Processed2DPlotData plotdata = plotDataColl[i] = gpi.GetRangesAndPoints(layer); plotdata.PreviousItemData = previousPlotData; previousPlotData = plotdata; int j = -1; foreach (int rowIndex in plotdata.RangeList.OriginalRowIndices()) { j++; AltaxoVariant xx = plotdata.GetXPhysical(rowIndex) + currxinc; AltaxoVariant yy = plotdata.GetYPhysical(rowIndex) + curryinc; Logical3D rel = new Logical3D(layer.XAxis.PhysicalVariantToNormal(xx), layer.YAxis.PhysicalVariantToNormal(yy)); double xabs, yabs; layer.CoordinateSystem.LogicalToLayerCoordinates(rel, out xabs, out yabs); plotdata.PlotPointsInAbsoluteLayerCoordinates[j] = new System.Drawing.PointF((float)xabs, (float)yabs); } if (_useClipping) { GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath(); } } } for (int i = coll.Count - 1; i >= 0; i--) { if (null == plotDataColl[i]) { coll[i].Paint(g, layer); } else { TransformedLayerWrapper layerwrapper = new TransformedLayerWrapper(layer, xincColl[i], yincColl[i]); ((G2DPlotItem)coll[i]).Paint(g, layerwrapper, plotDataColl[i]); } } }
public void PaintPreprocessing(System.Drawing.Graphics g, IPaintContext paintContext, IPlotArea layer, PlotItemCollection coll) { if (!CanUseStyle(layer, coll, out var plotDataDict)) { return; } else { paintContext.AddValue(this, plotDataDict); } AltaxoVariant[] ysumArray = null; foreach (IGPlotItem pi in coll) { if (pi is G2DPlotItem) { var gpi = pi as G2DPlotItem; Processed2DPlotData pdata = plotDataDict[gpi]; ysumArray = AbsoluteStackTransform.AddUp(ysumArray, pdata); } } // now plot the data - the summed up y is in yArray AltaxoVariant[] yArray = null; Processed2DPlotData previousItemData = null; foreach (IGPlotItem pi in coll) { if (pi is G2DPlotItem) { var gpi = pi as G2DPlotItem; Processed2DPlotData pdata = plotDataDict[gpi]; yArray = AbsoluteStackTransform.AddUp(yArray, pdata); var localArray = new AltaxoVariant[yArray.Length]; int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; AltaxoVariant y = 100 * yArray[j] / ysumArray[j]; localArray[j] = y; var rel = new Logical3D( layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(originalIndex)), layer.YAxis.PhysicalVariantToNormal(y)); layer.CoordinateSystem.LogicalToLayerCoordinates(rel, out var xabs, out var yabs); pdata.PlotPointsInAbsoluteLayerCoordinates[j] = new System.Drawing.PointF((float)xabs, (float)yabs); } // we have also to exchange the accessor for the physical y value and replace it by our own one pdata.YPhysicalAccessor = new IndexedPhysicalValueAccessor(delegate(int i) { return(localArray[i]); }); pdata.PreviousItemData = previousItemData; previousItemData = pdata; } } }
public void PaintPreprocessing(System.Drawing.Graphics g, IPaintContext paintContext, IPlotArea layer, PlotItemCollection coll) { if (!CanUseStyle(layer, coll, out var plotDataDict)) { return; } else { paintContext.AddValue(this, plotDataDict); } AltaxoVariant[] yArray = null; // First, add up all items since we start always with the last item int idx = -1; Processed2DPlotData previousItemData = null; foreach (IGPlotItem pi in coll) { if (pi is G2DPlotItem) { idx++; var gpi = pi as G2DPlotItem; Processed2DPlotData pdata = plotDataDict[gpi]; if (null == pdata) { continue; } yArray = AddUp(yArray, pdata); if (idx > 0) // this is not the first item { int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; var rel = new Logical3D( layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(originalIndex)), layer.YAxis.PhysicalVariantToNormal(yArray[j])); layer.CoordinateSystem.LogicalToLayerCoordinates(rel, out var xabs, out var yabs); pdata.PlotPointsInAbsoluteLayerCoordinates[j] = new System.Drawing.PointF((float)xabs, (float)yabs); } } // we have also to exchange the accessor for the physical y value and replace it by our own one var localArray = (AltaxoVariant[])yArray.Clone(); var localArrayHolder = new LocalArrayHolder(localArray, pdata); pdata.YPhysicalAccessor = localArrayHolder.GetPhysical; pdata.PreviousItemData = previousItemData; previousItemData = pdata; } } }
/// <summary> /// Determines whether the plot items in <paramref name="coll"/> can be plotted as stack. Presumption is that all plot items /// have the same number of plot points, and that all items have the same order of x values associated with the plot points. /// </summary> /// <param name="layer">Plot layer.</param> /// <param name="coll">Collection of plot items.</param> /// <param name="plotDataList">Output: dictionary with associates each plot item with a list of processed plot data.</param> /// <returns>Returns <c>true</c> if the plot items in <paramref name="coll"/> can be plotted as stack; otherwise, <c>false</c>.</returns> public static bool CanUseStyle(IPlotArea layer, PlotItemCollection coll, out Dictionary <G2DPlotItem, Processed2DPlotData> plotDataList) { plotDataList = new Dictionary <G2DPlotItem, Processed2DPlotData>(); AltaxoVariant[] xArray = null; int idx = -1; foreach (IGPlotItem pi in coll) { if (pi is G2DPlotItem) { idx++; var gpi = (G2DPlotItem)pi; Processed2DPlotData pdata = gpi.GetRangesAndPoints(layer); plotDataList.Add(gpi, pdata); if (null != pdata) { if (xArray == null) { xArray = new AltaxoVariant[pdata.RangeList.PlotPointCount]; int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; xArray[j] = pdata.GetXPhysical(originalIndex); } } else // this is not the first item { if (pdata.RangeList.PlotPointCount != xArray.Length) { return(false); } int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; if (xArray[j] != pdata.GetXPhysical(originalIndex)) { return(false); } } } } } } return(idx >= 1); }
/// <summary> /// Test wether the mouse hits a plot item. /// </summary> /// <param name="layer">The layer in which this plot item is drawn into.</param> /// <param name="hitpoint">The point where the mouse is pressed.</param> /// <returns>Null if no hit, or a <see cref="IHitTestObject" /> if there was a hit.</returns> public override IHitTestObject HitTest(IPlotArea layer, PointD2D hitpoint) { Processed2DPlotData pdata = _cachedPlotDataUsedForPainting; if (null == pdata) { return(null); } PlotRangeList rangeList = pdata.RangeList; PointF[] ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; if (ptArray.Length < 2) { return(null); } if (ptArray.Length < 2048) { if (GdiExtensionMethods.IsPointIntoDistance((PointF)hitpoint, 2.5, ptArray)) { var gp = new GraphicsPath(); gp.AddLines(ptArray); gp.Widen(new Pen(Color.Black, 5)); return(new HitTestObject(gp, this)); } } else // we have too much points for the graphics path, so make a hit test first { int hitindex = -1; for (int i = 1; i < ptArray.Length; i++) { if (Math2D.IsPointIntoDistance((PointF)hitpoint, 5, ptArray[i - 1], ptArray[i])) { hitindex = i; break; } } if (hitindex < 0) { return(null); } var gp = new GraphicsPath(); int start = Math.Max(0, hitindex - 2); gp.AddLine(ptArray[start], ptArray[start + 1]); gp.AddLine(ptArray[start + 1], ptArray[start + 2]); gp.Widen(new Pen(Color.Black, 5)); return(new HitTestObject(gp, this)); } return(null); }
public override void Paint(Graphics g, IPaintContext context, IPlotArea layer, IGPlotItem prevPlotItem, IGPlotItem nextPlotItem) { Processed2DPlotData pdata = GetRangesAndPoints(layer); if (pdata != null) { Paint(g, layer, pdata, (prevPlotItem is G2DPlotItem) ? ((G2DPlotItem)prevPlotItem).GetPlotData(layer) : null, (nextPlotItem is G2DPlotItem) ? ((G2DPlotItem)nextPlotItem).GetPlotData(layer) : null ); } }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { if (null == pdata) { throw new ArgumentNullException(nameof(pdata)); } for (int i = _innerList.Count - 1; i >= 0; i--) { this[i].Paint(g, layer, pdata, prevItemData, nextItemData); } }
/// <summary> /// Template to get a fill path. /// </summary> /// <param name="gp">Graphics path to fill with data.</param> /// <param name="pdata">The plot data. Do not use the plot point positions from here, since they are not shifted when shifting group styles are present.</param> /// <param name="range">The plot range to use.</param> /// <param name="layer">Graphics layer.</param> /// <param name="fillDirection">Designates a bound to fill to.</param> /// <param name="ignoreMissingDataPoints">If true, missing data points are ignored.</param> /// <param name="connectCircular">If true, the line is connected circular, and the area is the polygon inside of that circular connection.</param> /// <param name="allLinePointsShiftedAlready">The plot positions, already shifted when a logical shift needed to be applied. Don't use the Range property of the pdata, since it is overriden by the next argument.</param> /// <param name="logicalShiftX">The logical shift in x-direction.</param> /// <param name="logicalShiftY">The logical shift in x-direction.</param> public abstract void FillOneRange( GraphicsPath gp, Processed2DPlotData pdata, IPlotRange range, IPlotArea layer, CSPlaneID fillDirection, bool ignoreMissingDataPoints, bool connectCircular, PointF[] allLinePointsShiftedAlready, double logicalShiftX, double logicalShiftY );
/// <summary> /// Test wether the mouse hits a plot item. /// </summary> /// <param name="layer">The layer in which this plot item is drawn into.</param> /// <param name="hitpoint">The point where the mouse is pressed.</param> /// <returns>Null if no hit, or a <see cref="IHitTestObject" /> if there was a hit.</returns> public override IHitTestObject HitTest(IPlotArea layer, PointF hitpoint) { Processed2DPlotData pdata = _cachedPlotDataUsedForPainting; if (null == pdata) { return(null); } PlotRangeList rangeList = pdata.RangeList; PointF[] ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; if (ptArray.Length < 2048) { GraphicsPath gp = new GraphicsPath(); gp.AddLines(ptArray); if (gp.IsOutlineVisible(hitpoint.X, hitpoint.Y, new Pen(Color.Black, 5))) { gp.Widen(new Pen(Color.Black, 5)); return(new HitTestObject(gp, this)); } } else // we have too much points for the graphics path, so make a hit test first { int hitindex = -1; for (int i = 1; i < ptArray.Length; i++) { if (Drawing2DRelated.IsPointIntoDistance(ptArray[i - 1], ptArray[i], hitpoint, 5)) { hitindex = i; break; } } if (hitindex < 0) { return(null); } GraphicsPath gp = new GraphicsPath(); int start = Math.Max(0, hitindex - 1); gp.AddLine(ptArray[start], ptArray[start + 1]); gp.AddLine(ptArray[start + 1], ptArray[start + 2]); gp.Widen(new Pen(Color.Black, 5)); return(new HitTestObject(gp, this)); } return(null); }
/// <inheritdoc/> public override void FillOneRange( GraphicsPath gp, Processed2DPlotData pdata, IPlotRange range, IPlotArea layer, CSPlaneID fillDirection, bool ignoreMissingDataPoints, bool connectCircular, PointF[] allLinePointsShiftedAlready, double logicalShiftX, double logicalShiftY ) { if (range.Length < 2) { return; } PointF[] linePoints = Segment2Connection_GetSubPoints(allLinePointsShiftedAlready, range, layer, connectCircular, out var lastIdx); if (connectCircular) { gp.AddLines(linePoints); gp.CloseFigure(); } else { int offs = range.LowerBound; for (int i = 0; i < linePoints.Length - 1; i += 2) { Logical3D r0 = layer.GetLogical3D(pdata, range.GetOriginalRowIndexFromPlotPointIndex(range.LowerBound + i)); r0.RX += logicalShiftX; r0.RY += logicalShiftY; layer.CoordinateSystem.GetIsolineFromPlaneToPoint(gp, fillDirection, r0); gp.AddLine(linePoints[i].X, linePoints[i].Y, linePoints[i + 1].X, linePoints[i + 1].Y); Logical3D r1 = layer.GetLogical3D(pdata, range.GetOriginalRowIndexFromPlotPointIndex(range.LowerBound + i + 1)); r1.RX += logicalShiftX; r1.RY += logicalShiftY; layer.CoordinateSystem.GetIsolineFromPointToPlane(gp, r1, fillDirection); layer.CoordinateSystem.GetIsolineOnPlane(gp, fillDirection, r1, r0); gp.StartFigure(); } gp.CloseFigure(); } }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { // adjust the skip frequency if it was not set appropriate if (_skipFreq <= 0) { _skipFreq = 1; } if (_scatterSymbol is NoSymbol) { return; } var cachedPathData = new CachedPathData(); var cachedBrushData = new CachedBrushData(); PlotRangeList rangeList = pdata.RangeList; PointF[] plotPositions = pdata.PlotPointsInAbsoluteLayerCoordinates; if (!_independentOnShiftingGroupStyles && (0 != _cachedLogicalShiftX || 0 != _cachedLogicalShiftY)) { plotPositions = Processed2DPlotData.GetPlotPointsInAbsoluteLayerCoordinatesWithShift(pdata, layer, _cachedLogicalShiftX, _cachedLogicalShiftY); } // Calculate current scatterSymbol overridden with frame and inset var scatterSymbol = CalculateOverriddenScatterSymbol(); if (_ignoreMissingDataPoints) { // in case we ignore the missing points, all ranges can be plotted // as one range, i.e. continuously // for this, we create the totalRange, which contains all ranges var totalRange = new PlotRangeCompound(rangeList); PaintOneRange(g, layer, plotPositions, totalRange, scatterSymbol, ref cachedPathData, ref cachedBrushData); } else // we not ignore missing points, so plot all ranges separately { for (int i = 0; i < rangeList.Count; i++) { PaintOneRange(g, layer, plotPositions, rangeList[i], scatterSymbol, ref cachedPathData, ref cachedBrushData); } } cachedBrushData.Clear(); cachedPathData.Clear(); }
/// <inheritdoc/> public override void FillOneRange( GraphicsPath gp, Processed2DPlotData pdata, IPlotRange range, IPlotArea layer, CSPlaneID fillDirection, bool ignoreMissingDataPoints, bool connectCircular, PointF[] allLinePoints, double logicalShiftX, double logicalShiftY ) { if (range.Length < 4) { return; } if (connectCircular) { var circularLinePointsLengthM1 = 2 + TrimToValidBezierLength(range.Length); var circularLinePoints = new PointF[circularLinePointsLengthM1 + 1]; Array.Copy(allLinePoints, range.LowerBound, circularLinePoints, 0, range.Length); // Extract circularLinePoints[circularLinePointsLengthM1] = circularLinePoints[0]; // amend missing control points if (circularLinePointsLengthM1 - range.Length >= 1) { circularLinePoints[circularLinePointsLengthM1 - 1] = GdiExtensionMethods.Interpolate(circularLinePoints[circularLinePointsLengthM1 - 3], circularLinePoints[circularLinePointsLengthM1], 0.5); // Last Control point should be halfway between } if (circularLinePointsLengthM1 - range.Length >= 2) { circularLinePoints[circularLinePointsLengthM1 - 2] = GdiExtensionMethods.Interpolate(circularLinePoints[circularLinePointsLengthM1 - 3], circularLinePoints[circularLinePointsLengthM1], 0.5); // Middle Control point should be halfway between previous fixed point and last(=first) fixed point } FillOneRange_PreprocessedPoints(gp, pdata, range, layer, fillDirection, circularLinePoints, connectCircular, logicalShiftX, logicalShiftY); } else { var trimmedLinePointsLength = TrimToValidBezierLength(range.Length); var trimmedLinePoints = new PointF[trimmedLinePointsLength]; Array.Copy(allLinePoints, range.LowerBound, trimmedLinePoints, 0, trimmedLinePointsLength); // Extract FillOneRange_PreprocessedPoints(gp, pdata, range, layer, fillDirection, trimmedLinePoints, connectCircular, logicalShiftX, logicalShiftY); } }
public override void PrepareStyles(PlotGroupStyleCollection externalGroups, IPlotArea layer) { Processed2DPlotData pdata = GetRangesAndPoints(layer); _localGroups = new PlotGroupStyleCollection(); // first add missing local group styles foreach (IG2DPlotStyle sps in _plotStyles) { sps.CollectLocalGroupStyles(externalGroups, _localGroups); } // now prepare the groups foreach (IG2DPlotStyle sps in _plotStyles) { sps.PrepareGroupStyles(externalGroups, _localGroups, layer, pdata); } }
/// <inheritdoc/> public override void FillOneRange( GraphicsPath gp, Processed2DPlotData pdata, IPlotRange range, IPlotArea layer, CSPlaneID fillDirection, bool ignoreMissingDataPoints, bool connectCircular, PointF[] allLinePoints, double logicalShiftX, double logicalShiftY ) { var circularLinePoints = new PointF[range.Length + (connectCircular ? 1 : 0)]; Array.Copy(allLinePoints, range.LowerBound, circularLinePoints, 0, range.Length); // Extract if (connectCircular) { circularLinePoints[circularLinePoints.Length - 1] = circularLinePoints[0]; } if (connectCircular) { gp.AddLines(circularLinePoints); gp.CloseFigure(); } else // not circular { Logical3D r0 = layer.GetLogical3D(pdata, range.OriginalFirstPoint); r0.RX += logicalShiftX; r0.RY += logicalShiftY; layer.CoordinateSystem.GetIsolineFromPlaneToPoint(gp, fillDirection, r0); gp.AddLines(circularLinePoints); Logical3D r1 = layer.GetLogical3D(pdata, connectCircular ? range.OriginalFirstPoint : range.OriginalLastPoint); r1.RX += logicalShiftX; r1.RY += logicalShiftY; layer.CoordinateSystem.GetIsolineFromPointToPlane(gp, r1, fillDirection); layer.CoordinateSystem.GetIsolineOnPlane(gp, fillDirection, r1, r0); gp.CloseFigure(); } }
/// <inheritdoc/> public override void FillOneRange( GraphicsPath gp, Processed2DPlotData pdata, IPlotRange range, IPlotArea layer, CSPlaneID fillDirection, bool ignoreMissingDataPoints, bool connectCircular, PointF[] allLinePoints, double logicalShiftX, double logicalShiftY ) { if (range.Length < 2) { return; } PointF[] linepts = GetStepPolylinePoints(allLinePoints, range, layer, connectCircular, out var numberOfPointsPerOriginalPoint, out var lastIdx); FillOneRange(gp, pdata, range, layer, fillDirection, linepts, connectCircular, allLinePoints, logicalShiftX, logicalShiftY); }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata) { PlotRangeList rangeList = pdata.RangeList; PointF[] ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; // adjust the skip frequency if it was not set appropriate if (_skipFreq <= 0) _skipFreq = 1; // paint the drop style if (this.DropLine.Count>0) { foreach (CSPlaneID id in _dropLine) layer.UpdateCSPlaneID(id); int rangeidx = 0; PlotRange range = pdata.RangeList[rangeidx]; for (int j = 0; j < ptArray.Length; j += _skipFreq) { // syncronize range while (j >= range.UpperBound) { rangeidx++; range = pdata.RangeList[rangeidx]; } Logical3D r3d = layer.GetLogical3D(pdata, j + range.OffsetToOriginal); foreach(CSPlaneID id in _dropLine) layer.CoordinateSystem.DrawIsolineFromPointToPlane(g,this._pen, r3d, id); } } // end paint the drop style // paint the scatter style if (this.Shape != XYPlotScatterStyles.Shape.NoSymbol) { // save the graphics stat since we have to translate the origin System.Drawing.Drawing2D.GraphicsState gs = g.Save(); float xpos = 0, ypos = 0; float xdiff, ydiff; for (int j = 0; j < ptArray.Length; j += _skipFreq) { xdiff = ptArray[j].X - xpos; ydiff = ptArray[j].Y - ypos; xpos = ptArray[j].X; ypos = ptArray[j].Y; g.TranslateTransform(xdiff, ydiff); this.Paint(g); } // end for g.Restore(gs); // Restore the graphics state } }
public static AltaxoVariant[] AddUp(AltaxoVariant[] yArray, Processed2DPlotData pdata) { if (yArray == null) { yArray = new AltaxoVariant[pdata.RangeList.PlotPointCount]; int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; yArray[j] = pdata.GetYPhysical(originalIndex); } } else // this is not the first item { int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; yArray[j] += pdata.GetYPhysical(originalIndex); } } return yArray; }
public void PrepareGroupStyles(PlotGroupStyleCollection externalGroups, PlotGroupStyleCollection localGroups, IPlotArea layer, Processed2DPlotData pdata) { if (this.IsColorProvider) ColorGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return this.LabelBrush.Color; }); else if (this.IsBackgroundColorProvider) ColorGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return this._backgroundStyle.Brush.Color; }); // SkipFrequency should be the same for all sub plot styles, so there is no "private" property if (!_independentSkipFrequency) SkipFrequencyGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return _skipFrequency; }); // IgnoreMissingDataPoints should be the same for all sub plot styles, so there is no "private" property IgnoreMissingDataPointsGroupStyle.PrepareStyle(externalGroups, localGroups, () => _ignoreMissingDataPoints); }
public void PaintOneRange(Graphics g, IPlotArea layer, IPlotRange range, Processed2DPlotData pdata) { if (this._labelColumnProxy.Document == null) return; _cachedStringFormat.Alignment = GdiExtensionMethods.ToGdi(_alignmentX); _cachedStringFormat.LineAlignment = GdiExtensionMethods.ToGdi(_alignmentY); if (null != _attachedPlane) _attachedPlane = layer.UpdateCSPlaneID(_attachedPlane); var ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; Altaxo.Data.IReadableColumn labelColumn = this._labelColumnProxy.Document; bool isUsingVariableColorForLabelText = null != _cachedColorForIndexFunction && IsColorReceiver; bool isUsingVariableColorForLabelBackground = null != _cachedColorForIndexFunction && (null != _backgroundStyle && _backgroundStyle.SupportsBrush && (_backgroundColorLinkage == ColorLinkage.Dependent || _backgroundColorLinkage == ColorLinkage.PreserveAlpha)); bool isUsingVariableColor = isUsingVariableColorForLabelText || isUsingVariableColorForLabelBackground; BrushX clonedTextBrush = null; BrushX clonedBackBrush = null; if (isUsingVariableColorForLabelText) clonedTextBrush = _brush.Clone(); if (isUsingVariableColorForLabelBackground) clonedBackBrush = _backgroundStyle.Brush.Clone(); // save the graphics stat since we have to translate the origin var gs = g.Save(); double xpos = 0, ypos = 0; double xpre, ypre; double xdiff, ydiff; bool isFormatStringContainingBraces = _labelFormatString?.IndexOf('{') >= 0; var culture = System.Threading.Thread.CurrentThread.CurrentCulture; bool mustUseLogicalCoordinates = null != this._attachedPlane || 0 != _cachedLogicalShiftX || 0 != _cachedLogicalShiftY; int lower = range.LowerBound; int upper = range.UpperBound; for (int j = lower; j < upper; j+=_skipFrequency) { int originalRowIndex = range.GetOriginalRowIndexFromPlotPointIndex(j); string label; if (string.IsNullOrEmpty(_labelFormatString)) { label = labelColumn[originalRowIndex].ToString(); } else if (!isFormatStringContainingBraces) { label = labelColumn[originalRowIndex].ToString(_labelFormatString, culture); } else { // the label format string can contain {0} for the label column item, {1} for the row index, {2} .. {4} for the x, y and z component of the data point label = string.Format(_labelFormatString, labelColumn[originalRowIndex], originalRowIndex, pdata.GetPhysical(0, originalRowIndex), pdata.GetPhysical(1, originalRowIndex), pdata.GetPhysical(2, originalRowIndex)); } if (string.IsNullOrEmpty(label)) continue; double localSymbolSize = _symbolSize; if (null != _cachedSymbolSizeForIndexFunction) { localSymbolSize = _cachedSymbolSizeForIndexFunction(originalRowIndex); } double localFontSize = _fontSizeOffset + _fontSizeFactor * localSymbolSize; if (!(localFontSize > 0)) continue; _font = _font.WithSize(localFontSize); // Start of preparation of brushes, if a variable color is used if (isUsingVariableColor) { Color c = _cachedColorForIndexFunction(originalRowIndex); if (isUsingVariableColorForLabelText) { clonedTextBrush.Color = new NamedColor(AxoColor.FromArgb(c.A, c.R, c.G, c.B), "e"); } if (isUsingVariableColorForLabelBackground) { if (_backgroundColorLinkage == ColorLinkage.PreserveAlpha) clonedBackBrush.Color = new NamedColor(AxoColor.FromArgb(clonedBackBrush.Color.Color.A, c.R, c.G, c.B), "e"); else clonedBackBrush.Color = new NamedColor(AxoColor.FromArgb(c.A, c.R, c.G, c.B), "e"); } } // end of preparation of brushes for variable colors if (mustUseLogicalCoordinates) // we must use logical coordinates because either there is a shift of logical coordinates, or an attached plane { Logical3D r3d = layer.GetLogical3D(pdata, originalRowIndex); r3d.RX += _cachedLogicalShiftX; r3d.RY += _cachedLogicalShiftY; if (null != this._attachedPlane) { var pp = layer.CoordinateSystem.GetPointOnPlane(this._attachedPlane, r3d); xpre = pp.X; ypre = pp.Y; } else { PointD3D pt; layer.CoordinateSystem.LogicalToLayerCoordinates(r3d, out xpre, out ypre); } } else // no shifting, thus we can use layer coordinates { xpre = ptArray[j].X; ypre = ptArray[j].Y; } xdiff = xpre - xpos; ydiff = ypre - ypos; xpos = xpre; ypos = ypre; g.TranslateTransform((float)xdiff, (float)ydiff); if (this._rotation != 0) g.RotateTransform((float)-this._rotation); this.PaintOneItem(g, label, localSymbolSize, clonedTextBrush, clonedBackBrush); if (this._rotation != 0) g.RotateTransform((float)this._rotation); } g.Restore(gs); // Restore the graphics state }
private void PaintFillToPrevPlotItem(Graphics g, IPlotArea layer, Altaxo.Graph.Gdi.Plot.Data.Processed2DPlotData pdata, Processed2DPlotData prevItemData) { // ensure that brush and pen are cached if (null != _fillBrush) { _fillBrush.SetEnvironment(new RectangleD2D(PointD2D.Empty, layer.Size), BrushX.GetEffectiveMaximumResolution(g, 1)); } PlotRangeList rangeList = pdata.RangeList; int rangelistlen = rangeList.Count; // we have to ignore the missing points here, thus all ranges can be plotted // as one range, i.e. continuously // for this, we create the totalRange, which contains all ranges PlotRange totalRange = new PlotRange(rangeList[0].LowerBound, rangeList[rangelistlen - 1].UpperBound, rangeList[0].OffsetToOriginal); _cachedPaintOneRange(g, pdata, totalRange, layer, prevItemData); }
public void PrepareGroupStyles(PlotGroupStyleCollection externalGroups, PlotGroupStyleCollection localGroups, IPlotArea layer, Processed2DPlotData pdata) { if (!_independentColor) Graph.Plot.Groups.ColorGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return this._strokePen.Color; }); if (!_independentSkipFrequency) SkipFrequencyGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return SkipFrequency; }); // IgnoreMissingDataPoints should be the same for all sub plot styles, so there is no "private" property IgnoreMissingDataPointsGroupStyle.PrepareStyle(externalGroups, localGroups, () => _ignoreMissingDataPoints); // note: symbol size and barposition are only applied, but not prepared // this item can not be used as provider of a symbol size }
public Processed2DPlotData GetPlotData(IPlotArea layer) { if (_cachedPlotDataUsedForPainting == null) _cachedPlotDataUsedForPainting = GetRangesAndPoints(layer); return _cachedPlotDataUsedForPainting; }
public void PrepareGroupStyles(PlotGroupStyleCollection externalGroups, PlotGroupStyleCollection localGroups, IPlotArea layer, Processed2DPlotData pdata) { if (this.IsColorProvider) ColorGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return this.Color; }); if (!_independentDashStyle) DashPatternGroupStyle.PrepareStyle(externalGroups, localGroups, delegate { return this.LinePen.DashPattern; }); IgnoreMissingDataPointsGroupStyle.PrepareStyle(externalGroups, localGroups, () => _ignoreMissingDataPoints); LineConnection2DGroupStyle.PrepareStyle(externalGroups, localGroups, () => new Tuple<ILineConnectionStyle, bool>(_connectionStyle, _connectCircular)); }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { if (this._connectionStyle is LineConnectionStyles.NoConnection) return; if (_independentOnShiftingGroupStyles) { _cachedLogicalShiftX = _cachedLogicalShiftY = 0; } PointF[] plotPositions = pdata.PlotPointsInAbsoluteLayerCoordinates; if (0 != _cachedLogicalShiftX || 0 != _cachedLogicalShiftY) { plotPositions = Processed2DPlotData.GetPlotPointsInAbsoluteLayerCoordinatesWithShift(pdata, layer, _cachedLogicalShiftX, _cachedLogicalShiftY); } Func<int, double> symbolGapFunction = null; if (_useSymbolGap) { if (null != _cachedSymbolSizeForIndexFunction && !_independentSymbolSize) { symbolGapFunction = (idx) => _symbolGapOffset + _symbolGapFactor * _cachedSymbolSizeForIndexFunction(idx); } else if (0 != _symbolGapOffset || 0 != _symbolGapFactor * _symbolSize) { symbolGapFunction = (idx) => _symbolGapOffset + _symbolGapFactor * _symbolSize; } else { symbolGapFunction = null; } } // ensure that brush and pen are cached if (null != _linePen) _linePen.Cached = true; PlotRangeList rangeList = pdata.RangeList; if (this._ignoreMissingDataPoints) { // in case we ignore the missing points, all ranges can be plotted // as one range, i.e. continuously // for this, we create the totalRange, which contains all ranges var totalRange = new PlotRangeCompound(rangeList); _connectionStyle.PaintOneRange(g, plotPositions, totalRange, layer, _linePen, symbolGapFunction, _skipFrequency, _connectCircular, this); } else // we not ignore missing points, so plot all ranges separately { for (int i = 0; i < rangeList.Count; i++) { _connectionStyle.PaintOneRange(g, plotPositions, rangeList[i], layer, _linePen, symbolGapFunction, _skipFrequency, _connectCircular, this); } } }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { // this is not a visible style, thus doing nothing }
public void PrepareGroupStyles(PlotGroupStyleCollection externalGroups, PlotGroupStyleCollection localGroups, IPlotArea layer, Processed2DPlotData pdata) { VariableSymbolSizeGroupStyle.PrepareStyle(externalGroups, localGroups, GetSymbolSize); }
/// <summary> /// This will create a point list out of the data, which can be used to plot the data. In order to create this list, /// the function must have knowledge how to calculate the points out of the data. This will be done /// by a function provided by the calling function. /// </summary> /// <param name="layer">The plot layer.</param> /// <returns>An array of plot points in layer coordinates.</returns> public Processed2DPlotData GetRangesAndPoints( Gdi.IPlotArea layer) { const double MaxRelativeValue = 1E2; Altaxo.Data.IReadableColumn xColumn = this.XColumn; Altaxo.Data.IReadableColumn yColumn = this.YColumn; if(null==xColumn || null==yColumn) return null; // this plotitem is only for x and y double columns if(this.PlottablePoints<=0) return null; Processed2DPlotData result = new Processed2DPlotData(); MyPlotData myPlotData = new MyPlotData(xColumn, yColumn); result.XPhysicalAccessor = new IndexedPhysicalValueAccessor(myPlotData.GetXPhysical); result.YPhysicalAccessor = new IndexedPhysicalValueAccessor(myPlotData.GetYPhysical); PlotRangeList rangeList = null; PointF[] ptArray = null; // allocate an array PointF to hold the line points ptArray = new PointF[this.PlottablePoints]; result.PlotPointsInAbsoluteLayerCoordinates = ptArray; // Fill the array with values // only the points where x and y are not NaNs are plotted! int i,j; bool bInPlotSpace = true; int rangeStart=0; int rangeOffset=0; rangeList = new PlotRangeList(); result.RangeList = rangeList; Scale xAxis = layer.XAxis; Scale yAxis = layer.YAxis; Gdi.G2DCoordinateSystem coordsys = layer.CoordinateSystem; int len = this.PlotRangeEnd; for(i=this.PlotRangeStart,j=0;i<len;i++) { if(xColumn.IsElementEmpty(i) || yColumn.IsElementEmpty(i)) { if(!bInPlotSpace) { bInPlotSpace=true; rangeList.Add(new PlotRange(rangeStart,j,rangeOffset)); } continue; } double x_rel,y_rel; double xcoord, ycoord; x_rel = xAxis.PhysicalVariantToNormal(xColumn[i]); y_rel = yAxis.PhysicalVariantToNormal(yColumn[i]); // chop relative values to an range of about -+ 10^6 if(x_rel>MaxRelativeValue) x_rel = MaxRelativeValue; if(x_rel<-MaxRelativeValue) x_rel=-MaxRelativeValue; if(y_rel>MaxRelativeValue) y_rel = MaxRelativeValue; if(y_rel<-MaxRelativeValue) y_rel=-MaxRelativeValue; // after the conversion to relative coordinates it is possible // that with the choosen axis the point is undefined // (for instance negative values on a logarithmic axis) // in this case the returned value is NaN if(coordsys.LogicalToLayerCoordinates(new Logical3D(x_rel,y_rel), out xcoord, out ycoord)) { if(bInPlotSpace) { bInPlotSpace=false; rangeStart = j; rangeOffset = i-j; } ptArray[j].X = (float)xcoord; ptArray[j].Y = (float)ycoord; j++; } else { if(!bInPlotSpace) { bInPlotSpace=true; rangeList.Add(new PlotRange(rangeStart,j,rangeOffset)); } } } // end for if(!bInPlotSpace) { bInPlotSpace=true; rangeList.Add(new PlotRange(rangeStart,j,rangeOffset)); // add the last range } return result; }
/// <summary>Initializes a new instance of the <see cref="LocalArrayHolder"/> class.</summary> /// <param name="localArray">The local array of transformed y values. The array length is equal to the number of plot points.</param> /// <param name="pdata">The processed plot data. The plot range member of this instance is used to build a dictionary which associates the original row indices to the indices of the <paramref name="localArray"/>.</param> public LocalArrayHolder(AltaxoVariant[] localArray, Processed2DPlotData pdata) { _localArray = localArray; _originalRowIndexToPlotIndex = pdata.RangeList.GetDictionaryOfOriginalRowIndicesToPlotIndices(); }
/// <summary> /// This will create a point list out of the data, which can be used to plot the data. In order to create this list, /// the function must have knowledge how to calculate the points out of the data. This will be done /// by a function provided by the calling function. /// </summary> /// <param name="layer">The plot layer.</param> /// <returns>An array of plot points in layer coordinates.</returns> public Processed2DPlotData GetRangesAndPoints( Gdi.IPlotArea layer) { const double MaxRelativeValue = 1E2; Altaxo.Data.IReadableColumn xColumn = this.XColumn; Altaxo.Data.IReadableColumn yColumn = this.YColumn; if (null == xColumn || null == yColumn) return null; // this plotitem is only for x and y double columns Processed2DPlotData result = new Processed2DPlotData(); MyPlotData myPlotData = new MyPlotData(xColumn, yColumn); result.XPhysicalAccessor = new IndexedPhysicalValueAccessor(myPlotData.GetXPhysical); result.YPhysicalAccessor = new IndexedPhysicalValueAccessor(myPlotData.GetYPhysical); PlotRangeList rangeList = null; // allocate an array PointF to hold the line points // _tlsBufferedPlotData is a static buffer that is allocated per thread // and thus is only used temporary here in this routine if (null == _tlsBufferedPlotData) _tlsBufferedPlotData = new List<PointF>(); else _tlsBufferedPlotData.Clear(); // Fill the array with values // only the points where x and y are not NaNs are plotted! bool bInPlotSpace = true; int plotRangeStart = 0; int rangeOffset = 0; rangeList = new PlotRangeList(); result.RangeList = rangeList; Scale xAxis = layer.XAxis; Scale yAxis = layer.YAxis; Gdi.G2DCoordinateSystem coordsys = layer.CoordinateSystem; int maxRowIndex = GetMaximumRowIndexFromDataColumns(); int plotArrayIdx = 0; foreach (int dataRowIdx in _dataRowSelection.GetSelectedRowIndicesFromTo(0, maxRowIndex, _dataTable?.Document?.DataColumns, maxRowIndex)) { if (xColumn.IsElementEmpty(dataRowIdx) || yColumn.IsElementEmpty(dataRowIdx)) { if (!bInPlotSpace) { bInPlotSpace = true; rangeList.Add(new PlotRange(plotRangeStart, plotArrayIdx, rangeOffset)); } continue; } double x_rel, y_rel; double xcoord, ycoord; x_rel = xAxis.PhysicalVariantToNormal(xColumn[dataRowIdx]); y_rel = yAxis.PhysicalVariantToNormal(yColumn[dataRowIdx]); // chop relative values to an range of about -+ 10^6 if (x_rel > MaxRelativeValue) x_rel = MaxRelativeValue; if (x_rel < -MaxRelativeValue) x_rel = -MaxRelativeValue; if (y_rel > MaxRelativeValue) y_rel = MaxRelativeValue; if (y_rel < -MaxRelativeValue) y_rel = -MaxRelativeValue; // after the conversion to relative coordinates it is possible // that with the choosen axis the point is undefined // (for instance negative values on a logarithmic axis) // in this case the returned value is NaN if (coordsys.LogicalToLayerCoordinates(new Logical3D(x_rel, y_rel), out xcoord, out ycoord)) { if (bInPlotSpace) { bInPlotSpace = false; plotRangeStart = plotArrayIdx; rangeOffset = dataRowIdx - plotArrayIdx; } _tlsBufferedPlotData.Add(new PointF((float)xcoord, (float)ycoord)); plotArrayIdx++; } else { if (!bInPlotSpace) { bInPlotSpace = true; rangeList.Add(new PlotRange(plotRangeStart, plotArrayIdx, rangeOffset)); } } } // end foreach if (!bInPlotSpace) { bInPlotSpace = true; rangeList.Add(new PlotRange(plotRangeStart, plotArrayIdx, rangeOffset)); // add the last range } result.PlotPointsInAbsoluteLayerCoordinates = _tlsBufferedPlotData.ToArray(); return result; }
public void GetFillPath(GraphicsPath gp, IPlotArea layer, Processed2DPlotData pdata, CSPlaneID fillDirection) { PointF[] plotPositions = pdata.PlotPointsInAbsoluteLayerCoordinates; if (0 != _cachedLogicalShiftX || 0 != _cachedLogicalShiftY) { plotPositions = Processed2DPlotData.GetPlotPointsInAbsoluteLayerCoordinatesWithShift(pdata, layer, _cachedLogicalShiftX, _cachedLogicalShiftY); } PlotRangeList rangeList = pdata.RangeList; fillDirection = layer.UpdateCSPlaneID(fillDirection); int rangelistlen = rangeList.Count; if (this._ignoreMissingDataPoints) { // in case we ignore the missing points, all ranges can be plotted // as one range, i.e. continuously // for this, we create the totalRange, which contains all ranges PlotRange totalRange = new PlotRange(rangeList[0].LowerBound, rangeList[rangelistlen - 1].UpperBound); _connectionStyle.FillOneRange(gp, pdata, totalRange, layer, fillDirection, _ignoreMissingDataPoints, _connectCircular, plotPositions, _cachedLogicalShiftX, _cachedLogicalShiftY); } else // we not ignore missing points, so plot all ranges separately { for (int i = 0; i < rangelistlen; i++) { _connectionStyle.FillOneRange(gp, pdata, rangeList[i], layer, fillDirection, _ignoreMissingDataPoints, _connectCircular, plotPositions, _cachedLogicalShiftX, _cachedLogicalShiftY); } } }
public void PrepareGroupStyles(PlotGroupStyleCollection externalGroups, PlotGroupStyleCollection localGroups, IPlotArea layer, Processed2DPlotData pdata) { if(this.IsColorProvider) ColorGroupStyle.PrepareStyle(externalGroups, localGroups, delegate() { return PlotColors.Colors.GetPlotColor(this.Color); }); SymbolShapeStyleGroupStyle.PrepareStyle(externalGroups, localGroups, delegate { return this.ShapeAndStyle; }); if(this.IsSymbolSizeProvider) SymbolSizeGroupStyle.PrepareStyle(externalGroups, localGroups, delegate() { return SymbolSize; }); // SkipFrequency should be the same for all sub plot styles, so there is no "private" property SkipFrequencyGroupStyle.PrepareStyle(externalGroups, localGroups, delegate() { return SkipFrequency; }); }
/// <summary> /// This will create a point list out of the data, which can be used to plot the data. In order to create this list, /// the function must have knowledge how to calculate the points out of the data. This will be done /// by a function provided by the calling function. /// </summary> /// <param name="layer">The plot layer.</param> /// <returns>An array of plot points in layer coordinates.</returns> public Processed2DPlotData GetRangesAndPoints( Gdi.IPlotArea layer) { const int functionPoints = 1000; const double MaxRelativeValue = 1E6; // allocate an array PointF to hold the line points PointF[] ptArray = new PointF[functionPoints]; Processed2DPlotData result = new Processed2DPlotData(); MyPlotData pdata = new MyPlotData(); result.PlotPointsInAbsoluteLayerCoordinates = ptArray; double[] xPhysArray = new double[functionPoints]; double[] yPhysArray = new double[functionPoints]; pdata._xPhysical = xPhysArray; pdata._yPhysical = yPhysArray; result.XPhysicalAccessor = new IndexedPhysicalValueAccessor(pdata.GetXPhysical); result.YPhysicalAccessor = new IndexedPhysicalValueAccessor(pdata.GetYPhysical); // double xorg = layer.XAxis.Org; // double xend = layer.XAxis.End; // Fill the array with values // only the points where x and y are not NaNs are plotted! int i, j; bool bInPlotSpace = true; int rangeStart = 0; PlotRangeList rangeList = new PlotRangeList(); result.RangeList = rangeList; Gdi.G2DCoordinateSystem coordsys = layer.CoordinateSystem; NumericalScale xaxis = layer.XAxis as NumericalScale; NumericalScale yaxis = layer.YAxis as NumericalScale; if (xaxis == null || yaxis == null) return null; for (i = 0, j = 0; i < functionPoints; i++) { double x_rel = ((double)i) / (functionPoints - 1); double x = xaxis.NormalToPhysical(x_rel); double y = Evaluate(x); if (Double.IsNaN(x) || Double.IsNaN(y)) { if (!bInPlotSpace) { bInPlotSpace = true; rangeList.Add(new PlotRange(rangeStart, j)); } continue; } // double x_rel = layer.XAxis.PhysicalToNormal(x); double y_rel = yaxis.PhysicalToNormal(y); // chop relative values to an range of about -+ 10^6 if (y_rel > MaxRelativeValue) y_rel = MaxRelativeValue; if (y_rel < -MaxRelativeValue) y_rel = -MaxRelativeValue; // after the conversion to relative coordinates it is possible // that with the choosen axis the point is undefined // (for instance negative values on a logarithmic axis) // in this case the returned value is NaN double xcoord, ycoord; if (coordsys.LogicalToLayerCoordinates(new Logical3D(x_rel, y_rel), out xcoord, out ycoord)) { if (bInPlotSpace) { bInPlotSpace = false; rangeStart = j; } xPhysArray[j] = x; yPhysArray[j] = y; ptArray[j].X = (float)xcoord; ptArray[j].Y = (float)ycoord; j++; } else { if (!bInPlotSpace) { bInPlotSpace = true; rangeList.Add(new PlotRange(rangeStart, j)); } } } // end for if (!bInPlotSpace) { bInPlotSpace = true; rangeList.Add(new PlotRange(rangeStart, j)); // add the last range } return result; }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { if (this._connectionStyle is LineConnectionStyles.NoConnection) return; PointF[] plotPositions = pdata.PlotPointsInAbsoluteLayerCoordinates; if(_independentOnShiftingGroupStyles) { _cachedLogicalShiftX = _cachedLogicalShiftY = 0; } if (0 != _cachedLogicalShiftX || 0 != _cachedLogicalShiftY) { plotPositions = Processed2DPlotData.GetPlotPointsInAbsoluteLayerCoordinatesWithShift(pdata, layer, _cachedLogicalShiftX, _cachedLogicalShiftY); } // ensure that brush and pen are cached if (null != _framePen) _framePen.Cached = true; if (null != _fillBrush) _fillBrush.SetEnvironment(new RectangleD2D(PointD2D.Empty, layer.Size), BrushX.GetEffectiveMaximumResolution(g, 1)); _fillDirection = layer.UpdateCSPlaneID(_fillDirection); var gp = new GraphicsPath(); PlotRangeList rangeList = pdata.RangeList; if (this._ignoreMissingDataPoints) { // in case we ignore the missing points, all ranges can be plotted // as one range, i.e. continuously // for this, we create the totalRange, which contains all ranges IPlotRange totalRange = new PlotRangeCompound(rangeList); _connectionStyle.FillOneRange(gp, pdata, totalRange, layer, _fillDirection, _ignoreMissingDataPoints, _connectCircular, plotPositions, _cachedLogicalShiftX, _cachedLogicalShiftY); } else // we not ignore missing points, so plot all ranges separately { for (int i = 0; i < rangeList.Count; i++) { _connectionStyle.FillOneRange(gp, pdata, rangeList[i], layer, _fillDirection, _ignoreMissingDataPoints, _connectCircular, plotPositions, _cachedLogicalShiftX, _cachedLogicalShiftY); } } g.FillPath(_fillBrush, gp); g.DrawPath(_framePen, gp); }
/// <summary> /// Needed for coordinate transforming styles to plot the data. /// </summary> /// <param name="g">Graphics context.</param> /// <param name="layer">The plot layer.</param> /// <param name="plotdata">The plot data. Since the data are transformed, you should not rely that the physical values in this item correspond to the area coordinates.</param> /// <param name="prevPlotData">Plot data of the previous plot item.</param> /// <param name="nextPlotData">Plot data of the next plot item.</param> public virtual void Paint(Graphics g, IPlotArea layer, Processed2DPlotData plotdata, Processed2DPlotData prevPlotData, Processed2DPlotData nextPlotData) { _cachedPlotDataUsedForPainting = plotdata; if (null != this._plotStyles) { _plotStyles.Paint(g, layer, plotdata, prevPlotData, nextPlotData); } }
public void StraightConnection_PaintOneRange( Graphics g, Processed2DPlotData pdata, PlotRange range, IPlotArea layer, Processed2DPlotData previousData) { PointF[] linePoints = pdata.PlotPointsInAbsoluteLayerCoordinates; PointF[] linepts = new PointF[range.Length]; Array.Copy(linePoints, range.LowerBound, linepts, 0, range.Length); // Extract int lastIdx = range.Length - 1; // Try to find points with a similar x value on otherlinepoints double firstLogicalX = layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(range.OriginalFirstPoint)); double lastLogicalX = layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(range.OriginalLastPoint)); double minDistanceToFirst = double.MaxValue; double minDistanceToLast = double.MaxValue; int minIdxFirst = -1; int minIdxLast = -1; foreach (var rangeP in previousData.RangeList) { for (int i = rangeP.LowerBound; i < rangeP.UpperBound; ++i) { double logicalX = layer.XAxis.PhysicalVariantToNormal(previousData.GetXPhysical(i + rangeP.OffsetToOriginal)); if (Math.Abs(logicalX - firstLogicalX) < minDistanceToFirst) { minDistanceToFirst = Math.Abs(logicalX - firstLogicalX); minIdxFirst = i; } if (Math.Abs(logicalX - lastLogicalX) < minDistanceToLast) { minDistanceToLast = Math.Abs(logicalX - lastLogicalX); minIdxLast = i; } } } // if nothing found, use the outmost boundaries of the plot points of the other data item if (minIdxFirst < 0) minIdxFirst = 0; if (minIdxLast < 0) minIdxLast = previousData.PlotPointsInAbsoluteLayerCoordinates.Length - 1; PointF[] otherLinePoints = new PointF[minIdxLast + 1 - minIdxFirst]; Array.Copy(previousData.PlotPointsInAbsoluteLayerCoordinates, minIdxFirst, otherLinePoints, 0, otherLinePoints.Length); Array.Reverse(otherLinePoints); // now paint this GraphicsPath gp = new GraphicsPath(); var layerSize = layer.Size; gp.StartFigure(); gp.AddLines(linepts); gp.AddLines(otherLinePoints); gp.CloseFigure(); if (_fillBrush.IsVisible) { g.FillPath(this._fillBrush, gp); } if (null != _framePen) g.DrawPath(_framePen, gp); gp.Reset(); } // end function PaintOneRange
private void PaintOneRange(Graphics g, IPlotArea layer, IPlotRange range, Processed2DPlotData pdata) { // adjust the skip frequency if it was not set appropriate if (_skipFrequency <= 0) _skipFrequency = 1; var dropTargets = new List<CSPlaneID>(_dropTargets.Select(id => layer.UpdateCSPlaneID(id))); if (_additionalDropTargetIsEnabled) { CSPlaneID userPlane; if (_additionalDropTargetUsePhysicalBaseValue) { userPlane = new CSPlaneID(_additionalDropTargetPerpendicularAxis, layer.Scales[_additionalDropTargetPerpendicularAxis].PhysicalVariantToNormal(_additionalDropTargetBaseValue)); } else { userPlane = new CSPlaneID(_additionalDropTargetPerpendicularAxis, _additionalDropTargetBaseValue); } dropTargets.Add(userPlane); } // paint the scatter style PointD3D pos = PointD3D.Empty; var gpath = new GraphicsPath(); if (null == _cachedSymbolSizeForIndexFunction && null == _cachedColorForIndexFunction) // using a constant symbol size and constant color { // update pen widths var pen = _pen.Clone(); double w1 = _lineWidth1Offset + _lineWidth1Factor * _cachedSymbolSize; pen.Width = w1; var gapStart = 0.5 * (_gapAtStartOffset + _gapAtStartFactor * _cachedSymbolSize); var gapEnd = 0.5 * (_gapAtEndOffset + _gapAtEndFactor * _cachedSymbolSize); int lower = range.LowerBound; int upper = range.UpperBound; for (int j = lower; j < upper; j += _skipFrequency) { var originalRowIndex = range.GetOriginalRowIndexFromPlotPointIndex(j); Logical3D r3d = layer.GetLogical3D(pdata, originalRowIndex); r3d.RX += _cachedLogicalShiftX; r3d.RY += _cachedLogicalShiftY; foreach (CSPlaneID id in dropTargets) { gpath.Reset(); layer.CoordinateSystem.GetIsolineFromPointToPlane(gpath, r3d, id); PointF[] shortenedPathPoints = null; if (gapStart != 0 || gapEnd != 0) { gpath.Flatten(); var pathPoints = gpath.PathPoints; shortenedPathPoints = GdiExtensionMethods.ShortenedBy(pathPoints, RADouble.NewAbs(gapStart), RADouble.NewAbs(gapEnd)); if (null != shortenedPathPoints) g.DrawLines(pen, shortenedPathPoints); } else { g.DrawPath(pen, gpath); } } } } else // using a variable symbol size or variable symbol color { int lower = range.LowerBound; int upper = range.UpperBound; for (int j = lower; j < upper; j += _skipFrequency) { var originalRowIndex = range.GetOriginalRowIndexFromPlotPointIndex(j); var pen = _pen.Clone(); if (null == _cachedColorForIndexFunction) { _cachedSymbolSize = _cachedSymbolSizeForIndexFunction(originalRowIndex); double w1 = _lineWidth1Offset + _lineWidth1Factor * _cachedSymbolSize; pen.Width = w1; } else { _cachedSymbolSize = null == _cachedSymbolSizeForIndexFunction ? _cachedSymbolSize : _cachedSymbolSizeForIndexFunction(originalRowIndex); double w1 = _lineWidth1Offset + _lineWidth1Factor * _cachedSymbolSize; var customSymbolColor = _cachedColorForIndexFunction(originalRowIndex); pen.Width = w1; pen.Color = NamedColor.FromArgb(customSymbolColor.A, customSymbolColor.R, customSymbolColor.G, customSymbolColor.B); } var gapStart = 0.5 * (_gapAtStartOffset + _gapAtStartFactor * _cachedSymbolSize); var gapEnd = 0.5 * (_gapAtEndOffset + _gapAtEndFactor * _cachedSymbolSize); Logical3D r3d = layer.GetLogical3D(pdata, originalRowIndex); r3d.RX += _cachedLogicalShiftX; r3d.RY += _cachedLogicalShiftY; foreach (CSPlaneID id in _dropTargets) { gpath.Reset(); layer.CoordinateSystem.GetIsolineFromPointToPlane(gpath, r3d, id); PointF[] shortenedPathPoints = null; if (gapStart != 0 || gapEnd != 0) { gpath.Flatten(); var pathPoints = gpath.PathPoints; shortenedPathPoints = GdiExtensionMethods.ShortenedBy(pathPoints, RADouble.NewAbs(gapStart), RADouble.NewAbs(gapEnd)); if (null != shortenedPathPoints) g.DrawLines(pen, shortenedPathPoints); } else { g.DrawPath(pen, gpath); } } } } }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { // adjust the skip frequency if it was not set appropriate if (_skipFrequency <= 0) _skipFrequency = 1; if (_independentOnShiftingGroupStyles) { _cachedLogicalShiftX = _cachedLogicalShiftY = 0; } PlotRangeList rangeList = pdata.RangeList; if (this._ignoreMissingDataPoints) { // in case we ignore the missing points, all ranges can be plotted // as one range, i.e. continuously // for this, we create the totalRange, which contains all ranges var totalRange = new PlotRangeCompound(rangeList); this.PaintOneRange(g, layer, totalRange, pdata); } else // we not ignore missing points, so plot all ranges separately { for (int i = 0; i < rangeList.Count; i++) { this.PaintOneRange(g, layer, rangeList[i], pdata); } } }
public void PrepareGroupStyles(PlotGroupStyleCollection externalGroups, PlotGroupStyleCollection localGroups, IPlotArea layer, Processed2DPlotData pdata) { if (this._fillColorLinkage == ColorLinkage.Dependent && this._fillBrush != null) ColorGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return this._fillBrush.Color; }); else if (this._frameColorLinkage == ColorLinkage.Dependent && this._framePen != null) ColorGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return this._framePen.Color; }); IgnoreMissingDataPointsGroupStyle.PrepareStyle(externalGroups, localGroups, () => _ignoreMissingDataPoints); LineConnection2DGroupStyle.PrepareStyle(externalGroups, localGroups, () => new Tuple<ILineConnectionStyle, bool>(_connectionStyle, _connectCircular)); }
protected void PaintOneRange(Graphics g, IPlotArea layer, IPlotRange range, Processed2DPlotData pdata) { const double logicalClampMinimum = -10; const double logicalClampMaximum = 11; // Plot error bars for the dependent variable (y) var columnX = ColumnX; var columnY = ColumnY; if (columnX == null || columnY == null) return; // nothing to do if both error columns are null if (!typeof(double).IsAssignableFrom(columnX.ItemType) || !typeof(double).IsAssignableFrom(columnY.ItemType)) return; // TODO make this an runtime paint error to be reported var strokePen = _strokePen.Clone(); using (GraphicsPath isoLine = new GraphicsPath()) { int lower = range.LowerBound; int upper = range.UpperBound; for (int j = lower; j < upper; j += _skipFrequency) { int originalRowIndex = range.GetOriginalRowIndexFromPlotPointIndex(j); double symbolSize = null == _cachedSymbolSizeForIndexFunction ? _symbolSize : _cachedSymbolSizeForIndexFunction(originalRowIndex); strokePen.Width = (_lineWidth1Offset + _lineWidth1Factor * symbolSize); if (null != _cachedColorForIndexFunction) strokePen.Color = GdiColorHelper.ToNamedColor(_cachedColorForIndexFunction(originalRowIndex), "VariableColor"); if (!(strokePen.EndCap is LineCaps.FlatCap)) strokePen.EndCap = strokePen.EndCap.WithMinimumAbsoluteAndRelativeSize(symbolSize * _endCapSizeFactor + _endCapSizeOffset, 1 + 1E-6); // Calculate target AltaxoVariant targetX, targetY; switch (_meaningOfValues) { case ValueInterpretation.AbsoluteDifference: { targetX = pdata.GetXPhysical(originalRowIndex) + columnX[originalRowIndex]; targetY = pdata.GetYPhysical(originalRowIndex) + columnY[originalRowIndex]; } break; case ValueInterpretation.AbsoluteValue: { targetX = columnX[originalRowIndex]; targetY = columnY[originalRowIndex]; } break; default: throw new NotImplementedException(nameof(_meaningOfValues)); } var logicalTarget = layer.GetLogical3D(targetX, targetY); var logicalOrigin = layer.GetLogical3D(pdata, originalRowIndex); if (!_independentOnShiftingGroupStyles && (0 != _cachedLogicalShiftX || 0 != _cachedLogicalShiftY)) { logicalOrigin.RX += _cachedLogicalShiftX; logicalOrigin.RY += _cachedLogicalShiftY; logicalTarget.RX += _cachedLogicalShiftX; logicalTarget.RY += _cachedLogicalShiftY; } if (!Calc.RMath.IsInIntervalCC(logicalOrigin.RX, logicalClampMinimum, logicalClampMaximum)) continue; if (!Calc.RMath.IsInIntervalCC(logicalOrigin.RY, logicalClampMinimum, logicalClampMaximum)) continue; if (!Calc.RMath.IsInIntervalCC(logicalOrigin.RZ, logicalClampMinimum, logicalClampMaximum)) continue; if (!Calc.RMath.IsInIntervalCC(logicalTarget.RX, logicalClampMinimum, logicalClampMaximum)) continue; if (!Calc.RMath.IsInIntervalCC(logicalTarget.RY, logicalClampMinimum, logicalClampMaximum)) continue; if (!Calc.RMath.IsInIntervalCC(logicalTarget.RZ, logicalClampMinimum, logicalClampMaximum)) continue; isoLine.Reset(); layer.CoordinateSystem.GetIsoline(isoLine, logicalOrigin, logicalTarget); if (null == isoLine) continue; PointF[] isoLinePathPoints = null; if (_useManualVectorLength) { isoLine.Flatten(); isoLinePathPoints = isoLine.PathPoints; double length = _vectorLengthOffset + _vectorLengthFactor * symbolSize; double isoLineLength = isoLinePathPoints.TotalLineLength(); isoLinePathPoints = isoLinePathPoints.ShortenedBy(RADouble.NewAbs(0), RADouble.NewAbs(isoLineLength - length)); if (null == isoLine) continue; } if (_useSymbolGap) { if (null == isoLinePathPoints) { isoLine.Flatten(); isoLinePathPoints = isoLine.PathPoints; } double gap = _symbolGapOffset + _symbolGapFactor * symbolSize; if (gap != 0) { isoLinePathPoints = isoLinePathPoints.ShortenedBy(RADouble.NewAbs(gap / 2), RADouble.NewAbs(0)); if (null == isoLine) continue; } } if (null != isoLinePathPoints) g.DrawLines(_strokePen, isoLinePathPoints); else g.DrawPath(strokePen, isoLine); } } }
public void PrepareGroupStyles(PlotGroupStyleCollection externalGroups, PlotGroupStyleCollection localGroups, IPlotArea layer, Processed2DPlotData pdata) { if (this.IsColorProvider) ColorGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return this.Color; }); ScatterSymbolGroupStyle.PrepareStyle(externalGroups, localGroups, delegate { return this._scatterSymbol; }); if (this.IsSymbolSizeProvider) SymbolSizeGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return SymbolSize; }); // SkipFrequency should be the same for all sub plot styles, so there is no "private" property SkipFrequencyGroupStyle.PrepareStyle(externalGroups, localGroups, delegate () { return SkipFrequency; }); // IgnoreMissingDataPoints should be the same for all sub plot styles, so there is no "private" property IgnoreMissingDataPointsGroupStyle.PrepareStyle(externalGroups, localGroups, () => _ignoreMissingDataPoints); }
public void PrepareGroupStyles(PlotGroupStyleCollection externalGroups, PlotGroupStyleCollection localGroups, IPlotArea layer, Processed2DPlotData pdata) { if (this.IsColorProvider) ColorGroupStyle.PrepareStyle(externalGroups, localGroups, delegate() { return PlotColors.Colors.GetPlotColor(this.Color); }); }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { // adjust the skip frequency if it was not set appropriate if (_skipFreq <= 0) _skipFreq = 1; if (this._scatterSymbol is NoSymbol) return; CachedPathData cachedPathData = new CachedPathData(); CachedBrushData cachedBrushData = new CachedBrushData(); PlotRangeList rangeList = pdata.RangeList; PointF[] plotPositions = pdata.PlotPointsInAbsoluteLayerCoordinates; if (!_independentOnShiftingGroupStyles && (0 != _cachedLogicalShiftX || 0 != _cachedLogicalShiftY)) { plotPositions = Processed2DPlotData.GetPlotPointsInAbsoluteLayerCoordinatesWithShift(pdata, layer, _cachedLogicalShiftX, _cachedLogicalShiftY); } // Calculate current scatterSymbol overridden with frame and inset var scatterSymbol = CalculateOverriddenScatterSymbol(); if (this._ignoreMissingDataPoints) { // in case we ignore the missing points, all ranges can be plotted // as one range, i.e. continuously // for this, we create the totalRange, which contains all ranges var totalRange = new PlotRangeCompound(rangeList); this.PaintOneRange(g, layer, plotPositions, totalRange, scatterSymbol, ref cachedPathData, ref cachedBrushData); } else // we not ignore missing points, so plot all ranges separately { for (int i = 0; i < rangeList.Count; i++) { this.PaintOneRange(g, layer, plotPositions, rangeList[i], scatterSymbol, ref cachedPathData, ref cachedBrushData); } } cachedBrushData.Clear(); cachedPathData.Clear(); }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata) { if (this._labelColumn.Document == null) return; if (null != _attachedPlane) layer.UpdateCSPlaneID(_attachedPlane); PlotRangeList rangeList = pdata.RangeList; PointF[] ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; Altaxo.Data.IReadableColumn labelColumn = this._labelColumn.Document; // save the graphics stat since we have to translate the origin System.Drawing.Drawing2D.GraphicsState gs = g.Save(); /* double bottomPosition = 0; double topPosition = 0; double leftPosition = 0; double rightPosition = 0; layer.CoordinateSystem.LogicalToLayerCoordinates(0, 0, out leftPosition, out bottomPosition); layer.CoordinateSystem.LogicalToLayerCoordinates(1, 1, out rightPosition, out topPosition); */ double xpos = 0, ypos = 0; double xpre, ypre; double xdiff, ydiff; for (int r = 0; r < rangeList.Count; r++) { int lower = rangeList[r].LowerBound; int upper = rangeList[r].UpperBound; int offset = rangeList[r].OffsetToOriginal; for (int j = lower; j < upper; j++) { string label = labelColumn[j + offset].ToString(); if (label == null || label == string.Empty) continue; xpre = ptArray[j].X; ypre = ptArray[j].Y; if (null!=this._attachedPlane) { Logical3D r3d = layer.GetLogical3D(pdata, j + offset); PointF pp = layer.CoordinateSystem.GetPointOnPlane(this._attachedPlane,r3d); xpre = pp.X; ypre = pp.Y; } xdiff = xpre - xpos; ydiff = ypre - ypos; xpos = xpre; ypos = ypre; g.TranslateTransform((float)xdiff, (float)ydiff); if (this._rotation != 0) g.RotateTransform((float)-this._rotation); this.Paint(g, label); if (this._rotation != 0) g.RotateTransform((float)this._rotation); } // end for } g.Restore(gs); // Restore the graphics state }