Esempio n. 1
0
		/// <summary>
		/// Template to make a line draw.
		/// </summary>
		/// <param name="g">Graphics context.</param>
		/// <param name="pdata">The plot data. Don't use the Range property of the pdata, since it is overriden by the next argument.</param>
		/// <param name="range">The plot range to use.</param>
		/// <param name="layer">Graphics layer.</param>
		/// <param name="pen">The pen to draw the line.</param>
		/// <param name="symbolGap">The size of the symbol gap. Argument is the original index of the data. The return value is the absolute symbol gap at this index.
		/// This function is null if no symbol gap is required.</param>
		/// <param name="skipFrequency">Skip frequency. Normally 1, thus all gaps are taken into account. If 2, only every 2nd gap is taken into account, and so on.</param>
		/// <param name="connectCircular">If true, the end of the line is connected with the start of the line.</param>
		public abstract void Paint(
			IGraphicsContext3D g,
			Processed3DPlotData pdata,
			PlotRange range,
			IPlotArea layer,
			PenX3D pen,
			Func<int, double> symbolGap,
			int skipFrequency,
			bool connectCircular);
Esempio n. 2
0
		protected OpenPathShapeBase(ItemLocationDirect location, Altaxo.Main.Properties.IReadOnlyPropertyBag context)
			: base(location)
		{
			if (null == context)
				context = PropertyExtensions.GetPropertyContextOfProject();

			var penWidth = GraphDocument.GetDefaultPenWidth(context);
			var foreColor = context.GetValue(GraphDocument.PropertyKeyDefaultForeColor);
			Pen = new PenX3D(foreColor, penWidth);
		}
Esempio n. 3
0
        public static bool AreEqualUnlessThickness(PenX3D pen1, PenX3D pen2)
        {
            bool isEqual =

                pen1.Material == pen2.Material &&
                pen1.CrossSection.GetType() == pen2.CrossSection.GetType() &&
                object.ReferenceEquals(pen1._dashPattern, pen2._dashPattern) && // Reference equality because DashPatterns parent list is determined by reference equality.
                object.Equals(pen1._lineStartCap, pen2._lineStartCap) &&
                object.Equals(pen1._lineEndCap, pen2._lineEndCap) &&
                object.Equals(pen1._dashStartCap, pen2._dashStartCap) &&
                object.Equals(pen1._dashEndCap, pen2._dashEndCap);

            return(isEqual);
        }
Esempio n. 4
0
 /// <summary>
 /// Initialization that is needed only once per straigth line (not once per dash).
 /// </summary>
 /// <param name="pen">The pen that is used to draw the line.</param>
 /// <param name="west">The west vector.</param>
 /// <param name="north">The north vector.</param>
 /// <param name="line">The global line to draw. This argument is needed to extract the line vector, which for a straight line is also the line vector for each individual dash segment.</param>
 public void Initialize(
     PenX3D pen,
     VectorD3D west,
     VectorD3D north,
     LineD3D line)
 {
     Initialize(
         pen.CrossSection,
         pen.Thickness1,
         pen.Thickness2,
         pen.DashStartCap,
         pen.DashEndCap,
         west,
         north,
         line
         );
 }
		/// <summary>
		/// Initialization that is needed only once per straigth line (not once per dash).
		/// </summary>
		/// <param name="pen">The pen that is used to draw the line.</param>
		/// <param name="west">The west vector.</param>
		/// <param name="north">The north vector.</param>
		/// <param name="line">The global line to draw. This argument is needed to extract the line vector, which for a straight line is also the line vector for each individual dash segment.</param>
		public void Initialize(
			PenX3D pen,
			VectorD3D west,
			VectorD3D north,
			LineD3D line)
		{
			Initialize(
				pen.CrossSection,
				pen.Thickness1,
				pen.Thickness2,
				pen.DashStartCap,
				pen.DashEndCap,
				west,
				north,
				line
				);
		}
Esempio n. 6
0
		private void EhDashEndCapRelSize_SelectionChangeCommitted(object sender, DependencyPropertyChangedEventArgs e)
		{
			_userChangedRelDashEndCapSize = true;

			if (_pen != null)
			{
				var cap = _pen.DashEndCap;
				if (null != cap)
				{
					cap = cap.WithMinimumAbsoluteAndRelativeSize(cap.MinimumAbsoluteSizePt, _cbDashEndCapRelSize.SelectedQuantityAsValueInSIUnits);
				}
				_pen = _pen.WithDashEndCap(cap);

				OnPenChanged();
			}
		}
