Example #1
0
        public static ImageSource GetImage(ILineCap join, bool isForEndCap)
        {
            const int    bmpHeight = 24;
            const int    bmpWidth  = 48;
            const double lineWidth = bmpHeight * 0.4;

            if (null == _interopBitmap)
            {
                _interopBitmap = new GdiToWpfBitmap(bmpWidth, bmpHeight);
            }

            using (var grfx = _interopBitmap.BeginGdiPainting())
            {
                grfx.CompositingMode = sdd.CompositingMode.SourceCopy;
                grfx.FillRectangle(System.Drawing.Brushes.Transparent, 0, 0, bmpWidth, bmpHeight);

                var linePen = new System.Drawing.Pen(System.Drawing.Brushes.Black, (float)Math.Ceiling(lineWidth));
                if (isForEndCap)
                {
                    //join.SetEndCap(linePen);
                    //grfx.DrawLine(linePen, 0, 0.5f * bmpHeight, bmpWidth * (1 - 0.25f), 0.5f * bmpHeight);
                }
                else
                {
                    //join.SetStartCap(linePen);
                    //grfx.DrawLine(linePen, 0.25f * bmpWidth, 0.5f * bmpHeight, bmpWidth, 0.5f * bmpHeight);
                }
                _interopBitmap.EndGdiPainting();
            }

            var img = new WriteableBitmap(_interopBitmap.WpfBitmap);

            img.Freeze();
            return(img);
        }
Example #2
0
            protected virtual PenX3D SDeserialize(object o, Altaxo.Serialization.Xml.IXmlDeserializationInfo info, object parent)
            {
                var material     = (IMaterial)info.GetValue("Material", null);
                var crossSection = (ICrossSectionOfLine)info.GetValue("CrossSection", null);

                var    lineJoin   = (PenLineJoin)info.GetEnum("LineJoin", typeof(PenLineJoin));
                double miterLimit = info.GetDouble("MiterLimit");

                var lineStartCap = ("LineStartCap" == info.CurrentElementName) ? (ILineCap)info.GetValue("LineStartCap", null) : null;
                var lineEndCap   = ("LineEndCap" == info.CurrentElementName) ? (ILineCap)info.GetValue("LineEndCap", null) : null;
                var dashPattern  = ("DashPattern" == info.CurrentElementName) ? (IDashPattern)info.GetValue("DashPattern", null) : null;

                dashPattern = dashPattern ?? DashPatterns.Solid.Instance;
                ILineCap dashStartCap = null, dashEndCap = null;
                bool     dashStartCapSuppression = false, dashEndCapSuppression = false;

                if (!DashPatterns.Solid.Instance.Equals(dashPattern))
                {
                    if ("DashStartCap" == info.CurrentElementName)
                    {
                        dashStartCap            = (ILineCap)info.GetValue("DashStartCap", null);
                        dashStartCapSuppression = info.GetBoolean("DashStartCapSuppression");
                    }

                    if ("DashEndCap" == info.CurrentElementName)
                    {
                        dashEndCap            = (ILineCap)info.GetValue("DashEndCap", null);
                        dashEndCapSuppression = info.GetBoolean("DashEndCapSuppression");
                    }
                }

                return(new PenX3D(material, crossSection, lineJoin, miterLimit, lineStartCap, lineEndCap, dashPattern, dashStartCap, dashStartCapSuppression, dashEndCap, dashEndCapSuppression));
            }
Example #3
0
        public PenX3D(
            IMaterial material,
            ICrossSectionOfLine crossSection,
            PenLineJoin lineJoin,
            double miterLimit,
            ILineCap lineStartCap, ILineCap lineEndCap, IDashPattern dashPattern, ILineCap dashStartCap, bool dashStartCapSuppressionIfSpaceInsufficient, ILineCap dashEndCap, bool dashEndCapSuppressionIfSpaceInsufficient)
        {
            if (!(miterLimit >= 1))
            {
                throw new ArgumentOutOfRangeException(nameof(miterLimit), "must be >= 1");
            }
            if (null == dashPattern)
            {
                throw new ArgumentNullException(nameof(dashPattern));
            }

            _material     = material;
            _crossSection = crossSection;
            _lineJoin     = lineJoin;
            _miterLimit   = miterLimit;
            _lineStartCap = lineStartCap;
            _lineEndCap   = lineEndCap;
            _dashPattern  = dashPattern;
            _dashStartCap = dashStartCap;
            _dashStartCapSuppressionIfSpaceInsufficient = dashStartCapSuppressionIfSpaceInsufficient;
            _dashEndCap = dashEndCap;
            _dashEndCapSuppressionIfSpaceInsufficient = dashEndCapSuppressionIfSpaceInsufficient;
        }
