Exemple #1
0
        /// <inheritdoc />
        public void AddGeometry(
            Action <PointD3D, VectorD3D> AddPositionAndNormal,
            Action <int, int, int, bool> AddIndices,
            ref int vertexIndexOffset,
            bool isStartCap,
            PointD3D basePoint,
            VectorD3D eastVector,
            VectorD3D northVector,
            VectorD3D forwardVectorNormalized,
            ICrossSectionOfLine lineCrossSection,
            PointD3D[] baseCrossSectionPositions,
            VectorD3D[] baseCrossSectionNormals,
            ref object temporaryStorageSpace)
        {
            var crossSectionVertexCount = lineCrossSection.NumberOfVertices;
            var crossSectionNormalCount = lineCrossSection.NumberOfNormals;

            var capCrossSectionPositions = baseCrossSectionPositions ?? (PointD3D[])temporaryStorageSpace ?? (PointD3D[])(temporaryStorageSpace = new PointD3D[crossSectionVertexCount]);

            if (null == baseCrossSectionPositions) // if null the positions were not provided
            {
                var matrix = Math3D.Get2DProjectionToPlane(eastVector, northVector, basePoint);
                for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
                {
                    capCrossSectionPositions[i] = matrix.Transform(lineCrossSection.Vertices(i));
                }
            }

            AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, isStartCap, basePoint, forwardVectorNormalized, capCrossSectionPositions);
        }
Exemple #2
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;
        }
Exemple #3
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));
            }
        }
Exemple #4
0
 public PenX3D WithCrossSection(ICrossSectionOfLine crossSection)
 {
     if (!object.ReferenceEquals(crossSection, _crossSection))
     {
         var result = (PenX3D)MemberwiseClone();
         result._crossSection = crossSection;
         return(result);
     }
     else
     {
         return(this);
     }
 }
 public abstract void AddGeometry(
     Action <PointD3D, VectorD3D> AddPositionAndNormal,
     Action <int, int, int, bool> AddIndices,
     ref int vertexIndexOffset,
     bool isStartCap,
     PointD3D basePoint,
     VectorD3D eastVector,
     VectorD3D northVector,
     VectorD3D forwardVectorNormalized,
     ICrossSectionOfLine lineCrossSection,
     PointD3D[] baseCrossSectionPositions,
     VectorD3D[] baseCrossSectionNormals,
     ref object temporaryStorageSpace);
Exemple #6
0
        /// <summary>
        /// Gets the vertices of a cross section from a certain vertex index to another vertex index (including the last vertex index).
        /// </summary>
        /// <param name="crossSection">The cross section.</param>
        /// <param name="firstVertexIndex">The first vertex index to include. Must be greater than or equal to zero.</param>
        /// <param name="lastIncludedVertexIndex">The last vertex index to include. Must be greater than <paramref name="firstVertexIndex"/>, but can be greater than the number of vertices of the cross section in order to describe a polygon that 'wraps around'.</param>
        /// <returns>The vertices from the first index up to and including the last index.</returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentException"></exception>
        public static IEnumerable <PointD2D> GetVerticesFromToIncluding(ICrossSectionOfLine crossSection, int firstVertexIndex, int lastIncludedVertexIndex)
        {
            if (!(firstVertexIndex <= lastIncludedVertexIndex))
            {
                throw new ArgumentOutOfRangeException(nameof(lastIncludedVertexIndex) + " must be greater then or equal to " + nameof(firstVertexIndex));
            }
            if (!(firstVertexIndex >= 0))
            {
                throw new ArgumentException(nameof(firstVertexIndex) + "must be >=0");
            }

            int vertexCount = crossSection.NumberOfVertices;

            for (int i = firstVertexIndex; i <= lastIncludedVertexIndex; ++i)
            {
                yield return(crossSection.Vertices(i % vertexCount));
            }
        }