Esempio n. 7
0
		private void EhMiterLimit_SelectionChangeCommitted(object sender, DependencyPropertyChangedEventArgs e)
		{
			if (_pen != null)
			{
				_pen = _pen.WithMiterLimit(_cbMiterLimit.SelectedQuantityInSIUnits);

				OnPenChanged();
			}
		}
Esempio n. 8
0
		public override bool CopyFrom(object obj)
		{
			var isCopied = base.CopyFrom(obj);
			if (isCopied && !object.ReferenceEquals(this, obj))
			{
				var from = obj as OpenPathShapeBase;
				if (from != null)
				{
					this._linePen = from._linePen;
				}
			}
			return isCopied;
		}
Esempio n. 9
0
		/// <summary>
		/// Template to make a line draw.
		/// </summary>
		/// <param name="g">Graphics context.</param>
		/// <param name="pdata">The plot data. Don't use the Range property of the pdata, since it is overriden by the next argument.</param>
		/// <param name="range">The plot range to use.</param>
		/// <param name="layer">Graphics layer.</param>
		/// <param name="pen">The pen to draw the line.</param>
		/// <param name="symbolGap">The size of the symbol gap. Argument is the original index of the data. The return value is the absolute symbol gap at this index. This function is null if no symbol gap is required.</param>
		/// <param name="skipFrequency">Skip frequency. Normally 1, thus all gaps are taken into account. If 2, only every 2nd gap is taken into account, and so on.</param>
		/// <param name="connectCircular">If true, the end of the line is connected with the start of the line.</param>
		public override void Paint(
			IGraphicsContext3D g,
			Processed3DPlotData pdata,
			PlotRange range,
			IPlotArea layer,
			PenX3D pen,
			Func<int, double> symbolGap,
			int skipFrequency,
			bool connectCircular)
		{
			var linePoints = pdata.PlotPointsInAbsoluteLayerCoordinates;
			var linepts = new PointD3D[range.Length + (connectCircular ? 1 : 0)];
			Array.Copy(linePoints, range.LowerBound, linepts, 0, range.Length); // Extract
			if (connectCircular) linepts[linepts.Length - 1] = linepts[0];
			int lastIdx = range.Length - 1 + (connectCircular ? 1 : 0);
			var layerSize = layer.Size;

			if (symbolGap != null)
			{
				if (skipFrequency <= 1) // skip all scatter symbol gaps -> thus skipOffset can be ignored
				{
					for (int i = 0; i < lastIdx; i++)
					{
						int originalIndex = range.OffsetToOriginal + i;
						var diff = linepts[i + 1] - linepts[i];
						double gapAtStart = symbolGap(originalIndex);
						double gapAtEnd = i != (range.Length-1) ? symbolGap(originalIndex + 1) : symbolGap(range.OffsetToOriginal);
						var relAtStart = 0.5 * gapAtStart / diff.Length; // 0.5 because symbolGap is the full gap between two lines, thus between the symbol center and the beginning of the line it is only 1/2
						var relAtEnd = 0.5 * gapAtEnd / diff.Length; // 0.5 because symbolGap is the full gap between two lines, thus between the symbol center and the beginning of the line it is only 1/2
						if ((relAtStart + relAtEnd) < 1) // a line only appears if sum of the gaps  is smaller than 1
						{
							var start = linepts[i] + relAtStart * diff;
							var stop = linepts[i + 1] - relAtEnd * diff;

							g.DrawLine(pen, start, stop);
						}
					} // end for
				} // skipFrequency was 1
				else // skipFrequency is > 1
				{
					for (int i = 0; i < lastIdx; i += skipFrequency)
					{
						int originalRowIndex = range.OriginalFirstPoint + i;

						double gapAtStart = symbolGap(originalRowIndex);
						double gapAtEnd = i != range.Length ? symbolGap(originalRowIndex + skipFrequency) : symbolGap(range.OffsetToOriginal);

						IPolylineD3D polyline = SharpPolylineD3D.FromPointsWithPossibleDublettes(linepts.Skip(i).Take(1 + skipFrequency));
						polyline = polyline.ShortenedBy(RADouble.NewAbs(gapAtStart / 2), RADouble.NewAbs(gapAtEnd / 2));

						if (null != polyline)
							g.DrawLine(pen, polyline);
					} // end for.
				}
			}
			else // no line symbol gap required, so we can use DrawLines to draw the lines
			{
				if (linepts.Length > 1) // we don't want to have a drawing exception if number of points is only one
				{
					g.DrawLine(pen, SharpPolylineD3D.FromPointsWithPossibleDublettes(linepts));
				}
			}
		}