Example #4
0
        public void Initialize(
            ICrossSectionOfLine crossSection,
            double thickness1,
            double thickness2,
            ILineCap startCap,
            ILineCap endCap,
            VectorD3D westVector,
            VectorD3D northVector,
            LineD3D line)
        {
            _crossSection                  = crossSection;
            _crossSectionVertexCount       = crossSection.NumberOfVertices;
            _crossSectionNormalCount       = crossSection.NumberOfNormals;
            _dashStartCap                  = startCap;
            _dashStartCapBaseInsetAbsolute = null == _dashStartCap ? 0 : _dashStartCap.GetAbsoluteBaseInset(thickness1, thickness2);
            _dashEndCap = endCap;
            _dashEndCapBaseInsetAbsolute = null == _dashEndCap ? 0 : _dashEndCap.GetAbsoluteBaseInset(thickness1, thickness2);
            _westVector                    = westVector;
            _northVector                   = northVector;
            _forwardVector                 = line.LineVectorNormalized;
            _lastNormalsTransformed        = new VectorD3D[_crossSectionNormalCount];
            _lastPositionsTransformedStart = new PointD3D[_crossSectionVertexCount];
            _lastPositionsTransformedEnd   = new PointD3D[_crossSectionVertexCount];

            // Get the matrix for the start plane
            var matrix = Math3D.Get2DProjectionToPlane(westVector, northVector, PointD3D.Empty);

            // note: for a single line segment, the normals need to be calculated only once

            for (int i = 0; i < _lastNormalsTransformed.Length; ++i)
            {
                _lastNormalsTransformed[i] = matrix.Transform(crossSection.Normals(i));
            }
        }
Example #5
0
        public PenX3D WithDashEndCap(ILineCap cap)
        {
            if (cap is LineCaps.Flat)
            {
                cap = null;
            }

            if (object.Equals(_dashEndCap, cap))
            {
                return(this);
            }

            var result = (PenX3D)MemberwiseClone();

            result._dashEndCap = cap;
            return(result);
        }
Example #6
0
        public void AddGeometry(
            Action <PointD3D, VectorD3D> AddPositionAndNormal,
            Action <int, int, int, bool> AddIndices,
            ref int vertexIndexOffset,
            LineD3D dashSegment,
            ILineCap overrideStartCap,
            ILineCap overrideEndCap)
        {
            if (null == _lastNormalsTransformed)
            {
                throw new InvalidProgramException("The structure is not initialized yet. Call Initialize before using it!");
            }

            PointD3D lineStart = dashSegment.P0;
            PointD3D lineEnd   = dashSegment.P1;

            var    lineVector = dashSegment.LineVector;
            double lineLength = lineVector.Length;

            if (null != _dashStartCap && null == overrideStartCap)
            {
                if (_dashStartCapBaseInsetAbsolute < 0)
                {
                    lineStart  += -_dashStartCapBaseInsetAbsolute * _forwardVector;
                    lineLength += _dashStartCapBaseInsetAbsolute;
                }
            }

            if (null != _dashEndCap && null == overrideEndCap)
            {
                if (_dashEndCapBaseInsetAbsolute < 0)
                {
                    lineEnd    += _dashEndCapBaseInsetAbsolute * _forwardVector;
                    lineLength += _dashEndCapBaseInsetAbsolute;
                }
            }

            AddGeometry(AddPositionAndNormal,
                        AddIndices,
                        ref vertexIndexOffset,
                        lineStart,
                        lineEnd,
                        lineLength > 0,
                        overrideStartCap,
                        overrideEndCap);
        }
