From cc3788df309c28a19f61331a5ec5379717799a9b Mon Sep 17 00:00:00 2001 From: ningshuxia <ningshuxia0927@outlook.com> Date: 星期日, 28 四月 2024 10:58:39 +0800 Subject: [PATCH] 分析代码 (未完成 --- Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier2.cs | 258 Schedule/IStation.Algorithm/DAL/BaseDAL.cs | 335 + Schedule/IStation.Algorithm/Model/Curve/Extensions/CurvePoint_Extensions.cs | 463 + Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml.user | 10 Schedule/IStation.Algorithm/Model/Base/BaseModel.cs | 27 Schedule/IStation.Algorithm/Model/Curve/PumpCalculate/PumpCalculateHelper.cs | 1659 +++++ Schedule/IStation.Algorithm/Schedule/ScheduleCalc - 复制.cs | 1932 +++++ Schedule/IStation.Algorithm/Entity/ScheduleCombineLog.cs | 53 Schedule/IStation.Algorithm/Model/Curve/Utils/UtilsHelper.cs | 235 Schedule/IStation.Algorithm/Schedule/Output/ScheduleScheme.cs | 77 Schedule/IStation.Algorithm/Model/Curve/Fit/eFitType.cs | 45 Schedule/IStation.Algorithm/Helper/SnowflakeIdHelper.cs | 46 Schedule/IStation.Algorithm/Data/陈行一输.json | 3074 +++++++++ Schedule/IStation.Algorithm/Model/Curve/Boundary/CurveBoundary.cs | 45 Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurve.cs | 179 Schedule/IStation.Algorithm/Model/Curve/Line/CurveLineHelper.cs | 225 Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve0.cs | 110 Schedule/IStation.Algorithm/Entity/BaseEntity.cs | 27 Schedule/IStation.Algorithm/Model/Json/JsonModel.cs | 37 Schedule/IStation.Algorithm/Schedule/bak/CalcOutput.cs | 10 Schedule/IStation.Algorithm/Helper/LongListHelper.cs | 46 Schedule/IStation.Algorithm/Entity/ScheduleCombine.cs | 59 Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper_v1.cs | 602 + Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve4_MathNet.cs | 113 Schedule/IStation.Algorithm/Data/陈行二输.json | 1466 ++++ Schedule/IStation.Algorithm/Helper/PermutationAndCombination.cs | 187 Schedule/IStation.Algorithm/Model/Pump/Pump.cs | 44 Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate_Disp.cs | 747 ++ Schedule/IStation.Algorithm/Model/Curve/Device/eDeviceSourceType.cs | 18 Schedule/IStation.Algorithm/Model/Curve/Point/CurvePointComparer.cs | 120 Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurveHelper.cs | 82 Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessConstant.cs | 105 Schedule/IStation.Algorithm/Model/Curve/Bezier/BezierCurveHelper.cs | 500 + Schedule/IStation.Algorithm/Model/Curve/Line/CurveLine.cs | 298 IStation.Schedule.sln | 31 Schedule/IStation.Algorithm/Model/Curve/Fit/FitHelper.cs | 274 Schedule/IStation.Algorithm/DAL/USplit.cs | 234 Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve3_MathNet.cs | 174 Schedule/IStation.Algorithm/Model/Curve/Utils/PermutationAndCombination.cs | 187 Schedule/IStation.Algorithm/Model/Curve/Express/CurveExpress.cs | 119 Schedule/IStation.Algorithm/Model/Curve/Constant/Constant.cs | 12 Schedule/IStation.Console/IStation.Console.csproj.user | 6 Schedule/IStation.Console/IStation.Console.csproj | 14 Schedule/IStation.Algorithm/Model/Json/JsonList.cs | 38 Schedule/IStation.Algorithm/Model/Curve/Extensions/CurveExpress_Extensions.cs | 539 + Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_MathNet.cs | 126 Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper.cs | 602 + Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine - 复制.cs | 101 Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine.cs | 53 Schedule/IStation.Algorithm/Schedule/bak/CalcInput.cs | 6 Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate.cs | 124 Schedule/IStation.Console/Program.cs | 24 Schedule/IStation.Algorithm/GlobalUsing.cs | 10 Schedule/IStation.Algorithm/Model/Curve/ParallelConnection/ParallelConnectionHelper.cs | 377 + Schedule/IStation.Algorithm/Helper/JsonHelper.cs | 49 Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_b0.cs | 128 Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier3.cs | 219 Schedule/IStation.Algorithm/Schedule/ScheduleCalc1.cs | 57 Schedule/IStation.Algorithm/Model/Curve/Utils/AmendCurveHelper.cs | 310 Schedule/IStation.Algorithm/Model/Curve/Fit/IFitPoint.cs | 26 Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml | 13 Schedule/IStation.Algorithm/Entity/ScheduleAnaLog.cs | 34 /dev/null | 9 Schedule/IStation.Algorithm/DAL/DbInitial.cs | 92 Schedule/IStation.Algorithm/Model/Curve/Point/GroupPoint.cs | 278 Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessCurvesHelper.cs | 707 ++ Schedule/IStation.Algorithm/Model/Curve/Point/CurvePoint.cs | 198 Schedule/IStation.Algorithm/Model/Curve/Parabola/ParabolaCurveHelper.cs | 516 + Schedule/IStation.Algorithm/IStation.Algorithm.csproj | 50 Schedule/IStation.Algorithm/Schedule/SchedulingCombineAnaHelper.cs | 586 + Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve1.cs | 106 71 files changed, 19,646 insertions(+), 17 deletions(-) diff --git a/IStation.Schedule.sln b/IStation.Schedule.sln new file mode 100644 index 0000000..1b45151 --- /dev/null +++ b/IStation.Schedule.sln @@ -0,0 +1,31 @@ +锘� +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32328.378 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStation.Algorithm", "Schedule\IStation.Algorithm\IStation.Algorithm.csproj", "{5FE2A7BF-1EF8-43A1-B357-95DE35DECD35}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IStation.Console", "Schedule\IStation.Console\IStation.Console.csproj", "{373E22E4-888B-404E-BE88-FF2F6D8E47E8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5FE2A7BF-1EF8-43A1-B357-95DE35DECD35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5FE2A7BF-1EF8-43A1-B357-95DE35DECD35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5FE2A7BF-1EF8-43A1-B357-95DE35DECD35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5FE2A7BF-1EF8-43A1-B357-95DE35DECD35}.Release|Any CPU.Build.0 = Release|Any CPU + {373E22E4-888B-404E-BE88-FF2F6D8E47E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {373E22E4-888B-404E-BE88-FF2F6D8E47E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {373E22E4-888B-404E-BE88-FF2F6D8E47E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {373E22E4-888B-404E-BE88-FF2F6D8E47E8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E02989A8-9B6F-43E5-AACA-790328215089} + EndGlobalSection +EndGlobal diff --git a/IStation.Scheduling.sln b/IStation.Scheduling.sln deleted file mode 100644 index e0667ee..0000000 --- a/IStation.Scheduling.sln +++ /dev/null @@ -1,25 +0,0 @@ -锘� -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32328.378 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStation.Scheduling.Algorithm", "Scheduling\IStation.Scheduling.Algorithm\IStation.Scheduling.Algorithm.csproj", "{43381EDE-EFDE-4D36-9B37-CAAD2F0A6109}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {43381EDE-EFDE-4D36-9B37-CAAD2F0A6109}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {43381EDE-EFDE-4D36-9B37-CAAD2F0A6109}.Debug|Any CPU.Build.0 = Debug|Any CPU - {43381EDE-EFDE-4D36-9B37-CAAD2F0A6109}.Release|Any CPU.ActiveCfg = Release|Any CPU - {43381EDE-EFDE-4D36-9B37-CAAD2F0A6109}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E02989A8-9B6F-43E5-AACA-790328215089} - EndGlobalSection -EndGlobal diff --git a/Schedule/IStation.Algorithm/DAL/BaseDAL.cs b/Schedule/IStation.Algorithm/DAL/BaseDAL.cs new file mode 100644 index 0000000..ac0550b --- /dev/null +++ b/Schedule/IStation.Algorithm/DAL/BaseDAL.cs @@ -0,0 +1,335 @@ +锘縩amespace IStation.DAL +{ + /// <summary> + /// 鏁版嵁搴撹闂熀绫� + /// </summary> + /// <typeparam name="T">瀹炰綋绫荤被鍨�</typeparam> + public partial class BaseDAL<T> + where T : Model.BaseModel, new() + { + /// <summary> + /// 鑾峰彇琛ㄥ悕绉� + /// </summary> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + public string TableName + { + get + { + var objType = typeof(T); + var att = objType.GetCustomAttributes(typeof(SugarTable), true); + if (att != null && att.Count() > 0) + return (att[0] as SugarTable).TableName; + return objType.Name; + } + + } + + /// <summary> + /// 杩炴帴閰嶇疆 + /// </summary> + public virtual ConnectionConfig ConnectionConfig + { + get + { + return default; + } + } + /// <summary> + /// 榛樿杩炴帴瀵硅薄 + /// </summary> + public ISqlSugarClient Connection + { + get + { + return new SqlSugarClient(ConnectionConfig); + } + } + + #region Insert + + /// <summary> + /// 鎻掑叆鎸囧畾瀵硅薄鍒版暟鎹簱涓� + /// </summary> + public virtual long Insert(T entity) + { + if (entity == null) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Insertable(entity).ExecuteReturnSnowflakeId(); + } + } + + /// <summary> + /// 鎻掑叆鎸囧畾瀵硅薄闆嗗悎鍒版暟鎹簱涓� + /// </summary> + public virtual bool Inserts(List<T> list) + { + if (list == null || list.Count < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Insertable(list).ExecuteReturnSnowflakeIdList().Count() > 0; + } + } + + /// <summary> + /// 鎻掑叆骞惰繑鍥� + /// </summary> + public virtual List<long> InsertsR(List<T> list) + { + if (list == null || list.Count < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Insertable(list).ExecuteReturnSnowflakeIdList(); + } + } + + /// <summary> + /// 澶ф壒閲忔彃鍏� + /// </summary> + public virtual bool BulkInserts(List<T> list) + { + if (list == null || list.Count < 1) + return default; + list.ForEach(x => x.ID = SnowFlakeSingle.instance.NextId()); + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Fastest<T>().BulkCopy(list) > 0; + } + } + + #endregion + + #region Update + + /// <summary> + /// 鏇存柊瀵硅薄灞炴�у埌鏁版嵁搴撲腑 + /// </summary> + public virtual bool Update(T entity) + { + if (entity == null) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Updateable(entity).ExecuteCommand() > 0; + } + } + + /// <summary> + /// 鏇存柊閮ㄥ垎 + /// </summary> + public virtual bool UpdatePart(T entity, List<string> pros) + { + if (entity == null) + return default; + if (pros == null || pros.Count < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Updateable(entity).UpdateColumns(pros.ToArray()).ExecuteCommand() > 0; + } + } + + /// <summary> + /// 鏇存柊鎸囧畾瀵硅薄闆嗗悎鍒版暟鎹簱涓� + /// </summary> + public virtual bool Updates(List<T> list) + { + if (list == null || list.Count < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Updateable(list).ExecuteCommand() > 0; + } + } + + /// <summary> + /// 鎵归噺鏇存柊閮ㄥ垎 + /// </summary> + public virtual bool UpdatesPart(List<T> list, List<string> pros) + { + if (list == null || list.Count() < 1) + return default; + if (pros == null || pros.Count < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Updateable(list).UpdateColumns(pros.ToArray()).ExecuteCommand() > 0; + } + } + + /// <summary> + /// 澶ф壒閲忔洿鏂� + /// </summary> + public virtual bool BulkUpdates(List<T> list) + { + if (list == null || list.Count < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Fastest<T>().BulkUpdate(list) > 0; + } + } + + #endregion + + #region Delete + + /// <summary> + /// 浠庢暟鎹簱涓垹闄ゆ寚瀹氬璞� + /// </summary> + public virtual bool Delete(T entity) + { + if (entity == null) + return default; + if (entity.ID < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Deleteable<T>().Where(entity).ExecuteCommand() > 0; + } + } + + /// <summary> + /// 浠庢暟鎹簱涓垹闄ゆ寚瀹氬璞¢泦鍚� + /// </summary> + public virtual bool Deletes(List<T> list) + { + if (list == null || list.Count < 1) + return default; + if (list.Exists(x => x.ID < 1)) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Deleteable<T>().Where(list).ExecuteCommand() > 0; + } + } + + /// <summary> + /// 鏍规嵁鎸囧畾瀵硅薄鐨処D,浠庢暟鎹簱涓垹闄ゆ寚瀹氬璞� + /// </summary> + public virtual bool DeleteByID(long ID) + { + if (ID < 1) + return default; + + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Deleteable<T>().Where(x => x.ID == ID).ExecuteCommand() > 0; + } + } + + /// <summary> + /// 閫氳繃id鍒楄〃鍒犻櫎 + /// </summary> + public virtual bool DeleteByIds(List<long> ids) + { + if (ids == null || ids.Count < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Deleteable<T>().Where(x => ids.Contains(x.ID)).ExecuteCommand() > 0; + } + } + + /// <summary> + /// 浠庢暟鎹簱涓垹闄ゆ墍鏈夊璞� + /// </summary> + public virtual bool DeleteAll() + { + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.DbMaintenance.TruncateTable<T>(); + } + } + + #endregion + + #region Query + + /// <summary> + /// 杩斿洖鏁版嵁搴撴墍鏈夌殑瀵硅薄闆嗗悎 + /// </summary> + public virtual List<T> GetAll() + { + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Queryable<T>().ToList(); + } + } + + /// <summary> + /// 鏌ヨ鏁版嵁搴�,杩斿洖鎸囧畾ID鐨勫璞� + /// </summary> + public virtual T GetByID(long id) + { + if (id < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Queryable<T>().First(x => x.ID == id); + } + } + + /// <summary> + /// 閫氭嫇id鍒楄〃鑾峰彇 + /// </summary> + /// <returns></returns> + public virtual List<T> GetByIds(List<long> ids) + { + if (ids == null || ids.Count < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Queryable<T>().OrderBy(x => x.ID).Where(x => ids.Contains(x.ID)).ToList(); + } + } + + #endregion + + #region Exist + + /// <summary> + /// 鍒ゆ柇鏁版嵁搴撴槸鍚﹀瓨鍦ㄥ璞� + /// </summary> + public virtual bool Exist(long id) + { + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Queryable<T>().Where(x => x.ID == id).Any(); + } + } + + #endregion + + #region Cover + + /// <summary> + /// 瑕嗙洊 + /// </summary> + public virtual bool Covers(List<T> list) + { + if (list == null || list.Count < 1) + return default; + + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + db.Ado.BeginTran(); + db.Deleteable<T>().ExecuteCommand(); + var bol = db.Insertable(list).ExecuteCommand() > 0; + if (!bol) + { + db.Ado.RollbackTran(); + return false; + } + db.Ado.CommitTran(); + } + return true; + } + + #endregion + } +} diff --git a/Schedule/IStation.Algorithm/DAL/DbInitial.cs b/Schedule/IStation.Algorithm/DAL/DbInitial.cs new file mode 100644 index 0000000..52c9d56 --- /dev/null +++ b/Schedule/IStation.Algorithm/DAL/DbInitial.cs @@ -0,0 +1,92 @@ +锘縰sing System.Data.SQLite; + +namespace IStation.DAL +{ + public class DbInitial + { + + private static string _dbName = "Db4Schedule.db"; + private static string _filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data"); + public static string DbFilePath + { + get => _filePath + "\\" + _dbName; + } + + /// <summary> + /// 鍒濆鏁版嵁搴� + /// </summary> + /// <param name="backup"></param> + /// <param name="stringDefaultLength"></param> + /// <returns></returns> + public static bool InitTables(bool backup = false, int stringDefaultLength = 250) + { + var db = GetDb(); + if (db == null) + return false; + + Type[] types = new Type[] { + typeof(Entity.ScheduleCombine), + typeof(Entity.ScheduleCombineLog), + typeof(Entity.ScheduleAnaLog), + + }; + + //Db.CodeFirst.SetStringDefaultLength(StringDefaultLength); + db.DbMaintenance.CreateDatabase(); + if (backup) + { + db.CodeFirst.BackupTable().InitTables(types); + } + else + { + db.CodeFirst.InitTables(types); + } + return true; + } + + private static SqlSugarClient GetDb() + { + var filePath = DbFilePath; + if (!System.IO.File.Exists(filePath)) + { + try + { + SQLiteConnection.CreateFile(filePath); + } + catch (Exception ex) + { + var errMsg = $".db 鏂囦欢涓嶅瓨鍦�!Path:{filePath}\r\n{ex.Message}"; + throw new Exception(errMsg); + } + } + + var config = new ConnectionConfig(); + config.ConnectionString = $"DataSource={filePath}"; + config.IsAutoCloseConnection = true; + config.DbType = SqlSugar.DbType.Sqlite; + config.ConfigureExternalServices = new ConfigureExternalServices() + { + EntityService = (property, column) => + { + //闄や富閿閮藉彲绌� + if (!column.IsPrimarykey) + { + column.IsNullable = true; + } + } + }; + + var db = new SqlSugarClient(config); + db.Aop.OnLogExecuting = (sql, pars) => + { + Console.WriteLine(sql + "\r\n" + db.Utilities.SerializeObject + (pars.ToDictionary(it => it.ParameterName, it => it.Value))); + Console.WriteLine(); + }; + + return db; + } + + } + +} diff --git a/Schedule/IStation.Algorithm/DAL/USplit.cs b/Schedule/IStation.Algorithm/DAL/USplit.cs new file mode 100644 index 0000000..f2d22f8 --- /dev/null +++ b/Schedule/IStation.Algorithm/DAL/USplit.cs @@ -0,0 +1,234 @@ +锘縰sing System.Reflection; +namespace IStation.Algorithm +{ + public class NewUnitTest + { + public static void SplitTest() + { + var db = new SqlSugarClient(new ConnectionConfig()); + + db.CodeFirst.SplitTables().InitTables<SplitTestTable>(); + + var data = new SplitTestTable() + { + CreateTime = Convert.ToDateTime("2019-12-1"), + Name = "jack" + }; + var datas = new List<SplitTestTable>() + { + new SplitTestTable() + { + CreateTime=Convert.ToDateTime("2019-12-1"), + Name="jack" + } , + new SplitTestTable() + { + CreateTime=Convert.ToDateTime("2022-02-1"), + Name="jack" + }, + new SplitTestTable() + { + CreateTime=Convert.ToDateTime("2020-02-1"), + Name="jack" + }, + new SplitTestTable() + { + CreateTime=Convert.ToDateTime("2021-12-1"), + Name="jack" + } + }; + + long id = db.Insertable(data).SplitTable().ExecuteReturnSnowflakeId(); + + List<long> ids = db.Insertable(datas).SplitTable().ExecuteReturnSnowflakeIdList(); + + var count = 0; + db.Queryable<SplitTestTable>().Where(it => it.Name.Contains("a")).SplitTable(tas => tas.Take(3)).ToPageList(1, 2, ref count); + + var table2019 = db.SplitHelper<SplitTestTable>().GetTableName("2019-12-1"); + db.Queryable<SplitTestTable>().Where(it => it.Name.Contains("a")).SplitTable(tas => tas.InTableNames(table2019)).ToList(); + + db.Queryable<SplitTestTable>().Where(it => it.Id == 1).SplitTable(tas => tas.Where(y => y.TableName.Contains("2019"))).ToList(); + + var deldata = new SplitTestTable() + { + Id = id, + CreateTime = DateTime.Now + }; + var tableName = db.SplitHelper(deldata).GetTableNames(); + db.Deleteable<SplitTestTable>().Where(deldata).SplitTable(tas => tas.InTableNames(tableName)).ExecuteCommand(); + + + db.Updateable(deldata).SplitTable(tas => tas.Take(3)).ExecuteCommand(); + db.Updateable(deldata).SplitTable(tas => tas.InTableNames(tableName)).ExecuteCommand(); + + + //浣跨敤鑷畾涔夊垎琛� + db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new WordSplitService(); + db.Insertable(new WordTestTable() + { + CreateTime = DateTime.Now, + Name = "BC" + }).SplitTable().ExecuteReturnSnowflakeId(); + db.Insertable(new WordTestTable() + { + CreateTime = DateTime.Now, + Name = "AC" + }).SplitTable().ExecuteReturnSnowflakeId(); + db.Insertable(new WordTestTable() + { + CreateTime = DateTime.Now, + Name = "ZBZ" + }).SplitTable().ExecuteReturnSnowflakeId(); + + //鍙煡A琛� + var listall = db.Queryable<WordTestTable>().Where(it => it.Name == "all").SplitTable(tas => tas.ContainsTableNames("_FirstA")).ToList(); + + } + } + + + + /// <summary> + /// 闅忎究璁剧疆涓�涓垎绫� + /// </summary> + [SplitTable(SplitType._Custom01)] + public class WordTestTable + { + [SugarColumn(IsPrimaryKey = true)] + public long Id { get; set; } + + [SplitField] //鏍囪瘑涓�涓嬪垎琛ㄥ瓧娈� + public string Name { get; set; } + + + public DateTime CreateTime { get; set; } + + } + + public class WordSplitService : ISplitTableService + { + /// <summary> + /// 杩斿洖鏁版嵁搴撲腑鎵�鏈夊垎琛� + /// </summary> + /// <param name="db"></param> + /// <param name="EntityInfo"></param> + /// <param name="tableInfos"></param> + /// <returns></returns> + public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos) + { + List<SplitTableInfo> result = new List<SplitTableInfo>(); + foreach (var item in tableInfos) + { + if (item.Name.Contains("_First")) //鍖哄垎鏍囪瘑濡傛灉涓嶇敤姝e垯绗﹀鏉備竴浜涳紝闃叉鎵鹃敊琛� + { + SplitTableInfo data = new SplitTableInfo() + { + TableName = item.Name //瑕佺敤item.name涓嶈鍐欓敊浜� + }; + result.Add(data); + } + } + return result.OrderBy(it => it.TableName).ToList();//鎵撴柇鐐圭湅涓�涓嬫湁娌℃湁鏌ュ嚭鎵�鏈夊垎琛� + } + + /// <summary> + /// 鑾峰彇鍒嗚〃瀛楁鐨勫�� + /// </summary> + /// <param name="db"></param> + /// <param name="entityInfo"></param> + /// <param name="splitType"></param> + /// <param name="entityValue"></param> + /// <returns></returns> + public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue) + { + var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null); + var value = splitColumn.PropertyInfo.GetValue(entityValue, null); + return value; + } + + /// <summary> + /// 榛樿琛ㄥ悕 + /// </summary> + /// <param name="db"></param> + /// <param name="EntityInfo"></param> + /// <returns></returns> + public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo) + { + return entityInfo.DbTableName + "_FirstA"; + } + + public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType type) + { + return entityInfo.DbTableName + "_FirstA";//鐩墠妯″紡灏戜笉闇�瑕佸垎绫�(鑷甫鐨勬湁 鏃ャ�佸懆銆佹湀銆佸銆佸勾绛夎繘琛屽尯鍒�) + } + + public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue) + { + return entityInfo.DbTableName + "_First" + GetFirstCode(fieldValue + ""); //鏍规嵁鍊兼寜棣栧瓧姣� + } + + #region 鑾峰彇棣栧瓧姣� + /// <summary> + /// 鍦ㄦ寚瀹氱殑瀛楃涓插垪琛–nStr涓绱㈢鍚堟嫾闊崇储寮曞瓧绗︿覆 + /// </summary> + /// <param name="CnStr">姹夊瓧瀛楃涓�</param> + /// <returns>鐩稿搴旂殑姹夎鎷奸煶棣栧瓧姣嶄覆</returns> + public static string GetFirstCode(string CnStr) + { + string Surname = CnStr.Substring(0, 1); + string strTemp = GetSpellCode(Surname); + return strTemp; + } + + /// <summary> + /// 寰楀埌涓�涓眽瀛楃殑鎷奸煶绗竴涓瓧姣嶏紝濡傛灉鏄竴涓嫳鏂囧瓧姣嶅垯鐩存帴杩斿洖澶у啓瀛楁瘝 + /// </summary> + /// <param name="CnChar">鍗曚釜姹夊瓧</param> + /// <returns>鍗曚釜澶у啓瀛楁瘝</returns> + private static string GetSpellCode(string CnChar) + { + long iCnChar; + byte[] arrCN = System.Text.Encoding.Default.GetBytes(CnChar); + + //濡傛灉鏄瓧姣嶏紝鍒欑洿鎺ヨ繑鍥� + if (arrCN.Length == 1) + { + CnChar = CnChar.ToUpper(); + } + else + { + int area = (short)arrCN[0]; + int pos = (short)arrCN[1]; + iCnChar = (area << 8) + pos; + + // iCnChar match the constant + string letter = "ABCDEFGHJKLMNOPQRSTWXYZ"; + int[] areacode = { 45217, 45253, 45761, 46318, 46826, 47010, 47297, 47614, 48119, 49062, 49324, 49896, 50371, 50614, 50622, 50906, 51387, 51446, 52218, 52698, 52980, 53689, 54481, 55290 }; + for (int i = 0; i < 23; i++) + { + if (areacode[i] <= iCnChar && iCnChar < areacode[i + 1]) + { + CnChar = letter.Substring(i, 1); + break; + } + } + } + return CnChar; + } + #endregion + } + + + [SplitTable(SplitType.Year)]//鎸夊勾鍒嗚〃 + [SugarTable("SplitTestTable_{year}{month}{day}")]//鐢熸垚琛ㄥ悕鏍煎紡 3涓彉閲忓繀椤昏鏈� + public class SplitTestTable + { + [SugarColumn(IsPrimaryKey = true)] + public long Id { get; set; } + + public string Name { get; set; } + [SplitField] + public DateTime CreateTime { get; set; } + } +} diff --git "a/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\270\200\350\276\223.json" "b/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\270\200\350\276\223.json" new file mode 100644 index 0000000..627d4e2 --- /dev/null +++ "b/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\270\200\350\276\223.json" @@ -0,0 +1,3074 @@ +[ + { + "Belong": 1, + "ID": 11, + "Code": "32SAP-13J", + "Name": "11#娉�", + "Qr": 4650.0, + "Hr": 36.0, + "Nr": 590.0, + "Pr": 524.0, + "Er": 0.0, + "Ic": 800.0, + "Oc": null, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": true, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 5706.52, + "Min": 0.0, + "Index0": 43.648883456052658, + "Index1": 7.4030314266712176E-05, + "Index2": -4.0550392935079751E-07, + "Index3": -1.5326481950336734E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 43.33 + }, + { + "X": 777.64, + "Y": 44.12 + }, + { + "X": 777.64, + "Y": 43.38 + }, + { + "X": 777.64, + "Y": 43.6 + }, + { + "X": 2363.29, + "Y": 40.44 + }, + { + "X": 2363.29, + "Y": 40.59 + }, + { + "X": 2368.42, + "Y": 42.24 + }, + { + "X": 2368.42, + "Y": 41.18 + }, + { + "X": 2948.46, + "Y": 40.03 + }, + { + "X": 2948.46, + "Y": 39.99 + }, + { + "X": 2957.71, + "Y": 39.99 + }, + { + "X": 3566.53, + "Y": 38.09 + }, + { + "X": 3566.53, + "Y": 38.07 + }, + { + "X": 3579.9, + "Y": 37.87 + }, + { + "X": 3995.35, + "Y": 36.41 + }, + { + "X": 4001.52, + "Y": 36.87 + }, + { + "X": 4001.52, + "Y": 36.83 + }, + { + "X": 4326.26, + "Y": 35.03 + }, + { + "X": 4326.26, + "Y": 35.19 + }, + { + "X": 4328.31, + "Y": 35.32 + }, + { + "X": 4626.6, + "Y": 33.71 + }, + { + "X": 4626.6, + "Y": 33.81 + }, + { + "X": 4629.69, + "Y": 33.92 + }, + { + "X": 4865.72, + "Y": 32.72 + }, + { + "X": 4867.78, + "Y": 32.42 + }, + { + "X": 4867.78, + "Y": 32.94 + }, + { + "X": 5208.79, + "Y": 30.53 + }, + { + "X": 5208.79, + "Y": 30.72 + }, + { + "X": 5220.1, + "Y": 30.52 + }, + { + "X": 5347.84, + "Y": 29.99 + }, + { + "X": 5347.84, + "Y": 30.25 + }, + { + "X": 5347.84, + "Y": 29.8 + }, + { + "X": 5706.52, + "Y": 27.98 + }, + { + "X": 5706.52, + "Y": 28.09 + }, + { + "X": 5706.52, + "Y": 28.38 + }, + { + "X": 5706.52, + "Y": 28.06 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 5706.52, + "Min": 0.0, + "Index0": -0.029779478378107644, + "Index1": 0.046685780520780026, + "Index2": -8.4107525765208659E-06, + "Index3": 4.8233872354460685E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 777.64, + "Y": 31.69 + }, + { + "X": 777.64, + "Y": 31.17 + }, + { + "X": 777.64, + "Y": 31.32 + }, + { + "X": 2363.29, + "Y": 68.49 + }, + { + "X": 2363.29, + "Y": 68.72 + }, + { + "X": 2368.42, + "Y": 71.67 + }, + { + "X": 2368.42, + "Y": 69.86 + }, + { + "X": 2948.46, + "Y": 77.25 + }, + { + "X": 2948.46, + "Y": 77.16 + }, + { + "X": 2957.71, + "Y": 77.41 + }, + { + "X": 3566.53, + "Y": 80.9 + }, + { + "X": 3566.53, + "Y": 80.88 + }, + { + "X": 3579.9, + "Y": 80.76 + }, + { + "X": 3995.35, + "Y": 82.29 + }, + { + "X": 4001.52, + "Y": 83.45 + }, + { + "X": 4001.52, + "Y": 83.36 + }, + { + "X": 4326.26, + "Y": 83.3 + }, + { + "X": 4326.26, + "Y": 83.66 + }, + { + "X": 4328.31, + "Y": 83.99 + }, + { + "X": 4626.6, + "Y": 83.7 + }, + { + "X": 4626.6, + "Y": 83.96 + }, + { + "X": 4629.69, + "Y": 84.26 + }, + { + "X": 4865.72, + "Y": 83.87 + }, + { + "X": 4867.78, + "Y": 83.31 + }, + { + "X": 4867.78, + "Y": 84.45 + }, + { + "X": 5208.79, + "Y": 82.2 + }, + { + "X": 5208.79, + "Y": 82.69 + }, + { + "X": 5220.1, + "Y": 82.33 + }, + { + "X": 5347.84, + "Y": 82.98 + }, + { + "X": 5347.84, + "Y": 83.65 + }, + { + "X": 5347.84, + "Y": 82.44 + }, + { + "X": 5706.52, + "Y": 81.86 + }, + { + "X": 5706.52, + "Y": 82.18 + }, + { + "X": 5706.52, + "Y": 83.06 + }, + { + "X": 5706.52, + "Y": 81.75 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 5706.52, + "Min": 0.0, + "Index0": 286.70251212427235, + "Index1": -0.0010888827584349908, + "Index2": 2.3429799453563776E-05, + "Index3": -2.7612070035556893E-09, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 292.46 + }, + { + "X": 777.64, + "Y": 295.0 + }, + { + "X": 777.64, + "Y": 294.9 + }, + { + "X": 777.64, + "Y": 295.0 + }, + { + "X": 2363.29, + "Y": 380.2 + }, + { + "X": 2363.29, + "Y": 380.4 + }, + { + "X": 2368.42, + "Y": 380.4 + }, + { + "X": 2368.42, + "Y": 380.4 + }, + { + "X": 2948.46, + "Y": 416.3 + }, + { + "X": 2948.46, + "Y": 416.4 + }, + { + "X": 2957.71, + "Y": 416.4 + }, + { + "X": 3566.53, + "Y": 457.6 + }, + { + "X": 3566.53, + "Y": 457.5 + }, + { + "X": 3579.9, + "Y": 457.4 + }, + { + "X": 3995.35, + "Y": 481.7 + }, + { + "X": 4001.52, + "Y": 481.8 + }, + { + "X": 4001.52, + "Y": 481.8 + }, + { + "X": 4326.26, + "Y": 495.8 + }, + { + "X": 4326.26, + "Y": 495.9 + }, + { + "X": 4328.31, + "Y": 496.0 + }, + { + "X": 4626.6, + "Y": 507.8 + }, + { + "X": 4626.6, + "Y": 507.7 + }, + { + "X": 4629.69, + "Y": 507.9 + }, + { + "X": 4865.72, + "Y": 517.3 + }, + { + "X": 4867.78, + "Y": 516.2 + }, + { + "X": 4867.78, + "Y": 517.4 + }, + { + "X": 5208.79, + "Y": 527.2 + }, + { + "X": 5208.79, + "Y": 527.3 + }, + { + "X": 5220.1, + "Y": 527.3 + }, + { + "X": 5347.84, + "Y": 526.7 + }, + { + "X": 5347.84, + "Y": 527.0 + }, + { + "X": 5347.84, + "Y": 526.8 + }, + { + "X": 5706.52, + "Y": 531.5 + }, + { + "X": 5706.52, + "Y": 531.5 + }, + { + "X": 5706.52, + "Y": 531.3 + }, + { + "X": 5706.52, + "Y": 533.7 + } + ], + "IsNull": false + } + }, + { + "Belong": 1, + "ID": 12, + "Code": "32SAP-13J", + "Name": "12#娉�", + "Qr": 4650.0, + "Hr": 36.0, + "Nr": 590.0, + "Pr": 524.0, + "Er": 0.0, + "Ic": 800.0, + "Oc": null, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": true, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 5675.26, + "Min": 0.0, + "Index0": 47.195534051251009, + "Index1": -0.0031316346389259966, + "Index2": 5.3083437637509132E-07, + "Index3": -9.8706792090612373E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 47.52 + }, + { + "X": 1258.78, + "Y": 43.87 + }, + { + "X": 1259.8, + "Y": 44.74 + }, + { + "X": 1259.8, + "Y": 43.11 + }, + { + "X": 1263.92, + "Y": 42.77 + }, + { + "X": 2579.45, + "Y": 42.25 + }, + { + "X": 2579.45, + "Y": 41.57 + }, + { + "X": 2582.54, + "Y": 40.66 + }, + { + "X": 2582.54, + "Y": 40.41 + }, + { + "X": 3385.26, + "Y": 38.94 + }, + { + "X": 3385.26, + "Y": 38.54 + }, + { + "X": 3387.32, + "Y": 39.24 + }, + { + "X": 4167.62, + "Y": 36.34 + }, + { + "X": 4167.62, + "Y": 36.25 + }, + { + "X": 4179.98, + "Y": 36.2 + }, + { + "X": 4192.35, + "Y": 36.25 + }, + { + "X": 4416.75, + "Y": 34.64 + }, + { + "X": 4425.0, + "Y": 34.97 + }, + { + "X": 4425.0, + "Y": 35.22 + }, + { + "X": 4988.82, + "Y": 32.48 + }, + { + "X": 4992.94, + "Y": 32.39 + }, + { + "X": 4992.94, + "Y": 32.45 + }, + { + "X": 5213.33, + "Y": 30.98 + }, + { + "X": 5213.33, + "Y": 31.17 + }, + { + "X": 5222.6, + "Y": 31.3 + }, + { + "X": 5674.23, + "Y": 28.37 + }, + { + "X": 5674.23, + "Y": 28.83 + }, + { + "X": 5675.26, + "Y": 28.83 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 5675.26, + "Min": 0.0, + "Index0": 0.20481919329756557, + "Index1": 0.044889561775007351, + "Index2": -7.8579066706635246E-06, + "Index3": 4.3596190722464567E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 1258.78, + "Y": 45.48 + }, + { + "X": 1259.8, + "Y": 46.42 + }, + { + "X": 1259.8, + "Y": 44.73 + }, + { + "X": 1263.92, + "Y": 44.52 + }, + { + "X": 2579.45, + "Y": 73.12 + }, + { + "X": 2579.45, + "Y": 71.95 + }, + { + "X": 2582.54, + "Y": 70.44 + }, + { + "X": 2582.54, + "Y": 70.01 + }, + { + "X": 3385.26, + "Y": 78.51 + }, + { + "X": 3385.26, + "Y": 77.68 + }, + { + "X": 3387.32, + "Y": 79.13 + }, + { + "X": 4167.62, + "Y": 82.59 + }, + { + "X": 4167.62, + "Y": 82.36 + }, + { + "X": 4179.98, + "Y": 82.49 + }, + { + "X": 4192.35, + "Y": 82.87 + }, + { + "X": 4416.75, + "Y": 81.62 + }, + { + "X": 4425.0, + "Y": 82.54 + }, + { + "X": 4425.0, + "Y": 83.1 + }, + { + "X": 4988.82, + "Y": 83.21 + }, + { + "X": 4992.94, + "Y": 83.06 + }, + { + "X": 4992.94, + "Y": 83.2 + }, + { + "X": 5213.33, + "Y": 82.22 + }, + { + "X": 5213.33, + "Y": 82.74 + }, + { + "X": 5222.6, + "Y": 83.21 + }, + { + "X": 5674.23, + "Y": 80.29 + }, + { + "X": 5674.23, + "Y": 81.64 + }, + { + "X": 5675.26, + "Y": 81.62 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 5675.26, + "Min": 0.0, + "Index0": 291.5189306898522, + "Index1": 0.012457757862366158, + "Index2": 1.8075021817032405E-05, + "Index3": -2.1891141843012458E-09, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 292.59 + }, + { + "X": 1258.78, + "Y": 330.9 + }, + { + "X": 1259.8, + "Y": 330.9 + }, + { + "X": 1259.8, + "Y": 330.9 + }, + { + "X": 1263.92, + "Y": 330.9 + }, + { + "X": 2579.45, + "Y": 406.1 + }, + { + "X": 2579.45, + "Y": 406.1 + }, + { + "X": 2582.54, + "Y": 406.2 + }, + { + "X": 2582.54, + "Y": 406.2 + }, + { + "X": 3385.26, + "Y": 457.5 + }, + { + "X": 3385.26, + "Y": 457.7 + }, + { + "X": 3387.32, + "Y": 457.7 + }, + { + "X": 4167.62, + "Y": 499.7 + }, + { + "X": 4167.62, + "Y": 499.9 + }, + { + "X": 4179.98, + "Y": 499.9 + }, + { + "X": 4192.35, + "Y": 499.7 + }, + { + "X": 4416.75, + "Y": 510.8 + }, + { + "X": 4425.0, + "Y": 510.9 + }, + { + "X": 4425.0, + "Y": 511.1 + }, + { + "X": 4988.82, + "Y": 530.6 + }, + { + "X": 4992.94, + "Y": 530.6 + }, + { + "X": 4992.94, + "Y": 530.7 + }, + { + "X": 5213.33, + "Y": 535.3 + }, + { + "X": 5213.33, + "Y": 535.2 + }, + { + "X": 5222.6, + "Y": 535.3 + }, + { + "X": 5674.23, + "Y": 546.4 + }, + { + "X": 5674.23, + "Y": 546.0 + }, + { + "X": 5675.26, + "Y": 546.3 + } + ], + "IsNull": false + } + }, + { + "Belong": 1, + "ID": 13, + "Code": "32SAP-13J", + "Name": "13#娉�", + "Qr": 4650.0, + "Hr": 36.0, + "Nr": 590.0, + "Pr": 524.0, + "Er": 0.0, + "Ic": 800.0, + "Oc": null, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": true, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 5830.07, + "Min": 0.0, + "Index0": 45.971466750718129, + "Index1": -0.0030685923474283584, + "Index2": 6.1600684431475443E-07, + "Index3": -1.0874614309657326E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 46.16 + }, + { + "X": 2045.66, + "Y": 40.22 + }, + { + "X": 2045.66, + "Y": 40.66 + }, + { + "X": 2045.66, + "Y": 41.8 + }, + { + "X": 2045.66, + "Y": 41.43 + }, + { + "X": 3175.97, + "Y": 39.51 + }, + { + "X": 3175.97, + "Y": 39.43 + }, + { + "X": 3183.17, + "Y": 39.18 + }, + { + "X": 3990.9, + "Y": 36.68 + }, + { + "X": 3990.9, + "Y": 37.08 + }, + { + "X": 4001.18, + "Y": 37.44 + }, + { + "X": 4001.18, + "Y": 36.77 + }, + { + "X": 4653.78, + "Y": 33.68 + }, + { + "X": 4653.78, + "Y": 33.76 + }, + { + "X": 4653.78, + "Y": 33.85 + }, + { + "X": 5005.03, + "Y": 31.81 + }, + { + "X": 5005.03, + "Y": 31.64 + }, + { + "X": 5008.12, + "Y": 31.76 + }, + { + "X": 5448.45, + "Y": 30.15 + }, + { + "X": 5448.45, + "Y": 29.95 + }, + { + "X": 5449.48, + "Y": 30.23 + }, + { + "X": 5778.65, + "Y": 27.88 + }, + { + "X": 5830.07, + "Y": 27.98 + }, + { + "X": 5830.07, + "Y": 27.6 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 5830.07, + "Min": 0.0, + "Index0": -0.18050658767605141, + "Index1": 0.043920723810219685, + "Index2": -7.3007203113442942E-06, + "Index3": 3.7599435997923435E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 2045.66, + "Y": 60.8 + }, + { + "X": 2045.66, + "Y": 61.47 + }, + { + "X": 2045.66, + "Y": 63.2 + }, + { + "X": 2045.66, + "Y": 62.63 + }, + { + "X": 3175.97, + "Y": 78.37 + }, + { + "X": 3175.97, + "Y": 78.2 + }, + { + "X": 3183.17, + "Y": 77.91 + }, + { + "X": 3990.9, + "Y": 82.39 + }, + { + "X": 3990.9, + "Y": 83.28 + }, + { + "X": 4001.18, + "Y": 84.29 + }, + { + "X": 4001.18, + "Y": 82.8 + }, + { + "X": 4653.78, + "Y": 83.32 + }, + { + "X": 4653.78, + "Y": 83.51 + }, + { + "X": 4653.78, + "Y": 83.74 + }, + { + "X": 5005.03, + "Y": 83.19 + }, + { + "X": 5005.03, + "Y": 82.78 + }, + { + "X": 5008.12, + "Y": 83.11 + }, + { + "X": 5448.45, + "Y": 84.01 + }, + { + "X": 5448.45, + "Y": 83.48 + }, + { + "X": 5449.48, + "Y": 84.23 + }, + { + "X": 5778.65, + "Y": 81.95 + }, + { + "X": 5830.07, + "Y": 82.99 + }, + { + "X": 5830.07, + "Y": 81.84 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 5830.07, + "Min": 0.0, + "Index0": 291.34365036887829, + "Index1": 0.0091342142239327628, + "Index2": 1.8648686848210918E-05, + "Index3": -2.2377680027802434E-09, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 291.53 + }, + { + "X": 2045.66, + "Y": 368.8 + }, + { + "X": 2045.66, + "Y": 368.7 + }, + { + "X": 2045.66, + "Y": 368.7 + }, + { + "X": 2045.66, + "Y": 368.8 + }, + { + "X": 3175.97, + "Y": 436.3 + }, + { + "X": 3175.97, + "Y": 436.4 + }, + { + "X": 3183.17, + "Y": 436.2 + }, + { + "X": 3990.9, + "Y": 484.2 + }, + { + "X": 3990.9, + "Y": 484.2 + }, + { + "X": 4001.18, + "Y": 484.3 + }, + { + "X": 4001.18, + "Y": 484.2 + }, + { + "X": 4653.78, + "Y": 512.6 + }, + { + "X": 4653.78, + "Y": 512.7 + }, + { + "X": 4653.78, + "Y": 512.6 + }, + { + "X": 5005.03, + "Y": 521.5 + }, + { + "X": 5005.03, + "Y": 521.3 + }, + { + "X": 5008.12, + "Y": 521.5 + }, + { + "X": 5448.45, + "Y": 532.8 + }, + { + "X": 5448.45, + "Y": 532.7 + }, + { + "X": 5449.48, + "Y": 533.0 + }, + { + "X": 5778.65, + "Y": 535.7 + }, + { + "X": 5830.07, + "Y": 535.6 + }, + { + "X": 5830.07, + "Y": 535.8 + } + ], + "IsNull": false + } + }, + { + "Belong": 1, + "ID": 14, + "Code": "32SAP-13J", + "Name": "14#娉�", + "Qr": 4650.0, + "Hr": 36.0, + "Nr": 590.0, + "Pr": 524.0, + "Er": 0.0, + "Ic": 800.0, + "Oc": null, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": true, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 5816.67, + "Min": 0.0, + "Index0": 44.330692861292135, + "Index1": -0.0017619779138461755, + "Index2": 2.5273009313700269E-07, + "Index3": -7.5656518409756874E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 44.41 + }, + { + "X": 1892.76, + "Y": 41.43 + }, + { + "X": 1892.76, + "Y": 40.75 + }, + { + "X": 1892.76, + "Y": 41.53 + }, + { + "X": 3182.14, + "Y": 38.98 + }, + { + "X": 3182.14, + "Y": 39.37 + }, + { + "X": 3183.17, + "Y": 38.78 + }, + { + "X": 3868.57, + "Y": 36.99 + }, + { + "X": 3882.96, + "Y": 36.77 + }, + { + "X": 3882.96, + "Y": 37.04 + }, + { + "X": 4326.53, + "Y": 35.41 + }, + { + "X": 4334.76, + "Y": 35.31 + }, + { + "X": 4334.76, + "Y": 35.36 + }, + { + "X": 4842.61, + "Y": 33.35 + }, + { + "X": 4850.84, + "Y": 32.4 + }, + { + "X": 4850.84, + "Y": 32.65 + }, + { + "X": 5276.67, + "Y": 30.51 + }, + { + "X": 5293.13, + "Y": 30.95 + }, + { + "X": 5293.13, + "Y": 31.33 + }, + { + "X": 5815.64, + "Y": 27.92 + }, + { + "X": 5816.67, + "Y": 28.08 + }, + { + "X": 5816.67, + "Y": 27.48 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 5816.67, + "Min": 0.0, + "Index0": 0.076877229505334418, + "Index1": 0.043944431065823131, + "Index2": -7.4435446354502728E-06, + "Index3": 3.9170880067088718E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 1892.76, + "Y": 59.62 + }, + { + "X": 1892.76, + "Y": 58.65 + }, + { + "X": 1892.76, + "Y": 59.77 + }, + { + "X": 3182.14, + "Y": 77.1 + }, + { + "X": 3182.14, + "Y": 77.88 + }, + { + "X": 3183.17, + "Y": 76.74 + }, + { + "X": 3868.57, + "Y": 80.91 + }, + { + "X": 3882.96, + "Y": 80.72 + }, + { + "X": 3882.96, + "Y": 81.31 + }, + { + "X": 4326.53, + "Y": 82.79 + }, + { + "X": 4334.76, + "Y": 82.72 + }, + { + "X": 4334.76, + "Y": 82.82 + }, + { + "X": 4842.61, + "Y": 83.79 + }, + { + "X": 4850.84, + "Y": 81.55 + }, + { + "X": 4850.84, + "Y": 82.18 + }, + { + "X": 5276.67, + "Y": 81.67 + }, + { + "X": 5293.13, + "Y": 83.1 + }, + { + "X": 5293.13, + "Y": 84.1 + }, + { + "X": 5815.64, + "Y": 80.87 + }, + { + "X": 5816.67, + "Y": 81.33 + }, + { + "X": 5816.67, + "Y": 79.59 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 5816.67, + "Min": 0.0, + "Index0": 294.58504861790516, + "Index1": 0.0036035001330806285, + "Index2": 2.0613084078424308E-05, + "Index3": -2.3733025096798723E-09, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 295.08 + }, + { + "X": 1892.76, + "Y": 358.4 + }, + { + "X": 1892.76, + "Y": 358.4 + }, + { + "X": 1892.76, + "Y": 358.4 + }, + { + "X": 3182.14, + "Y": 438.4 + }, + { + "X": 3182.14, + "Y": 438.4 + }, + { + "X": 3183.17, + "Y": 438.3 + }, + { + "X": 3868.57, + "Y": 481.9 + }, + { + "X": 3882.96, + "Y": 482.0 + }, + { + "X": 3882.96, + "Y": 482.0 + }, + { + "X": 4326.53, + "Y": 504.3 + }, + { + "X": 4334.76, + "Y": 504.2 + }, + { + "X": 4334.76, + "Y": 504.3 + }, + { + "X": 4842.61, + "Y": 525.2 + }, + { + "X": 4850.84, + "Y": 525.2 + }, + { + "X": 4850.84, + "Y": 525.2 + }, + { + "X": 5276.67, + "Y": 537.2 + }, + { + "X": 5293.13, + "Y": 537.2 + }, + { + "X": 5293.13, + "Y": 537.3 + }, + { + "X": 5815.64, + "Y": 547.1 + }, + { + "X": 5816.67, + "Y": 547.3 + }, + { + "X": 5816.67, + "Y": 547.3 + } + ], + "IsNull": false + } + }, + { + "Belong": 1, + "ID": 15, + "Code": "32SAP-13J涓�", + "Name": "15#娉�", + "Qr": 5600.0, + "Hr": 30.0, + "Nr": 590.0, + "Pr": 545.0, + "Er": 0.0, + "Ic": 800.0, + "Oc": null, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": true, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 4939.31, + "Min": 0.0, + "Index0": 38.848784252610116, + "Index1": -0.0025615098198609352, + "Index2": 6.2472450436789063E-07, + "Index3": -1.4190951976148514E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 38.84 + }, + { + "X": 1960.1, + "Y": 35.07 + }, + { + "X": 1960.1, + "Y": 35.48 + }, + { + "X": 1964.04, + "Y": 34.99 + }, + { + "X": 2612.49, + "Y": 33.19 + }, + { + "X": 2612.49, + "Y": 34.11 + }, + { + "X": 2614.46, + "Y": 34.1 + }, + { + "X": 2614.46, + "Y": 34.14 + }, + { + "X": 3502.63, + "Y": 31.13 + }, + { + "X": 3504.6, + "Y": 31.27 + }, + { + "X": 3504.6, + "Y": 31.48 + }, + { + "X": 3753.92, + "Y": 30.57 + }, + { + "X": 3753.92, + "Y": 30.61 + }, + { + "X": 3755.89, + "Y": 30.85 + }, + { + "X": 4266.37, + "Y": 28.21 + }, + { + "X": 4266.37, + "Y": 28.28 + }, + { + "X": 4271.29, + "Y": 28.1 + }, + { + "X": 4569.49, + "Y": 26.66 + }, + { + "X": 4569.49, + "Y": 26.73 + }, + { + "X": 4589.22, + "Y": 26.72 + }, + { + "X": 4917.65, + "Y": 24.41 + }, + { + "X": 4939.31, + "Y": 24.17 + }, + { + "X": 4939.31, + "Y": 24.44 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 4939.31, + "Min": 0.0, + "Index0": 0.086291932524684534, + "Index1": 0.0432677546745248, + "Index2": -6.4734156516059435E-06, + "Index3": 2.1200867590826553E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 1960.1, + "Y": 61.78 + }, + { + "X": 1960.1, + "Y": 62.49 + }, + { + "X": 1964.04, + "Y": 61.76 + }, + { + "X": 2612.49, + "Y": 70.81 + }, + { + "X": 2612.49, + "Y": 72.78 + }, + { + "X": 2614.46, + "Y": 73.02 + }, + { + "X": 2614.46, + "Y": 72.9 + }, + { + "X": 3502.63, + "Y": 80.49 + }, + { + "X": 3504.6, + "Y": 80.92 + }, + { + "X": 3504.6, + "Y": 81.46 + }, + { + "X": 3753.92, + "Y": 82.84 + }, + { + "X": 3753.92, + "Y": 82.95 + }, + { + "X": 3755.89, + "Y": 83.64 + }, + { + "X": 4266.37, + "Y": 83.19 + }, + { + "X": 4266.37, + "Y": 83.4 + }, + { + "X": 4271.29, + "Y": 82.94 + }, + { + "X": 4569.49, + "Y": 82.76 + }, + { + "X": 4569.49, + "Y": 82.97 + }, + { + "X": 4589.22, + "Y": 83.29 + }, + { + "X": 4917.65, + "Y": 81.24 + }, + { + "X": 4939.31, + "Y": 80.98 + }, + { + "X": 4939.31, + "Y": 81.72 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 4939.31, + "Min": 0.0, + "Index0": 254.15277878498898, + "Index1": -0.0004649136909574369, + "Index2": 1.7717208868668702E-05, + "Index3": -2.3309879237100042E-09, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 254.19 + }, + { + "X": 1960.1, + "Y": 303.2 + }, + { + "X": 1960.1, + "Y": 303.3 + }, + { + "X": 1964.04, + "Y": 303.2 + }, + { + "X": 2612.49, + "Y": 333.7 + }, + { + "X": 2612.49, + "Y": 333.6 + }, + { + "X": 2614.46, + "Y": 332.7 + }, + { + "X": 2614.46, + "Y": 333.6 + }, + { + "X": 3502.63, + "Y": 369.1 + }, + { + "X": 3504.6, + "Y": 369.0 + }, + { + "X": 3504.6, + "Y": 369.1 + }, + { + "X": 3753.92, + "Y": 377.5 + }, + { + "X": 3753.92, + "Y": 377.5 + }, + { + "X": 3755.89, + "Y": 377.5 + }, + { + "X": 4266.37, + "Y": 394.2 + }, + { + "X": 4266.37, + "Y": 394.2 + }, + { + "X": 4271.29, + "Y": 394.3 + }, + { + "X": 4569.49, + "Y": 401.1 + }, + { + "X": 4569.49, + "Y": 401.2 + }, + { + "X": 4589.22, + "Y": 401.2 + }, + { + "X": 4917.65, + "Y": 402.6 + }, + { + "X": 4939.31, + "Y": 401.7 + }, + { + "X": 4939.31, + "Y": 402.5 + } + ], + "IsNull": false + } + }, + { + "Belong": 1, + "ID": 16, + "Code": "32SAP-13J", + "Name": "16#娉�", + "Qr": 4650.0, + "Hr": 36.0, + "Nr": 590.0, + "Pr": 524.0, + "Er": 0.0, + "Ic": 800.0, + "Oc": null, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": true, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 6126.43, + "Min": 0.0, + "Index0": 46.643017065491925, + "Index1": -0.0033648102116144948, + "Index2": 6.7451378693440883E-07, + "Index3": -1.1419740906652952E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 46.84 + }, + { + "X": 2019.67, + "Y": 41.58 + }, + { + "X": 2020.66, + "Y": 40.86 + }, + { + "X": 2020.66, + "Y": 41.29 + }, + { + "X": 2930.76, + "Y": 40.5 + }, + { + "X": 2930.76, + "Y": 39.72 + }, + { + "X": 2938.65, + "Y": 39.55 + }, + { + "X": 2974.18, + "Y": 39.78 + }, + { + "X": 3721.11, + "Y": 37.86 + }, + { + "X": 3725.07, + "Y": 37.61 + }, + { + "X": 3725.07, + "Y": 37.92 + }, + { + "X": 4197.73, + "Y": 36.22 + }, + { + "X": 4204.67, + "Y": 35.95 + }, + { + "X": 4204.67, + "Y": 36.35 + }, + { + "X": 4588.89, + "Y": 34.5 + }, + { + "X": 4588.89, + "Y": 34.0 + }, + { + "X": 4588.89, + "Y": 34.45 + }, + { + "X": 4880.06, + "Y": 32.88 + }, + { + "X": 4880.06, + "Y": 32.99 + }, + { + "X": 4880.06, + "Y": 32.62 + }, + { + "X": 5221.48, + "Y": 31.0 + }, + { + "X": 5223.45, + "Y": 31.08 + }, + { + "X": 5223.45, + "Y": 31.06 + }, + { + "X": 5223.45, + "Y": 31.21 + }, + { + "X": 5581.67, + "Y": 29.14 + }, + { + "X": 5581.67, + "Y": 28.6 + }, + { + "X": 5581.67, + "Y": 28.53 + }, + { + "X": 5927.69, + "Y": 26.92 + }, + { + "X": 5927.69, + "Y": 26.12 + }, + { + "X": 5927.69, + "Y": 26.18 + }, + { + "X": 6112.59, + "Y": 26.01 + }, + { + "X": 6112.59, + "Y": 25.47 + }, + { + "X": 6126.43, + "Y": 25.35 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 6126.43, + "Min": 0.0, + "Index0": -0.072349765136914573, + "Index1": 0.043495037103022952, + "Index2": -6.5579793396888464E-06, + "Index3": 2.5856330842955474E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 2019.67, + "Y": 63.47 + }, + { + "X": 2020.66, + "Y": 62.4 + }, + { + "X": 2020.66, + "Y": 63.06 + }, + { + "X": 2930.76, + "Y": 78.79 + }, + { + "X": 2930.76, + "Y": 77.26 + }, + { + "X": 2938.65, + "Y": 77.17 + }, + { + "X": 2974.18, + "Y": 78.52 + }, + { + "X": 3721.11, + "Y": 84.52 + }, + { + "X": 3725.07, + "Y": 83.68 + }, + { + "X": 3725.07, + "Y": 84.72 + }, + { + "X": 4197.73, + "Y": 85.85 + }, + { + "X": 4204.67, + "Y": 85.33 + }, + { + "X": 4204.67, + "Y": 86.28 + }, + { + "X": 4588.89, + "Y": 86.98 + }, + { + "X": 4588.89, + "Y": 85.72 + }, + { + "X": 4588.89, + "Y": 86.86 + }, + { + "X": 4880.06, + "Y": 86.18 + }, + { + "X": 4880.06, + "Y": 86.47 + }, + { + "X": 4880.06, + "Y": 85.47 + }, + { + "X": 5221.48, + "Y": 85.19 + }, + { + "X": 5223.45, + "Y": 85.45 + }, + { + "X": 5223.45, + "Y": 85.39 + }, + { + "X": 5223.45, + "Y": 85.78 + }, + { + "X": 5581.67, + "Y": 83.99 + }, + { + "X": 5581.67, + "Y": 82.41 + }, + { + "X": 5581.67, + "Y": 82.21 + }, + { + "X": 5927.69, + "Y": 82.17 + }, + { + "X": 5927.69, + "Y": 79.74 + }, + { + "X": 5927.69, + "Y": 79.92 + }, + { + "X": 6112.59, + "Y": 81.73 + }, + { + "X": 6112.59, + "Y": 79.75 + }, + { + "X": 6126.43, + "Y": 79.57 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 6126.43, + "Min": 0.0, + "Index0": 284.39237264268604, + "Index1": 0.013257703782572074, + "Index2": 1.5556674212899002E-05, + "Index3": -1.8210526925957242E-09, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 284.17 + }, + { + "X": 2019.67, + "Y": 360.5 + }, + { + "X": 2020.66, + "Y": 360.6 + }, + { + "X": 2020.66, + "Y": 360.5 + }, + { + "X": 2930.76, + "Y": 410.5 + }, + { + "X": 2930.76, + "Y": 410.6 + }, + { + "X": 2938.65, + "Y": 410.4 + }, + { + "X": 2974.18, + "Y": 410.6 + }, + { + "X": 3721.11, + "Y": 454.2 + }, + { + "X": 3725.07, + "Y": 456.2 + }, + { + "X": 3725.07, + "Y": 454.3 + }, + { + "X": 4197.73, + "Y": 482.6 + }, + { + "X": 4204.67, + "Y": 482.7 + }, + { + "X": 4204.67, + "Y": 482.7 + }, + { + "X": 4588.89, + "Y": 496.0 + }, + { + "X": 4588.89, + "Y": 496.0 + }, + { + "X": 4588.89, + "Y": 496.0 + }, + { + "X": 4880.06, + "Y": 507.4 + }, + { + "X": 4880.06, + "Y": 507.4 + }, + { + "X": 4880.06, + "Y": 507.5 + }, + { + "X": 5221.48, + "Y": 517.8 + }, + { + "X": 5223.45, + "Y": 517.7 + }, + { + "X": 5223.45, + "Y": 517.7 + }, + { + "X": 5223.45, + "Y": 517.9 + }, + { + "X": 5581.67, + "Y": 527.7 + }, + { + "X": 5581.67, + "Y": 527.9 + }, + { + "X": 5581.67, + "Y": 527.8 + }, + { + "X": 5927.69, + "Y": 529.2 + }, + { + "X": 5927.69, + "Y": 529.1 + }, + { + "X": 5927.69, + "Y": 529.1 + }, + { + "X": 6112.59, + "Y": 530.1 + }, + { + "X": 6112.59, + "Y": 532.0 + }, + { + "X": 6126.43, + "Y": 531.9 + } + ], + "IsNull": false + } + }, + { + "Belong": 1, + "ID": 17, + "Code": "32SAP-13J", + "Name": "17#娉�", + "Qr": 4650.0, + "Hr": 36.0, + "Nr": 590.0, + "Pr": 524.0, + "Er": 0.0, + "Ic": 800.0, + "Oc": null, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": true, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 5817.77, + "Min": 0.0, + "Index0": 46.29151958927342, + "Index1": -0.0029727497663906096, + "Index2": 6.2151407926690086E-07, + "Index3": -1.0825635512548906E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 46.37 + }, + { + "X": 2067.15, + "Y": 41.89 + }, + { + "X": 2067.15, + "Y": 41.74 + }, + { + "X": 2074.33, + "Y": 41.38 + }, + { + "X": 2938.21, + "Y": 40.01 + }, + { + "X": 2938.21, + "Y": 39.85 + }, + { + "X": 2951.54, + "Y": 40.7 + }, + { + "X": 3504.28, + "Y": 39.08 + }, + { + "X": 3505.31, + "Y": 38.93 + }, + { + "X": 3505.31, + "Y": 39.33 + }, + { + "X": 4159.69, + "Y": 37.43 + }, + { + "X": 4159.69, + "Y": 36.96 + }, + { + "X": 4165.85, + "Y": 36.71 + }, + { + "X": 4578.05, + "Y": 34.96 + }, + { + "X": 4593.45, + "Y": 35.07 + }, + { + "X": 4593.45, + "Y": 35.01 + }, + { + "X": 4957.07, + "Y": 33.58 + }, + { + "X": 4958.1, + "Y": 33.75 + }, + { + "X": 4983.77, + "Y": 33.5 + }, + { + "X": 4983.77, + "Y": 33.22 + }, + { + "X": 5390.35, + "Y": 31.07 + }, + { + "X": 5396.52, + "Y": 31.52 + }, + { + "X": 5406.79, + "Y": 31.12 + }, + { + "X": 5814.69, + "Y": 28.84 + }, + { + "X": 5814.69, + "Y": 29.27 + }, + { + "X": 5817.77, + "Y": 28.52 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 5817.77, + "Min": 0.0, + "Index0": -0.019575514729941554, + "Index1": 0.043519486344108446, + "Index2": -6.9917120349141812E-06, + "Index3": 3.357802929240145E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 2067.15, + "Y": 63.35 + }, + { + "X": 2067.15, + "Y": 63.14 + }, + { + "X": 2074.33, + "Y": 62.81 + }, + { + "X": 2938.21, + "Y": 75.26 + }, + { + "X": 2938.21, + "Y": 74.96 + }, + { + "X": 2951.54, + "Y": 76.92 + }, + { + "X": 3504.28, + "Y": 81.46 + }, + { + "X": 3505.31, + "Y": 81.17 + }, + { + "X": 3505.31, + "Y": 82.0 + }, + { + "X": 4159.69, + "Y": 85.3 + }, + { + "X": 4159.69, + "Y": 84.24 + }, + { + "X": 4165.85, + "Y": 83.78 + }, + { + "X": 4578.05, + "Y": 83.91 + }, + { + "X": 4593.45, + "Y": 84.44 + }, + { + "X": 4593.45, + "Y": 84.31 + }, + { + "X": 4957.07, + "Y": 84.96 + }, + { + "X": 4958.1, + "Y": 85.41 + }, + { + "X": 4983.77, + "Y": 85.22 + }, + { + "X": 4983.77, + "Y": 84.51 + }, + { + "X": 5390.35, + "Y": 83.37 + }, + { + "X": 5396.52, + "Y": 84.66 + }, + { + "X": 5406.79, + "Y": 83.76 + }, + { + "X": 5814.69, + "Y": 82.58 + }, + { + "X": 5814.69, + "Y": 83.78 + }, + { + "X": 5817.77, + "Y": 81.71 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 5817.77, + "Min": 0.0, + "Index0": 307.01931393816551, + "Index1": -0.0026458915765584646, + "Index2": 2.1404341772937974E-05, + "Index3": -2.3482381074940487E-09, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 306.93 + }, + { + "X": 2067.15, + "Y": 372.5 + }, + { + "X": 2067.15, + "Y": 372.4 + }, + { + "X": 2074.33, + "Y": 372.4 + }, + { + "X": 2938.21, + "Y": 425.7 + }, + { + "X": 2938.21, + "Y": 425.6 + }, + { + "X": 2951.54, + "Y": 425.6 + }, + { + "X": 3504.28, + "Y": 458.1 + }, + { + "X": 3505.31, + "Y": 458.1 + }, + { + "X": 3505.31, + "Y": 458.1 + }, + { + "X": 4159.69, + "Y": 497.4 + }, + { + "X": 4159.69, + "Y": 497.3 + }, + { + "X": 4165.85, + "Y": 497.4 + }, + { + "X": 4578.05, + "Y": 519.8 + }, + { + "X": 4593.45, + "Y": 519.9 + }, + { + "X": 4593.45, + "Y": 519.8 + }, + { + "X": 4957.07, + "Y": 533.9 + }, + { + "X": 4958.1, + "Y": 533.9 + }, + { + "X": 4983.77, + "Y": 533.9 + }, + { + "X": 4983.77, + "Y": 533.8 + }, + { + "X": 5390.35, + "Y": 547.4 + }, + { + "X": 5396.52, + "Y": 547.5 + }, + { + "X": 5406.79, + "Y": 547.4 + }, + { + "X": 5814.69, + "Y": 553.4 + }, + { + "X": 5814.69, + "Y": 553.6 + }, + { + "X": 5817.77, + "Y": 553.3 + } + ], + "IsNull": false + } + }, + { + "Belong": 1, + "ID": 18, + "Code": "32SAP-13J", + "Name": "18#娉�", + "Qr": 4650.0, + "Hr": 36.0, + "Nr": 590.0, + "Pr": 524.0, + "Er": 0.0, + "Ic": 800.0, + "Oc": null, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": true, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 6292.58, + "Min": 0.0, + "Index0": 46.328403375451344, + "Index1": -0.0033444534937744526, + "Index2": 8.1459331951754646E-07, + "Index3": -1.20900570189885E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 46.36 + }, + { + "X": 2241.14, + "Y": 41.76 + }, + { + "X": 2241.14, + "Y": 41.07 + }, + { + "X": 2241.14, + "Y": 41.57 + }, + { + "X": 3377.86, + "Y": 38.53 + }, + { + "X": 3397.31, + "Y": 39.93 + }, + { + "X": 3397.31, + "Y": 39.97 + }, + { + "X": 3397.31, + "Y": 40.7 + }, + { + "X": 4353.25, + "Y": 36.86 + }, + { + "X": 4357.35, + "Y": 36.87 + }, + { + "X": 4365.55, + "Y": 37.75 + }, + { + "X": 4890.71, + "Y": 34.88 + }, + { + "X": 4892.76, + "Y": 35.08 + }, + { + "X": 4892.76, + "Y": 35.69 + }, + { + "X": 5403.72, + "Y": 32.42 + }, + { + "X": 5404.74, + "Y": 32.93 + }, + { + "X": 5404.74, + "Y": 33.37 + }, + { + "X": 5820.02, + "Y": 30.55 + }, + { + "X": 5825.15, + "Y": 30.5 + }, + { + "X": 5825.15, + "Y": 31.14 + }, + { + "X": 6282.33, + "Y": 26.97 + }, + { + "X": 6283.36, + "Y": 27.0 + }, + { + "X": 6286.43, + "Y": 27.76 + }, + { + "X": 6292.58, + "Y": 28.01 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 6292.58, + "Min": 0.0, + "Index0": 0.089636194191952179, + "Index1": 0.039879182718094985, + "Index2": -5.6897054116349428E-06, + "Index3": 2.0831895214907315E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 2241.14, + "Y": 63.79 + }, + { + "X": 2241.14, + "Y": 62.75 + }, + { + "X": 2241.14, + "Y": 63.52 + }, + { + "X": 3377.86, + "Y": 75.38 + }, + { + "X": 3397.31, + "Y": 78.58 + }, + { + "X": 3397.31, + "Y": 78.66 + }, + { + "X": 3397.31, + "Y": 80.1 + }, + { + "X": 4353.25, + "Y": 81.58 + }, + { + "X": 4357.35, + "Y": 81.69 + }, + { + "X": 4365.55, + "Y": 83.79 + }, + { + "X": 4890.71, + "Y": 82.52 + }, + { + "X": 4892.76, + "Y": 83.01 + }, + { + "X": 4892.76, + "Y": 84.45 + }, + { + "X": 5403.72, + "Y": 81.48 + }, + { + "X": 5404.74, + "Y": 82.76 + }, + { + "X": 5404.74, + "Y": 83.86 + }, + { + "X": 5820.02, + "Y": 80.63 + }, + { + "X": 5825.15, + "Y": 80.54 + }, + { + "X": 5825.15, + "Y": 82.23 + }, + { + "X": 6282.33, + "Y": 75.95 + }, + { + "X": 6283.36, + "Y": 76.05 + }, + { + "X": 6286.43, + "Y": 78.23 + }, + { + "X": 6292.58, + "Y": 79.0 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 6292.58, + "Min": 0.0, + "Index0": 318.59499238640313, + "Index1": 0.000650255309462579, + "Index2": 2.0174788177917332E-05, + "Index3": -2.0588702860738164E-09, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 318.08 + }, + { + "X": 2241.14, + "Y": 399.8 + }, + { + "X": 2241.14, + "Y": 399.7 + }, + { + "X": 2241.14, + "Y": 399.7 + }, + { + "X": 3377.86, + "Y": 470.5 + }, + { + "X": 3397.31, + "Y": 470.4 + }, + { + "X": 3397.31, + "Y": 470.4 + }, + { + "X": 3397.31, + "Y": 470.4 + }, + { + "X": 4353.25, + "Y": 536.0 + }, + { + "X": 4357.35, + "Y": 535.9 + }, + { + "X": 4365.55, + "Y": 536.0 + }, + { + "X": 4890.71, + "Y": 563.3 + }, + { + "X": 4892.76, + "Y": 563.4 + }, + { + "X": 4892.76, + "Y": 563.5 + }, + { + "X": 5403.72, + "Y": 585.9 + }, + { + "X": 5404.74, + "Y": 586.0 + }, + { + "X": 5404.74, + "Y": 586.1 + }, + { + "X": 5820.02, + "Y": 600.9 + }, + { + "X": 5825.15, + "Y": 601.1 + }, + { + "X": 5825.15, + "Y": 601.1 + }, + { + "X": 6282.33, + "Y": 607.9 + }, + { + "X": 6283.36, + "Y": 607.9 + }, + { + "X": 6286.43, + "Y": 607.9 + }, + { + "X": 6292.58, + "Y": 608.0 + } + ], + "IsNull": false + } + } +] \ No newline at end of file diff --git "a/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\272\214\350\276\223.json" "b/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\272\214\350\276\223.json" new file mode 100644 index 0000000..ddd6974 --- /dev/null +++ "b/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\272\214\350\276\223.json" @@ -0,0 +1,1466 @@ +[ + { + "Belong": 2, + "ID": 21, + "Code": "48LKXA-31", + "Name": "21#娉�", + "Qr": 12960.0, + "Hr": 31.0, + "Nr": 740.0, + "Pr": 1256.9, + "Er": 0.0, + "Ic": null, + "Oc": 900.0, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": false, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 14600.0, + "Min": 0.0, + "Index0": 62.0736047732983, + "Index1": -0.0073515291663797874, + "Index2": 8.35259554487076E-07, + "Index3": -3.4867138623173711E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 60.3 + }, + { + "X": 900.0, + "Y": 56.5 + }, + { + "X": 1800.0, + "Y": 52.7 + }, + { + "X": 2700.0, + "Y": 49.2 + }, + { + "X": 3600.0, + "Y": 45.8 + }, + { + "X": 4500.0, + "Y": 42.8 + }, + { + "X": 5400.0, + "Y": 40.1 + }, + { + "X": 6300.0, + "Y": 38.8 + }, + { + "X": 7200.0, + "Y": 38.0 + }, + { + "X": 8100.0, + "Y": 38.0 + }, + { + "X": 8460.0, + "Y": 38.0 + }, + { + "X": 9000.0, + "Y": 38.0 + }, + { + "X": 9900.0, + "Y": 38.1 + }, + { + "X": 10050.0, + "Y": 37.9 + }, + { + "X": 10800.0, + "Y": 37.2 + }, + { + "X": 11040.0, + "Y": 36.5 + }, + { + "X": 11520.0, + "Y": 35.4 + }, + { + "X": 11700.0, + "Y": 34.9 + }, + { + "X": 12600.0, + "Y": 32.1 + }, + { + "X": 12960.0, + "Y": 31.0 + }, + { + "X": 13500.0, + "Y": 29.2 + }, + { + "X": 13600.0, + "Y": 28.7 + }, + { + "X": 14400.0, + "Y": 25.0 + }, + { + "X": 14600.0, + "Y": 24.0 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 14400.0, + "Min": 0.0, + "Index0": 0.00847841570321677, + "Index1": 0.0031747076329174894, + "Index2": 1.2110982037729073E-06, + "Index3": -7.2525294020937019E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 8460.0, + "Y": 70.0 + }, + { + "X": 10050.0, + "Y": 80.0 + }, + { + "X": 11040.0, + "Y": 85.0 + }, + { + "X": 12600.0, + "Y": 87.6 + }, + { + "X": 13600.0, + "Y": 85.0 + }, + { + "X": 14400.0, + "Y": 80.0 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 14400.0, + "Min": 0.0, + "Index0": 499.84897949941569, + "Index1": 0.16123647965319343, + "Index2": -9.5358294624881279E-06, + "Index3": 1.2701637858833966E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 500.0 + }, + { + "X": 8460.0, + "Y": 1251.5 + }, + { + "X": 10050.0, + "Y": 1297.4 + }, + { + "X": 11040.0, + "Y": 1291.8 + }, + { + "X": 12600.0, + "Y": 1258.2 + }, + { + "X": 13600.0, + "Y": 1251.3 + }, + { + "X": 14400.0, + "Y": 1226.2 + } + ], + "IsNull": false + } + }, + { + "Belong": 2, + "ID": 22, + "Code": "66LKXA-48G", + "Name": "22#娉�", + "Qr": 14400.0, + "Hr": 32.5, + "Nr": 495.0, + "Pr": 1460.9, + "Er": 0.0, + "Ic": null, + "Oc": 1200.0, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": false, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 20160.0, + "Min": 0.0, + "Index0": 46.647547911829669, + "Index1": -0.0024071202620254638, + "Index2": 2.1158713432565427E-07, + "Index3": -7.9518867170862452E-12, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 46.0 + }, + { + "X": 1440.0, + "Y": 44.1 + }, + { + "X": 2880.0, + "Y": 42.1 + }, + { + "X": 4320.0, + "Y": 40.2 + }, + { + "X": 5760.0, + "Y": 38.5 + }, + { + "X": 7200.0, + "Y": 36.2 + }, + { + "X": 7488.0, + "Y": 36.0 + }, + { + "X": 8064.0, + "Y": 35.8 + }, + { + "X": 8640.0, + "Y": 35.8 + }, + { + "X": 10080.0, + "Y": 36.0 + }, + { + "X": 10656.0, + "Y": 36.0 + }, + { + "X": 11520.0, + "Y": 35.9 + }, + { + "X": 12384.0, + "Y": 35.2 + }, + { + "X": 12960.0, + "Y": 34.5 + }, + { + "X": 14400.0, + "Y": 32.5 + }, + { + "X": 15840.0, + "Y": 29.5 + }, + { + "X": 17280.0, + "Y": 26.3 + }, + { + "X": 17510.0, + "Y": 25.8 + }, + { + "X": 18720.0, + "Y": 23.1 + }, + { + "X": 19728.0, + "Y": 20.7 + }, + { + "X": 20160.0, + "Y": 19.8 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 19728.0, + "Min": 0.0, + "Index0": -0.068274552364318619, + "Index1": 0.010768209957501641, + "Index2": -2.2462507403024741E-07, + "Index3": -7.2208497578239813E-12, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 8640.0, + "Y": 70.0 + }, + { + "X": 10080.0, + "Y": 80.0 + }, + { + "X": 12384.0, + "Y": 85.0 + }, + { + "X": 14400.0, + "Y": 87.5 + }, + { + "X": 15840.0, + "Y": 85.0 + }, + { + "X": 17510.0, + "Y": 80.0 + }, + { + "X": 19728.0, + "Y": 70.0 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 19728.0, + "Min": 0.0, + "Index0": 500.13824346140365, + "Index1": 0.10182647090541627, + "Index2": -2.7257090131748466E-06, + "Index3": 1.8087315824196045E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 500.0 + }, + { + "X": 8640.0, + "Y": 1204.1 + }, + { + "X": 10080.0, + "Y": 1236.1 + }, + { + "X": 12384.0, + "Y": 1397.5 + }, + { + "X": 14400.0, + "Y": 1457.5 + }, + { + "X": 15840.0, + "Y": 1498.0 + }, + { + "X": 17510.0, + "Y": 1538.8 + }, + { + "X": 19728.0, + "Y": 1589.7 + } + ], + "IsNull": false + } + }, + { + "Belong": 2, + "ID": 23, + "Code": "66LKXA-48G", + "Name": "23#娉�", + "Qr": 14400.0, + "Hr": 32.5, + "Nr": 495.0, + "Pr": 1460.9, + "Er": 0.0, + "Ic": null, + "Oc": 1200.0, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": false, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 20160.0, + "Min": 0.0, + "Index0": 46.647547911829669, + "Index1": -0.0024071202620254638, + "Index2": 2.1158713432565427E-07, + "Index3": -7.9518867170862452E-12, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 46.0 + }, + { + "X": 1440.0, + "Y": 44.1 + }, + { + "X": 2880.0, + "Y": 42.1 + }, + { + "X": 4320.0, + "Y": 40.2 + }, + { + "X": 5760.0, + "Y": 38.5 + }, + { + "X": 7200.0, + "Y": 36.2 + }, + { + "X": 7488.0, + "Y": 36.0 + }, + { + "X": 8064.0, + "Y": 35.8 + }, + { + "X": 8640.0, + "Y": 35.8 + }, + { + "X": 10080.0, + "Y": 36.0 + }, + { + "X": 10656.0, + "Y": 36.0 + }, + { + "X": 11520.0, + "Y": 35.9 + }, + { + "X": 12384.0, + "Y": 35.2 + }, + { + "X": 12960.0, + "Y": 34.5 + }, + { + "X": 14400.0, + "Y": 32.5 + }, + { + "X": 15840.0, + "Y": 29.5 + }, + { + "X": 17280.0, + "Y": 26.3 + }, + { + "X": 17510.0, + "Y": 25.8 + }, + { + "X": 18720.0, + "Y": 23.1 + }, + { + "X": 19728.0, + "Y": 20.7 + }, + { + "X": 20160.0, + "Y": 19.8 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 19728.0, + "Min": 0.0, + "Index0": -0.068274552364318619, + "Index1": 0.010768209957501641, + "Index2": -2.2462507403024741E-07, + "Index3": -7.2208497578239813E-12, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 8640.0, + "Y": 70.0 + }, + { + "X": 10080.0, + "Y": 80.0 + }, + { + "X": 12384.0, + "Y": 85.0 + }, + { + "X": 14400.0, + "Y": 87.5 + }, + { + "X": 15840.0, + "Y": 85.0 + }, + { + "X": 17510.0, + "Y": 80.0 + }, + { + "X": 19728.0, + "Y": 70.0 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 19728.0, + "Min": 0.0, + "Index0": 500.13824346140365, + "Index1": 0.10182647090541627, + "Index2": -2.7257090131748466E-06, + "Index3": 1.8087315824196045E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 500.0 + }, + { + "X": 8640.0, + "Y": 1204.1 + }, + { + "X": 10080.0, + "Y": 1236.1 + }, + { + "X": 12384.0, + "Y": 1397.5 + }, + { + "X": 14400.0, + "Y": 1457.5 + }, + { + "X": 15840.0, + "Y": 1498.0 + }, + { + "X": 17510.0, + "Y": 1538.8 + }, + { + "X": 19728.0, + "Y": 1589.7 + } + ], + "IsNull": false + } + }, + { + "Belong": 2, + "ID": 24, + "Code": "66LKXA-48G", + "Name": "24#娉�", + "Qr": 14400.0, + "Hr": 32.5, + "Nr": 495.0, + "Pr": 1460.9, + "Er": 0.0, + "Ic": null, + "Oc": 1200.0, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": false, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 20160.0, + "Min": 0.0, + "Index0": 46.647547911829669, + "Index1": -0.0024071202620254638, + "Index2": 2.1158713432565427E-07, + "Index3": -7.9518867170862452E-12, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 46.0 + }, + { + "X": 1440.0, + "Y": 44.1 + }, + { + "X": 2880.0, + "Y": 42.1 + }, + { + "X": 4320.0, + "Y": 40.2 + }, + { + "X": 5760.0, + "Y": 38.5 + }, + { + "X": 7200.0, + "Y": 36.2 + }, + { + "X": 7488.0, + "Y": 36.0 + }, + { + "X": 8064.0, + "Y": 35.8 + }, + { + "X": 8640.0, + "Y": 35.8 + }, + { + "X": 10080.0, + "Y": 36.0 + }, + { + "X": 10656.0, + "Y": 36.0 + }, + { + "X": 11520.0, + "Y": 35.9 + }, + { + "X": 12384.0, + "Y": 35.2 + }, + { + "X": 12960.0, + "Y": 34.5 + }, + { + "X": 14400.0, + "Y": 32.5 + }, + { + "X": 15840.0, + "Y": 29.5 + }, + { + "X": 17280.0, + "Y": 26.3 + }, + { + "X": 17510.0, + "Y": 25.8 + }, + { + "X": 18720.0, + "Y": 23.1 + }, + { + "X": 19728.0, + "Y": 20.7 + }, + { + "X": 20160.0, + "Y": 19.8 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 19728.0, + "Min": 0.0, + "Index0": -0.068274552364318619, + "Index1": 0.010768209957501641, + "Index2": -2.2462507403024741E-07, + "Index3": -7.2208497578239813E-12, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 8640.0, + "Y": 70.0 + }, + { + "X": 10080.0, + "Y": 80.0 + }, + { + "X": 12384.0, + "Y": 85.0 + }, + { + "X": 14400.0, + "Y": 87.5 + }, + { + "X": 15840.0, + "Y": 85.0 + }, + { + "X": 17510.0, + "Y": 80.0 + }, + { + "X": 19728.0, + "Y": 70.0 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 19728.0, + "Min": 0.0, + "Index0": 500.13824346140365, + "Index1": 0.10182647090541627, + "Index2": -2.7257090131748466E-06, + "Index3": 1.8087315824196045E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 500.0 + }, + { + "X": 8640.0, + "Y": 1204.1 + }, + { + "X": 10080.0, + "Y": 1236.1 + }, + { + "X": 12384.0, + "Y": 1397.5 + }, + { + "X": 14400.0, + "Y": 1457.5 + }, + { + "X": 15840.0, + "Y": 1498.0 + }, + { + "X": 17510.0, + "Y": 1538.8 + }, + { + "X": 19728.0, + "Y": 1589.7 + } + ], + "IsNull": false + } + }, + { + "Belong": 2, + "ID": 25, + "Code": "66LKXA-48G", + "Name": "25#娉�", + "Qr": 14400.0, + "Hr": 32.5, + "Nr": 495.0, + "Pr": 1460.9, + "Er": 0.0, + "Ic": null, + "Oc": 1200.0, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": false, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 20160.0, + "Min": 0.0, + "Index0": 46.647547911829669, + "Index1": -0.0024071202620254638, + "Index2": 2.1158713432565427E-07, + "Index3": -7.9518867170862452E-12, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 46.0 + }, + { + "X": 1440.0, + "Y": 44.1 + }, + { + "X": 2880.0, + "Y": 42.1 + }, + { + "X": 4320.0, + "Y": 40.2 + }, + { + "X": 5760.0, + "Y": 38.5 + }, + { + "X": 7200.0, + "Y": 36.2 + }, + { + "X": 7488.0, + "Y": 36.0 + }, + { + "X": 8064.0, + "Y": 35.8 + }, + { + "X": 8640.0, + "Y": 35.8 + }, + { + "X": 10080.0, + "Y": 36.0 + }, + { + "X": 10656.0, + "Y": 36.0 + }, + { + "X": 11520.0, + "Y": 35.9 + }, + { + "X": 12384.0, + "Y": 35.2 + }, + { + "X": 12960.0, + "Y": 34.5 + }, + { + "X": 14400.0, + "Y": 32.5 + }, + { + "X": 15840.0, + "Y": 29.5 + }, + { + "X": 17280.0, + "Y": 26.3 + }, + { + "X": 17510.0, + "Y": 25.8 + }, + { + "X": 18720.0, + "Y": 23.1 + }, + { + "X": 19728.0, + "Y": 20.7 + }, + { + "X": 20160.0, + "Y": 19.8 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 19728.0, + "Min": 0.0, + "Index0": -0.068274552364318619, + "Index1": 0.010768209957501641, + "Index2": -2.2462507403024741E-07, + "Index3": -7.2208497578239813E-12, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 8640.0, + "Y": 70.0 + }, + { + "X": 10080.0, + "Y": 80.0 + }, + { + "X": 12384.0, + "Y": 85.0 + }, + { + "X": 14400.0, + "Y": 87.5 + }, + { + "X": 15840.0, + "Y": 85.0 + }, + { + "X": 17510.0, + "Y": 80.0 + }, + { + "X": 19728.0, + "Y": 70.0 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 19728.0, + "Min": 0.0, + "Index0": 500.13824346140365, + "Index1": 0.10182647090541627, + "Index2": -2.7257090131748466E-06, + "Index3": 1.8087315824196045E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 500.0 + }, + { + "X": 8640.0, + "Y": 1204.1 + }, + { + "X": 10080.0, + "Y": 1236.1 + }, + { + "X": 12384.0, + "Y": 1397.5 + }, + { + "X": 14400.0, + "Y": 1457.5 + }, + { + "X": 15840.0, + "Y": 1498.0 + }, + { + "X": 17510.0, + "Y": 1538.8 + }, + { + "X": 19728.0, + "Y": 1589.7 + } + ], + "IsNull": false + } + }, + { + "Belong": 2, + "ID": 26, + "Code": "66LKXA-48G", + "Name": "26#娉�", + "Qr": 14400.0, + "Hr": 32.5, + "Nr": 495.0, + "Pr": 1460.9, + "Er": 0.0, + "Ic": null, + "Oc": 1200.0, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": false, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 20160.0, + "Min": 0.0, + "Index0": 46.647547911829669, + "Index1": -0.0024071202620254638, + "Index2": 2.1158713432565427E-07, + "Index3": -7.9518867170862452E-12, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 46.0 + }, + { + "X": 1440.0, + "Y": 44.1 + }, + { + "X": 2880.0, + "Y": 42.1 + }, + { + "X": 4320.0, + "Y": 40.2 + }, + { + "X": 5760.0, + "Y": 38.5 + }, + { + "X": 7200.0, + "Y": 36.2 + }, + { + "X": 7488.0, + "Y": 36.0 + }, + { + "X": 8064.0, + "Y": 35.8 + }, + { + "X": 8640.0, + "Y": 35.8 + }, + { + "X": 10080.0, + "Y": 36.0 + }, + { + "X": 10656.0, + "Y": 36.0 + }, + { + "X": 11520.0, + "Y": 35.9 + }, + { + "X": 12384.0, + "Y": 35.2 + }, + { + "X": 12960.0, + "Y": 34.5 + }, + { + "X": 14400.0, + "Y": 32.5 + }, + { + "X": 15840.0, + "Y": 29.5 + }, + { + "X": 17280.0, + "Y": 26.3 + }, + { + "X": 17510.0, + "Y": 25.8 + }, + { + "X": 18720.0, + "Y": 23.1 + }, + { + "X": 19728.0, + "Y": 20.7 + }, + { + "X": 20160.0, + "Y": 19.8 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 19728.0, + "Min": 0.0, + "Index0": -0.068274552364318619, + "Index1": 0.010768209957501641, + "Index2": -2.2462507403024741E-07, + "Index3": -7.2208497578239813E-12, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 8640.0, + "Y": 70.0 + }, + { + "X": 10080.0, + "Y": 80.0 + }, + { + "X": 12384.0, + "Y": 85.0 + }, + { + "X": 14400.0, + "Y": 87.5 + }, + { + "X": 15840.0, + "Y": 85.0 + }, + { + "X": 17510.0, + "Y": 80.0 + }, + { + "X": 19728.0, + "Y": 70.0 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 19728.0, + "Min": 0.0, + "Index0": 500.13824346140365, + "Index1": 0.10182647090541627, + "Index2": -2.7257090131748466E-06, + "Index3": 1.8087315824196045E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 500.0 + }, + { + "X": 8640.0, + "Y": 1204.1 + }, + { + "X": 10080.0, + "Y": 1236.1 + }, + { + "X": 12384.0, + "Y": 1397.5 + }, + { + "X": 14400.0, + "Y": 1457.5 + }, + { + "X": 15840.0, + "Y": 1498.0 + }, + { + "X": 17510.0, + "Y": 1538.8 + }, + { + "X": 19728.0, + "Y": 1589.7 + } + ], + "IsNull": false + } + }, + { + "Belong": 2, + "ID": 27, + "Code": "48LKXA-31", + "Name": "27#娉�", + "Qr": 12960.0, + "Hr": 31.0, + "Nr": 740.0, + "Pr": 1256.9, + "Er": 0.0, + "Ic": null, + "Oc": 900.0, + "IOd": null, + "Ie": null, + "Oe": null, + "IsBp": true, + "IsSxp": false, + "CurveQH": { + "FitPow": 3, + "FitType": 0, + "Max": 14600.0, + "Min": 0.0, + "Index0": 62.0736047732983, + "Index1": -0.0073515291663797874, + "Index2": 8.35259554487076E-07, + "Index3": -3.4867138623173711E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 60.3 + }, + { + "X": 900.0, + "Y": 56.5 + }, + { + "X": 1800.0, + "Y": 52.7 + }, + { + "X": 2700.0, + "Y": 49.2 + }, + { + "X": 3600.0, + "Y": 45.8 + }, + { + "X": 4500.0, + "Y": 42.8 + }, + { + "X": 5400.0, + "Y": 40.1 + }, + { + "X": 6300.0, + "Y": 38.8 + }, + { + "X": 7200.0, + "Y": 38.0 + }, + { + "X": 8100.0, + "Y": 38.0 + }, + { + "X": 8460.0, + "Y": 38.0 + }, + { + "X": 9000.0, + "Y": 38.0 + }, + { + "X": 9900.0, + "Y": 38.1 + }, + { + "X": 10050.0, + "Y": 37.9 + }, + { + "X": 10800.0, + "Y": 37.2 + }, + { + "X": 11040.0, + "Y": 36.5 + }, + { + "X": 11520.0, + "Y": 35.4 + }, + { + "X": 11700.0, + "Y": 34.9 + }, + { + "X": 12600.0, + "Y": 32.1 + }, + { + "X": 12960.0, + "Y": 31.0 + }, + { + "X": 13500.0, + "Y": 29.2 + }, + { + "X": 13600.0, + "Y": 28.7 + }, + { + "X": 14400.0, + "Y": 25.0 + }, + { + "X": 14600.0, + "Y": 24.0 + } + ], + "IsNull": false + }, + "CurveQE": { + "FitPow": 3, + "FitType": 0, + "Max": 14400.0, + "Min": 0.0, + "Index0": 0.00847841570321677, + "Index1": 0.0031747076329174894, + "Index2": 1.2110982037729073E-06, + "Index3": -7.2525294020937019E-11, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 0.0 + }, + { + "X": 8460.0, + "Y": 70.0 + }, + { + "X": 10050.0, + "Y": 80.0 + }, + { + "X": 11040.0, + "Y": 85.0 + }, + { + "X": 12600.0, + "Y": 87.6 + }, + { + "X": 13600.0, + "Y": 85.0 + }, + { + "X": 14400.0, + "Y": 80.0 + } + ], + "IsNull": false + }, + "CurveQP": { + "FitPow": 3, + "FitType": 0, + "Max": 14400.0, + "Min": 0.0, + "Index0": 499.84897949941569, + "Index1": 0.16123647965319343, + "Index2": -9.5358294624881279E-06, + "Index3": 1.2701637858833966E-10, + "Index4": 0.0, + "DefinePoints": [ + { + "X": 0.0, + "Y": 500.0 + }, + { + "X": 8460.0, + "Y": 1251.5 + }, + { + "X": 10050.0, + "Y": 1297.4 + }, + { + "X": 11040.0, + "Y": 1291.8 + }, + { + "X": 12600.0, + "Y": 1258.2 + }, + { + "X": 13600.0, + "Y": 1251.3 + }, + { + "X": 14400.0, + "Y": 1226.2 + } + ], + "IsNull": false + } + } +] \ No newline at end of file diff --git a/Schedule/IStation.Algorithm/Entity/BaseEntity.cs b/Schedule/IStation.Algorithm/Entity/BaseEntity.cs new file mode 100644 index 0000000..c8daeee --- /dev/null +++ b/Schedule/IStation.Algorithm/Entity/BaseEntity.cs @@ -0,0 +1,27 @@ +锘縩amespace IStation.Entity +{ + /// <summary> + /// 鍩虹瀹炰綋 + /// </summary> + public class BaseEntity + { + /// <summary> + /// + /// </summary> + public BaseEntity() { } + + /// <summary> + /// + /// </summary> + public BaseEntity(BaseEntity rhs) + { + this.ID = rhs.ID; + } + + /// <summary> + /// 鑷鏍囪瘑 + /// </summary> + [SugarColumn(IsIdentity = true, IsPrimaryKey = true)] + public long ID { get; set; } + } +} diff --git a/Schedule/IStation.Algorithm/Entity/ScheduleAnaLog.cs b/Schedule/IStation.Algorithm/Entity/ScheduleAnaLog.cs new file mode 100644 index 0000000..290f28e --- /dev/null +++ b/Schedule/IStation.Algorithm/Entity/ScheduleAnaLog.cs @@ -0,0 +1,34 @@ +锘縩amespace IStation.Entity +{ + /// <summary> + /// 璋冨害鍒嗘瀽鏃ュ織 + /// </summary> + [SugarTable("ScheduleAnaLog")] + public class ScheduleAnaLog + { + public ScheduleAnaLog() { } + + public ScheduleAnaLog(string info) + { + this.Info = info; + this.CreateTime = DateTime.Now; + } + + /// <summary> + /// 鑷鏍囪瘑 + /// </summary> + [SugarColumn(IsIdentity = true, IsPrimaryKey = true)] + public int ID { get; set; } + + /// <summary> + /// 淇℃伅 + /// </summary> + public string Info { get; set; } + + /// <summary> + /// 鐢熸垚鏃堕棿 + /// </summary> + public DateTime CreateTime { get; set; } + + } +} diff --git a/Schedule/IStation.Algorithm/Entity/ScheduleCombine.cs b/Schedule/IStation.Algorithm/Entity/ScheduleCombine.cs new file mode 100644 index 0000000..e7aed35 --- /dev/null +++ b/Schedule/IStation.Algorithm/Entity/ScheduleCombine.cs @@ -0,0 +1,59 @@ +锘縩amespace IStation.Entity +{ + /// <summary> + /// 璋冨害缁勫悎 + /// </summary> + [SugarTable("ScheduleCombine")] + public class ScheduleCombine + { + public ScheduleCombine() { } + public ScheduleCombine(ScheduleCombine rhs) + { + this.RunFlag = rhs.RunFlag; + this.RunCount = rhs.RunCount; + this.RunHZ = rhs.RunHZ; + this.CurveQH = rhs.CurveQH; + this.CurveQP = rhs.CurveQP; + this.AnaStatus = rhs.AnaStatus; + } + + /// <summary> + /// 鑷鏍囪瘑 + /// </summary> + [SugarColumn(IsIdentity = true, IsPrimaryKey = true)] + public int ID { get; set; } + + /// <summary> + /// 杩愯鏍囧織 + /// </summary> + public string RunFlag { get; set; } + + /// <summary> + /// 杩愯鏁伴噺 + /// </summary> + public int RunCount { get; set; } + + /// <summary> + /// 杩愯棰戠巼鍒楄〃 + /// </summary> + public string RunHZ { get; set; } + + /// <summary> + /// 娴侀噺鎵▼绾� + /// </summary> + public string CurveQH { get; set; } + + /// <summary> + /// 娴侀噺鍔熺巼绾� + /// </summary> + public string CurveQP { get; set; } + + /// <summary> + /// 鍒嗘瀽鐘舵�� + /// </summary> + public bool AnaStatus { get; set; } + + } + + +} diff --git a/Schedule/IStation.Algorithm/Entity/ScheduleCombineLog.cs b/Schedule/IStation.Algorithm/Entity/ScheduleCombineLog.cs new file mode 100644 index 0000000..6e95ac3 --- /dev/null +++ b/Schedule/IStation.Algorithm/Entity/ScheduleCombineLog.cs @@ -0,0 +1,53 @@ +锘縩amespace IStation.Entity +{ + /// <summary> + /// 璋冨害缁勫悎鏃ュ織 + /// </summary> + [SugarTable("ScheduleCombineLog")] + public class ScheduleCombineLog + { + public ScheduleCombineLog() { } + + public ScheduleCombineLog(long scheduleCombineID, string flag, int count, DateTime start, DateTime end) + { + this.ScheduleCombineID = scheduleCombineID; + this.RunFlag = flag; + this.RunCount = count; + this.TotalSeconds = (end - start).TotalSeconds; + this.CreateTime = DateTime.Now; + } + + /// <summary> + /// 鑷鏍囪瘑 + /// </summary> + [SugarColumn(IsIdentity = true, IsPrimaryKey = true)] + public int ID { get; set; } + + /// <summary> + /// 璋冨害缁勫悎鏍囪瘑 + /// </summary> + public long ScheduleCombineID { get; set; } + + /// <summary> + /// 杩愯鏍囧織 + /// </summary> + public string RunFlag { get; set; } + + /// <summary> + /// 杩愯鏁伴噺 + /// </summary> + public int RunCount { get; set; } + + /// <summary> + /// 鍒嗘瀽鐢ㄦ椂(绉�) + /// </summary> + public double TotalSeconds { get; set; } + + /// <summary> + /// 鐢熸垚鏃堕棿 + /// </summary> + public DateTime CreateTime { get; set; } + + + } +} diff --git a/Schedule/IStation.Algorithm/GlobalUsing.cs b/Schedule/IStation.Algorithm/GlobalUsing.cs new file mode 100644 index 0000000..2ab14db --- /dev/null +++ b/Schedule/IStation.Algorithm/GlobalUsing.cs @@ -0,0 +1,10 @@ +锘縢lobal using IStation.Curve; +global using IStation.Model; +global using MathNet.Numerics; +global using Newtonsoft.Json; +global using SqlSugar; +global using System.ComponentModel; +global using System.Reflection; +global using System.Text; +global using Yitter.IdGenerator; + diff --git a/Schedule/IStation.Algorithm/Helper/JsonHelper.cs b/Schedule/IStation.Algorithm/Helper/JsonHelper.cs new file mode 100644 index 0000000..67fb736 --- /dev/null +++ b/Schedule/IStation.Algorithm/Helper/JsonHelper.cs @@ -0,0 +1,49 @@ +锘縩amespace IStation +{ + /// <summary> + /// json杈呭姪绫� + /// </summary> + public class JsonHelper + { + /// <summary> + /// 瀵硅薄杞负 json + /// </summary> + public static string Object2Json<T>(T t) + { + if (t == null) + return default; + return JsonConvert.SerializeObject(t); + } + + /// <summary> + /// 瀵硅薄杞负鏍煎紡 json + /// </summary> + public static string Object2FormatJson<T>(T t) + { + if (t == null) + return default; + return JsonConvert.SerializeObject(t, Formatting.Indented); + } + + /// <summary> + /// json杞负瀵硅薄 + /// </summary> + public static T Json2Object<T>(string json) + { + if (string.IsNullOrEmpty(json)) + return default; + try + { + return JsonConvert.DeserializeObject<T>(json); + } + catch (Exception ex) + { + var a = ex.Message; + return default; + } + + } + + + } +} diff --git a/Schedule/IStation.Algorithm/Helper/LongListHelper.cs b/Schedule/IStation.Algorithm/Helper/LongListHelper.cs new file mode 100644 index 0000000..c94246f --- /dev/null +++ b/Schedule/IStation.Algorithm/Helper/LongListHelper.cs @@ -0,0 +1,46 @@ +锘縩amespace IStations +{ + /// <summary> + /// 闀挎暣鍨嬪垪琛ㄨ緟鍔╃被 + /// </summary> + public class LongListHelper + { + //鍒嗗壊瀛楃 + private const string _split = ","; + + /// <summary> + /// 杞寲涓哄瓧绗︿覆 + /// </summary> + public static string ToString(IEnumerable<long> list) + { + if (list == null || list.Count() < 1) + return string.Empty; + return string.Join(_split, list); + } + + /// <summary> + /// 杞寲涓哄垪琛� + /// </summary> + /// <param name="str"></param> + /// <returns></returns> + public static List<long> ToList(string str) + { + if (string.IsNullOrEmpty(str)) + return new List<long>(); + try + { + var list = str.Split(new string[] { _split }, StringSplitOptions.RemoveEmptyEntries); + if (list.Count() < 1) + return new List<long>(); + return list.Select(x => Convert.ToInt64(x)).ToList(); + } + catch + { + return new List<long>(); + } + + } + + + } +} diff --git a/Schedule/IStation.Algorithm/Helper/PermutationAndCombination.cs b/Schedule/IStation.Algorithm/Helper/PermutationAndCombination.cs new file mode 100644 index 0000000..3d16e80 --- /dev/null +++ b/Schedule/IStation.Algorithm/Helper/PermutationAndCombination.cs @@ -0,0 +1,187 @@ +锘縩amespace IStation +{ + // 绠楁硶:鎺掑垪缁勫悎绫� + // + // 鐗堟潈鎵�鏈�(C) Snowdust + // 涓汉鍗氬 http://blog.csdn.net/snowdust & http://snowdust.cnblogs.com + // MSN & Email snowdust77@sina.com + // + // 姝ゆ簮浠g爜鍙厤璐圭敤浜庡悇绫昏蒋浠讹紙鍚晢涓氳蒋浠讹級 + // 鍏佽瀵规浠g爜鐨勮繘涓�姝ヤ慨鏀逛笌寮�鍙� + // 浣嗗繀椤诲畬鏁翠繚鐣欐鐗堟潈淇℃伅 + // + // 璋冪敤鏂规硶濡備笅: + // + // 1.GetPermutation(T[], startIndex, endIndex) + // 瀵箂tartIndex鍒癳ndIndex杩涜鎺掑垪锛屽叾浣欏厓绱犱笉鍙� + // + // 2.GetPermutation(T[]) + // 杩斿洖鏁扮粍鎵�鏈夊厓绱犵殑鍏ㄦ帓鍒� + // + // 3.GetPermutation(T[], n) + // 杩斿洖鏁扮粍涓璶涓厓绱犵殑鎺掑垪 + // + // 4.GetCombination(T[], n) + // 杩斿洖鏁扮粍涓璶涓厓绱犵殑缁勫悎 + + //浣跨敤瀹炰緥 + //int[] arr = new int[6]; + //for (int i = 0; i < arr.Length; i++) + //{ + // arr[i] = i + 1; + //} + ////姹傛帓鍒� + //List<int[]> lst_Permutation = Eventech.Model.PermutationAndCombination<int>.GetPermutation(arr, 3); + ////姹傜粍鍚� + //List<int[]> lst_Combination = Eventech.Model.PermutationAndCombination<int>.GetCombination(arr, 3); + + + public class PermutationAndCombination<T> + { + /// <summary> + /// 浜ゆ崲涓や釜鍙橀噺 + /// </summary> + /// <param name="a">鍙橀噺1</param> + /// <param name="b">鍙橀噺2</param> + public static void Swap(ref T a, ref T b) + { + T temp = a; + a = b; + b = temp; + } + + /// <summary> + /// 閫掑綊绠楁硶姹傛暟缁勭殑缁勫悎(绉佹湁鎴愬憳) + /// </summary> + /// <param name="list">杩斿洖鐨勮寖鍨�</param> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <param name="n">杈呭姪鍙橀噺</param> + /// <param name="m">杈呭姪鍙橀噺</param> + /// <param name="b">杈呭姪鏁扮粍</param> + /// <param name="M">杈呭姪鍙橀噺M</param> + private static void GetCombination(ref List<T[]> list, T[] t, int n, int m, int[] b, int M) + { + for (int i = n; i >= m; i--) + { + b[m - 1] = i - 1; + if (m > 1) + { + GetCombination(ref list, t, i - 1, m - 1, b, M); + } + else + { + if (list == null) + { + list = new List<T[]>(); + } + T[] temp = new T[M]; + for (int j = 0; j < b.Length; j++) + { + temp[j] = t[b[j]]; + } + list.Add(temp); + } + } + } + + /// <summary> + /// 閫掑綊绠楁硶姹傛帓鍒�(绉佹湁鎴愬憳) + /// </summary> + /// <param name="list">杩斿洖鐨勫垪琛�</param> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <param name="startIndex">璧峰鏍囧彿</param> + /// <param name="endIndex">缁撴潫鏍囧彿</param> + private static void GetPermutation(ref List<T[]> list, T[] t, int startIndex, int endIndex) + { + if (startIndex == endIndex) + { + if (list == null) + { + list = new List<T[]>(); + } + T[] temp = new T[t.Length]; + t.CopyTo(temp, 0); + list.Add(temp); + } + else + { + for (int i = startIndex; i <= endIndex; i++) + { + Swap(ref t[startIndex], ref t[i]); + GetPermutation(ref list, t, startIndex + 1, endIndex); + Swap(ref t[startIndex], ref t[i]); + } + } + } + + /// <summary> + /// 姹備粠璧峰鏍囧彿鍒扮粨鏉熸爣鍙风殑鎺掑垪锛屽叾浣欏厓绱犱笉鍙� + /// </summary> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <param name="startIndex">璧峰鏍囧彿</param> + /// <param name="endIndex">缁撴潫鏍囧彿</param> + /// <returns>浠庤捣濮嬫爣鍙峰埌缁撴潫鏍囧彿鎺掑垪鐨勮寖鍨�</returns> + public static List<T[]> GetPermutation(T[] t, int startIndex, int endIndex) + { + if (startIndex < 0 || endIndex > t.Length - 1) + { + return null; + } + List<T[]> list = new List<T[]>(); + GetPermutation(ref list, t, startIndex, endIndex); + return list; + } + + /// <summary> + /// 杩斿洖鏁扮粍鎵�鏈夊厓绱犵殑鍏ㄦ帓鍒� + /// </summary> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <returns>鍏ㄦ帓鍒楃殑鑼冨瀷</returns> + public static List<T[]> GetPermutation(T[] t) + { + return GetPermutation(t, 0, t.Length - 1); + } + + /// <summary> + /// 姹傛暟缁勪腑n涓厓绱犵殑鎺掑垪 + /// </summary> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <param name="n">鍏冪礌涓暟</param> + /// <returns>鏁扮粍涓璶涓厓绱犵殑鎺掑垪</returns> + public static List<T[]> GetPermutation(T[] t, int n) + { + if (n > t.Length) + { + return null; + } + List<T[]> list = new List<T[]>(); + List<T[]> c = GetCombination(t, n); + for (int i = 0; i < c.Count; i++) + { + List<T[]> l = new List<T[]>(); + GetPermutation(ref l, c[i], 0, n - 1); + list.AddRange(l); + } + return list; + } + + + /// <summary> + /// 姹傛暟缁勪腑n涓厓绱犵殑缁勫悎 + /// </summary> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <param name="n">鍏冪礌涓暟</param> + /// <returns>鏁扮粍涓璶涓厓绱犵殑缁勫悎鐨勮寖鍨�</returns> + public static List<T[]> GetCombination(T[] t, int n) + { + if (t.Length < n) + { + return null; + } + int[] temp = new int[n]; + List<T[]> list = new List<T[]>(); + GetCombination(ref list, t, t.Length, n, temp, n); + return list; + } + } +} diff --git a/Schedule/IStation.Algorithm/Helper/SnowflakeIdHelper.cs b/Schedule/IStation.Algorithm/Helper/SnowflakeIdHelper.cs new file mode 100644 index 0000000..d184f67 --- /dev/null +++ b/Schedule/IStation.Algorithm/Helper/SnowflakeIdHelper.cs @@ -0,0 +1,46 @@ +锘縩amespace IStation +{ + /// <summary> + /// 闆姳Id杈呭姪绫� + /// </summary> + public class SnowflakeIdHelper + { + + SnowflakeIdHelper() + { + var options = new IdGeneratorOptions(1); //鏋勯�犳柟娉曞垵濮嬪寲闆姳Id + YitIdHelper.SetIdGenerator(options); + } + + private static IIdGenerator _IdGenInstance = null; + public static IIdGenerator IdGenInstance => _IdGenInstance; + +聽聽聽聽聽聽聽聽///聽<summary> +聽聽聽聽聽聽聽聽///聽璁剧疆鍙傛暟锛屽缓璁▼搴忓垵濮嬪寲鏃舵墽琛屼竴娆� +聽聽聽聽聽聽聽聽///聽</summary> +聽聽聽聽聽聽聽聽///聽<param聽name="workerId">workerId</param> +聽聽聽聽聽聽聽聽public static void SetIdGenerator(ushort workerId) + { + var options = new IdGeneratorOptions() { WorkerId = workerId }; + _IdGenInstance = new DefaultIdGenerator(options); + } + +聽聽聽聽聽聽聽聽///聽<summary> +聽聽聽聽聽聽聽聽///聽鐢熸垚鏂扮殑Id +聽聽聽聽聽聽聽聽///聽璋冪敤鏈柟娉曞墠锛岃纭繚璋冪敤浜� SetIdGenerator 鏂规硶鍋氬垵濮嬪寲銆� +聽聽聽聽聽聽聽聽///聽鍚﹀垯灏嗕細鍒濆鍖栦竴涓猈orkerId涓�1鐨勫璞°�� +聽聽聽聽聽聽聽聽///聽</summary> +聽聽聽聽聽聽聽聽///聽<returns></returns> +聽聽聽聽聽聽聽聽public static long NextId() + { + if (_IdGenInstance == null) + { + _IdGenInstance = new DefaultIdGenerator( + new IdGeneratorOptions() { WorkerId = 0 } + ); + } + return _IdGenInstance.NewLong(); + } + + } +} diff --git a/Schedule/IStation.Algorithm/IStation.Algorithm.csproj b/Schedule/IStation.Algorithm/IStation.Algorithm.csproj new file mode 100644 index 0000000..57f8dfe --- /dev/null +++ b/Schedule/IStation.Algorithm/IStation.Algorithm.csproj @@ -0,0 +1,50 @@ +锘�<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net6.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>disable</Nullable> + <OutputType>Library</OutputType> + </PropertyGroup> + + <ItemGroup> + <Compile Remove="Schedule\bak\**" /> + <Compile Remove="Schedule\Output\**" /> + <Compile Remove="Schedule\v1_Model\**" /> + <EmbeddedResource Remove="Schedule\bak\**" /> + <EmbeddedResource Remove="Schedule\Output\**" /> + <EmbeddedResource Remove="Schedule\v1_Model\**" /> + <None Remove="Schedule\bak\**" /> + <None Remove="Schedule\Output\**" /> + <None Remove="Schedule\v1_Model\**" /> + </ItemGroup> + + <ItemGroup> + <Compile Remove="DAL\USplit.cs" /> + <Compile Remove="Entity\BaseEntity.cs" /> + <Compile Remove="Model\Schedule\ScheduleCombine - 澶嶅埗.cs" /> + <Compile Remove="Schedule\ScheduleCalc - 澶嶅埗.cs" /> + <Compile Remove="Schedule\ScheduleCalc1.cs" /> + <Compile Remove="Schedule\SchedulingAnaHelper - 澶嶅埗.cs" /> + <Compile Remove="Schedule\SchedulingAnaHelper.cs" /> + <Compile Remove="Schedule\SchedulingAnaHelper_v1.cs" /> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="MathNet.Numerics" Version="5.0.0" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> + <PackageReference Include="SqlSugarCore" Version="5.1.4.153" /> + <PackageReference Include="System.Data.SQLite" Version="1.0.118" /> + <PackageReference Include="Yitter.IdGenerator" Version="1.0.14" /> + </ItemGroup> + + <ItemGroup> + <None Update="Data\闄堣涓�杈�.json"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> + <None Update="Data\闄堣浜岃緭.json"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> + </ItemGroup> + +</Project> diff --git a/Schedule/IStation.Algorithm/Model/Base/BaseModel.cs b/Schedule/IStation.Algorithm/Model/Base/BaseModel.cs new file mode 100644 index 0000000..c0c51a6 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Base/BaseModel.cs @@ -0,0 +1,27 @@ +锘縩amespace IStation.Model +{ + /// <summary> + /// 鍩虹瀹炰綋 + /// </summary> + public class BaseModel + { + /// <summary> + /// + /// </summary> + public BaseModel() { } + + /// <summary> + /// + /// </summary> + public BaseModel(BaseModel rhs) + { + this.ID = rhs.ID; + } + + /// <summary> + /// 鑷鏍囪瘑 + /// </summary> + public virtual long ID { get; set; } + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier2.cs b/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier2.cs new file mode 100644 index 0000000..05c9a3c --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier2.cs @@ -0,0 +1,258 @@ +锘縩amespace IStation.Curve +{ + + /// <summary> + /// 璐濆灏旀洸绾跨被(浜屾) + /// </summary> + public class Bezier2 + { + /// <summary> + /// + /// </summary> + public Bezier2() { } + + /// <summary> + /// + /// </summary> + public Bezier2(List<CurvePoint> points) + { + if (points == null || points.Count < 3) + { + throw new Exception("鍙傛暟閿欒锛屾棤娉曡В鍑轰簩娆¤礉濉炲皵鏇茬嚎锛�"); + } + + this.Point0 = points[0]; + this.Point1 = points[1]; + this.Point2 = points[2]; + } + + + /// <summary> + /// 寮�濮嬬偣 + /// </summary> + public CurvePoint Point0 { get; set; } + + /// <summary> + /// 寮�濮嬬偣鐨勬帶鍒剁偣 + /// </summary> + public CurvePoint Point1 { get; set; } + + /// <summary> + /// 缁撴潫鐐� + /// </summary> + public CurvePoint Point2 { get; set; } + + /// <summary> + /// 鑾峰彇 X 鐢ㄤ簬鎻掑�� + /// </summary> + public double GetX(double uu) + { + return Point0.X * Math.Pow(1 - uu, 2) + + Point1.X * uu * (1 - uu) * 2 + + Point2.X * Math.Pow(uu, 2); + } + + /// <summary> + /// 鑾峰彇 Y 鐢ㄤ簬鎻掑�� + /// </summary> + public double GetY(double uu) + { + return Point0.Y * Math.Pow(1 - uu, 2) + + Point1.Y * uu * (1 - uu) * 2 + + Point2.Y * Math.Pow(uu, 2); + } + + /// <summary> + /// 閫氳繃 X 鑾峰彇浜ょ偣Y鍊� + /// </summary> + public bool GetSectPointYByX(double x, out double sect_y) + { + sect_y = 0; + //璐濆灏旀洸绾夸笌鎬ц兘鏇茬嚎鏈変氦鐐� + if ((x <= this.Point0.X && x >= this.Point2.X) || (x >= this.Point0.X && x <= this.Point2.X)) + { + #region 璐濆灏旀洸绾块泦鍚堝惊鐜� + //绗竴娆″惊鐜� + for (int i = 0; i < 10; i++) + { + var start0_uu = i * 0.1; + var end0_uu = start0_uu + 0.1; + var start0_p_x = this.GetX(start0_uu); + //var start0_p_y = this.GetY(start0_uu); + var end0_p_x = this.GetX(end0_uu); + //var end0_p_y = this.GetY(end0_uu); + if ((x <= start0_p_x && x >= end0_p_x) || (x >= start0_p_x && x <= end0_p_x)) + { + //绗簩娆″惊鐜� + for (int j = 0; j < 10; j++) + { + var start1_uu = start0_uu + j * 0.01; + var end1_uu = start1_uu + 0.01; + var start1_p_x = this.GetX(start1_uu); + //var start1_p_y = this.GetY(start1_uu); + var end1_p_x = this.GetX(end1_uu); + //var end1_p_y = this.GetY(end1_uu); + if ((x <= start1_p_x && x >= end1_p_x) || (x >= start1_p_x && x <= end1_p_x)) + { + //绗笁娆″惊鐜� + for (int k = 0; k < 10; k++) + { + var start2_uu = start1_uu + k * 0.001; + var end2_uu = start2_uu + 0.001; + var start2_p_x = this.GetX(start2_uu); + //var start2_p_y = this.GetY(start2_uu); + var end2_p_x = this.GetX(end2_uu); + //var end2_p_y = this.GetY(end2_uu); + if ((x <= start2_p_x && x >= end2_p_x) || (x >= start2_p_x && x <= end2_p_x)) + { + var set_x = (start2_p_x + end2_p_x) / 2; + sect_y = this.GetX((start2_uu + end2_uu) / 2); + + return true; + } + } + break; + } + } + break; + } + + } + #endregion + } + + return false; + } + + /// <summary> + /// 鏈�杩戠殑鐐� + /// </summary> + public CurvePoint GetClosePoint(CurvePoint ref_pt) + { + double boundary_min_x = Math.Min(Point0.X, Point2.X); + double boundary_max_x = Math.Max(Point0.X, Point2.X); + double boundary_min_y = Math.Min(Point0.Y, Point2.Y); + double boundary_max_y = Math.Max(Point0.Y, Point2.Y); + + double ratio_x = 0; + if (boundary_max_x == boundary_min_x) + { + ratio_x = 100 / (boundary_max_x); + } + else + { + ratio_x = 100 / (boundary_max_x - boundary_min_x); + } + + + double ratio_y = 0; + if (boundary_max_y == boundary_min_y) + { + ratio_y = 100 / (boundary_max_y); + } + else + { + ratio_y = 100 / (boundary_max_y - boundary_min_y); + } + + double chart_ref_x = (ref_pt.X - boundary_min_x) * ratio_x; + double chart_ref_y = (ref_pt.Y - boundary_min_y) * ratio_y; + + CurvePoint sect = null; + double min_dist = double.MaxValue; + for (double uu = 0; uu <= 1; uu = uu + 0.01) + { + double chart_x = (GetX(uu) - boundary_min_x) * ratio_x - chart_ref_x;//鐢变簬娴侀噺鎵▼鏁伴噺宸埆鐗瑰埆澶�, 鎵�浠ュ亣璁句粬浠湪涓�涓�100*100鐨勬柟鏍煎唴,姹傝窛绂� + double chart_y = (GetY(uu) - boundary_min_y) * ratio_y - chart_ref_y; + double distance = chart_x * chart_x + chart_y * chart_y; + if (distance < min_dist) + { + min_dist = distance; + sect = new CurvePoint(GetX(uu), GetY(uu)); + } + } + + return sect; + } + + /// <summary> + /// 姹備笌鏇茬嚎鐨勪氦鐐� (鍙兘鏈夊涓�,浣嗗彧鍙栫涓�涓偣) + /// </summary> + public CurvePoint GetCrossPoint(CurveExpress curve) + { + if (curve == null) + return null; + + //绗竴娆¤凯浠� + var index1 = GetCrossPointIndex_涓嶈凯浠�(curve, 0.2, 0, 5); + if (index1 < 0) + return null; + + //绗簩娆¤凯浠� + var index2 = GetCrossPointIndex_涓嶈凯浠�(curve, 0.02, 0.2 * index1, 10); + if (index2 < 0) + return null; + double uu = 0.2 * index1 + 0.02 * index2; + double x_bers = GetX(uu); + double y_bers = FitHelper.GetFitPointY(curve, x_bers); + + return new CurvePoint(x_bers, y_bers); + } + + //璁$畻鍦ㄧ鍑犱釜鐐圭浉浜�(鍙兘鏈夊涓�,浣嗗彧鍙栫涓�涓偣):鎬濊矾, 涓嶆柇閫艰繎,涓�涓鏁颁竴涓礋鏁板氨琛ㄧず鏈変氦鐐� + private int GetCrossPointIndex_涓嶈凯浠�(CurveExpress curve, double space, double start, int number) + { + double last_dis_y = 0; + + for (int i = 0; i <= number; i++) + { + double uu1 = start + space * i; + double x_bers = GetX(uu1); + double y_bers = GetY(uu1); + double y_curve = FitHelper.GetFitPointY(curve, x_bers); + double current_dis_y = y_bers - y_curve; + if (uu1 == 0) + { + last_dis_y = current_dis_y; + continue; + } + + if ((current_dis_y > 0 && last_dis_y < 0) || (current_dis_y < 0 && last_dis_y > 0)) + { + return i - 1; + } + + last_dis_y = current_dis_y; + } + + return -1; + } + + /// <summary> + /// 鍙樻垚涓�鏉′竴鏉$洿绾跨 + /// </summary> + /// <param name="pointNumber">璐濊禌灏旀洸绾夸腑闂存彃鍏ョ殑鐐规暟閲�</param> + public List<CurvePoint> GetApexPoints(int pointNumber) + { + var points_sect_list = new List<CurvePoint>(); + for (int i = 0; i <= pointNumber; i++) + { + var uu = i * 1.0 / pointNumber; + var p_x = this.GetX(uu); + var p_y = this.GetY(uu); + points_sect_list.Add(new CurvePoint(p_x, p_y)); + } + + return points_sect_list; + } + + /// <summary> + /// 鑾峰彇璺濈 + /// </summary> + public double Distance(CurvePoint point) + { + var point1 = GetClosePoint(point); + return point.Distance(point1); + } + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier3.cs b/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier3.cs new file mode 100644 index 0000000..eccb39c --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier3.cs @@ -0,0 +1,219 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 璐濆灏旀洸绾跨被(涓夋) + /// </summary> + public class Bezier3 + { + /// <summary> + /// + /// </summary> + public Bezier3() { } + + /// <summary> + /// + /// </summary> + public Bezier3(List<CurvePoint> points) + { + if (points == null || points.Count < 4) + { + throw new Exception("鍙傛暟閿欒锛屾棤娉曡В鍑轰笁娆¤礉濉炲皵鏇茬嚎锛�"); + } + + this.Point0 = points[0]; + this.Point1 = points[1]; + this.Point2 = points[2]; + this.Point3 = points[3]; + } + + /// <summary> + /// 寮�濮嬬偣 + /// </summary> + public CurvePoint Point0 { get; set; } + + /// <summary> + /// 寮�濮嬬偣鐨勬帶鍒剁偣 + /// </summary> + public CurvePoint Point1 { get; set; } + + /// <summary> + /// 缁撴潫鐐圭殑鎺у埗鐐� + /// </summary> + public CurvePoint Point2 { get; set; } + + /// <summary> + /// 缁撴潫鐐� + /// </summary> + public CurvePoint Point3 { get; set; } + + /// <summary> + /// 鑾峰彇 X 鐢ㄤ簬鎻掑�� + /// </summary> + public double GetX(double uu) + { + double u0 = Point3.X * uu * uu * uu; + double u1 = 3 * Point2.X * uu * uu * (1 - uu); + double u2 = 3 * Point1.X * uu * (1 - uu) * (1 - uu); + double u3 = Point0.X * (1 - uu) * (1 - uu) * (1 - uu); + + return u0 + u1 + u2 + u3; + } + + /// <summary> + /// 鑾峰彇 Y 鐢ㄤ簬鎻掑�� + /// </summary> + public double GetY(double uu) + { + double u0 = Point3.Y * uu * uu * uu; + double u1 = 3 * Point2.Y * uu * uu * (1 - uu); + double u2 = 3 * Point1.Y * uu * (1 - uu) * (1 - uu); + double u3 = Point0.Y * (1 - uu) * (1 - uu) * (1 - uu); + + return u0 + u1 + u2 + u3; + } + + /// <summary> + /// 璺濈鏈�杩戠殑鐐� + /// </summary> + public CurvePoint GetClosePoint(CurvePoint ref_pt) + { + double boundary_min_x = Math.Min(Point0.X, Point3.X); + double boundary_max_x = Math.Max(Point0.X, Point3.X); + double boundary_min_y = Math.Min(Point0.Y, Point3.Y); + double boundary_max_y = Math.Max(Point0.Y, Point3.Y); + //鐢变簬娴侀噺鎵▼鏁伴噺宸埆鐗瑰埆澶�, 鎵�浠ュ亣璁句粬浠湪涓�涓�100*100鐨勬柟鏍煎唴,姹傝窛绂� + double ratio_x = 0; + if (boundary_max_x == boundary_min_x) + { + ratio_x = 100 / (boundary_max_x); + } + else + { + ratio_x = 100 / (boundary_max_x - boundary_min_x); + } + + + double ratio_y = 0; + if (boundary_max_y == boundary_min_y) + { + ratio_y = 100 / (boundary_max_y); + } + else + { + ratio_y = 100 / (boundary_max_y - boundary_min_y); + } + + double chart_ref_x = (ref_pt.X - boundary_min_x) * ratio_x; + double chart_ref_y = (ref_pt.Y - boundary_min_y) * ratio_y; + + CurvePoint sect = null; + double min_dist = double.MaxValue; + for (double uu = 0; uu <= 1; uu = uu + 0.01) + { + double chart_x = (GetX(uu) - boundary_min_x) * ratio_x - chart_ref_x; + double chart_y = (GetY(uu) - boundary_min_y) * ratio_y - chart_ref_y; + double distance = chart_x * chart_x + chart_y * chart_y; + if (distance < min_dist) + { + min_dist = distance; + sect = new CurvePoint(GetX(uu), GetY(uu)); + } + } + + return sect; + } + + /// <summary> + /// 姹備笌鏇茬嚎鐨勪氦鐐� (鍙兘鏈夊涓�,浣嗗彧鍙栫涓�涓偣) + /// </summary> + public CurvePoint GetCrossPoint(CurveExpress curve) + { + if (curve == null) + return null; + + //绗竴娆¤凯浠� + var index1 = GetCrossPointIndex_涓嶈凯浠�(curve, 0.2, 0, 5); + if (index1 < 0) + return null; + + //绗簩娆¤凯浠� + var index2 = GetCrossPointIndex_涓嶈凯浠�(curve, 0.02, 0.2 * index1, 10); + if (index2 < 0) + return null; + double uu = 0.2 * index1 + 0.02 * index2; + double x_bers = GetX(uu); + double y_bers = FitHelper.GetFitPointY(curve, x_bers); + + return new CurvePoint(x_bers, y_bers); + } + + //璁$畻鍦ㄧ鍑犱釜鐐圭浉浜�(鍙兘鏈夊涓�,浣嗗彧鍙栫涓�涓偣):鎬濊矾, 涓嶆柇閫艰繎,涓�涓鏁颁竴涓礋鏁板氨琛ㄧず鏈変氦鐐� + private int GetCrossPointIndex_涓嶈凯浠�(CurveExpress curve, double space, double start, int number) + { + double last_dis_y = 0; + + for (int i = 0; i <= number; i++) + { + double uu1 = start + space * i; + double x_bers = GetX(uu1); + double y_bers = GetY(uu1); + double y_curve = FitHelper.GetFitPointY(curve, x_bers); + double current_dis_y = y_bers - y_curve; + if (uu1 == 0) + { + last_dis_y = current_dis_y; + continue; + } + + if ((current_dis_y > 0 && last_dis_y < 0) || (current_dis_y < 0 && last_dis_y > 0)) + { + return i - 1; + } + + last_dis_y = current_dis_y; + } + + return -1; + } + + /// <summary> + /// 鍙樻垚涓�鏉′竴鏉$洿绾挎 + /// </summary> + /// <param name="pointNumber">璐濊禌灏旀洸绾夸腑闂存彃鍏ョ殑鐐规暟閲�</param> + public List<CurvePoint> GetApexPoints(int pointNumber) + { + var points_sect_list = new List<CurvePoint>(); + for (int i = 0; i <= pointNumber; i++) + { + var uu = i * 1.0 / pointNumber; + var p_x = this.GetX(uu); + var p_y = this.GetY(uu); + points_sect_list.Add(new CurvePoint(p_x, p_y)); + } + + return points_sect_list; + } + + /// <summary> + /// 鑾峰彇璺濈 + /// </summary> + public double Distance(CurvePoint point) + { + var point1 = GetClosePoint(point); + return point.Distance(point1); + } + + /// <summary> + /// 閫氳繃 Y 鍒ゆ柇鏄惁鍦ㄥ叾涓� + /// </summary> + public bool IsInnerByY(double y) + { + if (y >= this.Point0.Y && y <= this.Point3.Y) + return true; + if (y >= this.Point3.Y && y <= this.Point0.Y) + return true; + return false; + } + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Bezier/BezierCurveHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Bezier/BezierCurveHelper.cs new file mode 100644 index 0000000..683316a --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Bezier/BezierCurveHelper.cs @@ -0,0 +1,500 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 璐濆灏旂嚎 + /// </summary> + public class BezierCurveHelper + { + /// <summary> + /// 鑾峰彇寮�鏀剧殑璐濆灏旀洸绾垮垪琛� + /// </summary> + public static List<Bezier3> CreateOpenCurves(List<CurvePoint> points) + { + //http://wenku.baidu.com/link?url=9TGvGfedfkbskSWwfeO_iJJHvIzL0E_mE3wwVlWs1kEvvT9dHDQFdArhcdh8yuCK3pUbw2soJKs5qiQKlzhA885Tgtbu-Cdr1T37ANki_mS + if (points == null || points.Count() < 4) + return default; + + int iPointCout = points.Count(); + double a = 0.25; + double b = 0.25; + List<Bezier3> controlPoint = new List<Bezier3>(); + //鐢熸垚4鎺у埗鐐癸紝浜х敓璐濆灏旀洸绾� + for (int i = 0; i < iPointCout - 1; i++) + { + Bezier3 bezier = new Bezier3(); + + bezier.Point0 = points[i]; + if (i == 0) + { + double x1 = points[i].X + a * (points[i + 1].X - points[i].X); + double y1 = points[i].Y + a * (points[i + 1].Y - points[i].Y); + bezier.Point1 = new CurvePoint(x1, y1); + } + else + { + double x1 = points[i].X + a * (points[i + 1].X - points[i - 1].X); + double y1 = points[i].Y + a * (points[i + 1].Y - points[i - 1].Y); + bezier.Point1 = new CurvePoint(x1, y1); + } + + if (i == iPointCout - 2) + { + double x2 = points[i + 1].X - b * (points[i + 1].X - points[i].X); + double y2 = points[i + 1].Y - b * (points[i + 1].Y - points[i].Y); + bezier.Point2 = new CurvePoint(x2, y2); + } + else + { + double x2 = points[i + 1].X - b * (points[i + 2].X - points[i].X); + double y2 = points[i + 1].Y - b * (points[i + 2].Y - points[i].Y); + bezier.Point2 = new CurvePoint(x2, y2); + } + + bezier.Point3 = points[i + 1]; + controlPoint.Add(bezier); + } + return controlPoint; + } + + /// <summary> + /// 鑾峰彇灏侀棴鐨勮礉濉炲皵鏇茬嚎鍒楄〃 + /// </summary> + public static List<Bezier3> CreateCloseCurves(List<CurvePoint> points) + { + //http://blog.csdn.net/microchenhong/article/details/6316332 + int originCount = points.Count(); + //鎺у埗鐐规敹缂╃郴鏁� 锛岀粡璋冭瘯0.6杈冨ソ + float scale = 0.6f; + var midpoints = new List<CurvePoint>(); + //鐢熸垚涓偣 + for (int i = 0; i < originCount; i++) + { + int nexti = (i + 1) % originCount; + double x = (points[i].X + points[nexti].X) / 2.0; + double y = (points[i].Y + points[nexti].Y) / 2.0; + midpoints.Add(new CurvePoint(x, y)); + } + + //骞崇Щ涓偣 + var extrapoints = new List<CurvePoint>();//[2 * originCount]; + for (int i = 0; i < originCount * 2; i++) + { + extrapoints.Add(new CurvePoint(0, 0)); + } + for (int i = 0; i < originCount; i++) + { + int nexti = (i + 1) % originCount; + int backi = (i + originCount - 1) % originCount; + var midinmid = new CurvePoint(); + midinmid.X = (midpoints[i].X + midpoints[backi].X) / 2.0; + midinmid.Y = (midpoints[i].Y + midpoints[backi].Y) / 2.0; + double offsetx = points[i].X - midinmid.X; + double offsety = points[i].Y - midinmid.Y; + int extraindex = 2 * i; + extrapoints[extraindex].X = midpoints[backi].X + offsetx; + extrapoints[extraindex].Y = midpoints[backi].Y + offsety; + //鏈� originPoint[i]鏂瑰悜鏀剁缉 + double addx = (extrapoints[extraindex].X - points[i].X) * scale; + double addy = (extrapoints[extraindex].Y - points[i].Y) * scale; + extrapoints[extraindex].X = points[i].X + addx; + extrapoints[extraindex].Y = points[i].Y + addy; + + int extranexti = (extraindex + 1) % (2 * originCount); + extrapoints[extranexti].X = midpoints[i].X + offsetx; + extrapoints[extranexti].Y = midpoints[i].Y + offsety; + //鏈� originPoint[i]鏂瑰悜鏀剁缉 + addx = (extrapoints[extranexti].X - points[i].X) * scale; + addy = (extrapoints[extranexti].Y - points[i].Y) * scale; + extrapoints[extranexti].X = points[i].X + addx; + extrapoints[extranexti].Y = points[i].Y + addy; + } + + List<Bezier3> controlPoint = new List<Bezier3>(); + //鐢熸垚4鎺у埗鐐癸紝浜х敓璐濆灏旀洸绾� + for (int i = 0; i < originCount - 1; i++) + { + Bezier3 bezier = new Bezier3(); + + bezier.Point0 = points[i]; + int extraindex = 2 * i; + bezier.Point1 = extrapoints[extraindex + 1]; + int extranexti = (extraindex + 2) % (2 * originCount); + bezier.Point2 = extrapoints[extranexti]; + int nexti = (i + 1) % originCount; + bezier.Point3 = points[nexti]; + controlPoint.Add(bezier); + } + return controlPoint; + } + + /// <summary> + /// 閫氳繃 X 鑾峰彇浜ょ偣 + /// </summary> + public static List<CurvePoint> GetSectPointsByX(List<Bezier3> allBeziers, double x) + { + if (allBeziers == null || allBeziers.Count() < 1) + return null; + + var points_sect_list = new List<CurvePoint>(); + foreach (var bezeir in allBeziers) + { + //璐濆灏旀洸绾夸笌鎬ц兘鏇茬嚎鏈変氦鐐� + if ((x <= bezeir.Point0.X && x >= bezeir.Point3.X) || (x >= bezeir.Point0.X && x <= bezeir.Point3.X)) + { + #region 璐濆灏旀洸绾块泦鍚堝惊鐜� + //绗竴娆″惊鐜� + for (int i = 0; i < 10; i++) + { + var start0_uu = i * 0.1; + var end0_uu = start0_uu + 0.1; + var start0_p_x = bezeir.GetX(start0_uu); + //var start0_p_y = bezeir.GetY(start0_uu); + var end0_p_x = bezeir.GetX(end0_uu); + //var end0_p_y = bezeir.GetY(end0_uu); + if ((x <= start0_p_x && x >= end0_p_x) || (x >= start0_p_x && x <= end0_p_x)) + { + //绗簩娆″惊鐜� + for (int j = 0; j < 10; j++) + { + var start1_uu = start0_uu + j * 0.01; + var end1_uu = start1_uu + 0.01; + var start1_p_x = bezeir.GetX(start1_uu); + //var start1_p_y = bezeir.GetY(start1_uu); + var end1_p_x = bezeir.GetX(end1_uu); + //var end1_p_y = bezeir.GetY(end1_uu); + if ((x <= start1_p_x && x >= end1_p_x) || (x >= start1_p_x && x <= end1_p_x)) + { + //绗笁娆″惊鐜� + for (int k = 0; k < 10; k++) + { + var start2_uu = start1_uu + k * 0.001; + var end2_uu = start2_uu + 0.001; + var start2_p_x = bezeir.GetX(start2_uu); + //var start2_p_y = bezeir.GetY(start2_uu); + var end2_p_x = bezeir.GetX(end2_uu); + //var end2_p_y = bezeir.GetY(end2_uu); + if ((x <= start2_p_x && x >= end2_p_x) || (x >= start2_p_x && x <= end2_p_x)) + { + var set_x = bezeir.GetX((start2_uu + end2_uu) / 2); + var set_y = bezeir.GetY((start2_uu + end2_uu) / 2); + var set_pt = new CurvePoint(set_x, set_y); + + points_sect_list.Add(set_pt); + break; + } + } + break; + } + } + break; + } + + } + #endregion + } + } + + return points_sect_list; + } + + /// <summary> + /// 閫氳繃 Y 鑾峰彇浜ょ偣 + /// </summary> + public static List<CurvePoint> GetSectPointsByY(List<Bezier3> allBeziers, double y) + { + if (allBeziers == null || allBeziers.Count() == 0) + return null; + var points_sect_list = new List<CurvePoint>(); + foreach (var bezeir in allBeziers) + { + //璐濆灏旀洸绾夸笌鎬ц兘鏇茬嚎鏈変氦鐐� + if ((y <= bezeir.Point0.Y && y >= bezeir.Point3.X) || (y >= bezeir.Point0.Y && y <= bezeir.Point3.Y)) + { + #region 璐濆灏旀洸绾块泦鍚堝惊鐜� + //绗竴娆″惊鐜� + for (int i = 0; i < 10; i++) + { + var start0_uu = i * 0.1; + var end0_uu = start0_uu + 0.1; + //var start0_p_x = bezeir.GetX(start0_uu); + var start0_p_y = bezeir.GetY(start0_uu); + //var end0_p_x = bezeir.GetX(end0_uu); + var end0_p_y = bezeir.GetY(end0_uu); + if ((y <= start0_p_y && y >= end0_p_y) || (y >= start0_p_y && y <= end0_p_y)) + { + //绗簩娆″惊鐜� + for (int j = 0; j < 10; j++) + { + var start1_uu = start0_uu + j * 0.01; + var end1_uu = start1_uu + 0.01; + // var start1_p_x = bezeir.GetX(start1_uu); + var start1_p_y = bezeir.GetY(start1_uu); + // var end1_p_x = bezeir.GetX(end1_uu); + var end1_p_y = bezeir.GetY(end1_uu); + if ((y <= start1_p_y && y >= end1_p_y) || (y >= start1_p_y && y <= end1_p_y)) + { + //绗笁娆″惊鐜� + for (int k = 0; k < 10; k++) + { + var start2_uu = start1_uu + k * 0.001; + var end2_uu = start2_uu + 0.001; + //var start2_p_x = bezeir.GetX(start2_uu); + var start2_p_y = bezeir.GetY(start2_uu); + // var end2_p_x = bezeir.GetX(end2_uu); + var end2_p_y = bezeir.GetY(end2_uu); + if ((y <= start2_p_y && y >= end2_p_y) || (y >= start2_p_y && y <= end2_p_y)) + { + var set_x = bezeir.GetX((start2_uu + end2_uu) / 2); + var set_y = bezeir.GetY((start2_uu + end2_uu) / 2); + var set_pt = new CurvePoint(set_x, set_y); + + points_sect_list.Add(set_pt); + break; + } + } + break; + } + } + break; + } + + } + #endregion + } + } + + return points_sect_list; + } + + /// <summary> + /// 閫氳繃 鏇茬嚎琛ㄨ揪寮� 鑾峰彇浜ょ偣 + /// </summary> + public static List<CurvePoint> GetCrossPoints(List<Bezier3> allBeziers, CurveExpress curve) + { + if (allBeziers == null || allBeziers.Count() == 0) + return null; + var points_sect_list = new List<CurvePoint>(); + foreach (var bezeir in allBeziers) + { + var pt = bezeir.GetCrossPoint(curve); + if (pt != null) + points_sect_list.Add(pt); + } + + return points_sect_list; + } + + /// <summary> + /// 閫氳繃 鏇茬嚎琛ㄨ揪寮� 鑾峰彇浜ょ偣 + /// </summary> + public static List<CurvePoint> GetCrossPoints(List<CurvePoint> originPoint, CurveExpress curve) + { + if (originPoint == null) + return null; + if (originPoint.Count() <= 2) + return null; + if (originPoint.Count() == 3) + { + var b2 = new Bezier2(originPoint); + var pt = b2.GetCrossPoint(curve); + if (pt == null) + return null; + return new List<CurvePoint>() { pt }; + } + + var allBeziers = CreateOpenCurves(originPoint); + + var points_sect_list = new List<CurvePoint>(); + foreach (var bezeir in allBeziers) + { + var pt = bezeir.GetCrossPoint(curve); + if (pt != null) + points_sect_list.Add(pt); + } + + return points_sect_list; + } + + /// <summary> + /// 鑾峰彇璺濈 + /// </summary> + public static double Distance(List<CurvePoint> curvePoints, CurvePoint point) + { + if (curvePoints == null || curvePoints.Count() == 0) + return 0; + if (curvePoints.Count() == 1) + { + var point1 = curvePoints.First(); + return Math.Sqrt((point1.X - point.X) * (point1.X - point.X) + (point1.Y - point.Y) * (point1.Y - point.Y)); + } + if (curvePoints.Count() == 2) + { + var point1 = curvePoints.First(); + var point2 = curvePoints.Last(); + + return CurveLineHelper.Distance(point1, point2, point); + } + if (curvePoints.Count() == 3) + { + var b2 = new Bezier2(curvePoints); + return b2.Distance(point); + } + + var allBeziers = CreateOpenCurves(curvePoints); + + double min_dis = double.MaxValue; + foreach (var bezeir in allBeziers) + { + var dis = bezeir.Distance(point); + min_dis = Math.Min(min_dis, dis); + } + + return min_dis; + } + + /// <summary> + /// 鑾峰彇璺濈(鎶婃洸绾垮帇缂╁埌100*100鐨勭洅瀛愰噷闈� Boundary 姹傝窛绂�) + /// </summary> + public static double Distance(CurveBoundary boundary, List<CurvePoint> curve_real, CurvePoint point_real) + { + if (curve_real == null || curve_real.Count() == 0) + return 0; + if (boundary == null) + return Distance(curve_real, point_real); + double ratio_x = 0; + if (boundary.MaxX == boundary.MinX) + { + ratio_x = 100 / (boundary.MaxX); + } + else + { + ratio_x = 100 / (boundary.MaxX - boundary.MinX); + } + + + double ratio_y = 0; + if (boundary.MaxY == boundary.MinY) + { + ratio_y = 100 / (boundary.MaxY); + } + else + { + ratio_y = 100 / (boundary.MaxY - boundary.MinY); + } + + var point_chart = new CurvePoint() { X = (point_real.X - boundary.MinX) * ratio_x, Y = (point_real.Y - boundary.MinY) * ratio_y }; + var curvePoints = new List<CurvePoint>(); + foreach (var pt in curve_real) + { + var point1 = new CurvePoint() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }; + curvePoints.Add(point1); + } + if (curvePoints.Count() == 1) + { + var point1 = curvePoints.First(); + return Math.Sqrt((point1.X - point_chart.X) * (point1.X - point_chart.X) + (point1.Y - point_chart.Y) * (point1.Y - point_chart.Y)); + } + if (curvePoints.Count() == 2) + { + var point1 = curvePoints.First(); + var point2 = curvePoints.Last(); + + return CurveLineHelper.Distance(point1, point2, point_chart); + } + if (curvePoints.Count() == 3) + { + var b2 = new Bezier2(curvePoints); + return b2.Distance(point_chart); + } + + var allBeziers = CreateOpenCurves(curvePoints); + + double min_dis = double.MaxValue; + foreach (var bezeir in allBeziers) + { + var dis = bezeir.Distance(point_chart); + min_dis = Math.Min(min_dis, dis); + } + + return min_dis; + } + + /// <summary> + /// 鍙樻垚鐩寸嚎绔� + /// </summary> + /// <param name="allBeziers">璐濆灏旀洸绾�</param> + /// <param name="pointNumber">璐濊禌灏旀洸绾夸腑闂存彃鍏ョ殑鐐规暟閲�</param> + /// <returns></returns> + public static List<CurvePoint> GetApexPoints(List<Bezier3> allBeziers, int pointNumber) + { + var points_sect_list = new List<CurvePoint>(); + foreach (var bezeir in allBeziers) + { + for (int i = 0; i <= pointNumber; i++) + { + var uu = i * 1.0 / pointNumber; + var p_x = bezeir.GetX(uu); + var p_y = bezeir.GetY(uu); + points_sect_list.Add(new CurvePoint(p_x, p_y)); + } + } + + return points_sect_list; + } + + /// <summary> + /// 鍙樻垚鐩寸嚎绔�(鍙拡瀵瑰紑鍙g殑鏇茬嚎) + /// </summary> + /// <param name="originPoint">璐濆灏旀洸绾�</param> + /// <param name="pointNumber">璐濊禌灏旀洸绾夸腑闂存彃鍏ョ殑鐐规暟閲�</param> + /// <returns></returns> + public static List<CurvePoint> GetApexPoints(List<CurvePoint> originPoint, int pointNumber) + { + if (originPoint == null) + return null; + if (originPoint.Count() <= 2) + return null; + if (originPoint.Count() == 3) + { + var b2 = new Bezier2(originPoint); + return b2.GetApexPoints(pointNumber); + } + + var allBeziers = CreateOpenCurves(originPoint); + var points_sect_list = new List<CurvePoint>(); + foreach (var bezeir in allBeziers) + { + for (int i = 0; i <= pointNumber; i++) + { + var uu = i * 1.0 / pointNumber; + var p_x = bezeir.GetX(uu); + var p_y = bezeir.GetY(uu); + points_sect_list.Add(new CurvePoint(p_x, p_y)); + } + } + + return points_sect_list; + } + + //涓夋璐濆灏旀洸绾� + private double bezier3funcX(double uu, List<CurvePoint> controlP) + { + double part0 = controlP[0].X * uu * uu * uu; + double part1 = 3 * controlP[1].X * uu * uu * (1 - uu); + double part2 = 3 * controlP[2].X * uu * (1 - uu) * (1 - uu); + double part3 = controlP[3].X * (1 - uu) * (1 - uu) * (1 - uu); + return part0 + part1 + part2 + part3; + } + private double bezier3funcY(double uu, List<CurvePoint> controlP) + { + double part0 = controlP[0].Y * uu * uu * uu; + double part1 = 3 * controlP[1].Y * uu * uu * (1 - uu); + double part2 = 3 * controlP[2].Y * uu * (1 - uu) * (1 - uu); + double part3 = controlP[3].Y * (1 - uu) * (1 - uu) * (1 - uu); + return part0 + part1 + part2 + part3; + } + + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Boundary/CurveBoundary.cs b/Schedule/IStation.Algorithm/Model/Curve/Boundary/CurveBoundary.cs new file mode 100644 index 0000000..c1fa941 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Boundary/CurveBoundary.cs @@ -0,0 +1,45 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鏇茬嚎杈圭晫 + /// </summary> + public class CurveBoundary : JsonModel<CurveBoundary> + { + /// <summary> + /// + /// </summary> + public CurveBoundary() { } + + /// <summary> + /// + /// </summary> + public CurveBoundary(double minX, double maxX, double minY, double maxY) + { + this.MinX = minX; + this.MaxX = maxX; + this.MinY = minY; + this.MaxY = maxY; + } + + /// <summary> + /// X鏈�灏忓�� + /// </summary> + public double MinX { get; set; } + + /// <summary> + /// X鏈�澶у�� + /// </summary> + public double MaxX { get; set; } + + /// <summary> + /// Y鏈�灏忓�� + /// </summary> + public double MinY { get; set; } + + /// <summary> + /// Y鏈�澶у�� + /// </summary> + public double MaxY { get; set; } + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Constant/Constant.cs b/Schedule/IStation.Algorithm/Model/Curve/Constant/Constant.cs new file mode 100644 index 0000000..05de9e2 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Constant/Constant.cs @@ -0,0 +1,12 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 甯搁噺 + /// </summary> + public class Constant + { + public const double g = 9.81;//閲嶅姏鍔犻�熷害 m/s虏 + public const double WaterDensity = 1000; //姘寸殑瀵嗗害 g/L kg/m鲁 + public const double OtherPressCoeff = 4 * 1000 / Math.PI / 3.6;//鍏朵粬鍘嬪姏绯绘暟 nsx ScadaAnaly鐢�,20020504 + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate.cs b/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate.cs new file mode 100644 index 0000000..a47bc44 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate.cs @@ -0,0 +1,124 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鏇茬嚎鍧愭爣鍙傛暟 + /// </summary> + public partial class CurveCoordinate : JsonModel<CurveCoordinate> + { + public CurveCoordinate() { } + + public CurveCoordinate(CurveCoordinate rhs) + { + this.GridNumberX = rhs.GridNumberX; + this.GridNumberY = rhs.GridNumberY; + this.CoordMinQ = rhs.CoordMinQ; + this.CoordSpaceQ = rhs.CoordSpaceQ; + this.CoordMinH = rhs.CoordMinH; + this.CoordSpaceH = rhs.CoordSpaceH; + this.StartLineNoH = rhs.StartLineNoH; + this.EndLineNoH = rhs.EndLineNoH; + this.CoordMinP = rhs.CoordMinP; + this.CoordSpaceP = rhs.CoordSpaceP; + this.StartLineNoP = rhs.StartLineNoP; + this.EndLineNoP = rhs.EndLineNoP; + this.DispPanelQP = rhs.DispPanelQP; + this.CoordMinE = rhs.CoordMinE; + this.CoordSpaceE = rhs.CoordSpaceE; + this.StartLineNoE = rhs.StartLineNoE; + this.EndLineNoE = rhs.EndLineNoE; + this.DispPanelQE = rhs.DispPanelQE; + } + + /// <summary> + /// X鍧愭爣闂撮殧鏁� 鍧愭爣绾挎瘮鍧愭爣闂撮殧澶�1 + /// </summary> + public int GridNumberX { get; set; } + + /// <summary> + /// Y鍧愭爣闂撮殧鏁� 鍧愭爣绾挎瘮鍧愭爣闂撮殧澶�1 + /// </summary> + public int GridNumberY { get; set; } + + /// <summary> + /// 娴侀噺鍧愭爣鏈�灏忓�� + /// </summary> + public double CoordMinQ { get; set; } + + /// <summary> + /// 娴侀噺鍧愭爣闂撮殧 + /// </summary> + public double CoordSpaceQ { get; set; } + + /// <summary> + /// 鎵▼鍧愭爣鏈�灏忓�� + /// </summary> + public double CoordMinH { get; set; } + + /// <summary> + /// 鎵▼鍧愭爣闂撮殧 + /// </summary> + public double CoordSpaceH { get; set; } + + /// <summary> + /// 鎵▼寮�濮嬬嚎鍙� + /// </summary> + public int StartLineNoH { get; set; } + + /// <summary> + /// 鎵▼缁撴潫绾垮彿 + /// </summary> + public int EndLineNoH { get; set; } + + /// <summary> + /// 鍔熺巼鍧愭爣鏈�灏忓�� + /// </summary> + public double CoordMinP { get; set; } + + /// <summary> + /// 鍔熺巼鍧愭爣闂撮殧 + /// </summary> + public double CoordSpaceP { get; set; } + + /// <summary> + /// 鍔熺巼寮�濮嬬嚎鍙� + /// </summary> + public int StartLineNoP { get; set; } + + /// <summary> + /// 鍔熺巼缁撴潫绾垮彿 + /// </summary> + public int EndLineNoP { get; set; } + + /// <summary> + /// 鍔熺巼鏄剧ず闈㈡澘 -1琛ㄧず涓嶆樉绀� 闈㈡澘0琛ㄧずQH 1琛ㄧずQP 2琛ㄧずQE + /// </summary> + public int DispPanelQP { get; set; } + + /// <summary> + /// 鏁堢巼鍧愭爣鏈�灏忓�� + /// </summary> + public double CoordMinE { get; set; } + + /// <summary> + /// 鏁堢巼鍧愭爣闂撮殧 + /// </summary> + public double CoordSpaceE { get; set; } + + /// <summary> + /// 鏁堢巼寮�濮嬬嚎鍙� + /// </summary> + public int StartLineNoE { get; set; } + + /// <summary> + /// 鏁堢巼缁撴潫绾垮彿 + /// </summary> + public int EndLineNoE { get; set; } + + /// <summary> + /// 鍔熺巼鏄剧ず闈㈡澘 -1琛ㄧず涓嶆樉绀� 闈㈡澘0琛ㄧずQH 1琛ㄧずQP 2琛ㄧずQE + /// </summary> + public int DispPanelQE { get; set; } + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate_Disp.cs b/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate_Disp.cs new file mode 100644 index 0000000..4bfe5a7 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate_Disp.cs @@ -0,0 +1,747 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// + /// </summary> + public partial class CurveCoordinate + { + #region 璁$畻鏄剧ず鍙傛暟鏂规硶 + + #region 榛樿 + /// <summary> + /// 鏈�澶ф祦閲�(鏄剧ず鍙傛暟) + /// </summary> + public double DispMaxQ() + { + return this.CoordMinQ + (double)this.GridNumberX * this.CoordSpaceQ; + } + + /// <summary> + /// 鏈�灏忔壃绋�(鏄剧ず鍙傛暟) + /// </summary> + public double DispMinH() + { + return this.CoordMinH + (double)this.StartLineNoH * this.CoordSpaceH; + } + + /// <summary> + /// 鏈�澶ф壃绋�(鏄剧ず鍙傛暟) + /// </summary> + public double DispMaxH() + { + return CoordMinH + (double)this.EndLineNoH * this.CoordSpaceH; + } + + /// <summary> + /// 鏈�灏忔晥鐜�(鏄剧ず鍙傛暟) + /// </summary> + public double DispMinE() + { + return this.CoordMinE + (double)this.StartLineNoE * this.CoordSpaceE; + } + + /// <summary> + /// 鏈�澶ф晥鐜�(鏄剧ず鍙傛暟) + /// </summary> + public double DispMaxE() + { + return this.CoordMinE + (double)this.EndLineNoE * this.CoordSpaceE; + } + + /// <summary> + /// 鏈�灏忓姛鐜�(鏄剧ず鍙傛暟) + /// </summary> + public double DispMinP() + { + return this.CoordMinP + (double)this.StartLineNoP * this.CoordSpaceP; + } + + /// <summary> + /// 鏈�澶у姛鐜�(鏄剧ず鍙傛暟) + /// </summary> + public double DispMaxP() + { + return this.CoordMinP + (double)this.EndLineNoP * this.CoordSpaceP; + } + + #endregion + + /// <summary> + /// 閲嶇疆鎵▼鍧愭爣 + /// </summary> + public void ResetCoordH(double space, double disMinH, double disMaxH) + { + this.CoordSpaceH = space; + this.EndLineNoH = this.GridNumberY; + this.StartLineNoH = this.EndLineNoH - (int)((disMaxH - disMinH) / this.CoordSpaceH); + this.CoordMinH = disMaxH - (double)this.EndLineNoH * this.CoordSpaceH; + } + #endregion + + #region 璁$畻鍧愭爣 + + /// <summary> + /// 璁$畻鍧愭爣 + /// </summary> + /// <param name="QH">娴侀噺鎵▼绾�</param> + /// <param name="QE">娴侀噺鏁堢巼绾�</param> + /// <param name="QP">娴侀噺鍔熺巼绾�</param> + /// <returns></returns> + public static CurveCoordinate CalcCoordinate(CurveExpress QH, CurveExpress QE, CurveExpress QP) + { + if (QH == null) + return null; + + List<CurvePoint> pointsQH = QH.GetFitPoints(20); + List<CurvePoint> pointsQE = null; + if (QE != null) + pointsQE = QE.GetFitPoints(20); + List<CurvePoint> pointsQP = null; + if (QP != null) + pointsQP = QP.GetFitPoints(20); + + return CalcCoordinate(pointsQH, pointsQE, pointsQP); + } + + /// <summary> + /// 璁$畻鍧愭爣 + /// </summary> + /// <param name="QH">娴侀噺鎵▼绾�</param> + /// <param name="QE">娴侀噺鏁堢巼绾�</param> + /// <param name="QP">娴侀噺鍔熺巼绾�</param> + /// <returns></returns> + public static CurveCoordinate CalcCoordinate(List<CurvePoint> QH, List<CurvePoint> QE, List<CurvePoint> QP) + { + if (QH == null) + return null; + double maxQ = 0.0; + double minQ = 1000.0; + double maxH = 0.0; + double minH = 1000.0; + double maxE = 0.0; + double minE = 1000.0; + double maxP = 0.0; + double minP = 1000.0; + + if (QE == null && QP == null) + { + minQ = QH.Min(x => x.X); + maxQ = QH.Max(x => x.X); + if (minQ > maxQ) + { + return null; + } + minH = QH.Min(x => x.Y); + maxH = QH.Max(x => x.Y); + if (minH > maxH) + { + return null; + } + } + else + { + CalcMinMaxValue(QH, QE, QP, ref maxQ, ref minQ, ref maxH, ref minH, ref maxE, ref minE, ref maxP, ref minP); + } + + return CalcCoordinate(minQ, maxQ, minH, maxH, minE, maxE, minP, maxP); + } + + /// <summary> + /// 璁$畻鏈�澶ф渶灏忓�� + /// </summary> + /// <param name="QH">娴侀噺鎵▼绾�</param> + /// <param name="QE">娴侀噺鏁堢巼绾�</param> + /// <param name="QP">娴侀噺鍔熺巼绾�</param> + /// <param name="maxQ">鏈�澶ф祦閲�</param> + /// <param name="minQ">鏈�灏忔祦閲�</param> + /// <param name="maxH">鏈�澶ф壃绋�</param> + /// <param name="minH">鏈�灏忔壃绋�</param> + /// <param name="maxE">鏈�澶ф晥鐜�</param> + /// <param name="minE">鏈�灏忔晥鐜�</param> + /// <param name="maxP">鏈�澶у姛鐜�</param> + /// <param name="minP">鏈�灏忓姛鐜�</param> + /// <returns></returns> + public static bool CalcMinMaxValue(List<CurvePoint> QH, List<CurvePoint> QE, List<CurvePoint> QP, ref double maxQ, ref double minQ, ref double maxH, ref double minH, ref double maxE, ref double minE, ref double maxP, ref double minP) + { + maxQ = 0.0; + minQ = 1000.0; + maxH = 0.0; + minH = 1000.0; + maxE = 0.0; + minE = 1000.0; + maxP = 0.0; + minP = 1000.0; + if (QH == null) + { + return false; + } + minQ = QH.Min(x => x.X); + maxQ = QH.Max(x => x.X); + if (minQ > maxQ) + { + return false; + } + minH = QH.Min(x => x.Y); + maxH = QH.Max(x => x.Y); + if (QE != null && QE.Count > 0) + { + minE = QE.Min(x => x.Y); + maxE = QE.Max(x => x.Y); + } + if (QP != null && QP.Count > 0) + { + minP = QP.Min(x => x.Y); + maxP = QP.Max(x => x.Y); + } + return true; + } + + /// <summary> + /// 璁$畻鍧愭爣 + /// </summary> + /// <param name="minQ">鏈�灏忔祦閲�</param> + /// <param name="maxQ">鏈�澶ф祦閲�</param> + /// <param name="minH">鏈�灏忔壃绋�</param> + /// <param name="maxH">鏈�澶ф壃绋�</param> + /// <param name="minE">鏈�灏忔晥鐜�</param> + /// <param name="maxE">鏈�澶ф晥鐜�</param> + /// <param name="minP">鏈�灏忓姛鐜�</param> + /// <param name="maxP">鏈�澶у姛鐜�</param> + /// <returns></returns> + public static CurveCoordinate CalcCoordinate(double minQ, double maxQ, double minH, double maxH, double minE, double maxE, double minP, double maxP) + { + if (minQ > maxQ - 0.01) + return null; + + if (minH > maxH - 0.01) + return null; + + var validGridNumH = 6; + var coordinateParas = new CurveCoordinate(); + coordinateParas.GridNumberX = 10; + coordinateParas.GridNumberY = 18; + CalcCoordinateQ(minQ, maxQ, ref coordinateParas, coordinateParas.GridNumberX); + CalcCoordinateH(minH, maxH, validGridNumH, ref coordinateParas, out double disMinH, out double disMaxH); + + if (maxP > minP + 0.01) + CalcCoordinateP(minP, maxP, disMaxH, 0, ref coordinateParas); + + if (maxE > minE + 0.01) + CalcCoordinateE(minE, maxE, ref coordinateParas); + + return coordinateParas; + } + + #endregion + + #region 璁$畻瀵瑰簲绾垮潗鏍� + + /// <summary> + /// 璁$畻娴侀噺鍧愭爣 + /// </summary> + /// <param name="minQ">鏈�灏忔祦閲�</param> + /// <param name="maxQ">鏈�澶ф祦閲�</param> + /// <param name="coordinateParas">鍧愭爣Model</param> + /// <param name="validGridNum">鏈夋晥鍒诲害鐐�</param> + /// <param name="default_num">鏀惧ぇ绯绘暟</param> + public static void CalcCoordinateQ(double minQ, double maxQ, ref CurveCoordinate coordinateParas, int validGridNum = 10, double default_num = 1.0) + { + var coordSpaceQ = GetOptimalSpaceMin(minQ / default_num, maxQ / default_num, validGridNum, out double disMinQ, out double disMaxQ) * default_num; + coordSpaceQ = Math.Max(0.5, coordSpaceQ / default_num) * default_num; + if (coordSpaceQ == 8.0) + coordSpaceQ = 10.0; + + disMinQ *= default_num; + //disMaxQ *= default_num; + var gridNumberX = 0; + + double min_q = disMinQ; + while (min_q < maxQ) + { + gridNumberX++; + min_q = disMinQ + gridNumberX * coordSpaceQ; + } + + if (gridNumberX <= 5) + { + coordSpaceQ *= 0.5; + gridNumberX *= 2; + } + + coordinateParas.CoordSpaceQ = coordSpaceQ; + coordinateParas.CoordMinQ = disMinQ; + coordinateParas.GridNumberX = gridNumberX; + } + + /// <summary> + /// 璁$畻鎵▼鍧愭爣 鍚繃婊� (Eventech: CalcCoordinateH2) + /// </summary> + /// <param name="minH">鏈�灏忔壃绋�</param> + /// <param name="maxH">鏈�澶ф壃绋�</param> + /// <param name="validGridNumH">鏈夋晥鎵▼鍒诲害鏁�</param> + /// <param name="coordinateParas">鍧愭爣Model</param> + /// <param name="disMinH">鏈�灏忔樉绀烘壃绋�</param> + /// <param name="disMaxH">鏈�澶ф樉绀烘壃绋�</param> + public static void CalcCoordinateH_Filter(double minH, double maxH, int validGridNumH, ref CurveCoordinate coordinateParas, out double disMinH, out double disMaxH) + { + if (maxH < 1.0) + { + disMinH = 0.0; + disMaxH = 1.0; + coordinateParas.ResetCoordH(0.1, disMinH, disMaxH); + } + else if (maxH < 2.0) + { + disMinH = 0.0; + disMaxH = 2.0; + coordinateParas.ResetCoordH(0.2, disMinH, disMaxH); + } + else if (maxH < 5.0) + { + disMinH = 0.0; + disMaxH = 5.0; + coordinateParas.ResetCoordH(0.5, disMinH, disMaxH); + } + else if (maxH < 10.0) + { + disMinH = 0.0; + disMaxH = 10.0; + coordinateParas.ResetCoordH(1.0, disMinH, disMaxH); + } + else if (maxH < 12.0) + { + coordinateParas.CoordSpaceH = 1.0; + disMinH = 0.0; + disMaxH = 12.0; + coordinateParas.ResetCoordH(1.0, disMinH, disMaxH); + } + else if (maxH < 15.0) + { + coordinateParas.CoordSpaceH = 2.0; + disMinH = 0.0; + disMaxH = 16.0; + coordinateParas.ResetCoordH(2.0, disMinH, disMaxH); + } + else if (maxH < 20.0) + { + coordinateParas.CoordSpaceH = 2.0; + disMinH = 0.0; + disMaxH = 20.0; + coordinateParas.ResetCoordH(2.0, disMinH, disMaxH); + } + else + { + CalcCoordinateH(minH, maxH, validGridNumH, ref coordinateParas, out disMinH, out disMaxH); + } + } + + /// <summary> + /// 璁$畻鎵▼鍧愭爣 + /// </summary> + /// <param name="minH">鏈�灏忔壃绋�</param> + /// <param name="maxH">鏈�澶ф壃绋�</param> + /// <param name="validGridNumH">鏈夋晥鎵▼鍒诲害鏁�</param> + /// <param name="coordinateParas">鍧愭爣Model</param> + /// <param name="disMinH">鏈�灏忔樉绀烘壃绋�</param> + /// <param name="disMaxH">鏈�澶ф樉绀烘壃绋�</param> + public static void CalcCoordinateH(double minH, double maxH, int validGridNumH, ref CurveCoordinate coordinateParas, out double disMinH, out double disMaxH) + { + var coordSpaceH = GetOptimalSpaceMax(minH, maxH, validGridNumH, out disMinH, out disMaxH); + int endLineNoH = coordinateParas.GridNumberY; + int stratLineNoH = endLineNoH; + + double max_h = disMaxH;//鍒ゆ柇鏉′欢 + while (max_h > minH * 0.98) + { + max_h -= coordSpaceH; + if (max_h < 0.0) + break; + stratLineNoH--; + } + + coordinateParas.CoordSpaceH = coordSpaceH; + coordinateParas.EndLineNoH = endLineNoH; + coordinateParas.StartLineNoH = stratLineNoH; + coordinateParas.CoordMinH = disMaxH - (double)endLineNoH * coordSpaceH; + } + + /// <summary> + /// 璁$畻鍔熺巼鍧愭爣 + /// </summary> + /// <param name="minP">鏈�灏忓姛鐜�</param> + /// <param name="maxP">鏈�澶у姛鐜�</param> + /// <param name="disMaxH">鏈�澶ф樉绀烘壃绋�</param> + /// <param name="downGridNum">鏈�浣庣偣鍒诲害</param> + /// <param name="coordinateParas">鍧愭爣Model</param> + public static void CalcCoordinateP(double minP, double maxP, double disMaxH, int downGridNum, ref CurveCoordinate coordinateParas) + { + int default_num = 5; + int spaceNum = coordinateParas.StartLineNoH - default_num - downGridNum; + if (spaceNum < 3) + spaceNum = 3; + + var coordSpaceP = GetOptimalSpaceMax(minP, maxP, spaceNum, out double disMinP, out double disMaxP); + int endLineNoP = coordinateParas.StartLineNoH - default_num; + int stratLineNoP = endLineNoP; + + double max_p = disMaxP; + while (max_p > minP * 0.98) + { + max_p -= coordSpaceP; + if (max_p < 0.0) + break; + stratLineNoP--; + } + + coordinateParas.CoordSpaceP = coordSpaceP; + coordinateParas.EndLineNoP = endLineNoP; + coordinateParas.StartLineNoP = stratLineNoP; + + //濡傛灉寮�濮嬪埢搴︿綆浜庢渶浣庣偣鍒诲害 閮藉線涓婂姞宸�� + if (coordinateParas.StartLineNoP < downGridNum) + { + int diff_num = downGridNum - coordinateParas.StartLineNoP; + + coordinateParas.EndLineNoP += diff_num; + coordinateParas.StartLineNoP += diff_num; + } + + coordinateParas.CoordMinH = GetByPlacesLength(disMaxH - (double)coordinateParas.EndLineNoH * coordinateParas.CoordSpaceH, 3); + coordinateParas.CoordMinP = GetByPlacesLength(disMaxP - (double)coordinateParas.EndLineNoP * coordinateParas.CoordSpaceP, 3); + } + + /// <summary> + /// 璁$畻鏁堢巼鍧愭爣 + /// </summary> + /// <param name="minE">鏈�灏忔晥鐜�</param> + /// <param name="maxE">鏈�澶ф晥鐜�</param> + /// <param name="coordinateParas">鍧愭爣Model</param> + public static void CalcCoordinateE(double minE, double maxE, ref CurveCoordinate coordinateParas) + { + int startLineNoE = coordinateParas.StartLineNoH - 6; + if (maxE <= 40.0) + { + coordinateParas.StartLineNoE = startLineNoE; + coordinateParas.EndLineNoE = coordinateParas.StartLineNoE + 6; + coordinateParas.CoordSpaceE = 5.0; + } + else if (maxE <= 50.0) + { + coordinateParas.StartLineNoE = startLineNoE - 5; + coordinateParas.EndLineNoE = coordinateParas.StartLineNoE + 10; + coordinateParas.CoordSpaceE = 5.0; + } + else if (maxE <= 60) + { + coordinateParas.StartLineNoE = startLineNoE; + coordinateParas.EndLineNoE = coordinateParas.StartLineNoE + 6; + coordinateParas.CoordSpaceE = 10.0; + } + else + { + coordinateParas.StartLineNoE = startLineNoE; + coordinateParas.EndLineNoE = coordinateParas.StartLineNoE + 5; + coordinateParas.CoordSpaceE = 20.0; + } + coordinateParas.CoordMinE = (double)(-coordinateParas.StartLineNoE) * coordinateParas.CoordSpaceE; + } + + #endregion + + #region Space 闂撮殧 + /// <summary> + /// 鑾峰彇鏈�灏忕殑闂撮殧 + /// </summary> + /// <param name="minValue">鏈�灏忓��</param> + /// <param name="maxValue">鏈�澶у��</param> + /// <param name="spaceNum">闂撮殧鏁伴噺</param> + /// <param name="minDisplay">鏈�灏忔樉绀哄弬鏁�</param> + /// <param name="maxDisplay">鏈�澶ф樉绀哄弬鏁�</param> + /// <returns></returns> + public static double GetOptimalSpaceMin(double minValue, double maxValue, int spaceNum, out double minDisplay, out double maxDisplay) + { + minDisplay = minValue; + maxDisplay = maxValue; + double num = maxValue - minValue; + if (num < 0.0 || spaceNum < 1) + { + return (maxValue - minValue) / 10.0; + } + + double optimalSpace = GetOptimalSpace((maxValue - minValue) / (double)spaceNum); + if (optimalSpace < 2.0) + { + minDisplay = Math.Floor(minValue / optimalSpace) * optimalSpace; + maxDisplay = minDisplay + (double)spaceNum * optimalSpace; + } + else + { + minDisplay = Math.Floor(minValue / optimalSpace) * optimalSpace; + maxDisplay = minDisplay + (double)spaceNum * optimalSpace; + } + + return optimalSpace; + } + + /// <summary> + /// 鑾峰彇鏈�澶х殑闂撮殧 + /// </summary> + /// <param name="minValue">鏈�灏忓��</param> + /// <param name="maxValue">鏈�澶у��</param> + /// <param name="spaceNum">闂撮殧鏁伴噺</param> + /// <param name="minDisplay">鏈�灏忔樉绀哄弬鏁�</param> + /// <param name="maxDisplay">鏈�澶ф樉绀哄弬鏁�</param> + /// <returns></returns> + public static double GetOptimalSpaceMax(double minValue, double maxValue, int spaceNum, out double minDisplay, out double maxDisplay) + { + minDisplay = minValue; + maxDisplay = maxValue; + double num = maxValue - minValue; + + if (maxValue > 20) + { + if (num < 0.0 || spaceNum < 1) + { + return (maxValue - minValue) / 5.0; + } + } + else + { + if (num < 0.0 || spaceNum < 1) + { + return (maxValue - minValue) / 10.0; + } + } + + double optimalSpace = GetOptimalSpace((maxValue - minValue) / (double)spaceNum, true); + maxDisplay = Math.Ceiling(maxValue / optimalSpace) * optimalSpace; + minDisplay = maxDisplay - (double)spaceNum * optimalSpace; + + if (minDisplay > minValue) + { + var diff = minDisplay - minValue; + if (diff < optimalSpace) + { + minDisplay -= optimalSpace; + } + + } + + return optimalSpace; + } + + /// <summary> + /// 鑾峰彇鏈�浣抽棿闅� (绮剧粏鍙栨暣) + /// </summary> + /// <param name="refSpace"> 闂撮殧</param> + /// <returns></returns> + public static double GetOptimalSpace(double refSpace, bool IsAccurate = false) + { + if (refSpace < 1E-06) + { + return 1.0; + } + + if (refSpace < 0.01) + { + double refSpace2 = refSpace * 100.0; + return GetOptimalSpace(refSpace2) / 100.0; + } + + if (refSpace < 0.1) + { + double refSpace3 = refSpace * 10.0; + return GetOptimalSpace(refSpace3) / 10.0; + } + + if (IsAccurate) + { + if (refSpace < 11.0) + { + if (refSpace < 1.35) + { + return 1.0; + } + + if (refSpace < 2.2) + { + return 2.0; + } + + if (refSpace < 5.5) + { + return 5.0; + } + + if (refSpace < 8.5) + { + return 8.0; + } + + return 10.0; + } + } + + if (refSpace < 1.0) + { + if (refSpace < 0.15) + { + return 0.1; + } + + if (refSpace < 0.22) + { + return 0.2; + } + + if (refSpace < 0.6) + { + return 0.5; + } + + return 1.0; + } + + if (refSpace < 1.2) + { + return 1.0; + } + + if (refSpace < 3.0) + { + if (refSpace < 1.2) + { + return 1.0; + } + + if (refSpace < 2.3) + { + return 2.0; + } + + return 3.0; + } + + if (refSpace < 11.0) + { + if (refSpace < 1.35) + { + return 1.0; + } + + if (refSpace < 2.2) + { + return 2.0; + } + + if (refSpace < 5.5) + { + return 5.0; + } + + if (refSpace < 8.5) + { + return 8.0; + } + + return 10.0; + } + + if (refSpace < 16.0) + { + return 15.0; + } + + if (refSpace < 22.0) + { + return 20.0; + } + + if (refSpace < 35.0) + { + return 25.0; + } + + if (refSpace < 41.0) + { + return 40.0; + } + + if (refSpace < 51.0) + { + return 50.0; + } + + if (refSpace < 61.0) + { + return 60.0; + } + + if (refSpace < 71.0) + { + return 70.0; + } + + if (refSpace < 78.0) + { + return 75.0; + } + + if (refSpace < 150.0) + { + return 100.0; + } + + if (refSpace < 230.0) + { + return 200.0; + } + + if (refSpace < 270.0) + { + return 250.0; + } + + if (refSpace < 1500.0) + { + int num = (int)(refSpace / 100.0); + return num * 100; + } + + int num2 = (int)(refSpace / 1000.0); + return num2 * 1000; + } + + #endregion + + #region 鏁板瓧杈呭姪鏂规硶 + /// <summary> + /// 鎸夋寚瀹氶暱搴﹁幏鍙� + /// </summary> + public static double GetByPlacesLength(double value, int length) + { + int decimalPlacesLength = GetDecimalPlacesLength(value); + if (decimalPlacesLength > length) + { + return Math.Round(value, length); + } + return value; + } + + /// <summary> + /// 鑾峰彇灏忔暟鐐归暱搴� + /// </summary> + private static int GetDecimalPlacesLength(double value) + { + string text = value.ToString(); + int num = text.IndexOf('.'); + if (num >= 0) + { + return text.Length - num - 1; + } + return 0; + } + #endregion + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurve.cs b/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurve.cs new file mode 100644 index 0000000..0bbe48c --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurve.cs @@ -0,0 +1,179 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 瑁呯疆鏇茬嚎 + /// </summary> + public class DeviceCurve : ICloneable + { + /// <summary> + /// + /// </summary> + public DeviceCurve() { } + + /// <summary> + /// + /// </summary> + public DeviceCurve(DeviceCurve rhs) + { + this.SourceType = rhs.SourceType; + this.OriginPoints = rhs.OriginPoints; + this.CurveInfo = rhs.CurveInfo; + this.CurveExpress = rhs.CurveExpress; + } + + /// <summary> + /// + /// </summary> + public DeviceCurve(double zeroPointH, IStation.Curve.CurvePoint endPoint, int fitPointNum = 12, eFitType fitType = eFitType.CubicCurve) + { + SetParabolaPoints(zeroPointH, endPoint); + ResetCurveInfo(fitPointNum, fitType); + } + + + + /// <summary> + /// 鏉ユ簮绫诲瀷 + /// </summary> + public eDeviceSourceType SourceType { get; set; } + + /// <summary> + /// 鎵嬪姩杈撳叆鏃舵槸杈撳叆鐨勭偣,浜屾鏇茬嚎鏄袱涓畾涔夌偣 + /// </summary> + public List<CurvePoint> OriginPoints { get; set; } + + /// <summary> + /// 鏇茬嚎涓婄殑鐐规湁鍙兘鏍规嵁鍧愭爣鏈�灏忓��,杩涜浜嗗垏鍓� + /// </summary> + public List<CurvePoint> CurveInfo { get; set; } + + /// <summary> + /// 鏇茬嚎鏂圭▼ + /// </summary> + public CurveExpress CurveExpress { get; set; } + + /// <summary> + /// 鑾峰彇0娴侀噺鐐规壃绋� + /// </summary> + public double GetZeroPointH() + { + if (this.OriginPoints == null || this.OriginPoints.Count < 1) + { + return default; + } + return this.OriginPoints[0].Y; + } + + /// <summary> + /// 璁剧疆鎶涚墿绾跨偣 + /// </summary> + public void SetParabolaPoints(double zeroPointH, IStation.Curve.CurvePoint endPoint) + { + this.SourceType = eDeviceSourceType.Twice; + this.OriginPoints = new List<IStation.Curve.CurvePoint>(); + this.OriginPoints.Add(new IStation.Curve.CurvePoint(0, zeroPointH)); + this.OriginPoints.Add(endPoint); + } + + /// <summary> + /// 閲嶇疆鏇茬嚎淇℃伅 + /// </summary> + public void ResetCurveInfo(int fitPointNum, eFitType fitType = eFitType.CubicCurve) + { + if (this.SourceType != eDeviceSourceType.Twice) + return; + if (this.OriginPoints == null || this.OriginPoints.Count != 2) + return; + + double equipCurveZeroH = this.OriginPoints[0].Y; + var endPt = this.OriginPoints[1]; + var points = new List<IStation.Curve.CurvePoint>(); + double k = (endPt.Y - equipCurveZeroH) / (endPt.X * endPt.X); + double minQ = 0; + double maxQ = endPt.X; + double space = (maxQ - minQ) / (fitPointNum - 1);//11涓偣 + for (int i = 0; i < fitPointNum; i++) + { + double x = space * i + minQ; + double y = k * x * x + equipCurveZeroH; + points.Add(new IStation.Curve.CurvePoint(x, y)); + } + + this.CurveInfo = points; + this.CurveExpress = IStation.Curve.FitHelper.BuildCurveExpress(points, fitType); + } + + /// <summary> + /// 鑾峰彇鎶涚墿绾跨郴鏁� + /// </summary> + public double GetParabolaCoeff() + { + if (this.OriginPoints == null || this.OriginPoints.Count != 2) + return default; + + double equipCurveZeroH = OriginPoints[0].Y; + var endPt = OriginPoints[1]; + List<IStation.Curve.CurvePoint> points = new List<IStation.Curve.CurvePoint>(); + return (endPt.Y - equipCurveZeroH) / (endPt.X * endPt.X); + } + + /// <summary> + /// 閫氳繃 鏈�灏忓�糦閲嶇疆鏇茬嚎淇℃伅 + /// </summary> + public void ResetCurveInfoByMinY(int fitPointNum, double minY, eFitType fitType = eFitType.CubicCurve) + { + if (this.SourceType != eDeviceSourceType.Twice) + return; + if (this.OriginPoints == null || this.OriginPoints.Count != 2) + return; + if (minY < 0.01) + { + ResetCurveInfo(fitPointNum, fitType); + return; + } + + + double equipCurveZeroH = this.OriginPoints[0].Y; + var endPt = this.OriginPoints[1]; + var points = new List<IStation.Curve.CurvePoint>(); + double k = (endPt.Y - equipCurveZeroH) / (endPt.X * endPt.X); + double minQ = 0; + if (minY > equipCurveZeroH) + { + minQ = Math.Sqrt((minY - equipCurveZeroH) / k); + } + double maxQ = endPt.X; + double space = (maxQ - minQ) / (fitPointNum - 1); + for (int i = 0; i < fitPointNum; i++) + { + double x = space * i + minQ; + double y = k * x * x + equipCurveZeroH; + points.Add(new IStation.Curve.CurvePoint(x, y)); + } + + this.CurveInfo = points; + } + + + #region Clone + + /// <summary> + /// + /// </summary> + public DeviceCurve Clone() + { + return new DeviceCurve(this); + } + + /// <summary> + /// + /// </summary> + object ICloneable.Clone() + { + return Clone(); + } + + + #endregion + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurveHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurveHelper.cs new file mode 100644 index 0000000..9b87038 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurveHelper.cs @@ -0,0 +1,82 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 瑁呯疆鏇茬嚎杈呭姪绫� + /// </summary> + public class DeviceCurveHelper + { + + /// <summary> + /// + /// </summary> + /// <param name="CurveExpressQH"></param> + /// <param name="designPoint"></param> + /// <param name="deviceCurveZeroH"></param> + /// <param name="isExendCurve">褰揹esignPoint瓒呰繃鏇茬嚎鏃�, 鏄惁寤堕暱瑁呯疆绾垮埌designPoint浣嶇疆</param> + /// <param name="fitPointNum"></param> + /// <param name="sectPoint"></param> + /// <returns></returns> + public static DeviceCurve CalcuDeviceCurve(CurveExpress CurveExpressQH, CurvePoint designPoint, double deviceCurveZeroH, bool isExendCurve, int fitPointNum, out CurvePoint sectPoint) + { + sectPoint = GetSectPoint(CurveExpressQH, designPoint, deviceCurveZeroH); + if (sectPoint == null) + { + return null; + } + if (isExendCurve) + { + IStation.Curve.CurvePoint endPt; + if (sectPoint.X > designPoint.X) + endPt = sectPoint; + else + endPt = designPoint; + + // + return new IStation.Curve.DeviceCurve(deviceCurveZeroH, endPt, fitPointNum, CurveExpressQH.FitType); + } + else + { + return new IStation.Curve.DeviceCurve(deviceCurveZeroH, sectPoint, fitPointNum, CurveExpressQH.FitType); + } + } + + /// <summary> + /// + /// </summary> + public static CurvePoint GetSectPoint(CurveExpress CurveExpressQH, CurvePoint designPoint, double equipCurveZeroH) + {//鏈変竴绉嶆儏鍐�: 鐢ㄥ寘缁滄硶鏈変氦鐐�(鍦ㄦ渶鏈熬),浣嗙敤瑁呯疆鏇茬嚎缁樺埗鏃�,涓庤缃洸绾挎病鏈変氦鐐�,鍥犱负浜ょ偣宸茶秴杩囨洸绾挎渶澶у�� + double ratioExtend = 1.15;//CurveExpressQH閫傚綋寤堕暱涓�鐐� + var sectPoint = ParabolaCurveHelper.GetSectPoint(CurveExpressQH, designPoint, equipCurveZeroH, ratioExtend); + if (sectPoint == null || sectPoint.IsZeroPoint()) + { + return null; + } + if (sectPoint.X > CurveExpressQH.Max * ratioExtend) + { + return null; + } + + return sectPoint; + } + + /// <summary> + /// + /// </summary> + public static CurvePoint GetSectPoint(CurveExpress CurveExpressQH, CurvePoint DesignPoint, double equipCurveZeroH, double ratioExtend) + {//鏈変竴绉嶆儏鍐�: 鐢ㄥ寘缁滄硶鏈変氦鐐�(鍦ㄦ渶鏈熬),浣嗙敤瑁呯疆鏇茬嚎缁樺埗鏃�,涓庤缃洸绾挎病鏈変氦鐐�,鍥犱负浜ょ偣宸茶秴杩囨洸绾挎渶澶у�� + + var sectPoint = ParabolaCurveHelper.GetSectPoint(CurveExpressQH, DesignPoint, equipCurveZeroH, ratioExtend); + if (sectPoint == null || sectPoint.IsZeroPoint()) + { + return null; + } + if (sectPoint.X > CurveExpressQH.Max * ratioExtend) + { + return null; + } + + return sectPoint; + } + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Device/eDeviceSourceType.cs b/Schedule/IStation.Algorithm/Model/Curve/Device/eDeviceSourceType.cs new file mode 100644 index 0000000..ae54b88 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Device/eDeviceSourceType.cs @@ -0,0 +1,18 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 瑁呯疆鏇茬嚎鏉ユ簮 + /// </summary> + public enum eDeviceSourceType + { + /// <summary> + /// 浜屾鏇茬嚎 + /// </summary> + Twice = 0, + + /// <summary> + /// 鎵嬪姩杈撳叆 + /// </summary> + Hand = 1 + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessConstant.cs b/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessConstant.cs new file mode 100644 index 0000000..aaf4aba --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessConstant.cs @@ -0,0 +1,105 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鏃犻噺绾插父閲� + /// </summary> + public class DimensionlessConstant + { + public static double[] + h35 = { 106.48, 107.45, 108.14, 108.45, 108.4, 108.12, 107.43, 106.22, 104.69, 102.55, 100, 96.31, 91.62, 85.72, 82.32 }, + q35 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p35 = { 29.35, 36.95, 44.29, 51.63, 59.05, 66.29, 73.53, 80.3, 87.16, 93.57, 100, 106.03, 111.56, 116.53, 118.91 }, + ef35 = { 0, 32.016, 51.9786, 66.5992, 77.5766, 85.9643, 92.2565, 96.3363, 98.7294, 99.7017, 100, 99.2818, 97.2984, 93.5774, 91.1162 }, + npsh35y = { 8.13, 7.78, 7.75 }, + npsh35x = { 3.02, 5.56, 7.002 }; + + public static double[] + q50 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + h50 = { 107.74, 108.68, 109.21, 109.35, 109.31, 108.93, 108.16, 107.01, 105.37, 103.07, 100, 95.7, 90.43, 84.41, 81.03 }, + p50 = { 31, 38.73, 46.27, 53.73, 60.9, 68.04, 74.89, 81.73, 87.93, 93.91, 100, 105.78, 111.04, 115.82, 118.09 }, + ef50 = { 0, 31.171, 50.2947, 64.4423, 75.5681, 84.4261, 91.0346, 95.6539, 98.5048, 99.8446, 100, 99.1393, 96.7859, 92.732, 90.1212 }, + npsh50x = { 8.32, 13.9, 16.68 }, + npsh50y = { 8.5, 7.6, 5.6 }; + + public static double[] + h70 = { 109.98, 110.47, 110.88, 111.04, 111, 110.4, 109.5, 107.98, 106.03, 103.38, 100, 95.35, 89.62, 83.27, 78.73 }, + q70 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p70 = { 32.95, 40.6, 48.06, 55.35, 62.2, 68.96, 75.62, 82.1, 88.09, 93.94, 100, 105.34, 110.45, 115.04, 117.17 }, + ef70 = { 0, 29.3813, 48.6052, 62.9238, 74.3451, 83.2073, 89.925, 94.9372, 98.3296, 99.7797, 100, 99.0413, 96.2992, 91.8033, 89.0156 }, + npsh70x = { 1.6, 3, 3.9 }, + npsh70y = { 6.6, 6.7, 6.0 }; + + public static double[] + h85 = { 112, 112.51, 112.79, 112.75, 112.36, 111.62, 110.58, 108.95, 106.76, 103.82, 100, 95.02, 89.19, 82.22, 78.27 }, + q85 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p85 = { 35.35, 42.54, 49.4, 56.33, 63.13, 69.85, 76.41, 82.59, 88.61, 94.38, 100, 105.15, 109.83, 114.25, 116.26 }, + ef85 = { 0, 27.9416, 46.721, 61.37, 72.91, 81.9, 88.82, 94.1319, 97.9261, 99.6572, 100, 98.8662, 95.8912, 91.0496, 88.0017 }, + npsh85x = { 30.6, 47.2, 55.6 }, + npsh85y = { 6.6, 5.9, 5.2 }; + + public static double[] + h100 = { 114.5, 114.41, 114.26, 114.02, 113.54, 112.77, 111.47, 109.67, 107.37, 103.87, 100, 94.55, 87.95, 80, 75.78 }, + q100 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p100 = { 37.83, 44.66, 51.51, 58.26, 64.74, 71.18, 77.41, 83.4, 89.02, 94.71, 100, 104.96, 109.34, 113.25, 115.1 }, + ef100 = { 0, 26.4816, 45.1972, 60.00, 71.7881, 80.8615, 87.9351, 93.497, 97.617, 99.5495, 100, 98.6925, 95.3254, 90.2162, 87.1612 }, + npsh100x = { 27.5, 45, 67.5 }, + npsh100y = { 8.5, 8, 7.5 }; + + public static double[] + h130 = { 116.7, 116.49, 116.13, 115.64, 114.92, 113.79, 112.38, 110.51, 107.8, 104.2, 100, 93.98, 86.55, 78.18, 73.52 }, + q130 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p130 = { 40.45, 47.29, 53.97, 60.5, 67, 73.14, 78.98, 84.54, 89.91, 94.75, 100, 104.52, 108.62, 111.91, 113.49 }, + ef130 = { 0, 23.9926, 42.4301, 57.3886, 69.6333, 79.22, 86.7537, 92.6697, 97.0876, 99.4481, 100, 98.6268, 94.9244, 89.3389, 85.8424 }, + npsh130x = { 22.5, 40, 50 }, + npsh130y = { 8, 7.5, 7.02 }; + + public static double[] + h150 = { 119.43, 118.96, 118.5, 117.82, 116.75, 115.37, 113.64, 111.3, 108.29, 104.61, 100, 93.73, 85.72, 76.43, 71.17 }, + q150 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p150 = { 44.65, 51.28, 57.8, 63.98, 70.12, 76.04, 81.7, 86.72, 91.46, 95.94, 100, 103.66, 106.94, 109.48, 110.71 }, + ef150 = { 0, 21.2608, 39.5384, 54.7678, 67.4627, 77.7696, 85.8892, 92.3006, 96.9549, 99.3641, 100, 98.5555, 94.4991, 87.961, 84.0969 }, + npsh150x = { 79.2, 73, 62.4 }, + npsh150y = { 6.37, 6.5, 6.79 }; + + public static double[] + h180 = { 124.19, 123.69, 122.8, 121.6, 120.05, 118.14, 115.76, 113.02, 109.58, 105.3, 100, 92.81, 84.49, 74.32, 68.43 }, + q180 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p180 = { 48.77, 54.89, 60.84, 66.52, 72.5, 78.17, 83.44, 88.16, 92.64, 96.74, 100, 102.56, 104.96, 106.9, 107.72 }, + ef180 = { 0, 19.3777, 37.2247, 52.6365, 65.4778, 76.2215, 84.9525, 91.7184, 96.6465, 99.2273, 100, 98.391, 93.9028, 86.7286, 82.3607 }, + npsh180x = { 18, 25, 30.6 }, + npsh180y = { 5.5, 6, 6.6 }; + + public static double[] + h200 = { 130.34, 129.52, 128.5, 127.08, 125.32, 123.04, 119.98, 116.18, 111.88, 106.52, 100, 91.84, 82.68, 71.57, 65.09 }, + q200 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p200 = { 52.27, 58.05, 63.79, 69.42, 74.91, 80.2, 85.25, 89.91, 93.89, 97.4, 100, 101.92, 103.39, 104.5, 104.97 }, + ef200 = { 0, 18.2632, 35.3759, 50.7, 63.6248, 75, 84.1399, 91.2574, 96.4082, 99.0917, 100, 98.2559, 93.4036, 86.7286, 82.3607 }, + npsh200x = { 50.06, 76.64, 92 }, + npsh200y = { 5.65, 6.29, 7.16 }; + + public static double[] + h281 = { 152.5, 150.47, 148.14, 145.17, 141.39, 136.75, 131.22, 124.79, 117.49, 109.27, 100, 81.43, 62.75 }, + q281 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 }, + p281 = { 90.5, 90.88, 91.4, 92.2, 93.32, 94.52, 95.58, 96.62, 97.86, 99.13, 100, 99.97, 99.95 }, + ef281 = { 0, 16.6501, 32.5298, 47.0981, 60.0777, 71.375, 80.9615, 88.7511, 94.8283, 98.8591, 100, 97.5118, 91.1817 }, + npsh281x = { 50.06, 76.64, 92 }, + npsh281y = { 5.65, 6.29, 7.16 }; + + public static double[] + h401 = { 197.5, 189.21, 180.68, 171.67, 162.17, 152.5, 142.93, 133.24, 123.1, 112.17, 100, 85.93, 69.24 }, + q401 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 }, + p401 = { 189, 171.97, 155.93, 141.55, 129.84, 121.5, 115.98, 111.86, 108.15, 104.31, 100, 94.96, 89.39 }, + ef401 = { 0, 11.8388, 23.8006, 36.2394, 48.6959, 60.5, 71.1767, 81.0133, 90.331, 97.5211, 100, 96.6122, 86.3745 }, + npsh401x = { 50.06, 76.64, 92 }, + npsh401y = { 5.65, 6.29, 7.16 }; + + public static double[] + h642 = { 290, 272, 252, 232, 212, 192.91, 174.04, 155.29, 136.77, 118.4, 100, 81.43, 62.75 }, + q642 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 }, + p642 = { 219.6, 219.6, 219.6, 219.6, 196.61, 177.5, 161.78, 147.3, 132.44, 116.55, 100, 83.25, 66.42 }, + ef642 = { 0, 10.5237, 21.1346, 31.9149, 42.8347, 53.75, 64.6001, 75.7284, 87.3088, 96.8113, 100, 93.9925, 76.3024 }, + npsh642x = { 50.06, 76.64, 92 }, + npsh642y = { 5.65, 6.29, 7.16 }; + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessCurvesHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessCurvesHelper.cs new file mode 100644 index 0000000..1d7cbaa --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessCurvesHelper.cs @@ -0,0 +1,707 @@ +锘縩amespace IStation.Curve +{ + public class DimensionlessCurvesHelper + { + #region 鏃犻噺绾插弬鏁� + static double[] h35 ={106.48,107.45,108.14,108.45,108.4,108.12,107.43, + 106.22,104.69,102.55,100,96.31,91.62,85.72,82.32}, + q35 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p35 ={29.35,36.95,44.29,51.63,59.05,66.29,73.53,80.3,87.16, + 93.57,100,106.03,111.56,116.53,118.91}, + ef35 ={0,32.016,51.9786,66.5992,77.5766,85.9643,92.2565,96.3363,98.7294, + 99.7017,100,99.2818,97.2984,93.5774,91.1162}, + npsh35y = { 8.13, 7.78, 7.75 }, + npsh35x = { 3.02, 5.56, 7.002 }; + static double[] q50 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + h50 ={107.74,108.68,109.21,109.35,109.31,108.93,108.16,107.01,105.37, + 103.07,100,95.7,90.43,84.41,81.03}, + p50 ={31,38.73,46.27,53.73,60.9,68.04,74.89,81.73,87.93, + 93.91,100,105.78,111.04,115.82,118.09}, + ef50 ={0,31.171,50.2947,64.4423,75.5681,84.4261,91.0346,95.6539,98.5048, + 99.8446,100,99.1393,96.7859,92.732,90.1212}, + npsh50x = { 8.32, 13.9, 16.68 }, + npsh50y = { 8.5, 7.6, 5.6 }; + static double[] h70 ={109.98,110.47,110.88,111.04,111,110.4,109.5,107.98, + 106.03,103.38,100,95.35,89.62,83.27,78.73}, + q70 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p70 ={32.95,40.6,48.06,55.35,62.2,68.96,75.62,82.1,88.09, + 93.94,100,105.34,110.45,115.04,117.17}, + ef70 ={0,29.3813,48.6052,62.9238,74.3451,83.2073,89.925,94.9372,98.3296, + 99.7797,100,99.0413,96.2992,91.8033,89.0156}, + npsh70x = { 1.6, 3, 3.9 }, + npsh70y = { 6.6, 6.7, 6.0 }; + static double[] h85 ={112,112.51,112.79,112.75,112.36,111.62,110.58,108.95, + 106.76,103.82,100,95.02,89.19,82.22,78.27}, + q85 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p85 ={35.35,42.54,49.4,56.33,63.13,69.85,76.41,82.59,88.61, + 94.38,100,105.15,109.83,114.25,116.26}, + ef85 ={0,27.9416,46.721,61.37,72.91,81.9,88.82,94.1319,97.9261, + 99.6572,100,98.8662,95.8912,91.0496,88.0017}, + npsh85x = { 30.6, 47.2, 55.6 }, + npsh85y = { 6.6, 5.9, 5.2 }; + static double[] h100 ={114.5,114.41,114.26,114.02,113.54,112.77,111.47, + 109.67,107.37,103.87,100,94.55,87.95,80,75.78}, + q100 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p100 ={37.83,44.66,51.51,58.26,64.74,71.18,77.41,83.4,89.02, + 94.71,100,104.96,109.34,113.25,115.1}, + ef100 ={0,26.4816,45.1972,60.00,71.7881,80.8615,87.9351,93.497,97.617, + 99.5495,100,98.6925,95.3254,90.2162,87.1612}, + npsh100x = { 27.5, 45, 67.5 }, + npsh100y = { 8.5, 8, 7.5 }; + static double[] h130 ={116.7,116.49,116.13,115.64,114.92,113.79,112.38, + 110.51,107.8,104.2,100,93.98,86.55,78.18,73.52}, + q130 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p130 ={40.45,47.29,53.97,60.5,67,73.14,78.98,84.54,89.91, + 94.75,100,104.52,108.62,111.91,113.49}, + ef130 ={0,23.9926,42.4301,57.3886,69.6333,79.22,86.7537,92.6697,97.0876, + 99.4481,100,98.6268,94.9244,89.3389,85.8424}, + npsh130x = { 22.5, 40, 50 }, + npsh130y = { 8, 7.5, 7.02 }; + static double[] h150 ={119.43,118.96,118.5,117.82,116.75,115.37, + 113.64,111.3,108.29,104.61,100,93.73,85.72,76.43,71.17}, + q150 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p150 ={44.65,51.28,57.8,63.98,70.12,76.04,81.7,86.72,91.46, + 95.94,100,103.66,106.94,109.48,110.71}, + ef150 ={0,21.2608,39.5384,54.7678,67.4627,77.7696,85.8892,92.3006,96.9549, + 99.3641,100,98.5555,94.4991,87.961,84.0969}, + npsh150x = { 79.2, 73, 62.4 }, + npsh150y = { 6.37, 6.5, 6.79 }; + static double[] h180 ={124.19,123.69,122.8,121.6,120.05,118.14, + 115.76,113.02,109.58,105.3,100,92.81,84.49,74.32,68.43}, + q180 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p180 ={48.77,54.89,60.84,66.52,72.5,78.17,83.44,88.16,92.64, + 96.74,100,102.56,104.96,106.9,107.72}, + ef180 ={0,19.3777,37.2247,52.6365,65.4778,76.2215,84.9525,91.7184,96.6465,99.2273, + 100,98.391,93.9028,86.7286,82.3607}, + npsh180x = { 18, 25, 30.6 }, + npsh180y = { 5.5, 6, 6.6 }; + static double[] h200 ={130.34,129.52,128.5,127.08,125.32,123.04, + 119.98,116.18,111.88,106.52,100,91.84,82.68,71.57,65.09}, + q200 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 }, + p200 ={52.27,58.05,63.79,69.42,74.91,80.2,85.25,89.91,93.89,97.4, + 100,101.92,103.39,104.5,104.97}, + ef200 ={0,18.2632,35.3759,50.7,63.6248,75,84.1399,91.2574,96.4082,99.0917,100, + 98.2559,93.4036,86.7286,82.3607}, + npsh200x = { 50.06, 76.64, 92 }, + npsh200y = { 5.65, 6.29, 7.16 }; + static double[] h281 ={152.5,150.47,148.14,145.17,141.39,136.75, + 131.22,124.79,117.49,109.27,100,81.43,62.75}, + q281 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 }, + p281 ={90.5,90.88,91.4,92.2,93.32,94.52,95.58,96.62,97.86, + 99.13,100,99.97,99.95}, + ef281 ={0,16.6501,32.5298,47.0981,60.0777,71.375,80.9615,88.7511,94.8283,98.8591, + 100,97.5118,91.1817}, + npsh281x = { 50.06, 76.64, 92 }, + npsh281y = { 5.65, 6.29, 7.16 }; + static double[] h401 ={197.5,189.21,180.68,171.67,162.17,152.5, + 142.93,133.24,123.1,112.17,100,85.93,69.24}, + q401 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 }, + p401 ={189,171.97,155.93,141.55,129.84,121.5,115.98,111.86, + 108.15,104.31,100,94.96,89.39}, + ef401 ={0,11.8388,23.8006,36.2394,48.6959,60.5,71.1767,81.0133,90.331, + 97.5211,100,96.6122,86.3745}, + npsh401x = { 50.06, 76.64, 92 }, + npsh401y = { 5.65, 6.29, 7.16 }; + static double[] h642 ={290,272,252,232,212,192.91,174.04,155.29,136.77,118.4, + 100,81.43,62.75}, + q642 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 }, + p642 ={219.6,219.6,219.6,219.6,196.61,177.5,161.78,147.3,132.44, + 116.55,100,83.25,66.42}, + ef642 ={0,10.5237,21.1346,31.9149,42.8347,53.75,64.6001,75.7284,87.3088, + 96.8113,100,93.9925,76.3024}, + npsh642x = { 50.06, 76.64, 92 }, + npsh642y = { 5.65, 6.29, 7.16 }; + #endregion + + + //璁$畻(甯︿慨姝� ) + public static bool CalcPoints(GroupPoint ratedParas, double n, + ref List<CurvePoint> pointsQH, + ref List<CurvePoint> pointsQE, + ref List<CurvePoint> pointsQP, + ref List<CurvePoint> pointsNPSH, bool isSxp, int stageNumber) + { + Create(ratedParas, n, ref pointsQH, ref pointsQE, ref pointsQP, ref pointsNPSH, isSxp, stageNumber); + + #region 淇娴侀噺鎵▼鏇茬嚎 淇濊瘉棰濆畾鐐瑰湪鏇茬嚎涓�:杩欐牱棰濆畾鐐瑰瀷璋遍�夊瀷鎵嶈兘閫変腑 + var expQH = FitHelper.BuildCurveExpress(pointsQH, eFitType.CubicCurve); + double fitH = expQH.GetFitPointY(ratedParas.Q); + if (fitH < ratedParas.H * 1.002) + { + int jdP = 1; + if (ratedParas.P < 2) + jdP = 3; + else if (ratedParas.P < 10) + jdP = 2; + else + jdP = 1; + + double spaceH = (ratedParas.H * 1.002 - fitH) * 1.01; + List<CurvePoint> corTestQHpoint = new List<CurvePoint>(); + List<CurvePoint> corTestQPpoint = new List<CurvePoint>(); + for (int i = 0; i < pointsQH.Count; i++) + { + double q = pointsQH[i].X; + double h = expQH.GetFitPointY(q); + double corH = h + spaceH; + if (Math.Abs(q - ratedParas.Q) < 0.0001) + { + corH = ratedParas.H;// phQH.Y + spaceH * 0.1; + } + corTestQHpoint.Add(new CurvePoint() { X = q, Y = corH }); + double corP = IStation.Curve.PumpCalculateHelper.CalculateP(q, corH, pointsQE[i].Y); + corTestQPpoint.Add(new CurvePoint() { X = q, Y = Math.Round(corP, jdP) }); + } + + //褰換=0鐐规椂锛孭涓嶄负0,浣嗚绠楃殑缁撴灉鏄疨=0,鎵�浠�0鐐规椂,闇�瑕佺敤鎻掑�兼硶 + double Q0 = pointsQP[0].X; + double P0 = CurveLineHelper.GetYbyX(corTestQPpoint[1].X, corTestQPpoint[1].Y, corTestQPpoint[2].X, corTestQPpoint[2].Y, 0); + if (P0 > pointsQP[1].Y * 0.98) + P0 = pointsQP[1].Y * 0.98; + corTestQPpoint[0] = new CurvePoint(Q0, P0); + + // + pointsQH = corTestQHpoint; + pointsQP = corTestQPpoint; + + //fitH = FitCurveHelper.GetFitPointY(pointsQH, ratedParas.Q); + } + #endregion + + #region 淇鏁堢巼绾� 楂樻晥鐐� 鏈夋椂涓嶆槸ratedParas.Q + var pointsQE_jiami_1 = pointsQE.GetFitPoints(eFitType.CubicCurve, 500); + CurvePoint currentMaxEffPt_1 = pointsQE_jiami_1.GetMaxPointY();//褰撳墠楂樻晥鐐� + if (Math.Abs(currentMaxEffPt_1.X - ratedParas.Q) / ratedParas.Q > 0.02) + { + var pointsQE_xiuzheng1 = GetMoveBSP(currentMaxEffPt_1.X, ratedParas.Q, pointsQE_jiami_1); + //if (pointsQE_xiuzheng1.Last().X < pointsQE.Last().X) + { + var xpre_e = FitHelper.BuildCurveExpress(pointsQE_xiuzheng1, eFitType.CubicCurve); + foreach (var pt in pointsQE) + { + if (pt.X < 0.1) + pt.Y = 0; + else + pt.Y = Math.Round(xpre_e.GetFitPointY(pt.X), 3); + } + } + } + #endregion + + return true; + } + + private static List<CurvePoint> GetMoveBSP(double maxEtaQ_old, double maxEtaQ_new, List<CurvePoint> points_curve_old) + { + List<CurvePoint> points_new = new List<CurvePoint>(); + + if (maxEtaQ_new < maxEtaQ_old) + {//鍚戝乏绉诲姩 + foreach (var pt_old in points_curve_old) + { + double new_x = 0; + if (pt_old.X < maxEtaQ_old) + { + new_x = pt_old.X * maxEtaQ_new / maxEtaQ_old; + } + else + { + new_x = pt_old.X - maxEtaQ_old + maxEtaQ_new; + } + + points_new.Add(new CurvePoint(new_x, pt_old.Y)); + } + } + else + {//鍚戝彸绉诲姩 + foreach (var pt_old in points_curve_old) + { + double new_x = 0; + + if (pt_old.X < maxEtaQ_old) + { + new_x = pt_old.X * maxEtaQ_new / maxEtaQ_old; + } + else + { + new_x = pt_old.X - maxEtaQ_old + maxEtaQ_new; + } + + points_new.Add(new CurvePoint(new_x, pt_old.Y)); + } + } + + return points_new; + } + + + public static bool CalcPoints(GroupPoint ratedParas, double n, + ref List<GroupPoint> correctPoints, bool isSxp, int stageNumber) + { + List<CurvePoint> pointsQH = null; + List<CurvePoint> pointsQE = null; + List<CurvePoint> pointsQP = null; + List<CurvePoint> pointsNPSH = null; + bool re = CalcPoints(ratedParas, n, ref pointsQH, ref pointsQE, ref pointsQP, ref pointsNPSH, isSxp, stageNumber); + if (!re) + return false; + int iCout = pointsQH.Count; + + correctPoints = new List<GroupPoint>(); + for (int i = 0; i < iCout; i++) + { + correctPoints.Add(new GroupPoint() + { + ID = i, + Q = pointsQH[i].X, + H = pointsQH[i].Y, + E = pointsQE[i].Y, + P = pointsQP[i].Y + }); + } + // + return true; + } + + //璁$畻(甯︿慨姝�) + public static bool CalcPoints(GroupPoint ratedParas, double n, double? K0, + ref List<CurvePoint> pointsQH, + ref List<CurvePoint> pointsQE, + ref List<CurvePoint> pointsQP, + ref List<CurvePoint> pointsNPSH, bool isSxp, int stageNumber) + { + bool re = CalcPoints(ratedParas, n, ref pointsQH, ref pointsQE, ref pointsQP, ref pointsNPSH, isSxp, stageNumber); + if (!re) + return false; + + if (K0 == null) + { + return re; + } + if (K0 < 1.001) + { + return re; + } + + var pointsOri = pointsQH; + double ori_zeroPtH = pointsOri[0].Y; + double zeroPtH = (double)K0 * ratedParas.H; + + //鍘绘帀鍓嶉潰鍑犱釜鐐� + int removePtNum = 3; + List<CurvePoint> pointsRemove = pointsOri.GetRange(removePtNum, pointsOri.Count - removePtNum); + pointsRemove.Insert(0, new CurvePoint(0, ori_zeroPtH)); + //閲嶆柊鑾峰彇鎷熷悎鐐� + List<CurvePoint> pointsRemove2 = pointsRemove.GetFitPoints(eFitType.CubicCurve, pointsOri.Count); + //杩涜淇 + var pointsAmend = AmendCurveHelper.ByZeroPointY( + pointsRemove2, + ratedParas.Q, zeroPtH); + List<CurvePoint> pointsReturn = new List<CurvePoint>(); + foreach (var oriPt in pointsOri) + { + if (oriPt.X < 1) + { + pointsReturn.Add(new CurvePoint() + { + X = oriPt.X, + Y = zeroPtH + }); + } + else if (Math.Abs(oriPt.X - ratedParas.Q) < 1) + { + pointsReturn.Add(new CurvePoint() + { + X = ratedParas.Q, + Y = ratedParas.H + }); + } + else + { + pointsReturn.Add(new CurvePoint() + { + X = oriPt.X, + Y = Math.Round(pointsAmend.GetFitPointY(oriPt.X), 3) + }); + } + } + // + pointsQH = pointsReturn; + + pointsQP = IStation.Curve.PumpCalculateHelper.CalculateP(pointsQH, pointsQE); + + return true; + } + + + + //淇QE绾�(鐢变簬鐢ㄥ師濮嬬偣,鎷熷悎鏇茬嚎鏈夊亸宸�,鎵�浠ュ幓鎺変竴浜涘皬娴侀噺鐐�,杩欐牱鎷熷悎濂戒簺) + private static List<CurvePoint> AmendPointQE(List<CurvePoint> pointsQE) + { + int removePtNum = 5; + List<CurvePoint> amendQEpoint = pointsQE.GetRange(removePtNum, pointsQE.Count - removePtNum); + amendQEpoint.Insert(0, new CurvePoint(0, 0)); + + CurveExpress exp = FitHelper.BuildCurveExpress(amendQEpoint, eFitType.CubicCurve); + for (int i = 1; i < removePtNum; i++) + { + amendQEpoint.Insert(i, new CurvePoint(pointsQE[i].X, FitHelper.GetFitPointY(exp, pointsQE[i].X))); + + } + + return amendQEpoint; + } + + //鍘熷(涓嶄慨姝�) + private static bool Create(GroupPoint ratedParas1, double n, + ref List<CurvePoint> pointsQH, ref List<CurvePoint> pointsQE, ref List<CurvePoint> pointsQP, ref List<CurvePoint> pointsNPSH, bool isSxp, int stageNumber) + { + pointsQH = null; + pointsQE = null; + pointsQP = null; + pointsNPSH = null; + + if (ratedParas1 == null) + return false; + if (stageNumber < 1) + stageNumber = 1; + pointsQH = new List<CurvePoint>(); + pointsQE = new List<CurvePoint>(); + pointsQP = new List<CurvePoint>(); + pointsNPSH = new List<CurvePoint>(); + + double Q = 0, H = 0; + double P = 0, E = 0; + int count = 0; + int i = 0; + + double calcP = ratedParas1.P; + double calcE = ratedParas1.E; + double calcQ = ratedParas1.Q; + if (isSxp) + calcQ = ratedParas1.Q / 2; + + //璁$畻姣旇浆閫� + double calcH = ratedParas1.H / stageNumber; + double ns = 3.65 * n * Math.Sqrt(calcQ / 3600) / Math.Pow(calcH, 0.75); + + #region 鏍规嵁姣旇浆閫熻绠� + if (ns < 35.1) + {//涓�0-35涔嬮棿鐨� + count = q35.Count(); + for (i = 0; i < count; i++) + {//VB浠g爜涓� 灏忎簬35涓嶇敤绛夋瘮渚嬫崲绠� + Q = calcQ * q35[i] / 100; + H = calcH * h35[i] / 100; + E = calcE * ef35[i] / 100; + P = calcP * p35[i] / 100; + if (H < 0.1) + continue; + pointsQH.Add(new CurvePoint(Q, H)); + pointsQP.Add(new CurvePoint(Q, P)); + pointsQE.Add(new CurvePoint(Q, E)); + } + } + else if (ns < 50.1) + { + count = Math.Min(q35.Count(), q50.Count()); + double ratio = (ns - 35) / (50 - 35); + for (i = 0; i < count; i++) + { + Q = calcQ * q35[i] / 100.0; + + H = h35[i] + (h50[i] - h35[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef35[i] + (ef50[i] - ef35[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else if (ns < 70.1) + { + count = Math.Min(q50.Count(), q70.Count()); + double ratio = (ns - 50) / (70 - 50); + for (i = 0; i < count; i++) + { + Q = calcQ * q50[i] / 100.0; + + H = h50[i] + (h70[i] - h50[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef50[i] + (ef70[i] - ef50[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else if (ns < 85.1) + { + count = Math.Min(q70.Count(), q85.Count()); + double ratio = (ns - 70) / (85 - 70); + for (i = 0; i < count; i++) + { + Q = calcQ * q70[i] / 100.0; + + H = h70[i] + (h85[i] - h70[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef70[i] + (ef85[i] - ef70[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else if (ns < 100.1) + { + count = Math.Min(q85.Count(), q100.Count()); + double ratio = (ns - 85) / (100 - 85); + for (i = 0; i < count; i++) + { + Q = calcQ * q85[i] / 100.0; + + H = h85[i] + (h100[i] - h85[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef85[i] + (ef100[i] - ef85[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else if (ns < 130.1) + { + count = Math.Min(q100.Count(), q130.Count()); + double ratio = (ns - 100) / (130 - 100); + for (i = 0; i < count; i++) + { + Q = calcQ * q100[i] / 100.0; + + H = h100[i] + (h130[i] - h100[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef100[i] + (ef130[i] - ef100[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else if (ns < 150.1) + { + count = Math.Min(q130.Count(), q150.Count()); + double ratio = (ns - 130) / (150 - 130); + for (i = 0; i < count; i++) + { + Q = calcQ * q130[i] / 100.0; + + H = h130[i] + (h150[i] - h130[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef130[i] + (ef150[i] - ef130[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else if (ns < 180.1) + { + count = Math.Min(q150.Count(), q180.Count()); + double ratio = (ns - 150) / (180 - 150); + for (i = 0; i < count; i++) + { + Q = calcQ * q150[i] / 100.0; + + H = h150[i] + (h180[i] - h150[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef150[i] + (ef180[i] - ef150[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else if (ns < 200.1) + { + count = Math.Min(q200.Count(), q180.Count()); + double ratio = (ns - 180) / (200 - 180); + for (i = 0; i < count; i++) + { + Q = calcQ * q180[i] / 100.0; + + H = h180[i] + (h200[i] - h180[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef180[i] + (ef200[i] - ef180[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else if (ns < 281.1) + { + count = Math.Min(q200.Count(), q281.Count()); + double ratio = (ns - 200) / (281 - 200); + for (i = 0; i < count; i++) + { + Q = calcQ * q200[i] / 100.0; + + H = h200[i] + (h281[i] - h200[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef200[i] + (ef281[i] - ef200[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else if (ns < 401.1) + { + count = Math.Min(q401.Count(), q281.Count()); + double ratio = (ns - 281) / (401 - 281); + for (i = 0; i < count; i++) + { + Q = calcQ * q281[i] / 100.0; + + H = h281[i] + (h401[i] - h281[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef281[i] + (ef401[i] - ef281[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else if (ns < 642.1) + { + count = Math.Min(q401.Count(), q642.Count()); + double ratio = (ns - 401) / (642 - 401); + for (i = 0; i < count; i++) + { + Q = calcQ * q401[i] / 100.0; + + H = h401[i] + (h642[i] - h401[i]) * ratio; + H = H * calcH / 100; + pointsQH.Add(new CurvePoint(Q, H)); + + E = ef401[i] + (ef642[i] - ef401[i]) * ratio; + E = E * calcE / 100; + pointsQE.Add(new CurvePoint(Q, E)); + + //璁$畻鍔熺巼 + P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + else //(ns > 642) + { + count = q642.Count(); + for (i = 0; i < count; i++) + {//VB浠g爜涓� 涓嶇敤绛夋瘮渚嬫崲绠� + Q = calcQ * q642[i] / 100; + H = calcH * h642[i] / 100; + E = calcE * ef642[i] / 100; + P = calcP * p642[i] / 100; + //MathFunc.Regulate(IStation.Common.Calculate.CalculateP(Q, H, Eff),2); + if (H < 0.1) + continue; + pointsQH.Add(new CurvePoint(Q, H)); + pointsQE.Add(new CurvePoint(Q, E)); + pointsQP.Add(new CurvePoint(Q, P)); + } + } + #endregion + + //褰換=0鐐规椂锛孭涓嶄负0,浣嗚绠楃殑缁撴灉鏄疨=0,鎵�浠�0鐐规椂,闇�瑕佺敤鎻掑�兼硶 + double Q0 = pointsQP[0].X; + double P0 = CurveLineHelper.GetYbyX(pointsQP[1].X, pointsQP[1].Y, pointsQP[2].X, pointsQP[2].Y, 0); + if (P0 > pointsQP[1].Y * 0.98) + P0 = pointsQP[1].Y * 0.98; + pointsQP[0] = new CurvePoint(Q0, P0); + + + + + if (isSxp) + { + if (pointsQH != null && pointsQE != null) + { + foreach (var pt in pointsQH) + { + pt.X = pt.X * 2; + } + foreach (var pt in pointsQE) + { + pt.X = pt.X * 2; + } + pointsQP = IStation.Curve.PumpCalculateHelper.CalculateP(pointsQH, pointsQE); + } + + if (pointsNPSH != null) + { + foreach (var pt in pointsNPSH) + { + pt.X = pt.X * 2; + } + } + } + + if (stageNumber > 1) + { + if (pointsQH != null && pointsQE != null) + { + foreach (var pt in pointsQH) + { + pt.Y = pt.Y * stageNumber; + } + pointsQP = IStation.Curve.PumpCalculateHelper.CalculateP(pointsQH, pointsQE); + } + } + + + return true; + } + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Express/CurveExpress.cs b/Schedule/IStation.Algorithm/Model/Curve/Express/CurveExpress.cs new file mode 100644 index 0000000..3d39d84 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Express/CurveExpress.cs @@ -0,0 +1,119 @@ +锘縩amespace IStation.Curve +{ + + /// <summary> + /// 鏇茬嚎琛ㄨ揪寮� + /// </summary> + public class CurveExpress : JsonModel<CurveExpress>, ICloneable + { + /// <summary> + /// + /// </summary> + public CurveExpress() { } + + /// <summary> + /// + /// </summary> + public CurveExpress(CurveExpress rhs) + { + this.FitType = rhs.FitType; + this.Min = rhs.Min; + this.Max = rhs.Max; + this.Index0 = rhs.Index0; + this.Index1 = rhs.Index1; + this.Index2 = rhs.Index2; + this.Index3 = rhs.Index3; + this.Index4 = rhs.Index4; + this.DefinePoints = rhs.DefinePoints?.Select(x => new CurvePoint(x)).ToList(); + } + + /// <summary> + /// 鎷熷悎绫诲瀷 + /// </summary> + public eFitType FitType { get; set; } + + /// <summary> + /// 鏈�澶у�� + /// </summary> + public double Max { get; set; } + + /// <summary> + /// 鏈�灏忓�� + /// </summary> + public double Min { get; set; } + + /// <summary> + /// 0娆$郴鏁� + /// </summary> + public double Index0 { get; set; } + + /// <summary> + /// 1娆$郴鏁� + /// </summary> + public double Index1 { get; set; } + + /// <summary> + /// 2娆$郴鏁� + /// </summary> + public double Index2 { get; set; } + + /// <summary> + /// 3娆$郴鏁� + /// </summary> + public double Index3 { get; set; } + + /// <summary> + /// 4娆$郴鏁� + /// </summary> + public double Index4 { get; set; } + + /// <summary> + /// 瀹氫箟鐐� + /// </summary> + public List<CurvePoint> DefinePoints { get; set; } + + + /// <summary> + /// 鑾峰彇鎷熷悎鐐� + /// </summary> + public double GetFitPointY(double x) + { + return FitHelper.GetFitPointY(this, x); + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐� + /// </summary> + public List<CurvePoint> GetFitPoints(int pointNumber = 20) + { + return FitHelper.GetFitPoints(this, pointNumber); + } + + /// <summary> + /// 鑾峰彇X鍖洪棿鍐呮嫙鍚堢偣 + /// </summary> + public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber = 20) + { + return FitHelper.GetFitPointsByXRange(this, minX, maxX, pointNumber); + } + + + /// <summary> + /// + /// </summary> + public CurveExpress Clone() + { + return new CurveExpress(this); + } + + /// <summary> + /// + /// </summary> + object ICloneable.Clone() + { + return Clone(); + } + + } + +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurveExpress_Extensions.cs b/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurveExpress_Extensions.cs new file mode 100644 index 0000000..a4997aa --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurveExpress_Extensions.cs @@ -0,0 +1,539 @@ +锘縩amespace IStation.Curve +{ + public static class CurveExpress_Extensions + { + + #region CurveFunction + + /// <summary> + /// 鑾峰彇鏇茬嚎鏂圭▼ + /// </summary> + public static string GetCurveFunction(this CurveExpress express, string xName = "Q") + { + + StringBuilder sb = new StringBuilder(); + sb.Append(Math.Abs(express.Index0).ToString("0.00")); + + if (express.Index1 > 0) + sb.Append(" + "); + else + sb.Append(" - "); + sb.Append(Math.Abs(express.Index1).ToString("0.0000")); + sb.Append(" * "); + sb.Append(xName); + + if (express.Index2 > 0) + sb.Append(" + "); + else + sb.Append(" - "); + sb.Append(Math.Abs(express.Index2).ToString("0.000000000")); + sb.Append(" * "); + sb.Append(xName); + sb.Append("^2 "); + + + if (express.Index3 > 0) + sb.Append(" + "); + else + sb.Append(" - "); + sb.Append(Math.Abs(express.Index3).ToString("0.000000000000")); + sb.Append(" * "); + sb.Append(xName); + sb.Append("^3 "); + + return sb.ToString(); + } + + /// <summary> + /// 鑾峰彇 + /// </summary> + /// <param name="functionIndex"></param> + /// <param name="functionCoeff"></param> + /// <param name="signValue"></param> + /// <param name="IndexValue"></param> + private static void GetFuncScientificValue(int functionIndex, double functionCoeff, ref double signValue, ref int IndexValue) + { + string strList = ""; + if (functionIndex == 0) + { + strList = functionCoeff.ToString("0.000e+000"); + } + else if (functionIndex == 1) + { + strList = functionCoeff.ToString("0.000000e+000"); + } + else if (functionIndex == 2) + { + strList = functionCoeff.ToString("#.#########e+000"); + } + else if (functionIndex == 3) + { + strList = functionCoeff.ToString("#.############e+000"); + } + string[] st1 = null; + st1 = strList.Split('e'); + signValue = Convert.ToDouble(st1[0]); + IndexValue = Convert.ToInt32(st1[1]); + } + + #endregion + + #region List<CurvePoint> Extend + + /// <summary> + /// 鑾峰彇鎷熷悎鐐� + /// </summary> + public static List<CurvePoint> GetFitPointsByExtend(this CurveExpress express, double ratioExtend, int pointNumber) + { + if (express == null) + return default; + var helper = new FitHelper(express); + return helper.GetFitPointsByXRange(express.Min, express.Max * ratioExtend, pointNumber); + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐� + /// </summary> + public static List<CurvePoint> GetFitPointsByExtend(this CurveExpress express, double ratioExtendmin, double ratioExtendmax, int pointNumber) + { + if (express == null) + return default; + var helper = new FitHelper(express); + return helper.GetFitPointsByXRange(express.Min * ratioExtendmin, express.Max * ratioExtendmax, pointNumber); + } + + #endregion + + #region 鑾峰緱X鍊� + + /// <summary> + /// 鑾峰緱Y鍊肩殑鍧愭爣浣嶇疆,澶氫釜鐐归噷鍙栨渶鍚庝竴涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�) + /// </summary> + /// <param name="curve"></param> + /// <param name="y"></param> + /// <param name="interPointNum"></param> + /// <returns></returns> + public static double? GetInterPointLastX(this CurveExpress curve, double y, int interPointNum = 20) + { + if (curve == null) + return null; + var points = FitHelper.GetFitPoints(curve, interPointNum); + if (points == null) + return null; + + //鍦ㄨ寖鍥村唴 + double maxY = (from yyy in points select yyy.Y).Max(); + double minY = (from yyy in points select yyy.Y).Min(); + + if (double.IsNaN(maxY) || double.IsNaN(minY)) + return null; + if (y < minY || y > maxY) + return null; + + var list = points.GetPointsByInterPointX(y); + if (list == null || list.Count < 1) + return null; + + return list.Last().X; + } + + + /// <summary> + /// 鑾峰緱Y鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�):浼氳绠楀欢闀块儴鍒�:鑰屼笖瑕佹眰points鐐规寜鐓т粠灏忓埌澶ф帓搴� + /// </summary> + /// <param name="curve"></param> + /// <param name="y"></param> + /// <param name="interPointNum"></param> + /// <returns></returns> + public static List<CurvePoint> GetInterPointExX(this CurveExpress curve, double y, int interPointNum) + { + if (curve == null) + return null; + var points = FitHelper.GetFitPoints(curve, interPointNum); + if (points == null) + return null; + + //鍦ㄨ寖鍥村唴 + double maxY = (from yyy in points select yyy.Y).Max(); + double minY = (from yyy in points select yyy.Y).Min(); + + if (double.IsNaN(maxY) || double.IsNaN(minY)) + return null; + if (y > minY && y < maxY) + { + return points.GetPointsByInterPointX(y); + } + + List<CurvePoint> ptList = new List<CurvePoint>(); + + //鍒ゆ柇鏄惁鍦ㄥ墠闈㈢殑寤堕暱閮ㄥ垎 + double x_start = CurveLineHelper.GetXbyY(points[0].X, points[0].Y, points[1].X, points[1].Y, y); + if (x_start <= points[0].X) + { + if (x_start > 0 && x_start > points[0].X * 0.9)//鏀句竴鐐逛綑閲� + ptList.Add(new CurvePoint(x_start, y)); + } + + //鍒ゆ柇鏄惁鍦ㄥ悗闈㈢殑寤堕暱閮ㄥ垎:U鍨嬫洸绾� 鏄墠鍚庨兘鏈� + double x_end = CurveLineHelper.GetXbyY(points[points.Count - 2].X, points[points.Count - 2].Y, points[points.Count - 1].X, points[points.Count - 1].Y, y); + if (x_end >= points[points.Count - 1].X && x_end < points[points.Count - 1].X * 1.1)//鏀句竴鐐逛綑閲� + { + ptList.Add(new CurvePoint(x_end, y)); + } + + if (ptList.Count == 0) + return null; + return ptList; + } + + + + /// <summary> + /// 鑾峰緱Y鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�):浼氳绠楀欢闀块儴鍒�:鑰屼笖瑕佹眰points鐐规寜鐓т粠灏忓埌澶ф帓搴� + /// </summary> + /// <param name="curve"></param> + /// <param name="y"></param> + /// <param name="interPointNum"></param> + /// <param name="extendRatio"></param> + /// <returns></returns> + public static List<CurvePoint> GetInterPointExX(this CurveExpress curve, double y, int interPointNum, double extendRatio) + { + if (curve == null) + return null; + var points = GetFitPointsByExtend(curve, extendRatio, interPointNum); + if (points == null) + return null; + + //鍦ㄨ寖鍥村唴 + double maxY = (from yyy in points select yyy.Y).Max(); + double minY = (from yyy in points select yyy.Y).Min(); + if (y > minY && y < maxY) + { + return points.GetPointsByInterPointX(y); + } + + List<CurvePoint> ptList = new List<CurvePoint>(); + //鍒ゆ柇鏄惁鍦ㄥ墠闈㈢殑寤堕暱閮ㄥ垎 + double x_start = CurveLineHelper.GetXbyY(points[0].X, points[0].Y, points[1].X, points[1].Y, y); + if (x_start <= points[0].X) + { + if (x_start > 0 && x_start > points[0].X * 0.9)//鏀句竴鐐逛綑閲� + ptList.Add(new CurvePoint(x_start, y)); + } + + //鍒ゆ柇鏄惁鍦ㄥ悗闈㈢殑寤堕暱閮ㄥ垎:U鍨嬫洸绾� 鏄墠鍚庨兘鏈� + double x_end = CurveLineHelper.GetXbyY(points[points.Count - 2].X, points[points.Count - 2].Y, points[points.Count - 1].X, points[points.Count - 1].Y, y); + if (x_end >= points[points.Count - 1].X && x_end < points[points.Count - 1].X * extendRatio)//鏀句竴鐐逛綑閲� + { + ptList.Add(new CurvePoint(x_end, y)); + } + + if (ptList.Count == 0) + return null; + return ptList; + } + + #endregion 鑾峰緱X鍊� + + #region 鑾峰緱Y鍊� + + /// <summary> + /// 鑾峰彇Y鍊兼渶澶у�肩殑鐐� + /// </summary> + public static CurvePoint GetMaxPoint(this CurveExpress express, int pointNumber = 200) + { + if (express == null) + return null; + if (express.FitType <= 0 && express.DefinePoints != null) + { + return express.DefinePoints.GetPointByMaxY(); + } + else if (express.FitType == eFitType.ThroughPoint) + { + return express.DefinePoints.GetPointByMaxY(); + } + else + { + var points = express.GetFitPoints(pointNumber); + return points.GetPointByMaxY(); + } + } + + /// <summary> + /// 鑾峰彇Y鍊兼渶澶у�肩殑鐐� + /// </summary> + public static CurvePoint GetMaxPointByRange(this CurveExpress express, double rangeMin, double rangeMax, int pointNumber = 200) + { + if (express == null) + return null; + var points = express.GetFitPointsByXRange(rangeMin, rangeMax, pointNumber); + return points.GetPointByMaxY(); + } + + + /// <summary> + /// 鑾峰彇鏈�澶ф渶灏廦 + /// </summary> + /// <param name=""></param> + public static bool GetMinMaxPointY(this CurveExpress express, out double maxY, out double minY) + { + if (express == null) + { + maxY = minY = 0; + return false; + } + var fitPoints = express.GetFitPoints(50); + if (fitPoints == null) + { + maxY = minY = 0; + return false; + } + maxY = fitPoints.Max(x => x.Y); + minY = fitPoints.Min(x => x.Y); + return true; + } + + #endregion 鍙朰鐨勬渶澶ф渶灏忓�� + + #region SimuValue + + /// <summary> + /// 鏍规嵁鐩镐技鐐硅缃浉浼兼洸绾�,鐩镐技鐐�(閫夋嫨鐐�)鐨剎:娴侀噺y:鏉ㄧ▼ + /// </summary> + public static double GetSimuValue(this CurveExpress express, CurvePoint simularPoint, double originValue, double extendRatio = 1) + { + if (express == null) + return -3; + if (simularPoint.X < 0.1 || simularPoint.Y < 0.1) + return -2; + if (simularPoint.X > express.Max * extendRatio * 1.5) + return -4; + + CurvePoint sectPoint = GetSectPoint(express, simularPoint, extendRatio); + if (sectPoint == null || sectPoint.IsZeroPoint()) + return -5; + + //璁$畻鐩镐技鐐圭殑杞��/鐩村緞 + return PumpCalculateHelper.CalculateSimuByH(originValue, sectPoint.Y, simularPoint.Y); + } + + //ratioIgnore:浣滅敤 褰搒imularPoint瓒呭嚭鏇茬嚎鑼冨洿鏃�,鏇茬嚎鎵╁ぇ鐨勫�嶆暟 + public static CurvePoint GetSectPoint(this CurveExpress CurveExpress, CurvePoint simularPoint, double ratioIgnore) + { + return GetSectPointGeneral(CurveExpress, simularPoint, 2, ratioIgnore); + } + + #endregion + + #region 鏇茬嚎涓嶩=K*Q^i鐨勪氦鐐� + + + //閫氳繃鐐箂imularPoint鍜岀偣(0,0)鐨勭洿绾�,涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0)) + public static CurvePoint GetSectPointLine(List<CurvePoint> CurvePoints, CurvePoint simularPoint) + { + CurvePoint sectPoint = new CurvePoint(0, 0); + if (CurvePoints == null || CurvePoints.Count < 2) + return sectPoint; + + //璁$畻鐩寸嚎鐨凨 + if (simularPoint.X < 1) + return sectPoint; + double a = simularPoint.Y / simularPoint.X; + if (a < 0.0001) + return sectPoint; + + //涓�2鐐硅繛鎴愮洿绾跨殑浜ょ偣,鍒ゆ柇浜ょ偣鏄惁鍦�2鐐逛箣闂�,鍗冲彲鏄洸绾跨殑浜ょ偣 + double b, c; + double x; + for (int i = 0; i < CurvePoints.Count - 1; i++) + { + CurveLineHelper.GetKandB(CurvePoints[i], CurvePoints[i + 1], out b, out c); + + /*瑙f柟绋� + * y=ax + * y=bx+c + */ + if (Math.Abs(a - b) < 0.001) + continue; + + x = c / (a - b); + if (IStation.Curve.UtilsHelper.IsMiddle(CurvePoints[i].X, CurvePoints[i + 1].X, x)) + { + sectPoint.X = x; + sectPoint.Y = a * x; + return sectPoint; + } + } + + return sectPoint; + } + + //閫氳繃鐐箂imularPoint鍜岀偣(0,0)鐨勬姏鐗╃嚎,涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0)) + //鏇茬嚎鍏紡:H=K*Q^2 + public static CurvePoint GetSectPointParabola(List<CurvePoint> CurvePoints, CurvePoint simularPoint) + { + return ParabolaCurveHelper.GetSectPoint(CurvePoints, simularPoint, 0); + } + + public static CurvePoint GetSectPointParabola(CurveExpress CurveExpress, CurvePoint simularPoint) + { + CurvePoint sectPoint = new CurvePoint(0, 0); + if (CurveExpress == null) + return sectPoint; + + return GetSectPointParabola(CurveExpress.GetFitPointsByExtend(1.2, 50), simularPoint); + } + + public static CurvePoint GetSectPointLine(this CurveExpress CurveExpress, CurvePoint simularPoint) + { + CurvePoint sectPoint = new CurvePoint(0, 0); + if (CurveExpress == null) + return sectPoint; + + //璁$畻鐩寸嚎鐨凨 + if (simularPoint.X < 1) + return sectPoint; + double a = simularPoint.Y / simularPoint.X; + if (a < 0.0001) + return sectPoint; + + //鐐硅秺澶氳秺绮剧‘ + return GetSectPointLine(CurveExpress.GetFitPoints(100), simularPoint); + } + + //鏇茬嚎H=K*Q^i 涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0)) + public static CurvePoint GetSectPointGeneral(List<CurvePoint> CurvePoints, CurvePoint simularPoint, double index) + { + CurvePoint sectPoint = new CurvePoint(0, 0); + if (CurvePoints == null || CurvePoints.Count < 2) + return sectPoint; + + if (simularPoint.X < 0.1) + return sectPoint; + + if (Math.Abs(index - 1) < 0.01) + return GetSectPointLine(CurvePoints, simularPoint); + if (Math.Abs(index - 2) < 0.01) + return GetSectPointParabola(CurvePoints, simularPoint); + + //璁$畻绯绘暟K + double fixK = simularPoint.Y / Math.Pow(simularPoint.X, index); + if (fixK < 0.000001) + return sectPoint; + + //鎬濊矾鏄粠simularPoint寮�濮嬮�愪釜澧炲姞0.1,鐩村埌k鍊兼渶鎺ヨ繎fixK + double space = (CurvePoints.Last().X - simularPoint.X) / 1200; + double x = simularPoint.X; + double y, k; + do + { + x = x + space; + y = 0; + if (!CurvePoints.GetInterPointY(x, out y)) + { + break; + } + + k = y / Math.Pow(x, index); + } while (k > fixK); + + sectPoint.X = x; + sectPoint.Y = y; + return sectPoint; + } + + //鏇茬嚎H=K*Q^i 涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0)) + public static CurvePoint GetSectPointGeneral(this CurveExpress express, CurvePoint simularPoint, double index) + { + CurvePoint sectPoint = new CurvePoint(0, 0); + if (express == null) + return sectPoint; + + if (simularPoint.X < 1) + return sectPoint; + + //妫�鏌ユ槸鍚﹀湪鏇茬嚎鐨勫尯鍩熻寖鍥村唴 + double maxQ = express.Max; + double maxH = express.GetFitPointY(maxQ); + double k1 = maxH / Math.Pow(maxQ, index); + double k2 = simularPoint.Y / Math.Pow(simularPoint.X, index); + if (k1 > k2) + { + return sectPoint; + } + + if (Math.Abs(index - 1) < 0.01) + return GetSectPointLine(express, simularPoint); + if (Math.Abs(index - 2) < 0.01) + return GetSectPointParabola(express, simularPoint); + + //璁$畻绯绘暟K + double fixK = simularPoint.Y / Math.Pow(simularPoint.X, index); + if (fixK < 0.000001) + return sectPoint; + + //鎬濊矾鏄粠simularPoint寮�濮嬮�愪釜澧炲姞0.1,鐩村埌k鍊兼渶鎺ヨ繎fixK + double space = (express.Max - simularPoint.X) / 1000; + double x = simularPoint.X; + double y, k; + do + { + x = x + space; + y = express.GetFitPointY(x); + k = y / Math.Pow(x, index); + } while (k > fixK); + + sectPoint.X = x; + sectPoint.Y = y; + return sectPoint; + } + + //ratioIgnore:浣滅敤 褰搒imularPoint瓒呭嚭鑼冨洿鏃�,鎵╁ぇ鐨勫�嶆暟 + public static CurvePoint GetSectPointGeneral(this CurveExpress curveExpress, CurvePoint simularPoint, double index, double ratioIgnore) + { + CurvePoint sectPoint = new CurvePoint(0, 0); + if (curveExpress == null) + return sectPoint; + + if (simularPoint.X < 1) + return sectPoint; + var CurveExpressEx = curveExpress.Clone(); + //妫�鏌ユ槸鍚﹀湪鏇茬嚎鐨勫尯鍩熻寖鍥村唴 + double maxQ = CurveExpressEx.Max; + double maxH = CurveExpressEx.GetFitPointY(maxQ); + double k1 = maxH / Math.Pow(maxQ, index); + double k2 = simularPoint.Y / Math.Pow(simularPoint.X, index); + if (k1 > k2) + { + CurveExpressEx.Max = CurveExpressEx.Max * ratioIgnore;//鏀惧ぇ1.2鍊� + } + + if (Math.Abs(index - 1) < 0.01) + return GetSectPointLine(CurveExpressEx, simularPoint); + if (Math.Abs(index - 2) < 0.01) + return GetSectPointParabola(CurveExpressEx, simularPoint); + + //璁$畻绯绘暟K + double fixK = simularPoint.Y / Math.Pow(simularPoint.X, index); + if (fixK < 0.000001) + return sectPoint; + + //鎬濊矾鏄粠simularPoint寮�濮嬮�愪釜澧炲姞0.1,鐩村埌k鍊兼渶鎺ヨ繎fixK + double space = (CurveExpressEx.Max - simularPoint.X) / 1000; + double x = simularPoint.X; + double y, k; + do + { + x = x + space; + y = CurveExpressEx.GetFitPointY(x); + k = y / Math.Pow(x, index); + } while (k > fixK); + + sectPoint.X = x; + sectPoint.Y = y; + return sectPoint; + } + + #endregion 鏇茬嚎涓嶩=K*Q^i鐨勪氦鐐� protect绫诲瀷,缁欏瓙绫昏皟鐢�,鎬庝箞瑕嗙洊GetSectPoint + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurvePoint_Extensions.cs b/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurvePoint_Extensions.cs new file mode 100644 index 0000000..23d3317 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurvePoint_Extensions.cs @@ -0,0 +1,463 @@ +锘縩amespace IStation.Curve +{ + public static class CurvePoint_Extensions + { + + #region Point + + /// <summary> + /// 鍒ゆ柇鏄惁鏄�0鐐�,鐢ㄤ簬鍒ゆ柇鍑芥暟鏄惁鎴愬姛杩斿洖 + /// </summary> + public static bool IsZeroPoint(this CurvePoint pt) + { + if (pt.X < 0.01 && pt.Y < 0.01) + return true; + else + return false; + } + + /// <summary> + /// 鐐瑰埌绾跨殑璺濈 + /// </summary> + public static double GetDistance(this CurvePoint pt1, List<CurvePoint> CurvePoints) + { + if (CurvePoints == null) + return 10000; + + double min_dis = double.MaxValue; + double dis = 0; + foreach (CurvePoint pt in CurvePoints) + { + dis = GetDistance(pt1, pt); + if (dis < min_dis) + min_dis = dis; + } + + return min_dis; + } + + /// <summary> + /// 涓ょ偣涔嬮棿鐨勮窛绂� + /// </summary> + public static double GetDistance(CurvePoint pt1, CurvePoint pt2) + { + return Math.Sqrt((pt1.X - pt2.X) * (pt1.X - pt2.X) + (pt1.Y - pt2.Y) * (pt1.Y - pt2.Y)); + } + + + /// <summary> + /// 璁$畻鎬婚暱搴� + /// </summary> + public static double CalcuTotalLength(this List<CurvePoint> ptList) + { + if (ptList == null || ptList.Count < 1) + { + return default; + } + double length = 0; + for (int i = 1; i < ptList.Count; i++) + { + length += ptList[i].Distance(ptList[i - 1]); + } + return length; + } + + #endregion + + #region List<CurvePoint> + + /// <summary> + /// 鑾峰彇Y鏈�灏忕殑鐐� + /// </summary> + public static CurvePoint GetPointByMinY(this List<CurvePoint> ptList) + { + if (ptList == null || ptList.Count < 1) + { + return default; + } + return ptList.OrderBy(x => x.Y).FirstOrDefault(); + } + + /// <summary> + /// 鑾峰彇Y鏈�澶х殑鐐� + /// </summary> + public static CurvePoint GetPointByMaxY(this List<CurvePoint> ptList) + { + if (ptList == null || !ptList.Any()) + { + return default; + } + return ptList.OrderBy(x => x.Y).LastOrDefault(); + } + + /// <summary> + /// 鑾峰彇Y鏈�灏忕殑鐐圭储寮� + /// </summary> + public static int GetPointIndexByMinY(this List<CurvePoint> ptList) + { + var pt = GetPointByMinY(ptList); + return ptList.IndexOf(pt); + } + + /// <summary> + /// 鑾峰彇Y鏈�澶х殑鐐圭储寮� + /// </summary> + public static int GetPointIndexByMaxY(this List<CurvePoint> ptList) + { + var pt = GetPointByMaxY(ptList); + return ptList.IndexOf(pt); + } + + /// <summary> + /// 鏍规嵁X 鑾峰彇鐐圭储寮� + /// </summary> + public static int GetPointIndexByX(this List<CurvePoint> ptList, double x) + { + if (ptList == null || !ptList.Any()) + { + return -1; + } + int index = 0; + foreach (var pt in ptList) + { + if (Math.Abs(pt.X - x) < 0.0001) + { + return index; + } + index++; + } + return -1; + } + + /// <summary> + /// 鑾峰彇X鏂瑰悜璺濈鏈�灏忕殑鐐� + /// </summary> + public static CurvePoint GetClosestPointByX(this List<CurvePoint> ptList, double x) + { + if (ptList == null || ptList.Count < 1) + { + return default; + } + var pt = ptList.OrderBy(t => Math.Abs(t.X - x)).FirstOrDefault(); + return pt; + } + + /// <summary> + /// 鑾峰彇X鏂瑰悜璺濈鏈�灏忕殑鐐圭储寮� + /// </summary> + public static int GetClosestPointIndexByX(this List<CurvePoint> ptList, double x) + { + var pt = GetClosestPointByX(ptList, x); + return ptList.IndexOf(pt); + } + + + /// <summary> + /// 鑾峰緱Y鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�) + /// </summary> + public static List<double> GetInterPointX(this List<CurvePoint> ptList, double y) + { + if (ptList == null || ptList.Count < 1) + { + return default; + } + var list = ptList.ToList(); + var equalPoints = new List<double>(); + int num = list.Count(); + for (int i = 0; i < num - 1; i++)//灏戜竴涓偣 + { + if ((y >= list[i].Y && y <= list[i + 1].Y) || (y <= list[i].Y && y >= list[i + 1].Y)) + {//鐩寸嚎鎻掑�� + double x; + if (Math.Abs(list[i].Y - list[i + 1].Y) < 0.01) + x = (list[i].X + list[i + 1].X) * 0.5; + else + x = list[i].X + (list[i + 1].X - list[i].X) * (y - list[i].Y) / (list[i + 1].Y - list[i].Y); + + equalPoints.Add(x); + } + } + return equalPoints; + } + + /// <summary> + /// 鑾峰緱Y鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�) + /// </summary> + public static List<CurvePoint> GetPointsByInterPointX(this List<CurvePoint> ptList, double y) + { + if (ptList == null || ptList.Count < 1) + { + return default; + } + var list = ptList.ToList(); + var equalPoints = new List<CurvePoint>(); + int num = list.Count(); + for (int i = 0; i < num - 1; i++)//灏戜竴涓偣 + { + if ((y >= list[i].Y && y <= list[i + 1].Y) || (y <= list[i].Y && y >= list[i + 1].Y)) + {//鐩寸嚎鎻掑�� + double x; + if (Math.Abs(list[i].Y - list[i + 1].Y) < 0.01) + x = (list[i].X + list[i + 1].X) * 0.5; + else + x = list[i].X + (list[i + 1].X - list[i].X) * (y - list[i].Y) / (list[i + 1].Y - list[i].Y); + + equalPoints.Add(new CurvePoint(x, y)); + } + } + return equalPoints; + } + + /// <summary> + /// 鑾峰緱X鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�) + /// </summary> + public static List<double> GetInterPointY(this List<CurvePoint> ptList, double x) + { + if (ptList == null || ptList.Count < 1) + { + return default; + } + var list = ptList.ToList(); + var equalPoints = new List<double>(); + int num = ptList.Count; + for (int i = 0; i < num - 1; i++)//灏戜竴涓偣 + { + if ((x >= list[i].X && x <= list[i + 1].X) || (x <= list[i].X && x >= list[i + 1].X)) + {//鐩寸嚎鎻掑�� + double y; + if (Math.Abs(list[i].X - list[i + 1].X) < 0.01) + y = (list[i].Y + list[i + 1].Y) * 0.5; + else + y = list[i].Y + (list[i + 1].Y - list[i].Y) * (x - list[i].X) / (list[i + 1].X - list[i].X); + + equalPoints.Add(y); + } + } + return equalPoints; + } + + /// <summary> + /// 鑾峰緱X鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�) + /// </summary> + public static List<CurvePoint> GetPointsByInterPointY(this List<CurvePoint> ptList, double x) + { + if (ptList == null || ptList.Count < 1) + { + return default; + } + var list = ptList.ToList(); + var equalPoints = new List<CurvePoint>(); + int num = ptList.Count; + for (int i = 0; i < num - 1; i++)//灏戜竴涓偣 + { + if ((x >= list[i].X && x <= list[i + 1].X) || (x <= list[i].X && x >= list[i + 1].X)) + {//鐩寸嚎鎻掑�� + double y; + if (Math.Abs(list[i].X - list[i + 1].X) < 0.01) + y = (list[i].Y + list[i + 1].Y) * 0.5; + else + y = list[i].Y + (list[i + 1].Y - list[i].Y) * (x - list[i].X) / (list[i + 1].X - list[i].X); + + equalPoints.Add(new CurvePoint(x, y)); + } + } + return equalPoints; + } + + + + /// <summary> + /// 鑾峰緱X鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣,鍙栫涓�涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�) + /// </summary> + public static bool GetInterPointY(this List<CurvePoint> points, double x, out double y) + { + y = 0; + if (points == null) + return false; + + int num = points.Count(); + for (int i = 0; i < num - 1; i++)//灏戜竴涓偣 + { + if ((x >= points[i].X && x <= points[i + 1].X) || (x <= points[i].X && x >= points[i + 1].X)) + {//鐩寸嚎鎻掑�� + if (Math.Abs(points[i].X - points[i + 1].X) < 0.01) + y = (points[i].Y + points[i + 1].Y) * 0.5; + else + y = points[i].Y + (points[i + 1].Y - points[i].Y) * (x - points[i].X) / (points[i + 1].X - points[i].X); + + return true; + } + } + return false; + } + + /// <summary> + /// ptList 鏄竴涓杈瑰舰,鍒ゆ柇鐐规槸鍚﹀湪澶氳竟褰㈤噷 + /// 鍘熺悊鏄� 閫氳繃p鍋氫竴涓�+X鏂瑰悜鐨勫皠绾�, 鍋舵暟涓氦鐐� 灏辨槸鍦ㄥ閮�,濂囨暟涓氨鏄湪鍐呴儴 + /// </summary> + public static bool IsInPolygon(this IEnumerable<CurvePoint> ptList, CurvePoint p, bool isClosed = true) + { + if (ptList == null || ptList.Count() < 1) + return default; + var list = ptList.ToList(); + int crossNum = 0; + + for (int i = 0; i < list.Count() - 1; i++) + { + if (p.IsIntersectLineLeft(list[i], list[i + 1])) + { + crossNum++; + } + } + + if (isClosed) + { + if (p.IsIntersectLineLeft(list[list.Count - 1], list[0])) + { + crossNum++; + } + } + + if ((crossNum % 2) == 0) + return false; + else + return true; + } + + /// <summary> + /// 鏄惁瀹屽叏鐩稿悓 + /// </summary> + public static bool IsEqualValueX(this List<CurvePoint> ptList, List<CurvePoint> comparerPtList) + { + if (ptList == null || ptList.Count() == 0) + { + if (comparerPtList == null || comparerPtList.Count() == 0) + { + return true; + } + + return false; + } + + if (comparerPtList == null || comparerPtList.Count() == 0) + { + if (ptList == null || ptList.Count() == 0) + { + return true; + } + + return false; + } + + if (ptList.Count != comparerPtList.Count) + { + return false; + } + + for (int i = 0; i < ptList.Count; i++) + { + if (Math.Abs(ptList[i].X - comparerPtList[i].X) > 0.001) + { + return false; + } + } + + return true; + } + + + #region 鑾峰彇鎷熷悎鐐� + + /// <summary> + /// 鑾峰彇鎷熷悎鐐筜 + /// </summary> + public static double GetFitPointY(this List<CurvePoint> ptList, double x) + { + if (ptList == null) + return default; + var express = FitHelper.BuildCurveExpress(ptList, eFitType.CubicCurve); + if (express == null) + return default; + return express.GetFitPointY(x); + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐筜 + /// </summary> + public static double GetFitPointY(this List<CurvePoint> ptList, eFitType fitType, double x) + { + if (ptList == null) + return default; + var express = FitHelper.BuildCurveExpress(ptList, fitType); + if (express == null) + return default; + return express.GetFitPointY(x); + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐� + /// </summary> + public static List<CurvePoint> GetFitPoints(this List<CurvePoint> ptList, eFitType fitType = eFitType.CubicCurve, int pointNumber = 20) + { + if (ptList == null) + return default; + var express = FitHelper.BuildCurveExpress(ptList, fitType); + if (express == null) + return default; + return express.GetFitPoints(pointNumber); + } + + + /// <summary> + /// 鑾峰彇鎷熷悎鐐� + /// </summary> + public static List<CurvePoint> GetFitPointsByExtend(this List<CurvePoint> ptList, eFitType fitType, double ratioExtend, int pointNumber = 20) + { + if (ptList == null) + return default; + var fitPow = FitHelper.GetFitPow(fitType); + if (ptList.Count < fitPow + 1) + return default; + var express = FitHelper.BuildCurveExpress(ptList, fitType); + return express.GetFitPointsByExtend(ratioExtend, pointNumber); + } + + #endregion + + #region 鍙朰鐨勬渶澶ф渶灏忓�� + + + /// <summary> + /// 鍙朰鐨勬渶澶ф渶灏忓�� + /// </summary> + public static bool GetMinMaxPointY(this List<CurvePoint> ptList, out double maxY, out double minY) + { + if (ptList == null || !ptList.Any()) + { + maxY = minY = 0; + return false; + } + var fitPoints = ptList.ToList(); + maxY = fitPoints.Max(x => x.Y); + minY = fitPoints.Min(x => x.Y); ; + return true; + } + + /// <summary> + /// 鍙杙oints涓璝鐨勬渶澶у��(涓�瀹氬湪points涓�) + /// </summary> + public static CurvePoint GetMaxPointY(this List<CurvePoint> ptList) + { + if (ptList == null || !ptList.Any()) + { + return new CurvePoint(0, 0); + } + return ptList.OrderByDescending(x => x.Y).First(); + } + + #endregion 鍙朰鐨勬渶澶ф渶灏忓�� + + + #endregion + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/FitHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/FitHelper.cs new file mode 100644 index 0000000..a285db7 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/FitHelper.cs @@ -0,0 +1,274 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鏇茬嚎鎷熷悎杈呭姪绫� + /// </summary> + public class FitHelper + { + /// <summary> + /// + /// </summary> + public FitHelper(CurveExpress express) + { + switch (express.FitType) + { + case eFitType.ThroughPoint: _fitPoint = new TwinRelateCurve0(express); break; + case eFitType.LinearCurve: _fitPoint = new TwinRelateCurve1(express); break; + case eFitType.ConicCurveB0: _fitPoint = new TwinRelateCurve2B0(express); break; + case eFitType.ConicCurve: _fitPoint = new TwinRelateCurve2M(express); break; + case eFitType.CubicCurve: _fitPoint = new TwinRelateCurve3M(express); break; + case eFitType.FourM: _fitPoint = new TwinRelateCurve4M(express); break; + default: break; + } + } + + /// <summary> + /// + /// </summary> + public FitHelper(List<CurvePoint> points, eFitType fitType = eFitType.CubicCurve) + { + switch (fitType) + { + case eFitType.ThroughPoint: _fitPoint = new TwinRelateCurve0(points); break; + case eFitType.LinearCurve: _fitPoint = new TwinRelateCurve1(points); break; + case eFitType.ConicCurveB0: _fitPoint = new TwinRelateCurve2B0(points); break; + case eFitType.ConicCurve: _fitPoint = new TwinRelateCurve2M(points); break; + case eFitType.CubicCurve: _fitPoint = new TwinRelateCurve3M(points); break; + case eFitType.FourM: _fitPoint = new TwinRelateCurve4M(points); break; + default: break; + } + } + + + //鎷熷悎鎺ュ彛瀵硅薄 + private IFitPoint _fitPoint = null; + + /// <summary> + /// 鑾峰彇鏇茬嚎鎷熷悎鐐筜鍊� + /// </summary> + public double GetFitPointY(double x) + { + if (_fitPoint == null) + return default; + return _fitPoint.GetFitPointY(x); + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPoints(int pointNumber) + { + if (_fitPoint == null) + return default; + return _fitPoint.GetFitPoints(pointNumber); + } + + /// <summary> + /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber) + { + if (_fitPoint == null) + return default; + return _fitPoint.GetFitPointsByXRange(minX, maxX, pointNumber); + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐筜 + /// </summary> + public static double GetFitPointY(CurveExpress express, double x) + { + if (express == null) + return default; + var helper = new FitHelper(express); + return helper.GetFitPointY(x); + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐� + /// </summary> + public static List<CurvePoint> GetFitPoints(List<CurvePoint> points, eFitType fitType = eFitType.CubicCurve, int pointNumber = 12) + { + if (points == null || !points.Any()) + return default; + var express = BuildCurveExpress(points, fitType); + var helper = new FitHelper(express); + return helper.GetFitPoints(pointNumber); + } + + + /// <summary> + /// 鑾峰彇鎷熷悎鐐� + /// </summary> + public static List<CurvePoint> GetFitPoints(CurveExpress express, int pointNumber) + { + if (express == null) + return default; + var helper = new FitHelper(express); + return helper.GetFitPoints(pointNumber); + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐� + /// </summary> + public static List<CurvePoint> GetFitPointsByXRange(CurveExpress express, double minX, double maxX, int pointNumber) + { + if (express == null) + return default; + var helper = new FitHelper(express); + return helper.GetFitPointsByXRange(minX, maxX, pointNumber); + } + + /// <summary> + /// 鑾峰彇鎷熷悎娆℃柟 + /// </summary> + public static int GetFitPow(eFitType fitType) + { + switch (fitType) + { + case eFitType.CubicCurve: return 3; + case eFitType.ConicCurve: return 2; + case eFitType.ConicCurveB0: return 2; + case eFitType.LinearCurve: return 1; + case eFitType.ThroughPoint: return 0; + case eFitType.FourM: return 4; + default: return 3; + } + } + + /// <summary> + /// 鑾峰彇鎷熷悎绫诲瀷 + /// </summary> + public static eFitType GetFitType(int fitPow) + { + switch (fitPow) + { + case 3: return eFitType.CubicCurve; + case 2: return eFitType.ConicCurve; + case 1: return eFitType.LinearCurve; + case 0: return eFitType.ThroughPoint; + case 4: return eFitType.FourM; + default: return eFitType.CubicCurve; + } + } + + /// <summary> + /// 鍒涘缓鏇茬嚎琛ㄨ揪寮� + /// </summary> + public static CurveExpress BuildCurveExpress(List<CurvePoint> points, eFitType fitType = eFitType.CubicCurve) + { + if (points == null || !points.Any()) + { + return default; + } + switch (fitType) + { + case eFitType.ThroughPoint: return TwinRelateCurve0.BuildCurveExpress(points); + case eFitType.LinearCurve: return TwinRelateCurve1.BuildCurveExpress(points); + case eFitType.ConicCurveB0: return TwinRelateCurve2B0.BuildCurveExpress(points); + case eFitType.ConicCurve: return TwinRelateCurve2M.BuildCurveExpress(points); + case eFitType.CubicCurve: return TwinRelateCurve3M.BuildCurveExpress(points); + case eFitType.FourM: return TwinRelateCurve4M.BuildCurveExpress(points); + default: return default; + } + } + + #region 鑾峰緱X鍊� + + /// <summary> + /// 鑾峰彇绾挎�ф彃鍊糥锛堝彲鑳芥湁澶氫釜鐐癸級 + /// </summary> + public static List<CurvePoint> GetInterPointX(List<CurvePoint> pts, double y) + { + if (pts == null || pts.Count < 2) + { + return default; + } + var list = new List<CurvePoint>(); + for (int i = 0; i < pts.Count - 1; i++) + { + if ((y >= pts[i].Y && y <= pts[i + 1].Y) || (y <= pts[i].Y && y >= pts[i + 1].Y)) + {//鐩寸嚎鎻掑�� + double x; + if (Math.Abs(pts[i].Y - pts[i + 1].Y) < 0.01) + x = (pts[i].X + pts[i + 1].X) * 0.5; + else + x = pts[i].X + (pts[i + 1].X - pts[i].X) * (y - pts[i].Y) / (pts[i + 1].Y - pts[i].Y); + + list.Add(new CurvePoint(x, y)); + } + } + return list; + } + + /// <summary> + /// 鑾峰彇绾挎�ф彃鍊糥锛堝彲鑳芥湁澶氫釜鐐癸級(鍏佽寤堕暱) + /// </summary> + public static List<CurvePoint> GetInterPointXByExtend(List<CurvePoint> pts, double y) + { + if (pts == null || pts.Count < 2) + { + return default; + } + + //鍦ㄨ寖鍥村唴 + var minY = pts.Min(x => x.Y); + var maxY = pts.Max(x => x.Y); + if (y >= minY && y <= maxY) + { + return GetInterPointX(pts, y); + } + + var list = new List<CurvePoint>(); + + //鍒ゆ柇鏄惁鍦ㄥ墠闈㈢殑寤堕暱閮ㄥ垎 + double x_start = CurveLineHelper.GetXbyY(pts[0].X, pts[0].Y, pts[1].X, pts[1].Y, y); + if (x_start <= pts[0].X) + { + if (x_start > 0 && x_start > pts[0].X * 0.9)//鏀句竴鐐逛綑閲� + { + list.Add(new CurvePoint(x_start, y)); + } + } + + //鍒ゆ柇鏄惁鍦ㄥ悗闈㈢殑寤堕暱閮ㄥ垎:U鍨嬫洸绾� 鏄墠鍚庨兘鏈� + double x_end = CurveLineHelper.GetXbyY(pts[pts.Count - 2].X, pts[pts.Count - 2].Y, pts[pts.Count - 1].X, pts[pts.Count - 1].Y, y); + if (x_end >= pts[pts.Count - 1].X && x_end < pts[pts.Count - 1].X * 1.1)//鏀句竴鐐逛綑閲� + { + list.Add(new CurvePoint(x_end, y)); + } + + return list; + } + + /// <summary> + /// 鑾峰彇绾挎�ф彃鍊糥锛堝彲鑳芥湁澶氫釜鐐癸級 + /// </summary> + public static List<CurvePoint> GetInterPointX(CurveExpress express, double y, int pointNumber = 20, double extendRatio = 1.0) + { + if (express == null) + { + return default; + } + var pts = express.GetFitPointsByXRange(express.Min, express.Max * extendRatio, pointNumber); + return GetInterPointX(pts, y); + } + + /// <summary> + /// 鑾峰彇绾挎�ф彃鍊糥锛堝彲鑳芥湁澶氫釜鐐癸級(鍏佽寤堕暱) + /// </summary> + public static List<CurvePoint> GetInterPointXByExtend(CurveExpress express, double y, int pointNumber = 20, double extendRatio = 1.2) + { + if (express == null) + { + return default; + } + var pts = express.GetFitPointsByXRange(express.Min, express.Max * extendRatio, pointNumber); + return GetInterPointXByExtend(pts, y); + + } + + #endregion 鑾峰緱X鍊� + + } +} \ No newline at end of file diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/IFitPoint.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/IFitPoint.cs new file mode 100644 index 0000000..7e5417c --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/IFitPoint.cs @@ -0,0 +1,26 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// + /// </summary> + public interface IFitPoint + { + + /// <summary> + /// 鑾峰彇鎷熷悎鐐筜 + /// </summary> + double GetFitPointY(double x); + + /// <summary> + /// 鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + List<CurvePoint> GetFitPoints(int pointNumber); + + /// <summary> + /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber); + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve0.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve0.cs new file mode 100644 index 0000000..091cff0 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve0.cs @@ -0,0 +1,110 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 涓嶆嫙鍚� + /// </summary> + public class TwinRelateCurve0 : IFitPoint + { + /// <summary> + /// + /// </summary> + public TwinRelateCurve0(CurveExpress express) + { + _express = express; + } + + /// <summary> + /// + /// </summary> + public TwinRelateCurve0(List<CurvePoint> points) + { + if (points == null || points.Count < 4) + { + throw new Exception("鍑虹幇鏁板�艰绠楅棶棰�, 鏃犳硶瑙e嚭涓嶆嫙鍚堢嚎锛�"); + } + _express = BuildCurveExpress(points); + } + + //鏇茬嚎琛ㄨ揪寮� + private CurveExpress _express = null; + + + /// <summary> + /// 鑾峰彇鎷熷悎鐐筜 + /// </summary> + public double GetFitPointY(double x) + { + if (_express == null) + { + return default; + } + //灏介噺鐢ㄨ礉濉炲皵鏇茬嚎 + if (_express.DefinePoints != null && _express.DefinePoints.Count > 4) + { + var b = BezierCurveHelper.CreateOpenCurves(_express.DefinePoints); + var s = BezierCurveHelper.GetSectPointsByX(b, x); + if (s != null && s.Count > 0) + { + return s.Last().Y; + } + } + + if (_express.DefinePoints != null && _express.DefinePoints.Count > 1) + { + var sect = _express.DefinePoints.GetInterPointY(x); + if (sect == null || sect.Count < 1) + { + return default; + } + return sect.First(); + } + return default; + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPoints(int pointNumber) + { + if (_express == null) + { + return default; + } + return _express.DefinePoints; + } + + /// <summary> + /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber) + { + if (_express == null) + { + return default; + } + return _express.DefinePoints; + } + + /// <summary> + /// 鍒涘缓鏇茬嚎琛ㄨ揪寮� + /// </summary> + public static CurveExpress BuildCurveExpress(List<CurvePoint> points) + { + if (points == null || points.Count < 4) + { + return default; + } + points = points.OrderBy(x => x.X).ToList(); + var express = new CurveExpress + { + FitType = eFitType.ThroughPoint, + DefinePoints = points.Select(x => new CurvePoint(x)).ToList() + }; + express.Min = points.Min(x => x.X); + express.Max = points.Max(x => x.X); + + return express; + } + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve1.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve1.cs new file mode 100644 index 0000000..29e6b78 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve1.cs @@ -0,0 +1,106 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鐩寸嚎 + /// </summary> + public class TwinRelateCurve1 : IFitPoint + { + /// <summary> + /// + /// </summary> + public TwinRelateCurve1(CurveExpress express) + { + _express = express; + } + + /// <summary> + /// + /// </summary> + public TwinRelateCurve1(List<CurvePoint> points) + { + if (points == null || points.Count < 2) + { + throw new Exception("鍑虹幇鏁板�艰绠楅棶棰�, 鏃犳硶瑙e嚭鐩寸嚎锛�"); + } + + _express = BuildCurveExpress(points); + } + + //鏇茬嚎琛ㄨ揪寮� + private CurveExpress _express = null; + + /// <summary> + /// 鑾峰彇鎷熷悎鐐筜 + /// </summary> + public double GetFitPointY(double x) + { + if (_express == null) + return default; + return _express.Index1 * x + _express.Index0; + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPoints(int pointNumber) + { + if (_express == null) + return default; + return GetFitPointsByXRange(_express.Min, _express.Max, pointNumber); + } + + /// <summary> + /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber) + { + if (_express == null) + return default; + if (pointNumber < 2) + pointNumber = 2; + if (pointNumber > 100) + pointNumber = 100; + + double space = (maxX - minX) / (pointNumber - 1); + if (space < 0.0001) + return default; + var points = new List<CurvePoint>(); + for (int i = 0; i < pointNumber; i++) + { + double x = space * i + minX; + double y = GetFitPointY(x); + points.Add(new CurvePoint(x, y)); + } + return points; + } + + /// <summary> + /// 鍒涘缓鏇茬嚎琛ㄨ揪寮� + /// </summary> + public static CurveExpress BuildCurveExpress(List<CurvePoint> points) + { + if (points == null || points.Count < 2) + { + return default; + } + points = points.OrderBy(x => x.X).ToList(); + if (!CurveLineHelper.GetKandB(points.First(), points.Last(), out double k, out double b)) + { + return default; + } + var express = new CurveExpress + { + FitType = eFitType.LinearCurve, + DefinePoints = points.Select(x => new CurvePoint(x)).ToList(), + Min = points.First().X, + Max = points.Last().X, + Index0 = b, + Index1 = k + }; + + return express; + } + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_MathNet.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_MathNet.cs new file mode 100644 index 0000000..af83de7 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_MathNet.cs @@ -0,0 +1,126 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鏍锋潯鏇茬嚎锛堜簩娆℃嫙鍚堬級锛氫娇鐢∕ath.Net + /// </summary> + public class TwinRelateCurve2M : IFitPoint + { + /// <summary> + /// + /// </summary> + public TwinRelateCurve2M(CurveExpress express) + { + _express = express; + } + + /// <summary> + /// + /// </summary> + public TwinRelateCurve2M(List<CurvePoint> points) + { + if (points == null || points.Count < 3) + { + throw new Exception("鍑虹幇鏁板�艰绠楅棶棰�, 鏃犳硶瑙e嚭浜屾鎷熷悎鏇茬嚎锛�"); + } + + + _express = BuildCurveExpress(points); + } + + //鏇茬嚎琛ㄨ揪寮� + private CurveExpress _express = null; + + /// <summary> + /// 鑾峰彇鎷熷悎鐐筜 + /// </summary> + public double GetFitPointY(double x) + { + if (_express == null) + return default; + return _express.Index2 * x * x + _express.Index1 * x + _express.Index0; + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPoints(int pointNumber) + { + if (_express == null) + { + return default; + } + return GetFitPointsByXRange(_express.Min, _express.Max, pointNumber); + } + + /// <summary> + /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber) + { + if (_express == null) + { + return default; + } + if (pointNumber < 1) + { + pointNumber = 12; + } + if (pointNumber > 10000) + { + pointNumber = 10000; + } + + double space = (maxX - minX) / (pointNumber - 1); + if (space < 0.0001) + { + return default; + } + var points = new List<CurvePoint>(); + for (int i = 0; i < pointNumber; i++) + { + double x = space * i + minX; + double y = GetFitPointY(x); + points.Add(new CurvePoint(x, y)); + } + return points; + } + + /// <summary> + /// 鍒涘缓鏇茬嚎琛ㄨ揪寮� + /// </summary> + public static CurveExpress BuildCurveExpress(List<CurvePoint> points) + { + if (points == null || points.Count < 3) + { + return default; + } + points = points.OrderBy(x => x.X).ToList(); + CurveExpress express = new CurveExpress + { + FitType = eFitType.ConicCurve, + DefinePoints = points.Select(x => new CurvePoint(x)).ToList(), + Min = points.First().X, + Max = points.Last().X + }; + + var X = (from x in points select x.X).ToArray(); + var Y = (from x in points select x.Y).ToArray(); + var res = Fit.Polynomial(X, Y, 2); + + //0娆℃柟 + express.Index0 = res[0]; + //1娆℃柟 + express.Index1 = res[1]; + //2娆℃柟 + express.Index2 = res[2]; + //3娆℃柟 + express.Index3 = 0;// res[3]; + + return express; + } + + + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_b0.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_b0.cs new file mode 100644 index 0000000..4b42992 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_b0.cs @@ -0,0 +1,128 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鏍锋潯鏇茬嚎锛堜簩娆℃嫙鍚堬級B=0 + /// </summary> + public class TwinRelateCurve2B0 : IFitPoint + { + /// <summary> + /// + /// </summary> + public TwinRelateCurve2B0(CurveExpress express) + { + _express = express; + } + + /// <summary> + /// + /// </summary> + public TwinRelateCurve2B0(List<CurvePoint> points) + { + if (points == null || points.Count < 3) + { + throw new Exception("鍑虹幇鏁板�艰绠楅棶棰�, 鏃犳硶瑙e嚭浜屾鎷熷悎鏇茬嚎(B=0)锛�"); + } + _express = BuildCurveExpress(points); + } + + //鏇茬嚎琛ㄨ揪寮� + private CurveExpress _express = null; + + /// <summary> + /// 鑾峰彇鎷熷悎鐐筜 + /// </summary> + public double GetFitPointY(double x) + { + if (_express == null) + { + return default; + } + return _express.Index2 * x * x + _express.Index0; + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPoints(int pointNumber) + { + if (_express == null) + { + return default; + } + return GetFitPointsByXRange(_express.Min, _express.Max, pointNumber); + } + + /// <summary> + /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber) + { + if (_express == null) + { + return default; + } + if (pointNumber < 1) + { + pointNumber = 12; + } + if (pointNumber > 10000) + { + pointNumber = 10000; + } + + double space = (maxX - minX) / (pointNumber - 1); + if (space < 0.0001) + { + return default; + } + var points = new List<CurvePoint>(); + for (int i = 0; i < pointNumber; i++) + { + double x = space * i + minX; + double y = GetFitPointY(x); + points.Add(new CurvePoint(x, y)); + } + return points; + } + + /// <summary> + /// 鍒涘缓鏇茬嚎琛ㄨ揪寮� + /// </summary> + public static CurveExpress BuildCurveExpress(List<CurvePoint> points) + { + if (points == null || points.Count < 3) + { + return default; + } + points = points.OrderBy(x => x.X).ToList(); + var count = points.Count; + var express = new CurveExpress + { + FitType = eFitType.ConicCurveB0, + DefinePoints = points.Select(x => new CurvePoint(x)).ToList(), + Min = points.First().X, + Max = points.Last().X + }; + + double rTotalH = 0.0; + double rTotalHQ2 = 0.0; + double rTotalQ2 = 0.0; + double rTotalQ4 = 0.0; + + for (int i = 0; i < count; i++) + { + rTotalH = rTotalH + points[i].Y; + rTotalHQ2 = rTotalHQ2 + points[i].Y * points[i].X * points[i].X; + rTotalQ2 = rTotalQ2 + points[i].X * points[i].X; + rTotalQ4 = rTotalQ4 + Math.Pow(points[i].X, 4); + } + express.Index2 = (rTotalH * rTotalQ2 - count * rTotalHQ2) / ((rTotalQ2 * rTotalQ2) - count * rTotalQ4); + express.Index0 = (rTotalQ2 * rTotalHQ2 - rTotalQ4 * rTotalH) / ((rTotalQ2 * rTotalQ2) - count * rTotalQ4); + + return express; + } + + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve3_MathNet.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve3_MathNet.cs new file mode 100644 index 0000000..4bd2b63 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve3_MathNet.cs @@ -0,0 +1,174 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鏍锋潯鏇茬嚎锛堜笁娆℃嫙鍚堬級锛氫娇鐢∕athNet + /// </summary> + public class TwinRelateCurve3M : IFitPoint + { + /// <summary> + /// + /// </summary> + public TwinRelateCurve3M(CurveExpress express) + { + _express = express; + } + + /// <summary> + /// + /// </summary> + public TwinRelateCurve3M(List<CurvePoint> points) + { + if (points == null || points.Count < 4) + { + throw new Exception("鍑虹幇鏁板�艰绠楅棶棰� 锛屾棤娉曡В鍑轰笁娆℃牱鏉℃洸绾匡紒"); + } + + _express = BuildCurveExpress(points); + } + + //鏇茬嚎琛ㄨ揪寮� + private CurveExpress _express = null; + + /// <summary> + /// 鑾峰彇鎷熷悎鐐筜 + /// </summary> + public double GetFitPointY(double x) + { + if (_express == null) + return default; + var dx = x;// - _express.Min; //涓嶇敤鍑忔帀鏈�灏忓��, 鍜宎lglib鏈夌偣涓嶄竴鏍� + return _express.Index3 * dx * dx * dx + _express.Index2 * dx * dx + _express.Index1 * dx + _express.Index0; + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPoints(int pointNumber) + { + if (_express == null) + { + return null; + } + + if (pointNumber < 1) + { + pointNumber = 12; + } + if (pointNumber > 10000) + { + pointNumber = 10000; + } + double space = (_express.Max - _express.Min) / (pointNumber - 1); + if (space < 0.0001) + { + return null; + } + List<CurvePoint> points = new List<CurvePoint>(); + for (int i = 0; i < pointNumber; i++) + { + double x = space * i + _express.Min; + double y = GetFitPointY(x); + points.Add(new CurvePoint(x, y)); + } + return points; + } + + /// <summary> + /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber) + { + if (pointNumber < 1) + { + pointNumber = 12; + } + if (pointNumber > 10000) + { + pointNumber = 10000; + } + if (minX >= maxX) + {//浜ゆ崲澶у皬 + var x_m = maxX; + maxX = minX; + minX = x_m; + } + double space = (maxX - minX) / (pointNumber - 1); + if (space < 0.0001) + { + return default; + } + + if (_express == null) + { + return null; + } + + if (pointNumber < 1) + { + pointNumber = 12; + } + if (pointNumber > 10000) + { + pointNumber = 10000; + } + + if (space < 0.0001) + { + return null; + } + List<CurvePoint> points = new List<CurvePoint>(); + for (int i = 0; i < pointNumber; i++) + { + double x = space * i + minX; + double y = GetFitPointY(x); + points.Add(new CurvePoint(x, y)); + } + return points; + } + + /// <summary> + /// 鍒涘缓鏇茬嚎琛ㄨ揪寮� + /// </summary> + public static CurveExpress BuildCurveExpress(List<CurvePoint> points) + { + if (points == null || points.Count < 4) + return null; + var express = new CurveExpress(); + express.DefinePoints = points; + + var X = (from x in points select x.X).ToArray(); + var Y = (from x in points select x.Y).ToArray(); + + var min = X.Min(); + var max = X.Max(); + var res = Fit.Polynomial(X, Y, 3); + + //鏇茬嚎绫诲瀷 + express.FitType = eFitType.CubicCurve; + express.DefinePoints = points.Select(x => new CurvePoint(x)).ToList(); + + //鑼冨洿 + express.Min = X.Min(); //鏈�灏忓�� + express.Max = X.Max();//鏈�澶у�� + + + //0娆℃柟 + express.Index0 = res[0]; + //1娆℃柟 + express.Index1 = res[1]; + //2娆℃柟 + express.Index2 = res[2]; + //3娆℃柟 + express.Index3 = res[3]; + + return express; + } + + + + + + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve4_MathNet.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve4_MathNet.cs new file mode 100644 index 0000000..b660e64 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve4_MathNet.cs @@ -0,0 +1,113 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鏍锋潯鏇茬嚎锛堝洓娆℃嫙鍚堬級锛氫娇鐢∕ATH.net + /// </summary> + public class TwinRelateCurve4M : IFitPoint + { + /// <summary> + /// + /// </summary> + public TwinRelateCurve4M(CurveExpress express) + { + _express = express; + } + + /// <summary> + /// + /// </summary> + public TwinRelateCurve4M(List<CurvePoint> points) + { + if (points == null || points.Count < 5) + { + throw new Exception("鍑虹幇鏁板�艰绠楅棶棰� 锛屾棤娉曡В鍑哄洓娆℃牱鏉℃洸绾�!"); + } + + _express = BuildCurveExpress(points); + } + + //鏇茬嚎琛ㄨ揪寮� + private CurveExpress _express = null; + + + /// <summary> + /// 鑾峰彇鎷熷悎鐐筜 + /// </summary> + public double GetFitPointY(double x) + { + if (_express == null) + return default; + //涓嶇敤鍑忔帀鏈�灏忓��, 鍜宎lglib鏈夌偣涓嶄竴鏍� + return _express.Index4 * x * x * x * x + _express.Index3 * x * x * x + _express.Index2 * x * x + _express.Index1 * x + _express.Index0; + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPoints(int pointNumber) + { + if (_express == null) + return default; + return GetFitPointsByXRange(_express.Min, _express.Max, pointNumber); + } + + /// <summary> + /// 閫氳繃鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛� + /// </summary> + public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber) + { + if (_express == null) + return default; + + if (pointNumber < 1) + pointNumber = 12; + if (pointNumber > 10000) + pointNumber = 10000; + double space = (maxX - minX) / (pointNumber - 1); + if (space < 0.0001) + return default; + var points = new List<CurvePoint>(); + for (int i = 0; i < pointNumber; i++) + { + double x = space * i + minX; + double y = this.GetFitPointY(x); + points.Add(new CurvePoint(x, y)); + } + return points; + } + + /// <summary> + /// 鍒涘缓鏇茬嚎琛ㄨ揪寮� + /// </summary> + public static CurveExpress BuildCurveExpress(List<CurvePoint> points) + { + if (points == null || points.Count < 5) + return default; + + points = points.OrderBy(x => x.X).ToList(); + CurveExpress express = new CurveExpress(); + express.FitType = eFitType.FourM; + express.DefinePoints = points.Select(x => new CurvePoint(x)).ToList(); + express.Min = points.First().X; + express.Max = points.Last().X; + + var X = (from x in points select x.X).ToArray(); + var Y = (from x in points select x.Y).ToArray(); + var res = MathNet.Numerics.Fit.Polynomial(X, Y, 4); + + //0娆℃柟 + express.Index0 = res[0]; + //1娆℃柟 + express.Index1 = res[1]; + //2娆℃柟 + express.Index2 = res[2]; + //3娆℃柟 + express.Index3 = res[3]; + //4娆℃柟 + express.Index4 = res[4]; + + return express; + } + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/eFitType.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/eFitType.cs new file mode 100644 index 0000000..0c0c2fe --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/eFitType.cs @@ -0,0 +1,45 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鎷熷悎绫诲瀷 + /// </summary> + public enum eFitType + { + /// <summary> + /// 涓嶆嫙鍚� + /// </summary> + [Description("涓嶆嫙鍚�")] + ThroughPoint = -1, + + /// <summary> + /// 涓夋鏍锋潯鎷熷悎 + /// </summary> + [Description("涓夋鏍锋潯鎷熷悎")] + CubicCurve = 0, + + /// <summary> + /// 浜屾鏇茬嚎鎷熷悎 + /// </summary> + [Description("浜屾鏇茬嚎鎷熷悎")] + ConicCurve = 1, + + /// <summary> + /// 浜屾鏇茬嚎鎷熷悎B=0 + /// </summary> + [Description("浜屾鏇茬嚎鎷熷悎B=0")] + ConicCurveB0 = 2, + + /// <summary> + /// 鐩寸嚎鎷熷悎 + /// </summary> + [Description("鐩寸嚎鎷熷悎")] + LinearCurve = 3, + + /// <summary> + /// 鍥涙鏍锋潯鎷熷悎 + /// </summary> + [Description("鍥涙鏍锋潯鎷熷悎")] + FourM = 4, + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLine.cs b/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLine.cs new file mode 100644 index 0000000..96ff7b6 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLine.cs @@ -0,0 +1,298 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鏇茬嚎鐩寸嚎 + /// </summary> + public class CurveLine : ICloneable + { + /// <summary> + /// + /// </summary> + public CurveLine() { } + + /// <summary> + /// + /// </summary> + public CurveLine(double x1, double y1, double x2, double y2) + { + this.Point0 = new CurvePoint(x1, y1); + this.Point1 = new CurvePoint(x2, y2); + } + + /// <summary> + /// + /// </summary> + public CurveLine(CurvePoint pt1, CurvePoint pt2) + { + this.Point0 = pt1; + this.Point1 = pt2; + } + + /// <summary> + /// + /// </summary> + public CurveLine(List<CurvePoint> pts) + { + if (pts == null || pts.Count < 2) + { + throw new Exception("鍙傛暟閿欒锛屾棤娉曡В鏋愬嚭鐩寸嚎锛�"); + } + this.Point0 = pts[0]; + this.Point1 = pts[1]; + } + + /// <summary> + /// + /// </summary> + public CurveLine(CurveLine rhs) + { + this.Point0 = new CurvePoint(rhs.Point0); + this.Point1 = new CurvePoint(rhs.Point1); + } + + /// <summary> + /// 绗竴涓偣 + /// </summary> + public CurvePoint Point0 { get; set; } + + /// <summary> + /// 绗簩涓偣 + /// </summary> + public CurvePoint Point1 { get; set; } + + /// <summary> + /// 鑾峰彇鎻掑�糦 + /// </summary> + public double GetInsertY(double x) + { + if (Math.Abs(this.Point1.X - this.Point0.X) < 0.000001) + { + return 0; + } + if (Math.Abs(this.Point1.Y - this.Point0.Y) < 0.000001) + { + return 0; + } + return this.Point0.Y + (this.Point1.Y - this.Point0.Y) / (this.Point1.X - this.Point0.X) * (x - this.Point0.X); + } + + /// <summary> + /// 鏄惁涓�涓偣鍚憍杞寸殑灏勭嚎绌块�忕嚎娈�,鏈変氦鐐逛笖鍦ㄧ嚎鐨勫乏杈� + /// </summary> + public bool IsIntersectLeft(CurvePoint pt) + { + double maxY = this.Point0.Y > this.Point1.Y ? this.Point0.Y : this.Point1.Y; + double minY = this.Point0.Y > this.Point1.Y ? this.Point1.Y : this.Point0.Y; + + if (Math.Abs(this.Point1.Y - this.Point0.Y) < 0.000001) + { + if (Math.Abs(pt.Y - this.Point0.Y) < 0.000001) + return true; + return false; + } + + + bool IsInLine = false; + if (pt.Y < maxY && pt.Y >= minY) + { + if (pt.X <= (this.Point0.X + (this.Point1.X - this.Point0.X) * (pt.Y - this.Point0.Y) / (this.Point1.Y - this.Point0.Y))) + { + IsInLine = true; + } + } + return IsInLine; + } + + /// <summary> + /// 鑾峰彇鍐呴儴鐐� + /// </summary> + public CurvePoint GetInnerPoint(double ratio) + { + var x = this.Point0.X + ratio * (this.Point1.X - this.Point0.X); + var y = this.Point0.Y + ratio * (this.Point1.Y - this.Point0.Y); + return new CurvePoint(x, y); + } + + /// <summary> + /// 鑾峰彇鍐呴儴X鍧愭爣 + /// </summary> + public double GetInnerX(double ratio) + { + var x = this.Point0.X + ratio * (this.Point1.X - this.Point0.X); + return x; + } + + /// <summary> + /// 鑾峰彇鍐呴儴Y鍧愭爣 + /// </summary> + public double GetInnerY(double ratio) + { + var y = this.Point0.Y + ratio * (this.Point1.Y - this.Point0.Y); + return y; + } + + /// <summary> + /// 杩斿洖鐩寸嚎鐨刱鍜宐 y=kx+b + /// </summary> + public bool GetKandB(out double k, out double b, double ignore = 0.000001) + { + k = b = 0; + + if (Math.Abs(this.Point0.X - this.Point1.X) < ignore) + {//绔栫洿 + k = 100000000; + b = this.Point0.X; + return false; + } + if (Math.Abs(this.Point0.Y - this.Point1.Y) < ignore) + {//骞宠 + k = 0; + b = this.Point0.X; + return true; + } + + + k = (this.Point0.Y - this.Point1.Y) / (this.Point0.X - this.Point1.X);// Math.Atan((pt1.Y - pt2.Y) / (pt1.X - pt2.X)) * 180 / Math.PI; + b = this.Point0.Y - k * this.Point0.X; + return true; + } + + /// <summary> + /// 閫氳繃 X 鑾峰彇 Y + /// </summary> + public double GetYByX(double x) + { + if (!GetKandB(out double k, out double b)) + { + return this.Point0.Y; + } + return k * x + b; + } + + /// <summary> + /// 閫氳繃 Y 鑾峰彇 X + /// </summary> + public double GetXByY(double y) + { + if (!GetKandB(out double k, out double b)) + { + return this.Point0.X; + } + return (y - b) / k; + } + + /// <summary> + /// 鑾峰彇涓棿鐐� + /// </summary> + public CurvePoint GetMiddlePoint() + { + return new CurvePoint((this.Point0.X + this.Point1.X) * 0.5, (this.Point0.Y + this.Point1.Y) * 0.5); + } + + /// <summary> + /// 閫氳繃 X 鍒ゆ柇鏄惁涓哄唴閮ㄧ偣 + /// </summary> + public bool IsInnerByX(double x) + { + if (x >= this.Point0.X && x <= this.Point1.X) + return true; + if (x >= this.Point1.X && x <= this.Point0.X) + return true; + return false; + } + + /// <summary> + /// 閫氳繃 Y 鍒ゆ柇鏄惁涓哄唴閮ㄧ偣 + /// </summary> + public bool IsInnerByY(double y) + { + if (y >= this.Point0.Y && y <= this.Point1.Y) + return true; + if (y >= this.Point1.Y && y <= this.Point0.Y) + return true; + return false; + } + + /// <summary> + /// 涓変釜鐐瑰湪鍚屼竴鏉$洿绾夸笂,杈撳叆(X1,Y1),(X2,Y2)浠ュ強娌�(X2,Y2)渚у欢闀縇ength,寰楀埌鐨勭偣(X3,Y3) + /// </summary> + public CurvePoint GetExtendPoint(double length) + { + double betweenLength = this.Point0.Distance(this.Point1); + if (betweenLength < 0.01) + return this.Point0; + + var extPt = new CurvePoint(); + extPt.X = (this.Point1.X - this.Point0.X) * length / betweenLength + this.Point1.X; + extPt.Y = (this.Point1.Y - this.Point0.Y) * length / betweenLength + this.Point1.Y; + + return extPt; + } + + /// <summary> + /// 姹傜洿绾垮涓�鐐瑰埌璇ョ洿绾跨殑鎶曞奖鐐� + /// </summary> + public CurvePoint GetProjectivePoint(CurvePoint pOut) + { + if (!GetKandB(out double k, out double b)) + return default; + return GetProjectivePoint(this.Point0, k, pOut); + } + + /// <summary> + /// 鐐瑰埌绾跨殑璺濈, 娉ㄦ剰涓嶄竴瀹氭槸鍨傜洿璺濈,鐐瑰彧鍦�(line_start鍜宭ine_end涔嬮棿 + /// </summary> + public double Distance(CurvePoint pt) + { + var project_pt = GetProjectivePoint(pt); + if (IsInnerByX(pt.X)) + return project_pt.Distance(pt); + var dis1 = this.Point0.Distance(pt); + var dis2 = this.Point1.Distance(pt); + if (dis1 < dis2) + return dis1; + else + return dis2; + } + + /// <summary> + /// 姹傜洿绾垮涓�鐐瑰埌璇ョ洿绾跨殑鎶曞奖鐐� + /// </summary> + /// <param name="pl">绾夸笂浠讳竴鐐�</param> + /// <param name="k">鐩寸嚎鏂滅巼</param> + /// <param name="pout">绾垮鎸囧畾鐐�</param> + public static CurvePoint GetProjectivePoint(CurvePoint pl, double k, CurvePoint pout) + { + CurvePoint pProject = new CurvePoint(); + if (k == 0) //鍨傜嚎鏂滅巼涓嶅瓨鍦ㄦ儏鍐� + { + pProject.X = pout.X; + pProject.Y = pout.Y; + } + else + { + pProject.X = (float)((k * pl.X + pout.X / k + pout.Y - pl.Y) / (1 / k + k)); + pProject.Y = (float)(-1 / k * (pProject.X - pout.X) + pout.Y); + } + return pProject; + } + + + /// <summary> + /// + /// </summary> + public CurveLine Clone() + { + return new CurveLine(this); + } + + /// <summary> + /// + /// </summary> + object ICloneable.Clone() + { + return this.Clone(); + } + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLineHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLineHelper.cs new file mode 100644 index 0000000..4059406 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLineHelper.cs @@ -0,0 +1,225 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鐩寸嚎杈呭姪绫� + /// </summary> + public static class CurveLineHelper + { + /// <summary> + /// 鏄惁鍨傜洿 + /// </summary> + /// <param name="k"></param> + /// <returns></returns> + public static bool IsVerticalK(double k) + { + if (k >= _verticalK - 1) + return true; + else + return false; + } + private const double _verticalK = 100000000;//鍨傜洿鏃禟鐨勫�� + + /// <summary> + /// 鑾峰彇鎻掑�糦 + /// </summary> + public static double GetInsertY(double x1, double y1, double x2, double y2, double x) + { + return new CurveLine(x1, y1, x2, y2).GetInsertY(x); + } + + /// <summary> + /// 鏄惁涓�涓偣鍚憍杞寸殑灏勭嚎绌块�忕嚎娈�,鏈変氦鐐逛笖鍦ㄧ嚎鐨勫乏杈� + /// </summary> + public static bool IsIntersectLeft(CurvePoint pt1, CurvePoint pt2, CurvePoint pt) + { + return new CurveLine(pt1, pt2).IsIntersectLeft(pt); + } + + /// <summary> + /// 鏄惁涓�涓偣鍚憍杞寸殑灏勭嚎绌块�忕嚎娈�,鏈変氦鐐逛笖鍦ㄧ嚎鐨勫乏杈� + /// </summary> + public static bool IsIntersectLeft(double x1, double y1, double x2, double y2, double x, double y) + { + return new CurveLine(x1, y1, x2, y2).IsIntersectLeft(new CurvePoint(x, y)); + } + + /// <summary> + /// X1鍜孹2涔嬮棿杩炰竴鏉$嚎, 鍦ㄦ瘮鐜噐atio澶勭偣鐨勫潗鏍� + /// </summary> + public static double GetInnerX(double x1, double x2, double ratio) + { + double x = x1 + ratio * (x2 - x1); + return x; + } + + /// <summary> + /// X1,Y1鍜孹2 Y2涔嬮棿杩炰竴鏉$嚎,鍦╔澶勭偣鐨刌鍧愭爣 + /// </summary> + public static double GetYbyX(double x1, double y1, double x2, double y2, double x) + { + return new CurveLine(x1, y1, x2, y2).GetYByX(x); + } + + /// <summary> + /// X1,Y1鍜孹2 Y2涔嬮棿杩炰竴鏉$嚎,鍦╕澶勭偣鐨刋鍧愭爣 + /// </summary> + public static double GetXbyY(double x1, double y1, double x2, double y2, double y) + { + return new CurveLine(x1, y1, x2, y2).GetXByY(y); + } + + /// <summary> + /// 杈撳叆(X1,Y1),(X1,Y1)鐢熸垚鐩寸嚎,杩斿洖鐩寸嚎鐨刱鍜宐 y=kx+b + /// </summary> + public static bool GetKandB(double x1, double y1, double x2, double y2, out double k, out double b, double ignore = 0.000001) + { + return new CurveLine(x1, y1, x2, y2).GetKandB(out k, out b, ignore); + } + + /// <summary> + /// 閫氳繃2鐐�,寰楀埌閫氳繃杩�2鐐圭殑鐩寸嚎鐨刱,b 绾跨殑褰㈠紡鏄� y=k*x+b,绔栫洿杩斿洖false + /// </summary> + public static bool GetKandB(CurvePoint pt1, CurvePoint pt2, out double k, out double b, double ignore = 0.000001) + { + return new CurveLine(pt1, pt2).GetKandB(out k, out b, ignore); + } + + /// <summary> + /// 鍙栦腑闂寸偣 + /// </summary> + public static CurvePoint GetMiddlePoint(CurvePoint pt1, CurvePoint pt2) + { + return new CurveLine(pt1, pt2).GetMiddlePoint(); + } + + /// <summary> + /// 鍙栧唴閮ㄧ偣 + /// </summary> + public static CurvePoint GetInnerPoint(CurvePoint startPt, CurvePoint endPt, double ratio) + { + return new CurveLine(startPt, endPt).GetInnerPoint(ratio); + } + + /// <summary> + /// 鏄惁鏄唴閮ㄧ偣 + /// </summary> + public static bool IsInnerByX(CurvePoint startPt, CurvePoint endPt, double x) + { + return new CurveLine(startPt, endPt).IsInnerByX(x); + } + + /// <summary> + /// 涓変釜鐐瑰湪鍚屼竴鏉$洿绾夸笂,杈撳叆(X1,Y1),(X2,Y2)浠ュ強娌�(X2,Y2)渚у欢闀縇ength,寰楀埌鐨勭偣(X3,Y3) + /// </summary> + public static CurvePoint GetExtendPoint(CurvePoint startPt, CurvePoint endPt, double length) + { + return new CurveLine(startPt, endPt).GetExtendPoint(length); + } + + /// <summary> + /// 姹傜洿绾垮涓�鐐瑰埌璇ョ洿绾跨殑鎶曞奖鐐� + /// </summary> + /// <param name="pl">绾夸笂浠讳竴鐐�</param> + /// <param name="k">鐩寸嚎鏂滅巼</param> + /// <param name="pout">绾垮鎸囧畾鐐�</param> + public static CurvePoint GetProjectivePoint(CurvePoint pl, double k, CurvePoint pout) + { + CurvePoint pProject = new CurvePoint(); + if (k == 0) //鍨傜嚎鏂滅巼涓嶅瓨鍦ㄦ儏鍐� + { + pProject.X = pout.X; + pProject.Y = pl.Y; + } + else + { + pProject.X = (float)((k * pl.X + pout.X / k + pout.Y - pl.Y) / (1 / k + k)); + pProject.Y = (float)(-1 / k * (pProject.X - pout.X) + pout.Y); + } + return pProject; + } + + /// <summary> + /// 姹傜洿绾垮涓�鐐瑰埌璇ョ洿绾跨殑鎶曞奖鐐� + /// </summary> + /// <param name="pLine1"></param> + /// <param name="pLine2"></param> + /// <param name="pOut"></param> + /// <returns></returns> + public static CurvePoint GetProjectivePoint(CurvePoint pLine1, CurvePoint pLine2, CurvePoint pOut) + { + if (!GetKandB(pLine1, pLine2, out double k, out double b)) + return default; + return GetProjectivePoint(pLine1, k, pOut); + } + + /// <summary> + /// 鐐瑰埌绾跨殑璺濈, 娉ㄦ剰涓嶄竴瀹氭槸鍨傜洿璺濈,鐐瑰彧鍦�(line_start鍜宭ine_end涔嬮棿 + /// </summary> + public static double Distance(CurvePoint line_start, CurvePoint line_end, CurvePoint point) + { + return new CurveLine(line_start, line_end).Distance(point); + } + + /// <summary> + /// 璁$畻浜ょ偣(娌℃湁 灏辫繑鍥瀗ull) + /// </summary> + public static IStation.Curve.CurvePoint GetCrossPoint(IStation.Curve.CurvePoint startPt1, IStation.Curve.CurvePoint endPt1, IStation.Curve.CurvePoint startPt2, IStation.Curve.CurvePoint endPt2) + { + if (startPt1 == null || endPt1 == null) + return null; + if (startPt2 == null || endPt2 == null) + return null; + + double k1, b1; + GetKandB(startPt1, endPt1, out k1, out b1); + + double k2, b2; + GetKandB(startPt2, endPt2, out k2, out b2); + + if (Math.Abs(k1 - k2) < 0.000001) + return null; + + if (k1 == _verticalK) + {//鍨傜洿 + return new IStation.Curve.CurvePoint(startPt1.X, startPt1.X * k2 + b2); + } + if (k2 == _verticalK) + {//鍨傜洿 + return new IStation.Curve.CurvePoint(startPt2.X, startPt2.X * k1 + b1); + } + + double sect_x = (b2 - b1) / (k1 - k2); + return new IStation.Curve.CurvePoint(sect_x, sect_x * k1 + b1); + } + + + /// <summary> + /// 鏄惁骞宠 + /// </summary> + /// <param name="startPt1"></param> + /// <param name="endPt1"></param> + /// <param name="startPt2"></param> + /// <param name="endPt2"></param> + /// <returns></returns> + public static bool IsParallel(IStation.Curve.CurvePoint startPt1, IStation.Curve.CurvePoint endPt1, IStation.Curve.CurvePoint startPt2, IStation.Curve.CurvePoint endPt2) + { + if (startPt1 == null || endPt1 == null) + return false; + if (startPt2 == null || endPt2 == null) + return false; + + double k1, b1; + GetKandB(startPt1, endPt1, out k1, out b1); + + double k2, b2; + GetKandB(startPt2, endPt2, out k2, out b2); + + if (Math.Abs(k1 - k2) < 0.000001) + return true; + else + return false; + } + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Parabola/ParabolaCurveHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Parabola/ParabolaCurveHelper.cs new file mode 100644 index 0000000..259e0ee --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Parabola/ParabolaCurveHelper.cs @@ -0,0 +1,516 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鎶涚墿绾� Parabola : H=K*Q^2 + S (娴侀噺鎵▼绾�) + /// </summary> + public class ParabolaCurveHelper + { + //閫氳繃鐐箂imularPoint鍜岀偣(0,0)鐨勬姏鐗╃嚎,涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0)) + //鏇茬嚎鍏紡锛欻=K*Q^2+S (S灏辨槸equipCurveZeroH瑁呯疆鏇茬嚎闈欐壃绋�) + //equipCurveZeroH鏄缃洸绾跨殑闈欐壃绋�,褰換=0鏃剁殑鎵▼ + public static IStation.Curve.CurvePoint GetSectPoint(IStation.Curve.CurveExpress curveExpress, IStation.Curve.CurvePoint simularPoint, double equipCurveZeroH) + { + //if (curveExpress.FitType == eFitType.ThroughPoint) + //{ + // var points = IStation.Curve.BezierCurveHelper.GetMultiplyPoints(curveExpress.DefinePoints, 3); + // return GetSectPoint(points, simularPoint, equipCurveZeroH); + //} + //else + { + var curveExpress2 = new IStation.Curve.CurveExpress(curveExpress); + curveExpress2.Max = curveExpress2.Max * 1.2; + var points = IStation.Curve.FitHelper.GetFitPoints(curveExpress2, 50); + return GetSectPoint(points, simularPoint, equipCurveZeroH); + } + } + + /// <summary> + /// + /// </summary> + /// <param name="curveExpress"></param> + /// <param name="simularPoint"></param> + /// <param name="equipCurveZeroH"></param> + /// <param name="ratioExtend"></param> + /// <returns></returns> + public static IStation.Curve.CurvePoint GetSectPoint(IStation.Curve.CurveExpress curveExpress, IStation.Curve.CurvePoint simularPoint, double equipCurveZeroH, + double ratioExtend) + { + //if (curveExpress.FitType == eFitType.ThroughPoint) + //{ + // if (curveExpress.DefinePoints == null || curveExpress.DefinePoints.Count() < 3) + // return null; + + // var points = IStation.Curve.BezierCurveHelper.GetMultiplyPoints(curveExpress.DefinePoints, 3); + // return GetSectPoint(points, simularPoint, equipCurveZeroH); + //} + //else + { + var curveExpress2 = new IStation.Curve.CurveExpress(curveExpress); + curveExpress2.Max = curveExpress2.Max * ratioExtend; + var points = IStation.Curve.FitHelper.GetFitPoints(curveExpress2, 50); + //var points = IStation.Curve.FitHelper.GetFitPointsByExtend(curveExpress, ratioExtend, 50); + return GetSectPoint(points, simularPoint, equipCurveZeroH); + } + } + + //閫氳繃鐐箂imularPoint鍜岀偣(0,0)鐨勬姏鐗╃嚎,涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0)) + //鏇茬嚎鍏紡锛欻=K*Q^2+S (S灏辨槸equipCurveZeroH瑁呯疆鏇茬嚎闈欐壃绋�) + //S鏄缃洸绾跨殑闈欐壃绋�,褰換=0鏃剁殑鎵▼ + public static IStation.Curve.CurvePoint GetSectPoint(List<IStation.Curve.CurvePoint> CurvePoints, IStation.Curve.CurvePoint simularPoint, double equipCurveZeroH) + { + IStation.Curve.CurvePoint sectPoint = new IStation.Curve.CurvePoint(0, 0); + if (CurvePoints == null || CurvePoints.Count < 2) + return sectPoint; + //if (simularPoint.X < CurvePoints.First().X) + // return sectPoint; + + //if (DesignPoint.X > CurvePoints.Last().X) + // return sectPoint; + + + //璁$畻鎶涚墿绾跨殑K (a) + if (simularPoint.X < 0.1) + {//X=0 + return CurvePoints.First(); + } + + if (simularPoint.Y < 0.01) + {//Y=0 + return CurvePoints.Last(); + } + double a = (simularPoint.Y - equipCurveZeroH) / (simularPoint.X * simularPoint.X); + if (a < 0.0001) + GetSectPointLn(CurvePoints, simularPoint); + + //2鐐硅繛鎴愮洿绾夸笌鎶涚墿绾跨殑浜ょ偣,鍒ゆ柇浜ょ偣鏄惁鍦�2鐐逛箣闂�,鍗冲彲鏄洸绾跨殑浜ょ偣 + double b, c; + double delta = 0; + double x_j1, x_j2; + for (int i = 0; i < CurvePoints.Count - 1; i++) + { + if (Math.Abs(CurvePoints[i].Y - CurvePoints[i + 1].Y) < 0.00001) + {//姘村钩鐨� + x_j1 = Math.Sqrt((CurvePoints[i].Y - equipCurveZeroH) / a); + if (CurvePoints[i].X.IsMiddle(CurvePoints[i + 1].X, x_j1)) + { + sectPoint.X = x_j1; + sectPoint.Y = CurvePoints[i].Y; + return sectPoint; + } + } + else + { + CurveLineHelper.GetKandB(CurvePoints[i], CurvePoints[i + 1], out b, out c, 0.0000000001); + c = c - equipCurveZeroH; + + //瑙f柟绋� ax2-bx-c=0 + delta = b * b + 4 * a * c; + if (delta < 0) + continue; + + x_j1 = (b + Math.Sqrt(delta)) / (2 * a); + if (x_j1 >= 0 && CurvePoints[i].X.IsMiddle(CurvePoints[i + 1].X, x_j1)) + { + sectPoint.X = x_j1; + sectPoint.Y = b * x_j1 + c + equipCurveZeroH; + return sectPoint; + } + + x_j2 = (b - Math.Sqrt(delta)) / (2 * a); + if (x_j2 >= 0 && CurvePoints[i].X.IsMiddle(CurvePoints[i + 1].X, x_j2)) + { + sectPoint.X = x_j2; + sectPoint.Y = b * x_j2 + c + equipCurveZeroH; + return sectPoint; + } + } + } + + return sectPoint; + } + + + + + //閫氳繃鐐箂imularPoint鍜岀偣(0,0)鐨勬姏鐗╃嚎,涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0)):褰撴祦閲忕壒鍒ぇ锛孒姣旇緝灏忔椂鐢� + //鏇茬嚎鍏紡锛欻=K*Q^2,鐒跺悗涓よ竟鍙栧鏁� + protected static IStation.Curve.CurvePoint GetSectPointLn(List<IStation.Curve.CurvePoint> CurvePoints, IStation.Curve.CurvePoint simularPoint) + { + IStation.Curve.CurvePoint sectPoint = new IStation.Curve.CurvePoint(0, 0); + if (CurvePoints == null || CurvePoints.Count < 2) + return sectPoint; + + //璁$畻鍙栧鏁板悗鐩寸嚎鐨凨 + double a = Math.Log10(simularPoint.Y) / Math.Log10(simularPoint.X); + if (a < 0.0001) + return sectPoint; + + //鎵�鏈夌殑绾夸笂鐨勭偣鍙栧鏁� + List<IStation.Curve.CurvePoint> CurvePointsLn = new List<IStation.Curve.CurvePoint>(); + for (int i = 0; i < CurvePoints.Count; i++) + { + if (CurvePoints[i].X > 1)//闃叉绗竴涓偣锛歑=0 + CurvePointsLn.Add(new IStation.Curve.CurvePoint(Math.Log10(CurvePoints[i].X), Math.Log10(CurvePoints[i].Y))); + } + + //涓�2鐐硅繛鎴愮洿绾跨殑浜ょ偣,鍒ゆ柇浜ょ偣鏄惁鍦�2鐐逛箣闂�,鍗冲彲鏄洸绾跨殑浜ょ偣 + double b, c; + double x; + for (int i = 0; i < CurvePointsLn.Count - 1; i++) + { + CurveLineHelper.GetKandB(CurvePointsLn[i], CurvePointsLn[i + 1], out b, out c); + + /*瑙f柟绋� + * y=ax + * y=bx+c + */ + if (Math.Abs(a - b) < 0.001) + continue; + + x = c / (a - b); + if (CurvePointsLn[i].X.IsMiddle(CurvePointsLn[i + 1].X, x)) + { + sectPoint.X = Math.Pow(10, x); + sectPoint.Y = Math.Pow(10, a * x); + + return sectPoint; + } + } + + return sectPoint; + } + } + + /// <summary> + /// 鎶涚墿绾� Parabola : y = K * Q^2 + B * Q; + /// </summary> + public class ParabolaECurveHelper + { + //浠绘剰涓ょ偣 + public static bool GetCurvePara(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, out double K, out double B) + { + //鎶涚墿绾挎嫙鍚� y=ax2+bx; + double y1 = pt1.Y; + double x1 = pt1.X; + double y2 = pt2.Y; + double x2 = pt2.X; + + K = (y1 * x2 - y2 * x1) / (x1 * x1 * x2 - x2 * x2 * x1); + B = (y1 * x2 * x2 - y2 * x1 * x1) / (x1 * x2 * x2 - x2 * x1 * x1); + + return true; + } + + + //宸ヤ綔鐐瑰拰楂樻晥鐐� + public static bool GetCurveParaByBEP(IStation.Curve.CurvePoint wrkPt, double bep_q, out double bep_eta, out double K, out double B) + { + //鎶涚墿绾挎嫙鍚� + //鎬濊矾 Y=0鏃�, X=0鎴� -B/K + //鎵�浠� bep_q = -B/K * 0.5 + + + + K = wrkPt.Y / (wrkPt.X * wrkPt.X - 2 * bep_q * wrkPt.X); + B = -2 * K * bep_q; + + bep_eta = K * bep_q * bep_q + B * bep_q; + + //if (bep_eta > 0.95) + //{ + + //} + + return true; + } + + + } + + /// <summary> + /// 鎶涚墿绾� Parabola : H = K * Q^2 (瑁呯疆鏇茬嚎) + /// </summary> + public class ParabolaZCurveHelper + { + private double _k = 0; + public double GetK() + { + return _k; + } + public ParabolaZCurveHelper(IStation.Curve.CurvePoint pt) + { + this._k = pt.Y / pt.X / pt.X; + } + public ParabolaZCurveHelper(double x, double y) + { + this._k = y / x / x; + } + public double GetY(double x) + { + return x * x * this._k; + } + public double GetX(double y) + { + return Math.Sqrt(y * this._k); + } + + //璁$畻浠巟1鍒皒2鐨勫姬闀� + public double CalcCurveLengthByX(double pt1_x, double pt2_x) + { + //鎬濊矾鏄粠鎸夌洿绾垮彔鍔� + double x1 = pt1_x; + double x2 = pt2_x; + if (pt1_x > pt2_x) + { + x1 = pt2_x; + x2 = pt1_x; + } + + double space = (x2 - x1) / 1200; + double x_last = x1; + double y_last = GetY(x1); + double total_length = 0; + for (int i = 1; i <= 1200; i++) + { + double x = x1 + space * i; + double y = GetY(x); + double sub_length = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); + x_last = x; + y_last = y; + + total_length += sub_length; + } + + return total_length; + } + + //璁$畻鐐圭殑浣嶇疆, x1鍒皒2寮ч暱鐨勬憜鏀捐矾 + public IStation.Curve.CurvePoint CalcPointPosiByX(double x1, double x2, double length_ratio) + { + if (length_ratio < 0.001) + { + return new IStation.Curve.CurvePoint(x1, GetY(x1)); + } + + //鎬濊矾鏄粠鎸夌洿绾垮彔鍔� + int point_number = 1800; + double space = (x2 - x1) / point_number; + double x_last = x1; + double y_last = GetY(x1); + double total_length = 0; + + for (int i = 1; i <= point_number; i++) + { + double x = x1 + space * i; + double y = GetY(x); + double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); + x_last = x; + y_last = y; + + total_length += len; + } + + double calc_length = total_length * length_ratio; + double len2 = 0; + x_last = x1; + y_last = GetY(x1); + for (int i = 1; i <= point_number; i++) + { + double x = x1 + space * i; + double y = GetY(x); + double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); + x_last = x; + y_last = y; + + len2 += len; + if (len2 > calc_length) + { + return new IStation.Curve.CurvePoint(x, y); + } + } + + return new IStation.Curve.CurvePoint(x2, GetY(x2)); + } + public IStation.Curve.CurvePoint CalcPointPosi(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double length_ratio) + { + return CalcPointPosiByX(pt1.X, pt2.X, length_ratio); + } + + + //璁$畻鐐箈鍦ㄥ姬闀�(x1->x2)涓殑鐧惧垎鐜� + public double CalcPointRatioByX(double x1, double x2, double x_center) + { + double length1 = CalcCurveLengthByX(x1, x2); + double length2 = CalcCurveLengthByX(x1, x_center); + + return length2 / length1; + } + public double CalcPointRatio(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double x_center) + { + double length1 = CalcCurveLengthByX(pt1.X, pt2.X); + double length2 = CalcCurveLengthByX(pt1.X, x_center); + + return length2 / length1; + } + + } + + /// <summary> + /// 鎶涚墿绾� Parabola : H = K * Q^2 (瑁呯疆鏇茬嚎) :鍥捐〃娉�: 鏈夋椂鐢≦H宸埆姣旇緝澶ф椂, 鐢ㄨ窛绂昏绠椾細鏈変簺闂 + /// </summary> + public class ParabolaZChartCurveHelper + { + private double _k = 1; + + private double _chartWidth = 1000; + private double _chartHeight = 600; + + private double _ratio_scale_x = 1; + private double _ratio_scale_y = 1; + private double GetK() + {//涓嶅澶� , 澶栭儴鐭ラ亾K 娌℃湁鎰忎箟 + return _k; + } + public ParabolaZChartCurveHelper(IStation.Curve.CurvePoint pt) + { + if (pt == null) + return; + + this._ratio_scale_x = _chartWidth / pt.X; + this._ratio_scale_y = _chartHeight / pt.Y; + + this._k = _chartHeight / _chartWidth / _chartWidth; + } + public ParabolaZChartCurveHelper(double x, double y) + { + this._ratio_scale_x = _chartWidth / x; + this._ratio_scale_y = _chartHeight / y; + this._k = _chartHeight / _chartWidth / _chartWidth; + } + private double GetY_chart(double x) + { + return x * x * this._k; + } + private double GetX_chart(double y) + { + return Math.Sqrt(y * this._k); + } + public double GetY(double x) + { + double chart_x = x * this._ratio_scale_x; + var chart_y = chart_x * chart_x * this._k; + return chart_y / this._ratio_scale_y; + } + + //璁$畻浠巟1鍒皒2鐨勫姬闀�(娉ㄦ剰鏃跺浘琛ㄤ笂鐨勮窛绂�) + public double CalcCurveLengthByX(double real_x_1, double real_x_2) + { + double pt1_x = real_x_1 * this._ratio_scale_x; + double pt2_x = real_x_2 * this._ratio_scale_x; + + //鎬濊矾鏄粠鎸夌洿绾垮彔鍔� + double x1 = pt1_x; + double x2 = pt2_x; + if (pt1_x > pt2_x) + { + x1 = pt2_x; + x2 = pt1_x; + } + + double space = (x2 - x1) / 1200; + double x_last = x1; + double y_last = GetY_chart(x1); + double total_length = 0; + for (int i = 1; i <= 1200; i++) + { + double x = x1 + space * i; + double y = GetY_chart(x); + double sub_length = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); + x_last = x; + y_last = y; + + total_length += sub_length; + } + + return total_length; + } + + private IStation.Curve.CurvePoint FromChartToReal(double chart_pt_x, double chart_pt_y) + { + return new IStation.Curve.CurvePoint(chart_pt_x / this._ratio_scale_x, chart_pt_y / this._ratio_scale_y); + } + //璁$畻鐐圭殑浣嶇疆, x1鍒皒2寮ч暱鐨勬憜鏀捐矾 + public IStation.Curve.CurvePoint CalcPointPosiByX(double real_x_1, double real_x_2, double length_ratio) + { + double x1 = real_x_1 * this._ratio_scale_x; + double x2 = real_x_2 * this._ratio_scale_x; + + if (length_ratio < 0.001) + { + return FromChartToReal(x1, GetY_chart(x1)); + } + + //鎬濊矾鏄粠鎸夌洿绾垮彔鍔� + int point_number = 1800; + double space = (x2 - x1) / point_number; + double x_last = x1; + double y_last = GetY_chart(x1); + double total_length = 0; + + for (int i = 1; i <= point_number; i++) + { + double x = x1 + space * i; + double y = GetY_chart(x); + double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); + x_last = x; + y_last = y; + + total_length += len; + } + + double calc_length = total_length * length_ratio; + double len2 = 0; + x_last = x1; + y_last = GetY_chart(x1); + for (int i = 1; i <= point_number; i++) + { + double x = x1 + space * i; + double y = GetY_chart(x); + double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); + x_last = x; + y_last = y; + + len2 += len; + if (len2 > calc_length) + { + return FromChartToReal(x, y); + } + } + + return FromChartToReal(x2, GetY_chart(x2)); + } + public IStation.Curve.CurvePoint CalcPointPosi(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double length_ratio) + { + return CalcPointPosiByX(pt1.X, pt2.X, length_ratio); + } + + + //璁$畻鐐箈鍦ㄥ姬闀�(x1->x2)涓殑鐧惧垎鐜� + public double CalcPointRatioByX(double x1, double x2, double x_center) + { + double length1 = CalcCurveLengthByX(x1, x2); + double length2 = CalcCurveLengthByX(x1, x_center); + + return length2 / length1; + } + public double CalcPointRatio(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double x_center) + { + double length1 = CalcCurveLengthByX(pt1.X, pt2.X); + double length2 = CalcCurveLengthByX(pt1.X, x_center); + + return length2 / length1; + } + + } + +} \ No newline at end of file diff --git a/Schedule/IStation.Algorithm/Model/Curve/ParallelConnection/ParallelConnectionHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/ParallelConnection/ParallelConnectionHelper.cs new file mode 100644 index 0000000..216470e --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/ParallelConnection/ParallelConnectionHelper.cs @@ -0,0 +1,377 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 涓插苟鑱旇緟鍔╃被 + /// </summary> + public class ParallelConnectionHelper + { + + // 璁$畻鏇茬嚎鍒楄〃 + private List<CurveExpress> _curveQhList = new List<CurveExpress>(); + private List<CurveExpress> _curveQpList = new List<CurveExpress>(); + + // 寤堕暱鐜�, 榛樿涓嶅欢闀� + private double _extendMinRatio = 1; + private double _extendMaxRatio = 1; + + //姹俀鐨勬渶澶ф渶灏忓�� + double minQ = 0, maxQ = 100000; + + //姹侶鐨勬渶澶ф渶灏忓�� + double minH = 0, maxH = 100000; + + #region Curve + /// <summary> + /// 娣诲姞 + /// </summary> + /// <param name="curveQh"></param> + /// <param name="curveQp"></param> + public void AddCurve(CurveExpress curveQh, CurveExpress curveQp) + { + if (curveQh != null) + _curveQhList.Add(curveQh); + + if (curveQp != null) + _curveQpList.Add(curveQp); + } + + /// <summary> + /// 娣诲姞 + /// </summary> + /// <param name="pointsQH"></param> + /// <param name="pointsQP"></param> + public void AddCurve(List<CurvePoint> pointsQH, List<CurvePoint> pointsQP) + { + if (pointsQH != null && pointsQH.Count > 3) + _curveQhList.Add(FitHelper.BuildCurveExpress(pointsQH, eFitType.CubicCurve)); + if (pointsQP != null && pointsQP.Count > 3) + _curveQpList.Add(FitHelper.BuildCurveExpress(pointsQH, eFitType.CubicCurve)); + } + + /// <summary> + /// 娓呴櫎 + /// </summary> + public void ClearCurve() + { + this.minQ = 0; + this.maxQ = 100000; + this.minH = 0; + this.maxH = 100000; + _curveQhList.Clear(); + _curveQpList.Clear(); + } + #endregion + + /// <summary> + /// 璁$畻骞惰仈 + /// </summary> + /// <param name="pointQH"></param> + /// <param name="pointQE"></param> + /// <param name="pointQP"></param> + /// <returns></returns> + public bool CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP) + { + pointQH = pointQE = pointQP = null; + //姹侶鐨勬渶澶ф渶灏忓�� + if (!CalculateMaxMinH()) + return false; + + //璁$畻骞惰仈 + return GetCurveParallel(out pointQH, out pointQE, out pointQP); + } + + /// <summary> + /// 浠庡苟鑱旀洸绾夸腑鍒嗗壊鍑哄崟娉垫洸绾� + /// </summary> + /// <param name="connectPointsQH"></param> + /// <param name="separatePointsQH"></param> + /// <returns></returns> + public bool SeparateParallelQH(List<CurvePoint> connectPointsQH, out List<CurvePoint> separatePointsQH) + { + separatePointsQH = new List<CurvePoint>(); + + maxH = (from x in connectPointsQH select x.Y).Max(); + minH = (from x in connectPointsQH select x.Y).Min(); + + int insert_num = 30; + double space = (maxH - minH) / (insert_num - 1); + + double H = minH; + int i = 0, j = 0; + for (j = 0; j < insert_num; j++) + { + //璁$畻娴侀噺 + List<CurvePoint> listQ = FitHelper.GetInterPointX(connectPointsQH, H); + if (listQ == null || listQ.Count == 0) + { + continue; + } + double totalQ = listQ.Last().X; + bool isInsect = true; + for (i = 0; i < _curveQhList.Count(); i++) + { + var currentQH = _curveQhList[i]; + //璁$畻娴侀噺 + List<CurvePoint> listQ2 = FitHelper.GetInterPointX(currentQH, H); + if (listQ2 == null || listQ2.Count == 0) + { + isInsect = false; + continue; + } + double Q = listQ2.Last().X; + totalQ = totalQ - Q; + } + + //娣诲姞鍒板垪琛� + if (isInsect) + { + separatePointsQH.Add(new CurvePoint(totalQ, H)); + } + + H = H + space; + } + + if (separatePointsQH.Count < 3) + { + separatePointsQH = null; + return false; + } + + var express = FitHelper.BuildCurveExpress(separatePointsQH, eFitType.CubicCurve); + separatePointsQH = FitHelper.GetFitPoints(express, 20); + return true; + } + + + //璁$畻涓茶仈 + public bool CalculateSeries( + out List<CurvePoint> pointsQH, + out List<CurvePoint> pointsQE, + out List<CurvePoint> pointsQP) + { + pointsQH = pointsQE = pointsQP = null; + //姹俀鐨勬渶澶ф渶灏忓�� + if (!CalculateMaxMinQ()) + return false; + + //璁$畻骞惰仈 + return GetCurveSeries(out pointsQH, out pointsQE, out pointsQP); + } + + + private bool CalculateMaxMinH() + { + if (_curveQhList == null || _curveQhList.Count() == 0) + return false; + foreach (var curves in _curveQhList) + { + if (curves == null) + continue; + double min_h = 0, max_h = 0; + GetMinMaxPointYByRatio(curves, _extendMinRatio, _extendMaxRatio, out max_h, out min_h); + this.minH = Math.Max(min_h, this.minH); + this.maxH = Math.Min(max_h, this.maxH); + + } + if (this.maxH < this.minH) + return false; + return true; + } + + private bool CalculateMaxMinQ() + { + if (_curveQhList == null || _curveQhList.Count() == 0) + return false; + foreach (var curve in _curveQhList) + { + if (curve == null) + continue; + + minQ = Math.Max(curve.Min * _extendMinRatio, minH); + maxQ = Math.Min(curve.Max * _extendMaxRatio, maxH); + } + + if (minQ > maxQ - 3) + return false; + else + return true; + } + + //璁$畻骞惰仈 + private bool GetCurveParallel(out List<CurvePoint> pointsQH, out List<CurvePoint> pointsQE, out List<CurvePoint> pointsQP) + { + if (_curveQhList == null || !_curveQhList.Any()) + { + pointsQH = null; + pointsQE = null; + pointsQP = null; + return false; + } + + pointsQH = new List<CurvePoint>(); + pointsQE = new List<CurvePoint>(); + pointsQP = new List<CurvePoint>(); + + int insert_num = 30; + double space = (maxH - minH) / (insert_num - 1); + + double H = minH; + int i = 0, j = 0; + for (j = 0; j < insert_num; j++) + { + double totalQ = 0; + double totalP = 0; + bool isInsect = true; + for (i = 0; i < _curveQhList.Count(); i++) + { + CurveExpress currentQH = _curveQhList[i]; + CurveExpress currentQP = null; + if (_curveQpList != null && _curveQpList.Count > i) + currentQP = _curveQpList[i]; + + //璁$畻娴侀噺 + List<CurvePoint> listQ = FitHelper.GetInterPointX(currentQH, H); + if (listQ == null || listQ.Count == 0) + { + isInsect = false; + continue; + } + double Q = listQ.Last().X; + totalQ = totalQ + Q; + + //璁$畻鍔熺巼 + if (currentQP != null) + { + double p = FitHelper.GetFitPointY(currentQP, Q); + totalP = totalP + p; + } + } + + //娣诲姞鍒板垪琛� + if (isInsect) + { + pointsQH.Add(new CurvePoint(totalQ, H)); + if (totalP > 0.001) + { + pointsQP.Add(new CurvePoint(totalQ, totalP)); + + double E = PumpCalculateHelper.CalculateE(totalQ, H, totalP); + pointsQE.Add(new CurvePoint(totalQ, E)); + } + } + + H = H + space; + } + + //鏍规嵁娴侀噺鎺掑簭 + CurvePointComparer.Sort featPointComp = new CurvePointComparer.Sort(CurvePointComparer.eSortType.X); + pointsQH.Sort(featPointComp); + if (pointsQE != null && pointsQE.Count > 2) + pointsQE.Sort(featPointComp); + if (pointsQP != null && pointsQP.Count > 2) + pointsQP.Sort(featPointComp); + + return true; + } + + //璁$畻涓茶仈 + private bool GetCurveSeries(out List<CurvePoint> pointsQH, out List<CurvePoint> pointsQE, out List<CurvePoint> pointsQP) + { + if (_curveQhList.Count() == 0) + { + pointsQH = null; + pointsQE = null; + pointsQP = null; + return false; + } + pointsQH = new List<CurvePoint>(); + pointsQE = new List<CurvePoint>(); + pointsQP = new List<CurvePoint>(); + + int insert_num = 30; + double space = (maxQ - minQ) / (insert_num - 1); + + double Q = minQ; + int i = 0, j = 0; + for (j = 0; j < insert_num; j++) + { + double totalH = 0; + double totalP = 0; + bool isInsect = true; + for (i = 0; i < _curveQhList.Count(); i++) + { + CurveExpress currentQH = _curveQhList[i]; + CurveExpress currentQP = null; + if (_curveQpList != null && _curveQpList.Count > i) + currentQP = _curveQpList[i]; + + //璁$畻H + double h = FitHelper.GetFitPointY(currentQH, Q); + totalH = totalH + h; + + //璁$畻鍔熺巼 + if (currentQP != null) + { + double p = FitHelper.GetFitPointY(currentQP, Q); + + totalP = totalP + p; + } + } + + //娣诲姞鍒板垪琛� + if (isInsect) + { + pointsQH.Add(new CurvePoint(Q, totalH)); + if (totalP > 0.001) + { + pointsQP.Add(new CurvePoint(Q, totalP)); + + double E = PumpCalculateHelper.CalculateE(Q, totalH, totalP); + pointsQE.Add(new CurvePoint(Q, E)); + } + } + + Q = Q + space; + } + + //鏍规嵁娴侀噺鎺掑簭 + CurvePointComparer.Sort featPointComp = new CurvePointComparer.Sort(CurvePointComparer.eSortType.X); + pointsQH.Sort(featPointComp); + if (pointsQE != null && pointsQE.Count > 2) + pointsQE.Sort(featPointComp); + if (pointsQP != null && pointsQP.Count > 2) + pointsQP.Sort(featPointComp); + + return true; + } + + /// <summary> + /// 鑾峰彇鎷熷悎鐐�(寤堕暱鐜�):鍜孏etFitPointsByExtend涓�妯′竴鏍� + /// </summary> + public static List<CurvePoint> GetFitPointsByRatio(CurveExpress express, double ratioExtendmin, double ratioExtendmax, int pointNumber) + { + if (express == null) + return default; + return express.GetFitPointsByXRange(express.Min * ratioExtendmin, express.Max * ratioExtendmax, pointNumber); + } + + //鑾峰彇寤堕暱鍚� MaxY MinY + public static bool GetMinMaxPointYByRatio(CurveExpress express, double ratioExtendmin, double ratioExtendmax, out double maxY, out double minY) + { + if (express == null) + { + maxY = minY = 0; + return false; + } + var fitPoints = GetFitPointsByRatio(express, ratioExtendmin, ratioExtendmax, 50); + if (fitPoints == null || !fitPoints.Any()) + { + maxY = minY = 0; + return false; + } + maxY = (from x in fitPoints select x.Y).Max(); + minY = (from x in fitPoints select x.Y).Min(); + return true; + } + } +} \ No newline at end of file diff --git a/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePoint.cs b/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePoint.cs new file mode 100644 index 0000000..f030f0b --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePoint.cs @@ -0,0 +1,198 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 鏇茬嚎鐐� + /// </summary> + public partial class CurvePoint : JsonList<CurvePoint>, ICloneable + { + + /// <summary> + /// + /// </summary> + public CurvePoint() { } + + /// <summary> + /// + /// </summary> + public CurvePoint(int x, int y) + { + this.X = x; + this.Y = y; + } + + /// <summary> + /// + /// </summary> + public CurvePoint(float x, float y) + { + this.X = x; + this.Y = y; + } + + /// <summary> + /// + /// </summary> + public CurvePoint(double x, double y) + { + this.X = x; + this.Y = y; + } + + /// <summary> + /// + /// </summary> + public CurvePoint(decimal x, decimal y) + { + this.X = (double)x; + this.Y = (double)y; + } + + /// <summary> + /// + /// </summary> + public CurvePoint(CurvePoint rhs) + { + this.X = rhs.X; + this.Y = rhs.Y; + } + + + /// <summary> + /// X + /// </summary> + public double X { get; set; } + + /// <summary> + /// Y + /// </summary> + public double Y { get; set; } + + /// <summary> + /// 鑾峰彇涓ょ偣涔嬮棿鐨勮窛绂� + /// </summary> + public double Distance(CurvePoint pt) + { + if (pt == null) + { + return double.MaxValue; + } + return Math.Sqrt(Math.Pow(this.X - pt.X, 2) + Math.Pow(this.Y - pt.Y, 2)); + } + + /// <summary> + /// 鑾峰彇鐐瑰埌绾跨殑璺濈 + /// </summary> + public double Distance(List<CurvePoint> ptList) + { + if (ptList == null || ptList.Count < 1) + { + return double.MaxValue; + } + return ptList.Min(x => x.Distance(this)); + } + + /// <summary> + /// 鍒ゆ柇鏄惁鏄浂鐐� + /// </summary> + public bool IsZeroPoint() + { + if (this.X < 0.01 && this.Y < 0.01) + { + return true; + } + return false; + } + + /*/// <summary> + /// 鍒ゆ柇鏄惁涓烘湁鏁堢偣 + /// </summary> + public bool IsValidPoint() + { + if (!(!double.IsNormal(this.X) || !double.IsNormal(this.Y))) + { + return true; + } + return false; + }*/ + + /// <summary> + /// 鍒ゆ柇鏄惁涓烘棤鏁堢偣 + /// </summary> + public bool IsInvalidPoint() + { + if (double.IsNaN(this.X) || double.IsInfinity(this.X) || this.X == double.MinValue || this.X == double.MaxValue) + { + return true; + } + if (double.IsNaN(this.Y) || double.IsInfinity(this.Y) || this.Y == double.MinValue || this.Y == double.MaxValue) + { + return true; + } + return false; + } + + /// <summary> + /// 鏄惁娌縳杞寸殑灏勭嚎绌块�忕嚎娈�,鏈変氦鐐逛笖鍦ㄧ嚎鐨勫乏杈� + /// </summary> + public bool IsIntersectLineLeft(CurvePoint pt1, CurvePoint pt2) + { + if (pt1 == null || pt2 == null) + { + return false; + } + if (Math.Abs(pt1.Y - pt2.Y) < 0.0001) + { + if (Math.Abs(this.Y - pt1.Y) < 0.0001) + { + return true; + } + } + var ymin = UtilsHelper.Min(pt1.Y, pt2.Y); + var ymax = UtilsHelper.Max(pt1.Y, pt2.Y); + if (this.Y < ymax && this.Y >= ymin) + { + if (this.X <= (pt1.X + (pt2.X - pt1.X) * (this.Y - pt1.Y) / (pt2.Y - pt1.Y))) + { + return true; + } + } + return false; + } + + + /// <summary> + /// + /// </summary> + public CurvePoint Clone() + { + return new CurvePoint(this); + } + + /// <summary> + /// + /// </summary> + object ICloneable.Clone() + { + return this.Clone(); + } + + + + + + + + + + + + + + + + } + + + + +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePointComparer.cs b/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePointComparer.cs new file mode 100644 index 0000000..0646fe7 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePointComparer.cs @@ -0,0 +1,120 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// + /// </summary> + public class CurvePointComparer + { + /// <summary> + /// 鎺掑簭绫诲瀷 + /// </summary> + public enum eSortType + { + X, + Y + } + + /// <summary> + /// 鐩哥瓑绫诲瀷 + /// </summary> + public enum eEqualType + { + X, + Y, + ALL + } + + /// <summary> + /// 鎺掑簭姣旇緝 + /// </summary> + public class Sort : IComparer<CurvePoint> + { + public Sort(eSortType sortType) + { + _sortType = sortType; + } + + private const double _ignore = 0.0001; + private eSortType _sortType; + + int IComparer<CurvePoint>.Compare(CurvePoint obj1, CurvePoint obj2) + { + if (_sortType == eSortType.X) + { + if (Math.Abs(obj1.X - obj2.X) < _ignore) + { + return 0; + } + else if (obj1.X > obj2.X) + { + return 1; + } + else + { + return -1; + } + } + else + { + if (Math.Abs(obj1.Y - obj2.Y) < _ignore) + { + return 0; + } + else if (obj1.Y > obj2.Y) + { + return 1; + } + else + { + return -1; + } + } + } + } + + /// <summary> + /// 鐩哥瓑姣旇緝 + /// </summary> + public class Equal : IEqualityComparer<CurvePoint> + { + public Equal() + { + + } + public Equal(double ignore, eEqualType equalType) + { + this._ignore = ignore; + this._equalType = equalType; + } + + private double _ignore = 0.001; + private eEqualType _equalType = eEqualType.X; + + public bool Equals(CurvePoint lhs, CurvePoint rhs) + { + switch (_equalType) + { + case eEqualType.X: + if (Math.Abs(lhs.X - rhs.X) < _ignore) + return true; + break; + case eEqualType.Y: + if (Math.Abs(lhs.Y - rhs.Y) < _ignore) + return true; + break; + case eEqualType.ALL: + if (Math.Abs(lhs.X - rhs.X) < _ignore && Math.Abs(lhs.Y - rhs.Y) < _ignore) + return true; + break; + } + return false; + } + + public int GetHashCode(CurvePoint obj) + { + return 0; + } + + } + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Point/GroupPoint.cs b/Schedule/IStation.Algorithm/Model/Curve/Point/GroupPoint.cs new file mode 100644 index 0000000..6e0cb45 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Point/GroupPoint.cs @@ -0,0 +1,278 @@ +锘縩amespace IStation.Curve +{ + public class GroupPoint : ICloneable + { + private int id = 0; + public int ID { get { return id; } set { id = value; } } + public double Q { get; set; } + public double H { get; set; } + public double E { get; set; } + public double P { get; set; } + public double NPSH { get { return _npsh; } set { _npsh = value; } } + private double _npsh = -1; + public GroupPoint() { } + public GroupPoint(GroupPoint rhs) + { + this.ID = rhs.ID; + this.Q = rhs.Q; + this.H = rhs.H; + this.E = rhs.E; + this.P = rhs.P; + this.NPSH = rhs.NPSH; + } + public GroupPoint(string dsString) + { + ResetParas(dsString); + } + public bool ResetParas(string dsString) + { + if (string.IsNullOrEmpty(dsString)) return false; + if (dsString.Contains("|")) + {//鍙兘鏄疓roupPointList鐨勫瓧绗� + + string[] strParas = dsString.Split('|'); + int iCount = strParas.Count(); + if (iCount < 2) + return false; + + return ResetParas(strParas[1]);//鍙栭粯璁ょ涓�涓垚鍛樺嵆鍙� + + } + var paras = dsString.Split(','); + if (paras.Count() < 5) + return false; + ID = Convert.ToInt32(paras[0]); + Q = Convert.ToDouble(paras[1]); + H = Convert.ToDouble(paras[2]); + E = Convert.ToDouble(paras[3]); + P = Convert.ToDouble(paras[4]); + NPSH = Convert.ToDouble(paras[5]); + return true; + } + public static GroupPoint ToParameter(string dsString) + { + if (string.IsNullOrEmpty(dsString)) return null; + if (dsString.Contains("|")) + {//鍙兘鏄疓roupPointList鐨勫瓧绗� + + string[] strParas = dsString.Split('|'); + int iCount = strParas.Count(); + if (iCount < 2) + return null; + + return GroupPoint.ToParameter(strParas[1]);//鍙栭粯璁ょ涓�涓垚鍛樺嵆鍙� + } + + var paras = dsString.Split(','); + if (paras.Count() < 5) + return null; + GroupPoint pt = new GroupPoint(); + pt.ID = Convert.ToInt32(paras[0]); + pt.Q = Convert.ToDouble(paras[1]); + pt.H = Convert.ToDouble(paras[2]); + pt.E = Convert.ToDouble(paras[3]); + pt.P = Convert.ToDouble(paras[4]); + pt.NPSH = Convert.ToDouble(paras[5]); + + return pt; + } + + + public GroupPoint(int id, double q, double h, double e, double p) + { + ID = id; + Q = q; + H = h; + E = e; + P = p; + } + public GroupPoint(int id, double q, double h, double e, double p, double npsh) + { + ID = id; + Q = q; + H = h; + E = e; + P = p; + NPSH = npsh; + } + + public override string ToString() + { + return string.Format("Q:{0:0.0},H:{1:0.0},E:{2:0.0},P:{3:0.0}", Q, H, E, P); + } + public string ToDsString() + { + return string.Format("{0},{1},{2},{3},{4},{5}", ID, Q, H, E, P, NPSH); + } + + public IStation.Curve.GroupPoint RoundAll(int decimals) + { + this.Q = Math.Round(this.Q, decimals); + this.H = Math.Round(this.H, decimals); + this.E = Math.Round(this.E, decimals); + this.P = Math.Round(this.P, decimals); + this.NPSH = Math.Round(this.NPSH, decimals); + return this; + } + public IStation.Curve.GroupPoint RoundAll_Small(int decimals, double small = 2) + { + if (this.Q < small) + this.Q = Math.Round(this.Q, 3); + else + this.Q = Math.Round(this.Q, decimals); + if (this.H < small) + this.H = Math.Round(this.H, 3); + else + this.H = Math.Round(this.H, decimals); + if (this.E < small) + this.E = Math.Round(this.E, 3); + else + this.E = Math.Round(this.E, decimals); + if (this.P < small) + this.P = Math.Round(this.P, 3); + else + this.P = Math.Round(this.P, decimals); + this.NPSH = Math.Round(this.NPSH, decimals); + return this; + } + + #region Clone + public GroupPoint Clone() //瀵瑰鎻愪緵涓�涓垱寤鸿嚜韬殑娴呰〃鍓湰鐨勮兘鍔� + { + return (GroupPoint)this.MemberwiseClone(); + } + object ICloneable.Clone() + { + return this.Clone(); + } + #endregion + + public enum eSortType + { + ID, + Q, + H, + E, + P + } + + //鎺掑簭鏂规硶 + public class Comparer : IComparer<IStation.Curve.GroupPoint> + { + private eSortType sortType; + public Comparer(eSortType type = eSortType.Q) + { + sortType = type; + } + + #region IComparer<GroupPoint> 鎴愬憳 + int IComparer<IStation.Curve.GroupPoint>.Compare(IStation.Curve.GroupPoint obj1, IStation.Curve.GroupPoint obj2) + { + if (sortType == eSortType.ID) + { + if (obj1.ID == obj2.ID) + { + return 0; + } + else if (obj1.ID > obj2.ID) + { + return 1; + } + else + { + return -1; + } + } + else if (sortType == eSortType.Q) + { + if (Math.Abs(obj1.Q - obj2.Q) < 0.0001) + { + return 0; + } + else if (obj1.Q > obj2.Q) + { + return 1; + } + else + { + return -1; + } + } + else if (sortType == eSortType.H) + { + if (Math.Abs(obj1.H - obj2.H) < 0.0001) + { + return 0; + } + else if (obj1.H > obj2.H) + { + return 1; + } + else + { + return -1; + } + } + else if (sortType == eSortType.E) + { + if (Math.Abs(obj1.E - obj2.E) < 0.0001) + { + return 0; + } + else if (obj1.E > obj2.E) + { + return 1; + } + else + { + return -1; + } + } + else + { + if (Math.Abs(obj1.P - obj2.P) < 0.0001) + { + return 0; + } + else if (obj1.P > obj2.P) + { + return 1; + } + else + { + return -1; + } + } + } + + #endregion + } + + //姣旇緝鐩稿悓:涓昏鐢ㄤ笌LIST鐨凜ontains鏂规硶 + public class EqualComparer : IEqualityComparer<IStation.Curve.GroupPoint> + { + private double ignoreDis = 0.001; + public EqualComparer() + { + ignoreDis = 0.001; + } + public EqualComparer(double dis) + { + ignoreDis = dis; + } + public bool Equals(IStation.Curve.GroupPoint lhs, IStation.Curve.GroupPoint rhs) + { + if (Math.Abs(lhs.Q - rhs.Q) < ignoreDis && Math.Abs(lhs.H - rhs.H) < ignoreDis) + return true; + + return false; + } + + public int GetHashCode(IStation.Curve.GroupPoint obj) + { + return 0; + // return obj.H.GetHashCode() + obj.Q.GetHashCode(); + } + } + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/PumpCalculate/PumpCalculateHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/PumpCalculate/PumpCalculateHelper.cs new file mode 100644 index 0000000..ddb2f56 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/PumpCalculate/PumpCalculateHelper.cs @@ -0,0 +1,1659 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 娉佃绠楄緟鍔╃被 + /// </summary> + public class PumpCalculateHelper + { + #region 甯歌璁$畻 + + #region 璁$畻鎵▼ + + /// <summary> + /// 璁$畻鎵▼ + /// </summary> + /// <param name="q">鐬椂娴侀噺 m鲁/h</param> + /// <param name="pr1">杩涘彛鍘嬪姏 mpa</param> + /// <param name="pr2">鍑哄彛鍘嬪姏 mpa</param> + /// <param name="d1">杩涘彛鍙e緞 mm</param> + /// <param name="d2">鍑哄彛鍙e緞 mm</param> + /// <param name="z1">杩涘彛鏍囬珮 m</param> + /// <param name="z2">鍑哄彛鏍囬珮 m</param> + /// <returns>鎵▼ m</returns> + public static double CalculateH(double q, double pr1, double pr2, double d1, double d2, double z1, double z2) + { + var qa = q / 3600; + var pr1a = pr1 * 1000000; + var pr2a = pr2 * 1000000; + var d1a = d1 / 1000; + var d2a = d2 / 1000; + var v1 = qa * 4 / (Math.PI * Math.Pow(d1a, 2)); + var v2 = qa * 4 / (Math.PI * Math.Pow(d2a, 2)); + var distance = z2 - z1; + var pg = Constant.WaterDensity * Constant.g; + var g2 = 2 * Constant.g; + + var h = (pr2a / pg - pr1a / pg) + (Math.Pow(v2, 2) / g2 - Math.Pow(v1, 2) / g2) + distance; + return h; + } + + + /// <summary> + /// 璁$畻 OtherPress (娴嬮噺鎵▼= 鍘嬪樊 + 琛ㄤ綅宸� + 娴侀��) + /// </summary> + /// <param name="q">娴侀噺 m鲁/h </param> + /// <param name="inletPipeDia">杩涘彛绠″緞 mm </param> + /// <param name="outletPipeDia">鍑哄彛绠″緞 mm </param> + /// <param name="inletElevation">杩涘彛鏍囬珮 mm </param> + /// <param name="outletElevation">鍑哄彛鏍囬珮 mm </param> + /// <returns></returns> + public static double CalculateOtherPress(double? q, double? inletPipeDia, double? outletPipeDia, double? inletElevation, double? outletElevation) + { + if (q == null || q.Value < 0.05) + { + if (outletElevation == null || inletElevation == null) + return 0; + return outletElevation.Value - inletElevation.Value; + } + + double flow = q.Value; + double inPipeV = 0; + if (inletPipeDia != null && inletPipeDia.Value > 0.1) + { + // 娴侀�熻绠� pipeD =mm,pumpFlow=m3/p + inPipeV = Constant.OtherPressCoeff * flow / inletPipeDia.Value / inletPipeDia.Value; + } + + double outPipeV = 0; + if (outletPipeDia != null && outletPipeDia.Value > 0.1) + { + // 娴侀�熻绠� rPipeD =mm,rPumpFlow=m3/p + outPipeV = Constant.OtherPressCoeff * flow / outletPipeDia.Value / outletPipeDia.Value; + } + + double differV = (outPipeV * outPipeV - inPipeV * inPipeV) / Constant.g / 2.0; + + if (outletElevation == null || inletElevation == null) + return differV; + + return differV + outletElevation.Value - inletElevation.Value; + } + + #endregion + + #region 璁$畻鏁堢巼 + + /// <summary> + /// 璁$畻鏁堢巼 + /// </summary> + /// <param name="q"> 鐬椂娴侀噺 m鲁/h</param> + /// <param name="h"> 鎵▼ m</param> + /// <param name="p"> 鍔熺巼 kw</param> + /// <param name="蟻"> 瀵嗗害 kg/m^3</param> + /// <param name="g"> 閲嶅姏鍔犻�熷害 m/s^2</param> + /// <returns>鐧惧垎鏁�</returns> + public static double CalculateE(double q, double h, double p, double 蟻, double g) + { + var qa = q / 3600; + var pa = p * 1000; + double e = 0; + if (pa < 0.1) + { + return e; + } + e = 蟻 * g * qa * h / pa; + return Math.Round(e * 100, 2); + } + + /// <summary> + /// 璁$畻鏁堢巼 + /// </summary> + /// <param name="q"> 鐬椂娴侀噺 m鲁/h</param> + /// <param name="h"> 鎵▼ m</param> + /// <param name="p"> 鍔熺巼 kw</param> + /// <returns>鐧惧垎鏁�</returns> + public static double CalculateE(double q, double h, double p) + { + return CalculateE(q, h, p, Constant.WaterDensity, Constant.g); + } + + /// <summary> + /// 璁$畻鏁堢巼 + /// </summary> + /// <param name="q"> 鐬椂娴侀噺 m鲁/h</param> + /// <param name="h"> 鎵▼ m</param> + /// <param name="p"> 鍔熺巼 kw</param> + /// <param name="蟻"> 瀵嗗害 kg/m^3</param> + /// <returns>鐧惧垎鏁�</returns> + public static double CalculateE(double q, double h, double p, double 蟻) + { + return CalculateE(q, h, p, 蟻, Constant.g); + } + + #endregion + + #region 璁$畻鍔熺巼 + + /// <summary> + /// 璁$畻鍔熺巼 + /// </summary> + /// <param name="q">鐬椂娴侀噺 m鲁/h</param> + /// <param name="h">鎵▼ m</param> + /// <param name="e">鏁堢巼 鐧惧垎鏁�</param> + /// <param name="蟻">瀵嗗害kg/m鲁</param> + /// <param name="g">閲嶅姏鍔犻�熷害 m/s虏</param> + /// <returns>kw</returns> + public static double CalculateP(double q, double h, double e, double 蟻, double g) + { + var qa = q / 3600; + var ea = e / 100; + double p = 0; + if (ea < 0.01) + { + return p; + } + p = 蟻 * g * qa * h / ea; + p = p / 1000;//鎹㈢畻鎴恔w + if (p < 2) + { + return Math.Round(p, 4); + } + if (p < 30) + { + return Math.Round(p, 3); + } + if (p < 100) + { + return Math.Round(p, 2); + } + return Math.Round(p, 1); + + } + + /// <summary> + /// 璁$畻鍔熺巼 + /// </summary> + /// <param name="q">鐬椂娴侀噺 m鲁/h</param> + /// <param name="h">鎵▼ m</param> + /// <param name="e">鏁堢巼 鐧惧垎鏁�</param> + /// <param name="蟻">瀵嗗害kg/m鲁</param> + /// <returns>kw</returns> + public static double CalculateP(double q, double h, double e, double 蟻) + { + return CalculateP(q, h, e, 蟻, Constant.g); + } + + /// <summary> + /// 璁$畻鍔熺巼 + /// </summary> + /// <param name="q">鐬椂娴侀噺 m鲁/h</param> + /// <param name="h">鎵▼ m</param> + /// <param name="e">鏁堢巼 鐧惧垎鏁�</param> + /// <returns>kw</returns> + public static double CalculateP(double q, double h, double e) + { + return CalculateP(q, h, e, Constant.WaterDensity, Constant.g); + } + + #endregion + + #region Mpa<=>m + + /// <summary> + /// Mpa=>m + /// </summary> + public static double Mpa2M(double mpa) + { + return mpa * Constant.WaterDensity / Constant.g; + } + + /// <summary> + /// m=>Mpa + /// </summary> + public static double M2Mpa(double m) + { + return m * Constant.g / Constant.WaterDensity; + } + + + #endregion + + #region 璁$畻鐢ㄧ數閲� + + /// <summary> + /// 璁$畻鐢ㄧ數閲� + /// </summary> + /// <param name="p">鍔熺巼kw</param> + /// <param name="t">鏃堕棿h</param> + /// <returns>kw*h</returns> + public static double CalculateD(double p, double t) + { + return p * t; + } + + #endregion + + #region 璁$畻绱Н娴侀噺 + + /// <summary> + /// 璁$畻绱Н娴侀噺 + /// </summary> + /// <param name="q">鐬椂娴侀噺m鲁/h</param> + /// <param name="t">鏃堕棿h</param> + /// <returns>m鲁</returns> + public static double CalculateQt(double q, double t) + { + return q * t; + } + + #endregion + + #region 璁$畻鑳借�� + + /// <summary> + /// 璁$畻鍗冨惃鑳借�� + /// </summary> + /// <param name="p">鍔熺巼kW</param> + /// <param name="q">鐬椂娴侀噺m鲁/h</param> + /// <returns>kW路h/km鲁</returns> + public static double CalculateWP(double p, double q) + { + if (q < 0.1) + { + return default; + } + return p / q * 1000; + } + + /// <summary> + /// 璁$畻鍗曚綅鑳借�� + /// </summary> + /// <param name="p">鍔熺巼kW</param> + /// <param name="q">鐬椂娴侀噺m鲁/h</param> + /// <param name="h">鎵▼m</param> + /// <returns>kW路h/km鲁</returns> + public static double CalculateUWP(double p, double q, double h) + { + if (q < 0.1) + { + return default; + } + if (h < 0.1) + { + return default; + } + return p / q / h * 1000; + } + + #endregion + + #region 棰戠巼鎹㈢畻 + + /// <summary> + /// 鏍规嵁棰戠巼璁$畻娴侀噺 + /// </summary> + /// <param name="q">鐬椂娴侀噺 m鲁/h</param> + /// <param name="hz">棰戠巼</param> + /// <param name="hzr">棰濆畾棰戠巼</param> + /// <returns></returns> + public static double CalculateQByHz(double q, double hz, double hzr = 50) + { + if (hzr < 0.1) + { + return q; + } + if (hz < 0.1) + { + return q; + } + /* if (hz > hzr) + { + return q; + }*/ + double f_ratio = hzr / hz; + + return q * f_ratio; + } + + /// <summary> + /// 鏍规嵁棰戠巼璁$畻鎵▼ + /// </summary> + /// <param name="h">鎵▼ m</param> + /// <param name="hz">棰戠巼 </param> + /// <param name="hzr">棰濆畾棰戠巼</param> + /// <returns></returns> + public static double CalculateHByHz(double h, double hz, double hzr = 50) + { + if (hzr < 0.1) + { + return h; + } + if (hz < 0.1) + { + return h; + } + /* if (hz > hzr) + { + return h; + }*/ + double f_ratio = hzr / hz; + return h * f_ratio * f_ratio; + } + + /// <summary> + /// 鏍规嵁棰戠巼璁$畻 50hz鍔熺巼 + /// </summary> + /// <param name="p">鍔熺巼 kw</param> + /// <param name="hz">棰戠巼 kw</param> + /// <param name="hzr">棰濆畾棰戠巼</param> + /// <returns></returns> + public static double CalculatePByHz(double p, double hz, double hzr = 50) + { + if (hzr < 0.1) + { + return p; + } + if (hz < 0.1) + { + return p; + } + /* if (hz > hzr) + { + return p; + }*/ + double f_ratio = hzr / hz; + return p * f_ratio * f_ratio * f_ratio; + } + + /// <summary> + /// 鏍规嵁杞�熻绠楁祦閲� + /// </summary> + /// <param name="q">鐬椂娴侀噺 m鲁/h</param> + /// <param name="n">杞�� r/min</param> + /// <param name="nr">棰濆畾杞�� r/min</param> + /// <returns></returns> + public static double CalculateQByN(double q, double n, double nr) + { + if (nr < 0.1) + { + return q; + } + if (n < 0.1) + { + return q; + } + double f_ratio = nr / n; + + return q * f_ratio; + } + + /// <summary> + /// 鏍规嵁杞�熻绠楁壃绋� + /// </summary> + /// <param name="h">鎵▼ m</param> + /// <param name="n">杞�� r/min</param> + /// <param name="nr">棰濆畾杞�� r/min</param> + /// <returns></returns> + public static double CalculateHByN(double h, double n, double nr) + { + if (nr < 0.1) + { + return h; + } + if (n < 0.1) + { + return h; + } + double f_ratio = nr / n; + + return h * f_ratio * f_ratio; + } + + /// <summary> + /// 鏍规嵁杞�熻绠楀姛鐜� + /// </summary> + /// <param name="p">鍔熺巼 kw</param> + /// <param name="n">杞�� r/min</param> + /// <param name="nr">棰濆畾杞�� r/min</param> + /// <returns></returns> + public static double CalculatePByN(double p, double n, double nr) + { + if (nr < 0.1) + { + return p; + } + if (n < 0.1) + { + return p; + } + double f_ratio = nr / n; + + return p * f_ratio * f_ratio * f_ratio; + } + + #endregion + + + #endregion + + #region 澶嶆潅璁$畻 + + #region Simu + + /// <summary> + /// 鐭ラ亾鍘熷閫熷害,浠ュ強鍘熷鐨勬潹绋婬浠ュ強瀵瑰簲鐨勫彉閫熷悗鐨勬潹绋�,姹傚彉閫熷悗鐨勯�熷害 + /// </summary> + /// <param name="originSpeend"></param> + /// <param name="originH"></param> + /// <param name="changeH"></param> + /// <returns></returns> + public static double CalculateSimuByH(double originSpeend, double originH, double changeH) + { + double ratio = Math.Pow(originH / changeH, 1.0 / 2.0); + return originSpeend / ratio; + } + + /// <summary> + /// 鐭ラ亾鍘熷閫熷害,浠ュ強鍘熷鐨勬祦閲廞浠ュ強瀵瑰簲鐨勫彉閫熷悗鐨勬潹绋�,姹傚彉閫熷悗鐨勯�熷害 + /// </summary> + /// <param name="originSpeend"></param> + /// <param name="originQ"></param> + /// <param name="changeQ"></param> + /// <returns></returns> + public static double CalculateSimuByQ(double originSpeend, double originQ, double changeQ) + { + double ratio = originQ / changeQ; + return originSpeend / ratio; + } + #endregion + + #region 鐩镐技鎹㈢畻 + + /// <summary> + /// 璁$畻鐩镐技娴侀噺鎵▼鏇茬嚎 + /// </summary> + /// <param name="express">琛ㄨ揪寮�</param> + /// <param name="originHz">鍘熷棰戠巼</param> + /// <param name="changeHz">鎹㈢畻棰戠巼</param> + /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param> + /// <returns></returns> + public static CurveExpress CalculateSimilarQH(CurveExpress express, double originHz, double changeHz, int pointNumber = 12) + { + if (express == null) + return null; + if (changeHz < 1) + return null; + List<CurvePoint> fitPoints = null; + if (express.DefinePoints != null && express.DefinePoints.Any()) + fitPoints = express.DefinePoints; + else + fitPoints = FitHelper.GetFitPoints(express, pointNumber); + + var ratio = changeHz / originHz; + var similarPoints = new List<CurvePoint>(); + foreach (CurvePoint fitPoint in fitPoints) + { + var similarPoint = new CurvePoint(); + similarPoint.X = fitPoint.X * ratio; + similarPoint.Y = fitPoint.Y * ratio * ratio; + similarPoints.Add(similarPoint); + } + + return FitHelper.BuildCurveExpress(similarPoints, express.FitType); + } + + /// <summary> + /// 璁$畻鐩镐技娴侀噺鍔熺巼鏇茬嚎 + /// </summary> + /// <param name="curvePoints">琛ㄨ揪寮�</param> + /// <param name="originHz">鍘熷棰戠巼</param> + /// <param name="changeHz">鎹㈢畻棰戠巼</param> + /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param> + /// <returns></returns> + public static CurveExpress CalculateSimilarQP(CurveExpress curvePoints, double originHz, double changeHz, int pointNumber = 12) + { + if (curvePoints == null) + return null; + if (changeHz < 1) + return null; + List<CurvePoint> fitPoints = null; + if (curvePoints.DefinePoints != null && curvePoints.DefinePoints.Any()) + fitPoints = curvePoints.DefinePoints; + else + fitPoints = FitHelper.GetFitPoints(curvePoints, pointNumber); + + var ratio = changeHz / originHz; + var similarPoints = new List<CurvePoint>(); + foreach (CurvePoint fitPoint in fitPoints) + { + var similarPoint = new CurvePoint(); + similarPoint.X = fitPoint.X * ratio; + similarPoint.Y = fitPoint.Y * ratio * ratio * ratio; + similarPoints.Add(similarPoint); + } + return FitHelper.BuildCurveExpress(similarPoints, curvePoints.FitType); + } + + /// <summary> + /// 璁$畻鐩镐技娴侀噺鏁堢巼鏇茬嚎 + /// </summary> + /// <param name="curvePoints">琛ㄨ揪寮�</param> + /// <param name="originHz">鍘熷棰戠巼</param> + /// <param name="changeHz">鎹㈢畻棰戠巼</param> + /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param> + /// <returns></returns> + public static CurveExpress CalculateSimilarQE(CurveExpress curvePoints, double originHz, double changeHz, int pointNumber = 12) + { + if (curvePoints == null) + return null; + if (changeHz < 1) + return null; + List<CurvePoint> fitPoints = null; + if (curvePoints.DefinePoints != null && curvePoints.DefinePoints.Any()) + fitPoints = curvePoints.DefinePoints; + else + fitPoints = FitHelper.GetFitPoints(curvePoints, pointNumber); + + var ratio = changeHz / originHz; + var similarPoints = new List<CurvePoint>(); + foreach (CurvePoint fitPoint in fitPoints) + { + var similarPoint = new CurvePoint(); + similarPoint.X = fitPoint.X * ratio; + similarPoint.Y = fitPoint.Y; + similarPoints.Add(similarPoint); + } + return FitHelper.BuildCurveExpress(similarPoints, curvePoints.FitType); + } + + /// <summary> + /// 璁$畻鐩镐技娴侀噺鎵▼鏇茬嚎鐐� + /// </summary> + /// <param name="fitPoints">鏇茬嚎鐐�</param> + /// <param name="originHz">鍘熷棰戠巼</param> + /// <param name="changeHz">鎹㈢畻棰戠巼</param> + /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param> + /// <returns></returns> + public static List<CurvePoint> CalculateSimilarQH(List<CurvePoint> fitPoints, double originHz, double changeHz) + { + if (fitPoints == null || !fitPoints.Any()) + return null; + if (changeHz < 1) + return null; + + var ratio = changeHz / originHz; + var similarPoints = new List<CurvePoint>(); + foreach (CurvePoint fitPoint in fitPoints) + { + var similarPoint = new CurvePoint(); + similarPoint.X = fitPoint.X * ratio; + similarPoint.Y = fitPoint.Y * ratio * ratio; + similarPoints.Add(similarPoint); + } + return similarPoints; + } + + /// <summary> + /// 璁$畻鐩镐技娴侀噺鍔熺巼鏇茬嚎鐐� + /// </summary> + /// <param name="fitPoints">鏇茬嚎鐐�</param> + /// <param name="originHz">鍘熷棰戠巼</param> + /// <param name="changeHz">鎹㈢畻棰戠巼</param> + /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param> + /// <returns></returns> + public static List<CurvePoint> CalculateSimilarQP(List<CurvePoint> fitPoints, double originHz, double changeHz) + { + if (fitPoints == null || !fitPoints.Any()) + return null; + if (changeHz < 1) + return null; + + var ratio = changeHz / originHz; + var similarPoints = new List<CurvePoint>(); + foreach (CurvePoint fitPoint in fitPoints) + { + var similarPoint = new CurvePoint(); + similarPoint.X = fitPoint.X * ratio; + similarPoint.Y = fitPoint.Y * ratio * ratio * ratio; + similarPoints.Add(similarPoint); + } + return similarPoints; + } + + /// <summary> + /// 璁$畻鐩镐技娴侀噺鏁堢巼鏇茬嚎鐐� + /// </summary> + /// <param name="fitPoints">鏇茬嚎鐐�</param> + /// <param name="originHz">鍘熷棰戠巼</param> + /// <param name="changeHz">鎹㈢畻棰戠巼</param> + /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param> + /// <returns></returns> + public static List<CurvePoint> CalculateSimilarQE(List<CurvePoint> fitPoints, double originHz, double changeHz) + { + if (fitPoints == null || !fitPoints.Any()) + return null; + if (changeHz < 1) + return null; + + var ratio = changeHz / originHz; + var similarPoints = new List<CurvePoint>(); + foreach (CurvePoint fitPoint in fitPoints) + { + var similarPoint = new CurvePoint(); + similarPoint.X = fitPoint.X * ratio; + similarPoint.Y = fitPoint.Y; + similarPoints.Add(similarPoint); + } + return similarPoints; + } + + + /// <summary> + /// 璁$畻鐩镐技娴侀噺鎵▼鐐� + /// </summary> + /// <param name="fitPoint">鐐�</param> + /// <param name="originHz">鍘熷棰戠巼</param> + /// <param name="changeHz">鎹㈢畻棰戠巼</param> + /// <returns></returns> + public static CurvePoint CalculateSimilarQH(CurvePoint fitPoint, double originHz, double changeHz) + { + if (fitPoint == null) + return null; + if (changeHz < 1) + return null; + var ratio = changeHz / originHz; + var similarPoint = new CurvePoint(); + similarPoint.X = fitPoint.X * ratio; + similarPoint.Y = fitPoint.Y * ratio * ratio; + return similarPoint; + } + + /// <summary> + /// 璁$畻鐩镐技娴侀噺鍔熺巼鐐� + /// </summary> + /// <param name="express">鐐�</param> + /// <param name="originHz">鍘熷棰戠巼</param> + /// <param name="changeHz">鎹㈢畻棰戠巼</param> + /// <returns></returns> + public static CurvePoint CalculateSimilarQP(CurvePoint fitPoint, double originHz, double changeHz) + { + if (fitPoint == null) + return null; + if (changeHz < 1) + return null; + var ratio = changeHz / originHz; + var similarPoint = new CurvePoint(); + similarPoint.X = fitPoint.X * ratio; + similarPoint.Y = fitPoint.Y * ratio * ratio * ratio; + return similarPoint; + } + + /// <summary> + /// 璁$畻鐩镐技娴侀噺鏁堢巼鐐� + /// </summary> + /// <param name="express">鐐�</param> + /// <param name="originHz">鍘熷棰戠巼</param> + /// <param name="changeHz">鎹㈢畻棰戠巼</param> + /// <returns></returns> + public static CurvePoint CalculateSimilarQE(CurvePoint fitPoint, double originHz, double changeHz) + { + if (fitPoint == null) + return null; + if (changeHz < 1) + return null; + var ratio = changeHz / originHz; + var similarPoint = new CurvePoint(); + similarPoint.X = fitPoint.X * ratio; + similarPoint.Y = fitPoint.Y; + + return similarPoint; + } + #endregion + + #region 璁$畻姣旇浆閫熷害 + + public static double CalculateNs(double Q, double H, double n) + { + return 3.65 * n * Math.Sqrt(Q / 3600) / Math.Pow(H, 0.75); + } + public static decimal CalculateNs(decimal Q, decimal H, decimal n) + { + return Convert.ToDecimal(3.65 * Convert.ToDouble(n) * Math.Sqrt(Convert.ToDouble(Q) / 3600) / Math.Pow(Convert.ToDouble(H), 0.75)); + } + + #endregion + + #region 璁$畻鎺ㄨ崘鍙傛暟 + + public enum eCalculatePumpType + { + 鍗曠骇鍗曞惛绂诲績娉� = 1, + 澶氱骇绂诲績娉� = 2, + 鍙屽惛绂诲績娉� = 3, + 鍖栧伐娉� = 4, + 娓f祮娉� = 5, + 闀胯酱娉� = 6 + } + + //capacity + static double[] effq = new double[33] { 5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1500, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000 }; + //1 single stage seriesEntity eff + static double[] singleeff = new double[33] { 58.0, 64.0, 67.2, 69.4, 70.9, 72.0, 73.8, 74.9, 75.8, 76.5, 77.0, 77.6, 78.0, 79.8, 80.8, 82.0, 83.0, 83.7, 84.2, 84.7, 85.0, 85.3, 85.7, 86.6, 87.2, 88.0, 88.6, 89.0, 89.2, 89.5, 89.7, 89.9, 90.0 }; + //2 multi stage seriesEntity eff + static double[] multieff = new double[26] { 55.4, 59.4, 61.8, 63.5, 64.8, 65.9, 67.5, 68.9, 69.9, 70.9, 71.5, 72.3, 72.9, 75.3, 76.9, 79.2, 80.6, 81.5, 82.2, 82.8, 83.1, 83.5, 83.9, 84.8, 85.1, 85.5 }; + //1 correct eff + static double[] effcorrect1 = new double[19] { 32, 25.5, 20.6, 17.3, 14.7, 12.5, 10.5, 9.0, 7.5, 6.0, 5.0, 4.0, 3.2, 2.5, 2.0, 1.5, 1.0, 0.5, 0 }; + //2 correct eff + static double[] effcorrect2 = new double[10] { 0, 0.3, 0.7, 1.0, 1.3, 1.7, 1.9, 2.2, 2.7, 3.0 }; + static double[] effns1 = new double[19] { 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 110, 120 }; + static double[] effns2 = new double[10] { 210, 220, 230, 240, 250, 260, 270, 280, 290, 300 }; + + + /// <summary> + /// 鏍规嵁娉电被鍨嬭绠楁帹鑽愭晥鐜� + /// </summary> + /// <param name="q">娴侀噺</param> + /// <param name="h">鎵▼</param> + /// <param name="n">杞��</param> + /// <param name="pumpType">娉电被鍨�<see cref="eCalculatePumpType" /></param> + /// <returns></returns> + public static double CalculateEByPumpType(double q, double h, double n, int pumpType) + { + double ns = CalculateNs(q, h, n); + + double eff, qjs1, qjs2, qjs3, effjs1, effjs2, effjs3, correct = 1; + int i = 0; + double dltE = 0.0; + + double q0 = q; + double h0 = h; + + // + double t = 1000; + if (pumpType == (int)eCalculatePumpType.鍗曠骇鍗曞惛绂诲績娉�) + t = 10000; + if (pumpType == (int)eCalculatePumpType.澶氱骇绂诲績娉�) + t = 300000; + if (pumpType == (int)eCalculatePumpType.鍙屽惛绂诲績娉�) + t = 10000; + if (pumpType == (int)eCalculatePumpType.鍖栧伐娉�) + t = 10000; + if (pumpType == (int)eCalculatePumpType.娓f祮娉�) + t = 10000; + if (pumpType == (int)eCalculatePumpType.闀胯酱娉�) + t = 10000; + if (q0 > t) + { + i = effq.Length - 1; + } + else if (q0 >= 1.5 && q0 <= t) + { + i = 0; + for (i = 0; effq[i] <= q0; i++) + { + if (i + 1 == effq.Count()) + { + break; + } + } + } + else + { + return -1; + } + if (i >= effq.Length) + i = effq.Length - 1; + + if (q0 >= 10) + { + qjs1 = effq[i]; + qjs2 = effq[i - 1]; + qjs3 = effq[i - 2]; + switch (pumpType) + { + case 1: + if (i >= singleeff.Length) + i = singleeff.Length - 1; + effjs1 = singleeff[i]; + effjs2 = singleeff[i - 1]; + effjs3 = singleeff[i - 2]; + break; + case 2: + if (i >= multieff.Length) + i = multieff.Length - 1; + effjs1 = multieff[i]; + effjs2 = multieff[i - 1]; + effjs3 = multieff[i - 2]; + break; + case 3: + if (i >= singleeff.Length) + i = singleeff.Length - 1; + effjs1 = singleeff[i]; + effjs2 = singleeff[i - 1]; + effjs3 = singleeff[i - 2]; + dltE = -2; + break; + case 4: + if (i >= singleeff.Length) + i = singleeff.Length - 1; + effjs1 = singleeff[i]; + effjs2 = singleeff[i - 1]; + effjs3 = singleeff[i - 2]; + dltE = 5; + break; + case 5: + effjs1 = singleeff[i]; + effjs2 = singleeff[i - 1]; + effjs3 = singleeff[i - 2]; + dltE = 8; + break; + default: + effjs1 = singleeff[i]; + effjs2 = singleeff[i - 1]; + effjs3 = singleeff[i - 2]; + dltE = 3.5; + break; + } + } + else + { + qjs1 = effq[2]; + qjs2 = effq[1]; + qjs3 = effq[0]; + switch (pumpType) + { + case 1: + effjs1 = singleeff[2]; + effjs2 = singleeff[1]; + effjs3 = singleeff[0]; + break; + case 2: + effjs1 = multieff[2]; + effjs2 = multieff[1]; + effjs3 = multieff[0]; + break; + case 3: + effjs1 = singleeff[2]; + effjs2 = singleeff[1]; + effjs3 = singleeff[0]; + dltE = -2; + break; + case 4: + effjs1 = singleeff[2]; + effjs2 = singleeff[1]; + effjs3 = singleeff[0]; + dltE = 5; + break; + case 5: + effjs1 = singleeff[2]; + effjs2 = singleeff[1]; + effjs3 = singleeff[0]; + dltE = 8; + break; + default: + effjs1 = singleeff[2]; + effjs2 = singleeff[1]; + effjs3 = singleeff[0]; + dltE = 3.5; + break; + } + } + + eff = (q0 - qjs2) * (q0 - qjs3) * effjs1 / ((qjs1 - qjs2) * (qjs1 - qjs3)) + + (q0 - qjs1) * (q0 - qjs3) * effjs2 / ((qjs2 - qjs1) * (qjs2 - qjs3)) + + (q0 - qjs1) * (q0 - qjs2) * effjs3 / ((qjs3 - qjs1) * (qjs3 - qjs2)) - dltE; + + if ((ns < 120 && ns >= 20) || (ns < 300 && ns > 210)) + { + if (ns < 120 && ns >= 20) + { + for (i = 0; effns1[i] <= ns; i++) + { + } + if (ns >= 25) + { + qjs1 = effns1[i]; + qjs2 = effns1[i - 1]; + qjs3 = effns1[i - 2]; + effjs1 = effcorrect1[i]; + effjs2 = effcorrect1[i - 1]; + effjs3 = effcorrect1[i - 2]; + } + else + { + qjs1 = effns1[i + 1]; + qjs2 = effns1[i]; + qjs3 = effns1[i - 1]; + effjs1 = effcorrect1[i + 1]; + effjs2 = effcorrect1[i]; + effjs3 = effcorrect1[i - 1]; + } + } + if (ns < 300 && ns > 210) + { + for (i = 0; effns2[i] <= ns; i++) + { + } + if (ns >= 220) + { + qjs1 = effns2[i]; + qjs2 = effns2[i - 1]; + qjs3 = effns2[i - 2]; + effjs1 = effcorrect2[i]; + effjs2 = effcorrect2[i - 1]; + effjs3 = effcorrect2[i - 2]; + } + else + { + qjs1 = effns2[i + 1]; + qjs2 = effns2[i]; + qjs3 = effns2[i - 1]; + effjs1 = effcorrect2[i + 1]; + effjs2 = effcorrect2[i]; + effjs3 = effcorrect2[i - 1]; + } + } + correct = (ns - qjs2) * (ns - qjs3) * effjs1 / ((qjs1 - qjs2) * (qjs1 - qjs3)) + + (ns - qjs1) * (ns - qjs3) * effjs2 / ((qjs2 - qjs1) * (qjs2 - qjs3)) + + (ns - qjs1) * (ns - qjs2) * effjs3 / ((qjs3 - qjs1) * (qjs3 - qjs2)); + } + if (ns >= 300) + correct = 3.0; + if (ns < 20) + correct = 32.0; + if (ns >= 120 && ns <= 210) + correct = 0; + eff = eff - correct; + + return eff; + } + + //璁$畻鎺ㄨ崘NPSHr + public static double CalculateNPSHrByPumpType(double Q, double H, double n, int iPumpType) + { + double ns = CalculateNs(Q, H, n); + double S_Q = 10; + if (iPumpType == 3) + S_Q = Q / 2; + else + S_Q = Q; + + double K = Math.Pow(ns, 1.3333) * 216 / 1000000; + return K * H; + } + + #endregion + + #region 璁$畻鍔熺巼 + + /// <summary> + /// 璁$畻鍔熺巼 + /// </summary> + /// <param name="ptQHs">娴侀噺鎵▼鐐�</param> + /// <param name="ptQEs">娴侀噺鏁堢巼鐐�</param> + /// <returns>娴侀噺鍔熺巼鐐�</returns> + public static List<CurvePoint> CalculateP(List<CurvePoint> ptQHs, List<CurvePoint> ptQEs) + { + if (ptQHs == null || ptQHs.Count() <= 2) + return null; + bool isXStartZero = ptQHs.First().X > 500 || ptQHs.First().X > ptQHs.Last().X * 0.2; + return CalculateP(eFitType.CubicCurve, eFitType.CubicCurve, eFitType.CubicCurve, ptQHs, ptQEs, Constant.WaterDensity, -1, isXStartZero); + } + + /// <summary> + /// 璁$畻鍔熺巼 + /// </summary> + /// <param name="fitQH">娴侀噺鎵▼绾挎嫙鍚堟柟寮�</param> + /// <param name="fitQE">娴侀噺鏁堢巼绾挎嫙鍚堟柟寮�</param> + /// <param name="fitQP">娴侀噺鍔熺巼绾挎嫙鍚堟柟寮�</param> + /// <param name="ptQHs">娴侀噺鎵▼鐐�</param> + /// <param name="ptQEs">娴侀噺鏁堢巼鐐�</param> + /// <param name="midu">姘寸殑瀵嗗害</param> + /// <param name="zeroPower">娴侀噺涓�0鏃剁殑鍔熺巼</param> + /// <param name="isXStartZero">娴侀噺鏄惁涓�0</param> + /// <returns></returns> + public static List<CurvePoint> CalculateP( + eFitType fitQH, + eFitType fitQE, + eFitType fitQP, + List<CurvePoint> ptQHs, + List<CurvePoint> ptQEs, + double midu, + double zeroPower, + bool isXStartZero) + { + if (ptQHs == null || ptQHs.Count < 3) + return null; + if (ptQEs == null || ptQEs.Count < 3) + return null; + + var curveQH = FitHelper.BuildCurveExpress(ptQHs, fitQH); + var curveQE = FitHelper.BuildCurveExpress(ptQEs, fitQE); + + var curveQP = CalculateP(fitQP, curveQH, curveQE, midu, zeroPower, isXStartZero); + return curveQP.GetFitPoints(ptQEs.Count()); + } + + /// <summary> + /// 璁$畻鍔熺巼 + /// </summary> + /// <param name="fitQP">娴侀噺鍔熺巼绾挎嫙鍚堟柟寮�</param> + /// <param name="curveQH">娴侀噺鎵▼绾�</param> + /// <param name="curveQE">娴侀噺鏁堢巼绾�</param> + /// <param name="midu">姘寸殑瀵嗗害</param> + /// <param name="zeroPower">娴侀噺涓�0鏃剁殑鍔熺巼</param> + /// <param name="isXStartZero">娴侀噺鏄惁涓�0</param> + /// <returns></returns> + public static CurveExpress CalculateP(eFitType fitQP, CurveExpress curveQH, CurveExpress curveQE, double midu, double zeroPower, bool isXStartZero) + { + if (curveQH == null || curveQE == null) + return null; + int pointNumber = 16;//鐐逛笉鑳藉お澶� + var ptQHs = curveQH.GetFitPoints(pointNumber); + if (ptQHs == null || ptQHs.Count < 3) + return null; + var ptQEs = curveQE.GetFitPoints(pointNumber); + if (ptQEs == null || ptQEs.Count < 3) + return null; + + List<CurvePoint> pointQP = new List<CurvePoint>(); + //闂磋窛 + double minQ = Math.Max(ptQHs.First().X, ptQEs.First().X); + double maxQ = Math.Min(ptQHs.Last().X, ptQEs.Last().X); + + // + double Q, H, E, P; + double space = (maxQ - minQ) / (pointNumber - 1); + + //淇濊瘉浠�0寮�濮�: 淇濊瘉Q=0鏃�,P涓嶆槸璁$畻鍑烘潵鐨�; + if (isXStartZero) + { + for (int i = 5; i < pointNumber; i++)//鍓嶉潰鍑犱釜鐐逛笉瑕� + { + Q = ptQEs.First().X + space * i; + E = curveQE.GetFitPointY(Q); + H = curveQH.GetFitPointY(Q); + if (H < 0.1 || E < 0.5) + continue; + + P = CalculateP(Q, H, E, midu); + if (P < 2) + { + P = Math.Round(P, 3); + } + else if (P < 30) + { + P = Math.Round(P, 2); + } + else if (P < 100) + { + P = Math.Round(P, 1); + } + else + { + P = Math.Round(P, 0); + } + pointQP.Add(new CurvePoint(Q, P)); + } + + pointQP = FitHelper.GetFitPoints(pointQP, fitQP, pointNumber); + if (pointQP == null) + return null; + + + if (zeroPower > 0.1) + { + pointQP.Insert(0, new CurvePoint(0, zeroPower)); + } + else + { + if (pointQP[0].Y >= pointQP[1].Y) + { + pointQP[0].Y = pointQP[1].Y * 0.95; + } + double startP = CurveLineHelper.GetYbyX(pointQP[0].X, pointQP[0].Y, pointQP[1].X, pointQP[1].Y, 0); + if (startP < 0.001) + startP = pointQP[0].Y; + + if (startP < 2) + { + startP = Math.Round(startP, 3); + } + else if (startP < 30) + { + startP = Math.Round(startP, 2); + } + else if (startP < 100) + { + startP = Math.Round(startP, 1); + } + else + { + startP = Math.Round(startP, 0); + } + + pointQP.Insert(0, new CurvePoint(0, startP)); + } + + + return FitHelper.BuildCurveExpress(pointQP, fitQP); + } + else + { + for (int i = 0; i < pointNumber; i++)//鍓嶉潰鍑犱釜鐐逛笉瑕� + { + Q = ptQEs.First().X + space * i; + E = curveQE.GetFitPointY(Q); + H = curveQH.GetFitPointY(Q); + if (H < 0.1 || E < 0.5) + continue; + + P = CalculateP(Q, H, E, midu); + if (P < 2) + { + P = Math.Round(P, 3); + } + else if (P < 30) + { + P = Math.Round(P, 2); + } + else if (P < 100) + { + P = Math.Round(P, 1); + } + else + { + P = Math.Round(P, 0); + } + pointQP.Add(new CurvePoint(Q, P)); + } + + pointQP = FitHelper.GetFitPoints(pointQP, fitQP, pointNumber); + if (pointQP == null) + return null; + + return FitHelper.BuildCurveExpress(pointQP, fitQP); + + } + + } + + #endregion + + #region 璁$畻鏁堢巼 + + public static CurveExpress CalculateE(eFitType fitType, CurveExpress expressQH, CurveExpress expressQP) + { + return CalculateE(fitType, expressQH, expressQP, Constant.WaterDensity); + } + public static CurveExpress CalculateE(CurveExpress expressQH, CurveExpress expressQP) + { + return CalculateE(expressQH, expressQP, Constant.WaterDensity); + } + public static CurveExpress CalculateE(CurveExpress expressQH, CurveExpress expressQP, bool isXStartZero) + { + return CalculateE(expressQH, expressQP, Constant.WaterDensity, isXStartZero); + } + + public static CurveExpress CalculateE(CurveExpress expressQH, CurveExpress expressQP, double midu) + { + if (expressQH == null) + return null; + return CalculateE(expressQH.FitType, expressQH, expressQP, midu); + } + public static CurveExpress CalculateE(CurveExpress expressQH, CurveExpress expressQP, double midu, bool isXStartZero) + { + if (expressQH == null) + return null; + return CalculateE(expressQH.FitType, expressQH, expressQP, midu, isXStartZero); + } + + public static CurveExpress CalculateE(eFitType fitTypeQE, CurveExpress expressQH, CurveExpress expressQP, double midu) + { + if (expressQH == null) + return null; + + bool isXStartZero = true; + if (expressQH.Min > 500 || expressQH.Min > expressQH.Max * 0.1) + { + isXStartZero = false; + } + else + { + isXStartZero = true; + } + + return CalculateE(fitTypeQE, expressQH, expressQP, midu, isXStartZero); + } + + public static CurveExpress CalculateE(eFitType fitTypeQE, CurveExpress expressQH, CurveExpress expressQP, double midu, bool isXStartZero) + { + if (expressQH == null) + return null; + if (expressQP == null) + return null; + int PointNumber = 12; + List<CurvePoint> pointQE = new List<CurvePoint>(); + List<CurvePoint> pointQP = FitHelper.GetFitPoints(expressQP, PointNumber); + + double Q, H, Eff, Power; + FitHelper fitCurve = new FitHelper(expressQH); + for (int i = 0; i < pointQP.Count; i++) + { + Q = pointQP[i].X; + Power = pointQP[i].Y; + H = fitCurve.GetFitPointY(Q); + Eff = CalculateE(Q, H, Power, midu); + pointQE.Add(new CurvePoint(Q, Eff)); + } + + //淇濊瘉Q=0鏃�,Eff=0; + if (isXStartZero) + { + pointQE[0] = new CurvePoint(0, 0); + var fitCurve1 = FitHelper.GetFitPoints(pointQE, fitTypeQE, pointQE.Count()); + pointQE = AmendCurveHelper.ByZeroPointY(fitCurve1, pointQE[3].X, 0); + return FitHelper.BuildCurveExpress(pointQE, fitTypeQE); + } + else + { + return FitHelper.BuildCurveExpress(pointQE, fitTypeQE); + } + } + + + public static List<CurvePoint> CalculateEpoint( + eFitType CurveFitTypeQE, + CurveExpress expressQH, + CurveExpress expressQP, + int PointNumber, + double midu) + { + if (expressQH == null) + return null; + if (expressQP == null) + return null; + + List<CurvePoint> pointQE = new List<CurvePoint>(); + List<CurvePoint> pointQP = FitHelper.GetFitPoints(expressQP, PointNumber); + + double Q, H, Eff, Power; + FitHelper fitCurve = new FitHelper(expressQH); + for (int i = 0; i < pointQP.Count; i++) + { + Q = pointQP[i].X; + Power = pointQP[i].Y; + H = fitCurve.GetFitPointY(Q); + Eff = CalculateE(Q, H, Power, midu); + + pointQE.Add(new CurvePoint(Q, Eff)); + } + + bool isXStartZero = true; + if (pointQE.First().X > 500 || pointQE.First().X > pointQE.Last().X * 0.1) + { + isXStartZero = false; + } + else + { + isXStartZero = true; + } + + //淇濊瘉Q=0鏃�,Eff=0; + if (isXStartZero) + { + pointQE[0] = new CurvePoint(0, 0); + var fitCurve1 = FitHelper.GetFitPoints(pointQE, CurveFitTypeQE, pointQE.Count()); + return AmendCurveHelper.ByZeroPointY(fitCurve1, pointQE[3].X, 0); + } + else + { + return FitHelper.GetFitPoints(pointQE, CurveFitTypeQE, pointQE.Count()); + } + } + + + //娉ㄦ剰姝ゆ柟娉� 杩斿洖鐨勭偣娌℃湁鎷熷悎 + public static List<CurvePoint> CalculateE_AlignPointP( + List<CurvePoint> pointQH, + List<CurvePoint> pointQP, + double midu, bool isXStartZero) + { + return CalculateE_AlignPointP( + eFitType.CubicCurve, + eFitType.CubicCurve, + eFitType.CubicCurve, + pointQH, pointQP, midu, isXStartZero); + } + + public static List<CurvePoint> CalculateE_AlignPointP( + eFitType CurveFitTypeQH, + eFitType CurveFitTypeQE, + eFitType CurveFitTypeQP, + List<CurvePoint> pointQH, + List<CurvePoint> pointQP, + double midu, bool isXStartZero) + { + if (pointQH == null || pointQH.Count < 3) + return null; + if (pointQP == null || pointQP.Count < 3) + return null; + + List<CurvePoint> pointQE = new List<CurvePoint>(); + + if (pointQH.IsEqualValueX(pointQP)) + {//x閮戒竴鑷� + for (int i = 0; i < pointQP.Count; i++) + { + double Q, H, Eff, Power; + Q = pointQP[i].X; + Power = pointQP[i].Y; + H = pointQH[i].Y; + Eff = CalculateE(Q, H, Power, midu); + pointQE.Add(new CurvePoint(Q, Eff)); + } + } + else + { + FitHelper fitCurve_QP = new FitHelper(pointQP, CurveFitTypeQP); + FitHelper fitCurve_QH = new FitHelper(pointQH, CurveFitTypeQH); + for (int i = 0; i < pointQP.Count; i++) + { + double Q, H, Eff, Power; + Q = pointQP[i].X; + Power = fitCurve_QP.GetFitPointY(Q); + H = fitCurve_QH.GetFitPointY(Q); + Eff = CalculateE(Q, H, Power, midu); + pointQE.Add(new CurvePoint(Q, Eff)); + } + } + + + //pointQE = FitHelper.GetFitPointsByExtend(pointQE); + + //淇濊瘉Q=0鏃�,Eff=0; + if (isXStartZero) + { + pointQE[0] = new CurvePoint(0, 0); + } + + return pointQE; + } + + #endregion + + #region 鍔熺巼鏁堢巼鎹㈢畻 + /// <summary> + /// 璁$畻鏁堢巼 瀵瑰叾鍔熺巼 + /// </summary> + public static List<CurvePoint> CalculateELineByP(List<CurvePoint> ptQHs, List<CurvePoint> ptQPs, bool isXStartZero) + { + return CalculateELineByP(eFitType.CubicCurve, eFitType.CubicCurve, ptQHs, ptQPs, isXStartZero); + } + + /// <summary> + /// 璁$畻鏁堢巼 瀵瑰叾鍔熺巼 + /// </summary> + public static List<CurvePoint> CalculateELineByP(eFitType fitTypeQH, eFitType fitTypeQP, List<CurvePoint> ptQHs, List<CurvePoint> ptQPs, bool isXStartZero) + { + if (ptQHs == null || ptQHs.Count < 3) + { + return null; + } + + if (ptQPs == null || ptQPs.Count < 3) + { + return null; + } + + List<CurvePoint> list = new List<CurvePoint>(); + if (ptQHs.IsEqualValueX(ptQPs)) + { + for (int i = 0; i < ptQPs.Count; i++) + { + double x = ptQPs[i].X; + double y = ptQPs[i].Y; + double y2 = ptQHs[i].Y; + double y3 = CalculateE(x, y2, y, Constant.WaterDensity); + list.Add(new CurvePoint(x, y3)); + } + } + else + { + FitHelper fitCurveHelper = new FitHelper(ptQPs, fitTypeQP); + FitHelper fitCurveHelper2 = new FitHelper(ptQHs, fitTypeQH); + for (int j = 0; j < ptQPs.Count; j++) + { + double x2 = ptQPs[j].X; + double fitPointY = fitCurveHelper.GetFitPointY(x2); + double fitPointY2 = fitCurveHelper2.GetFitPointY(x2); + double y4 = CalculateE(x2, fitPointY2, fitPointY, Constant.WaterDensity); + list.Add(new CurvePoint(x2, y4)); + } + } + + if (isXStartZero) + { + list[0] = new CurvePoint(0, 0); + } + + return list; + } + + /// <summary> + /// 璁$畻鏁堢巼 瀵瑰叾鏁堢巼 + /// </summary> + public static List<CurvePoint> CalculateP_AlignPointE(eFitType fitTypeQH, eFitType fitTypeQE, List<CurvePoint> ptQHs, List<CurvePoint> ptQEs, double midu, double ref_zero_power, bool isXStartZero) + { + if (ptQHs == null || ptQHs.Count < 3) + { + return null; + } + + if (ptQEs == null || ptQEs.Count < 3) + { + return null; + } + + + List<CurvePoint> list = new List<CurvePoint>(); + if (ptQHs.IsEqualValueX(ptQEs)) + { + for (int i = 0; i < ptQEs.Count(); i++) + { + double x = ptQEs[i].X; + double y = ptQEs[i].Y; + double y2 = ptQHs[i].Y; + if (!(y2 < 0.1) && !(y < 0.5)) + { + double num = CalculateP(x, y2, y, midu); + num = ((num < 2.0) ? Math.Round(num, 3) : ((num < 30.0) ? Math.Round(num, 2) : ((!(num < 100.0)) ? Math.Round(num, 0) : Math.Round(num, 1)))); + list.Add(new CurvePoint(x, num)); + } + } + } + else + { + FitHelper fitCurveHelper = new FitHelper(ptQEs, fitTypeQE); + FitHelper fitCurveHelper2 = new FitHelper(ptQHs, fitTypeQH); + for (int j = 0; j < ptQEs.Count(); j++) + { + if (j == ptQEs.Count() - 2) + { + //娴嬭瘯浠g爜 + } + double x2 = ptQEs[j].X; + double fitPointY = fitCurveHelper.GetFitPointY(x2); + double fitPointY2 = fitCurveHelper2.GetFitPointY(x2); + if (!(fitPointY2 < 0.09) && !(fitPointY < 0.5)) + { + double num2 = CalculateP(x2, fitPointY2, fitPointY, midu); + num2 = ((num2 < 2.0) ? Math.Round(num2, 3) : ((num2 < 30.0) ? Math.Round(num2, 2) : ((!(num2 < 100.0)) ? Math.Round(num2, 0) : Math.Round(num2, 1)))); + list.Add(new CurvePoint(x2, num2)); + } + } + } + + if (isXStartZero) + { + if (list[0].X < 1.0) + { + if (ref_zero_power > 0.0) + { + list[0].X = 0.0; + list[0].Y = ref_zero_power; + } + else + { + list.RemoveAt(0); + var fitPoints = FitHelper.GetFitPoints(list); + if (fitPoints[0].Y >= fitPoints[1].Y) + { + fitPoints[0].Y = fitPoints[1].Y * 0.95; + } + + double num3 = CurveLineHelper.GetYbyX(fitPoints[0].X, fitPoints[0].Y, fitPoints[1].X, fitPoints[1].Y, 0.0); + if (num3 < 0.001) + { + num3 = fitPoints[0].Y; + } + + num3 = ((num3 < 2.0) ? Math.Round(num3, 3) : ((num3 < 30.0) ? Math.Round(num3, 2) : ((!(num3 < 100.0)) ? Math.Round(num3, 0) : Math.Round(num3, 1)))); + list.Insert(0, new CurvePoint(0.0, num3)); + } + } + else if (ref_zero_power > 0.0) + { + list.Insert(0, new CurvePoint(0.0, ref_zero_power)); + } + else + { + var fitPoints2 = FitHelper.GetFitPoints(list); + if (fitPoints2[0].Y >= fitPoints2[1].Y) + { + fitPoints2[0].Y = fitPoints2[1].Y * 0.95; + } + + double num4 = CurveLineHelper.GetYbyX(fitPoints2[0].X, fitPoints2[0].Y, fitPoints2[1].X, fitPoints2[1].Y, 0.0); + if (num4 < 0.001) + { + num4 = fitPoints2[0].Y; + } + + num4 = ((num4 < 2.0) ? Math.Round(num4, 3) : ((num4 < 30.0) ? Math.Round(num4, 2) : ((!(num4 < 100.0)) ? Math.Round(num4, 0) : Math.Round(num4, 1)))); + list.Insert(0, new CurvePoint(0.0, num4)); + } + } + + return list; + } + + + /// <summary> + /// 璁$畻鏁堢巼 瀵瑰叾鏁堢巼 + /// </summary> + public static List<CurvePoint> CalculateP_AlignPointE(List<CurvePoint> ptQHs, List<CurvePoint> ptQEs, double midu, double ref_zero_power, bool isXStartZero) + { + if (ptQHs == null || ptQHs.Count < 3) + { + return null; + } + + if (ptQEs == null || ptQEs.Count < 3) + { + return null; + } + + + List<CurvePoint> list = new List<CurvePoint>(); + if (ptQHs.IsEqualValueX(ptQEs)) + { + for (int i = 0; i < ptQEs.Count(); i++) + { + double x = ptQEs[i].X; + double y = ptQEs[i].Y; + double y2 = ptQHs[i].Y; + if (!(y2 < 0.1) && !(y < 0.5)) + { + double num = CalculateP(x, y2, y, midu); + num = ((num < 2.0) ? Math.Round(num, 3) : ((num < 30.0) ? Math.Round(num, 2) : ((!(num < 100.0)) ? Math.Round(num, 0) : Math.Round(num, 1)))); + list.Add(new CurvePoint(x, num)); + } + } + } + else + { + FitHelper fitCurveHelper = new FitHelper(ptQEs); + FitHelper fitCurveHelper2 = new FitHelper(ptQHs); + for (int j = 0; j < ptQEs.Count(); j++) + { + double x2 = ptQEs[j].X; + double fitPointY = fitCurveHelper.GetFitPointY(x2); + double fitPointY2 = fitCurveHelper2.GetFitPointY(x2); + if (!(fitPointY2 < 0.1) && !(fitPointY < 0.5)) + { + double num2 = CalculateP(x2, fitPointY2, fitPointY, midu); + num2 = ((num2 < 2.0) ? Math.Round(num2, 3) : ((num2 < 30.0) ? Math.Round(num2, 2) : ((!(num2 < 100.0)) ? Math.Round(num2, 0) : Math.Round(num2, 1)))); + list.Add(new CurvePoint(x2, num2)); + } + } + } + + if (isXStartZero) + { + if (list[0].X < 1.0) + { + if (ref_zero_power > 0.0) + { + list[0].X = 0.0; + list[0].Y = ref_zero_power; + } + else + { + list.RemoveAt(0); + var fitPoints = FitHelper.GetFitPoints(list); + if (fitPoints[0].Y >= fitPoints[1].Y) + { + fitPoints[0].Y = fitPoints[1].Y * 0.95; + } + + double num3 = CurveLineHelper.GetYbyX(fitPoints[0].X, fitPoints[0].Y, fitPoints[1].X, fitPoints[1].Y, 0.0); + if (num3 < 0.001) + { + num3 = fitPoints[0].Y; + } + + num3 = ((num3 < 2.0) ? Math.Round(num3, 3) : ((num3 < 30.0) ? Math.Round(num3, 2) : ((!(num3 < 100.0)) ? Math.Round(num3, 0) : Math.Round(num3, 1)))); + list.Insert(0, new CurvePoint(0.0, num3)); + } + } + else if (ref_zero_power > 0.0) + { + list.Insert(0, new CurvePoint(0.0, ref_zero_power)); + } + else + { + var fitPoints2 = FitHelper.GetFitPoints(list); + if (fitPoints2[0].Y >= fitPoints2[1].Y) + { + fitPoints2[0].Y = fitPoints2[1].Y * 0.95; + } + + double num4 = CurveLineHelper.GetYbyX(fitPoints2[0].X, fitPoints2[0].Y, fitPoints2[1].X, fitPoints2[1].Y, 0.0); + if (num4 < 0.001) + { + num4 = fitPoints2[0].Y; + } + + num4 = ((num4 < 2.0) ? Math.Round(num4, 3) : ((num4 < 30.0) ? Math.Round(num4, 2) : ((!(num4 < 100.0)) ? Math.Round(num4, 0) : Math.Round(num4, 1)))); + list.Insert(0, new CurvePoint(0.0, num4)); + } + } + + return list; + } + #endregion + + #endregion + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Utils/AmendCurveHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Utils/AmendCurveHelper.cs new file mode 100644 index 0000000..baabfe5 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Utils/AmendCurveHelper.cs @@ -0,0 +1,310 @@ +锘縩amespace IStation.Curve +{ + //淇鏇茬嚎 + public static class AmendCurveHelper + { + /// <summary> + /// 鏍规嵁鏇茬嚎涓竴涓偣锛屼慨鏀规洸绾匡紝鎸夋瘮渚嬭皟鏁达紙0鐐逛笉浼氬彉锛屽湪newPt.X鍙樺寲鏈�澶э紝澶т簬newPt.X鐨勭偣 鍜宯ewPt涓�鏍峰彉鍖� + /// </summary> + /// <param name="originCurvePoints"></param> + /// <param name="newPt">鍦╪ewPt.X</param> + /// <returns></returns> + public static List<CurvePoint> ByOnePointY1(List<CurvePoint> originCurvePoints, CurvePoint newPt) + { + if (originCurvePoints == null) + return null; + + List<CurvePoint> newCurve = new List<CurvePoint>(); + + //璁$畻宸窛 + double baseX = newPt.X; + double baseDisY = originCurvePoints.GetFitPointY(baseX) - newPt.Y; + + // + for (int i = 0; i < originCurvePoints.Count; i++) + { + double dis = 1; + if (originCurvePoints[i].X <= baseX) + { + dis = originCurvePoints[i].X * baseDisY / baseX; + } + else + { + dis = baseDisY; + } + + newCurve.Add(new CurvePoint(originCurvePoints[i].X, originCurvePoints[i].Y - dis)); + } + + // + newCurve.Add(newPt); + + return FitHelper.GetFitPoints(newCurve, eFitType.CubicCurve); + } + + + public static CurveExpress ByOnePointY1(CurveExpress originCurve, CurvePoint newPt) + { + return ByOnePointY1(originCurve, newPt, 30); + } + + //insertPointNumber瓒婂瓒婄簿纭� + public static CurveExpress ByOnePointY1(CurveExpress originCurve, CurvePoint newPt, int insertPointNumber) + { + if (originCurve == null) + return null; + + CurveExpress newCurveExpress = originCurve; + for (int i = 0; i < 3; i++) + { + newCurveExpress = ByOnePointY1鍐呴儴(newCurveExpress, newPt, insertPointNumber); + } + + return newCurveExpress; + } + + private static CurveExpress ByOnePointY1鍐呴儴(CurveExpress originCurve, CurvePoint newPt, int insertPointNumber) + { + if (originCurve == null) + return null; + + List<CurvePoint> newCurvePoints = new List<CurvePoint>(); + List<CurvePoint> originCurvePoints = FitHelper.GetFitPoints(originCurve, insertPointNumber); + //璁$畻宸窛 + double baseX = newPt.X; + double baseDisY = FitHelper.GetFitPointY(originCurve, baseX) - newPt.Y; + + // + for (int i = 0; i < insertPointNumber; i++) + { + double dis = 1; + if (originCurvePoints[i].X <= baseX) + { + dis = originCurvePoints[i].X * baseDisY / baseX; + } + else + { + dis = baseDisY; + } + + newCurvePoints.Add(new CurvePoint(originCurvePoints[i].X, originCurvePoints[i].Y - dis)); + } + + // + newCurvePoints.Add(newPt); + + var newCurveExpress = FitHelper.BuildCurveExpress(newCurvePoints); + return newCurveExpress; + } + + + /// <summary> + /// + /// </summary> + /// <param name="originCurve"></param> + /// <param name="newPt"></param> + /// <param name="ignoreDis">灏忎簬澶氬皯灏变笉杩唬浜�</param> + /// <param name="SplitPointNumber">鍒嗗壊鐐规暟</param> + /// <param name="iterationNum">杩唬娆℃暟</param> + /// <returns></returns> + public static CurveExpress ByOnePointY1(CurveExpress originCurve, CurvePoint newPt, double ignoreDis, + int SplitPointNumber = 100, int iterationNum = 6) + { + if (originCurve == null) + return null; + CurveExpress newCurve = new CurveExpress(originCurve); + + for (int i = 0; i < iterationNum; i++) + { + var pointQE = FitHelper.GetFitPoints(newCurve, SplitPointNumber); + newCurve = FitHelper.BuildCurveExpress(AmendCurveHelper.ByOnePointY1(pointQE, newPt)); + if (Math.Abs(FitHelper.GetFitPointY(newCurve, newPt.X) - newPt.Y) < ignoreDis) + { + return newCurve; + } + } + + return newCurve; + } + + + //2鐐逛慨琛�,鏂版洸绾块�氳繃minPt,maxPt + public static List<CurvePoint> ByTwoPointY1(List<CurvePoint> originCurve0, CurvePoint minPt, CurvePoint fixPt, CurvePoint maxPt) + { + if (originCurve0 == null || originCurve0.Count < 3) + return null; + //if (minPt.X > fixPt.X) + // return null; + //if (fixPt.X > maxPt.X) + // return null; + + double x, y; + + //鍏堜繚璇侀�氳繃棰濆畾瑙勫畾鐐� + double ratedDis1 = originCurve0.GetFitPointY(fixPt.X) - fixPt.Y; + var originCurve1 = originCurve0;// new List<CurvePoint>(); + //foreach (var pt in originCurve0) + //{ + // newCurve.Add(new CurvePoint(pt.X, pt.Y - ratedDis1)); + //} + double ratedPtDisY = originCurve1.GetFitPointY(fixPt.X) - fixPt.Y; + double minPtDisY = originCurve1.GetFitPointY(minPt.X) - minPt.Y; + double maxPtDisY = originCurve1.GetFitPointY(maxPt.X) - maxPt.Y; + + List<CurvePoint> amendCurve = new List<CurvePoint>(); + int num = 4; + double space = minPt.X / (num - 1); + for (int i = 0; i < num - 1; i++) + { + x = space * i; + y = originCurve1.GetFitPointY(x) - minPtDisY * i / (num - 1); + amendCurve.Add(new CurvePoint(x, y)); + } + + //鎻掑叆灏忔祦閲忕偣 + amendCurve.Add(minPt); + + //灏忔祦閲忕偣鍜屼腑闂寸偣鎻掑叆2鐐� + x = minPt.X + (fixPt.X - minPt.X) / 3; + y = originCurve1.GetFitPointY(x) - (ratedPtDisY + (ratedPtDisY - minPtDisY) / 3); + amendCurve.Add(new CurvePoint(x, y)); + + + x = minPt.X + (fixPt.X - minPt.X) * 2 / 3; + y = originCurve1.GetFitPointY(x) - (ratedPtDisY + (ratedPtDisY - minPtDisY) * 2 / 3); + amendCurve.Add(new CurvePoint(x, y)); + + + //鎻掑叆棰濆畾鐐� + amendCurve.Add(fixPt); + + //涓棿鎻掑叆2鐐� + x = fixPt.X + (maxPt.X - fixPt.X) / 3; + y = originCurve1.GetFitPointY(x) - (maxPtDisY + (maxPtDisY - ratedPtDisY) / 3); + amendCurve.Add(new CurvePoint(x, y)); + + + x = minPt.X + (fixPt.X - minPt.X) * 2 / 3; + y = originCurve1.GetFitPointY(x) - (maxPtDisY + (maxPtDisY - ratedPtDisY) * 2 / 3); + amendCurve.Add(new CurvePoint(x, y)); + + + + //鎻掑叆澶ф祦閲忕偣 + amendCurve.Add(maxPt); + + //鎻掑叆鏈�鍚庝竴涓偣 + if (maxPt.X < originCurve1.Last().X * 0.98) + { + amendCurve.Add(new CurvePoint(originCurve1.Last().X, originCurve1.Last().Y - maxPtDisY)); + } + + + return FitHelper.GetFitPoints(amendCurve); + } + + + public static List<CurvePoint> ByThreePointY1(List<CurvePoint> originCurve0, CurvePoint minPt, CurvePoint ratedPt, CurvePoint maxPt, int splitPointNum = 13) + { + if (originCurve0 == null || originCurve0.Count < 3) + return null; + if (minPt.X > ratedPt.X) + return null; + if (ratedPt.X > maxPt.X) + return null; + + var originCurve1 = originCurve0.GetFitPoints(eFitType.CubicCurve, splitPointNum); + + int indexMinDis = 0; + double minDis = minPt.X; + for (int i = 0; i < originCurve1.Count; i++) + { + var pt = originCurve1[i]; + if (Math.Abs(pt.X - minPt.X) < minDis) + { + minDis = Math.Abs(pt.X - minPt.X); + indexMinDis = i; + } + } + originCurve1[indexMinDis].X = minPt.X; + originCurve1[indexMinDis].Y = minPt.Y; + + + indexMinDis = 0; + minDis = ratedPt.X; + for (int i = 0; i < originCurve1.Count; i++) + { + var pt = originCurve1[i]; + if (Math.Abs(pt.X - ratedPt.X) < minDis) + { + minDis = Math.Abs(pt.X - minPt.X); + indexMinDis = i; + } + } + originCurve1[indexMinDis].X = ratedPt.X; + originCurve1[indexMinDis].Y = ratedPt.Y; + + + indexMinDis = 0; + minDis = maxPt.X; + for (int i = 0; i < originCurve1.Count; i++) + { + var pt = originCurve1[i]; + if (Math.Abs(pt.X - maxPt.X) < minDis) + { + minDis = Math.Abs(pt.X - minPt.X); + indexMinDis = i; + } + } + originCurve1[indexMinDis].X = maxPt.X; + originCurve1[indexMinDis].Y = maxPt.Y; + + // FitHelper theCurveFit = new FitHelper(); + // theCurveFit.FitPointNum = originCurve.Count; + return FitHelper.GetFitPoints(originCurve1); + } + + + //淇敼鏇茬嚎0鐐逛綅缃殑鍊硷紝鏇茬嚎鍊间細鏍规嵁姣斾緥閫愭笎鍙樺寲锛岀洿鍒癴ixPtX锛屼笉鍐嶅彉鍖� + public static List<CurvePoint> ByZeroPointY(List<CurvePoint> originCurve, double fixPtX, double zeroPtY) + { + if (originCurve == null || originCurve.Count < 3) + return null; + + List<CurvePoint> newCurve = new List<CurvePoint>(); + + + //璁$畻宸窛 + double zeroDis = originCurve.First().Y - zeroPtY; + + // + for (int i = 0; i < originCurve.Count; i++) + { + double dis = 0; + if (originCurve[i].X <= fixPtX) + { + dis = zeroDis * (1 - originCurve[i].X / fixPtX); + } + else + { + dis = 0; + } + + newCurve.Add(new CurvePoint(originCurve[i].X, originCurve[i].Y - dis)); + } + + // + return newCurve.GetFitPoints(eFitType.CubicCurve, originCurve.Count); + } + + + public static CurveExpress ByZeroPointY(CurveExpress originCurve, double fixPtX, double zeroPtY) + { + if (originCurve == null) + return null; + List<CurvePoint> originCurvePoint = FitHelper.GetFitPoints(originCurve, 30); + return FitHelper.BuildCurveExpress(ByZeroPointY(originCurvePoint, fixPtX, zeroPtY)); + } + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Utils/PermutationAndCombination.cs b/Schedule/IStation.Algorithm/Model/Curve/Utils/PermutationAndCombination.cs new file mode 100644 index 0000000..0cdf850 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Utils/PermutationAndCombination.cs @@ -0,0 +1,187 @@ +锘縩amespace IStation.Curve +{ + // 绠楁硶:鎺掑垪缁勫悎绫� + // + // 鐗堟潈鎵�鏈�(C) Snowdust + // 涓汉鍗氬 http://blog.csdn.net/snowdust & http://snowdust.cnblogs.com + // MSN & Email snowdust77@sina.com + // + // 姝ゆ簮浠g爜鍙厤璐圭敤浜庡悇绫昏蒋浠讹紙鍚晢涓氳蒋浠讹級 + // 鍏佽瀵规浠g爜鐨勮繘涓�姝ヤ慨鏀逛笌寮�鍙� + // 浣嗗繀椤诲畬鏁翠繚鐣欐鐗堟潈淇℃伅 + // + // 璋冪敤鏂规硶濡備笅: + // + // 1.GetPermutation(T[], startIndex, endIndex) + // 瀵箂tartIndex鍒癳ndIndex杩涜鎺掑垪锛屽叾浣欏厓绱犱笉鍙� + // + // 2.GetPermutation(T[]) + // 杩斿洖鏁扮粍鎵�鏈夊厓绱犵殑鍏ㄦ帓鍒� + // + // 3.GetPermutation(T[], n) + // 杩斿洖鏁扮粍涓璶涓厓绱犵殑鎺掑垪 + // + // 4.GetCombination(T[], n) + // 杩斿洖鏁扮粍涓璶涓厓绱犵殑缁勫悎 + + //浣跨敤瀹炰緥 + //int[] arr = new int[6]; + //for (int i = 0; i < arr.Length; i++) + //{ + // arr[i] = i + 1; + //} + ////姹傛帓鍒� + //List<int[]> lst_Permutation = Eventech.Model.PermutationAndCombination<int>.GetPermutation(arr, 3); + ////姹傜粍鍚� + //List<int[]> lst_Combination = Eventech.Model.PermutationAndCombination<int>.GetCombination(arr, 3); + + + public class PermutationAndCombination<T> + { + /// <summary> + /// 浜ゆ崲涓や釜鍙橀噺 + /// </summary> + /// <param name="a">鍙橀噺1</param> + /// <param name="b">鍙橀噺2</param> + public static void Swap(ref T a, ref T b) + { + T temp = a; + a = b; + b = temp; + } + + /// <summary> + /// 閫掑綊绠楁硶姹傛暟缁勭殑缁勫悎(绉佹湁鎴愬憳) + /// </summary> + /// <param name="list">杩斿洖鐨勮寖鍨�</param> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <param name="n">杈呭姪鍙橀噺</param> + /// <param name="m">杈呭姪鍙橀噺</param> + /// <param name="b">杈呭姪鏁扮粍</param> + /// <param name="M">杈呭姪鍙橀噺M</param> + private static void GetCombination(ref List<T[]> list, T[] t, int n, int m, int[] b, int M) + { + for (int i = n; i >= m; i--) + { + b[m - 1] = i - 1; + if (m > 1) + { + GetCombination(ref list, t, i - 1, m - 1, b, M); + } + else + { + if (list == null) + { + list = new List<T[]>(); + } + T[] temp = new T[M]; + for (int j = 0; j < b.Length; j++) + { + temp[j] = t[b[j]]; + } + list.Add(temp); + } + } + } + + /// <summary> + /// 閫掑綊绠楁硶姹傛帓鍒�(绉佹湁鎴愬憳) + /// </summary> + /// <param name="list">杩斿洖鐨勫垪琛�</param> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <param name="startIndex">璧峰鏍囧彿</param> + /// <param name="endIndex">缁撴潫鏍囧彿</param> + private static void GetPermutation(ref List<T[]> list, T[] t, int startIndex, int endIndex) + { + if (startIndex == endIndex) + { + if (list == null) + { + list = new List<T[]>(); + } + T[] temp = new T[t.Length]; + t.CopyTo(temp, 0); + list.Add(temp); + } + else + { + for (int i = startIndex; i <= endIndex; i++) + { + Swap(ref t[startIndex], ref t[i]); + GetPermutation(ref list, t, startIndex + 1, endIndex); + Swap(ref t[startIndex], ref t[i]); + } + } + } + + /// <summary> + /// 姹備粠璧峰鏍囧彿鍒扮粨鏉熸爣鍙风殑鎺掑垪锛屽叾浣欏厓绱犱笉鍙� + /// </summary> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <param name="startIndex">璧峰鏍囧彿</param> + /// <param name="endIndex">缁撴潫鏍囧彿</param> + /// <returns>浠庤捣濮嬫爣鍙峰埌缁撴潫鏍囧彿鎺掑垪鐨勮寖鍨�</returns> + public static List<T[]> GetPermutation(T[] t, int startIndex, int endIndex) + { + if (startIndex < 0 || endIndex > t.Length - 1) + { + return null; + } + List<T[]> list = new List<T[]>(); + GetPermutation(ref list, t, startIndex, endIndex); + return list; + } + + /// <summary> + /// 杩斿洖鏁扮粍鎵�鏈夊厓绱犵殑鍏ㄦ帓鍒� + /// </summary> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <returns>鍏ㄦ帓鍒楃殑鑼冨瀷</returns> + public static List<T[]> GetPermutation(T[] t) + { + return GetPermutation(t, 0, t.Length - 1); + } + + /// <summary> + /// 姹傛暟缁勪腑n涓厓绱犵殑鎺掑垪 + /// </summary> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <param name="n">鍏冪礌涓暟</param> + /// <returns>鏁扮粍涓璶涓厓绱犵殑鎺掑垪</returns> + public static List<T[]> GetPermutation(T[] t, int n) + { + if (n > t.Length) + { + return null; + } + List<T[]> list = new List<T[]>(); + List<T[]> c = GetCombination(t, n); + for (int i = 0; i < c.Count; i++) + { + List<T[]> l = new List<T[]>(); + GetPermutation(ref l, c[i], 0, n - 1); + list.AddRange(l); + } + return list; + } + + + /// <summary> + /// 姹傛暟缁勪腑n涓厓绱犵殑缁勫悎 + /// </summary> + /// <param name="t">鎵�姹傛暟缁�</param> + /// <param name="n">鍏冪礌涓暟</param> + /// <returns>鏁扮粍涓璶涓厓绱犵殑缁勫悎鐨勮寖鍨�</returns> + public static List<T[]> GetCombination(T[] t, int n) + { + if (t.Length < n) + { + return null; + } + int[] temp = new int[n]; + List<T[]> list = new List<T[]>(); + GetCombination(ref list, t, t.Length, n, temp, n); + return list; + } + } +} diff --git a/Schedule/IStation.Algorithm/Model/Curve/Utils/UtilsHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Utils/UtilsHelper.cs new file mode 100644 index 0000000..9f70097 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Curve/Utils/UtilsHelper.cs @@ -0,0 +1,235 @@ +锘縩amespace IStation.Curve +{ + /// <summary> + /// 杈呭姪绫� + /// </summary> + public static class UtilsHelper + { + /// <summary> + /// 姹備袱涓暟鍊肩殑鏈�灏忓�� + /// </summary> + public static double Min(this double first, double second) + { + return first > second ? second : first; + } + + /// <summary> + /// 姹備袱涓暟鍊肩殑鏈�澶у�� + /// </summary> + public static double Max(this double first, double second) + { + return first > second ? first : second; + } + + /// <summary> + /// 鏄惁涓轰腑闂存暟 + /// </summary> + public static bool IsMiddle(this double x, double x1, double x2) + { + return (x >= x1 && x <= x2) || (x <= x1 && x >= x2); + } + + #region 16杩涘埗瀛楃 + /// <summary> + /// 16杩涘埗瀛楃杞崄杩涘埗:濡侫1灏辨槸10*16+1 + /// </summary> + public static int GetDecimalByHexString(string strHexStr) + { + if (strHexStr.Count() != 2) + return 0; + return GetDecimalByHexChar(strHexStr[0]) * 16 + GetDecimalByHexChar(strHexStr[1]); + } + + /// <summary> + /// 鑾峰彇16杩涘埗瀛楃 + /// </summary> + public static short GetDecimalByHexChar(char strHexStr) + { + switch (strHexStr) + { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + case 'a': + case 'A': + return 10; + case 'b': + case 'B': + return 11; + case 'c': + case 'C': + return 12; + case 'd': + case 'D': + return 13; + case 'e': + case 'E': + return 14; + case 'f': + case 'F': + return 15; + + default: + return 0; + } + } + + #endregion + + #region 鍥涜垗浜斿叆鍦嗘暣 + //鍥涜垗浜斿叆鍦嗘暣,濡� 0.44 -> 0.4 , 0.46 -> 0.5//flag--灏忔暟鐐瑰悗浣嶆暟 + public static double Regulate(double v, int flag) + { + bool isNegative = false; + //濡傛灉鏄礋鏁� + if (v < 0) + { + isNegative = true; + v = Math.Abs(v); + } + else + { + isNegative = false; + } + + double value = Math.Round(v, flag); + if (isNegative) + { + value = -value; + } + return value; + } + + //鍥涜垗浜斿叆鍦嗘暣,濡� 0.44 -> 0.4 , 0.46 -> 0.5//flag--灏忔暟鐐瑰悗浣嶆暟 + public static List<IStation.Curve.CurvePoint> Regulate(List<IStation.Curve.CurvePoint> inPoints, int flag) + { + if (inPoints == null) + return null; + List<IStation.Curve.CurvePoint> outPoints = new List<IStation.Curve.CurvePoint>(); + for (int i = 0; i < inPoints.Count(); i++) + { + outPoints.Add(new IStation.Curve.CurvePoint(Regulate(inPoints[i].X, flag), Regulate(inPoints[i].Y, flag))); + } + return outPoints; + } + + public static List<IStation.Curve.CurvePoint> Regulate(List<IStation.Curve.CurvePoint> inPoints, int flagX, int flagY) + { + if (inPoints == null) + return null; + List<IStation.Curve.CurvePoint> outPoints = new List<IStation.Curve.CurvePoint>(); + for (int i = 0; i < inPoints.Count(); i++) + { + outPoints.Add(new IStation.Curve.CurvePoint(Regulate(inPoints[i].X, flagX), Regulate(inPoints[i].Y, flagY))); + } + return outPoints; + } + #endregion + + #region 鍚戜笂鍦嗘暣 + + public static double RegulateUp(double m, int flag) + { + double k = 1; + for (int i = 0; i < flag; i++) + { + k = k * 10; + } + return System.Math.Ceiling(m * k) / k; + } + + public static int RoundUp2(double v) + { + int k = (int)(v / 2) * 2 + 2; + return k; + } + public static int RoundUp5(double v) + { + int k = (int)(v / 5) * 5 + 5; + return k; + } + public static int RoundUp10(double v) + { + int k = (int)(v / 10) * 10 + 10; + return k; + } + #endregion + + #region 鍚戜笅鍦嗘暣 + + public static double RegulateDown(double m, int flag) + { + double k = 1; + for (int i = 0; i < flag; i++) + { + k = k * 10; + } + return System.Math.Floor(m * k) / k; + } + public static int RoundDown2(double v) + { + int k = (int)(v / 2) * 2; + return k; + } + public static int RoundDown5(double v) + { + int k = (int)(v / 5) * 5; + return k; + } + public static int RoundDown10(double v) + { + int k = (int)(v / 10) * 10; + return k; + } + + #endregion + + #region 灏忔暟鐐归暱搴� + /// <summary> + /// 鑾峰彇灏忔暟鐐归暱搴� + /// </summary> + public static int GetDecimalPlacesLength(double value) + { + string text = value.ToString(); + int num = text.IndexOf('.'); + if (num >= 0) + { + return text.Length - num - 1; + } + return 0; + } + + + /// <summary> + /// 鑾峰彇灏忔暟鐐归暱搴� + /// </summary> + public static double GetByPlacesLength(double value, int length) + { + int decimalPlacesLength = GetDecimalPlacesLength(value); + if (decimalPlacesLength > length) + { + return Math.Round(value, length); + } + return value; + } + #endregion + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Json/JsonList.cs b/Schedule/IStation.Algorithm/Model/Json/JsonList.cs new file mode 100644 index 0000000..f783cc4 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Json/JsonList.cs @@ -0,0 +1,38 @@ +锘縩amespace IStation.Model +{ + /// <summary> + /// + /// </summary> + public abstract class JsonList<T> : JsonModel<T> where T : class, new() + { + /// <summary> + /// To json + /// </summary> + public static string ToJson(List<T> list) + { + if (list == null || list.Count < 1) + return default; + return JsonHelper.Object2Json(list); + } + + /// <summary> + /// To list + /// </summary> + public static List<T> ToList(string json) + { + if (string.IsNullOrEmpty(json)) + return null; + try + { + return JsonHelper.Json2Object<List<T>>(json); + } + catch + { + return null; + } + } + + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Json/JsonModel.cs b/Schedule/IStation.Algorithm/Model/Json/JsonModel.cs new file mode 100644 index 0000000..7147236 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Json/JsonModel.cs @@ -0,0 +1,37 @@ +锘縩amespace IStation.Model +{ + /// <summary> + /// + /// </summary> + public abstract class JsonModel<T> where T : class, new() + { + + /// <summary> + /// To json + /// </summary> + /// <returns></returns> + public virtual string ToJson() + { + return JsonHelper.Object2Json(this); + } + + /// <summary> + /// To model + /// </summary> + public static T ToModel(string json) + { + if (string.IsNullOrEmpty(json)) + return null; + try + { + return JsonHelper.Json2Object<T>(json); + } + catch + { + return null; + } + } + + + } +} diff --git a/Schedule/IStation.Algorithm/Model/Pump/Pump.cs b/Schedule/IStation.Algorithm/Model/Pump/Pump.cs new file mode 100644 index 0000000..c1e72fd --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Pump/Pump.cs @@ -0,0 +1,44 @@ +锘縩amespace IStation.Model +{ + public class Pump + { + public Pump() { } + public Pump(Pump rhs) + { + this.Belong = rhs.Belong; + this.Qr = rhs.Qr; + this.Hr = rhs.Hr; + this.Nr = rhs.Nr; + this.Pr = rhs.Pr; + this.Er = rhs.Er; + this.Ic = rhs.Ic; + this.Oc = rhs.Oc; + this.IOd = rhs.IOd; + this.IsBp = rhs.IsBp; + this.IsSxp = rhs.IsSxp; + this.CurveQH = rhs.CurveQH; + this.CurveQE = rhs.CurveQE; + this.CurveQP = rhs.CurveQP; + } + + public int Belong { get; set; } + public int ID { get; set; } + public string Code { get; set; } + public string Name { get; set; } + public double Qr { get; set; } + public double Hr { get; set; } + public double Nr { get; set; } + public double Pr { get; set; } + public double Er { get; set; } + public double? Ic { get; set; } + public double? Oc { get; set; } + public double? IOd { get; set; } + public double? Ie { get; set; } + public double? Oe { get; set; } + public bool IsBp { get; set; } + public bool IsSxp { get; set; } + public CurveExpress CurveQH { get; set; } + public CurveExpress CurveQE { get; set; } + public CurveExpress CurveQP { get; set; } + } +} diff --git "a/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine - \345\244\215\345\210\266.cs" "b/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine - \345\244\215\345\210\266.cs" new file mode 100644 index 0000000..6511954 --- /dev/null +++ "b/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine - \345\244\215\345\210\266.cs" @@ -0,0 +1,101 @@ +锘縩amespace IStation.Model +{ + /// <summary> + /// 璋冨害缁勫悎 + /// </summary> + [SplitTable(SplitType._Custom01)] + public class ScheduleCombine : Model.BaseModel + { + public ScheduleCombine() { } + public ScheduleCombine(ScheduleCombine rhs) + { + this.ID = rhs.ID; + this.Pump1 = rhs.Pump1; + this.Pump2 = rhs.Pump2; + this.Pump3 = rhs.Pump3; + this.Head = rhs.Head; + this.Flow = rhs.Flow; + this.Power = rhs.Power; + this.WP = rhs.WP; + this.UWP = rhs.UWP; + //this.IsExtend = rhs.IsExtend; + //this.ExtendRatio = rhs.ExtendRatio; + } + + public void Round() + { + this.Pump1 = Math.Round(this.Pump1, 1); + this.Pump2 = Math.Round(this.Pump2, 1); + this.Pump3 = Math.Round(this.Pump3, 1); + this.Head = Math.Round(this.Head, 1); + this.Flow = Math.Round(this.Flow, 1); + this.Power = Math.Round(this.Power, 1); + this.WP = Math.Round(this.WP, 1); + this.UWP = Math.Round(this.UWP, 1); + + } + + /// <summary> + /// 杩愯鏍囧織 (鏍囧織鏋氫妇) + /// </summary> + [SplitField] + public string RunFlag { get; set; } + // public int RunFlag { get; set; } + + /// <summary> + /// 娉�1 + /// </summary> + public double Pump1 { get; set; } + + /// <summary> + /// 娉�2 + /// </summary> + public double Pump2 { get; set; } + + /// <summary> + /// 娉�3 + /// </summary> + public double Pump3 { get; set; } + + + /// <summary> + /// 鎵▼ + /// </summary> + public double Head { get; set; } + + /// <summary> + /// 鎬绘祦閲� + /// </summary> + public double Flow { get; set; } + + /// <summary> + /// 鎬诲姛鐜� + /// </summary> + public double Power { get; set; } + + /// <summary> + /// 鍗冨惃姘磋兘鑰� + /// </summary> + public double WP { get; set; } + + /// <summary> + /// 鍗曚綅鑳借�� + /// </summary> + public double UWP { get; set; } + + ///// <summary> + ///// 鏄惁寤堕暱 + ///// </summary> + //public bool IsExtend { get; set; } + + ///// <summary> + ///// 寤堕暱姣� + ///// </summary> + //public double ExtendRatio { get; set; } + public DateTime CreateTime { get; set; } + + + } + + +} diff --git a/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine.cs b/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine.cs new file mode 100644 index 0000000..c6dfc38 --- /dev/null +++ b/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine.cs @@ -0,0 +1,53 @@ +锘縩amespace IStation.Model +{ + /// <summary> + /// 璋冨害缁勫悎 + /// </summary> + [SugarTable("ScheduleCombine")] + public class ScheduleCombine : Model.BaseModel + { + public ScheduleCombine() { } + public ScheduleCombine(ScheduleCombine rhs) + { + this.RunFlag = rhs.RunFlag; + this.RunCount = rhs.RunCount; + this.RunHZ = rhs.RunHZ; + this.CurveQH = rhs.CurveQH; + this.CurveQP = rhs.CurveQP; + this.AnaStatus = rhs.AnaStatus; + } + + /// <summary> + /// 杩愯鏍囧織 + /// </summary> + public string RunFlag { get; set; } + + /// <summary> + /// 杩愯鏁伴噺 + /// </summary> + public int RunCount { get; set; } + + /// <summary> + /// 杩愯棰戠巼鍒楄〃 + /// </summary> + public string RunHZ { get; set; } + + /// <summary> + /// 娴侀噺鎵▼绾� + /// </summary> + public CurveExpress CurveQH { get; set; } + + /// <summary> + /// 娴侀噺鍔熺巼绾� + /// </summary> + public CurveExpress CurveQP { get; set; } + + /// <summary> + /// 鍒嗘瀽鐘舵�� + /// </summary> + public bool AnaStatus { get; set; } + + } + + +} diff --git a/Schedule/IStation.Algorithm/Schedule/Output/ScheduleScheme.cs b/Schedule/IStation.Algorithm/Schedule/Output/ScheduleScheme.cs new file mode 100644 index 0000000..61b750e --- /dev/null +++ b/Schedule/IStation.Algorithm/Schedule/Output/ScheduleScheme.cs @@ -0,0 +1,77 @@ +锘縩amespace IStation.Algorithm +{ + /// <summary> + /// 璋冨害鏂规 + /// </summary> + public class ScheduleScheme + { + public ScheduleScheme() { } + public ScheduleScheme(ScheduleScheme rhs) + { + this.Belong = rhs.Belong; + this.ID = rhs.ID; + this.RunFlags = rhs.RunFlags; + this.RunCount = rhs.RunCount; + this.FrequencyList = rhs.FrequencyList?.ToList(); + this.TotalFlow = rhs.TotalFlow; + this.TotalHead = rhs.TotalHead; + this.TotalPower = rhs.TotalPower; + this.WP = rhs.WP; + this.UWP = rhs.UWP; + } + + + /// <summary> + /// 鎵�灞� + /// </summary> + public int Belong { get; set; } + + /// <summary> + /// 鏍囪瘑 + /// </summary> + public long ID { get; set; } + + /// <summary> + /// 娉佃繍琛屾爣蹇� + /// </summary> + public int RunFlags { get; set; } + + /// <summary> + /// 娉佃繍琛屾暟閲� + /// </summary> + public int RunCount { get; set; } + + /// <summary> + /// 杩愯棰戠巼鍒楄〃 + /// </summary> + public List<int> FrequencyList { get; set; } + + /// <summary> + /// 鎬绘祦閲� + /// </summary> + public double TotalFlow { get; set; } + + /// <summary> + /// 鎬绘壃绋� + /// </summary> + public double TotalHead { get; set; } + + /// <summary> + /// 鎬诲姛鐜� + /// </summary> + public int TotalPower { get; set; } + + /// <summary> + /// 鍗冨惃姘磋兘鑰� + /// </summary> + public double WP { get; set; } + + /// <summary> + /// 鍗曚綅鑳借�� + /// </summary> + public double UWP { get; set; } + + } + + +} diff --git "a/Schedule/IStation.Algorithm/Schedule/ScheduleCalc - \345\244\215\345\210\266.cs" "b/Schedule/IStation.Algorithm/Schedule/ScheduleCalc - \345\244\215\345\210\266.cs" new file mode 100644 index 0000000..940cfa5 --- /dev/null +++ "b/Schedule/IStation.Algorithm/Schedule/ScheduleCalc - \345\244\215\345\210\266.cs" @@ -0,0 +1,1932 @@ +锘縩amespace IStation.Algorithm +{ + /// <summary> + /// 璋冨害鍒嗘瀽(鏍稿績绠楁硶) + /// </summary> + public class ScheduleCalc + { + double _frequency_def = 50; + double _frequency_min = 25; + double _frequency_max = 50; + double _frequency_space = 0.1;//棰戠巼闂撮殧 + + + public bool CalcOptList(List<Model.Pump> pumps) + { + if (pumps == null || pumps.Count < 1) + return false; + + #region 鑾峰彇骞堕绠椾竴涓� + + var fixPumpCalcList = new List<PumpCalcModel>();//鍥洪娉� + var frePumpCalcList = new List<PumpCalcModel>();//鍙橀娉� + + foreach (var pump in pumps) + { + if (pump.IsBp) + { + //鍙橀娉� + var calcModel = new PumpCalcModel(pump, _frequency_min, _frequency_max, _frequency_space); + if (calcModel.AllowCalc) + frePumpCalcList.Add(calcModel); + + } + else + { + //鍥洪娉� + var calcModel = new PumpCalcModel(pump); + if (calcModel.AllowCalc) + fixPumpCalcList.Add(calcModel); + } + } + + #endregion + + var pumpCount = pumps.Count; + for (int runCount = 1; runCount <= 8; runCount++) + { + var arr = Combination(pumps, runCount); + pump_combine.Add(arr.ToList()); + } + + + #region 寮�濮嬪垎鏋� + + + if (fixPumpCalcList == null || fixPumpCalcList.Count() == 0) + { + //娌℃湁鍚堥�傜殑鍥洪娉� + var array = frePumpCalcList.ToArray(); + AddOnlyFrePumpPrj(array); + } + else + { + //鍒嗘瀽娌℃湁鍙橀娉靛紑鍚殑鎯呭喌 + AddOnlyFrePumpPrj(frePumpCalcList.ToArray()); + + //鍒嗘瀽鏈夊浐棰戞车寮�鍚殑鎯呭喌 + for (int fixPumpNum = 1; fixPumpNum <= fixPumpCalcList.Count(); fixPumpNum++) + { + + //寰楀埌鎵�鏈夋帓鍒楃粍鍚�(宸ラ) + List<ISupply.WinFrmUI.Epanet.Dispatch.Model.FixPumpAnaData[]> fixPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FixPumpAnaData>.GetCombination( + fixPumpCalcList.ToArray(), fixPumpNum); + + #region 鍒嗘瀽姣忕缁勫悎 + foreach (ISupply.WinFrmUI.Epanet.Dispatch.Model.FixPumpAnaData[] fixPumpAnaCombine in fixPumpAnaCombineList) + { + //閬嶅巻鍚勭宸ラ缁勫悎 + #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉� + List<long> machine_ids = new List<long>(); + if (fixPumpAnaCombine != null) + { + foreach (var item in fixPumpAnaCombine) + machine_ids.Add(item.MachineDetail.MachineID); + } + if (!IsAccordMachineRunFilter(machine_ids)) + { + continue; + } + #endregion + + var fix_pump_total_flow = (from x in fixPumpAnaCombine select x.AnaItem50Hz.WorkPointQ).Sum(); + if (fix_pump_total_flow > _targetQmax) + { + continue; + } + if (fix_pump_total_flow > _targetQmin) + {//鍙敤鍥洪娉靛嵆鍙� + AddOnlyFixPumpPrj(fixPumpAnaCombine, fix_pump_total_flow); + } + else if (frePumpCalcList.Count() > 0) + { + //鍙湁涓�鍙板彉棰戞车 + AddSingleFreqPumpPrj1(fixPumpAnaCombine, frePumpCalcList.ToArray()); + //鏈�2鍙板彉棰戞车 + if (frePumpCalcList.Count() >= 2) + { + AddMultiFreqPumpPrj2(fixPumpAnaCombine, frePumpCalcList.ToArray()); + } + //鏈�3鍙板彉棰戞车 + if (frePumpCalcList.Count() >= 3) + { + AddMultiFreqPumpPrj3(fixPumpAnaCombine, frePumpCalcList.ToArray()); + } + //鏈�4鍙板彉棰戞车 + if (frePumpCalcList.Count() >= 4) + { + AddMultiFreqPumpPrj4(fixPumpAnaCombine, frePumpCalcList.ToArray(), fix_pump_total_flow); + } + //鏈�5鍙板彉棰戞车 + if (frePumpCalcList.Count() >= 5) + { + AddMultiFreqPumpPrj5(fixPumpAnaCombine, frePumpCalcList.ToArray(), fix_pump_total_flow); + } + } + } + #endregion + } + } + #endregion + + //璁$畻 + var ds_disp_project_list = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme>(); + foreach (var project in _anaSchemeList) + { + //璁$畻娴侀噺 + //project.TotalWrkQ = (from x in project.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum(); + if (project.TotalWrkQ <= _targetQmax && project.TotalWrkQ >= this._targetQmin) + ds_disp_project_list.Add(project); + + project.UWP = Math.Round(project.UWP, 3); + project.WP = Math.Round(project.WP, 3); + project.SpanQ = Math.Round(project.TotalWrkQ - _targetQ, 0); + project.CalcItemParas(); + } + + // 0 鍔熺巼 1 娴侀噺闂撮殧 + if (SchemeSortType == ISupply.WinFrmUI.Epanet.Dispatch.Model.eAnaSchemeSortType.鍔熺巼) + ds_disp_project_list = (from x in ds_disp_project_list orderby x.TotalWrkP select x).ToList(); + else if (SchemeSortType == ISupply.WinFrmUI.Epanet.Dispatch.Model.eAnaSchemeSortType.娴侀噺宸��) + ds_disp_project_list = (from x in ds_disp_project_list orderby Math.Abs(x.SpanQ) select x).ToList(); + + //閲嶆柊缂栧彿ID + for (int i = 0; i < ds_disp_project_list.Count; i++) + { + ds_disp_project_list[i].ID = i + 1; + } + + if (ReturnSchemeNumber <= 0) + return ds_disp_project_list; + else + return ds_disp_project_list.Take(ReturnSchemeNumber).ToList(); + } + + + + + + + + #region 绠楀嚭鏄惁绗﹀悎鐨勫浐棰戞车:GetFixPumpAnaData + privatePumpCalcModel GetFixPumpAnaData(ISupply.WinFrmUI.Epanet.Dispatch.Model.MachineDetailEx Machine) + { + if (Machine == null) + return null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem anaData = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + if (CalcAnaCurve(Machine.MaxCurveInfoQH, Machine.MaxCurveInfoQP, + this._targetH, 50, Machine.Percentage, ref anaData) <= 0) + return null; + + anaData.CurveInfoQH = Machine.MaxCurveInfoQH; + anaData.CurveInfoQP = Machine.MaxCurveInfoQP; + anaData.Frequence = 50; + anaData.Speed = Machine.RatedN; + + return newPumpCalcModel() { MachineDetail = Machine, AnaItem50Hz = anaData }; + } + #endregion + + + #region 绠楀嚭鏄惁绗﹀悎鐨勫彉棰戞车:GetFrePumpAnaData + + privatePumpCalcModel GetFrePumpAnaData( + ISupply.WinFrmUI.Epanet.Dispatch.Model.MachineDetailEx Machine) + { + if (Machine == null) + return null; + + PumpCalcModel anaData = newPumpCalcModel(); + anaData.MachineDetail = Machine; + anaData.AnaItemList = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem>(); + + double targetH = this._targetH; + + + + + double maxH; + double minH; + var points50 = ISupply.Model.FitCurveHelper.GetFitPoints(Machine.MaxCurveInfoQH, 50); + ISupply.Model.FitCurveHelper.GetMinMaxPointY(points50, out maxH, out minH); + if (maxH < targetH) + { + return null; + } + + + var pointsMin = ISupply.Common.SpeedSimuCalculer.GetSimuPointQH(Machine.MaxCurveInfoQH, 50, MinChangeFrequence); + ISupply.Model.FitCurveHelper.GetMinMaxPointY(pointsMin, out maxH, out minH); + if (minH > targetH) + { + return null; + } + + //鑾峰彇姣忎釜棰戠巼鐨勫��(绮楃畻) + for (double freqCurrentFrequ = 50; freqCurrentFrequ > MinChangeFrequence; + freqCurrentFrequ = freqCurrentFrequ - ChangeFrequenceSpaece) + { + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curve = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + int ret = CalcAnaCurve(Machine.MaxCurveInfoQH, Machine.MaxCurveInfoQP, this._targetH, freqCurrentFrequ, Machine.Percentage, ref curve); + if (ret == -1) + break;//-1 琛ㄧず鏈�澶ф壃绋嬮兘宸茬粡浣庝簬鐩爣鎵▼浜�, 娌″繀瑕佸啀杩唬浜� + if (ret == 0) + continue; + curve.Speed = Machine.CalcSpeedByFrequence(curve.Frequence); + + anaData.AnaItemList.Add(curve); + } + + + + return anaData; + } + #endregion + + + #region 绮剧畻 + private void CalcDetailAccurate(ref ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme project) + { + //娌℃湁鍙橀娉�, 灏辨病鏈夊繀瑕佺簿绠� + var frequecePumps = (from x in project.Items where x.IsFrequency select x); + if (frequecePumps == null || frequecePumps.Count() == 0) + return; + + + if (frequecePumps.Count() == 1) + {//鍙湁涓�鍙�,姣旇緝绠�鍗� + #region 鍙湁涓�鍙�,姣旇緝绠�鍗� + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem current_adjust_item = frequecePumps.FirstOrDefault(); + var current_machine = (from x in this._allMachineList where x.MachineID == current_adjust_item.MachineID select x).FirstOrDefault(); + if (current_machine == null) + return; + + var totalWrkQ_other = (from x in project.Items where x.WorkPointQ > 0 && x.MachineID != current_adjust_item.MachineID select x.WorkPointQ).Sum(); + // var target_pump_flow = this._targetQ - totalWrkQ_other; + + var max_fr = Math.Min(50, current_adjust_item.Frequence + ChangeFrequenceSpaece * 2); + var min_fr = current_adjust_item.Frequence - ChangeFrequenceSpaece * 2; + + double flow_chajiu = Math.Abs(project.TotalWrkQ - this._targetQ); + + for (double fre = max_fr; fre > min_fr; fre = fre - 0.1) + { + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem ana_item = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + int ret = CalcAnaCurve(current_machine.MaxCurveInfoQH, current_machine.MaxCurveInfoQP, + this._targetH, + fre, current_machine.Percentage, ref ana_item); + if (ret == -1) + return;//-1 琛ㄧず鏈�澶ф壃绋嬮兘宸茬粡浣庝簬鐩爣鎵▼浜�, 娌″繀瑕佸啀杩唬浜� + + if (ret == 0) + continue; + var total_q = totalWrkQ_other + ana_item.WorkPointQ; + if (total_q < this._targetQmin) + break;//濡傛灉宸茬粡浣庝簬鏈�灏�,涓嶇敤鍐嶅彉棰戜簡 + if (Math.Abs(total_q - this._targetQ) < flow_chajiu) + { + flow_chajiu = Math.Abs(total_q - this._targetQ); + current_adjust_item.Frequence = Math.Round(fre, 1); + current_adjust_item.WorkPointQ = Math.Round(ana_item.WorkPointQ, 1); + current_adjust_item.WorkPointP = Math.Round(ana_item.WorkPointP, 1); + + + // 鍐嶆眹鎬讳竴涓� + project.TotalWrkQ = (from x in project.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum(); + project.TotalWrkP = (from x in project.Items where x.WorkPointP > 0 select x.WorkPointP).Sum(); + + project.UWP = Calcu_UWP(project.TotalWrkP, project.TotalWrkQ, this._targetH); + project.WP = Calcu_WP(project.TotalWrkP, project.TotalWrkQ); + } + + if (total_q < this._targetQ) + { + break; + } + } + #endregion + + } + else if (frequecePumps.Count() == 2) + { + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem adjust_item_1 = frequecePumps.ElementAt(0); + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem adjust_item_2 = frequecePumps.ElementAt(1); + var adjust_machine_1 = (from x in this._allMachineList where x.MachineID == adjust_item_1.MachineID select x).FirstOrDefault(); + if (adjust_machine_1 == null) + return; + var adjust_machine_2 = (from x in this._allMachineList where x.MachineID == adjust_item_2.MachineID select x).FirstOrDefault(); + if (adjust_machine_2 == null) + return; + //闄や簡璋冭В娉电殑鍏朵粬娉垫祦閲� + var total_flow_other = (from x in project.Items where x.WorkPointQ > 0 && x.MachineID != adjust_machine_1.MachineID && x.MachineID != adjust_machine_2.MachineID select x.WorkPointQ).Sum(); + + var total_power_other = (from x in project.Items where x.WorkPointP > 0 && x.MachineID != adjust_machine_1.MachineID && x.MachineID != adjust_machine_2.MachineID select x.WorkPointP).Sum(); + + List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem> item_js_1 = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem>(); + for (double fre = Math.Min(50, adjust_item_1.Frequence + ChangeFrequenceSpaece * 2); + fre > adjust_item_1.Frequence - ChangeFrequenceSpaece * 2; + fre = fre - 0.1) + { + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem ana_item = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + int ret = CalcAnaCurve(adjust_machine_1.MaxCurveInfoQH, + adjust_machine_1.MaxCurveInfoQP, + this._targetH, + fre, adjust_machine_1.Percentage, ref ana_item); + if (ret == -1) + break; + item_js_1.Add(ana_item); + } + + List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem> item_js_2 = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem>(); + for (double fre = Math.Min(50, adjust_item_2.Frequence + ChangeFrequenceSpaece * 2); + fre > adjust_item_2.Frequence - ChangeFrequenceSpaece * 2; + fre = fre - 0.1) + { + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem ana_item = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + int ret = CalcAnaCurve(adjust_machine_2.MaxCurveInfoQH, adjust_machine_2.MaxCurveInfoQP, + this._targetH, fre, adjust_machine_2.Percentage, ref ana_item); + if (ret == -1) + break; + item_js_2.Add(ana_item); + } + + double ump_chajiu = project.UWP; + + foreach (var item1 in item_js_1) + { + foreach (var item2 in item_js_2) + { + var total_flow = item1.WorkPointQ + item2.WorkPointQ + total_flow_other; + if (Math.Abs(total_flow - this._targetQ) < this._targetQ * 0.01) + { + var total_power = item1.WorkPointP + item2.WorkPointP + total_power_other; + var uwp = Calcu_UWP(total_power, total_flow, this._targetH); + + if (uwp < ump_chajiu) + { + adjust_item_1.ResetItem(item1); + adjust_item_2.ResetItem(item2); + adjust_item_1.Frequence = Math.Round(item1.Frequence, 1); + adjust_item_2.Frequence = Math.Round(item2.Frequence, 1); + + // 鍐嶆眹鎬讳竴涓� + project.TotalWrkQ = (from x in project.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum(); + project.TotalWrkP = (from x in project.Items where x.WorkPointP > 0 select x.WorkPointP).Sum(); + + project.UWP = Calcu_UWP(project.TotalWrkP, project.TotalWrkQ, this._targetH); + project.WP = Calcu_WP(project.TotalWrkP, project.TotalWrkQ); + } + + } + } + } + + + + } + else + { + //鍝釜娉垫祦閲忓ぇ,灏辫皟鏁村摢涓车 + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem aj_pump = frequecePumps.FirstOrDefault(); + foreach (var p in project.Items) + { + if (!p.IsFrequency) + continue; + if (p.WorkPointQ > aj_pump.WorkPointQ) + { + aj_pump = p; + } + } + //闄や簡璋冭В娉电殑鍏朵粬娉垫祦閲� + var total_flow_other = (from x in project.Items where x.WorkPointQ > 0 && x.MachineID != aj_pump.MachineID select x.WorkPointQ).Sum(); + // + double flow_chajiu = Math.Abs(project.TotalWrkQ - this._targetQ); + // + var pump_curve = (from x in this._allMachineList where x.MachineID == aj_pump.MachineID select x).FirstOrDefault(); + if (pump_curve != null) + { + var max_fr = Math.Min(50, aj_pump.Frequence + ChangeFrequenceSpaece * 2); + var min_fr = aj_pump.Frequence - ChangeFrequenceSpaece * 2; + for (double fre = max_fr; fre > min_fr; fre = fre - 0.1) + { + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curve = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + int ret = CalcAnaCurve(pump_curve.MaxCurveInfoQH, pump_curve.MaxCurveInfoQP, + this._targetH, fre, pump_curve.Percentage, ref curve); + if (ret == -1) + break;//-1 琛ㄧず鏈�澶ф壃绋嬮兘宸茬粡浣庝簬鐩爣鎵▼浜�, 娌″繀瑕佸啀杩唬浜� + if (ret == 0) + continue; + var total_q = total_flow_other + curve.WorkPointQ; + if (total_q < this._targetQmin) + break;//濡傛灉宸茬粡浣庝簬鏈�灏�,涓嶇敤鍐嶅彉棰戜簡 + if (Math.Abs(total_q - this._targetQ) < flow_chajiu) + { + flow_chajiu = Math.Abs(total_q - this._targetQ); + aj_pump.Frequence = Math.Round(fre, 1); + aj_pump.WorkPointQ = Math.Round(curve.WorkPointQ, 1); + aj_pump.WorkPointP = Math.Round(curve.WorkPointP, 1); + + //鍐嶆眹鎬讳竴涓� + project.TotalWrkQ = (from x in project.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum(); + project.TotalWrkP = (from x in project.Items where x.WorkPointP > 0 select x.WorkPointP).Sum(); + + project.UWP = Calcu_UWP(project.TotalWrkP, project.TotalWrkQ, this._targetH); + project.WP = Calcu_WP(project.TotalWrkP, project.TotalWrkQ); + } + + if (total_q < this._targetQ) + { + break; + } + } + } + } + + + } + #endregion + + + #region 鏍规嵁棰戠巼鍊�,璁$畻鍙橀鏇茬嚎 + /// <summary> + /// 鏍规嵁棰戠巼鍊�,璁$畻鍙橀鏇茬嚎(澶栭儴涔熶細璋冪敤) + /// </summary> + /// <param name="MaxCurveInfoQH"></param> + /// <param name="MaxCurveInfoQP"></param> + /// <param name="targetH"></param> + /// <param name="freqCurrentFrequ"></param> + /// <param name="ana_data"></param> + /// <returns></returns> + public static int CalcAnaCurve( + ISupply.Model.CurveExpress MaxCurveInfoQH, + ISupply.Model.CurveExpress MaxCurveInfoQP, + double targetH, + double freqCurrentFrequ,//棰戠巼鍊� + double extendMaxRatio, + ref ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem ana_data) + { + if (ana_data == null) + ana_data = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + + if (freqCurrentFrequ >= 49.9) + { + ana_data.Frequence = freqCurrentFrequ; + ana_data.CurveInfoQH = MaxCurveInfoQH; + ana_data.CurveInfoQP = MaxCurveInfoQP; + + double flow = 0; + var pointsQH = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(ana_data.CurveInfoQH, extendMaxRatio, 50); + if (!GetFolwByHead(pointsQH, targetH, ref flow)) + { + ana_data.IsOverMaxH = true; + ana_data.Note = "宸茶秴鍑烘渶澶у彲琛岀殑娴侀噺"; + return 0; + } + flow = Math.Round(flow, 1); + + var head = ISupply.Model.FitCurveHelper.GetFitPointY(ana_data.CurveInfoQH, Math.Round(flow, 1)); + head = Math.Round(head, 1); + ana_data.WorkPointQ = flow; + ana_data.WorkPointH = head; + ana_data.WorkPointP = Math.Round(ISupply.Model.FitCurveHelper.GetFitPointY(ana_data.CurveInfoQP, ana_data.WorkPointQ), 1); + ana_data.WorkPointE = Math.Round(ISupply.Common.PumpParaHelper.CalculateE(ana_data.WorkPointQ, ana_data.WorkPointH, ana_data.WorkPointP), 1); + + ana_data.IsExtendCurve = false; + if (flow > ana_data.CurveInfoQH.Max) + {//鍦ㄥ欢闀跨嚎涓� + ana_data.IsExtendCurve = true; + ana_data.RatioExtend = extendMaxRatio; + + //寤堕暱鐜� + double extRatioQ = Math.Round(flow * 100 / ana_data.CurveInfoQH.Max, 1); + ana_data.Note = string.Format("鍦ㄥ欢闀挎洸绾块儴鍒�,鍙傛暟鍙兘涓嶅噯纭�,寤堕暱鐜囦负:{0:0.0}", extRatioQ); + } + + return 1; + } + else + { + #region 鍙橀 + + ana_data.Frequence = Math.Round(freqCurrentFrequ, 1); + + + ana_data.CurveInfoQH = ISupply.Common.SpeedSimuCalculer.GetSimuPointQH(MaxCurveInfoQH, 50, ana_data.Frequence); + ana_data.CurveInfoQP = ISupply.Common.SpeedSimuCalculer.GetSimuPointQP(MaxCurveInfoQP, 50, ana_data.Frequence); + + double flow = 0; + var pointsQH = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(ana_data.CurveInfoQH, extendMaxRatio, 50); + if (!GetFolwByHead(pointsQH, targetH, ref flow)) + { + ana_data.IsOverMaxH = true; + ana_data.Note = "宸茶秴鍑烘渶澶у彲琛岀殑娴侀噺"; + return 0; + } + flow = Math.Round(flow, 1); + + var head = ISupply.Model.FitCurveHelper.GetFitPointY(ana_data.CurveInfoQH, Math.Round(flow, 1)); + head = Math.Round(head, 1); + ana_data.WorkPointQ = flow; + ana_data.WorkPointH = head; + ana_data.WorkPointP = Math.Round(ISupply.Model.FitCurveHelper.GetFitPointY(ana_data.CurveInfoQP, ana_data.WorkPointQ), 1); + ana_data.WorkPointE = Math.Round(ISupply.Common.PumpParaHelper.CalculateE(ana_data.WorkPointQ, ana_data.WorkPointH, ana_data.WorkPointP), 1); + + ana_data.IsExtendCurve = false; + if (flow > ana_data.CurveInfoQH.Max) + {//鍦ㄥ欢闀跨嚎涓� + ana_data.IsExtendCurve = true; + ana_data.RatioExtend = extendMaxRatio; + + //寤堕暱鐜� + double extRatioQ = Math.Round(flow * 100 / ana_data.CurveInfoQH.Max, 1); + ana_data.Note = string.Format("鍦ㄥ欢闀挎洸绾块儴鍒�,鍙傛暟鍙兘涓嶅噯纭�,寤堕暱鐜囦负:{0:0.0}", extRatioQ); + } + + + + #endregion + + return 1; + } + + } + + //鏍规嵁鍘嬪樊璁$畻娴侀噺 + //private static double OtherPressCoeff = 4 * 1000 / Math.PI / 3.6; + + /// <summary> + /// + /// </summary> + /// <param name="curveInfoQH"></param> + /// <param name="h"></param> + /// <param name="q"></param> + /// <returns></returns> + public static bool GetFolwByHead(List<ISupply.Model.CurvePoint> curveInfoQH, double h, ref double q) + { + List<ISupply.Model.CurvePoint> listQ = ISupply.Model.FitCurveHelper.GetInterPointX(curveInfoQH, h); + if (listQ == null || listQ.Count == 0) + { + return false; + } + + q = listQ.Last().X; + + return true; + } + + /// <summary> + /// 鏍规嵁棰戠巼鍊�,璁$畻鍙橀鏇茬嚎 + /// </summary> + /// <param name="MaxCurveInfoQH"></param> + /// <param name="targetH"></param> + /// <param name="freqCurrentFrequ"></param> + /// <param name="curve"></param> + /// <returns></returns> + public static int CalcAnaCurveDDD( + ISupply.Model.CurveExpress MaxCurveInfoQH, + double targetH, + double freqCurrentFrequ,//棰戠巼鍊� + double extendMaxRatio, + ref ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curve) + { + if (curve == null) + curve = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + if (freqCurrentFrequ >= 49.9) + { + curve.Frequence = freqCurrentFrequ; + curve.CurveInfoQH = MaxCurveInfoQH; + double maxH; + double minH; + var points = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(curve.CurveInfoQH, extendMaxRatio, 50); + ISupply.Model.FitCurveHelper.GetMinMaxPointY(points, out maxH, out minH); + if (maxH < targetH) + { + curve.IsOverMaxH = true; + curve.Note = "宸茶秴鍑烘渶澶ц繍琛屾壃绋�"; + return -1;//-1 琛ㄧず鏈�澶ф壃绋嬮兘宸茬粡浣庝簬鐩爣鎵▼浜�, 娌″繀瑕佸啀杩唬浜� + } + + List<ISupply.Model.CurvePoint> interPts = ISupply.Model.FitCurveHelper.GetInterPointX(points, targetH); + if (interPts == null || interPts.Count == 0) + { + curve.IsOverMaxH = true; + curve.Note = "宸茶秴鍑烘渶澶у彲琛岀殑娴侀噺"; + return 0; + } + ISupply.Model.CurvePoint pt = interPts.Last(); + if (pt.X < MinFlowIngore) + { + curve.IsOverMaxH = true; + curve.Note = "宸茶秴鍑烘渶澶у彲琛岀殑娴侀噺"; + return -1; + } + + curve.IsExtendCurve = false; + curve.WorkPointQ = Math.Round(pt.X, 1); + curve.WorkPointH = Math.Round(pt.Y, 1); + + if (pt.X > curve.CurveInfoQH.Max) + {//鍦ㄥ欢闀跨嚎涓� + curve.IsExtendCurve = true; + curve.RatioExtend = extendMaxRatio; + + //寤堕暱鐜� + double extRatioQ = Math.Round(pt.X * 100 / curve.CurveInfoQH.Max, 1); + curve.Note = string.Format("鍦ㄥ欢闀挎洸绾块儴鍒�,鍙傛暟鍙兘涓嶅噯纭�,寤堕暱鐜囦负:{0:0.0}", extRatioQ); + + //鏁堢巼寤堕暱涓嶇ǔ瀹� + //if (anaData.CurveInfoQP != null) + //{ + // var exPointsQP = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(anaData.CurveInfoQP, ExtendMaxRatio, 50);//寤堕暱 + // anaData.WorkPointP = Math.Round(ISupply.Model.FitCurveHelper.GetFitPointY(exPointsQP, anaData.WorkPointQ), 1); + // anaData.WorkPointE = ISupply.Common.PumpParaHelper.CalculateE(anaData.WorkPointQ, anaData.WorkPointH, anaData.WorkPointP); + //} + } + else + { + curve.IsExtendCurve = false; + } + return 1; + } + else + { + #region 鍙橀 + + curve.Frequence = freqCurrentFrequ; + + + curve.CurveInfoQH = ISupply.Common.SpeedSimuCalculer.GetSimuPointQH(MaxCurveInfoQH, 50, freqCurrentFrequ); + + var points = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(curve.CurveInfoQH, extendMaxRatio, 50);//寤堕暱 + + //ISupply.Model.FitCurveHelper.GetMinMaxPointY(points, out maxH, out minH); + List<ISupply.Model.CurvePoint> extPtsQH = ISupply.Model.FitCurveHelper.GetInterPointX(points, targetH); + if (extPtsQH == null || extPtsQH.Count == 0) + {//鍦ㄥ欢闀跨嚎閮芥病鏈変氦鐐�,灏变笉瑕佸啀杩唬浜�. + if (targetH > curve.CurveInfoQH.Index0) + return -1;//-1 琛ㄧず鏈�澶ф壃绋嬮兘宸茬粡浣庝簬鐩爣鎵▼浜�, 娌″繀瑕佸啀杩唬浜� + + return 0; + } + + ISupply.Model.CurvePoint pt = extPtsQH.Last(); + if (pt.X < MinFlowIngore) + { + return -1; + } + + + curve.IsExtendCurve = false; + curve.WorkPointQ = Math.Round(pt.X, 1); + curve.WorkPointH = Math.Round(pt.Y, 1); + + if (pt.X > curve.CurveInfoQH.Max) + {//鍦ㄥ欢闀跨嚎涓� + curve.IsExtendCurve = true; + curve.RatioExtend = extendMaxRatio; + + //寤堕暱鐜� + double extRatioQ = Math.Round(pt.X * 100 / curve.CurveInfoQH.Max, 1); + curve.Note = string.Format("鍦ㄥ欢闀挎洸绾块儴鍒�,鍙傛暟鍙兘涓嶅噯纭�,寤堕暱鐜囦负:{0:0.0}", extRatioQ); + //if (MaxCurveInfoQP != null) + //{ + // curve.CurveInfoQP = ISupply.Common.SpeedSimuCalculer.GetSimuPointQP(MaxCurveInfoQP, 50, freqCurrentFrequ); + // var exPointsQP = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(curve.CurveInfoQP, ExtendMaxRatio, 50);//寤堕暱 + // curve.WorkPointP = Math.Round(ISupply.Model.FitCurveHelper.GetFitPointY(exPointsQP, curve.WorkPointQ), 1); + // curve.WorkPointE = ISupply.Common.PumpParaHelper.CalculateE(curve.WorkPointQ, curve.WorkPointH, curve.WorkPointP); + //} + } + else + { + curve.IsExtendCurve = false; + //if (MaxCurveInfoQP != null) + //{ + // curve.CurveInfoQP = ISupply.Common.SpeedSimuCalculer.GetSimuPointQP(MaxCurveInfoQP, 50, freqCurrentFrequ); + // curve.WorkPointP = Math.Round(ISupply.Model.FitCurveHelper.GetFitPointY(curve.CurveInfoQP, curve.WorkPointQ), 1); + // curve.WorkPointE = ISupply.Common.PumpParaHelper.CalculateE(curve.WorkPointQ, curve.WorkPointH, curve.WorkPointP); + //} + } + #endregion + + return 1; + } + + } + + + #endregion + + + #region 娣诲姞椤圭洰 (鍙湁鐢ㄥ浐棰戞车) + private ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme AddOnlyFixPumpPrj( + PumpCalcModel[] fixPumpAnaDataList, + double totalQ) + { + // + var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme(); + + rowPrj.TotalWrkQ = totalQ; + rowPrj.TotalWrkH = Math.Round(this._targetH, 2); + rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>(); + + foreach (var fixPump in fixPumpAnaDataList) + { + if (fixPump.AnaItem50Hz.WorkPointQ < 1) + continue; + + var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz); + + rowPrj.Items.Add(itemRow); + } + AddScheme(rowPrj, false); + + return rowPrj; + } + #endregion + + + #region 娣诲姞椤圭洰 鍙湁鐢ㄥ彉棰戦娉靛嵆鍙� + private void AddOnlyFrePumpPrj( + PumpCalcModel[] frePumpAnaList) + { + AddSingleFreqPumpPrj1(null, frePumpAnaList); + + //鏈�2鍙板彉棰戞车 + if (frePumpAnaList.Count() >= 2) + { + AddMultiFreqPumpPrj2(null, frePumpAnaList); + } + + //鏈�3鍙板彉棰戞车 + if (frePumpAnaList.Count() >= 3) + { + AddMultiFreqPumpPrj3(null, frePumpAnaList); + } + + //鏈�4鍙板彉棰戞车 + if (frePumpAnaList.Count() >= 4) + { + AddMultiFreqPumpPrj4(null, frePumpAnaList, 0); + } + + //鏈�5鍙板彉棰戞车 + if (frePumpAnaList.Count() >= 5) + { + AddMultiFreqPumpPrj5(null, frePumpAnaList, 0); + } + + + } + #endregion + + + + + + #region 娣诲姞椤圭洰 鍙湁1鍙板彉棰戞车:AddOneFreqPumpPrj + private int AddSingleFreqPumpPrj1(double targetHead, PumpCalcModel[] fixPumpCalcList, PumpCalcModel[] frePumpCalcList) + { + if (frePumpCalcList == null || frePumpCalcList.Length == 0) + return 0; + + double fix_pump_total_flow = 0; + if (fixPumpCalcList != null) + { + fix_pump_total_flow = (from x in fixPumpCalcList select x.AnaItem50Hz.WorkPointQ).Sum(); + } + if (fix_pump_total_flow >= this._targetQ * 0.99) + return 0; + + int addPrjNum = 0; + foreach (var freqPump in frePumpCalcList) + { + #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉� + List<long> machine_ids = new List<long>(); + machine_ids.Add(freqPump.MachineDetail.MachineID); + if (fixPumpCalcList != null) + { + foreach (var item in fixPumpCalcList) + machine_ids.Add(item.MachineDetail.MachineID); + } + if (!IsAccordMachineRunFilter(machine_ids)) + { + continue; + } + #endregion + + + double h = Math.Round(this._targetH, 2); + + var wrkSpeed = ISupply.Common.SpeedSimuCalculer.GetSimuValue( + freqPump.MachineDetail.MaxCurveInfoQH, + new ISupply.Model.CurvePoint(_targetQ - fix_pump_total_flow, h), 2900); + + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem currentAna = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + + double fre = Math.Round(50 * wrkSpeed / 2900, 1); + if (fre > 50) + { + fre = 50; + } + int ret = CalcAnaCurve(freqPump.MachineDetail.MaxCurveInfoQH, + freqPump.MachineDetail.MaxCurveInfoQP, this._targetH, fre, freqPump.MachineDetail.Percentage, ref currentAna); + if (ret == -1) + continue; + if (ret == 0) + continue; + currentAna.Speed = freqPump.MachineDetail.CalcSpeedByFrequence(fre); + + + var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme(); + rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>(); + + #region 鍔犲叆鍥洪娉靛紑鍚俊鎭� + if (fixPumpCalcList != null) + { + foreach (var fixPump in fixPumpCalcList) + { + if (fixPump.AnaItem50Hz.WorkPointQ < 1) + continue; + var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz); + rowPrj.Items.Add(itemRow); + } + } + #endregion + + + var itemRowF = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump.MachineDetail, currentAna); + rowPrj.Items.Add(itemRowF); + + AddScheme(rowPrj, false); + addPrjNum++; + } + + return addPrjNum; + } + #endregion + + + #region 娣诲姞椤圭洰 鍙湁2鍙板彉棰戞车:AddTwoFreqPumpPrj + private int AddMultiFreqPumpPrj2( + PumpCalcModel[] fixPumpCalcList, + PumpCalcModel[] allFreqPumpAnaList) + { + int addPrjNum = 0; + int frePumpNum = 2; + if (allFreqPumpAnaList == null || allFreqPumpAnaList.Count() < frePumpNum) + return addPrjNum; + + //鍒ゆ柇鏈�澶у紑鏈烘暟 + if (_max_open_machine_number > 0) + { + int macine_number = 2; + if (fixPumpCalcList != null) + { + macine_number = macine_number + fixPumpCalcList.Count(); + } + if (macine_number > _max_open_machine_number) + return 0; + } + + + double fix_pump_total_flow = 0; + if (fixPumpCalcList != null) + { + fix_pump_total_flow = (from x in fixPumpCalcList select x.AnaItem50Hz.WorkPointQ).Sum(); + } + + var freqPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData>. + GetCombination(allFreqPumpAnaList, frePumpNum); + + foreach (var freqPumpAnaCombine in freqPumpAnaCombineList) + { + var freqPump1 = freqPumpAnaCombine[0]; + var freqPump2 = freqPumpAnaCombine[1]; + + #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉� + List<long> machine_ids = new List<long> + { + freqPump1.MachineDetail.MachineID, + freqPump2.MachineDetail.MachineID + }; + if (fixPumpCalcList != null) + { + foreach (var item in fixPumpCalcList) + machine_ids.Add(item.MachineDetail.MachineID); + } + if (!IsAccordMachineRunFilter(machine_ids)) + { + continue; + } + #endregion + + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData1 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData2 = null; + + + var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme(); + rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>(); + + #region 鍔犲叆鍥洪娉靛紑鍚俊鎭� + if (fixPumpCalcList != null) + { + foreach (var fixPump in fixPumpCalcList) + { + if (fixPump.AnaItem50Hz.WorkPointQ < 1) + continue; + + var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz); + rowPrj.Items.Add(itemRow); + } + } + #endregion + + bool isActCalc = true; + + if (freqPump1.MachineDetail.PumpCode == freqPump2.MachineDetail.PumpCode) + { + //鍚屽瀷鍙� + #region 娴侀噺瀵瑰崐鍒� + var fre_pump_total_flow = this._targetQ - fix_pump_total_flow; + isActCalc = false; + + double h = Math.Round(this._targetH, 2); + + //娴侀噺瀵瑰崐鍒� + var wrkSpeed1 = ISupply.Common.SpeedSimuCalculer.GetSimuValue(freqPump1.MachineDetail.MaxCurveInfoQH, + new ISupply.Model.CurvePoint((_targetQ - fix_pump_total_flow) * 0.5, h), 2900); + curveData1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + double fre1 = Math.Round(50 * wrkSpeed1 / 2900, 1); + int ret1 = CalcAnaCurve(freqPump1.MachineDetail.MaxCurveInfoQH, + freqPump1.MachineDetail.MaxCurveInfoQP, this._targetH, fre1, freqPump1.MachineDetail.Percentage, ref curveData1); + if (ret1 == -1) + continue; + if (ret1 == 0) + continue; + curveData1.Speed = freqPump1.MachineDetail.CalcSpeedByFrequence(fre1); + + + + var wrkSpeed2 = ISupply.Common.SpeedSimuCalculer.GetSimuValue(freqPump2.MachineDetail.MaxCurveInfoQH, + new ISupply.Model.CurvePoint((_targetQ - fix_pump_total_flow) * 0.5, h), 2900); + curveData2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem(); + double fre2 = Math.Round(50 * wrkSpeed2 / 2900, 1); + int ret2 = CalcAnaCurve(freqPump2.MachineDetail.MaxCurveInfoQH, + freqPump2.MachineDetail.MaxCurveInfoQP, + this._targetH, fre2, freqPump2.MachineDetail.Percentage, ref curveData2); + if (ret2 == -1) + continue; + if (ret2 == 0) + continue; + curveData2.Speed = freqPump2.MachineDetail.CalcSpeedByFrequence(fre2); + #endregion + } + else + { + isActCalc = true; + + double minSpanQ = _targetQ; + double totalPower = freqPump1.MachineDetail.RatedP + freqPump2.MachineDetail.RatedP; + //鎵惧埌绂籣targetQ鏈�鎺ヨ繎鐨勯鐜囩偣 + for (int index1 = 0; index1 < freqPump1.AnaItemList.Count; index1++) + { + //棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index2 = 0; index2 < freqPump2.AnaItemList.Count; index2++) + { + var anaItem1 = freqPump1.AnaItemList[index1]; + var anaItem2 = freqPump2.AnaItemList[index2]; + + + double freTotalQ = anaItem1.WorkPointQ + anaItem2.WorkPointQ; //棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + double freTotalP = anaItem1.WorkPointP + anaItem2.WorkPointP; + + var diffFlow = Math.Abs(fix_pump_total_flow + freTotalQ - _targetQ); + if (diffFlow < minSpanQ) + { + minSpanQ = Math.Abs(fix_pump_total_flow + freTotalQ - _targetQ); + curveData1 = anaItem1; + curveData2 = anaItem2; + totalPower = curveData1.WorkPointP + curveData2.WorkPointP; + } + + if (diffFlow < _targetQ * 0.01 && freTotalP < totalPower) + { + curveData1 = anaItem1; + curveData2 = anaItem2; + totalPower = curveData1.WorkPointP + curveData2.WorkPointP; + } + } + } + } + + + if (curveData1?.WorkPointQ > 1) + { + var itemRowF1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump1.MachineDetail, curveData1); + rowPrj.Items.Add(itemRowF1); + } + + + if (curveData2?.WorkPointQ > 1) + { + var itemRowF2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump2.MachineDetail, curveData2); + rowPrj.Items.Add(itemRowF2); + } + + if (rowPrj.Items.Count == 0) + return default; + + if (AddScheme(rowPrj, isActCalc)) + addPrjNum++; + + } + + return addPrjNum; + } + #endregion + + + #region 娣诲姞椤圭洰 鍙湁3鍙板彉棰戞车:AddThreeFreqPumpPrj + private int AddMultiFreqPumpPrj3( + PumpCalcModel[] fixPumpCalcList, + PumpCalcModel[] allFreqPumpAnaList) + { + int addPrjNum = 0; + int frePumpNum = 3; + if (allFreqPumpAnaList == null || allFreqPumpAnaList.Count() < frePumpNum) + return addPrjNum; + + //鍒ゆ柇鏈�澶у紑鏈烘暟 + if (_max_open_machine_number > 0) + { + int macine_number = 3; + if (fixPumpCalcList != null) + { + macine_number = macine_number + fixPumpCalcList.Count(); + } + if (macine_number > _max_open_machine_number) + return 0; + } + + double fix_pump_total_flow = 0; + if (fixPumpCalcList != null) + { + fix_pump_total_flow = (from x in fixPumpCalcList select x.AnaItem50Hz.WorkPointQ).Sum(); + } + + List<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData[]> freqPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData>.GetCombination( + allFreqPumpAnaList.ToArray(), frePumpNum); + foreach (var freqPumpAnaCombine in freqPumpAnaCombineList) + { + var freqPump1 = freqPumpAnaCombine[0]; + var freqPump2 = freqPumpAnaCombine[1]; + var freqPump3 = freqPumpAnaCombine[2]; + + #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉� + List<long> machine_ids = new List<long> + { + freqPump1.MachineDetail.MachineID, + freqPump2.MachineDetail.MachineID, + freqPump3.MachineDetail.MachineID + }; + if (fixPumpCalcList != null) + { + foreach (var item in fixPumpCalcList) + machine_ids.Add(item.MachineDetail.MachineID); + } + if (!IsAccordMachineRunFilter(machine_ids)) + { + continue; + } + #endregion + + double freTotalQ = fix_pump_total_flow; + double minSpanQ = _targetQmax; + double totalPower = freqPump1.MachineDetail.RatedP + freqPump2.MachineDetail.RatedP + freqPump3.MachineDetail.RatedP; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData1 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData2 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData3 = null; + + // + var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme(); + + rowPrj.TotalWrkQ = freTotalQ; + rowPrj.TotalWrkH = Math.Round(this._targetH, 2); + rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>(); + + //鎵惧埌绂籣targetQ鏈�鎺ヨ繎鐨勯鐜囩偣 + for (int index1 = 0; index1 < freqPump1.AnaItemList.Count; index1++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index2 = 0; index2 < freqPump2.AnaItemList.Count; index2++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index3 = 0; index3 < freqPump3.AnaItemList.Count; index3++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + + var anaItem1 = freqPump1.AnaItemList[index1]; + var anaItem2 = freqPump2.AnaItemList[index2]; + var anaItem3 = freqPump3.AnaItemList[index3]; + + double wrkQ = anaItem1.WorkPointQ + anaItem2.WorkPointQ + anaItem3.WorkPointQ; + double freTotalP = anaItem1.WorkPointP + anaItem2.WorkPointP + anaItem3.WorkPointP; + + + var diffFlow = Math.Abs(fix_pump_total_flow + wrkQ - _targetQ); + if (diffFlow < minSpanQ) + { + freTotalQ = fix_pump_total_flow + wrkQ; + rowPrj.TotalWrkQ = freTotalQ; + minSpanQ = Math.Abs(freTotalQ - _targetQ); + curveData1 = anaItem1; + curveData2 = anaItem2; + curveData3 = anaItem3; + totalPower = curveData1.WorkPointP + curveData2.WorkPointP + curveData3.WorkPointP; + } + + if (diffFlow < _targetQ * 0.01 && freTotalP < totalPower) + { + curveData1 = anaItem1; + curveData2 = anaItem2; + curveData3 = anaItem3; + totalPower = curveData1.WorkPointP + curveData2.WorkPointP + curveData3.WorkPointP; + } + + } + } + } + + // + if (freTotalQ < _targetQmax && freTotalQ > _targetQmin && curveData1 != null) + { + #region 鍔犲叆鍥洪娉靛紑鍚俊鎭� + if (fixPumpCalcList != null) + { + foreach (var fixPump in fixPumpCalcList) + { + if (fixPump.AnaItem50Hz.WorkPointQ < 1) + continue; + var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz); + rowPrj.Items.Add(itemRow); + } + } + #endregion + + + if (curveData1.WorkPointQ > 1) + { + var itemRowF1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump1.MachineDetail, curveData1); + rowPrj.Items.Add(itemRowF1); + } + + if (curveData2.WorkPointQ > 1) + { + var itemRowF2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump2.MachineDetail, curveData2); + rowPrj.Items.Add(itemRowF2); + } + + if (curveData3.WorkPointQ > 1) + { + var itemRowF3 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump3.MachineDetail, curveData3); + rowPrj.Items.Add(itemRowF3); + } + + AddScheme(rowPrj, true); + addPrjNum++; + } + } + + return addPrjNum; + } + #endregion + + + #region 娣诲姞椤圭洰 鍙湁4鍙板彉棰戞车:AddFourFreqPumpPrj + private int AddMultiFreqPumpPrj4( + PumpCalcModel[] fixPumpCalcList, + PumpCalcModel[] allFreqPumpAnaList, + double fix_pump_total_flow) + { + int addPrjNum = 0; + int frePumpNum = 4; + if (allFreqPumpAnaList == null || allFreqPumpAnaList.Count() < frePumpNum) + return addPrjNum; + + //鍒ゆ柇鏈�澶у紑鏈烘暟 + if (_max_open_machine_number > 0) + { + int macine_number = 4; + if (fixPumpCalcList != null) + { + macine_number = macine_number + fixPumpCalcList.Count(); + } + if (macine_number > _max_open_machine_number) + return 0; + } + + List<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData[]> freqPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData>.GetCombination( + allFreqPumpAnaList, frePumpNum); + foreach (var freqPumpAnaCombine in freqPumpAnaCombineList) + { + var freqPump1 = freqPumpAnaCombine[0]; + var freqPump2 = freqPumpAnaCombine[1]; + var freqPump3 = freqPumpAnaCombine[2]; + var freqPump4 = freqPumpAnaCombine[3]; + + #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉� + List<long> machine_ids = new List<long> + { + freqPump1.MachineDetail.MachineID, + freqPump2.MachineDetail.MachineID, + freqPump3.MachineDetail.MachineID, + freqPump4.MachineDetail.MachineID + }; + if (fixPumpCalcList != null) + { + foreach (var item in fixPumpCalcList) + machine_ids.Add(item.MachineDetail.MachineID); + } + if (!IsAccordMachineRunFilter(machine_ids)) + { + continue; + } + #endregion + + double totalPower = + freqPump1.MachineDetail.RatedP + + freqPump2.MachineDetail.RatedP + + freqPump3.MachineDetail.RatedP + + freqPump4.MachineDetail.RatedP; + + double freTotalQ = fix_pump_total_flow; + double minSpanQ = _targetQmax; + + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData1 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData2 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData3 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData4 = null; + + var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme(); + rowPrj.TotalWrkQ = freTotalQ; + rowPrj.TotalWrkH = Math.Round(_targetH, 2); + rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>(); + + + + //鎵惧埌绂籣targetQ鏈�鎺ヨ繎鐨勯鐜囩偣 + for (int index1 = 0; index1 < freqPump1.AnaItemList.Count; index1++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index2 = 0; index2 < freqPump2.AnaItemList.Count; index2++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index3 = 0; index3 < freqPump3.AnaItemList.Count; index3++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index4 = 0; index4 < freqPump4.AnaItemList.Count; index4++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + var anaItem1 = freqPump1.AnaItemList[index1]; + var anaItem2 = freqPump2.AnaItemList[index2]; + var anaItem3 = freqPump3.AnaItemList[index3]; + var anaItem4 = freqPump4.AnaItemList[index4]; + + double wrkQ = anaItem1.WorkPointQ + anaItem2.WorkPointQ + anaItem3.WorkPointQ + anaItem4.WorkPointQ; + double freTotalP = anaItem1.WorkPointP + anaItem2.WorkPointP + anaItem3.WorkPointP + anaItem4.WorkPointP; + + var diffFlow = Math.Abs(fix_pump_total_flow + wrkQ - _targetQ); + if (diffFlow < minSpanQ) + { + freTotalQ = fix_pump_total_flow + wrkQ; + rowPrj.TotalWrkQ = freTotalQ; + minSpanQ = Math.Abs(freTotalQ - _targetQ); + curveData1 = anaItem1; + curveData2 = anaItem2; + curveData3 = anaItem3; + curveData4 = anaItem4; + totalPower = curveData1.WorkPointP + curveData2.WorkPointP + curveData3.WorkPointP + curveData4.WorkPointP; + } + + if (diffFlow < _targetQ * 0.01 && freTotalP < totalPower) + { + curveData1 = anaItem1; + curveData2 = anaItem2; + curveData3 = anaItem3; + curveData4 = anaItem4; + totalPower = curveData1.WorkPointP + curveData2.WorkPointP + curveData3.WorkPointP + curveData4.WorkPointP; + } + } + } + } + } + + // + if (freTotalQ < _targetQmax && freTotalQ > _targetQmin && curveData1 != null) + { + #region 鍔犲叆鍥洪娉靛紑鍚俊鎭� + if (fixPumpCalcList != null) + { + foreach (var fixPump in fixPumpCalcList) + { + if (fixPump.AnaItem50Hz.WorkPointQ < 1) + continue; + var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz); + rowPrj.Items.Add(itemRow); + } + } + #endregion + + + var itemRowF1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump1.MachineDetail, curveData1); + rowPrj.Items.Add(itemRowF1); + + var itemRowF2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump2.MachineDetail, curveData2); + rowPrj.Items.Add(itemRowF2); + + var itemRowF3 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump3.MachineDetail, curveData3); + rowPrj.Items.Add(itemRowF3); + + var itemRowF4 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump4.MachineDetail, curveData4); + rowPrj.Items.Add(itemRowF4); + + + AddScheme(rowPrj, true); + addPrjNum++; + } + } + + return addPrjNum; + } + #endregion + + + #region 娣诲姞椤圭洰 鍙湁5鍙板彉棰戞车:AddMultiFreqPumpPrj5 + private int AddMultiFreqPumpPrj5( + PumpCalcModel[] fixPumpCalcList, + PumpCalcModel[] allFreqPumpAnaList, + double fix_pump_total_flow) + { + int addPrjNum = 0; + int frePumpNum = 5; + if (allFreqPumpAnaList == null || allFreqPumpAnaList.Count() < frePumpNum) + return addPrjNum; + + //鍒ゆ柇鏈�澶у紑鏈烘暟 + if (_max_open_machine_number > 0) + { + int macine_number = 5; + if (fixPumpCalcList != null) + { + macine_number = macine_number + fixPumpCalcList.Count(); + } + if (macine_number > _max_open_machine_number) + return 0; + } + + List<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData[]> freqPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData>.GetCombination( + allFreqPumpAnaList, frePumpNum); + foreach (var freqPumpAnaCombine in freqPumpAnaCombineList) + { + var freqPump1 = freqPumpAnaCombine[0]; + var freqPump2 = freqPumpAnaCombine[1]; + var freqPump3 = freqPumpAnaCombine[2]; + var freqPump4 = freqPumpAnaCombine[3]; + var freqPump5 = freqPumpAnaCombine[4]; + + #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉� + List<long> machine_ids = new List<long>(); + machine_ids.Add(freqPump1.MachineDetail.MachineID); + machine_ids.Add(freqPump2.MachineDetail.MachineID); + machine_ids.Add(freqPump3.MachineDetail.MachineID); + machine_ids.Add(freqPump4.MachineDetail.MachineID); + machine_ids.Add(freqPump5.MachineDetail.MachineID); + if (fixPumpCalcList != null) + { + foreach (var item in fixPumpCalcList) + machine_ids.Add(item.MachineDetail.MachineID); + } + if (!IsAccordMachineRunFilter(machine_ids)) + { + continue; + } + #endregion + + double freTotalQ = fix_pump_total_flow; + double minSpanQ = _targetQmax; + double totalPower = + freqPump1.MachineDetail.RatedP + + freqPump2.MachineDetail.RatedP + + freqPump3.MachineDetail.RatedP + + freqPump4.MachineDetail.RatedP + + freqPump5.MachineDetail.RatedP; + + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData1 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData2 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData3 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData4 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData5 = null; + + var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme(); + rowPrj.TotalWrkQ = freTotalQ; + rowPrj.TotalWrkH = Math.Round(_targetH, 2); + rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>(); + + //double TotalWrkP = 0; + + + //鎵惧埌绂籣targetQ鏈�鎺ヨ繎鐨勯鐜囩偣 + for (int index1 = 0; index1 < freqPump1.AnaItemList.Count; index1++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index2 = 0; index2 < freqPump2.AnaItemList.Count; index2++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index3 = 0; index3 < freqPump3.AnaItemList.Count; index3++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index4 = 0; index4 < freqPump4.AnaItemList.Count; index4++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index5 = 0; index5 < freqPump5.AnaItemList.Count; index5++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + + var anaItem1 = freqPump1.AnaItemList[index1]; + var anaItem2 = freqPump2.AnaItemList[index2]; + var anaItem3 = freqPump3.AnaItemList[index3]; + var anaItem4 = freqPump4.AnaItemList[index4]; + var anaItem5 = freqPump5.AnaItemList[index5]; + + double wrkQ = + anaItem1.WorkPointQ + + anaItem2.WorkPointQ + + anaItem3.WorkPointQ + + anaItem4.WorkPointQ + + anaItem5.WorkPointQ; + + double freTotalP = + anaItem1.WorkPointP + + anaItem2.WorkPointP + + anaItem3.WorkPointP + + anaItem4.WorkPointP + + anaItem5.WorkPointP; + var diffFlow = Math.Abs(fix_pump_total_flow + wrkQ - _targetQ); + if (diffFlow < minSpanQ) + { + freTotalQ = fix_pump_total_flow + wrkQ; + rowPrj.TotalWrkQ = freTotalQ; + minSpanQ = Math.Abs(freTotalQ - _targetQ); + curveData1 = anaItem1; + curveData2 = anaItem2; + curveData3 = anaItem3; + curveData4 = anaItem4; + curveData5 = anaItem5; + totalPower = + curveData1.WorkPointP + + curveData2.WorkPointP + + curveData3.WorkPointP + + curveData4.WorkPointP + + curveData5.WorkPointP; + } + + if (diffFlow < _targetQ * 0.01 && freTotalP < totalPower) + { + curveData1 = anaItem1; + curveData2 = anaItem2; + curveData3 = anaItem3; + curveData4 = anaItem4; + curveData5 = anaItem5; + totalPower = + curveData1.WorkPointP + + curveData2.WorkPointP + + curveData3.WorkPointP + + curveData4.WorkPointP + + curveData5.WorkPointP; + } + } + } + } + } + } + + // + if (freTotalQ < _targetQmax && freTotalQ > _targetQmin && curveData1 != null) + { + #region 鍔犲叆鍥洪娉靛紑鍚俊鎭� + if (fixPumpCalcList != null) + { + foreach (var fixPump in fixPumpCalcList) + { + if (fixPump.AnaItem50Hz.WorkPointQ < 1) + continue; + var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz); + rowPrj.Items.Add(itemRow); + } + } + #endregion + + + var itemRowF1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump1.MachineDetail, curveData1); + rowPrj.Items.Add(itemRowF1); + + var itemRowF2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump2.MachineDetail, curveData2); + rowPrj.Items.Add(itemRowF2); + + var itemRowF3 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump3.MachineDetail, curveData3); + rowPrj.Items.Add(itemRowF3); + + var itemRowF4 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump4.MachineDetail, curveData4); + rowPrj.Items.Add(itemRowF4); + + var itemRowF5 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump5.MachineDetail, curveData5); + rowPrj.Items.Add(itemRowF5); + + + AddScheme(rowPrj, true); + addPrjNum++; + } + } + + return addPrjNum; + } + #endregion + + + #region 娣诲姞椤圭洰 鍙湁6鍙板彉棰戞车:AddMultiFreqPumpPrj6 + private int AddMultiFreqPumpPrj6( + PumpCalcModel[] fixPumpCalcList, + PumpCalcModel[] allFreqPumpAnaList, + double fix_pump_total_flow) + { + int addPrjNum = 0; + int frePumpNum = 6; + if (allFreqPumpAnaList == null || allFreqPumpAnaList.Count() < frePumpNum) + return addPrjNum; + + //鍒ゆ柇鏈�澶у紑鏈烘暟 + if (_max_open_machine_number > 0) + { + int macine_number = 6; + if (fixPumpCalcList != null) + { + macine_number = macine_number + fixPumpCalcList.Count(); + } + if (macine_number > _max_open_machine_number) + return 0; + } + + List<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData[]> freqPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData>.GetCombination( + allFreqPumpAnaList, frePumpNum); + foreach (var freqPumpAnaList in freqPumpAnaCombineList) + { + var freqPump1 = freqPumpAnaList[0]; + var freqPump2 = freqPumpAnaList[1]; + var freqPump3 = freqPumpAnaList[2]; + var freqPump4 = freqPumpAnaList[3]; + var freqPump5 = freqPumpAnaList[4]; + var freqPump6 = freqPumpAnaList[5]; + + #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉� + List<long> machine_ids = new List<long>(); + machine_ids.Add(freqPump1.MachineDetail.MachineID); + machine_ids.Add(freqPump2.MachineDetail.MachineID); + machine_ids.Add(freqPump3.MachineDetail.MachineID); + machine_ids.Add(freqPump4.MachineDetail.MachineID); + machine_ids.Add(freqPump5.MachineDetail.MachineID); + machine_ids.Add(freqPump6.MachineDetail.MachineID); + if (fixPumpCalcList != null) + { + foreach (var item in fixPumpCalcList) + machine_ids.Add(item.MachineDetail.MachineID); + } + if (!IsAccordMachineRunFilter(machine_ids)) + { + continue; + } + #endregion + + + double freTotalQ = fix_pump_total_flow; + double minSpanQ = _targetQmax; + + double totalPower = + freqPump1.MachineDetail.RatedP + + freqPump2.MachineDetail.RatedP + + freqPump3.MachineDetail.RatedP + + freqPump4.MachineDetail.RatedP + + freqPump5.MachineDetail.RatedP + + freqPump6.MachineDetail.RatedP; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData1 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData2 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData3 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData4 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData5 = null; + ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData6 = null; + + var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme(); + rowPrj.TotalWrkQ = freTotalQ; + rowPrj.TotalWrkH = Math.Round(this._targetH, 2); + rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>(); + + + //鎵惧埌绂籣targetQ鏈�鎺ヨ繎鐨勯鐜囩偣 + for (int index1 = 0; index1 < freqPump1.AnaItemList.Count; index1++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index2 = 0; index2 < freqPump2.AnaItemList.Count; index2++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index3 = 0; index3 < freqPump3.AnaItemList.Count; index3++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index4 = 0; index4 < freqPump4.AnaItemList.Count; index4++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index5 = 0; index5 < freqPump5.AnaItemList.Count; index5++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + for (int index6 = 0; index6 < freqPump6.AnaItemList.Count; index6++) + {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏� + + var anaItem1 = freqPump1.AnaItemList[index1]; + var anaItem2 = freqPump2.AnaItemList[index2]; + var anaItem3 = freqPump3.AnaItemList[index3]; + var anaItem4 = freqPump4.AnaItemList[index4]; + var anaItem5 = freqPump5.AnaItemList[index5]; + var anaItem6 = freqPump6.AnaItemList[index6]; + + double wrkQ = + anaItem1.WorkPointQ + + anaItem2.WorkPointQ + + anaItem3.WorkPointQ + + anaItem4.WorkPointQ + + anaItem5.WorkPointQ + + anaItem6.WorkPointQ; + double freTotalP = + anaItem1.WorkPointP + + anaItem2.WorkPointP + + anaItem3.WorkPointP + + anaItem4.WorkPointP + + anaItem5.WorkPointP + + anaItem6.WorkPointP; + + var diffFlow = Math.Abs(fix_pump_total_flow + wrkQ - _targetQ); + if (diffFlow < minSpanQ) + { + freTotalQ = fix_pump_total_flow + wrkQ; + rowPrj.TotalWrkQ = freTotalQ; + minSpanQ = Math.Abs(freTotalQ - _targetQ); + curveData1 = anaItem1; + curveData2 = anaItem2; + curveData3 = anaItem3; + curveData4 = anaItem4; + curveData5 = anaItem5; + curveData6 = anaItem6; + + totalPower = + curveData1.WorkPointP + + curveData2.WorkPointP + + curveData3.WorkPointP + + curveData4.WorkPointP + + curveData5.WorkPointP + + curveData6.WorkPointP; + } + + + if (diffFlow < _targetQ * 0.01 && freTotalP < totalPower) + { + curveData1 = anaItem1; + curveData2 = anaItem2; + curveData3 = anaItem3; + curveData4 = anaItem4; + curveData5 = anaItem5; + curveData6 = anaItem6; + + totalPower = + curveData1.WorkPointP + + curveData2.WorkPointP + + curveData3.WorkPointP + + curveData4.WorkPointP + + curveData5.WorkPointP + + curveData6.WorkPointP; + } + } + } + } + } + } + } + + // + if (freTotalQ < _targetQmax && freTotalQ > _targetQmin && curveData1 != null) + { + #region 鍔犲叆鍥洪娉靛紑鍚俊鎭� + if (fixPumpCalcList != null) + { + foreach (var fixPump in fixPumpCalcList) + { + if (fixPump.AnaItem50Hz.WorkPointQ < 1) + continue; + var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz); + + rowPrj.Items.Add(itemRow); + } + } + #endregion + + + var itemRowF1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump1.MachineDetail, curveData1); + rowPrj.Items.Add(itemRowF1); + + var itemRowF2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump2.MachineDetail, curveData2); + rowPrj.Items.Add(itemRowF2); + + var itemRowF3 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump3.MachineDetail, curveData3); + rowPrj.Items.Add(itemRowF3); + + var itemRowF4 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump4.MachineDetail, curveData4); + rowPrj.Items.Add(itemRowF4); + + var itemRowF5 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump5.MachineDetail, curveData5); + rowPrj.Items.Add(itemRowF5); + + var itemRowF6 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump6.MachineDetail, curveData6); + rowPrj.Items.Add(itemRowF6); + + AddScheme(rowPrj, true); + addPrjNum++; + } + } + + return addPrjNum; + } + #endregion + + + + private int _schemeID = 1; + private bool AddScheme(ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme project, bool IsAccurateCalc) + { + + try + { + + project.TotalWrkQ = (from x in project.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum(); + project.TotalWrkH = Math.Round((from x in project.Items where x.WorkPointH > 0 select x.WorkPointH).Average(), 2); + + project.TotalWrkP = Math.Round((from x in project.Items where x.WorkPointP > 0 select x.WorkPointP).Sum(), 2); + project.TotalWrkE = ISupply.Common.PumpParaHelper.CalculateE(project.TotalWrkQ, project.TotalWrkH, project.TotalWrkP); + project.UWP = Calcu_UWP(project.TotalWrkP, project.TotalWrkQ, this._targetH); + project.WP = Calcu_WP(project.TotalWrkP, project.TotalWrkQ); + + if (project.TotalWrkQ > _targetQmax || project.TotalWrkQ < _targetQmin) + { + return false; + } + + } + catch (Exception ex) + { + + throw; + } + //璁$畻娴侀噺 + //rowPrj.TotalWrkQ = (from x in rowPrj.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum(); + //if (rowPrj.TotalWrkQ <= _targetQmax && rowPrj.TotalWrkQ >= this._targetQmin) + // ds_disp_project_list.Add(project); + + if (_machine_flow_limit_max_dict != null) + { + foreach (var item in project.Items) + { + if (_machine_flow_limit_max_dict.ContainsKey(item.MachineID)) + {//鎿嶄綔寮�鏈洪檺鍒� + if (item.WorkPointQ > _machine_flow_limit_max_dict[item.MachineID]) + return false; + } + } + } + + if (_machine_flow_limit_min_dict != null) + { + foreach (var item in project.Items) + { + if (_machine_flow_limit_min_dict.ContainsKey(item.MachineID)) + {//鎿嶄綔寮�鏈洪檺鍒� + if (item.WorkPointQ < _machine_flow_limit_min_dict[item.MachineID]) + return false; + } + } + } + + + + + if (_anaSchemeList == null) + _anaSchemeList = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme>(); + + + + //鍐嶇簿绠椾竴涓� + if (IsAccurateCalc) + CalcDetailAccurate(ref project); + + + project.ID = _schemeID; + _anaSchemeList.Add(project); + _schemeID++; + + return true; + } + /// <summary> + /// 鍗曚綅姘磋�� 鍗冨惃姘� + /// </summary> + public static double Calcu_UWP(double P, double Q, double H) + { + if (Q <= 0.001) + return 0; + if (H <= 0.00001) + return 0; + if (P <= 0.001) + return 0; + return P * 1000f / Q / H; + } + /// <summary> + /// 鍗曚綅姘磋�� 鍗冨惃姘� + /// </summary> + public static double Calcu_UWP(double P, double Q, double inletPress, double outletPress) + { + double H = (outletPress - inletPress) * 102; + if (Q <= 0.001) + return 0; + if (H <= 0.00001) + return 0; + if (P <= 0.001) + return 0; + return P * 1000f / Q / H; + } + /// <summary> + /// 鍗曚綅姘磋�� + /// </summary> + public static double Calcu_WP(double P, double Q) + { + if (Q <= 0.001) + return 0; + + if (P <= 0.001) + return 0; + return P * 1000f / Q; + } + } + + + public class PumpCalcModel + { + public PumpCalcModel() { } + public PumpCalcModel(Model.Pump rhs) + { + this.Qr = rhs.Qr; + this.Hr = rhs.Hr; + this.Nr = rhs.Nr; + this.Pr = rhs.Pr; + this.Er = rhs.Er; + if (rhs.CurveQH != null && rhs.CurveQP != null) + { + this.CurveQH = rhs.CurveQH.Clone(); + this.CurveQP = rhs.CurveQP.Clone(); + this.AllowCalc = true; + } + } + + public PumpCalcModel(Model.Pump rhs, double freMin, double freMax, double freSpace) : this(rhs) + { + this.CalcFrequencyItems(freMin, freMax, freSpace); + } + + public int ID { get; set; } + public string Code { get; set; } + public string Name { get; set; } + public double Qr { get; set; } + public double Hr { get; set; } + public double Nr { get; set; } + public double Pr { get; set; } + public double Er { get; set; } + public bool IsBp { get; set; } + public CurveExpress CurveQH { get; set; } + public CurveExpress CurveQP { get; set; } + public List<PumpFrequencyItem> PumpFrequencyItems { get; set; } + public bool AllowCalc { get; set; } + + void CalcFrequencyItems(double freMin, double freMax, double freSpace) + { + if (!this.AllowCalc) + return; + + this.PumpFrequencyItems = new List<PumpFrequencyItem>(); + for (double fre = freMax; fre >= freMin; fre -= freSpace) + { + var fre_def = 50; + var freItem = new PumpFrequencyItem(); + freItem.Frequency = fre; + freItem.CurveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(this.CurveQH, fre_def, fre); + freItem.CurveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(this.CurveQP, fre_def, fre); + this.PumpFrequencyItems.Add(freItem); + } + } + } + + public class PumpFrequencyItem + { + public double Frequency { get; set; } + public Curve.CurveExpress CurveQH { get; set; } + public Curve.CurveExpress CurveQP { get; set; } + } + +} + + + diff --git a/Schedule/IStation.Algorithm/Schedule/ScheduleCalc1.cs b/Schedule/IStation.Algorithm/Schedule/ScheduleCalc1.cs new file mode 100644 index 0000000..30d9c0d --- /dev/null +++ b/Schedule/IStation.Algorithm/Schedule/ScheduleCalc1.cs @@ -0,0 +1,57 @@ +锘縩amespace IStation.Algorithm +{ + public class ScheduleCalc1 + { + private int _belong = 0; + private int[] _run_flags = null; + private List<Model.Pump> _pumps = null; + + /// <summary> + /// 鍒濆鍖栬绠楀弬鏁� + /// </summary> + /// <param name="belong">鎵�灞炲璞�</param> + /// <param name="pumps">娉靛垪琛�</param> + /// <returns></returns> + private bool InitCalcParas(int belong, List<Model.Pump> pumps) + { + _belong = 0; + _pumps = null; + _run_flags = null; + _combine = null; + if (pumps == null || pumps.Count < 1) + return false; + _belong = belong; + _pumps = pumps; + _run_flags = pumps.Select(x => x.ID).OrderBy(x => x).ToArray(); + _combine = new List<int>(); + return true; + } + + + private List<int> _combine = null; + private bool CW(int belong, List<Model.Pump> pumps) + { + var bol = InitCalcParas(belong, pumps); + if (!bol) return false; + + + + return true; + } + + + + private void DoWork(int r, int i, int t) + { + if (r.Length / 2 >= t) + { + _combine.Add(r); + return; + } + for (; i < _run_flags.Length;) + { + DoWork(r + _run_flags[i], ++i, t); + } + } + } +} diff --git a/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper.cs b/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper.cs new file mode 100644 index 0000000..245499e --- /dev/null +++ b/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper.cs @@ -0,0 +1,602 @@ +锘縰sing IStation.DAL; +using System.Reflection; + +namespace IStation.Algorithm +{ + /// <summary> + /// 鍒嗘瀽娉甸」 + /// </summary> + public class AnaPumpItem + { + public AnaPumpItem() { } + public AnaPumpItem(Pump rhs) + { + this.ID = rhs.ID; + this.Name = rhs.Name; + this.Code = rhs.Code; + this.IsBp = rhs.IsBp; + this.Qr = rhs.Qr; + this.Hr = rhs.Hr; + this.Nr = rhs.Nr; + this.Pr = rhs.Pr; + this.Er = rhs.Er; + if (rhs.CurveQH != null && rhs.CurveQP != null) + { + this.CurveQH = rhs.CurveQH.Clone(); + this.CurveQP = rhs.CurveQP.Clone(); + this.AllowCalc = true; + } + } + + public AnaPumpItem(Pump rhs, double freDef, double freMin, double freMax, double freSpace) : this(rhs) + { + this.CalcFrequencyItems(freDef, freMin, freMax, freSpace); + } + + public int ID { get; set; } + public string Code { get; set; } + public string Name { get; set; } + public double Qr { get; set; } + public double Hr { get; set; } + public double Nr { get; set; } + public double Pr { get; set; } + public double Er { get; set; } + public bool IsBp { get; set; } + public Curve.CurveExpress CurveQH { get; set; } + public Curve.CurveExpress CurveQP { get; set; } + public List<AnaPumpFreItem> AnaFrequencyItems { get; set; } + public bool AllowCalc { get; set; } + + void CalcFrequencyItems(double freDef, double freMin, double freMax, double freSpace) + { + if (!this.AllowCalc) + return; + + this.AnaFrequencyItems = new List<AnaPumpFreItem>(); + //var freItemDef = new AnaFrequencyItem(); + //freItemDef.Frequency = freMax; + //freItemDef.CurveQH = this.CurveQH.Clone(); + //freItemDef.CurveQP = this.CurveQP.Clone(); + //this.AnaFrequencyItems.Add(freItemDef); + for (double fre = freMax; fre >= freMin; fre -= freSpace) + { + var freItem = new AnaPumpFreItem(); + freItem.Frequency = fre; + freItem.CurveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(this.CurveQH, freDef, fre); + freItem.CurveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(this.CurveQP, freDef, fre); + this.AnaFrequencyItems.Add(freItem); + } + } + } + + /// <summary> + /// 鍒嗘瀽娉靛彉棰戦」 + /// </summary> + public class AnaPumpFreItem + { + public double Frequency { get; set; } + public Curve.CurveExpress CurveQH { get; set; } + public Curve.CurveExpress CurveQP { get; set; } + } + + /// <summary> + /// 璋冨害鍒嗘瀽杈呭姪绫� + /// </summary> + public class SchedulingAnaHelper + { + double _frequency_def = 50; + double _frequency_min = 25; + double _frequency_max = 50; + double _frequency_space = 0.1;//棰戠巼闂撮殧 + double _head_space = 0.1; + + ParallelConnectionHelper _parallelConnectionHelper = new ParallelConnectionHelper(); + + #region TableName + string _tableFrePumpTag = "B"; + string _tableFixPumpTag = "G"; + string _tableSpaceMark = "_"; + + string GetTableName(List<AnaPumpItem> pumpItems) + { + var tableName = string.Empty; + var count = pumpItems.Count; + pumpItems = pumpItems.OrderBy(p => p.ID).ToList(); + for (int i = 0; i < count; i++) + { + var pumpItem = pumpItems[i]; + tableName += GetTableName(pumpItem); + if ((i + 1) != count) + { + tableName += _tableSpaceMark; + } + } + return tableName; + } + + string GetTableName(AnaPumpItem pumpItem) + { + return (pumpItem.IsBp ? _tableFrePumpTag : _tableFixPumpTag) + pumpItem.ID; + } + + #endregion + + public bool AnaOptList(List<Pump> pumps) + { + if (pumps == null || pumps.Count < 1) + return false; + var fre_def = _frequency_def; + var anaPumpItems = new List<AnaPumpItem>(); + foreach (var pump in pumps) + { + if (pump.IsBp) + { + //鍙橀娉� + var anaPump = new AnaPumpItem(pump, fre_def, _frequency_min, _frequency_max, _frequency_space); + if (anaPump.AllowCalc) + anaPumpItems.Add(anaPump); + } + else + { + //鍥洪娉� + var anaPump = new AnaPumpItem(pump); + if (anaPump.AllowCalc) + anaPumpItems.Add(anaPump); + } + } + + if (anaPumpItems.Count < 1) + return false; + + var maxRunCount = 3; + var anaPumpItemsArray = anaPumpItems.ToArray(); + for (int runCount = 1; runCount <= maxRunCount; runCount++) + { + var pumpCombineList = PermutationAndCombination<AnaPumpItem>.GetCombination(anaPumpItemsArray, runCount); + //if (runCount == 1) + //{ + // foreach (var pumpCombine in pumpCombineList) + // { + // var start = DateTime.Now; + // AnaSinglePump(pumpCombine[0], _head_space); + // var end = DateTime.Now; + // var tabName = GetTableName(pumpCombine[0]); + // Db.Insert(tabName, 1, start, end); + // } + //} + //else + if (runCount == 2) + { + foreach (var pumpCombine in pumpCombineList) + { + var start = DateTime.Now; + var list = pumpCombine.ToList(); + AnaTwoPumps(list, _head_space); + var end = DateTime.Now; + var tabName = GetTableName(list); + Db.Insert(tabName, 1, start, end); + } + } + //else if (runCount == 3) + //{ + // foreach (var pumpCombine in pumpCombineList) + // { + // var start = DateTime.Now; + // var list = pumpCombine.ToList(); + // AnaThreePumps(list, _head_space); + // var end = DateTime.Now; + // var tabName = GetTableName(list); + // Db.Insert(tabName, 1, start, end); + // } + //} + } + + return true; + } + + private void AnaSinglePump(AnaPumpItem anaPump, double headSpace) + { + if (anaPump == null) + return; + if (!anaPump.AllowCalc) + return; + //var runFlag = (int)Math.Pow(2, anaPump.ID);//杩愯鏍囧織 + var runFlag = GetTableName(anaPump);//杩愯鏍囧織 + var scheduleCombineList = new List<ScheduleCombine>(); + var anaFreItems = anaPump.AnaFrequencyItems; + foreach (var anaFreItem in anaFreItems) + { + var curveQH = anaFreItem.CurveQH; + var curveQP = anaFreItem.CurveQP; + var bol = curveQH.GetMinMaxPointY(out double maxY, out double minY); + if (!bol) + continue; + var maxHead = Math.Ceiling(maxY); + var minHead = Math.Floor(minY); + + for (double head = minHead; head <= maxHead; head += headSpace) + { + var flow = curveQH.GetInterPointLastX(head); + if (!flow.HasValue) + continue; + + var scheduleCombine = new ScheduleCombine(); + scheduleCombine.RunFlag = runFlag; + scheduleCombine.Pump1 = anaFreItem.Frequency; + scheduleCombine.Head = head; + scheduleCombine.Flow = flow.Value; + scheduleCombine.Power = curveQP.GetFitPointY(flow.Value); + scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head); + scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow); + scheduleCombine.Round(); + scheduleCombineList.Add(scheduleCombine); + } + } + + var success = Db.BulkInserts(scheduleCombineList); + if (!success) + { + + } + } + + + private void AnaTwoPumps(List<AnaPumpItem> anaPumps, double headSpace) + { + if (anaPumps == null || anaPumps.Count != 2) + return; + if (anaPumps.Exists(x => !x.AllowCalc)) + return; + string runFlag = GetTableName(anaPumps); //杩愯鏍囧織 + //foreach (var anaPump in anaPumps) + //{ + // runFlag = runFlag | (int)Math.Pow(2, anaPump.ID); + //} + var scheduleCombineList = new List<ScheduleCombine>(); + var anaFreItems1 = anaPumps[0].AnaFrequencyItems; + var anaFreItems2 = anaPumps[1].AnaFrequencyItems; + for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++) + { + for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++) + { + var anaFreItem1 = anaFreItems1[anaIndex1]; + var anaFreItem2 = anaFreItems2[anaIndex2]; + + _parallelConnectionHelper.ClearCurve(); + _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP); + _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP); + var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP); + if (!allowParallel) + continue; + var bol = pointQH.GetMinMaxPointY(out double maxY, out double minY); + if (!bol) + continue; + var maxHead = Math.Ceiling(maxY); + var minHead = Math.Floor(minY); + + for (double head = minHead; head <= maxHead; head += headSpace) + { + var flow = pointQH.GetInterPointX(head)?.LastOrDefault(); + if (!flow.HasValue) + continue; + var scheduleCombine = new ScheduleCombine(); + scheduleCombine.RunFlag = runFlag; + scheduleCombine.Pump1 = anaFreItem1.Frequency; + scheduleCombine.Pump2 = anaFreItem2.Frequency; + scheduleCombine.Head = head; + scheduleCombine.Flow = flow.Value; + scheduleCombine.Power = pointQP.GetFitPointY(flow.Value); + scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head); + scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow); + scheduleCombine.Round(); + scheduleCombineList.Add(scheduleCombine); + } + } + } + var success = Db.BulkInserts(scheduleCombineList); + if (!success) + { + + } + } + + private void AnaThreePumps(List<AnaPumpItem> anaPumps, double headSpace) + { + if (anaPumps == null || anaPumps.Count != 3) + return; + if (anaPumps.Exists(x => !x.AllowCalc)) + return; + string runFlag = GetTableName(anaPumps);//杩愯鏍囧織 + //foreach (var anaPump in anaPumps) + //{ + // runFlag = runFlag | (int)Math.Pow(2, anaPump.ID); + //} + var scheduleCombineList = new List<ScheduleCombine>(); + var anaFreItems1 = anaPumps[0].AnaFrequencyItems; + var anaFreItems2 = anaPumps[1].AnaFrequencyItems; + var anaFreItems3 = anaPumps[2].AnaFrequencyItems; + for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++) + { + for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++) + { + for (int anaIndex3 = 0; anaIndex3 < anaFreItems3.Count; anaIndex3++) + { + var anaFreItem1 = anaFreItems1[anaIndex1]; + var anaFreItem2 = anaFreItems2[anaIndex2]; + var anaFreItem3 = anaFreItems3[anaIndex3]; + + _parallelConnectionHelper.ClearCurve(); + _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP); + _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP); + var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP); + if (!allowParallel) + continue; + var bol = pointQH.GetMinMaxPointY(out double maxY, out double minY); + if (!bol) + continue; + var maxHead = Math.Ceiling(maxY); + var minHead = Math.Floor(minY); + + for (double head = minHead; head <= maxHead; head += headSpace) + { + var flow = pointQH.GetInterPointX(head)?.LastOrDefault(); + if (!flow.HasValue) + continue; + var scheduleCombine = new ScheduleCombine(); + scheduleCombine.RunFlag = runFlag; + scheduleCombine.Pump1 = anaFreItem1.Frequency; + scheduleCombine.Pump2 = anaFreItem2.Frequency; + scheduleCombine.Pump3 = anaFreItem3.Frequency; + scheduleCombine.Head = head; + scheduleCombine.Flow = flow.Value; + scheduleCombine.Power = pointQP.GetFitPointY(flow.Value); + scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head); + scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow); + scheduleCombine.Round(); + scheduleCombineList.Add(scheduleCombine); + } + } + } + } + var success = Db.BulkInserts(scheduleCombineList); + if (!success) + { + + } + + } + + } + + /// <summary> + /// 鏁版嵁搴� + /// </summary> + public class Db + { + /// <summary> + /// 杩炴帴閰嶇疆 + /// </summary> + public static ConnectionConfig ConnectionConfig + { + get + { + + var filePath = DbInitial.DbFilePath; + if (!System.IO.File.Exists(filePath)) + { + DAL.DbInitial.InitTables(); + } + + var config = new ConnectionConfig() + { + ConnectionString = $"DataSource={filePath}", + IsAutoCloseConnection = true, + DbType = SqlSugar.DbType.Sqlite + }; + return config; + } + } + + + + /// <summary> + /// 澶ф壒閲忔彃鍏� + /// </summary> + public static bool BulkInserts(List<ScheduleCombine> list) + { + if (list == null || list.Count < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + ///鑷繁鏉ュ埗瀹氬畾涔夌殑瑙勫垯 + db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new RunFlagSubTableService(); + db.CodeFirst + .SplitTables()//鏍囪瘑鍒嗚〃 + .InitTables<ScheduleCombine>(); //绋嬪簭鍚姩鏃跺姞杩欎竴琛�,濡傛灉涓�寮犺〃娌℃湁浼氬垵濮嬪寲涓�寮� + + //澶ф暟鎹啓鍏�+琛ㄤ笉瀛樺湪浼氬缓琛� + //鑷姩鎵捐〃澶ф暟鎹啓鍏� + return db.Fastest<ScheduleCombine>().SplitTable().BulkCopy(list) > 0; + } + } + + /// <summary> + /// 鎻掑叆 + /// </summary> + public static bool Insert(string flag, int count, DateTime start, DateTime end) + { + var log = new ScheduleAnaLog(flag, count, start, end); + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Insertable(log).ExecuteCommand() > 0; + } + } + + internal static object SplitHelper<T>() + { + throw new NotImplementedException(); + } + } + + /// <summary> + /// 鍒嗚〃瑙勫垯 + /// </summary> + public class RunFlagSubTableService : ISplitTableService + { + /// <summary> + /// 鑾峰彇鎵�鏈夌殑鏁版嵁搴撲腑鐨勮〃 + /// </summary> + /// <param name="db"></param> + /// <param name="EntityInfo"></param> + /// <param name="tableInfos"></param> + /// <returns></returns> + /// <exception cref="NotImplementedException"></exception> + public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos) + { + List<SplitTableInfo> result = new List<SplitTableInfo>(); + foreach (var item in tableInfos) + { + if (item.Name.Contains("_Run_")) //鍖哄垎鏍囪瘑濡傛灉涓嶇敤姝e垯绗﹀鏉備竴浜涳紝闃叉鎵鹃敊琛� + { + SplitTableInfo data = new SplitTableInfo() + { + TableName = item.Name //瑕佺敤item.name涓嶈鍐欓敊浜� + }; + result.Add(data); + } + } + return result.OrderBy(it => it.TableName).ToList();//鎵撴柇鐐圭湅涓�涓嬫湁娌℃湁鏌ュ嚭鎵�鏈夊垎琛� + } + + /// <summary> + /// + /// </summary> + /// <param name="db"></param> + /// <param name="entityInfo"></param> + /// <param name="splitType"></param> + /// <param name="entityValue"></param> + /// <returns></returns> + public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue) + { + var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null); + + return splitColumn.PropertyInfo.GetValue(entityValue, null); + } + + /// <summary> + /// + /// </summary> + /// <param name="db"></param> + /// <param name="EntityInfo"></param> + /// <returns></returns> + public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo) + { + return EntityInfo.DbTableName + "_Run"; + } + + public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType type) + { + return EntityInfo.DbTableName + "_Run"; + } + + /// <summary> + /// 纭畾鐢熸垚鏁版嵁搴撹〃鐨勬椂鍊欙紝琛ㄧ殑鍚嶇О + /// </summary> + /// <param name="db"></param> + /// <param name="entityInfo"></param> + /// <param name="splitType"></param> + /// <param name="fieldValue"></param> + /// <returns></returns> + public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue) + { + return entityInfo.DbTableName + "_Run_" + fieldValue.ToString(); + } + } + + /// <summary> + /// 璋冨害缁勫悎 + /// </summary> + [SplitTable(SplitType._Custom01)] + public class ScheduleCombine + { + public ScheduleCombine() { } + public ScheduleCombine(ScheduleCombine rhs) + { + this.Pump1 = rhs.Pump1; + this.Pump2 = rhs.Pump2; + this.Pump3 = rhs.Pump3; + this.Head = rhs.Head; + this.Flow = rhs.Flow; + this.Power = rhs.Power; + this.WP = rhs.WP; + this.UWP = rhs.UWP; + } + + public void Round() + { + this.Pump1 = Math.Round(this.Pump1, 1); + this.Pump2 = Math.Round(this.Pump2, 1); + this.Pump3 = Math.Round(this.Pump3, 1); + this.Head = Math.Round(this.Head, 1); + this.Flow = Math.Round(this.Flow, 1); + this.Power = Math.Round(this.Power, 1); + this.WP = Math.Round(this.WP, 1); + this.UWP = Math.Round(this.UWP, 1); + + } + + /// <summary> + /// 杩愯鏍囧織 (鏍囧織鏋氫妇) + /// </summary> + [SplitField] + public string RunFlag { get; set; } + + /// <summary> + /// 娉�1 + /// </summary> + public double Pump1 { get; set; } + + /// <summary> + /// 娉�2 + /// </summary> + public double Pump2 { get; set; } + + /// <summary> + /// 娉�3 + /// </summary> + public double Pump3 { get; set; } + + /// <summary> + /// 鎵▼ + /// </summary> + public double Head { get; set; } + + /// <summary> + /// 鎬绘祦閲� + /// </summary> + public double Flow { get; set; } + + /// <summary> + /// 鎬诲姛鐜� + /// </summary> + public double Power { get; set; } + + /// <summary> + /// 鍗冨惃姘磋兘鑰� + /// </summary> + public double WP { get; set; } + + /// <summary> + /// 鍗曚綅鑳借�� + /// </summary> + public double UWP { get; set; } + + /// <summary> + /// 鍒涘缓鏃堕棿 + /// </summary> + public DateTime CreateTime { get; set; } = DateTime.Now; + + + } +} + diff --git a/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper_v1.cs b/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper_v1.cs new file mode 100644 index 0000000..446ddca --- /dev/null +++ b/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper_v1.cs @@ -0,0 +1,602 @@ +锘縰sing IStation.DAL; +using System.Reflection; + +namespace IStation.Algorithm +{ + /// <summary> + /// 鍒嗘瀽娉甸」 + /// </summary> + public class AnaPumpItem + { + public AnaPumpItem() { } + public AnaPumpItem(Pump rhs) + { + this.ID = rhs.ID; + this.Name = rhs.Name; + this.Code = rhs.Code; + this.IsBp = rhs.IsBp; + this.Qr = rhs.Qr; + this.Hr = rhs.Hr; + this.Nr = rhs.Nr; + this.Pr = rhs.Pr; + this.Er = rhs.Er; + if (rhs.CurveQH != null && rhs.CurveQP != null) + { + this.CurveQH = rhs.CurveQH.Clone(); + this.CurveQP = rhs.CurveQP.Clone(); + this.AllowCalc = true; + } + } + + public AnaPumpItem(Pump rhs, double freDef, double freMin, double freMax, double freSpace) : this(rhs) + { + this.CalcFrequencyItems(freDef, freMin, freMax, freSpace); + } + + public int ID { get; set; } + public string Code { get; set; } + public string Name { get; set; } + public double Qr { get; set; } + public double Hr { get; set; } + public double Nr { get; set; } + public double Pr { get; set; } + public double Er { get; set; } + public bool IsBp { get; set; } + public Curve.CurveExpress CurveQH { get; set; } + public Curve.CurveExpress CurveQP { get; set; } + public List<AnaPumpFreItem> AnaFrequencyItems { get; set; } + public bool AllowCalc { get; set; } + + void CalcFrequencyItems(double freDef, double freMin, double freMax, double freSpace) + { + if (!this.AllowCalc) + return; + + this.AnaFrequencyItems = new List<AnaPumpFreItem>(); + //var freItemDef = new AnaFrequencyItem(); + //freItemDef.Frequency = freMax; + //freItemDef.CurveQH = this.CurveQH.Clone(); + //freItemDef.CurveQP = this.CurveQP.Clone(); + //this.AnaFrequencyItems.Add(freItemDef); + for (double fre = freMax; fre >= freMin; fre -= freSpace) + { + var freItem = new AnaPumpFreItem(); + freItem.Frequency = fre; + freItem.CurveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(this.CurveQH, freDef, fre); + freItem.CurveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(this.CurveQP, freDef, fre); + this.AnaFrequencyItems.Add(freItem); + } + } + } + + /// <summary> + /// 鍒嗘瀽娉靛彉棰戦」 + /// </summary> + public class AnaPumpFreItem + { + public double Frequency { get; set; } + public Curve.CurveExpress CurveQH { get; set; } + public Curve.CurveExpress CurveQP { get; set; } + } + + /// <summary> + /// 璋冨害鍒嗘瀽杈呭姪绫� + /// </summary> + public class SchedulingAnaHelper + { + double _frequency_def = 50; + double _frequency_min = 25; + double _frequency_max = 50; + double _frequency_space = 0.1;//棰戠巼闂撮殧 + double _head_space = 0.1; + + ParallelConnectionHelper _parallelConnectionHelper = new ParallelConnectionHelper(); + + #region TableName + string _tableFrePumpTag = "B"; + string _tableFixPumpTag = "G"; + string _tableSpaceMark = "_"; + + string GetTableName(List<AnaPumpItem> pumpItems) + { + var tableName = string.Empty; + var count = pumpItems.Count; + pumpItems = pumpItems.OrderBy(p => p.ID).ToList(); + for (int i = 0; i < count; i++) + { + var pumpItem = pumpItems[i]; + tableName += GetTableName(pumpItem); + if ((i + 1) != count) + { + tableName += _tableSpaceMark; + } + } + return tableName; + } + + string GetTableName(AnaPumpItem pumpItem) + { + return (pumpItem.IsBp ? _tableFrePumpTag : _tableFixPumpTag) + pumpItem.ID; + } + + #endregion + + public bool AnaOptList(List<Pump> pumps) + { + if (pumps == null || pumps.Count < 1) + return false; + var fre_def = _frequency_def; + var anaPumpItems = new List<AnaPumpItem>(); + foreach (var pump in pumps) + { + if (pump.IsBp) + { + //鍙橀娉� + var anaPump = new AnaPumpItem(pump, fre_def, _frequency_min, _frequency_max, _frequency_space); + if (anaPump.AllowCalc) + anaPumpItems.Add(anaPump); + } + else + { + //鍥洪娉� + var anaPump = new AnaPumpItem(pump); + if (anaPump.AllowCalc) + anaPumpItems.Add(anaPump); + } + } + + if (anaPumpItems.Count < 1) + return false; + + var maxRunCount = 3; + var anaPumpItemsArray = anaPumpItems.ToArray(); + for (int runCount = 1; runCount <= maxRunCount; runCount++) + { + var pumpCombineList = PermutationAndCombination<AnaPumpItem>.GetCombination(anaPumpItemsArray, runCount); + //if (runCount == 1) + //{ + // foreach (var pumpCombine in pumpCombineList) + // { + // var start = DateTime.Now; + // AnaSinglePump(pumpCombine[0], _head_space); + // var end = DateTime.Now; + // var tabName = GetTableName(pumpCombine[0]); + // Db.Insert(tabName, 1, start, end); + // } + //} + //else + if (runCount == 2) + { + foreach (var pumpCombine in pumpCombineList) + { + var start = DateTime.Now; + var list = pumpCombine.ToList(); + AnaTwoPumps(list, _head_space); + var end = DateTime.Now; + var tabName = GetTableName(list); + Db.Insert(tabName, 1, start, end); + } + } + //else if (runCount == 3) + //{ + // foreach (var pumpCombine in pumpCombineList) + // { + // var start = DateTime.Now; + // var list = pumpCombine.ToList(); + // AnaThreePumps(list, _head_space); + // var end = DateTime.Now; + // var tabName = GetTableName(list); + // Db.Insert(tabName, 1, start, end); + // } + //} + } + + return true; + } + + private void AnaSinglePump(AnaPumpItem anaPump, double headSpace) + { + if (anaPump == null) + return; + if (!anaPump.AllowCalc) + return; + //var runFlag = (int)Math.Pow(2, anaPump.ID);//杩愯鏍囧織 + var runFlag = GetTableName(anaPump);//杩愯鏍囧織 + var scheduleCombineList = new List<ScheduleCombine>(); + var anaFreItems = anaPump.AnaFrequencyItems; + foreach (var anaFreItem in anaFreItems) + { + var curveQH = anaFreItem.CurveQH; + var curveQP = anaFreItem.CurveQP; + var bol = curveQH.GetMinMaxPointY(out double maxY, out double minY); + if (!bol) + continue; + var maxHead = Math.Ceiling(maxY); + var minHead = Math.Floor(minY); + + for (double head = minHead; head <= maxHead; head += headSpace) + { + var flow = curveQH.GetInterPointLastX(head); + if (!flow.HasValue) + continue; + + var scheduleCombine = new ScheduleCombine(); + scheduleCombine.RunFlag = runFlag; + scheduleCombine.Pump1 = anaFreItem.Frequency; + scheduleCombine.Head = head; + scheduleCombine.Flow = flow.Value; + scheduleCombine.Power = curveQP.GetFitPointY(flow.Value); + scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head); + scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow); + scheduleCombine.Round(); + scheduleCombineList.Add(scheduleCombine); + } + } + + var success = Db.BulkInserts(scheduleCombineList); + if (!success) + { + + } + } + + + private void AnaTwoPumps(List<AnaPumpItem> anaPumps, double headSpace) + { + if (anaPumps == null || anaPumps.Count != 2) + return; + if (anaPumps.Exists(x => !x.AllowCalc)) + return; + string runFlag = GetTableName(anaPumps); //杩愯鏍囧織 + //foreach (var anaPump in anaPumps) + //{ + // runFlag = runFlag | (int)Math.Pow(2, anaPump.ID); + //} + var scheduleCombineList = new List<ScheduleCombine>(); + var anaFreItems1 = anaPumps[0].AnaFrequencyItems; + var anaFreItems2 = anaPumps[1].AnaFrequencyItems; + for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++) + { + for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++) + { + var anaFreItem1 = anaFreItems1[anaIndex1]; + var anaFreItem2 = anaFreItems2[anaIndex2]; + + _parallelConnectionHelper.ClearCurve(); + _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP); + _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP); + var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP); + if (!allowParallel) + continue; + var bol = pointQH.GetMinMaxPointY(out double maxY, out double minY); + if (!bol) + continue; + var maxHead = Math.Ceiling(maxY); + var minHead = Math.Floor(minY); + + for (double head = minHead; head <= maxHead; head += headSpace) + { + var flow = pointQH.GetInterPointX(head)?.LastOrDefault(); + if (!flow.HasValue) + continue; + var scheduleCombine = new ScheduleCombine(); + scheduleCombine.RunFlag = runFlag; + scheduleCombine.Pump1 = anaFreItem1.Frequency; + scheduleCombine.Pump2 = anaFreItem2.Frequency; + scheduleCombine.Head = head; + scheduleCombine.Flow = flow.Value; + scheduleCombine.Power = pointQP.GetFitPointY(flow.Value); + scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head); + scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow); + scheduleCombine.Round(); + scheduleCombineList.Add(scheduleCombine); + } + } + } + var success = Db.BulkInserts(scheduleCombineList); + if (!success) + { + + } + } + + private void AnaThreePumps(List<AnaPumpItem> anaPumps, double headSpace) + { + if (anaPumps == null || anaPumps.Count != 3) + return; + if (anaPumps.Exists(x => !x.AllowCalc)) + return; + string runFlag = GetTableName(anaPumps);//杩愯鏍囧織 + //foreach (var anaPump in anaPumps) + //{ + // runFlag = runFlag | (int)Math.Pow(2, anaPump.ID); + //} + var scheduleCombineList = new List<ScheduleCombine>(); + var anaFreItems1 = anaPumps[0].AnaFrequencyItems; + var anaFreItems2 = anaPumps[1].AnaFrequencyItems; + var anaFreItems3 = anaPumps[2].AnaFrequencyItems; + for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++) + { + for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++) + { + for (int anaIndex3 = 0; anaIndex3 < anaFreItems3.Count; anaIndex3++) + { + var anaFreItem1 = anaFreItems1[anaIndex1]; + var anaFreItem2 = anaFreItems2[anaIndex2]; + var anaFreItem3 = anaFreItems3[anaIndex3]; + + _parallelConnectionHelper.ClearCurve(); + _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP); + _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP); + var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP); + if (!allowParallel) + continue; + var bol = pointQH.GetMinMaxPointY(out double maxY, out double minY); + if (!bol) + continue; + var maxHead = Math.Ceiling(maxY); + var minHead = Math.Floor(minY); + + for (double head = minHead; head <= maxHead; head += headSpace) + { + var flow = pointQH.GetInterPointX(head)?.LastOrDefault(); + if (!flow.HasValue) + continue; + var scheduleCombine = new ScheduleCombine(); + scheduleCombine.RunFlag = runFlag; + scheduleCombine.Pump1 = anaFreItem1.Frequency; + scheduleCombine.Pump2 = anaFreItem2.Frequency; + scheduleCombine.Pump3 = anaFreItem3.Frequency; + scheduleCombine.Head = head; + scheduleCombine.Flow = flow.Value; + scheduleCombine.Power = pointQP.GetFitPointY(flow.Value); + scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head); + scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow); + scheduleCombine.Round(); + scheduleCombineList.Add(scheduleCombine); + } + } + } + } + var success = Db.BulkInserts(scheduleCombineList); + if (!success) + { + + } + + } + + } + + /// <summary> + /// 鏁版嵁搴� + /// </summary> + public class Db + { + /// <summary> + /// 杩炴帴閰嶇疆 + /// </summary> + public static ConnectionConfig ConnectionConfig + { + get + { + + var filePath = DbInitial.DbFilePath; + if (!System.IO.File.Exists(filePath)) + { + DAL.DbInitial.InitTables(); + } + + var config = new ConnectionConfig() + { + ConnectionString = $"DataSource={filePath}", + IsAutoCloseConnection = true, + DbType = SqlSugar.DbType.Sqlite + }; + return config; + } + } + + + + /// <summary> + /// 澶ф壒閲忔彃鍏� + /// </summary> + public static bool BulkInserts(List<ScheduleCombine> list) + { + if (list == null || list.Count < 1) + return default; + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + ///鑷繁鏉ュ埗瀹氬畾涔夌殑瑙勫垯 + db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new RunFlagSubTableService(); + db.CodeFirst + .SplitTables()//鏍囪瘑鍒嗚〃 + .InitTables<ScheduleCombine>(); //绋嬪簭鍚姩鏃跺姞杩欎竴琛�,濡傛灉涓�寮犺〃娌℃湁浼氬垵濮嬪寲涓�寮� + + //澶ф暟鎹啓鍏�+琛ㄤ笉瀛樺湪浼氬缓琛� + //鑷姩鎵捐〃澶ф暟鎹啓鍏� + return db.Fastest<ScheduleCombine>().SplitTable().BulkCopy(list) > 0; + } + } + + /// <summary> + /// 鎻掑叆 + /// </summary> + public static bool Insert(string flag, int count, DateTime start, DateTime end) + { + var log = new AnaLog(flag, count, start, end); + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Insertable(log).ExecuteCommand() > 0; + } + } + + internal static object SplitHelper<T>() + { + throw new NotImplementedException(); + } + } + + /// <summary> + /// 鍒嗚〃瑙勫垯 + /// </summary> + public class RunFlagSubTableService : ISplitTableService + { + /// <summary> + /// 鑾峰彇鎵�鏈夌殑鏁版嵁搴撲腑鐨勮〃 + /// </summary> + /// <param name="db"></param> + /// <param name="EntityInfo"></param> + /// <param name="tableInfos"></param> + /// <returns></returns> + /// <exception cref="NotImplementedException"></exception> + public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos) + { + List<SplitTableInfo> result = new List<SplitTableInfo>(); + foreach (var item in tableInfos) + { + if (item.Name.Contains("_Run_")) //鍖哄垎鏍囪瘑濡傛灉涓嶇敤姝e垯绗﹀鏉備竴浜涳紝闃叉鎵鹃敊琛� + { + SplitTableInfo data = new SplitTableInfo() + { + TableName = item.Name //瑕佺敤item.name涓嶈鍐欓敊浜� + }; + result.Add(data); + } + } + return result.OrderBy(it => it.TableName).ToList();//鎵撴柇鐐圭湅涓�涓嬫湁娌℃湁鏌ュ嚭鎵�鏈夊垎琛� + } + + /// <summary> + /// + /// </summary> + /// <param name="db"></param> + /// <param name="entityInfo"></param> + /// <param name="splitType"></param> + /// <param name="entityValue"></param> + /// <returns></returns> + public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue) + { + var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null); + + return splitColumn.PropertyInfo.GetValue(entityValue, null); + } + + /// <summary> + /// + /// </summary> + /// <param name="db"></param> + /// <param name="EntityInfo"></param> + /// <returns></returns> + public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo) + { + return EntityInfo.DbTableName + "_Run"; + } + + public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType type) + { + return EntityInfo.DbTableName + "_Run"; + } + + /// <summary> + /// 纭畾鐢熸垚鏁版嵁搴撹〃鐨勬椂鍊欙紝琛ㄧ殑鍚嶇О + /// </summary> + /// <param name="db"></param> + /// <param name="entityInfo"></param> + /// <param name="splitType"></param> + /// <param name="fieldValue"></param> + /// <returns></returns> + public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue) + { + return entityInfo.DbTableName + "_Run_" + fieldValue.ToString(); + } + } + + /// <summary> + /// 璋冨害缁勫悎 + /// </summary> + [SplitTable(SplitType._Custom01)] + public class ScheduleCombine + { + public ScheduleCombine() { } + public ScheduleCombine(ScheduleCombine rhs) + { + this.Pump1 = rhs.Pump1; + this.Pump2 = rhs.Pump2; + this.Pump3 = rhs.Pump3; + this.Head = rhs.Head; + this.Flow = rhs.Flow; + this.Power = rhs.Power; + this.WP = rhs.WP; + this.UWP = rhs.UWP; + } + + public void Round() + { + this.Pump1 = Math.Round(this.Pump1, 1); + this.Pump2 = Math.Round(this.Pump2, 1); + this.Pump3 = Math.Round(this.Pump3, 1); + this.Head = Math.Round(this.Head, 1); + this.Flow = Math.Round(this.Flow, 1); + this.Power = Math.Round(this.Power, 1); + this.WP = Math.Round(this.WP, 1); + this.UWP = Math.Round(this.UWP, 1); + + } + + /// <summary> + /// 杩愯鏍囧織 (鏍囧織鏋氫妇) + /// </summary> + [SplitField] + public string RunFlag { get; set; } + + /// <summary> + /// 娉�1 + /// </summary> + public double Pump1 { get; set; } + + /// <summary> + /// 娉�2 + /// </summary> + public double Pump2 { get; set; } + + /// <summary> + /// 娉�3 + /// </summary> + public double Pump3 { get; set; } + + /// <summary> + /// 鎵▼ + /// </summary> + public double Head { get; set; } + + /// <summary> + /// 鎬绘祦閲� + /// </summary> + public double Flow { get; set; } + + /// <summary> + /// 鎬诲姛鐜� + /// </summary> + public double Power { get; set; } + + /// <summary> + /// 鍗冨惃姘磋兘鑰� + /// </summary> + public double WP { get; set; } + + /// <summary> + /// 鍗曚綅鑳借�� + /// </summary> + public double UWP { get; set; } + + /// <summary> + /// 鍒涘缓鏃堕棿 + /// </summary> + public DateTime CreateTime { get; set; } = DateTime.Now; + + + } +} + diff --git a/Schedule/IStation.Algorithm/Schedule/SchedulingCombineAnaHelper.cs b/Schedule/IStation.Algorithm/Schedule/SchedulingCombineAnaHelper.cs new file mode 100644 index 0000000..75a435e --- /dev/null +++ b/Schedule/IStation.Algorithm/Schedule/SchedulingCombineAnaHelper.cs @@ -0,0 +1,586 @@ +锘縰sing IStations; +using MathNet.Numerics.LinearAlgebra.Factorization; + +namespace IStation.Algorithm +{ + /// <summary> + /// 鍒嗘瀽娉甸」 + /// </summary> + public class AnaPumpItem + { + public AnaPumpItem() { } + public AnaPumpItem(Pump rhs) + { + this.ID = rhs.ID; + this.Name = rhs.Name; + this.Code = rhs.Code; + this.IsBp = rhs.IsBp; + this.Qr = rhs.Qr; + this.Hr = rhs.Hr; + this.Nr = rhs.Nr; + this.Pr = rhs.Pr; + this.Er = rhs.Er; + if (rhs.CurveQH != null && rhs.CurveQP != null) + { + this.CurveQH = rhs.CurveQH.Clone(); + this.CurveQP = rhs.CurveQP.Clone(); + this.AllowCalc = true; + } + } + + public AnaPumpItem(Pump rhs, double freDef, double freMin, double freMax, double freSpace) : this(rhs) + { + this.CalcFrequencyItems(freDef, freMin, freMax, freSpace); + } + + public int ID { get; set; } + public string Code { get; set; } + public string Name { get; set; } + public double Qr { get; set; } + public double Hr { get; set; } + public double Nr { get; set; } + public double Pr { get; set; } + public double Er { get; set; } + public bool IsBp { get; set; } + public Curve.CurveExpress CurveQH { get; set; } + public Curve.CurveExpress CurveQP { get; set; } + public List<AnaPumpFreItem> AnaFrequencyItems { get; set; } + public bool AllowCalc { get; set; } + + void CalcFrequencyItems(double freDef, double freMin, double freMax, double freSpace) + { + if (!this.AllowCalc) + return; + + this.AnaFrequencyItems = new List<AnaPumpFreItem>(); + //var freItemDef = new AnaFrequencyItem(); + //freItemDef.Frequency = freMax; + //freItemDef.CurveQH = this.CurveQH.Clone(); + //freItemDef.CurveQP = this.CurveQP.Clone(); + //this.AnaFrequencyItems.Add(freItemDef); + for (double fre = freMax; fre >= freMin; fre -= freSpace) + { + var freItem = new AnaPumpFreItem(); + freItem.Frequency = fre; + freItem.CurveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(this.CurveQH, freDef, fre); + freItem.CurveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(this.CurveQP, freDef, fre); + this.AnaFrequencyItems.Add(freItem); + } + } + } + + /// <summary> + /// 鍒嗘瀽娉靛彉棰戦」 + /// </summary> + public class AnaPumpFreItem + { + public double Frequency { get; set; } + public Curve.CurveExpress CurveQH { get; set; } + public Curve.CurveExpress CurveQP { get; set; } + } + + /// <summary> + /// 璋冨害鍒嗘瀽杈呭姪绫� + /// </summary> + public class SchedulingCombineAnaHelper + { + double _frequency_def = 50; + double _frequency_min = 25; + double _frequency_max = 50; + double _frequency_space = 0.1;//棰戠巼闂撮殧 + + ParallelConnectionHelper _parallelConnectionHelper = new ParallelConnectionHelper(); + + #region TableName + string _tableFrePumpTag = "B"; + string _tableFixPumpTag = "G"; + string _tableSpaceMark = "_"; + + string GetTableName(List<AnaPumpItem> pumpItems) + { + var tableName = string.Empty; + var count = pumpItems.Count; + pumpItems = pumpItems.OrderBy(p => p.ID).ToList(); + for (int i = 0; i < count; i++) + { + var pumpItem = pumpItems[i]; + tableName += GetTableName(pumpItem); + if ((i + 1) != count) + { + tableName += _tableSpaceMark; + } + } + return tableName; + } + + string GetTableName(AnaPumpItem pumpItem) + { + return (pumpItem.IsBp ? _tableFrePumpTag : _tableFixPumpTag) + pumpItem.ID; + } + + #endregion + + /// <summary> + /// 鍒嗘瀽娉电粍鍚� + /// </summary> + /// <param name="pumps">娉靛垪琛�</param> + /// <returns></returns> + public bool AnaCombine(List<Pump> pumps) + { + if (pumps == null || pumps.Count < 1) + return false; + var fre_def = _frequency_def; + var anaPumpItems = new List<AnaPumpItem>(); + foreach (var pump in pumps) + { + if (pump.IsBp) + { + //鍙橀娉� + var anaPump = new AnaPumpItem(pump, fre_def, _frequency_min, _frequency_max, _frequency_space); + if (anaPump.AllowCalc) + anaPumpItems.Add(anaPump); + } + else + { + //鍥洪娉� + var anaPump = new AnaPumpItem(pump); + if (anaPump.AllowCalc) + anaPumpItems.Add(anaPump); + } + } + + if (anaPumpItems.Count < 1) + return false; + + Db.Insert("寮�濮嬪垎鏋�"); + var maxRunCount = 3; + var anaPumpItemsArray = anaPumpItems.ToArray(); + for (int runCount = 1; runCount <= maxRunCount; runCount++) + { + var pumpCombineList = PermutationAndCombination<AnaPumpItem>.GetCombination(anaPumpItemsArray, runCount); + if (runCount == 1) + { + Db.Insert($"鍒嗘瀽1鍙版车,{pumpCombineList.Count}涓粍鍚堛��"); + for (int i = 0; i < pumpCombineList.Count; i++) + { + var anaPump = pumpCombineList[i][0]; + var runFlag = GetTableName(anaPump); + Db.Insert($"寮�濮嬪垎鏋�:{runFlag},涓嬫爣:{i}"); + AnaSinglePump(runFlag, anaPump); + } + } + else + if (runCount == 2) + { + Db.Insert($"鍒嗘瀽2鍙版车,{pumpCombineList.Count}涓粍鍚堛��"); + for (int i = 0; i < pumpCombineList.Count; i++) + { + var combine = pumpCombineList[i]; + var list = combine.ToList(); + string runFlag = GetTableName(list); //杩愯鏍囧織 + Db.Insert($"寮�濮嬪垎鏋�:{runFlag},涓嬫爣:{i}"); + AnaTwoPumps(runFlag, list); + } + } + else if (runCount == 3) + { + Db.Insert($"鍒嗘瀽3鍙版车,{pumpCombineList.Count}涓粍鍚堛��"); + for (int i = 0; i < pumpCombineList.Count; i++) + { + var combine = pumpCombineList[i]; + var list = combine.ToList(); + string runFlag = GetTableName(list); //杩愯鏍囧織 + Db.Insert($"寮�濮嬪垎鏋�:{runFlag},涓嬫爣:{i}"); + AnaThreePumps(runFlag, list); + } + } + } + Db.Insert("鍒嗘瀽瀹屾瘯"); + return true; + } + + private void AnaSinglePump(string runFlag, AnaPumpItem anaPump) + { + if (anaPump == null) + return; + if (!anaPump.AllowCalc) + return; + var scheduleCombineList = new List<Model.ScheduleCombine>(); + var anaFreItems = anaPump.AnaFrequencyItems; + foreach (var anaFreItem in anaFreItems) + { + var scheduleCombine = new Model.ScheduleCombine(); + scheduleCombine.RunFlag = runFlag; + scheduleCombine.RunCount = 1; + scheduleCombine.RunHZ = anaFreItem.Frequency.ToString(); + scheduleCombine.CurveQH = anaFreItem.CurveQH; + scheduleCombine.CurveQP = anaFreItem.CurveQP; + scheduleCombine.AnaStatus = false; + scheduleCombineList.Add(scheduleCombine); + } + var success = Db.BulkInserts(scheduleCombineList); + if (!success) + { + + } + } + + private void AnaTwoPumps(string runFlag, List<AnaPumpItem> anaPumps) + { + if (anaPumps == null || anaPumps.Count != 2) + return; + if (anaPumps.Exists(x => !x.AllowCalc)) + return; + var scheduleCombineList = new List<ScheduleCombine>(); + var anaFreItems1 = anaPumps[0].AnaFrequencyItems; + var anaFreItems2 = anaPumps[1].AnaFrequencyItems; + for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++) + { + for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++) + { + var anaFreItem1 = anaFreItems1[anaIndex1]; + var anaFreItem2 = anaFreItems2[anaIndex2]; + + _parallelConnectionHelper.ClearCurve(); + _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP); + _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP); + var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP); + if (!allowParallel) + continue; + + var scheduleCombine = new Model.ScheduleCombine(); + scheduleCombine.RunFlag = runFlag; + scheduleCombine.RunCount = 2; + scheduleCombine.RunHZ = $"{anaFreItem1.Frequency},{anaFreItem2.Frequency}"; + scheduleCombine.CurveQH = FitHelper.BuildCurveExpress(pointQH); + scheduleCombine.CurveQP = FitHelper.BuildCurveExpress(pointQP); + scheduleCombine.AnaStatus = false; + scheduleCombineList.Add(scheduleCombine); + } + } + var success = Db.BulkInserts(scheduleCombineList); + if (!success) + { + + } + } + + private void AnaThreePumps(string runFlag, List<AnaPumpItem> anaPumps) + { + if (anaPumps == null || anaPumps.Count != 3) + return; + if (anaPumps.Exists(x => !x.AllowCalc)) + return; + var scheduleCombineList = new List<ScheduleCombine>(); + var anaFreItems1 = anaPumps[0].AnaFrequencyItems; + var anaFreItems2 = anaPumps[1].AnaFrequencyItems; + var anaFreItems3 = anaPumps[2].AnaFrequencyItems; + for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++) + { + for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++) + { + for (int anaIndex3 = 0; anaIndex3 < anaFreItems3.Count; anaIndex3++) + { + var anaFreItem1 = anaFreItems1[anaIndex1]; + var anaFreItem2 = anaFreItems2[anaIndex2]; + var anaFreItem3 = anaFreItems3[anaIndex3]; + + _parallelConnectionHelper.ClearCurve(); + _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP); + _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP); + _parallelConnectionHelper.AddCurve(anaFreItem3.CurveQH, anaFreItem3.CurveQP); + var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP); + if (!allowParallel) + continue; + + var scheduleCombine = new Model.ScheduleCombine(); + scheduleCombine.RunFlag = runFlag; + scheduleCombine.RunCount = 3; + scheduleCombine.RunHZ = $"{anaFreItem1.Frequency},{anaFreItem2.Frequency},{anaFreItem3.Frequency}"; + scheduleCombine.CurveQH = FitHelper.BuildCurveExpress(pointQH); + scheduleCombine.CurveQP = FitHelper.BuildCurveExpress(pointQP); + scheduleCombine.AnaStatus = false; + scheduleCombineList.Add(scheduleCombine); + + } + } + } + var success = Db.BulkInserts(scheduleCombineList); + if (!success) + { + + } + + } + + } + + /// <summary> + /// 鏁版嵁搴� + /// </summary> + public class Db + { + /// <summary> + /// 杩炴帴閰嶇疆 + /// </summary> + public static ConnectionConfig ConnectionConfig + { + get + { + + var filePath = DAL.DbInitial.DbFilePath; + if (!System.IO.File.Exists(filePath)) + { + DAL.DbInitial.InitTables(); + } + + var config = new ConnectionConfig() + { + ConnectionString = $"DataSource={filePath}", + IsAutoCloseConnection = true, + DbType = SqlSugar.DbType.Sqlite + }; + return config; + } + } + + + + /// <summary> + /// 澶ф壒閲忔彃鍏� + /// </summary> + public static bool BulkInserts() + { + //if (list == null || list.Count < 1) + // return default; + //var entities = Models2Entities(list); + //using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + //{ + // ///鑷繁鏉ュ埗瀹氬畾涔夌殑瑙勫垯 + // db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new RunFlagSubTableService(); + // db.CodeFirst + // .SplitTables()//鏍囪瘑鍒嗚〃 + // .InitTables<ScheduleCombine>(); //绋嬪簭鍚姩鏃跺姞杩欎竴琛�,濡傛灉涓�寮犺〃娌℃湁浼氬垵濮嬪寲涓�寮� + + // //澶ф暟鎹啓鍏�+琛ㄤ笉瀛樺湪浼氬缓琛� + // //鑷姩鎵捐〃澶ф暟鎹啓鍏� + // return db.Fastest<Entity.ScheduleCombine>().SplitTable().BulkCopy(entities) > 0; + //} + + return false; + } + + /// <summary> + /// 澶ф壒閲忔彃鍏� + /// </summary> + public static bool BulkInserts(List<Model.ScheduleCombine> list) + { + if (list == null || list.Count < 1) + return default; + var entities = Models2Entities(list); + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Fastest<Entity.ScheduleCombine>().BulkCopy(entities) > 0; + } + } + + static List<Entity.ScheduleCombine> Models2Entities(List<Model.ScheduleCombine> modelList) + { + if (modelList == null || modelList.Count < 1) + return default; + var entities = new List<Entity.ScheduleCombine>(); + foreach (var model in modelList) + { + var entity = new Entity.ScheduleCombine(); + //entity.ID = + entity.RunFlag = model.RunFlag; + entity.RunCount = model.RunCount; + entity.RunHZ = model.RunHZ; + entity.CurveQH = model.CurveQH.ToJson(); + entity.CurveQP = model.CurveQP.ToJson(); + entity.AnaStatus = model.AnaStatus; + entities.Add(entity); + } + return entities; + } + + /// <summary> + /// 鎻掑叆 + /// </summary> + public static bool Insert(string info) + { + var log = new Entity.ScheduleAnaLog(info); + using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig)) + { + return db.Insertable(log).ExecuteCommandIdentityIntoEntity(); + } + } + + internal static object SplitHelper<T>() + { + throw new NotImplementedException(); + } + } + + /// <summary> + /// 鍒嗚〃瑙勫垯 + /// </summary> + public class RunFlagSubTableService : ISplitTableService + { + /// <summary> + /// 鑾峰彇鎵�鏈夌殑鏁版嵁搴撲腑鐨勮〃 + /// </summary> + /// <param name="db"></param> + /// <param name="EntityInfo"></param> + /// <param name="tableInfos"></param> + /// <returns></returns> + /// <exception cref="NotImplementedException"></exception> + public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos) + { + List<SplitTableInfo> result = new List<SplitTableInfo>(); + foreach (var item in tableInfos) + { + if (item.Name.Contains("_Run_")) //鍖哄垎鏍囪瘑濡傛灉涓嶇敤姝e垯绗﹀鏉備竴浜涳紝闃叉鎵鹃敊琛� + { + SplitTableInfo data = new SplitTableInfo() + { + TableName = item.Name //瑕佺敤item.name涓嶈鍐欓敊浜� + }; + result.Add(data); + } + } + return result.OrderBy(it => it.TableName).ToList();//鎵撴柇鐐圭湅涓�涓嬫湁娌℃湁鏌ュ嚭鎵�鏈夊垎琛� + } + + /// <summary> + /// + /// </summary> + /// <param name="db"></param> + /// <param name="entityInfo"></param> + /// <param name="splitType"></param> + /// <param name="entityValue"></param> + /// <returns></returns> + public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue) + { + var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null); + + return splitColumn.PropertyInfo.GetValue(entityValue, null); + } + + /// <summary> + /// + /// </summary> + /// <param name="db"></param> + /// <param name="EntityInfo"></param> + /// <returns></returns> + public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo) + { + return EntityInfo.DbTableName + "_Run"; + } + + public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType type) + { + return EntityInfo.DbTableName + "_Run"; + } + + /// <summary> + /// 纭畾鐢熸垚鏁版嵁搴撹〃鐨勬椂鍊欙紝琛ㄧ殑鍚嶇О + /// </summary> + /// <param name="db"></param> + /// <param name="entityInfo"></param> + /// <param name="splitType"></param> + /// <param name="fieldValue"></param> + /// <returns></returns> + public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue) + { + return entityInfo.DbTableName + "_Run_" + fieldValue.ToString(); + } + } + + ///// <summary> + ///// 璋冨害缁勫悎 + ///// </summary> + //[SplitTable(SplitType._Custom01)] + //public class ScheduleCombine + //{ + // public ScheduleCombine() { } + // public ScheduleCombine(ScheduleCombine rhs) + // { + // this.Pump1 = rhs.Pump1; + // this.Pump2 = rhs.Pump2; + // this.Pump3 = rhs.Pump3; + // this.Head = rhs.Head; + // this.Flow = rhs.Flow; + // this.Power = rhs.Power; + // this.WP = rhs.WP; + // this.UWP = rhs.UWP; + // } + + // public void Round() + // { + // this.Pump1 = Math.Round(this.Pump1, 1); + // this.Pump2 = Math.Round(this.Pump2, 1); + // this.Pump3 = Math.Round(this.Pump3, 1); + // this.Head = Math.Round(this.Head, 1); + // this.Flow = Math.Round(this.Flow, 1); + // this.Power = Math.Round(this.Power, 1); + // this.WP = Math.Round(this.WP, 1); + // this.UWP = Math.Round(this.UWP, 1); + + // } + + // /// <summary> + // /// 杩愯鏍囧織 (鏍囧織鏋氫妇) + // /// </summary> + // [SplitField] + // public string RunFlag { get; set; } + + // /// <summary> + // /// 娉�1 + // /// </summary> + // public double Pump1 { get; set; } + + // /// <summary> + // /// 娉�2 + // /// </summary> + // public double Pump2 { get; set; } + + // /// <summary> + // /// 娉�3 + // /// </summary> + // public double Pump3 { get; set; } + + // /// <summary> + // /// 鎵▼ + // /// </summary> + // public double Head { get; set; } + + // /// <summary> + // /// 鎬绘祦閲� + // /// </summary> + // public double Flow { get; set; } + + // /// <summary> + // /// 鎬诲姛鐜� + // /// </summary> + // public double Power { get; set; } + + // /// <summary> + // /// 鍗冨惃姘磋兘鑰� + // /// </summary> + // public double WP { get; set; } + + // /// <summary> + // /// 鍗曚綅鑳借�� + // /// </summary> + // public double UWP { get; set; } + + // /// <summary> + // /// 鍒涘缓鏃堕棿 + // /// </summary> + // public DateTime CreateTime { get; set; } = DateTime.Now; + + + //} +} + diff --git a/Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingInput.cs b/Schedule/IStation.Algorithm/Schedule/bak/CalcInput.cs similarity index 95% rename from Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingInput.cs rename to Schedule/IStation.Algorithm/Schedule/bak/CalcInput.cs index ffcbae3..cc9cb1b 100644 --- a/Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingInput.cs +++ b/Schedule/IStation.Algorithm/Schedule/bak/CalcInput.cs @@ -1,9 +1,9 @@ -锘縩amespace IStation.Scheduling.Algorithm +锘縩amespace IStation.Model { /// <summary> - /// 璋冨害鍏ュ弬 + /// 璁$畻鍏ュ弬 /// </summary> - public class SchedulingInput + public class CalcInput { /// <summary> /// 瀛h妭 1:鏄� 2:澶� 3:绉� 4:鍐� diff --git a/Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingOutput.cs b/Schedule/IStation.Algorithm/Schedule/bak/CalcOutput.cs similarity index 92% rename from Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingOutput.cs rename to Schedule/IStation.Algorithm/Schedule/bak/CalcOutput.cs index fd26788..f27d262 100644 --- a/Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingOutput.cs +++ b/Schedule/IStation.Algorithm/Schedule/bak/CalcOutput.cs @@ -1,9 +1,9 @@ -锘縩amespace IStation.Scheduling.Algorithm +锘縩amespace IStation.Model { /// <summary> /// 璁$畻鍑哄弬 /// </summary> - public class SchedulingOutput + public class CalcOutput { /// <summary> /// 鏂规鍒楄〃 @@ -67,10 +67,10 @@ /// <summary> /// 娉典俊鎭� /// </summary> - public class Pump + public class PumpInfo { - public Pump() { } - public Pump(Pump rhs) + public PumpInfo() { } + public PumpInfo(PumpInfo rhs) { this.ID = rhs.ID; this.Q = rhs.Q; diff --git a/Schedule/IStation.Console/IStation.Console.csproj b/Schedule/IStation.Console/IStation.Console.csproj new file mode 100644 index 0000000..5541a6d --- /dev/null +++ b/Schedule/IStation.Console/IStation.Console.csproj @@ -0,0 +1,14 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>net6.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\IStation.Algorithm\IStation.Algorithm.csproj" /> + </ItemGroup> + +</Project> diff --git a/Schedule/IStation.Console/IStation.Console.csproj.user b/Schedule/IStation.Console/IStation.Console.csproj.user new file mode 100644 index 0000000..4f2b164 --- /dev/null +++ b/Schedule/IStation.Console/IStation.Console.csproj.user @@ -0,0 +1,6 @@ +锘�<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <_LastSelectedProfileId>C:\WorkCode\IStation\Service.Ch.V1.0\Schedule\IStation.Console\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId> + </PropertyGroup> +</Project> \ No newline at end of file diff --git a/Schedule/IStation.Console/Program.cs b/Schedule/IStation.Console/Program.cs new file mode 100644 index 0000000..8e0d13b --- /dev/null +++ b/Schedule/IStation.Console/Program.cs @@ -0,0 +1,24 @@ +锘縰sing IStation; +using IStation.Algorithm; +using IStation.Model; + +//DbInitial.InitTables(); + +SnowflakeIdHelper.SetIdGenerator(1); + +var folder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data"); +var ch1 = folder + "\\" + "闄堣涓�杈�.json"; +var ch1_json = File.ReadAllText(ch1); +var ch1Pumps = JsonHelper.Json2Object<List<Pump>>(ch1_json); + + + +var ch2 = folder + "\\" + "闄堣浜岃緭.json"; +var ch2_json = File.ReadAllText(ch2); +var ch2Pumps = JsonHelper.Json2Object<List<Pump>>(ch2_json); + + +var helper = new SchedulingCombineAnaHelper(); +helper.AnaCombine(ch1Pumps); + +Console.WriteLine("鍒嗘瀽瀹屾瘯"); \ No newline at end of file diff --git a/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml b/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..154e035 --- /dev/null +++ b/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,13 @@ +锘�<?xml version="1.0" encoding="utf-8"?> +<!-- +https://go.microsoft.com/fwlink/?LinkID=208121. +--> +<Project> + <PropertyGroup> + <Configuration>Release</Configuration> + <Platform>Any CPU</Platform> + <PublishDir>bin\Release\net6.0\publish\</PublishDir> + <PublishProtocol>FileSystem</PublishProtocol> + <_TargetId>Folder</_TargetId> + </PropertyGroup> +</Project> \ No newline at end of file diff --git a/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml.user b/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml.user new file mode 100644 index 0000000..d13aa8b --- /dev/null +++ b/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -0,0 +1,10 @@ +锘�<?xml version="1.0" encoding="utf-8"?> +<!-- +https://go.microsoft.com/fwlink/?LinkID=208121. +--> +<Project> + <PropertyGroup> + <History>True|2024-04-28T02:47:31.7982351Z;True|2024-04-28T10:35:09.9659769+08:00;True|2024-04-28T10:34:06.3953736+08:00;</History> + <LastFailureDetails /> + </PropertyGroup> +</Project> \ No newline at end of file diff --git a/Scheduling/IStation.Scheduling.Algorithm/IStation.Scheduling.Algorithm.csproj b/Scheduling/IStation.Scheduling.Algorithm/IStation.Scheduling.Algorithm.csproj deleted file mode 100644 index 141e38f..0000000 --- a/Scheduling/IStation.Scheduling.Algorithm/IStation.Scheduling.Algorithm.csproj +++ /dev/null @@ -1,9 +0,0 @@ -<Project Sdk="Microsoft.NET.Sdk"> - - <PropertyGroup> - <TargetFramework>net6.0</TargetFramework> - <ImplicitUsings>enable</ImplicitUsings> - <Nullable>disable</Nullable> - </PropertyGroup> - -</Project> -- Gitblit v1.9.3