Esempio n. 10
0
		/// <summary>
		/// Initialization that is needed only once per straigth line (not once per dash).
		/// </summary>
		/// <param name="pen">The pen that is used to draw the line.</param>
		public void Initialize(
			PenX3D pen
			)
		{
			Initialize(
				pen.CrossSection,
				pen.Thickness1,
				pen.Thickness2,
				pen.LineJoin,
				pen.MiterLimit,
				pen.DashStartCap,
				pen.DashEndCap
				);
		}
Esempio n. 11
0
		public bool Apply(bool disposeController)
		{
			_doc = _view.Pen;
			return true;
		}
Esempio n. 12
0
		public PenAllPropertiesController(PenX3D doc)
		{
			_doc = doc;
			Initialize(true);
		}
Esempio n. 13
0
		public static bool AreEqualUnlessThickness(PenX3D pen1, PenX3D pen2)
		{
			bool isEqual =

				pen1.Material == pen2.Material &&
				pen1.CrossSection.GetType() == pen2.CrossSection.GetType() &&
				object.ReferenceEquals(pen1._dashPattern, pen2._dashPattern) && // Reference equality because DashPatterns parent list is determined by reference equality.
				object.Equals(pen1._lineStartCap, pen2._lineStartCap) &&
				object.Equals(pen1._lineEndCap, pen2._lineEndCap) &&
				object.Equals(pen1._dashStartCap, pen2._dashStartCap) &&
				object.Equals(pen1._dashEndCap, pen2._dashEndCap);

			return isEqual;
		}
Esempio n. 14
0
		public void AddGeometry(
		Action<PointD3D, VectorD3D> AddPositionAndNormal,
		Action<int, int, int, bool> AddIndices,
		ref int vertexIndexOffset,
		PenX3D pen,
		LineD3D line
		)
		{
			var westnorth = PolylineMath3D.GetWestNorthVectors(line);
			var westVector = westnorth.Item1;
			var northVector = westnorth.Item2;

			if (pen.DashPattern is DashPatterns.Solid)
			{
				// draw without a dash pattern - we consider the whole line as one dash segment, but instead of dash caps, with line caps
				_dashSegment.Initialize(pen.CrossSection, pen.Thickness1, pen.Thickness2, pen.LineStartCap, pen.LineEndCap, westVector, northVector, line);
				_dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, line, null, null);
			}
			else
			{
				// draw with a dash pattern
				_dashSegment.Initialize(pen, westVector, northVector, line);

				double dashOffset = 0;
				PointD3D lineStart = line.P0;
				PointD3D lineEnd = line.P1;

				var lineVector = line.LineVector;
				double lineLength = lineVector.Length;
				var lineVectorNormalized = lineVector / lineLength;

				// calculate the real start and end of the line, taking the line start and end cap length into account
				if (null != pen.LineStartCap)
				{
					var v = pen.LineStartCap.GetAbsoluteBaseInset(pen.Thickness1, pen.Thickness2);

					if (v < 0)
					{
						dashOffset = -v;
						lineStart += -v * lineVectorNormalized;
						lineLength += v;
					}
				}

				if (null != pen.LineEndCap)
				{
					var v = pen.LineEndCap.GetAbsoluteBaseInset(pen.Thickness1, pen.Thickness2);
					if (v < 0)
					{
						lineEnd += v * lineVectorNormalized;
						lineLength += v;
					}
				}

				// now draw the individual dash segments

				bool wasLineStartCapDrawn = false;
				bool wasLineEndCapDrawn = false;

				if (lineLength > 0)
				{
					foreach (var seg in Math3D.DissectStraightLineWithDashPattern(new LineD3D(lineStart, lineEnd), pen.DashPattern, pen.DashPattern.DashOffset, Math.Max(pen.Thickness1, pen.Thickness2), dashOffset))
					{
						if (seg.P0 == lineStart) // this is the start of the line, thus we must use the lineStartCap instead of the dashStartCap
						{
							_dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, seg, pen.LineStartCap, null);
							wasLineStartCapDrawn = true;
						}
						else if (seg.P1 == lineEnd) // this is the end of the line, thus we must use the lineEndCap instead of the dashEndCap
						{
							_dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, seg, null, pen.LineEndCap);
							wasLineEndCapDrawn = true;
						}
						else // this is a normal dashSegment, thus we can use dashStartCap and dashEndCap
						{
							_dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, seg, null, null);
						}
					}
				}

				object temporaryStorageSpace = null;

				// if the start cap was not drawn before, it must be drawn now
				if (!wasLineStartCapDrawn && null != pen.LineStartCap)
				{
					pen.LineStartCap.AddGeometry(
						AddPositionAndNormal,
						AddIndices,
						ref vertexIndexOffset,
						true,
						lineStart,
						westVector,
						northVector,
						lineVectorNormalized,
						pen.CrossSection,
						null,
						null,
						ref temporaryStorageSpace);
				}

				// if the end cap was not drawn before, it must be drawn now
				if (!wasLineEndCapDrawn && null != pen.LineEndCap)
				{
					pen.LineEndCap.AddGeometry(
						AddPositionAndNormal,
						AddIndices,
						ref vertexIndexOffset,
						false,
						lineEnd,
						westVector,
						northVector,
						lineVectorNormalized,
						pen.CrossSection,
						null,
						null,
						ref temporaryStorageSpace);
				}
			}
		}