Exemple #7
0
        /// <summary>
        /// Adds the triangle geometry for this 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. Must be actualized during this call.</param>
        /// <param name="isStartCap">If set to <c>true</c>, a start cap is drawn; otherwise, an end cap is drawn.</param>
        /// <param name="basePoint">The location of the middle point of the line at the cap's location.</param>
        /// <param name="westVector">The west vector for orientation of the cross section.</param>
        /// <param name="northVector">The north vector for orientation of the cross section.</param>
        /// <param name="forwardVector">The forward vector for orientation of the cross section.</param>
        /// <param name="crossSection">The cross section of the line.</param>
        public static void AddGeometry(
            Action <PointD3D, VectorD3D> AddPositionAndNormal,
            Action <int, int, int, bool> AddIndices,
            ref int vertexIndexOffset,
            bool isStartCap,
            PointD3D basePoint,
            VectorD3D westVector,
            VectorD3D northVector,
            VectorD3D forwardVector,
            ICrossSectionOfLine crossSection
            )
        {
            if (isStartCap)
            {
                forwardVector = -forwardVector;
            }

            var matrix = Matrix4x3.NewFromBasisVectorsAndLocation(westVector, northVector, forwardVector, basePoint);

            int currIndex = vertexIndexOffset;
            int crossSectionPositionCount = crossSection.NumberOfVertices;

            // Add the midpoint
            // add the middle point of the end cap and the normal of the end cap
            AddPositionAndNormal(basePoint, forwardVector);
            ++currIndex;

            for (int i = 0; i < crossSectionPositionCount; ++i)
            {
                var sp = matrix.Transform(crossSection.Vertices(i));
                AddPositionAndNormal(sp, forwardVector);

                AddIndices(
                    currIndex - 1, // mid point of the end cap
                    currIndex + i,
                    currIndex + (1 + i) % crossSectionPositionCount,
                    isStartCap);
            }

            currIndex        += crossSectionPositionCount;
            vertexIndexOffset = currIndex;
        }
        public static void Add(
            Action <PointD3D, VectorD3D> AddPositionAndNormal,
            Action <int, int, int, bool> AddIndices,
            ref int vertexIndexOffset,
            bool isStartCap,
            PointD3D basePoint,
            VectorD3D westVector,
            VectorD3D northVector,
            VectorD3D forwardVectorNormalized,
            ICrossSectionOfLine lineCrossSection,
            PointD3D[] crossSectionPositions,
            VectorD3D[] crossSectionNormals,
            ref object temporaryStorageSpace,
            ILineCapContour capContour
            )
        {
            var crossSectionVertexCount = lineCrossSection.NumberOfVertices;
            var crossSectionNormalCount = lineCrossSection.NumberOfNormals;
            var contourZScale           = 0.5 * Math.Max(lineCrossSection.Size1, lineCrossSection.Size2);

            // do we need a flat end at the beginning of the cap?
            if (null == crossSectionPositions &&         // if lineCrossSectionPositions are null, it means that our cap is not connected to the line and needs a flat end
                capContour.Vertices(0) == _pointD2D_0_1) // furthermore the cap assumes to be started at the cross section
            {
                // the parameter isStartCap must be negated, because this flat cap is the "counterpart" of our cap to draw
                Flat.AddGeometry(
                    AddPositionAndNormal,
                    AddIndices,
                    ref vertexIndexOffset,
                    !isStartCap,
                    basePoint,
                    westVector,
                    northVector,
                    forwardVectorNormalized,
                    lineCrossSection);
            }

            if (isStartCap)
            {
                forwardVectorNormalized = -forwardVectorNormalized;
            }

            var contourVertexCount = capContour.NumberOfVertices;
            var contourNormalCount = capContour.NumberOfNormals;

            // now the calculation can start

            CrossSectionCases previousCrossSectionType = CrossSectionCases.MiddlePointSmooth;
            int  previousGeneratedPoints            = 0;
            int  previousContourVertexIndex         = 0;
            bool isOnSecondSideOfContourVertexSharp = true;

            for (int contourVertexIndex = 0, contourNormalIndex = 0; contourVertexIndex < contourVertexCount; ++contourVertexIndex, ++contourNormalIndex)
            {
                // we have 4 different situations here:
                // 1st) the crossSection.Y is zero, thus this is the middle point (the normal should then go in z-direction) -> we need only one single vertex and normal for that
                // 2nd) the countour normal is in x-direction  -> we need only a point for each crossSection vertex, but not for each crossSectionNormal
                // 3rd) the regular case -> we need a point for each crossSection normal

                var capContourVertex = capContour.Vertices(contourVertexIndex);
                var capContourNormal = capContour.Normals(contourNormalIndex);

                CrossSectionCases currentCrossSectionType;
                if (capContourVertex.Y == 0 && capContourNormal.Y == 0)
                {
                    currentCrossSectionType = CrossSectionCases.MiddlePointSmooth;
                }
                else if (capContourVertex.Y == 0)
                {
                    currentCrossSectionType = CrossSectionCases.MiddlePointSharp;
                }
                else if (0 == capContourNormal.Y)
                {
                    currentCrossSectionType = CrossSectionCases.VerticesOnly;
                }
                else
                {
                    currentCrossSectionType = CrossSectionCases.Regular;
                }

                var currentLocation = basePoint + forwardVectorNormalized * capContourVertex.X * contourZScale;
                var matrix          = Matrix4x3.NewFromBasisVectorsAndLocation(westVector, northVector, forwardVectorNormalized, currentLocation);

                int currentGeneratedPoints = 0;
                switch (currentCrossSectionType)
                {
                case CrossSectionCases.MiddlePointSmooth:
                {
                    var position = matrix.Transform(PointD2D.Empty);
                    var normal   = matrix.Transform(new VectorD3D(0, 0, capContourNormal.X));
                    AddPositionAndNormal(position, normal);
                    currentGeneratedPoints = 1;
                }
                break;

                case CrossSectionCases.MiddlePointSharp:
                {
                    for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
                    {
                        var normal1  = (i == 0) ? lineCrossSection.Normals(crossSectionNormalCount - 1) : lineCrossSection.Normals(j - 1);
                        var normal2  = lineCrossSection.Normals(j);
                        var sn       = (normal1 + normal2).Normalized;
                        var utNormal = GetNormalVector(lineCrossSection.Vertices(i), sn, capContourNormal, contourZScale);
                        AddPositionAndNormal(currentLocation, matrix.Transform(utNormal)); // store the tip point with the averaged normal
                        if (lineCrossSection.IsVertexSharp(i))
                        {
                            ++j;
                        }
                    }
                    currentGeneratedPoints = crossSectionVertexCount;
                }
                break;

                case CrossSectionCases.VerticesOnly:
                {
                    var commonNormal = matrix.Transform(new VectorD3D(0, 0, capContourNormal.X));
                    for (int i = 0; i < crossSectionVertexCount; ++i)
                    {
                        var position = matrix.Transform(lineCrossSection.Vertices(i) * capContourVertex.Y);
                        AddPositionAndNormal(position, commonNormal);
                    }
                    currentGeneratedPoints = crossSectionVertexCount;
                }
                break;

                case CrossSectionCases.Regular:
                {
                    for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
                    {
                        var sp       = lineCrossSection.Vertices(i);
                        var sn       = lineCrossSection.Normals(j);
                        var utNormal = GetNormalVector(sp, sn, capContourNormal, contourZScale);
                        var position = matrix.Transform(sp * capContourVertex.Y);
                        var normal   = matrix.Transform(utNormal);

                        AddPositionAndNormal(position, normal);

                        if (lineCrossSection.IsVertexSharp(i))
                        {
                            ++j;
                            sn       = lineCrossSection.Normals(j);
                            utNormal = GetNormalVector(sp, sn, capContourNormal, contourZScale);
                            normal   = matrix.Transform(utNormal);
                            AddPositionAndNormal(position, normal);
                        }
                    }
                    currentGeneratedPoints = crossSectionNormalCount;
                }
                break;

                default:
                    throw new NotImplementedException();
                }
                vertexIndexOffset += currentGeneratedPoints;

                // now we start generating triangles

                if (contourVertexIndex > previousContourVertexIndex)
                {
                    int voffset1 = vertexIndexOffset - currentGeneratedPoints;
                    int voffset0 = voffset1 - previousGeneratedPoints;
                    switch (previousCrossSectionType)
                    {
                    case CrossSectionCases.MiddlePointSmooth:
                    {
                        switch (currentCrossSectionType)
                        {
                        case CrossSectionCases.MiddlePointSmooth: // Middle point to middle point
                        {
                            // no triangles, since from middle point to middle point we have an infinity thin line
                        }
                        break;

                        case CrossSectionCases.MiddlePointSharp: // Middle point to middle point
                        {
                            // no triangles, since from middle point to middle point we have an infinity thin line
                        }
                        break;

                        case CrossSectionCases.VerticesOnly: // Middle point to vertices only
                        {
                            for (int i = 0; i < crossSectionVertexCount; ++i)
                            {
                                AddIndices(voffset0, voffset1 + i, voffset1 + (i + 1) % crossSectionVertexCount, isStartCap);
                            }
                        }
                        break;

                        case CrossSectionCases.Regular: // Middle point to regular
                        {
                            for (int i = 0; i < crossSectionNormalCount; ++i)
                            {
                                AddIndices(voffset0, voffset1 + i, voffset1 + (i + 1) % crossSectionNormalCount, isStartCap);
                            }
                        }
                        break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                    break;

                    case CrossSectionCases.MiddlePointSharp:
                    {
                        switch (currentCrossSectionType)
                        {
                        case CrossSectionCases.MiddlePointSmooth: // Middle point to middle point
                        {
                            // no triangles, since from middle point to middle point we have an infinity thin line
                        }
                        break;

                        case CrossSectionCases.MiddlePointSharp: // Middle point to middle point
                        {
                            // no triangles, since from middle point to middle point we have an infinity thin line
                        }
                        break;

                        case CrossSectionCases.VerticesOnly: // MiddlePointSharp to VerticesOnly
                        {
                            for (int i = 0; i < crossSectionVertexCount; ++i)
                            {
                                AddIndices(voffset0, voffset1 + i, voffset1 + (i + 1) % crossSectionVertexCount, isStartCap);
                            }
                        }
                        break;

                        case CrossSectionCases.Regular: // MiddlePointSharp to Regular
                        {
                            for (int i = 0, j = 0; i < crossSectionNormalCount; ++i, ++j)
                            {
                                AddIndices(voffset0 + i, voffset1 + i, voffset1 + (i + 1) % crossSectionNormalCount, isStartCap);
                            }
                        }
                        break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                    break;

                    case CrossSectionCases.VerticesOnly:
                    {
                        switch (currentCrossSectionType)
                        {
                        case CrossSectionCases.MiddlePointSmooth: // VerticesOnly to MiddlePoint
                        {
                            for (int i = 0; i < crossSectionVertexCount; ++i)
                            {
                                AddIndices(voffset1, voffset0 + i, voffset0 + (i + 1) % crossSectionVertexCount, isStartCap);
                            }
                        }
                        break;

                        case CrossSectionCases.VerticesOnly: // VerticesOnly to VerticesOnly
                        {
                            for (int i = 0; i < crossSectionVertexCount; ++i)
                            {
                                AddIndices(voffset0 + ((i == 0) ? crossSectionVertexCount - 1 : i - 1), voffset0 + i, voffset1 + i, isStartCap);
                                AddIndices(voffset0 + ((i == 0) ? crossSectionVertexCount - 1 : i - 1), voffset1 + i, voffset1 + ((i == 0) ? crossSectionVertexCount - 1 : i - 1), isStartCap);
                            }
                        }
                        break;

                        case CrossSectionCases.Regular: // VerticesOnly to regular
                        {
                            throw new NotImplementedException();
                        }
                        //break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                    break;

                    case CrossSectionCases.Regular:
                    {
                        switch (currentCrossSectionType)
                        {
                        case CrossSectionCases.MiddlePointSmooth: // Regular to MiddlePointOnly
                        {
                            for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
                            {
                                AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset0 + j, voffset1, isStartCap);

                                if (lineCrossSection.IsVertexSharp(i))
                                {
                                    ++j;
                                }
                            }
                        }
                        break;

                        case CrossSectionCases.MiddlePointSharp: // Regular to MiddlePointSharp
                        {
                            for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
                            {
                                AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset0 + j, voffset1 + i, isStartCap);

                                if (lineCrossSection.IsVertexSharp(i))
                                {
                                    ++j;
                                }
                            }
                        }
                        break;

                        case CrossSectionCases.VerticesOnly: // Regular to VerticesOnly
                        {
                            for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
                            {
                                AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset0 + j, voffset1 + i, isStartCap);
                                AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset1 + i, voffset1 + ((i == 0) ? crossSectionVertexCount - 1 : i - 1), isStartCap);

                                if (lineCrossSection.IsVertexSharp(i))
                                {
                                    ++j;
                                }
                            }
                        }
                        break;

                        case CrossSectionCases.Regular: // Regular to Regular
                        {
                            for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
                            {
                                AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset0 + j, voffset1 + j, isStartCap);
                                AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset1 + j, voffset1 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), isStartCap);

                                if (lineCrossSection.IsVertexSharp(i))
                                {
                                    ++j;
                                }
                            }
                        }
                        break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                    break;

                    default:
                        throw new NotImplementedException();
                    }
                }

                if (!isOnSecondSideOfContourVertexSharp && capContour.IsVertexSharp(contourVertexIndex) && contourVertexIndex < (contourVertexCount - 1))
                {
                    previousContourVertexIndex = contourVertexIndex;
                    --contourVertexIndex; // trick: decrement the vertex index, it is incremented then again in the following for loop, so that contourVertexIndex stays constant
                    isOnSecondSideOfContourVertexSharp = true;
                    continue;
                }
                isOnSecondSideOfContourVertexSharp = false;

                // now we switch the current calculated positions and normals with the old ones
                previousCrossSectionType   = currentCrossSectionType;
                previousGeneratedPoints    = currentGeneratedPoints;
                previousContourVertexIndex = contourVertexIndex;
            }
        }
Exemple #9
0
		public override void AddGeometry(Action<PointD3D, VectorD3D> AddPositionAndNormal, Action<int, int, int, bool> AddIndices, ref int vertexIndexOffset, bool isStartCap, PointD3D basePoint, VectorD3D eastVector, VectorD3D northVector, VectorD3D forwardVectorNormalized, ICrossSectionOfLine lineCrossSection, PointD3D[] baseCrossSectionPositions, VectorD3D[] baseCrossSectionNormals, ref object temporaryStorageSpace)
		{
			double relSize = Math.Max(_minimumRelativeSize, _minimumAbsoluteSize / Math.Max(lineCrossSection.Size1, lineCrossSection.Size2));

			Add(
				AddPositionAndNormal,
				AddIndices,
				ref vertexIndexOffset,
				isStartCap,
				basePoint,
				eastVector,
				northVector,
				forwardVectorNormalized,
				lineCrossSection,
				baseCrossSectionPositions,
				baseCrossSectionNormals,
				ref temporaryStorageSpace,
				new ArrowContour(relSize));
		}
Exemple #10
0
		public PenX3D WithCrossSection(ICrossSectionOfLine crossSection)
		{
			if (!object.ReferenceEquals(crossSection, _crossSection))
			{
				var result = (PenX3D)this.MemberwiseClone();
				result._crossSection = crossSection;
				return result;
			}
			else
			{
				return this;
			}
		}
Exemple #11
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;
		}
