public static void GetSystemListBySqDistancesFrom(BaseUtils.SortedListDoubleDuplicate <ISystem> distlist, // MUST use duplicate double list to protect against EDSM having two at the same point double x, double y, double z, int maxitems, double mindist, // 0 = no min dist, always spherical double maxdist, bool spherical, // enforces sphere on maxdist, else its a cube for maxdist SQLiteConnectionSystem cn, Action <ISystem> LookedUp = null ) { // for comparision, using the grid screener is slower than the xy index. keep code for record // grid screener.. "s.sectorid IN (Select id FROM Sectors sx where sx.gridid IN (" + strinlist + ")) " + //var gridids = GridId.Ids(x - maxdist, x + maxdist, z - maxdist, z + maxdist); // find applicable grid ids across this range.. //var strinlist = string.Join(",", (from x1 in gridids select x1.ToStringInvariant())); // here we convert using invariant for paranoia sake. int mindistint = mindist > 0 ? SystemClass.DoubleToInt(mindist) * SystemClass.DoubleToInt(mindist) : 0; // needs a xz index for speed using (DbCommand cmd = cn.CreateSelect("Systems s", MakeSystemQueryEDDB, where : "s.x >= @xv - @maxdist " + "AND s.x <= @xv + @maxdist " + "AND s.z >= @zv - @maxdist " + "AND s.z <= @zv + @maxdist " + "AND s.y >= @yv - @maxdist " + "AND s.y <= @yv + @maxdist " + (mindist > 0 ? ("AND (s.x-@xv)*(s.x-@xv)+(s.y-@yv)*(s.y-@yv)+(s.z-@zv)*(s.z-@zv)>=" + (mindistint).ToStringInvariant()) : ""), orderby: "(s.x-@xv)*(s.x-@xv)+(s.y-@yv)*(s.y-@yv)+(s.z-@zv)*(s.z-@zv)", // just use squares to order joinlist: MakeSystemQueryEDDBJoinList, limit: "@max" )) { cmd.AddParameterWithValue("@xv", SystemClass.DoubleToInt(x)); cmd.AddParameterWithValue("@yv", SystemClass.DoubleToInt(y)); cmd.AddParameterWithValue("@zv", SystemClass.DoubleToInt(z)); cmd.AddParameterWithValue("@max", maxitems + 1); // 1 more, because if we are on a System, that will be returned cmd.AddParameterWithValue("@maxdist", SystemClass.DoubleToInt(maxdist)); // System.Diagnostics.Debug.WriteLine(cn.ExplainQueryPlanString(cmd)); using (DbDataReader reader = cmd.ExecuteReader()) { while (reader.Read())// && distlist.Count < maxitems) // already sorted, and already limited to max items { SystemClass s = MakeSystem(reader); LookedUp?.Invoke(s); // callback to say looked up double distsq = s.DistanceSq(x, y, z); if ((!spherical || distsq <= maxdist * maxdist)) { distlist.Add(distsq, s); // which Rob has seen crashing the program! Bad EDSM! } } } } }
internal static ISystem GetSystemNearestTo(Point3D currentpos, Point3D wantedpos, double maxfromcurpos, double maxfromwanted, SystemsNearestMetric routemethod, SQLiteConnectionSystem cn, Action <ISystem> LookedUp = null, int limitto = 1000) { using (DbCommand cmd = cn.CreateSelect("Systems s", MakeSystemQueryNamed, where : "x >= @xc - @maxfromcurpos " + "AND x <= @xc + @maxfromcurpos " + "AND z >= @zc - @maxfromcurpos " + "AND z <= @zc + @maxfromcurpos " + "AND x >= @xw - @maxfromwanted " + "AND x <= @xw + @maxfromwanted " + "AND z >= @zw - @maxfromwanted " + "AND z <= @zw + @maxfromwanted " + "AND y >= @yc - @maxfromcurpos " + "AND y <= @yc + @maxfromcurpos " + "AND y >= @yw - @maxfromwanted " + "AND y <= @yw + @maxfromwanted ", orderby: "(s.x-@xw)*(s.x-@xw)+(s.y-@yw)*(s.y-@yw)+(s.z-@zw)*(s.z-@zw)", // orderby distance from wanted limit: limitto, joinlist: MakeSystemQueryNamedJoinList)) { cmd.AddParameterWithValue("@xw", SystemClass.DoubleToInt(wantedpos.X)); // easier to manage with named paras cmd.AddParameterWithValue("@yw", SystemClass.DoubleToInt(wantedpos.Y)); cmd.AddParameterWithValue("@zw", SystemClass.DoubleToInt(wantedpos.Z)); cmd.AddParameterWithValue("@maxfromwanted", SystemClass.DoubleToInt(maxfromwanted)); cmd.AddParameterWithValue("@xc", SystemClass.DoubleToInt(currentpos.X)); cmd.AddParameterWithValue("@yc", SystemClass.DoubleToInt(currentpos.Y)); cmd.AddParameterWithValue("@zc", SystemClass.DoubleToInt(currentpos.Z)); cmd.AddParameterWithValue("@maxfromcurpos", SystemClass.DoubleToInt(maxfromcurpos)); //System.Diagnostics.Debug.WriteLine(cn.ExplainQueryPlanString(cmd)); using (DbDataReader reader = cmd.ExecuteReader()) { var systems = MakeSystemEnumerable(reader, callback: LookedUp); return(GetSystemNearestTo(systems, currentpos, wantedpos, maxfromcurpos, maxfromwanted, routemethod)); } } }
///////////////////////////////////////// List of systems near xyz between mindist and maxdist internal static void GetSystemListBySqDistancesFrom(BaseUtils.SortedListDoubleDuplicate <ISystem> distlist, // MUST use duplicate double list to protect against EDSM having two at the same point double x, double y, double z, int maxitems, double mindist, // 0 = no min dist, always spherical double maxdist, bool spherical, // enforces sphere on maxdist, else its a cube for maxdist SQLiteConnectionSystem cn, Action <ISystem> LookedUp = null ) { // for comparision, using the grid screener is slower than the xy index. keep code for record // grid screener.. "s.sectorid IN (Select id FROM Sectors sx where sx.gridid IN (" + strinlist + ")) " + //var gridids = GridId.Ids(x - maxdist, x + maxdist, z - maxdist, z + maxdist); // find applicable grid ids across this range.. //var strinlist = string.Join(",", (from x1 in gridids select x1.ToStringInvariant())); // here we convert using invariant for paranoia sake. // System.Diagnostics.Debug.WriteLine("Time1 " + BaseUtils.AppTicks.TickCountLap("SDC")); int mindistint = mindist > 0 ? SystemClass.DoubleToInt(mindist) * SystemClass.DoubleToInt(mindist) : 0; // needs a xz index for speed using (DbCommand cmd = cn.CreateSelect("Systems s", MakeSystemQueryNamed, where : "s.x >= @xv - @maxdist " + "AND s.x <= @xv + @maxdist " + "AND s.z >= @zv - @maxdist " + "AND s.z <= @zv + @maxdist " + "AND s.y >= @yv - @maxdist " + "AND s.y <= @yv + @maxdist " + (mindist > 0 ? ("AND (s.x-@xv)*(s.x-@xv)+(s.y-@yv)*(s.y-@yv)+(s.z-@zv)*(s.z-@zv)>=" + (mindistint).ToStringInvariant()) : ""), orderby: "(s.x-@xv)*(s.x-@xv)+(s.y-@yv)*(s.y-@yv)+(s.z-@zv)*(s.z-@zv)", // just use squares to order joinlist: MakeSystemQueryNamedJoinList, limit: "@max" )) { cmd.AddParameterWithValue("@xv", SystemClass.DoubleToInt(x)); cmd.AddParameterWithValue("@yv", SystemClass.DoubleToInt(y)); cmd.AddParameterWithValue("@zv", SystemClass.DoubleToInt(z)); cmd.AddParameterWithValue("@max", maxitems + 1); // 1 more, because if we are on a System, that will be returned cmd.AddParameterWithValue("@maxdist", SystemClass.DoubleToInt(maxdist)); // System.Diagnostics.Debug.WriteLine(cn.ExplainQueryPlanString(cmd)); int xi = SystemClass.DoubleToInt(x); int yi = SystemClass.DoubleToInt(y); int zi = SystemClass.DoubleToInt(z); long maxdistsqi = (long)SystemClass.DoubleToInt(maxdist) * (long)SystemClass.DoubleToInt(maxdist); long count = 0; using (DbDataReader reader = cmd.ExecuteReader()) { // System.Diagnostics.Debug.WriteLine("Time1.5 " + BaseUtils.AppTicks.TickCountLap("SDC")); while (reader.Read()) // already sorted, and already limited to max items { int sxi = reader.GetInt32(0); int syi = reader.GetInt32(1); int szi = reader.GetInt32(2); long distsqi = (long)(xi - sxi) * (long)(xi - sxi) + (long)(yi - syi) * (long)(yi - syi) + (long)(zi - szi) * (long)(zi - szi); if (!spherical || distsqi <= maxdistsqi) { SystemClass s = MakeSystem(reader); double distnorm = ((double)distsqi) / SystemClass.XYZScalar / SystemClass.XYZScalar; //System.Diagnostics.Debug.WriteLine("System " + s.Name + " " + Math.Sqrt(distnorm).ToString("0.0")); LookedUp?.Invoke(s); // callback to say looked up distlist.Add(distnorm, s); // which Rob has seen crashing the program! Bad EDSM! } count++; } // System.Diagnostics.Debug.WriteLine("Time2 " + BaseUtils.AppTicks.TickCountLap("SDC") + " count " + count); } } }
internal static ISystem GetSystemNearestTo(Point3D currentpos, Point3D wantedpos, double maxfromcurpos, double maxfromwanted, int routemethod, SQLiteConnectionSystem cn, Action <ISystem> LookedUp = null, int limitto = 1000) { using (DbCommand cmd = cn.CreateSelect("Systems s", MakeSystemQueryEDDB, where : "x >= @xc - @maxfromcurpos " + "AND x <= @xc + @maxfromcurpos " + "AND z >= @zc - @maxfromcurpos " + "AND z <= @zc + @maxfromcurpos " + "AND x >= @xw - @maxfromwanted " + "AND x <= @xw + @maxfromwanted " + "AND z >= @zw - @maxfromwanted " + "AND z <= @zw + @maxfromwanted " + "AND y >= @yc - @maxfromcurpos " + "AND y <= @yc + @maxfromcurpos " + "AND y >= @yw - @maxfromwanted " + "AND y <= @yw + @maxfromwanted ", orderby: "(s.x-@xw)*(s.x-@xw)+(s.y-@yw)*(s.y-@yw)+(s.z-@zw)*(s.z-@zw)", // orderby distance from wanted limit: limitto, joinlist: MakeSystemQueryEDDBJoinList)) { cmd.AddParameterWithValue("@xw", SystemClass.DoubleToInt(wantedpos.X)); // easier to manage with named paras cmd.AddParameterWithValue("@yw", SystemClass.DoubleToInt(wantedpos.Y)); cmd.AddParameterWithValue("@zw", SystemClass.DoubleToInt(wantedpos.Z)); cmd.AddParameterWithValue("@maxfromwanted", SystemClass.DoubleToInt(maxfromwanted)); cmd.AddParameterWithValue("@xc", SystemClass.DoubleToInt(currentpos.X)); cmd.AddParameterWithValue("@yc", SystemClass.DoubleToInt(currentpos.Y)); cmd.AddParameterWithValue("@zc", SystemClass.DoubleToInt(currentpos.Z)); cmd.AddParameterWithValue("@maxfromcurpos", SystemClass.DoubleToInt(maxfromcurpos)); //System.Diagnostics.Debug.WriteLine(cn.ExplainQueryPlanString(cmd)); double bestmindistance = double.MaxValue; SystemClass nearestsystem = null; using (DbDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { SystemClass s = MakeSystem(reader); LookedUp?.Invoke(s); // callback to say looked up Point3D syspos = new Point3D(s.X, s.Y, s.Z); double distancefromwantedx2 = Point3D.DistanceBetweenX2(wantedpos, syspos); // range between the wanted point and this, ^2 double distancefromcurposx2 = Point3D.DistanceBetweenX2(currentpos, syspos); // range between the wanted point and this, ^2 // ENSURE its withing the circles now if (distancefromcurposx2 <= (maxfromcurpos * maxfromcurpos) && distancefromwantedx2 <= (maxfromwanted * maxfromwanted)) { if (routemethod == metric_nearestwaypoint) { if (distancefromwantedx2 < bestmindistance) { nearestsystem = s; bestmindistance = distancefromwantedx2; } } else { Point3D interceptpoint = currentpos.InterceptPoint(wantedpos, syspos); // work out where the perp. intercept point is.. double deviation = Point3D.DistanceBetween(interceptpoint, syspos); double metric = 1E39; if (routemethod == metric_mindevfrompath) { metric = deviation; } else if (routemethod == metric_maximum100ly) { metric = (deviation <= 100) ? distancefromwantedx2 : metric; // no need to sqrt it.. } else if (routemethod == metric_maximum250ly) { metric = (deviation <= 250) ? distancefromwantedx2 : metric; } else if (routemethod == metric_maximum500ly) { metric = (deviation <= 500) ? distancefromwantedx2 : metric; } else if (routemethod == metric_waypointdev2) { metric = Math.Sqrt(distancefromwantedx2) + deviation / 2; } if (metric < bestmindistance) { nearestsystem = s; bestmindistance = metric; } } } } } return(nearestsystem); } }