Esempio n. 15
0
		private void EhBrush_SelectionChangeCommitted(object sender, EventArgs e)
		{
			if (_pen != null)
			{
				var oldPen = _pen;
				_pen = _pen.WithMaterial(_cbBrush.SelectedMaterial);
				if (!object.ReferenceEquals(_pen, oldPen))
					OnPenChanged();
			}
		}
Esempio n. 16
0
        public void AddGeometry(
            Action <PointD3D, VectorD3D> AddPositionAndNormal,
            Action <int, int, int, bool> AddIndices,
            ref int vertexIndexOffset,
            PenX3D pen,
            LineD3D line
            )
        {
            var westnorth   = PolylineMath3D.GetWestNorthVectors(line);
            var westVector  = westnorth.Item1;
            var northVector = westnorth.Item2;

            if (pen.DashPattern is DashPatterns.Solid)
            {
                // draw without a dash pattern - we consider the whole line as one dash segment, but instead of dash caps, with line caps
                _dashSegment.Initialize(pen.CrossSection, pen.Thickness1, pen.Thickness2, pen.LineStartCap, pen.LineEndCap, westVector, northVector, line);
                _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, line, null, null);
            }
            else
            {
                // draw with a dash pattern
                _dashSegment.Initialize(pen, westVector, northVector, line);

                double   dashOffset = 0;
                PointD3D lineStart  = line.P0;
                PointD3D lineEnd    = line.P1;

                var    lineVector           = line.LineVector;
                double lineLength           = lineVector.Length;
                var    lineVectorNormalized = lineVector / lineLength;

                // calculate the real start and end of the line, taking the line start and end cap length into account
                if (null != pen.LineStartCap)
                {
                    var v = pen.LineStartCap.GetAbsoluteBaseInset(pen.Thickness1, pen.Thickness2);

                    if (v < 0)
                    {
                        dashOffset  = -v;
                        lineStart  += -v * lineVectorNormalized;
                        lineLength += v;
                    }
                }

                if (null != pen.LineEndCap)
                {
                    var v = pen.LineEndCap.GetAbsoluteBaseInset(pen.Thickness1, pen.Thickness2);
                    if (v < 0)
                    {
                        lineEnd    += v * lineVectorNormalized;
                        lineLength += v;
                    }
                }

                // now draw the individual dash segments

                bool wasLineStartCapDrawn = false;
                bool wasLineEndCapDrawn   = false;

                if (lineLength > 0)
                {
                    foreach (var seg in Math3D.DissectStraightLineWithDashPattern(new LineD3D(lineStart, lineEnd), pen.DashPattern, pen.DashPattern.DashOffset, Math.Max(pen.Thickness1, pen.Thickness2), dashOffset))
                    {
                        if (seg.P0 == lineStart) // this is the start of the line, thus we must use the lineStartCap instead of the dashStartCap
                        {
                            _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, seg, pen.LineStartCap, null);
                            wasLineStartCapDrawn = true;
                        }
                        else if (seg.P1 == lineEnd) // this is the end of the line, thus we must use the lineEndCap instead of the dashEndCap
                        {
                            _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, seg, null, pen.LineEndCap);
                            wasLineEndCapDrawn = true;
                        }
                        else // this is a normal dashSegment, thus we can use dashStartCap and dashEndCap
                        {
                            _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, seg, null, null);
                        }
                    }
                }

                object temporaryStorageSpace = null;

                // if the start cap was not drawn before, it must be drawn now
                if (!wasLineStartCapDrawn && null != pen.LineStartCap)
                {
                    pen.LineStartCap.AddGeometry(
                        AddPositionAndNormal,
                        AddIndices,
                        ref vertexIndexOffset,
                        true,
                        lineStart,
                        westVector,
                        northVector,
                        lineVectorNormalized,
                        pen.CrossSection,
                        null,
                        null,
                        ref temporaryStorageSpace);
                }

                // if the end cap was not drawn before, it must be drawn now
                if (!wasLineEndCapDrawn && null != pen.LineEndCap)
                {
                    pen.LineEndCap.AddGeometry(
                        AddPositionAndNormal,
                        AddIndices,
                        ref vertexIndexOffset,
                        false,
                        lineEnd,
                        westVector,
                        northVector,
                        lineVectorNormalized,
                        pen.CrossSection,
                        null,
                        null,
                        ref temporaryStorageSpace);
                }
            }
        }
