コード例 #1
0
ファイル: AxisLabelStyle.cs プロジェクト: olesar/Altaxo
        /// <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);
            }
        }
コード例 #2
0
ファイル: AxisLabelStyle.cs プロジェクト: olesar/Altaxo
        /// <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;
        }