Example #7
0
		public static ImageSource GetImage(ILineCap join, bool isForEndCap)
		{
			const int bmpHeight = 24;
			const int bmpWidth = 48;
			const double lineWidth = bmpHeight * 0.4;

			if (null == _interopBitmap)
				_interopBitmap = new GdiToWpfBitmap(bmpWidth, bmpHeight);

			using (var grfx = _interopBitmap.BeginGdiPainting())
			{
				grfx.CompositingMode = sdd.CompositingMode.SourceCopy;
				grfx.FillRectangle(System.Drawing.Brushes.Transparent, 0, 0, bmpWidth, bmpHeight);

				var linePen = new System.Drawing.Pen(System.Drawing.Brushes.Black, (float)Math.Ceiling(lineWidth));
				if (isForEndCap)
				{
					//join.SetEndCap(linePen);
					//grfx.DrawLine(linePen, 0, 0.5f * bmpHeight, bmpWidth * (1 - 0.25f), 0.5f * bmpHeight);
				}
				else
				{
					//join.SetStartCap(linePen);
					//grfx.DrawLine(linePen, 0.25f * bmpWidth, 0.5f * bmpHeight, bmpWidth, 0.5f * bmpHeight);
				}
				_interopBitmap.EndGdiPainting();
			}

			var img = new WriteableBitmap(_interopBitmap.WpfBitmap);
			img.Freeze();
			return img;
		}
		/// <summary>
		/// Adds the triangle geometry. Here, the position of the startcap base and of the endcap base is already calculated and provided in the arguments.
		/// </summary>
		/// <param name="AddPositionAndNormal">The procedure to add a vertex position and normal.</param>
		/// <param name="AddIndices">The procedure to add vertex indices for one triangle.</param>
		/// <param name="vertexIndexOffset">The vertex index offset.</param>
		/// <param name="polylinePoints">The points of the polyline to draw. This is not the original polyline segment, but the polyline segment shortened to account for the start and end cap.</param>
		/// <param name="drawLine">If this parameter is true, the line segment between lineStart and lineEnd is drawn. If false, the line segment itself is not drawn, but the start end end caps are drawn.</param>
		/// <param name="overrideStartCap">If not null, this parameter override the start cap that is stored in this class.</param>
		/// <param name="overrideEndCap">If not null, this parameter overrides the end cap that is stored in this class.</param>
		/// <exception cref="System.InvalidProgramException">The structure is not initialized yet. Call Initialize before using it!</exception>
		public void AddGeometry(
			Action<PointD3D, VectorD3D> AddPositionAndNormal,
			Action<int, int, int, bool> AddIndices,
			ref int vertexIndexOffset,
			IEnumerable<PolylinePointD3D> polylinePoints,
			bool drawLine,
			ILineCap overrideStartCap,
			ILineCap overrideEndCap
			)
		{
			if (null == _normalsTransformedCurrent)
				throw new InvalidProgramException("The structure is not initialized yet. Call Initialize before using it!");

			var resultingStartCap = overrideStartCap ?? _dashStartCap;
			var resultingEndCap = overrideEndCap ?? _dashEndCap;

			// draw the straight line if the remaining line length is >0
			if (drawLine)
			{
				AddGeometryForLineOnly(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, polylinePoints);
			}

			// now the start cap
			if (null != resultingStartCap)
			{
				resultingStartCap.AddGeometry(
					AddPositionAndNormal,
					AddIndices,
					ref vertexIndexOffset,
					true,
					_startCapCOS.Position,
					_startCapCOS.WestVector,
					_startCapCOS.NorthVector,
					_startCapCOS.ForwardVector,
					_crossSection,
					null,
					null,
					ref _startCapTemporaryStorageSpace);
			}
			else if (drawLine)
			{
				/*
				LineCaps.Flat.AddGeometry(
					AddPositionAndNormal,
					AddIndices,
					ref vertexIndexOffset,
					true,
					_startCapBase,
					_startCapForwardVector,
					null
					);
				*/

				LineCaps.Flat.Instance.AddGeometry(
				AddPositionAndNormal,
				AddIndices,
				ref vertexIndexOffset,
				true,
				_startCapCOS.Position,
				_startCapCOS.WestVector,
				_startCapCOS.NorthVector,
				_startCapCOS.ForwardVector,
				_crossSection,
				null,
				null,
				ref _startCapTemporaryStorageSpace);
			}

			if (null != resultingEndCap)
			{
				resultingEndCap.AddGeometry(
				AddPositionAndNormal,
					AddIndices,
					ref vertexIndexOffset,
					false,
					_endCapCOS.Position,
					_endCapCOS.WestVector,
					_endCapCOS.NorthVector,
					_endCapCOS.ForwardVector,
					_crossSection,
					null,
					null,
					ref _endCapTemporaryStorageSpace);
			}
			else if (drawLine)
			{
				/*
				LineCaps.Flat.AddGeometry(
					AddPositionAndNormal,
					AddIndices,
					ref vertexIndexOffset,
					false,
					_endCapBase,
					_endCapForwardVector,
					null
					);
				*/

				LineCaps.Flat.Instance.AddGeometry(
					AddPositionAndNormal,
					AddIndices,
					ref vertexIndexOffset,
					false,
					_endCapCOS.Position,
					_endCapCOS.WestVector,
					_endCapCOS.NorthVector,
					_endCapCOS.ForwardVector,
					_crossSection,
					null,
					null,
					ref _endCapTemporaryStorageSpace);
			}
		}
		/// <summary>
		/// Adds the triangle geometry for a polyline segment with start and end cap.
		/// </summary>
		/// <param name="AddPositionAndNormal">The procedure to add a vertex position and normal.</param>
		/// <param name="AddIndices">The procedure to add vertex indices for one triangle.</param>
		/// <param name="vertexIndexOffset">The vertex index offset.</param>
		/// <param name="polylinePoints">The points of the original polyline to draw (not shortened to account for start and end cap).</param>
		/// <param name="westVector">West vector at the start of the original polyline.</param>
		/// <param name="northVector">North vector at the start of the original polyline.</param>
		/// <param name="forwardVector">Forward vector at the start of the original polyline.</param>
		/// <param name="overrideStartCap">If not null, this parameter override the start cap that is stored in this class.</param>
		/// <param name="overrideEndCap">If not null, this parameter overrides the end cap that is stored in this class.</param>
		public void AddGeometry(
		Action<PointD3D, VectorD3D> AddPositionAndNormal,
		Action<int, int, int, bool> AddIndices,
		ref int vertexIndexOffset,
		IList<PointD3D> polylinePoints,
		VectorD3D westVector,
		VectorD3D northVector,
		VectorD3D forwardVector,
		ILineCap overrideStartCap,
		ILineCap overrideEndCap)
		{
			if (null == _normalsTransformedCurrent)
				throw new InvalidProgramException("The structure is not initialized yet. Call Initialize before using it!");

			_polylineIndexAtStartCapBase = 0;
			_startCapForwardAndPositionProvided = false;
			_startCapNeedsJoiningSegment = false;

			_polylineIndexAtEndCapBase = polylinePoints.Count - 1;
			_endCapForwardAndPositionProvided = false;
			_endCapNeedsJoiningSegment = false;

			if (null != _dashStartCap && null == overrideStartCap)
			{
				if (_dashStartCapBaseInsetAbsolute < 0)
				{
					_polylineIndexAtStartCapBase = PolylineMath3D.GetFractionalStartIndexOfPolylineWithCapInsetAbsolute(
						polylinePoints,
						-_dashStartCapBaseInsetAbsolute,
						out _startCapForwardAndPositionProvided,
						out _startCapNeedsJoiningSegment,
						_startCapCOS);
				}
			}

			if (null != _dashEndCap && null == overrideEndCap)
			{
				if (_dashEndCapBaseInsetAbsolute < 0)
				{
					_polylineIndexAtEndCapBase = PolylineMath3D.GetFractionalEndIndexOfPolylineWithCapInsetAbsolute(
						polylinePoints,
						-_dashEndCapBaseInsetAbsolute,
						out _endCapForwardAndPositionProvided,
						out _endCapNeedsJoiningSegment,
						_endCapCOS);
				}
			}

			bool isLineDrawn = _polylineIndexAtEndCapBase > _polylineIndexAtStartCapBase && !double.IsNaN(_polylineIndexAtStartCapBase) && !double.IsNaN(_polylineIndexAtEndCapBase);

			if (!isLineDrawn) // if no line is drawn, then we must provide the start cap and end cap at least with the west and north vectors
			{
				_startCapCOS.WestVector = westVector;
				_startCapCOS.NorthVector = northVector;
				PolylineMath3D.GetWestAndNorthVectorsForNextSegment(_startCapCOS.ForwardVector, forwardVector, ref _startCapCOS.WestVector, ref _startCapCOS.NorthVector);

				_endCapCOS.WestVector = _startCapCOS.WestVector;
				_endCapCOS.NorthVector = _startCapCOS.NorthVector;
				PolylineMath3D.GetWestAndNorthVectorsForNextSegment(_endCapCOS.ForwardVector, _startCapCOS.ForwardVector, ref _endCapCOS.WestVector, ref _endCapCOS.NorthVector);
			}

			AddGeometry(AddPositionAndNormal,
				AddIndices,
				ref vertexIndexOffset,
				isLineDrawn ? PolylineMath3D.GetPolylineWithFractionalStartAndEndIndex(polylinePoints, westVector, northVector, forwardVector, _polylineIndexAtStartCapBase, _polylineIndexAtEndCapBase, _startCapForwardAndPositionProvided, _startCapNeedsJoiningSegment, _startCapCOS, _endCapForwardAndPositionProvided, _endCapNeedsJoiningSegment, _endCapCOS) : PolylineMath3D.GetEmptyPolyline(),
				isLineDrawn,
				overrideStartCap,
				overrideEndCap);
		}
