Hi,
We are researching in Radar device. We need to build a software which displays Radar information and targets like this:
especially scanning effect.
Does your SDK meet this need? (maybe more complex)
The polar chart like your screenshot is good for sample? Could you pls make a sample for radar effect?
Thanks,
Radar scanner
Moderator: Queue Moderators
- ArctionPasi
- Posts: 1367
- Joined: Tue Mar 26, 2013 10:57 pm
- Location: Finland
- Contact:
Re: Radar scanner
Hi,
thanks for asking. We'll try to provide a working example with source code this week.
thanks for asking. We'll try to provide a working example with source code this week.
LightningChart Support Team, PT
Re: Radar scanner
thanks you in advance,ArctionPasi wrote:Hi,
thanks for asking. We'll try to provide a working example with source code this week.
- ArctionPasi
- Posts: 1367
- Joined: Tue Mar 26, 2013 10:57 pm
- Location: Finland
- Contact:
Re: Radar scanner
Ok, made a radar simulation.
Just create a UserControl on your project and place that on your form. Use this code for the UserControl.
Set System.Windows.Forms.Timer with 10 ms interval to your UserControl as well, and set timerScanUpdater_Tick as its Tick event handler.
Thet it makes a live simulation, using jet fighter level object speeds.
Just create a UserControl on your project and place that on your form. Use this code for the UserControl.
Set System.Windows.Forms.Timer with 10 ms interval to your UserControl as well, and set timerScanUpdater_Tick as its Tick event handler.
Code: Select all
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using Arction.LightningChartUltimate;
using Arction.LightningChartUltimate.Axes;
using Arction.LightningChartUltimate.SeriesPolar;
using Arction.LightningChartUltimate.EventMarkers;
using Arction.LightningChartUltimate.Views.ViewPolar;
namespace DemoAppWinForms
{
/// <summary>
/// Polar radar example.
/// </summary>
public partial class ExamplePolarRadar : UserControl
{
//Chart
private LightningChartUltimate m_chart = null;
private List<MovingObject> m_listMovingObjects = new List<MovingObject>();
private const double RotationDegreesPerSec = 90;
//Time that it takes to rotate full 360 degrees
private const double SweepTime = 360.0 / RotationDegreesPerSec;
private Stopwatch m_stopWatchTimeLineAnim = new Stopwatch();
private const int SectorCountInSweep = 45;
private const double RangeKm = 20;
private static Color SweepColorBegin = Color.FromArgb(100, Color.Lime);
private static Color SweepColorEnd = Color.FromArgb(0, 0, 0, 0);
private const int MovingObjectCount = 10;
/// <summary>
/// Constructor.
/// </summary>
public ExamplePolarRadar()
{
InitializeComponent();
CreateChart();
//Start animation time line
m_stopWatchTimeLineAnim.Reset();
m_stopWatchTimeLineAnim.Start();
//Create a couple of moving objects
CreateMovingObjects();
//Start the timer which updates the objects
this.timerScanUpdater.Start();
}
/// <summary>
/// Create chart
/// </summary>
private void CreateChart()
{
//Create new chart
m_chart = new LightningChartUltimate();
//Disable rendering, strongly recommended before updating chart properties
m_chart.BeginUpdate();
//Set active view
m_chart.ActiveView = ActiveView.ViewPolar;
//Chart parent must be set
m_chart.Parent = this;
//Fill parent area with chart
m_chart.Dock = DockStyle.Fill;
//Chart name
m_chart.Name = "ChartPolarRadar";
m_chart.Title.Text = "Scanning radar chart, radius "+RangeKm.ToString()+ " km";
//Get 1st polar axis and set it up
AxisPolar axis = m_chart.ViewPolar.Axes[0];
axis.MajorGrid.Visible = true;
axis.MinorGrid.Visible = true;
axis.TickMarkLocation = PolarGridTickmarkLocation.Outside;
axis.Reversed = true;
axis.InnerCircleRadiusPercentage = 0;
axis.MajorDivCount = 4;
axis.MinAmplitude = 0;
axis.MaxAmplitude = RangeKm;
axis.MouseScaling = true;
axis.MouseScrolling = true;
axis.Title.Visible = false;
axis.Visible = true;
axis.Units.RadialOffsetPercentage = 100;
axis.AmplitudeAxisLineVisible = false;
axis.LabelsFont = new Font("Tahoma", 25f, FontStyle.Regular);
axis.MinorGrid.Visible = false;
axis.AngularGrid.Visible = true;
axis.AngleOrigin = -90;
axis.AngularAxisCircleVisible = false;
axis.AngularGrid.Color = Color.FromArgb(50, 0, 160, 120);
axis.AngularGrid.LineWidth = 2;
axis.MajorGrid.Color = Color.FromArgb(50, 0, 160, 120);
//Remove existing PointLineSeries
m_chart.ViewPolar.PointLineSeries.Clear();
//Direction vector
PointLineSeriesPolar directionVec = new PointLineSeriesPolar(m_chart.ViewPolar, axis);
directionVec.LineStyle.Width = 3;
directionVec.LineStyle.Color = Color.White;
directionVec.MouseInteraction = false;
m_chart.ViewPolar.PointLineSeries.Add(directionVec);
m_chart.ViewPolar.GraphBackground.Color = Color.FromArgb(0, 32, 0);
m_chart.ViewPolar.GraphBackground.GradientFill = GradientFill.Radial;
//Create sectors for gradient sweep
for (int iSector = 0; iSector < SectorCountInSweep; iSector++)
{
Sector sector = new Sector(m_chart.ViewPolar, axis);
sector.Behind = true;
sector.MinAmplitude = 0;
sector.MaxAmplitude = RangeKm;
sector.BorderlineStyle.Width = 0;
sector.BorderlineStyle.Color = Color.Transparent;
sector.Fill.GradientFill = GradientFill.Solid;
sector.Fill.Color = ChartTools.CalcGradient(SweepColorBegin, SweepColorEnd, 100.0 * (double)iSector / (double)SectorCountInSweep);
sector.Title.ShowInLegendBox = false;
sector.MouseInteraction = false;
m_chart.ViewPolar.Sectors.Add(sector);
}
m_chart.ViewPolar.LegendBox.Visible = false;
//Allow chart rendering
m_chart.EndUpdate();
m_chart.SizeChanged += new EventHandler(m_chart_SizeChanged);
}
/// <summary>
/// Size has been changed
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void m_chart_SizeChanged(object sender, EventArgs e)
{
m_chart.BeginUpdate();
//Update the moving objects to correct screen coordinates based on their polar angle and amplitude info
foreach (MovingObject mo in m_listMovingObjects)
{
int iXCoord, iYCoord;
m_chart.ViewPolar.Axes[0].ValueToCoord(mo.PolarAngle, mo.PolarAmplitude,out iXCoord, out iYCoord);
mo.PositionX = iXCoord;
mo.PositionY = iYCoord;
}
m_chart.EndUpdate();
}
/// <summary>
/// Create bunch of moving objects
/// </summary>
private void CreateMovingObjects()
{
double dWidth = m_chart.ClientSize.Width;
double dHeight = m_chart.ClientSize.Height;
int iCoordX, iCoordY;
Random rand = new Random();
int iCenterX, iCenterY, iDiameter;
m_chart.ViewPolar.GetChartDiameterAndCenter(out iDiameter, out iCenterX, out iCenterY);
for (int i=0;i<MovingObjectCount; i++)
{
iCoordX = iCenterX - iDiameter/4 + (int)(rand.NextDouble() * (double) iDiameter/2);
iCoordY = iCenterY - iDiameter/4 + (int)(rand.NextDouble() * (double) iDiameter/2);
double dKph = 500 + rand.NextDouble() * 1500.0; //Simulate jet fighter speeds
m_listMovingObjects.Add(new MovingObject(m_chart.ViewPolar, iCoordX, iCoordY,
m_stopWatchTimeLineAnim.ElapsedMilliseconds / 1000.0, rand.NextDouble() * 360.0, dKph, SweepTime * 2.0));
}
}
/// <summary>
/// Timer that updates the scanning effect, object positions and fading.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void timerScanUpdater_Tick(object sender, EventArgs e)
{
if (m_chart == null)
return;
m_chart.BeginUpdate();
double dTimeSec = m_stopWatchTimeLineAnim.ElapsedMilliseconds / 1000.0;
double dCurrentAngleDeg = (RotationDegreesPerSec * dTimeSec);
if(dCurrentAngleDeg < 0)
dCurrentAngleDeg += 360.0;
dCurrentAngleDeg %= 360.0;
//Update the beam direction vector
PointLineSeriesPolar directionVec = m_chart.ViewPolar.PointLineSeries[0];
directionVec.Points = new PolarSeriesPoint[]
{ new PolarSeriesPoint(dCurrentAngleDeg, 0), new PolarSeriesPoint(dCurrentAngleDeg, RangeKm) };
//Update the sweep sectors
double dSectorStepDeg = 45.0 / (double)SectorCountInSweep;
for (int iSector = 0; iSector < SectorCountInSweep; iSector++)
{
Sector sector = m_chart.ViewPolar.Sectors[iSector];
sector.BeginAngle = dCurrentAngleDeg - (double)iSector * dSectorStepDeg;
sector.EndAngle = dCurrentAngleDeg - (double)(iSector+1) * dSectorStepDeg;
}
//Update the targets
UpdateMovingObjects(dCurrentAngleDeg, dTimeSec);
m_chart.EndUpdate();
}
/// <summary>
/// Update moving objects
/// </summary>
/// <param name="currentAngleDeg"></param>
/// <param name="timeSec"></param>
void UpdateMovingObjects(double currentAngleDeg, double timeSec)
{
AxisPolar axis = m_chart.ViewPolar.Axes[0];
foreach(MovingObject mo in m_listMovingObjects)
{
bool bStartNow = false;
//axis.CoordToValue((int) mo.PositionX, (int)mo.PositionY, out dObjectAngle, out dObjectDistance);
mo.UpdatePosition(timeSec);
if (mo.Started == false)
{
//if(m_chart.ViewPolar.Sectors[0].IsMouseOver((int)mo.PositionX, (int)mo.PositionY))
if (currentAngleDeg >= mo.PolarAngle && currentAngleDeg <= mo.PolarAngle + 10)
bStartNow = true;
}
else
{
if (
//((timeSec - mo.AnimTimeLineTimeStartedSec) > (0.5 * SweepTime))
//&& //(m_chart.ViewPolar.Sectors[0].IsMouseOver((int)mo.PositionX, (int)mo.PositionY)))
(currentAngleDeg >= mo.PolarAngle && currentAngleDeg <= mo.PolarAngle + 10))
{
bStartNow = true;
}
}
if (bStartNow)
{
mo.StartFadeaway(timeSec);
}
mo.UpdateFadeaway(timeSec);
}
}
}
/// <summary>
/// Moving object class. This object represtents an object on the radar.
/// </summary>
public class MovingObject
{
static Color MovingObjectCenter = Color.FromArgb(255, 0, 255, 255);
static Color MovingObjectEdge = Color.FromArgb(100, MovingObjectCenter);
public double PositionX;
public double PositionY;
public double AnimTimeLineTimeStartedSec;
public double CartesianHeadingAngle;
public double CartesianVelocityKph;
public double AnimTimeLineSecsWhenLastPosUpdated;
public bool Started = false;
public double FadeAwayDuration;
public PolarEventMarker Marker;
public AxisPolar Axis;
public ViewPolar ChartView;
public double PolarAngle;
public double PolarAmplitude;
/// <summary>
/// Constructor
/// </summary>
/// <param name="chartView">Owner polar view</param>
/// <param name="x">X position as screen coordinates</param>
/// <param name="y">Y position as screen coordinates</param>
/// <param name="createdSeconds">Creating timestamp in seconds</param>
/// <param name="cartesianHeading">Heading in screen coordinates</param>
/// <param name="cartesianVelocityKph">Velocity, km/h</param>
/// <param name="totalSweepDuration">Sweep duration in seconds</param>
public MovingObject(ViewPolar chartView,
double x, double y, double createdSeconds, double cartesianHeading, double cartesianVelocityKph, double totalSweepDuration)
{
PositionX = x;
PositionY = y;
AnimTimeLineTimeStartedSec = createdSeconds;
CartesianHeadingAngle = cartesianHeading;
CartesianVelocityKph = cartesianVelocityKph;
AnimTimeLineSecsWhenLastPosUpdated = createdSeconds;
FadeAwayDuration = totalSweepDuration;
//Add a marker that represents the moving object
Axis = chartView.Axes[0];
Marker = new PolarEventMarker();
double dAngle, dAmplitude;
Axis.CoordToValue((int) x,(int) y,out dAngle, out dAmplitude);
Marker.AngleValue = dAngle;
Marker.Amplitude = dAmplitude;
Marker.Symbol.Shape = Shape.Circle;
Marker.Symbol.Color1 = MovingObjectCenter;
Marker.Symbol.Color2 = MovingObjectEdge;
Marker.Symbol.Width = 17;
Marker.Symbol.Height = 17;
Marker.Symbol.BorderWidth = 0;
Marker.Label.Visible = false;
Marker.Visible = false;
Marker.MouseInteraction = false;
chartView.Markers.Add(Marker);
PolarAmplitude = dAmplitude;
PolarAngle = dAngle;
ChartView = chartView;
}
/// <summary>
/// Start fadeaway animation
/// </summary>
/// <param name="timeSec">Time in seconds</param>
public void StartFadeaway(double timeSec)
{
Started = true;
AnimTimeLineTimeStartedSec = timeSec;
Marker.Visible = true;
double dAngle, dAmplitude;
Axis.CoordToValue((int)PositionX, (int)PositionY, out dAngle, out dAmplitude);
Marker.AngleValue = dAngle;
Marker.Amplitude = dAmplitude;
Marker.Visible = dAmplitude <= Axis.MaxAmplitude;
if (Marker.Visible == false)
CartesianHeadingAngle += 180.0;//Get it back to screen by reversing its heading
}
/// <summary>
/// Update object position
/// </summary>
/// <param name="timeSec">Time in seconds</param>
public void UpdatePosition(double timeSec)
{
double dAngleRad = MathRoutines.DegreesAsRadians(CartesianHeadingAngle);
double dPixelsPerKm = GetPixelsPerKm();
double dMoveNowPixels = dPixelsPerKm * (timeSec - AnimTimeLineSecsWhenLastPosUpdated) * CartesianVelocityKph / 3600.0;
PositionX += dMoveNowPixels * Math.Cos(dAngleRad);
PositionY -= dMoveNowPixels * Math.Sin(dAngleRad);
double dAngle, dAmplitude;
Axis.CoordToValue((int)PositionX, (int)PositionY, out dAngle, out dAmplitude);
PolarAngle = dAngle;
PolarAmplitude = dAmplitude;
AnimTimeLineSecsWhenLastPosUpdated = timeSec;
}
/// <summary>
/// Calculate how many pixels represent 1 km
/// </summary>
/// <returns>Pixels per km</returns>
private double GetPixelsPerKm()
{
int iXMax, iYMax;
Axis.ValueToCoord(0, Axis.MaxAmplitude, out iXMax, out iYMax);
double dXMax = (double)iXMax;
double dYMax = (double)iYMax;
int iXMin, iYMin;
Axis.ValueToCoord(0, Axis.MinAmplitude, out iXMin, out iYMin);
double dXMin = (double)iXMin;
double dYMin = (double)iYMin;
return Math.Sqrt((dXMax - dXMin) * (dXMax - dXMin) + (dYMax - dYMin) * (dYMax - dYMin)) / Axis.MaxAmplitude;
}
/// <summary>
/// Update fadeaway
/// </summary>
/// <param name="timeSec">Time in seconds</param>
public void UpdateFadeaway(double timeSec)
{
double dAnimPosPercents = (timeSec - AnimTimeLineTimeStartedSec) / FadeAwayDuration * 100.0;
Marker.Symbol.Color1 = ChartTools.CalcGradient(MovingObjectCenter, Color.FromArgb(0, 0, 0, 0), dAnimPosPercents);
Marker.Symbol.Color2 = ChartTools.CalcGradient(MovingObjectEdge, Color.FromArgb(0, 0, 0, 0), dAnimPosPercents);
Marker.Symbol.Width = (float)(11.0 + (100 - dAnimPosPercents) * 17.0 / 100.0);
Marker.Symbol.Height = (float)(11.0 + (100 - dAnimPosPercents) * 17.0 / 100.0);
}
}
}
LightningChart Support Team, PT
Re: Radar scanner
Awesome supports, we will add LightningChart to our project. Thanks