public Ray(IRay r) { this.Org = r.Origin; this.Dir = r.Direction; this.maxT = r.Max; this.minT = r.Min; }
public static IList<Point> GetIntersects(IRay line1, IRay line2) { IList<Point> list = new List<Point>(); Point p1 = new Point(line1.Point.X, line1.Point.Y); Point p2 = new Point(line1.Point.X + line1.Vector.X, line1.Point.Y + line1.Vector.Y); Point q1 = new Point(line2.Point.X, line2.Point.Y); Point q2 = new Point(line2.Point.X + line2.Vector.X, line2.Point.Y + line2.Vector.Y); double x21 = p2.X - p1.X; double y21 = p2.Y - p1.Y; double x31 = q1.X - p1.X; double y31 = q1.Y - p1.Y; double x43 = q2.X - q1.X; double y43 = q2.Y - q1.Y; double paramDenominator = x43 * y21 - x21 * y43; double s = (x43 * y31 - x31 * y43) / paramDenominator; double x = p1.X + (p2.X - p1.X) * s; double y = p1.Y + (p2.Y - p1.Y) * s; list.Add(new Point(x, y)); return list; }
public static Optional<IBody> RaySelect(this IUniverse uni, Vector3 origin, Vector3 dir, IRay rayCastProvider = null) { if (rayCastProvider == null) rayCastProvider = new Ray(); double furthestBodyPos = uni.Bodies.Max(b => (b.Position() - origin).Magnitude) + 100; // need to tune this. need to basically find the max dimension size of the biggest object var res = rayCastProvider.Cast(uni.Bodies.Select(b => new TransformedObj<IEdgeIntersector>(b.Dynamics.Transform, b.CollisionShape)), origin, dir, furthestBodyPos); return res.Match( hit => uni.Bodies.Single(b => b.CollisionShape == hit.HitObject.Obj).ToOptional(), () => Optional<IBody>.Nothing ); }
public static IList<Point> GetIntersects(ICircle circle, IRay line) { IList<Point> list = new List<Point>(); double a = Math.Pow(line.Vector.X, 2) + Math.Pow(line.Vector.Y, 2); double b = 2 * (line.Vector.X * (line.Point.X - circle.Center.X) + line.Vector.Y * (line.Point.Y - circle.Center.Y)); double c = Math.Pow(circle.Center.X, 2) + Math.Pow(circle.Center.Y, 2); c += Math.Pow(line.Point.X, 2) + Math.Pow(line.Point.Y, 2); c -= 2 * (circle.Center.X * line.Point.X + circle.Center.Y * line.Point.Y); c -= Math.Pow(circle.Radius, 2); double bb4ac = b * b - 4 * a * c; if (bb4ac < 0) return list; else if (bb4ac == 0) { double mu = -b / (2 * a); Point intersectionPoint = new Point(line.Point.X + mu * line.Vector.X, line.Point.Y + mu * line.Vector.Y); list.Add(intersectionPoint); } else { double mu = -b + Math.Sqrt(bb4ac) / (2 * a); Point intersectionPoint1 = new Point(line.Point.X + mu * line.Vector.X, line.Point.Y + mu * line.Vector.Y); mu = -b - Math.Sqrt(bb4ac) / (2 * a); Point intersectionPoint2 = new Point(line.Point.X + mu * line.Vector.X, line.Point.Y + mu * line.Vector.Y); list.Add(intersectionPoint1); list.Add(intersectionPoint2); } return list; }
/// <summary> Sample the <paramref name="scene"/> with a <paramref name="sample"/> returning a color found </summary> /// <param name="scene">The <see cref="IScene"/> to sample </param> /// <param name="ray">The <see cref="Ir4"/> to trace through the <paramref name="scene"/> </param> /// <param name="spectrum">The throughput <see cref="ISpectrum"/></param> /// <param name="recursionDepth">The depth of recursion</param> /// <returns>The color found for the <see cref="ISample"/></returns> public ISpectrum Sample(IScene scene, IRay ray, ISpectrum spectrum, int recursionDepth) { if (spectrum.Equals(ISpectrum.Black)) { return(ISpectrum.Black); } /// Russian Roulette float throughput = 1f; if (recursionDepth >= GauranteedRecursionDepth) { if (Utils.ThreadRandom.NextSingle() < RussianRouletteChance) { return(ISpectrum.Black); } else { throughput = 1f / RussianRouletteChance; } } /// Sample Distance IDistanceQuery?distanceQuery = scene.Trace(ray, spectrum); if (distanceQuery is null) { return(ISpectrum.Black); } Position1 distance = distanceQuery.DistanceDistribution.Sample(Utils.ThreadRandom); if (distance == Position1.PositiveInfinity) { return(ISpectrum.Black); } /// Sample Primitive IProbabilityDistribution <IPrimitive>?primitives = distanceQuery.TryGetPrimitives(distance); if (primitives is null) { throw new InvalidOperationException("Distance was sampled but no primitive was found"); } IPrimitive primitive = primitives.Sample(Utils.ThreadRandom); /// Get Intersection Position Position3 position = primitive.Material.DensityProfile.GetPosition(ray, distance, primitive.Shape); /// Sample Material Orientation IProbabilityDistribution <Normal3>?orientations = primitive.Material.OrientationProfile.GetOrientations(position, ray.Direction, primitive.Shape); if (orientations is null) { return(ISpectrum.Black); } Normal3 orientation = orientations.Sample(Utils.ThreadRandom); /// Get Direct Illumination ISpectrum directIllumination = RGBColors.Black; if (primitive.Material.EmittanceProfile.IsEmitting) { directIllumination = primitive.Material.EmittanceProfile.GetEmittance(position, orientation, -ray.Direction); } /// Get Indirect Illumination ISpectrum indirectIllumination = RGBColors.Black; if (!primitive.Material.AbsorptionProfile.IsBlackBody) { /// Sample Direction IProbabilityDistribution <Normal3> directions = primitive.Material.ReflectionProfile.GetDirections(ray.Direction, position, orientation, spectrum); Normal3 direction = directions.Sample(Utils.ThreadRandom); /// Get Albedo ISpectrum albedo = primitive.Material.AbsorptionProfile.GetAlbedo(position, orientation, -direction); /// Get Ray IRay raySample = primitive.Material.DensityProfile.GetRay(position, orientation, direction); /// Sample Indirect Illumination indirectIllumination = albedo * Sample(scene, raySample, spectrum * albedo, recursionDepth + 1); } /// Light Throughput Calculation return((directIllumination + indirectIllumination) * throughput); }
public void Sample(float x, float y, float u0, float u1, float u2, out IRay ray, out float pdf) { throw new NotImplementedException(); }
/// <summary> /// Highlights/Unhighlights Gizmo drawables on mouse roll-over /// </summary> /// <param name="clickRay"></param> private void HighlightGizmoOnRollOver(IRay clickRay) { var gizmos = GetGizmos(false); foreach (var item in gizmos) { item.UnhighlightGizmo(BackgroundPreviewViewModel); object hitObject; if (item.HitTest(clickRay.GetOriginPoint(), clickRay.GetDirectionVector(), out hitObject)) { item.HighlightGizmo(BackgroundPreviewViewModel, RenderPackageFactory); } } }
public void GetRay(double xp, double yp, out IRay cameraRay) { var u = (float)(2.0f * xp / w - 1.0f); var v = (float)(1.0f - 2.0f * yp / h); Vector rdir = mRight * u + mUp * v + this.Look; var rorig = (Position + rdir * 0.1f); rdir.Normalize(); cameraRay = new RayData(rorig, rdir); }
public static Point? GetNearest(IRay i, Point p) { var ps = GetIntersections(i, new Ray2D(p, p + i.Vector.GetNormal())); return ps.Count == 1 ? new Point?(ps[0]) : null; }
public Position3 GetPosition(IRay ray, Position1 distance, IShape shape) { return(shape.IntersectPosition(ray, distance)); }
public IDistanceDistribution?GetDistances(IRay ray, ISpectrum spectrum, IInterval interval) { return(ray.WithinBounds(interval.Entry) ? new DeltaDistance(interval.Entry) : null); }
/// <summary> /// Returns an Enumerable enumerating the ray /// </summary> public static IEnumerable <TPayload> ToEnumerable <TPayload>(this IRay <TPayload> ray) => new RayEnumerableAdapter <TPayload>(ray);
public void Sample(float x, float y, float u0, float u1, float u2, out IRay ray, out float pdf) { pdf = 1f; GetRay(x,y, out ray); }
public void GetRay(double x, double y, out IRay cameraRay) { RayData r; this.GetRay(x, y, out r); cameraRay = r; }
/// <summary> Handle input for the <see cref="InteractiveObserver"/> </summary> /// <param name="keyboard">The <see cref="KeyboardState"/> to handle input from</param> /// <param name="mouse">The <see cref="MouseState"/> to handle input from</param> public void HandleInput(KeyboardState keyboard, MouseState mouse) { if (keyboard.IsKeyPressed(Keys.F1)) { Drawing = Drawing.Next(); } if (keyboard.IsKeyPressed(Keys.F2)) { Debug = Debug.Next(); } if (keyboard.IsKeyPressed(Keys.F3)) { TextColor = 0xffffff - TextColor; } if (keyboard.IsKeyPressed(Keys.L)) { CameraLock = !CameraLock; } if (!CameraLock) { if (mouse.WasButtonDown(MouseButton.Left) && !mouse.IsButtonDown(MouseButton.Left)) { Vector2 position = new((float)mouse.X / Screen.Width, (float)mouse.Y / Screen.Height); IRay ray = Camera.GetCameraRay(position, position); Camera.SetViewDirection(ray.Direction); } if (keyboard.IsKeyDown(Keys.Space)) { Camera.Move(Camera.Up * MoveSpeed); } if (keyboard.IsKeyDown(Keys.LeftShift)) { Camera.Move(Camera.Down * MoveSpeed); } if (keyboard.IsKeyDown(Keys.W)) { Camera.Move(Camera.Front * MoveSpeed); } if (keyboard.IsKeyDown(Keys.A)) { Camera.Move(Camera.Left * MoveSpeed); } if (keyboard.IsKeyDown(Keys.S)) { Camera.Move(Camera.Back * MoveSpeed); } if (keyboard.IsKeyDown(Keys.D)) { Camera.Move(Camera.Right * MoveSpeed); } if (keyboard.IsKeyPressed(Keys.Equal)) { Camera.HorizontalFOV *= 1f + FOVSensitivity; } if (keyboard.IsKeyPressed(Keys.Minus)) { Camera.HorizontalFOV /= 1f + FOVSensitivity; } if (keyboard.IsKeyDown(Keys.Up)) { Camera.Rotate(Normal3.DefaultRight, -RotateSensitivity); } if (keyboard.IsKeyDown(Keys.Down)) { Camera.Rotate(Normal3.DefaultRight, RotateSensitivity); } if (keyboard.IsKeyDown(Keys.Right)) { Camera.Rotate(Normal3.DefaultUp, RotateSensitivity); } if (keyboard.IsKeyDown(Keys.Left)) { Camera.Rotate(Normal3.DefaultUp, -RotateSensitivity); } if (keyboard.IsKeyDown(Keys.Q)) { Camera.Rotate(Normal3.DefaultFront, RotateSensitivity); } if (keyboard.IsKeyDown(Keys.E)) { Camera.Rotate(Normal3.DefaultFront, -RotateSensitivity); } } }
public static IList<Point> GetIntersects(ISegment line1, IRay line2) { IList<Point> list = new List<Point>(); Ray2D Ray = new Ray2D(line1.StartPoint, line1.EndPoint); IList<Point> intersect = line2.Intersection(Ray); if (intersect.Count > 0 && ( intersect[0].X > Math.Min(line1.StartPoint.X, line1.EndPoint.X) && intersect[0].X < Math.Max(line1.StartPoint.X, line1.EndPoint.X) && intersect[0].Y > Math.Min(line1.StartPoint.Y, line1.EndPoint.Y) && intersect[0].Y < Math.Max(line1.StartPoint.Y, line1.EndPoint.Y) ) ) { list.Add(intersect[0]); } return list; }
public static IList<Point> GetIntersects(IRay line, IPoint point) { IList<Point> list = new List<Point>(); double c = -(line.Vector.X * line.Point.X) - (line.Vector.Y * line.Point.Y); if ((line.Vector.X * point.X + line.Vector.Y * point.Y + c).IsEqual(0)) { list.Add(new Point(point.X, point.Y)); } return list; }
public IEnumerable <Position1> IntersectDistances(IRay ray) { return((BoundingBox as IIntersectable).Intersects(ray) ? OriginalShape.IntersectDistances(ray) : Enumerable.Empty <Position1>()); }
/// <summary> /// Constructor /// </summary> public RayEnumerableAdapter(IRay <TPayload> ray) : base(ray.Origin) { }
public static Point GetOriginPoint(this IRay ray) { return(ray.Origin.ToPoint()); }
public void GetRay(double x, double y, out IRay cameraRay) { throw new NotImplementedException(); }
public static Vector GetDirectionVector(this IRay ray) { return(ray.Direction.ToVector()); }
/// <summary> /// Highlights/Unhighlights Gizmo drawables on mouse roll-over /// </summary> /// <param name="clickRay"></param> private void HighlightGizmoOnRollOver(IRay clickRay) { var gizmos = GetGizmos(false); foreach (var item in gizmos) { item.UnhighlightGizmo(); using (var originPt = clickRay.GetOriginPoint()) using (var dirVec = clickRay.GetDirectionVector()) { object hitObject; if (item.HitTest(originPt, dirVec, out hitObject)) { item.HighlightGizmo(); return; } } } }
/// <summary> /// Called on each bar update event (incoming tick) /// </summary> protected override void OnBarUpdate() { //If we are not processing the current bar, return if (CurrentBar != Bars.GetBar(DateTime.Now)) { return; } //Get current bid double bid = Bars.GetClose(Bars.GetBar(DateTime.Now)); if (previous_bid < 0) { previous_bid = bid; } IDrawObject drawing_object = DrawObjects[trendLineTag]; //Reset if drawing object is deleted or does not exist... if (drawing_object == null) { Type = null; AlertDone = false; } if (drawing_object != null && (drawing_object.DrawType == DrawType.Ray || drawing_object.DrawType == DrawType.ExtendedLine || drawing_object.DrawType == DrawType.Line)) { double y1, y2; int bar1, bar2; DateTime time1, time2; if (drawing_object.DrawType == DrawType.Ray) { IRay ray = (IRay)drawing_object; y1 = ray.Anchor1Y; y2 = ray.Anchor2Y; time1 = ray.Anchor1Time; time2 = ray.Anchor2Time; bar1 = ray.Anchor1BarsAgo; bar2 = ray.Anchor2BarsAgo; } else if (drawing_object.DrawType == DrawType.ExtendedLine) { IExtendedLine line = (IExtendedLine)drawing_object; y1 = line.StartY; y2 = line.EndY; time1 = line.StartTime; time2 = line.EndTime; bar1 = line.StartBarsAgo; bar2 = line.EndBarsAgo; } else { ILine line = (ILine)drawing_object; y1 = line.StartY; y2 = line.EndY; time1 = line.StartTime; time2 = line.EndTime; bar1 = line.StartBarsAgo; bar2 = line.EndBarsAgo; } //Reset alert if object has moved if ((time1 != this.sTime1 || time2 != this.sTime2 || y1 != this.sY1 || y2 != this.sY2) && this.sTime1 != null && this.sTime2 != null) { Type = null; AlertDone = false; } if (AlertDone == false) { //Store anchor to detect if object has moved this.sTime1 = time1; this.sTime2 = time2; this.sY1 = y1; this.sY2 = y2; //Calculate price target double y = y2 - y1; double x = bar1 - bar2; double slope = y / x; double deltaY = bar2 * slope; //time difference in ticks * slope double price_target = Math.Round(y2 + deltaY, 5); //IF price is below current price target or straddles it, THEN we alert when the bid>=price_target if (Type == null && (price_target - previous_bid) >= 0) { Type = "up"; } if (Type == null && (previous_bid - price_target) >= 0) { Type = "down"; } previous_bid = bid; if (Type == "up" && bid >= price_target) { Alert("TrendLineAlert", NinjaTrader.Cbi.Priority.High, "Reached Trend Line @ " + price_target, AlertSound, 10, Color.Black, Color.Yellow); AlertDone = true; } if (Type == "down" && bid <= price_target) { Alert("TrendLineAlert", NinjaTrader.Cbi.Priority.High, "Reached Trend Line @ " + price_target, AlertSound, 10, Color.Black, Color.Yellow); AlertDone = true; } } } }
public void GetRay(double x, double y, out IRay cameraRay) { cameraRay = this.GetRay((float)x, (float)y); }
public Position3 GetPosition(IRay ray, Position1 distance, IShape shape) { return(ray.Travel(distance)); }
public void Sample(float xp, float yp, float u0, float u1, float u2, out IRay r, out float pdf) { Point Pras = new Point(xp, yp, 0); //Point Pcamera = UnProject(ref Pras); var u = 2.0f * xp / Width - 1.0f; var v = 1.0f - 2.0f * yp / Height; Vector ray_dir = new Vector(x.x * u + y.x * v + dir.x, x.y * u + y.y * v + dir.y, x.z * u + y.z * v + dir.z); Vector ray_target = (Vector)(Position + ray_dir * focal_scale); Point ray_origin = Position; var ray = new RayData(ray_origin, ray_dir, 0f, 1e20f); // Modify ray for depth of field if (lensRadius > 0f) { // Sample point on lens float lensU = 0f, lensV = 0f; float samplelensU = rnd.NextFloat(); float samplelensV = rnd.NextFloat(); MC.ConcentricSampleDisk(samplelensU, samplelensV, ref lensU, ref lensV); lensU *= lensRadius; lensV *= lensRadius; ray_target += lensRadius * (lensU * Vector.Normalize(x) + lensV * Vector.Normalize(y)); // Compute point on plane of focus //float ft = focalDistance / ray.Dir.z; //Point Pfocus = ray.Point(ft); // Update ray for effect of lens ray.Org = ray_origin; ray.Dir = Vector.Normalize(ray_target - (Vector)ray_origin); } pdf = 1; r = (IRay)ray; }
protected override void OnBarUpdate() { //DETERMINE LOCATION OF LAST UP/DOWN TREND LINES signal = 0; int upTrendOccurence = 1; int upTrendStartBarsAgo = 0; int upTrendEndBarsAgo = 0; int downTrendOccurence = 1; int downTrendStartBarsAgo = 0; int downTrendEndBarsAgo = 0; // Only calculate new autotrend line if ray hasent been put into manual mode by unlocking current ray if (((DrawObjects["UpTrendRay"] == null) || (DrawObjects["UpTrendRay"].Locked)) && ((DrawObjects["DownTrendRay"] == null) || (DrawObjects["DownTrendRay"].Locked))) // if ( (DrawObjects["UpTrendRay"].Locked) || (DrawObjects["DowntrendTrendRay"].Locked) ) { //Only do the following if existing ray is in auto mode // Calculate up trend line upTrendOccurence = 1; while (Low[upTrendEndBarsAgo] <= Low[upTrendStartBarsAgo]) { upTrendStartBarsAgo = Swing(strength).SwingLowBar(0, upTrendOccurence + 1, CurrentBar); upTrendEndBarsAgo = Swing(strength).SwingLowBar(0, upTrendOccurence, CurrentBar); if (upTrendStartBarsAgo < 0 || upTrendEndBarsAgo < 0) { break; } upTrendOccurence++; } // Calculate down trend line downTrendOccurence = 1; while (High[downTrendEndBarsAgo] >= High[downTrendStartBarsAgo]) { downTrendStartBarsAgo = Swing(strength).SwingHighBar(0, downTrendOccurence + 1, CurrentBar); downTrendEndBarsAgo = Swing(strength).SwingHighBar(0, downTrendOccurence, CurrentBar); if (downTrendStartBarsAgo < 0 || downTrendEndBarsAgo < 0) { break; } downTrendOccurence++; } } // Clear out arrows that mark trend line breaks unless ShowHistory flag is true if (!showHistory) { RemoveDrawObject("DownTrendBreak"); } if (!showHistory) { RemoveDrawObject("UpTrendBreak"); } //PROCESS UPTREND LINE IF CURRENT if (upTrendStartBarsAgo > 0 && upTrendEndBarsAgo > 0 && upTrendStartBarsAgo < downTrendStartBarsAgo) { RemoveDrawObject("DownTrendRay"); double startBarPrice = Low[upTrendStartBarsAgo]; double endBarPrice = Low[upTrendEndBarsAgo]; double changePerBar = (endBarPrice - startBarPrice) / (Math.Abs(upTrendEndBarsAgo - upTrendStartBarsAgo)); //Test to see if this is a new trendline and increment lineCounter if so. if (startBarPrice != startBarPriceOld) { direction = 1; //Signal that we have a new uptrend and put dot on trendline where new trend detected if (showHistory) { DrawDot(CurrentBar.ToString(), true, 0, startBarPrice + (upTrendStartBarsAgo * changePerBar), UpTrendColor); } lineCount = lineCount + 1; triggerBarIndex = 0; ResetAlert("Alert"); } startBarPriceOld = startBarPrice; // // Draw the up trend line // If user has unlocked the ray use manual rays position instead of auto generated positions to track ray position if ((DrawObjects["UpTrendRay"] != null) && (!DrawObjects["UpTrendRay"].Locked)) { IRay upTrendRay = (IRay)DrawObjects["UpTrendRay"]; startBarPrice = upTrendRay.Anchor1Y; endBarPrice = upTrendRay.Anchor2Y; upTrendStartBarsAgo = upTrendRay.Anchor1BarsAgo; upTrendEndBarsAgo = upTrendRay.Anchor2BarsAgo; changePerBar = (endBarPrice - startBarPrice) / (Math.Abs(upTrendRay.Anchor2BarsAgo - upTrendRay.Anchor1BarsAgo)); upTrendRay.Pen.DashStyle = DashStyle.Dash; upTrendRay.Pen.Color = Color.Blue; } else { DrawRay("UpTrendRay", false, upTrendStartBarsAgo, startBarPrice, upTrendEndBarsAgo, endBarPrice, UpTrendColor, DashStyle.Solid, lineWidth); } //Draw the history line that will stay persistent on chart using lineCounter to establish a unique name if (showHistory) { DrawLine("HistoryLine" + lineCount.ToString(), false, upTrendStartBarsAgo, startBarPrice, 0, startBarPrice + (upTrendStartBarsAgo * changePerBar), UpHistColor, DashStyle.Solid, lineWidth); } //SET RETURN VALUES FOR INDICATOR // Check for an uptrend line break trendPrice = (startBarPrice + (upTrendStartBarsAgo * changePerBar)); for (int barsAgo = upTrendEndBarsAgo - 1; barsAgo >= 0; barsAgo--) { if (Close[barsAgo] < endBarPrice + (Math.Abs(upTrendEndBarsAgo - barsAgo) * changePerBar)) { if (showHistory) { DrawArrowDown("UpTrendBreak" + lineCount.ToString(), barsAgo, High[barsAgo] + TickSize, downTrendColor); } else { DrawArrowDown("UpTrendBreak", barsAgo, High[barsAgo] + TickSize, downTrendColor); } // Set the break signal only if the break is on the right most bar if (barsAgo == 0) { signal = -1; } // Alert will only trigger in real-time if (AlertOnBreak && triggerBarIndex == 0) { triggerBarIndex = CurrentBar - upTrendEndBarsAgo; Alert("Alert", Priority.High, "Up trend line broken", "Alert2.wav", 100000, Color.Black, Color.Red); } break; } } } else //DETECT AND PROCESS DOWNTREND LINE IF CURRENT if (downTrendStartBarsAgo > 0 && downTrendEndBarsAgo > 0 && upTrendStartBarsAgo > downTrendStartBarsAgo) { RemoveDrawObject("UpTrendRay"); double startBarPrice = High[downTrendStartBarsAgo]; double endBarPrice = High[downTrendEndBarsAgo]; double changePerBar = (endBarPrice - startBarPrice) / (Math.Abs(downTrendEndBarsAgo - downTrendStartBarsAgo)); //Test to see if this is a new trendline and increment lineCount if so. if (startBarPrice != startBarPriceOld) { direction = -1; //signl that we have a new downtrend if (showHistory) { DrawDot(CurrentBar.ToString(), true, 0, startBarPrice + (downTrendStartBarsAgo * changePerBar), DownTrendColor); } lineCount = lineCount + 1; triggerBarIndex = 0; ResetAlert("Alert"); } startBarPriceOld = startBarPrice; // // Draw the down trend line // If user has unlocked the ray use manual rays position instead if ((DrawObjects["DownTrendRay"] != null) && (!DrawObjects["DownTrendRay"].Locked)) { IRay downTrendRay = (IRay)DrawObjects["DownTrendRay"]; startBarPrice = downTrendRay.Anchor1Y; endBarPrice = downTrendRay.Anchor2Y;; downTrendStartBarsAgo = downTrendRay.Anchor1BarsAgo; downTrendEndBarsAgo = downTrendRay.Anchor2BarsAgo; changePerBar = (endBarPrice - startBarPrice) / (Math.Abs(downTrendRay.Anchor2BarsAgo - downTrendRay.Anchor1BarsAgo)); downTrendRay.Pen.DashStyle = DashStyle.Dash; downTrendRay.Pen.Color = Color.Blue; } else { DrawRay("DownTrendRay", false, downTrendStartBarsAgo, startBarPrice, downTrendEndBarsAgo, endBarPrice, DownTrendColor, DashStyle.Solid, lineWidth); } if (showHistory) { DrawLine("HistoryLine" + lineCount.ToString(), false, downTrendStartBarsAgo, startBarPrice, 0, startBarPrice + (downTrendStartBarsAgo * changePerBar), downHistColor, DashStyle.Solid, lineWidth); } //SET RETURN VALUES FOR INDICATOR // Check for a down trend line break trendPrice = (startBarPrice + (downTrendStartBarsAgo * changePerBar)); for (int barsAgo = downTrendEndBarsAgo - 1; barsAgo >= 0; barsAgo--) { // direction=-1; if (Close[barsAgo] > endBarPrice + (Math.Abs(downTrendEndBarsAgo - barsAgo) * changePerBar)) { if (showHistory) { DrawArrowUp("DownTrendBreak" + lineCount.ToString(), barsAgo, Low[barsAgo] - TickSize, upTrendColor); } else { DrawArrowUp("DownTrendBreak", barsAgo, Low[barsAgo] - TickSize, upTrendColor); } // Set the break signal only if the break is on the right most bar if (barsAgo == 0) { signal = 1; } // Alert will only trigger in real-time if (AlertOnBreak && triggerBarIndex == 0) { triggerBarIndex = CurrentBar - downTrendEndBarsAgo; Alert("Alert", Priority.High, "Down trend line broken", "Alert2.wav", 100000, Color.Black, Color.Green); } break; } } } }