Example #10
0
		/// <summary>
		/// Initialization that is needed only once per straigth line (not once per dash).
		/// </summary>
		/// <param name="crossSection">The cross section of the pen that is used to draw the line.</param>
		/// <param name="thickness1">Thickness1 of the pen.</param>
		/// <param name="thickness2">Thickness2 of the pen.</param>
		/// <param name="lineJoin">The LineJoin property of the pen.</param>
		/// <param name="miterLimit">The MiterLimit property of the pen.</param>
		/// <param name="startCap">The start cap to be used for this polyline segment.</param>
		/// <param name="endCap">The end cap to be used for this polyline segment.</param>
		public void Initialize(
		ICrossSectionOfLine crossSection,
		double thickness1,
		double thickness2,
		PenLineJoin lineJoin,
		double miterLimit,
		ILineCap startCap,
		ILineCap endCap)
		{
			this._crossSection = crossSection;
			this._crossSectionVertexCount = crossSection.NumberOfVertices;
			this._crossSectionNormalCount = crossSection.NumberOfNormals;
			this._crossSectionMaximalDistanceFromCenter = _crossSection.GetMaximalDistanceFromCenter();
			this._crossSectionPartsTriangleIndices = new Dictionary<Tuple<int, int>, int[]>();
			this._lineJoin = lineJoin;
			this._miterLimit = miterLimit;
			this._miterLimitDotThreshold = Math.Cos(Math.PI - 2 * Math.Asin(1 / miterLimit));

			this._dashStartCap = startCap;
			this._dashStartCapBaseInsetAbsolute = null == _dashStartCap ? 0 : _dashStartCap.GetAbsoluteBaseInset(thickness1, thickness2);
			this._dashEndCap = endCap;
			this._dashEndCapBaseInsetAbsolute = null == _dashEndCap ? 0 : _dashEndCap.GetAbsoluteBaseInset(thickness1, thickness2);

			_positionsTransformedStartCurrent = new PointD3D[_crossSectionVertexCount];
			_positionsTransformedEndCurrent = new PointD3D[_crossSectionVertexCount];
			_positionsTransformedStartNext = new PointD3D[_crossSectionVertexCount];
			_normalsTransformedCurrent = new VectorD3D[_crossSectionNormalCount];
			_normalsTransformedNext = new VectorD3D[_crossSectionNormalCount];
			_crossSectionRotatedVertices = new VectorD2D[_crossSectionVertexCount];
			_startCapCOS = new PolylinePointD3DAsClass();
			_endCapCOS = new PolylinePointD3DAsClass();
		}
		public void Initialize(
		ICrossSectionOfLine crossSection,
		double thickness1,
		double thickness2,
		ILineCap startCap,
		ILineCap endCap,
		VectorD3D westVector,
		VectorD3D northVector,
		LineD3D line)
		{
			this._crossSection = crossSection;
			this._crossSectionVertexCount = crossSection.NumberOfVertices;
			this._crossSectionNormalCount = crossSection.NumberOfNormals;
			this._dashStartCap = startCap;
			this._dashStartCapBaseInsetAbsolute = null == _dashStartCap ? 0 : _dashStartCap.GetAbsoluteBaseInset(thickness1, thickness2);
			this._dashEndCap = endCap;
			this._dashEndCapBaseInsetAbsolute = null == _dashEndCap ? 0 : _dashEndCap.GetAbsoluteBaseInset(thickness1, thickness2);
			this._westVector = westVector;
			this._northVector = northVector;
			this._forwardVector = line.LineVectorNormalized;
			this._lastNormalsTransformed = new VectorD3D[_crossSectionNormalCount];
			this._lastPositionsTransformedStart = new PointD3D[_crossSectionVertexCount];
			this._lastPositionsTransformedEnd = new PointD3D[_crossSectionVertexCount];

			// Get the matrix for the start plane
			var matrix = Math3D.Get2DProjectionToPlane(westVector, northVector, PointD3D.Empty);

			// note: for a single line segment, the normals need to be calculated only once

			for (int i = 0; i < _lastNormalsTransformed.Length; ++i)
			{
				_lastNormalsTransformed[i] = matrix.Transform(crossSection.Normals(i));
			}
		}
		/// <summary>
		/// Adds the triangle geometry. Here, the position of the startcap base and of the endcap base is already calculated and provided in the arguments.
		/// </summary>
		/// <param name="AddPositionAndNormal">The procedure to add a vertex position and normal.</param>
		/// <param name="AddIndices">The procedure to add vertex indices for one triangle.</param>
		/// <param name="vertexIndexOffset">The vertex index offset.</param>
		/// <param name="lineStart">The line start. This is the precalculated base of the start line cap.</param>
		/// <param name="lineEnd">The line end. Here, this is the precalculated base of the end line cap.</param>
		/// <param name="drawLine">If this parameter is true, the line segment between lineStart and lineEnd is drawn. If false, the line segment itself is not drawn, but the start end end caps are drawn.</param>
		/// <param name="overrideStartCap">If not null, this parameter override the start cap that is stored in this class.</param>
		/// <param name="overrideEndCap">If not null, this parameter overrides the end cap that is stored in this class.</param>
		/// <exception cref="System.InvalidProgramException">The structure is not initialized yet. Call Initialize before using it!</exception>
		public void AddGeometry(
			Action<PointD3D, VectorD3D> AddPositionAndNormal,
			Action<int, int, int, bool> AddIndices,
			ref int vertexIndexOffset,
			PointD3D lineStart,
			PointD3D lineEnd,
			bool drawLine,
			ILineCap overrideStartCap,
			ILineCap overrideEndCap
			)
		{
			if (null == _lastNormalsTransformed)
				throw new InvalidProgramException("The structure is not initialized yet. Call Initialize before using it!");

			var resultingStartCap = overrideStartCap ?? _dashStartCap;
			var resultingEndCap = overrideEndCap ?? _dashEndCap;

			// draw the straight line if the remaining line length is >0
			if (drawLine)
			{
				// Get the matrix for the start plane
				var matrix = Math3D.Get2DProjectionToPlane(_westVector, _northVector, lineStart);
				for (int i = 0; i < _crossSectionVertexCount; ++i)
					_lastPositionsTransformedStart[i] = matrix.Transform(_crossSection.Vertices(i));

				matrix = Math3D.Get2DProjectionToPlane(_westVector, _northVector, lineEnd);
				for (int i = 0; i < _crossSectionVertexCount; ++i)
					_lastPositionsTransformedEnd[i] = matrix.Transform(_crossSection.Vertices(i));

				// draw the line segment now
				var currIndex = vertexIndexOffset;
				for (int i = 0, j = 0; i < _crossSectionVertexCount; ++i, ++j)
				{
					if (j == 0)
					{
						AddIndices(currIndex, currIndex + 1, currIndex + 2 * _crossSectionNormalCount - 2, false);
						AddIndices(currIndex + 2 * _crossSectionNormalCount - 2, currIndex + 1, currIndex + 2 * _crossSectionNormalCount - 1, false);
					}
					else
					{
						AddIndices(currIndex, currIndex + 1, currIndex - 2, false);
						AddIndices(currIndex - 2, currIndex + 1, currIndex - 1, false);
					}

					AddPositionAndNormal(_lastPositionsTransformedStart[i], _lastNormalsTransformed[j]);
					AddPositionAndNormal(_lastPositionsTransformedEnd[i], _lastNormalsTransformed[j]);
					currIndex += 2;

					if (_crossSection.IsVertexSharp(i))
					{
						++j;
						AddPositionAndNormal(_lastPositionsTransformedStart[i], _lastNormalsTransformed[j]);
						AddPositionAndNormal(_lastPositionsTransformedEnd[i], _lastNormalsTransformed[j]);
						currIndex += 2;
					}
				}
				vertexIndexOffset = currIndex;
			}

			// now the start cap
			if (null != resultingStartCap)
			{
				resultingStartCap.AddGeometry(
					AddPositionAndNormal,
					AddIndices,
					ref vertexIndexOffset,
					true,
					lineStart,
					_westVector,
					_northVector,
					_forwardVector,
					_crossSection,
					drawLine ? _lastPositionsTransformedStart : null,
					_lastNormalsTransformed,
					ref _startCapTemporaryStorageSpace);
			}
			else if (drawLine)
			{
				LineCaps.Flat.AddGeometry(
					AddPositionAndNormal,
					AddIndices,
					ref vertexIndexOffset,
					true,
					lineStart,
					_forwardVector,
					_lastPositionsTransformedStart
					);
			}

			if (null != resultingEndCap)
			{
				resultingEndCap.AddGeometry(
				AddPositionAndNormal,
					AddIndices,
					ref vertexIndexOffset,
					false,
					lineEnd,
					_westVector,
					_northVector,
					_forwardVector,
					_crossSection,
					drawLine ? _lastPositionsTransformedEnd : null,
					_lastNormalsTransformed,
					ref _endCapTemporaryStorageSpace);
			}
			else if (drawLine)
			{
				LineCaps.Flat.AddGeometry(
					AddPositionAndNormal,
					AddIndices,
					ref vertexIndexOffset,
					false,
					lineEnd,
					_forwardVector,
					_lastPositionsTransformedEnd
					);
			}
		}
		public void AddGeometry(
		Action<PointD3D, VectorD3D> AddPositionAndNormal,
		Action<int, int, int, bool> AddIndices,
		ref int vertexIndexOffset,
		LineD3D dashSegment,
			ILineCap overrideStartCap,
			ILineCap overrideEndCap)
		{
			if (null == _lastNormalsTransformed)
				throw new InvalidProgramException("The structure is not initialized yet. Call Initialize before using it!");

			PointD3D lineStart = dashSegment.P0;
			PointD3D lineEnd = dashSegment.P1;

			var lineVector = dashSegment.LineVector;
			double lineLength = lineVector.Length;

			if (null != _dashStartCap && null == overrideStartCap)
			{
				if (_dashStartCapBaseInsetAbsolute < 0)
				{
					lineStart += -_dashStartCapBaseInsetAbsolute * _forwardVector;
					lineLength += _dashStartCapBaseInsetAbsolute;
				}
			}

			if (null != _dashEndCap && null == overrideEndCap)
			{
				if (_dashEndCapBaseInsetAbsolute < 0)
				{
					lineEnd += _dashEndCapBaseInsetAbsolute * _forwardVector;
					lineLength += _dashEndCapBaseInsetAbsolute;
				}
			}

			AddGeometry(AddPositionAndNormal,
				AddIndices,
				ref vertexIndexOffset,
				lineStart,
				lineEnd,
				lineLength > 0,
				overrideStartCap,
				overrideEndCap);
		}
