Thanks Chris:
I actually resolved this this morning. I tried a new approach. Instead of trying to calculate a point with trig, I found some formulas to find an intersecting point of two lines. I adapted it to the silverlight viewer.
For future reference of anyone trying to do this here is how I accompished this:
public void ShowPerpFromPipe(MapPoint p1, MapPoint p2, MapPoint p3)
{
try
{
ESRI.ArcGIS.Client.Projection.WebMercator merc = new ESRI.ArcGIS.Client.Projection.WebMercator();
Point p1x = MyMap.MapToScreen(p1);
Point p2x = MyMap.MapToScreen(p2);
Point p3x = MyMap.MapToScreen(p3);
p1.SpatialReference = p3.SpatialReference;
p2.SpatialReference = p3.SpatialReference;
p1 = merc.ToGeographic(p1) as MapPoint;
p2 = merc.ToGeographic(p2) as MapPoint;
p3 = merc.ToGeographic(p3) as MapPoint;
double pipeAngle = GetAngle(p1, p2);
p1 = merc.FromGeographic(p1) as MapPoint;
p2 = merc.FromGeographic(p2) as MapPoint;
MapPoint mp;
mp = Support.GetPointFromHeading(p3, 1, pipeAngle - 90);
p3 = merc.FromGeographic(p3) as MapPoint;
mp = merc.FromGeographic(mp) as MapPoint;
MapPoint p4 = new MapPoint();
p4 = findIntersection(p1, p2, p3, mp);
MyGraphicsLayer.Graphics.Clear();
ESRI.ArcGIS.Client.Geometry.Polyline ply = Support.GraphicLineBetweenPoint(p4, p3, Colors.Red);
}
catch (Exception ex)
{
}
}
Supporting Functions:
public static MapPoint GetPointFromHeading(MapPoint start, double distanceKM, double heading)
{
double brng = heading / 180 * Math.PI;
double lon1 = start.X / 180 * Math.PI;
double lat1 = start.Y / 180 * Math.PI;
double dR = distanceKM / 6378.137; //Angular distance in radians
double lat2 = Math.Asin(Math.Sin(lat1) * Math.Cos(dR) + Math.Cos(lat1) * Math.Sin(dR) * Math.Cos(brng));
double lon2 = lon1 + Math.Atan2(Math.Sin(brng) * Math.Sin(dR) * Math.Cos(lat1), Math.Cos(dR) - Math.Sin(lat1) * Math.Sin(lat2));
double lon = lon2 / Math.PI * 180;
double lat = lat2 / Math.PI * 180;
while (lon < -180) lon += 360;
while (lat < -90) lat += 180;
while (lon > 180) lon -= 360;
while (lat > 90) lat -= 180;
return new MapPoint(lon, lat);
}
public MapPoint findIntersection(MapPoint p1, MapPoint p2, MapPoint p3, MapPoint p4)
{
double x1 = p1.X;
double y1 = p1.Y;
double x2 = p2.X;
double y2 = p2.Y;
double x3 = p3.X;
double y3 = p3.Y;
double x4 = p4.X;
double y4 = p4.Y;
double x;
double y;
double A1 = y2 - y1;
double B1 = x1 - x2;
double C1 = A1 * x1 + B1 * y1;
double A2 = y4 - y3;
double B2 = x3 - x4;
double C2 = A2 * x3 + B2 * y3;
double det = A1 * B2 - A2 * B1;
if (det == 0)
{
throw new NotImplementedException("Lines are Parallel");
}
else
{
x = (B2 * C1 - B1 * C2) / det;
y = (A1 * C2 - A2 * C1) / det;
}
MapPoint mp = new MapPoint();
mp.X = x;
mp.Y = y;
return mp;
}
public static ESRI.ArcGIS.Client.Geometry.Polyline GraphicLineBetweenPoint(MapPoint p1, MapPoint p2, Color clr)
{
Graphic clickGraphic = new Graphic();
SolidColorBrush sl = new SolidColorBrush();
sl.Color = clr;
SimpleLineSymbol simpleline = new SimpleLineSymbol();
simpleline.Width = 4;
simpleline.Color = sl;
ESRI.ArcGIS.Client.Geometry.PointCollection pc = new ESRI.ArcGIS.Client.Geometry.PointCollection();
pc.Add(p1);
pc.Add(p2);
ESRI.ArcGIS.Client.Geometry.Polyline pl = new ESRI.ArcGIS.Client.Geometry.Polyline();
pl.Paths.Add(pc);
clickGraphic.Symbol = simpleline;
clickGraphic.Geometry = pl;
clickGraphic.Geometry.SpatialReference = MyMap.SpatialReference;
MyGraphicsLayer.Graphics.Add(clickGraphic);
return pl;
}
private double GetAngle(MapPoint p1, MapPoint p2)
{
MapPoint p1x = p1;
MapPoint p2x = p2;
double angle = Math.Atan2((p2x.X - p1x.X), (p2x.Y - p1x.Y)) / Math.PI * 180 - 90;
if (angle < 0)
angle = (angle * -1);
angle = 90 - angle;
return angle;
}