Esempio n. 17
0
		private void EhDashEndCap_SelectionChangeCommitted(object sender, EventArgs e)
		{
			if (_pen != null)
			{
				var cap = _cbDashEndCap.SelectedLineCap;
				if (_userChangedAbsDashEndCapSize && _cbDashEndCapAbsSize != null)
					cap = cap.WithMinimumAbsoluteAndRelativeSize(_cbDashEndCapAbsSize.SelectedQuantityAsValueInPoints, cap.MinimumRelativeSize);
				if (_userChangedRelDashEndCapSize && _cbDashEndCapRelSize != null)
					cap = cap.WithMinimumAbsoluteAndRelativeSize(cap.MinimumAbsoluteSizePt, _cbDashEndCapRelSize.SelectedQuantityAsValueInSIUnits);

				_pen = _pen.WithDashEndCap(cap);

				if (_cbDashEndCapAbsSize != null)
				{
					var oldValue = _userChangedAbsDashEndCapSize;
					_cbDashEndCapAbsSize.SelectedQuantityAsValueInPoints = cap.MinimumAbsoluteSizePt;
					_userChangedAbsDashEndCapSize = oldValue;
				}
				if (_cbDashEndCapRelSize != null)
				{
					var oldValue = _userChangedRelDashEndCapSize;
					_cbDashEndCapRelSize.SelectedQuantityAsValueInSIUnits = cap.MinimumRelativeSize;
					_userChangedRelDashEndCapSize = oldValue;
				}

				OnPenChanged();
			}
		}
Esempio n. 18
0
		private void EhDashStartCapAbsSize_SelectionChangeCommitted(object sender, DependencyPropertyChangedEventArgs e)
		{
			_userChangedAbsDashStartCapSize = true;

			if (_pen != null)
			{
				var cap = _pen.DashStartCap;

				if (null != cap)
				{
					cap = cap.WithMinimumAbsoluteAndRelativeSize(_cbDashStartCapAbsSize.SelectedQuantityAsValueInPoints, cap.MinimumRelativeSize);
				}

				_pen = _pen.WithDashStartCap(cap);

				OnPenChanged();
			}
		}
Esempio n. 19
0
		private void EhThickness2_ChoiceChanged(object sender, DependencyPropertyChangedEventArgs e)
		{
			if (_pen != null)
			{
				var oldPen = _pen;
				_pen = _pen.WithThickness2(_cbThickness2.SelectedQuantityAsValueInPoints);

				if (!object.ReferenceEquals(_pen, oldPen))
					OnPenChanged();
			}
		}
Esempio n. 20
0
		private void EhDashPattern_SelectionChangeCommitted(object sender, EventArgs e)
		{
			if (_pen != null)
			{
				var oldPen = _pen;
				_pen = _pen.WithDashPattern(_cbDashPattern.SelectedItem);
				if (!object.ReferenceEquals(_pen, oldPen))
					OnPenChanged();
			}
		}
Esempio n. 21
0
		private void EhCrossSection_SelectionChangeCommitted(object sender, EventArgs e)
		{
			if (_pen != null)
			{
				var node = (SelectableListNode)_cbCrossSection.SelectedValue;
				if (null != node)
				{
					var type = (Type)node.Tag;
					var crossSection = (ICrossSectionOfLine)Activator.CreateInstance(type);
					crossSection = crossSection.WithSize(_pen.Thickness1, _pen.Thickness2);
					var oldPen = _pen;
					_pen = _pen.WithCrossSection(crossSection);
					if (!object.ReferenceEquals(_pen, oldPen))
						OnPenChanged();
				}
			}
		}
