/// <summary> /// 根据导线点计算巷道左右帮的点 /// 前后两个导线点坐标一样的情况未处理,传入的导线点数据需要保证不重复. /// </summary> /// <params name="wirePts">导线点实体</params> /// <params name="verticesLeftBtmRet">out,根据导线点计算出的巷道左帮所有点</params> /// <params name="verticesRightBtmRet">out,根据导线点计算出的巷道右帮所有点</params> /// <returns></returns> public bool calc_left_and_right_vertics(WirePoint[] wirePts, ref Vector3_DW[] verticesLeftBtmRet, ref Vector3_DW[] verticesRightBtmRet) { if (wirePts == null) { return(false); } int nTraversePtCnt = wirePts.Length; if (nTraversePtCnt < 1) { return(false); } #region 仅含两个导线点 if (nTraversePtCnt == 2) { bool bRet = calc_left_and_right_vertics_with2_traver_points(wirePts, ref verticesLeftBtmRet, ref verticesRightBtmRet); if (bRet == false) { return(false); } } #endregion #region 大于等于三个点 else { var lstLeftBtmVertices = new List <Vector3_DW>(); var lstRightBtmVertices = new List <Vector3_DW>(); #region For loop for (int i = 0; i < nTraversePtCnt - 2; i++) { var lwDatasPreTmp = new[] { wirePts[i], wirePts[i + 1] }; var lwDatasNextTmp = new[] { wirePts[i + 1], wirePts[i + 2] }; Vector3_DW[] verticesLeftPreTmp = null; Vector3_DW[] verticesRightPreTmp = null; if (false == calc_left_and_right_vertics_with2_traver_points(lwDatasPreTmp, ref verticesLeftPreTmp, ref verticesRightPreTmp)) { return(false); } Vector3_DW[] verticesLeftNextTmp = null; Vector3_DW[] verticesRightNextTmp = null; if (false == calc_left_and_right_vertics_with2_traver_points(lwDatasNextTmp, ref verticesLeftNextTmp, ref verticesRightNextTmp)) { return(false); } var vertexMid2D = new Vector2_DW(); var vertexLeftMid = new Vector3_DW(); var vertexRightMid = new Vector3_DW(); //左邦中间的点 LineIntersectType lit = ToolsMath_DW.LineXLine(new Vector2_DW(verticesLeftPreTmp[0].X, verticesLeftPreTmp[0].Y), new Vector2_DW(verticesLeftPreTmp[1].X, verticesLeftPreTmp[1].Y), new Vector2_DW(verticesLeftNextTmp[0].X, verticesLeftNextTmp[0].Y), new Vector2_DW(verticesLeftNextTmp[1].X, verticesLeftNextTmp[1].Y), ref vertexMid2D); if (lit == LineIntersectType.None) //有重复点,可能是这种情况eg:p0(0, 0), p1(2, 0),p2(1, 0), p3(4, 0) { vertexLeftMid.X = verticesLeftPreTmp[1].X; vertexLeftMid.Y = verticesLeftPreTmp[1].Y; vertexLeftMid.Z = lwDatasPreTmp[1].coordinate_z; } else { vertexLeftMid.X = vertexMid2D.X; vertexLeftMid.Y = vertexMid2D.Y; vertexLeftMid.Z = lwDatasPreTmp[1].coordinate_z; } //右邦中间的点 lit = ToolsMath_DW.LineXLine(new Vector2_DW(verticesRightPreTmp[0].X, verticesRightPreTmp[0].Y), new Vector2_DW(verticesRightPreTmp[1].X, verticesRightPreTmp[1].Y), new Vector2_DW(verticesRightNextTmp[0].X, verticesRightNextTmp[0].Y), new Vector2_DW(verticesRightNextTmp[1].X, verticesRightNextTmp[1].Y), ref vertexMid2D); if (lit == LineIntersectType.None) //有重复点,可能是这种情况eg:p0(0, 0), p1(2, 0),p2(1, 0), p3(4, 0) { vertexRightMid.X = verticesRightPreTmp[1].X; vertexRightMid.Y = verticesRightPreTmp[1].Y; vertexRightMid.Z = lwDatasPreTmp[1].coordinate_z; } else { vertexRightMid.X = vertexMid2D.X; vertexRightMid.Y = vertexMid2D.Y; vertexRightMid.Z = lwDatasPreTmp[1].coordinate_z; } //保存计算出来的点 //第一个顶点 if (i == 0) { lstLeftBtmVertices.Add(verticesLeftPreTmp[0]); lstRightBtmVertices.Add(verticesRightPreTmp[0]); } //中间的顶点 lstLeftBtmVertices.Add(vertexLeftMid); lstRightBtmVertices.Add(vertexRightMid); //最后一个顶点 if (i == nTraversePtCnt - 3) { lstLeftBtmVertices.Add(verticesLeftNextTmp[1]); lstRightBtmVertices.Add(verticesRightNextTmp[1]); } } //end for #endregion verticesLeftBtmRet = lstLeftBtmVertices.ToArray(); verticesRightBtmRet = lstRightBtmVertices.ToArray(); } #endregion return(true); }
//double CalcNearestDis(Vector3_DW pt, PreWarningSpecialDataCalcBase[] spDataEnts, out Vector3_DW outNearestPt) //{ // double minDis = 0; // outNearestPt = Vector3_DW.zero; // int nSpecialDataEnts = spDataEnts.Length; // for (int spDataIdx = 0; spDataIdx < nSpecialDataEnts; spDataIdx++) // { // double tmpDis = spDataEnts[spDataIdx].CalcDis(pt, out outNearestPt); // if (spDataIdx == 0) // { // minDis = tmpDis; // } // if (tmpDis < minDis) // { // minDis = tmpDis; // } // } // return minDis; //} /// <summary> /// 计算预警结果 /// </summary> /// <param name="tunnelID">巷道ID</param> /// <returns>预警结果列表,注:可能返回空。当该巷道未绑定预警规则时则返回null</returns> public PreWarningResultEntity[] CalcPreWarningResult(int tunnelID, DateTime minTime, DateTime maxTime) { List <PreWarningResultEntity> lstAllResult = new List <PreWarningResultEntity>(); //查询巷道信息表,获取该巷道使用的规则编码和参数信息列表 RuleCodeAndParamInfo[] allParamInfo = PreWarningRulesBLL.GetTunnelBindingRuleCodesAndParams(tunnelID); if (allParamInfo == null) { Alert.alert("该巷道未绑定预警规则!"); //该巷道未绑定预警规则 return(null); } //Hashtable htTbls = GetPreWarningDataTableAndBindingTables(); //查询预警数据表管理表,获取所有的预警数据表和对应的预警数据字段与规则编码对应关系表信息 DataTblAndBindingTblInfoEntity[] tableInfo = GetPreWarningDataTableAndBindingTablesInfo(); //int nTables = htTbls.Count; int nTables = tableInfo.Length; //try //{ //遍历所有的预警数据表 //foreach (string dataTblName in htTbls.Keys) for (int tblIdx = 0; tblIdx < nTables; tblIdx++) { string dataTblName = tableInfo[tblIdx].DataTableName; //获取当前预警数据表中巷道ID、时间等符合条件的所有预警数据。 DataSet dsData = null; if (tableInfo[tblIdx].NeedConstrains == true) { dsData = GetPreWarningDatas(dataTblName, tunnelID, minTime, maxTime); } else { dsData = GetPreWarningDatas(dataTblName); } int nDataCnt = dsData.Tables[0].Rows.Count; //遍历当前预警数据表中所有数据 for (int dataIdx = 0; dataIdx < nDataCnt; dataIdx++) { //预警数据表绑定的表名(预警数据字段与规则编码表) //string bindingTableName = htTbls[dataTblName].ToString(); string bindingTableName = tableInfo[tblIdx].BindingTableName; //读取当前预警数据表对应的预警数据字段与规则编码关系表,获取预警数据字段与规则编码关系表中所有字段名、规则编码及字段使用方式 //string[] fieldNames = GetPreWarningDataBindingTableFieldNames(bindingTableName); BindingTableEntity[] bindingEnt = GetPreWarningDataBindingTableEntity(bindingTableName); //if (fieldNames == null) if (bindingEnt == null) { Alert.alert("表:" + bindingTableName + "中未将数据字段与规则编码绑定!"); continue; } //int nFieldCnt = fieldNames.Length; int nFieldCnt = bindingEnt.Length; #region 遍历所有字段名(数据)[字段使用方式为 非直接使用的 一种字段使用方式只能对应一条记录!] for (int fieldIdx = 0; fieldIdx < nFieldCnt; fieldIdx++) { //获取当前记录中的字段 //string curFieldName = fieldNames[fieldIdx]; string curFieldName = bindingEnt[fieldIdx].ColumnName; //获取当前字段对应的值 double fieldValue = 0; try { //当前记录中字段的 字段使用方式 是否为:直接使用 if (bindingEnt[fieldIdx].UseManner == COLUMN_USE_MANNER.DIRECT_USE) { fieldValue = Convert.ToDouble(dsData.Tables[0].Rows[dataIdx][curFieldName]); } //需要进行特殊预警数据计算(如:距断层、陷落柱等距离) #region 特殊数据计算 else { //根据预警数据表名称获取预警数据实体(如:断层实体、陷落柱实体) PreWarningSpecialDataCalcBase calcDataEnt = GetPreWarningSpecialDataEntitiesByTblName(tableInfo[tblIdx].DataTableName, dsData.Tables[0].Rows[dataIdx]); if (calcDataEnt == null) { //未对该数据表进行维护 //获取下一预警数据表(此处为了省事,break后会获取下一预警数据,而非下一预警数据表!理论上应该获取下一预警数据表) break; } //字段使用方式是否为:计算最近距离 if (bindingEnt[fieldIdx].UseManner == COLUMN_USE_MANNER.CALC_NEAREST_DIS) { Vector3_DW ptTunnel = Vector3_DW.zero; //获取当前巷道当前位置 MARK 尚未实现 Vector3_DW outPtNearest = Vector3_DW.zero; fieldValue = calcDataEnt.CalcNearestDis(ptTunnel, out outPtNearest); } //字段使用方式是否为:计算值(如探头瓦斯浓度增加值) else if (bindingEnt[fieldIdx].UseManner == COLUMN_USE_MANNER.CALC_VALUE) { fieldValue = calcDataEnt.CalcValue(); } else { Alert.alert("表:" + dataTblName + " 中数据库中录入的字段使用方式不正确!"); //获取下一记录(字段名、规则编码及字段使用方式) //如果一个数据表对应多种计算方法,则需要在绑定表中添加一列标识使用哪个函数。 //目前尚未处理一个数据表对应多种计算方法的情况 continue; } } #endregion }//end of try catch (Exception ex) { Alert.alert("获取表(" + bindingTableName + ")中的字段(" + curFieldName + ")对应的值出错:" + ex.Message); continue; } //获取当前字段名对应的所有规则编码 //string[] ruleCodes = GetRuleCodesByFieldName(curFieldName, bindingTableName); //当前规则编码在规则编码和参数信息列表中是否存在 //int nRuleCodeCnt = ruleCodes.Length; //遍历当前字段名对应的所有规则编码(该步骤不需要!!先前算法绕弯了,速度较慢) //for (int ruleCodeIdx = 0; ruleCodeIdx < nRuleCodeCnt; ruleCodeIdx++) //{ //string curRuleCode = ruleCodes[ruleCodeIdx]; string curRuleCode = bindingEnt[fieldIdx].BindingWarningRules; //当前规则编码在规则编码和参数信息列表中是否存在 RuleCodeAndParamInfo curParamsInfo = null; if (!IsRuleCodeExistInTunnelParamInfo(curRuleCode, allParamInfo, out curParamsInfo)) { //不存在 continue; } //存在 //读取预警规则表,获取当前规则编码的预警规则实体信息 PreWarningRulesEntity preWarningEnt = PreWarningRulesBLL.GetPreWarningRulesEntityByRuleCode(curRuleCode); //当前字段值通过预警规则实体中的比较符(注:比较符可能含多个)与规则编码和参数信息中的参数值进行比较,比较结果是否为True。 if (GetCompareResultByEntAndParamInfo(fieldValue, preWarningEnt, curParamsInfo)) { //比较结果为TRUE PreWarningResultEntity oneResult = new PreWarningResultEntity(); if (preWarningEnt.IndicatorType != Const_WM.YES_NO_INDICATOR) { if (!preWarningEnt.UpdateRuleDescriptionByParams(curParamsInfo.PreWarningParams)) { Alert.alert("更新预警规则实体规则描述信息失败!"); continue; } } //预警规则实体信息 oneResult.PreWarningRulesEntity = preWarningEnt; //预警数据通用信息 PreWarningDataCommonInfoEntity dataEnt = GetWarningDataCommonInfo(dsData.Tables[0].Rows[dataIdx], curFieldName); dataEnt.TunnelID = tunnelID; oneResult.WarningDataCommonInfoEnt = dataEnt; //将当前记录信息及预警规则实体信息添加至预警结果列表 lstAllResult.Add(oneResult); } //}//end of 遍历当前字段名对应的所有规则编码 } //end of 遍历所有字段名 #endregion 遍历所有字段名 } //end of 遍历当前预警数据表中所有数据 } //end of 遍历所有的预警数据表 //}//end of try //catch (Exception ex) //{ // Alert.alert(ex.Message); //} return(lstAllResult.ToArray()); }//end of function
/// <summary> /// 计算仅含两个导线点的巷道的左右邦点 /// </summary> /// <params name="wirePts"></params> /// <params name="verticesLeftRet"></params> /// <params name="verticesRightRet"></params> /// <returns></returns> private bool calc_left_and_right_vertics_with2_traver_points(WirePoint[] wirePts, ref Vector3_DW[] verticesLeftRet, ref Vector3_DW[] verticesRightRet) { if (wirePts == null) { return(false); } int nTraversePtCnt = wirePts.Length; if (nTraversePtCnt != 2) { return(false); } //仅含两个导线点 if (nTraversePtCnt == 2) { var ptPre = new Vector2_DW(wirePts[0].coordinate_x, wirePts[0].coordinate_y); var ptNext = new Vector2_DW(wirePts[1].coordinate_x, wirePts[1].coordinate_y); Vector2_DW vecForwardDir = (ptNext - ptPre).Normalize(); /*根据法线方向判断巷道左右邦. * 若垂直向量vecPerpendicular与vecForwardDir的叉积所得向量与Y轴夹角小于90度(二者点积大于0),,则认为该垂直向量为左帮方向 * x1*x2 + y1*y2 = 0//垂直 * x1*y2 - x2*y1 = 0//平行 * *点积 a●b=|a|*|b|*cos(w)=x1*x2+y1*y2=0 *叉积 aXb=|a|*|b|*sin(w)=(x1*z2-z1*y2)x^+(z1*x2-z1*y2)y^+(x1*y2-y1*x2)z^(右手螺旋定则)=0 -->二维的表示平行四边形的面积 *混合积 (aXb)●c = |aXb|*|c|*cos(aXb,c) -->平行六面体的体积 */ var vecPerpendicularLeft = new Vector2_DW(vecForwardDir.Y, -vecForwardDir.X); Vector2_DW vecPerpendicularRight = -vecPerpendicularLeft; Vector3_DW vecNormal = Vector3_DW.Cross(new Vector3_DW(vecForwardDir.X, vecForwardDir.Y, 0), new Vector3_DW(vecPerpendicularLeft.X, vecPerpendicularLeft.Y, 0)); if (vecNormal.Z < 0) { Vector2_DW vecSwap = vecPerpendicularLeft; vecPerpendicularLeft = vecPerpendicularRight; vecPerpendicularRight = vecSwap; } var leftVertices = new List <Vector3_DW>(); var rightVertices = new List <Vector3_DW>(); Vector2_DW ptLeftPre = ptPre + vecPerpendicularLeft * wirePts[0].left_distance; Vector2_DW ptLeftNext = ptNext + vecPerpendicularLeft * wirePts[1].left_distance; Vector2_DW ptRightPre = ptPre + vecPerpendicularRight * wirePts[0].right_distance; Vector2_DW ptRightNext = ptNext + vecPerpendicularRight * wirePts[1].right_distance; leftVertices.Add(new Vector3_DW(ptLeftPre.X, ptLeftPre.Y, wirePts[0].coordinate_z)); leftVertices.Add(new Vector3_DW(ptLeftNext.X, ptLeftNext.Y, wirePts[1].coordinate_z)); rightVertices.Add(new Vector3_DW(ptRightPre.X, ptRightPre.Y, wirePts[0].coordinate_z)); rightVertices.Add(new Vector3_DW(ptRightNext.X, ptRightNext.Y, wirePts[1].coordinate_z)); verticesLeftRet = leftVertices.ToArray(); verticesRightRet = rightVertices.ToArray(); } return(true); }