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); }
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)); }
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 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); }
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); }
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); }
/// <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); }
/// <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 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; }
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; }