Пример #1
0
            public override void Draw(IGraphicsContext3D g, DrawContext dc, double xbase, double ybase, double zbase)
            {
                var mylayer = (HostLayer)dc.LinkedObject;

                var layer = mylayer as XYZPlotLayer;

                if (_layerNumber >= 0 && mylayer.SiblingLayers != null && _layerNumber < mylayer.SiblingLayers.Count)
                {
                    layer = mylayer.SiblingLayers[_layerNumber] as XYZPlotLayer;
                }

                if (null == layer)
                {
                    return;
                }

                if (_plotNumber < layer.PlotItems.Flattened.Length)
                {
                    var        fontInfo = dc.FontCache.GetFontInfo(Style.FontId);
                    IGPlotItem pa       = layer.PlotItems.Flattened[_plotNumber];

                    var symbolpos  = new PointD3D(xbase, (ybase + 0.5 * fontInfo.cyDescent - 0.5 * fontInfo.cyAscent), 0);
                    var symbolRect = new RectangleD3D(symbolpos, new VectorD3D(SizeX, 0, 0));
                    symbolRect = symbolRect.WithPadding(0, fontInfo.Size, 0);
                    pa.PaintSymbol(g, symbolRect);

                    if (!dc.bForPreview)
                    {
                        var volume = new RectangleTransformedD3D(
                            new RectangleD3D(symbolpos.X, symbolpos.Y - 0.5 * fontInfo.cyLineSpace, 0, SizeX, fontInfo.cyLineSpace, 0), dc.transformMatrix);
                        dc._cachedSymbolPositions.Add(volume, pa);
                    }
                }
            }
Пример #2
0
        /// <summary>
        /// Measures the background size and position.
        /// </summary>
        /// <param name="itemRectangle">Position and size of the item for which this background is intended. For text, this is the position and size of the text rectangle, already with a margin around.</param>
        /// <returns>
        /// The position and size of the rectangle that fully includes the background (but not the item).
        /// </returns>
        public RectangleD3D Measure(RectangleD3D itemRectangle)
        {
            _resultingDistance  = _customDistance.HasValue ? _customDistance.Value : itemRectangle.SizeZ / 2;
            _resultingThickness = _customThickness.HasValue ? _customThickness.Value : itemRectangle.SizeZ;

            return(GetRectangleToDraw(itemRectangle));
        }