Exemple #12
0
 public PenX3D(NamedColor color, double thickness)
 {
     _material     = Materials.GetSolidMaterial(color);
     _crossSection = new CrossSections.Rectangular(thickness, thickness);
     _dashPattern  = DashPatternListManager.Instance.BuiltinDefaultSolid;
 }
Exemple #13
0
 public PenX3D(IMaterial material, ICrossSectionOfLine crossSection)
 {
     _material     = material;
     _crossSection = crossSection;
     _dashPattern  = DashPatternListManager.Instance.BuiltinDefaultSolid;
 }
Exemple #14
0
		public PenX3D(IMaterial material, ICrossSectionOfLine crossSection)
		{
			_material = material;
			_crossSection = crossSection;
			_dashPattern = DashPatternListManager.Instance.BuiltinDefaultSolid;
		}
		public static void Add(
			Action<PointD3D, VectorD3D> AddPositionAndNormal,
			Action<int, int, int, bool> AddIndices,
			ref int vertexIndexOffset,
			bool isStartCap,
			PointD3D basePoint,
			VectorD3D westVector,
			VectorD3D northVector,
			VectorD3D forwardVectorNormalized,
			ICrossSectionOfLine lineCrossSection,
			PointD3D[] crossSectionPositions,
			VectorD3D[] crossSectionNormals,
			ref object temporaryStorageSpace,
			ILineCapContour capContour
			)
		{
			var crossSectionVertexCount = lineCrossSection.NumberOfVertices;
			var crossSectionNormalCount = lineCrossSection.NumberOfNormals;
			var contourZScale = 0.5 * Math.Max(lineCrossSection.Size1, lineCrossSection.Size2);

			// do we need a flat end at the beginning of the cap?
			if (null == crossSectionPositions && // if lineCrossSectionPositions are null, it means that our cap is not connected to the line and needs a flat end
						capContour.Vertices(0) == _pointD2D_0_1) // furthermore the cap assumes to be started at the cross section
			{
				// the parameter isStartCap must be negated, because this flat cap is the "counterpart" of our cap to draw
				Flat.AddGeometry(
					AddPositionAndNormal,
					AddIndices,
					ref vertexIndexOffset,
					!isStartCap,
					basePoint,
					westVector,
					northVector,
					forwardVectorNormalized,
					lineCrossSection);
			}

			if (isStartCap)
				forwardVectorNormalized = -forwardVectorNormalized;

			var contourVertexCount = capContour.NumberOfVertices;
			var contourNormalCount = capContour.NumberOfNormals;

			// now the calculation can start

			CrossSectionCases previousCrossSectionType = CrossSectionCases.MiddlePointSmooth;
			int previousGeneratedPoints = 0;
			int previousContourVertexIndex = 0;
			bool isOnSecondSideOfContourVertexSharp = true;
			for (int contourVertexIndex = 0, contourNormalIndex = 0; contourVertexIndex < contourVertexCount; ++contourVertexIndex, ++contourNormalIndex)
			{
				// we have 4 different situations here:
				// 1st) the crossSection.Y is zero, thus this is the middle point (the normal should then go in z-direction) -> we need only one single vertex and normal for that
				// 2nd) the countour normal is in x-direction  -> we need only a point for each crossSection vertex, but not for each crossSectionNormal
				// 3rd) the regular case -> we need a point for each crossSection normal

				var capContourVertex = capContour.Vertices(contourVertexIndex);
				var capContourNormal = capContour.Normals(contourNormalIndex);

				CrossSectionCases currentCrossSectionType;
				if (capContourVertex.Y == 0 && capContourNormal.Y == 0)
					currentCrossSectionType = CrossSectionCases.MiddlePointSmooth;
				else if (capContourVertex.Y == 0)
					currentCrossSectionType = CrossSectionCases.MiddlePointSharp;
				else if (0 == capContourNormal.Y)
					currentCrossSectionType = CrossSectionCases.VerticesOnly;
				else
					currentCrossSectionType = CrossSectionCases.Regular;

				var currentLocation = basePoint + forwardVectorNormalized * capContourVertex.X * contourZScale;
				var matrix = Matrix4x3.NewFromBasisVectorsAndLocation(westVector, northVector, forwardVectorNormalized, currentLocation);

				int currentGeneratedPoints = 0;
				switch (currentCrossSectionType)
				{
					case CrossSectionCases.MiddlePointSmooth:
						{
							var position = matrix.Transform(PointD2D.Empty);
							var normal = matrix.Transform(new VectorD3D(0, 0, capContourNormal.X));
							AddPositionAndNormal(position, normal);
							currentGeneratedPoints = 1;
						}
						break;

					case CrossSectionCases.MiddlePointSharp:
						{
							for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
							{
								var normal1 = (i == 0) ? lineCrossSection.Normals(crossSectionNormalCount - 1) : lineCrossSection.Normals(j - 1);
								var normal2 = lineCrossSection.Normals(j);
								var sn = (normal1 + normal2).Normalized;
								var utNormal = GetNormalVector(lineCrossSection.Vertices(i), sn, capContourNormal, contourZScale);
								AddPositionAndNormal(currentLocation, matrix.Transform(utNormal)); // store the tip point with the averaged normal
								if (lineCrossSection.IsVertexSharp(i))
								{
									++j;
								}
							}
							currentGeneratedPoints = crossSectionVertexCount;
						}
						break;

					case CrossSectionCases.VerticesOnly:
						{
							var commonNormal = matrix.Transform(new VectorD3D(0, 0, capContourNormal.X));
							for (int i = 0; i < crossSectionVertexCount; ++i)
							{
								var position = matrix.Transform(lineCrossSection.Vertices(i) * capContourVertex.Y);
								AddPositionAndNormal(position, commonNormal);
							}
							currentGeneratedPoints = crossSectionVertexCount;
						}
						break;

					case CrossSectionCases.Regular:
						{
							for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
							{
								var sp = lineCrossSection.Vertices(i);
								var sn = lineCrossSection.Normals(j);
								var utNormal = GetNormalVector(sp, sn, capContourNormal, contourZScale);
								var position = matrix.Transform(sp * capContourVertex.Y);
								var normal = matrix.Transform(utNormal);

								AddPositionAndNormal(position, normal);

								if (lineCrossSection.IsVertexSharp(i))
								{
									++j;
									sn = lineCrossSection.Normals(j);
									utNormal = GetNormalVector(sp, sn, capContourNormal, contourZScale);
									normal = matrix.Transform(utNormal);
									AddPositionAndNormal(position, normal);
								}
							}
							currentGeneratedPoints = crossSectionNormalCount;
						}
						break;

					default:
						throw new NotImplementedException();
				}
				vertexIndexOffset += currentGeneratedPoints;

				// now we start generating triangles

				if (contourVertexIndex > previousContourVertexIndex)
				{
					int voffset1 = vertexIndexOffset - currentGeneratedPoints;
					int voffset0 = voffset1 - previousGeneratedPoints;
					switch (previousCrossSectionType)
					{
						case CrossSectionCases.MiddlePointSmooth:
							{
								switch (currentCrossSectionType)
								{
									case CrossSectionCases.MiddlePointSmooth: // Middle point to middle point
										{
											// no triangles, since from middle point to middle point we have an infinity thin line
										}
										break;

									case CrossSectionCases.MiddlePointSharp: // Middle point to middle point
										{
											// no triangles, since from middle point to middle point we have an infinity thin line
										}
										break;

									case CrossSectionCases.VerticesOnly: // Middle point to vertices only
										{
											for (int i = 0; i < crossSectionVertexCount; ++i)
											{
												AddIndices(voffset0, voffset1 + i, voffset1 + (i + 1) % crossSectionVertexCount, isStartCap);
											}
										}
										break;

									case CrossSectionCases.Regular: // Middle point to regular
										{
											for (int i = 0; i < crossSectionNormalCount; ++i)
											{
												AddIndices(voffset0, voffset1 + i, voffset1 + (i + 1) % crossSectionNormalCount, isStartCap);
											}
										}
										break;

									default:
										throw new NotImplementedException();
								}
							}
							break;

						case CrossSectionCases.MiddlePointSharp:
							{
								switch (currentCrossSectionType)
								{
									case CrossSectionCases.MiddlePointSmooth: // Middle point to middle point
										{
											// no triangles, since from middle point to middle point we have an infinity thin line
										}
										break;

									case CrossSectionCases.MiddlePointSharp: // Middle point to middle point
										{
											// no triangles, since from middle point to middle point we have an infinity thin line
										}
										break;

									case CrossSectionCases.VerticesOnly: // MiddlePointSharp to VerticesOnly
										{
											for (int i = 0; i < crossSectionVertexCount; ++i)
											{
												AddIndices(voffset0, voffset1 + i, voffset1 + (i + 1) % crossSectionVertexCount, isStartCap);
											}
										}
										break;

									case CrossSectionCases.Regular: // MiddlePointSharp to Regular
										{
											for (int i = 0, j = 0; i < crossSectionNormalCount; ++i, ++j)
											{
												AddIndices(voffset0 + i, voffset1 + i, voffset1 + (i + 1) % crossSectionNormalCount, isStartCap);
											}
										}
										break;

									default:
										throw new NotImplementedException();
								}
							}
							break;

						case CrossSectionCases.VerticesOnly:
							{
								switch (currentCrossSectionType)
								{
									case CrossSectionCases.MiddlePointSmooth: // VerticesOnly to MiddlePoint
										{
											for (int i = 0; i < crossSectionVertexCount; ++i)
											{
												AddIndices(voffset1, voffset0 + i, voffset0 + (i + 1) % crossSectionVertexCount, isStartCap);
											}
										}
										break;

									case CrossSectionCases.VerticesOnly: // VerticesOnly to VerticesOnly
										{
											for (int i = 0; i < crossSectionVertexCount; ++i)
											{
												AddIndices(voffset0 + ((i == 0) ? crossSectionVertexCount - 1 : i - 1), voffset0 + i, voffset1 + i, isStartCap);
												AddIndices(voffset0 + ((i == 0) ? crossSectionVertexCount - 1 : i - 1), voffset1 + i, voffset1 + ((i == 0) ? crossSectionVertexCount - 1 : i - 1), isStartCap);
											}
										}
										break;

									case CrossSectionCases.Regular: // VerticesOnly to regular
										{
											throw new NotImplementedException();
										}
									//break;

									default:
										throw new NotImplementedException();
								}
							}
							break;

						case CrossSectionCases.Regular:
							{
								switch (currentCrossSectionType)
								{
									case CrossSectionCases.MiddlePointSmooth: // Regular to MiddlePointOnly
										{
											for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
											{
												AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset0 + j, voffset1, isStartCap);

												if (lineCrossSection.IsVertexSharp(i))
													++j;
											}
										}
										break;

									case CrossSectionCases.MiddlePointSharp: // Regular to MiddlePointSharp
										{
											for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
											{
												AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset0 + j, voffset1 + i, isStartCap);

												if (lineCrossSection.IsVertexSharp(i))
													++j;
											}
										}
										break;

									case CrossSectionCases.VerticesOnly: // Regular to VerticesOnly
										{
											for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
											{
												AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset0 + j, voffset1 + i, isStartCap);
												AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset1 + i, voffset1 + ((i == 0) ? crossSectionVertexCount - 1 : i - 1), isStartCap);

												if (lineCrossSection.IsVertexSharp(i))
													++j;
											}
										}
										break;

									case CrossSectionCases.Regular: // Regular to Regular
										{
											for (int i = 0, j = 0; i < crossSectionVertexCount; ++i, ++j)
											{
												AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset0 + j, voffset1 + j, isStartCap);
												AddIndices(voffset0 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), voffset1 + j, voffset1 + ((j == 0) ? crossSectionNormalCount - 1 : j - 1), isStartCap);

												if (lineCrossSection.IsVertexSharp(i))
													++j;
											}
										}
										break;

									default:
										throw new NotImplementedException();
								}
							}
							break;

						default:
							throw new NotImplementedException();
					}
				}

				if (!isOnSecondSideOfContourVertexSharp && capContour.IsVertexSharp(contourVertexIndex) && contourVertexIndex < (contourVertexCount - 1))
				{
					previousContourVertexIndex = contourVertexIndex;
					--contourVertexIndex; // trick: decrement the vertex index, it is incremented then again in the following for loop, so that contourVertexIndex stays constant
					isOnSecondSideOfContourVertexSharp = true;
					continue;
				}
				isOnSecondSideOfContourVertexSharp = false;

				// now we switch the current calculated positions and normals with the old ones
				previousCrossSectionType = currentCrossSectionType;
				previousGeneratedPoints = currentGeneratedPoints;
				previousContourVertexIndex = contourVertexIndex;
			}
		}
