/// <summary> /// 计算Ping流量 /// </summary> /// <param name="param">参数</param> /// <param name="EastVelocity">船速东向分量</param> /// <param name="NorthVelocity">船速北向分量</param> /// <param name="HeadingOffset">航向角改正值,单位:弧度</param> /// <returns>计算结果</returns> public static EnsembleFlowInfo CalculateEnsembleFlow(CalculateEnsembleFlowParam param, double EastVelocity, double NorthVelocity, double HeadingOffset) { EnsembleFlow flow = new EnsembleFlow(); flow.BottomMode = param.RiverDischargeBottomMode; flow.TopMode = param.RiverDischargeTopMode; flow.Draft = param.RiverDischargeDraft; flow.Exponent = param.RiverDischargeExponent; flow.MinAmplitude = param.RiverDischargeConditions.RiverDischargeMinAmplitude; flow.MinCorrelation = param.RiverDischargeConditions.RiverDischargeMinCorrelation; flow.MinNG3 = param.RiverDischargeConditions.RiverDischargeMinNG3; flow.MinNG4 = param.RiverDischargeConditions.RiverDischargeMinNG4; flow.PulseLag = param.RiverDischargeInstrument.RiverDischargePulseLag; flow.PulseLength = param.RiverDischargeInstrument.RiverDischargePulseLength; flow.BeamAngle = param.RiverDischargeInstrument.RiverDischargeBeamAngle; //LPJ 2013-5-21 将船速采用传递的参数---start EarthVelocity boat = new EarthVelocity(); ////boat.EastVelocity = - param.RiverDischargeOrgData.B_Earth[0]; ////boat.NorthVelocity = - param.RiverDischargeOrgData.B_Earth[1]; //boat.EastVelocity = param.RiverDischargeOrgData.B_Earth[0]; //JZH 2012-04-08 //boat.NorthVelocity = param.RiverDischargeOrgData.B_Earth[1]; //JZH 2012-04-08 boat.EastVelocity = EastVelocity; boat.NorthVelocity = NorthVelocity; //LPJ 2013-5-21 将船速采用传递的参数---end return(flow.CalculateEnsembleFlow(param.RiverDischargeOrgData, boat, param.RiverDischarge_dTime, HeadingOffset)); }
//JZH 2012-04-08 添加一个计算岸边平均流速的方法 public static double CalculateShoreVelocity(CalculateShoreFlowParam param) { ShoreFlow flow = new ShoreFlow(); EarthVelocity eVel = new EarthVelocity(); eVel = flow.CalculateAvgVelocity(param.RiverDischargeOrgData, 0.0); double fVelDir = System.Math.Atan2(eVel.EastVelocity, eVel.NorthVelocity); if (fVelDir < 0) { fVelDir = fVelDir / 3.14159 * 180 + 360; } else { fVelDir = fVelDir / 3.14159 * 180; } return(fVelDir); }
/// <summary> /// 计算地理坐标系下的平均流速 /// </summary> /// <param name="srcs">参与计算的数据</param> /// <param name="draft">吃水</param> /// <returns>地理坐标系下的平均流速</returns> public EarthVelocity CalculateAvgVelocity(ArrayClass[] srcs, double draft) //JZH 2012-04-08 提供公共方法 { EarthVelocity avg = new EarthVelocity(); { avg.EastVelocity = 0; avg.NorthVelocity = 0; avg.UpVelocity = 0; avg.qVelocity = 0; } List <EarthVelocity> vels = new List <EarthVelocity>(); foreach (ArrayClass src in srcs) { //如果状态异常,则不用此数据 //if (src.E_Status != 0x00) //LPJ 2016-12-12 cancel 用户实际测量时发现其他数据正常,但状态异常,直接导致岸边流量不计算 // continue; if (src.B_Earth[0] > 80 || src.B_Earth[1] > 80 || src.B_Earth[2] > 80 || src.B_Earth[3] > 80) { continue; } //单元大小 double Da = src.A_CellSize; //if (Da < 1e-6) // throw new Exception("Cell Size too small"); //底跟踪四个波束中的最小深度 double Dmin = double.NaN; //计算四个波束的平均深度 int num = 0; double depthSum = 0; foreach (double d in src.B_Range) { if (d < 1e-6) { continue; } if (double.IsNaN(Dmin)) { Dmin = d; } else { if (d < Dmin) { Dmin = d; } } num++; depthSum += d; } if (num == 0) // 深度均无效则此此次测线数据无效 { continue; } double Davg = depthSum / num; //有效单元的可能最大深度 double DLGmax = Dmin * Math.Cos(beamAngle / 180.0 * Math.PI) + draft - Math.Max((pulseLength + pulseLag) / 2.0, 0.5 * Da); //水面到水底的距离 double Dtotal = Davg + draft; //单元深度 double binDepth = src.A_FirstCellDepth + draft; List <EarthVelocity> cell_vels = new List <EarthVelocity>(); for (int i = 0; binDepth < DLGmax && i < src.E_Cells && i * 4 < src.Earth.Length; i++) { if (!IsGoodBin(src, i)) { continue; } //if (src.B_Velocity[0] > 80 || src.B_Velocity[1] > 80 || src.B_Velocity[2] > 80 || src.B_Velocity[3] > 80) // continue; ////获取速度信息 //double ve = src.Earth[0, i] - src.B_Earth[0]; //double vn = src.Earth[1, i] - src.B_Earth[1]; //double vu = src.Earth[2, i] - src.B_Earth[2]; //double vq = src.Earth[3, i] - src.B_Earth[3]; //获取绝对速度信息 JZH 2012-02-05 double ve = src.Earth[0, i] + src.B_Earth[0]; double vn = src.Earth[1, i] + src.B_Earth[1]; double vu = src.Earth[2, i] + src.B_Earth[2]; double vq = src.Earth[3, i] + src.B_Earth[3]; EarthVelocity ev = new EarthVelocity(); ev.EastVelocity = ve; ev.NorthVelocity = vn; ev.UpVelocity = vu; ev.qVelocity = vq; cell_vels.Add(ev); binDepth += Da; } //如果有效单元少于1个,则这个测线数据不可信 if (cell_vels.Count < 1) { continue; } //求一条测线上平均流速 double avg_ve = 0, avg_vn = 0, avg_vu = 0, avg_vq = 0; foreach (EarthVelocity earth_v in cell_vels) { avg_ve += earth_v.EastVelocity; avg_vn += earth_v.NorthVelocity; avg_vu += earth_v.UpVelocity; avg_vq += earth_v.qVelocity; } avg_ve /= cell_vels.Count; avg_vn /= cell_vels.Count; avg_vu /= cell_vels.Count; avg_vq /= cell_vels.Count; EarthVelocity cells_avg = new EarthVelocity(); cells_avg.EastVelocity = avg_ve; cells_avg.NorthVelocity = avg_vn; cells_avg.UpVelocity = avg_vu; cells_avg.qVelocity = avg_vq; vels.Add(cells_avg); } //如果数据组全部不可信,则返回null //if (vels.Count == 0) // throw new Exception("No Useful Ensembles"); //求多次测量平均速度 double avgall_ve = 0, avgall_vn = 0, avgall_vu = 0, avgall_vq = 0; foreach (EarthVelocity avg_v in vels) { avgall_ve += avg_v.EastVelocity; avgall_vn += avg_v.NorthVelocity; avgall_vu += avg_v.UpVelocity; avgall_vq += avg_v.qVelocity; } if (vels.Count > 0) { avgall_ve /= vels.Count; avgall_vn /= vels.Count; avgall_vu /= vels.Count; avgall_vq /= vels.Count; //EarthVelocity avg = new EarthVelocity(); avg.EastVelocity = avgall_ve; avg.NorthVelocity = avgall_vn; avg.UpVelocity = avgall_vu; avg.qVelocity = avgall_vq; } return(avg); }
/// <summary> /// 计算实测单元流量 /// </summary> /// <param name="src">参与计算的数据</param> /// <param name="boatVelocity">船速(地理坐标系下)</param> /// <param name="dTime">时间差</param> /// <returns>单元流量信息集合</returns> public EnsembleFlowInfo CalculateEnsembleFlow(ArrayClass src, EarthVelocity boatVelocity, double dTime) { EnsembleFlowInfo ensembleFlow = new EnsembleFlowInfo(); ensembleFlow.Valid = false; if (Math.Abs(boatVelocity.EastVelocity) > 80 || Math.Abs(boatVelocity.NorthVelocity) > 80) { return(ensembleFlow); } //单元大小 double Da = src.A_CellSize; if (Da < 1e-6) { return(ensembleFlow); } //底跟踪四个波束中的最小深度 double Dmin = double.NaN; //计算四个波束的平均深度 int num = 0; double depthSum = 0; foreach (double d in src.B_Range) { if (d < 1e-6) { continue; } if (double.IsNaN(Dmin)) { Dmin = d; } else { if (d < Dmin) { Dmin = d; } } num++; depthSum += d; } if (num == 0) { return(ensembleFlow); } double Davg = depthSum / num; //有效单元的可能最大深度 double DLGmax = Dmin * Math.Cos(beamAngle / 180.0 * Math.PI) + draft - Math.Max((pulseLength + pulseLag) / 2.0, Da / 2.0); //水面到水底的距离 double Dtotal = Davg + draft; //第一个有效单元 MeasuredBinInfo firstValid = new MeasuredBinInfo(); firstValid.Status = BinFlowStatus.Bad; //最后一个有效单元 MeasuredBinInfo lastValid = new MeasuredBinInfo(); //单元深度 double binDepth = src.A_FirstCellDepth + draft; //实测累计流量 double SumMeasuredFlow = 0; //累计东向水速 double SumEastVelocity = 0; //累计北向水速 double SumNorthVelocity = 0; //GoodBin个数 int GoodBinCount = 0; List <MeasuredBinInfo> binsInfoArray = new List <MeasuredBinInfo>(); // 保存有效单元的索引号 List <int> validBinsIndex = new List <int>(); for (int i = 0; binDepth < DLGmax && i < src.E_Cells && i * 4 < src.Earth.Length; i++, binDepth += Da) { //获取矢量交叉乘积 double xi = CrossProduct(src.Earth[0, i], src.Earth[1, i], boatVelocity.EastVelocity, boatVelocity.NorthVelocity); MeasuredBinInfo binInfo = new MeasuredBinInfo(); binInfo.Depth = binDepth; binInfo.Flow = xi * dTime * Da; binInfo.Status = (IsGoodBin(src, i) ? BinFlowStatus.Good : BinFlowStatus.Bad); binsInfoArray.Add(binInfo); if (binInfo.Status == BinFlowStatus.Good) { if (firstValid.Status == BinFlowStatus.Bad) { firstValid = binInfo; } lastValid = binInfo; SumMeasuredFlow += binInfo.Flow; SumEastVelocity += src.Earth[0, i]; SumNorthVelocity += src.Earth[1, i]; GoodBinCount++; //保存一个有效单元索引 validBinsIndex.Add(i); } } ensembleFlow.BinsInfo = binsInfoArray.ToArray(); if (firstValid.Status == BinFlowStatus.Bad) { return(ensembleFlow); } //第一个有效单元的深度 double Dtop = firstValid.Depth; //最后一个有效单元的深度 double Dlg = lastValid.Depth; double Z3 = Dtotal; double Z2 = Dtotal - Dtop + Da / 2.0; double Z1 = Dtotal - Dlg - Da / 2.0; //实测流量 ensembleFlow.MeasuredFlow = dTime * (Z2 - Z1) * CrossProduct(SumEastVelocity / GoodBinCount, SumNorthVelocity / GoodBinCount, boatVelocity.EastVelocity, boatVelocity.NorthVelocity); //顶部流量 switch (topMode) { case TopFlowMode.Constants: ensembleFlow.TopFlow = firstValid.Flow / Da * (Z3 - Z2); break; case TopFlowMode.PowerFunction: { double a = exponent + 1; ensembleFlow.TopFlow = SumMeasuredFlow * (Math.Pow(Z3, a) - Math.Pow(Z2, a)) / (Math.Pow(Z2, a) - Math.Pow(Z1, a)); } break; case TopFlowMode.Slope: { //用于外延计算的 validbins 数量不足,则降为常数法计算 if (validBinsIndex.Count < 6) { ensembleFlow.TopFlow = firstValid.Flow / Da * (Z3 - Z2); break; } else { // validbin 的信息,三个列表是索引对应同一个 validbin // 每个 validbin 的深度信息 List <double> binsDepth = new List <double>(); // 每个 validbin 的东向速度 List <double> binsEastVelocity = new List <double>(); // 每个 validbin 的北向速度 List <double> binsNorthVelocity = new List <double>(); for (int i = 0; i < 3; i++) { // validbin 索引号 int bin_index = validBinsIndex[i]; // validbin 深度(从水面起) double bin_depth = src.A_FirstCellDepth + draft + bin_index * Da; // 东向和北向速度 double bin_east_vel = src.Earth[0, bin_index]; double bin_north_vel = src.Earth[1, bin_index]; //加入列表 binsDepth.Add(bin_depth); binsEastVelocity.Add(bin_east_vel); binsNorthVelocity.Add(bin_north_vel); } // 外延计算 // 外延的深度位置(从水面起算) double dep = (Z3 - Z2) / 2; // 外延计算东向速度 Slope east_slope = new Slope(); east_slope.setXYs(binsDepth.ToArray(), binsEastVelocity.ToArray()); double east_vel; try { east_vel = east_slope.calY(dep); } // 外延失败,斜角为90度,转而采用常数法 catch (DivideByZeroException) { ensembleFlow.TopFlow = firstValid.Flow / Da * (Z3 - Z2); break; } //外延计算北向速度 Slope north_slope = new Slope(); north_slope.setXYs(binsDepth.ToArray(), binsNorthVelocity.ToArray()); double north_vel; try { north_vel = north_slope.calY(dep); } // 外延失败,斜角为90度,转而采用常数法 catch (DivideByZeroException) { ensembleFlow.TopFlow = firstValid.Flow / Da * (Z3 - Z2); break; } // 计算流量 ensembleFlow.TopFlow = dTime * (Z3 - Z2) * CrossProduct(east_vel, north_vel, boatVelocity.EastVelocity, boatVelocity.NorthVelocity); break; } } default: break; } //底部流量 switch (bottomMode) { case BottomFlowMode.Constants: ensembleFlow.BottomFlow = lastValid.Flow / Da * Z1; break; case BottomFlowMode.PowerFunction: { double a = exponent + 1; ensembleFlow.BottomFlow = SumMeasuredFlow * Math.Pow(Z1, a) / (Math.Pow(Z2, a) - Math.Pow(Z1, a)); } break; default: break; } ensembleFlow.Valid = true; return(ensembleFlow); }