Esempio n. 22
0
    public void AddWithNormals(
    Action<PointD3D, VectorD3D> AddPositionAndNormal,
    Action<int, int, int, bool> AddIndices,
    ref int vertexIndexOffset,
    PenX3D pen,
    IList<PointD3D> polylinePoints
    )
    {
      if (pen.DashPattern is DashPatterns.Solid)
      {
        // draw without a dash pattern - we consider the whole line as one dash segment, but instead of dash caps, with line caps
        _dashSegment.Initialize(pen.CrossSection, pen.Thickness1, pen.Thickness2, pen.LineJoin, pen.MiterLimit, pen.LineStartCap, pen.LineEndCap);
        var westNorth = PolylineMath3D.GetWestNorthVectorAtStart(polylinePoints);
        _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, polylinePoints, westNorth.WestVector, westNorth.NorthVector, westNorth.ForwardVector, null, null);
      }
      else
      {
        // draw with a dash pattern
        _dashSegment.Initialize(pen);

        double dashOffset = 0;

        bool startCapForwardAndPositionProvided = false;
        bool startCapNeedsJoinSegment = false;
        var startCapCOS = new PolylinePointD3DAsClass();
        bool endCapForwardAndPositionProvided = false;
        bool endCapNeedsJoinSegment = false;
        var endCapCOS = new PolylinePointD3DAsClass();

        double startIndex = 0;
        double endIndex = polylinePoints.Count - 1;

        // calculate the real start and end of the line, taking the line start and end cap length into account
        if (null != pen.LineStartCap)
        {
          var v = pen.LineStartCap.GetAbsoluteBaseInset(pen.Thickness1, pen.Thickness2);

          if (v < 0)
          {
            dashOffset = -v;

            startIndex = PolylineMath3D.GetFractionalStartIndexOfPolylineWithCapInsetAbsolute(
              polylinePoints,
              -v,
              out startCapForwardAndPositionProvided,
              out startCapNeedsJoinSegment,
              startCapCOS);
          }
        }

        if (null != pen.LineEndCap)
        {
          var v = pen.LineEndCap.GetAbsoluteBaseInset(pen.Thickness1, pen.Thickness2);
          if (v < 0)
          {
            endIndex = PolylineMath3D.GetFractionalEndIndexOfPolylineWithCapInsetAbsolute(
              polylinePoints,
              -v,
              out endCapForwardAndPositionProvided,
              out endCapNeedsJoinSegment,
              endCapCOS);
          }
        }

        // now draw the individual dash segments

        bool wasLineStartCapDrawn = false;
        bool wasLineEndCapDrawn = false;

        var en = PolylineMath3D.DissectPolylineWithDashPattern(
              polylinePoints,
              startIndex, endIndex,
              pen.DashPattern,
              pen.DashPattern.DashOffset,
              Math.Max(pen.Thickness1, pen.Thickness2),
              dashOffset,
              startCapForwardAndPositionProvided,
              startCapNeedsJoinSegment,
              startCapCOS,
              endCapForwardAndPositionProvided,
              endCapNeedsJoinSegment,
              endCapCOS
              ).GetEnumerator();

        if (!en.MoveNext())
        {
          // there is no segment at all in the list, but maybe we can draw the start and end line caps
        }
        else
        {
          var previousPointList = en.Current;
          var currentPointList = en.Current;

          if (en.MoveNext())
            currentPointList = en.Current;
          else
            currentPointList = null;

          // if current point list is null, then there is only one segment, namely previousPointList, we have to draw it with start line cap and end line cap.
          if (currentPointList == null)
          {
            // note start line cap and end line cap will be overridden for this segment, but only then if the seamless merge with the dash segment
            bool overrideLineStartCap = startCapForwardAndPositionProvided && previousPointList[0].Position == startCapCOS.Position;
            bool overrideLineEndCap = endCapForwardAndPositionProvided && previousPointList[previousPointList.Count - 1].Position == endCapCOS.Position;
            _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, previousPointList, overrideLineStartCap ? pen.LineStartCap : null, overrideLineEndCap ? pen.LineEndCap : null);
            wasLineStartCapDrawn = overrideLineStartCap;
            wasLineEndCapDrawn = overrideLineEndCap;
          }
          else // there are at least two segments
          {
            // this is the start of the line, thus we must use the lineStartCap instead of the dashStartCap

            // note start line cap will be overridden for this first segment, but only then if it seamlessly merge with the start of the dash segment
            bool overrideLineStartCap = startCapForwardAndPositionProvided && previousPointList[0].Position == startCapCOS.Position;
            _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, previousPointList, overrideLineStartCap ? pen.LineStartCap : null, null);
            wasLineStartCapDrawn = overrideLineStartCap;

            previousPointList = currentPointList;
            while (en.MoveNext())
            {
              var currentList = en.Current;

              // draw the previous list as a normal dashSegment, thus we can use dashStartCap and dashEndCap
              _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, previousPointList, null, null);
              previousPointList = currentList;
            }

            // now currentList is the last list, we can draw an endcap to this
            bool overrideLineEndCap = endCapForwardAndPositionProvided && previousPointList[previousPointList.Count - 1].Position == endCapCOS.Position;
            _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, previousPointList, null, overrideLineEndCap ? pen.LineEndCap : null);
            wasLineEndCapDrawn = overrideLineEndCap;
          }

          object temporaryStorageSpace = null;

          // if the start cap was not drawn before, it must be drawn now
          if (!wasLineStartCapDrawn && null != pen.LineStartCap)
          {
            pen.LineStartCap.AddGeometry(
              AddPositionAndNormal,
              AddIndices,
              ref vertexIndexOffset,
              true,
              startCapCOS.Position,
              startCapCOS.WestVector,
              startCapCOS.NorthVector,
              startCapCOS.ForwardVector,
              pen.CrossSection,
              null,
              null,
              ref temporaryStorageSpace);
          }

          // if the end cap was not drawn before, it must be drawn now
          if (!wasLineEndCapDrawn && null != pen.LineEndCap)
          {
            pen.LineEndCap.AddGeometry(
              AddPositionAndNormal,
              AddIndices,
              ref vertexIndexOffset,
              false,
              endCapCOS.Position,
              endCapCOS.WestVector,
              endCapCOS.NorthVector,
              endCapCOS.ForwardVector,
              pen.CrossSection,
              null,
              null,
              ref temporaryStorageSpace);
          }
        }
      }
    }
