/// <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);
        }
Example #3
0
        /// <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);
        }
Example #4
0
        /// <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);
        }