public virtual object Clone() { PathToolSegment newSeg = new PathToolSegment(); CopyTo(newSeg); return(newSeg); }
public virtual void CopyTo(PathToolSegment other) { StartAnchor.CopyDataValues(other.StartAnchor); EndAnchor.CopyDataValues(other.EndAnchor); other.Name = Name; }
public override bool IsAlertConditionTrue(AlertConditionItem conditionItem, Condition condition, ChartAlertValue[] values, ChartControl chartControl, ChartScale chartScale) { PathToolSegment segAnchors = conditionItem.Tag as PathToolSegment; if (segAnchors == null) { return(false); } ChartPanel chartPanel = chartControl.ChartPanels[PanelIndex]; Point lineStartPoint = segAnchors.StartAnchor.GetPoint(chartControl, chartPanel, chartScale); Point lineEndPoint = segAnchors.EndAnchor.GetPoint(chartControl, chartPanel, chartScale); double minLineX = double.MaxValue; double maxLineX = double.MinValue; foreach (Point point in new[] { lineStartPoint, lineEndPoint }) { minLineX = Math.Min(minLineX, point.X); maxLineX = Math.Max(maxLineX, point.X); } // first thing, if our smallest x is greater than most recent bar, we have nothing to do yet. // do not try to check Y because lines could cross through stuff double firstBarX = values[0].ValueType == ChartAlertValueType.StaticValue ? minLineX : chartControl.GetXByTime(values[0].Time); double firstBarY = chartScale.GetYByValue(values[0].Value); // dont have to take extension into account as its already handled in min/max line x // bars completely passed our line if (maxLineX < firstBarX) { return(false); } // bars not yet to our line if (minLineX > firstBarX) { return(false); } // NOTE: normalize line points so the leftmost is passed first. Otherwise, our vector // math could end up having the line normal vector being backwards if user drew it backwards. // but we dont care the order of anchors, we want 'up' to mean 'up'! Point leftPoint = lineStartPoint.X < lineEndPoint.X ? lineStartPoint : lineEndPoint; Point rightPoint = lineEndPoint.X > lineStartPoint.X ? lineEndPoint : lineStartPoint; Point barPoint = new Point(firstBarX, firstBarY); // NOTE: 'left / right' is relative to if line was vertical. it can end up backwards too MathHelper.PointLineLocation pointLocation = MathHelper.GetPointLineLocation(leftPoint, rightPoint, barPoint); // for vertical things, think of a vertical line rotated 90 degrees to lay flat, where it's normal vector is 'up' switch (condition) { case Condition.Greater: return(pointLocation == MathHelper.PointLineLocation.LeftOrAbove); case Condition.GreaterEqual: return(pointLocation == MathHelper.PointLineLocation.LeftOrAbove || pointLocation == MathHelper.PointLineLocation.DirectlyOnLine); case Condition.Less: return(pointLocation == MathHelper.PointLineLocation.RightOrBelow); case Condition.LessEqual: return(pointLocation == MathHelper.PointLineLocation.RightOrBelow || pointLocation == MathHelper.PointLineLocation.DirectlyOnLine); case Condition.Equals: return(pointLocation == MathHelper.PointLineLocation.DirectlyOnLine); case Condition.NotEqual: return(pointLocation != MathHelper.PointLineLocation.DirectlyOnLine); case Condition.CrossAbove: case Condition.CrossBelow: Predicate <ChartAlertValue> predicate = v => { double barX = chartControl.GetXByTime(v.Time); double barY = chartScale.GetYByValue(v.Value); Point stepBarPoint = new Point(barX, barY); MathHelper.PointLineLocation ptLocation = MathHelper.GetPointLineLocation(leftPoint, rightPoint, stepBarPoint); if (condition == Condition.CrossAbove) { return(ptLocation == MathHelper.PointLineLocation.LeftOrAbove); } return(ptLocation == MathHelper.PointLineLocation.RightOrBelow); }; return(MathHelper.DidPredicateCross(values, predicate)); } return(false); }