/// <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); }
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; }
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)); } }
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);
/// <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)); } }
/// <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; } }
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)); }
public PenX3D WithCrossSection(ICrossSectionOfLine crossSection) { if (!object.ReferenceEquals(crossSection, _crossSection)) { var result = (PenX3D)this.MemberwiseClone(); result._crossSection = crossSection; return result; } else { return this; } }
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; }
public PenX3D(NamedColor color, double thickness) { _material = Materials.GetSolidMaterial(color); _crossSection = new CrossSections.Rectangular(thickness, thickness); _dashPattern = DashPatternListManager.Instance.BuiltinDefaultSolid; }
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; } }
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);
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(); }
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()); }