C# 使用三角函数SQL Server
我有一个带有Dapper的WebApi项目,我有表产品:C# 使用三角函数SQL Server,c#,sql-server,C#,Sql Server,我有一个带有Dapper的WebApi项目,我有表产品: [Key] public int idProducts { get; set; } public string Name { get; set; } public float Latitude { get; set; } public float Longitude { get; set; } public int ProductsItems { get; set; } public decimal Price { get; set; }
[Key]
public int idProducts { get; set; }
public string Name { get; set; }
public float Latitude { get; set; }
public float Longitude { get; set; }
public int ProductsItems { get; set; }
public decimal Price { get; set; }
我需要计算从A点到B点的距离,检查是否小于1km,我已经计算过了,但在C点
private static double distance(double lat1, double lon1, double lat2, double lon2, char unit)
{
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) *
Math.Sin(deg2rad(lat2)) +
Math.Cos(deg2rad(lat1)) *
Math.Cos(deg2rad(lat2)) *
Math.Cos(deg2rad(theta));
dist = Math.Acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
dist = dist * 1.609344;
return (dist);
}
private static double deg2rad(double deg)
{
return (deg * Math.PI / 180.0);
}
private static double rad2deg(double rad)
{
return (rad / Math.PI * 180.0);
}
而布尔艾利斯=距离-8.157908,-34.931675,-8.164891,-34.919033,'K'<1
但那样的话,我就必须从产品中选择*,以列表的形式获取所有结果,并循环获取每个项目,检查从a到B的距离是否有效,是否不实用!我不习惯在涉及数学的问题上提出这样的问题
如何创建一个查询,在其中我可以从a点传递Lat和Long,并进行计算,然后只返回有效项的列表?您可以在SQL Server中使用地理信息
范例
我应该补充一点,UDF的计算与Google地图的计算几乎不谋而合。要稍微改进John的答案,您可以这样做:
CREATE TABLE YourTable (
ID INT PRIMARY KEY
, Lat FLOAT
, Lon FLOAT
, Location AS GEOGRAPHY::Point(Lat, Lon, 4326));
INSERT INTO YourTable (ID, Lat, Lon)
VALUES
(1,-8.157908, -34.931675)
, (2,-8.164891, -34.919033)
, (3,-8.159999, -34.939999);
GO
CREATE FUNCTION GetCloserThanOneKilometer (
@Lat FLOAT
, @Lon FLOAT
, @Distance FLOAT)
RETURNS TABLE
AS
RETURN
SELECT *
FROM YourTable
WHERE GEOGRAPHY::Point(@Lat, @Lon, 4326).STDistance(Location) <= @Distance;
不能在数据库中将其作为查询处理吗?这可以很容易地用SQL重写。您还可以创建一个计算列来存储位置,而无需每次都计算该位置:这是类似的,但看看C中的这行,双距离双lat1,双lon1,双lat2,双lon2,字符单位lat1和lon1是我要通过语法传递的值,每次调用都会不同,lat2和lon2已经存储在这个表中,类似于检查Lat和Long PASS是否距离此表中的所有这些值小于1km,并仅返回有效值。@EvaldasBuinauskas非常正确,我应该指出这一点。我想要一个简单的例子。很好的改进。。。清晰、清晰的示例+1这正是我想要的!谢谢埃瓦尔达斯和约翰!
ID Lat Lng Meters
1 -8.157908 -34.931675 0 --<< Orgin/Fetch
3 -8.159999 -34.939999 946.007737339573
CREATE Function [dbo].[udf-Geo-Meters](@Lat1 FLOAT, @Lng1 FLOAT, @Lat2 FLOAT, @Lng2 FLOAT)
Returns Float as
Begin
Return ACOS(SIN(PI()*@Lat1/180.0)*SIN(PI()*@Lat2/180.0)+COS(PI()*@Lat1/180.0)*COS(PI()*@Lat2/180.0)*COS(PI()*@Lng2/180.0-PI()*@Lng1/180.0)) * 6371008.8
-- 6.371 mean radius of earth in meters
End
CREATE TABLE YourTable (
ID INT PRIMARY KEY
, Lat FLOAT
, Lon FLOAT
, Location AS GEOGRAPHY::Point(Lat, Lon, 4326));
INSERT INTO YourTable (ID, Lat, Lon)
VALUES
(1,-8.157908, -34.931675)
, (2,-8.164891, -34.919033)
, (3,-8.159999, -34.939999);
GO
CREATE FUNCTION GetCloserThanOneKilometer (
@Lat FLOAT
, @Lon FLOAT
, @Distance FLOAT)
RETURNS TABLE
AS
RETURN
SELECT *
FROM YourTable
WHERE GEOGRAPHY::Point(@Lat, @Lon, 4326).STDistance(Location) <= @Distance;
SELECT *
FROM GetCloserThanOneKilometer(-8.157908, -34.931675, 1000);
GO