Example #14
0
        /// <summary>
        /// Adds the triangle geometry. Here, the position of the startcap base and of the endcap base is already calculated and provided in the arguments.
        /// </summary>
        /// <param name="AddPositionAndNormal">The procedure to add a vertex position and normal.</param>
        /// <param name="AddIndices">The procedure to add vertex indices for one triangle.</param>
        /// <param name="vertexIndexOffset">The vertex index offset.</param>
        /// <param name="lineStart">The line start. This is the precalculated base of the start line cap.</param>
        /// <param name="lineEnd">The line end. Here, this is the precalculated base of the end line cap.</param>
        /// <param name="drawLine">If this parameter is true, the line segment between lineStart and lineEnd is drawn. If false, the line segment itself is not drawn, but the start end end caps are drawn.</param>
        /// <param name="overrideStartCap">If not null, this parameter override the start cap that is stored in this class.</param>
        /// <param name="overrideEndCap">If not null, this parameter overrides the end cap that is stored in this class.</param>
        /// <exception cref="System.InvalidProgramException">The structure is not initialized yet. Call Initialize before using it!</exception>
        public void AddGeometry(
            Action <PointD3D, VectorD3D> AddPositionAndNormal,
            Action <int, int, int, bool> AddIndices,
            ref int vertexIndexOffset,
            PointD3D lineStart,
            PointD3D lineEnd,
            bool drawLine,
            ILineCap overrideStartCap,
            ILineCap overrideEndCap
            )
        {
            if (null == _lastNormalsTransformed)
            {
                throw new InvalidProgramException("The structure is not initialized yet. Call Initialize before using it!");
            }

            var resultingStartCap = overrideStartCap ?? _dashStartCap;
            var resultingEndCap   = overrideEndCap ?? _dashEndCap;

            // draw the straight line if the remaining line length is >0
            if (drawLine)
            {
                // Get the matrix for the start plane
                var matrix = Math3D.Get2DProjectionToPlane(_westVector, _northVector, lineStart);
                for (int i = 0; i < _crossSectionVertexCount; ++i)
                {
                    _lastPositionsTransformedStart[i] = matrix.Transform(_crossSection.Vertices(i));
                }

                matrix = Math3D.Get2DProjectionToPlane(_westVector, _northVector, lineEnd);
                for (int i = 0; i < _crossSectionVertexCount; ++i)
                {
                    _lastPositionsTransformedEnd[i] = matrix.Transform(_crossSection.Vertices(i));
                }

                // draw the line segment now
                var currIndex = vertexIndexOffset;
                for (int i = 0, j = 0; i < _crossSectionVertexCount; ++i, ++j)
                {
                    if (j == 0)
                    {
                        AddIndices(currIndex, currIndex + 1, currIndex + 2 * _crossSectionNormalCount - 2, false);
                        AddIndices(currIndex + 2 * _crossSectionNormalCount - 2, currIndex + 1, currIndex + 2 * _crossSectionNormalCount - 1, false);
                    }
                    else
                    {
                        AddIndices(currIndex, currIndex + 1, currIndex - 2, false);
                        AddIndices(currIndex - 2, currIndex + 1, currIndex - 1, false);
                    }

                    AddPositionAndNormal(_lastPositionsTransformedStart[i], _lastNormalsTransformed[j]);
                    AddPositionAndNormal(_lastPositionsTransformedEnd[i], _lastNormalsTransformed[j]);
                    currIndex += 2;

                    if (_crossSection.IsVertexSharp(i))
                    {
                        ++j;
                        AddPositionAndNormal(_lastPositionsTransformedStart[i], _lastNormalsTransformed[j]);
                        AddPositionAndNormal(_lastPositionsTransformedEnd[i], _lastNormalsTransformed[j]);
                        currIndex += 2;
                    }
                }
                vertexIndexOffset = currIndex;
            }

            // now the start cap
            if (null != resultingStartCap)
            {
                resultingStartCap.AddGeometry(
                    AddPositionAndNormal,
                    AddIndices,
                    ref vertexIndexOffset,
                    true,
                    lineStart,
                    _westVector,
                    _northVector,
                    _forwardVector,
                    _crossSection,
                    drawLine ? _lastPositionsTransformedStart : null,
                    _lastNormalsTransformed,
                    ref _startCapTemporaryStorageSpace);
            }
            else if (drawLine)
            {
                LineCaps.Flat.AddGeometry(
                    AddPositionAndNormal,
                    AddIndices,
                    ref vertexIndexOffset,
                    true,
                    lineStart,
                    _forwardVector,
                    _lastPositionsTransformedStart
                    );
            }

            if (null != resultingEndCap)
            {
                resultingEndCap.AddGeometry(
                    AddPositionAndNormal,
                    AddIndices,
                    ref vertexIndexOffset,
                    false,
                    lineEnd,
                    _westVector,
                    _northVector,
                    _forwardVector,
                    _crossSection,
                    drawLine ? _lastPositionsTransformedEnd : null,
                    _lastNormalsTransformed,
                    ref _endCapTemporaryStorageSpace);
            }
            else if (drawLine)
            {
                LineCaps.Flat.AddGeometry(
                    AddPositionAndNormal,
                    AddIndices,
                    ref vertexIndexOffset,
                    false,
                    lineEnd,
                    _forwardVector,
                    _lastPositionsTransformedEnd
                    );
            }
        }