Exemple #16
0
        public override void AddGeometry(Action <PointD3D, VectorD3D> AddPositionAndNormal, Action <int, int, int, bool> AddIndices, ref int vertexIndexOffset, bool isStartCap, PointD3D basePoint, VectorD3D eastVector, VectorD3D northVector, VectorD3D forwardVectorNormalized, ICrossSectionOfLine lineCrossSection, PointD3D[] baseCrossSectionPositions, VectorD3D[] baseCrossSectionNormals, ref object temporaryStorageSpace)
        {
            double relSize          = Math.Max(_minimumRelativeSize, _minimumAbsoluteSize / Math.Max(lineCrossSection.Size1, lineCrossSection.Size2));
            double relDiscThickness = 2 * Math.Min(lineCrossSection.Size1, lineCrossSection.Size2) / Math.Max(lineCrossSection.Size1, lineCrossSection.Size2);

            Add(
                AddPositionAndNormal,
                AddIndices,
                ref vertexIndexOffset,
                isStartCap,
                basePoint,
                eastVector,
                northVector,
                forwardVectorNormalized,
                lineCrossSection,
                baseCrossSectionPositions,
                baseCrossSectionNormals,
                ref temporaryStorageSpace,
                new Contour(relSize, relDiscThickness));
        }
		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));
			}
		}
		public abstract void AddGeometry(
			Action<PointD3D, VectorD3D> AddPositionAndNormal,
			Action<int, int, int, bool> AddIndices,
			ref int vertexIndexOffset,
			bool isStartCap,
			PointD3D basePoint,
			VectorD3D eastVector,
			VectorD3D northVector,
			VectorD3D forwardVectorNormalized,
			ICrossSectionOfLine lineCrossSection,
			PointD3D[] baseCrossSectionPositions,
			VectorD3D[] baseCrossSectionNormals,
			ref object temporaryStorageSpace);