Esempio n. 23
0
		private void EhLineJoin_SelectionChangeCommitted(object sender, EventArgs e)
		{
			if (_pen != null)
			{
				_pen = _pen.WithLineJoin(_cbLineJoin.SelectedLineJoin);

				OnPenChanged();
			}
		}
Esempio n. 24
0
		public void AddWithNormals(
		Action<PointD3D, VectorD3D> AddPositionAndNormal,
		Action<int, int, int, bool> AddIndices,
		ref int vertexIndexOffset,
		PenX3D pen,
		IList<PointD3D> polylinePoints
		)
		{
			if (pen.DashPattern is DashPatterns.Solid)
			{
				// draw without a dash pattern - we consider the whole line as one dash segment, but instead of dash caps, with line caps
				_dashSegment.Initialize(pen.CrossSection, pen.Thickness1, pen.Thickness2, pen.LineJoin, pen.MiterLimit, pen.LineStartCap, pen.LineEndCap);
				var westNorth = PolylineMath3D.GetWestNorthVectorAtStart(polylinePoints);
				_dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, polylinePoints, westNorth.WestVector, westNorth.NorthVector, westNorth.ForwardVector, null, null);
			}
			else
			{
				// draw with a dash pattern
				_dashSegment.Initialize(pen);

				double dashOffset = 0;

				bool startCapForwardAndPositionProvided = false;
				bool startCapNeedsJoinSegment = false;
				PolylinePointD3DAsClass startCapCOS = new PolylinePointD3DAsClass();
				bool endCapForwardAndPositionProvided = false;
				bool endCapNeedsJoinSegment = false;
				PolylinePointD3DAsClass endCapCOS = new PolylinePointD3DAsClass();

				double startIndex = 0;
				double endIndex = polylinePoints.Count - 1;

				// calculate the real start and end of the line, taking the line start and end cap length into account
				if (null != pen.LineStartCap)
				{
					var v = pen.LineStartCap.GetAbsoluteBaseInset(pen.Thickness1, pen.Thickness2);

					if (v < 0)
					{
						dashOffset = -v;

						startIndex = PolylineMath3D.GetFractionalStartIndexOfPolylineWithCapInsetAbsolute(
							polylinePoints,
							-v,
							out startCapForwardAndPositionProvided,
							out startCapNeedsJoinSegment,
							startCapCOS);
					}
				}

				if (null != pen.LineEndCap)
				{
					var v = pen.LineEndCap.GetAbsoluteBaseInset(pen.Thickness1, pen.Thickness2);
					if (v < 0)
					{
						endIndex = PolylineMath3D.GetFractionalEndIndexOfPolylineWithCapInsetAbsolute(
							polylinePoints,
							-v,
							out endCapForwardAndPositionProvided,
							out endCapNeedsJoinSegment,
							endCapCOS);
					}
				}

				// now draw the individual dash segments

				bool wasLineStartCapDrawn = false;
				bool wasLineEndCapDrawn = false;

				var en = PolylineMath3D.DissectPolylineWithDashPattern(
							polylinePoints,
							startIndex, endIndex,
							pen.DashPattern,
							pen.DashPattern.DashOffset,
							Math.Max(pen.Thickness1, pen.Thickness2),
							dashOffset,
							startCapForwardAndPositionProvided,
							startCapNeedsJoinSegment,
							startCapCOS,
							endCapForwardAndPositionProvided,
							endCapNeedsJoinSegment,
							endCapCOS
							).GetEnumerator();

				if (!en.MoveNext())
				{
					// there is no segment at all in the list, but maybe we can draw the start and end line caps
				}
				else
				{
					var previousPointList = en.Current;
					var currentPointList = en.Current;

					if (en.MoveNext())
						currentPointList = en.Current;
					else
						currentPointList = null;

					// if current point list is null, then there is only one segment, namely previousPointList, we have to draw it with start line cap and end line cap.
					if (currentPointList == null)
					{
						// note start line cap and end line cap will be overridden for this segment, but only then if the seamless merge with the dash segment
						bool overrideLineStartCap = startCapForwardAndPositionProvided && previousPointList[0].Position == startCapCOS.Position;
						bool overrideLineEndCap = endCapForwardAndPositionProvided && previousPointList[previousPointList.Count - 1].Position == endCapCOS.Position;
						_dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, previousPointList, overrideLineStartCap ? pen.LineStartCap : null, overrideLineEndCap ? pen.LineEndCap : null);
						wasLineStartCapDrawn = overrideLineStartCap;
						wasLineEndCapDrawn = overrideLineEndCap;
					}
					else // there are at least two segments
					{
						// this is the start of the line, thus we must use the lineStartCap instead of the dashStartCap

						// note start line cap will be overridden for this first segment, but only then if it seamlessly merge with the start of the dash segment
						bool overrideLineStartCap = startCapForwardAndPositionProvided && previousPointList[0].Position == startCapCOS.Position;
						_dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, previousPointList, overrideLineStartCap ? pen.LineStartCap : null, null);
						wasLineStartCapDrawn = overrideLineStartCap;

						previousPointList = currentPointList;
						while (en.MoveNext())
						{
							var currentList = en.Current;

							// draw the previous list as a normal dashSegment, thus we can use dashStartCap and dashEndCap
							_dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, previousPointList, null, null);
							previousPointList = currentList;
						}

						// now currentList is the last list, we can draw an endcap to this
						bool overrideLineEndCap = endCapForwardAndPositionProvided && previousPointList[previousPointList.Count - 1].Position == endCapCOS.Position;
						_dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, previousPointList, null, overrideLineEndCap ? pen.LineEndCap : null);
						wasLineEndCapDrawn = overrideLineEndCap;
					}

					object temporaryStorageSpace = null;

					// if the start cap was not drawn before, it must be drawn now
					if (!wasLineStartCapDrawn && null != pen.LineStartCap)
					{
						pen.LineStartCap.AddGeometry(
							AddPositionAndNormal,
							AddIndices,
							ref vertexIndexOffset,
							true,
							startCapCOS.Position,
							startCapCOS.WestVector,
							startCapCOS.NorthVector,
							startCapCOS.ForwardVector,
							pen.CrossSection,
							null,
							null,
							ref temporaryStorageSpace);
					}

					// if the end cap was not drawn before, it must be drawn now
					if (!wasLineEndCapDrawn && null != pen.LineEndCap)
					{
						pen.LineEndCap.AddGeometry(
							AddPositionAndNormal,
							AddIndices,
							ref vertexIndexOffset,
							false,
							endCapCOS.Position,
							endCapCOS.WestVector,
							endCapCOS.NorthVector,
							endCapCOS.ForwardVector,
							pen.CrossSection,
							null,
							null,
							ref temporaryStorageSpace);
					}
				}
			}
		}
		public ColorTypeThicknessPenController(PenX3D doc)
		{
			if (doc == null) throw new ArgumentNullException("doc");
			_doc = doc;
			_tempDoc = _doc;
		}