public override void Paint(IGraphicsContext3D g, IPaintContext context) { var gs = g.SaveGraphicsState(); g.PrependTransform(_transformation); g.DrawLine(_linePen, Bounds.Location, Bounds.LocationPlusSize); g.RestoreGraphicsState(gs); }
/// <summary> /// Transforms the graphics context is such a way, that the object can be drawn in local coordinates. /// </summary> /// <param name="g">Graphics context (should be saved beforehand).</param> protected virtual void TransformGraphics(IGraphicsContext3D g) { if (RotationX != 0 || RotationY != 0 || RotationZ != 0 || ScaleX != 1 || ScaleY != 1 || ScaleZ != 1 || ShearX != 0 || ShearY != 0 || ShearZ != 0) { g.PrependTransform(Matrix4x3.NewScalingShearingRotationDegreesTranslation( _location.ScaleX, _location.ScaleY, _location.ScaleY , _location.ShearX, _location.ShearY, _location.ShearZ, _location.RotationX, _location.RotationY, _location.RotationZ, _location.AbsolutePivotPosition.X, _location.AbsolutePivotPositionY, _location.AbsolutePivotPositionZ)); } else { var p = _location.AbsolutePivotPosition; g.TranslateTransform(p.X, p.Y, p.Z); } }
/// <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; }
/// <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); VectorD3D outVector; 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) { List<AltaxoVariant> filteredTicks = new List<AltaxoVariant>(); List<double> 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 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 (this._rotationZ != 0) math.RotationZDegreePrepend(this._rotationZ); if (this._rotationY != 0) math.RotationYDegreePrepend(this._rotationY); if (this._rotationX != 0) math.RotationXDegreePrepend(this._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 (this._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; }