/// <summary> /// For a given plot point of index oldplotindex, finds the index and coordinates of a plot point /// of index oldplotindex+increment. /// </summary> /// <param name="layer">The layer this plot belongs to.</param> /// <param name="oldplotindex">Old plot index.</param> /// <param name="increment">Increment to the plot index.</param> /// <returns>Information about the new plot point find at position (oldplotindex+increment). Returns null if no such point exists.</returns> public XYScatterPointInformation GetNextPlotPoint(IPlotArea layer, int oldplotindex, int increment) { Processed2DPlotData pdata; if (null != (pdata = _cachedPlotDataUsedForPainting)) { PlotRangeList rangeList = pdata.RangeList; PointF[] ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; if (ptArray.Length == 0) { return(null); } int minindex = oldplotindex + increment; minindex = Math.Max(minindex, 0); minindex = Math.Min(minindex, ptArray.Length - 1); // ok, minindex is the point we are looking for // so we have a look in the rangeList, what row it belongs to int rowindex = rangeList.GetRowIndexForPlotIndex(minindex); return(new XYScatterPointInformation(ptArray[minindex], rowindex, minindex)); } return(null); }
/// <summary> /// Returns the index of a scatter point that is closest to the location <c>hitpoint</c> /// </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>The information about the point that is nearest to the location, or null if it can not be determined.</returns> public XYZScatterPointInformation GetNearestPlotPoint(IPlotArea layer, HitTestPointData hitpoint) { Processed3DPlotData pdata; if (null != (pdata = _cachedPlotDataUsedForPainting)) { PlotRangeList rangeList = pdata.RangeList; var ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; double mindistance = double.MaxValue; int minindex = -1; var hitTransformation = hitpoint.HitTransformation; var lineStart = hitTransformation.Transform(ptArray[0]).PointD2DWithoutZ; for (int i = 1; i < ptArray.Length; i++) { var lineEnd = hitTransformation.Transform(ptArray[i]).PointD2DWithoutZ; double distance = Math2D.SquareDistanceLineToPoint(PointD2D.Empty, lineStart, lineEnd); if (distance < mindistance) { mindistance = distance; minindex = Math2D.Distance(lineStart, PointD2D.Empty) < Math2D.Distance(lineEnd, PointD2D.Empty) ? i - 1 : i; } lineStart = lineEnd; } // ok, minindex is the point we are looking for // so we have a look in the rangeList, what row it belongs to int rowindex = rangeList.GetRowIndexForPlotIndex(minindex); return(new XYZScatterPointInformation(ptArray[minindex], rowindex, minindex)); } return(null); }
public void Paint(Graphics g, IPlotArea layer, Altaxo.Graph.Gdi.Plot.Data.Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { if (_fillToPrevPlotItem && null != prevItemData) { PaintFillToPrevPlotItem(g, layer, pdata, prevItemData); } if (_fillToNextPlotItem && null != nextItemData) { // 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; if (rangelistlen > 0) { // 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 var totalRange = new PlotRange(rangeList[0].LowerBound, rangeList[rangelistlen - 1].UpperBound); _cachedPaintOneRange(g, pdata, totalRange, layer, nextItemData); } } }
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> /// Returns the index of a scatter point that is nearest to the location <c>hitpoint</c> /// </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>The information about the point that is nearest to the location, or null if it can not be determined.</returns> public XYScatterPointInformation GetNearestPlotPoint(IPlotArea layer, PointD2D hitpoint) { Processed2DPlotData pdata; if (null != (pdata = _cachedPlotDataUsedForPainting)) { PlotRangeList rangeList = pdata.RangeList; PointF[] ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; double mindistance = double.MaxValue; int minindex = -1; for (int i = 1; i < ptArray.Length; i++) { double distance = Math2D.SquareDistanceLineToPoint(hitpoint, ptArray[i - 1], ptArray[i]); if (distance < mindistance) { mindistance = distance; minindex = Math2D.Distance(ptArray[i - 1], hitpoint) < Math2D.Distance(ptArray[i], hitpoint) ? i - 1 : i; } } // ok, minindex is the point we are looking for // so we have a look in the rangeList, what row it belongs to int rowindex = rangeList.GetRowIndexForPlotIndex(minindex); return(new XYScatterPointInformation(ptArray[minindex], rowindex, minindex)); } return(null); }
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); } } }
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(IGraphicsContext3D g, IPlotArea layer, Processed3DPlotData pdata, Processed3DPlotData prevItemData, Processed3DPlotData nextItemData) { PlotRangeList rangeList = pdata.RangeList; var ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; // adjust the skip frequency if it was not set appropriate if (_skipFreq <= 0) { _skipFreq = 1; } // paint the scatter style if (!ScatterSymbols.NoSymbol.Instance.Equals(_symbolShape)) { PointD3D pos = PointD3D.Empty; if (null == _cachedSymbolSizeForIndexFunction && null == _cachedColorForIndexFunction) // using a constant symbol size { for (int r = 0; r < rangeList.Count; r++) { var range = rangeList[r]; int lower = range.LowerBound; int upper = range.UpperBound; for (int j = lower; j < upper; j += _skipFreq) { _symbolShape.Paint(g, _material, ptArray[j], _symbolSize); } // end for all points in range } // end for all ranges } else // using a variable symbol size or variable symbol color { 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 += _skipFreq) { if (null == _cachedColorForIndexFunction) { double customSymbolSize = _cachedSymbolSizeForIndexFunction(j + offset); _symbolShape.Paint(g, _material, ptArray[j], customSymbolSize); } else { double customSymbolSize = null == _cachedSymbolSizeForIndexFunction ? _symbolSize : _cachedSymbolSizeForIndexFunction(j + offset); var customSymbolColor = _cachedColorForIndexFunction(j + offset); _symbolShape.Paint(g, _material.WithColor(NamedColor.FromArgb(customSymbolColor.A, customSymbolColor.R, customSymbolColor.G, customSymbolColor.B)), ptArray[j], customSymbolSize); } } } } } }
/// <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); }
/// <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); }
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(); }
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 void Paint(System.Drawing.Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { if (null == pdata) { throw new ArgumentNullException(nameof(pdata)); } PlotRangeList rangeList = pdata.RangeList; System.Drawing.PointF[] ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; layer.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(0, 0), out var xleft, out var ybottom); layer.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(1, 1), out var xright, out var ytop); float xe = (float)xright; float ye = (float)ybottom; var path = new GraphicsPath(); double globalBaseValue; if (_usePhysicalBaseValue) { globalBaseValue = layer.YAxis.PhysicalVariantToNormal(_baseValue); if (double.IsNaN(globalBaseValue)) { globalBaseValue = 0; } } else { globalBaseValue = _baseValue.ToDouble(); } bool useVariableFillColor = null != _fillBrush && null != _cachedColorForIndexFunction && !_independentFillColor; bool useVariableFrameColor = null != _framePen && null != _cachedColorForIndexFunction && !_independentFrameColor; var fillBrush = _fillBrush == null ? null : useVariableFillColor?_fillBrush.Clone() : _fillBrush; var framePen = _framePen == null ? null : useVariableFrameColor?_framePen.Clone() : _framePen; int j = -1; foreach (int originalRowIndex in pdata.RangeList.OriginalRowIndices()) { j++; double xcn = _xOffsetLogical + layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(originalRowIndex)); double xln = xcn - 0.5 * _xSizeLogical; double xrn = xcn + 0.5 * _xSizeLogical; double ycn = layer.YAxis.PhysicalVariantToNormal(pdata.GetYPhysical(originalRowIndex)); double ynbase = globalBaseValue; if (_startAtPreviousItem && pdata.PreviousItemData != null) { double prevstart = layer.YAxis.PhysicalVariantToNormal(pdata.PreviousItemData.GetYPhysical(originalRowIndex)); if (!double.IsNaN(prevstart)) { ynbase = prevstart; ynbase += Math.Sign(ynbase - globalBaseValue) * _previousItemYGap; } } path.Reset(); layer.CoordinateSystem.GetIsoline(path, new Logical3D(xln, ynbase), new Logical3D(xln, ycn)); layer.CoordinateSystem.GetIsoline(path, new Logical3D(xln, ycn), new Logical3D(xrn, ycn)); layer.CoordinateSystem.GetIsoline(path, new Logical3D(xrn, ycn), new Logical3D(xrn, ynbase)); layer.CoordinateSystem.GetIsoline(path, new Logical3D(xrn, ynbase), new Logical3D(xln, ynbase)); path.CloseFigure(); if (null != fillBrush) { if (useVariableFillColor) { fillBrush.Color = GdiColorHelper.ToNamedColor(_cachedColorForIndexFunction(originalRowIndex), "VariableColor"); } fillBrush.SetEnvironment(path.GetBounds(), BrushX.GetEffectiveMaximumResolution(g, 1)); g.FillPath(fillBrush, path); } if (null != framePen) { if (useVariableFrameColor) { framePen.Color = GdiColorHelper.ToNamedColor(_cachedColorForIndexFunction(originalRowIndex), "VariableColor"); } framePen.SetEnvironment(path.GetBounds(), BrushX.GetEffectiveMaximumResolution(g, 1)); g.DrawPath(framePen, path); } } }
/// <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 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 }
public void Paint(IGraphicsContext3D g, IPlotArea layer, Processed3DPlotData pdata, Processed3DPlotData prevItemData, Processed3DPlotData nextItemData) { if (null == pdata) { throw new ArgumentNullException(nameof(pdata)); } PlotRangeList rangeList = pdata.RangeList; var ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; layer.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(0, 0, 0), out var leftFrontBotton); layer.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(1, 1, 1), out var rightBackTop); double globalBaseValue; if (_usePhysicalBaseValue) { globalBaseValue = layer.ZAxis.PhysicalVariantToNormal(_baseValue); if (double.IsNaN(globalBaseValue)) { globalBaseValue = 0; } } else { globalBaseValue = _baseValue.ToDouble(); } bool useVariableColor = null != _cachedColorForIndexFunction && !_independentColor; var pen = _pen; int j = -1; foreach (int originalRowIndex in pdata.RangeList.OriginalRowIndices()) { j++; double xCenterLogical = layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(originalRowIndex)); double xLowerLogical = xCenterLogical + _xOffsetLogical; double xUpperLogical = xLowerLogical + _xSizeLogical; double yCenterLogical = layer.YAxis.PhysicalVariantToNormal(pdata.GetYPhysical(originalRowIndex)); double yLowerLogical = yCenterLogical + _yOffsetLogical; double yUpperLogical = yLowerLogical + _ySizeLogical; double zCenterLogical = layer.ZAxis.PhysicalVariantToNormal(pdata.GetZPhysical(originalRowIndex)); double zBaseLogical = globalBaseValue; if (_startAtPreviousItem && pdata.PreviousItemData != null) { double prevstart = layer.ZAxis.PhysicalVariantToNormal(pdata.PreviousItemData.GetZPhysical(originalRowIndex)); if (!double.IsNaN(prevstart)) { zBaseLogical = prevstart; zBaseLogical += Math.Sign(zBaseLogical - globalBaseValue) * _previousItemZGap; } } layer.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(xLowerLogical, yCenterLogical, zBaseLogical), out var lcp); layer.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(xUpperLogical, yCenterLogical, zBaseLogical), out var ucp); layer.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(xCenterLogical, yLowerLogical, zBaseLogical), out var clp); layer.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(xCenterLogical, yUpperLogical, zBaseLogical), out var cup); double penWidth1 = (lcp - ucp).Length; double penWidth2 = (clp - cup).Length; if (_useUniformCrossSectionThickness) { pen = pen.WithUniformThickness(Math.Min(penWidth1, penWidth2)); } else { pen = pen.WithThickness1(penWidth1); pen = pen.WithThickness2(penWidth2); } if (useVariableColor) { pen = pen.WithColor(GdiColorHelper.ToNamedColor(_cachedColorForIndexFunction(originalRowIndex), "VariableColor")); } var isoLine = layer.CoordinateSystem.GetIsoline(new Logical3D(xLowerLogical, yLowerLogical, zBaseLogical), new Logical3D(xLowerLogical, yLowerLogical, zCenterLogical)); g.DrawLine(pen, isoLine); } }
/// <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; }
/// <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; }
public void Paint(System.Drawing.Graphics g, IPlotArea layer, Processed2DPlotData pdata) { PlotRangeList rangeList = pdata.RangeList; System.Drawing.PointF[] ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; // paint the drop style double xleft, xright, ytop, ybottom; layer.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(0, 0), out xleft, out ybottom); layer.CoordinateSystem.LogicalToLayerCoordinates(new Logical3D(1, 1), out xright, out ytop); float xe = (float)xright; float ye = (float)ybottom; GraphicsPath path = new GraphicsPath(); double globalBaseValue; if (_usePhysicalBaseValue) { globalBaseValue = layer.YAxis.PhysicalVariantToNormal(_baseValue); if (double.IsNaN(globalBaseValue)) { globalBaseValue = 0; } } else { globalBaseValue = _baseValue.ToDouble(); } int j = -1; foreach (int originalRowIndex in pdata.RangeList.OriginalRowIndices()) { j++; double xcn = layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(originalRowIndex)); double xln = xcn + _position; double xrn = xln + _width; double ycn = layer.YAxis.PhysicalVariantToNormal(pdata.GetYPhysical(originalRowIndex)); double ynbase = globalBaseValue; if (_startAtPreviousItem && pdata.PreviousItemData != null) { double prevstart = layer.YAxis.PhysicalVariantToNormal(pdata.PreviousItemData.GetYPhysical(originalRowIndex)); if (!double.IsNaN(prevstart)) { ynbase = prevstart; ynbase += Math.Sign(ynbase - globalBaseValue) * _previousItemYGap; } } path.Reset(); layer.CoordinateSystem.GetIsoline(path, new Logical3D(xln, ynbase), new Logical3D(xln, ycn)); layer.CoordinateSystem.GetIsoline(path, new Logical3D(xln, ycn), new Logical3D(xrn, ycn)); layer.CoordinateSystem.GetIsoline(path, new Logical3D(xrn, ycn), new Logical3D(xrn, ynbase)); layer.CoordinateSystem.GetIsoline(path, new Logical3D(xrn, ynbase), new Logical3D(xln, ynbase)); path.CloseFigure(); _fillBrush.Rectangle = path.GetBounds(); g.FillPath(_fillBrush, path); if (_framePen != null) { _framePen.BrushRectangle = path.GetBounds(); g.DrawPath(_framePen, path); } } }
public void Paint(IGraphicsContext3D g, IPlotArea layer, Processed3DPlotData pdata, Processed3DPlotData prevItemData, Processed3DPlotData nextItemData) { const double logicalClampMinimum = -10; const double logicalClampMaximum = 11; // Plot error bars for the dependent variable (y) PlotRangeList rangeList = pdata.RangeList; var ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; var columnX = ColumnX; var columnY = ColumnY; var columnZ = ColumnZ; if (columnX == null || columnY == null || columnZ == null) { return; // nothing to do if both error columns are null } if (!typeof(double).IsAssignableFrom(columnX.ItemType) || !typeof(double).IsAssignableFrom(columnY.ItemType) || !typeof(double).IsAssignableFrom(columnZ.ItemType)) { return; // TODO make this an runtime paint error to be reported } var strokePen = _strokePen; foreach (PlotRange r in rangeList) { int lower = r.LowerBound; int upper = r.UpperBound; int offset = r.OffsetToOriginal; for (int j = lower; j < upper; j += _skipFrequency) { int originalRow = j + offset; double symbolSize = null == _cachedSymbolSizeForIndexFunction ? _symbolSize : _cachedSymbolSizeForIndexFunction(originalRow); strokePen = strokePen.WithThickness1(_lineWidth1Offset + _lineWidth1Factor * symbolSize); strokePen = strokePen.WithThickness2(_lineWidth2Offset + _lineWidth2Factor * symbolSize); if (null != _cachedColorForIndexFunction) { strokePen = strokePen.WithColor(GdiColorHelper.ToNamedColor(_cachedColorForIndexFunction(originalRow), "VariableColor")); } if (null != strokePen.LineEndCap) { strokePen = strokePen.WithLineEndCap(strokePen.LineEndCap.WithMinimumAbsoluteAndRelativeSize(symbolSize * _endCapSizeFactor + _endCapSizeOffset, 1 + 1E-6)); } // Calculate target AltaxoVariant targetX, targetY, targetZ; switch (_meaningOfValues) { case ValueInterpretation.AbsoluteDifference: { targetX = pdata.GetXPhysical(originalRow) + columnX[originalRow]; targetY = pdata.GetYPhysical(originalRow) + columnY[originalRow]; targetZ = pdata.GetZPhysical(originalRow) + columnZ[originalRow]; } break; case ValueInterpretation.AbsoluteValue: { targetX = columnX[originalRow]; targetY = columnY[originalRow]; targetZ = columnZ[originalRow]; } break; default: throw new NotImplementedException(nameof(_meaningOfValues)); } var logicalTarget = layer.GetLogical3D(targetX, targetY, targetZ); var logicalOrigin = layer.GetLogical3D(pdata, originalRow); if (!_independentOnShiftingGroupStyles && (0 != _cachedLogicalShiftX || 0 != _cachedLogicalShiftY || 0 != _cachedLogicalShiftZ)) { logicalOrigin.RX += _cachedLogicalShiftX; logicalOrigin.RY += _cachedLogicalShiftY; logicalOrigin.RZ += _cachedLogicalShiftZ; logicalTarget.RX += _cachedLogicalShiftX; logicalTarget.RY += _cachedLogicalShiftY; logicalTarget.RZ += _cachedLogicalShiftZ; } 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; } var isoLine = layer.CoordinateSystem.GetIsoline(logicalOrigin, logicalTarget); if (null == isoLine) { continue; } if (_useManualVectorLength) { double length = _vectorLengthOffset + _vectorLengthFactor * symbolSize; double isoLineLength = isoLine.TotalLineLength; isoLine = isoLine.ShortenedBy(RADouble.NewAbs(0), RADouble.NewAbs(isoLineLength - length)); if (null == isoLine) { continue; } } if (_useSymbolGap) { double gap = _symbolGapOffset + _symbolGapFactor * symbolSize; if (gap != 0) { isoLine = isoLine.ShortenedBy(RADouble.NewAbs(gap / 2), RADouble.NewAbs(0)); if (null == isoLine) { continue; } } } g.DrawLine(strokePen, isoLine); } } }
protected void PaintXErrorBars(System.Drawing.Graphics g, IPlotArea layer, Altaxo.Graph.Gdi.Plot.Data.Processed2DPlotData pdata) { // Plot error bars for the independent variable (x) PlotRangeList rangeList = pdata.RangeList; PointF[] ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; INumericColumn posErrCol = _positiveErrorColumn.Document; INumericColumn negErrCol = _negativeErrorColumn.Document; if (posErrCol == null && negErrCol == null) { return; // nothing to do if both error columns are null } System.Drawing.Drawing2D.GraphicsPath errorBarPath = new System.Drawing.Drawing2D.GraphicsPath(); Region oldClippingRegion = g.Clip; Region newClip = (Region)oldClippingRegion.Clone(); foreach (PlotRange r in rangeList) { int lower = r.LowerBound; int upper = r.UpperBound; int offset = r.OffsetToOriginal; for (int j = lower; j < upper; j++) { AltaxoVariant x = pdata.GetXPhysical(j + offset); Logical3D lm = layer.GetLogical3D(pdata, j + offset); lm.RX += _cachedLogicalShiftOfIndependent; if (lm.IsNaN) { continue; } Logical3D lh = lm; Logical3D ll = lm; bool lhvalid = false; bool llvalid = false; if (posErrCol != null) { lh.RX = layer.XAxis.PhysicalVariantToNormal(x + Math.Abs(posErrCol[j + offset])); lhvalid = !lh.IsNaN; } if (negErrCol != null) { ll.RX = layer.XAxis.PhysicalVariantToNormal(x - Math.Abs(negErrCol[j + offset])); llvalid = !ll.IsNaN; } if (!(lhvalid || llvalid)) { continue; // nothing to do for this point if both pos and neg logical point are invalid. } // now paint the error bar if (_symbolGap) // if symbol gap, then clip the painting, exclude a rectangle of size symbolSize x symbolSize { double xlm, ylm; layer.CoordinateSystem.LogicalToLayerCoordinates(lm, out xlm, out ylm); newClip.Union(oldClippingRegion); newClip.Exclude(new RectangleF((float)(xlm - _symbolSize / 2), (float)(ylm - _symbolSize / 2), _symbolSize, _symbolSize)); g.Clip = newClip; } if (lhvalid && llvalid) { errorBarPath.Reset(); layer.CoordinateSystem.GetIsoline(errorBarPath, ll, lm); layer.CoordinateSystem.GetIsoline(errorBarPath, lm, lh); g.DrawPath(_strokePen, errorBarPath); } else if (llvalid) { layer.CoordinateSystem.DrawIsoline(g, _strokePen, ll, lm); } else if (lhvalid) { layer.CoordinateSystem.DrawIsoline(g, _strokePen, lm, lh); } // now the end bars if (_showEndBars) { if (lhvalid) { PointF outDir; layer.CoordinateSystem.GetNormalizedDirection(lm, lh, 1, new Logical3D(0, 1), out outDir); outDir.X *= _symbolSize / 2; outDir.Y *= _symbolSize / 2; double xlay, ylay; layer.CoordinateSystem.LogicalToLayerCoordinates(lh, out xlay, out ylay); // Draw a line from x,y to g.DrawLine(_strokePen, (float)(xlay - outDir.X), (float)(ylay - outDir.Y), (float)(xlay + outDir.X), (float)(ylay + outDir.Y)); } if (llvalid) { PointF outDir; layer.CoordinateSystem.GetNormalizedDirection(lm, ll, 1, new Logical3D(0, 1), out outDir); outDir.X *= _symbolSize / 2; outDir.Y *= _symbolSize / 2; double xlay, ylay; layer.CoordinateSystem.LogicalToLayerCoordinates(ll, out xlay, out ylay); // Draw a line from x,y to g.DrawLine(_strokePen, (float)(xlay - outDir.X), (float)(ylay - outDir.Y), (float)(xlay + outDir.X), (float)(ylay + outDir.Y)); } } } } g.Clip = oldClippingRegion; }
public void Paint(Graphics g, IPlotArea layer, Processed2DPlotData pdata, Processed2DPlotData prevItemData, Processed2DPlotData nextItemData) { if (_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 (_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(IGraphicsContext3D g, IPlotArea layer, Processed3DPlotData pdata, Processed3DPlotData prevItemData, Processed3DPlotData nextItemData) { PlotRangeList rangeList = pdata.RangeList; var ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; // adjust the skip frequency if it was not set appropriate if (_skipFreq <= 0) { _skipFreq = 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; if (null == _cachedSymbolSizeForIndexFunction && null == _cachedColorForIndexFunction) // using a constant symbol size and constant color { var pen = _pen; // update pen widths double w1 = _lineWidth1Offset + _lineWidth1Factor * _cachedSymbolSize; double w2 = _lineWidth2Offset + _lineWidth2Factor * _cachedSymbolSize; pen = pen.WithThickness1(w1).WithThickness2(w2); var gapStart = 0.5 * (_gapAtStartOffset + _gapAtStartFactor * _cachedSymbolSize); var gapEnd = 0.5 * (_gapAtEndOffset + _gapAtEndFactor * _cachedSymbolSize); for (int r = 0; r < rangeList.Count; r++) { var range = rangeList[r]; int lower = range.LowerBound; int upper = range.UpperBound; for (int j = lower; j < upper; j += _skipFreq) { Logical3D r3d = layer.GetLogical3D(pdata, j + range.OffsetToOriginal); foreach (CSPlaneID id in dropTargets) { layer.CoordinateSystem.GetIsolineFromPointToPlane(r3d, id, out var isoLine); if (gapStart != 0 || gapEnd != 0) { isoLine = isoLine.ShortenedBy(RADouble.NewAbs(gapStart), RADouble.NewAbs(gapEnd)); } if (null != isoLine) { g.DrawLine(pen, isoLine); } } } } // for each range } else // using a variable symbol size or variable symbol color { for (int r = 0; r < rangeList.Count; r++) { var range = rangeList[r]; int lower = range.LowerBound; int upper = range.UpperBound; int offset = range.OffsetToOriginal; for (int j = lower; j < upper; j += _skipFreq) { var pen = _pen; if (null == _cachedColorForIndexFunction) { _cachedSymbolSize = _cachedSymbolSizeForIndexFunction(j + offset); double w1 = _lineWidth1Offset + _lineWidth1Factor * _cachedSymbolSize; double w2 = _lineWidth2Offset + _lineWidth2Factor * _cachedSymbolSize; pen = _pen.WithThickness1(w1).WithThickness2(w2); } else { _cachedSymbolSize = null == _cachedSymbolSizeForIndexFunction ? _cachedSymbolSize : _cachedSymbolSizeForIndexFunction(j + offset); double w1 = _lineWidth1Offset + _lineWidth1Factor * _cachedSymbolSize; double w2 = _lineWidth2Offset + _lineWidth2Factor * _cachedSymbolSize; var customSymbolColor = _cachedColorForIndexFunction(j + offset); pen = _pen.WithThickness1(w1).WithThickness2(w2).WithColor(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, j + rangeList[r].OffsetToOriginal); foreach (CSPlaneID id in _dropTargets) { layer.CoordinateSystem.GetIsolineFromPointToPlane(r3d, id, out var isoLine); if (gapStart != 0 || gapEnd != 0) { isoLine = isoLine.ShortenedBy(RADouble.NewAbs(gapStart), RADouble.NewAbs(gapEnd)); } if (null != isoLine) { g.DrawLine(pen, isoLine); } } } } } }