/// <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> /// <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 virtual void FillOneRange( GraphicsPath gp, Processed2DPlotData pdata, IPlotRange range, IPlotArea layer, CSPlaneID fillDirection, PointF[] linePoints, bool connectCircular, PointF[] allLinePointsShiftedAlready, double logicalShiftX, double logicalShiftY ) { if (connectCircular) { gp.AddLines(linePoints); gp.CloseFigure(); } else { Logical3D r0 = layer.GetLogical3D(pdata, range.OriginalFirstPoint); r0.RX += logicalShiftX; r0.RY += logicalShiftY; layer.CoordinateSystem.GetIsolineFromPlaneToPoint(gp, fillDirection, r0); gp.AddLines(linePoints); Logical3D r1 = layer.GetLogical3D(pdata, range.OriginalLastPoint); r1.RX += logicalShiftX; r1.RY += logicalShiftY; layer.CoordinateSystem.GetIsolineFromPointToPlane(gp, r1, fillDirection); layer.CoordinateSystem.GetIsolineOnPlane(gp, fillDirection, r1, r0); gp.CloseFigure(); } }
public void PaintPreprocessing(System.Drawing.Graphics g, IPaintContext paintContext, IPlotArea layer, PlotItemCollection coll) { var paintData = new CachedPaintData { _clippingColl = new System.Drawing.Region[coll.Count], _plotDataColl = new Processed2DPlotData[coll.Count], _xincColl = new double[coll.Count], _yincColl = new double[coll.Count] }; paintContext.AddValue(this, paintData); // First prepare int idx = -1; Processed2DPlotData previousPlotData = null; for (int i = 0; i < coll.Count; i++) { if (coll[i] is G2DPlotItem) { idx++; double currxinc = paintData._xincColl[i] = idx * _xinc * _scaleXInc; double curryinc = paintData._yincColl[i] = idx * _yinc * _scaleYInc; G2DPlotItem gpi = coll[i] as G2DPlotItem; Processed2DPlotData plotdata = paintData._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 clipping is used, we must get a clipping region for every plot item // and combine the regions from if (_useClipping) { if (i == 0) paintData._clippingColl[i] = g.Clip; Plot.Styles.LinePlotStyle linestyle = null; foreach (Plot.Styles.IG2DPlotStyle st in gpi.Style) { if (st is Plot.Styles.LinePlotStyle) { linestyle = st as Plot.Styles.LinePlotStyle; break; } } if (null != linestyle) { GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath(); linestyle.GetFillPath(path, layer, plotdata, CSPlaneID.Bottom); if ((i + 1) < paintData._clippingColl.Length) { paintData._clippingColl[i + 1] = (Region)paintData._clippingColl[i].Clone(); paintData._clippingColl[i + 1].Exclude(path); } } else { if ((i + 1) < paintData._clippingColl.Length) paintData._clippingColl[i + 1] = paintData._clippingColl[i]; } } } } }
/// <summary> /// Calculates from two layer coordinate values (in points usually) the relative coordinates of the point (between 0 and 1). Returns true if the conversion /// is possible, otherwise false. /// </summary> /// <param name="xlocation">On return, gives the x coordinate of the converted value (for instance location).</param> /// <param name="ylocation">On return, gives the y coordinate of the converted value (for instance location).</param> /// <param name="r">The logical coordinate as the result of the conversion.</param> /// <returns>True if the conversion was successfull, false if the conversion was not possible.</returns> public override bool LayerToLogicalCoordinates(double xlocation, double ylocation, out Logical3D r) { r = new Logical3D(); double wx = xlocation - _midX; double wy = -ylocation + _midY; if (wx == 0 && wy == 0) { r.RX = 0; r.RY = 0; } else { r.RX = Math.Atan2(wy, wx) / (2 * Math.PI); r.RY = 2 * Math.Sqrt(wx * wx + wy * wy) / _radius; } if (_isXreverse) { r.RX = 1 - r.RX; } if (_isYreverse) { r.RY = 1 - r.RY; } if (_isXYInterchanged) { double hr = r.RX; r.RX = r.RY; r.RY = hr; } return(!double.IsNaN(r.RX) && !double.IsNaN(r.RY)); }
/// <summary> /// Paints the axis style labels. /// </summary> /// <param name="g">Graphics environment.</param> /// <param name="coordSyst">The coordinate system. Used to get the path along the axis.</param> /// <param name="scale">Scale.</param> /// <param name="tickSpacing">If not <c>null</c>, this parameter provides a custom tick spacing that is used instead of the default tick spacing of the scale.</param> /// <param name="styleInfo">Information about begin of axis, end of axis.</param> /// <param name="outerDistance">Distance between axis and labels.</param> /// <param name="useMinorTicks">If true, minor ticks are shown.</param> public virtual void Paint(Graphics g, G2DCoordinateSystem coordSyst, Scale scale, TickSpacing tickSpacing, CSAxisInformation styleInfo, double outerDistance, bool useMinorTicks) { _cachedAxisStyleInfo = styleInfo; CSLineID styleID = styleInfo.Identifier; Scale raxis = scale; TickSpacing ticking = tickSpacing; _enclosingPath.Reset(); _enclosingPath.FillMode = FillMode.Winding; // with Winding also overlapping rectangles are selected var helperPath = new GraphicsPath(); var math = new Matrix(); Logical3D r0 = styleID.GetLogicalPoint(styleInfo.LogicalValueAxisOrg); Logical3D r1 = styleID.GetLogicalPoint(styleInfo.LogicalValueAxisEnd); Logical3D outer; var dist_x = outerDistance; // Distance from axis tick point to label var dist_y = outerDistance; // y distance from axis tick point to label // dist_x += this._font.SizeInPoints/3; // add some space to the horizontal direction in order to separate the chars a little from the ticks // next statement is necessary to have a consistent string length both // on 0 degree rotated text and rotated text // without this statement, the text is fitted to the pixel grid, which // leads to "steps" during scaling g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; double[] relpositions; AltaxoVariant[] ticks; if (useMinorTicks) { relpositions = ticking.GetMinorTicksNormal(raxis); ticks = ticking.GetMinorTicksAsVariant(); } else { relpositions = ticking.GetMajorTicksNormal(raxis); ticks = ticking.GetMajorTicksAsVariant(); } if (!_suppressedLabels.IsEmpty) { var filteredTicks = new List <AltaxoVariant>(); var filteredRelPositions = new List <double>(); for (int i = 0; i < ticks.Length; i++) { if (_suppressedLabels.ByValues.Contains(ticks[i])) { continue; } if (_suppressedLabels.ByNumbers.Contains(i)) { continue; } if (_suppressedLabels.ByNumbers.Contains(i - ticks.Length)) { continue; } filteredTicks.Add(ticks[i]); filteredRelPositions.Add(relpositions[i]); } ticks = filteredTicks.ToArray(); relpositions = filteredRelPositions.ToArray(); } IMeasuredLabelItem[] labels = _labelFormatting.GetMeasuredItems(g, _font, _stringFormat, ticks); double emSize = _font.Size; CSAxisSide labelSide = null != _labelSide ? _labelSide.Value : styleInfo.PreferredLabelSide; for (int i = 0; i < ticks.Length; i++) { double r = relpositions[i]; if (!Altaxo.Calc.RMath.IsInIntervalCC(r, -1000, 1000)) { continue; } outer = coordSyst.GetLogicalDirection(styleID.ParallelAxisNumber, labelSide); PointD2D tickorg = coordSyst.GetNormalizedDirection(r0, r1, r, outer, out var outVector); PointD2D tickend = tickorg + outVector * outerDistance; PointD2D msize = labels[i].Size; PointD2D morg = tickend; if (_automaticRotationShift) { double alpha = _rotation * Math.PI / 180 - Math.Atan2(outVector.Y, outVector.X); double shift = msize.Y * 0.5 * Math.Abs(Math.Sin(alpha)) + (msize.X + _font.Size / 2) * 0.5 * Math.Abs(Math.Cos(alpha)); morg = morg + outVector * shift; } else { morg = morg.WithXPlus(outVector.X * _font.Size / 3); } var mrect = new RectangleD2D(morg, msize); if (_automaticRotationShift) { AdjustRectangle(ref mrect, StringAlignment.Center, StringAlignment.Center); } else { AdjustRectangle(ref mrect, _horizontalAlignment, _verticalAlignment); } math.Reset(); math.Translate((float)morg.X, (float)morg.Y); if (_rotation != 0) { math.Rotate((float)-_rotation); } math.Translate((float)(mrect.X - morg.X + emSize * _xOffset), (float)(mrect.Y - morg.Y + emSize * _yOffset)); System.Drawing.Drawing2D.GraphicsState gs = g.Save(); g.MultiplyTransform(math); if (_backgroundStyle != null) { _backgroundStyle.Draw(g, new RectangleD2D(PointD2D.Empty, msize)); } _brush.SetEnvironment(new RectangleD2D(PointD2D.Empty, msize), BrushX.GetEffectiveMaximumResolution(g, 1)); labels[i].Draw(g, _brush, new PointF(0, 0)); g.Restore(gs); // Restore the graphics state helperPath.Reset(); helperPath.AddRectangle(new RectangleF(PointF.Empty, (SizeF)msize)); helperPath.Transform(math); _enclosingPath.AddPath(helperPath, true); } }
/// <summary> /// Calculates from two logical values (values between 0 and 1) the coordinates of the point. Returns true if the conversion /// is possible, otherwise false. /// </summary> /// <param name="r">The logical point to convert.</param> /// <param name="xlocation">On return, gives the x coordinate of the converted value (for instance location).</param> /// <param name="ylocation">On return, gives the y coordinate of the converted value (for instance location).</param> /// <returns>True if the conversion was successfull, false if the conversion was not possible.</returns> public override bool LogicalToLayerCoordinates(Logical3D r, out double xlocation, out double ylocation) { if (_isXreverse) r.RX = 1 - r.RX; if (_isYreverse) r.RY = 1 - r.RY; if (_isXYInterchanged) { double hr = r.RX; r.RX = r.RY; r.RY = hr; } double phi = r.RX * 2 * Math.PI; double rad = _radius * r.RY; xlocation = _midX + rad * Math.Cos(phi); ylocation = _midY - rad * Math.Sin(phi); return !double.IsNaN(xlocation) && !double.IsNaN(ylocation); }
// CoordinateSystem is not affine, or scales are non-linear private void BuildImageV3(Graphics gfrx, IPlotArea gl, IReadOnlyList <double> lx, IReadOnlyList <double> ly, IROMatrix <double> vcolumns) { // allocate a bitmap of same dimensions than the underlying layer _imageType = CachedImageType.Other; int dimX = (int)Math.Ceiling(gl.Size.X / 72.0 * gfrx.DpiX); int dimY = (int)Math.Ceiling(gl.Size.Y / 72.0 * gfrx.DpiY); dimX = Math.Min(2048, dimX); dimY = Math.Min(2048, dimY); // look if the image has the right dimensions if (null == _cachedImage || _cachedImage.Width != dimX || _cachedImage.Height != dimY) { if (null != _cachedImage) { _cachedImage.Dispose(); } // please notice: the horizontal direction of the image is related to the row index!!! (this will turn the image in relation to the table) // and the vertical direction of the image is related to the column index _cachedImage = new System.Drawing.Bitmap(dimX, dimY, System.Drawing.Imaging.PixelFormat.Format32bppArgb); } byte[] imageBytes = new byte[dimX * dimY * 4]; double widthByDimX = gl.Size.X / dimX; double heightByDimY = gl.Size.Y / dimY; var rel = new Logical3D(); double minRX = lx[0]; double maxRX = lx[lx.Count - 1]; double minRY = ly[0]; double maxRY = ly[ly.Count - 1]; if (minRX > maxRX) { double h = minRX; minRX = maxRX; maxRX = h; } if (minRY > maxRY) { double h = minRY; minRY = maxRY; maxRY = h; } var interpol = new BivariateLinearSpline(lx, ly, vcolumns); Color colorInvalid = _colorProvider.GetColor(double.NaN); int addr = 0; for (int ny = 0; ny < dimY; ny++) { double py = (ny + 0.5) * heightByDimY; for (int nx = 0; nx < dimX; nx++, addr += 4) { double px = (nx + 0.5) * widthByDimX; if (false == gl.CoordinateSystem.LayerToLogicalCoordinates(px, py, out rel)) { _cachedImage.SetPixel(nx, ny, colorInvalid); } else // conversion to relative coordinates was possible { double rx = rel.RX; double ry = rel.RY; if (rx < minRX || rx > maxRX || ry < minRY || ry > maxRY) { //_cachedImage.SetPixel(nx, ny, _colorInvalid); imageBytes[addr + 0] = colorInvalid.B; imageBytes[addr + 1] = colorInvalid.G; imageBytes[addr + 2] = colorInvalid.R; imageBytes[addr + 3] = colorInvalid.A; } else { double val = interpol.Interpolate(rx, ry); if (double.IsNaN(val)) { //_cachedImage.SetPixel(nx, ny, _colorInvalid); imageBytes[addr + 0] = colorInvalid.B; imageBytes[addr + 1] = colorInvalid.G; imageBytes[addr + 2] = colorInvalid.R; imageBytes[addr + 3] = colorInvalid.A; } else { //_cachedImage.SetPixel(nx, ny, GetColor(val)); Color c = GetColor(val); imageBytes[addr + 0] = c.B; imageBytes[addr + 1] = c.G; imageBytes[addr + 2] = c.R; imageBytes[addr + 3] = c.A; } } } } } // Lock the bitmap's bits. var rect = new Rectangle(0, 0, _cachedImage.Width, _cachedImage.Height); System.Drawing.Imaging.BitmapData bmpData = _cachedImage.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, _cachedImage.PixelFormat); // Get the address of the first line. IntPtr ptr = bmpData.Scan0; // Copy the RGB values back to the bitmap System.Runtime.InteropServices.Marshal.Copy(imageBytes, 0, ptr, imageBytes.Length); _cachedImage.UnlockBits(bmpData); }
/// <summary> /// Calculates from two layer coordinate values (in points usually) the relative coordinates of the point (between 0 and 1). Returns true if the conversion /// is possible, otherwise false. /// </summary> /// <param name="xlocation">On return, gives the x coordinate of the converted value (for instance location).</param> /// <param name="ylocation">On return, gives the y coordinate of the converted value (for instance location).</param> /// <param name="r">The logical coordinates as the result of conversion.</param> /// <returns>True if the conversion was successfull, false if the conversion was not possible.</returns> public override bool LayerToLogicalCoordinates(double xlocation, double ylocation, out Logical3D r) { r = new Logical3D(xlocation / _layerWidth, 1 - ylocation / _layerHeight); if (_isXYInterchanged) { double hr = r.RX; r.RX = r.RY; r.RY = hr; } if (_isXreverse) { r.RX = 1 - r.RX; } if (_isYreverse) { r.RY = 1 - r.RY; } return(!double.IsNaN(r.RX) && !double.IsNaN(r.RY)); }
public override bool LogicalToLayerCoordinates(Logical3D r, out double xlocation, out double ylocation) { xlocation = _projectionMatrix.M11 * r.RX + _projectionMatrix.M12 * r.RY + _projectionMatrix.M13 * r.RZ; ylocation = _projectionMatrix.M21 * r.RX + _projectionMatrix.M22 * r.RY + _projectionMatrix.M23 * r.RZ; ylocation = _projectionMatrix.M22 - ylocation; return true; }
/// <summary> /// Draws an isoline on the plot area. /// </summary> /// <param name="g">Graphics context.</param> /// <param name="pen">The style of the pen used to draw the line.</param> /// <param name="r0">Starting point in logical coordinates.</param> /// <param name="r1">End point in logical coordinates.</param> public virtual void DrawIsoline(System.Drawing.Graphics g, System.Drawing.Pen pen, Logical3D r0, Logical3D r1) { using (GraphicsPath path = new GraphicsPath()) { GetIsoline(path, r0, r1); g.DrawPath(pen, path); } }
/// <summary> /// Gets a iso line in a path object. /// </summary> /// <param name="path">The graphics path.</param> /// <param name="r0">Starting position in logical coordinates.</param> /// <param name="r1">End position in logical coordinates.</param> public abstract void GetIsoline(System.Drawing.Drawing2D.GraphicsPath path, Logical3D r0, Logical3D r1);
/// <summary> /// Calculates from two coordinates of a point the logical values (values between 0 and 1). Returns true if the conversion /// is possible, otherwise false. /// </summary> /// <param name="xlocation">The x coordinate of the converted value (for instance location).</param> /// <param name="ylocation">The y coordinate of the converted value (for instance location).</param> /// <param name="r">The computed logical position value.</param> /// <returns>True if the conversion was successfull, false if the conversion was not possible. For 3D coordinate systems, /// the relative values of x and y with z=0 should be returned.</returns> public abstract bool LayerToLogicalCoordinates(double xlocation, double ylocation, out Logical3D r);
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(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); } } } } } }
public Logical3D GetLogical3D(AltaxoVariant x, AltaxoVariant y) { Logical3D shifted = new Logical3D( _xScale.PhysicalVariantToNormal(x), _yScale.PhysicalVariantToNormal(y)); return shifted; }
public Logical3D GetLogical3D(I3DPhysicalVariantAccessor acc, int idx) { Logical3D shifted = new Logical3D( _xScale.PhysicalVariantToNormal(acc.GetXPhysical(idx)), _yScale.PhysicalVariantToNormal(acc.GetYPhysical(idx))); return shifted; }
public override bool LogicalToLayerCoordinatesAndDirection( Logical3D r0, Logical3D r1, double t, out double ax, out double ay, out double adx, out double ady) { if (_isXreverse) { r0.RX = 1 - r0.RX; r1.RX = 1 - r1.RX; } if (_isYreverse) { r0.RY = 1 - r0.RY; r1.RY = 1 - r1.RY; } if (_isXYInterchanged) { double hr0 = r0.RX; r0.RX = r0.RY; r0.RY = hr0; double hr1 = r1.RX; r1.RX = r1.RY; r1.RY = hr1; } double rx = r0.RX + t * (r1.RX - r0.RX); double ry = r0.RY + t * (r1.RY - r0.RY); ax = _layerWidth * rx; ay = _layerHeight * (1 - ry); adx = _layerWidth * (r1.RX - r0.RX); ady = _layerHeight * (r0.RY - r1.RY); return !double.IsNaN(ax) && !double.IsNaN(ay); }
public override void GetIsoline(System.Drawing.Drawing2D.GraphicsPath g, Logical3D r0, Logical3D r1) { double ax0, ax1, ay0, ay1; if (LogicalToLayerCoordinates(r0, out ax0, out ay0) && LogicalToLayerCoordinates(r1, out ax1, out ay1)) { g.AddLine((float)ax0, (float)ay0, (float)ax1, (float)ay1); } }
/// <summary> /// Draws an isoline beginning from a given point to the axis. /// </summary> /// <param name="path">Graphics path to fill with the isoline.</param> /// <param name="r">Logical coordinate of the start point.</param> /// <param name="id">The logical plane to end the isoline.</param> public virtual void GetIsolineFromPointToPlane(GraphicsPath path, Logical3D r, CSPlaneID id) { if (id.PerpendicularAxisNumber == 0) { GetIsoline(path, r, new Logical3D(id.LogicalValue, r.RY, r.RZ)); } else if (id.PerpendicularAxisNumber == 1) { GetIsoline(path, r, new Logical3D(r.RX, id.LogicalValue, r.RZ)); } else { GetIsoline(path, r, new Logical3D(r.RX, r.RY, id.LogicalValue)); } }
public override bool LayerToLogicalCoordinates(double xlocation, double ylocation, out Logical3D r) { throw new Exception("The method or operation is not implemented."); }
/// <summary> /// Draws an isoline beginning from a given point to a plane. /// </summary> /// <param name="g">Graphics to draw the isoline to.</param> /// <param name="pen">The pen to use.</param> /// <param name="r">Logical coordinate of the start point.</param> /// <param name="id">The logical plane to end the isoline.</param> public virtual void DrawIsolineFromPointToPlane(Graphics g, System.Drawing.Pen pen, Logical3D r, CSPlaneID id) { if (id.PerpendicularAxisNumber == 0) { DrawIsoline(g, pen, r, new Logical3D(id.LogicalValue, r.RY, r.RZ)); } else if (id.PerpendicularAxisNumber == 1) { DrawIsoline(g, pen, r, new Logical3D(r.RX, id.LogicalValue, r.RZ)); } else { DrawIsoline(g, pen, r, new Logical3D(r.RX, r.RY, id.LogicalValue)); } }
public void Paint(System.Drawing.Graphics g, IPlotArea layer, PlotItemCollection coll) { Dictionary<G2DPlotItem, Processed2DPlotData> plotDataDict; if (!CanUseStyle(layer, coll, out plotDataDict)) { CoordinateTransformingStyleBase.Paint(g, layer, coll); return; } AltaxoVariant[] ysumArray = null; foreach (IGPlotItem pi in coll) { if (pi is G2DPlotItem) { G2DPlotItem 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) { G2DPlotItem gpi = pi as G2DPlotItem; Processed2DPlotData pdata = plotDataDict[gpi]; yArray = AbsoluteStackTransform.AddUp(yArray, pdata); AltaxoVariant[] 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; Logical3D rel = new Logical3D( layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(originalIndex)), layer.YAxis.PhysicalVariantToNormal(y)); double xabs, yabs; layer.CoordinateSystem.LogicalToLayerCoordinates(rel, out xabs, out 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; } } for (int i = coll.Count - 1; i >= 0; --i) { IGPlotItem pi = coll[i]; if (pi is G2DPlotItem) { G2DPlotItem gpi = pi as G2DPlotItem; Processed2DPlotData pdata = plotDataDict[gpi]; gpi.Paint(g, layer, pdata); } else { pi.Paint(g, layer); } } }
/// <summary> /// Draws an isoline on a plane beginning from r0 to r1. For r0,r1 either ry0,ry1 is used (if it is an x-axis), /// otherwise rx0,rx1 is used. The other parameter pair is not used. /// </summary> /// <param name="path">Graphics path to fill with the isoline.</param> /// <param name="r0">Logical coordinate of the start point.</param> /// <param name="r1">Logical coordinate of the end point.</param> /// <param name="id">The axis to end the isoline.</param> public virtual void GetIsolineOnPlane(GraphicsPath path, CSPlaneID id, Logical3D r0, Logical3D r1) { if (id.PerpendicularAxisNumber == 0) { GetIsoline(path, new Logical3D(id.LogicalValue, r0.RY, r0.RZ), new Logical3D(id.LogicalValue, r1.RY, r1.RZ)); } else if (id.PerpendicularAxisNumber == 1) { GetIsoline(path, new Logical3D(r0.RX, id.LogicalValue, r0.RZ), new Logical3D(r1.RX, id.LogicalValue, r1.RZ)); } else { GetIsoline(path, new Logical3D(r0.RX, r0.RY, id.LogicalValue), new Logical3D(r1.RX, r1.RY, id.LogicalValue)); } }
public void Paint(System.Drawing.Graphics g, IPlotArea layer, PlotItemCollection coll) { Dictionary<G2DPlotItem, Processed2DPlotData> plotDataDict; if (!CanUseStyle(layer, coll, out plotDataDict)) { CoordinateTransformingStyleBase.Paint(g, layer, coll); return; } 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++; G2DPlotItem gpi = pi as G2DPlotItem; Processed2DPlotData pdata = plotDataDict[gpi]; yArray = AddUp(yArray, pdata); if(idx>0) // this is not the first item { int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; Logical3D rel = new Logical3D( layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(originalIndex)), layer.YAxis.PhysicalVariantToNormal(yArray[j])); double xabs, yabs; layer.CoordinateSystem.LogicalToLayerCoordinates(rel, out xabs, out 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 AltaxoVariant[] localArray = (AltaxoVariant[])yArray.Clone(); pdata.YPhysicalAccessor = new IndexedPhysicalValueAccessor(delegate(int i) { return localArray[i]; }); pdata.PreviousItemData = previousItemData; previousItemData = pdata; } } for (int i = coll.Count - 1; i >= 0; --i) { IGPlotItem pi = coll[i]; if (pi is G2DPlotItem) { G2DPlotItem gpi = pi as G2DPlotItem; Processed2DPlotData pdata = plotDataDict[gpi]; gpi.Paint(g, layer, pdata); } else { pi.Paint(g, layer); } } }
public PointD2D GetPointOnPlane(CSPlaneID id, Logical3D r) { double x, y; if (id.PerpendicularAxisNumber == 0) LogicalToLayerCoordinates(new Logical3D(id.LogicalValue, r.RY, r.RZ), out x, out y); else if (id.PerpendicularAxisNumber == 1) LogicalToLayerCoordinates(new Logical3D(r.RX, id.LogicalValue, r.RZ), out x, out y); else LogicalToLayerCoordinates(new Logical3D(r.RX, r.RY, id.LogicalValue), out x, out y); return new PointD2D(x, y); }
/// <summary> /// Calculates from two layer coordinate values (in points usually) the relative coordinates of the point (between 0 and 1). Returns true if the conversion /// is possible, otherwise false. /// </summary> /// <param name="xlocation">On return, gives the x coordinate of the converted value (for instance location).</param> /// <param name="ylocation">On return, gives the y coordinate of the converted value (for instance location).</param> /// <param name="r">The logical coordinate as the result of the conversion.</param> /// <returns>True if the conversion was successfull, false if the conversion was not possible.</returns> public override bool LayerToLogicalCoordinates(double xlocation, double ylocation, out Logical3D r) { r = new Logical3D(); double wx = xlocation - _midX; double wy = -ylocation + _midY; if (wx == 0 && wy == 0) { r.RX = 0; r.RY = 0; } else { r.RX = Math.Atan2(wy, wx) / (2 * Math.PI); r.RY = 2 * Math.Sqrt(wx * wx + wy * wy) / _radius; } if (_isXreverse) r.RX = 1 - r.RX; if (_isYreverse) r.RY = 1 - r.RY; if (_isXYInterchanged) { double hr = r.RX; r.RX = r.RY; r.RY = hr; } return !double.IsNaN(r.RX) && !double.IsNaN(r.RY); }
/// <summary> /// Converts logical coordinates along an isoline to layer coordinates and returns the direction of the isoline at this point. /// </summary> /// <param name="r0">Logical coordinates of starting point of the isoline.</param> /// <param name="r1">Logical coordinates of end point of the isoline.</param> /// <param name="t">Parameter between 0 and 1 that determines the point on the isoline. /// A value of 0 denotes the starting point of the isoline, a value of 1 the end point. The logical /// coordinates are linear interpolated between starting point and end point.</param> /// <param name="angle">Angle between direction of the isoline and returned normalized direction vector.</param> /// <param name="normalizeddirection">Returns the normalized direction vector,i.e. a vector of norm 1, that /// has the angle <paramref name="angle"/> to the tangent of the isoline. </param> /// <returns>The location (in layer coordinates) of the isoline point.</returns> public PointD2D GetNormalizedDirection( Logical3D r0, Logical3D r1, double t, double angle, out PointD2D normalizeddirection) { double ax, ay, adx, ady; this.LogicalToLayerCoordinatesAndDirection( r0, r1, t, out ax, out ay, out adx, out ady); if (angle != 0) { double phi = Math.PI * angle / 180; double hdx = adx * Math.Cos(phi) + ady * Math.Sin(phi); ady = -adx * Math.Sin(phi) + ady * Math.Cos(phi); adx = hdx; } // Normalize the vector double rr = Calc.RMath.Hypot(adx, ady); if (rr > 0) { adx /= rr; ady /= rr; } normalizeddirection = new PointD2D(adx, ady); return new PointD2D(ax, ay); }
public override void GetIsoline(System.Drawing.Drawing2D.GraphicsPath path, Logical3D r0, Logical3D r1) { LogicalToLayerCoordinates(r0, out var x0, out var y0); LogicalToLayerCoordinates(r1, out var x1, out var y1); path.AddLine((float)x0, (float)y0, (float)x1, (float)y1); }
/// <summary> /// Converts logical coordinates along an isoline to layer coordinates and returns the direction of the isoline at this point. /// </summary> /// <param name="r0">Logical starting point of the isoline.</param> /// <param name="r1">Logical end point of the isoline.</param> /// <param name="t">Parameter between 0 and 1 that determines the point on the isoline. /// A value of 0 denotes the starting point of the isoline, a value of 1 the end point. The logical /// coordinates are linear interpolated between starting point and end point.</param> /// <param name="direction">Logical direction vector.</param> /// <param name="normalizeddirection">Returns the normalized direction vector,i.e. a vector of norm 1, that /// goes in the logical direction provided by the previous argument. </param> /// <returns>The location (in layer coordinates) of the isoline point.</returns> public virtual PointD2D GetNormalizedDirection( Logical3D r0, Logical3D r1, double t, Logical3D direction, out PointD2D normalizeddirection) { double ax, ay, adx, ady; Logical3D rn0 = Logical3D.Interpolate(r0, r1, t); Logical3D rn1 = rn0 + direction; this.LogicalToLayerCoordinatesAndDirection(rn0, rn1, 0, out ax, out ay, out adx, out ady); double hypot = Calc.RMath.Hypot(adx, ady); if (0 == hypot) { // then we look a little bit displaced - we might be at the midpoint where the directions are undefined double displT = t; if (displT < 0.5) displT += 1E-6; else displT -= 1E-6; Logical3D displR = Logical3D.Interpolate(r0, r1, displT); Logical3D displD = displR + direction; double dummyx, dummyy; LogicalToLayerCoordinatesAndDirection(displR, displD, 0, out dummyx, out dummyy, out adx, out ady); hypot = Calc.RMath.Hypot(adx, ady); } // Normalize the vector if (hypot > 0) { adx /= hypot; ady /= hypot; } normalizeddirection = new PointD2D(adx, ady); return new PointD2D(ax, ay); }
/// <summary> /// Paint the axis in the Graphics context. /// </summary> /// <param name="g">The graphics context painting to.</param> /// <param name="layer">The layer the axis belongs to.</param> /// <param name="styleInfo">The axis information of the axis to paint.</param> /// <param name="customTickSpacing">If not <c>null</c>, this parameter provides a custom tick spacing that is used instead of the default tick spacing of the scale.</param> public void Paint(IGraphicsContext3D g, IPlotArea layer, CSAxisInformation styleInfo, TickSpacing customTickSpacing) { CSLineID styleID = styleInfo.Identifier; _cachedAxisStyleInfo = styleInfo; Scale axis = layer.Scales[styleID.ParallelAxisNumber]; TickSpacing ticking = null != customTickSpacing ? customTickSpacing : layer.Scales[styleID.ParallelAxisNumber].TickSpacing; Logical3D r0 = styleID.GetLogicalPoint(styleInfo.LogicalValueAxisOrg); Logical3D r1 = styleID.GetLogicalPoint(styleInfo.LogicalValueAxisEnd); var sweepPath = layer.CoordinateSystem.GetIsoline(r0, r1); g.DrawLine(_axisPen, sweepPath); _cachedMainLinePointsUsedForHitTesting = sweepPath.Points.ToArray(); var majorTickLinesUsedForHitTesting = new List <LineD3D>(); var minorTickLinesUsedForHitTesting = new List <LineD3D>(); Logical3D outer; // now the major ticks VectorD3D outVector; double[] majorticks = ticking.GetMajorTicksNormal(axis); for (int i = 0; i < majorticks.Length; i++) { double r = majorticks[i]; if (_showFirstUpMajorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstUp); var tickorg = layer.CoordinateSystem.GetPositionAndNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _majorTickLength; g.DrawLine(_majorTickPen, tickorg, tickend); majorTickLinesUsedForHitTesting.Add(new LineD3D(tickorg, tickend)); } if (_showFirstDownMajorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstDown); var tickorg = layer.CoordinateSystem.GetPositionAndNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _majorTickLength; g.DrawLine(_majorTickPen, tickorg, tickend); majorTickLinesUsedForHitTesting.Add(new LineD3D(tickorg, tickend)); } if (_showSecondUpMajorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.SecondUp); var tickorg = layer.CoordinateSystem.GetPositionAndNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _majorTickLength; g.DrawLine(_majorTickPen, tickorg, tickend); majorTickLinesUsedForHitTesting.Add(new LineD3D(tickorg, tickend)); } if (_showSecondDownMajorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.SecondDown); var tickorg = layer.CoordinateSystem.GetPositionAndNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _majorTickLength; g.DrawLine(_majorTickPen, tickorg, tickend); majorTickLinesUsedForHitTesting.Add(new LineD3D(tickorg, tickend)); } } // now the major ticks double[] minorticks = ticking.GetMinorTicksNormal(axis); for (int i = 0; i < minorticks.Length; i++) { double r = minorticks[i]; if (_showFirstUpMinorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstUp); var tickorg = layer.CoordinateSystem.GetPositionAndNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _minorTickLength; g.DrawLine(_minorTickPen, tickorg, tickend); minorTickLinesUsedForHitTesting.Add(new LineD3D(tickorg, tickend)); } if (_showFirstDownMinorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstDown); var tickorg = layer.CoordinateSystem.GetPositionAndNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _minorTickLength; g.DrawLine(_minorTickPen, tickorg, tickend); minorTickLinesUsedForHitTesting.Add(new LineD3D(tickorg, tickend)); } if (_showSecondUpMinorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.SecondUp); var tickorg = layer.CoordinateSystem.GetPositionAndNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _minorTickLength; g.DrawLine(_minorTickPen, tickorg, tickend); minorTickLinesUsedForHitTesting.Add(new LineD3D(tickorg, tickend)); } if (_showSecondDownMinorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.SecondDown); var tickorg = layer.CoordinateSystem.GetPositionAndNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _minorTickLength; g.DrawLine(_minorTickPen, tickorg, tickend); minorTickLinesUsedForHitTesting.Add(new LineD3D(tickorg, tickend)); } } _cachedMajorTickLinesUsedForHitTesting = majorTickLinesUsedForHitTesting.ToArray(); _cachedMinorTickLinesUsedForHitTesting = minorTickLinesUsedForHitTesting.ToArray(); }
/// <summary> /// Calculates from two logical values (values between 0 and 1) the coordinates of the point. Returns true if the conversion /// is possible, otherwise false. /// </summary> /// <param name="r">The logical position value.</param> /// <param name="xlocation">On return, gives the x coordinate of the converted value (for instance location).</param> /// <param name="ylocation">On return, gives the y coordinate of the converted value (for instance location).</param> /// <returns>True if the conversion was successfull, false if the conversion was not possible.</returns> public abstract bool LogicalToLayerCoordinates(Logical3D r, out double xlocation, out double ylocation);
/// <summary> /// Calculates from two logical values (values between 0 and 1) the coordinates of the point. Returns true if the conversion /// is possible, otherwise false. /// </summary> /// <param name="r">The logical coordinates to convert.</param> /// <param name="xlocation">On return, gives the x coordinate of the converted value (for instance location).</param> /// <param name="ylocation">On return, gives the y coordinate of the converted value (for instance location).</param> /// <returns>True if the conversion was successfull, false if the conversion was not possible.</returns> public override bool LogicalToLayerCoordinates(Logical3D r, out double xlocation, out double ylocation) { if (_isXreverse) r.RX = 1 - r.RX; if (_isYreverse) r.RY = 1 - r.RY; if (_isXYInterchanged) { double hr = r.RX; r.RX = r.RY; r.RY = hr; } xlocation = _layerWidth * r.RX; ylocation = _layerHeight * (1 - r.RY); return !double.IsNaN(xlocation) && !double.IsNaN(ylocation); }
/// <summary> /// Converts logical coordinates along an isoline to layer coordinates and the appropriate derivative. /// </summary> /// <param name="r0">Logical position of starting point of the isoline.</param> /// <param name="r1">Logical position of end point of the isoline.</param> /// <param name="t">Parameter between 0 and 1 that determines the point on the isoline. /// A value of 0 denotes the starting point of the isoline, a value of 1 the end point. The logical /// coordinates are linear interpolated between starting point and end point.</param> /// <param name="ax">Layer coordinate x of the isoline point.</param> /// <param name="ay">Layer coordinate y of the isoline point.</param> /// <param name="adx">Derivative of layer coordinate x with respect to parameter t at the point (ax,ay).</param> /// <param name="ady">Derivative of layer coordinate y with respect to parameter t at the point (ax,ay).</param> /// <returns>True if the conversion was sucessfull, otherwise false.</returns> public abstract bool LogicalToLayerCoordinatesAndDirection( Logical3D r0, Logical3D r1, double t, out double ax, out double ay, out double adx, out double ady);
/// <summary> /// Calculates from two layer coordinate values (in points usually) the relative coordinates of the point (between 0 and 1). Returns true if the conversion /// is possible, otherwise false. /// </summary> /// <param name="xlocation">On return, gives the x coordinate of the converted value (for instance location).</param> /// <param name="ylocation">On return, gives the y coordinate of the converted value (for instance location).</param> /// <param name="r">The logical coordinates as the result of conversion.</param> /// <returns>True if the conversion was successfull, false if the conversion was not possible.</returns> public override bool LayerToLogicalCoordinates(double xlocation, double ylocation, out Logical3D r) { r = new Logical3D(xlocation / _layerWidth, 1 - ylocation / _layerHeight); if (_isXYInterchanged) { double hr = r.RX; r.RX = r.RY; r.RY = hr; } if (_isXreverse) r.RX = 1 - r.RX; if (_isYreverse) r.RY = 1 - r.RY; return !double.IsNaN(r.RX) && !double.IsNaN(r.RY); }
public override bool LogicalToLayerCoordinatesAndDirection(Logical3D r0, Logical3D r1, double t, out double ax, out double ay, out double adx, out double ady) { LogicalToLayerCoordinates(Logical3D.Interpolate(r0,r1,t),out ax, out ay); double x0, y0, x1, y1; LogicalToLayerCoordinates(r0, out x0, out y0); LogicalToLayerCoordinates(r1, out x1, out y1); adx = x1 - x0; ady = y1 - y0; return true; }
public override void GetIsoline(System.Drawing.Drawing2D.GraphicsPath path, Logical3D r0, Logical3D r1) { double x0, y0, x1, y1; LogicalToLayerCoordinates(r0, out x0, out y0); LogicalToLayerCoordinates(r1, out x1, out y1); path.AddLine((float)x0, (float)y0, (float)x1, (float)y1); }
/// <summary> /// Draws an isoline beginning from a plane to the given point. /// </summary> /// <param name="path">Graphics path to fill with the isoline.</param> /// <param name="id">The logical plane to start drawing from.</param> /// <param name="r">Logical coordinates of the end point.</param> public virtual void GetIsolineFromPlaneToPoint(GraphicsPath path, CSPlaneID id, Logical3D r) { if (id.PerpendicularAxisNumber == 0) { GetIsoline(path, new Logical3D(id.LogicalValue, r.RY, r.RZ), r); } else if (id.PerpendicularAxisNumber == 1) { GetIsoline(path, new Logical3D(r.RX, id.LogicalValue, r.RZ), r); } else { GetIsoline(path, new Logical3D(r.RX, r.RY, id.LogicalValue), r); } }
public override void GetIsoline(System.Drawing.Drawing2D.GraphicsPath g, Logical3D r0, Logical3D r1) { if (LogicalToLayerCoordinates(r0, out var ax0, out var ay0) && LogicalToLayerCoordinates(r1, out var ax1, out var ay1)) { g.AddLine((float)ax0, (float)ay0, (float)ax1, (float)ay1); } }
/// <summary> /// Paint the axis in the Graphics context. /// </summary> /// <param name="g">The graphics context painting to.</param> /// <param name="layer">The layer the axis belongs to.</param> /// <param name="styleInfo">The axis information of the axis to paint.</param> public void Paint(Graphics g, XYPlotLayer layer, CSAxisInformation styleInfo) { CSLineID styleID = styleInfo.Identifier; _cachedAxisStyleInfo = styleInfo.Clone(); Scale axis = styleID.ParallelAxisNumber == 0 ? layer.XAxis : layer.YAxis; Logical3D r0 = styleID.Begin; Logical3D r1 = styleID.End; layer.CoordinateSystem.DrawIsoline(g, _axisPen, r0, r1); Logical3D outer; // now the major ticks PointF outVector; double[] majorticks = axis.GetMajorTicksNormal(); for (int i = 0; i < majorticks.Length; i++) { double r = majorticks[i]; if (_showFirstUpMajorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstUp); PointF tickorg = layer.CoordinateSystem.GetNormalizedDirection(r0, r1, r, outer, out outVector); PointF tickend = tickorg; tickend.X += outVector.X * _majorTickLength; tickend.Y += outVector.Y * _majorTickLength; g.DrawLine(_majorTickPen, tickorg, tickend); } if (_showFirstDownMajorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstDown); PointF tickorg = layer.CoordinateSystem.GetNormalizedDirection(r0, r1, r, outer, out outVector); PointF tickend = tickorg; tickend.X += outVector.X * _majorTickLength; tickend.Y += outVector.Y * _majorTickLength; g.DrawLine(_majorTickPen, tickorg, tickend); } } // now the major ticks double[] minorticks = axis.GetMinorTicksNormal(); for (int i = 0; i < minorticks.Length; i++) { double r = minorticks[i]; if (_showFirstUpMinorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstUp); PointF tickorg = layer.CoordinateSystem.GetNormalizedDirection(r0, r1, r, outer, out outVector); PointF tickend = tickorg; tickend.X += outVector.X * _minorTickLength; tickend.Y += outVector.Y * _minorTickLength; g.DrawLine(_minorTickPen, tickorg, tickend); } if (_showFirstDownMinorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstDown); PointF tickorg = layer.CoordinateSystem.GetNormalizedDirection(r0, r1, r, outer, out outVector); PointF tickend = tickorg; tickend.X += outVector.X * _minorTickLength; tickend.Y += outVector.Y * _minorTickLength; g.DrawLine(_minorTickPen, tickorg, tickend); } } }
/// <summary> /// Paints the axis style labels. /// </summary> /// <param name="g">Graphics environment.</param> /// <param name="coordSyst">The coordinate system. Used to get the path along the axis.</param> /// <param name="scale">Scale.</param> /// <param name="tickSpacing">If not <c>null</c>, this parameter provides a custom tick spacing that is used instead of the default tick spacing of the scale.</param> /// <param name="styleInfo">Information about begin of axis, end of axis.</param> /// <param name="outerDistance">Distance between axis and labels.</param> /// <param name="useMinorTicks">If true, minor ticks are shown.</param> public virtual void Paint(IGraphicsContext3D g, G3DCoordinateSystem coordSyst, Scale scale, TickSpacing tickSpacing, CSAxisInformation styleInfo, double outerDistance, bool useMinorTicks) { _cachedAxisStyleInfo = styleInfo; CSLineID styleID = styleInfo.Identifier; Scale raxis = scale; TickSpacing ticking = tickSpacing; var math = Matrix4x3.Identity; Logical3D r0 = styleID.GetLogicalPoint(styleInfo.LogicalValueAxisOrg); Logical3D r1 = styleID.GetLogicalPoint(styleInfo.LogicalValueAxisEnd); Logical3D outer; double[] relpositions; AltaxoVariant[] ticks; if (useMinorTicks) { relpositions = ticking.GetMinorTicksNormal(raxis); ticks = ticking.GetMinorTicksAsVariant(); } else { relpositions = ticking.GetMajorTicksNormal(raxis); ticks = ticking.GetMajorTicksAsVariant(); } if (!_suppressedLabels.IsEmpty) { var filteredTicks = new List <AltaxoVariant>(); var filteredRelPositions = new List <double>(); for (int i = 0; i < ticks.Length; i++) { if (_suppressedLabels.ByValues.Contains(ticks[i])) { continue; } if (_suppressedLabels.ByNumbers.Contains(i)) { continue; } if (_suppressedLabels.ByNumbers.Contains(i - ticks.Length)) { continue; } filteredTicks.Add(ticks[i]); filteredRelPositions.Add(relpositions[i]); } ticks = filteredTicks.ToArray(); relpositions = filteredRelPositions.ToArray(); } IMeasuredLabelItem[] labels = _labelFormatting.GetMeasuredItems(g, _font, ticks); double emSize = _font.Size; CSAxisSide labelSide = null != _labelSide ? _labelSide.Value : styleInfo.PreferredLabelSide; var labelOutlines = new RectangularObjectOutline[ticks.Length]; for (int i = 0; i < ticks.Length; i++) { double r = relpositions[i]; if (!Altaxo.Calc.RMath.IsInIntervalCC(r, -1000, 1000)) { continue; } outer = coordSyst.GetLogicalDirection(styleID.ParallelAxisNumber, labelSide); PointD3D tickorg = coordSyst.GetPositionAndNormalizedDirection(r0, r1, r, outer, out var outVector); PointD3D tickend = tickorg + outVector * outerDistance; var msize = labels[i].Size; var morg = tickend; if (_automaticRotationShift) { // if this option is choosen, we have to find a shift value that shifts the center of the text outwards so that the bounding box of the text will not cross the plane that is // defined by the tickend point and the normal vector outVector // Assume that the text is now centered x, y, and z around the point tickend (but here we use origin instead tickend) math = Matrix4x3.NewRotation(_rotationX, _rotationY, _rotationZ); // we have to find all points with negative distance to the plane spanned by tickend and the vector outVector (but again instead of tickend we use origin) var msizePad = msize + new VectorD3D( (_font.Size * 1) / 3, // whereas above and below text no padding is neccessary, it is optically nicer to have left and right padding of the string by 1/6 of font size. 0, (_font.Size * 1) / 3 // same padding applies to z ); var crect = new RectangleD3D((PointD3D)(-0.5 * msizePad), msizePad); // our text centered around origin double shift = 0; foreach (PointD3D p in crect.Vertices) { PointD3D ps = math.Transform(p); double distance = Math3D.GetDistancePointToPlane(ps, PointD3D.Empty, outVector); if (-distance > shift) { shift = -distance; // only negative distances will count here } } morg += outVector * shift; } else { morg = morg.WithXPlus(outVector.X * _font.Size / 3); } var mrect = new RectangleD3D(morg, msize); if (_automaticRotationShift) { mrect = AdjustRectangle(mrect, Alignment.Center, Alignment.Center, Alignment.Center); } else { mrect = AdjustRectangle(mrect, _alignmentX, _alignmentY, _alignmentZ); } math = Matrix4x3.Identity; math.TranslatePrepend(morg.X, morg.Y, morg.Z); if (_rotationZ != 0) { math.RotationZDegreePrepend(_rotationZ); } if (_rotationY != 0) { math.RotationYDegreePrepend(_rotationY); } if (_rotationX != 0) { math.RotationXDegreePrepend(_rotationX); } math.TranslatePrepend((mrect.X - morg.X + emSize * _offsetX), (mrect.Y - morg.Y + emSize * _offsetY), (mrect.Z - morg.Z + emSize * _offsetZ)); var gs = g.SaveGraphicsState(); g.PrependTransform(math); if (_backgroundStyle != null) { var itemRectangle = new RectangleD3D(PointD3D.Empty, msize); _backgroundStyle.Measure(itemRectangle); _backgroundStyle.Draw(g, itemRectangle); } labels[i].Draw(g, _brush, PointD3D.Empty); labelOutlines[i] = new RectangularObjectOutline(new RectangleD3D(PointD3D.Empty, msize), math); g.RestoreGraphicsState(gs); // Restore the graphics state } _cachedLabelOutlines = labelOutlines; }
public void PaintPreprocessing(System.Drawing.Graphics g, IPaintContext paintContext, IPlotArea layer, PlotItemCollection coll) { var paintData = new CachedPaintData { _clippingColl = new System.Drawing.Region[coll.Count], _plotDataColl = new Processed2DPlotData[coll.Count], _xincColl = new double[coll.Count], _yincColl = new double[coll.Count] }; paintContext.AddValue(this, paintData); // First prepare int idx = -1; Processed2DPlotData previousPlotData = null; for (int i = 0; i < coll.Count; i++) { if (coll[i] is G2DPlotItem) { idx++; double currxinc = paintData._xincColl[i] = idx * _xinc * _scaleXInc; double curryinc = paintData._yincColl[i] = idx * _yinc * _scaleYInc; var gpi = coll[i] as G2DPlotItem; Processed2DPlotData plotdata = paintData._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; var rel = new Logical3D(layer.XAxis.PhysicalVariantToNormal(xx), layer.YAxis.PhysicalVariantToNormal(yy)); layer.CoordinateSystem.LogicalToLayerCoordinates(rel, out var xabs, out var yabs); plotdata.PlotPointsInAbsoluteLayerCoordinates[j] = new System.Drawing.PointF((float)xabs, (float)yabs); } // if clipping is used, we must get a clipping region for every plot item // and combine the regions from if (_useClipping) { if (i == 0) { paintData._clippingColl[i] = g.Clip; } Plot.Styles.LinePlotStyle linestyle = null; foreach (Plot.Styles.IG2DPlotStyle st in gpi.Style) { if (st is Plot.Styles.LinePlotStyle) { linestyle = st as Plot.Styles.LinePlotStyle; break; } } if (null != linestyle) { var path = new System.Drawing.Drawing2D.GraphicsPath(); linestyle.GetFillPath(path, layer, plotdata, CSPlaneID.Bottom); if ((i + 1) < paintData._clippingColl.Length) { paintData._clippingColl[i + 1] = paintData._clippingColl[i].Clone(); paintData._clippingColl[i + 1].Exclude(path); } } else { if ((i + 1) < paintData._clippingColl.Length) { paintData._clippingColl[i + 1] = paintData._clippingColl[i]; } } } } } }
/// <summary> /// Gets a iso line in a path object. /// </summary> /// <param name="r0">Starting position in logical coordinates.</param> /// <param name="r1">End position in logical coordinates.</param> /// <returns>The graphics path for the isoline.</returns> public abstract IPolylineD3D GetIsoline(Logical3D r0, Logical3D r1);
public override bool LogicalToLayerCoordinatesAndDirection( Logical3D r0, Logical3D r1, double t, out double ax, out double ay, out double adx, out double ady) { if (_isXreverse) { r0.RX = 1 - r0.RX; r1.RX = 1 - r1.RX; } if (_isYreverse) { r0.RY = 1 - r0.RY; r1.RY = 1 - r1.RY; } if (_isXYInterchanged) { double hr0 = r0.RX; r0.RX = r0.RY; r0.RY = hr0; double hr1 = r1.RX; r1.RX = r1.RY; r1.RY = hr1; } double rx = r0.RX + t * (r1.RX - r0.RX); double ry = r0.RY + t * (r1.RY - r0.RY); double phi = -2 * Math.PI * rx; double rad = _radius * ry; ax = _midX + rad * Math.Cos(phi); ay = _midY + rad * Math.Sin(phi); adx = _radius * ((r1.RY - r0.RY) * Math.Cos(phi) + 2 * Math.PI * (r1.RX - r0.RX) * ry * Math.Sin(phi)); ady = _radius * ((r1.RY - r0.RY) * Math.Sin(phi) - 2 * Math.PI * (r1.RX - r0.RX) * ry * Math.Cos(phi)); return !double.IsNaN(ax) && !double.IsNaN(ay); }
/// <summary> /// Calculates from two logical values (values between 0 and 1) the coordinates of the point. Returns true if the conversion /// is possible, otherwise false. /// </summary> /// <param name="r">The logical position value.</param> /// <param name="location">On return, gives the coordinates of the converted value (for instance location).</param> /// <returns>True if the conversion was successfull, false if the conversion was not possible.</returns> public abstract bool LogicalToLayerCoordinates(Logical3D r, out PointD3D location);
public override void GetIsoline(System.Drawing.Drawing2D.GraphicsPath g, Logical3D r0, Logical3D r1) { double ax0, ax1, ay0, ay1; if (LogicalToLayerCoordinates(r0, out ax0, out ay0) && LogicalToLayerCoordinates(r1, out ax1, out ay1)) { // add a line when this is a radial ray if (((r0.RX == r1.RX) && !_isXYInterchanged) || ((r0.RY == r1.RY) && _isXYInterchanged)) { g.AddLine((float)ax0, (float)ay0, (float)ax1, (float)ay1); } // add an arc if this is a tangential ray else if (((r0.RY == r1.RY) && !_isXYInterchanged) || ((r0.RX == r1.RX) && _isXYInterchanged)) { double startAngle = 180 * Math.Atan2(_midY - ay0, ax0 - _midX) / Math.PI; double sweepAngle; if (_isXYInterchanged) { sweepAngle = (r1.RY - r0.RY) * 360; if (_isYreverse) sweepAngle = -sweepAngle; } else { sweepAngle = (r1.RX - r0.RX) * 360; if (_isXreverse) sweepAngle = -sweepAngle; } double r = Calc.RMath.Hypot(_midY - ay0, ax0 - _midX); if (r > 0) g.AddArc((float)(_midX - r), (float)(_midY - r), (float)(2 * r), (float)(2 * r), (float)-startAngle, (float)-sweepAngle); } else // if it is neither radial nor tangential { int points = _isXYInterchanged ? (int)(Math.Abs(r1.RY - r0.RY) * 360) : (int)(Math.Abs(r1.RX - r0.RX) * 360); points = Math.Max(1, Math.Min(points, 3600)); // in case there is a rotation more than one turn limit the number of points PointF[] pts = new PointF[points + 1]; for (int i = 0; i <= points; i++) { Logical3D r = new Logical3D(r0.RX + i * (r1.RX - r0.RX) / points, r0.RY + i * (r1.RY - r0.RY) / points); double ax, ay; LogicalToLayerCoordinates(r, out ax, out ay); pts[i] = new PointF((float)ax, (float)ay); } g.AddLines(pts); } } }
/// <summary> /// Converts logical coordinates along an isoline to layer coordinates and the appropriate derivative. /// </summary> /// <param name="r0">Logical position of starting point of the isoline.</param> /// <param name="r1">Logical position of end point of the isoline.</param> /// <param name="t">Parameter between 0 and 1 that determines the point on the isoline. /// A value of 0 denotes the starting point of the isoline, a value of 1 the end point. The logical /// coordinates are linear interpolated between starting point and end point.</param> /// <param name="position">Layer coordinate of the isoline point.</param> /// <param name="direction">Derivative of layer coordinate with respect to parameter t at the point <paramref name="position"/>.</param> /// <returns>True if the conversion was sucessfull, otherwise false.</returns> public abstract bool LogicalToLayerCoordinatesAndDirection( Logical3D r0, Logical3D r1, double t, out PointD3D position, out VectorD3D direction);
/// <summary> /// Calculates from two coordinates of a point the logical values (values between 0 and 1). Returns true if the conversion /// is possible, otherwise false. /// </summary> /// <param name="location">The x coordinate of the converted value (for instance location).</param> /// <param name="r">The computed logical position value.</param> /// <returns>True if the conversion was successfull, false if the conversion was not possible. For 3D coordinate systems, /// the relative values of x and y with z=0 should be returned.</returns> public abstract bool LayerToLogicalCoordinates(PointD3D location, out Logical3D r);
public override IPolylineD3D GetIsoline(Logical3D r0, Logical3D r1) { LogicalToLayerCoordinates(r0, out var pt0); LogicalToLayerCoordinates(r1, out var pt1); return(new StraightLineAsPolylineD3D(pt0, pt1)); }
// CoordinateSystem is not affine, or scales are non-linear private void BuildImageV3(Graphics gfrx, IPlotArea gl, IROVector lx, IROVector ly, IROMatrix vcolumns) { // allocate a bitmap of same dimensions than the underlying layer _imageType = CachedImageType.Other; int dimX = (int)Math.Ceiling(gl.Size.X / 72.0 * gfrx.DpiX); int dimY = (int)Math.Ceiling(gl.Size.Y / 72.0 * gfrx.DpiY); dimX = Math.Min(2048, dimX); dimY = Math.Min(2048, dimY); // look if the image has the right dimensions if (null == _cachedImage || _cachedImage.Width != dimX || _cachedImage.Height != dimY) { if (null != _cachedImage) _cachedImage.Dispose(); // please notice: the horizontal direction of the image is related to the row index!!! (this will turn the image in relation to the table) // and the vertical direction of the image is related to the column index _cachedImage = new System.Drawing.Bitmap(dimX, dimY, System.Drawing.Imaging.PixelFormat.Format32bppArgb); } byte[] imageBytes = new byte[dimX * dimY * 4]; double widthByDimX = gl.Size.X / dimX; double heightByDimY = gl.Size.Y / dimY; Logical3D rel = new Logical3D(); double minRX = lx[0]; double maxRX = lx[lx.Length - 1]; double minRY = ly[0]; double maxRY = ly[ly.Length - 1]; if (minRX > maxRX) { double h = minRX; minRX = maxRX; maxRX = h; } if (minRY > maxRY) { double h = minRY; minRY = maxRY; maxRY = h; } BivariateLinearSpline interpol = new BivariateLinearSpline(lx, ly, vcolumns); Color colorInvalid = _colorProvider.GetColor(double.NaN); int addr = 0; for (int ny = 0; ny < dimY; ny++) { double py = (ny + 0.5) * heightByDimY; for (int nx = 0; nx < dimX; nx++, addr += 4) { double px = (nx + 0.5) * widthByDimX; if (false == gl.CoordinateSystem.LayerToLogicalCoordinates(px, py, out rel)) { _cachedImage.SetPixel(nx, ny, colorInvalid); } else // conversion to relative coordinates was possible { double rx = rel.RX; double ry = rel.RY; if (rx < minRX || rx > maxRX || ry < minRY || ry > maxRY) { //_cachedImage.SetPixel(nx, ny, _colorInvalid); imageBytes[addr + 0] = colorInvalid.B; imageBytes[addr + 1] = colorInvalid.G; imageBytes[addr + 2] = colorInvalid.R; imageBytes[addr + 3] = colorInvalid.A; } else { double val = interpol.Interpolate(rx, ry); if (double.IsNaN(val)) { //_cachedImage.SetPixel(nx, ny, _colorInvalid); imageBytes[addr + 0] = colorInvalid.B; imageBytes[addr + 1] = colorInvalid.G; imageBytes[addr + 2] = colorInvalid.R; imageBytes[addr + 3] = colorInvalid.A; } else { //_cachedImage.SetPixel(nx, ny, GetColor(val)); Color c = GetColor(val); imageBytes[addr + 0] = c.B; imageBytes[addr + 1] = c.G; imageBytes[addr + 2] = c.R; imageBytes[addr + 3] = c.A; } } } } } // Lock the bitmap's bits. Rectangle rect = new Rectangle(0, 0, _cachedImage.Width, _cachedImage.Height); System.Drawing.Imaging.BitmapData bmpData = _cachedImage.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, _cachedImage.PixelFormat); // Get the address of the first line. IntPtr ptr = bmpData.Scan0; // Copy the RGB values back to the bitmap System.Runtime.InteropServices.Marshal.Copy(imageBytes, 0, ptr, imageBytes.Length); _cachedImage.UnlockBits(bmpData); }
public override void GetIsoline(System.Drawing.Drawing2D.GraphicsPath g, Logical3D r0, Logical3D r1) { double ax0, ax1, ay0, ay1; if (LogicalToLayerCoordinates(r0, out ax0, out ay0) && LogicalToLayerCoordinates(r1, out ax1, out ay1)) { // add a line when this is a radial ray if (((r0.RX == r1.RX) && !_isXYInterchanged) || ((r0.RY == r1.RY) && _isXYInterchanged)) { g.AddLine((float)ax0, (float)ay0, (float)ax1, (float)ay1); } // add an arc if this is a tangential ray else if (((r0.RY == r1.RY) && !_isXYInterchanged) || ((r0.RX == r1.RX) && _isXYInterchanged)) { double startAngle = 180 * Math.Atan2(_midY - ay0, ax0 - _midX) / Math.PI; double sweepAngle; if (_isXYInterchanged) { sweepAngle = (r1.RY - r0.RY) * 360; if (_isYreverse) { sweepAngle = -sweepAngle; } } else { sweepAngle = (r1.RX - r0.RX) * 360; if (_isXreverse) { sweepAngle = -sweepAngle; } } double r = Calc.RMath.Hypot(_midY - ay0, ax0 - _midX); if (r > 0) { g.AddArc((float)(_midX - r), (float)(_midY - r), (float)(2 * r), (float)(2 * r), (float)-startAngle, (float)-sweepAngle); } } else // if it is neither radial nor tangential { int points = _isXYInterchanged ? (int)(Math.Abs(r1.RY - r0.RY) * 360) : (int)(Math.Abs(r1.RX - r0.RX) * 360); points = Math.Max(1, Math.Min(points, 3600)); // in case there is a rotation more than one turn limit the number of points PointF[] pts = new PointF[points + 1]; for (int i = 0; i <= points; i++) { Logical3D r = new Logical3D(r0.RX + i * (r1.RX - r0.RX) / points, r0.RY + i * (r1.RY - r0.RY) / points); double ax, ay; LogicalToLayerCoordinates(r, out ax, out ay); pts[i] = new PointF((float)ax, (float)ay); } g.AddLines(pts); } } }
/// <summary> /// Paint the axis in the Graphics context. /// </summary> /// <param name="g">The graphics context painting to.</param> /// <param name="layer">The layer the axis belongs to.</param> /// <param name="styleInfo">The axis information of the axis to paint.</param> /// <param name="customTickSpacing">If not <c>null</c>, this parameter provides a custom tick spacing that is used instead of the default tick spacing of the scale.</param> public void Paint(Graphics g, IPlotArea layer, CSAxisInformation styleInfo, TickSpacing customTickSpacing) { CSLineID styleID = styleInfo.Identifier; _cachedAxisStyleInfo = styleInfo; Scale axis = layer.Scales[styleID.ParallelAxisNumber]; TickSpacing ticking = null != customTickSpacing ? customTickSpacing : layer.Scales[styleID.ParallelAxisNumber].TickSpacing; Logical3D r0 = styleID.GetLogicalPoint(styleInfo.LogicalValueAxisOrg); Logical3D r1 = styleID.GetLogicalPoint(styleInfo.LogicalValueAxisEnd); layer.CoordinateSystem.DrawIsoline(g, _axisPen, r0, r1); Logical3D outer; // now the major ticks PointD2D outVector; double[] majorticks = ticking.GetMajorTicksNormal(axis); for (int i = 0; i < majorticks.Length; i++) { double r = majorticks[i]; if (_showFirstUpMajorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstUp); var tickorg = layer.CoordinateSystem.GetNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _majorTickLength; g.DrawLine(_majorTickPen, (PointF)tickorg, (PointF)tickend); } if (_showFirstDownMajorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstDown); var tickorg = layer.CoordinateSystem.GetNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _majorTickLength; g.DrawLine(_majorTickPen, (PointF)tickorg, (PointF)tickend); } } // now the major ticks double[] minorticks = ticking.GetMinorTicksNormal(axis); for (int i = 0; i < minorticks.Length; i++) { double r = minorticks[i]; if (_showFirstUpMinorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstUp); var tickorg = layer.CoordinateSystem.GetNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _minorTickLength; g.DrawLine(_minorTickPen, (PointF)tickorg, (PointF)tickend); } if (_showFirstDownMinorTicks) { outer = layer.CoordinateSystem.GetLogicalDirection(styleID.ParallelAxisNumber, CSAxisSide.FirstDown); var tickorg = layer.CoordinateSystem.GetNormalizedDirection(r0, r1, r, outer, out outVector); var tickend = tickorg + outVector * _minorTickLength; g.DrawLine(_minorTickPen, (PointF)tickorg, (PointF)tickend); } } }
public void PaintPreprocessing(IPaintContext paintContext, IPlotArea layer, PlotItemCollection coll) { Dictionary<G3DPlotItem, Processed3DPlotData> plotDataDict = null; if (!CanUseStyle(layer, coll, out plotDataDict)) { return; } else { paintContext.AddValue(this, plotDataDict); } AltaxoVariant[] vArray = null; // First, add up all items since we start always with the last item int idx = -1; Processed3DPlotData previousItemData = null; foreach (IGPlotItem pi in coll) { if (pi is G3DPlotItem) { idx++; G3DPlotItem gpi = pi as G3DPlotItem; Processed3DPlotData pdata = plotDataDict[gpi]; vArray = AddUp(vArray, pdata); if (idx > 0) // this is not the first item { int j = -1; foreach (int originalIndex in pdata.RangeList.OriginalRowIndices()) { j++; Logical3D rel = new Logical3D( layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(originalIndex)), layer.YAxis.PhysicalVariantToNormal(pdata.GetYPhysical(originalIndex)), layer.ZAxis.PhysicalVariantToNormal(vArray[j])); PointD3D pabs; layer.CoordinateSystem.LogicalToLayerCoordinates(rel, out pabs); pdata.PlotPointsInAbsoluteLayerCoordinates[j] = pabs; } } // we have also to exchange the accessor for the physical y value and replace it by our own one AltaxoVariant[] localArray = (AltaxoVariant[])vArray.Clone(); LocalArrayHolder localArrayHolder = new LocalArrayHolder(localArray, pdata); pdata.ZPhysicalAccessor = localArrayHolder.GetPhysical; pdata.PreviousItemData = previousItemData; previousItemData = pdata; } } }
public void Paint(System.Drawing.Graphics g, IPlotArea layer, PlotItemCollection coll) { Dictionary <G2DPlotItem, Processed2DPlotData> plotDataDict; if (!CanUseStyle(layer, coll, out plotDataDict)) { CoordinateTransformingStyleBase.Paint(g, layer, coll); return; } AltaxoVariant[] ysumArray = null; foreach (IGPlotItem pi in coll) { if (pi is G2DPlotItem) { G2DPlotItem 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) { G2DPlotItem gpi = pi as G2DPlotItem; Processed2DPlotData pdata = plotDataDict[gpi]; yArray = AbsoluteStackTransform.AddUp(yArray, pdata); AltaxoVariant[] 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; Logical3D rel = new Logical3D( layer.XAxis.PhysicalVariantToNormal(pdata.GetXPhysical(originalIndex)), layer.YAxis.PhysicalVariantToNormal(y)); double xabs, yabs; layer.CoordinateSystem.LogicalToLayerCoordinates(rel, out xabs, out 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; } } for (int i = coll.Count - 1; i >= 0; --i) { IGPlotItem pi = coll[i]; if (pi is G2DPlotItem) { G2DPlotItem gpi = pi as G2DPlotItem; Processed2DPlotData pdata = plotDataDict[gpi]; gpi.Paint(g, layer, pdata); } else { pi.Paint(g, layer); } } }