Example #15
0
		public PenX3D WithDashEndCap(ILineCap cap)
		{
			if (cap is LineCaps.Flat)
				cap = null;

			if (object.Equals(_dashEndCap, cap))
				return this;

			var result = (PenX3D)this.MemberwiseClone();
			result._dashEndCap = cap;
			return result;
		}
Example #16
0
		public PenX3D(
			IMaterial material,
			ICrossSectionOfLine crossSection,
			PenLineJoin lineJoin,
			double miterLimit,
			ILineCap lineStartCap, ILineCap lineEndCap, IDashPattern dashPattern, ILineCap dashStartCap, bool dashStartCapSuppressionIfSpaceInsufficient, ILineCap dashEndCap, bool dashEndCapSuppressionIfSpaceInsufficient)
		{
			if (!(miterLimit >= 1))
				throw new ArgumentOutOfRangeException(nameof(miterLimit), "must be >= 1");
			if (null == dashPattern)
				throw new ArgumentNullException(nameof(dashPattern));

			_material = material;
			_crossSection = crossSection;
			_lineJoin = lineJoin;
			_miterLimit = miterLimit;
			_lineStartCap = lineStartCap;
			_lineEndCap = lineEndCap;
			_dashPattern = dashPattern;
			_dashStartCap = dashStartCap;
			_dashStartCapSuppressionIfSpaceInsufficient = dashStartCapSuppressionIfSpaceInsufficient;
			_dashEndCap = dashEndCap;
			_dashEndCapSuppressionIfSpaceInsufficient = dashEndCapSuppressionIfSpaceInsufficient;
		}