Пример #3
0
        /// <summary>
        /// Draws the specified background
        /// </summary>
        /// <param name="g">The drawing context.</param>
        /// <param name="itemRectangle">Position and size of the item for which this background is intended. For text, this is the position and size of the text rectangle, already with a margin around.
        /// This parameter should have the same size as was used in the previous call to <see cref="Measure(RectangleD3D)" /></param>
        /// <param name="material">The material to use for this background.</param>
        /// <exception cref="NotImplementedException"></exception>
        public void Draw(IGraphicsContext3D g, RectangleD3D itemRectangle, IMaterial material)
        {
            var rectangleToDraw = GetRectangleToDraw(itemRectangle);

            var buffers = g.GetPositionNormalIndexedTriangleBuffer(material);

            if (null != buffers.PositionNormalColorIndexedTriangleBuffer)
            {
                var c     = material.Color.Color;
                var voffs = buffers.PositionNormalColorIndexedTriangleBuffer.VertexCount;
                Altaxo.Drawing.D3D.SolidCube.Add(
                    rectangleToDraw.X, rectangleToDraw.Y, rectangleToDraw.Z, rectangleToDraw.SizeX, rectangleToDraw.SizeY, rectangleToDraw.SizeZ,
                    (point, normal) => buffers.PositionNormalColorIndexedTriangleBuffer.AddTriangleVertex(point.X, point.Y, point.Z, normal.X, normal.Y, normal.Z, c.ScR, c.ScG, c.ScB, c.ScA),
                    (i1, i2, i3) => buffers.IndexedTriangleBuffer.AddTriangleIndices(i1 + voffs, i2 + voffs, i3 + voffs),
                    ref voffs);
            }
            else if (null != buffers.PositionNormalIndexedTriangleBuffer)
            {
                var voffs = buffers.PositionNormalIndexedTriangleBuffer.VertexCount;
                Altaxo.Drawing.D3D.SolidCube.Add(
                    rectangleToDraw.X, rectangleToDraw.Y, rectangleToDraw.Z, rectangleToDraw.SizeX, rectangleToDraw.SizeY, rectangleToDraw.SizeZ,
                    (point, normal) => buffers.PositionNormalIndexedTriangleBuffer.AddTriangleVertex(point.X, point.Y, point.Z, normal.X, normal.Y, normal.Z),
                    (i1, i2, i3) => buffers.IndexedTriangleBuffer.AddTriangleIndices(i1 + voffs, i2 + voffs, i3 + voffs),
                    ref voffs);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
            /// <summary>
            /// Determines whether the grip is hit by the current mouse position.
            /// </summary>
            /// <param name="mousePosition">The mouse position (hit ray).</param>
            /// <returns></returns>
            public bool IsGripHit(HitTestPointData mousePosition)
            {
                var vec  = new VectorD3D(_gripRadius, _gripRadius, _gripRadius);
                var rect = new RectangleD3D(_gripCenter - vec, 2 * vec);

                return(mousePosition.IsHit(rect, out var z));
            }
Пример #5
0
        public void Paint(IGraphicsContext3D g, IPlotArea layer, CSPlaneID plane, int axisnumber)
        {
            if (!_showGrid)
            {
                return;
            }

            Scale       axis    = layer.Scales[axisnumber];
            TickSpacing ticking = layer.Scales[axisnumber].TickSpacing;

            var layerRect = new RectangleD3D(PointD3D.Empty, layer.Size);

            if (_showZeroOnly)
            {
                var    var = new Altaxo.Data.AltaxoVariant(0.0);
                double rel = axis.PhysicalVariantToNormal(var);
                //_majorPen.SetEnvironment(layerRect, BrushX.GetEffectiveMaximumResolution(g, 1));
                if (rel >= 0 && rel <= 1)
                {
                    var logV = new Logical3D();
                    logV.SetR(plane.PerpendicularAxisNumber, plane.LogicalValue);
                    logV.SetR(axisnumber, rel);
                    var thirdAxisNumber = Logical3D.GetPerpendicularAxisNumber(plane.PerpendicularAxisNumber, axisnumber);
                    var line            = layer.CoordinateSystem.GetIsoline(logV.WithR(thirdAxisNumber, 0), logV.WithR(thirdAxisNumber, 1));
                    g.DrawLine(MajorPen, line);
                }
            }
            else
            {
                double[] ticks;

                if (_showMinor)
                {
                    //_minorPen.SetEnvironment(layerRect, BrushX.GetEffectiveMaximumResolution(g, 1));
                    ticks = ticking.GetMinorTicksNormal(axis);
                    for (int i = 0; i < ticks.Length; ++i)
                    {
                        var logV = new Logical3D();
                        logV.SetR(plane.PerpendicularAxisNumber, plane.LogicalValue);
                        logV.SetR(axisnumber, ticks[i]);
                        var thirdAxisNumber = Logical3D.GetPerpendicularAxisNumber(plane.PerpendicularAxisNumber, axisnumber);
                        var line            = layer.CoordinateSystem.GetIsoline(logV.WithR(thirdAxisNumber, 0), logV.WithR(thirdAxisNumber, 1));
                        g.DrawLine(MinorPen, line);
                    }
                }

                //MajorPen.SetEnvironment(layerRect, BrushX.GetEffectiveMaximumResolution(g, 1));
                ticks = ticking.GetMajorTicksNormal(axis);
                for (int i = 0; i < ticks.Length; ++i)
                {
                    var logV = new Logical3D();
                    logV.SetR(plane.PerpendicularAxisNumber, plane.LogicalValue);
                    logV.SetR(axisnumber, ticks[i]);
                    var thirdAxisNumber = Logical3D.GetPerpendicularAxisNumber(plane.PerpendicularAxisNumber, axisnumber);
                    var line            = layer.CoordinateSystem.GetIsoline(logV.WithR(thirdAxisNumber, 0), logV.WithR(thirdAxisNumber, 1));
                    g.DrawLine(MajorPen, line);
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Gets the bounds of the root layer.
        /// </summary>
        /// <returns></returns>
        private RectangleD3D GetViewBounds()
        {
            var matrix = _camera.LookAtRHMatrix;
            var rect   = new RectangleD3D(PointD3D.Empty, RootLayer.Size);
            var bounds = RectangleD3D.NewRectangleIncludingAllPoints(rect.Vertices.Select(x => matrix.Transform(x)));

            return(bounds);
        }
Пример #7
0
        public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
        {
            bounds = bounds.WithPadding(0, 0, -bounds.SizeZ / 4);
            var heightBy2 = new VectorD3D(0, 0, bounds.SizeZ / 4);

            g.DrawLine(_pen, bounds.Center - heightBy2, bounds.Center + heightBy2);

            return(bounds);
        }
Пример #8
0
        public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
        {
            for (int i = _innerList.Count - 1; i >= 0; i--)
            {
                bounds = this[i].PaintSymbol(g, bounds);
            }

            return(bounds);
        }
Пример #9
0
        public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
        {
            if (!ScatterSymbols.NoSymbol.Instance.Equals(_symbolShape))
            {
                _symbolShape.Paint(g, _material, bounds.Center, _symbolSize);
                bounds = bounds.WithPadding(0, Math.Max(0, SymbolSize - bounds.SizeY), Math.Max(0, SymbolSize - bounds.SizeZ));
            }

            return(bounds);
        }
Пример #10
0
 /// <summary>
 /// Gets the rectangle for the background to draw. Used both by <see cref="Measure"/> as well as <see cref="Draw"/>.
 /// </summary>
 /// <param name="itemRectangle">The item rectangle.</param>
 /// <returns></returns>
 private RectangleD3D GetRectangleToDraw(RectangleD3D itemRectangle)
 {
     return(new RectangleD3D(
                itemRectangle.X - _padding.Left,
                itemRectangle.Y - _padding.Bottom,
                itemRectangle.Z - _resultingDistance - itemRectangle.SizeZ,
                itemRectangle.SizeX + _padding.Left + _padding.Right,
                itemRectangle.SizeY + _padding.Top + _padding.Bottom,
                _resultingThickness
                ));
 }
            /// <summary>Draws the grip in the graphics context.</summary>
            /// <param name="g">Graphics context.</param>
            public void Show(IOverlayContext3D g)
            {
                var buf = g.PositionColorLineListBuffer;

                var vec  = new VectorD3D(_gripRadius, _gripRadius, _gripRadius);
                var rect = new RectangleD3D(_gripCenter - vec, 2 * vec);

                foreach (var line in rect.Edges)
                {
                    buf.AddLine(line.P0.X, line.P0.Y, line.P0.Z, line.P1.X, line.P1.Y, line.P1.Z, 1, 0, 0, 1);
                }
            }
Пример #12
0
        /// <summary>
        /// Gets the absolute enclosing rectangle, taking into account ScaleX, ScaleY, Rotation and Shear (SSRS).
        /// </summary>
        /// <returns>The enclosing rectangle in absolute values.</returns>
        public RectangleD3D GetAbsoluteEnclosingRectangle()
        {
            var m = Matrix4x3.NewScalingShearingRotationDegreesTranslation(
                ScaleX, ScaleY, ScaleZ,
                ShearX, ShearY, ShearZ,
                RotationX, RotationY, RotationZ,
                AbsolutePivotPositionX, AbsolutePivotPositionY, AbsolutePivotPositionZ);

            m.TranslatePrepend(AbsoluteVectorPivotToLeftUpper.X, AbsoluteVectorPivotToLeftUpper.Y, AbsoluteVectorPivotToLeftUpper.Z);

            var r = new RectangleD3D(PointD3D.Empty, AbsoluteSize);

            return(RectangleD3D.NewRectangleIncludingAllPoints(r.Vertices.Select(p => m.Transform(p))));
        }
Пример #13
0
        public RectangleD3D AdjustRectangle(RectangleD3D r, Alignment alignmentX, Alignment alignmentY, Alignment alignmentZ)
        {
            double rX = r.X;
            double rY = r.Y;
            double rZ = r.Z;

            switch (alignmentZ)
            {
            case Alignment.Near:
                break;

            case Alignment.Center:
                rZ -= 0.5 * r.SizeZ;
                break;

            case Alignment.Far:
                rZ -= r.SizeZ;
                break;
            }
            switch (alignmentY)
            {
            case Alignment.Near:
                break;

            case Alignment.Center:
                rY -= 0.5 * r.SizeY;
                break;

            case Alignment.Far:
                rY -= r.SizeY;
                break;
            }
            switch (alignmentX)
            {
            case Alignment.Near:
                break;

            case Alignment.Center:
                rX -= 0.5 * r.SizeX;
                break;

            case Alignment.Far:
                rX -= r.SizeX;
                break;
            }

            return(new RectangleD3D(rX, rY, rZ, r.SizeX, r.SizeY, r.SizeZ));
        }
Пример #14
0
        /// <summary>
        /// Determines whether a polyline is hit.
        /// </summary>
        /// <param name="points">The points that make out the polyline.</param>
        /// <param name="thickness1">The thickness of the pen in east direction.</param>
        /// <param name="thickness2">The thickness of the pen in north direction.</param>
        /// <returns>True if the polyline is hit; otherwise false.</returns>
        public bool IsHit(IEnumerable <PointD3D> points, double thickness1, double thickness2)
        {
            var polyline = PolylineMath3D.GetPolylinePointsWithWestAndNorth(points);

            var coll = polyline.GetEnumerator();

            if (!coll.MoveNext())
            {
                return(false); // no points
            }
            double thickness1By2 = thickness1 / 2;
            double thickness2By2 = thickness2 / 2;
            var    pts           = new PointD3D[8];

            PointD3D P0 = coll.Current.Position;

            while (coll.MoveNext())
            {
                var P1 = coll.Current.Position;    // end point of current line
                var e  = coll.Current.WestVector;  // east vector
                var n  = coll.Current.NorthVector; // north vector

                pts[0] = _hitTransformation.Transform(P0 - thickness1By2 * e - thickness2By2 * n);
                pts[1] = _hitTransformation.Transform(P1 - thickness1By2 * e - thickness2By2 * n);
                pts[2] = _hitTransformation.Transform(P0 + thickness1By2 * e - thickness2By2 * n);
                pts[3] = _hitTransformation.Transform(P1 + thickness1By2 * e - thickness2By2 * n);
                pts[4] = _hitTransformation.Transform(P0 - thickness1By2 * e + thickness2By2 * n);
                pts[5] = _hitTransformation.Transform(P1 - thickness1By2 * e + thickness2By2 * n);
                pts[6] = _hitTransformation.Transform(P0 + thickness1By2 * e + thickness2By2 * n);
                pts[7] = _hitTransformation.Transform(P1 + thickness1By2 * e + thickness2By2 * n);

                foreach (var ti in RectangleD3D.GetTriangleIndices())
                {
                    if (HitTestWithAlreadyTransformedPoints(pts[ti.Item1], pts[ti.Item2], pts[ti.Item3], out var z) && z >= 0)
                    {
                        return(true);
                    }
                }

                P0 = P1; // take previous point from current point
            }

            return(false);
        }
Пример #15
0
            public override IGripManipulationHandle[] GetGrips(int gripLevel)
            {
                if (gripLevel <= 1)
                {
                    var ls  = (LineShape)_hitobject;
                    var pts = new PointD3D[] { PointD3D.Empty, (PointD3D)ls.Size };
                    for (int i = 0; i < pts.Length; i++)
                    {
                        var pt = ls._transformation.Transform(pts[i]);
                        pt     = Transformation.Transform(pt);
                        pts[i] = pt;
                    }

                    var grips = new IGripManipulationHandle[gripLevel == 0 ? 1 : 3];

                    // Translation grips
                    var bounds         = ls.Bounds;
                    var wn             = PolylineMath3D.GetWestNorthVectors(bounds.Size);
                    var transformation = Matrix4x3.NewFromBasisVectorsAndLocation(wn.Item1, wn.Item2, bounds.Size.Normalized, PointD3D.Empty);

                    transformation.AppendTransform(ls._transformation);
                    transformation.AppendTransform(Transformation);

                    double t1            = 0.55 * ls._linePen.Thickness1;
                    double t2            = 0.55 * ls._linePen.Thickness2;
                    var    rect          = new RectangleD3D(-t1, -t2, 0, 2 * t1, 2 * t2, bounds.Size.Length);
                    var    objectOutline = new RectangularObjectOutline(rect, transformation);
                    grips[0] = new MovementGripHandle(this, objectOutline, null);

                    // PathNode grips
                    if (gripLevel == 1)
                    {
                        grips[2] = grips[0]; // put the movement grip to the background, the two NodeGrips need more priority
                        var gripRadius = Math.Max(t1, t2);
                        grips[0] = new PathNodeGripHandle(this, new VectorD3D(0, 0, 0), pts[0], gripRadius);
                        grips[1] = new PathNodeGripHandle(this, new VectorD3D(1, 1, 1), pts[1], gripRadius);
                    }
                    return(grips);
                }
                else
                {
                    return(base.GetGrips(gripLevel));
                }
            }
Пример #16
0
        /// <summary>
        /// Determines whether the specified 3D-rectangle r is hit by a ray given by the provided transformation matrix that would transform
        /// the hit ray in a ray at x=0, y=0, and z=-Infinity .. +Infinity.
        /// </summary>
        /// <param name="r">The rectangle r.</param>
        /// <param name="rayTransformation">The hit ray transformation.</param>
        /// <param name="z">If there was a hit, this is the z coordinate of the hit (otherwise, NaN is returned).</param>
        /// <returns>True if the rectangle is hit by a ray given by the provided hit ray matrix.</returns>
        public static bool IsRectangleHitByRay(RectangleD3D r, Matrix4x4 rayTransformation, out double z)
        {
            var vertices = new PointD3D[8];

            int i = 0;

            foreach (var v in r.Vertices)
            {
                vertices[i++] = rayTransformation.Transform(v);
            }

            foreach (var ti in r.TriangleIndices)
            {
                if (HitTestWithAlreadyTransformedPoints(vertices[ti.Item1], vertices[ti.Item2], vertices[ti.Item3], out z) && z >= 0)
                {
                    return(true);
                }
            }

            z = double.NaN;
            return(false);
        }
Пример #17
0
        protected void MeasureBackground(IGraphicsContext3D g, double itemSizeX, double itemSizeY, double itemSizeZ)
        {
            var fontInfo = FontManager3D.Instance.GetFontInformation(_font);

            double widthOfOne_n   = Glyph.MeasureString("n", _font).X;
            double widthOfThree_M = Glyph.MeasureString("MMM", _font).X;

            if (_background != null)
            {
                _cachedTextPadding = new Margin2D(
                    0.25 * widthOfOne_n,
                    fontInfo.cyDescent,
                    0.25 * widthOfOne_n,
                    fontInfo.cyDescent
                    );
            }
            else
            {
                _cachedTextPadding = new Margin2D(0, 0, 0, 0);
            }

            var paddedTextSize = new VectorD3D((itemSizeX + _cachedTextPadding.Left + _cachedTextPadding.Right), (itemSizeY + _cachedTextPadding.Bottom + _cachedTextPadding.Top), itemSizeZ);
            var textRectangle  = new RectangleD3D(PointD3D.Empty, paddedTextSize); // the origin of the padded text rectangle is always 0

            if (_background != null)
            {
                var backgroundRect = _background.Measure(textRectangle);
                _cachedExtendedTextBounds = backgroundRect.WithRectangleIncluded(textRectangle); //  _cachedExtendedTextBounds.WithOffset(textRectangle.X - backgroundRect.X, textRectangle.Y - backgroundRect.Y, 0);

                ((ItemLocationDirectAutoSize)_location).SetSizeInAutoSizeMode(_cachedExtendedTextBounds.Size, false);
                _cachedTextOffset = new PointD3D(textRectangle.X - backgroundRect.X + _cachedTextPadding.Left, textRectangle.Y - backgroundRect.Y + _cachedTextPadding.Bottom, 0);
            }
            else
            {
                ((ItemLocationDirectAutoSize)_location).SetSizeInAutoSizeMode(paddedTextSize, false);
                _cachedExtendedTextBounds = textRectangle;
                _cachedTextOffset         = PointD3D.Empty;
            }
        }
Пример #18
0
        public bool IsHit(LineD3D line, double thickness1, double thickness2)
        {
            if (!(line.Length > 0))
            {
                return(false);
            }

            var eastnorth = PolylineMath3D.GetWestNorthVectors(line);
            var e         = eastnorth.Item1; // east vector
            var n         = eastnorth.Item2; // north vector

            double thickness1By2 = thickness1 / 2;
            double thickness2By2 = thickness2 / 2;
            var    pts           = new PointD3D[8];

            pts[0] = _hitTransformation.Transform(line.P0 - thickness1By2 * e - thickness2By2 * n);
            pts[1] = _hitTransformation.Transform(line.P1 - thickness1By2 * e - thickness2By2 * n);
            pts[2] = _hitTransformation.Transform(line.P0 + thickness1By2 * e - thickness2By2 * n);
            pts[3] = _hitTransformation.Transform(line.P1 + thickness1By2 * e - thickness2By2 * n);
            pts[4] = _hitTransformation.Transform(line.P0 - thickness1By2 * e + thickness2By2 * n);
            pts[5] = _hitTransformation.Transform(line.P1 - thickness1By2 * e + thickness2By2 * n);
            pts[6] = _hitTransformation.Transform(line.P0 + thickness1By2 * e + thickness2By2 * n);
            pts[7] = _hitTransformation.Transform(line.P1 + thickness1By2 * e + thickness2By2 * n);

            double z;

            foreach (var ti in RectangleD3D.GetTriangleIndices())
            {
                if (HitTestWithAlreadyTransformedPoints(pts[ti.Item1], pts[ti.Item2], pts[ti.Item3], out z) && z >= 0)
                {
                    return(true);
                }
            }

            z = double.NaN;
            return(false);
        }
Пример #19
0
        public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
        {
            if (IsVisible)
            {
                var gs = g.SaveGraphicsState();
                g.TranslateTransform((VectorD3D)bounds.Center);
                var halfwidth = bounds.SizeX / 2;
                var symsize   = _symbolSize;

                if (_useSymbolGap)
                {
                    // plot a line with the length of symbolsize from
                    PaintLine(g, new PointD3D(-halfwidth, 0, 0), new PointD3D(-symsize, 0, 0));
                    PaintLine(g, new PointD3D(symsize, 0, 0), new PointD3D(halfwidth, 0, 0));
                }
                else // no gap
                {
                    PaintLine(g, new PointD3D(-halfwidth, 0, 0), new PointD3D(halfwidth, 0, 0));
                }
                g.RestoreGraphicsState(gs);
            }

            return(bounds);
        }
Пример #20
0
 /// <summary>
 /// Draws the specified background
 /// </summary>
 /// <param name="g">The drawing context.</param>
 /// <param name="itemRectangle">Position and size of the item for which this background is intended. For text, this is the position and size of the text rectangle, already with a margin around.
 /// This parameter should have the same size as was used in the previous call to <see cref="Measure(RectangleD3D)" /></param>
 /// <exception cref="NotImplementedException"></exception>
 public void Draw(IGraphicsContext3D g, RectangleD3D itemRectangle)
 {
     Draw(g, itemRectangle, _material);
 }
Пример #21
0
		public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
		{
			if (!ScatterSymbols.NoSymbol.Instance.Equals(_symbolShape))
			{
				_symbolShape.Paint(g, _material, bounds.Center, _symbolSize);
				bounds = bounds.WithPadding(0, Math.Max(0, this.SymbolSize - bounds.SizeY), Math.Max(0, this.SymbolSize - bounds.SizeZ));
			}

			return bounds;
		}
Пример #22
0
		/// <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;
		}
Пример #23
0
			public override void Draw(IGraphicsContext3D g, DrawContext dc, double xbase, double ybase, double zbase)
			{
				var mylayer = (HostLayer)dc.LinkedObject;

				var layer = mylayer as XYZPlotLayer;

				if (_layerNumber >= 0 && mylayer.SiblingLayers != null && _layerNumber < mylayer.SiblingLayers.Count)
					layer = mylayer.SiblingLayers[_layerNumber] as XYZPlotLayer;

				if (null == layer)
					return;

				if (_plotNumber < layer.PlotItems.Flattened.Length)
				{
					var fontInfo = dc.FontCache.GetFontInfo(Style.FontId);
					IGPlotItem pa = layer.PlotItems.Flattened[_plotNumber];

					PointD3D symbolpos = new PointD3D(xbase, (ybase + 0.5 * fontInfo.cyDescent - 0.5 * fontInfo.cyAscent), 0);
					RectangleD3D symbolRect = new RectangleD3D(symbolpos, new VectorD3D(SizeX, 0, 0));
					symbolRect = symbolRect.WithPadding(0, fontInfo.Size, 0);
					pa.PaintSymbol(g, symbolRect);

					if (!dc.bForPreview)
					{
						var volume = new RectangleTransformedD3D(
							new RectangleD3D(symbolpos.X, symbolpos.Y - 0.5 * fontInfo.cyLineSpace, 0, SizeX, fontInfo.cyLineSpace, 0), dc.transformMatrix);
						dc._cachedSymbolPositions.Add(volume, pa);
					}
				}
			}
Пример #24
0
		public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
		{
			// this is not a visible style, thus doing nothing
			return RectangleD3D.Empty;
		}
Пример #25
0
 public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
 {
     // this is not a visible style, thus doing nothing
     return(RectangleD3D.Empty);
 }
Пример #26
0
 /// <summary>
 /// Determines whether the specified 3D-rectangle r is hit by a ray given by x=0, y=0, z>0.
 /// </summary>
 /// <param name="r">The rectangle r.</param>
 /// <param name="z">If there was a hit, this is the z coordinate of the hit.</param>
 /// <returns>True if the rectangle is hit by a ray given by x=0, y=0, z>0.</returns>
 public bool IsHit(RectangleD3D r, out double z)
 {
     return(IsRectangleHitByRay(r, _hitTransformation, out z));
 }
Пример #27
0
        /// <summary>
        /// Gets the hit point on that plane of the active layer rectangle, that is facing the camera.
        /// </summary>
        /// <param name="doc">The graph document containing the active layer.</param>
        /// <param name="activeLayer">The active layer of the graph document.</param>
        /// <param name="hitposition">Hit point in relative screen coordinates. The z-component is the aspect ratio of the screen (y/x).</param>
        /// <param name="hitPointOnPlaneInActiveLayerCoordinates">Output: The hit point on the plane of the active layer that faces the camera. The hit point is returned in active layer coordinates.</param>
        /// <param name="rotationsRadian">The rotation angles that can be used e.g. to orient text so that the text is most readable from the current camera setting. Rotation angle around x is the x-component of the returned vector, and so on.</param>
        /// <exception cref="InvalidProgramException">There should always be a plane of a rectangle that can be hit!</exception>
        public static void GetHitPointOnActiveLayerPlaneFacingTheCamera(GraphDocument doc, HostLayer activeLayer, PointD3D hitposition, out PointD3D hitPointOnPlaneInActiveLayerCoordinates, out VectorD3D rotationsRadian)
        {
            var activeLayerTransformation = activeLayer.TransformationFromRootToHere();
            var camera  = doc.Camera;
            var hitData = new HitTestPointData(camera.GetHitRayMatrix(hitposition));

            hitData = hitData.NewFromAdditionalTransformation(activeLayerTransformation);                               // now hitdata are in layer cos

            var targetToEye = hitData.WorldTransformation.Transform(camera.TargetToEyeVectorNormalized);                // targetToEye in layer coordinates
            var upEye       = hitData.WorldTransformation.Transform(camera.UpVectorPerpendicularToEyeVectorNormalized); // camera up vector in layer coordinates

            // get the face which has the best dot product between the eye vector of the camera and the plane's normal
            var      layerRect = new RectangleD3D(PointD3D.Empty, activeLayer.Size);
            double   maxval    = double.MinValue;
            PlaneD3D maxPlane  = PlaneD3D.Empty;

            foreach (var plane in layerRect.Planes)
            {
                double val = VectorD3D.DotProduct(plane.Normal, targetToEye);
                if (val > maxval)
                {
                    maxval   = val;
                    maxPlane = plane;
                }
            }

            bool isHit = hitData.IsPlaneHitByRay(maxPlane, out hitPointOnPlaneInActiveLayerCoordinates); // hitPointOnPlane is in layer coordinates too

            if (!isHit)
            {
                throw new InvalidProgramException("There should always be a plane of a rectangle that can be hit!");
            }

            VectorD3D zaxis = maxPlane.Normal;
            VectorD3D yaxis = upEye;

            // Find y axis perpendicular to zaxis
            maxval = double.MinValue;
            foreach (var plane in layerRect.Planes)
            {
                double val = VectorD3D.DotProduct(plane.Normal, upEye);
                if (val > maxval && 0 == VectorD3D.DotProduct(plane.Normal, zaxis))
                {
                    maxval = val;
                    yaxis  = plane.Normal;
                }
            }
            var xaxis = VectorD3D.CrossProduct(yaxis, zaxis);

            // now we have all information about the spatial position and orientation of the text:
            // hitPointOnPlane is the position of the text
            // maxPlane.Normal is the face orientation of the text
            // maxUpVector is the up orientation of the text

            double cx, sx, cy, sy, cz, sz;

            sy = xaxis.Z;
            if (1 != Math.Abs(sy))
            {
                cy = Math.Sqrt(1 - sy * sy);
                cz = xaxis.X / cy;
                sz = xaxis.Y / cy;
                sx = yaxis.Z / cy;
                cx = zaxis.Z / cy;
            }
            else // sy is +1, thus cy is zero
            {
                // we set x-rotation to zero, i.e. cx==1 and sx==0
                cy = 0;
                cx = 1;
                sx = 0;
                cz = yaxis.Y;
                sz = -yaxis.X;
            }

            rotationsRadian = new VectorD3D(Math.Atan2(sx, cx), Math.Atan2(sy, cy), Math.Atan2(sz, cz));
        }
Пример #28
0
 public RectangleD3D GetBounds()
 {
     return(RectangleD3D.NewRectangleIncludingAllPoints(AsPoints()));
 }
Пример #29
0
 public RectangularObjectOutline(RectangleD3D rectangle, Matrix4x3 transformation)
 {
     _rectangle      = rectangle;
     _transformation = transformation;
 }
Пример #30
0
		public override void PaintSymbol(IGraphicsContext3D g, RectangleD3D location)
		{
			_plotStyles.PaintSymbol(g, location);
		}
Пример #31
0
 public RectangleD3D GetBounds(Matrix3x3 transformation)
 {
     return(RectangleD3D.NewRectangleIncludingAllPoints(AsPoints().Select(p => transformation.Transform(p))));
 }
Пример #32
0
        /// <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;
        }
Пример #33
0
 /// <summary>
 /// Determines whether the specified 3D-rectangle r is hit by a ray given by x=0, y=0, z>0.
 /// </summary>
 /// <param name="r">The rectangle r.</param>
 /// <param name="rectangleToWorldTransformation">An additional transformation that transformes the given rectangle into the same coordinates as the hit data.</param>
 /// <param name="z">If there was a hit, this is the z coordinate of the hit.</param>
 /// <returns>True if the rectangle is hit by a ray given by x=0, y=0, z>0.</returns>
 public bool IsHit(RectangleD3D r, Matrix4x3 rectangleToWorldTransformation, out double z)
 {
     return(IsRectangleHitByRay(r, _hitTransformation.WithPrependedTransformation(rectangleToWorldTransformation), out z));
 }
Пример #34
0
		public RectangleD3D AdjustRectangle(RectangleD3D r, Alignment alignmentX, Alignment alignmentY, Alignment alignmentZ)
		{
			double rX = r.X;
			double rY = r.Y;
			double rZ = r.Z;

			switch (alignmentZ)
			{
				case Alignment.Near:
					break;

				case Alignment.Center:
					rZ -= 0.5 * r.SizeZ;
					break;

				case Alignment.Far:
					rZ -= r.SizeZ;
					break;
			}
			switch (alignmentY)
			{
				case Alignment.Near:
					break;

				case Alignment.Center:
					rY -= 0.5 * r.SizeY;
					break;

				case Alignment.Far:
					rY -= r.SizeY;
					break;
			}
			switch (alignmentX)
			{
				case Alignment.Near:
					break;

				case Alignment.Center:
					rX -= 0.5 * r.SizeX;
					break;

				case Alignment.Far:
					rX -= r.SizeX;
					break;
			}

			return new RectangleD3D(rX, rY, rZ, r.SizeX, r.SizeY, r.SizeZ);
		}
Пример #35
0
 /// <summary>
 /// Paints a appropriate symbol in the given rectangle. The width of the rectangle is mandatory, but if the heigth is too small,
 /// you should extend the bounding rectangle and set it as return value of this function.
 /// </summary>
 /// <param name="g">The graphics context.</param>
 /// <param name="bounds">The bounds, in which the symbol should be painted.</param>
 /// <returns>If the height of the bounding rectangle is sufficient for painting, returns the original bounding rectangle. Otherwise, it returns a rectangle that is
 /// inflated in y-Direction. Do not inflate the rectangle in x-direction!</returns>
 public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
 {
     return(RectangleD3D.Empty);
 }
Пример #36
0
 /// <summary>
 /// Paints a symbol for this plot item for use in a legend.
 /// </summary>
 /// <param name="g">The graphics context.</param>
 /// <param name="location">The rectangle where the symbol should be painted into.</param>
 public virtual void PaintSymbol(IGraphicsContext3D g, RectangleD3D location)
 {
 }
Пример #37
0
		public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
		{
			return RectangleD3D.Empty;
		}
Пример #38
0
		public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
		{
			bounds = bounds.WithPadding(0, 0, -bounds.SizeZ / 4);
			var heightBy2 = new VectorD3D(0, 0, bounds.SizeZ / 4);

			g.DrawLine(_pen, bounds.Center - heightBy2, bounds.Center + heightBy2);

			return bounds;
		}
Пример #39
0
		public RectangleD3D PaintSymbol(IGraphicsContext3D g, RectangleD3D bounds)
		{
			if (IsVisible)
			{
				var gs = g.SaveGraphicsState();
				g.TranslateTransform((VectorD3D)bounds.Center);
				var halfwidth = bounds.SizeX / 2;
				var symsize = _symbolSize;

				if (_useSymbolGap)
				{
					// plot a line with the length of symbolsize from
					PaintLine(g, new PointD3D(-halfwidth, 0, 0), new PointD3D(-symsize, 0, 0));
					PaintLine(g, new PointD3D(symsize, 0, 0), new PointD3D(halfwidth, 0, 0));
				}
				else // no gap
				{
					PaintLine(g, new PointD3D(-halfwidth, 0, 0), new PointD3D(halfwidth, 0, 0));
				}
				g.RestoreGraphicsState(gs);
			}

			return bounds;
		}