Exemple #19
0
		public override void AddGeometry(Action<PointD3D, VectorD3D> AddPositionAndNormal, Action<int, int, int, bool> AddIndices, ref int vertexIndexOffset, bool isStartCap, PointD3D basePoint, VectorD3D eastVector, VectorD3D northVector, VectorD3D forwardVectorNormalized, ICrossSectionOfLine lineCrossSection, PointD3D[] baseCrossSectionPositions, VectorD3D[] baseCrossSectionNormals, ref object temporaryStorageSpace)
		{
			Add(
				AddPositionAndNormal,
				AddIndices,
				ref vertexIndexOffset,
				isStartCap,
				basePoint,
				eastVector,
				northVector,
				forwardVectorNormalized,
				lineCrossSection,
				baseCrossSectionPositions,
				baseCrossSectionNormals,
				ref temporaryStorageSpace,
				_contour);
		}
		/// <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();
		}
Exemple #21
0
 public override void AddGeometry(Action <PointD3D, VectorD3D> AddPositionAndNormal, Action <int, int, int, bool> AddIndices, ref int vertexIndexOffset, bool isStartCap, PointD3D basePoint, VectorD3D eastVector, VectorD3D northVector, VectorD3D forwardVectorNormalized, ICrossSectionOfLine lineCrossSection, PointD3D[] baseCrossSectionPositions, VectorD3D[] baseCrossSectionNormals, ref object temporaryStorageSpace)
 {
     Add(
         AddPositionAndNormal,
         AddIndices,
         ref vertexIndexOffset,
         isStartCap,
         basePoint,
         eastVector,
         northVector,
         forwardVectorNormalized,
         lineCrossSection,
         baseCrossSectionPositions,
         baseCrossSectionNormals,
         ref temporaryStorageSpace,
         new TriangleContour());
 }
Exemple #22
0
		public PenX3D(NamedColor color, double thickness)
		{
			_material = Materials.GetSolidMaterial(color);
			_crossSection = new CrossSections.Rectangular(thickness, thickness);
			_dashPattern = DashPatternListManager.Instance.BuiltinDefaultSolid;
		}