diff --git a/src/BlockMaker.cpp b/src/BlockMaker.cpp new file mode 100644 index 0000000..bd8ce13 --- /dev/null +++ b/src/BlockMaker.cpp @@ -0,0 +1,2911 @@ +// Copyright (c) Naiky Company. All rights reserved. +// +// Abstract: +// G文件到CVT格式数据定义文件 wangwenbo 2010.02.18 +////////////////////////////////////////////////////////////////////// +#include "StdAfx.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW +#endif + +using namespace ncmath; + +#define DEGREE2RADIAN(deg) ((deg) / 180.0 * c_nPIE) + +CS_T s_szFORMATORVERSIONERROR = _DEFCS(_CSV(11400), + _CHINESE("|E|加工文件格式错误或版本不符") + _ENGLISH("|E|Error file format or version")); +CS_T s_szSUBPROGREPEATED = _DEFCS(_CSV(11401), + _CHINESE("|E|子程序重复") + _ENGLISH("|E|Subprogram repeat")); +CS_T s_szSUBPROGFORMATERROR = _DEFCS(_CSV(11402), + _CHINESE("|E|子程序格式错误") + _ENGLISH("|E|Subprogram format error")); +CS_T s_szERROR_NOSUBPROGRAM_NO = _DEFCS(_CSV(11403), + _CHINESE("找不到调用的子程序(%d)") + _ENGLISH("Not found the subprogram(%d) invoked")); +CS_T s_szERROR_NOSUBPROGRAM_NAME = _DEFCS(_CSV(11404), + _CHINESE("找不到调用的子程序(%s)") + _ENGLISH("Not found the Subprogram(%s) invoked")); +CS_T s_szERROR_G51_INSTRUCTION = _DEFCS(_CSV(11405), + _CHINESE("G51 指令错误") + _ENGLISH("G51 instruction error")); +CS_T s_szERROR_DUPLICATE_CODE_OF_SAME_GROUP = _DEFCS(_CSV(11406), + _CHINESE("同组G/M指令重复") + _ENGLISH("Repeated G/M code in one group")); +CS_T s_szERROR_WCS_OVERRANGE = _DEFCS(_CSV(11407), + _CHINESE("工件坐标超出允许范围:轴%c") + _ENGLISH("Workpiece coordinates are beyond permissible range: axis-%c")); +CS_T s_szERROR_SPECIAL_CIRCLE_CYCLE = _DEFCS(_CSV(11408), + _CHINESE("G34/35/36/37 指令错误:特殊固定循环指令不匹配,无指定的动作") + _ENGLISH("G34/35/36/37 instruction error: special fixed cycle instruction mismatched: no motion specified")); +CS_T s_szERROR_SPECIAL_CIRCLE_CYCLE_FORMAT = _DEFCS(_CSV(11409), + _CHINESE("G34/35/36/37 指令错误:特殊固定循环指令格式错误") + _ENGLISH("G34/35/36/37 instruction error: special fixed cycle instruction format error")); +CS_T s_szERROR_SFC_TOO_MANY_TIMES = _DEFCS(_CSV(11410), + _CHINESE("G34/35/36/37 指令错误:指定的循环次数太大") + _ENGLISH("G34/35/36/37 instruction error: too much times specified for loop")); +CS_T s_szERROR_DUPLICATE_L_K_INSTRUCTION = _DEFCS(_CSV(11411), + _CHINESE("固定循环指令中L、K指令重复") + _ENGLISH("Repeated L/K codes in fixed cycle command")); +CS_T s_szERROR_MATCH_TAGGEDDATA = _DEFCS(_CSV(11412), + _CHINESE("无法找到合适的地址字") + _ENGLISH("Cannot match the address data")); +CS_T s_szERROR_UNEXPECTED_TAGGEDDATA = _DEFCS(_CSV(11413), + _CHINESE("不应该出现的地址字:%s") + _ENGLISH("Unexpected address data:%s")); +CS_T s_szERROR_MATCH_BACKWARDRULE = _DEFCS(_CSV(11414), + _CHINESE("G代码格式错误:匹配规则失败") + _ENGLISH("G code format error: matching rule failed")); +CS_T s_szERROR_INVALID_GCODE = _DEFCS(_CSV(11415), + _CHINESE("无效G指令:G%g") + _ENGLISH("Invalid G code:G%d")); +CS_T s_szERROR_INVALID_MCODE = _DEFCS(_CSV(11416), + _CHINESE("无效M指令:M%d") + _ENGLISH("Invalid M code:M%d")); +CS_T s_szERROR_UNKOWN_TOKEN = _DEFCS(_CSV(11417), + _CHINESE("无效的指令:%s%d") + _ENGLISH("Invalid instruction:%s%d")); +CS_T s_szERROR_NOENOUGHPARAMETERS = _DEFCS(_CSV(11418), + _CHINESE("%s:参数不足") + _ENGLISH("%s:Need more parameters")); +CS_T s_szERROR_G51_50_NOTMATCH = _DEFCS(_CSV(11419), + _CHINESE("G51/G50指令不配对 ") + _ENGLISH("G51/G50 mismatch")); +CS_T s_szERROR_G51D1_50D1_NOTMATCH = _DEFCS(_CSV(11420), + _CHINESE("G51.1/G50.1指令不配对 ") + _ENGLISH("G51.1/G50.1 mismatch")); +CS_T s_szERROR_INVALID_PROGRAM_UNDER_REVOLVING_MODE = _DEFCS(_CSV(11421), + _CHINESE("旋转轴方式下不支持圆弧角度编程") + _ENGLISH("Don't support G2/G3 code whose unit is angle under revolving mode")); +CS_T s_szCHANGE_TOOL_MESSAGE = _DEFCS(_CSV(11422), + _CHINESE("现在需要换一把刀,换刀请停止,换刀后断点继续;不换刀请按“开始”继续") + _ENGLISH("Now need to change tool, please press stop to change tool, or directly press 'start' to continue if cutter exchange is no needed")); +CS_T s_szERROR_IJK_ERROR = _DEFCS(_CSV(11423), + _CHINESE("IJK参数错误。请修改参数!") + _ENGLISH("IJK param. error, please modify it!")); +CS_T s_szERROR_ARC_RADIUS_TOO_SMALL = _DEFCS(_CSV(11424), + _CHINESE("圆弧半径过小:必须大于0.001") + _ENGLISH("Too Small Arc Radius value: the minimal value is 0.001 ")); +CS_T s_szERROR_ARC_RADIUSERROR = _DEFCS(_CSV(11425), + _CHINESE("圆弧半径超差:请检查加工代码或修改参数设置") + _ENGLISH("Too big tolerance of Arc radius: Please check NC-code or revise parameters setting")); +CS_T s_szARCPLANE = _DEFCS(_CSV(11426), + _CHINESE("当转换为2维数据时,仅支持G17平面") + _ENGLISH("Only Support G17 when convert to 2D")); +CS_T s_szERROR_G904_SPEEDERROR = _DEFCS(_CSV(11427), + _CHINESE("G904指令指定速度不正确") + _ENGLISH("Speed specified by G904 error ")); +CS_T s_szERROR_G904_DISTERROR = _DEFCS(_CSV(11428), + _CHINESE("G904指令指定距离不正确") + _ENGLISH("Distance specified by G904 error")); +CS_T s_szERROR_G904_ERROR_MISSADDR = _DEFCS(_CSV(11429), + _CHINESE("G904指令不正确:缺少地址字") + _ENGLISH("G904 instruction error: missing address data")); +CS_T s_szERROR_G51_ZERO_ZOOM_ASPECT = _DEFCS(_CSV(11430), + _CHINESE("G51 指令错误:缩放比例为0") + _ENGLISH("G51 instruction error: scaling is zero")); +CS_T s_szERROR_INCORRECT_ASPECT_FOR_RADIUS = _DEFCS(_CSV(11431), + _CHINESE("圆弧插补时两轴缩放比例不一致") + _ENGLISH("Inconsistent zoom ratio between the two axes when arc interpolation")); +CS_T s_szERROR_G51_1_NOT1ST_TRANSFORM = _DEFCS(_CSV(11432), + _CHINESE("G51.1/G50.1 指令错误:该指令不能在G68或G51模式下使用") + _ENGLISH("G51.1/G50.1 instruction error: G50.1 and G51.1 can not be specified under G68 or G51 mode.")); +CS_T s_szERROR_G68_69_NOTMATCH = _DEFCS(_CSV(11433), + _CHINESE("G68/G69指令不配对") + _ENGLISH("G68/G69 mismatch")); +CS_T s_szERROR_SPIRALPITCH = _DEFCS(_CSV(11434), + _CHINESE("不支持螺旋线") + _ENGLISH("Don't Support Spiralling")); +CS_T s_szCALLTIMES = _DEFCS(_CSV(11435), + _CHINESE("循环调用次数为%d\n是否省略?") + _ENGLISH("Cycle call time is %d\nOmitted or NOT?")); +CS_T s_csERROR_G65SubProg_Error = _DEFCS(_CSV(11436), + _CHINESE("调用的子程序号小于或等于0(提醒您注意:子程序号应大于0,否则请使用子程序名)") + _ENGLISH("The number of subprograme is less than or equal 0(Attention: The number of subprograme must be more than 0, or please use the subprograme's name)")); + +// 这里列出的是对于省略G地址字的情况下,由相应的地址字可以推导出的G代码列表 +// 可以省略的G地址字目前包括:G 0, 1, 2, 3, 7, 73, 74, 76, 81, 82, 83, 84, 85, 86, 87, 88, 89 +// 由m_pCodeGenerator->m_ModalData.m_GeneralMotion.m_nGNo标示,下表仅仅用于检查有效性。 +const int CBlockMaker::m_MatchGScope[][32] = +{ + {TK_ADR_FIRST, -1}, + {TK_ADR_A, -1}, + {TK_ADR_B, -1}, + {TK_ADR_C, -1}, + {TK_ADR_D, -1}, + {TK_ADR_E, -1}, + {TK_ADR_F, -1}, + {TK_ADR_G, -1}, + {TK_ADR_H, 7, -1}, + {TK_ADR_I, 2, 3, 76, -1}, + {TK_ADR_J, 2, 3, 76, -1}, + {TK_ADR_K, 2, 3, -1}, + {TK_ADR_L, -1}, + {TK_ADR_M, -1}, + {TK_ADR_N, -1}, + {TK_ADR_O, -1}, + {TK_ADR_P, 74, 76, 82, 84, 89, -1}, + {TK_ADR_Q, 73, 83, -1}, + {TK_ADR_R, 2, 3, -1}, + {TK_ADR_S, -1}, + {TK_ADR_T, -1}, + {TK_ADR_U, -1}, + {TK_ADR_V, -1}, + {TK_ADR_W, -1}, + {TK_ADR_X, 0, 1, 2, 3, 7, 73, 74, 76, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1}, + {TK_ADR_Y, 0, 1, 2, 3, 7, 73, 74, 76, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1}, + {TK_ADR_Z, 0, 1, 2, 3, 7, 73, 74, 76, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1}, + {TK_ADR_FX, -1}, + {TK_ADR_FY, -1}, + {TK_ADR_FZ, -1}, + {TK_ADR_LEVEL, -1}, + {TK_ADR_LX, -1}, + {TK_ADR_LY, -1}, + {TK_ADR_LZ, -1}, + {TK_ADR_MSG, -1}, + {TK_ADR_PLC, -1}, + {TK_ADR_PX, -1}, + {TK_ADR_PY, -1}, + {TK_ADR_PZ, -1}, + {TK_ADR_SYNCPOS, -1}, + {TK_ADR_LAST, -1}, +}; + +// Note:为了提高查找的效率,最常用的规则放在最前边! +const CBlockMaker::rule_t CBlockMaker::m_RuleList_Pre[] = +{ + // token, value, func + {TK_ADR_G, 53, &G53}, + {TK_ADR_G, 54, &SelectWorkCoor}, + {TK_ADR_G, 55, &SelectWorkCoor}, + {TK_ADR_G, 56, &SelectWorkCoor}, + {TK_ADR_G, 57, &SelectWorkCoor}, + {TK_ADR_G, 58, &SelectWorkCoor}, + {TK_ADR_G, 59, &SelectWorkCoor}, + {TK_ADR_G, 68, &G68}, + {TK_ADR_G, 69, &G69}, + + {TK_ADR_G, 90, &G90_G91}, + {TK_ADR_G, 91, &G90_G91}, + + {TK_ADR_G, 17, &G17_G18_G19}, + {TK_ADR_G, 18, &G17_G18_G19}, + {TK_ADR_G, 19, &G17_G18_G19}, + + {TK_ADR_G, 20, &G20_G21_G70_G71}, + {TK_ADR_G, 21, &G20_G21_G70_G71}, + {TK_ADR_G, 70, &G20_G21_G70_G71}, + {TK_ADR_G, 71, &G20_G21_G70_G71}, + + {TK_ADR_S, -1, &SpindleRev}, + {TK_ADR_F, -1, &FeedRate}, + + {TK_ADR_G, 98, &G98_G99}, + {TK_ADR_G, 99, &G98_G99}, + + {TK_ADR_G, 40, &G40}, + {TK_ADR_G, 41, &G41_G42}, + {TK_ADR_G, 42, &G41_G42}, + {TK_ADR_G, 43, &G43_G44}, + {TK_ADR_G, 44, &G43_G44}, + {TK_ADR_G, 49, &G49}, + + {TK_ADR_G, 50, &G50}, + {TK_ADR_G, 51, &G51}, + {TK_ADR_G, 50.1, &G50_1}, + {TK_ADR_G, 51.1, &G51_1}, + + {TK_ADR_G, 92, &G92}, + {TK_ADR_G, 992, &G992}, + {TK_ADR_G, 921, &G921}, + {TK_ADR_G, 922, &G922}, + {TK_ADR_G, 923, &G923}, + + {TK_ADR_G, 905, &G905}, + {TK_ADR_G, 907, &G907}, + {TK_ADR_G, 908, &G908}, + {TK_ADR_M, 0, &M0_M1}, + {TK_ADR_M, 1, &M0_M1}, + {TK_ADR_M, 2, &M2_M30}, + {TK_ADR_M, 3, &M3_M4_M5}, + {TK_ADR_M, 4, &M3_M4_M5}, + {TK_ADR_M, 5, &M3_M4_M5}, + {TK_ADR_M, 801, &M801}, + {TK_ADR_M, 802, &M802}, + {TK_ADR_M, 901, &M901}, + {TK_ADR_M, 902, &M902}, + {TK_ADR_M, 903, &M903}, + {TK_ADR_M, 904, &M904_M905}, + {TK_ADR_M, 905, &M904_M905}, +}; + +const CBlockMaker::rule_t CBlockMaker::m_RuleList_Normal[] = +{ + // token, value, func + {TK_ADR_G, 1, &G0_G1}, + {TK_ADR_G, 0, &G0_G1}, + {TK_ADR_G, 2, &G2_G3}, + {TK_ADR_G, 3, &G2_G3}, + {TK_ADR_G, 4, &G4}, + {TK_ADR_G, 7, &G7}, + {TK_ADR_G, 28, &G28}, + {TK_ADR_G, 65, &G65_M98}, + + {TK_ADR_G, 34, &G34_G36}, + {TK_ADR_G, 35, &G35}, + {TK_ADR_G, 36, &G34_G36}, + {TK_ADR_G, 37, &G37}, + + {TK_ADR_G, 73, &FixedCycle}, + {TK_ADR_G, 74, &FixedCycle}, + {TK_ADR_G, 75, &FixedCycle}, + {TK_ADR_G, 76, &FixedCycle}, + {TK_ADR_G, 77, &FixedCycle}, + {TK_ADR_G, 78, &FixedCycle}, + {TK_ADR_G, 79, &FixedCycle}, + {TK_ADR_G, 80, &G80}, + {TK_ADR_G, 81, &FixedCycle}, + {TK_ADR_G, 82, &FixedCycle}, + {TK_ADR_G, 83, &FixedCycle}, + {TK_ADR_G, 84, &FixedCycle}, + {TK_ADR_G, 85, &FixedCycle}, + {TK_ADR_G, 86, &FixedCycle}, + {TK_ADR_G, 87, &FixedCycle}, + {TK_ADR_G, 88, &FixedCycle}, + {TK_ADR_G, 89, &FixedCycle}, + + {TK_ADR_G, 903, &G903}, + {TK_ADR_G, 904, &G904}, + {TK_ADR_G, 906, &G906}, + {TK_ADR_G, 925, &G925_G926}, + {TK_ADR_G, 926, &G925_G926}, + {TK_ADR_G, 927, &G927}, + {TK_ADR_SYNCPOS, -1, &SyncPos}, + {TK_ADR_G, 9, &G9}, + + {TK_ADR_COMMENT, 0, &Comment}, +}; + +const CBlockMaker::rule_t CBlockMaker::m_RuleList_Post[] = +{ + {TK_ADR_X, -1, &MatchG}, + {TK_ADR_Y, -1, &MatchG}, + {TK_ADR_Z, -1, &MatchG}, + {TK_ADR_T, -1, &M6_T}, + {TK_ADR_H, -1, &Rule_Error}, + {TK_ADR_I, -1, &MatchG}, + {TK_ADR_J, -1, &MatchG}, + {TK_ADR_K, -1, &MatchG}, + {TK_ADR_L, -1, &Rule_Error}, + {TK_ADR_LX, -1, &Rule_Error}, + {TK_ADR_LY, -1, &Rule_Error}, + {TK_ADR_LZ, -1, &Rule_Error}, + {TK_ADR_M, 6, &M6_T}, + {TK_ADR_M, 17, &M17_M99}, + {TK_ADR_M, 98, &G65_M98}, + {TK_ADR_M, 99, &M17_M99}, + {TK_ADR_M, 30, &M2_M30}, + {TK_ADR_MSG, -1, &Rule_Error}, + {TK_ADR_P, -1, &MatchG}, + {TK_ADR_PX, -1, &Rule_Error}, + {TK_ADR_PY, -1, &Rule_Error}, + {TK_ADR_PZ, -1, &Rule_Error}, + {TK_ADR_Q, -1, &MatchG}, + {TK_ADR_R, -1, &MatchG}, + {TK_ADR_D, -1, &Rule_Error}, + {TK_ADR_FX, -1, &Rule_Error}, + {TK_ADR_FY, -1, &Rule_Error}, + {TK_ADR_FZ, -1, &Rule_Error}, + {TK_ADR_PLC, -1, &Ignore}, + {TK_ADR_LEVEL, -1, &Ignore}, + {TK_ADR_A, -1, &Ignore}, + {TK_ADR_B, -1, &Ignore}, + {TK_ADR_C, -1, &Ignore}, + {TK_ADR_U, -1, &Ignore}, + {TK_ADR_V, -1, &Ignore}, + {TK_ADR_W, -1, &Ignore}, + + {TK_ADR_G, -1, &GUnknown}, + {TK_ADR_M, -1, &MUnknown}, + {TK_ADR_COMMENT, -1, &MatchComment}, +}; + +CBlockMaker::CBlockMaker() +: m_ptCurPosOrig(0.f, 0.f, 0.f) +, m_ptDestPosOrig(0.f, 0.f, 0.f) +, m_ptCurPos(0.f, 0.f, 0.f) +, m_ptDestPos(0.f, 0.f, 0.f) +{ + m_nUnit = 1.0; + m_nRadiusTolerance = 1.f; + m_nPreRuleNum = _countof(m_RuleList_Pre); + m_nNormalRuleNum = _countof(m_RuleList_Normal); + m_nPostRuleNum = _countof(m_RuleList_Post); +} + +CBlockMaker::~CBlockMaker() +{ + for (INT_PTR _i = 0, _Size = m_arrPTransform.GetSize(); _i < _Size; ++_i) + delete m_arrPTransform[_i]; + + m_arrPTransform.RemoveAll(); + m_mapSubIntProgIndex.RemoveAll(); + m_mapSubStrProgIndex.RemoveAll(); +} + +void CBlockMaker::Reset() +{ + m_Parser.Reset(); + m_ModalData.Reset(); +} + +const char* CBlockMaker::GetTokenAlias(token_t nToken_) const +{ + return m_Parser.m_TokenAnalyser.GetTokenAlias(nToken_); +} + +void CBlockMaker::ReadCode() +{ + m_Parser.m_Entities.Reset(); + + do + { + if (m_Parser.NextToken() == TK_EOF) + break; + + m_Parser.Statement(); + } while (m_Parser.m_Entities.GetCount() == 0); + + if (m_Parser.m_Entities.GetCount() > 0) + { + AnalyseEntities(); + } +} + +void CBlockMaker::AnalyseEntities() +{ + do + { + AnalyseCurrentEntity(); + } while(m_Parser.m_Entities.MoveForWard()); +} + +void CBlockMaker::AnalyseCurrentEntity() +{ + const rule_t* _pRule = NULL; + + CTaggedEntity& _CurEntity = m_Parser.m_Entities.GetCurrentEntity(); + int _nSize = _CurEntity.GetCount(); + ASSERT(_nSize > 0); + + int _i; + + // pre rule + for (_i = 0; _i < _nSize; _i++) + { + if (_CurEntity[_i].m_bDeleted) + continue; + + _pRule = GetRule_Pre(_CurEntity[_i].m_nToken, _CurEntity[_i].m_nValue); + if (_pRule) + (this->*_pRule->pFunction) (&_CurEntity[_i]); + } + + // normal rule + for (_i = 0; _i < _nSize; _i++) + { + if (_CurEntity[_i].m_bDeleted) + continue; + + _pRule = GetRule_Normal(_CurEntity[_i].m_nToken, _CurEntity[_i].m_nValue); + if (_pRule) + (this->*_pRule->pFunction) (&_CurEntity[_i]); + } + + // post rule + for (_i = 0; _i < _nSize; _i++) + { + if (_CurEntity[_i].m_bDeleted) + continue; + + _pRule = GetRule_Post(_CurEntity[_i].m_nToken, _CurEntity[_i].m_nValue); + if (_pRule) + (this->*_pRule->pFunction)(&_CurEntity[_i]); + else + { + m_strTemp.Format(_GETCS(s_szERROR_UNKOWN_TOKEN), + GetTokenAlias(_CurEntity[_i].m_nToken), + (int)(_CurEntity[_i].m_nValue)); + throw(m_strTemp); + } + } + + return; +} + +// Forward rules +void CBlockMaker::G0_G1(CTaggedData* pTaggedData_) +{ + if (TK_ADR_G == pTaggedData_->m_nToken) + { + //m_ModalData.m_nGNumber用来区分G0 G1 --- 吴阳明 2010.3.19 + m_ModalData.m_nGNumber = (int)pTaggedData_->m_nValue; + MatchTaggedData(TK_ADR_G, m_ModalData.m_nGNumber); + } + + //获取目标位置--- 吴阳明 2010.3.19 + RetrieveDestPosition(); + + //存取G00及G01所需的凸度、进给速率、平面、终点位置,直线进给凸度为零--- 吴阳明 2010.3.19 + //用CCvtNode来存储相关信息,并压入到ListUnits中去 wudian 2010.07.20 + cvt::CCvtNode* _pNode = new cvt::CCvtNode; + _pNode->m_nBulge = 0.0; + _pNode->m_nPlane = m_ModalData.m_nPlane; + _pNode->m_ptPos.Set(m_ptDestPos.x, m_ptDestPos.y, m_ptDestPos.z); + //用bIsG00来区分G01和G00 --- 吴阳明 2010.3.19 + if (m_ModalData.m_nGNumber == 0) + _pNode->m_bIsG00 = true; + else + _pNode->m_bIsG00 = false; + ListUnits.push_back(_pNode); + + //将终点设为新的起点 wudian 2010.07.20 + m_ptCurPosOrig = m_ptDestPosOrig; + m_ptCurPos = m_ptDestPos; + return; +} + +//圆弧插补。 wudian 2010.07.20 +void CBlockMaker::G2_G3(CTaggedData* pTaggedData_) +{ + //断言 wudian 2010.07.20. + ASSERT(pTaggedData_ != NULL); + + //区分G2还是G3,标记该代码已被使用过。 wudian 2010.07.20. + if (TK_ADR_G == pTaggedData_->m_nToken) + { + m_ModalData.m_nGNumber = (int) pTaggedData_->m_nValue; + MatchTaggedData(TK_ADR_G, m_ModalData.m_nGNumber); + } + + //获得终点坐标。 wudian 2010.07.20. + RetrieveDestPosition(); + + //圆心 wudian 2010.07.20. + DPOINT3 _ptCenter = RetrieveArcParameters(); + //如果是2,就是顺时针旋转。不是2,就是逆时针。 wudian 2010.07.20. + bool _bClock = (m_ModalData.m_nGNumber == 2); + //计算起点到终点,转过的角度。 wudian 2010.07.20. + double _nAngle = CalAngle3D(m_ptCurPos, m_ptDestPos, _ptCenter, m_ModalData.m_nPlane, _bClock); // 扫过的角 + + // 起始角 + int _nAxisX; + int _nAxisY; + //把左右轴标记出来 wudian 2010.07.20. + GetLeftRightAxis(m_ModalData.m_nPlane, _nAxisX, _nAxisY); + DPOINT2 _vec; + _vec.x = m_ptCurPos[_nAxisX] - _ptCenter[_nAxisX]; + _vec.y = m_ptCurPos[_nAxisY] - _ptCenter[_nAxisY]; + //起点与圆心的连线,与X轴正方向德夹角。 wudian 2010.07.20. + double _nStartAngle = _compute_angle(_vec.x, _vec.y); + + if (DOUBLE_LE(fabs(_nAngle), c_nPIE)) + { + //优弧保持原状处理 + cvt::CCvtNode* _pNode = new cvt::CCvtNode; + + _pNode->m_nBulge = tan(_nAngle / 4.f); + _pNode->m_nPlane = m_ModalData.m_nPlane; + _pNode->m_ptPos.Set(m_ptDestPos.x, m_ptDestPos.y, m_ptDestPos.z); + _pNode->m_bIsG00 = false; + + ListUnits.push_back(_pNode); + } + else + { + //劣弧分成圆心角相等的两段圆弧处理 + double _nAngle2 = _nAngle / 2.f; + + cvt::CCvtNode* _pNode1 = new cvt::CCvtNode; + cvt::CCvtNode* _pNode2 = new cvt::CCvtNode; + + _pNode1->m_nBulge = _pNode2->m_nBulge = tan(_nAngle2 / 4.f); + _pNode1->m_nPlane = _pNode2->m_nPlane = m_ModalData.m_nPlane; + _pNode1->m_bIsG00 = _pNode2->m_bIsG00 = false; + + DPOINT3 _ptMidArc = _ptCenter; + _ptMidArc[_nAxisX] = _ptCenter[_nAxisX] + m_ModalData.m_nArcRadius * cos(_nStartAngle + _nAngle2); + _ptMidArc[_nAxisY] = _ptCenter[_nAxisY] + m_ModalData.m_nArcRadius * sin(_nStartAngle + _nAngle2); + + _pNode1->m_ptPos.Set(_ptMidArc.x, _ptMidArc.y, _ptMidArc.z); + _pNode2->m_ptPos.Set(m_ptDestPos.x, m_ptDestPos.y ,m_ptDestPos.z); + + ListUnits.push_back(_pNode1); + ListUnits.push_back(_pNode2); + } + + m_ptCurPosOrig = m_ptDestPosOrig; + m_ptCurPos = m_ptDestPos; + return; +} + +// Description: +// get revise arc's center to fit the start and end point. +// +// Parameters: +// in: +// ptStart_ start point +// ptEnd_ end point +// ptCenter_ old center point +// pltype_ plane +// nRadiusTolerance_ arc radius tolerance +// Note: +// Exceptions: +// Algorithm: +// use projection algorithm: +//获得弧的圆心。 wudian 2010.07.20. +DPOINT3 CBlockMaker::_get_revise_arc_center_( + const DPOINT3& ptStart_, + const DPOINT3& ptEnd_, + const DPOINT3& ptCenter_) +{ + int _nLeftAxis; + int _nRightAxis; + GetLeftRightAxis(m_ModalData.m_nPlane, _nLeftAxis, _nRightAxis); + + double _nXe = ptEnd_[_nLeftAxis]; + double _nYe = ptEnd_[_nRightAxis]; + double _nXs = ptStart_[_nLeftAxis]; + double _nYs = ptStart_[_nRightAxis]; + double _nXc = ptCenter_[_nLeftAxis]; + double _nYc = ptCenter_[_nRightAxis]; + double _nXo = (_nXe + _nXs) / 2.0; //中点 + double _nYo = (_nYe + _nYs) / 2.0; + + double _nD = powersum2(_nXs - _nXe, _nYs - _nYe); + if (DOUBLE_EQU_ZERO(_nD)) //起点和终点重合,直接返回,不进行修正 + return ptCenter_; + + ///////////////////////////////////////////////////////////////////////////////// + // 圆弧编程误差分析: + // 如果起点到圆心的距离和终点到圆心的距离大于最大误差,则报错,退出。 + double _nRadiusEnd = sqrt(powersum2(fabs(_nXs - _nXc), fabs(_nYs - _nYc))); + double _nRadiusStart = sqrt(powersum2(fabs(_nXe - _nXc), fabs(_nYe - _nYc))); + if (m_nRadiusTolerance > 0.0 + && fabs(_nRadiusEnd - _nRadiusStart) > m_nRadiusTolerance) + { + throw(_GETCS(s_szERROR_ARC_RADIUSERROR)); + } + + // 误差分析结束 + ////////////////////////////////////////////////////////////////////////// + + // 重新计算圆弧圆心,即原来的圆心到起点和终点的中垂线上的垂足: + // algorithm1: + double _nXret1 = 0.0; + double _nYret1 = 0.0; + if (DOUBLE_EQU(_nXe, _nXs)) + { + _nXret1 = _nXc; + _nYret1 = _nYo; + } + else if (DOUBLE_EQU(_nYe, _nYs)) + { + _nXret1 = _nXo; + _nYret1 = _nYc; + } + else + { + double _nK1 = (_nYe - _nYs) / (_nXe - _nXs); + double _nK2 = -1.0 / _nK1; + _nXret1 = (_nK1 * _nXc - _nK2 * _nXo - _nYc + _nYo) / (_nK1 - _nK2); + _nYret1 = _nK1 * (_nXret1 - _nXc) + _nYc; + } + + // // algorithm2: + // double _nTNumerator = 0.5 * (_nXo - _nXc) * (_nYe - _nYs) + // + 0.5 * (_nYo - _nYc) * (_nXe - _nXs); + // double _nT = _nTNumerator / (_nD / 4.0); + // double _nXret2 = _nXo - (_nYe - _nYs) * _nT; + // double _nYret2 = _nYo - (_nXe - _nXs) * _nT; + // + // ASSERT(_nXret1 == _nXret2 && _nYret1 == _nYret2); + + DPOINT3 _ptCenter = ptCenter_; + _ptCenter[_nLeftAxis] = (double)_nXret1; + _ptCenter[_nRightAxis] = (double)_nYret1; + return _ptCenter; +} + + +// Description: +// Calcaulate the arc's center with the radius and start/end point. +// Parameters: +// ptStart_ +// ptEnd_ +// ptCenter_ +// nRadius_: can be negative or positive +// negative -- large arc +// positive -- little arc +// pltype_ +// nDirection_ :1, clockwise(NCFGARCINTERPCW), -1, anti-clockwise(NCFGARCINTERPCCW) +// bKnown_: when the nRadius_' sign is not correct for top means, and +// the initial center has been given. +// nRadiusTolerance_ arc radius tolerance +// Note: +// Exceptions: +// Algorithm: +DPOINT3 CBlockMaker::_get_arc_center_by_radius( + const DPOINT3& ptStart_, + const DPOINT3& ptEnd_, + const DPOINT3& ptCenter_, + double nRadius_) +{ + DPOINT3 _ptCenter = ptCenter_; + if (fabs(nRadius_) < 0.001) + { + throw(_GETCS(s_szERROR_ARC_RADIUS_TOO_SMALL)); + } + + int _nLeftAxis = -1; + int _nRightAxis = -1; + GetLeftRightAxis(m_ModalData.m_nPlane, _nLeftAxis, _nRightAxis); + + for (int i = 0; i < 3; i++) + { + if (i != _nLeftAxis + && i != _nRightAxis) + { + _ptCenter[i] = ptStart_[i]; + } + } + + //if (ptStart_ == ptEnd_) + //{ + // if (bKnown_) + // { + // //整圆 + // return _ptCenter; + // } + // else + // { + // //摘自FANUC连接说明书(功能)(上) + // //如果X、Y、Z全部省略,终点和起点为同一位置, + // //而又使用了R时,这样,就是指定了0度的圆弧,实际上刀具不移动。 + // return ptEnd_; + // } + //} + + DPOINT2 _c0(ptCenter_[_nLeftAxis], ptCenter_[_nRightAxis]); + DPOINT2 _start(ptStart_[_nLeftAxis], ptStart_[_nRightAxis]); + DPOINT2 _end(ptEnd_[_nLeftAxis], ptEnd_[_nRightAxis]); + DPOINT2 _center; + + DPOINT3 _vec(ptStart_.x - ptEnd_.x, ptStart_.y - ptEnd_.y, ptStart_.z - ptEnd_.z); + double _nDistFromStartToEnd = _vec.GetLength(); + if (DOUBLE_GE(_nDistFromStartToEnd, fabs(nRadius_) * 2.f)) + { + if (fabs(_nDistFromStartToEnd - fabs(nRadius_) * 2.0) < m_nRadiusTolerance) // 认为是半圆 + { + _center.x = (_start.x + _end.x) / 2.f; + _center.y = (_start.y + _end.y) / 2.f; + } + else + { + throw(_GETCS(s_szERROR_ARC_RADIUSERROR)); + } + } + else + { + DPOINT2 _c1, _c2; + int _select = -1; + if (DOUBLE_EQU(_start.x, _end.x)) + { + _c1.y = _c2.y = (_start.y + _end.y) / 2.f; + double _nTemp = power(nRadius_) - power(_start.y - _end.y)/4.f; + if (DOUBLE_EQU_ZERO(_nTemp)) + _nTemp = 0.0; + _nTemp = sqrt(_nTemp); + _c1.x = _start.x - _nTemp; + _c2.x = _start.x + _nTemp; + } + else if (DOUBLE_EQU(_start.y, _end.y)) + { + _c1.x = _c2.x = (_start.x + _end.x) / 2.f; + double _nTemp = power(nRadius_) - power(_start.x - _end.x)/4.f; + if (DOUBLE_EQU_ZERO(_nTemp)) + _nTemp = 0.0; + _nTemp = sqrt(_nTemp); + _c1.y = _start.y - _nTemp; + _c2.y = _start.y + _nTemp; + } + else + { + GetCenter(_start, _end, nRadius_, _c1, _c2); + } + // end compute + + ////选择圆心 + //if (bKnown_) //对圆心重新修正时 + //{ + // if (power(_c0.x -_c2.x) + power(_c0.y -_c2.y) + // <= power(_c0.x -_c1.x) + power(_c0.y -_c1.y)) + // { + // _select = 2; + // } + // else + // { + // _select = 1; + // } + //} // Update center + //else //选择圆心 + { + double _sita11, _sita12, _sita21, _sita22; + _sita11 = _compute_angle(_start.x - _c1.x, _start.y - _c1.y); + _sita12 = _compute_angle(_end.x - _c1.x, _end.y - _c1.y); + _sita21 = _compute_angle(_start.x - _c2.x, _start.y - _c2.y); + _sita22 = _compute_angle(_end.x - _c2.x, _end.y - _c2.y); + + if (m_ModalData.m_nGNumber == 3) + { + if (_sita12 < _sita11) + _sita12 += c_nPIE * 2.0; + + if (nRadius_ > 0) + { + if (_sita12 - _sita11 < c_nPIE) + { + _select = 1; + } + else + { + _select = 2; + } + } + else + { + if (_sita12 - _sita11 > c_nPIE) + { + _select = 1; + } + else + { + _select = 2; + } + } + } // end NCFGARCINTERPCCW + else// NCFGARCINTERPCW + { + if (_sita12 > _sita11) + _sita12 -= c_nPIE * 2.0; + + if (nRadius_ > 0) + { + if (_sita11 - _sita12 < c_nPIE) + { + _select = 1; + } + else + { + _select = 2; + } + } + else + { + if (_sita11 - _sita12 > c_nPIE) + { + _select = 1; + } + else + { + _select = 2; + } + } + }// end NCFGARCINTERPCW + } + switch (_select) + { + case 1: + _center.x = _c1.x; + _center.y = _c1.y; + break; + case 2: + _center.x = _c2.x; + _center.y = _c2.y; + break; + default: + ASSERT(false); + } + } + + _ptCenter[_nLeftAxis] = _center.x; + _ptCenter[_nRightAxis] = _center.y; + + return _ptCenter; +} + +// 填充圆心,半径,螺旋线等参数。 +DPOINT3 CBlockMaker::RetrieveArcParameters() +{ + const token_t _tkTagTokenIJK[] = + { + TK_ADR_I, + TK_ADR_J, + TK_ADR_K, + }; + + int _nAxisX = -1; + int _nAxisY = -1; + GetLeftRightAxis(m_ModalData.m_nPlane, _nAxisX, _nAxisY); + + int _nIndex = -1; + if (SearchTaggedData(&_nIndex, TK_ADR_R)) + { + m_ModalData.m_bArcIJKMode = false; + } + else if (SearchTaggedData(&_nIndex, _tkTagTokenIJK[_nAxisX]) + || SearchTaggedData(&_nIndex, _tkTagTokenIJK[_nAxisY])) + { + m_ModalData.m_bArcIJKMode = true; + } + + INT_PTR _i, _size; + + // Check m_pCodeGenerator->m_ModalData.m_ptZoomAspect, axis x must be same as y + for (_i = 0, _size = m_arrPTransform.GetSize(); _i < _size; ++_i) + { + CTransform* _pTrans = m_arrPTransform[_i]; + if (_pTrans->m_nTransformType == CTransform::TF_ZOOM) + { + DPOINT3 _nxAspect = ((CZoomTransform*)_pTrans)->m_ptAspect; + if (!DOUBLE_EQU(_nxAspect[_nAxisX], _nxAspect[_nAxisY])) + throw(_GETCS(s_szERROR_INCORRECT_ASPECT_FOR_RADIUS)); + } + } + + // Get circle center position + DPOINT3 _ptCurPos = m_ptCurPosOrig; + DPOINT3 _ptDestPos = m_ptDestPosOrig; + DPOINT3 _ptCenter; + if (m_ModalData.m_bArcIJKMode) + { + //[问题提出]: 参数"圆弧IJK增量方式有效"设置为否, + // 刀路中的圆弧指令后无IJK参数或该平面上仅有一个参数时如G2 Y100 J50, + // 提示“IJK参数错误。请修改参数!”,该提示不清楚明,让人难以理解。 + //[修改方案]: 默认当前点为圆心。 + // --- 焦逸 2011 1 17 + m_ModalData.m_ptArcCenter = m_ptCurPosOrig; + + // G2/3 X_Y_Z_I_J_K_F_, Find circle center position + DPOINT3 _nxArcCenter = m_ptCurPos; + for (int _axis = 0; _axis < 3; _axis++) + { + if (SearchTaggedData(&_nIndex, _tkTagTokenIJK[_axis])) + { + MatchTaggedData(_nIndex, _tkTagTokenIJK[_axis]); + double _nTemp = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + _nTemp = TranslateToMM(_nTemp, _axis); // W.Coor. + + if (_nAxisX == _axis || _nAxisY == _axis) + { + //if (!_pParamter->m_bIJKIncreaseMode) // Absolute Coor. + // //_nxArcCenter[_axis] = m_pCodeGenerator->WorkCoorToMachineCoor(_nTemp, _axis); + // _nxArcCenter[_axis] = _nTemp; + //else + _nxArcCenter[_axis] = _ptCurPos[_axis] + (double)_nTemp; + } + else // Circle center is equal to start position, whatever what is Spiral Depth + { + throw(_GETCS(s_szERROR_SPIRALPITCH)); // K is SpiralPitch, don't zoom it + } + } + else // if omitted + { + if (_nAxisX == _axis || _nAxisY == _axis) + { + if (!m_ModalData.m_bIJKIncreaseMode) + { + double _nTemp = m_ModalData.m_ptArcCenter[_axis]; + if (IsInvalidDouble(_nTemp)) + throw(_GETCS(s_szERROR_IJK_ERROR)); + _nxArcCenter[_axis] = _nTemp; + } + } + } + } + m_ModalData.m_ptArcCenter = _nxArcCenter; + + DPOINT3 _ptTemp; + _Transform(_ptCurPos, _ptTemp); + _ptCurPos = _ptTemp; + _Transform(_nxArcCenter, _ptTemp); + _ptCenter = _ptTemp; + _Transform(_ptDestPos, _ptTemp); + _ptDestPos = _ptTemp; + + // 圆心编程时,由于精度的原因,可能造成起点到圆心的距离 + // 和终点到圆心的距离不等, + // 为防止该情况出现,需要重新计算圆心 + try + { + // Use the position after transform + _ptCenter= _get_revise_arc_center_( + _ptCurPos, + _ptDestPos, + _ptCenter); + } + catch(LPCTSTR pszErr_) + { + throw(pszErr_); + } + } + else // G2/3 X_Y_Z_R_F_ + { + // If NO R existed + double _nRadius = m_ModalData.m_nArcRadius; + if (SearchTaggedData(&_nIndex, TK_ADR_R)) + { + MatchTaggedData(_nIndex, TK_ADR_R); + double _nRadiusTemp = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + _nRadius = (double)TranslateToMM(_nRadiusTemp, 0); //转换单位(英制,公制,不能是度) + m_ModalData.m_nArcRadius = _nRadius; + } + + //半径编程,需要计算圆心 + DPOINT3 _nxCenter = _get_arc_center_by_radius( + _ptCurPos, + _ptDestPos, + _nxCenter, + _nRadius); + + for (int _axis = 0; _axis < 3; _axis++) + { + if (_nAxisX != _axis && _nAxisY != _axis + && SearchTaggedData(&_nIndex, _tkTagTokenIJK[_axis])) + { + MatchTaggedData(_nIndex, _tkTagTokenIJK[_axis]); + throw(_GETCS(s_szERROR_SPIRALPITCH)); + } + } + + DPOINT3 _ptTemp; + _Transform(_ptCurPos, _ptTemp); + _ptCurPos = _ptTemp; + _Transform(_nxCenter, _ptTemp); + _ptCenter = _ptTemp; + _Transform(_ptDestPos, _ptTemp); + _ptDestPos = _ptTemp; + } + CMirrorTransform* _pMirrorTrans = NULL; + for (_i = 0, _size = m_arrPTransform.GetSize(); _i < _size; ++_i) + { + if (m_arrPTransform[_i]->m_nTransformType == CTransform::TF_MIRROR) + { + ASSERT(!_pMirrorTrans); + _pMirrorTrans = (CMirrorTransform*)m_arrPTransform[_i]; +#ifdef NDEBUG + break; +#endif + } + } + + if (_pMirrorTrans) + { + BOOL _bRevser = _pMirrorTrans->m_bxMirror[_nAxisX] ^ _pMirrorTrans->m_bxMirror[_nAxisY]; + if (_bRevser) + m_ModalData.m_nGNumber = (m_ModalData.m_nGNumber == 2) ? 2 : 3; + } + + DPOINT2 _vec(_ptCenter[_nAxisX] - m_ptCurPos[_nAxisX], _ptCenter[_nAxisY] - m_ptCurPos[_nAxisY]); + m_ModalData.m_nArcRadius = (double)_vec.GetLength(); + m_ModalData.m_ptArcCenter = _ptCenter; + return _ptCenter; +} + +const CBlockMaker::rule_t* CBlockMaker::GetRule_Pre(token_t tkAddr_, double nTagValue_) +{ + for (int _i = 0; _i < m_nPreRuleNum; _i++) + { + if (m_RuleList_Pre[_i].tkAddr == tkAddr_) + { + if (m_RuleList_Pre[_i].nTagValue == -1 + || m_RuleList_Pre[_i].nTagValue == nTagValue_) + { + return &m_RuleList_Pre[_i]; + } + } + } + + return NULL; +} + +const CBlockMaker::rule_t* CBlockMaker::GetRule_Normal(token_t tkAddr_, double nTagValue_) +{ + for (int _i = 0; _i < m_nNormalRuleNum; _i++) + { + if (m_RuleList_Normal[_i].tkAddr == tkAddr_) + { + if (m_RuleList_Normal[_i].nTagValue == -1 + || m_RuleList_Normal[_i].nTagValue == nTagValue_) + { + return &m_RuleList_Normal[_i]; + } + } + } + + return NULL; +} + +const CBlockMaker::rule_t* CBlockMaker::GetRule_Post(token_t tkAddr_, double nTagValue_) +{ + for (int _i = 0; _i < m_nPostRuleNum; _i++) + { + if (m_RuleList_Post[_i].tkAddr == tkAddr_) + { + if (m_RuleList_Post[_i].nTagValue == -1 + || m_RuleList_Post[_i].nTagValue == nTagValue_) + { + return &m_RuleList_Post[_i]; + } + } + } + + return NULL; +} + +void CBlockMaker::MatchG(CTaggedData* pTaggedData_) +{ + int _nGNo = m_ModalData.m_nGNumber; + int _nIndex = pTaggedData_->m_nToken - TK_ADR_FIRST; + ASSERT(m_MatchGScope[_nIndex][0] == pTaggedData_->m_nToken); + bool _bValid = false; + for (const int*_pMatchNos = &m_MatchGScope[_nIndex][1]; + *_pMatchNos != -1; + _pMatchNos++) + { + if (*_pMatchNos == _nGNo) + { + _bValid = true; + break; + } + } + + if (!_bValid) + { + throw(_GETCS(s_szERROR_MATCH_BACKWARDRULE)); + } + + const rule_t* _pRule = GetRule(TK_ADR_G, _nGNo); + if (_pRule) + { + (this->*_pRule->pFunction) (pTaggedData_); + } + else + { + throw(_GETCS(s_szERROR_MATCH_BACKWARDRULE)); + } +} + +void CBlockMaker::Ignore(CTaggedData* pTaggedData_) +{ + TRACE("Ignore instruction:%s%f", + GetTokenAlias(pTaggedData_->m_nToken), + pTaggedData_->m_nValue); +} + +//取出文件中的进给速度赋值给指令分析对象的进给速度成员 +void CBlockMaker::FeedRate(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_F, c_nINVALID_DOUBLE); + m_ModalData.m_nProgramSpeed = pTaggedData_->m_nValue; + + cvt::CCvtFeedRat* _pFeedRat = new cvt::CCvtFeedRat; + _pFeedRat->m_nFeedRat = pTaggedData_->m_nValue; + + ListUnits.push_back(_pFeedRat); + return; +} + +//确定是绝对值编程还是相对值编程 wangwenbo 2010.03.22 +void CBlockMaker::G90_G91(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int)pTaggedData_->m_nValue; + ASSERT(_nGNumber == 90 || _nGNumber == 91); + m_ModalData.m_bAbsolute = _nGNumber == 90 ? true : false; + MatchTaggedData(TK_ADR_G, _nGNumber); +} + +//确定加工平面信息 wangwenbo 2010.03.22 +void CBlockMaker::G17_G18_G19(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int) pTaggedData_->m_nValue; + ASSERT(_nGNumber == 17 || _nGNumber == 18 || _nGNumber == 19); + + //平面的确定 + switch (_nGNumber) + { + case 17: + m_ModalData.m_nPlane = cvt::plane_xy; + break; + + case 18: + m_ModalData.m_nPlane = cvt::plane_zx; + break; + + case 19: + m_ModalData.m_nPlane = cvt::plane_yz; + break; + + default: + ASSERT(false); + break; + } + + MatchTaggedData(TK_ADR_G, _nGNumber); +} + +//确定加工轮廓度量 wangwenbo 2010.03.22 +void CBlockMaker::G20_G21_G70_G71(CTaggedData* pTaggedData_) +{ + int _nGNumber = (int) pTaggedData_->m_nValue; + switch (_nGNumber) + { + case 20: + case 70: + m_ModalData.m_nUnit = 25.4f / m_nUnit; + break; + + case 21: + case 71: + m_ModalData.m_nUnit = 1.f / m_nUnit; + break; + + default: + ASSERT(false); + } + + MatchTaggedData(TK_ADR_G, _nGNumber); +} + +void CBlockMaker::M6_T(CTaggedData* pTaggedData_) +{ + ASSERT((pTaggedData_->m_nToken == TK_ADR_M && pTaggedData_->m_nValue == 6) + || pTaggedData_->m_nToken == TK_ADR_T); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (SearchTaggedData(&_nIndex, TK_ADR_M)) + MatchTaggedData(_nIndex, TK_ADR_M); + + if (SearchTaggedData(&_nIndex, TK_ADR_T)) + { + m_ModalData.m_nToolIndex = (int)m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + MatchTaggedData(_nIndex, TK_ADR_T); + } + + cvt::CCvtToolINo* _pToolNo = new cvt::CCvtToolINo; + + _pToolNo->m_nToolNo = m_ModalData.m_nToolIndex; + ListUnits.push_back(_pToolNo); + + return; +} + +void CBlockMaker::Rule_Error(CTaggedData* pTaggedData_) +{ + TRACE("Rule_Error for Token: %s\n", GetTokenAlias(pTaggedData_->m_nToken)); + m_strTemp.Format(_GETCS(s_szERROR_UNEXPECTED_TAGGEDDATA), + GetTokenAlias(pTaggedData_->m_nToken)); + throw(m_strTemp); +} + +//寻找当下的TaggedData,参数pnIndex_指向一个整数,该整数是CurrentEntity的下标值。 +//找到则返回true,否则返回false。 wudian 2010.07.20 +bool CBlockMaker::SearchTaggedData(int* pnIndex_, token_t tagToken_, + double ntagValue_/* = c_nINVALID_DOUBLE*/) const +{ + //用CTaggedEntity类型的指针,指向”当前的一个CTaggedEntity" + //解释下m_Parser.m_Entities ? wudian 2010.07.20 + const CTaggedEntity* _pTaggedEntity = &m_Parser.m_Entities.GetCurrentEntity(); + //在CTaggedEntity中找到当前对应的一个CtaggeData, + // wudian 2010.07.20 + for (int _i = 0, _nSize = _pTaggedEntity->GetCount(); _i < _nSize; _i++) + { + if ((*_pTaggedEntity)[_i].m_bDeleted) + { + continue; + } + if ((*_pTaggedEntity)[_i].m_nToken == tagToken_) + { + if (IsInvalidDouble(ntagValue_) || (*_pTaggedEntity)[_i].m_nValue == ntagValue_) + { + if (pnIndex_) + { + *pnIndex_ = _i; + } + + return true; + } + } + } + + return false; +} + +// return searched index +int CBlockMaker::MatchTaggedData(token_t tagToken_, double ntagValue_/* = c_nINVALID_DOUBLE*/) +{ + int _nIndex; + //没有找到正确的CTaggedData对象,就抛出异常 wudian 2010.07.20 + if (!SearchTaggedData(&_nIndex, tagToken_, ntagValue_)) + { + throw(_GETCS(s_szERROR_MATCH_TAGGEDDATA)); + } + + //表明该G0或G1已经被使用了 wudian 2010.07.20 + m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_bDeleted = true; + return _nIndex; +} + +void CBlockMaker::MatchTaggedData(int nIndex_, token_t tagToken_, double ntagValue_/* = c_nINVALID_DOUBLE*/) +{ + if (m_Parser.m_Entities.GetCurrentEntity()[nIndex_].m_nToken != tagToken_) + { + throw(_GETCS(s_szERROR_MATCH_TAGGEDDATA)); + } + + if (IsValidDouble(ntagValue_) + && m_Parser.m_Entities.GetCurrentEntity()[nIndex_].m_nValue != ntagValue_) + { + throw(_GETCS(s_szERROR_MATCH_TAGGEDDATA)); + } + + m_Parser.m_Entities.GetCurrentEntity()[nIndex_].m_bDeleted = true; +} + +// 转换为机械坐标 +// 区分增量非增量,补偿工件原点偏移 +// 不管初始单位是英寸、角度还是毫米,最后都转化成为毫米。 +void CBlockMaker::RetrieveDestPosition() +{ + static const token_t _tkTagToken[] = + { + TK_ADR_X, + TK_ADR_Y, + TK_ADR_Z, + }; + C_ASSERT(3 == _countof(_tkTagToken)); + + m_ptDestPosOrig = m_ptCurPosOrig; + int _nIndex; + for (int _axis = 0; _axis < 3; ++_axis) + { + if (!SearchTaggedData(&_nIndex, _tkTagToken[_axis])) + continue; + + MatchTaggedData(_nIndex, _tkTagToken[_axis]); + double _nTemp = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + _nTemp = TranslateToMM(_nTemp, _axis); + _SetOrigCoorToDestination(m_ptDestPosOrig, (double)_nTemp, _axis); + } + + _Transform(m_ptDestPosOrig, m_ptDestPos); + return; +} + +void CBlockMaker::_SetOrigCoorToDestination(DPOINT3& nxDest_, double nMCoor_, int nAxis_) +{ + ASSERT(nAxis_ >= 0 && nAxis_ <= 3); + if (!m_ModalData.m_bAbsolute) + { + nxDest_[nAxis_] = m_ptCurPosOrig[nAxis_] + nMCoor_; + return; + } + + nxDest_[nAxis_] = nMCoor_ + m_ModalData.m_ptOffset[nAxis_]; + return; +} + +double CBlockMaker::TranslateToMM(double nCoordinate_, int nAxis_) const +{ + double _nRet = m_ModalData.m_nUnit * nCoordinate_; + return _nRet; +} + +const CBlockMaker::rule_t* CBlockMaker::GetRule(token_t tkAddr_, double nTagValue_) +{ + const CBlockMaker::rule_t* _pRule = GetRule_Pre(tkAddr_, nTagValue_); + if (_pRule) + return _pRule; + _pRule = GetRule_Normal(tkAddr_, nTagValue_); + if (_pRule) + return _pRule; + _pRule = GetRule_Post(tkAddr_, nTagValue_); + return _pRule; +} + +// Go to machine zero reference through middle point for specified axis. +void CBlockMaker::G28(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 28); + UNREFERENCED_PARAMETER(pTaggedData_); + + MatchTaggedData(TK_ADR_G, 28); + + __point3 _axFind(false, false, false); + static const token_t _tkTagToken[] = { TK_ADR_X, TK_ADR_Y, TK_ADR_Z }; + cvt::CCvtG28* _pCCvtG28 = new cvt::CCvtG28; + //依次遍历各个轴进行坐标来存储中间位置 --- 吴阳明 2010.3.19 + for (int _i = 0, _nIndex; _i < _countof(_tkTagToken); _i++) + { + if (SearchTaggedData(&_nIndex, _tkTagToken[_i])) + { + _axFind[_i] = true; + //存取中间位置的各个改变坐标的值 --- 吴阳明 2010.3.19 + switch(_i) + { + case 0: + _pCCvtG28->m_ptMidPos.x = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + break; + case 1: + _pCCvtG28->m_ptMidPos.y = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + break; + case 2: + _pCCvtG28->m_ptMidPos.z = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + break; + default: + ASSERT(false); + } + } + } + //将G28存入链表中 --- 吴阳明 2010.3.19 + ListUnits.push_back(_pCCvtG28); + + RetrieveDestPosition(); + m_ptDestPos.x = m_ptDestPos.y = m_ptDestPos.z = 0.f; + m_ptCurPos = m_ptDestPos; + return; +} + +void CBlockMaker::G4(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 4); + UNREFERENCED_PARAMETER(pTaggedData_); + + MatchTaggedData(TK_ADR_G, 4); + + int _nIndex; + //获取G04暂停时间在m_Entities中所存储的位置 --- 吴阳明 2010.3.19 + if (!SearchTaggedData(&_nIndex, TK_ADR_P)) + { + m_strTemp.Format(_GETCS(s_szERROR_NOENOUGHPARAMETERS), "G04"); + throw(m_strTemp); + } + + //求取暂停时间--- 吴阳明 2010.3.19 + cvt::CCvtPause* _pCvtPause = new cvt::CCvtPause; + _pCvtPause->m_nPauseTime = (int)m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + + ListUnits.push_back(_pCvtPause); + + MatchTaggedData(_nIndex, TK_ADR_P); + + return; +} + +void CBlockMaker::G9(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 9); + UNREFERENCED_PARAMETER(pTaggedData_); + + MatchTaggedData(TK_ADR_G, 9); + return; +} + +void CBlockMaker::G40(CTaggedData* pTaggedData_) +{ + int _nGNumber = int(pTaggedData_->m_nValue); + MatchTaggedData(pTaggedData_->m_nToken, _nGNumber); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(_nGNumber == 40); + UNREFERENCED_PARAMETER(pTaggedData_); + + //存储半径补偿信息到ListUnits链表中--- 吴阳明 2010.3.19 + cvt::CCvtCutCompensate* _pCCvtCutCopmensate = new cvt::CCvtCutCompensate; + //刀补类型 --- 吴阳明 2010.3.19 + _pCCvtCutCopmensate->m_nCCType = cvt::cc_g40; + //取消刀补,刀补号设置为-1 wangwenbo 2010.03.22 + _pCCvtCutCopmensate->m_nCutNo = -1; + ListUnits.push_back(_pCCvtCutCopmensate); +} + +void CBlockMaker::G41_G42(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int) pTaggedData_->m_nValue; + ASSERT(_nGNumber == 41 || _nGNumber == 42); + + MatchTaggedData(TK_ADR_G, _nGNumber); + + // 支持不带参数的G43/G44,不带参数时生成的CCvtCutCompensate中m_nCutNo域为-1 + // 缺少参数时如何处置由调用方决定 ---- 杨开锦 2013-06-24 + int _nCutNo = -1; + int _nIndex = 0; + if (SearchTaggedData(&_nIndex, TK_ADR_D)) + { + MatchTaggedData(_nIndex, TK_ADR_D); + _nCutNo = (int)m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + } + + //根据_nGNumber的不同值进行G41和G42的存储--- 吴阳明 2010.3.19 + cvt::CCvtCutCompensate* _pCCvtCutCopmensate = new cvt::CCvtCutCompensate; + if (_nGNumber == 41) + _pCCvtCutCopmensate->m_nCCType = cvt::cc_g41; + else + _pCCvtCutCopmensate->m_nCCType = cvt::cc_g42; + //刀具半径补偿信息--- 吴阳明 2010.3.19 + _pCCvtCutCopmensate->m_nCutNo = _nCutNo; + ListUnits.push_back(_pCCvtCutCopmensate); +} + +void CBlockMaker::G43_G44(CTaggedData* pTaggedData_) +{ + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int) pTaggedData_->m_nValue; + ASSERT(_nGNumber == 43 || _nGNumber == 44); + UNREFERENCED_PARAMETER(pTaggedData_); + + // 支持不带参数的G43/G44,不带参数时生成的CCvtCutCompensate中m_nCutNo域为-1 + // 缺少参数时如何处置由调用方决定 ---- 杨开锦 2013-06-24 + int _nCutNo = -1; + int _nIndex = 0; + if (SearchTaggedData(&_nIndex, TK_ADR_H)) + { + MatchTaggedData(_nIndex, TK_ADR_H); + _nCutNo = (int)m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + } + + //根据_nGNumber的不同值进行G43和G44的存储--- 吴阳明 2010.3.19 + cvt::CCvtCutCompensate* _pCCvtCutCopmensate = new cvt::CCvtCutCompensate; + if (_nGNumber == 43) + _pCCvtCutCopmensate->m_nCCType = cvt::cc_g43; + else + _pCCvtCutCopmensate->m_nCCType = cvt::cc_g44; + //刀具长度补偿偏置号--- 吴阳明 2010.3.19 + _pCCvtCutCopmensate->m_nCutNo = _nCutNo; + ListUnits.push_back(_pCCvtCutCopmensate); +} + +void CBlockMaker::G49(CTaggedData* pTaggedData_) +{ + int _nGNumber = int(pTaggedData_->m_nValue); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(_nGNumber == 49); + MatchTaggedData(TK_ADR_G, _nGNumber); + + int _nIndex; + //如果找到了H*,表示该代码已经使用过 wudian 2010.07.20 + if (SearchTaggedData(&_nIndex, TK_ADR_H)) + MatchTaggedData(_nIndex, TK_ADR_H); + + //存储取消刀具长度补偿信息--- 吴阳明 2010.3.19 + cvt::CCvtCutCompensate* _pCCvtCutCopmensate = new cvt::CCvtCutCompensate; + _pCCvtCutCopmensate->m_nCCType = cvt::cc_g49; + //取消刀具长度补偿,刀补号设置为-1 wangwenbo 2010.03.22 + _pCCvtCutCopmensate->m_nCutNo = -1; + ListUnits.push_back(_pCCvtCutCopmensate); +} + +//取消缩放功能 wangwenbo 2010.03.22 +//取消比例功能。 wudian 2010.07.20. +void CBlockMaker::G50(CTaggedData* pTaggedData_) +{ + //断言,指针pTaggedData_不为空,且m_nToken为G,且m_nValue为50 wudian 2010.07.20. + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 50); + //找到G50这个代码段,标记它已经被使用了。 wudian 2010.07.20. + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + if (!KillNearTransform(CTransform::TF_ZOOM)) + throw(_GETCS(s_szERROR_G51_50_NOTMATCH)); + //将终点设为新的起点。 wudian 2010.07.20. + _MoveCurPosToRespPos(); + return; +} + +//设定缩放功能 wangwenbo 2010.03.22 +void CBlockMaker::G51(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 51); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + _StoreZoomInf(pTaggedData_); + _MoveCurPosToRespPos(); + return; +} + +//G50.1 X_Y_Z_:指定镜像功能无效的轴。 +void CBlockMaker::G50_1(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G && pTaggedData_->m_nValue == 50.1); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + // Find out mirror transform + //我还没弄清楚什么是镜像功能,一下代码没看懂 wudian 2010.07.20. + INT_PTR _size = m_arrPTransform.GetSize(); + if (0 == _size) + return; + + int _i; + CMirrorTransform* _pMirrorTrans = NULL; + for (_i = 0; _i < _size; ++_i) + { + if (m_arrPTransform[_i]->m_nTransformType == CTransform::TF_MIRROR) + { + ASSERT(!_pMirrorTrans); + _pMirrorTrans = (CMirrorTransform*)m_arrPTransform[_i]; + } + } + ASSERT(_pMirrorTrans == m_arrPTransform[0]); + + static const token_t _tkTagToken[] = + { + TK_ADR_X, + TK_ADR_Y, + TK_ADR_Z, + }; + bool _bSucess = false; + int _nIndex; + int _nSize = _countof(_tkTagToken); + for (_i = 0; _i < _nSize; _i++) + { + if (SearchTaggedData(&_nIndex, _tkTagToken[_i])) + { + _bSucess = true; + MatchTaggedData(_nIndex, _tkTagToken[_i]); + _pMirrorTrans->m_bxMirror[_i] = false; + } + } + + if (!_bSucess || + (!_pMirrorTrans->m_bxMirror[0] && !_pMirrorTrans->m_bxMirror[1] && !_pMirrorTrans->m_bxMirror[2])) + { + if (!KillNearTransform(CTransform::TF_MIRROR)) + throw(_GETCS(s_szERROR_G51D1_50D1_NOTMATCH)); + } + + _MoveCurPosToRespPos(); +} + +//G51.1 X_Y_Z_:指定镜像中心,镜像中心可以是点,也可以是线。该指令指示对加工轮廓的镜像进行加工。 --- 吴典 2011 2 23 +void CBlockMaker::G51_1(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G && pTaggedData_->m_nValue == 51.1); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + _StoreMirrorInf(pTaggedData_); + _MoveCurPosToRespPos(); + + return; +} + +void CBlockMaker::G53(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 53); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + UNREFERENCED_PARAMETER(pTaggedData_); +} + +//G54~G59 --- 吴典 2011 2 23 +void CBlockMaker::SelectWorkCoor(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nNumber = (int) pTaggedData_->m_nValue; + ASSERT(_nNumber >= 54 && _nNumber <= 59); + MatchTaggedData(pTaggedData_->m_nToken, _nNumber); +} + +void CBlockMaker::G65_M98(CTaggedData* pTaggedData_) +{ + ASSERT ((pTaggedData_->m_nToken == TK_ADR_G && pTaggedData_->m_nValue == 65) + || (pTaggedData_->m_nToken == TK_ADR_M && pTaggedData_->m_nValue == 98)); + + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_P)) + { + m_strTemp.Format(_GETCS(s_szERROR_NOENOUGHPARAMETERS), "G65/M98"); + throw(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_P); + + int _nSubProgramNo = (int) m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + LPCSTR _pszSubProgramName = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_pszValue; + + int _nCallingTimes = 1; + if (SearchTaggedData(&_nIndex, TK_ADR_L)) + { + MatchTaggedData(_nIndex, TK_ADR_L); + _nCallingTimes = (int)m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + if (_nCallingTimes > 1) + { + if (m_pGToCvtTranslateParam->m_nSubProgCallTime == 1) + _nCallingTimes = 1; + else if (m_pGToCvtTranslateParam->m_nSubProgCallTime == 3) + { + CString _str; + _str.Format(_GETCS(s_szCALLTIMES), _nCallingTimes); + if (IDYES == AfxMessageBox(_str, MB_YESNO)) + _nCallingTimes = 1; + } + } + } + + if (_nCallingTimes == 0) + return; + + if (_nSubProgramNo > 0) + MakeCall(_nSubProgramNo, _nCallingTimes); + else if (_pszSubProgramName != NULL) + MakeCall(_pszSubProgramName, _nCallingTimes); + else + throw(_GETCS(s_csERROR_G65SubProg_Error)); + + //存储G65/M98的相关信息--- 吴阳明 2010.3.19 + cvt::CCvtG65* _pCCvtG65 = new cvt::CCvtG65; + //循环次数--- 吴阳明 2010.3.19 + _pCCvtG65->m_nCallingTimes = _nCallingTimes; + //子程序调用方式--- 吴阳明 2010.3.19 + if (_nSubProgramNo > 0) + { + _pCCvtG65->m_nCallWay = cvt::callway_no; + _pCCvtG65->m_nSubPathNo = _nSubProgramNo; + } + else + { + _pCCvtG65->m_nCallWay = cvt::callway_name; + _pCCvtG65->m_pszSubPathName = _pszSubProgramName; + } + ListUnits.push_back(_pCCvtG65); +} + +//旋转功能开。 wudian 2010.07.20. +void CBlockMaker::G68(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 68); + MatchTaggedData(TK_ADR_G, 68); + + //存储旋转信息。 wudian 2010.07.20. + _StoreRevInf(pTaggedData_); + //猜的:终点变新起点。 wudian 2010.07.20. + _MoveCurPosToRespPos(); + + return; +} + +//旋转功能关。 wudian 2010.07.20. +void CBlockMaker::G69(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 69); + MatchTaggedData(TK_ADR_G, 69); + + if (!KillNearTransform(CTransform::TF_REV)) + throw(_GETCS(s_szERROR_G68_69_NOTMATCH)); + _MoveCurPosToRespPos(); + return; +} + +//取消固定循环功能。 wudian 2010.07.20. +void CBlockMaker::G80(CTaggedData* pTaggedData_) +{ + ASSERT(int(pTaggedData_->m_nValue) == 80); + MatchTaggedData(TK_ADR_G, 80); +} + +//复归到初始点或R点。 wudian 2010.07.20. +void CBlockMaker::G98_G99(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int)pTaggedData_->m_nValue; + ASSERT(_nGNumber == 98 ||_nGNumber == 99); + + MatchTaggedData(TK_ADR_G, _nGNumber); +} + +//工件坐标系设定 wangwenbo 2010.03.22 +void CBlockMaker::G92(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 92); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(92 == pTaggedData_->m_nValue); + + static const token_t _tkTagToken[] = + { + TK_ADR_X, TK_ADR_Y, TK_ADR_Z + }; + + int _nIndex; + DPOINT3 _nxOffset(0.f, 0.f, 0.f); + for (int _axis = 0; _axis < 3; ++_axis) + { + if (SearchTaggedData(&_nIndex, _tkTagToken[_axis])) + { + MatchTaggedData(_nIndex, _tkTagToken[_axis]); + _nxOffset[_axis] = double(m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue); + m_ModalData.m_ptOffset[_axis] = m_ptCurPos[_axis] - _nxOffset[_axis]; + } + } + + return; +} + +void CBlockMaker::G992(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 992); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(992 == pTaggedData_->m_nValue); + + static const token_t _tkTagTokenXYZ[] = {TK_ADR_X, TK_ADR_Y, TK_ADR_Z}; + static const token_t _tkTagTokenIJK[] = {TK_ADR_I, TK_ADR_J, TK_ADR_K}; + int _nIndex; + for (int _axis = 0; _axis < 3; ++_axis) + { + if (SearchTaggedData(&_nIndex, _tkTagTokenXYZ[_axis])) + MatchTaggedData(_nIndex, _tkTagTokenXYZ[_axis]); + else if (SearchTaggedData(&_nIndex, _tkTagTokenIJK[_axis])) + MatchTaggedData(_nIndex, _tkTagTokenIJK[_axis]); + } + + return; +} + +//G921 X_Y_Z_:设置当前工件坐标系的当前点的工件坐标,不写的轴不修改,不同步偏移其他工件坐标系。 +//该指令可用在测量工件表面和测量工件的中心/边界时。 +//attention:本系统中,G921指令未做解析! --- 吴典 2011 2 23 +void CBlockMaker::G921(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 921); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(921 == pTaggedData_->m_nValue); + + static const token_t _tkTagToken[] = + { + TK_ADR_X, TK_ADR_Y, TK_ADR_Z + }; + + int _nIndex; + for (int _axis = 0; _axis < 3; ++_axis) + { + if (SearchTaggedData(&_nIndex, _tkTagToken[_axis])) + MatchTaggedData(_nIndex, _tkTagToken[_axis]); + } + + return; +} + +//attention:本系统暂未对G922指令进行解析。 --- 吴典 2011 2 23 +//G922 X_Y_Z_P_讲解:P_用于指定偏置的类型,-4表示外部偏移;-1表示当前工件坐标系,可忽略;0~5对应G54~G59。 +//本指令可用在测量工件表面和测量工件的中心/边界时。 +void CBlockMaker::G922(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 922); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(922 == pTaggedData_->m_nValue); + + static const token_t _tkTagToken[] = + { + TK_ADR_X, TK_ADR_Y, TK_ADR_Z + }; + + int _nIndex; + for (int _axis = 0; _axis < 3; ++_axis) + { + if (SearchTaggedData(&_nIndex, _tkTagToken[_axis])) + MatchTaggedData(_nIndex, _tkTagToken[_axis]); + } + if (SearchTaggedData(&_nIndex, TK_ADR_P)) + MatchTaggedData(_nIndex, TK_ADR_P); + + return; +} + +void CBlockMaker::G923(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 923); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(923 == pTaggedData_->m_nValue); + + static const token_t _tkTagToken[] = + { + TK_ADR_X, TK_ADR_Y, TK_ADR_Z + }; + + int _nIndex; + for (int _axis = 0; _axis < 3; ++_axis) + { + if (SearchTaggedData(&_nIndex, _tkTagToken[_axis])) + MatchTaggedData(_nIndex, _tkTagToken[_axis]); + } + if (SearchTaggedData(&_nIndex, TK_ADR_P)) + MatchTaggedData(_nIndex, TK_ADR_P); + + return; +} + +void CBlockMaker::G903(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 903); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 903); + UNREFERENCED_PARAMETER(pTaggedData_); +} + +void CBlockMaker::G904(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 904); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + static const token_t _tkTagToken[][4] = + { + {TK_ADR_FX, TK_ADR_PX, TK_ADR_LX, TK_ADR_X}, + {TK_ADR_FY, TK_ADR_PY, TK_ADR_LY, TK_ADR_Y}, + {TK_ADR_FZ, TK_ADR_PZ, TK_ADR_LZ, TK_ADR_Z}, + }; + + for (int _loop = 0; _loop < 3; _loop++) + { + int _nIndex; + if (SearchTaggedData(&_nIndex, _tkTagToken[_loop][0])) + { + MatchTaggedData(_nIndex, _tkTagToken[_loop][0]); + + if (!SearchTaggedData(&_nIndex, _tkTagToken[_loop][1])) + throw(_GETCS(s_szERROR_G904_ERROR_MISSADDR)); + MatchTaggedData(_nIndex, _tkTagToken[_loop][1]); + + if (!SearchTaggedData(&_nIndex, _tkTagToken[_loop][2])) + throw(_GETCS(s_szERROR_G904_ERROR_MISSADDR)); + MatchTaggedData(_nIndex, _tkTagToken[_loop][2]); + + if (SearchTaggedData(&_nIndex, _tkTagToken[_loop][3])) + MatchTaggedData(_nIndex, _tkTagToken[_loop][3]); + } + } + + return; +} + +void CBlockMaker::G905(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 905); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); +} + +void CBlockMaker::SyncPos(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_SYNCPOS); + ASSERT(pTaggedData_->m_nValue == -1); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); +} + +void CBlockMaker::G906(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 906); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + int _nIndex = 0; + + //等待时间,单位为毫秒 + if (SearchTaggedData(&_nIndex, TK_ADR_P)) + { + MatchTaggedData(_nIndex, TK_ADR_P); + + //查找端口号 + if (!SearchTaggedData(&_nIndex, TK_ADR_PLC)) + { + m_strTemp.Format(_GETCS(s_szERROR_NOENOUGHPARAMETERS), "G906"); + throw(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_PLC); + + //端口电平值 + if (!SearchTaggedData(&_nIndex, TK_ADR_LEVEL)) + { + m_strTemp.Format(_GETCS(s_szERROR_NOENOUGHPARAMETERS), "G906"); + throw(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_LEVEL); + } +} + +void CBlockMaker::G907(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 907); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 907); + UNREFERENCED_PARAMETER(pTaggedData_); + return; +} + +void CBlockMaker::G908(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 908); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 908); + UNREFERENCED_PARAMETER(pTaggedData_); + return; +} + +void CBlockMaker::G925_G926(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int) pTaggedData_->m_nValue; + ASSERT(_nGNumber == 925 || _nGNumber == 926); + + MatchTaggedData(TK_ADR_G, _nGNumber); +} + +//看过 wudian 2010.07.20 +void CBlockMaker::M0_M1(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + int _nNumber = int(pTaggedData_->m_nValue); + ASSERT(_nNumber == 0 || _nNumber == 1); + MatchTaggedData(TK_ADR_M, pTaggedData_->m_nValue); + UNREFERENCED_PARAMETER(pTaggedData_); + + //存储停止信息,M0为cvt_m0,M1为cvt_m1--- 吴阳明 2010.3.19 + cvt::CCvtUnit* _pCCvtUnit = new cvt::CCvtUnit; + if (_nNumber == 0) + _pCCvtUnit->m_nType = cvt::cvt_m0; + else + _pCCvtUnit->m_nType = cvt::cvt_m1; + ListUnits.push_back(_pCCvtUnit); +} + +// 遇到此指令应该结束加工任务,并把文件指针指向程序文件头。 +void CBlockMaker::M2_M30(CTaggedData* pTaggedData_) +{ + //是不是该把这句放到ASSERT后面 wudian 2010.07.20 + MatchTaggedData(TK_ADR_M, pTaggedData_->m_nValue); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(2 == pTaggedData_->m_nValue || 30 == pTaggedData_->m_nValue); + + //存储停止信息,M2为cvt_m2,M1为cvt_m30--- 吴阳明 2010.3.19 + cvt::CCvtUnit* _pCCvtUnit = new cvt::CCvtUnit; + if (pTaggedData_->m_nValue == 2) + _pCCvtUnit->m_nType = cvt::cvt_m2; + else + _pCCvtUnit->m_nType = cvt::cvt_m30; + ListUnits.push_back(_pCCvtUnit); + + // 利用异常机制来停止分析过程 + THROW(""); +} + +void CBlockMaker::M3_M4_M5(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, pTaggedData_->m_nValue); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + int _nNumber = (int)pTaggedData_->m_nValue; + ASSERT(3 == _nNumber || _nNumber == 4 || _nNumber == 5); + + //主轴旋转方向及停止存取 + cvt::CCvtSpindleAct* _pSpindleAct = new cvt::CCvtSpindleAct; + if (_nNumber == 3) + _pSpindleAct->m_nSpindleAction = cvt::Spindleaction_Clock; + else if (_nNumber == 4) + _pSpindleAct->m_nSpindleAction = cvt::Spindleaction_antiClock; + else + _pSpindleAct->m_nSpindleAction = cvt::Spindleaction_stop; + ListUnits.push_back(_pSpindleAct); +} + +//用到了Transform.h中的内容,没弄懂 wudian 2010.07.20 +void CBlockMaker::M17_M99(CTaggedData* pTaggedData_) +{ + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 17 || pTaggedData_->m_nValue == 99); + + //存储子程序返回信息--- 吴阳明 2010.3.19 + cvt::CCvtUnit* _pCCvtUnit = new cvt::CCvtUnit; + if (pTaggedData_->m_nValue == 17) + _pCCvtUnit->m_nType = cvt::cvt_m17; + else + _pCCvtUnit->m_nType = cvt::cvt_m99; + ListUnits.push_back(_pCCvtUnit); + + StackItem _si; + if (!m_Stack.Pop(&_si)) + return; + + if (_si.siLoop == 1) + { + if (_si.siMode == StackItem::CIRCYC) + { + throw("Don't Support Circyc now"); + // SFC_ProcStack(&_si); + } + else + { + ASSERT (_si.siMode == StackItem::NORMAL); + m_Parser.m_TokenAnalyser.SetPosition(_si.siPos); + } + } + else + { + ASSERT(_si.siLoop > 0); + _si.siLoop--; + m_Stack.Push(_si); + + long _pos; + if (_si.siProgNo > 0) + _pos = GetSubProg(_si.siProgNo); + else + _pos = GetSubProg(_si.siProgName); + ASSERT(_pos >= 0); + m_Parser.m_TokenAnalyser.SetPosition(_pos); + } +} + +void CBlockMaker::M801(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, 801); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 801); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_MSG)) + { + m_strTemp.Format(_GETCS(s_szERROR_NOENOUGHPARAMETERS), "M801"); + throw(m_strTemp); + } + + MatchTaggedData(_nIndex, TK_ADR_MSG); +} + +void CBlockMaker::M802(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, 802); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 802); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_P)) + { + m_strTemp.Format(_GETCS(s_szERROR_NOENOUGHPARAMETERS), "M802"); + throw(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_P); +} + +void CBlockMaker::M901(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, 901); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 901); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_PLC)) + { + m_strTemp.Format(_GETCS(s_szERROR_NOENOUGHPARAMETERS), "M901"); + throw(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_PLC); + + _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_LEVEL)) + { + m_strTemp.Format(_GETCS(s_szERROR_NOENOUGHPARAMETERS), "M901"); + throw(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_LEVEL); +} + +void CBlockMaker::M902(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, 902); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 902); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_H)) + { + m_strTemp.Format(_GETCS(s_szERROR_NOENOUGHPARAMETERS), "M902"); + throw(m_strTemp); + } + + MatchTaggedData(_nIndex, TK_ADR_H); +} + +void CBlockMaker::M903(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, 903); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 903); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_H)) + { + m_strTemp.Format(_GETCS(s_szERROR_NOENOUGHPARAMETERS), "M903"); + throw(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_H); +} + +void CBlockMaker::M904_M905(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 904 || pTaggedData_->m_nValue == 905); + + MatchTaggedData(TK_ADR_M, pTaggedData_->m_nValue); + return; +} + +void CBlockMaker::G927(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 927); + + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); +} + +//提取G文件中的主轴信息,放入CVT数据链表 +void CBlockMaker::SpindleRev(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_S, pTaggedData_->m_nValue); + m_ModalData.m_nSpindleRev = int(pTaggedData_->m_nValue); + + cvt::CCvtSpindleRev* _pSpindleRev = new cvt::CCvtSpindleRev; + + _pSpindleRev->m_nSpindleRev = int(pTaggedData_->m_nValue); + + ListUnits.push_back(_pSpindleRev); +} + +void CBlockMaker::GInvalid(CTaggedData* pTaggedData_) +{ + int _nIndex; + SearchTaggedData(&_nIndex, TK_ADR_G); + MatchTaggedData(_nIndex, TK_ADR_G); + m_strTemp.Format(_GETCS(s_szERROR_INVALID_GCODE), pTaggedData_->m_nValue); + throw(m_strTemp); +} + +void CBlockMaker::MInvalid(CTaggedData* pTaggedData_) +{ + int _nIndex; + SearchTaggedData(&_nIndex, TK_ADR_M); + MatchTaggedData(_nIndex, TK_ADR_M); + int _nValue = (int) pTaggedData_->m_nValue; + m_strTemp.Format(_GETCS(s_szERROR_INVALID_MCODE), _nValue); + //PARSEENGINEWARNING(m_strTemp); +} + +void CBlockMaker::GUnknown(CTaggedData* pTaggedData_) +{ + int _nIndex; + SearchTaggedData(&_nIndex, TK_ADR_G); + MatchTaggedData(_nIndex, TK_ADR_G); + return; +} + +void CBlockMaker::MUnknown(CTaggedData* pTaggedData_) +{ + int _nIndex; + SearchTaggedData(&_nIndex, TK_ADR_M); + MatchTaggedData(_nIndex, TK_ADR_M); +} + +void CBlockMaker::Comment(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_COMMENT); + ASSERT(pTaggedData_->m_pszValue && pTaggedData_->m_pszValue[0]); + + cvt::CCvtComment* _pComment = new cvt::CCvtComment; + strcpy_s(_pComment->m_szText, pTaggedData_->m_pszValue); + ListUnits.push_back(_pComment); +} + +void CBlockMaker::MatchComment(CTaggedData* pTaggedData_) +{ +} + +void CBlockMaker::FixedCycle(CTaggedData* pTaggedData_) +{ + ASSERT(int(pTaggedData_->m_nValue) != 80); + + int _nIndex; + if (SearchTaggedData(&_nIndex, TK_ADR_G)) + { + int _nGNumber = (int)pTaggedData_->m_nValue; + MatchTaggedData(TK_ADR_G, _nGNumber); + } + + FC_RetrieveInf(pTaggedData_); + + return; +} + +void CBlockMaker::G34_G36(CTaggedData* pTaggedData_) +{ + ASSERT(NULL != pTaggedData_); + SFC_RetrieveInf(pTaggedData_); + return; +} + +void CBlockMaker::G35(CTaggedData* pTaggedData_) +{ + ASSERT(NULL != pTaggedData_); + SFC_RetrieveInf(pTaggedData_); + return; +} + +void CBlockMaker::G37(CTaggedData* pTaggedData_) +{ + ASSERT(NULL != pTaggedData_); + SFC_RetrieveInf(pTaggedData_); + return; +} + +void CBlockMaker::SFC_RetrieveInf(CTaggedData* pTaggedData_) +{ + ASSERT(NULL != pTaggedData_); + int _nG_Number = (int) pTaggedData_->m_nValue; + ASSERT(TK_ADR_G == pTaggedData_->m_nToken && (_nG_Number > 33 && _nG_Number < 38)); + MatchTaggedData(TK_ADR_G, _nG_Number); + + // Type + const static _SFC_Item::_SFCTYPE _s_sfcType[] = + { + _SFC_Item::SFC_34, + _SFC_Item::SFC_35, + _SFC_Item::SFC_36, + _SFC_Item::SFC_37, + }; + m_SpecialFixCyc.m_nType = _s_sfcType[_nG_Number - 34]; + + struct _TokenValue + { + token_t nToken; + double* pValue; + }; + _TokenValue* _pTVTable = NULL; + int _nSize = 0; + + switch(m_SpecialFixCyc.m_nType) + { + case _SFC_Item::SFC_34: + { + _TokenValue _s_TV34[] = + { + {TK_ADR_I, &m_SpecialFixCyc.m_G34.nRadius}, + {TK_ADR_J, &m_SpecialFixCyc.m_G34.nStartAngle}, + {TK_ADR_K, &m_SpecialFixCyc.m_G34.nCount}, + }; + _pTVTable = (_TokenValue*)_alloca(sizeof(_s_TV34)); + memcpy(_pTVTable, _s_TV34, sizeof(_s_TV34)); + _nSize = _countof(_s_TV34); + } + break; + + case _SFC_Item::SFC_35: + { + _TokenValue _s_TV35[] = + { + {TK_ADR_I, &m_SpecialFixCyc.m_G35.nStep}, + {TK_ADR_J, &m_SpecialFixCyc.m_G35.nAngle}, + {TK_ADR_K, &m_SpecialFixCyc.m_G35.nCount}, + }; + _pTVTable = (_TokenValue*)_alloca(sizeof(_s_TV35)); + memcpy(_pTVTable, _s_TV35, sizeof(_s_TV35)); + _nSize = _countof(_s_TV35); + } + break; + + case _SFC_Item::SFC_36: + { + _TokenValue _s_TV36[] = + { + {TK_ADR_I, &m_SpecialFixCyc.m_G36.nRadius}, + {TK_ADR_J, &m_SpecialFixCyc.m_G36.nStartAngle}, + {TK_ADR_P, &m_SpecialFixCyc.m_G36.nStep}, + {TK_ADR_K, &m_SpecialFixCyc.m_G36.nCount}, + }; + _pTVTable = (_TokenValue*)_alloca(sizeof(_s_TV36)); + memcpy(_pTVTable, _s_TV36, sizeof(_s_TV36)); + _nSize = _countof(_s_TV36); + } + break; + + case _SFC_Item::SFC_37: + { + _TokenValue _s_TV37[] = + { + {TK_ADR_I, &m_SpecialFixCyc.m_G37.nStepX}, + {TK_ADR_P, &m_SpecialFixCyc.m_G37.nCountX}, + {TK_ADR_J, &m_SpecialFixCyc.m_G37.nStepY}, + {TK_ADR_K, &m_SpecialFixCyc.m_G37.nCountY}, + }; + _pTVTable = (_TokenValue*)_alloca(sizeof(_s_TV37)); + memcpy(_pTVTable, _s_TV37, sizeof(_s_TV37)); + _nSize = _countof(_s_TV37); + } + break; + + default: + ASSERT(false); + break; + } + + for (int _i = 0; _i < _nSize; _i++) + { + int _nIndex; + if(SearchTaggedData(&_nIndex, _pTVTable[_i].nToken)) + MatchTaggedData(_nIndex, _pTVTable[_i].nToken); + else + throw(_GETCS(s_szERROR_SPECIAL_CIRCLE_CYCLE_FORMAT)); + } + + return; +} + +void CBlockMaker::FC_RetrieveInf(CTaggedData* pTaggedData_) +{ + const token_t _s_tkpCoors[] = + { + TK_ADR_X, + TK_ADR_Y, + TK_ADR_Z, + TK_ADR_R, + }; + + int _i, _size; + for (_i = 0, _size = _countof(_s_tkpCoors); _i < _size; _i++) + { + token_t _tkCur = _s_tkpCoors[_i]; + + int _nIndex = -1; + // Find them out successfully + if (SearchTaggedData(&_nIndex, _tkCur)) + MatchTaggedData(_nIndex, _tkCur); + } + + // 2. Times + const token_t _s_tkpTimes[] = + { + TK_ADR_L, + TK_ADR_K, + }; + for (_i = 0, _size = _countof(_s_tkpTimes); _i < _size; _i++) + { + token_t _tkCur = _s_tkpTimes[_i]; + + int _nIndex = -1; + if (SearchTaggedData(&_nIndex, _tkCur)) + MatchTaggedData(_nIndex, _tkCur); + } + + // 3. Other information + const token_t _s_tkpCommon[] = + { + TK_ADR_Q, + TK_ADR_P, + TK_ADR_F, + TK_ADR_I, + TK_ADR_J, + }; + for (_i = 0, _size = _countof(_s_tkpCommon); _i < _size; _i++) + { + token_t _tkCur = _s_tkpCommon[_i]; + int _nIndex = -1; + if (SearchTaggedData(&_nIndex, _tkCur)) + { + MatchTaggedData(_nIndex, _tkCur); + } + } + + return; +} + +void CBlockMaker::G7(CTaggedData* pTaggedData_) +{ + ///////////////////////////////////////////////////////////////// + // When deal with NORM Rule instruction, + // The PRE instruction were disappeared all, + // Only POST && NORM are all right. + if (TK_ADR_G == pTaggedData_->m_nToken) + { + int _nGNumber = (int) pTaggedData_->m_nValue; + MatchTaggedData(TK_ADR_G, _nGNumber); + } + + RetrieveDestPosition(); + + m_ptCurPos = m_ptDestPos; + return; +} + +// Section transform: +void CBlockMaker::_StoreZoomInf(CTaggedData* pTaggedData_) +{ + UNREFERENCED_PARAMETER(pTaggedData_); + CZoomTransform* _pZoomTrans = new CZoomTransform; + _pZoomTrans->m_ptCenterOrig = m_ptCurPosOrig; + + static const token_t _tkTagToken[] = + { + TK_ADR_X, TK_ADR_I, + TK_ADR_Y, TK_ADR_J, + TK_ADR_Z, TK_ADR_K, + }; + + DPOINT3 _nxCurPos = m_ptCurPosOrig; + int _nIndex; + //取缩放中心和缩放比例 wangwenbo 2010.03.18 + if (SearchTaggedData(&_nIndex, TK_ADR_P)) + { + MatchTaggedData(_nIndex, TK_ADR_P); + double _nAspect = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + if (_nAspect == 0.) + throw(_GETCS(s_szERROR_G51_ZERO_ZOOM_ASPECT)); + + for (int _loop = 0; _loop < 3; _loop++) + { + if (SearchTaggedData(&_nIndex, _tkTagToken[_loop * 2])) + { + MatchTaggedData(_nIndex, _tkTagToken[_loop * 2]); + double _nTemp = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + + if (SearchTaggedData(&_nIndex, _tkTagToken[_loop * 2 + 1])) + throw(_GETCS(s_szERROR_G51_INSTRUCTION)); + + _pZoomTrans->m_ptAspect[_loop] = double(_nAspect); + + _nTemp = TranslateToMM(_nTemp, _loop); + _SetOrigCoorToDestination(_pZoomTrans->m_ptCenterOrig, double(_nTemp), _loop); + } + } + } + else + { + for (int _loop = 0; _loop < 3; _loop++) + { + //分别取缩放中心和缩放比例 wangwenbo 2010 03 18 + if (SearchTaggedData(&_nIndex, _tkTagToken[_loop * 2])) + { + MatchTaggedData(_nIndex, _tkTagToken[_loop * 2]); + double _nTemp = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + _nTemp = TranslateToMM(_nTemp, _loop); + _SetOrigCoorToDestination(_pZoomTrans->m_ptCenterOrig, double(_nTemp), _loop); + + try + { + _nIndex = MatchTaggedData(_tkTagToken[_loop * 2 + 1]); + _pZoomTrans->m_ptAspect[_loop] = double(m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue); + } + catch (...) + { + throw(_GETCS(s_szERROR_G51_INSTRUCTION)); + } + } + } + } + + // Transform at first then add it to transform queue + _Transform(_pZoomTrans->m_ptCenterOrig, _pZoomTrans->m_ptCenter); + _pZoomTrans->m_bIsValidCenter = true; + + m_arrPTransform.Add(_pZoomTrans); + + return; +} + +// m_ptCentre of revolving is the original machine coordinate, NO zoom, NO revolve +void CBlockMaker::_StoreRevInf(CTaggedData* pTaggedData_) +{ + UNREFERENCED_PARAMETER(pTaggedData_); + CRevTransform* _pRevTrans = new CRevTransform; + _pRevTrans->m_ptCenterOrig = m_ptCurPosOrig; + _pRevTrans->m_nPlane = m_ModalData.m_nPlane; + + static const token_t _tkTagToken[] = + { + TK_ADR_X, + TK_ADR_Y, + TK_ADR_Z, + TK_ADR_R, + }; + int _nIndex; + for (int _i = 0, _size = _countof(_tkTagToken); _i < _size; _i++) + { + if (SearchTaggedData(&_nIndex, _tkTagToken[_i])) + { + MatchTaggedData(_nIndex, _tkTagToken[_i]); + double _nTemp = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + + if (TK_ADR_R == _tkTagToken[_i]) + { + // Revolving angle, original unit is degree + _pRevTrans->m_nAngle = DEGREE2RADIAN(_nTemp); + + // Check whether MirrorTransform exist + // There is one MirrorTransform at most + CMirrorTransform* _pMirrorTrans = NULL; + for (_i = 0; _i < m_arrPTransform.GetSize(); ++_i) + { + if (m_arrPTransform[_i]->m_nTransformType == CTransform::TF_MIRROR) + { + ASSERT(!_pMirrorTrans); + _pMirrorTrans = (CMirrorTransform*)m_arrPTransform[_i]; +#ifdef NDEBUG + break; +#endif + } + } + + if (_pMirrorTrans) + _pRevTrans->m_nAngle *= -1.; + + continue; + } + + _nTemp = TranslateToMM(_nTemp, _i); + _SetOrigCoorToDestination(_pRevTrans->m_ptCenterOrig, double(_nTemp), _i); + } + } + + _Transform(_pRevTrans->m_ptCenterOrig, _pRevTrans->m_ptCenter); + _pRevTrans->m_bIsValidCenter = true; + m_arrPTransform.Add(_pRevTrans); + + return; +} + +void CBlockMaker::_StoreMirrorInf(CTaggedData* pTaggedData_) +{ + UNREFERENCED_PARAMETER(pTaggedData_); + INT_PTR _nSize = m_arrPTransform.GetSize(); + int _i; + for (_i = 0; _i < _nSize; ++_i) + { + if (m_arrPTransform[_i]->m_nTransformType != CTransform::TF_MIRROR) + { + throw(_GETCS(s_szERROR_G51_1_NOT1ST_TRANSFORM)); + return; // Not arrive here until implement of ErrorHandler() was changed + } + } + + bool _bOverWrite = (_nSize != 0); + CMirrorTransform* _pMirrorTrans = NULL; + if (_bOverWrite) + { + ASSERT(m_arrPTransform[_nSize - 1]->m_nTransformType == CTransform::TF_MIRROR); + _pMirrorTrans = (CMirrorTransform*)m_arrPTransform[_nSize - 1]; + } + else + { + _pMirrorTrans = new CMirrorTransform; + _pMirrorTrans->m_ptCenterOrig = m_ptCurPosOrig; + } + + static const token_t _tkTagToken[] = + { + TK_ADR_X, + TK_ADR_Y, + TK_ADR_Z, + }; + int _nIndex; + for (_i = 0, _nSize = _countof(_tkTagToken); _i < _nSize; _i++) + { + if (SearchTaggedData(&_nIndex, _tkTagToken[_i])) + { + MatchTaggedData(_nIndex, _tkTagToken[_i]); + double _nTemp = m_Parser.m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + _nTemp = TranslateToMM(_nTemp, _i); + _SetOrigCoorToDestination(_pMirrorTrans->m_ptCenterOrig, double(_nTemp), _i); + _pMirrorTrans->m_bxMirror[_i] = true; + } + } + + _pMirrorTrans->m_bIsValidCenter = false; + if (!_bOverWrite) + m_arrPTransform.Add(_pMirrorTrans); + + return; +} + +void CBlockMaker::_Transform(const DPOINT3& nxBefore_, DPOINT3& nxAfter_) const +{ + nxAfter_ = nxBefore_; + + if (0 == m_arrPTransform.GetSize()) + return; + + DPOINT3 _nxMidBefore = nxBefore_; + DPOINT3 _nxMidAfter(0.0, 0.0, 0.0); + for (INT_PTR _i = 0, _size = m_arrPTransform.GetSize(); _i < _size; ++_i) + { + CTransform* _pTransForm = m_arrPTransform[_i]; + + // If current transform center is not valid, make it valid at first + if (!_pTransForm->m_bIsValidCenter) + { + DPOINT3 _nxCenterBefore = _pTransForm->m_ptCenterOrig; + DPOINT3 _nxCenterAfter = _pTransForm->m_ptCenterOrig; + CTransform* _pTFTemp = NULL; + + for (int _j = 0; _j < _i; ++_j) + { + _pTFTemp = m_arrPTransform[_j]; + ASSERT(_pTFTemp->m_bIsValidCenter); + _pTFTemp->Transform(_nxCenterBefore, _nxCenterAfter); + _nxCenterBefore = _nxCenterAfter; + } + + _pTransForm->m_ptCenter = _nxCenterAfter; + _pTransForm->m_bIsValidCenter = true; + } + + _pTransForm->Transform(_nxMidBefore, _nxMidAfter); + _nxMidBefore = _nxMidAfter; + } + nxAfter_ = _nxMidAfter; + + return; +} + +void CBlockMaker::_MoveCurPosToRespPos() +{ + _Transform(m_ptDestPosOrig, m_ptDestPos); + m_ptCurPos = m_ptDestPos; + return; +} + +bool CBlockMaker::KillNearTransform(CTransform::transform_t nType_) +{ + // Remove the lastest transform + for (INT_PTR _size = m_arrPTransform.GetSize(), _i = _size - 1; _i >= 0; --_i) + { + CTransform* _pTF = m_arrPTransform[_i]; + if (_pTF->m_nTransformType != nType_) + continue; + + // Because transforms before it has been changed + for (INT_PTR _loop = _size - 1; _loop > _i; --_loop) + m_arrPTransform[_loop]->m_bIsValidCenter = false; + + delete _pTF; + m_arrPTransform.RemoveAt(_i); + return true; + } + + return false; +} + +bool CBlockMaker::ScanCodeFileData() +{ + if (!m_Parser.m_TokenAnalyser.m_pBuffer) + { + return false; + } + + m_mapSubStrProgIndex.RemoveAll(); + m_mapSubIntProgIndex.RemoveAll(); + + try + { + const char* _pData = m_Parser.m_TokenAnalyser.m_pBuffer; + if (!_pData) + { + return false; + } + const __int64 _nDataLength = m_Parser.m_TokenAnalyser.m_nLength; + const char* _p1 = _pData; + __int64 _count = _nDataLength; + while (_count) + { + const char* _p2 = (char*)memchr(_p1, '\n', (size_t)_count); + bool _bEnd = (NULL == _p2); + if (_bEnd) + _p2 = _pData + _nDataLength - 1; + + const char* _pTemp = _p1; + while (isspace(*_pTemp) && _pTemp < _p2) + { + _pTemp++; + } + + // search sub-program at this line: "O" + if (*_pTemp == 'O' || *_pTemp == 'o') + { + if (!AddSubProg(_pTemp, _p1)) + return false; + } + + if (!_bEnd) + { + _p1 = _p2 + 1; + _count = _nDataLength - (_p1 - _pData); + } + else + break; + } + } + catch (CException* e) + { + UNREFERENCED_PARAMETER(e); + throw (_GETCS(s_szFORMATORVERSIONERROR)); + return false; + } + + return true; +} + +bool CBlockMaker::AddSubProg(PCSTR psz_, PCSTR p1_) +{ + ASSERT(*psz_ == 'O' || *psz_ == 'o'); + + if (psz_[1] == '\"') + { + char _szSubName[256]; + + char* _pTo = _szSubName; + const char* _pFrom = psz_ + 2; + while (*_pFrom && (*_pFrom != '\"') && (*_pFrom != '\n') && (*_pFrom != '\r')) + { + *_pTo++ = *_pFrom++; + if (_pTo >= (_szSubName + sizeof(_szSubName) - 1)) + break; + } + *_pTo = 0; + + if (!strlen(_szSubName) || (*_pFrom != '\"')) + { + TRACE0(_GETCS(s_szSUBPROGFORMATERROR)); + return false; + } + else if (GetSubProg(_szSubName) > -1) + { + TRACE0(_GETCS(s_szSUBPROGREPEATED)); + return false; + } + + m_mapSubStrProgIndex[_szSubName] = p1_; + } + else + { + int _sub_no = atoi(psz_ + 1); + // Note: 0 is a valid subprogram number + if (GetSubProg(_sub_no) > -1) + { + TRACE0(_GETCS(s_szSUBPROGREPEATED)); + return false; + } + + m_mapSubIntProgIndex[_sub_no] = p1_; + } + + return true; +} + +int CBlockMaker::GetSubProg(int sub_no_) const +{ + const char* _p = NULL; + bool _ret = m_mapSubIntProgIndex.Lookup(sub_no_, _p) ? true : false; + if (!_ret) + _p = NULL; + + int _nRet = -1; + if (_p) + { + _nRet = (int)(_p - m_Parser.m_TokenAnalyser.m_pBuffer); + } + return _nRet; +} + +int CBlockMaker::GetSubProg(const char* sub_name_) const +{ + const char* _p = NULL; + bool _ret = m_mapSubStrProgIndex.Lookup(sub_name_, _p) ? true : false; + if (!_ret) + _p = NULL; + + int _nRet = -1; + if (_p) + { + _nRet = (int)(_p - m_Parser.m_TokenAnalyser.m_pBuffer); + } + return _nRet; +} + +void CBlockMaker::MakeCall(int nSubProgNo_, int nCallTimes_) +{ + long _fp = -1; + StackItem _si; + + _fp = GetSubProg(nSubProgNo_); + if (_fp < 0) + goto MAKE_CALL_ERROR; + + _si.siPos = (int)m_Parser.m_TokenAnalyser.GetPosition(); + _si.siLoop = nCallTimes_; + _si.siProgNo = nSubProgNo_; + m_Stack.Push(_si); + + m_Parser.m_TokenAnalyser.SetPosition(_fp); + return; + +MAKE_CALL_ERROR: + m_strTemp.Format(_GETCS(s_szERROR_NOSUBPROGRAM_NO), nSubProgNo_); + throw(m_strTemp); +} + +// pszSubProgName_ ----- 被调用子程序的名字 +// nCallTimes_ ----- 子程序调用次数 +void CBlockMaker::MakeCall(LPCSTR pszSubProgName_, int nCallTimes_) +{ + long _fp = -1; + StackItem _si; + + _fp = GetSubProg(pszSubProgName_); + if (_fp < 0) + goto MAKE_CALL_ERROR; + + _si.siPos = (int)m_Parser.m_TokenAnalyser.GetPosition(); + _si.siLoop = nCallTimes_; + _tcsncpy_s(_si.siProgName, pszSubProgName_, sizeof(_si.siProgName) - 1); + m_Stack.Push(_si); + + m_Parser.m_TokenAnalyser.SetPosition(_fp); + return; + +MAKE_CALL_ERROR: + m_strTemp.Format(_GETCS(s_szERROR_NOSUBPROGRAM_NAME), pszSubProgName_); + throw(m_strTemp); +} diff --git a/src/CamRepeatedDelete.cpp b/src/CamRepeatedDelete.cpp new file mode 100644 index 0000000..9aa8c0a --- /dev/null +++ b/src/CamRepeatedDelete.cpp @@ -0,0 +1,1961 @@ +// Copyright (c) Naiky Company. All rights reserved. +// +// Abstract: +// 删除重复的加工边 潘乐婷 2010-5-4 +/////////////////////////////////////////////////////////// +#include "stdafx.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW +#endif + +inline bool _equal(double x, double y, double epslon) +{ + ASSERT(_IsValid(x)); + ASSERT(_IsValid(y)); + ASSERT(epslon > 0.); + return (fabs(x - y) < epslon); +} + +inline bool _great(double x, double y, double epslon) +{ + ASSERT(_IsValid(x)); + ASSERT(_IsValid(y)); + ASSERT(epslon > 0.); + return (x >= y + epslon); +} + +inline bool _less(double x, double y, double epslon) +{ + ASSERT(IsValidDouble(x)); + ASSERT(IsValidDouble(y)); + ASSERT(epslon > 0.); + return (x <= y - epslon); +} + +const double c_nPERCENT_FOR_COMPARE0 = 1.0; +const double c_nPERCENT_FOR_COMPARE1 = 1.e-1; +const double c_nPERCENT_FOR_COMPARE2 = 1.e-2; +// const double c_nPERCENT_FOR_COMPARE3 = 1.e-3; + +//#define _less_percent(x, y) abs(y) > c_nPERCENT_FOR_COMPARE1 ? _less (x / abs(y), y / abs(y), c_nPERCENT_FOR_COMPARE1) : _less (x, y, c_nPERCENT_FOR_COMPARE1) +//#define _equal_percent(x, y) abs(y) > c_nPERCENT_FOR_COMPARE1 ? _equal (x / abs(y), y / abs(y), c_nPERCENT_FOR_COMPARE1) : _equal(x, y, c_nPERCENT_FOR_COMPARE1) +//#define _great_percent(x, y) abs(y) > c_nPERCENT_FOR_COMPARE1 ? _great(x / abs(y), y / abs(y), c_nPERCENT_FOR_COMPARE1) : _great(x, y, c_nPERCENT_FOR_COMPARE1) + +#define _float_less(x,y) _less (x, y, c_nPERCENT_FOR_COMPARE2/*c_nPERCENT_FOR_COMPARE3*/) +#define _float_equ(x,y) _equal(x, y, c_nPERCENT_FOR_COMPARE2/*c_nPERCENT_FOR_COMPARE3*/) +#define _float_great(x,y) _great(x, y, c_nPERCENT_FOR_COMPARE2/*c_nPERCENT_FOR_COMPARE3*/) +#define _float_ge(x, y) (_float_great(x, y) || _float_equ(x, y)) /* x >= y */ +#define _float_le(x, y) (_float_less(x, y) || _float_equ(x, y)) /* x <= y */ +// 截距用1.e-1比较精度 孙彦春 2012-7-26 +#define _float_less_CoeB(x,y) ((x > 100 || x < -100) ? _less(x, y, c_nPERCENT_FOR_COMPARE0/*c_nPERCENT_FOR_COMPARE2*/) : _less(x, y, c_nPERCENT_FOR_COMPARE1/*c_nPERCENT_FOR_COMPARE3*/)) +#define _float_equ_CoeB(x,y) ((x > 100 || x < -100) ? _equal(x, y, c_nPERCENT_FOR_COMPARE0/*c_nPERCENT_FOR_COMPARE2*/) : _equal(x, y, c_nPERCENT_FOR_COMPARE1/*c_nPERCENT_FOR_COMPARE3*/)) + +using namespace nce; + +CCamRepeatedDelete::CCamRepeatedDelete() +{ +} + +CCamRepeatedDelete::~CCamRepeatedDelete() +{ +} + +void CCamRepeatedDelete::CamRepeatedDelete(IN const CCamGroup* pSrcCamGroup_,IN OUT CCamGroup* pDestCamGroup_) +{ + //先删除所有Path类型的对象的重复边,遇到点时先不处理,将该点保存到pDesCadGroup_ + CamRepeatedDelete_Path(pSrcCamGroup_, pDestCamGroup_); + //再删除所有Hole类型的对象 潘乐婷 2010-7-12 + CamRepeatedDelete_Hole(pDestCamGroup_); +} + +void CCamRepeatedDelete::CamRepeatedDelete_Path(IN const CCamGroup* pSrcCamGroup_,IN OUT CCamGroup* pDestCamGroup_) +{ + CCamGroup* _pCamGroupPath = new CCamGroup; + // _pCamGroupPath->m_nOwnerGroupId = pDestCamGroup_->m_nID; + + CamObjectList::const_iterator _it; + for (_it = pSrcCamGroup_->GetObjectsList()->begin(); _it != pSrcCamGroup_->GetObjectsList()->end(); ++_it) + { + const CCamObject* _pCamObject = (*_it); + CamRepeatedDelete_Path(_pCamObject, _pCamGroupPath); + } + + if (GetCamgroupSize(_pCamGroupPath)) + { + pDestCamGroup_->GetObjectsList()->push_back(_pCamGroupPath); + } + else + { + delete _pCamGroupPath; + } + return; +} + +void CCamRepeatedDelete::CamRepeatedDelete_Path(IN const CCamObject* pCamObject_,IN OUT CCamGroup* pCamGroup_) +{ + switch(pCamObject_->GetType()) + { + case nce::campath: + CamRepeatedDelete_Path(reinterpret_cast(pCamObject_), pCamGroup_); + break; + + case nce::camhole: + { + //该函数删除的是path类型的重复边,如果为点类型,先将该点保存到pCamGroup_中,在所有path类型的对象处理完后再来处理点类型 潘乐婷 2010-7-12 + CCamHole* _pHole = (CCamHole*)pCamObject_->Clone(); + //_pHole->m_nOwnerGroupId = pCamGroup_->m_nID; + pCamGroup_->GetObjectsList()->push_back(_pHole); + } + break; + + case nce::camgroup: + CamRepeatedDelete_Path(reinterpret_cast(pCamObject_), pCamGroup_); + break; + + case nce::camscanlines: + ASSERT(FALSE); + break; + default: + ASSERT(false); + break; + } + + return; +} + +void CCamRepeatedDelete::CamRepeatedDelete_Path(IN const CCamPath* pPath_,IN OUT CCamGroup* pCamGroup_) +{ + CCamPath* _pDesPath = new CCamPath; + _pDesPath->SetParamIndex(pPath_->GetParamIndex()); + _pDesPath->SetParamString(pPath_->GetParamString()); + //_pDesPath->m_nOwnerGroupId = pCamGroup_->m_nID; + + // void* _pData = pPath_->m_pNodes; + // BYTE* _pTypes = pPath_->m_pTypes; + // ASSERT(NULL != _pData && NULL != _pTypes); + int _nNodeCount = pPath_->GetNodeCount(); + + DPOINT3 _ptCurPoint = pPath_->GetStartPoint(); + _pDesPath->SetStartPoint(_ptCurPoint); + DPOINT3 _ptNextPoint = _ptCurPoint; + + for (int _i = 0; _i < _nNodeCount; ++_i) + { + nce::CCamPath::NODE _node = pPath_->GetNode(_i); + switch(_node.nType & 0xF0) + { + case CCamPath::nt_line: + { + GetLineNode(_node, _ptNextPoint); + //根据线段的起点与终点坐标计算该线段的信息,返回该线段信息对象 潘乐婷 2010-7-12 + LineInfo _pLineInfo = CalculateLineFormula(_ptCurPoint, _ptNextPoint); + if (ModifyLine(&_pLineInfo)) + { + //ModifyLine()函数返回true表示该段直线有重复部分已经被删除 潘乐婷 2010-7-12 + if (_pLineInfo.vecPositions.size() == 0) + { + //如果删除后该段线段中不再有线段了,表示该段线段整段被删除了 潘乐婷 2010-7-12 + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ptNextPoint); + } + else + { + //如果删除后该段线段中还有线段,则将线段逐段取出增加到_pDesPath中。 + //如果该段线段被分割成不相连的小段,则在不相连的地方要先将前段_pDesPath保存到pCamGroup_中, + //再new出一个新的CCamPath对象用_pDesPath来记录 潘乐婷 2010-7-12 + if (_pLineInfo.bDirReversed == false) + { + //_pLineInfo中记录的线段信息总是按照x增大的方向记录的,可能与原线段的方向相反,bDirReversed为false表示不与原线段方向相反, + //即原线段的方向就是沿x增大的方向的,则从_pLineInfo中从头至尾取出删除重复线段后的线段添加到_pDesPath中 + //如前所述处理如果该线段被分割成不相连的小段的情况 潘乐婷 2010-7-12 + if (DPOINT3_EQU(_pLineInfo.vecPositions.front().ptStartPoint, _pDesPath->GetEndPoint()) && + DPOINT3_EQU(_pLineInfo.vecPositions.back().ptEndPoint, _ptNextPoint)) + { + ASSERT(_pLineInfo.vecPositions.size() > 1); + for (std::list::iterator _it = _pLineInfo.vecPositions.begin(); _it != _pLineInfo.vecPositions.end(); ++_it) + { + _pDesPath->AddLine((*_it).ptEndPoint); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _pLineInfo.vecPositions.end()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + } + } + } + else if (DPOINT3_EQU(_pLineInfo.vecPositions.front().ptStartPoint, _pDesPath->GetEndPoint()) && + !DPOINT3_EQU(_pLineInfo.vecPositions.back().ptEndPoint, _ptNextPoint)) + { + for (std::list::iterator _it = _pLineInfo.vecPositions.begin(); _it != _pLineInfo.vecPositions.end(); ++_it) + { + _pDesPath->AddLine((*_it).ptEndPoint); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _pLineInfo.vecPositions.end()) + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + else if ((DPOINT3)_pLineInfo.vecPositions.front().ptStartPoint != (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_pLineInfo.vecPositions.back().ptEndPoint == _ptNextPoint) + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_pLineInfo.vecPositions.front().ptStartPoint); + + for (std::list::iterator _it = _pLineInfo.vecPositions.begin(); _it != _pLineInfo.vecPositions.end(); ++_it) + { + _pDesPath->AddLine((*_it).ptEndPoint); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _pLineInfo.vecPositions.end()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + } + } + } + else + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_pLineInfo.vecPositions.front().ptStartPoint); + + for (std::list::iterator _it = _pLineInfo.vecPositions.begin(); _it != _pLineInfo.vecPositions.end(); ++_it) + { + _pDesPath->AddLine((*_it).ptEndPoint); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _pLineInfo.vecPositions.end()) + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + } + else + { + //_pLineInfo中记录的线段信息总是按照x增大的方向记录的,可能与原线段的方向相反,bDirReversed为true表示与原线段方向相反, + //即原线段的方向是沿x减小的方向的,则从_pLineInfo中取线段时要从其vecPositions的末尾向开头取 潘乐婷 2010-7-12 + if ((DPOINT3)_pLineInfo.vecPositions.back().ptEndPoint == (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_pLineInfo.vecPositions.front().ptStartPoint == _ptNextPoint) + { + ASSERT(_pLineInfo.vecPositions.size() > 1); + for (std::list::reverse_iterator _it = _pLineInfo.vecPositions.rbegin(); _it != _pLineInfo.vecPositions.rend(); ++_it) + { + _pDesPath->AddLine((*_it).ptStartPoint); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _pLineInfo.vecPositions.rend()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + } + } + } + else if ((DPOINT3)_pLineInfo.vecPositions.back().ptEndPoint == (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_pLineInfo.vecPositions.front().ptStartPoint != _ptNextPoint) + { + for (std::list::reverse_iterator _it = _pLineInfo.vecPositions.rbegin(); _it != _pLineInfo.vecPositions.rend(); ++_it) + { + _pDesPath->AddLine((*_it).ptStartPoint); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _pLineInfo.vecPositions.rend()) + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + else if ((DPOINT3)_pLineInfo.vecPositions.back().ptEndPoint != (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_pLineInfo.vecPositions.front().ptStartPoint == _ptNextPoint) + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_pLineInfo.vecPositions.back().ptEndPoint); + + for (std::list::reverse_iterator _it = _pLineInfo.vecPositions.rbegin(); _it != _pLineInfo.vecPositions.rend(); ++_it) + { + _pDesPath->AddLine((*_it).ptStartPoint); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _pLineInfo.vecPositions.rend()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + } + } + } + else + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_pLineInfo.vecPositions.back().ptEndPoint); + + for (std::list::reverse_iterator _it = _pLineInfo.vecPositions.rbegin(); _it != _pLineInfo.vecPositions.rend(); ++_it) + { + _pDesPath->AddLine((*_it).ptStartPoint); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _pLineInfo.vecPositions.rend()) + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + } + } + } + else + { + _pDesPath->AddLine(_ptNextPoint); + } + + _ptCurPoint = _ptNextPoint; + } + break; + + case CCamPath::nt_arc: + { + double _nBulgeOriginal = 0; + GetArcNode(_node, _ptNextPoint, _nBulgeOriginal); + //根据圆弧的起点、终点、凸度计算该圆弧的信息,返回该圆弧信息对象 潘乐婷 2010-7-12 + ArcInfo _ArcInfo = CalculateArcInfo(_ptCurPoint, _ptNextPoint, _nBulgeOriginal); + if (ModifyArc(&_ArcInfo)) + { + //ModifyLine()函数返回true表示该段圆弧有重复部分已经被删除 潘乐婷 2010-7-12 + if (_ArcInfo.vecPositions.size() == 0) + { + if (_pDesPath->GetNodeCount() != 0) + { + //如果删除后该段圆弧中不再有圆弧段了,表示该段圆弧整段被删除了 潘乐婷 2010-7-12 + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ptNextPoint); + } + else + { + //如果删除后该段圆弧中还有圆弧段,则将圆弧段逐段取出增加到_pDesPath中。 + //如果该段圆弧被分割成不相连的小段,则在不相连的地方要先将前段_pDesPath保存到pCamGroup_中, + //再new出一个新的CCamPath对象用_pDesPath来记录 潘乐婷 2010-7-12 + if (_ArcInfo.bDirReversed == false) + { + //_ArcInfo中记录的圆弧信息总是按照逆时针旋转的方向记录的,可能与原圆弧的方向相反,bDirReversed为false表示不与原圆弧方向相反, + //即原圆弧的方向就是按逆时针旋转的方向的,则从_ArcInfo中从头至尾取出删除重复圆弧段后的圆弧段添加到_pDesPath中 + //如前所述处理如果该圆弧被分割成不相连的小段的情况 潘乐婷 2010-7-12 + if ((DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint == (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint == _ptNextPoint) + { + ASSERT(_ArcInfo.vecPositions.size() > 1); + for (std::list::iterator _it = _ArcInfo.vecPositions.begin(); _it != _ArcInfo.vecPositions.end(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nStartAngle, (*_it).nEndAngle); + _pDesPath->AddArc((*_it).ptEndPoint, _nBulge, CCamPath::nt_arc_xy); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.end()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + } + } + } + else if ((DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint == (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint != _ptNextPoint) + { + for (std::list::iterator _it = _ArcInfo.vecPositions.begin(); _it != _ArcInfo.vecPositions.end(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nStartAngle, (*_it).nEndAngle); + _pDesPath->AddArc((*_it).ptEndPoint, _nBulge, CCamPath::nt_arc_xy); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.end()) + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + else if ((DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint != (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint == _ptNextPoint) + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ArcInfo.vecPositions.front().ptStartPoint); + + for (std::list::iterator _it = _ArcInfo.vecPositions.begin(); _it != _ArcInfo.vecPositions.end(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nStartAngle, (*_it).nEndAngle); + _pDesPath->AddArc((*_it).ptEndPoint, _nBulge, CCamPath::nt_arc_xy); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.end()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + } + } + } + else + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ArcInfo.vecPositions.front().ptStartPoint); + + for (std::list::iterator _it = _ArcInfo.vecPositions.begin(); _it != _ArcInfo.vecPositions.end(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nStartAngle, (*_it).nEndAngle); + _pDesPath->AddArc((*_it).ptEndPoint, _nBulge, CCamPath::nt_arc_xy); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.end()) + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + } + else + { + //_ArcInfo中记录的圆弧信息总是按照逆时针旋转的方向记录的,可能与原圆弧的方向相反,bDirReversed为true表示与原圆弧方向相反, + //即原圆弧的方向是沿顺时针旋转的方向的,则从_ArcInfo中取圆弧段时要从其vecPositions的末尾向开头取 潘乐婷 2010-7-12 + if ((DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint == (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint == _ptNextPoint) + { + ASSERT(_ArcInfo.vecPositions.size() > 1); + for (std::list::reverse_iterator _it = _ArcInfo.vecPositions.rbegin(); _it != _ArcInfo.vecPositions.rend(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nEndAngle, (*_it).nStartAngle); + _pDesPath->AddArc((*_it).ptStartPoint, _nBulge, CCamPath::nt_arc_xy); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.rend()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + } + } + } + else if ((DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint == (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint != _ptNextPoint) + { + for (std::list::reverse_iterator _it = _ArcInfo.vecPositions.rbegin(); _it != _ArcInfo.vecPositions.rend(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nEndAngle, (*_it).nStartAngle); + _pDesPath->AddArc((*_it).ptStartPoint, _nBulge, CCamPath::nt_arc_xy); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.rend()) + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + else if ((DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint != (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint == _ptNextPoint) + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ArcInfo.vecPositions.back().ptEndPoint); + + for (std::list::reverse_iterator _it = _ArcInfo.vecPositions.rbegin(); _it != _ArcInfo.vecPositions.rend(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nEndAngle, (*_it).nStartAngle); + _pDesPath->AddArc((*_it).ptStartPoint, _nBulge, CCamPath::nt_arc_xy); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.rend()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + } + } + } + else + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ArcInfo.vecPositions.back().ptEndPoint); + + for (std::list::reverse_iterator _it = _ArcInfo.vecPositions.rbegin(); _it != _ArcInfo.vecPositions.rend(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nEndAngle, (*_it).nStartAngle); + _pDesPath->AddArc((*_it).ptStartPoint, _nBulge, CCamPath::nt_arc_xy); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.rend()) + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + } + } + } + else + { + _pDesPath->AddArc(_ptNextPoint , _nBulgeOriginal, CCamPath::nt_arc_xy); + } + + _ptCurPoint = _ptNextPoint; + } + break; + + case CCamPath::nt_circle: + { + //圆的处理与圆弧类似,参照圆弧的处理 潘乐婷 2010-7-12 + double _nRadius = 0; + GetCircleNode(_node, _ptNextPoint, _nRadius); + ArcInfo _ArcInfo = CalculateArcInfo(_ptCurPoint, _ptNextPoint, _nRadius, _node.nType/* _pTypes[_i]*/); + if (ModifyArc(&_ArcInfo)) + { + if (_ArcInfo.vecPositions.size() == 0) + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ptNextPoint); + } + else + { + if (_ArcInfo.bDirReversed == false) + { + if ((DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint == (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint == _ptNextPoint) + { + ASSERT(_ArcInfo.vecPositions.size() > 1); + for (std::list::iterator _it = _ArcInfo.vecPositions.begin(); _it != _ArcInfo.vecPositions.end(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nStartAngle, (*_it).nEndAngle); + _pDesPath->AddArc((*_it).ptEndPoint, _nBulge, CCamPath::nt_arc_xy); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.end()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + } + } + } + else if ((DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint == (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint != _ptNextPoint) + { + for (std::list::iterator _it = _ArcInfo.vecPositions.begin(); _it != _ArcInfo.vecPositions.end(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nStartAngle, (*_it).nEndAngle); + _pDesPath->AddArc((*_it).ptEndPoint, _nBulge, CCamPath::nt_arc_xy); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.end()) + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + else if ((DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint != (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint == _ptNextPoint) + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ArcInfo.vecPositions.front().ptStartPoint); + + for (std::list::iterator _it = _ArcInfo.vecPositions.begin(); _it != _ArcInfo.vecPositions.end(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nStartAngle, (*_it).nEndAngle); + _pDesPath->AddArc((*_it).ptEndPoint, _nBulge, CCamPath::nt_arc_xy); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.end()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + } + } + } + else + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ArcInfo.vecPositions.front().ptStartPoint); + + for (std::list::iterator _it = _ArcInfo.vecPositions.begin(); _it != _ArcInfo.vecPositions.end(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nStartAngle, (*_it).nEndAngle); + _pDesPath->AddArc((*_it).ptEndPoint, _nBulge, CCamPath::nt_arc_xy); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.end()) + _pDesPath->SetStartPoint((*_itt).ptStartPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + } + else + { + if ((DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint == (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint == _ptNextPoint) + { + ASSERT(_ArcInfo.vecPositions.size() > 1); + for (std::list::reverse_iterator _it = _ArcInfo.vecPositions.rbegin(); _it != _ArcInfo.vecPositions.rend(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nEndAngle, (*_it).nStartAngle); + _pDesPath->AddArc((*_it).ptStartPoint, _nBulge, CCamPath::nt_arc_xy); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.rend()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + } + } + } + else if ((DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint == (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint != _ptNextPoint) + { + for (std::list::reverse_iterator _it = _ArcInfo.vecPositions.rbegin(); _it != _ArcInfo.vecPositions.rend(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nEndAngle, (*_it).nStartAngle); + _pDesPath->AddArc((*_it).ptStartPoint, _nBulge, CCamPath::nt_arc_xy); + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.rend()) + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + else + _pDesPath->SetStartPoint(_ptNextPoint); + } + } + else if ((DPOINT3)_ArcInfo.vecPositions.back().ptEndPoint != (DPOINT3)_pDesPath->GetEndPoint() && + (DPOINT3)_ArcInfo.vecPositions.front().ptStartPoint == _ptNextPoint) + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ArcInfo.vecPositions.back().ptEndPoint); + + for (std::list::reverse_iterator _it = _ArcInfo.vecPositions.rbegin(); _it != _ArcInfo.vecPositions.rend(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nEndAngle, (*_it).nStartAngle); + _pDesPath->AddArc((*_it).ptStartPoint, _nBulge, CCamPath::nt_arc_xy); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.rend()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + } + } + } + else + { + if (_pDesPath->GetNodeCount() != 0) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + } + + _pDesPath->SetStartPoint(_ArcInfo.vecPositions.back().ptEndPoint); + + for (std::list::reverse_iterator _it = _ArcInfo.vecPositions.rbegin(); _it != _ArcInfo.vecPositions.rend(); ++_it) + { + double _nBulge = CalculateBulge((*_it).nEndAngle, (*_it).nStartAngle); + _pDesPath->AddArc((*_it).ptStartPoint, _nBulge, CCamPath::nt_arc_xy); + + std::list::reverse_iterator _itt = _it; + ++_itt; + if (_itt != _ArcInfo.vecPositions.rend()) + { + AddPath(pCamGroup_, _pDesPath, pPath_->GetParamIndex()); + _pDesPath->SetStartPoint((*_itt).ptEndPoint); + } + } + } + } + } + } + else + { + _pDesPath->AddCircle(_ArcInfo.ptCenterPoint, _node.nType); + } + _ptCurPoint = _ptNextPoint; + } + break; + + default: + ASSERT(false); + break; + } + } + + if (_pDesPath->GetNodeCount() != 0) + pCamGroup_->GetObjectsList()->push_back(_pDesPath); + else + delete _pDesPath; + + return; +} + +//根据线段的起点与终点坐标计算该线段的信息,返回该线段信息对象 潘乐婷 2010-7-12 +LineInfo CCamRepeatedDelete::CalculateLineFormula(DPOINT3 ptStartPoint_, DPOINT3 ptEndPoint_) +{ + LineInfo _LineInfo; + if (_float_equ(ptStartPoint_.x, ptEndPoint_.x)) + { + //如果该段线段与x轴垂直,则其没有斜率 + _LineInfo.bSlopeExist = false; + //nCoefficientA记录的是该段线段的x坐标值 + _LineInfo.nCoefficientA = ptStartPoint_.x; + + //按照y增大的方向记录该段线段的起始点y坐标 潘乐婷 2010-7-12 + if (ptStartPoint_.y < ptEndPoint_.y) + { + LinePosition _LinePosition(ptStartPoint_, ptEndPoint_); + _LineInfo.vecPositions.push_back(_LinePosition); + } + else + { + //如果该段线段是沿y减小的方向的,则记录仍按照y增大的方向记录,但bDirReversed值为true表示该_LinePosition记录的线段与原线段方向相反 + LinePosition _LinePosition(ptEndPoint_, ptStartPoint_); + _LineInfo.bDirReversed = true; + _LineInfo.vecPositions.push_back(_LinePosition); + } + } + else + { + //如果该线段不与x轴垂直,则nCoefficientA与nCoefficientB分别记录的是该段线段的斜率与截距 潘乐婷 2010-7-12 + _LineInfo.bSlopeExist = true; + _LineInfo.nCoefficientA = (ptEndPoint_.y - ptStartPoint_.y) / (ptEndPoint_.x - ptStartPoint_.x); + _LineInfo.nCoefficientB = ptStartPoint_.y - _LineInfo.nCoefficientA * ptStartPoint_.x; + + //按照x增大的方向记录该线段的起点与终点x值,改线段的起点与终点y值可以通过x值和斜率与截距计算出来 潘乐婷 2010-7-12 + if (_float_less(ptStartPoint_.x, ptEndPoint_.x)) + { + LinePosition _LinePosition(ptStartPoint_, ptEndPoint_); + _LineInfo.vecPositions.push_back(_LinePosition); + } + else + { + //如果该段线段原本是按照x减小的方向的,则记录时仍按照x增大的方向记录,但bDirReversed值为true表示该_LinePosition记录的线段与原线段方向相反 + LinePosition _LinePosition(ptEndPoint_, ptStartPoint_); + _LineInfo.bDirReversed = true; + _LineInfo.vecPositions.push_back(_LinePosition); + } + } + + return _LineInfo; +} + +//根据圆弧的起点、终点、凸度计算该圆弧的信息,返回该圆弧信息对象 潘乐婷 2010-7-12 +ArcInfo CCamRepeatedDelete::CalculateArcInfo(DPOINT3 ptStartPoint_, DPOINT3 ptEndPoint_, double nBulge_) +{ + ASSERT(nBulge_ != 0.); + ASSERT((ptStartPoint_ - ptEndPoint_).GetLength() > 0.); + if (nBulge_ > 0.) + { + //如果凸度大于0,则该圆弧段按照逆时针方向旋转 + ArcInfo _ArcInfo; + DPOINT3 _center; + double _nAngleStart, _nAngleEnd, _nRadius; + double _nBulge = nBulge_; + RetrieveArcInf(ptStartPoint_, ptEndPoint_, _nBulge, &_center, &_nAngleStart, &_nAngleEnd, &_nRadius); + _ArcInfo.ptCenterPoint = _center; + _ArcInfo.nRadius = _nRadius; + ArcPosition _ArcPosition(_nAngleStart, _nAngleEnd, ptStartPoint_, ptEndPoint_); + _ArcInfo.vecPositions.push_back(_ArcPosition); + return _ArcInfo; + } + else + { + //如果凸度小于0,则该圆弧段按顺时针方向旋转,则保存该圆弧信息时按逆时针方向保存,但bDirReversed为true表示记录的圆弧信息与原圆弧的方向相反 + ArcInfo _ArcInfo; + _ArcInfo.bDirReversed = true; + DPOINT3 _center; + double _nAngleStart, _nAngleEnd, _nRadius; + double _nBulge = - nBulge_; + RetrieveArcInf(ptEndPoint_, ptStartPoint_, _nBulge, &_center, &_nAngleStart, &_nAngleEnd, &_nRadius); + _ArcInfo.ptCenterPoint = _center; + _ArcInfo.nRadius = _nRadius; + ArcPosition _ArcPostion(_nAngleStart, _nAngleEnd, ptEndPoint_, ptStartPoint_); + _ArcInfo.vecPositions.push_back(_ArcPostion); + return _ArcInfo; + } +} + +//根据圆的起点,圆心,半径,顺/逆时针旋转方向计算该圆的信息,返回该圆的信息对象 潘乐婷 2010-7-12 +ArcInfo CCamRepeatedDelete::CalculateArcInfo(DPOINT3 ptStartPoint_, DPOINT3 ptCenterPoint_, double nRadius_, BYTE nType_) +{ + ArcInfo _ArcInfo; + DPOINT3 _ptCenter(ptCenterPoint_.x, ptCenterPoint_.y, ptCenterPoint_.z); + _ArcInfo.ptCenterPoint = _ptCenter; + _ArcInfo.nRadius = nRadius_; + _ArcInfo.bDirReversed = (nType_ == CCamPath::nt_circle_xy_ccw) ? false : true; + double _nAngle = ncmath::D2GetNormalAngle(ptStartPoint_.x - ptCenterPoint_.x, ptStartPoint_.y - ptCenterPoint_.y); + ArcPosition _ArcPosition(_nAngle, _nAngle + 2 * ncmath::c_nPIE, ptStartPoint_, ptStartPoint_); + _ArcInfo.vecPositions.push_back(_ArcPosition); + return _ArcInfo; +} + +void CCamRepeatedDelete::RetrieveArcInf(IN const DPOINT3& ptStart_, IN const DPOINT3&ptEnd_, IN const double& nBulge_, + OUT DPOINT3* pptCenter_, OUT double* pnStartAngle_, OUT double* pnEndAngle_, OUT double* pnRadius_) +{ + DPOINT3 _ptFromTo = (DPOINT3)ptEnd_ - (DPOINT3)ptStart_; + double _nLen = _ptFromTo.GetLength(); + ASSERT(DOUBLE_GE_ZERO(_nLen)); + if (DOUBLE_EQU_ZERO(_nLen)) + { + pptCenter_->x = ptStart_.x; + pptCenter_->y = ptStart_.y; + *pnStartAngle_ = 0.; + *pnEndAngle_ = 0.; + *pnRadius_ = 0.; + return; + } + + // Inner angle + double _alpha = atan(nBulge_) * 4.; + ASSERT(DOUBLE_NOT_ZERO(_alpha)); + + // 1) Radius + double _nRadius = _nLen * 0.5 / sin(_alpha * 0.5); + *pnRadius_ = fabs(_nRadius); + + // 2) Circle centre + // 2-1) proportional translate + ASSERT(DOUBLE_NOT_ZERO(_nLen)); + double _nK = _nRadius / _nLen; + + DPOINT2 _ptByPropTrans; + _ptByPropTrans.x = _ptFromTo.x * _nK; + _ptByPropTrans.y = _ptFromTo.y * _nK; + + // 2-2) revolving transform + double _theta = (ncmath::c_nPIE - _alpha) * 0.5; + DPOINT2 _ptByRevTrans; + _ptByRevTrans.x = cos(_theta) * _ptByPropTrans.x - sin(_theta) * _ptByPropTrans.y; + _ptByRevTrans.y = sin(_theta) * _ptByPropTrans.x + cos(_theta) * _ptByPropTrans.y; + + // 2-3) Get circle center + pptCenter_->x = ptStart_.x + _ptByRevTrans.x; + pptCenter_->y = ptStart_.y + _ptByRevTrans.y; + ASSERT(ptStart_.z == ptEnd_.z); + pptCenter_->z = ptStart_.z; + + // 3) Start angle + *pnStartAngle_ = ncmath::D2GetNormalAngle(ptStart_.x - pptCenter_->x, ptStart_.y - pptCenter_->y); + + // 4) End angle + *pnEndAngle_ = *pnStartAngle_ + _alpha; + + return; +} + +//返回该段直线是否被修改过,如果该直线有与某直线重复的部分被删除,则表示其被修改过,函数调用之后pLineInfo_对象中的重复部分将被删除 潘乐婷 2010-7-12 +bool CCamRepeatedDelete::ModifyLine(LineInfo* pLineInfo_) +{ + if (pLineInfo_->bSlopeExist) + { + //如果该段线段有斜率,则从m_vecLineInfo_SlopeExist查找改线段是否有部分与已存在的线段重复 + if (m_vecLineInfo_SlopeExist.size() != 0) + { + lineinfo_holder::const_iterator _itMiddle = bsearchLineInfo(pLineInfo_, m_vecLineInfo_SlopeExist); + for (lineinfo_holder::iterator _it = m_vecLineInfo_SlopeExist.begin(); _it != m_vecLineInfo_SlopeExist.end(); ++_it) + { + bool _b = _float_less((*_it).nCoefficientA, pLineInfo_->nCoefficientA); + bool _b2 = _float_equ((*_it).nCoefficientA, pLineInfo_->nCoefficientA); + bool _b3 = _float_less_CoeB((*_it).nCoefficientB, pLineInfo_->nCoefficientB); + if (_b || (_b2 && _b3)) + continue; + else if (_float_equ((*_it).nCoefficientA, pLineInfo_->nCoefficientA) && _float_equ_CoeB((*_it).nCoefficientB, pLineInfo_->nCoefficientB)) + { + ASSERT(pLineInfo_->vecPositions.size() == 1); + DPOINT3 _ptStartPoint = pLineInfo_->vecPositions.front().ptStartPoint; + DPOINT3 _ptEndPoint = pLineInfo_->vecPositions.front().ptEndPoint; + pLineInfo_->vecPositions.clear(); + bool _bModified = false; + for (std::list::iterator _iter = (*_it).vecPositions.begin(); _iter != (*_it).vecPositions.end(); ++_iter) + { + if (_float_ge(_ptStartPoint.x, (*_iter).ptEndPoint.x)) + continue; + else if (_float_less(_ptStartPoint.x, (*_iter).ptStartPoint.x) && _float_great(_ptEndPoint.x, (*_iter).ptEndPoint.x)) + { + LinePosition _LinePosition; + _LinePosition.ptStartPoint = _ptStartPoint; + _LinePosition.ptEndPoint = (*_iter).ptStartPoint; + _LinePosition.ptEndPoint.y = pLineInfo_->nCoefficientA * (*_iter).ptStartPoint.x + pLineInfo_->nCoefficientB; + pLineInfo_->vecPositions.push_back(_LinePosition); + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).ptEndPoint.x, _LinePosition.ptStartPoint.x)) + { + (*_iter).ptStartPoint = (*_itera).ptStartPoint; + (*_it).vecPositions.erase(_itera); + } + else + (*_iter).ptStartPoint = _LinePosition.ptStartPoint; + } + else + (*_iter).ptStartPoint = _LinePosition.ptStartPoint; + + _ptStartPoint.x = (*_iter).ptEndPoint.x; + _ptStartPoint.y = pLineInfo_->nCoefficientA * (*_iter).ptEndPoint.x + pLineInfo_->nCoefficientB; + _bModified = true; + } + else if (_float_less(_ptStartPoint.x, (*_iter).ptStartPoint.x) + && _float_great(_ptEndPoint.x, (*_iter).ptStartPoint.x) && _float_le(_ptEndPoint.x, (*_iter).ptEndPoint.x)) + { + LinePosition _LinePosition; + _LinePosition.ptStartPoint = _ptStartPoint; + _LinePosition.ptEndPoint = (*_iter).ptStartPoint; + _LinePosition.ptEndPoint.y = pLineInfo_->nCoefficientA * (*_iter).ptStartPoint.x + pLineInfo_->nCoefficientB; + pLineInfo_->vecPositions.push_back(_LinePosition); + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).ptEndPoint.x, _LinePosition.ptStartPoint.x)) + { + (*_iter).ptStartPoint = (*_itera).ptStartPoint; + (*_it).vecPositions.erase(_itera); + } + else + (*_iter).ptStartPoint = _LinePosition.ptStartPoint; + } + else + (*_iter).ptStartPoint = _LinePosition.ptStartPoint; + + return true; + } + else if (_float_less(_ptStartPoint.x, (*_iter).ptStartPoint.x) && _float_equ(_ptEndPoint.x, (*_iter).ptStartPoint.x)) + { + LinePosition _LinePosition; + _LinePosition.ptStartPoint = _ptStartPoint; + _LinePosition.ptEndPoint = (*_iter).ptStartPoint; + _LinePosition.ptEndPoint.y = pLineInfo_->nCoefficientA * (*_iter).ptStartPoint.x + pLineInfo_->nCoefficientB; + pLineInfo_->vecPositions.push_back(_LinePosition); + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).ptEndPoint.x, _LinePosition.ptStartPoint.x)) + { + (*_iter).ptStartPoint.x = (*_itera).ptStartPoint.x; + (*_it).vecPositions.erase(_itera); + } + else + (*_iter).ptStartPoint.x = _LinePosition.ptStartPoint.x; + } + else + (*_iter).ptStartPoint.x = _LinePosition.ptStartPoint.x; + + return _bModified; + } + else if (_float_less(_ptStartPoint.x, (*_iter).ptStartPoint.x) && _float_less(_ptEndPoint.x, (*_iter).ptStartPoint.x)) + { + LinePosition _LinePosition; + _LinePosition.ptStartPoint = _ptStartPoint; + _LinePosition.ptEndPoint = _ptEndPoint; + pLineInfo_->vecPositions.push_back(_LinePosition); + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).ptEndPoint.x, _LinePosition.ptStartPoint.x)) + (*_itera).ptEndPoint.x = _LinePosition.ptEndPoint.x; + else + _iter = (*_it).vecPositions.insert(_iter, _LinePosition); + } + else + _iter = (*_it).vecPositions.insert(_iter, _LinePosition); + + return _bModified; + } + else if (_float_ge(_ptStartPoint.x, (*_iter).ptStartPoint.x) && _float_great(_ptEndPoint.x, (*_iter).ptEndPoint.x)) + { + _ptStartPoint.x = (*_iter).ptEndPoint.x; + _ptStartPoint.y = pLineInfo_->nCoefficientA * (*_iter).ptEndPoint.x + pLineInfo_->nCoefficientB; + _bModified = true; + } + else if (_float_ge(_ptStartPoint.x, (*_iter).ptStartPoint.x) && _float_le(_ptEndPoint.x, (*_iter).ptEndPoint.x)) + { + return true; + } + } + + LinePosition _LinePosition; + _LinePosition.ptStartPoint = _ptStartPoint; + _LinePosition.ptEndPoint = _ptEndPoint; + pLineInfo_->vecPositions.push_back(_LinePosition); + + std::list::iterator _iter = (*_it).vecPositions.end(); + --_iter; + if (_float_equ((*_iter).ptEndPoint.x, _LinePosition.ptStartPoint.x)) + { + (*_iter).ptEndPoint = _LinePosition.ptEndPoint; + } + else + (*_it).vecPositions.push_back(_LinePosition); + + return _bModified; + } + else + { + m_vecLineInfo_SlopeExist.insert(_it, *pLineInfo_); + return false; + } + } + + m_vecLineInfo_SlopeExist.push_back(*pLineInfo_); + return false; + } + else + { + m_vecLineInfo_SlopeExist.push_back(*pLineInfo_); + return false; + } + } + else + { + //如果该段线段没有斜率,则从m_vecLineInfo_SlopeUnExist查找改线段是否有部分与已存在的线段重复 + if (m_vecLineInfo_SlopeUnExist.size() != 0) + { + for (lineinfo_holder::iterator _it = m_vecLineInfo_SlopeUnExist.begin(); _it != m_vecLineInfo_SlopeUnExist.end(); ++_it) + { + if (_less((*_it).nCoefficientA, pLineInfo_->nCoefficientA, c_nPERCENT_FOR_COMPARE1)) + continue; + else if (_equal((*_it).nCoefficientA, pLineInfo_->nCoefficientA, c_nPERCENT_FOR_COMPARE1)) + { + ASSERT(pLineInfo_->vecPositions.size() == 1); + DPOINT3 _ptStartPoint = pLineInfo_->vecPositions.front().ptStartPoint; + DPOINT3 _ptEndPoint = pLineInfo_->vecPositions.front().ptEndPoint; + pLineInfo_->vecPositions.clear(); + bool _bModified = false; + for (std::list::iterator _iter = (*_it).vecPositions.begin(); _iter != (*_it).vecPositions.end(); ++_iter) + { + if (_float_ge(_ptStartPoint.y, (*_iter).ptEndPoint.y)) + continue; + else if (_float_less(_ptStartPoint.y, (*_iter).ptStartPoint.y) && _float_great(_ptEndPoint.y, (*_iter).ptEndPoint.y)) + { + LinePosition _LinePosition; + _LinePosition.ptStartPoint = _ptStartPoint; + _LinePosition.ptEndPoint = _ptStartPoint; + _LinePosition.ptEndPoint.y = (*_iter).ptStartPoint.y; + pLineInfo_->vecPositions.push_back(_LinePosition); + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).ptEndPoint.y, _LinePosition.ptStartPoint.y)) + { + (*_iter).ptStartPoint.y = (*_itera).ptStartPoint.y; + (*_it).vecPositions.erase(_itera); + } + else + (*_iter).ptStartPoint.y = _LinePosition.ptStartPoint.y; + } + else + (*_iter).ptStartPoint = _LinePosition.ptStartPoint; + + _ptStartPoint.y = (*_iter).ptEndPoint.y; + _bModified = true; + } + else if (_float_less(_ptStartPoint.y, (*_iter).ptStartPoint.y) + && _float_great(_ptEndPoint.y, (*_iter).ptStartPoint.y) && _float_le(_ptEndPoint.y, (*_iter).ptEndPoint.y)) + { + LinePosition _LinePosition; + _LinePosition.ptStartPoint = _ptStartPoint; + _LinePosition.ptEndPoint = _ptStartPoint; + _LinePosition.ptEndPoint.y = (*_iter).ptStartPoint.y; + pLineInfo_->vecPositions.push_back(_LinePosition); + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).ptEndPoint.y, _LinePosition.ptStartPoint.y)) + { + (*_iter).ptStartPoint.y = (*_itera).ptStartPoint.y; + (*_it).vecPositions.erase(_itera); + } + else + (*_iter).ptStartPoint.y = _LinePosition.ptStartPoint.y; + } + else + (*_iter).ptStartPoint.y = _LinePosition.ptStartPoint.y; + + return true; + } + else if (_float_less(_ptStartPoint.y, (*_iter).ptStartPoint.y) && _float_equ(_ptEndPoint.y, (*_iter).ptStartPoint.y)) + { + LinePosition _LinePosition; + _LinePosition.ptStartPoint = _ptStartPoint; + _LinePosition.ptEndPoint = _ptStartPoint; + _LinePosition.ptEndPoint.y = (*_iter).ptStartPoint.y; + pLineInfo_->vecPositions.push_back(_LinePosition); + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).ptEndPoint.y, _LinePosition.ptStartPoint.y)) + { + (*_iter).ptStartPoint.y = (*_itera).ptStartPoint.y; + (*_it).vecPositions.erase(_itera); + } + else + (*_iter).ptStartPoint.y = _LinePosition.ptStartPoint.y; + } + else + (*_iter).ptStartPoint.y = _LinePosition.ptStartPoint.y; + + return _bModified; + } + else if (_float_less(_ptStartPoint.y, (*_iter).ptStartPoint.y) && _float_less(_ptEndPoint.y, (*_iter).ptStartPoint.y)) + { + LinePosition _LinePosition; + _LinePosition.ptStartPoint = _ptStartPoint; + _LinePosition.ptEndPoint = _ptEndPoint; + pLineInfo_->vecPositions.push_back(_LinePosition); + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).ptEndPoint.y, _LinePosition.ptStartPoint.y)) + (*_itera).ptEndPoint.y = _LinePosition.ptEndPoint.y; + else + _iter = (*_it).vecPositions.insert(_iter, _LinePosition); + } + else + _iter = (*_it).vecPositions.insert(_iter, _LinePosition); + + return _bModified; + } + else if (_float_ge(_ptStartPoint.y, (*_iter).ptStartPoint.y) && _float_great(_ptEndPoint.y, (*_iter).ptEndPoint.y)) + { + _ptStartPoint.y = (*_iter).ptEndPoint.y; + _bModified = true; + } + else if (_float_ge(_ptStartPoint.y, (*_iter).ptStartPoint.y) && _float_le(_ptEndPoint.y, (*_iter).ptEndPoint.y)) + { + return true; + } + } + + LinePosition _LinePosition; + _LinePosition.ptStartPoint = _ptStartPoint; + _LinePosition.ptEndPoint = _ptEndPoint; + pLineInfo_->vecPositions.push_back(_LinePosition); + + std::list::iterator _iter = (*_it).vecPositions.end(); + --_iter; + if (_float_equ((*_iter).ptEndPoint.y, _LinePosition.ptStartPoint.y)) + { + (*_iter).ptEndPoint.y = _LinePosition.ptEndPoint.y; + } + else + (*_it).vecPositions.push_back(_LinePosition); + + return _bModified; + } + else + { + m_vecLineInfo_SlopeUnExist.insert(_it, *pLineInfo_); + return false; + } + } + + m_vecLineInfo_SlopeUnExist.push_back(*pLineInfo_); + return false; + } + else + { + m_vecLineInfo_SlopeUnExist.push_back(*pLineInfo_); + return false; + } + } +} + +//返回该段圆弧是否被修改过,如果该圆弧有与某圆弧重复的部分被删除,则表示其被修改过,函数调用之后pArcInfo_对象中的重复部分将被删除 潘乐婷 2010-7-12 +bool CCamRepeatedDelete::ModifyArc(ArcInfo* pArcInfo_) +{ + double _nRadius = pArcInfo_->nRadius; + DPOINT3 _ptCenterPoint = pArcInfo_->ptCenterPoint; + ASSERT(pArcInfo_->vecPositions.size() == 1); + std::list _ArcPositionOrig; + _ArcPositionOrig.clear(); + _ArcPositionOrig.push_back(pArcInfo_->vecPositions.front()); + + if (_ArcPositionOrig.front().nEndAngle > 2 * ncmath::c_nPIE) + { + //如果该圆弧的终点角度大于2pie,则将该圆弧分成起始角度到2pie与2pie到终止角度的两端圆弧, + double _nEndAngle = _ArcPositionOrig.front().nEndAngle; + DPOINT3 _ptEndPoint =_ArcPositionOrig.front().ptEndPoint; + _ArcPositionOrig.front().nEndAngle = 2 * ncmath::c_nPIE; + DPOINT3 _ptMiddlePoint = CalcPoint(_ptCenterPoint, _nRadius, 0.); + _ArcPositionOrig.front().ptEndPoint = _ptMiddlePoint; + + ArcPosition _ArcPosition(0., _nEndAngle - 2 * ncmath::c_nPIE, _ptMiddlePoint, _ptEndPoint); + _ArcPositionOrig.push_back(_ArcPosition); + } + + if (m_vecArcInfo.size() != 0) + { + for (arcinfo_holder::iterator _it = m_vecArcInfo.begin(); _it != m_vecArcInfo.end(); ++_it) + { + if (_float_equ((*_it).nRadius, pArcInfo_->nRadius) + && _float_equ((*_it).ptCenterPoint.x, pArcInfo_->ptCenterPoint.x) + && _float_equ((*_it).ptCenterPoint.y, pArcInfo_->ptCenterPoint.y)) + { + pArcInfo_->vecPositions.clear(); + + int _nRound = 0; + bool _bRound = _ArcPositionOrig.size() == 1 ? false : true; + bool _bModified = false; + for (std::list::iterator _iterOrig = _ArcPositionOrig.begin(); _iterOrig != _ArcPositionOrig.end(); ++_iterOrig, ++_nRound) + { + double _nStartAngle = (*_iterOrig).nStartAngle; + double _nEndAngle = (*_iterOrig).nEndAngle; + DPOINT3 _ptStartPoint = (*_iterOrig).ptStartPoint; + DPOINT3 _ptEndPoint = (*_iterOrig).ptEndPoint; + bool _bFinished = false; + + for (std::list::iterator _iter = (*_it).vecPositions.begin(); _iter != (*_it).vecPositions.end(); ++_iter) + { + if (_float_ge(_nStartAngle, (*_iter).nEndAngle)) + continue; + else if (_float_less(_nStartAngle, (*_iter).nStartAngle) && _float_great(_nEndAngle, (*_iter).nEndAngle)) + { + DPOINT3 _ptEnd = CalcPoint(_ptCenterPoint, _nRadius, (*_iter).nStartAngle); + if (pArcInfo_->vecPositions.size() != 0 && DOUBLE_EQU(pArcInfo_->vecPositions.back().nEndAngle, _nStartAngle + 2 * ncmath::c_nPIE)) + { + pArcInfo_->vecPositions.back().nEndAngle = (*_iter).nStartAngle + 2 * ncmath::c_nPIE; + pArcInfo_->vecPositions.back().ptEndPoint = _ptEnd; + } + else + { + ArcPosition _ArcPosition(_nStartAngle, (*_iter).nStartAngle, _ptStartPoint, _ptEnd); + pArcInfo_->vecPositions.push_back(_ArcPosition); + } + +#ifdef _DEBUG + DPOINT3 _ptStart = CalcPoint((*_it).ptCenterPoint, (*_it).nRadius, _nStartAngle); +#endif + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).nEndAngle, _nStartAngle)) + { + (*_iter).nStartAngle = (*_itera).nStartAngle; + (*_it).vecPositions.erase(_itera); + } + else + (*_iter).nStartAngle = _nStartAngle; + } + else + (*_iter).nStartAngle = _nStartAngle; + + _nStartAngle = (*_iter).nEndAngle; + _ptStartPoint = CalcPoint(_ptCenterPoint, _nRadius, (*_iter).nEndAngle); + _bModified = true; + } + else if (_float_less(_nStartAngle, (*_iter).nStartAngle) && _float_great(_nEndAngle, (*_iter).nStartAngle) && _float_le(_nEndAngle, (*_iter).nEndAngle)) + { + DPOINT3 _ptEnd = CalcPoint(_ptCenterPoint, _nRadius, (*_iter).nStartAngle); + if (pArcInfo_->vecPositions.size() != 0 && DOUBLE_EQU(pArcInfo_->vecPositions.back().nEndAngle, _nStartAngle + 2 *ncmath::c_nPIE)) + { + pArcInfo_->vecPositions.back().nEndAngle = (*_iter).nStartAngle + 2 *ncmath::c_nPIE; + pArcInfo_->vecPositions.back().ptEndPoint = _ptEnd; + } + else + { + ArcPosition _ArcPosition(_nStartAngle, (*_iter).nStartAngle, _ptStartPoint, _ptEnd); + pArcInfo_->vecPositions.push_back(_ArcPosition); + } +#ifdef _DEBUG + DPOINT3 _ptStart = CalcPoint((*_it).ptCenterPoint, (*_it).nRadius, (*_iter).nStartAngle); +#endif + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).nEndAngle, _nStartAngle)) + { + (*_iter).nStartAngle = (*_itera).nStartAngle; + (*_it).vecPositions.erase(_itera); + } + else + (*_iter).nStartAngle = _nStartAngle; + } + else + (*_iter).nStartAngle = _nStartAngle; + + if (_nRound || !_bRound) + return true; + else + { + _bModified = true; + _bFinished = true; + break; + } + } + else if (_float_less(_nStartAngle, (*_iter).nStartAngle) && _float_equ(_nEndAngle, (*_iter).nStartAngle)) + { + DPOINT3 _ptEnd = CalcPoint(_ptCenterPoint, _nRadius, (*_iter).nStartAngle); + if (pArcInfo_->vecPositions.size() != 0 && DOUBLE_EQU(pArcInfo_->vecPositions.back().nEndAngle, _nStartAngle + 2 * ncmath::c_nPIE)) + { + pArcInfo_->vecPositions.back().nEndAngle = (*_iter).nStartAngle + 2 *ncmath::c_nPIE; + pArcInfo_->vecPositions.back().ptEndPoint = _ptEnd; + } + else + { + ArcPosition _ArcPosition(_nStartAngle, (*_iter).nStartAngle, _ptStartPoint, _ptEnd); + pArcInfo_->vecPositions.push_back(_ArcPosition); + } +#ifdef _DEBUG + DPOINT3 _ptStart = CalcPoint((*_it).ptCenterPoint, (*_it).nRadius, _nStartAngle); +#endif + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).nEndAngle, _nStartAngle)) + { + (*_iter).nStartAngle = (*_itera).nStartAngle; + (*_it).vecPositions.erase(_itera); + } + else + (*_iter).nStartAngle = _nStartAngle; + } + else + (*_iter).nStartAngle = _nStartAngle; + + if (_nRound || !_bRound) + return _bModified; + else + { + _bFinished = true; + break; + } + } + else if (_float_less(_nStartAngle, (*_iter).nStartAngle) && _float_less(_nEndAngle, (*_iter).nStartAngle)) + { + ArcPosition _ArcPosition(_nStartAngle, _nEndAngle, _ptStartPoint, _ptEndPoint); + if (pArcInfo_->vecPositions.size() != 0 && DOUBLE_EQU(pArcInfo_->vecPositions.back().nEndAngle, _nStartAngle + 2 * ncmath::c_nPIE)) + { + pArcInfo_->vecPositions.back().nEndAngle = (*_iter).nStartAngle + 2 * ncmath::c_nPIE; + pArcInfo_->vecPositions.back().ptEndPoint = _ptEndPoint; + } + else + { + pArcInfo_->vecPositions.push_back(_ArcPosition); + } +#ifdef _DEBUG + DPOINT3 _ptStart = CalcPoint((*_it).ptCenterPoint, (*_it).nRadius, _nStartAngle); + DPOINT3 _ptEnd = CalcPoint((*_it).ptCenterPoint, (*_it).nRadius, _nEndAngle); +#endif + + if (_iter != (*_it).vecPositions.begin()) + { + std::list::iterator _itera = _iter; + --_itera; + if (_float_equ((*_itera).nEndAngle, _nStartAngle)) + (*_itera).nEndAngle = _nEndAngle; + else + _iter = (*_it).vecPositions.insert(_iter, _ArcPosition); + } + else + _iter = (*_it).vecPositions.insert(_iter, _ArcPosition); + + if (_nRound || !_bRound) + return _bModified; + else + { + _bFinished = true; + break; + } + } + else if (_float_ge(_nStartAngle, (*_iter).nStartAngle) && _float_great(_nEndAngle, (*_iter).nEndAngle)) + { + _nStartAngle = (*_iter).nEndAngle; + _ptStartPoint = CalcPoint(_ptCenterPoint, _nRadius, (*_iter).nEndAngle); +#ifdef _DEBUG + DPOINT3 _ptStart = CalcPoint((*_it).ptCenterPoint, (*_it).nRadius, (*_iter).nEndAngle); +#endif + _bModified = true; + } + else if (_float_ge(_nStartAngle, (*_iter).nStartAngle) && _float_le(_nEndAngle, (*_iter).nEndAngle)) + { + if (_nRound || !_bRound) + return true; + else + { + _bFinished = true; + _bModified = true; + break; + } + } + } + + if (!_bFinished) + { + ArcPosition _ArcPosition(_nStartAngle, _nEndAngle, _ptStartPoint, _ptEndPoint); + pArcInfo_->vecPositions.push_back(_ArcPosition); + + std::list::iterator _iter = (*_it).vecPositions.end(); + --_iter; + if (_float_equ((*_iter).nEndAngle, _ArcPosition.nStartAngle)) + { + (*_iter).nEndAngle = _ArcPosition.nEndAngle; + } + else + (*_it).vecPositions.push_back(_ArcPosition); + + if (_nRound || !_bRound) + return _bModified; + } + } + } + else if (_float_great((*_it).nRadius, pArcInfo_->nRadius)) + { + arcinfo_holder::iterator _itTemp = _it; + if (++_itTemp == m_vecArcInfo.end()) + { + if (_ArcPositionOrig.size() > 1) + { + if (_float_equ(_ArcPositionOrig.back().nEndAngle, _ArcPositionOrig.front().nStartAngle)) + { + ArcInfo _ArcInfo = *pArcInfo_; + _ArcInfo.vecPositions.front().nStartAngle = 0.; + _ArcInfo.vecPositions.front().nEndAngle = 2 * ncmath::c_nPIE; + m_vecArcInfo.push_back(_ArcInfo); + } + else + { + ArcInfo _ArcInfo = *pArcInfo_; + _ArcInfo.vecPositions.clear(); + for (std::list::reverse_iterator _it = _ArcPositionOrig.rbegin(); _it != _ArcPositionOrig.rend(); ++_it) + { + _ArcInfo.vecPositions.push_back(*_it); + } + + m_vecArcInfo.push_back(_ArcInfo); + } + } + else + m_vecArcInfo.push_back(*pArcInfo_); + + return false; + } + } + } + + if (_ArcPositionOrig.size() > 1) + { + if (_float_equ(_ArcPositionOrig.back().nEndAngle, _ArcPositionOrig.front().nStartAngle)) + { + ArcInfo _ArcInfo = *pArcInfo_; + _ArcInfo.vecPositions.front().nStartAngle = 0.; + _ArcInfo.vecPositions.front().nEndAngle = 2 * ncmath::c_nPIE; + m_vecArcInfo.push_back(_ArcInfo); + } + else + { + ArcInfo _ArcInfo = *pArcInfo_; + _ArcInfo.vecPositions.clear(); + for (std::list::reverse_iterator _it = _ArcPositionOrig.rbegin(); _it != _ArcPositionOrig.rend(); ++_it) + { + _ArcInfo.vecPositions.push_back(*_it); + } + + m_vecArcInfo.push_back(_ArcInfo); + } + } + else + m_vecArcInfo.push_back(*pArcInfo_); + + return false; + } + else + { + if (_ArcPositionOrig.size() > 1) + { + if (_float_equ(_ArcPositionOrig.back().nEndAngle, _ArcPositionOrig.front().nStartAngle)) + { + ArcInfo _ArcInfo = *pArcInfo_; + _ArcInfo.vecPositions.front().nStartAngle = 0.; + _ArcInfo.vecPositions.front().nEndAngle = 2 * ncmath::c_nPIE; + m_vecArcInfo.push_back(_ArcInfo); + } + else + { + ArcInfo _ArcInfo = *pArcInfo_; + _ArcInfo.vecPositions.clear(); + for (std::list::reverse_iterator _it = _ArcPositionOrig.rbegin(); _it != _ArcPositionOrig.rend(); ++_it) + { + _ArcInfo.vecPositions.push_back(*_it); + } + + m_vecArcInfo.push_back(_ArcInfo); + } + } + else + m_vecArcInfo.push_back(*pArcInfo_); + + return false; + } +} + +//根据直线终点的类型,直线起点的坐标,从该数据的内存块中读取直线终点坐标 +//调用后内存地址增加,调用前要确保该段为直线 潘乐婷 2009-12-8 +void CCamRepeatedDelete::GetLineNode(IN const nce::CCamPath::NODE& Node_, IN OUT DPOINT3& nxCurPoint_) +{ + switch (Node_.nType) + { + case CCamPath::nt_line_x: + { + nxCurPoint_.x = Node_.ptEnd.x; + } + break; + + case CCamPath::nt_line_y: + { + nxCurPoint_.y = Node_.ptEnd.y; + } + break; + + case CCamPath::nt_line_z: + { + nxCurPoint_.z = Node_.ptEnd.z; + } + break; + + case CCamPath::nt_line_xy: + { + nxCurPoint_.x = Node_.ptEnd.x; + nxCurPoint_.y = Node_.ptEnd.y; + } + break; + + case CCamPath::nt_line_zx: + { + nxCurPoint_.x = Node_.ptEnd.x; + nxCurPoint_.z = Node_.ptEnd.z; + } + break; + + case CCamPath::nt_line_yz: + { + nxCurPoint_.y = Node_.ptEnd.y; + nxCurPoint_.z = Node_.ptEnd.z; + } + break; + + case CCamPath::nt_line_xyz: + { + nxCurPoint_.x = Node_.ptEnd.x; + nxCurPoint_.y = Node_.ptEnd.y; + nxCurPoint_.z = Node_.ptEnd.z; + } + break; + + default: + ASSERT(false); + break; + } +} + +//根据圆弧的类型,圆弧起点的坐标,从该数据的内存块中读取圆弧终点坐标和该段圆弧的凸度 +//调用后内存地址增加,调用前要确保该段为圆弧 潘乐婷 2009-12-8 +void CCamRepeatedDelete::GetArcNode(IN const nce::CCamPath::NODE& Node_, IN OUT DPOINT3& nxCurPoint_, OUT double& nBulge_) +{ + nBulge_ = Node_.nBulge; + switch (Node_.nType) + { + case CCamPath::nt_arc_xy: + nxCurPoint_.x = Node_.ptEnd.x; + nxCurPoint_.y = Node_.ptEnd.y; + break; + + case CCamPath::nt_arc_zx: + nxCurPoint_.x = Node_.ptEnd.x; + nxCurPoint_.z = Node_.ptEnd.z; + break; + + case CCamPath::nt_arc_yz: + nxCurPoint_.y = Node_.ptEnd.y; + nxCurPoint_.z = Node_.ptEnd.z; + break; + + default: + ASSERT(false); + break; + } +} + +//根据圆的类型,圆起点的坐标,从该数据的内存块中读取圆心坐标和该圆的半径 +//调用后内存地址增加,调用前要确保该段为圆 潘乐婷 2009-12-8 +void CCamRepeatedDelete::GetCircleNode(IN const CCamPath::NODE& Node_, IN OUT DPOINT3& nxCurPoint_, OUT double& nRadius_) +{ + nRadius_ = Node_.nRadius; + switch (Node_.nType) + { + case CCamPath::nt_circle_xy_cw: + case CCamPath::nt_circle_xy_ccw: + { + nxCurPoint_.x = Node_.ptCenter.x; + nxCurPoint_.y = Node_.ptCenter.y; + } + break; + + case CCamPath::nt_circle_zx_cw: + case CCamPath::nt_circle_zx_ccw: + { + nxCurPoint_.x = Node_.ptCenter.x; + nxCurPoint_.z = Node_.ptCenter.z; + } + break; + + case CCamPath::nt_circle_yz_cw: + case CCamPath::nt_circle_yz_ccw: + { + nxCurPoint_.y = Node_.ptCenter.y; + nxCurPoint_.z = Node_.ptCenter.z; + } + break; + + default: + ASSERT(false); + break; + } +} + +void CCamRepeatedDelete::CamRepeatedDelete_Hole(IN OUT CCamGroup* pDestCamGroup_) +{ + for (CamObjectList::iterator _it = pDestCamGroup_->GetObjectsList()->begin(); _it != pDestCamGroup_->GetObjectsList()->end();) + { + if ((*_it)->GetType() == camhole) + { + if (ModifyHole(&((CCamHole*)(*_it))->GetStart())) + { + CCamHole* _pHole = reinterpret_cast(*_it); + delete _pHole; + _it = pDestCamGroup_->GetObjectsList()->erase(_it); + } + else + ++_it; + } + else if ((*_it)->GetType() == camgroup) + { + CamRepeatedDelete_Hole((CCamGroup*)(*_it)); + ++_it; + } + else + ++_it; + } +} + +//该点是否重复,如果该点在某圆弧或线段上或者已存在某点坐标与该点相同则表示该点是重复的点 潘乐婷 2010-7-12 +bool CCamRepeatedDelete::ModifyHole(const DPOINT3* pHolePoint_) +{ + holeinfo_holder::iterator _itera = m_vecHoleInfo.begin(); + for (; _itera != m_vecHoleInfo.end(); ++_itera) + { + if (_float_equ((*_itera).x, pHolePoint_->x) && _float_equ((*_itera).y, pHolePoint_->y)) + return true; + else if (_float_great(pHolePoint_->x, (*_itera).x) || (_float_equ(pHolePoint_->x, (*_itera).x) && _float_great(pHolePoint_->y, (*_itera).y))) + break; + } + + for (lineinfo_holder::iterator _it = m_vecLineInfo_SlopeUnExist.begin(); _it != m_vecLineInfo_SlopeUnExist.end(); ++_it) + { + if (_float_equ((*_it).nCoefficientA, pHolePoint_->x)) + { + for (std::list::iterator _iter = (*_it).vecPositions.begin(); _iter != (*_it).vecPositions.end(); ++_iter) + { + if (_float_great(pHolePoint_->y, (*_iter).ptEndPoint.y)) + continue; + else if (_float_ge(pHolePoint_->y, (*_iter).ptStartPoint.y) && _float_le(pHolePoint_->y, (*_iter).ptEndPoint.y)) + return true; + else + break; + } + } + else if (_float_great((*_it).nCoefficientA, pHolePoint_->x)) + break; + } + + for (lineinfo_holder::iterator _it = m_vecLineInfo_SlopeExist.begin(); _it != m_vecLineInfo_SlopeExist.end(); ++_it) + { + if (_float_equ_CoeB(pHolePoint_->y, (*_it).nCoefficientA * pHolePoint_->x + (*_it).nCoefficientB)) + { + for (std::list::iterator _iter = (*_it).vecPositions.begin(); _iter != (*_it).vecPositions.end(); ++_iter) + { + if (_float_great(pHolePoint_->x, (*_iter).ptEndPoint.x)) + continue; + else if (_float_ge(pHolePoint_->x, (*_iter).ptStartPoint.x) && _float_le(pHolePoint_->x, (*_iter).ptEndPoint.x)) + return true; + else + break; + } + } + } + + for (arcinfo_holder::iterator _it = m_vecArcInfo.begin(); _it != m_vecArcInfo.end(); ++_it) + { + double _nDis = sqrt((pHolePoint_->x - (*_it).ptCenterPoint.x) * (pHolePoint_->x - (*_it).ptCenterPoint.x) + + (pHolePoint_->y - (*_it).ptCenterPoint.y) *(pHolePoint_->y - (*_it).ptCenterPoint.y)); + if (_float_equ(_nDis, (*_it).nRadius)) + { + double _nAngle = ncmath::D2GetNormalAngle(pHolePoint_->x - (*_it).ptCenterPoint.x, pHolePoint_->y - (*_it).ptCenterPoint.y); + + for (std::list::iterator _iter = (*_it).vecPositions.begin(); _iter != (*_it).vecPositions.end(); ++_iter) + { + if (_float_great(_nAngle, (*_iter).nEndAngle)) + continue; + else if (_float_ge(_nAngle, (*_iter).nStartAngle) && _float_le(_nAngle, (*_iter).nEndAngle)) + return true; + else + break; + } + } + } + + m_vecHoleInfo.insert(_itera, *pHolePoint_); + // 该点和任何图形都不重合,记录该点,然后返回false 孙彦春 2012-8-5 + return false; +} + +double nce::CalculateBulge(double nAngleStart_, double nAngleEnd_) +{ + double _theta = (nAngleEnd_ - nAngleStart_) / 4.; + ASSERT(!DOUBLE_EQU(fabs(_theta), ncmath::c_nPIE / 2.)); + double _nBulge = tan(_theta); + return _nBulge; +} + +bool CCamRepeatedDelete::DPOINT3_EQU(const DPOINT3& pt1_, const DPOINT3& pt2_) +{ + bool _bSkipAll = true; + for (int _i = 0; _i != 3; ++_i) + { + if (!IsValidDouble(pt1_[_i]) && !IsValidDouble(pt2_[_i])) + { + continue; + } + // 没有执行continue;说明至少有一个是有效double数字 孙彦春 2012-7-25 + _bSkipAll = false; + if (!IsValidDouble(pt1_[_i]) || !IsValidDouble(pt2_[_i])) + { + return false; + } + // + if (!DOUBLE_EQU(pt1_[_i], pt2_[_i])) + { + return false; + } + } + if (_bSkipAll) + { + return false; + } + return true; +} + +size_t CCamRepeatedDelete::GetCamgroupSize(const CCamGroup* pCamGroup_) +{ + size_t _nSize = 0; + for (CamObjectList::const_iterator _it = pCamGroup_->GetObjectsList()->begin(); _it != pCamGroup_->GetObjectsList()->end(); ++_it) + { + cam_t _type = (*_it)->GetType(); + if (_type == camhole || _type == campath) + { + ++_nSize; + } + else if (_type == camgroup) + { + _nSize += GetCamgroupSize((CCamGroup*)(*_it)); + } + else/* if(_type == camobject || _type == camscanlines)*/ + { + ASSERT(FALSE); + } + } + return _nSize; +} + +// 给定节点lineInfo_,找到第一个小于lineInfo_的节点的迭代器作为返回值,找不到时返回vectorLineInfo_SlopeExist.end(); +lineinfo_holder::const_iterator CCamRepeatedDelete::bsearchLineInfo(const LineInfo* lineInfo_, const lineinfo_holder& ListLineInfo_SlopeExist) +{ + lineinfo_holder::iterator iLineInfo; + size_t _nSize = ListLineInfo_SlopeExist.size(); + if (_nSize == 0) + return ListLineInfo_SlopeExist.end(); + + lineinfo_holder::const_iterator _itBegin = ListLineInfo_SlopeExist.begin(); + lineinfo_holder::const_iterator _itEnd = ListLineInfo_SlopeExist.end(); + lineinfo_holder::const_iterator _itMiddle = ListLineInfo_SlopeExist.begin(); + _nSize = (_nSize - 1) / 2; + while(_nSize--) + { + ++_itMiddle; + } + LineInfo _MiddleLineInfo = *_itMiddle; + if (lineInfo_ < &_MiddleLineInfo) + { + while(_itMiddle != _itEnd) + { + _itMiddle++; + _MiddleLineInfo = *_itMiddle; + if (lineInfo_ < &_MiddleLineInfo) + { + continue; + } + else + { + _itMiddle--; + return (_itMiddle); + } + } + } + else + { + while(_itMiddle != _itBegin) + { + _itMiddle--; + _MiddleLineInfo = *_itMiddle; + if (lineInfo_ < &_MiddleLineInfo) + { + return _itMiddle; + } + } + } + + return ListLineInfo_SlopeExist.end(); +} + +bool nce::LineInfo::operator<(const LineInfo& other_) +{ + ASSERT(bSlopeExist && other_.bSlopeExist); + if (_float_great(nCoefficientA, other_.nCoefficientA)) + { + return false; + } + if (_float_less(nCoefficientA, other_.nCoefficientA)) + { + return true; + } + if (_float_equ(nCoefficientA, other_.nCoefficientA)) + { + if (_float_great(nCoefficientB, other_.nCoefficientB)) + { + return false; + } + else if (_float_less(nCoefficientB, other_.nCoefficientB)) + { + return true; + } + else + { + ASSERT(_float_equ(nCoefficientB, other_.nCoefficientB)); + ASSERT(other_.vecPositions.size() == 1); + ASSERT(vecPositions.size() == 1); + + DPOINT3 _ptStartPoint = other_.vecPositions.front().ptStartPoint; + DPOINT3 _ptEndPointthis = vecPositions.front().ptEndPoint; + + if (_float_less(_ptEndPointthis.x, _ptStartPoint.x)) + return true; + else + return false; + } + } + ASSERT(FALSE); + return false; +} diff --git a/src/ClientAdapter.cpp b/src/ClientAdapter.cpp new file mode 100644 index 0000000..d71a3b4 --- /dev/null +++ b/src/ClientAdapter.cpp @@ -0,0 +1,1455 @@ +// Copyright 漏 2010 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +#include "Stdafx.h" +#include "ClientAdapter.h" + +#include "include\cef_client.h" +#include "include\wrapper\cef_stream_resource_handler.h" + +#include "CefAuthCallbackWrapper.h" +#include "CefBeforeDownloadCallbackWrapper.h" +#include "CefCertificateCallbackWrapper.h" +#include "CefContextMenuParamsWrapper.h" +#include "CefDownloadItemCallbackWrapper.h" +#include "DragData.h" +#include "CefFileDialogCallbackWrapper.h" +#include "CefFrameWrapper.h" +#include "CefJSDialogCallbackWrapper.h" +#include "CefMenuModelWrapper.h" +#include "Request.h" +#include "CefResourceRequestHandlerAdapter.h" +#include "CefRequestCallbackWrapper.h" +#include "CefRunContextMenuCallbackWrapper.h" +#include "CefSslInfoWrapper.h" +#include "CefBrowserWrapper.h" +#include "ManagedCefBrowserAdapter.h" +#include "Messaging\Messages.h" +#include "PopupFeatures.h" +#include "Serialization\Primitives.h" +#include "Serialization\V8Serialization.h" +#include "Serialization\JsObjectsSerialization.h" +#include "Serialization\ObjectsSerialization.h" +#include "TypeConversion.h" +#include "WindowInfo.h" + +using namespace CefSharp::Internals::Messaging; +using namespace CefSharp::Internals::Serialization; +using namespace System::Security::Cryptography::X509Certificates; + +namespace CefSharp +{ + namespace Internals + { + IBrowser^ ClientAdapter::GetBrowserWrapper(int browserId) + { + if (_cefBrowser.get()) + { + if (_cefBrowser->GetIdentifier() == browserId) + { + return _browser; + } + + //IJavascriptCallbacks that are finalized after the browser has been Disposed + //but before the IBrowserAdapter.IsDisposed is set might end up here + //attempting to access _popupBrowsers which has been set to null already. + auto popupBrowsers = _popupBrowsers; + + if (Object::ReferenceEquals(popupBrowsers, nullptr)) + { + return nullptr; + } + + IBrowser^ popupBrowser; + if (popupBrowsers->TryGetValue(browserId, popupBrowser)) + { + return popupBrowser; + } + } + + return nullptr; + } + + IBrowser^ ClientAdapter::GetBrowserWrapper(int browserId, bool isPopup) + { + if (_browserControl->HasParent) + { + return _browser; + } + + if (isPopup) + { + IBrowser^ popupBrowser; + if (_popupBrowsers->TryGetValue(browserId, popupBrowser)) + { + return popupBrowser; + } + + return nullptr; + } + + return _browser; + } + + void ClientAdapter::CloseAllPopups(bool forceClose) + { + if (_popupBrowsers->Count > 0) + { + for each (IBrowser^ browser in _popupBrowsers->Values) + { + browser->GetHost()->CloseBrowser(forceClose); + // NOTE: We don't dispose the IBrowsers here + // because ->CloseBrowser() will invoke + // ->OnBeforeClose() for the browser. + // OnBeforeClose() disposes the IBrowser there. + } + } + } + + bool ClientAdapter::OnBeforePopup(CefRefPtr browser, CefRefPtr frame, const CefString& target_url, + const CefString& target_frame_name, CefLifeSpanHandler::WindowOpenDisposition target_disposition, bool user_gesture, + const CefPopupFeatures& popupFeatures, CefWindowInfo& windowInfo, + CefRefPtr& client, CefBrowserSettings& settings, CefRefPtr& extraInfo, bool* no_javascript_access) + { + auto handler = _browserControl->LifeSpanHandler; + + if (handler == nullptr) + { + return false; + } + + IWebBrowser^ newBrowser = nullptr; + bool createdWrapper = false; + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + CefFrameWrapper frameWrapper(frame); + PopupFeatures popupFeaturesWrapper(&popupFeatures); + BrowserSettings browserSettingsWrapper(&settings); + WindowInfo windowInfoWrapper(&windowInfo); + + auto result = handler->OnBeforePopup( + _browserControl, browserWrapper, + %frameWrapper, StringUtils::ToClr(target_url), + StringUtils::ToClr(target_frame_name), + (CefSharp::WindowOpenDisposition)target_disposition, + user_gesture, %popupFeaturesWrapper, + %windowInfoWrapper, %browserSettingsWrapper, *no_javascript_access, newBrowser); + + if (newBrowser != nullptr) + { + //newBrowser should never be set to _browserControl (I've seen user code where someone attepted to do this). + //So throw exception to make that perfectly clear. + if (Object::ReferenceEquals(_browserControl, newBrowser)) + { + throw gcnew Exception("newBrowser should be a new instance of ChromiumWebBrowser or null."); + } + + //newBrowser is not null and result is true, whilst the documentation clearly states returning true will + //cancel popup creation people keep expecting that newBrowser will do something which it won't + if (result == true) + { + throw gcnew Exception("returning true cancels popup creation, if you return true newBrowser should be set to null." + + "Previously no exception was thrown in this instance, this exception has been added to reduce the number of" + + " support requests from people returning true and setting newBrowser and expecting popups to work."); + } + + auto newBrowserInternal = dynamic_cast(newBrowser); + + if (newBrowserInternal != nullptr) + { + //This should already be set using the SetAsPopup extension, just making doubly sure + newBrowserInternal->HasParent = true; + + auto browserAdapter = dynamic_cast(newBrowserInternal->BrowserAdapter); + if (browserAdapter != nullptr) + { + client = browserAdapter->GetClientAdapter().get(); + } + } + } + + return result; + } + + void ClientAdapter::OnAfterCreated(CefRefPtr browser) + { + BrowserRefCounter::Instance->Increment(); + + auto browserWrapper = gcnew CefBrowserWrapper(browser); + + auto isPopup = browser->IsPopup() && !_browserControl->HasParent; + + if (isPopup) + { + // Add to the list of popup browsers. + _popupBrowsers->Add(browser->GetIdentifier(), browserWrapper); + } + else + { + _browserHwnd = browser->GetHost()->GetWindowHandle(); + _cefBrowser = browser; + + _browser = browserWrapper; + + if (!Object::ReferenceEquals(_browserAdapter, nullptr)) + { + _browserAdapter->OnAfterBrowserCreated(browserWrapper); + } + } + + auto handler = _browserControl->LifeSpanHandler; + + if (handler != nullptr) + { + handler->OnAfterCreated(_browserControl, browserWrapper); + } + } + + bool ClientAdapter::DoClose(CefRefPtr browser) + { + auto handler = _browserControl->LifeSpanHandler; + + if (handler != nullptr) + { + //By this point it's possible IBrowser references have been disposed + //Rather than attempting to rework the rather complex closing logic + //It's easier to pass in a new wrapper and dispose it straight away + CefBrowserWrapper browserWrapper(browser); + + return handler->DoClose(_browserControl, %browserWrapper); + } + + return false; + } + + void ClientAdapter::OnBeforeClose(CefRefPtr browser) + { + auto isPopup = browser->IsPopup() && !_browserControl->HasParent; + auto handler = _browserControl->LifeSpanHandler; + + if (handler != nullptr) + { + //By this point it's possible IBrowser references have been disposed + //Rather than attempting to rework the rather complex closing logic + //It's easier to pass in a new wrapper and dispose it straight away + CefBrowserWrapper browserWrapper(browser); + + handler->OnBeforeClose(_browserControl, %browserWrapper); + } + + if (isPopup) + { + // Remove from the browser popup list. + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), true); + _popupBrowsers->Remove(browser->GetIdentifier()); + // Dispose the CefBrowserWrapper + delete browserWrapper; + } + //TODO: When creating a new ChromiumWebBrowser and passing in a newBrowser to OnBeforePopup + //the handles don't match up (at least in WPF), need to investigate further. + else if (_browserHwnd == browser->GetHost()->GetWindowHandle() || _browserControl->HasParent) + { + _cefBrowser = NULL; + } + + BrowserRefCounter::Instance->Decrement(); + } + + void ClientAdapter::OnLoadingStateChange(CefRefPtr browser, bool isLoading, bool canGoBack, bool canGoForward) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto args = gcnew LoadingStateChangedEventArgs(browserWrapper, canGoBack, canGoForward, isLoading); + + if (!browser->IsPopup() || _browserControl->HasParent) + { + _browserControl->SetLoadingStateChange(args); + } + + auto handler = _browserControl->LoadHandler; + + if (handler != nullptr) + { + handler->OnLoadingStateChange(_browserControl, args); + } + } + + void ClientAdapter::OnAddressChange(CefRefPtr browser, CefRefPtr frame, const CefString& address) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto args = gcnew AddressChangedEventArgs(browserWrapper, StringUtils::ToClr(address)); + + if (!browser->IsPopup() || _browserControl->HasParent) + { + _browserControl->SetAddress(args); + } + + auto handler = _browserControl->DisplayHandler; + + if (handler != nullptr) + { + handler->OnAddressChanged(_browserControl, args); + } + } + + bool ClientAdapter::OnAutoResize(CefRefPtr browser, const CefSize& new_size) + { + auto handler = _browserControl->DisplayHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + return handler->OnAutoResize(_browserControl, browserWrapper, CefSharp::Structs::Size(new_size.width, new_size.height)); + } + + bool ClientAdapter::OnCursorChange(CefRefPtr browser, CefCursorHandle cursor, cef_cursor_type_t type, const CefCursorInfo& custom_cursor_info) + { + auto handler = _browserControl->DisplayHandler; + + if (handler == nullptr) + { + InternalCursorChange(browser, cursor, type, custom_cursor_info); + + return false; + } + + CursorInfo customCursorInfo; + + //TODO: this is duplicated in RenderClientAdapter::InternalCursorChange + //Only create the struct when we actually have a custom cursor + if (type == cef_cursor_type_t::CT_CUSTOM) + { + Point hotspot = Point(custom_cursor_info.hotspot.x, custom_cursor_info.hotspot.y); + Size size = Size(custom_cursor_info.size.width, custom_cursor_info.size.height); + customCursorInfo = CursorInfo(IntPtr((void*)custom_cursor_info.buffer), hotspot, custom_cursor_info.image_scale_factor, size); + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + auto handled = handler->OnCursorChange(_browserControl, browserWrapper, (IntPtr)cursor, (CefSharp::Enums::CursorType)type, customCursorInfo); + + if (handled) + { + return true; + } + + InternalCursorChange(browser, cursor, type, custom_cursor_info); + + return false; + }; + + void ClientAdapter::InternalCursorChange(CefRefPtr browser, CefCursorHandle cursor, cef_cursor_type_t type, const CefCursorInfo& custom_cursor_info) + { + + } + + void ClientAdapter::OnTitleChange(CefRefPtr browser, const CefString& title) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto args = gcnew TitleChangedEventArgs(browserWrapper, StringUtils::ToClr(title)); + + if (browser->IsPopup() && !_browserControl->HasParent) + { + // Set the popup window title + auto hwnd = browser->GetHost()->GetWindowHandle(); + SetWindowText(hwnd, std::wstring(title).c_str()); + } + else + { + _browserControl->SetTitle(args); + } + + auto handler = _browserControl->DisplayHandler; + + if (handler != nullptr) + { + handler->OnTitleChanged(_browserControl, args); + } + } + + void ClientAdapter::OnFaviconURLChange(CefRefPtr browser, const std::vector& iconUrls) + { + auto handler = _browserControl->DisplayHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnFaviconUrlChange(_browserControl, browserWrapper, StringUtils::ToClr(iconUrls)); + } + } + + void ClientAdapter::OnFullscreenModeChange(CefRefPtr browser, bool fullscreen) + { + auto handler = _browserControl->DisplayHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnFullscreenModeChange(_browserControl, browserWrapper, fullscreen); + } + } + + void ClientAdapter::OnLoadingProgressChange(CefRefPtr browser, double progress) + { + auto handler = _browserControl->DisplayHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnLoadingProgressChange(_browserControl, browserWrapper, progress); + } + } + + bool ClientAdapter::OnTooltip(CefRefPtr browser, CefString& text) + { + auto tooltip = StringUtils::ToClr(text); + bool hasChanged = tooltip != _tooltip; + bool returnFlag = true; + + //NOTE: Only called if tooltip changed otherwise called many times + // also only called when using OSR, https://bitbucket.org/chromiumembedded/cef/issues/783 + + if (hasChanged) + { + auto handler = _browserControl->DisplayHandler; + if (handler != nullptr) + { + returnFlag = handler->OnTooltipChanged(_browserControl, tooltip); + } + + if (!browser->IsPopup() || _browserControl->HasParent) + { + _tooltip = tooltip; + _browserControl->SetTooltipText(_tooltip); + } + } + + return returnFlag; + } + + bool ClientAdapter::OnConsoleMessage(CefRefPtr browser, cef_log_severity_t level, const CefString& message, const CefString& source, int line) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + auto args = gcnew ConsoleMessageEventArgs(browserWrapper, (LogSeverity)level, StringUtils::ToClr(message), StringUtils::ToClr(source), line); + + if (!browser->IsPopup() || _browserControl->HasParent) + { + _browserControl->OnConsoleMessage(args); + } + + auto handler = _browserControl->DisplayHandler; + if (handler == nullptr) + { + return false; + } + + return handler->OnConsoleMessage(_browserControl, args); + } + + void ClientAdapter::OnStatusMessage(CefRefPtr browser, const CefString& value) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto args = gcnew StatusMessageEventArgs(browserWrapper, StringUtils::ToClr(value)); + + if (!browser->IsPopup() || _browserControl->HasParent) + { + _browserControl->OnStatusMessage(args); + } + + auto handler = _browserControl->DisplayHandler; + if (handler != nullptr) + { + handler->OnStatusMessage(_browserControl, args); + } + } + + bool ClientAdapter::OnKeyEvent(CefRefPtr browser, const CefKeyEvent& event, CefEventHandle os_event) + { + auto handler = _browserControl->KeyboardHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + return handler->OnKeyEvent( + _browserControl, browserWrapper, (KeyType)event.type, event.windows_key_code, + event.native_key_code, + (CefEventFlags)event.modifiers, event.is_system_key == 1); + } + + bool ClientAdapter::OnPreKeyEvent(CefRefPtr browser, const CefKeyEvent& event, CefEventHandle os_event, bool* is_keyboard_shortcut) + { + auto handler = _browserControl->KeyboardHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + return handler->OnPreKeyEvent( + _browserControl, browserWrapper, (KeyType)event.type, event.windows_key_code, + event.native_key_code, (CefEventFlags)event.modifiers, event.is_system_key == 1, + *is_keyboard_shortcut); + } + + void ClientAdapter::OnLoadStart(CefRefPtr browser, CefRefPtr frame, TransitionType transitionType) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + if (!browser->IsPopup() || _browserControl->HasParent) + { + _browserControl->OnFrameLoadStart(gcnew FrameLoadStartEventArgs(browserWrapper, %frameWrapper, (CefSharp::TransitionType)transitionType)); + } + + auto handler = _browserControl->LoadHandler; + if (handler != nullptr) + { + handler->OnFrameLoadStart(_browserControl, gcnew FrameLoadStartEventArgs(browserWrapper, %frameWrapper, (CefSharp::TransitionType)transitionType)); + } + } + + void ClientAdapter::OnLoadEnd(CefRefPtr browser, CefRefPtr frame, int httpStatusCode) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + if (!browser->IsPopup() || _browserControl->HasParent) + { + _browserControl->OnFrameLoadEnd(gcnew FrameLoadEndEventArgs(browserWrapper, %frameWrapper, httpStatusCode)); + } + + auto handler = _browserControl->LoadHandler; + + if (handler != nullptr) + { + handler->OnFrameLoadEnd(_browserControl, gcnew FrameLoadEndEventArgs(browserWrapper, %frameWrapper, httpStatusCode)); + } + } + + void ClientAdapter::OnLoadError(CefRefPtr browser, CefRefPtr frame, ErrorCode errorCode, const CefString& errorText, const CefString& failedUrl) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + if (!browser->IsPopup() || _browserControl->HasParent) + { + _browserControl->OnLoadError(gcnew LoadErrorEventArgs(browserWrapper, %frameWrapper, + (CefErrorCode)errorCode, StringUtils::ToClr(errorText), StringUtils::ToClr(failedUrl))); + } + + auto handler = _browserControl->LoadHandler; + + if (handler != nullptr) + { + handler->OnLoadError(_browserControl, + gcnew LoadErrorEventArgs(browserWrapper, %frameWrapper, (CefErrorCode)errorCode, StringUtils::ToClr(errorText), StringUtils::ToClr(failedUrl))); + } + } + + bool ClientAdapter::OnBeforeBrowse(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, bool userGesture, bool isRedirect) + { + auto handler = _browserControl->RequestHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + Request requestWrapper(request); + + return handler->OnBeforeBrowse(_browserControl, browserWrapper, %frameWrapper, %requestWrapper, userGesture, isRedirect); + } + + bool ClientAdapter::OnOpenURLFromTab(CefRefPtr browser, CefRefPtr frame, const CefString& targetUrl, + CefRequestHandler::WindowOpenDisposition targetDisposition, bool userGesture) + { + auto handler = _browserControl->RequestHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + return handler->OnOpenUrlFromTab(_browserControl, browserWrapper, %frameWrapper, StringUtils::ToClr(targetUrl), (CefSharp::WindowOpenDisposition)targetDisposition, userGesture); + } + + CefRefPtr ClientAdapter::GetResourceRequestHandler(CefRefPtr browser, + CefRefPtr frame, CefRefPtr request, bool isNavigation, bool isDownload, const CefString& requestInitiator, bool& disableDefaultHandling) + { + auto handler = _browserControl->RequestHandler; + auto resourceRequestHandlerFactory = _browserControl->ResourceRequestHandlerFactory; + + //No handler and no factory, we'll just return null + if (handler == nullptr && resourceRequestHandlerFactory == nullptr) + { + return NULL; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + Request requestWrapper(request); + + if (handler != nullptr) + { + auto resourceRequestHandler = handler->GetResourceRequestHandler(_browserControl, browserWrapper, %frameWrapper, + %requestWrapper, isNavigation, isDownload, StringUtils::ToClr(requestInitiator), disableDefaultHandling); + + if (resourceRequestHandler != nullptr) + { + return new CefResourceRequestHandlerAdapter(_browserControl, resourceRequestHandler); + } + } + + if (resourceRequestHandlerFactory != nullptr && resourceRequestHandlerFactory->HasHandlers) + { + auto factoryHandler = resourceRequestHandlerFactory->GetResourceRequestHandler(_browserControl, browserWrapper, %frameWrapper, + %requestWrapper, isNavigation, isDownload, StringUtils::ToClr(requestInitiator), disableDefaultHandling); + + if (factoryHandler != nullptr) + { + return new CefResourceRequestHandlerAdapter(_browserControl, factoryHandler); + } + } + + return NULL; + } + + bool ClientAdapter::OnCertificateError(CefRefPtr browser, cef_errorcode_t cert_error, const CefString& request_url, CefRefPtr ssl_info, CefRefPtr callback) + { + auto handler = _browserControl->RequestHandler; + + if (handler == nullptr) + { + return false; + } + + // If callback is empty the error cannot be recovered from and the request will be canceled automatically. + // Still notify the user of the certificate error just don't provide a callback. + auto requestCallback = callback == NULL ? nullptr : gcnew CefRequestCallbackWrapper(callback); + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto sslInfoWrapper = gcnew CefSslInfoWrapper(ssl_info); + + return handler->OnCertificateError(_browserControl, browserWrapper, (CefErrorCode)cert_error, StringUtils::ToClr(request_url), sslInfoWrapper, requestCallback); + } + + bool ClientAdapter::OnQuotaRequest(CefRefPtr browser, const CefString& originUrl, int64 newSize, CefRefPtr callback) + { + auto handler = _browserControl->RequestHandler; + + if (handler == nullptr) + { + return false; + } + + auto requestCallback = gcnew CefRequestCallbackWrapper(callback); + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + return handler->OnQuotaRequest(_browserControl, browserWrapper, StringUtils::ToClr(originUrl), newSize, requestCallback); + } + + void ClientAdapter::OnPluginCrashed(CefRefPtr browser, const CefString& plugin_path) + { + auto handler = _browserControl->RequestHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnPluginCrashed(_browserControl, browserWrapper, StringUtils::ToClr(plugin_path)); + } + } + + void ClientAdapter::OnRenderViewReady(CefRefPtr browser) + { + auto handler = _browserControl->RequestHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnRenderViewReady(_browserControl, browserWrapper); + } + } + + void ClientAdapter::OnRenderProcessTerminated(CefRefPtr browser, TerminationStatus status) + { + auto handler = _browserControl->RequestHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnRenderProcessTerminated(_browserControl, browserWrapper, (CefTerminationStatus)status); + } + } + + void ClientAdapter::OnDocumentAvailableInMainFrame(CefRefPtr browser) + { + auto handler = _browserControl->RequestHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnDocumentAvailableInMainFrame(_browserControl, browserWrapper); + } + } + + bool ClientAdapter::GetAuthCredentials(CefRefPtr browser, const CefString& originUrl, bool isProxy, + const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr callback) + { + if (isProxy && CefSharpSettings::Proxy != nullptr && CefSharpSettings::Proxy->IP == StringUtils::ToClr(host) && CefSharpSettings::Proxy->HasUsernameAndPassword()) + { + callback->Continue(StringUtils::ToNative(CefSharpSettings::Proxy->Username), StringUtils::ToNative(CefSharpSettings::Proxy->Password)); + return true; + } + + auto handler = _browserControl->RequestHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto callbackWrapper = gcnew CefAuthCallbackWrapper(callback); + + return handler->GetAuthCredentials( + _browserControl, browserWrapper, StringUtils::ToClr(originUrl), isProxy, + StringUtils::ToClr(host), port, StringUtils::ToClr(realm), + StringUtils::ToClr(scheme), callbackWrapper); + } + + bool ClientAdapter::OnSelectClientCertificate(CefRefPtr browser, bool isProxy, const CefString& host, + int port, const CefRequestHandler::X509CertificateList& certificates, CefRefPtr callback) + { + + auto handler = _browserControl->RequestHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto callbackWrapper = gcnew CefCertificateCallbackWrapper(callback, certificates); + + auto list = gcnew X509Certificate2Collection(); + + std::vector >::const_iterator it = + certificates.begin(); + for (; it != certificates.end(); ++it) + { + auto bytes((*it)->GetDEREncoded()); + auto byteSize = bytes->GetSize(); + + auto bufferByte = gcnew cli::array(byteSize); + pin_ptr src = &bufferByte[0]; // pin pointer to first element in arr + + bytes->GetData(static_cast(src), byteSize, 0); + auto cert = gcnew X509Certificate2(bufferByte); + list->Add(cert); + } + + return handler->OnSelectClientCertificate( + _browserControl, browserWrapper, isProxy, + StringUtils::ToClr(host), port, list, callbackWrapper); + } + + void ClientAdapter::OnBeforeContextMenu(CefRefPtr browser, CefRefPtr frame, + CefRefPtr params, CefRefPtr model) + { + auto handler = _browserControl->MenuHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + CefContextMenuParamsWrapper contextMenuParamsWrapper(params); + CefMenuModelWrapper menuModelWrapper(model); + + handler->OnBeforeContextMenu(_browserControl, browserWrapper, %frameWrapper, %contextMenuParamsWrapper, %menuModelWrapper); + } + } + + bool ClientAdapter::OnContextMenuCommand(CefRefPtr browser, CefRefPtr frame, + CefRefPtr params, int commandId, EventFlags eventFlags) + { + auto handler = _browserControl->MenuHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + CefContextMenuParamsWrapper contextMenuParamsWrapper(params); + + return handler->OnContextMenuCommand(_browserControl, browserWrapper, %frameWrapper, %contextMenuParamsWrapper, + (CefMenuCommand)commandId, (CefEventFlags)eventFlags); + } + + return false; + } + + void ClientAdapter::OnContextMenuDismissed(CefRefPtr browser, CefRefPtr frame) + { + auto handler = _browserControl->MenuHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + handler->OnContextMenuDismissed(_browserControl, browserWrapper, %frameWrapper); + } + } + + bool ClientAdapter::RunContextMenu(CefRefPtr browser, CefRefPtr frame, CefRefPtr params, CefRefPtr model, CefRefPtr callback) + { + auto handler = _browserControl->MenuHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + CefContextMenuParamsWrapper contextMenuParamsWrapper(params); + CefMenuModelWrapper menuModelWrapper(model); + + auto callbackWrapper = gcnew CefRunContextMenuCallbackWrapper(callback); + + return handler->RunContextMenu(_browserControl, browserWrapper, %frameWrapper, %contextMenuParamsWrapper, %menuModelWrapper, callbackWrapper); + } + + void ClientAdapter::OnGotFocus(CefRefPtr browser) + { + auto handler = _browserControl->FocusHandler; + + if (handler == nullptr) + { + return; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnGotFocus(_browserControl, browserWrapper); + } + + bool ClientAdapter::OnSetFocus(CefRefPtr browser, FocusSource source) + { + auto handler = _browserControl->FocusHandler; + + if (handler == nullptr) + { + // Allow the focus to be set by default. + return false; + } + + //For DevTools (which is hosted as a popup) OnSetFocus is called before OnAfterCreated so we don't + // have a reference to the standard popup IBrowser wrapper, so we just pass a + // short term reference. + CefBrowserWrapper browserWrapper(browser); + + return handler->OnSetFocus(_browserControl, %browserWrapper, (CefFocusSource)source); + } + + void ClientAdapter::OnTakeFocus(CefRefPtr browser, bool next) + { + auto handler = _browserControl->FocusHandler; + + if (handler == nullptr) + { + return; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnTakeFocus(_browserControl, browserWrapper, next); + } + + bool ClientAdapter::OnJSDialog(CefRefPtr browser, const CefString& origin_url, + JSDialogType dialog_type, const CefString& message_text, const CefString& default_prompt_text, + CefRefPtr callback, bool& suppress_message) + { + auto handler = _browserControl->JsDialogHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto callbackWrapper = gcnew CefJSDialogCallbackWrapper(callback); + return handler->OnJSDialog(_browserControl, browserWrapper, + StringUtils::ToClr(origin_url), (CefJsDialogType)dialog_type, + StringUtils::ToClr(message_text), StringUtils::ToClr(default_prompt_text), callbackWrapper, suppress_message); + } + + bool ClientAdapter::OnBeforeUnloadDialog(CefRefPtr browser, const CefString& message_text, bool is_reload, CefRefPtr callback) + { + auto handler = _browserControl->JsDialogHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto callbackWrapper = gcnew CefJSDialogCallbackWrapper(callback); + + return handler->OnBeforeUnloadDialog(_browserControl, browserWrapper, StringUtils::ToClr(message_text), is_reload, callbackWrapper); + } + + void ClientAdapter::OnResetDialogState(CefRefPtr browser) + { + auto handler = _browserControl->JsDialogHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnResetDialogState(_browserControl, browserWrapper); + } + } + + void ClientAdapter::OnDialogClosed(CefRefPtr browser) + { + auto handler = _browserControl->JsDialogHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnDialogClosed(_browserControl, browserWrapper); + } + } + + bool ClientAdapter::OnFileDialog(CefRefPtr browser, FileDialogMode mode, const CefString& title, + const CefString& default_file_path, const std::vector& accept_filters, int selected_accept_filter, + CefRefPtr callback) + { + auto handler = _browserControl->DialogHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto callbackWrapper = gcnew CefFileDialogCallbackWrapper(callback); + + auto dialogMode = mode & FileDialogMode::FILE_DIALOG_TYPE_MASK; + auto dialogFlags = mode & ~FileDialogMode::FILE_DIALOG_TYPE_MASK; + + return handler->OnFileDialog( + _browserControl, + browserWrapper, + (CefFileDialogMode)dialogMode, + (CefFileDialogFlags)dialogFlags, + StringUtils::ToClr(title), + StringUtils::ToClr(default_file_path), + StringUtils::ToClr(accept_filters), + selected_accept_filter, + callbackWrapper); + } + + bool ClientAdapter::OnDragEnter(CefRefPtr browser, CefRefPtr dragData, DragOperationsMask mask) + { + auto handler = _browserControl->DragHandler; + + if (handler == nullptr) + { + return false; + } + + DragData dragDataWrapper(dragData); + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + return handler->OnDragEnter(_browserControl, browserWrapper, %dragDataWrapper, (CefSharp::Enums::DragOperationsMask)mask); + } + + void ClientAdapter::OnDraggableRegionsChanged(CefRefPtr browser, CefRefPtr frame, const std::vector& regions) + { + auto handler = _browserControl->DragHandler; + + if (handler != nullptr) + { + auto regionsList = TypeConversion::FromNative(regions); + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + return handler->OnDraggableRegionsChanged(_browserControl, browserWrapper, %frameWrapper, regionsList); + } + } + + void ClientAdapter::OnBeforeDownload(CefRefPtr browser, CefRefPtr download_item, + const CefString& suggested_name, CefRefPtr callback) + { + auto handler = _browserControl->DownloadHandler; + + if (handler != nullptr) + { + auto downloadItem = TypeConversion::FromNative(download_item); + downloadItem->SuggestedFileName = StringUtils::ToClr(suggested_name); + + auto callbackWrapper = gcnew CefBeforeDownloadCallbackWrapper(callback); + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnBeforeDownload(_browserControl, browserWrapper, downloadItem, callbackWrapper); + } + }; + + void ClientAdapter::OnDownloadUpdated(CefRefPtr browser, CefRefPtr download_item, + CefRefPtr callback) + { + auto handler = _browserControl->DownloadHandler; + + if (handler != nullptr) + { + auto callbackWrapper = gcnew CefDownloadItemCallbackWrapper(callback); + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnDownloadUpdated(_browserControl, browserWrapper, TypeConversion::FromNative(download_item), callbackWrapper); + } + } + + void ClientAdapter::OnFindResult(CefRefPtr browser, int identifier, int count, const CefRect& selectionRect, int activeMatchOrdinal, bool finalUpdate) + { + auto handler = _browserControl->FindHandler; + + if (handler != nullptr) + { + auto rect = Rect(selectionRect.x, selectionRect.y, selectionRect.width, selectionRect.height); + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnFindResult(_browserControl, browserWrapper, identifier, count, rect, activeMatchOrdinal, finalUpdate); + } + } + + bool ClientAdapter::GetAudioParameters(CefRefPtr browser, CefAudioParameters & params) + { + auto handler = _browserControl->AudioHandler; + + if (handler == nullptr) + { + return false; + } + + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + auto parameters = new AudioParameters((CefSharp::Enums::ChannelLayout)params.channel_layout, params.sample_rate, params.frames_per_buffer); + + auto result = handler->GetAudioParameters(_browserControl, browserWrapper, *parameters); + + if (result) + { + params.channel_layout = (cef_channel_layout_t)parameters->ChannelLayout; + params.sample_rate = parameters->SampleRate; + params.frames_per_buffer = parameters->FramesPerBuffer; + } + + return result; + } + + void ClientAdapter::OnAudioStreamStarted(CefRefPtr browser, const CefAudioParameters& params, int channels) + { + auto handler = _browserControl->AudioHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + AudioParameters parameters((CefSharp::Enums::ChannelLayout)params.channel_layout, params.sample_rate, params.frames_per_buffer); + + handler->OnAudioStreamStarted(_browserControl, browserWrapper, parameters, channels); + } + } + + void ClientAdapter::OnAudioStreamPacket(CefRefPtr browser, const float** data, int frames, int64 pts) + { + auto handler = _browserControl->AudioHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnAudioStreamPacket(_browserControl, browserWrapper, IntPtr((void *)data), frames, pts); + } + } + + void ClientAdapter::OnAudioStreamStopped(CefRefPtr browser) + { + auto handler = _browserControl->AudioHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnAudioStreamStopped(_browserControl, browserWrapper); + } + } + + void ClientAdapter::OnAudioStreamError(CefRefPtr browser, const CefString& message) + { + auto handler = _browserControl->AudioHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + + handler->OnAudioStreamError(_browserControl, browserWrapper, StringUtils::ToClr(message)); + } + } + + bool ClientAdapter::OnProcessMessageReceived(CefRefPtr browser, CefRefPtr frame, CefProcessId source_process, CefRefPtr message) + { + if (_disposed) + { + return true; + } + + auto handled = false; + auto name = message->GetName(); + auto argList = message->GetArgumentList(); + + //TODO: JSB Rename messages (remove Root from name) + if (name == kJavascriptRootObjectRequest) + { + auto browserAdapter = _browserAdapter; + if (Object::ReferenceEquals(browserAdapter, nullptr) || browserAdapter->IsDisposed) + { + return true; + } + + auto objectRepository = browserAdapter->JavascriptObjectRepository; + + if (objectRepository == nullptr) + { + return true; + } + + auto callbackId = GetInt64(argList, 0); + auto objectNames = argList->GetList(1); + + auto names = gcnew List(objectNames->GetSize()); + for (size_t i = 0; i < objectNames->GetSize(); i++) + { + names->Add(StringUtils::ToClr(objectNames->GetString(i))); + } + + //Call GetObjects with the list of names provided (will default to all if the list is empty + //Previously we only sent a response if there were bound objects, now we always send + //a response so the promise is resolved. + auto objs = objectRepository->GetObjects(names); + + auto msg = CefProcessMessage::Create(kJavascriptRootObjectResponse); + auto responseArgList = msg->GetArgumentList(); + SetInt64(responseArgList, 0, callbackId); + SerializeJsObjects(objs, responseArgList, 1); + frame->SendProcessMessage(CefProcessId::PID_RENDERER, msg); + + handled = true; + } + else if (name == kJavascriptObjectsBoundInJavascript) + { + auto browserAdapter = _browserAdapter; + if (Object::ReferenceEquals(browserAdapter, nullptr) || browserAdapter->IsDisposed) + { + return true; + } + + auto objectRepository = browserAdapter->JavascriptObjectRepository; + + if (objectRepository == nullptr) + { + return true; + } + + auto boundObjects = argList->GetList(0); + auto objs = gcnew List^>(boundObjects->GetSize()); + for (size_t i = 0; i < boundObjects->GetSize(); i++) + { + auto obj = boundObjects->GetDictionary(i); + auto objectName = obj->GetString("Name"); + auto alreadyBound = obj->GetBool("AlreadyBound"); + auto isCached = obj->GetBool("IsCached"); + + objs->Add(Tuple::Create(StringUtils::ToClr(objectName), alreadyBound, isCached)); + } + + objectRepository->ObjectsBound(objs); + + handled = true; + } + else if (name == kOnContextCreatedRequest) + { + //In certain circumstances the frame has already been destroyed by the time + //we get here, only continue if we have a valid frame reference + if (frame.get() && frame->IsValid()) + { + if (frame->IsMain()) + { + _browserControl->SetCanExecuteJavascriptOnMainFrame(frame->GetIdentifier(), true); + } + + auto handler = _browserControl->RenderProcessMessageHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + handler->OnContextCreated(_browserControl, browserWrapper, %frameWrapper); + } + } + + handled = true; + } + else if (name == kOnContextReleasedRequest) + { + //In certain circumstances the frame has already been destroyed by the time + //we get here, only continue if we have a valid frame reference + if (frame.get() && frame->IsValid()) + { + if (frame->IsMain()) + { + _browserControl->SetCanExecuteJavascriptOnMainFrame(frame->GetIdentifier(), false); + } + + auto handler = _browserControl->RenderProcessMessageHandler; + + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + handler->OnContextReleased(_browserControl, browserWrapper, %frameWrapper); + } + } + + handled = true; + } + else if (name == kOnFocusedNodeChanged) + { + auto handler = _browserControl->RenderProcessMessageHandler; + if (handler != nullptr) + { + IDomNode^ node = nullptr; + + // 0: is a node (bool) + // 1: tag name (string) + // 2: attributes (dictionary) + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + auto notEmpty = argList->GetBool(0); + if (notEmpty) + { + // Node information was passed from the render process. + auto tagName = StringUtils::ToClr(argList->GetString(1)); + auto argAttributes = argList->GetDictionary(2); + auto attributes = gcnew System::Collections::Generic::Dictionary(); + CefDictionaryValue::KeyList keys; + argAttributes->GetKeys(keys); + for (auto key : keys) + { + attributes->Add(StringUtils::ToClr(key), StringUtils::ToClr(argAttributes->GetString(key))); + } + + node = gcnew DomNode(tagName, attributes); + } + + // DomNode will be empty if input focus was cleared + handler->OnFocusedNodeChanged(_browserControl, browserWrapper, %frameWrapper, node); + } + } + else if (name == kOnUncaughtException) + { + auto handler = _browserControl->RenderProcessMessageHandler; + if (handler != nullptr) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + auto exception = gcnew JavascriptException(); + exception->Message = StringUtils::ToClr(argList->GetString(0)); + + auto stackTrace = gcnew System::Collections::Generic::List(); + + auto argFrames = argList->GetList(1); + + for (auto i = 0; i < static_cast(argFrames->GetSize()); i++) + { + auto argFrame = argFrames->GetList(i); + + auto stackFrame = gcnew JavascriptStackFrame(); + stackFrame->FunctionName = StringUtils::ToClr(argFrame->GetString(0)); + stackFrame->LineNumber = argFrame->GetInt(1); + stackFrame->ColumnNumber = argFrame->GetInt(2); + stackFrame->SourceName = StringUtils::ToClr(argFrame->GetString(3)); + + stackTrace->Add(stackFrame); + } + + exception->StackTrace = stackTrace->ToArray(); + + handler->OnUncaughtException(_browserControl, browserWrapper, %frameWrapper, exception); + } + } + else if (name == kEvaluateJavascriptResponse || name == kJavascriptCallbackResponse) + { + auto browserAdapter = _browserAdapter; + if (Object::ReferenceEquals(browserAdapter, nullptr) || browserAdapter->IsDisposed) + { + return true; + } + + auto callbackFactory = browserAdapter->JavascriptCallbackFactory; + + auto success = argList->GetBool(0); + auto callbackId = GetInt64(argList, 1); + + auto pendingTask = _pendingTaskRepository->RemovePendingTask(callbackId); + if (pendingTask != nullptr) + { + auto response = gcnew JavascriptResponse(); + response->Success = success; + + if (success) + { + response->Result = DeserializeObject(argList, 2, callbackFactory); + } + else + { + response->Message = StringUtils::ToClr(argList->GetString(2)); + } + + CefSharp::Internals::TaskExtensions::TrySetResultAsync(pendingTask, response); + } + + handled = true; + } + else if (name == kJavascriptAsyncMethodCallRequest) + { + auto browserAdapter = _browserAdapter; + if (Object::ReferenceEquals(browserAdapter, nullptr) || browserAdapter->IsDisposed) + { + return true; + } + + auto callbackFactory = browserAdapter->JavascriptCallbackFactory; + auto methodRunnerQueue = browserAdapter->MethodRunnerQueue; + + //Dispose is called on a different thread, so there's a chance + //dispose is called after our IsDisposed checks, make sure we have + //actual references. + if (callbackFactory == nullptr || methodRunnerQueue == nullptr) + { + return true; + } + + auto frameId = frame->GetIdentifier(); + auto objectId = GetInt64(argList, 0); + auto callbackId = GetInt64(argList, 1); + auto methodName = StringUtils::ToClr(argList->GetString(2)); + auto arguments = argList->GetList(3); + auto methodInvocation = gcnew MethodInvocation(browser->GetIdentifier(), frameId, objectId, methodName, (callbackId > 0 ? Nullable(callbackId) : Nullable())); + for (auto i = 0; i < static_cast(arguments->GetSize()); i++) + { + methodInvocation->Parameters->Add(DeserializeObject(arguments, i, callbackFactory)); + } + + methodRunnerQueue->Enqueue(methodInvocation); + + handled = true; + } + else if (name == kJavascriptMessageReceived) + { + auto browserAdapter = _browserAdapter; + if (Object::ReferenceEquals(browserAdapter, nullptr) || browserAdapter->IsDisposed) + { + return true; + } + + auto callbackFactory = browserAdapter->JavascriptCallbackFactory; + //In certain circumstances the frame has already been destroyed by the time + //we get here, only continue if we have a valid frame reference + if (frame.get() && frame->IsValid()) + { + auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup()); + CefFrameWrapper frameWrapper(frame); + + auto deserializedMessage = DeserializeObject(argList, 0, callbackFactory); + + _browserControl->SetJavascriptMessageReceived(gcnew JavascriptMessageReceivedEventArgs(browserWrapper, %frameWrapper, deserializedMessage)); + } + + handled = true; + } + + return handled; + } + + PendingTaskRepository^ ClientAdapter::GetPendingTaskRepository() + { + return _pendingTaskRepository; + } + + void ClientAdapter::MethodInvocationComplete(MethodInvocationResult^ result) + { + auto browser = GetBrowserWrapper(result->BrowserId); + + if (result->CallbackId.HasValue && browser != nullptr && !browser->IsDisposed) + { + auto wrapper = static_cast(browser); + if (wrapper == nullptr) + { + return; + } + + auto cefBrowser = wrapper->Browser; + + if (cefBrowser.get()) + { + auto frame = cefBrowser->GetFrame(result->FrameId); + + if (frame.get() && frame->IsValid()) + { + auto message = CefProcessMessage::Create(kJavascriptAsyncMethodCallResponse); + auto argList = message->GetArgumentList(); + SetInt64(argList, 0, result->CallbackId.Value); + argList->SetBool(1, result->Success); + if (result->Success) + { + SerializeV8Object(argList, 2, result->Result, result->NameConverter); + } + else + { + argList->SetString(2, StringUtils::ToNative(result->Message)); + } + + frame->SendProcessMessage(CefProcessId::PID_RENDERER, message); + } + } + } + } + } +} diff --git a/src/ControlTarget.cpp b/src/ControlTarget.cpp new file mode 100644 index 0000000..6338e15 --- /dev/null +++ b/src/ControlTarget.cpp @@ -0,0 +1,3087 @@ +// ************************************************************************** // +// ControlTarget.cpp : implementation of the CControlTarget class +// Copyright(c)2012 Naiky Company. All rights reserved. +// +// Abstract: +// 本文件实现CControlTarget类。 +// ********************************************* ---- 卢伟 2012-01-07 ***** // +#include "StdAfx.h" +#include "ControlTarget.h" +#include "CycMachiningTarget.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +CS_T s_csBreakPointResume = _DEFCS(_CSV(18028), + _CHINESE("断点继续") + _ENGLISH("BreakPointResume")); +CS_T s_csGoForward = _DEFCS(_CSV(18029), + _CHINESE("前进") + _ENGLISH("GoForward")); +CS_T s_csGoBackward = _DEFCS(_CSV(18030), + _CHINESE("后退") + _ENGLISH("GoBackward")); +CS_T s_csBACKREFPROMPT = _DEFCS(_CSV(18031), + _CHINESE("即将进行回机械原点操作\n是否确认?") + _ENGLISH("It's going to go back to Reference Point\nConform or Not?")); +CS_T s_csFORBIDORIGINBACK = _DEFCS(_CSV(18032), + _CHINESE("当前点不允许执行自动倒行") + _ENGLISH("It's forbid to AutoBack at the current point")); +CS_T s_csFORBIDORIGINFORWARD = _DEFCS(_CSV(18033), + _CHINESE("当前点不允许执行自动正行") + _ENGLISH("It's forbid to AutoForward at the current point")); +CS_T s_csNoObjInFileForAction = _DEFCS(_CSV(18034), + _CHINESE("|E|文件无图形,%s不可用!") + _ENGLISH("|E|No figure in the file, unable to %s!")); +CS_T s_csFORBIDRESUME = _DEFCS(_CSV(18035), + _CHINESE("|E|当前点不允许执行断点继续") + _ENGLISH("|E|It's forbid to Resume at the current point")); +CS_T s_csCANNOTSIMUCUT_NOOBJ = _DEFCS(_CSV(18036), + _CHINESE("文件无图形,无法走边框!") + _ENGLISH("No figure in the file,can not SimuCut!")); +CS_T s_csCANNOTSIMUCUT_JUST1DOT = _DEFCS(_CSV(18037), + _CHINESE("文件只有一个点,无法走边框!") + _ENGLISH("Just 1 Dot in the file,can not SimuCut!")); +CS_T s_csFileChanged = _DEFCS(_CSV(18038), + _CHINESE("文件已修改,保存后方可执行机床加工动作!\n是否保存?") + _ENGLISH("File changed, can not mach untill saved!\nSave or not?")); +CS_T s_cs2YDetectConfigError = _DEFCS(_CSV(18039), + _CHINESE("|F|双Y原点检测配置有误,请检查!") + _ENGLISH("|F|Config for 2YErrorDetecting is wrong, please check!")); +CS_T s_csOperateDangerous = _DEFCS(_CSV(18040), + _CHINESE("当前操作存在危险: 建议先抬起切割头。\n是否继续...") + _ENGLISH("Operation dangerous: It's better to raise cutter first.\nContinue or not...")); +CS_T s_csNHOURSLEFTFORCECLOSE = _DEFCS(_CSV(18041), + _CHINESE("|F|注册过期,系统将在%d小时内自动关闭!") + _ENGLISH("|F|The system is expired.\nNcEditor Will Be Closed In %d Hours Without Registered Again!")); +CS_T s_csNoNearPoint = _DEFCS(_CSV(18042), + _CHINESE("|E|没有找到邻近点!") + _ENGLISH("|E|No near point be found!")); +CS_T s_csFORBIDNEARSTART = _DEFCS(_CSV(18043), + _CHINESE("|E|当前点不允许执行邻近点加工!") + _ENGLISH("|E|It's forbid to near start at the current point!")); +CS_T s_csEXCEEDWORKTABLE = _DEFCS(_CSV(18526), + _CHINESE("|E|加工文件超出工作台范围!") + _ENGLISH("|E|Exceed the worktable travel limit!")); +CS_T s_szNOAVALIBLEOBJECTTOMACH = _DEFCS(_CSV(18619), + _CHINESE("当前运动不执行,请确认是否存在加工图形,或处于选择加工模式而未选中任何图形。") + _ENGLISH("Current motion cannot be executed. Please make sure graphic to be machined exists or it has been selected.")); +CS_T s_szCONFIG_TUBE_NOK = _DEFCS(_CSV(18619), + _CHINESE("系统配置不支持加工管材文件!") + _ENGLISH("Tube file is not supported under current System Config.")); +CS_T s_szFORSEHOMEBEFORBEGIN = _DEFCS(_CSV(18619), + _CHINESE("加工前各轴请先回机械原点!") + _ENGLISH("Before machining, all axes must go home!")); + +static bool _FindObjectByID(IN nce::CCadObject* pCadObj_, IN int nID_, OUT nce::CCadObject** ppResult_); +typedef std::vector vectorUINT; +void _GetCadIDList(IN nce::CadObjectList* pListCads_, OUT vectorUINT& setIDs_); +void _GetCamGroupByCadID(IN nce::CCamGroup* pCCamGroup_, IN vectorUINT setIDs_, OUT nce::CCamGroup* pOutCCamGroup_); + +const CHAR c_szScanType[] = "ScanType"; +//穿孔方式 +const char c_szPerforateType[] = "PerforateType"; +//穿孔气体 +const char c_szPerBlowType[] = "PerBlowType"; +//切割气体 +const char c_szCutBlowType[] = "CutBlowType"; +//冷却气 +const char c_szCoolBlowType[] = "CoolBlowType"; +//图层不加工 +const char c_szOutput[] = "Output"; +//一级气体 +const char c_szFirstSegBlowType[] = "FirstSegBlowType"; +//二级气体 +const char c_szSecondSegBlowType[] = "SecondSegBlowType"; +//三级气体 +const char c_szThirdSegBlowType[] = "ThirdSegBlowType"; +//一级气体flag +const char c_szFirstSegPunch[] = "FirstSegPunch"; +//二级气体flag +const char c_szSecondSegPunch[] = "SecondSegPunch"; +//三级气体flag +const char c_szThirdSegPunch[] = "ThirdSegPunch"; + +using namespace mach; +using namespace ncmath; +using namespace nce; + +CControlTarget* CControlTarget::ms_pControlTarget = NULL; +CControlTarget* GetControlTarget() +{ + return CControlTarget::ms_pControlTarget; +} + +/////////////////////////////////////////////////////////////////////////////// +// CControlTarget +// +IMPLEMENT_DYNAMIC(CControlTarget, CNceTarget) +BEGIN_MESSAGE_MAP(CControlTarget, CNceTarget) + ON_COMMAND(IDCMD_CONTROLTARGET_SHOWCONTROLDLG, OnShowControlDlg) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_SHOWCONTROLDLG, OnUpdateShowControlDlg) + + // 这里是特色响应,应写在OnCommand的前面进行拦截 ---- 杨开锦 2012-05-25 + ON_COMMAND(IDCMD_CONTROLTARGET_DETECT2YERROR, OnDetect2YError) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_DETECT2YERROR, OnUpdateDetect2YError) + ON_COMMAND(IDCMD_CONTROLTARGET_CLEARW, OnClearW) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_CLEARW, OnUpdateClearW) + ON_COMMAND(IDCMD_CONTROLTARGET_CLEARWZ, OnClearWZ) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_CLEARWZ, OnUpdateClearWZ) + ON_COMMAND(IDCMD_CONTROLTARGET_STOP, OnStop) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_STOP, OnUpdateStop) + ON_COMMAND(IDCMD_CONTROLTARGET_DIRECTSET, OnDirectSet) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_DIRECTSET, OnUpdateDirectSet) + ON_COMMAND(IDCMD_CONTROLTARGET_BACKRDLG, OnBackRDlg) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_BACKRDLG, OnUpdateBackRDlg) + ON_COMMAND(IDCMD_CONTROLTARGET_MACHSELECTED, OnIsMachSelected) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_MACHSELECTED, OnUpdateIsMachSelected) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_STARTSELECTION, OnUpdateStartSelectNotMove) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_ZBACKR, OnUpdateZBackOrg) + ON_UPDATE_COMMAND_UI(IDCMD_CONTROLTARGET_FOLLOWCONTROL, OnUpdateFollowCtrl) + ON_TARGET_NOTIFY(TN_NAMEDCOMMAND, OnNamedCommand) + ON_COMMAND_RANGE(IDCMD_CONTROLTARGET_BACKR, IDCMD_CONTROLTARGET_BACKWARDEND, OnCommand) + ON_UPDATE_COMMAND_UI_RANGE(IDCMD_CONTROLTARGET_BACKR, IDCMD_CONTROLTARGET_BACKWARDEND, OnUpdateCommandUI) + ON_TARGET_NOTIFY(TN_TIMER_EVERY40MILLISECOND, OnEvery40Millisecond) + ON_TARGET_NOTIFY(TN_POST_INITINSTANCE, OnPostInitInstance) +END_MESSAGE_MAP() + +CControlTarget::CControlTarget() +: c_nMinGFOBDistance(0.01) +, m_bShowControlDlg(true) +, m_nGFOBDistance(10.0) +, m_nGFOBMode(0x00) +, m_bShowBkrefDlgWhenStart(TRUE) +, m_nGFOBKeyState(0) +, m_bEnableKeyMsg(true) +{ + ASSERT(ms_pControlTarget == NULL); + ms_pControlTarget = this; + + // 命令表 ---- 杨开锦 2012-04-13 + typedef CControlTarget ThisClass; + static const CommandItem _s_CommandItems[] = + { + // nID strName strCommand strCEParameter pGetEParameter + // MFC命令号 命名命令 C#命令 CanExecute参数 Execute参数 + { IDCMD_CONTROLTARGET_BACKR, "BackR", "BackR", NULL, NULL, }, + { IDCMD_CONTROLTARGET_XBACKR, "BackR", "BackR", NULL, &ThisClass::_GetParamForXBackR, }, + { IDCMD_CONTROLTARGET_YBACKR, "BackR", "BackR", NULL, &ThisClass::_GetParamForYBackR, }, + { IDCMD_CONTROLTARGET_ZBACKR, "BackRZ", "BackRZ", NULL, &ThisClass::_GetParamForZBackR, }, + { IDCMD_CONTROLTARGET_DIRECTSET, "DirectSet", "DirectSet", NULL, NULL, }, + { IDCMD_CONTROLTARGET_MOVETOFIXPOS, "BackFP", "BackFixPos", NULL, NULL, }, + { IDCMD_CONTROLTARGET_BACKW, "BackW", "BackW", NULL, NULL, }, + { IDCMD_CONTROLTARGET_CLEARW, "ClearW", "ClearW", NULL, NULL, }, + { IDCMD_CONTROLTARGET_BACKWZ, "BackWZ", "BackWZ", NULL, NULL, }, + { IDCMD_CONTROLTARGET_CLEARWZ, "ClearWZ", "ClearWZ", NULL, NULL, }, + { IDCMD_CONTROLTARGET_SIMUCUT, "WalkBoundRect", "RunGCode", "G00 X0 Y0", &ThisClass::_GetParamForCommand_SimuCut, }, + { IDCMD_CONTROLTARGET_START, "Start", "Start", "0,1", NULL, }, + { IDCMD_CONTROLTARGET_PAUSE, "Pause", "Pause", NULL, NULL, }, + { IDCMD_CONTROLTARGET_STOP, "Stop", "Stop", NULL, NULL, }, + { IDCMD_CONTROLTARGET_STARTSELECTION, "StartSelection", "StartSelection", "0,1", &ThisClass::_GetParamForCommand_MachSelect, }, + { IDCMD_CONTROLTARGET_BREAKPOINTRESUME, "BPResume", "BPResume", "0,1", &ThisClass::_GetParamForCommand_BreakPointResume, }, + { IDCMD_CONTROLTARGET_STARTNEARPOINT, "NearStart", "NearStart", "0,1", &ThisClass::_GetParamForCommand_StartNearPoint, }, + { IDCMD_CONTROLTARGET_SIMULATE, "Simulate", "Simulate", "0,1", NULL, }, + { IDCMD_CONTROLTARGET_DIRRUN, "DirRun", "DirRun", "0,1", NULL, }, + { IDCMD_CONTROLTARGET_FOLLOWCONTROL, "FollowCtrl", "FollowCtrl", NULL, NULL, }, + + { IDCMD_CONTROLTARGET_JOGFORWARD, "JogForward", "DirRunSelection", "0,1", &ThisClass::_GetParamForCommand_GoForward, }, + { IDCMD_CONTROLTARGET_INCFORWARD, "IncForward", "DirRunSelection", "0,1", &ThisClass::_GetParamForCommand_IncForward, }, + { IDCMD_CONTROLTARGET_JOGBACKWARD, "JogBackward", "DirRunSelection", "0,1", &ThisClass::_GetParamForCommand_GoBackward, }, + { IDCMD_CONTROLTARGET_INCBACKWARD, "IncBackward", "DirRunSelection", "0,1", &ThisClass::_GetParamForCommand_IncBackward, }, + { IDCMD_CONTROLTARGET_FORWARDBEGIN, "ForwardBegin", "DirRunSelection", "0,1", &ThisClass::_GetParamForCommand_ForwardBegin, }, + { IDCMD_CONTROLTARGET_BACKWARDBEGIN, "BackwardBegin", "DirRunSelection", "0,1", &ThisClass::_GetParamForCommand_BackwardBegin, }, + { IDCMD_CONTROLTARGET_FORWARDEND, "ForwardEnd", "DirRunSelection", "0,1", &ThisClass::_GetParamForCommand_ForwardEnd, }, + { IDCMD_CONTROLTARGET_BACKWARDEND, "BackwardEnd", "DirRunSelection", "0,1", &ThisClass::_GetParamForCommand_BackwardEnd, }, + +// { IDCMD_CONTROLTARGET_STARTEDGEFIND, "StartAutoEdgeFind", "StartAutoEdgeFind", NULL, NULL }, + }; + m_vectorCommandItems.clear(); + m_vectorCommandItems = CommandItemVector(_s_CommandItems + 0, _s_CommandItems + _countof(_s_CommandItems)); + + memset(m_KeyStates, 0, sizeof(KeyState) * _countof(m_KeyStates)); + + static WSItem _s_WSItems[] = + { + { "DirRun", "DirRunSelection2", }, + { "Simulate", "SimulateSelection", }, + { "Start", "StartSelection", }, + }; + m_vectorWSItems.clear(); + m_vectorWSItems = WSItemsVector(_s_WSItems + 0, _s_WSItems + _countof(_s_WSItems)); + + // 添加初始化配置的支持 ---- 杨开锦 2015-06-12 + CString _strCT = NceGetPrivateProfileString(_T("ControlTarget"), NULL); + CString _strSBD = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowBkrefDlg")); + if (_strCT == "" || _strSBD == "0" || _strSBD == "false" || _strSBD == "False" || _strSBD == "FALSE") + { + m_bShowBkrefDlgWhenStart = FALSE; + } + m_bAutoZBkrefWhenStart = FALSE; + + CString _strEnableMotionAccel = NceGetPrivateProfileString(_T("ControlTarget"), _T("EnableMotionAccel"), _T("1")); + if (_strEnableMotionAccel == _T("0")) + { + m_bEnableKeyMsg = false; + } + + m_pwndControlDlg = NULL; + m_bIsMinSize = false; + + LOAD_PARAM(this, CControlTarget); +} + +CControlTarget::~CControlTarget() +{ + ASSERT(ms_pControlTarget == this); + ms_pControlTarget = NULL; + + SAVE_PARAM(this, CControlTarget); +} + +void CControlTarget::Initialize() +{ + // 如果没有CommandManager,则默认不显示机床控制栏 ---- 杨开锦 2012-06-22 + ASSERT(m_bShowControlDlg == true); + if (!mach::GetCommandManager()) + { + m_bShowControlDlg = true; + } +} + +bool CControlTarget::CanExecuteCommand(LPCSTR pszCommand_, LPCSTR pszParameter_) +{ + ASSERT(pszCommand_ && pszCommand_[0]); + + bool _bCanExecute = false; + CCommandManager* _pCommandManager = mach::GetCommandManager(); + if (!_pCommandManager + || pszParameter_ && pszParameter_[0] && !_pCommandManager->CanExecute(pszCommand_, pszParameter_, "LPCSTR", &_bCanExecute) + || (!pszParameter_ || !pszParameter_[0]) && !_pCommandManager->CanExecute(pszCommand_, &_bCanExecute)) + { + return false; + } + + return _bCanExecute; +} + +bool CControlTarget::ExecuteCommand(LPCSTR pszCommand_, LPCSTR pszParameter_) +{ + ASSERT(pszCommand_ && pszCommand_[0]); + + CCommandManager* _pCommandManager = mach::GetCommandManager(); + if (!_pCommandManager) + { + return false; + } + + if (pszParameter_ && pszParameter_[0] && !_pCommandManager->Execute(pszCommand_, pszParameter_, "LPCSTR") + || (!pszParameter_ || !pszParameter_[0]) && !_pCommandManager->Execute(pszCommand_)) + { + return false; + } + + return true; +} + +void CControlTarget::OnNamedCommand(WPARAM wParam_, LPARAM lParam_) +{ + const CStringA _c_strTargetName = "CControlTarget"; + if (_c_strTargetName != (PCSTR)wParam_) + { + return; + } + + // 查表调用 ---- 杨开锦 2012-04-13 + for (size_t _i = 0; _i < m_vectorCommandItems.size(); _i++) + { + const CommandItem& _item = m_vectorCommandItems[_i]; + if (_item.strName != (PCSTR)lParam_) + { + ASSERT(_i != m_vectorCommandItems.size() - 1); + continue; + } + + // 这里之所以不是直接调用掉,而是重新映射一遍,旨在精确遵从命名命令的定 + // 义:命名命令是给ID型的命令起一个String型的名字,方便以字符串的形式调 + // 到ID型的命令。 ---- 杨开锦 2012-04-14 + OnCmdMsg(_item.nID, 0, NULL, NULL); + break; + } +} + +void CControlTarget::OnShowControlDlg() +{ + m_bShowControlDlg = !m_bShowControlDlg; + UpdateAllVisions(); +} + +void CControlTarget::OnMinControlDlg() +{ + ((CMachineControlDlg_Left*)m_pwndControlDlg)->OnMinSize(); +} + +void CControlTarget::OnMaxControlDlg() +{ + ((CMachineControlDlg_Left*)m_pwndControlDlg)->OnMaxSize(); +} + +void CControlTarget::OnUpdateShowControlDlg(CCmdUI* pCmdUI_) +{ + ASSERT(pCmdUI_); + + // 当前显示时,Enalbe菜单使可以不显示;当前不显示时,要有CommandManager时才 + // Enable菜单,以便能显示。 ---- 杨开锦 2012-06-22 + bool _bEnable = m_bShowControlDlg || mach::GetCommandManager() != NULL; + pCmdUI_->Enable(_bEnable ? TRUE : FALSE); + + bool _bCheck = m_bShowControlDlg; + pCmdUI_->SetCheck(_bCheck ? 1 : 0); +} + +void CControlTarget::OnCommand(UINT nID_) +{ + //点击加工时,判断当前加工图形所用气压是否过低 + if (nID_ == IDCMD_CONTROLTARGET_START) + { + _SendGasPressureInfo(); + } + //济南邦德LT版本,当正向限位时,无法进行模拟功能 ---20170623 张磊 + if ((nID_ == IDCMD_CONTROLTARGET_SIMULATE) || (nID_ == IDCMD_CONTROLTARGET_BACKR)) + { + CString _flag = NceGetPrivateProfileString(_T("ZPLimit"), _T("ZPLimitCheck"), _T("0")); + CString _Portflag = NceGetPrivateProfileString(_T("ZPLimit"), _T("StopperPort"), _T("0")); + if ("1" == _flag) + { + mach::CPortsManager* _pPortsManager = mach::GetPortsManager(); + BitPort _Port; + ASSERT(_pPortsManager); + if (_pPortsManager) + { + _pPortsManager->GetBitPort((LPCSTR)_Portflag, &_Port); + if(_Port.bValue) + { + return; + } + } + } + } + if ((nID_ == IDCMD_CONTROLTARGET_START + || nID_ == IDCMD_CONTROLTARGET_DIRRUN + || nID_ == IDCMD_CONTROLTARGET_SIMULATE)) + { + CTubeTarget* _pTubeTarget = GetTubeTarget(); + ASSERT(_pTubeTarget); + // 管材文件不支持在非管材配置下仿真/加工 ---- yangxiaobin 2017-01-09 + if (_pTubeTarget->IsTubeFile() && !_pTubeTarget->IsEnable()) + { + NceShowMessage(_GETCS(s_szCONFIG_TUBE_NOK)); + return; + } + } + + //如果在倒计时时间内,点击开始和空运行按钮,则取消循环间隔的反馈,停止循环加工 ----liangyan 2013-9-22 + if (nID_ == IDCMD_CONTROLTARGET_START || nID_ == IDCMD_CONTROLTARGET_DIRRUN) + { + int m_nTimeRemain = 0; + CCycMachiningTarget* _pCycMachiningTarget = GetCycMachiningTarget(); + if (_pCycMachiningTarget->GetCountDownRemain(&m_nTimeRemain) && m_nTimeRemain > 0) + { + _pCycMachiningTarget->SetEnable(FALSE); + return; + } + } + + if (nID_ == IDCMD_CONTROLTARGET_START + || nID_ == IDCMD_CONTROLTARGET_DIRRUN + || nID_ == IDCMD_CONTROLTARGET_SIMUCUT) + { + mach::CParamManager* _pParamManager = mach::GetParamManager(); + ASSERT(_pParamManager); + mach::ParameterValue _PV; + memset(&_PV, 0, sizeof(mach::ParameterValue)); + _pParamManager->GetParameterValue("ForceHome", &_PV); + ASSERT(_PV.nType = mach::ParameterValue::VT_BOOL); + bool _bForceHome = _PV.bValue; + + memset(&_PV, 0, sizeof(mach::ParameterValue)); + _pParamManager->GetParameterValue("ChannelIsRefered", &_PV); + ASSERT(_PV.nType = mach::ParameterValue::VT_BOOL); + if (!_PV.bValue && _bForceHome) + { + AfxMessageBox(_GETCS(s_szFORSEHOMEBEFORBEGIN)); + return; + } + } + + // 查找 ---- 杨开锦 2012-04-13 + size_t _nCmdIndex = m_vectorCommandItems.size(); + for (size_t _i = 0; _i < m_vectorCommandItems.size(); _i++) + { + const CommandItem& _item = m_vectorCommandItems[_i]; + if (nID_ != _item.nID) + { + continue; + } + + _nCmdIndex = _i; + break; + } + if (_nCmdIndex < 0 || m_vectorCommandItems.size() <= _nCmdIndex) + { + ASSERT(FALSE); + return; + } + + // 发送预消息 ---- 杨开锦 2016-09-07 + if (!m_vectorCommandItems[_nCmdIndex].strCommand.IsEmpty()) + { + CStringA _strCommand = m_vectorCommandItems[_nCmdIndex].strCommand; + CStringA _strParameter = m_vectorCommandItems[_nCmdIndex].pGetEParameter ? (this->*m_vectorCommandItems[_nCmdIndex].pGetEParameter)() : ""; + if (SendTargetMessage(ID_TARGET_BROADCAST, TM_COMMAND_PREEXECUTE, (WPARAM)(PCSTR)_strCommand, (LPARAM)(PCSTR)_strParameter) != 0L) + { + return; + } + } + + // 为慎重计,回机械原点前要提示 ---- 杨开锦 2012-04-14 + if (nID_ == IDCMD_CONTROLTARGET_BACKR + || nID_ == IDCMD_CONTROLTARGET_XBACKR + || nID_ == IDCMD_CONTROLTARGET_YBACKR + || nID_ == IDCMD_CONTROLTARGET_ZBACKR) + { + if (AfxMessageBox(_GETCS(s_csBACKREFPROMPT), MB_OKCANCEL) != IDOK) + return; + } + + // 方管下不能走边框 ---- 吴畏 2017-01-11 + if (nID_ == IDCMD_CONTROLTARGET_SIMUCUT) + { + CTubeTarget* _pTubeTarget = GetTubeTarget(); + if (_pTubeTarget && _pTubeTarget->IsEnable()) + { + return; + } + } + + + + // 判断若界面无图形,或者图形为一点,则不能走边框 ---- 嘎松卓玛 2012-02-23 + if (nID_ == IDCMD_CONTROLTARGET_SIMUCUT) + { + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + nce::CCadGroup* _pCurrentCadGroup = _pFileTarget->GetCurrentCadGroup(); + ASSERT(_pCurrentCadGroup); + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + DRECT _rcBound; + if (_pStateManager->IsSelectedMach()) + { + CSelectTarget* _pSelectTarget = GetSelectTarget(); + ASSERT(_pSelectTarget); + const CadObjectList* _plistSelectObjs = _pSelectTarget->GetSelectedCadObjects(); + _rcBound = _plistSelectObjs && _plistSelectObjs->size() > 0 ? _pSelectTarget->GetSelObjsBoundRect() : DRECT(0.0, 0.0, 0.0, 0.0); + } + else + { + _rcBound = _pCurrentCadGroup->GetBoundRect(); + } + + if (_rcBound.width <= 0.0 && _rcBound.height <= 0.0) + { + NceShowMessage(_GETCS(s_szNOAVALIBLEOBJECTTOMACH)); + return; + } + } + + // 如果是循环加工停止后再开始提示是否继续循环加工,若不继续则清楚循环次数,加工完当前次数就 + // 不加工了。 ---- 黄海燕 2016-03-16 + if (nID_ == IDCMD_CONTROLTARGET_START + || nID_ == IDCMD_CONTROLTARGET_DIRRUN) + { + CCycMachiningTarget* _pCycMachiningTarget = GetCycMachiningTarget(); + if (_pCycMachiningTarget + && _pCycMachiningTarget->GetEnable() + && _pCycMachiningTarget->GetCycTimes() - 1 > _pCycMachiningTarget->GetCycDones() + && (_pCycMachiningTarget->IsInterrupt() + || _pCycMachiningTarget->GetCycDones() == 0) + && NceGetPrivateProfileString(_T("ControlTarget"), _T("CycStartPrompt")) == _T("1")) + { + CContineCyclicalMachDlg* _pwndDlg = GetContineCyclicalMachDlg(); + ASSERT(_pwndDlg); + if (_pwndDlg->DoModal() == IDCANCEL) + return; + } + } + + // 开始加工时自动以当前点为停靠点 ---- 杨开锦 2014-04-28 + // 即,开始加工时,自动执行坐标清零 + // 开始加工、走边框、空动行都清零 ---- DingQiang 2015-06-09 + static DWORD _s_nLastTime = ::GetTickCount(); + mach::CStateManager::State _nState = mach::CStateManager::Invalid; + if ((nID_ == IDCMD_CONTROLTARGET_START + || nID_ == IDCMD_CONTROLTARGET_DIRRUN + || nID_ == IDCMD_CONTROLTARGET_SIMUCUT) + && mach::GetStateManager()->GetState(&_nState) + && _nState == mach::CStateManager::Idle + && NceGetPrivateProfileString(_T("ControlTarget"), _T("AutoClearW")) == _T("1")) + { + // 两次进入时间间隔不超过300ms的话就不清零了,为了解决按手柄连续发多次指令,弹对话框的问题。 + // 通过这个方式解决不是很好,暂时这样,待杨实现在PLC中处理手柄消息,再到PLC中处理。 + // ---- 黄海燕 2015-10-10 + CStringA _strCommand = m_vectorCommandItems[_nCmdIndex].strCommand; + CStringA _strParameter = m_vectorCommandItems[_nCmdIndex].pGetEParameter ? (this->*m_vectorCommandItems[_nCmdIndex].pGetEParameter)() : ""; + DWORD _nCurTime = ::GetTickCount(); + DWORD _nSpaceTime = _nCurTime - _s_nLastTime; + bool _bSmallInterval = false; + if (_nSpaceTime < 300 && _s_nLastTime != _nCurTime) + { + _bSmallInterval = true; + } + _s_nLastTime = _nCurTime; + if (CanExecuteCommand(_strCommand, _strParameter) && !_bSmallInterval) + OnCmdMsg(IDCMD_CONTROLTARGET_CLEARW, 0, NULL, NULL); + } + + // 开始加工、仿真、空运行、选择加工等之前,提示保存文件 ---- 杨开锦 2012-04-14 + if (nID_ == IDCMD_CONTROLTARGET_START + || nID_ == IDCMD_CONTROLTARGET_SIMULATE + || nID_ == IDCMD_CONTROLTARGET_DIRRUN + || nID_ == IDCMD_CONTROLTARGET_STARTSELECTION + || nID_ == IDCMD_CONTROLTARGET_BREAKPOINTRESUME + || nID_ == IDCMD_CONTROLTARGET_JOGFORWARD + || nID_ == IDCMD_CONTROLTARGET_INCFORWARD + || nID_ == IDCMD_CONTROLTARGET_JOGBACKWARD + || nID_ == IDCMD_CONTROLTARGET_INCBACKWARD + || nID_ == IDCMD_CONTROLTARGET_FORWARDBEGIN + || nID_ == IDCMD_CONTROLTARGET_BACKWARDBEGIN + || nID_ == IDCMD_CONTROLTARGET_FORWARDEND + || nID_ == IDCMD_CONTROLTARGET_BACKWARDEND + || nID_ == IDCMD_CONTROLTARGET_STARTNEARPOINT + || nID_ == IDCMD_CONTROLTARGET_SIMUCUT) + { + if (!_CheckFileSaved()) + return; + } + + // 没有加工文件的时候,断点继续、前进、后退不可用 ---- 张敬婷 2012-05-25 + ASSERT(GetFileTarget()); + if (GetFileTarget()->GetCurrentCadGroup()->GetNumOfChild() <= 0) + { + #define _PromptEmpty(Id, Action) \ + if (nID_ == Id) \ + { \ + CString _strPrompt; \ + _strPrompt.Format(_GETCS(s_csNoObjInFileForAction), Action); \ + NceShowMessage(_strPrompt); \ + return; \ + } + _PromptEmpty(IDCMD_CONTROLTARGET_BREAKPOINTRESUME, _GETCS(s_csBreakPointResume)); + _PromptEmpty(IDCMD_CONTROLTARGET_JOGFORWARD, _GETCS(s_csGoForward)); + _PromptEmpty(IDCMD_CONTROLTARGET_INCFORWARD, _GETCS(s_csGoForward)); + _PromptEmpty(IDCMD_CONTROLTARGET_FORWARDBEGIN, _GETCS(s_csGoForward)); + _PromptEmpty(IDCMD_CONTROLTARGET_FORWARDEND, _GETCS(s_csGoForward)); + _PromptEmpty(IDCMD_CONTROLTARGET_JOGBACKWARD, _GETCS(s_csGoBackward)); + _PromptEmpty(IDCMD_CONTROLTARGET_INCBACKWARD, _GETCS(s_csGoBackward)); + _PromptEmpty(IDCMD_CONTROLTARGET_BACKWARDBEGIN, _GETCS(s_csGoBackward)); + _PromptEmpty(IDCMD_CONTROLTARGET_BACKWARDEND, _GETCS(s_csGoBackward)); + #undef _PromptEmpty + } + + // 检测加工对象是否超过软限位。 ---- 黄海燕 2015-09-29 + ASSERT(m_vectorCommandItems[_nCmdIndex].nID == nID_); + CStringA _strCommand = m_vectorCommandItems[_nCmdIndex].strCommand; + CStringA _strParameter = m_vectorCommandItems[_nCmdIndex].pGetEParameter ? (this->*m_vectorCommandItems[_nCmdIndex].pGetEParameter)() : ""; + + if (nID_ == IDCMD_CONTROLTARGET_START + || nID_ == IDCMD_CONTROLTARGET_DIRRUN + || nID_ == IDCMD_CONTROLTARGET_STARTSELECTION + || nID_ == IDCMD_CONTROLTARGET_BREAKPOINTRESUME + || nID_ == IDCMD_CONTROLTARGET_STARTNEARPOINT + || nID_ == IDCMD_CONTROLTARGET_SIMUCUT) + { + if (_IsOutsideTheSotfLimit(_strParameter)) + { + NceShowMessage(_GETCS(s_csEXCEEDWORKTABLE)); + return; + } + } + //当进行仿真时,只进行错误提示,但还是会继续加工-----20170714 张磊 + if (nID_ == IDCMD_CONTROLTARGET_SIMULATE) + { + bool _bSimOutRange = false; + if (_IsOutsideTheSotfLimit(_strParameter)) + { + _bSimOutRange = true; + } + CString _strSimOutRange("SimOutRange"); + SendTargetMessage(ID_TARGET_PARAMMANAGER, TM_SET_PARAMVALUE, WPARAM(_strSimOutRange.GetBuffer()), (LPARAM)&_bSimOutRange); + } + // 走边框功能经过多次调整后,支持图形工艺以及加工选中功能,与加工的限位判断条件已经变成一样,故本段注释,将判断和其他操作统一。 ----陈思 2017-06-14 + // 走边框由于不是加工全部图形,也不是加工选中图形,需要单独检测软限位 + //if(nID_ == IDCMD_CONTROLTARGET_SIMUCUT) + //{ + // if (_IsRectOutsideTheSotfLimit(_strParameter)) + // { + // NceShowMessage(_GETCS(s_csEXCEEDWORKTABLE)); + // return; + // } + //} + + // 开始加工前通知各个模块做好准备,如居中当前视图等。 ----黄海燕 2015-05-27 + CString _strAutoAdjust = NceGetPrivateProfileString(_T("ControlTarget"), _T("AutoAdjustView")); + if ((nID_ == IDCMD_CONTROLTARGET_START + || nID_ == IDCMD_CONTROLTARGET_DIRRUN + || nID_ == IDCMD_CONTROLTARGET_SIMUCUT + || nID_ == IDCMD_CONTROLTARGET_BREAKPOINTRESUME) + && _strAutoAdjust == _T("1")) + { + SendTargetMessage(ID_TARGET_VIEWPORTADJUST, TN_TASKSTART); + SendTargetMessage(ID_TARGET_TUBE, TN_TASKSTART); + } + + // 对于管材配置,仿真和其他开始加工的视图表现不同 ---- 吴畏 2016-12-30 + if (nID_ == IDCMD_CONTROLTARGET_SIMULATE && _strAutoAdjust == _T("1")) + { + SendTargetMessage(ID_TARGET_VIEWPORTADJUST, TN_TASKSTART); + SendTargetMessage(ID_TARGET_TUBE, TN_TASKSTART_SIMULATE); + } + + // 如当前为选择加工,则调用相应选择加工指令。 ---- 黄海燕 2016-09-27 + if (nID_ == IDCMD_CONTROLTARGET_START + || nID_ == IDCMD_CONTROLTARGET_SIMULATE + || nID_ == IDCMD_CONTROLTARGET_DIRRUN) + { + // 暂停时调用开始指令,不调用选择加工。 ---- 黄海燕 2016-09-06 + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + mach::CStateManager::State _nState = CStateManager::Idle; + if(_pStateManager->GetState(&_nState) + && _nState != CStateManager::Pausing + && _pStateManager->IsSelectedMach()) + { + ASSERT(_strParameter.IsEmpty()); + _strParameter = _GetParamForCommand_MachSelect(); + if (_strParameter.IsEmpty()) + { + NceShowMessage(_GETCS(s_szNOAVALIBLEOBJECTTOMACH)); + return; + } + + for (int _i = 0; _i < (int)m_vectorWSItems.size(); _i++) + { + if (_strCommand != m_vectorWSItems[_i].strWholeMachCommand) + continue; + _strCommand = m_vectorWSItems[_i].strSelectMachCommand; + break; + } + } + } + + if (nID_ == IDCMD_CONTROLTARGET_BREAKPOINTRESUME) + { + for (int _i = 0; _i < (int)m_vectorWSItems.size(); _i++) + { + // 如果上一次就是选择加工,则直接调用上一个指令。 ---- 黄海燕 2016-09-03 + if (m_vectorWSItems[_i].strSelectMachCommand == m_strLastTaskCommand) + { + _strCommand = m_strLastTaskCommand; + break; + } + + // 如果上一次是完整加工,则调用它的选择加工指令实现。 ---- 黄海燕 2016-09-03 + if (m_vectorWSItems[_i].strWholeMachCommand == m_strLastTaskCommand) + { + _strCommand = m_vectorWSItems[_i].strSelectMachCommand; + break; + } + } + } + + // 真实加工和空运行才支持断点继续。 ---- 黄海燕 2016-09-03 + if (nID_ == IDCMD_CONTROLTARGET_START + || nID_ == IDCMD_CONTROLTARGET_DIRRUN + || nID_ == IDCMD_CONTROLTARGET_STARTSELECTION + || nID_ == IDCMD_CONTROLTARGET_STARTNEARPOINT) + { + m_strLastTaskCommand = _strCommand; + m_strLastTaskCommandParam = _strParameter; + } + + // 仿真前先计算和显示预估时间 ---- 杨开锦 2016-10-11 + if (nID_ == IDCMD_CONTROLTARGET_START + || nID_ == IDCMD_CONTROLTARGET_SIMULATE) + { + CalculateOneHoleTime(); + CTubeTarget* _pTubeTarget = GetTubeTarget(); + ASSERT(_pTubeTarget); + if (!_pTubeTarget->IsEnable()) + { + // 管材配置不显示 + AfxGetMainWnd()->SendMessage(WM_COMMAND, IDCMD_RUNREPORTTARGET_SHOWESTIMATION); + // Fix TFS work item #2739 to enable shortcut keys + AfxGetMainWnd()->SetFocus(); + } + } + + // 记录一下断点的位置。 + if ((nID_ != IDCMD_CONTROLTARGET_BREAKPOINTRESUME && _strCommand == _T("StartSelection")) || + (nID_ == IDCMD_CONTROLTARGET_STARTNEARPOINT && _strCommand == _T("NearStart"))) + + { + NceFilePos _nPos = _SelectionFirst(_strParameter); + CStateManager* _pStateManager = GetStateManager(); + _pStateManager->SetSelectedMachFilePos(_nPos); + } + + // 调用 ---- 杨开锦 2012-04-14 + ExecuteCommand(_strCommand, _strParameter); +} + +void CControlTarget::OnUpdateCommandUI(CCmdUI* pCmdUI_) +{ + // 查找 ---- 杨开锦 2012-04-13 + size_t _nCmdIndex = m_vectorCommandItems.size(); + for (size_t _i = 0; _i < m_vectorCommandItems.size(); _i++) + { + const CommandItem& _item = m_vectorCommandItems[_i]; + if (pCmdUI_->m_nID != _item.nID) + { + continue; + } + + _nCmdIndex = _i; + break; + } + if (_nCmdIndex < 0 || m_vectorCommandItems.size() <= _nCmdIndex) + { + // 谁发现进了这里请告诉我 ---- 杨开锦 2012-08-06 + ASSERT(FALSE); + return; + } + + // 更新 ---- 杨开锦 2012-04-14 + bool _bEnable = false; + ASSERT(m_vectorCommandItems[_nCmdIndex].nID == pCmdUI_->m_nID); + CStringA _strCommand = m_vectorCommandItems[_nCmdIndex].strCommand; + CStringA _strParameter = m_vectorCommandItems[_nCmdIndex].strCEParameter; + _bEnable = CanExecuteCommand(_strCommand, _strParameter); + static const struct RunningStateItem + { + UINT nID; + DWORD nMask; + } _s_cItem[] = + { + {IDCMD_CONTROLTARGET_START, 0x00000001}, + {IDCMD_CONTROLTARGET_SIMULATE, 0x00000002}, + {IDCMD_CONTROLTARGET_DIRRUN, 0x00000004}, + {IDCMD_CONTROLTARGET_SIMUCUT, 0x00000008}, + {IDCMD_CONTROLTARGET_BACKR, 0x00000010}, + {IDCMD_CONTROLTARGET_BACKW, 0x00000020}, + {IDCMD_CONTROLTARGET_MOVETOFIXPOS, 0x00000040}, + {IDCMD_CONTROLTARGET_PAUSE, 0}, + }; + + for (int _i = 0; _i < _countof(_s_cItem); _i++) + { + if (pCmdUI_->m_nID == _s_cItem[_i].nID) + { + CStateManager* _pStateManager = GetStateManager(); + if (!_pStateManager) + { + break; + } + + BOOL _bCheck = FALSE; + if (pCmdUI_->m_nID == IDCMD_CONTROLTARGET_PAUSE) + { + // 暂停 + mach::CStateManager::State _nState = CStateManager::Idle; + if(_pStateManager->GetState(&_nState) && _nState == CStateManager::Pausing) + { + _bCheck = TRUE; + } + } + else + { + DWORD _nRunningState = 0; + _pStateManager->GetRunningState(&_nRunningState); + _bCheck = _nRunningState & _s_cItem[_i].nMask; + } + + // 方管下走边框不可用 ---- 吴畏 2017-01-11 + if (pCmdUI_->m_nID == IDCMD_CONTROLTARGET_SIMUCUT) + { + CTubeTarget* _pTubeTarget = GetTubeTarget(); + if (_pTubeTarget && _pTubeTarget->IsEnable()) + { + _bEnable = FALSE; + } + } + + if (_bEnable) + { + pCmdUI_->SetCheck(FALSE); + pCmdUI_->Enable(); + return; + } + + if (_bCheck) + { + pCmdUI_->SetCheck(); + } + else + { + pCmdUI_->SetCheck(FALSE); + pCmdUI_->Enable(_bEnable); + } + + return; + } + } + + pCmdUI_->Enable(_bEnable ? TRUE : FALSE); +} + +// 配置办法: +// [Detect2YError] +// Enable="1" +// Subprogram="BKREF-2YERROR-DETECT" +// 其中,Enable节表示是否启用 双Y偏差检测,Subprogram为双Y偏差检测的子程序。 +// ---- 杨开锦 2012-06-21 +void CControlTarget::OnDetect2YError() +{ + CString _strEnable = NceGetPrivateProfileString(_T("Detect2YError"), _T("Enable"), _T("0")); + _strEnable.Trim(); + if (_strEnable == _T("0")) + { + ASSERT(FALSE); + return; + } + + // 取子程序,RunGCode ---- 杨开锦 2012-06-21 + CStringA _strSubprogram = NceGetPrivateProfileString(_T("Detect2YError"), _T("Subprogram")); + if (_strSubprogram.IsEmpty()) + { + ASSERT(FALSE); + return; + } + + // 提示确认 ---- 杨开锦 2012-06-21 + if (AfxMessageBox(_GETCS(s_csOperateDangerous), MB_YESNO) != IDYES) + { + return; + } + + // 执行检测 ---- 杨开锦 2012-06-21 + CStringA _strGCode; + _strGCode.Format("G65 P\"%s\" L1\n", _strSubprogram); + ExecuteCommand("RunGCode", _strGCode); +} + +// 配置办法: +// [Detect2YError] +// Enable="1" +// Subprogram="BKREF-2YERROR-DETECT" +// 其中,Enable节表示是否启用 双Y偏差检测,如果不启用则不显示菜单。默认为不启用。 +// ---- 杨开锦 2012-06-21 +void CControlTarget::OnUpdateDetect2YError(CCmdUI* pCmdUI_) +{ + ASSERT(pCmdUI_); + + if (pCmdUI_->m_pMenu) + { + CString _strEnable = NceGetPrivateProfileString(_T("Detect2YError"), _T("Enable"), _T("0")); + _strEnable.Trim(); + if (_strEnable == _T("0")) + { + pCmdUI_->m_pMenu->DeleteMenu(pCmdUI_->m_nID, MF_BYCOMMAND); + return; + } + } + + // 取子程序,判断是否可RunGCode ---- 杨开锦 2012-06-21 + CStringA _strSubprogram = NceGetPrivateProfileString(_T("Detect2YError"), _T("Subprogram")); + if (_strSubprogram.IsEmpty()) + { + pCmdUI_->Enable(FALSE); + return; + } + + CStringA _strGCode; + _strGCode.Format("G65 P\"%s\" L1\n", _strSubprogram); + if (!CanExecuteCommand("RunGCode", _strGCode)) + { + pCmdUI_->Enable(FALSE); + return; + } + + pCmdUI_->Enable(TRUE); +} + +void CControlTarget::OnClearW() +{ + // 通过Action完成,以便可撤销 ---- 杨开锦 2012-03-30 + SendTargetMessage(ID_TARGET_SETORIGIN, TN_SETORIGIN, 0, 0); + CClearWorkcoorAction::Do(TRUE); // 可撤销 +} + +void CControlTarget::OnUpdateClearW(CCmdUI* pCmdUI_) +{ + bool _bCanExecute = CanExecuteCommand("ClearW", NULL); + pCmdUI_->Enable(_bCanExecute ? TRUE : FALSE); +} + +void CControlTarget::OnClearWZ() +{ + CClearWorkcoorActionZ::Do(TRUE); +} + +void CControlTarget::OnUpdateClearWZ(CCmdUI* pCmdUI_) +{ + // 加工时也不能手动设置Z的工件原点。 ---- 黄海燕 2014-12-23 + CStateManager* _pStateManager = GetStateManager(); + CStateManager::State _nState = CStateManager::Idle; + bool _bCanExecute = _pStateManager + && _pStateManager->GetState(&_nState) + && (_nState == CStateManager::Idle + || _nState == CStateManager::Estop + || _nState == CStateManager::Invalid) + && CanExecuteCommand("ClearWZ", NULL); + pCmdUI_->Enable(_bCanExecute ? TRUE : FALSE); +} + +void CControlTarget::OnStop() +{ + ASSERT(!CanExecuteCommand("Stop", NULL) || !CanExecuteCommand("StopSimulate", NULL)); + + if (CanExecuteCommand("Stop", NULL)) + { + ExecuteCommand("Stop", NULL); + } + + if (CanExecuteCommand("StopSimulate", NULL)) + { + ExecuteCommand("StopSimulate", NULL); + } +} + +void CControlTarget::OnUpdateStop(CCmdUI* pCmdUI_) +{ + ASSERT(!CanExecuteCommand("Stop", NULL) || !CanExecuteCommand("StopSimulate", NULL)); + bool _bCanExecute = CanExecuteCommand("Stop", NULL) || CanExecuteCommand("StopSimulate", NULL); + bool _bBoardSupport = NceGetPrivateProfileString(_T("ControlTarget"), _T("BoardSupport")) == _T("1"); + // 顶料端口打开时会和仿真一样进入锁定状态,所以会使stop和stopsimulate同时为true, + // 为了顶料端口打开的时候禁止停止按键,临时加一个判断解决问题,后续应更改解决方案----2017.06.27 陈思 + if (_bBoardSupport) + { + mach::CPortsManager* _pPortsManager = mach::GetPortsManager(); + mach::BitPort _BitPort; + _pPortsManager->GetBitPort("10038", &_BitPort); + if (_BitPort.bValue) + { + _bCanExecute = false; + } + } + pCmdUI_->Enable(_bCanExecute ? TRUE : FALSE); +} + +void CControlTarget::OnBackRDlg() +{ + CBkrefDlg _dlg; + _dlg.m_bShowBkrefDlgWhenStart = m_bShowBkrefDlgWhenStart; + _dlg.m_bAutoZBkrefWhenStart = m_bAutoZBkrefWhenStart; + _dlg.DoModal(); + m_bShowBkrefDlgWhenStart = _dlg.m_bShowBkrefDlgWhenStart; + m_bAutoZBkrefWhenStart = _dlg.m_bAutoZBkrefWhenStart; +} + +void CControlTarget::OnUpdateBackRDlg(CCmdUI* pCmdUI_) +{ +} + +void CControlTarget::OnUpdateZBackOrg(CCmdUI* pCmdUI_) +{ + bool _bShow = NceGetPrivateProfileString(_T("ControlTarget"), _T("EnableZ"), " ") == "1"; + if (pCmdUI_->m_pMenu && !_bShow) + { + pCmdUI_->m_pMenu->DeleteMenu(pCmdUI_->m_nID, MF_BYCOMMAND); + } + pCmdUI_->Enable(CanExecuteCommand("BackRZ", "Z")); +} + +void CControlTarget::OnUpdateFollowCtrl(CCmdUI* pCmdUI_) +{ + bool _bEnable = CanExecuteCommand("FollowCtrl", NULL); + pCmdUI_->Enable(_bEnable ? TRUE : FALSE); + if (pCmdUI_->m_pMenu && !_bEnable) + { + pCmdUI_->m_pMenu->DeleteMenu(pCmdUI_->m_nID, MF_BYCOMMAND); + } +} + +void CControlTarget::OnIsMachSelected() +{ + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + BOOL _bMachSelected = _pStateManager->IsSelectedMach(); + _bMachSelected = !_bMachSelected; + _pStateManager->SetSelectedMach(_bMachSelected); + //设置加工选中图形是否勾选的flag于CMachineControlDlg,用于两个界面同步----20170712 张磊 + ((CMachineControlDlg*)m_pwndControlDlg)->SetSelectMach(_bMachSelected); +} + +void CControlTarget::OnUpdateIsMachSelected(CCmdUI* pCmd_) +{ + CStateManager* _pStateManager = GetStateManager(); + CStateManager::State _nState = CStateManager::Idle; + bool _bEnable = _pStateManager + && _pStateManager->GetState(&_nState) + && _nState == CStateManager::Idle; + pCmd_->SetCheck(_pStateManager && _pStateManager->IsSelectedMach()); + pCmd_->Enable(_bEnable); +} + +void CControlTarget::OnUpdateStartSelectNotMove(CCmdUI* pCmd_) +{ + CStateManager* _pStateManager = GetStateManager(); + CStateManager::State _nState = CStateManager::Idle; + bool _bEnable = _pStateManager + && _pStateManager->GetState(&_nState) + && _nState == CStateManager::Idle + && CanExecuteCommand("StartSelection", "0,1"); + pCmd_->Enable(_bEnable); +} + +// 定时器更新Vision ---- 杨开锦 2012-04-17 +void CControlTarget::OnEvery40Millisecond(WPARAM wParam_, LPARAM lParam_) +{ + _DoTraceKeyState(); + + // Every 160 Millisecond ---- 杨开锦 2012-04-17 + static int _s_nTimerCount = rand(); + _s_nTimerCount = (_s_nTimerCount + 1) % 4; + if (_s_nTimerCount == 0) + { + UpdateVisions(); + } +} + +void CControlTarget::OnPostInitInstance(WPARAM wParam_, LPARAM lParam_) +{ + if (m_bShowBkrefDlgWhenStart) + { + CWnd* _pMainWnd = AfxGetMainWnd(); + ASSERT(_pMainWnd); + _pMainWnd->SendMessage(WM_COMMAND, IDCMD_CONTROLTARGET_BACKRDLG, 0L); + } + + if (m_bAutoZBkrefWhenStart) + { + // 直接调用命令执行,如果发送CMD消息来执行还会弹出一个确认对话框 ---- DingQiang 2016-09-18 + ExecuteCommand("BackRZ", NULL); + } + + bool _bCheckWPosition = (NceGetPrivateProfileString(_T("ExchangeWorkbench"), _T("Enable"), _T("0")) == "1"); + if (_bCheckWPosition) + { + CWnd* _pMainWnd = AfxGetMainWnd(); + ASSERT(_pMainWnd); + _pMainWnd->SendMessage(WM_COMMAND, IDCMD_EXCHANGEWORKBENCHTARGET_CHECKWPOSITION, 0L); + } +} + +void CControlTarget::OnDirectSet() +{ + // 设置XY所在通道机械原点标志。 ---- 黄海燕 2015-01-04 + if (CanExecuteCommand("DirectSet", NULL)) + { + ExecuteCommand("DirectSet", NULL); + } + + // 设置Z所在通道机械原点标志。 ---- 黄海燕 2015-01-04 + if (CanExecuteCommand("DirectSetZ", NULL)) + { + ExecuteCommand("DirectSetZ", NULL); + } +} + +void CControlTarget::OnUpdateDirectSet(CCmdUI* pCmdUI_) +{ + bool _bCanExecute = CanExecuteCommand("DirectSet", NULL) || CanExecuteCommand("DirectSetZ", NULL); + pCmdUI_->Enable(_bCanExecute); +} + +bool CControlTarget::_CheckFileSaved() +{ + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + if (!_pFileTarget->IsModified()) // 已保存 + { + return true; + } + + bool _bNeedPrompt; + // 读取ini文件的参数---- DingQiang 2012-05-07 + CString _strTranslateType = NceGetPrivateProfileString(_T("ControlTarget"), _T("NeedPromptSave")); + int _nTranslateType = atoi(_strTranslateType); + switch (_nTranslateType) + { + case 0: _bNeedPrompt = false; break; + case 1: _bNeedPrompt = true; break; + default: ASSERT(FALSE); _bNeedPrompt = true; + } + + if (!_bNeedPrompt) + { + AfxGetMainWnd()->SendMessage(WM_COMMAND, IDCMD_FILETARGET_SAVE_WITHOUTDIALOG); + if (!_pFileTarget->IsModified()) + { + return true; + } + else + return false; + } + else + { + if (AfxMessageBox(_GETCS(s_csFileChanged), MB_YESNO) == IDYES) // 提示保存 + { + AfxGetMainWnd()->SendMessage(WM_COMMAND, IDCMD_FILETARGET_SAVE); + if (!_pFileTarget->IsModified()) + { + return true; + } + else + { + return false; + } + } + else // 提示了,但不保存 + { + ASSERT(_pFileTarget->IsModified()); + return false; + } + } +} + +bool CControlTarget::_CheckWorktable() +{ + // 当前cam的外接矩形 ---- DingQiang 2015-09-30 + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + static CSimuCutHelper _s_SimuCutHelper; + DRECT _rcBound = _s_SimuCutHelper.GetBoundRect(_pFileTarget->GetCurrentCamGroup()); + + // 工作台矩形 ---- DingQiang 2015-09-30 + double _pWorktable[4]; + DRECT _rcWorktable; + SendTargetMessage(ID_TARGET_WORKTABLE, TM_GET_WORKTABLE,(WPARAM)_pWorktable); + _rcWorktable.x = _pWorktable[0]; + _rcWorktable.y = _pWorktable[1]; + _rcWorktable.width = _pWorktable[2]; + _rcWorktable.height = _pWorktable[3]; + + return _rcWorktable.Contains(_rcBound); +} + +// 走边框G指令 ---- 杨开锦 2012-04-14 +CStringA CControlTarget::_GetParamForCommand_SimuCut() +{ + // 当前图形的外接矩形 ---- 杨开锦 2012-04-14 + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + DRECT _rcBound; + DRECT _rcBoundLast; + if (_pStateManager->IsSelectedMach()) + { + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + CCadGroup* _pCadGroup = _pFileTarget->GetCurrentCadGroup(); + if (NULL == _pCamGroup || NULL == _pCadGroup) + { + return ""; + } + + if (_pCamGroup->GetNumOfChild() <= 0 || _pCadGroup->GetNumOfChild() <= 0) + { + return ""; + } + + // 选中加工,直接联合所有选中CAM的外框 ---- 吴畏 2017-06-08 + bool _bFirstRect = true; + CamObjectList* _plistCamObjs = _pCamGroup->GetObjectsList(); + for (CamObjectList::const_iterator _it = _plistCamObjs->begin(); _it != _plistCamObjs->end(); _it++) + { + // 不需要考虑重合的CAM + CCamObject* _pCam = *_it; + CCadObject* _pCad = NULL; + + // 根据Cam中的CadID属性找到对应的Cad + bool _bFound = _FindObjectByID(_pCadGroup, (int)_pCam->GetKey_DBL("CadID"), &_pCad); + ASSERT(_bFound); + + // TFS#4040 - 选中加工图形走边框后,删除某图形,接着走边框将返回false ---- yangxiaobin + if (!_bFound) + continue; + if (_pCad!=NULL && _pCad->IsSelected()) + { + static CSimuCutHelper _s_SimuCutHelper; + _rcBoundLast = _s_SimuCutHelper._GetBoundRect_Object(_pCam); + if (_bFirstRect) + { + _rcBound = _rcBoundLast; + _bFirstRect = false; + } + else + { + DRECT::Union(_rcBound, _rcBound, _rcBoundLast); + } + } + } + } + else + { + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + static CSimuCutHelper _s_SimuCutHelper; + _rcBound = _s_SimuCutHelper.GetBoundRect(_pFileTarget->GetCurrentCamGroup()); + } + + if (_rcBound.width < 0.0 || _rcBound.height < 0.0) + { + return ""; + } + + // 逆时针走边框 + DPOINT2 _ptCor[] = // Corner + { + DPOINT2(_rcBound.GetLeft(), _rcBound.GetBottom()), + DPOINT2(_rcBound.GetRight(), _rcBound.GetBottom()), + DPOINT2(_rcBound.GetRight(), _rcBound.GetTop()), + DPOINT2(_rcBound.GetLeft(), _rcBound.GetTop()), + }; + + // 若设置了巡边定位,外接矩形框需调整 ---- 嘎松卓玛 2012.11.14 + CWCSAdjustTarget* _pWCSAdjustTarget = GetWCSAdjustTarget(); + if (_pWCSAdjustTarget) + { + for (int _i = 0; _i < _countof(_ptCor); _i++) + { + _ptCor[_i] = _pWCSAdjustTarget->DoWCSAdjust(_ptCor[_i]); + } + } + + // 以主轴当前位置最优起始索引 ---- 杨开锦 2012-04-14 + size_t _nBSI = 0; // BestStartIndex + if (CParamManager* _pParamManager = GetParamManager()) + { + DPOINT2 _ptCurrentPos; + ParameterValue _ParameterValueAxis0; + ParameterValue _ParameterValueAxis1; + _pParamManager->GetParameterValue("State_Axis0_WorkcoorPos", &_ParameterValueAxis0); + _pParamManager->GetParameterValue("State_Axis1_WorkcoorPos", &_ParameterValueAxis1); + if ((_ParameterValueAxis0.nType == ParameterValue::VT_DOUBLE) + &&(_ParameterValueAxis1.nType == ParameterValue::VT_DOUBLE)) + { + _ptCurrentPos.x = _ParameterValueAxis0.dValue; + _ptCurrentPos.y = _ParameterValueAxis1.dValue; + + double _nBestDistance = DBL_MAX; + for (size_t _i = 0; _i < _countof(_ptCor); _i++) + { + double _nDistance = (_ptCor[_i] - _ptCurrentPos).GetLength(); + if (_nDistance < _nBestDistance) + { + _nBSI = _i; + _nBestDistance = _nDistance; + } + } + } + } + + // 该变量用于保存要走边框图形的外接矩形生成的G代码 ---- 嘎松卓玛 2012-02-24 + CStringA _strGCode = ""; + + // 以便RunCode时可以知道是由什么命令触发 + _strGCode.Append("'Command=SimuCut\n"); + + // 写时间戳,使每次生成的Code是不一样的 + SYSTEMTIME _t; + GetLocalTime(&_t); + _strGCode.AppendFormat("'Time=%d-%02d-%02d %02d:%02d:%02d\n", _t.wYear, _t.wMonth, _t.wDay, _t.wHour, _t.wMinute, _t.wSecond); + + // 执行走边框前一些动作,如随动打开关闭随动等。 ---- 黄海燕 2015-10-11 + CStringA _strPreSubPro = NceGetPrivateProfileString(_T("ControlTarget"), _T("PreSimuCutActions")); + if (!_strPreSubPro.IsEmpty()) + { + CStringA _strPreActions; + _strPreActions.Format("G65 P\"%s\" L1\n", _strPreSubPro); + _strGCode.AppendFormat(_strPreActions); + } + + // 走边框速度 + CStringA _strG = "G00"; + CStringA _strF = ""; + CString _strSimuCutSpeed = NceGetPrivateProfileString(_T("ControlTarget"), _T("SimuCutSpeed")); + if (!_strSimuCutSpeed.IsEmpty()) + { + _strG = "G905 G00"; + _strF.Format("F=%s", CStringA(_strSimuCutSpeed)); + } + + C_ASSERT(_countof(_ptCor) == 4); + _strGCode.AppendFormat("%s X%.4f Y%.4f %s\r\n", _strG, _ptCor[(_nBSI + 0) % 4].x, _ptCor[(_nBSI + 0) % 4].y, _strF); + _strGCode.AppendFormat("%s X%.4f Y%.4f %s\r\n", _strG, _ptCor[(_nBSI + 1) % 4].x, _ptCor[(_nBSI + 1) % 4].y, _strF); + _strGCode.AppendFormat("%s X%.4f Y%.4f %s\r\n", _strG, _ptCor[(_nBSI + 2) % 4].x, _ptCor[(_nBSI + 2) % 4].y, _strF); + _strGCode.AppendFormat("%s X%.4f Y%.4f %s\r\n", _strG, _ptCor[(_nBSI + 3) % 4].x, _ptCor[(_nBSI + 3) % 4].y, _strF); + _strGCode.AppendFormat("%s X%.4f Y%.4f %s\r\n", _strG, _ptCor[(_nBSI + 4) % 4].x, _ptCor[(_nBSI + 4) % 4].y, _strF); + if(NceGetPrivateProfileString(_T("ControlTarget"), _T("AutoClearW")) == _T("1")) + { + // 开始前设置了当前点为原点,结束后就要回原点 ---- DingQiang 2015-06-09 + _strGCode.AppendFormat("G65 P\"TOORG\" L1\n"); + } + return _strGCode; +} + +// 断点继续参数 ---- DingQiang 2015-06-30 +CStringA CControlTarget::_GetParamForCommand_BreakPointResume() +{ + //执行断点继续前先判断下当前所用气体气压是否低 + _SendGasPressureInfo(); + + // 读取当前采用的断点位置是哪一种: + // 0或者没有配则表示采用默认的文件位置,即机床停止后不动时的文件位置。 + // 1表示停止消息发出时的位置,此时一般会在内核执行停止前关光,用这个文件位 + // 置的目的就是为了能接上关光的位置 ---- DingQiang 2015-06-30 + CString _strBPPT = NceGetPrivateProfileString(_T("ControlTarget"), _T("BreakPointPosType")); + int _nBPPT = _strBPPT.IsEmpty() ? 0 : atoi(_strBPPT); + + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + ASSERT(_nBPPT == 0 || _nBPPT == 1); + NceFilePos _StartPos; + if (_nBPPT == 0) + { + _StartPos = CFilePositionHelper::GetCurrentMachFilePosition(); + } + else + { + ParameterValue _ParameterValue; + memset(&_ParameterValue, 0, sizeof(ParameterValue)); + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + _pParamManager->GetParameterValue("PreStopFilePos", &_ParameterValue); + ASSERT(_ParameterValue.nType == ParameterValue::VT_INT64); + // 1. Get start position + _StartPos = _ParameterValue.i64Value; + } + + CString _strBackDistance = NceGetPrivateProfileString(_T("BreakPointFallback"), _T("BreakPointFallbackDistance")); + double _nBackDistance = atof(_strBackDistance); + ASSERT(_nBackDistance >= 0.0); + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + ASSERT(_pCamGroup); + const CCamObject* _pStartCamObject = CFilePositionHelper::FindCamObjectByID(_pCamGroup, _StartPos.nID); + + // 将回退后的位置作为断点继续的起始位置 ---- 边俊霞 2016-10-10 + if (_pStartCamObject && DOUBLE_GREAT(_nBackDistance, 0.0)) + { + // 当前加工文件的起点和终点不进行回退 ---- 边俊霞 2016-11-02 + NceFilePos _CurrentCamEndPos; + _CurrentCamEndPos = CFilePositionHelper::ScanEndPos(_pStartCamObject); + bool _bStartPos = DOUBLE_EQU(_StartPos.nOffset, 0.0) && DOUBLE_EQU(_StartPos.nRate, 0.0); + bool _bEndPos = _StartPos == _CurrentCamEndPos; + + if (!_bStartPos && !_bEndPos) + { + int _nBackOffset = _StartPos.nOffset; + double _nBackRate = _StartPos.nRate; + double _nActualTravelLength = 0.0; + bool _bSucceed = CFilePositionHelper::TravelBackward(dynamic_cast(_pStartCamObject), + _StartPos.nOffset, _StartPos.nRate, _nBackDistance, &_nBackOffset, &_nBackRate, &_nActualTravelLength); + ASSERT(0.0 <= _nActualTravelLength && _nActualTravelLength <= _nBackDistance); + + _StartPos.nOffset = _nBackOffset; + _StartPos.nRate = _nBackRate; + } + } + + if (_StartPos <= EOF) + { + _StartPos = 0; + } + + _pStateManager->SetSelectedMachFilePos(_StartPos); + + if (!_pStateManager->IsSelectedMach()) + { + NceFilePos _nEndPos; + _nEndPos = CFilePositionHelper::ScanEndPos(_pCamGroup); + if (_pStartCamObject && _pStartCamObject->GetType() == campath) + { + int _nEndOffset = _StartPos.nOffset; + double _nEndRate = _StartPos.nRate; + double _nActualTravelLength = 0.0; + bool _bSucceed = CFilePositionHelper::TravelForward(dynamic_cast(_pStartCamObject), + _StartPos.nOffset, _StartPos.nRate, 1.0e-1, + &_nEndOffset, &_nEndRate, &_nActualTravelLength); + ASSERT(_bSucceed); + if (_nActualTravelLength <= 1.0e-2) + { + // 断点所在路径剩下很少,修订到路径末开始 ---- 杨开锦 2012-04-14 + _StartPos.nOffset = _nEndOffset; + _StartPos.nRate = _nEndRate; + } + } + + if (!_pStartCamObject + || _pStartCamObject->GetType() != camhole && _pStartCamObject->GetType() != campath + || (__int64)_StartPos == (__int64)_nEndPos) + { + NceShowMessage(_GETCS(s_csFORBIDRESUME)); + return ""; + } + + CStringA _strParameter; + _strParameter.Format("%lld,%lld", (__int64)_StartPos, (__int64)_nEndPos); + return _strParameter; + } + + ASSERT(m_strLastTaskCommand == _T("StartSelection") + || m_strLastTaskCommand == _T("NearStart") + || m_strLastTaskCommand == _T("DirRunSelection2")); + + ASSERT(!m_strLastTaskCommandParam.IsEmpty()); + CStringA _strParameter = _Mid(m_strLastTaskCommandParam, _StartPos); + if (_strParameter.IsEmpty()) + { + NceShowMessage(_GETCS(s_csFORBIDRESUME)); + } + + return _strParameter; +} + +CStringA CControlTarget::_GetParamForCommand_GoForward() +{ + // 1. Get start position + NceFilePos _StartPos = CFilePositionHelper::GetCurrentMachFilePosition(); + if (_StartPos <= EOF) + { + _StartPos = 0; + } + + // 2. Get end position + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + ASSERT(_pCamGroup); + NceFilePos _nEndPos = CFilePositionHelper::ScanEndPos(_pCamGroup); + + // 3. Working + const CCamObject* _pStartCamObject = CFilePositionHelper::FindCamObjectByID(_pCamGroup, _StartPos.nID); + if (_pStartCamObject && _pStartCamObject->GetType() == campath) + { + int _nEndOffset = _StartPos.nOffset; + double _nEndRate = _StartPos.nRate; + double _nActualTravelLength = 0.0; + bool _bSucceed = CFilePositionHelper::TravelForward(dynamic_cast(_pStartCamObject), + _StartPos.nOffset, _StartPos.nRate, 1.0e-1, + &_nEndOffset, &_nEndRate, &_nActualTravelLength); + ASSERT(_bSucceed); + if (_nActualTravelLength <= 1.0e-2) + { + // 断点所在路径剩下很少,修订到路径末开始 ---- 杨开锦 2012-04-14 + _StartPos.nOffset = _nEndOffset; + _StartPos.nRate = _nEndRate; + } + } + + if (!_pStartCamObject + || _pStartCamObject->GetType() != camhole && _pStartCamObject->GetType() != campath + || (__int64)_StartPos == (__int64)_nEndPos) + { + NceShowMessage(_GETCS(s_csFORBIDRESUME)); + return ""; + } + + CStringA _strParameter; + _strParameter.Format("%lld,%lld", (__int64)_StartPos, (__int64)_nEndPos); + return _strParameter; +} + +CStringA CControlTarget::_GetParamForCommand_StartNearPoint() +{ + //执行临近点加工前先判断下当前所用气体气压是否低 + _SendGasPressureInfo(); + + //找到当前工件坐标位置 ---- DingQiang 2013-06-28 + DPOINT2 _ptCur; + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParameterValue; + memset(&_ParameterValue, 0, sizeof(ParameterValue)); + _pParamManager->GetParameterValue("State_Axis0_WorkcoorPos", &_ParameterValue); + ASSERT(_ParameterValue.nType == ParameterValue::VT_DOUBLE); + _ptCur.x = _ParameterValue.dValue; + _pParamManager->GetParameterValue("State_Axis1_WorkcoorPos", &_ParameterValue); + ASSERT(_ParameterValue.nType == ParameterValue::VT_DOUBLE); + _ptCur.y = _ParameterValue.dValue; + + // 读邻近点半径 ---- DingQiang 2013-06-26 + CString _strNearRadius = NceGetPrivateProfileString(_T("ControlTarget"), _T("NearPointRadius")); + double _nNearRadius = _tstof(_strNearRadius); + + // 找到满足要求集合的Cad图形的ID集合 ---- DingQiang 2013-06-26 + CFileTarget* _pFileTarget = GetFileTarget(); + const CCadGroup* _pCurrentCadGroup = _pFileTarget->GetCurrentCadGroup(); + setUINT _setIDs; + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + if (_pStateManager->IsSelectedMach()) + { + // 如果是勾选了<加工选中图形>,则是从选中图形中提取邻近图形 ---- 杨开锦 2016-09-13 + CSelectTarget* _pSelectTarget = GetSelectTarget(); + ASSERT(_pSelectTarget); + const CadObjectList* _plistSelectedCads = _pSelectTarget->GetSelectedCadObjects(); + ASSERT(_plistSelectedCads); + CCadGroup _group; + *(_group.GetObjectsList()) = *_plistSelectedCads; + GetCadIDByCircle(&_group, _ptCur, _nNearRadius, _setIDs); + _group.PickOffAll(); + } + else + { + GetCadIDByCircle(_pCurrentCadGroup, _ptCur, _nNearRadius, _setIDs); + } + + if (_setIDs.size() == 0) + { + NceShowMessage(_GETCS(s_csNoNearPoint)); + return ""; + } + + // 在cam数据中找到这些ID集合的cam数据,再求出目标点到每个cam的距离,求出最近 + // 的cam数据 ---- DingQiang 2013-06-26 + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + CamObjectList _listCam; + GetCamListByCadID(_pCamGroup, _setIDs, &_listCam); + if (_listCam.size() == 0) + { + NceShowMessage(_GETCS(s_csNoNearPoint)); + return ""; + } + + // 找最近的点的文件位置 ---- DingQiang 2013-06-27 + __int64 _StartPos = 0; + double _nMinDis = GetCamMinDistance(&_listCam, _ptCur, &_StartPos); + ASSERT(_nMinDis < DBL_MAX); + + CStringA _strParameter; + if (_pStateManager->IsSelectedMach()) + { + // 如果是勾选了<加工选中图形>,则是从选中图形的加工范围里选取 ---- 杨开锦 2016-09-13 + _strParameter = _Mid(_GetParamForCommand_MachSelect(), _StartPos); + } + else + { + NceFilePos _nEndPos = CFilePositionHelper::ScanEndPos(_pCamGroup); + if((__int64)_StartPos != (__int64)_nEndPos) + _strParameter.Format("%lld,%lld", (__int64)_StartPos, (__int64)_nEndPos); + } + + // 开始和结速点在同一个位置时不加工 ---- DingQiang 2013-06-28 + if (_strParameter.IsEmpty()) + { + NceShowMessage(_GETCS(s_csFORBIDNEARSTART)); + } + + return _strParameter; +} + +CStringA CControlTarget::_GetParamForCommand_MachSelect() +{ +// MAKE_NCEPOS() + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + CCadGroup* _pCadGroup = _pFileTarget->GetCurrentCadGroup(); + ASSERT(_pCadGroup); + setUINT _selectCadId; + GetCadSelectID(_pCadGroup, _selectCadId); + if (_selectCadId.size() == 0) + { + return ""; + } + + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + ASSERT(_pCamGroup); + listCamInfo _selectCamInfo; + GetCamSelectID(_pCamGroup, _selectCadId, _selectCamInfo); + if (_selectCamInfo.size() == 0) + { + return ""; + } + + CStringA _str; + for (listCamInfo::const_iterator _it = _selectCamInfo.begin(); _it != _selectCamInfo.end(); ++_it) + { + _str.AppendFormat("%lld,%lld;", _it->nStartPos, _it->nEndPos); + } + + if (!_str.IsEmpty()) + { + _str = _str.Left(_str.GetLength() - 1); + } + return _str; +} + +CStringA CControlTarget::_GetParamForCommand_GoBackward() +{ + // 1. Get start position + NceFilePos _StartPos = CFilePositionHelper::GetCurrentMachFilePosition(); + if (_StartPos <= EOF) + { + _StartPos = 0; + } + + // 2. Get end position + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + ASSERT(_pCamGroup); + NceFilePos _nEndPos = CFilePositionHelper::ScanStartPos(_pCamGroup); + + // 3. Working + const CCamObject* _pStartCamObject = CFilePositionHelper::FindCamObjectByID(_pCamGroup, _StartPos.nID); + if (_pStartCamObject && _pStartCamObject->GetType() == campath) + { + int _nEndOffset = _StartPos.nOffset; + double _nEndRate = _StartPos.nRate; + double _nActualTravelLength = 0.0; + bool _bSucceed = CFilePositionHelper::TravelBackward(dynamic_cast(_pStartCamObject), + _StartPos.nOffset, _StartPos.nRate, 1.0e-1, + &_nEndOffset, &_nEndRate, &_nActualTravelLength); + ASSERT(_bSucceed); + if (_nActualTravelLength <= 1.0e-2) + { + // 断点所在路径剩下很少,修订到路径头开始 ---- 杨开锦 2012-04-14 + _StartPos.nOffset = _nEndOffset; + _StartPos.nRate = _nEndRate; + } + } + + if (!_pStartCamObject + || _pStartCamObject->GetType() != camhole && _pStartCamObject->GetType() != campath + || (__int64)_StartPos == (__int64)_nEndPos) + { + NceShowMessage(_GETCS(s_csFORBIDRESUME)); + return ""; + } + + CStringA _strParameter; + _strParameter.Format("%lld,%lld", (__int64)_StartPos, (__int64)_nEndPos); + return _strParameter; +} + +CStringA CControlTarget::_GetParamForCommand_IncForward() +{ + // 1. Get start position + NceFilePos _StartPos = CFilePositionHelper::GetCurrentMachFilePosition(); + if (_StartPos <= EOF) + { + _StartPos = 0; + } + + // 2. Get end position + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + ASSERT(_pCamGroup); + ASSERT(m_nGFOBDistance > 0.0); + NceFilePos _nEndPos = _StartPos; + double _nActualTravelLength = 0.0; + bool _bSucceed = CFilePositionHelper::TravelForward(_pCamGroup, + _StartPos, m_nGFOBDistance, &_nEndPos, &_nActualTravelLength); + ASSERT(0.0 <= _nActualTravelLength && _nActualTravelLength <= m_nGFOBDistance); + + // 3. Working + const CCamObject* _pStartCamObject = CFilePositionHelper::FindCamObjectByID(_pCamGroup, _StartPos.nID); + if (_pStartCamObject && _pStartCamObject->GetType() == campath) + { + int _nEndOffset = _StartPos.nOffset; + double _nEndRate = _StartPos.nRate; + double _nActualTravelLength = 0.0; + bool _bSucceed = CFilePositionHelper::TravelForward(dynamic_cast(_pStartCamObject), + _StartPos.nOffset, _StartPos.nRate, 1.0e-1, + &_nEndOffset, &_nEndRate, &_nActualTravelLength); + ASSERT(_bSucceed); + if (_nActualTravelLength <= 1.0e-2) + { + // 断点所在路径剩下很少,修订到路径头开始 ---- 杨开锦 2012-04-14 + _StartPos.nOffset = _nEndOffset; + _StartPos.nRate = _nEndRate; + } + } + + if (!_pStartCamObject + || _pStartCamObject->GetType() != camhole && _pStartCamObject->GetType() != campath + || (__int64)_StartPos == (__int64)_nEndPos) + { + NceShowMessage(_GETCS(s_csFORBIDRESUME)); + return ""; + } + + CStringA _strParameter; + _strParameter.Format("%lld,%lld", (__int64)_StartPos, (__int64)_nEndPos); + return _strParameter; +} + +CStringA CControlTarget::_GetParamForCommand_IncBackward() +{ + // 1. Get start position + NceFilePos _StartPos = CFilePositionHelper::GetCurrentMachFilePosition(); + if (_StartPos <= EOF) + { + _StartPos = 0; + } + + // 2. Get end position + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + ASSERT(_pCamGroup); + ASSERT(m_nGFOBDistance > 0.0); + NceFilePos _nEndPos = _StartPos; + double _nActualTravelLength = 0.0; + bool _bSucceed = CFilePositionHelper::TravelBackward(_pCamGroup, + _StartPos, m_nGFOBDistance, &_nEndPos, &_nActualTravelLength); + ASSERT(0.0 <= _nActualTravelLength && _nActualTravelLength <= m_nGFOBDistance); + + // 3. Working + const CCamObject* _pStartCamObject = CFilePositionHelper::FindCamObjectByID(_pCamGroup, _StartPos.nID); + if (_pStartCamObject && _pStartCamObject->GetType() == campath) + { + int _nEndOffset = _StartPos.nOffset; + double _nEndRate = _StartPos.nRate; + double _nActualTravelLength = 0.0; + bool _bSucceed = CFilePositionHelper::TravelBackward(dynamic_cast(_pStartCamObject), + _StartPos.nOffset, _StartPos.nRate, 1.0e-1, + &_nEndOffset, &_nEndRate, &_nActualTravelLength); + ASSERT(_bSucceed); + if (_nActualTravelLength <= 1.0e-2) + { + // 断点所在路径剩下很少,修订到路径头开始 ---- 杨开锦 2012-04-14 + _StartPos.nOffset = _nEndOffset; + _StartPos.nRate = _nEndRate; + } + } + + if (!_pStartCamObject + || _pStartCamObject->GetType() != camhole && _pStartCamObject->GetType() != campath + || (__int64)_StartPos == (__int64)_nEndPos) + { + NceShowMessage(_GETCS(s_csFORBIDRESUME)); + return ""; + } + + CStringA _strParameter; + _strParameter.Format("%lld,%lld", (__int64)_StartPos, (__int64)_nEndPos); + return _strParameter; +} + +CStringA CControlTarget::_GetParamForCommand_ForwardBegin() +{ + CStringA _strRet; + if (GetGFOBMode() == 0x00) + { + _strRet = _GetParamForCommand_GoForward(); + } + + return _strRet; +} + +CStringA CControlTarget::_GetParamForCommand_BackwardBegin() +{ + CStringA _strRet; + if (GetGFOBMode() == 0x00) + { + _strRet = _GetParamForCommand_GoBackward(); + } + + return _strRet; +} + +CStringA CControlTarget::_GetParamForCommand_ForwardEnd() +{ + CStringA _strRet; + if (GetGFOBMode() == 0x00) + { + AfxGetMainWnd()->SendMessage(WM_COMMAND, IDCMD_CONTROLTARGET_STOP, 0); + return _strRet; + } + + ASSERT(GetGFOBMode() == 0x01); + _strRet = _GetParamForCommand_IncForward(); + return _strRet; +} + +CStringA CControlTarget::_GetParamForCommand_BackwardEnd() +{ + CStringA _strRet; + if (GetGFOBMode() == 0x00) + { + AfxGetMainWnd()->SendMessage(WM_COMMAND, IDCMD_CONTROLTARGET_STOP, 0); + return _strRet; + } + + ASSERT(GetGFOBMode() == 0x01); + _strRet = _GetParamForCommand_IncBackward(); + return _strRet; +} + +CStringA CControlTarget::_GetParamForXBackR() +{ + return "X"; +} + +CStringA CControlTarget::_GetParamForYBackR() +{ + return "Y"; +} + +CStringA CControlTarget::_GetParamForZBackR() +{ + return "Z"; +} + +CStringA CControlTarget::_GetParamForCommand_BackWZ() +{ + return "G65 P\"TOZORG\" L1\n"; +} + +void CControlTarget::_ToTraceKeyState(UINT nChar_, bool bEnable_) +{ + // 不再跟踪,撤销数据 ---- 杨开锦 2013-09-06 + if (!bEnable_) + { + for(int _i = 0; _i < _countof(m_KeyStates); _i++) + { + KeyState& _ks = m_KeyStates[_i]; + if (_ks.nChar == nChar_) + { + _ks.nChar = 0; + _ks.nState = 0; + } + } + return; + } + + // 开始跟踪,记录初值 ---- 杨开锦 2013-09-06 + BOOL _nInitState = ::GetKeyState(nChar_) < 0 ? 1 : 0; + + for(int _i = 0; _i < _countof(m_KeyStates); _i++) + { + KeyState& _ks = m_KeyStates[_i]; + if (_ks.nChar == nChar_) + { + _ks.nState = _nInitState; + return; + } + } + + for(int _i = 0; _i < _countof(m_KeyStates); _i++) + { + KeyState& _ks = m_KeyStates[_i]; + if (_ks.nChar == 0) + { + _ks.nChar = nChar_; + _ks.nState = _nInitState; + return; + } + } + + // No slot to trace any more ---- 杨开锦 2013-09-06 + ASSERT(FALSE); +} + +void CControlTarget::_DoTraceKeyState() +{ + for(int _i = 0; _i < _countof(m_KeyStates); _i++) + { + KeyState& _ks = m_KeyStates[_i]; + if (_ks.nChar == 0) + { + continue; + } + + BOOL _nState = ::GetKeyState(_ks.nChar) < 0 ? 1 : 0; + if (_nState != _ks.nState) + { + _ks.nState = _nState; + + // 将跟踪到的按键状态变更模拟为键盘消息 ---- 杨开锦 2013-09-06 + MSG _msg = { NULL, _nState == 0 ? WM_KEYUP : WM_KEYDOWN, WPARAM(_ks.nChar), LPARAM(1) }; + OnKeyMessage(&_msg); + } + } +} + +void CControlTarget::GetCadSelectID(IN const CCadGroup* pCadGroup_, OUT setUINT& setIDs_) +{ + ASSERT(pCadGroup_); + int _nNumOfChild = pCadGroup_->GetNumOfChild(); + const CCadObject* _pCadObject = NULL; + typedef std::pair pairRet; + for (int _i = 0; _i != _nNumOfChild; ++_i) + { + _pCadObject = pCadGroup_->GetAt(_i); + if (_pCadObject->IsSelected()) + { + pairRet _Ret = setIDs_.insert(_pCadObject->GetID()); + ASSERT(_Ret.second); + } + if (_pCadObject->GetType() == cadgroup) + { + GetCadSelectID((CCadGroup*)_pCadObject, setIDs_); + } + + // 当选中图形为文字时也要递归求ID ---- DingQiang 2012-11-30 + if (_pCadObject->GetType() == cadtext) + { + CCadText* _pCadText = (CCadText*)_pCadObject; + GetCadSelectID(_pCadText->GetTextGroup(), setIDs_); + } + } +} + +void CControlTarget::GetCamSelectID(IN const nce::CCamGroup* pCamGroup_, IN const setUINT& setIDs_, OUT listCamInfo& setCamInfo_) +{ + ASSERT(pCamGroup_); + ASSERT(setIDs_.size()); + int _nNumOfChild = pCamGroup_->GetNumOfChild(); + for (int _i = 0; _i != _nNumOfChild; ++_i) + { + const CCamObject* _pCamObject = pCamGroup_->GetAt(_i); + cam_t _elet = _pCamObject->GetType(); + if (_elet == camgroup) + { + GetCamSelectID((CCamGroup*)_pCamObject, setIDs_, setCamInfo_); + } + else + { + ASSERT(_elet == camhole || _elet == campath); + UINT _nID = (UINT)_pCamObject->GetKey_DBL("CadID"); + if (setIDs_.find(_nID) != setIDs_.end()) + { + // 使用CFilePositionHelper来进行文件位置的相关计算 ---- 杨开锦 2015-08-30 + CamInfo _caminfo = { + _pCamObject->GetID(), + CFilePositionHelper::ScanStartPos(_pCamObject), + CFilePositionHelper::ScanEndPos(_pCamObject)}; + setCamInfo_.push_back(_caminfo); + } + } + } +} + +void CControlTarget::GetCadIDByCircle(IN const nce::CCadGroup* pCCadGroup_, DPOINT2 ptCenter_, double nRadius_, OUT setUINT& setIDs_) +{ + ASSERT(pCCadGroup_); + int _nNumOfChild = pCCadGroup_->GetNumOfChild(); + const CCadObject* _pCadObject = NULL; + for (int _it = 0; _it < _nNumOfChild; _it++) + { + _pCadObject = pCCadGroup_->GetAt(_it); + if (_pCadObject->GetType() == cadgroup) + { + GetCadIDByCircle((CCadGroup*)_pCadObject, ptCenter_, nRadius_, setIDs_); + continue; + } + + if (_pCadObject->GetType() == cadtext) + { + GetCadIDByCircle(((CCadText*)_pCadObject)->GetTextGroup(), ptCenter_, nRadius_, setIDs_); + continue; + } + + double _nMinDis = GetMinDistance(_pCadObject, ptCenter_); + if (_nMinDis <= nRadius_) + { + setIDs_.insert(_pCadObject->GetID()); + } + } +} + +void CControlTarget::GetCamListByCadID(IN nce::CCamGroup* pCCamGroup_, IN setUINT setIDs_, OUT CamObjectList* plistCamObject) +{ + ASSERT(pCCamGroup_); + ASSERT(plistCamObject->size() == 0); + CCamObject* _pCamObject = NULL; + for (int _it = 0; _it < pCCamGroup_->GetNumOfChild(); _it++) + { + _pCamObject = pCCamGroup_->GetAt(_it); + if (_pCamObject->GetType() == camgroup) + { + GetCamListByCadID((CCamGroup*)_pCamObject, setIDs_, plistCamObject); + continue; + } + + UINT _CadID = (UINT)_pCamObject->GetKey_DBL("CadID"); + if (setIDs_.find(_CadID) != setIDs_.end()) + { + plistCamObject->push_back(_pCamObject); + } + } +} + +// 查找第一个与CadID对应的Cam对象。 ---- 黄海燕 2017-05-21 +void CControlTarget::GetFirstCamObjByCadID(IN nce::CCamGroup* pCCamGroup_, IN UINT nCadID_, OUT CCamObject** ppCamObject_) +{ + ASSERT(pCCamGroup_ && ppCamObject_); + CamObjectList* _plistCamObjs = pCCamGroup_->GetObjectsList(); + for (CamObjectList::iterator _it = _plistCamObjs->begin(); + _it != _plistCamObjs->end(); _it++) + { + // 排除预穿孔产生的点。 ---- 黄海燕 2017-05-21 + if ((*_it)->GetKey_DBL("CadID") == nCadID_ + && (*_it)->GetType() == campath) + { + *ppCamObject_ = *_it; + return; + } + } +} + +double CControlTarget::GetCamMinDistance(IN const nce::CCamObject* pCamObject_, IN DPOINT2 pt_, OUT __int64* pnPos_ /* = NULL */) +{ + ASSERT(pCamObject_); + + double _nMinDis = DBL_MAX; + cam_t _type = pCamObject_->GetType(); + switch (_type) + { + case camhole: + { + CCamHole* _pCamHole = (CCamHole*)pCamObject_; + _nMinDis = GetCamMinDistance(_pCamHole, pt_, pnPos_); + } + break; + case campath: + { + CCamPath* _pCamPath = (CCamPath*)pCamObject_; + _nMinDis = GetCamMinDistance(_pCamPath, pt_, pnPos_); + } + break; + case camgroup: + { + CCamGroup* _pCamGroup = (CCamGroup*)pCamObject_; + _nMinDis = GetCamMinDistance(_pCamGroup->GetObjectsList(), pt_, pnPos_); + } + break; + default: + ASSERT(FALSE); + break; + } + + return _nMinDis; +} + +double CControlTarget::GetCamMinDistance(IN const nce::CCamHole* pCamHole_, IN DPOINT2 pt_, OUT __int64* pnPos_ /*= NULL*/) +{ + ASSERT(pCamHole_); + DPOINT2 _ptTemp(pCamHole_->GetStart().x, pCamHole_->GetStart().y); + + if (pnPos_) + { + NceFilePos _pos; + _pos.SetID(pCamHole_->GetID()); + _pos.SetOffset(0); + _pos.SetRate(0); + + *pnPos_ = (__int64)_pos; + } + + return (pt_ - _ptTemp).GetLength(); +} + +double CControlTarget::GetCamMinDistance(IN const nce::CCamPath* pCamPath_, IN DPOINT2 pt_, OUT __int64* pnPos_ /*= NULL*/) +{ + ASSERT(pCamPath_ != NULL); + double _nMinDis = DBL_MAX; + __int64 _nPos = 0; + + // 如果该Path是NURBS曲线路径,则调用NURBS曲线拟合模块计算最短距离及其对应的文件位置 ---- duquan 2016-07-28 + CCamSplineWrapper _CamSplineWrapper(pCamPath_); + if (_CamSplineWrapper.IsSpline()) + { + NceFilePos _pos; + _pos.SetID(pCamPath_->GetID()); + _pos.SetOffset(0); + _pos.SetRate(0.); + + _nMinDis = _CamSplineWrapper.GetMinDistFromAimPos(pt_, &_pos); + _nPos = (__int64)_pos; + if (pnPos_ != NULL) + *pnPos_ = _nPos; + + return _nMinDis; + } + + UINT _nNodeCount = pCamPath_->GetNodeCount(); + for (UINT _it = 0; _it < _nNodeCount; _it++) + { + double _nDistance = DBL_MAX; + double _nRate = 0; + + CCamPath::NODE _nNode = pCamPath_->GetNode(_it); + CCamPath::NODE_T _typeNode = _nNode.nType; + if (_typeNode == CCamPath::nt_line_xy + || _typeNode == CCamPath::nt_line_x + || _typeNode == CCamPath::nt_line_y) + { + DPOINT2 _ptStart(_nNode.ptStart.x, _nNode.ptStart.y); + DPOINT2 _ptEnd(_nNode.ptEnd.x, _nNode.ptEnd.y); + DPOINT2 _vecTemp = pt_ - _ptStart; + DPOINT2 _vecLine = _ptEnd - _ptStart; + double _nTemp = _vecTemp * _vecLine; + double _nValue = _vecLine * _vecLine; + ASSERT(_nValue >= 0.0); + + DPOINT2 _point; + if (_nTemp < 0.0) + { + _point = _ptStart; + _nRate = 0; + } + else if (_nTemp > _nValue) + { + _point = _ptEnd; + _nRate = 1; + } + else + { + LineD2D _line(_ptStart, _ptEnd); + D2GetProjectionPoint(pt_, _line, &_point); + _nRate = (_point - _ptStart).GetLength() / (_ptEnd - _ptStart).GetLength(); + } + + _nDistance = (pt_ - _point).GetLength(); + } + else if (_typeNode == CCamPath::nt_arc_xy) + { + DPOINT2 _ptStart(_nNode.ptStart.x, _nNode.ptStart.y); + DPOINT2 _ptEnd(_nNode.ptEnd.x, _nNode.ptEnd.y); + DPOINT2 _ptCenter; + double _nStartAngle; + double _nRadius; + double _nSweptAngle; + SEGMENT::SolveArc(_ptStart, _ptEnd, _nNode.nBulge, &_ptCenter, &_nRadius, &_nStartAngle, &_nSweptAngle); + + DPOINT2 _vector = pt_ - _ptCenter; + double _nAngle = D2GetNormalAngle(_vector); + double _nMin = _nSweptAngle > 0 ? _nStartAngle : _nStartAngle + _nSweptAngle; + double _nMax = _nSweptAngle > 0 ? _nStartAngle + _nSweptAngle : _nStartAngle; + bool _bInRange = IsInRange(_nAngle, _nMin, _nMax); + if (_bInRange) + { + _nDistance = abs((pt_ - _ptCenter).GetLength() - _nRadius); + _nRate = (_nAngle - _nStartAngle) / _nSweptAngle; + } + else + { + double _nDis1 = (pt_ - _ptStart).GetLength(); + double _nDis2 = (pt_ - _ptEnd).GetLength(); + if (_nDis1 < _nDis2) + { + _nDistance = _nDis1; + _nRate = 0; + } + else + { + _nDistance = _nDis2; + _nRate = 1; + } + } + } + else if (_typeNode == CCamPath::nt_circle_xy_cw + || _typeNode == CCamPath::nt_circle_xy_ccw) + { + DPOINT2 _ptCenter(_nNode.ptCenter.x, _nNode.ptCenter.y); + DPOINT2 _vector = pt_ - _ptCenter; + double _nRadius = _nNode.nRadius; + double _nAngle = D2GetNormalAngle(_vector); + double _nLength = (pt_ - _ptCenter).GetLength(); + if (_typeNode == CCamPath::nt_circle_xy_cw) + { + _nRate = (2 * c_nPIE - _nAngle) / (2 * c_nPIE); + } + else + { + _nRate = _nAngle / (2 * c_nPIE); + } + + _nDistance = abs(_nLength - _nRadius); + } + else + { + ASSERT(FALSE); + continue; + } + + if (_nDistance < _nMinDis) + { + _nMinDis = _nDistance; + NceFilePos _pos; + _pos.SetID(pCamPath_->GetID()); + + // 当起点等于终点,并且找到的点离起点距离很小时则修订到图形起点 ---- DingQiang 2013-07-08 + if (pCamPath_->GetStartPoint() == pCamPath_->GetEndPoint() + && _it == _nNodeCount -1 + && abs(_nRate - 1) < 1.0e-2) + { + _pos.SetOffset(0); + _pos.SetRate(0); + } + else + { + _pos.SetOffset(_it); + _pos.SetRate(_nRate); + } + + _nPos = (__int64)_pos; + } + } + + if (pnPos_) + { + *pnPos_ = _nPos; + } + + return _nMinDis; +} + +double CControlTarget::GetCamMinDistance(IN const nce::CamObjectList* plistCamObject_, IN DPOINT2 pt_, OUT __int64* pnPos_ /*= NULL*/) +{ + ASSERT(plistCamObject_ && plistCamObject_->size() > 0); + double _nMinDis = DBL_MAX; + __int64 _nPos = 0; + const CCamObject* _pCamObject = NULL; + for (CamObjectList::const_iterator _it = plistCamObject_->begin(); _it != plistCamObject_->end(); _it++) + { + const CCamObject* _pCam = *_it; + __int64 _nPosTemp =0; + double _nDistance = GetCamMinDistance(_pCam, pt_, &_nPosTemp); + if (_nDistance < _nMinDis) + { + _nMinDis = _nDistance; + _nPos = _nPosTemp; + _pCamObject = _pCam; + } + } + + if (pnPos_ && _pCamObject) + { + *pnPos_ = _nPos; + } + + return _nMinDis; +} + +bool operator<(const CamInfo& caminfo1_, const CamInfo& caminfo2_) +{ + return caminfo1_.nID < caminfo2_.nID; +}; + +BOOL CControlTarget::OnKeyMessage(const MSG* pMsg_) +{ + ASSERT(pMsg_); + + CCommandManager* _pCommandManager = GetCommandManager(); + if (!_pCommandManager) + { + return FALSE; + } + + //如果焦点窗口是编辑框,则不进行手动操作 ---- 杨开锦 2012-04-13 + HWND _hwndFocus = ::GetFocus(); + if (::IsWindow(_hwndFocus)) + { + TCHAR _szWndClassName[64]; + memset(_szWndClassName, 0, _countof(_szWndClassName) * sizeof(TCHAR)); + ::GetClassName(_hwndFocus, _szWndClassName, _countof(_szWndClassName)); + if (!_tcsicmp(_szWndClassName, _T("Edit"))) + { + return FALSE; + } + } + + BOOL _bSucceed = FALSE; + static const struct GFOBMsgItem + { + UINT nGFOBMessage; // WM_KEYDOWN or WM_KEYUP + UINT nGFOBChar; + UINT nGFOBRepCnt; + DWORD nGFOBMode; // 0x00-点动, 0x01-前进/后退指定的距离 + UINT nGFOBCmdID; + DWORD nMask; + } _s_GFOBMsgItems[] = + { + { WM_KEYDOWN, VK_F3, 1, 0x00, IDCMD_CONTROLTARGET_JOGBACKWARD, 0x00000001}, + { WM_KEYDOWN, VK_F4, 1, 0x00, IDCMD_CONTROLTARGET_JOGFORWARD, 0x00000002}, + { WM_KEYUP, VK_F3, 1, 0x00, IDCMD_CONTROLTARGET_STOP, 0x00000001}, + { WM_KEYUP, VK_F4, 1, 0x00, IDCMD_CONTROLTARGET_STOP, 0x00000002}, + + { WM_KEYUP, VK_F3, 1, 0x01, IDCMD_CONTROLTARGET_INCBACKWARD, 0x00000001}, + { WM_KEYUP, VK_F4, 1, 0x01, IDCMD_CONTROLTARGET_INCFORWARD, 0x00000002}, + }; + for (size_t _i = 0; _i < _countof(_s_GFOBMsgItems); _i++) + { + const GFOBMsgItem& _item = _s_GFOBMsgItems[_i]; + if (pMsg_->message != _item.nGFOBMessage + || static_cast(pMsg_->wParam) != _item.nGFOBChar + || LOWORD(pMsg_->lParam) != _item.nGFOBRepCnt + || GetGFOBMode() != _item.nGFOBMode) + { + continue; + } + + // 开启/关闭按键状态跟踪 ---- 杨开锦 2013-09-04 + _ToTraceKeyState(UINT(pMsg_->wParam), pMsg_->message == WM_KEYDOWN ? true : false); + + _bSucceed = OnCmdMsg(_item.nGFOBCmdID, 0, NULL, NULL); + + if (_item.nGFOBMessage == WM_KEYDOWN) + { + m_nGFOBKeyState |= _item.nMask; + } + else + { + m_nGFOBKeyState &= !_item.nMask; + } + } + + return _bSucceed ? TRUE : FALSE; +} + +void CControlTarget::SetGFOBMode(DWORD nGFOBMode_) +{ + m_nGFOBMode = nGFOBMode_; + CParamManager* _pParamManager = GetParamManager(); + if (_pParamManager) + { + mach::ParameterValue _Parameter; + memset(&_Parameter, 0, sizeof(mach::ParameterValue)); + _Parameter.nType = mach::ParameterValue::VT_INT; + _Parameter.iValue = m_nGFOBMode == 1 ? 1 : 0; + _pParamManager->SetParameterValue("GoBackMode", &_Parameter); + } +} + +DWORD CControlTarget::GetGFOBMode() +{ + CParamManager* _pParamManager = GetParamManager(); + if (_pParamManager) + { + mach::ParameterValue _Parameter; + memset(&_Parameter, 0, sizeof(mach::ParameterValue)); + if (_pParamManager->GetParameterValue("GoBackMode", &_Parameter)) + { + ASSERT(_Parameter.nType == mach::ParameterValue::VT_INT); + m_nGFOBMode = _Parameter.iValue; + } + } + + return m_nGFOBMode; +} + +bool CControlTarget::_IsOutsideTheSotfLimit(const CStringA strFilePosition_) +{ + CParamManager* _pParamManager = GetParamManager(); + if (!_pParamManager) + { + ASSERT(FALSE); + return false; + } + mach::ParameterValue _IsCheckLimitX; + mach::ParameterValue _IsCheckLimitY; + bool _bSuccess = _pParamManager->GetParameterValue("IsCheckLimitX", &_IsCheckLimitX); + _bSuccess &= _pParamManager->GetParameterValue("IsCheckLimitY", &_IsCheckLimitY); + ASSERT(_IsCheckLimitX.nType == ParameterValue::VT_BOOL && _IsCheckLimitY.nType == ParameterValue::VT_BOOL); + if (!_IsCheckLimitX.bValue && !_IsCheckLimitY.bValue) + return false; + + mach::ParameterValue _IsReferedX; + mach::ParameterValue _IsReferedY; + _bSuccess &= _pParamManager->GetParameterValue("IsReferedX", &_IsReferedX); + _bSuccess &= _pParamManager->GetParameterValue("IsReferedY", &_IsReferedY); + ASSERT(_IsReferedX.nType == ParameterValue::VT_BOOL && _IsReferedY.nType == ParameterValue::VT_BOOL); + if (!_bSuccess) + { + ASSERT(FALSE); + return false; + } + // 没有回机械原点不检查软限位。 + if (!_IsReferedX.bValue && !_IsReferedY.bValue) + { + return false; + } + + CFileTarget* _pFileTarget = GetFileTarget(); + if (!_pFileTarget) + { + ASSERT(FALSE); + return false; + } + + // 没拿到图形就不用往下判断了。 ---- 黄海燕 2015-12-12 + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + if (_pFileTarget->GetFilePath().IsEmpty() + || !_pCamGroup->GetObjectsList() + || _pCamGroup->GetObjectsList()->size() == 0) + { + return false; + } + + double _pWorktable[4]; + DRECT _rcWorktable; + SendTargetMessage(ID_TARGET_WORKTABLE, TM_GET_WORKTABLE,(WPARAM)_pWorktable); + _rcWorktable.x = _pWorktable[0]; + _rcWorktable.y = _pWorktable[1]; + _rcWorktable.width = _pWorktable[2]; + _rcWorktable.height = _pWorktable[3]; + DRECT _rectBound; + static CSimuCutHelper _s_SimuCutHelper; + CStateManager* _pStateManager = GetStateManager(); + + // 加工所有图形。 + if (!_pStateManager->IsSelectedMach()) + { + _rectBound = _s_SimuCutHelper.GetBoundRect(_pFileTarget->GetCurrentCamGroup()); + } + + // 选择加工。 + else + { + DRECT _rectBoundLast; + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + CCadGroup* _pCadGroup = _pFileTarget->GetCurrentCadGroup(); + + CSelectTarget* _pSelectTarget = GetSelectTarget(); + ASSERT(_pSelectTarget); + const CadObjectList* _plistSelectObjs = _pSelectTarget->GetSelectedCadObjects(); + + vectorUINT _setCadID; + CCamGroup* _pSelcetCamGroup = new CCamGroup; + _GetCadIDList((CadObjectList*)_plistSelectObjs,_setCadID); + if (_setCadID.size() > 0) + { + _GetCamGroupByCadID(_pCamGroup, _setCadID, _pSelcetCamGroup); + _rectBound = _s_SimuCutHelper.GetBoundRect(_pSelcetCamGroup); + } + _pSelcetCamGroup->GetObjectsList()->clear(); + delete _pSelcetCamGroup; + } + + _DoWCSAdjust(_rectBound); + if (_IsCheckLimitX.bValue && _IsReferedX.bValue + && (_rectBound.GetLeft() < _rcWorktable.GetLeft() || _rectBound.GetRight() > _rcWorktable.GetRight())) + return true; + + if (_IsCheckLimitY.bValue && _IsReferedY.bValue + && (_rectBound.GetBottom() < _rcWorktable.GetBottom() || _rectBound.GetTop() > _rcWorktable.GetTop())) + return true; + + return false; +} + +bool CControlTarget::_IsRectOutsideTheSotfLimit(const CStringA strFilePosition_) +{ + CParamManager* _pParamManager = GetParamManager(); + if (!_pParamManager) + { + ASSERT(FALSE); + return false; + } + mach::ParameterValue _IsCheckLimitX; + mach::ParameterValue _IsCheckLimitY; + bool _bSuccess = _pParamManager->GetParameterValue("IsCheckLimitX", &_IsCheckLimitX); + _bSuccess &= _pParamManager->GetParameterValue("IsCheckLimitY", &_IsCheckLimitY); + ASSERT(_IsCheckLimitX.nType == ParameterValue::VT_BOOL && _IsCheckLimitY.nType == ParameterValue::VT_BOOL); + if (!_IsCheckLimitX.bValue && !_IsCheckLimitY.bValue) + return false; + + mach::ParameterValue _IsReferedX; + mach::ParameterValue _IsReferedY; + _bSuccess &= _pParamManager->GetParameterValue("IsReferedX", &_IsReferedX); + _bSuccess &= _pParamManager->GetParameterValue("IsReferedY", &_IsReferedY); + ASSERT(_IsReferedX.nType == ParameterValue::VT_BOOL && _IsReferedY.nType == ParameterValue::VT_BOOL); + if (!_bSuccess) + { + ASSERT(FALSE); + return false; + } + // 没有回机械原点不检查软限位。 + if (!_IsReferedX.bValue && !_IsReferedY.bValue) + { + return false; + } + + CFileTarget* _pFileTarget = GetFileTarget(); + if (!_pFileTarget) + { + ASSERT(FALSE); + return false; + } + + // 没拿到图形就不用往下判断了。 ---- 黄海燕 2015-12-12 + CCamGroup* _pCamGroup = _pFileTarget->GetCurrentCamGroup(); + if (_pFileTarget->GetFilePath().IsEmpty() + || !_pCamGroup->GetObjectsList() + || _pCamGroup->GetObjectsList()->size() == 0) + { + return false; + } + + double _pWorktable[4]; + DRECT _rcWorktable; + SendTargetMessage(ID_TARGET_WORKTABLE, TM_GET_WORKTABLE,(WPARAM)_pWorktable); + _rcWorktable.x = _pWorktable[0]; + _rcWorktable.y = _pWorktable[1]; + _rcWorktable.width = _pWorktable[2]; + _rcWorktable.height = _pWorktable[3]; + DRECT _rectBound; + + // 边框是否超过限位 + static CSimuCutHelper _s_SimuCutHelper; + ASSERT(!strFilePosition_.IsEmpty()); + _rectBound = _s_SimuCutHelper.GetBoundRect(_pFileTarget->GetCurrentCamGroup()); + _DoWCSAdjust(_rectBound); + if (_IsCheckLimitX.bValue && _IsReferedX.bValue + && (_rectBound.GetLeft() < _rcWorktable.GetLeft() || _rectBound.GetRight() > _rcWorktable.GetRight())) + return true; + + if (_IsCheckLimitY.bValue && _IsReferedY.bValue + && (_rectBound.GetBottom() < _rcWorktable.GetBottom() || _rectBound.GetTop() > _rcWorktable.GetTop())) + return true; + + return false; +} + +// 求指定加工范围内从特定位置开始的后部,不在此范围内返回空字符串。 ---- 黄海燕 2016-09-14 +CStringA CControlTarget::_Mid(const CStringA& strSelection_, __int64 nStartPos_) +{ + if (strSelection_.IsEmpty()) + { + ASSERT(FALSE); + return ""; + } + + int _nIndex = strSelection_.Find(_T(';')); + CString _strSection = _nIndex == -1 ? strSelection_ : strSelection_.Mid(0, _nIndex); + __int64 _nLastEndPos = -1; + CString _strRet; + while(!_strSection.IsEmpty()) + { + __int64 _nStart = 0; + __int64 _nEnd = 0; + int _nCount = sscanf_s(_strSection, _T("%lld,%lld"), &_nStart, &_nEnd); + ASSERT(_nCount == 2); + + // 默认传进来文件区间是递增的,"a,b;c,d",a < b < c < d。 ---- 黄海燕 2016-09-14 + ASSERT(_nLastEndPos <= _nStart && _nStart <= _nEnd); + + // 当前位置不在传进来的区间内。 ---- 黄海燕 2016-09-14 + if (nStartPos_ < _nStart + && _nLastEndPos == -1) + { + return ""; + } + + // 当前位置落在区间和区间的空隙内,形如"a,b;c,d", 当前位置 > b && 当前位置 < c。 ---- 黄海燕 2016-09-14 + if (nStartPos_ < _nStart + && _nLastEndPos > 0 + && nStartPos_ > _nLastEndPos) + { + _strRet.Format(_T("%lld,%lld;"), _nStart, _nEnd); + if (_nIndex != -1) + _strRet += strSelection_.Right(strSelection_.GetLength() - _nIndex - 1); + break; + } + + // 当前位置在某个区间内。 ---- 黄海燕 2016-09-14 + if (nStartPos_ >= _nStart && nStartPos_ < _nEnd) + { + _strRet.Format(_T("%lld,%lld;"), nStartPos_, _nEnd); + if (_nIndex != -1) + _strRet += strSelection_.Right(strSelection_.GetLength() - _nIndex - 1); + break; + } + + // 当前位置刚好是某个区间的终点。 ---- 黄海燕 2016-09-14 + if (nStartPos_ == _nEnd && _nIndex != -1) + { + _strRet = strSelection_.Right(strSelection_.GetLength() - _nIndex - 1); + break; + } + + if (_nIndex == -1) + break; + + _nLastEndPos = _nEnd; + int _nNextIndex = strSelection_.Find(_T(';'), _nIndex + 1); + _strSection = _nNextIndex == -1 + ? strSelection_.Right(strSelection_.GetLength() - _nIndex - 1) + : strSelection_.Mid(_nIndex + 1, _nNextIndex - _nIndex); + _nIndex = _nNextIndex; + } + + // 如果最后一个是分号,则删掉。 ---- 黄海燕 2016-09-14 + int _nLen = _strRet.GetLength(); + if (_nLen > 0 && _strRet[_nLen - 1] == _T(';')) + { + _strRet.Delete(_nLen - 1); + } + + return _strRet; +} + +void CControlTarget::_DoWCSAdjust(DRECT& rcRect_) +{ + CWCSAdjustTarget* _pWCSAdjustTarget = GetWCSAdjustTarget(); + if (!_pWCSAdjustTarget) + return; + + DRECT _rcOrg = rcRect_; + DPOINT2 _ptTopLeft (_rcOrg.GetLeft(), _rcOrg.GetTop()); + DPOINT2 _ptRightBottom(_rcOrg.GetRight(), _rcOrg.GetBottom()); + DPOINT2 _ptBottomLeft(_rcOrg.GetLeft(), _rcOrg.GetBottom()); + DPOINT2 _ptTopRight(_rcOrg.GetRight(), _rcOrg.GetTop()); + _ptTopLeft = _pWCSAdjustTarget->DoWCSAdjust(_ptTopLeft); + _ptRightBottom = _pWCSAdjustTarget->DoWCSAdjust(_ptRightBottom); + _ptBottomLeft = _pWCSAdjustTarget->DoWCSAdjust(_ptBottomLeft); + _ptTopRight = _pWCSAdjustTarget->DoWCSAdjust(_ptTopRight); + double _nLeft = min(min(min(_ptTopLeft.x, _ptTopRight.x), _ptBottomLeft.x), _ptRightBottom.x); + double _nRight = max(max(max(_ptTopLeft.x, _ptTopRight.x), _ptBottomLeft.x), _ptRightBottom.x); + double _nBottom = min(min(min(_ptTopLeft.y, _ptTopRight.y), _ptBottomLeft.y), _ptRightBottom.y); + double _nTop = max(max(max(_ptTopLeft.y, _ptTopRight.y), _ptBottomLeft.y), _ptRightBottom.y); + DRECT _rcNew; + _rcNew.x = _nLeft; + _rcNew.y = _nBottom; + _rcNew.width = _nRight - _nLeft; + _rcNew.height = _nTop - _nBottom; + rcRect_ = _rcNew; +} + +// 根据Cad的ID找到对应的Cad +static bool _FindObjectByID(IN CCadObject* pCadObject_, IN int nID_, OUT CCadObject** ppResult_) +{ + if (pCadObject_->GetID() == nID_) + { + *ppResult_ = pCadObject_; + return true; + } + + if (pCadObject_->GetType() == cadtext) + { + CCadText* _pCadText = dynamic_cast(pCadObject_); + ASSERT(_pCadText); + if (_FindObjectByID(_pCadText->GetTextGroup(), nID_, ppResult_)) + return true; + } + if (pCadObject_->GetType() == cadgroup) + { + CCadGroup* _pCadGroup = dynamic_cast(pCadObject_); + ASSERT(_pCadGroup); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCad = _pCadGroup->GetAt(_i); + ASSERT(_pCad); + if (_FindObjectByID(_pCad, nID_, ppResult_)) + return true; + } + } + + return false; +} + +__int64 CControlTarget::_SelectionFirst(const CStringA& strSelection_) +{ + if (strSelection_.IsEmpty()) + { + ASSERT(FALSE); + return 0; + } + + int _nIndex = strSelection_.Find(_T(';')); + CString _strSection = _nIndex == -1 ? strSelection_ : strSelection_.Mid(0, _nIndex); + __int64 _nLastEndPos = -1; + CString _strRet; + if(!_strSection.IsEmpty()) + { + __int64 _nStart = 0; + __int64 _nEnd = 0; + int _nCount = sscanf_s(_strSection, _T("%lld,%lld"), &_nStart, &_nEnd); + ASSERT(_nCount == 2); + return _nStart; + } + return 0; +} + + +void _GetCadIDObj(IN CCadObject* pCadObject_, OUT vectorUINT& setIDs_) +{ + setIDs_.push_back(pCadObject_->GetID()); + if (pCadObject_->GetType() == cadtext) + { + CCadText* _pCadText = dynamic_cast(pCadObject_); + ASSERT(_pCadText); + _GetCadIDObj(_pCadText->GetTextGroup(), setIDs_); + + } + if (pCadObject_->GetType() == cadgroup) + { + CCadGroup* _pCadGroup = dynamic_cast(pCadObject_); + ASSERT(_pCadGroup); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCad = _pCadGroup->GetAt(_i); + ASSERT(_pCad); + _GetCadIDObj(_pCad, setIDs_); + } + } +} + +void _GetCadIDList(IN CadObjectList* pListCads_, OUT vectorUINT& setIDs_) +{ + for (CadObjectList::iterator _it = pListCads_->begin(); _it != pListCads_->end(); _it++) + { + _GetCadIDObj(*_it, setIDs_); + } +} + +void _GetCamGroupByCadID(IN nce::CCamGroup* pCCamGroup_, IN vectorUINT setIDs_, OUT nce::CCamGroup* pOutCCamGroup_) +{ + ASSERT(pCCamGroup_); + CamObjectList* _plistCamObjs = pCCamGroup_->GetObjectsList(); + for (CamObjectList::const_iterator _it = _plistCamObjs->begin(); _it != _plistCamObjs->end(); _it++) + { + // 不需要考虑重合的CAM + CCamObject* _pCam = *_it; + CCadObject* _pCad = NULL; + + // 根据Cam中的CadID属性找到对应的Cad + int _nID = (int)_pCam->GetKey_DBL("CadID"); + if (std::find(setIDs_.begin(), setIDs_.end(), _nID) != setIDs_.end()) + { + pOutCCamGroup_->GetObjectsList()->push_back(_pCam); + } + } + return; + for (int _i = 0; _i < setIDs_.size(); _i++) + { + CCamObject* _pCamObject = NULL; + SendTargetMessage(ID_TARGET_CADTOCAM, TN_GETCAM_BYCADID, setIDs_[_i], (LPARAM)&_pCamObject); + if (_pCamObject != NULL) + { + pOutCCamGroup_->GetObjectsList()->push_back(_pCamObject); + } + } + +} + +void CControlTarget::_SendGasPressureInfo() +{ + CString _flag = NceGetPrivateProfileString(_T("GasCheck"), _T("GNGasCheck"), _T("0")); + if ("1" != _flag) + { + return; + } + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + bool _bAirCheck = false; + bool _bOxygenCheck = false; + bool _bNitrogenCheck = false; + CFileTarget* _pFileTarget = GetFileTarget(); + ASSERT(_pFileTarget); + nce::ParamVector* _pParamVector = _pFileTarget->GetCurrentCadParams(); + nce::CCadGroup* _pCurrentCadGroup = _pFileTarget->GetCurrentCadGroup(); + + for (size_t _i = 0; _i < _pParamVector->size(); _i++) + { + + if (_bAirCheck && _bOxygenCheck && _bNitrogenCheck) + { + continue; + } + if (_pStateManager->IsSelectedMach()) + { + bool _isSelect = false; + //判断选中图层所选择的气体类型是否要发气压低警告 + for (int _j = 0; _j < _pCurrentCadGroup->GetNumOfChild(); _j++) + { + if (_pCurrentCadGroup->GetAt(_j)->IsSelected()) + { + if (_i == _pCurrentCadGroup->GetAt(_j)->GetParamIndex()) + { + _isSelect = true; + } + } + } + + if(!_isSelect) + { + continue; + } + } + else + { + //判断当前所存在图层所选择的气体类型是否要发气压低警告 + for (int _j = 0; _j < _pCurrentCadGroup->GetNumOfChild(); _j++) + { + if (_i == _pCurrentCadGroup->GetAt(_j)->GetParamIndex()) + { + CParam* _pParam = _pParamVector->at(_i); + if(_pParam->GetKey(c_szOutput) == _T("0")) + { + continue; + } + //冷却气判定 + if (_pParam->GetKey(c_szCoolBlowType) == _T("0")) + { + _bAirCheck = true; + } + if (_pParam->GetKey(c_szCoolBlowType) == _T("1")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szCoolBlowType) == _T("2")) + { + _bOxygenCheck = true; + } + if (_pParam->GetKey(c_szCoolBlowType) == _T("3")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szCoolBlowType) == _T("4")) + { + _bOxygenCheck = true; + } + + //穿孔方式 + //直接穿孔 + if (_pParam->GetKey(c_szPerforateType) == _T("0")) + { + //切割气体判定 + if (_pParam->GetKey(c_szCutBlowType) == _T("0")) + { + _bAirCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("1")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("2")) + { + _bOxygenCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("3")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("4")) + { + _bOxygenCheck = true; + } + } + //渐进穿孔或分段穿孔 + if (_pParam->GetKey(c_szPerforateType) == _T("1") || _pParam->GetKey(c_szPerforateType) == _T("2")) + { + //切割气体判定 + if (_pParam->GetKey(c_szCutBlowType) == _T("0")) + { + _bAirCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("1")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("2")) + { + _bOxygenCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("3")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("4")) + { + _bOxygenCheck = true; + } + + //穿孔气体判定 + if (_pParam->GetKey(c_szPerBlowType) == _T("0")) + { + _bAirCheck = true; + } + if (_pParam->GetKey(c_szPerBlowType) == _T("1")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szPerBlowType) == _T("2")) + { + _bOxygenCheck = true; + } + if (_pParam->GetKey(c_szPerBlowType) == _T("3")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szPerBlowType) == _T("4")) + { + _bOxygenCheck = true; + } + + } + //三级穿孔 + if (_pParam->GetKey(c_szPerforateType) == _T("3")) + { + //切割气体判定 + if (_pParam->GetKey(c_szCutBlowType) == _T("0")) + { + _bAirCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("1")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("2")) + { + _bOxygenCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("3")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szCutBlowType) == _T("4")) + { + _bOxygenCheck = true; + } + //一级 + if (_pParam->GetKey(c_szFirstSegPunch) == _T("1")) + { + if (_pParam->GetKey(c_szFirstSegBlowType) == _T("0")) + { + _bAirCheck = true; + } + if (_pParam->GetKey(c_szFirstSegBlowType) == _T("1")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szFirstSegBlowType) == _T("2")) + { + _bOxygenCheck = true; + } + if (_pParam->GetKey(c_szFirstSegBlowType) == _T("3")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szFirstSegBlowType) == _T("4")) + { + _bOxygenCheck = true; + } + } + //二级 + if (_pParam->GetKey(c_szSecondSegPunch) == _T("1")) + { + if (_pParam->GetKey(c_szSecondSegBlowType) == _T("0")) + { + _bAirCheck = true; + } + if (_pParam->GetKey(c_szSecondSegBlowType) == _T("1")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szSecondSegBlowType) == _T("2")) + { + _bOxygenCheck = true; + } + if (_pParam->GetKey(c_szSecondSegBlowType) == _T("3")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szSecondSegBlowType) == _T("4")) + { + _bOxygenCheck = true; + } + } + //三级 + if (_pParam->GetKey(c_szThirdSegPunch) == _T("1")) + { + if (_pParam->GetKey(c_szThirdSegBlowType) == _T("0")) + { + _bAirCheck = true; + } + if (_pParam->GetKey(c_szThirdSegBlowType) == _T("1")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szThirdSegBlowType) == _T("2")) + { + _bOxygenCheck = true; + } + if (_pParam->GetKey(c_szThirdSegBlowType) == _T("3")) + { + _bNitrogenCheck = true; + } + if (_pParam->GetKey(c_szThirdSegBlowType) == _T("4")) + { + _bOxygenCheck = true; + } + } + + } + } + //点加工的同时还需要判断一下通用图层中的气体类型 + CParamManager* _pParamManager = GetParamManager(); + + ParameterValue _DefaultBlowType; + _pParamManager->GetParameterValue("GP_DefaultBlowType", &_DefaultBlowType); + if(0 == _DefaultBlowType.iValue) + { + _bAirCheck = true; + } + else if ((1 == _DefaultBlowType.iValue) || (3 == _DefaultBlowType.iValue)) + { + _bNitrogenCheck = true; + } + else if ((2 == _DefaultBlowType.iValue) || (4 == _DefaultBlowType.iValue)) + { + _bOxygenCheck = true; + } + CString _strCheckAir("EnableCheckAir"); + SendTargetMessage(ID_TARGET_PARAMMANAGER, TM_SET_PARAMVALUE, WPARAM(_strCheckAir.GetBuffer()), (LPARAM)&_bAirCheck); + + CString _strCheckOxygen("EnableCheckOxygen"); + SendTargetMessage(ID_TARGET_PARAMMANAGER, TM_SET_PARAMVALUE, WPARAM(_strCheckOxygen.GetBuffer()), (LPARAM)&_bOxygenCheck); + + CString _strCheckNitrogen("EnableCheckNitrogen"); + SendTargetMessage(ID_TARGET_PARAMMANAGER, TM_SET_PARAMVALUE, WPARAM(_strCheckNitrogen.GetBuffer()), (LPARAM)&_bNitrogenCheck); + } + } + } + +} +void CControlTarget::SetSelectMach(bool _bSelectMach) +{ + m_bSelectMach = _bSelectMach; +} +bool CControlTarget::GetSelectMach() +{ + return m_bSelectMach; +} diff --git a/src/Decode.cpp b/src/Decode.cpp new file mode 100644 index 0000000..1f757cc --- /dev/null +++ b/src/Decode.cpp @@ -0,0 +1,1622 @@ +#include "stdafx.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW +#endif + +//static int s_counter; +void * __cdecl eng_malloc(size_t nSize) +{ + void *res = malloc(nSize); + +// s_counter++; +// TRACE("eng_malloc: %d: %p\n", s_counter, res); + return res; +} + +void __cdecl eng_free(void * pUserData) +{ + free(pUserData); + +// s_counter--; +// TRACE("eng_free: %d: %p\n", s_counter, pUserData); +} + +struct JD_PATH_INFO_05; + +struct X2 { + BYTE* pData; + int nSize; + + X2(void* pBuffer_, int size_); + ~X2(); + WORD* Decode5(); + WORD* Decode6(); + WORD* Decode7(); + WORD* Decode8(); + BYTE* Decode9(); +}; + +X2::X2(void* pBuffer_, int size_) +{ + pData = new BYTE[size_]; + if (pData) + { + memcpy(pData, pBuffer_, size_); + nSize = size_; + } +} + +X2::~X2() +{ + delete[] pData; +} + +void DecodePassword04(JD_PWD_04* pPwd_) +{ + X2 _x2(&pPwd_->nKey, sizeof(WORD)); + + switch (pPwd_->nMethod) + { + case 5: + { + WORD* _pDecoded = _x2.Decode5(); + if (_pDecoded) + pPwd_->nKey = *_pDecoded; + } + break; + + case 6: + { + WORD* _pDecoded = _x2.Decode6(); + if (_pDecoded) + pPwd_->nKey = *_pDecoded; + } + break; + + case 7: + { + WORD* _pDecoded = _x2.Decode7(); + if (_pDecoded) + pPwd_->nKey = *_pDecoded; + } + break; + + case 8: + { + WORD* _pDecoded = _x2.Decode8(); + if (_pDecoded) + pPwd_->nKey = *_pDecoded; + } + break; + + case 9: + { + BYTE* _pDecoded = _x2.Decode9(); + if (_pDecoded) + pPwd_->nKey = (WORD)*_pDecoded; + eng_free(_pDecoded); // this line is added by zzk to fix memory leak. + } + break; + + default: + return; + } + return; +} + +void DecodePassword05(JD_PATH_INFO_05* pInfo_) +{ + X2 _x2(&pInfo_->nKey, sizeof(WORD)); + + switch (pInfo_->nMethod) + { + case 5: + { + WORD* _pDecoded = _x2.Decode5(); + if (_pDecoded) + pInfo_->nKey = *_pDecoded; + } + break; + + case 6: + { + WORD* _pDecoded = _x2.Decode6(); + if (_pDecoded) + pInfo_->nKey = *_pDecoded; + } + break; + + case 7: + { + WORD* _pDecoded = _x2.Decode7(); + if (_pDecoded) + pInfo_->nKey = *_pDecoded; + } + break; + + case 8: + { + WORD* _pDecoded = _x2.Decode8(); + if (_pDecoded) + pInfo_->nKey = *_pDecoded; + } + break; + + case 9: + { + BYTE* _pDecoded = _x2.Decode9(); + if (_pDecoded) + pInfo_->nKey = (WORD)*_pDecoded; + eng_free(_pDecoded); // this line is added by zzk to fix memory leak. + } + break; + + default: + return; + } + return; +} + +__declspec(naked) void DecodeBuffer( + BYTE* /* pBuffer */, + DWORD /* size */, + JD_PWD_04* /* pKey */) +{ + __asm { + push ebx + push ebp + push esi + mov esi,dword ptr ss:[esp+0X18] + push edi + mov ax,word ptr ds:[esi+0X2] ; encode_method == ax + cmp ax,0X5 + jl short L_LABEL1 + cmp ax,0X8 + jg short L_LABEL1 + movsx ecx,word ptr ds:[esi+0XA] ; encode_method == 5, 6, 7, 8, goto here + movsx edi,word ptr ds:[esi+0X6] + mov eax,ecx + cdq + sub eax,edx ; get abs(eax)? + mov edx,dword ptr ss:[esp+0X18] ; size == edx, number of bytes to decode + lea ecx,dword ptr ds:[ecx+edi-1] ; index = ecx + edi - 1; + sar eax,1 + cmp ecx,edx ; index = size? + jge short L_LABEL2 + mov ebx,dword ptr ss:[esp+0X14] ; pBuffer == ebx + + L_LABEL5: + test eax,eax ; + lea ecx,dword ptr ds:[edi+ebx] + jle short L_LABEL3 + mov edx,eax + + L_LABEL4: + mov bp,word ptr ds:[esi] ; Unknown_Encoded1 == bp + xor word ptr ds:[ecx],bp + add ecx,2 ; move to next WORD + dec edx + jnz short L_LABEL4 + + L_LABEL3: + movsx edx,word ptr ds:[esi+0X8] + movsx ecx,word ptr ds:[esi+0XA] + add edi,edx + lea edx,dword ptr ds:[ecx+edi-1] + mov ecx,dword ptr ss:[esp+0X18] + cmp edx,ecx + jl short L_LABEL5 + pop edi + pop esi + pop ebp + pop ebx + retn + + L_LABEL1: + cmp ax,0X9 + jnz short L_LABEL2 + movsx ebp,word ptr ds:[esi+0X6] + movsx edi,word ptr ds:[esi+0XA] + mov ebx,dword ptr ss:[esp+0X18] + mov dl,byte ptr ds:[esi] + lea eax,dword ptr ds:[edi+ebp-1] + cmp eax,ebx + jge short L_LABEL2 + + L_LABEL8: + xor eax,eax + test edi,edi + jle short L_LABEL6 + mov ecx,dword ptr ss:[esp+0X14] + add ecx,ebp + + L_LABEL7: + xor byte ptr ds:[ecx+eax],dl + inc eax + cmp eax,edi + jl short L_LABEL7 + + L_LABEL6: + movsx eax,word ptr ds:[esi+0X8] + movsx ecx,word ptr ds:[esi+0XA] + add ebp,eax + lea eax,dword ptr ds:[ecx+ebp-1] + cmp eax,ebx + jl short L_LABEL8 + + L_LABEL2: + pop edi + pop esi + pop ebp + pop ebx + retn + } +} + +DWORD s_nDATA00419268[] = // table 1 +{ + 0x01 ^ 0x55, 0x03 ^ 0x55, 0x05 ^ 0x55, 0x0F ^ 0x55, + 0x11 ^ 0x55, 0x33 ^ 0x55, 0x55 ^ 0x55, 0xFF ^ 0x55, + 0x1A ^ 0x55, 0x2E ^ 0x55, 0x72 ^ 0x55, 0x96 ^ 0x55, + 0xA1 ^ 0x55, 0xF8 ^ 0x55, 0x13 ^ 0x55, 0x35 ^ 0x55, + 0x5F ^ 0x55, 0xE1 ^ 0x55, 0x38 ^ 0x55, 0x48 ^ 0x55, + 0xD8 ^ 0x55, 0x73 ^ 0x55, 0x95 ^ 0x55, 0xA4 ^ 0x55, + 0xF7 ^ 0x55, 0x02 ^ 0x55, 0x06 ^ 0x55, 0x0A ^ 0x55, + 0x1E ^ 0x55, 0x22 ^ 0x55, 0x66 ^ 0x55, 0xAA ^ 0x55, + 0xE5 ^ 0x55, 0x34 ^ 0x55, 0x5C ^ 0x55, 0xE4 ^ 0x55, + 0x37 ^ 0x55, 0x59 ^ 0x55, 0xEB ^ 0x55, 0x26 ^ 0x55, + 0x6A ^ 0x55, 0xBE ^ 0x55, 0xD9 ^ 0x55, 0x70 ^ 0x55, + 0x90 ^ 0x55, 0xAB ^ 0x55, 0xE6 ^ 0x55, 0x31 ^ 0x55, + 0x53 ^ 0x55, 0xF5 ^ 0x55, 0x04 ^ 0x55, 0x0C ^ 0x55, + 0x14 ^ 0x55, 0x3C ^ 0x55, 0x44 ^ 0x55, 0xCC ^ 0x55, + 0x4F ^ 0x55, 0xD1 ^ 0x55, 0x68 ^ 0x55, 0xB8 ^ 0x55, + 0xD3 ^ 0x55, 0x6E ^ 0x55, 0xB2 ^ 0x55, 0xCD ^ 0x55, + 0x4C ^ 0x55, 0xD4 ^ 0x55, 0x67 ^ 0x55, 0xA9 ^ 0x55, + 0xE0 ^ 0x55, 0x3B ^ 0x55, 0x4D ^ 0x55, 0xD7 ^ 0x55, + 0x62 ^ 0x55, 0xA6 ^ 0x55, 0xF1 ^ 0x55, 0x08 ^ 0x55, + 0x18 ^ 0x55, 0x28 ^ 0x55, 0x78 ^ 0x55, 0x88 ^ 0x55, + 0x83 ^ 0x55, 0x9E ^ 0x55, 0xB9 ^ 0x55, 0xD0 ^ 0x55, + 0x6B ^ 0x55, 0xBD ^ 0x55, 0xDC ^ 0x55, 0x7F ^ 0x55, + 0x81 ^ 0x55, 0x98 ^ 0x55, 0xB3 ^ 0x55, 0xCE ^ 0x55, + 0x49 ^ 0x55, 0xDB ^ 0x55, 0x76 ^ 0x55, 0x9A ^ 0x55, + 0xB5 ^ 0x55, 0xC4 ^ 0x55, 0x57 ^ 0x55, 0xF9 ^ 0x55, + 0x10 ^ 0x55, 0x30 ^ 0x55, 0x50 ^ 0x55, 0xF0 ^ 0x55, + 0x0B ^ 0x55, 0x1D ^ 0x55, 0x27 ^ 0x55, 0x69 ^ 0x55, + 0xBB ^ 0x55, 0xD6 ^ 0x55, 0x61 ^ 0x55, 0xA3 ^ 0x55, + 0xFE ^ 0x55, 0x19 ^ 0x55, 0x2B ^ 0x55, 0x7D ^ 0x55, + 0x87 ^ 0x55, 0x92 ^ 0x55, 0xAD ^ 0x55, 0xEC ^ 0x55, + 0x2F ^ 0x55, 0x71 ^ 0x55, 0x93 ^ 0x55, 0xAE ^ 0x55, + 0xE9 ^ 0x55, 0x20 ^ 0x55, 0x60 ^ 0x55, 0xA0 ^ 0x55, + 0xFB ^ 0x55, 0x16 ^ 0x55, 0x3A ^ 0x55, 0x4E ^ 0x55, + 0xD2 ^ 0x55, 0x6D ^ 0x55, 0xB7 ^ 0x55, 0xC2 ^ 0x55, + 0x5D ^ 0x55, 0xE7 ^ 0x55, 0x32 ^ 0x55, 0x56 ^ 0x55, + 0xFA ^ 0x55, 0x15 ^ 0x55, 0x3F ^ 0x55, 0x41 ^ 0x55, + 0xC3 ^ 0x55, 0x5E ^ 0x55, 0xE2 ^ 0x55, 0x3D ^ 0x55, + 0x47 ^ 0x55, 0xC9 ^ 0x55, 0x40 ^ 0x55, 0xC0 ^ 0x55, + 0x5B ^ 0x55, 0xED ^ 0x55, 0x2C ^ 0x55, 0x74 ^ 0x55, + 0x9C ^ 0x55, 0xBF ^ 0x55, 0xDA ^ 0x55, 0x75 ^ 0x55, + 0x9F ^ 0x55, 0xBA ^ 0x55, 0xD5 ^ 0x55, 0x64 ^ 0x55, + 0xAC ^ 0x55, 0xEF ^ 0x55, 0x2A ^ 0x55, 0x7E ^ 0x55, + 0x82 ^ 0x55, 0x9D ^ 0x55, 0xBC ^ 0x55, 0xDF ^ 0x55, + 0x7A ^ 0x55, 0x8E ^ 0x55, 0x89 ^ 0x55, 0x80 ^ 0x55, + 0x9B ^ 0x55, 0xB6 ^ 0x55, 0xC1 ^ 0x55, 0x58 ^ 0x55, + 0xE8 ^ 0x55, 0x23 ^ 0x55, 0x65 ^ 0x55, 0xAF ^ 0x55, + 0xEA ^ 0x55, 0x25 ^ 0x55, 0x6F ^ 0x55, 0xB1 ^ 0x55, + 0xC8 ^ 0x55, 0x43 ^ 0x55, 0xC5 ^ 0x55, 0x54 ^ 0x55, + 0xFC ^ 0x55, 0x1F ^ 0x55, 0x21 ^ 0x55, 0x63 ^ 0x55, + 0xA5 ^ 0x55, 0xF4 ^ 0x55, 0x07 ^ 0x55, 0x09 ^ 0x55, + 0x1B ^ 0x55, 0x2D ^ 0x55, 0x77 ^ 0x55, 0x99 ^ 0x55, + 0xB0 ^ 0x55, 0xCB ^ 0x55, 0x46 ^ 0x55, 0xCA ^ 0x55, + 0x45 ^ 0x55, 0xCF ^ 0x55, 0x4A ^ 0x55, 0xDE ^ 0x55, + 0x79 ^ 0x55, 0x8B ^ 0x55, 0x86 ^ 0x55, 0x91 ^ 0x55, + 0xA8 ^ 0x55, 0xE3 ^ 0x55, 0x3E ^ 0x55, 0x42 ^ 0x55, + 0xC6 ^ 0x55, 0x51 ^ 0x55, 0xF3 ^ 0x55, 0x0E ^ 0x55, + 0x12 ^ 0x55, 0x36 ^ 0x55, 0x5A ^ 0x55, 0xEE ^ 0x55, + 0x29 ^ 0x55, 0x7B ^ 0x55, 0x8D ^ 0x55, 0x8C ^ 0x55, + 0x8F ^ 0x55, 0x8A ^ 0x55, 0x85 ^ 0x55, 0x94 ^ 0x55, + 0xA7 ^ 0x55, 0xF2 ^ 0x55, 0x0D ^ 0x55, 0x17 ^ 0x55, + 0x39 ^ 0x55, 0x4B ^ 0x55, 0xDD ^ 0x55, 0x7C ^ 0x55, + 0x84 ^ 0x55, 0x97 ^ 0x55, 0xA2 ^ 0x55, 0xFD ^ 0x55, + 0x1C ^ 0x55, 0x24 ^ 0x55, 0x6C ^ 0x55, 0xB4 ^ 0x55, + 0xC7 ^ 0x55, 0x52 ^ 0x55, 0xF6 ^ 0x55, 0x00 ^ 0x55, +}; + +DWORD s_nDATA00419668[] = // table 2 +{ + 0x16 ^ 0x55, 0x12 ^ 0x55, 0x11 ^ 0x55, 0x14 ^ 0x55, + 0x15 ^ 0x55, 0x16 ^ 0x55, 0x13 ^ 0x55, 0x26 ^ 0x55, + 0x77 ^ 0x55, 0x36 ^ 0x55, 0x06 ^ 0x55, 0x36 ^ 0x55, + 0x56 ^ 0x55, 0x30 ^ 0x55, 0x35 ^ 0x55, 0x29 ^ 0x55, + 0x33 ^ 0x55, 0x52 ^ 0x55, 0x41 ^ 0x55, 0x32 ^ 0x55, + 0x81 ^ 0x55, 0x26 ^ 0x55, 0x16 ^ 0x55, 0x15 ^ 0x55, + 0x16 ^ 0x55, 0x16 ^ 0x55, 0x34 ^ 0x55, 0x26 ^ 0x55, + 0x14 ^ 0x55, 0x81 ^ 0x55, 0x16 ^ 0x55, 0x51 ^ 0x55, +}; + +DWORD s_nDATA00418168[] = // table 3 +{ + 0xD1310BA6 ^ 0x55555555, 0x98DFB5AC ^ 0x55555555, 0x2FFD72DB ^ 0x55555555, 0xD01ADFB7 ^ 0x55555555, + 0xB8E1AFED ^ 0x55555555, 0x6A267E96 ^ 0x55555555, 0xBA7C9045 ^ 0x55555555, 0xF12C7F99 ^ 0x55555555, + 0x24A19947 ^ 0x55555555, 0xB3916CF7 ^ 0x55555555, 0x0801F2E2 ^ 0x55555555, 0x858EFC16 ^ 0x55555555, + 0x636920D8 ^ 0x55555555, 0x71574E69 ^ 0x55555555, 0xA458FEA3 ^ 0x55555555, 0xF4933D7E ^ 0x55555555, + 0x0D95748F ^ 0x55555555, 0x728EB658 ^ 0x55555555, 0x718BCD58 ^ 0x55555555, 0x82154AEE ^ 0x55555555, + 0x7B54A41D ^ 0x55555555, 0xC25A59B5 ^ 0x55555555, 0x9C30D539 ^ 0x55555555, 0x2AF26013 ^ 0x55555555, + 0xC5D1B023 ^ 0x55555555, 0x286085F0 ^ 0x55555555, 0xCA417918 ^ 0x55555555, 0xB8DB38EF ^ 0x55555555, + 0x8E79DCB0 ^ 0x55555555, 0x603A180E ^ 0x55555555, 0x6C9E0E8B ^ 0x55555555, 0xB01E8A3E ^ 0x55555555, + 0xD71577C1 ^ 0x55555555, 0xBD314B27 ^ 0x55555555, 0x78AF2FDA ^ 0x55555555, 0x55605C60 ^ 0x55555555, + 0xE65525F3 ^ 0x55555555, 0xAA55AB94 ^ 0x55555555, 0x57489862 ^ 0x55555555, 0x63E81440 ^ 0x55555555, + 0x55CA396A ^ 0x55555555, 0x2AAB10B6 ^ 0x55555555, 0xB4CC5C34 ^ 0x55555555, 0x1141E8CE ^ 0x55555555, + 0xA15486AF ^ 0x55555555, 0x7C72E993 ^ 0x55555555, 0xB3EE1411 ^ 0x55555555, 0x636FBC2A ^ 0x55555555, + 0x2BA9C55D ^ 0x55555555, 0x741831F6 ^ 0x55555555, 0xCE5C3E16 ^ 0x55555555, 0x9B87931E ^ 0x55555555, + 0xAFD6BA33 ^ 0x55555555, 0x6C24CF5C ^ 0x55555555, 0x7A325381 ^ 0x55555555, 0x28958677 ^ 0x55555555, + 0x3B8F4898 ^ 0x55555555, 0x6B4BB9AF ^ 0x55555555, 0xC4BFE81B ^ 0x55555555, 0x66282193 ^ 0x55555555, + 0x61D809CC ^ 0x55555555, 0xFB21A991 ^ 0x55555555, 0x487CAC60 ^ 0x55555555, 0x5DEC8032 ^ 0x55555555, + 0xEF845D5D ^ 0x55555555, 0xE98575B1 ^ 0x55555555, 0xDC262302 ^ 0x55555555, 0xEB651B88 ^ 0x55555555, + 0x23893E81 ^ 0x55555555, 0xD396ACC5 ^ 0x55555555, 0x0F6D6FF3 ^ 0x55555555, 0x83F44239 ^ 0x55555555, + 0x2E0B4482 ^ 0x55555555, 0xA4842004 ^ 0x55555555, 0x69C8F04A ^ 0x55555555, 0x9E1F9B5E ^ 0x55555555, + 0x21C66842 ^ 0x55555555, 0xF6E96C9A ^ 0x55555555, 0x670C9C61 ^ 0x55555555, 0xABD388F0 ^ 0x55555555, + 0x6A51A0D2 ^ 0x55555555, 0xD8542F68 ^ 0x55555555, 0x960FA728 ^ 0x55555555, 0xAB5133A3 ^ 0x55555555, + 0x6EEF0B6C ^ 0x55555555, 0x137A3BE4 ^ 0x55555555, 0xBA3BF050 ^ 0x55555555, 0x7EFB2A98 ^ 0x55555555, + 0xA1F1651D ^ 0x55555555, 0x39AF0176 ^ 0x55555555, 0x66CA593E ^ 0x55555555, 0x82430E88 ^ 0x55555555, + 0x8CEE8619 ^ 0x55555555, 0x456F9FB4 ^ 0x55555555, 0x7D84A5C3 ^ 0x55555555, 0x3B8B5EBE ^ 0x55555555, + 0xE06F75D8 ^ 0x55555555, 0x85C12073 ^ 0x55555555, 0x401A449F ^ 0x55555555, 0x56C16AA6 ^ 0x55555555, + 0x4ED3AA62 ^ 0x55555555, 0x363F7706 ^ 0x55555555, 0x1BFEDF72 ^ 0x55555555, 0x429B023D ^ 0x55555555, + 0x37D0D724 ^ 0x55555555, 0xD00A1248 ^ 0x55555555, 0xDB0FEAD3 ^ 0x55555555, 0x49F1C09B ^ 0x55555555, + 0x075372C9 ^ 0x55555555, 0x80991B7B ^ 0x55555555, 0x25D479D8 ^ 0x55555555, 0xF6E8DEF7 ^ 0x55555555, + 0xE3FE501A ^ 0x55555555, 0xB6794C3B ^ 0x55555555, 0x976CE0BD ^ 0x55555555, 0x04C006BA ^ 0x55555555, + 0xC1A94FB6 ^ 0x55555555, 0x409F60C4 ^ 0x55555555, 0x5E5C9EC2 ^ 0x55555555, 0x196A2463 ^ 0x55555555, + 0x68FB6FAF ^ 0x55555555, 0x3E6C53B5 ^ 0x55555555, 0x1339B2EB ^ 0x55555555, 0x3B52EC6F ^ 0x55555555, + 0x6DFC511F ^ 0x55555555, 0x9B30952C ^ 0x55555555, 0xCC814544 ^ 0x55555555, 0xAF5EBD09 ^ 0x55555555, + 0xBEE3D004 ^ 0x55555555, 0xDE334AFD ^ 0x55555555, 0x660F2807 ^ 0x55555555, 0x192E4BB3 ^ 0x55555555, + 0xC0CBA857 ^ 0x55555555, 0x45C8740F ^ 0x55555555, 0xD20B5F39 ^ 0x55555555, 0xB9D3FBDB ^ 0x55555555, + 0x5579C0BD ^ 0x55555555, 0x1A60320A ^ 0x55555555, 0xD6A100C6 ^ 0x55555555, 0x402C7279 ^ 0x55555555, + 0x679F25FE ^ 0x55555555, 0xFB1FA3CC ^ 0x55555555, 0x8EA5E9F8 ^ 0x55555555, 0xDB3222F8 ^ 0x55555555, + 0x3C7516DF ^ 0x55555555, 0xFD616B15 ^ 0x55555555, 0x2F501EC8 ^ 0x55555555, 0xAD0552AB ^ 0x55555555, + 0x323DB5FA ^ 0x55555555, 0xFD238760 ^ 0x55555555, 0x53317B48 ^ 0x55555555, 0x3E00DF82 ^ 0x55555555, + 0x9E5C57BB ^ 0x55555555, 0xCA6F8CA0 ^ 0x55555555, 0x1A87562E ^ 0x55555555, 0xDF1769DB ^ 0x55555555, + 0xD542A8F6 ^ 0x55555555, 0x287EFFC3 ^ 0x55555555, 0xAC6732C6 ^ 0x55555555, 0x8C4F5573 ^ 0x55555555, + 0x695B27B0 ^ 0x55555555, 0xBBCA58C8 ^ 0x55555555, 0xE1FFA35D ^ 0x55555555, 0xB8F011A0 ^ 0x55555555, + 0x10FA3D98 ^ 0x55555555, 0xFD2183B8 ^ 0x55555555, 0x4AFCB56C ^ 0x55555555, 0x2DD1D35B ^ 0x55555555, + 0x9A53E479 ^ 0x55555555, 0xB6F84565 ^ 0x55555555, 0xD28E49BC ^ 0x55555555, 0x4BFB9790 ^ 0x55555555, + 0xE1DDF2DA ^ 0x55555555, 0xA4CB7E33 ^ 0x55555555, 0x62FB1341 ^ 0x55555555, 0xCEE4C6E8 ^ 0x55555555, + 0xEF20CADA ^ 0x55555555, 0x36774C01 ^ 0x55555555, 0xD07E9EFE ^ 0x55555555, 0x2BF11FB4 ^ 0x55555555, + 0x95DBDA4D ^ 0x55555555, 0xAE909198 ^ 0x55555555, 0xEAAD8E71 ^ 0x55555555, 0x6B93D5A0 ^ 0x55555555, + 0xD08ED1D0 ^ 0x55555555, 0xAFC725E0 ^ 0x55555555, 0x8E3C5B2F ^ 0x55555555, 0x8E7594B7 ^ 0x55555555, + 0x8FF6E2FB ^ 0x55555555, 0xF2122B64 ^ 0x55555555, 0x8888B812 ^ 0x55555555, 0x900DF01C ^ 0x55555555, + 0x4FAD5EA0 ^ 0x55555555, 0x688FC31C ^ 0x55555555, 0xD1CFF191 ^ 0x55555555, 0xB3A8C1AD ^ 0x55555555, + 0x2F2F2218 ^ 0x55555555, 0xBE0E1777 ^ 0x55555555, 0xEA752DFE ^ 0x55555555, 0x8B021FA1 ^ 0x55555555, + 0xE5A0CC0F ^ 0x55555555, 0xB56F74E8 ^ 0x55555555, 0x18ACF3D6 ^ 0x55555555, 0xCE89E299 ^ 0x55555555, + 0xB4A84FE0 ^ 0x55555555, 0xFD13E0B7 ^ 0x55555555, 0x7CC43B81 ^ 0x55555555, 0xD2ADA8D9 ^ 0x55555555, + 0x165FA266 ^ 0x55555555, 0x80957705 ^ 0x55555555, 0x93CC7314 ^ 0x55555555, 0x211A1477 ^ 0x55555555, + 0xE6AD2065 ^ 0x55555555, 0x77B5FA86 ^ 0x55555555, 0xC75442F5 ^ 0x55555555, 0xFB9D35CF ^ 0x55555555, + 0xEBCDAF0C ^ 0x55555555, 0x7B3E89A0 ^ 0x55555555, 0xD6411BD3 ^ 0x55555555, 0xAE1E7E49 ^ 0x55555555, + 0x00250E2D ^ 0x55555555, 0x2071B35E ^ 0x55555555, 0x226800BB ^ 0x55555555, 0x57B8E0AF ^ 0x55555555, + 0x2464369B ^ 0x55555555, 0xF009B91E ^ 0x55555555, 0x5563911D ^ 0x55555555, 0x59DFA6AA ^ 0x55555555, + 0x78C14389 ^ 0x55555555, 0xD95A537F ^ 0x55555555, 0x207D5BA2 ^ 0x55555555, 0x02E5B9C5 ^ 0x55555555, + 0x83260376 ^ 0x55555555, 0x6295CFA9 ^ 0x55555555, 0x11C81968 ^ 0x55555555, 0x4E734A41 ^ 0x55555555, + 0xB3472DCA ^ 0x55555555, 0x7B14A94A ^ 0x55555555, 0x1B510052 ^ 0x55555555, 0x9A532915 ^ 0x55555555, + 0xD60F573F ^ 0x55555555, 0xBC9BC6E4 ^ 0x55555555, 0x2B60A476 ^ 0x55555555, 0x81E67400 ^ 0x55555555, + 0x08BA6FB5 ^ 0x55555555, 0x571BE91F ^ 0x55555555, 0xF296EC6B ^ 0x55555555, 0x2A0DD915 ^ 0x55555555, + 0xB6636521 ^ 0x55555555, 0xE7B9F9B6 ^ 0x55555555, 0xFF34052E ^ 0x55555555, 0xC5855664 ^ 0x55555555, + 0x53B02D5D ^ 0x55555555, 0xA99F8FA1 ^ 0x55555555, 0x08BA4799 ^ 0x55555555, 0x6E85076A ^ 0x55555555, + 0x4B7A70E9 ^ 0x55555555, 0xB5B32944 ^ 0x55555555, 0xDB75092E ^ 0x55555555, 0xC4192623 ^ 0x55555555, + 0xAD6EA6B0 ^ 0x55555555, 0x49A7DF7D ^ 0x55555555, 0x9CEE60B8 ^ 0x55555555, 0x8FEDB266 ^ 0x55555555, + 0xECAA8C71 ^ 0x55555555, 0x699A17FF ^ 0x55555555, 0x5664526C ^ 0x55555555, 0xC2B19EE1 ^ 0x55555555, + 0x193602A5 ^ 0x55555555, 0x75094C29 ^ 0x55555555, 0xA0591340 ^ 0x55555555, 0xE4183A3E ^ 0x55555555, + 0x3F54989A ^ 0x55555555, 0x5B429D65 ^ 0x55555555, 0x6B8FE4D6 ^ 0x55555555, 0x99F73FD6 ^ 0x55555555, + 0xA1D29C07 ^ 0x55555555, 0xEFE830F5 ^ 0x55555555, 0x4D2D38E6 ^ 0x55555555, 0xF0255DC1 ^ 0x55555555, + 0x4CDD2086 ^ 0x55555555, 0x8470EB26 ^ 0x55555555, 0x6382E9C6 ^ 0x55555555, 0x021ECC5E ^ 0x55555555, + 0x09686B3F ^ 0x55555555, 0x3EBAEFC9 ^ 0x55555555, 0x3C971814 ^ 0x55555555, 0x6B6A70A1 ^ 0x55555555, + 0x687F3584 ^ 0x55555555, 0x52A0E286 ^ 0x55555555, 0xB79C5305 ^ 0x55555555, 0xAA500737 ^ 0x55555555, + 0x3E07841C ^ 0x55555555, 0x7FDEAE5C ^ 0x55555555, 0x8E7D44EC ^ 0x55555555, 0x5716F2B8 ^ 0x55555555, + 0xB03ADA37 ^ 0x55555555, 0xF0500C0D ^ 0x55555555, 0xF01C1F04 ^ 0x55555555, 0x0200B3FF ^ 0x55555555, + 0xAE0CF51A ^ 0x55555555, 0x3CB574B2 ^ 0x55555555, 0x25837A58 ^ 0x55555555, 0xDC0921BD ^ 0x55555555, + 0xD19113F9 ^ 0x55555555, 0x7CA92FF6 ^ 0x55555555, 0x94324773 ^ 0x55555555, 0x22F54701 ^ 0x55555555, + 0x3AE5E581 ^ 0x55555555, 0x37C2DADC ^ 0x55555555, 0xC8B57634 ^ 0x55555555, 0x9AF3DDA7 ^ 0x55555555, + 0xA9446146 ^ 0x55555555, 0x0FD0030E ^ 0x55555555, 0xECC8C73E ^ 0x55555555, 0xA4751E41 ^ 0x55555555, + 0xE238CD99 ^ 0x55555555, 0x3BEA0E2F ^ 0x55555555, 0x3280BBA1 ^ 0x55555555, 0x183EB331 ^ 0x55555555, + 0x4E548B38 ^ 0x55555555, 0x4F6DB908 ^ 0x55555555, 0x6F420D03 ^ 0x55555555, 0xF60A04BF ^ 0x55555555, + 0x2CB81290 ^ 0x55555555, 0x24977C79 ^ 0x55555555, 0x5679B072 ^ 0x55555555, 0xBCAF89AF ^ 0x55555555, + 0xDE9A771F ^ 0x55555555, 0xD9930810 ^ 0x55555555, 0xB38BAE12 ^ 0x55555555, 0xDCCF3F2E ^ 0x55555555, + 0x5512721F ^ 0x55555555, 0x2E6B7124 ^ 0x55555555, 0x501ADDE6 ^ 0x55555555, 0x9F84CD87 ^ 0x55555555, + 0x7A584718 ^ 0x55555555, 0x7408DA17 ^ 0x55555555, 0xBC9F9ABC ^ 0x55555555, 0xE94B7D8C ^ 0x55555555, + 0xEC7AEC3A ^ 0x55555555, 0xDB851DFA ^ 0x55555555, 0x63094366 ^ 0x55555555, 0xC464C3D2 ^ 0x55555555, + 0xEF1C1847 ^ 0x55555555, 0x3215D908 ^ 0x55555555, 0xDD433B37 ^ 0x55555555, 0x24C2BA16 ^ 0x55555555, + 0x12A14D43 ^ 0x55555555, 0x2A65C451 ^ 0x55555555, 0x50940002 ^ 0x55555555, 0x133AE4DD ^ 0x55555555, + 0x71DFF89E ^ 0x55555555, 0x10314E55 ^ 0x55555555, 0x81AC77D6 ^ 0x55555555, 0x5F11199B ^ 0x55555555, + 0x043556F1 ^ 0x55555555, 0xD7A3C76B ^ 0x55555555, 0x3C11183B ^ 0x55555555, 0x5924A509 ^ 0x55555555, + 0xF28FE6ED ^ 0x55555555, 0x97F1FBFA ^ 0x55555555, 0x9EBABF2C ^ 0x55555555, 0x1E153C6E ^ 0x55555555, + 0x86E34570 ^ 0x55555555, 0xEAE96FB1 ^ 0x55555555, 0x860E5E0A ^ 0x55555555, 0x5A3E2AB3 ^ 0x55555555, + 0x771FE71C ^ 0x55555555, 0x4E3D06FA ^ 0x55555555, 0x2965DCB9 ^ 0x55555555, 0x99E71D0F ^ 0x55555555, + 0x803E89D6 ^ 0x55555555, 0x5266C825 ^ 0x55555555, 0x2E4CC978 ^ 0x55555555, 0x9C10B36A ^ 0x55555555, + 0xC6150EBA ^ 0x55555555, 0x94E2EA78 ^ 0x55555555, 0xA5FC3C53 ^ 0x55555555, 0x1E0A2DF4 ^ 0x55555555, + 0xF2F74EA7 ^ 0x55555555, 0x361D2B3D ^ 0x55555555, 0x1939260F ^ 0x55555555, 0x19C27960 ^ 0x55555555, + 0x5223A708 ^ 0x55555555, 0xF71312B6 ^ 0x55555555, 0xEBADFE6E ^ 0x55555555, 0xEAC31F66 ^ 0x55555555, + 0xE3BC4595 ^ 0x55555555, 0xA67BC883 ^ 0x55555555, 0xB17F37D1 ^ 0x55555555, 0x018CFF28 ^ 0x55555555, + 0xC332DDEF ^ 0x55555555, 0xBE6C5AA5 ^ 0x55555555, 0x65582185 ^ 0x55555555, 0x68AB9802 ^ 0x55555555, + 0xEECEA50F ^ 0x55555555, 0xDB2F953B ^ 0x55555555, 0x2AEF7DAD ^ 0x55555555, 0x5B6E2F84 ^ 0x55555555, + 0x1521B628 ^ 0x55555555, 0x29076170 ^ 0x55555555, 0xECDD4775 ^ 0x55555555, 0x619F1510 ^ 0x55555555, + 0x13CCA830 ^ 0x55555555, 0xEB61BD96 ^ 0x55555555, 0x0334FE1E ^ 0x55555555, 0xAA0363CF ^ 0x55555555, + 0xB5735C90 ^ 0x55555555, 0x4C70A239 ^ 0x55555555, 0xD59E9E0B ^ 0x55555555, 0xCBAADE14 ^ 0x55555555, + 0xEECC86BC ^ 0x55555555, 0x60622CA7 ^ 0x55555555, 0x9CAB5CAB ^ 0x55555555, 0xB2F3846E ^ 0x55555555, + 0x648B1EAF ^ 0x55555555, 0x19BDF0CA ^ 0x55555555, 0xA02369B9 ^ 0x55555555, 0x655ABB50 ^ 0x55555555, + 0x40685A32 ^ 0x55555555, 0x3C2AB4B3 ^ 0x55555555, 0x319EE9D5 ^ 0x55555555, 0xC021B8F7 ^ 0x55555555, + 0x9B540B19 ^ 0x55555555, 0x875FA099 ^ 0x55555555, 0x95F7997E ^ 0x55555555, 0x623D7DA8 ^ 0x55555555, + 0xF837889A ^ 0x55555555, 0x97E32D77 ^ 0x55555555, 0x11ED935F ^ 0x55555555, 0x16681281 ^ 0x55555555, + 0x0E358829 ^ 0x55555555, 0xC7E61FD6 ^ 0x55555555, 0x96DEDFA1 ^ 0x55555555, 0x7858BA99 ^ 0x55555555, + 0x57F584A5 ^ 0x55555555, 0x1B227263 ^ 0x55555555, 0x9B83C3FF ^ 0x55555555, 0x1AC24696 ^ 0x55555555, + 0xCDB30AEB ^ 0x55555555, 0x532E3054 ^ 0x55555555, 0x8FD948E4 ^ 0x55555555, 0x6DBC3128 ^ 0x55555555, + 0x58EBF2EF ^ 0x55555555, 0x34C6FFEA ^ 0x55555555, 0xFE28ED61 ^ 0x55555555, 0xEE7C3C73 ^ 0x55555555, + 0x5D4A14D9 ^ 0x55555555, 0xE864B7E3 ^ 0x55555555, 0x42105D14 ^ 0x55555555, 0x203E13E0 ^ 0x55555555, + 0x45EEE2B6 ^ 0x55555555, 0xA3AAABEA ^ 0x55555555, 0xDB6C4F15 ^ 0x55555555, 0xFACB4FD0 ^ 0x55555555, + 0xC742F442 ^ 0x55555555, 0xEF6ABBB5 ^ 0x55555555, 0x654F3B1D ^ 0x55555555, 0x41CD2105 ^ 0x55555555, + 0xD81E799E ^ 0x55555555, 0x86854DC7 ^ 0x55555555, 0xE44B476A ^ 0x55555555, 0x3D816250 ^ 0x55555555, + 0xCF62A1F2 ^ 0x55555555, 0x5B8D2646 ^ 0x55555555, 0xFC8883A0 ^ 0x55555555, 0xC1C7B6A3 ^ 0x55555555, + 0x7F1524C3 ^ 0x55555555, 0x69CB7492 ^ 0x55555555, 0x47848A0B ^ 0x55555555, 0x5692B285 ^ 0x55555555, + 0x095BBF00 ^ 0x55555555, 0xAD19489D ^ 0x55555555, 0x1462B174 ^ 0x55555555, 0x23820E00 ^ 0x55555555, + 0x58428D2A ^ 0x55555555, 0x0C55F5EA ^ 0x55555555, 0x1DADF43E ^ 0x55555555, 0x233F7061 ^ 0x55555555, + 0x3372F092 ^ 0x55555555, 0x8D937E41 ^ 0x55555555, 0xD65FECF1 ^ 0x55555555, 0x6C223BDB ^ 0x55555555, + 0x7CDE3759 ^ 0x55555555, 0xCBEE7460 ^ 0x55555555, 0x4085F2A7 ^ 0x55555555, 0xCE77326E ^ 0x55555555, + 0xA6078084 ^ 0x55555555, 0x19F8509E ^ 0x55555555, 0xE8EFD855 ^ 0x55555555, 0x61D99735 ^ 0x55555555, + 0xA969A7AA ^ 0x55555555, 0xC50C06C2 ^ 0x55555555, 0x5A04ABFC ^ 0x55555555, 0x800BCADC ^ 0x55555555, + 0x9E447A2E ^ 0x55555555, 0xC3453484 ^ 0x55555555, 0xFDD56705 ^ 0x55555555, 0x0E1E9EC9 ^ 0x55555555, + 0xDB73DBD3 ^ 0x55555555, 0x105588CD ^ 0x55555555, 0x675FDA79 ^ 0x55555555, 0xE3674340 ^ 0x55555555, + 0xC5C43465 ^ 0x55555555, 0x713E38D8 ^ 0x55555555, 0x3D28F89E ^ 0x55555555, 0xF16DFF20 ^ 0x55555555, + 0x153E21E7 ^ 0x55555555, 0x8FB03D4A ^ 0x55555555, 0xE6E39F2B ^ 0x55555555, 0xDB83ADF7 ^ 0x55555555, + 0xE93D5A68 ^ 0x55555555, 0x948140F7 ^ 0x55555555, 0xF64C261C ^ 0x55555555, 0x94692934 ^ 0x55555555, + 0x411520F7 ^ 0x55555555, 0x7602D4F7 ^ 0x55555555, 0xBCF46B2E ^ 0x55555555, 0xD4A20068 ^ 0x55555555, + 0xD4082471 ^ 0x55555555, 0x3320F46A ^ 0x55555555, 0x43B7D4B7 ^ 0x55555555, 0x500061AF ^ 0x55555555, + 0x1E39F62E ^ 0x55555555, 0x97244546 ^ 0x55555555, 0x14214F74 ^ 0x55555555, 0xBF8B8840 ^ 0x55555555, + 0x4D95FC1D ^ 0x55555555, 0x96B591AF ^ 0x55555555, 0x70F4DDD3 ^ 0x55555555, 0x66A02F45 ^ 0x55555555, + 0xBFBC09EC ^ 0x55555555, 0x03BD9785 ^ 0x55555555, 0x7FAC6DD0 ^ 0x55555555, 0x31CB8504 ^ 0x55555555, + 0x96EB27B3 ^ 0x55555555, 0x55FD3941 ^ 0x55555555, 0xDA2547E6 ^ 0x55555555, 0xABCA0A9A ^ 0x55555555, + 0x28507825 ^ 0x55555555, 0x530429F4 ^ 0x55555555, 0x0A2C86DA ^ 0x55555555, 0xE9B66DFB ^ 0x55555555, + 0x68DC1462 ^ 0x55555555, 0xD7486900 ^ 0x55555555, 0x680EC0A4 ^ 0x55555555, 0x27A18DEE ^ 0x55555555, + 0x4F3FFEA2 ^ 0x55555555, 0xE887AD8C ^ 0x55555555, 0xB58CE006 ^ 0x55555555, 0x7AF4D6B6 ^ 0x55555555, + 0xAACE1E7C ^ 0x55555555, 0xD3375FEC ^ 0x55555555, 0xCE78A399 ^ 0x55555555, 0x406B2A42 ^ 0x55555555, + 0x20FE9E35 ^ 0x55555555, 0xD9F385B9 ^ 0x55555555, 0xEE39D7AB ^ 0x55555555, 0x3B124E8B ^ 0x55555555, + 0x1DC9FAF7 ^ 0x55555555, 0x4B6D1856 ^ 0x55555555, 0x26A36631 ^ 0x55555555, 0xEAE397B2 ^ 0x55555555, + 0x3A6EFA74 ^ 0x55555555, 0xDD5B4332 ^ 0x55555555, 0x6841E7F7 ^ 0x55555555, 0xCA7820FB ^ 0x55555555, + 0xFB0AF54E ^ 0x55555555, 0xD8FEB397 ^ 0x55555555, 0x454056AC ^ 0x55555555, 0xBA489527 ^ 0x55555555, + 0x55533A3A ^ 0x55555555, 0x20838D87 ^ 0x55555555, 0xFE6BA9B7 ^ 0x55555555, 0xD096954B ^ 0x55555555, + 0x55A867BC ^ 0x55555555, 0xA1159A58 ^ 0x55555555, 0xCCA92963 ^ 0x55555555, 0x99E1DB33 ^ 0x55555555, + 0xA62A4A56 ^ 0x55555555, 0x3F3125F9 ^ 0x55555555, 0x5EF47E1C ^ 0x55555555, 0x9029317C ^ 0x55555555, + 0xFDF8E802 ^ 0x55555555, 0x04272F70 ^ 0x55555555, 0x80BB155C ^ 0x55555555, 0x05282CE3 ^ 0x55555555, + 0x95C11548 ^ 0x55555555, 0xE4C66D22 ^ 0x55555555, 0x48C1133F ^ 0x55555555, 0xC70F86DC ^ 0x55555555, + 0x07F9C9EE ^ 0x55555555, 0x41041F0F ^ 0x55555555, 0x404779A4 ^ 0x55555555, 0x5D886E17 ^ 0x55555555, + 0x325F51EB ^ 0x55555555, 0xD59BC0D1 ^ 0x55555555, 0xF2BCC18F ^ 0x55555555, 0x41113564 ^ 0x55555555, + 0x257B7834 ^ 0x55555555, 0x602A9C60 ^ 0x55555555, 0xDFF8E8A3 ^ 0x55555555, 0x1F636C1B ^ 0x55555555, + 0x0E12B4C2 ^ 0x55555555, 0x02E1329E ^ 0x55555555, 0xAF664FD1 ^ 0x55555555, 0xCAD18115 ^ 0x55555555, + 0x6B2395E0 ^ 0x55555555, 0x333E92E1 ^ 0x55555555, 0x3B240B62 ^ 0x55555555, 0xEEBEB922 ^ 0x55555555, + 0x85B2A20E ^ 0x55555555, 0xE6BA0D99 ^ 0x55555555, 0xDE720C8C ^ 0x55555555, 0x2DA2F728 ^ 0x55555555, + 0xD0127845 ^ 0x55555555, 0x95B794FD ^ 0x55555555, 0x647D0862 ^ 0x55555555, 0xE7CCF5F0 ^ 0x55555555, + 0x5449A36F ^ 0x55555555, 0x877D48FA ^ 0x55555555, 0xC39DFD27 ^ 0x55555555, 0xF33E8D1E ^ 0x55555555, + 0x0A476341 ^ 0x55555555, 0x992EFF74 ^ 0x55555555, 0x3A6F6EAB ^ 0x55555555, 0xF4F8FD37 ^ 0x55555555, + 0xA812DC60 ^ 0x55555555, 0xA1EBDDF8 ^ 0x55555555, 0x991BE14C ^ 0x55555555, 0xDB6E6B0D ^ 0x55555555, + 0xC67B5510 ^ 0x55555555, 0x6D672C37 ^ 0x55555555, 0x2765D43B ^ 0x55555555, 0xDCD0E804 ^ 0x55555555, + 0xF1290DC7 ^ 0x55555555, 0xCC00FFA3 ^ 0x55555555, 0xB5390F92 ^ 0x55555555, 0x690FED0B ^ 0x55555555, + 0x667B9FFB ^ 0x55555555, 0xCEDB7D9C ^ 0x55555555, 0xA091CF0B ^ 0x55555555, 0xD9155EA3 ^ 0x55555555, + 0xBB132F88 ^ 0x55555555, 0x515BAD24 ^ 0x55555555, 0x7B9479BF ^ 0x55555555, 0x763BD6EB ^ 0x55555555, + 0x37392EB3 ^ 0x55555555, 0xCC115979 ^ 0x55555555, 0x8026E297 ^ 0x55555555, 0xF42E312D ^ 0x55555555, + 0x6842ADA7 ^ 0x55555555, 0xC66A2B3B ^ 0x55555555, 0x12754CCC ^ 0x55555555, 0x782EF11C ^ 0x55555555, + 0x6A124237 ^ 0x55555555, 0xB79251E7 ^ 0x55555555, 0x06A1BBE6 ^ 0x55555555, 0x4BFB6350 ^ 0x55555555, + 0x1A6B1018 ^ 0x55555555, 0x11CAEDFA ^ 0x55555555, 0x3D25BDD8 ^ 0x55555555, 0xE2E1C3C9 ^ 0x55555555, + 0x44421659 ^ 0x55555555, 0x0A121386 ^ 0x55555555, 0xD90CEC6E ^ 0x55555555, 0xD5ABEA2A ^ 0x55555555, + 0x64AF674E ^ 0x55555555, 0xDA86A85F ^ 0x55555555, 0xBEBFE988 ^ 0x55555555, 0x64E4C3FE ^ 0x55555555, + 0x9DBC8057 ^ 0x55555555, 0xF0F7C086 ^ 0x55555555, 0x60787BF8 ^ 0x55555555, 0x6003604D ^ 0x55555555, + 0xD1FD8346 ^ 0x55555555, 0xF6381FB0 ^ 0x55555555, 0x7745AE04 ^ 0x55555555, 0xD736FCCC ^ 0x55555555, + 0x83426B33 ^ 0x55555555, 0xF01EAB71 ^ 0x55555555, 0xB0804187 ^ 0x55555555, 0x3C005E5F ^ 0x55555555, + 0x77A057BE ^ 0x55555555, 0xBDE8AE24 ^ 0x55555555, 0x55464299 ^ 0x55555555, 0xBF582E61 ^ 0x55555555, + 0x4E58F48F ^ 0x55555555, 0xF2DDFDA2 ^ 0x55555555, 0xF474EF38 ^ 0x55555555, 0x8789BDC2 ^ 0x55555555, + 0x5366F9C3 ^ 0x55555555, 0xC8B38E74 ^ 0x55555555, 0xB475F255 ^ 0x55555555, 0x46FCD9B9 ^ 0x55555555, + 0x7AEB2661 ^ 0x55555555, 0x8B1DDF84 ^ 0x55555555, 0x846A0E79 ^ 0x55555555, 0x915F95E2 ^ 0x55555555, + 0x466E598E ^ 0x55555555, 0x20B45770 ^ 0x55555555, 0x8CD55591 ^ 0x55555555, 0xC902DE4C ^ 0x55555555, + 0xB90BACE1 ^ 0x55555555, 0xBB8205D0 ^ 0x55555555, 0x11A86248 ^ 0x55555555, 0x7574A99E ^ 0x55555555, + 0xB77F19B6 ^ 0x55555555, 0xE0A9DC09 ^ 0x55555555, 0x662D09A1 ^ 0x55555555, 0xC4324633 ^ 0x55555555, + 0xE85A1F02 ^ 0x55555555, 0x09F0BE8C ^ 0x55555555, 0x4A99A025 ^ 0x55555555, 0x1D6EFE10 ^ 0x55555555, + 0x1AB93D1D ^ 0x55555555, 0x0BA5A4DF ^ 0x55555555, 0xA186F20F ^ 0x55555555, 0x2868F169 ^ 0x55555555, + 0xDCB7DA83 ^ 0x55555555, 0x573906FE ^ 0x55555555, 0xA1E2CE9B ^ 0x55555555, 0x4FCD7F52 ^ 0x55555555, + 0x50115E01 ^ 0x55555555, 0xA70683FA ^ 0x55555555, 0xA002B5C4 ^ 0x55555555, 0x0DE6D027 ^ 0x55555555, + 0x9AF88C27 ^ 0x55555555, 0x773F8641 ^ 0x55555555, 0xC3604C06 ^ 0x55555555, 0x61A806B5 ^ 0x55555555, + 0xF0177A28 ^ 0x55555555, 0xC0F586E0 ^ 0x55555555, 0x006058AA ^ 0x55555555, 0x30DC7D62 ^ 0x55555555, + 0x11E69ED7 ^ 0x55555555, 0x2338EA63 ^ 0x55555555, 0x53C2DD94 ^ 0x55555555, 0xC2C21634 ^ 0x55555555, + 0xBBCBEE56 ^ 0x55555555, 0x90BCB6DE ^ 0x55555555, 0xEBFC7DA1 ^ 0x55555555, 0xCE591D76 ^ 0x55555555, + 0x6F05E409 ^ 0x55555555, 0x4B7C0188 ^ 0x55555555, 0x39720A3D ^ 0x55555555, 0x7C927C24 ^ 0x55555555, + 0x86E3725F ^ 0x55555555, 0x724D9DB9 ^ 0x55555555, 0x1AC15BB4 ^ 0x55555555, 0xD39EB8FC ^ 0x55555555, + 0xED545578 ^ 0x55555555, 0x08FCA5B5 ^ 0x55555555, 0xD83D7CD3 ^ 0x55555555, 0x4DAD0FC4 ^ 0x55555555, + 0x1E50EF5E ^ 0x55555555, 0xB161E6F8 ^ 0x55555555, 0xA28514D9 ^ 0x55555555, 0x6C51133C ^ 0x55555555, + 0x6FD5C7E7 ^ 0x55555555, 0x56E14EC4 ^ 0x55555555, 0x362ABFCE ^ 0x55555555, 0xDDC6C837 ^ 0x55555555, + 0xD79A3234 ^ 0x55555555, 0x92638212 ^ 0x55555555, 0x670EFA8E ^ 0x55555555, 0x406000E0 ^ 0x55555555, + 0x3A39CE37 ^ 0x55555555, 0xD3FAF5CF ^ 0x55555555, 0xABC27737 ^ 0x55555555, 0x5AC52D1B ^ 0x55555555, + 0x5CB0679E ^ 0x55555555, 0x4FA33742 ^ 0x55555555, 0xD3822740 ^ 0x55555555, 0x99BC9BBE ^ 0x55555555, + 0xD5118E9D ^ 0x55555555, 0xBF0F7315 ^ 0x55555555, 0xD62D1C7E ^ 0x55555555, 0xC700C47B ^ 0x55555555, + 0xB78C1B6B ^ 0x55555555, 0x21A19045 ^ 0x55555555, 0xB26EB1BE ^ 0x55555555, 0x6A366EB4 ^ 0x55555555, + 0x5748AB2F ^ 0x55555555, 0xBC946E79 ^ 0x55555555, 0xC6A376D2 ^ 0x55555555, 0x6549C2C8 ^ 0x55555555, + 0x530FF8EE ^ 0x55555555, 0x468DDE7D ^ 0x55555555, 0xD5730A1D ^ 0x55555555, 0x4CD04DC6 ^ 0x55555555, + 0x2939BBDB ^ 0x55555555, 0xA9BA4650 ^ 0x55555555, 0xAC9526E8 ^ 0x55555555, 0xBE5EE304 ^ 0x55555555, + 0xA1FAD5F0 ^ 0x55555555, 0x6A2D519A ^ 0x55555555, 0x63EF8CE2 ^ 0x55555555, 0x9A86EE22 ^ 0x55555555, + 0xC089C2B8 ^ 0x55555555, 0x43242EF6 ^ 0x55555555, 0xA51E03AA ^ 0x55555555, 0x9CF2D0A4 ^ 0x55555555, + 0x83C061BA ^ 0x55555555, 0x9BE96A4D ^ 0x55555555, 0x8FE51550 ^ 0x55555555, 0xBA645BD6 ^ 0x55555555, + 0x2826A2F9 ^ 0x55555555, 0xA73A3AE1 ^ 0x55555555, 0x4BA99586 ^ 0x55555555, 0xEF5562E9 ^ 0x55555555, + 0xC72FEFD3 ^ 0x55555555, 0xF752F7DA ^ 0x55555555, 0x3F046F69 ^ 0x55555555, 0x77FA0A59 ^ 0x55555555, + 0x80E4A915 ^ 0x55555555, 0x87B08601 ^ 0x55555555, 0x9B09E6AD ^ 0x55555555, 0x3B3EE593 ^ 0x55555555, + 0xE990FD5A ^ 0x55555555, 0x9E34D797 ^ 0x55555555, 0x2CF0B7D9 ^ 0x55555555, 0x022B8B51 ^ 0x55555555, + 0x96D5AC3A ^ 0x55555555, 0x017DA67D ^ 0x55555555, 0xD1CF3ED6 ^ 0x55555555, 0x7C7D2D28 ^ 0x55555555, + 0x1F9F25CF ^ 0x55555555, 0xADF2B89B ^ 0x55555555, 0x5AD6B472 ^ 0x55555555, 0x5A88F54C ^ 0x55555555, + 0xE029AC71 ^ 0x55555555, 0xE019A5E6 ^ 0x55555555, 0x47B0ACFD ^ 0x55555555, 0xED93FA9B ^ 0x55555555, + 0xE8D3C48D ^ 0x55555555, 0x283B57CC ^ 0x55555555, 0xF8D56629 ^ 0x55555555, 0x79132E28 ^ 0x55555555, + 0x785F0191 ^ 0x55555555, 0xED756055 ^ 0x55555555, 0xF7960E44 ^ 0x55555555, 0xE3D35E8C ^ 0x55555555, + 0x15056DD4 ^ 0x55555555, 0x88F46DBA ^ 0x55555555, 0x03A16125 ^ 0x55555555, 0x0564F0BD ^ 0x55555555, + 0xC3EB9E15 ^ 0x55555555, 0x3C9057A2 ^ 0x55555555, 0x97271AEC ^ 0x55555555, 0xA93A072A ^ 0x55555555, + 0x1B3F6D9B ^ 0x55555555, 0x1E6321F5 ^ 0x55555555, 0xF59C66FB ^ 0x55555555, 0x26DCF319 ^ 0x55555555, + 0x7533D928 ^ 0x55555555, 0xB155FDF5 ^ 0x55555555, 0x03563482 ^ 0x55555555, 0x8ABA3CBB ^ 0x55555555, + 0x28517711 ^ 0x55555555, 0xC20AD9F8 ^ 0x55555555, 0xABCC5167 ^ 0x55555555, 0xCCAD925F ^ 0x55555555, + 0x4DE81751 ^ 0x55555555, 0x3830DC8E ^ 0x55555555, 0x379D5862 ^ 0x55555555, 0x9320F991 ^ 0x55555555, + 0xEA7A90C2 ^ 0x55555555, 0xFB3E7BCE ^ 0x55555555, 0x5121CE64 ^ 0x55555555, 0x774FBE32 ^ 0x55555555, + 0xA8B6E37E ^ 0x55555555, 0xC3293D46 ^ 0x55555555, 0x48DE5369 ^ 0x55555555, 0x6413E680 ^ 0x55555555, + 0xA2AE0810 ^ 0x55555555, 0xDD6DB224 ^ 0x55555555, 0x69852DFD ^ 0x55555555, 0x09072166 ^ 0x55555555, + 0xB39A460A ^ 0x55555555, 0x6445C0DD ^ 0x55555555, 0x586CDECF ^ 0x55555555, 0x1C20C8AE ^ 0x55555555, + 0x5BBEF7DD ^ 0x55555555, 0x1B588D40 ^ 0x55555555, 0xCCD2017F ^ 0x55555555, 0x6BB4E3BB ^ 0x55555555, + 0xDDA26A7E ^ 0x55555555, 0x3A59FF45 ^ 0x55555555, 0x3E350A44 ^ 0x55555555, 0xBCB4CDD5 ^ 0x55555555, + 0x72EACEA8 ^ 0x55555555, 0xFA6484BB ^ 0x55555555, 0x8D6612AE ^ 0x55555555, 0xBF3C6F47 ^ 0x55555555, + 0xD29BE463 ^ 0x55555555, 0x542F5D9E ^ 0x55555555, 0xAEC2771B ^ 0x55555555, 0xF64E6370 ^ 0x55555555, + 0x740E0D8D ^ 0x55555555, 0xE75B1357 ^ 0x55555555, 0xF8721671 ^ 0x55555555, 0xAF537D5D ^ 0x55555555, + 0x4040CB08 ^ 0x55555555, 0x4EB4E2CC ^ 0x55555555, 0x34D2466A ^ 0x55555555, 0x0115AF84 ^ 0x55555555, + 0xE1B00428 ^ 0x55555555, 0x95983A1D ^ 0x55555555, 0x06B89FB4 ^ 0x55555555, 0xCE6EA048 ^ 0x55555555, + 0x6F3F3B82 ^ 0x55555555, 0x3520AB82 ^ 0x55555555, 0x011A1D4B ^ 0x55555555, 0x277227F8 ^ 0x55555555, + 0x611560B1 ^ 0x55555555, 0xE7933FDC ^ 0x55555555, 0xBB3A792B ^ 0x55555555, 0x344525BD ^ 0x55555555, + 0xA08839E1 ^ 0x55555555, 0x51CE794B ^ 0x55555555, 0x2F32C9B7 ^ 0x55555555, 0xA01FBAC9 ^ 0x55555555, + 0xE01CC87E ^ 0x55555555, 0xBCC7D1F6 ^ 0x55555555, 0xCF0111C3 ^ 0x55555555, 0xA1E8AAC7 ^ 0x55555555, + 0x1A908749 ^ 0x55555555, 0xD44FBD9A ^ 0x55555555, 0xD0DADECB ^ 0x55555555, 0xD50ADA38 ^ 0x55555555, + 0x0339C32A ^ 0x55555555, 0xC6913667 ^ 0x55555555, 0x8DF9317C ^ 0x55555555, 0xE0B12B4F ^ 0x55555555, + 0xF79E59B7 ^ 0x55555555, 0x43F5BB3A ^ 0x55555555, 0xF2D519FF ^ 0x55555555, 0x27D9459C ^ 0x55555555, + 0xBF97222C ^ 0x55555555, 0x15E6FC2A ^ 0x55555555, 0x0F91FC71 ^ 0x55555555, 0x9B941525 ^ 0x55555555, + 0xFAE59361 ^ 0x55555555, 0xCEB69CEB ^ 0x55555555, 0xC2A86459 ^ 0x55555555, 0x12BAA8D1 ^ 0x55555555, + 0xB6C1075E ^ 0x55555555, 0xE3056A0C ^ 0x55555555, 0x10D25065 ^ 0x55555555, 0xCB03A442 ^ 0x55555555, + 0xE0EC6E0E ^ 0x55555555, 0x1698DB3B ^ 0x55555555, 0x4C98A0BE ^ 0x55555555, 0x3278E964 ^ 0x55555555, + 0x9F1F9532 ^ 0x55555555, 0xE0D392DF ^ 0x55555555, 0xD3A0342B ^ 0x55555555, 0x8971F21E ^ 0x55555555, + 0x1B0A7441 ^ 0x55555555, 0x4BA3348C ^ 0x55555555, 0xC5BE7120 ^ 0x55555555, 0xC37632D8 ^ 0x55555555, + 0xDF359F8D ^ 0x55555555, 0x9B992F2E ^ 0x55555555, 0xE60B6F47 ^ 0x55555555, 0x0FE3F11D ^ 0x55555555, + 0xE54CDA54 ^ 0x55555555, 0x1EDAD891 ^ 0x55555555, 0xCE6279CF ^ 0x55555555, 0xCD3E7E6F ^ 0x55555555, + 0x1618B166 ^ 0x55555555, 0xFD2C1D05 ^ 0x55555555, 0x848FD2C5 ^ 0x55555555, 0xF6FB2299 ^ 0x55555555, + 0xF523F357 ^ 0x55555555, 0xA6327623 ^ 0x55555555, 0x93A83531 ^ 0x55555555, 0x56CCCD02 ^ 0x55555555, + 0xACF08162 ^ 0x55555555, 0x5A75EBB5 ^ 0x55555555, 0x6E163697 ^ 0x55555555, 0x88D273CC ^ 0x55555555, + 0xDE966292 ^ 0x55555555, 0x81B949D0 ^ 0x55555555, 0x4C50901B ^ 0x55555555, 0x71C65614 ^ 0x55555555, + 0xE6C6C7BD ^ 0x55555555, 0x327A140A ^ 0x55555555, 0x45E1D006 ^ 0x55555555, 0xC3F27B9A ^ 0x55555555, + 0xC9AA53FD ^ 0x55555555, 0x62A80F00 ^ 0x55555555, 0xBB25BFE2 ^ 0x55555555, 0x35BDD2F6 ^ 0x55555555, + 0x71126905 ^ 0x55555555, 0xB2040222 ^ 0x55555555, 0xB6CBCF7C ^ 0x55555555, 0xCD769C2B ^ 0x55555555, + 0x53113EC0 ^ 0x55555555, 0x1640E3D3 ^ 0x55555555, 0x38ABBD60 ^ 0x55555555, 0x2547ADF0 ^ 0x55555555, + 0xBA38209C ^ 0x55555555, 0xF746CE76 ^ 0x55555555, 0x77AFA1C5 ^ 0x55555555, 0x20756060 ^ 0x55555555, + 0x85CBFE4E ^ 0x55555555, 0x8AE88DD8 ^ 0x55555555, 0x7AAAF9B0 ^ 0x55555555, 0x4CF9AA7E ^ 0x55555555, + 0x1948C25C ^ 0x55555555, 0x02FB8A8C ^ 0x55555555, 0x01C36AE4 ^ 0x55555555, 0xD6EBE1F9 ^ 0x55555555, + 0x90D4F869 ^ 0x55555555, 0xA65CDEA0 ^ 0x55555555, 0x3F09252D ^ 0x55555555, 0xC208E69F ^ 0x55555555, + 0xB74E6132 ^ 0x55555555, 0xCE77E25B ^ 0x55555555, 0x578FDFE3 ^ 0x55555555, 0x3AC372E6 ^ 0x55555555, +}; + +DWORD s_nDATA00419168[] = // table 4 +{ + 0x428A2F98 ^ 0x55555555, 0x71374491 ^ 0x55555555, 0xB5C0FBCF ^ 0x55555555, 0xE9B5DBA5 ^ 0x55555555, + 0x3956C25B ^ 0x55555555, 0x59F111F1 ^ 0x55555555, 0x923F82A4 ^ 0x55555555, 0xAB1C5ED5 ^ 0x55555555, + 0xD807AA98 ^ 0x55555555, 0x12835B01 ^ 0x55555555, 0x243185BE ^ 0x55555555, 0x550C7DC3 ^ 0x55555555, + 0x72BE5D74 ^ 0x55555555, 0x80DEB1FE ^ 0x55555555, 0x9BDC06A7 ^ 0x55555555, 0xC19BF174 ^ 0x55555555, + 0xE49B69C1 ^ 0x55555555, 0xEFBE4786 ^ 0x55555555, 0x0FC19DC6 ^ 0x55555555, 0x240CA1CC ^ 0x55555555, + 0x2DE92C6F ^ 0x55555555, 0x4A7484AA ^ 0x55555555, 0x5CB0A9DC ^ 0x55555555, 0x76F988DA ^ 0x55555555, + 0x983E5152 ^ 0x55555555, 0xA831C66D ^ 0x55555555, 0xB00327C8 ^ 0x55555555, 0xBF597FC7 ^ 0x55555555, + 0xC6E00BF3 ^ 0x55555555, 0xD5A79147 ^ 0x55555555, 0x06CA6351 ^ 0x55555555, 0x14292967 ^ 0x55555555, + 0x27B70A85 ^ 0x55555555, 0x2E1B2138 ^ 0x55555555, 0x4D2C6DFC ^ 0x55555555, 0x53380D13 ^ 0x55555555, + 0x650A7354 ^ 0x55555555, 0x766A0ABB ^ 0x55555555, 0x81C2C92E ^ 0x55555555, 0x92722C85 ^ 0x55555555, + 0xA2BFE8A1 ^ 0x55555555, 0xA81A664B ^ 0x55555555, 0xC24B8B70 ^ 0x55555555, 0xC76C51A3 ^ 0x55555555, + 0xD192E819 ^ 0x55555555, 0xD6990624 ^ 0x55555555, 0xF40E3585 ^ 0x55555555, 0x106AA070 ^ 0x55555555, + 0x19A4C116 ^ 0x55555555, 0x1E376C08 ^ 0x55555555, 0x2748774C ^ 0x55555555, 0x34B0BCB5 ^ 0x55555555, + 0x391C0CB3 ^ 0x55555555, 0x4ED8AA4A ^ 0x55555555, 0x5B9CCA4F ^ 0x55555555, 0x682E6FF3 ^ 0x55555555, + 0x748F82EE ^ 0x55555555, 0x78A5636F ^ 0x55555555, 0x84C87814 ^ 0x55555555, 0x8CC70208 ^ 0x55555555, + 0x90BEFFFA ^ 0x55555555, 0xA4506CEB ^ 0x55555555, 0xBEF9A3F7 ^ 0x55555555, 0xC67178F2 ^ 0x55555555, +}; + +DWORD s_nDATA004197E8[] = // table 5 +{ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000000, +}; + +DWORD s_nDATA004198E8[] = // table 6 +{ + 0x00000001 + 0x00000068, 0x00000003 + 0x00000068, 0x00000005 + 0x00000068, 0x00000000 + 0x00000068, + 0x00000011 + 0x00000068, 0x00000033 + 0x00000068, 0x00000055 + 0x00000068, 0x00000075 + 0x00000068, + 0x0000001A + 0x00000068, 0x0000002E + 0x00000068, 0x00000072 + 0x00000068, 0x00000015 + 0x00000068, + 0x000000A1 + 0x00000068, 0x000000F8 + 0x00000068, 0x00000013 + 0x00000068, 0x00000035 + 0x00000068, + 0x000000A0 + 0x00000068, 0x00000039 + 0x00000068, 0x0000004B + 0x00000068, 0x000000DD + 0x00000068, + 0x0000007C + 0x00000068, 0x00000084 + 0x00000068, 0x00000097 + 0x00000068, 0x000000A2 + 0x00000068, + 0x000000FD + 0x00000068, 0x0000001C + 0x00000068, 0x00000024 + 0x00000068, 0x0000006C + 0x00000068, + 0x000000B4 + 0x00000068, 0x000000C7 + 0x00000068, 0x00000052 + 0x00000068, 0x000000F6 + 0x00000068, + 0x0000000F + 0x00000068, 0x000000C3 + 0x00000068, 0x0000005E + 0x00000068, 0x000000E2 + 0x00000068, + 0x0000003D + 0x00000068, 0x00000047 + 0x00000068, 0x000000C9 + 0x00000068, 0x00000040 + 0x00000068, + 0x000000C0 + 0x00000068, 0x0000005B + 0x00000068, 0x000000ED + 0x00000068, 0x0000002C + 0x00000068, + 0x00000074 + 0x00000068, 0x0000009C + 0x00000068, 0x000000BF + 0x00000068, 0x000000DA + 0x00000068, + 0x000000FF + 0x00000068, 0x000000FB + 0x00000068, 0x00000016 + 0x00000068, 0x0000003A + 0x00000068, + 0x0000004E + 0x00000068, 0x000000D2 + 0x00000068, 0x0000006D + 0x00000068, 0x000000B7 + 0x00000068, + 0x000000C2 + 0x00000068, 0x0000005D + 0x00000068, 0x000000E7 + 0x00000068, 0x00000032 + 0x00000068, + 0x00000056 + 0x00000068, 0x000000FA + 0x00000068, 0x00000096 + 0x00000068, 0x0000003F + 0x00000068, + 0x00000041 + 0x00000068, 0x0000009F + 0x00000068, 0x000000BA + 0x00000068, 0x000000D5 + 0x00000068, + 0x00000064 + 0x00000068, 0x000000AC + 0x00000068, 0x000000EF + 0x00000068, 0x0000002A + 0x00000068, + 0x0000007E + 0x00000068, 0x00000082 + 0x00000068, 0x0000009D + 0x00000068, 0x000000BC + 0x00000068, + 0x000000DF + 0x00000068, 0x0000007A + 0x00000068, 0x0000008E + 0x00000068, 0x00000089 + 0x00000068, + 0x00000080 + 0x00000068, 0x0000009B + 0x00000068, 0x000000B6 + 0x00000068, 0x000000C1 + 0x00000068, + 0x00000058 + 0x00000068, 0x000000E8 + 0x00000068, 0x00000023 + 0x00000068, 0x00000065 + 0x00000068, + 0x000000AF + 0x00000068, 0x000000EA + 0x00000068, 0x00000025 + 0x00000068, 0x0000006F + 0x00000068, + 0x000000B1 + 0x00000068, 0x000000C8 + 0x00000068, 0x00000043 + 0x00000068, 0x000000C5 + 0x00000068, + 0x00000054 + 0x00000068, 0x000000FC + 0x00000068, 0x0000001F + 0x00000068, 0x00000021 + 0x00000068, + 0x00000063 + 0x00000068, 0x000000A5 + 0x00000068, 0x000000F4 + 0x00000068, 0x00000007 + 0x00000068, + 0x00000009 + 0x00000068, 0x0000001B + 0x00000068, 0x0000002D + 0x00000068, 0x00000077 + 0x00000068, + 0x00000099 + 0x00000068, 0x000000B0 + 0x00000068, 0x000000CB + 0x00000068, 0x00000046 + 0x00000068, + 0x000000CA + 0x00000068, 0x00000045 + 0x00000068, 0x000000CF + 0x00000068, 0x0000004A + 0x00000068, + 0x000000DE + 0x00000068, 0x00000079 + 0x00000068, 0x0000008B + 0x00000068, 0x00000086 + 0x00000068, + 0x00000091 + 0x00000068, 0x000000A8 + 0x00000068, 0x000000E3 + 0x00000068, 0x0000003E + 0x00000068, + 0x00000042 + 0x00000068, 0x000000C6 + 0x00000068, 0x00000051 + 0x00000068, 0x000000F3 + 0x00000068, + 0x0000000E + 0x00000068, 0x00000012 + 0x00000068, 0x00000036 + 0x00000068, 0x0000005A + 0x00000068, + 0x000000EE + 0x00000068, 0x00000029 + 0x00000068, 0x0000007B + 0x00000068, 0x0000008D + 0x00000068, + 0x0000008C + 0x00000068, 0x0000008F + 0x00000068, 0x0000008A + 0x00000068, 0x00000085 + 0x00000068, + 0x00000094 + 0x00000068, 0x000000A7 + 0x00000068, 0x000000F2 + 0x00000068, 0x0000000D + 0x00000068, + 0x00000017 + 0x00000068, 0x00000053 + 0x00000068, 0x000000F5 + 0x00000068, 0x00000004 + 0x00000068, + 0x0000000C + 0x00000068, 0x00000014 + 0x00000068, 0x0000003C + 0x00000068, 0x00000044 + 0x00000068, + 0x000000CC + 0x00000068, 0x0000004F + 0x00000068, 0x000000D1 + 0x00000068, 0x00000068 + 0x00000068, + 0x000000B8 + 0x00000068, 0x000000D3 + 0x00000068, 0x0000006E + 0x00000068, 0x000000B2 + 0x00000068, + 0x000000CD + 0x00000068, 0x0000004C + 0x00000068, 0x000000D4 + 0x00000068, 0x00000067 + 0x00000068, + 0x000000A9 + 0x00000068, 0x000000E0 + 0x00000068, 0x0000003B + 0x00000068, 0x0000004D + 0x00000068, + 0x000000D7 + 0x00000068, 0x00000062 + 0x00000068, 0x000000A6 + 0x00000068, 0x000000F1 + 0x00000068, + 0x00000008 + 0x00000068, 0x00000018 + 0x00000068, 0x00000028 + 0x00000068, 0x00000078 + 0x00000068, + 0x00000088 + 0x00000068, 0x00000083 + 0x00000068, 0x0000009E + 0x00000068, 0x000000B9 + 0x00000068, + 0x000000D0 + 0x00000068, 0x0000006B + 0x00000068, 0x000000BD + 0x00000068, 0x000000DC + 0x00000068, + 0x0000007F + 0x00000068, 0x00000081 + 0x00000068, 0x00000098 + 0x00000068, 0x000000B3 + 0x00000068, + 0x000000CE + 0x00000068, 0x00000049 + 0x00000068, 0x000000DB + 0x00000068, 0x00000076 + 0x00000068, + 0x0000009A + 0x00000068, 0x000000B5 + 0x00000068, 0x000000C4 + 0x00000068, 0x00000057 + 0x00000068, + 0x000000F9 + 0x00000068, 0x00000010 + 0x00000068, 0x00000030 + 0x00000068, 0x00000050 + 0x00000068, + 0x000000F0 + 0x00000068, 0x0000000B + 0x00000068, 0x0000001D + 0x00000068, 0x00000027 + 0x00000068, + 0x00000069 + 0x00000068, 0x000000BB + 0x00000068, 0x000000D6 + 0x00000068, 0x00000061 + 0x00000068, + 0x000000A3 + 0x00000068, 0x000000FE + 0x00000068, 0x00000019 + 0x00000068, 0x0000002B + 0x00000068, + 0x0000007D + 0x00000068, 0x00000087 + 0x00000068, 0x00000092 + 0x00000068, 0x000000AD + 0x00000068, + 0x000000EC + 0x00000068, 0x0000002F + 0x00000068, 0x00000071 + 0x00000068, 0x00000093 + 0x00000068, + 0x000000AE + 0x00000068, 0x000000E9 + 0x00000068, 0x00000020 + 0x00000068, 0x00000060 + 0x00000068, + 0x0000005F + 0x00000068, 0x000000E1 + 0x00000068, 0x00000038 + 0x00000068, 0x00000048 + 0x00000068, + 0x000000D8 + 0x00000068, 0x00000073 + 0x00000068, 0x00000095 + 0x00000068, 0x000000A4 + 0x00000068, + 0x000000F7 + 0x00000068, 0x00000002 + 0x00000068, 0x00000006 + 0x00000068, 0x0000000A + 0x00000068, + 0x0000001E + 0x00000068, 0x00000022 + 0x00000068, 0x00000066 + 0x00000068, 0x000000AA + 0x00000068, + 0x000000E5 + 0x00000068, 0x00000034 + 0x00000068, 0x0000005C + 0x00000068, 0x000000E4 + 0x00000068, + 0x00000037 + 0x00000068, 0x00000059 + 0x00000068, 0x000000EB + 0x00000068, 0x00000026 + 0x00000068, + 0x0000006A + 0x00000068, 0x000000BE + 0x00000068, 0x000000D9 + 0x00000068, 0x00000070 + 0x00000068, + 0x00000090 + 0x00000068, 0x000000AB + 0x00000068, 0x000000E6 + 0x00000068, 0x00000031 + 0x00000068, +}; + +__declspec(naked) WORD* X2::Decode5() +{ + __asm { + push edi + mov edi,ecx + mov eax,dword ptr ds:[edi+4] + test eax,eax + jle short LABEL1 + cmp dword ptr ds:[edi],0 + je short LABEL1 + push ebp + push esi + xor ebp,ebp + xor ecx,ecx + xor esi,esi + test eax,eax + jle short LABEL2 + push ebx + + LABEL7: + cmp ebp,0x3FF + jle short LABEL3 + xor ebp,ebp + + LABEL3: + mov eax,dword ptr ds:[edi] + mov dl,byte ptr ds:[ebp*4+s_nDATA00418168] + add eax,esi + mov bl,byte ptr ds:[eax] + xor bl,dl + inc ebp + mov byte ptr ds:[eax],bl + mov eax,dword ptr ds:[edi] + lea edx,dword ptr ds:[eax+esi] + movzx ax,byte ptr ds:[eax+esi] + or ah,0x58 + cmp ecx,7 + jle short LABEL4 + xor ecx,ecx + + LABEL4: + and eax,0x0FFFF + ror eax,cl + test al,1 + je short LABEL5 + and al,0x0FE + jmp short LABEL6 + + LABEL5: + or al,1 + LABEL6: + rol eax,cl + inc ecx + inc esi + mov byte ptr ds:[edx],al + mov eax,dword ptr ds:[edi+4] + cmp esi,eax + jl short LABEL7 + pop ebx + + LABEL2: + mov eax,dword ptr ds:[edi] + pop esi + pop ebp + pop edi + retn + + LABEL1: + xor eax,eax + pop edi + retn + } +} + +__declspec(naked) void _Decode6_Sub() +{ + __asm { + mov eax,dword ptr ss:[esp+8] + test eax,eax + jle short LABEL1 + mov ecx,dword ptr ss:[esp+4] + push esi + mov esi,eax + + LABEL3: + mov al,byte ptr ds:[ecx] + mov dl,al + and dl,0x80 + movzx dx,dl + shl al,1 + test dx,dx + mov byte ptr ds:[ecx],al + je short LABEL2 + or al,1 + mov byte ptr ds:[ecx],al + + LABEL2: + dec esi + jnz short LABEL3 + pop esi + + LABEL1: + retn 8 + } +} + +__declspec(naked) WORD* X2::Decode6() +{ + __asm { + push edi + mov edi,ecx + mov eax,dword ptr ds:[edi+4] + test eax,eax + jle short LABEL1 + cmp dword ptr ds:[edi],0 + je short LABEL1 + push ebx + push ebp + push esi + xor ebx,ebx + xor esi,esi + xor ebp,ebp + test eax,eax + jle short LABEL2 + + LABEL5: + cmp esi,0x3F + jle short LABEL3 + xor esi,esi + + LABEL3: + mov eax,dword ptr ds:[edi] + mov cl,byte ptr ds:[esi*4+s_nDATA00419168] + add eax,ebp + mov dl,byte ptr ds:[eax] + xor dl,cl + inc esi + cmp ebx,8 + mov byte ptr ds:[eax],dl + jle short LABEL4 + xor ebx,ebx + + LABEL4: + mov edx,dword ptr ds:[edi] + push ebx + add edx,ebp + mov ecx,edi + push edx + call _Decode6_Sub + mov eax,dword ptr ds:[edi+4] + inc ebx + inc ebp + cmp ebp,eax + jl short LABEL5 + + LABEL2: + mov eax,dword ptr ds:[edi] + pop esi + pop ebp + pop ebx + pop edi + retn + LABEL1: + xor eax,eax + pop edi + retn + } +} + +__declspec(naked) WORD* X2::Decode7() +{ + __asm { + push ebp + mov ebp,ecx + mov eax,dword ptr ss:[ebp+4] + test eax,eax + jle short L_FAILED + cmp dword ptr ss:[ebp],0 + je short L_FAILED + push edi + xor edx,edx + xor edi,edi + test eax,eax + jle short LABEL1 + push ebx + push esi + + LABEL3: + cmp edx,0x1F + jle short LABEL2 + xor edx,edx + + LABEL2: + mov eax,dword ptr ss:[ebp] + mov ebx,dword ptr ds:[edx*4+s_nDATA00419668] + lea esi,dword ptr ds:[eax+edi] + mov al,byte ptr ds:[eax+edi] + mov ecx,eax + and ecx,0xFF + cmp ecx,ebx + mov cl,bl + sub al,cl + xor ecx,ecx + mov byte ptr ds:[esi],al + mov eax,dword ptr ss:[ebp] + add eax,edi + inc edx + inc edi + mov cl,byte ptr ds:[eax] + mov cl,byte ptr ds:[ecx*4+s_nDATA00419268] + mov byte ptr ds:[eax],cl + mov eax,dword ptr ss:[ebp+4] + cmp edi,eax + jl short LABEL3 + pop esi + pop ebx + + LABEL1: + mov eax,dword ptr ss:[ebp] + pop edi + pop ebp + retn + + L_FAILED: + xor eax,eax + pop ebp + retn + } +} + +__declspec(naked) WORD* X2::Decode8() +{ + __asm { + sub esp,0x44 + mov edx,ecx + mov dword ptr ss:[esp],edx + mov eax,dword ptr ds:[edx+4] + test eax,eax + jle LABEL1 + cmp dword ptr ds:[edx],0 + je LABEL1 + push ebx + xor ebx,ebx + test eax,eax + jle LABEL2 + push ebp + push esi + push edi + + LABEL8: + mov eax,dword ptr ds:[edx] + xor ecx,ecx + xor edx,edx + mov dl,byte ptr ds:[eax+ebx] + lea edi,dword ptr ds:[eax+ebx] + lea eax,dword ptr ss:[esp+0x14] + + LABEL3: + mov esi,1 + shl esi,cl + and esi,edx + neg esi + sbb esi,esi + add eax,4 + neg esi + mov dword ptr ds:[eax-4],esi + inc ecx + cmp ecx,8 + jl short LABEL3 + mov eax, OFFSET s_nDATA004197E8 + lea ecx,dword ptr ss:[esp+0x34] + + LABEL5: + mov dword ptr ds:[ecx],0 + lea edx,dword ptr ss:[esp+0x14] + mov esi,8 + + LABEL4: + mov ebp,dword ptr ds:[edx] + add edx,4 + imul ebp,dword ptr ds:[eax] + add dword ptr ds:[ecx],ebp + add eax,4 + dec esi + jnz short LABEL4 + add ecx,4 + cmp eax, OFFSET s_nDATA004197E8[0x100] + jl short LABEL5 + xor edx,edx + xor ecx,ecx + lea eax,dword ptr ss:[esp+0x34] + + LABEL7: + cmp dword ptr ds:[eax],1 + jnz short LABEL6 + mov esi,1 + shl esi,cl + add edx,esi + + LABEL6: + inc ecx + add eax,4 + cmp ecx,8 + jl short LABEL7 + mov byte ptr ds:[edi],dl + mov edx,dword ptr ss:[esp+0x10] + inc ebx + cmp ebx,dword ptr ds:[edx+4] + jl LABEL8 + pop edi + pop esi + pop ebp + + LABEL2: + mov eax,dword ptr ds:[edx] + pop ebx + add esp,0x44 + retn + + LABEL1: + xor eax,eax + add esp,0x44 + retn + } +} + +__declspec(naked) void Decode9_Sub() +{ + __asm { + mov edx,dword ptr ss:[esp+8] + xor eax,eax + push esi + test edx,edx + jle short D9D_LABEL1 + mov ecx,dword ptr ss:[esp+8] + mov esi,dword ptr ss:[esp+0x10] + + D9D_LABEL3: + cmp dword ptr ds:[ecx],esi + je short D9D_LABEL2 + inc eax + add ecx,4 + cmp eax,edx + jl short D9D_LABEL3 + + D9D_LABEL1: + or eax, 0xFFFFFFFF + + D9D_LABEL2: + pop esi + retn 0x0C + } +} + +__declspec(naked) BYTE* X2::Decode9() +{ + __asm { + sub esp,8 + push esi + mov esi,ecx + mov eax,dword ptr ds:[esi+4] + test eax,eax + jle LABEL1 + cmp dword ptr ds:[esi],0 + je LABEL1 + cdq + sub eax,edx + push ebp + sar eax,1 + push edi + push eax + call eng_malloc // old code is call new + mov ebp,eax + mov eax,dword ptr ds:[esi+4] + add esp,4 + xor edi,edi + test eax,eax + mov dword ptr ss:[esp+0x10],ebp + jle short LABEL2 + push ebx + + LABEL3: + mov eax,dword ptr ds:[esi] + xor ecx,ecx + add eax,edi + xor ebx,ebx + mov cl,byte ptr ds:[eax] + mov bl,byte ptr ds:[eax+1] + push ecx + push 0x100 + push OFFSET s_nDATA004198E8 + mov ecx,esi + call Decode9_Sub + push ebx + push 0x100 + push OFFSET s_nDATA004198E8 + mov ecx,esi + mov dword ptr ss:[esp+0x1C],eax + call Decode9_Sub + mov ecx,eax + mov bl,byte ptr ss:[esp+0x10] + cdq + and edx,7 + add eax,edx + sar eax,3 + mov dl,al + shl dl,4 + add dl,bl + mov ebx,dword ptr ds:[esi] + shl al,3 + mov byte ptr ds:[ebx+edi],dl + mov edx,dword ptr ds:[esi] + add edx,edi + sub cl,al + add edi,2 + mov bl,byte ptr ds:[edx] + xor bl,cl + inc ebp + mov byte ptr ds:[edx],bl + mov eax,dword ptr ds:[esi] + mov cl,byte ptr ds:[eax+edi-2] + mov byte ptr ss:[ebp-1],cl + mov eax,dword ptr ds:[esi+4] + cmp edi,eax + jl short LABEL3 + mov ebp,dword ptr ss:[esp+0x14] // return the memory allocated by eng_malloc + pop ebx + + LABEL2: + mov edx,dword ptr ds:[esi] + push edx + call dword ptr [free] // call free to release memory X2::pData + add esp,4 + mov eax,ebp // set return to eax + mov dword ptr ds:[esi],0 + mov dword ptr ds:[esi+4],0 + pop edi + pop ebp + pop esi + add esp,8 + retn + + LABEL1: + xor eax,eax + pop esi + add esp,8 + retn + } +} + +__declspec(naked) BOOL ReadCode( + BYTE* /* pSection */, + DWORD* /* pOffset */, + JD_PATH_INFO_05* /* pInfo */, + BYTE* /* pBuffer */) +{ + __asm { + mov eax,dword ptr ss:[esp+8] ; + mov edx,dword ptr ss:[esp+4] ; Arg1: pSection + push esi + mov esi,dword ptr ss:[esp+0x14] ; Arg4 + mov ecx,dword ptr ds:[eax] ; ecx <== *pOffset + push edi + mov edi,dword ptr ss:[esp+0x14] ; Arg3 + mov cl,byte ptr ds:[ecx+edx] ; cl <== pSection[*p2] + mov byte ptr ds:[esi],cl ; *pBuffer <== cl + mov edx,dword ptr ds:[eax] + inc edx + mov dword ptr ds:[eax],edx ; p2++ + movsx eax,word ptr ds:[edi+0x40] + cmp eax,0 ; Switch (cases 0..9) + je short CASE_0356789 + cmp eax,1 + je short CASE_12 + cmp eax,2 + je short CASE_12 + cmp eax,3 + je short CASE_0356789 + cmp eax,4 + je short CASE_4 + cmp eax,5 + je short CASE_0356789 + cmp eax,6 + je short CASE_0356789 + cmp eax,7 + je short CASE_0356789 + cmp eax,8 + je short CASE_0356789 + cmp eax,9 + je short CASE_0356789 + + jmp CASE_DEFAULT + + CASE_12: + mov dl,byte ptr ds:[edi+0x42] ; Cases 1,2 of switch 00401832 + mov al,byte ptr ds:[esi] + xor al,dl + pop edi + mov byte ptr ds:[esi],al + mov eax,1 + pop esi + retn + + CASE_4: + mov cx,word ptr ds:[edi+0x42] ; Case 4 of switch 00401832 + test cx,cx + jl short CASE_DEFAULT + cmp cx,7 + jg short CASE_DEFAULT + mov al,byte ptr ds:[esi] + movsx edx,cx + mov ecx,8 + sub ecx,edx + mov dl,al + shl dl,cl + mov cl,byte ptr ds:[edi+0x42] + shr al,cl + or dl,al + mov byte ptr ds:[esi],dl + + CASE_0356789: + pop edi ; Cases 0,3,5,6,7,8,9 of switch 00401832 + mov eax,1 + pop esi + retn + + CASE_DEFAULT: + pop edi ; Default case of switch 00401832 + xor eax,eax + pop esi + retn + } +} + +__declspec(naked) BOOL ReadDWORD( + BYTE* /* pSection */, + DWORD* /* pOffset */, + JD_PATH_INFO_05* /* pInfo */, + DWORD /* code */, + void* /* pBuffer */, + DWORD /* size */) +{ + __asm { + mov eax,dword ptr ss:[esp+0x18] ; eax <== size_ + mov edx,dword ptr ss:[esp+8] ; edx <== pOffset + push ebx + push ebp + push esi + mov esi,dword ptr ds:[edx] ; esi <== offset + lea ebp,dword ptr ds:[eax*4] ; ebp <== size_ * 4 + mov eax,dword ptr ss:[esp+0x10] ; eax <== path_section + mov ecx,ebp + add esi,eax ; esi <== path_section + offset + mov eax,dword ptr ss:[esp+0x20] ; eax <== pBuffer + mov ebx,ecx ; ebx <== size_ * 4 + push edi + mov edi,eax ; copy size_ DWORD from section[offset] to pBuffer + shr ecx,2 + rep movs dword ptr es:[edi],dword ptr ds:[esi] + mov ecx,ebx + and ecx,3 + rep movs byte ptr es:[edi],byte ptr ds:[esi] + mov edi,dword ptr ds:[edx] + add edi,ebp + mov dword ptr ds:[edx],edi ; update *pOffset_ + mov edi,dword ptr ss:[esp+0x1C] + movsx ecx,word ptr ds:[edi+0x40] ; ecx <== nMethod + mov dl,byte ptr ds:[edi+0x42] ; dl <== nKey + + cmp ecx,0 ; Switch (cases 0..9) + je CASE_0 + cmp ecx,1 + je CASE_1 + cmp ecx,2 + je CASE_2 + cmp ecx,3 + je CASE_3 + cmp ecx,4 + je CASE_4 + cmp ecx,5 + je CASE_5678 + cmp ecx,6 + je CASE_5678 + cmp ecx,7 + je CASE_5678 + cmp ecx,8 + je CASE_5678 + cmp ecx,9 + je CASE_9 + jmp CASE_DEFAULT + + CASE_1: + xor ecx,ecx ; Case 1 of switch JDSimu_004018F2 + test ebp,ebp + jle CASE_0 + + JDSimu_0040190C: + mov bl,byte ptr ds:[ecx+eax] + xor bl,dl + mov byte ptr ds:[ecx+eax],bl + inc ecx + cmp ecx,ebp + jl short JDSimu_0040190C + pop edi + pop esi + pop ebp + mov eax,1 + pop ebx + retn + + CASE_2: + xor ecx,ecx ; Case 2 of switch JDSimu_004018F2 + test ebp,ebp + jle CASE_0 + mov dl,byte ptr ss:[esp+0x20] + + JDSimu_00401931: + mov bl,byte ptr ds:[ecx+eax] + xor bl,dl + mov byte ptr ds:[ecx+eax],bl + inc ecx + cmp ecx,ebp + jl short JDSimu_00401931 + pop edi + pop esi + pop ebp + mov eax,1 + pop ebx + retn + + CASE_3: + movsx ecx,word ptr ds:[edi+0x42] ; Case 3 of switch JDSimu_004018F2 + cmp ecx,0 + je short L_CASE_0 ; Switch (cases 0..3) + cmp ecx,1 + je short L_CASE_1 + cmp ecx,2 + je short L_CASE_2 + cmp ecx,3 + je short L_CASE_3 + jmp short CASE_DEFAULT + + L_CASE_0: + xor ecx,ecx ; Case 0 of switch JDSimu_0040194C + mov edx,1 + jmp short JDSimu_00401984 + + L_CASE_1: + mov ecx,1 ; Case 1 of switch JDSimu_0040194C + mov edx,2 + jmp short JDSimu_00401984 + + L_CASE_2: + mov ecx,2 ; Case 2 of switch JDSimu_0040194C + mov edx,3 + jmp short JDSimu_00401984 + + L_CASE_3: + mov ecx,3 ; Case 3 of switch JDSimu_0040194C + xor edx,edx + + JDSimu_00401984: + mov esi,dword ptr ss:[esp+0x28] ; esi <== size_ + test esi,esi + jle CASE_0 + add eax,edx + sub ecx,edx + + JDSimu_00401994: + mov bl,byte ptr ds:[eax] + mov dl,byte ptr ds:[ecx+eax] + mov byte ptr ds:[ecx+eax],bl + mov byte ptr ds:[eax],dl + add eax,4 + dec esi + jnz short JDSimu_00401994 + pop edi + pop esi + pop ebp + mov eax,1 + pop ebx + retn + + CASE_4: + mov cx,word ptr ds:[edi+0x42] ; Case 4 of switch JDSimu_004018F2 + test cx,cx + jl short CASE_DEFAULT + cmp cx,7 + jg short CASE_DEFAULT + xor esi,esi + test ebp,ebp + jle short CASE_0 + + JDSimu_004019C3: + movsx ebx,word ptr ds:[edi+0x42] + mov dl,byte ptr ds:[esi+eax] + mov ecx,8 + sub ecx,ebx + mov bl,dl + shl bl,cl + mov cl,byte ptr ds:[edi+0x42] + shr dl,cl + or bl,dl + mov byte ptr ds:[esi+eax],bl + inc esi + cmp esi,ebp + jl short JDSimu_004019C3 + pop edi + pop esi + pop ebp + mov eax,1 + pop ebx + retn + + CASE_5678: + shr ebp,1 ; Cases 5,6,7,8 of switch JDSimu_004018F2 + mov ecx,ebp + test ecx,ecx + jle short CASE_0 + + JDSimu_004019F6: + mov dx,word ptr ds:[edi+0x42] + xor word ptr ds:[eax],dx + add eax,2 + dec ecx + jnz short JDSimu_004019F6 + pop edi + pop esi + pop ebp + mov eax,1 + pop ebx + retn + + CASE_9: + xor ecx,ecx ; Case 9 of switch JDSimu_004018F2 + test ebp,ebp + jle short CASE_0 + + JDSimu_00401A13: + mov bl,byte ptr ds:[ecx+eax] + xor bl,dl + mov byte ptr ds:[ecx+eax],bl + inc ecx + cmp ecx,ebp + jl short JDSimu_00401A13 + + CASE_0: + pop edi ; Case 0 of switch JDSimu_004018F2 + pop esi + pop ebp + mov eax,1 + pop ebx + retn + + CASE_DEFAULT: + pop edi ; Default case of switch JDSimu_0040194C + pop esi + pop ebp + xor eax,eax + pop ebx + retn + } +} + +__declspec(naked) BOOL ReadSection( + BYTE* /* pSection */, + DWORD* /* pOffset */, + JD_PATH_INFO_05* /* pInfo */, + DWORD /* code */, + void* /* pBuffer */) +{ + __asm { + mov eax,dword ptr ss:[esp+8] + push ebp + mov ebp,dword ptr ss:[esp+8] + push esi + mov ecx,dword ptr ds:[eax] + mov esi,dword ptr ss:[esp+0x1C] + add ecx,ebp + mov ebp,dword ptr ss:[esp+0x14] + push edi + mov edx,dword ptr ds:[ecx] + mov dword ptr ds:[esi],edx + mov edi,dword ptr ds:[eax] + add edi,4 + mov dword ptr ds:[eax],edi + mov cl,byte ptr ss:[ebp+0x42] + movsx eax,word ptr ss:[ebp+0x40] + + cmp eax,0 ; Switch (cases 0..4) + je CASE_03 + cmp eax,1 + je CASE_1 + cmp eax,2 + je CASE_2 + cmp eax,3 + je CASE_03 + cmp eax,4 + je CASE_4 + jmp CASE_DEFAULT + + CASE_1: + xor eax,eax ; Case 1 of switch 00401A99 + + JDSimu_00401AA7: + mov dl,byte ptr ds:[eax+esi] + xor dl,cl + mov byte ptr ds:[eax+esi],dl + inc eax + cmp eax,4 + jl short JDSimu_00401AA7 + pop edi + pop esi + mov eax,1 + pop ebp + retn + + CASE_2: + mov cl,byte ptr ss:[esp+0x1C] ; Case 2 of switch 00401A99 + xor eax,eax + + JDSimu_00401AC4: + mov dl,byte ptr ds:[eax+esi] + xor dl,cl + mov byte ptr ds:[eax+esi],dl + inc eax + cmp eax,4 + jl short JDSimu_00401AC4 + + CASE_4: + mov ax,word ptr ss:[ebp+0x42] ; Case 4 of switch 00401A99 + test ax,ax + jl short CASE_DEFAULT + cmp ax,7 + jg short CASE_DEFAULT + xor edi,edi + + JDSimu_00401AE3: + movsx edx,word ptr ss:[ebp+0x42] + mov al,byte ptr ds:[edi+esi] + mov ecx,8 + sub ecx,edx + mov dl,al + shl dl,cl + mov cl,byte ptr ss:[ebp+0x42] + shr al,cl + or dl,al + mov byte ptr ds:[edi+esi],dl + inc edi + cmp edi,4 + jl short JDSimu_00401AE3 + + CASE_03: + pop edi ; Cases 0,3 of switch 00401A99 + pop esi + mov eax,1 + pop ebp + retn + + CASE_DEFAULT: + pop edi ; Default case of switch 00401A99 + pop esi + xor eax,eax + pop ebp + retn + } +} + +void CorrectTables() +{ + static bool _s_bCorrected = false; + if (_s_bCorrected) + return; + + _s_bCorrected = true; + + /////////////////////////////// + // begin to correct tables ... + + int _i; + + // DWORD s_nDATA00419268[] = + for (_i = 0; _i < _countof(s_nDATA00419268); ++_i) + { + s_nDATA00419268[_i] ^= 0x55; + } + + // DWORD s_nDATA00419668[] = + for (_i = 0; _i < _countof(s_nDATA00419668); ++_i) + { + s_nDATA00419668[_i] ^= 0x55; + } + + // DWORD s_nDATA00418168[] = + for (_i = 0; _i < _countof(s_nDATA00418168); ++_i) + { + s_nDATA00418168[_i] ^= 0x555555; + } + + // DWORD s_nDATA00419168[] = + for (_i = 0; _i < _countof(s_nDATA00419168); ++_i) + { + s_nDATA00419168[_i] ^= 0x55555555; + } + + // DWORD s_nDATA004197E8[] = + // nothing need to do. + + // DWORD s_nDATA004198E8[] = + for (_i = 0; _i < _countof(s_nDATA004198E8); ++_i) + { + s_nDATA004198E8[_i] -= 0x00000068; + } + + return; +} diff --git a/src/DefaultMenu.cpp b/src/DefaultMenu.cpp new file mode 100644 index 0000000..945f218 --- /dev/null +++ b/src/DefaultMenu.cpp @@ -0,0 +1,1441 @@ +// ************************************************************************** // +// DefaultMenu.cpp : implementation of the CDefaultMenu class +// Copyright(c)2010 Naiky Company. All rights reserved. +// +// Abstract: +// 本文件实现CDefaultMenu类。 +// ********************************************* ---- 杨开锦 2010-06-07 ***** // +#include "stdafx.h" +#include "DefaultMenu.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// 文件 ---- 杨开锦 2010-06-07 +CS_T s_szMENU_FILE = _DEFCS(_CSV(15200), + _CHINESE("文件(&F)") + _ENGLISH("&File")); +CS_T s_szMENU_FILE_NEW = _DEFCS(_CSV(15201), + _CHINESE("新建(&N)\tCtrl+N") + _ENGLISH("&New\tCtrl+N")); +CS_T s_szMENU_FILE_OPEN = _DEFCS(_CSV(15202), + _CHINESE("打开(&O)...\tCtrl+O") + _ENGLISH("&Open...\tCtrl+O")); +CS_T s_szMENU_FILE_IMPORT = _DEFCS(_CSV(15203), + _CHINESE("导入文件(&I)...\tCtrl+I") + _ENGLISH("&Import File...\tCtrl+I")); +CS_T s_szMENU_FILE_EXPORT = _DEFCS(_CSV(15204), + _CHINESE("导出文件") + _ENGLISH("Export File")); +CS_T s_csEXPORTFEEDBACK = _DEFCS(_CSV(15532), + _CHINESE("导出反馈数据") + _ENGLISH("Export Feedback Pulse")); +CS_T s_csEXPORTSEND = _DEFCS(_CSV(15542), + _CHINESE("导出发送数据") + _ENGLISH("Export Send Pulse")); +CS_T s_szMENU_FILE_INSERT = _DEFCS(_CSV(15205), + _CHINESE("插入文件...") + _ENGLISH("Insert File...")); +CS_T s_szMENU_OBJECT_NEST = _DEFCS(_CSV(15486), + _CHINESE("排版") + _ENGLISH("Nest")); +CS_T s_szMENU_FILE_SAVE = _DEFCS(_CSV(15206), + _CHINESE("保存(&S)\tCtrl+S") + _ENGLISH("&Save\tCtrl+S")); +CS_T s_szMENU_FILE_SAVE_AS = _DEFCS(_CSV(15207), + _CHINESE("另存为(&A)...") + _ENGLISH("Save &As...")); +CS_T s_szMENU_FILE_SAVE_SELECTED_AS = _DEFCS(_CSV(15208), + _CHINESE("保存选中图形...") + _ENGLISH("Save Selected Objects As...")); +CS_T s_szMENU_FILE_RECENTFILES_NCE = _DEFCS(_CSV(15209), + _CHINESE("最近打开的NCE文件") + _ENGLISH("Recent Nce Files")); +CS_T s_szMENU_FILE_RECENTFILES_NONE = _DEFCS(_CSV(15210), + _CHINESE("空") + _ENGLISH("None")); +CS_T s_szMENU_APPEXIT_RESTARTSOFTWARE = _DEFCS(_CSV(15509), + _CHINESE("重启软件") + _ENGLISH("Restart Software")); +CS_T s_szMENU_APPEXIT_SHUTDOWNSYSTEM = _DEFCS(_CSV(15510), + _CHINESE("关闭系统") + _ENGLISH("Shutdown System")); +CS_T s_szMENU_APPEXIT_REBOOTSYSTEM = _DEFCS(_CSV(15511), + _CHINESE("重启系统") + _ENGLISH("Reboot System")); +CS_T s_szMENU_APPEXIT_SHOWDESKTOP= _DEFCS(_CSV(15512), + _CHINESE("显示桌面") + _ENGLISH("Show Desktop")); +CS_T s_szMENU_FILE_EXIT = _DEFCS(_CSV(15212), + _CHINESE("退出") + _ENGLISH("Exit")); + +// 编辑 ---- 杨开锦 2010-06-07 +CS_T s_szMENU_EDIT = _DEFCS(_CSV(15213), + _CHINESE("编辑(&E)") + _ENGLISH("&Edit")); +CS_T s_szMENU_EDIT_UNDO = _DEFCS(_CSV(15214), + _CHINESE("撤销(&U)\tCtrl+Z") + _ENGLISH("&Undo\tCtrl+Z")); +CS_T s_szMENU_EDIT_REDO = _DEFCS(_CSV(15215), + _CHINESE("重做(&R)\tCtrl+Y") + _ENGLISH("&Redo\tCtrl+Y")); +CS_T s_szMENU_EDIT_SELECT_ALL = _DEFCS(_CSV(15216), + _CHINESE("全选(&A)\tCtrl+A") + _ENGLISH("Select &All\tCtrl+A")); +CS_T s_szMENU_EDIT_SELECT_REV = _DEFCS(_CSV(15217), + _CHINESE("反选(&V)\tCtrl+Shift+A") + _ENGLISH("Select In&vert\tCtrl+Shift+A")); +CS_T s_szMENU_EDIT_CLEAR_SELECT = _DEFCS(_CSV(15218), + _CHINESE("取消选择\tShift+A") + _ENGLISH("Clear Selected\tShift+A")); +CS_T s_szMENU_EDIT_SELECT_UNCLOSE = _DEFCS(_CSV(15218), + _CHINESE("选择不封闭图形") + _ENGLISH("Select Unclose")); +CS_T s_szMENU_EDIT_SELECT_TINY = _DEFCS(_CSV(15218), + _CHINESE("选择小图形") + _ENGLISH("Select Tiny")); +CS_T s_szMENU_EDIT_SELECT_BYCOLOR = _DEFCS(_CSV(15218), + _CHINESE("按图层选择") + _ENGLISH("Select By Layer")); +CS_T s_szMENU_EDIT_SELECT_BYTYPE = _DEFCS(_CSV(15218), + _CHINESE("按类型选择") + _ENGLISH("Select By Type")); +CS_T s_szMENU_EDIT_SELECT_BYINOUT = _DEFCS(_CSV(15218), + _CHINESE("按嵌套关系选择") + _ENGLISH("Select By Inner-Outer")); +CS_T s_szMENU_EDIT_SELECT_BYINOUT_IN = _DEFCS(_CSV(15218), + _CHINESE("里层图形") + _ENGLISH("Inner")); +CS_T s_szMENU_EDIT_SELECT_BYINOUT_OUT = _DEFCS(_CSV(15218), + _CHINESE("外层图形") + _ENGLISH("Outer")); +CS_T s_szMENU_EDIT_SELECT_SIMILAR = _DEFCS(_CSV(15539), + _CHINESE("选择相似图形") + _ENGLISH("Select Similar")); +CS_T s_szMENU_EDIT_DELETE = _DEFCS(_CSV(15219), + _CHINESE("删除(&D)\tDelete") + _ENGLISH("&Delete\tDelete")); +CS_T s_szMENU_EDIT_CUT = _DEFCS(_CSV(15220), + _CHINESE("剪切(&T)\tCtrl+X") + _ENGLISH("Cu&t\tCtrl+X")); +CS_T s_szMENU_EDIT_COPY = _DEFCS(_CSV(15221), + _CHINESE("复制(&C)\tCtrl+C") + _ENGLISH("&Copy\tCtrl+C")); +CS_T s_szMENU_EDIT_PASTE = _DEFCS(_CSV(15222), + _CHINESE("粘贴(&P)\tCtrl+V") + _ENGLISH("&Paste\tCtrl+V")); +CS_T s_szMENU_EDIT_PASTE_AS_GROUP = _DEFCS(_CSV(15223), + _CHINESE("粘贴为组") + _ENGLISH("Paste as Group")); +CS_T s_szMENU_EDIT_CLEAR_CLIPBOARD = _DEFCS(_CSV(15224), + _CHINESE("清除剪贴板") + _ENGLISH("Clear Clipboard")); + +// 选择 ---- 吴畏 2017-02-13 +CS_T s_szMENU_CHOOSE = _DEFCS(_CSV(15224), + _CHINESE("选择(&C)") + _ENGLISH("&Choose")); + +// 视图 ---- 杨开锦 2010-06-07 +CS_T s_szMENU_VIEW = _DEFCS(_CSV(15225), + _CHINESE("视图(&V)") + _ENGLISH("&View")); +CS_T s_szMENU_VIEW_VIEWPORT_TRANSLATE = _DEFCS(_CSV(15226), + _CHINESE("视图平移(&P)") + _ENGLISH("&Pan")); +CS_T s_szMENU_VIEW_VIEWPORT_ZOOM_BYDRAG = _DEFCS(_CSV(15227), + _CHINESE("实时缩放(&Z)") + _ENGLISH("&Zoom")); +CS_T s_szMENU_VIEW_VIEWPORT_ZOOM_BYRECT = _DEFCS(_CSV(15228), + _CHINESE("窗选放大") + _ENGLISH("Zoom by Rect")); +CS_T s_szMENU_VIEW_VIEWPORT_FITTOWINDOW = _DEFCS(_CSV(15229), + _CHINESE("调整至最适大小\tNum*") + _ENGLISH("Fit to Window\tNum*")); +CS_T s_szMENU_VIEW_SHOW_ORDER = _DEFCS(_CSV(15230), + _CHINESE("显示次序(&O)") + _ENGLISH("Show &Order")); +CS_T s_szMENU_VIEW_SHOW_STARTPOINT = _DEFCS(_CSV(15231), + _CHINESE("显示起点(&S)") + _ENGLISH("Show &Start Point")); +CS_T s_szMENU_VIEW_SHOW_DIRECTION = _DEFCS(_CSV(15232), + _CHINESE("显示方向(&D)") + _ENGLISH("Show &Direction")); +CS_T s_szMENU_VIEW_SHOW_INTRODUCE = _DEFCS(_CSV(15233), + _CHINESE("显示引刀线(&L)") + _ENGLISH("Show &Lead-in/out Line")); +CS_T s_szMENU_VIEW_SHOW_TRACEPATH = _DEFCS(_CSV(15234), + _CHINESE("轨迹显示(&T)") + _ENGLISH("&Track")); +CS_T s_szMENU_VIEW_SHOW_MACHINGPATH = _DEFCS(_CSV(15522), + _CHINESE("显示加工轨迹(&M)") + _ENGLISH("Show &Maching Track")); +CS_T s_szMENU_VIEW_SHOW_FEEDBACKPATH = _DEFCS(_CSV(15523), + _CHINESE("显示反馈轨迹(&F)") + _ENGLISH("Show &Feedback Track")); +CS_T s_szMENU_VIEW_SHOW_NOPATH = _DEFCS(_CSV(15524), + _CHINESE("不显示轨迹") + _ENGLISH("Hide Track")); +CS_T s_szMENU_VIEW_SHOW_TRACEPOINT = _DEFCS(_CSV(15235), + _CHINESE("显示当前点(&C)") + _ENGLISH("Show &Current Point")); +CS_T s_szMENU_VIEW_MIDDLE_TRACEPOINT = _DEFCS(_CSV(15236), + _CHINESE("居中当前点\tEnd") + _ENGLISH("Middle Current Point\tEnd")); +CS_T s_szMENU_VIEW_CLEAR_TRACEPATH = _DEFCS(_CSV(15237), + _CHINESE("清除轨迹\tF12") + _ENGLISH("Clear Track\tF12")); +CS_T s_szMENU_VIEW_WIREFRAMEMODE = _DEFCS(_CSV(15239), + _CHINESE("线框模式") + _ENGLISH("Wireframe Mode")); +CS_T s_szMENE_VIEW_FILLMODE = _DEFCS(_CSV(15238), + _CHINESE("填充模式") + _ENGLISH("Fill Mode")); +CS_T s_szMENE_VIEW_DYNFILLMODE = _DEFCS(_CSV(15238), + _CHINESE("同步填充模式") + _ENGLISH("Dynamic Fill Mode")); + +// 绘图 ---- 杨开锦 2010-06-11 +CS_T s_szMENU_DRAW = _DEFCS(_CSV(15241), + _CHINESE("绘图(&D)") + _ENGLISH("&Draw")); +CS_T s_szMENU_DRAW_DOT = _DEFCS(_CSV(15242), + _CHINESE("点(&D)") + _ENGLISH("&Dot")); +CS_T s_szMENU_DRAW_LINE = _DEFCS(_CSV(15243), + _CHINESE("线段(&L)") + _ENGLISH("&Line")); +CS_T s_szMENU_DRAW_BEELINE = _DEFCS(_CSV(15244), + _CHINESE("直线(&B)") + _ENGLISH("&Beeline")); +CS_T s_szMENU_DRAW_POLYLINE = _DEFCS(_CSV(15245), + _CHINESE("多义线(&P)") + _ENGLISH("&Polyline")); +CS_T s_szMENU_DRAW_CIRCLE = _DEFCS(_CSV(15246), + _CHINESE("圆(&C)") + _ENGLISH("&Circle")); +CS_T s_szMENU_DRAW_ARC = _DEFCS(_CSV(15247), + _CHINESE("圆弧(&A)") + _ENGLISH("&Arc")); +CS_T s_szMENU_DRAW_ELLIPSE = _DEFCS(_CSV(15248), + _CHINESE("椭圆(&E)") + _ENGLISH("&Ellipse")); +CS_T s_szMENU_DRAW_ELLIPSEARC = _DEFCS(_CSV(15249), + _CHINESE("椭圆弧(&I)") + _ENGLISH("Ell&ipseArc")); +CS_T s_szMENU_DRAW_RECTANGLE = _DEFCS(_CSV(15250), + _CHINESE("矩形(&R)") + _ENGLISH("&Rectangle")); +CS_T s_szMENU_DRAW_POLYGON = _DEFCS(_CSV(15251), + _CHINESE("正多边形(&Y)") + _ENGLISH("Pol&ygon")); +CS_T s_szMENU_DRAW_STAR = _DEFCS(_CSV(15252), + _CHINESE("星形(&S)") + _ENGLISH("&Star")); +CS_T s_szMENU_DRAW_TEXT = _DEFCS(_CSV(15253), + _CHINESE("文字(&T)") + _ENGLISH("&Text")); +CS_T s_szMENU_CIRCLECUTTIPS = _DEFCS(_CSV(15323), + _CHINESE("圆管切割") + _ENGLISH("Pipe Cutting")); +CS_T s_szMENU_TUBEGUIDE = _DEFCS(_CSV(15323), + _CHINESE("管材切割向导(&U)") + _ENGLISH("Pipe C&utting Guide")); +CS_T s_csTEACHINGCODE = _DEFCS(_CSV(15324), + _CHINESE("视教编程(&H)") + _ENGLISH("Teac&hing")); +CS_T s_szMENU_DRAW_GALLERY = _DEFCS(_CSV(15322), + _CHINESE("图库(&G)\tCtrl+G") + _ENGLISH("&Gallery\tCtrl+G")); +CS_T s_szMENU_OBJECT_CATCH = _DEFCS(_CSV(15294), + _CHINESE("捕捉") + _ENGLISH("Catch")); +CS_T s_szMENU_OBJECT_CATCH_OPTION = _DEFCS(_CSV(15295), + _CHINESE("捕捉选项") + _ENGLISH("Catch Options")); +CS_T s_szMENU_OBJECT_CATCH_POLARAXISINCANGLE = _DEFCS(_CSV(15296), + _CHINESE("极轴增量角<...>") + _ENGLISH("Polar IncAngle<...>")); + +// 套料 ---- 吴畏 2017-02-13 +CS_T s_szMENU_NEST = _DEFCS(_CSV(15296), + _CHINESE("套料(&N)") + _ENGLISH("&Nest")); + +// 对象 Wanglou 2010-06-09 +CS_T s_szMENU_OBJECT = _DEFCS(_CSV(15257), + _CHINESE("对象(&O)") + _ENGLISH("&Object")); +CS_T s_szMENU_HOME = _DEFCS(_CSV(15257), + _CHINESE("常用(&H)") + _ENGLISH("&Home")); +CS_T s_szMENU_OBJECT_TRANSLATE = _DEFCS(_CSV(15258), + _CHINESE("平移") + _ENGLISH("Translate")); +CS_T s_szMENU_OBJECT_ROTATE = _DEFCS(_CSV(15259), + _CHINESE("旋转") + _ENGLISH("Rotate")); +CS_T s_szMENU_OBJECT_SCALE = _DEFCS(_CSV(15259), + _CHINESE("缩放") + _ENGLISH("Scale")); +CS_T s_szMENU_OBJECT_ALIGN = _DEFCS(_CSV(15260), + _CHINESE("对齐(&A)") + _ENGLISH("&Align")); +CS_T s_szMENU_OBJECT_ALIGN_LEFT = _DEFCS(_CSV(15261), + _CHINESE("左边对齐(&L)") + _ENGLISH("Align &Left")); +CS_T s_szMENU_OBJECT_ALIGN_RIGHT = _DEFCS(_CSV(15262), + _CHINESE("右边对齐(&R)") + _ENGLISH("Align &Right")); +CS_T s_szMENU_OBJECT_ALIGN_TOP = _DEFCS(_CSV(15263), + _CHINESE("顶边对齐(&T)") + _ENGLISH("Align &Top")); +CS_T s_szMENU_OBJECT_ALIGN_BOTTOM = _DEFCS(_CSV(15264), + _CHINESE("底边对齐(&B)") + _ENGLISH("Align &Bottom")); +CS_T s_szMENU_OBJECT_ALIGN_CENTERPT = _DEFCS(_CSV(15265), + _CHINESE("中心点对齐(&C)") + _ENGLISH("Align &Center Point")); +CS_T S_SZMENU_OBJECT_ALIGN_MIDLINE_H = _DEFCS(_CSV(15266), + _CHINESE("水平中线对齐(&H)") + _ENGLISH("Align &Horizontal Midline")); +CS_T s_szMENU_OBJECT_ALIGN_MIDLINE_V = _DEFCS(_CSV(15267), + _CHINESE("垂直中线对齐(&V)") + _ENGLISH("Align &Vertical Midline")); +CS_T S_SZMENU_OBJECT_ALIGN_DECENTRAL_H = _DEFCS(_CSV(15268), + _CHINESE("水平分散对齐") + _ENGLISH("Distribute Horizontally")); +CS_T S_SZMENU_OBJECT_ALIGN_DECENTRAL_V = _DEFCS(_CSV(15269), + _CHINESE("垂直分散对齐") + _ENGLISH("Distribute Vertically")); +CS_T s_szMENU_OBJECT_GROUPANDBREAK = _DEFCS(_CSV(15558), + _CHINESE("组合/解散") + _ENGLISH("Group/Break")); +CS_T s_szMENU_OBJECT_GROUP = _DEFCS(_CSV(15270), + _CHINESE("组合") + _ENGLISH("Group")); +CS_T s_szMENU_OBJECT_BREAKGROUP = _DEFCS(_CSV(15271), + _CHINESE("解散组合") + _ENGLISH("Break Group")); +CS_T s_szMENU_OBJECT_COMBINE = _DEFCS(_CSV(15272), + _CHINESE("合并\tCtrl+J") + _ENGLISH("Combine\tCtrl+J")); +CS_T s_szMENU_OBJECT_EXPLODE = _DEFCS(_CSV(15272), + _CHINESE("炸开") + _ENGLISH("Explode")); +CS_T s_szMENU_OBJECT_BREAK = _DEFCS(_CSV(15419), + _CHINESE("打断") + _ENGLISH("Break")); +CS_T s_szMENU_OBJECT_MEASURE = _DEFCS(_CSV(15279), + _CHINESE("测量距离") + _ENGLISH("Measure")); +CS_T s_szMUNU_OBJECT_CADCHECK = _DEFCS(_CSV(15278), + _CHINESE("图形检测\tCtrl+T") + _ENGLISH("Shape Check\tCtrl+T")); +CS_T s_szMENU_OBJECT_PREPROCESSING = _DEFCS(_CSV(15280), + _CHINESE("图形预处理") + _ENGLISH("Shape Pre-process")); +CS_T s_szMENU_OBJECT_INSTANTPREPROCESSING = _DEFCS(_CSV(15559), + _CHINESE("一键预处理") + _ENGLISH("Instant Pre-process")); +CS_T s_szMENU_OBJECT_CLIPOVERLAP = _DEFCS(_CSV(15281), + _CHINESE("删除重复边") + _ENGLISH("Clip Overlaps")); +CS_T s_szMENU_OBJECT_DELETESHORTIES = _DEFCS(_CSV(15282), + _CHINESE("删除小图形") + _ENGLISH("Delete Shorties")); +CS_T s_szMENU_OBJECT_CURVESMOOTHER = _DEFCS(_CSV(15283), + _CHINESE("曲线光滑") + _ENGLISH("Smooth Curve")); +CS_T s_szMENU_OBJECT_TRANSLATETEXT = _DEFCS(_CSV(15286), + _CHINESE("文字转换成图形") + _ENGLISH("Translate Text to Polylines")); +CS_T s_szMENU_OBJECT_SPECIALTECH = _DEFCS(_CSV(15567), + _CHINESE("特殊工艺") + _ENGLISH("Special Technics")); +CS_T s_szMENU_OBJECT_STOPCORNER = _DEFCS(_CSV(15539), + _CHINESE("冷却点") + _ENGLISH("Cooling Point")); +CS_T s_szRELEASEANGLE = _DEFCS(_CSV(15528), + _CHINESE("释放角") + _ENGLISH("Release Angle")); +CS_T s_szMENU_OBJECT_CHAMFER = _DEFCS(_CSV(15529), + _CHINESE("倒角") + _ENGLISH("Chamfer")); +CS_T s_szMENU_OBJECT_ADDBRIDGE = _DEFCS(_CSV(15419), + _CHINESE("桥接") + _ENGLISH("Add Bridge")); +CS_T s_szMENU_OBJECT_MICROJOINT = _DEFCS(_CSV(15272), + _CHINESE("微连") + _ENGLISH("Micro Joint")); +CS_T s_szMENU_OBJECT_SETMICROJOINT = _DEFCS(_CSV(15272), + _CHINESE("微连设置") + _ENGLISH("Set Micro Joint")); +CS_T s_szMENU_OBJECT_EXPLODEMICROJOINT = _DEFCS(_CSV(15272), + _CHINESE("炸开微连") + _ENGLISH("Explode MicroJoin")); +CS_T s_szMENU_OBJECT_SCAN = _DEFCS(_CSV(15518), + _CHINESE("扫描") + _ENGLISH("Scan")); +CS_T s_szMENU_OBJECT_LINESCAN = _DEFCS(_CSV(15519), + _CHINESE("直线连接扫描") + _ENGLISH("Line Scan")); +CS_T s_szMENU_OBJECT_ARCSCAN = _DEFCS(_CSV(15520), + _CHINESE("圆弧连接扫描") + _ENGLISH("Arc Scan")); +CS_T s_szMENU_OBJECT_SCANLOT = _DEFCS(_CSV(15520), + _CHINESE("广告字LED扫描") + _ENGLISH("Scan LED On Text")); +CS_T s_szMENU_OBJECT_UNFILLANDFILL = _DEFCS(_CSV(15254), + _CHINESE("阴/阳切") + _ENGLISH("Unfill/Fill")); +CS_T s_szMENU_OBJECT_FILL = _DEFCS(_CSV(15288), + _CHINESE("阳切") + _ENGLISH("Fill")); +CS_T s_szMENU_OBJECT_UNFILL = _DEFCS(_CSV(15289), + _CHINESE("阴切") + _ENGLISH("Unfill")); +CS_T s_szMENU_OBJECT_AUTOSETFILL = _DEFCS(_CSV(15290), + _CHINESE("自动设置阴阳切") + _ENGLISH("Auto Set Fill")); +CS_T s_szMUNU_OBJECT_ORDER = _DEFCS(_CSV(15273), + _CHINESE("加工顺序") + _ENGLISH("Mach Order")); +CS_T s_szMENU_OBJECT_AUTOSETORDER = _DEFCS(_CSV(15274), + _CHINESE("自动设置加工顺序(&A)\tCtrl+E") + _ENGLISH("&Auto Set Mach Order\tCtrl+E")); +CS_T s_szMENU_OBJECT_MANUALSETORDER = _DEFCS(_CSV(15275), + _CHINESE("手动设置加工顺序(&M)") + _ENGLISH("&Manual Set Mach Order")); +CS_T s_szMENU_OBJECT_MANUALSPECIFYORDER = _DEFCS(_CSV(15276), + _CHINESE("指定单独工件加工顺序(&S)") + _ENGLISH("&Specify Single Mach Order")); +CS_T s_szMUNU_OBJECT_ORDER_LIST = _DEFCS(_CSV(15277), + _CHINESE("加工顺序列表(&L)") + _ENGLISH("Mach Order &List")); +CS_T s_szMENU_OBJECT_MACHDIRECTION = _DEFCS(_CSV(15255), + _CHINESE("加工方向") + _ENGLISH("Mach Direction")); +CS_T s_szMENU_OBJECT_REVERSEDIRECTION = _DEFCS(_CSV(15284), + _CHINESE("改变加工方向") + _ENGLISH("Reverse Direction")); +CS_T s_szMENU_OBJECT_SETDIRECTION = _DEFCS(_CSV(15285), + _CHINESE("设置加工方向\tCtrl+D") + _ENGLISH("Set Direction\tCtrl+D")); +CS_T s_szMENU_OBJECT_LEADLINE = _DEFCS(_CSV(15353), + _CHINESE("引刀线") + _ENGLISH("Lead Line")); +CS_T s_szMENU_OBJECT_INTROSTART = _DEFCS(_CSV(15287), + _CHINESE("引刀线起点\tCtrl+Q") + _ENGLISH("Start Cut Point\tCtrl+Q")); +CS_T s_szMENU_OBJECT_INTRODUCE = _DEFCS(_CSV(15291), + _CHINESE("设置引刀线\tCtrl+W") + _ENGLISH("Set Lead-in/out Line\tCtrl+W")); +CS_T s_szMENU_OBJECT_INTERSECTINGLINE = _DEFCS(_CSV(15292), + _CHINESE("设置相贯线") + _ENGLISH("Set Intersecting Line")); +CS_T s_szMENU_OBJECT_SETCRC = _DEFCS(_CSV(15293), + _CHINESE("设置割缝补偿\tCtrl+R") + _ENGLISH("Set Kerf Compensation\tCtrl+R")); +CS_T s_szINSTANTSETTING = _DEFCS(_CSV(15256), + _CHINESE("一键设置\tCtrl+1") + _ENGLISH("Instant Setting\tCtrl+1")); +CS_T s_szMENU_OBJECT_PARAMGROUPSETTING = _DEFCS(_CSV(15489), + _CHINESE("图层设置\tCtrl+2") + _ENGLISH("Layer Setting")); +CS_T s_szMENU_OBJECT_CLEAR = _DEFCS(_CSV(15547), + _CHINESE("清除") + _ENGLISH("Clear")); +CS_T s_szMENU_OBJECT_CLEARINTRO = _DEFCS(_CSV(15528), + _CHINESE("清除引刀线") + _ENGLISH("Clear Lead-in/out Line")); +CS_T s_szMENU_OBJECT_CLEARCRC = _DEFCS(_CSV(15548), + _CHINESE("清除割缝补偿") + _ENGLISH("Clear Kerf Comp")); +CS_T s_szMENU_OBJECT_CLEARSTOPCORNER = _DEFCS(_CSV(15539), + _CHINESE("清除冷却点") + _ENGLISH("Clear Cooling Point")); +CS_T s_szMENU_OBJECT_CLEARMICROJOINT = _DEFCS(_CSV(15272), + _CHINESE("清除微连") + _ENGLISH("Clear Micro Joint")); +CS_T s_szMENU_OBJECT_CLEARCHAMFER = _DEFCS(_CSV(15548), + _CHINESE("清除倒角") + _ENGLISH("Clear Chamfer")); +CS_T s_szMENU_OBJECT_CLEARRELEASEANGLE = _DEFCS(_CSV(15557), + _CHINESE("清除释放角") + _ENGLISH("Clear Release Angle")); +CS_T s_szMENU_OBJECT_CLEARCHOP = _DEFCS(_CSV(15573), + _CHINESE("清除切碎") + _ENGLISH("Clear Chop")); +CS_T s_szMENU_OBJECT_CHOP = _DEFCS(_CSV(15557), + _CHINESE("切碎") + _ENGLISH("Chop")); +CS_T s_szMENU_OBJECT_TUBELOCATION = _DEFCS(_CSV(15498), + _CHINESE("图形定位") + _ENGLISH("Location")); + +// 加工 ---- 边俊霞 2016-6-8 +CS_T s_szMENU_MACH = _DEFCS(_CSV(15298), + _CHINESE("加工(&M)") + _ENGLISH("&Mach")); +CS_T s_szMENU_MACH_STATISTICS = _DEFCS(_CSV(15302), + _CHINESE("统计信息(&S)") + _ENGLISH("Show &Statistics")); +CS_T s_csCRCRUN = _DEFCS(_CSV(15320), + _CHINESE("循环加工") + _ENGLISH("Cyclical Machining")); +CS_T s_csBKREF = _DEFCS(_CSV(15305), + _CHINESE("回机械原点(&H)") + _ENGLISH("Go &Home")); +CS_T s_csBKALL = _DEFCS(_CSV(15306), + _CHINESE("全部回\tCtrl+Home") + _ENGLISH("All Go Home\tCtrl+Home")); +CS_T s_csDIRECTSET = _DEFCS(_CSV(15312), + _CHINESE("直接设定") + _ENGLISH("Set Directly")); +CS_T s_csBKX = _DEFCS(_CSV(15307), + _CHINESE("X轴回") + _ENGLISH("X Go Home")); +CS_T s_csBKY = _DEFCS(_CSV(15308), + _CHINESE("Y轴回") + _ENGLISH("Y Go Home")); +CS_T s_csBKZ = _DEFCS(_CSV(15513), + _CHINESE("Z轴回") + _ENGLISH("Z Go Home")); +CS_T s_csBKW = _DEFCS(_CSV(15513), + _CHINESE("W轴回") + _ENGLISH("W Go Home")); +CS_T s_csBKWFFOCUS = _DEFCS(_CSV(15513), + _CHINESE("W轴回") + _ENGLISH("W Go Home")); +CS_T s_csBKDLG = _DEFCS(_CSV(15309), + _CHINESE("回机械原点设置") + _ENGLISH("Go Home Setting")); +CS_T s_csDETECT2YERROR = _DEFCS(_CSV(15304), + _CHINESE("双Y原点检测") + _ENGLISH("Detect 2Y Origin")); +CS_T s_csMOVETOWORKORIGIN = _DEFCS(_CSV(15310), + _CHINESE("回工件原点(&W)\tF6") + _ENGLISH("Work Origin\tF6")); +CS_T s_csMOVETOFIXEDPOS = _DEFCS(_CSV(15311), + _CHINESE("回固定点(&F)") + _ENGLISH("BackTo&FixedPoint")); +CS_T s_csMACHCONTROL = _DEFCS(_CSV(15502), + _CHINESE("加工控制") + _ENGLISH("Mach Control")); +CS_T s_csSTART = _DEFCS(_CSV(15521), + _CHINESE("开始\tF9") + _ENGLISH("Start\tF9")); +CS_T s_csPAUSE = _DEFCS(_CSV(15561), + _CHINESE("暂停\tF10") + _ENGLISH("Pause\tF10")); +CS_T s_csSTOP = _DEFCS(_CSV(15562), + _CHINESE("停止\tF11") + _ENGLISH("Stop\tF11")); +CS_T s_csRESUME = _DEFCS(_CSV(15563), + _CHINESE("断点继续\tShift+F9") + _ENGLISH("Breakpoint Resume\tShift+F9")); +CS_T s_csSIMU = _DEFCS(_CSV(15564), + _CHINESE("仿真\tF8") + _ENGLISH("Simulate\tF8")); +CS_T s_csDIRRUN = _DEFCS(_CSV(15565), + _CHINESE("空运行") + _ENGLISH("Dry Run")); +CS_T s_csSIMUCUTBOUNDRECT = _DEFCS(_CSV(15566), + _CHINESE("走边框\tF7") + _ENGLISH("Frame\tF7")); +CS_T s_csMARKPOSITION = _DEFCS(_CSV(15525), + _CHINESE("标记点") + _ENGLISH("Mark Position")); +CS_T s_csMARKTHISPOSITION = _DEFCS(_CSV(15526), + _CHINESE("标记坐标") + _ENGLISH("Mark Current Position")); +CS_T s_csMOVETOMARKPOSITION = _DEFCS(_CSV(15527), + _CHINESE("回标记点") + _ENGLISH("BackToMarkPosition")); +CS_T s_szMENU_VIEW_SETORIGINPOSITION = _DEFCS(_CSV(15240), + _CHINESE("设置原点方位") + _ENGLISH("Set Origin Position")); +CS_T s_csSetWorkOrigin = _DEFCS(_CSV(15514), + _CHINESE("设置工件原点") + _ENGLISH("Set WorkOrg")); +CS_T s_csSetWorkOriginXY = _DEFCS(_CSV(15515), + _CHINESE("设置XY工件原点(&X)") + _ENGLISH("Set WorkOrg of &XY")); +CS_T s_csSetWorkOriginZ = _DEFCS(_CSV(15516), + _CHINESE("设置Z工件原点(&Z)") + _ENGLISH("Set WorkOrg of &Z")); +CS_T s_csWCSAdjust = _DEFCS(_CSV(15313), + _CHINESE("巡边定位") + _ENGLISH("WCS Adjust")); +CS_T s_csSTARTNEAR = _DEFCS(_CSV(15319), + _CHINESE("从邻近点加工") + _ENGLISH("Start for Near Point")); +CS_T s_csSTARTSELECTION = _DEFCS(_CSV(15317), + _CHINESE("加工选中图形") + _ENGLISH("Machine Selected")); +CS_T s_csSTARTSELECTIONNOTMOVE = _DEFCS(_CSV(15533), + _CHINESE("原位置加工\tCtrl+F9") + _ENGLISH("From Original Position\tCtrl+F9")); +CS_T s_csSTARTSELECTIONINCURPOS = _DEFCS(_CSV(15536), + _CHINESE("当前点定位切割") + _ENGLISH("From Current Position")); +CS_T s_csANALOGADJUST = _DEFCS(_CSV(15328), + _CHINESE("模拟量调节") + _ENGLISH("Analog Adjust")); +CS_T s_csLIGHTADJUST = _DEFCS(_CSV(15327), + _CHINESE("光路调节") + _ENGLISH("Light Adjust")); +CS_T s_csCATCHPOWER = _DEFCS(_CSV(15541), + _CHINESE("显示功率") + _ENGLISH("Show Power")); +CS_T s_csAUTOCLEAN = _DEFCS(_CSV(15538), + _CHINESE("清洁喷嘴") + _ENGLISH("Auto Clean Nozzle")); +CS_T s_csAUTOLUBRICATE = _DEFCS(_CSV(15537), + _CHINESE("润滑") + _ENGLISH("Lubricate")); +CS_T s_csFPMAPPING = _DEFCS(_CSV(15326), + _CHINESE("速度功率调节") + _ENGLISH("Adjust Power")); +CS_T s_csEDGINGCODE = _DEFCS(_CSV(15325), + _CHINESE("异形扫描(&E)") + _ENGLISH("&Edging")); +CS_T s_csRESERVEDOUTPUT = _DEFCS(_CSV(15576), + _CHINESE("备用输出") + _ENGLISH("Reserved Output")); +CS_T s_csRESERVEDOUTPUT1 = _DEFCS(_CSV(15577), + _CHINESE("备用输出1") + _ENGLISH("Reserved Output1")); +CS_T s_csRESERVEDOUTPUT2 = _DEFCS(_CSV(15578), + _CHINESE("备用输出2") + _ENGLISH("Reserved Output2")); +CS_T s_csRESERVEDOUTPUT3 = _DEFCS(_CSV(15579), + _CHINESE("备用输出3") + _ENGLISH("Reserved Output3")); + +// 管理 ---- 吴畏 2017-02-09 +CS_T s_szMENU_MANAGE= _DEFCS(_CSV(15560), + _CHINESE("管理(&A)") + _ENGLISH("M&anage")); +CS_T s_szMENU_PRINT= _DEFCS(_CSV(15560), + _CHINESE("打印加工信息") + _ENGLISH("Print Manage Info")); + +// 系统 ---- 边俊霞 2016-06-08 +CS_T s_szMENU_SYSTEM = _DEFCS(_CSV(15560), + _CHINESE("系统(&S)") + _ENGLISH("&System")); +CS_T s_szMENU_HELP_LANGUAGE = _DEFCS(_CSV(15331), + _CHINESE("语言(&L)") + _ENGLISH("&Language")); +CS_T s_szMENU_MACH_CONFIG = _DEFCS(_CSV(15303), + _CHINESE("配置") + _ENGLISH("Configs")); +CS_T s_szMENU_MACH_RECTTUBECONFIG = _DEFCS(_CSV(15300), + _CHINESE("管材设置") + _ENGLISH("Tube Cutting Setting")); +CS_T s_szMENU_MACH_PARAM = _DEFCS(_CSV(15300), + _CHINESE("系统参数(&P)\tCtrl+P") + _ENGLISH("System &Parameters\tCtrl+P")); +CS_T s_szMENU_MACH_PORTS = _DEFCS(_CSV(15301), + _CHINESE("端口设置(&O)\tAlt+0") + _ENGLISH("P&orts Setting\tAlt+0")); +CS_T s_csFOLLOWCONTROL = _DEFCS(_CSV(15517), + _CHINESE("随动控制") + _ENGLISH("Follow Control")); +CS_T s_csFOCUSCONTROL= _DEFCS(_CSV(15540), + _CHINESE("焦点控制") + _ENGLISH("Focus Control")); +CS_T s_csWORKBENCHCONTROL= _DEFCS(_CSV(15572), + _CHINESE("交换工作台") + _ENGLISH("Exchange Workbench")); +CS_T s_csAXESERR = _DEFCS(_CSV(15329), + _CHINESE("丝杠误差补偿向导") + _ENGLISH("Screw-Err Compensation Guide")); +CS_T s_csVERTICALITYCORR = _DEFCS(_CSV(15574), + _CHINESE("垂直度矫正向导") + _ENGLISH("Verticality Correction Guide")); +CS_T s_szMENU_FILE_MAKESETUP = _DEFCS(_CSV(15211), + _CHINESE("制作参数备份安装包") + _ENGLISH("Make Param Backup Installer")); +CS_T s_szMENU_FILE_PARAMBACKUP = _DEFCS(_CSV(15485), + _CHINESE("制作参数备份") + _ENGLISH("Make Param Backup")); +CS_T s_szMENU_HELP_LOG = _DEFCS(_CSV(15332), + _CHINESE("日志(&G)...") + _ENGLISH("Lo&g...")); +CS_T s_szMENU_HELP_DIAGNOSE = _DEFCS(_CSV(15337), + _CHINESE("硬件诊断...") + _ENGLISH("Hardware Diagnose...")); +CS_T s_szMENU_PORT_DEFINE = _DEFCS(_CSV(15337), + _CHINESE("系统端口功能自定义 功能电平等") + _ENGLISH("Port Define")); +CS_T s_szMENU_WARNING_DEFINE = _DEFCS(_CSV(15337), + _CHINESE("报警信号设置") + _ENGLISH("Warning Define")); +CS_T s_szMENU_PLC_DEFINE = _DEFCS(_CSV(15337), + _CHINESE("PLC程序编辑") + _ENGLISH("PLC Define")); +CS_T s_szMENU_EXMODULE_DEFINE = _DEFCS(_CSV(15337), + _CHINESE("扩展模块配置") + _ENGLISH("Extend Module Define")); +CS_T s_szMENU_RESET_PARAM = _DEFCS(_CSV(15337), + _CHINESE("系统标准配置") + _ENGLISH("Reset System Param")); + +// 维护 ---- 吴畏 2017-02-09 +CS_T s_szMENU_MAINTAIN = _DEFCS(_CSV(15337), + _CHINESE("维护(&T)") + _ENGLISH("Main&tain")); +CS_T s_szMENU_PHONECALL = _DEFCS(_CSV(15337), + _CHINESE("电话服务") + _ENGLISH("PhoneCall")); +CS_T s_szMENU_REMOTE = _DEFCS(_CSV(15337), + _CHINESE("远程诊断") + _ENGLISH("Remote Diagnosis")); + +// 帮助 ---- 杨开锦 2010-06-07 +CS_T s_szMENU_HELP = _DEFCS(_CSV(15330), + _CHINESE("帮助(&H)") + _ENGLISH("&Help")); +CS_T s_szMENU_SHORTCUTKEY = _DEFCS(_CSV(15333), + _CHINESE("快捷键说明(&K)...\tF1") + _ENGLISH("Shortcut &Key Information...\tF1")); +CS_T s_szMENU_USERMANUAL = _DEFCS(_CSV(15334), + _CHINESE("用户手册(&U)...") + _ENGLISH("&User Manual...")); +CS_T s_szMENU_DAILYTIPS = _DEFCS(_CSV(15335), + _CHINESE("每日提示(&T)...") + _ENGLISH("&Daily Tips...")); +CS_T s_szMENU_WEIHONGINTRO = _DEFCS(_CSV(15336), + _CHINESE("维宏简介...") + _ENGLISH("Weihong Introduction...")); +CS_T s_szMENU_HELP_ABOUT = _DEFCS(_CSV(15338), + _CHINESE("关于(&A)...") + _ENGLISH("&About NcEditor...")); +CS_T s_szMENU_SOFTWARE_GUIDE = _DEFCS(_CSV(15338), + _CHINESE("软件教程.") + _ENGLISH("Software Guide")); +CS_T s_szMENU_LASER_GUIDE = _DEFCS(_CSV(15338), + _CHINESE("激光器指南") + _ENGLISH("Laser Guide")); +CS_T s_szMENU_COMPANY_INTRO = _DEFCS(_CSV(15338), + _CHINESE("公司简介") + _ENGLISH("Company Introduction")); +CS_T s_szMENU_APPEXIT_SHUTDOWNOPERATESYSTEM = _DEFCS(_CSV(15510), + _CHINESE("关闭操作系统") + _ENGLISH("Shutdown Operate System")); +CS_T s_szMENU_APPEXIT_REBOOTOPERATESYSTEM = _DEFCS(_CSV(15511), + _CHINESE("重启操作系统") + _ENGLISH("Reboot Operate System")); +CS_T s_szMENU_AUTOHIDE = _DEFCS(_CSV(15511), + _CHINESE("自动隐藏控制栏") + _ENGLISH("Auto Hide Control Bar")); + +BOOL CDefaultMenu::SetMenuItems() +{ + CString _strAjustDlgTitle(_GETCS(s_csLIGHTADJUST)); + CString _strAdjustDlgType = NceGetPrivateProfileString(_T("AnalogControl"), _T("AdjustDlgType")); + if (!_strAdjustDlgType.IsEmpty()) + { + _strAjustDlgTitle = _GETCS(s_csANALOGADJUST); + } + + CString _strWeihongIntroEnable = NceGetPrivateProfileString(_T("DefaultMenu"), _T("EnableWeiHongIntroMenu"), _T("")); + MenuItem _MenuItemWeihongIntro; + _MenuItemWeihongIntro = MenuItem(MENUITEM, _GETCS(s_szMENU_WEIHONGINTRO), IDCMD_HELPTARGET_WEIHONGINTRO); + if (_strWeihongIntroEnable == _T("0")) + { + _MenuItemWeihongIntro = MenuItem(MENUITEM, NULL); + + } + + CString _strEnable = NceGetPrivateProfileString(_T("Tube"), _T("Enable"), _T("")); + bool _bIsTube = _strEnable == _T("True"); + + //保定蜂鸟备用输出显示判断----2017/6/1 张磊 + CString _strReserved = NceGetPrivateProfileString(_T("ReservedOutput"), _T("IsShow"), _T("")); + bool _bIsReserved = _strReserved == _T("True"); + + // 菜单配置列表 ---- 杨开锦 2010-06-07 + + CString _strRunReportWarningAlign = NceGetPrivateProfileString(_T("DefaultMenu"), _T("MenuStyle"), _T("")); + if (_strRunReportWarningAlign == _T("")) + { + MenuItem _MenuItems[] = + { + MenuItem(BEGIN), + // 文件 ---- 杨开锦 2010-06-07 + MenuItem(POPUP, _GETCS(s_szMENU_FILE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_NEW), IDCMD_FILETARGET_NEW), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_OPEN), IDCMD_FILETARGET_OPEN), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_IMPORT), IDCMD_IMPORTFILETARGET_IMPORT), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_INSERT), IDCMD_IMPORTFILETARGET_INSERT), + #ifdef _DEBUG + // 导出nce文件为nc文件只能用于研发部内部,切忌不能将此菜单给用户开放 ---- 嘎松卓玛 2012.09.22 + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_EXPORT), IDCMD_EXPORTFILETARGET_EXPORT), + #endif + MenuItem(MENUITEM, _GETCS(s_csEXPORTFEEDBACK), IDCMD_PULSERECORDTARGET_EXPORTFEEDBAK), + MenuItem(MENUITEM, _GETCS(s_csEXPORTSEND), IDCMD_PULSERECORDTARGET_EXPORTSEND), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_NEST), IDCMD_NESTPROFESSORTARGET_NEST2), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_SAVE), IDCMD_FILETARGET_SAVE), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_SAVE_AS), IDCMD_FILETARGET_SAVE_AS), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_SAVE_SELECTED_AS), IDCMD_FILETARGET_SAVE_SELECT), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_szMENU_FILE_RECENTFILES_NCE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_RECENTFILES_NONE), IDCMD_FILETARGET_MRUNCE_FIRST), + MenuItem(END), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_APPEXIT_RESTARTSOFTWARE), IDCMD_APPEXITTARGET_RESTARTSOFTWARE), + MenuItem(MENUITEM, _GETCS(s_szMENU_APPEXIT_SHUTDOWNSYSTEM), IDCMD_APPEXITTARGET_SHUTDOWMSYSTEM), + MenuItem(MENUITEM, _GETCS(s_szMENU_APPEXIT_REBOOTSYSTEM), IDCMD_APPEXITTARGET_REBOOTSYSTEM), + MenuItem(MENUITEM, _GETCS(s_szMENU_APPEXIT_SHOWDESKTOP), IDCMD_APPEXITTARGET_SHOWDESKTOP), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_EXIT), ID_APP_EXIT), + MenuItem(END), + + // 编辑 ---- 杨开锦 2010-06-07 + MenuItem(POPUP, _GETCS(s_szMENU_EDIT)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_UNDO), IDCMD_UNDOREDOTARGET_UNDO), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_REDO), IDCMD_UNDOREDOTARGET_REDO), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_ALL), IDCMD_SELECTTARGET_SELECTALL), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_REV), IDCMD_SELECTTARGET_SELECTREV), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_CLEAR_SELECT), IDCMD_SELECTTARGET_CLEARSELECT), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_UNCLOSE), IDCMD_SELECTTARGET_SELECTUNCLOSE), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_TINY), IDCMD_SELECTTARGET_SELECTTINY), + MenuItem(POPUP, _GETCS(s_szMENU_EDIT_SELECT_BYCOLOR)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _T("0"), IDCMD_SELECTTARGET_SELECTBYCOLOR0), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_EDIT_SELECT_BYTYPE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _T("0"), IDCMD_SELECTTARGET_SELECTBYTYPE0), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_EDIT_SELECT_BYINOUT)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_BYINOUT_IN), IDCMD_FILLTARGET_SELECTINNER), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_BYINOUT_OUT), IDCMD_FILLTARGET_SELECTOUTER), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_SIMILAR), IDCMD_SELECTTARGET_SELECTSIMILAR), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_DELETE), IDCMD_DELETETARGET_DELETE), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_CUT), IDCMD_CLIPBOARDTARGET_CUT), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_COPY), IDCMD_CLIPBOARDTARGET_COPY), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_PASTE), IDCMD_CLIPBOARDTARGET_PASTE), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_PASTE_AS_GROUP), IDCMD_CLIPBOARDTARGET_PASTEASGROUP), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_CLEAR_CLIPBOARD), IDCMD_CLIPBOARDTARGET_CLEAR), + MenuItem(END), + + // 视图 ---- 杨开锦 2010-06-07 + MenuItem(POPUP, _GETCS(s_szMENU_VIEW)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_VIEWPORT_TRANSLATE), IDCMD_VIEWPORTTRANSLATEBYDRAGTARGET_TRANSLATEBYDRAG), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_VIEWPORT_ZOOM_BYDRAG), IDCMD_VIEWPORTZOOMBYDRAGTARGET_ZOOMBYDRAG), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_VIEWPORT_ZOOM_BYRECT), IDCMD_VIEWPORTZOOMBYRECTTARGET_ZOOMBYRECT), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_VIEWPORT_FITTOWINDOW), IDCMD_VIEWPORTADJUSTTARGET_FITWINDOW), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_ORDER), IDCMD_OBJECTORDERTARGET_SHOWORDER), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_STARTPOINT), IDCMD_INTROTARGET_SHOWSTARTPOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_DIRECTION), IDCMD_DIRECTIONTARGET_ADDARROW), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_INTRODUCE), IDCMD_INTROTARGET_SHOWINTRO), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_szMENU_VIEW_SHOW_TRACEPATH)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_NOPATH), IDCMD_TRACETARGET_HIDETRACEPATH), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_MACHINGPATH), IDCMD_TRACETARGET_SHOWMACHINGPATH), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_FEEDBACKPATH), IDCMD_TRACETARGET_SHOWFEEDBACKPATH), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_CLEAR_TRACEPATH), IDCMD_TRACETARGET_CLEARTRACEPATH), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_TRACEPOINT), IDCMD_TRACETARGET_SHOWTRACEPOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_MIDDLE_TRACEPOINT), IDCMD_TRACETARGET_MIDDLETRACEPOINT), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_WIREFRAMEMODE), IDCMD_FILLTARGET_SELECTWIREFRAMEMODE), + MenuItem(MENUITEM, _GETCS(s_szMENE_VIEW_FILLMODE), IDCMD_FILLTARGET_SELECTOPAQUEMODE), + //MenuItem(MENUITEM, _GETCS(s_szMENE_VIEW_DYNFILLMODE), IDCMD_FILLTARGET_SELECTFILLMODE), + MenuItem(END), + + // 绘图 ---- 杨开锦 2010-06-11 + MenuItem(POPUP, _GETCS(s_szMENU_DRAW)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_DOT), IDCMD_DRAWDOTTARGET_DRAWDOT), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_LINE), IDCMD_DRAWLINETARGET_DRAWLINE), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_CIRCLE), IDCMD_DRAWCIRCLETARGET_DRAWCIRCLE), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_ARC), IDCMD_DRAWARCTARGET_DRAWARC), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_ELLIPSE), IDCMD_DRAWELLIPSETARGET_DRAWELLIPSE), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_ELLIPSEARC), IDCMD_DRAWELLIPSEARCTARGET_DRAWELLIPSEARC), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_RECTANGLE), IDCMD_DRAWRECTANGLETARGET_DRAWRECTANGLE), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_POLYLINE), IDCMD_DRAWPOLYLINETARGET_DRAWPOLYLINE), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_POLYGON), IDCMD_DRAWPOLYGONTARGET_DRAWPOLYGON), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_STAR), IDCMD_DRAWSTARTARGET_DRAWSTAR), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_TEXT), IDCMD_DRAWTEXTTARGET_DRAWTEXT), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _bIsTube ? _GETCS(s_szMENU_TUBEGUIDE) : _GETCS(s_szMENU_CIRCLECUTTIPS), IDCMD_INTERSECTINGLINETARGET_INTERSECTINGLINE_R2), + MenuItem(MENUITEM, _GETCS(s_csTEACHINGCODE), IDCMD_TEACHINGTARGET_TEACHINGCODE), + MenuItem(MENUITEM, _GETCS(s_szMENU_DRAW_GALLERY), IDCMD_GALLERYTARGET_GALLERY), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CATCH), IDCMD_CATCHTARGET_SWITCH), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CATCH_OPTION), IDCMD_CATCHTARGET_OPTION), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CATCH_POLARAXISINCANGLE), IDCMD_CATCHPOLARAXISTARGET_SETINCANGLE), + MenuItem(END), + + // 对象 Wanglou 2010-06-09 + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_TRANSLATE), IDCMD_TRANSLATETARGET_TRANSLATE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ROTATE), IDCMD_ROTATETARGET_TRANSLATE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_SCALE), IDCMD_SCALETARGET_TRANSLATE), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_ALIGN)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_LEFT), IDCMD_ALIGNTARGET_ALIGN_LEFT), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_RIGHT), IDCMD_ALIGNTARGET_ALIGN_RIGHT), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_TOP), IDCMD_ALIGNTARGET_ALIGN_TOP), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_BOTTOM), IDCMD_ALIGNTARGET_ALIGN_BOTTOM), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_CENTERPT), IDCMD_ALIGNTARGET_ALIGN_CENTERPOINT), + MenuItem(MENUITEM, _GETCS(S_SZMENU_OBJECT_ALIGN_MIDLINE_H), IDCMD_ALIGNTARGET_ALIGN_MIDLINE_H), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_MIDLINE_V), IDCMD_ALIGNTARGET_ALIGN_MIDLINE_V), + MenuItem(MENUITEM, _GETCS(S_SZMENU_OBJECT_ALIGN_DECENTRAL_H), IDCMD_ALIGNTARGET_ALIGN_DECENTRAL_H), + MenuItem(MENUITEM, _GETCS(S_SZMENU_OBJECT_ALIGN_DECENTRAL_V), IDCMD_ALIGNTARGET_ALIGN_DECENTRAL_V), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_GROUPANDBREAK)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_GROUP), IDCMD_GROUPTARGET_GROUP), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_BREAKGROUP), IDCMD_GROUPTARGET_BREAKGROUP), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_COMBINE), IDCMD_JOINTARGET_ONJOIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_EXPLODE), IDCMD_EXPLODETARGET_EXPLODE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_BREAK), IDCMD_ADDBRIDGE_ADDBRIDGE), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_TUBELOCATION), IDCMD_TUBELOCATIONTARGET_TUBELOCATION), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_MEASURE), IDCMD_DISTANCETARGET_DISTANCE), + MenuItem(MENUITEM, _GETCS(s_szMUNU_OBJECT_CADCHECK), IDCMD_CADCHECKERTARGET_CADCHECK), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_PREPROCESSING)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_INSTANTPREPROCESSING), IDCMD_CADPREPROCESSINGTARGET_PREPROCESSING), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLIPOVERLAP), IDCMD_OVERLAPTARGET_CLIPOVERLAP), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_DELETESHORTIES), IDCMD_DELETETARGET_DELETESHORTIES), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CURVESMOOTHER), IDCMD_SMOOTHTARGET_SMOOTH), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_TRANSLATETEXT), IDCMD_TRANSLATETEXTTARGET_TRANSLATETEXT), + MenuItem(END), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_SPECIALTECH)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_STOPCORNER), IDCMD_STOPCORNERTARGET_SETSTOPCORNER), + MenuItem(MENUITEM, _GETCS(s_szRELEASEANGLE), IDCMD_RELEASEANGLETARGET_RELEASEANGLE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CHAMFER), IDCMD_CHAMFERTARGETR2_CHAMFER), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ADDBRIDGE), IDCMD_BRIDGETARGET_BRIDGE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_MICROJOINT), IDCMD_MICROJOINTTARGET_MICROJOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_EXPLODEMICROJOINT), IDCMD_MICROJOINTTARGET_EXPLODEMICROJOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CHOP), IDCMD_CHOPTARGET_CHOP), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_SCAN)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_LINESCAN), IDCMD_SCANTARGET_LINESCAN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ARCSCAN), IDCMD_SCANTARGET_ARCSCAN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_SCANLOT), IDCMD_SCANTARGET_SCANLEDONTEXT), + MenuItem(END), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_UNFILLANDFILL)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_FILL), IDCMD_FILLTARGET_FILL), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_UNFILL), IDCMD_FILLTARGET_UNFILL), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_AUTOSETFILL), IDCMD_FILLTARGET_AUTOSETFILL), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMUNU_OBJECT_ORDER)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_AUTOSETORDER), IDCMD_OBJECTORDERTARGET_AUTOSETORDER), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_MANUALSETORDER), IDCMD_OBJECTORDERTARGET_MANUSETORDER), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_MANUALSPECIFYORDER), IDCMD_OBJECTORDERTARGET_MANUSPECIFYORDER), + MenuItem(MENUITEM, _GETCS(s_szMUNU_OBJECT_ORDER_LIST), IDCMD_OBJECTORDERTARGET_SETORDERLIST), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_MACHDIRECTION)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_REVERSEDIRECTION), IDCMD_DIRECTIONTARGET_REVERSEDIRECTION), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_SETDIRECTION), IDCMD_DIRECTIONTARGET_SETDIRECTION), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_LEADLINE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_INTROSTART), IDCMD_INTROTARGET_SETINTROSTART), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_INTRODUCE), IDCMD_INTROTARGET_INTRO), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_INTERSECTINGLINE), IDCMD_INTERSECTINGLINETARGET_INTERSECTINGLINE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_SETCRC), IDCMD_CRCTARGET_CRC), + MenuItem(MENUITEM, _GETCS(s_szINSTANTSETTING), IDCMD_INSTANTSETTINGTARGET_SETTING), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_PARAMGROUPSETTING), IDCMD_PARAMGROUPTARGET_SETTING), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_CLEAR)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARINTRO), IDCMD_INTROTARGET_CLEARINTRO), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARCRC), IDCMD_CRCTARGET_CLEARCRC), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARSTOPCORNER), IDCMD_STOPCORNERTARGET_CLEARSTOPCORNER), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARMICROJOINT), IDCMD_MICROJOINTTARGET_CLEARMICROJOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARCHAMFER), IDCMD_CHAMFERTARGETR2_CLEARCHAMFER), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARRELEASEANGLE), IDCMD_RELEASEANGLETARGET_CLEARRELEASEANGLE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARCHOP), IDCMD_CHOPTARGET_CLEARCHOP), + MenuItem(END), + MenuItem(END), + + // 加工 ---- 边俊霞 2016-6-8 + MenuItem(POPUP, _GETCS(s_szMENU_MACH)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_MACH_STATISTICS), IDCMD_RUNREPORTTARGET_SHOWSTATISTICS), + MenuItem(MENUITEM, _GETCS(s_csCRCRUN), IDCMD_CYCMACHININGTARGET_CYCMACHINING), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_csBKREF)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_csBKALL), IDCMD_CONTROLTARGET_BACKR), + MenuItem(MENUITEM, _GETCS(s_csDIRECTSET), IDCMD_CONTROLTARGET_DIRECTSET), + MenuItem(MENUITEM, _GETCS(s_csBKX), IDCMD_CONTROLTARGET_XBACKR), + MenuItem(MENUITEM, _GETCS(s_csBKY), IDCMD_CONTROLTARGET_YBACKR), + MenuItem(MENUITEM, _GETCS(s_csBKZ), IDCMD_CONTROLTARGET_ZBACKR), + MenuItem(MENUITEM, _GETCS(s_csBKW), IDCMD_EXCHANGEWORKBENCHTARGET_BACKR), + MenuItem(MENUITEM, _GETCS(s_csBKWFFOCUS), IDCMD_FOCUSCONTROLTARGET_BACKR), + MenuItem(MENUITEM, _GETCS(s_csBKDLG), IDCMD_CONTROLTARGET_BACKRDLG), + MenuItem(MENUITEM, _GETCS(s_csDETECT2YERROR), IDCMD_CONTROLTARGET_DETECT2YERROR), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_csMOVETOWORKORIGIN), IDCMD_CONTROLTARGET_BACKW), + MenuItem(MENUITEM, _GETCS(s_csMOVETOFIXEDPOS), IDCMD_CONTROLTARGET_MOVETOFIXPOS), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_csSTARTSELECTION), IDCMD_CONTROLTARGET_MACHSELECTED), + MenuItem(POPUP, _GETCS(s_csMACHCONTROL)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_csSTART), IDCMD_CONTROLTARGET_START), + MenuItem(MENUITEM, _GETCS(s_csPAUSE), IDCMD_CONTROLTARGET_PAUSE), + MenuItem(MENUITEM, _GETCS(s_csSTOP), IDCMD_CONTROLTARGET_STOP), + MenuItem(MENUITEM, _GETCS(s_csRESUME), IDCMD_CONTROLTARGET_BREAKPOINTRESUME), + MenuItem(MENUITEM, _GETCS(s_csSIMU), IDCMD_CONTROLTARGET_SIMULATE), + MenuItem(MENUITEM, _GETCS(s_csDIRRUN), IDCMD_CONTROLTARGET_DIRRUN), + MenuItem(MENUITEM, _GETCS(s_csSIMUCUTBOUNDRECT), IDCMD_CONTROLTARGET_SIMUCUT), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_csSTARTNEAR), IDCMD_CONTROLTARGET_STARTNEARPOINT), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_csMARKPOSITION), IDCMD_MARKPOINTTARGET_MARKPOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SETORIGINPOSITION), IDCMD_SETORIGIN_SET), + MenuItem(POPUP, _GETCS(s_csSetWorkOrigin)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_csSetWorkOriginXY), IDCMD_CONTROLTARGET_CLEARW), + MenuItem(MENUITEM, _GETCS(s_csSetWorkOriginZ), IDCMD_CONTROLTARGET_CLEARWZ), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_csWCSAdjust), IDCMD_WCSADJUSTTARGET_SETTING), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _strAjustDlgTitle, IDCMD_ANALOGCONTROLTARGET_ANALOGCONTROL), + MenuItem(MENUITEM, _GETCS(s_csCATCHPOWER), IDCMD_CATCHPOWERTARGET_CATCH), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_csAUTOCLEAN), IDCMD_AUTOCLEANTARGET_AUTOCLEAN), + MenuItem(MENUITEM, _GETCS(s_csAUTOLUBRICATE), IDCMD_LUBRICATETARGET_LUBRICATE), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_csRESERVEDOUTPUT)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_csRESERVEDOUTPUT1 ), IDCMD_ANALOGCONTROLTARGET_RESERVEDOUTPUT0), + MenuItem(MENUITEM, _GETCS(s_csRESERVEDOUTPUT2 ), IDCMD_ANALOGCONTROLTARGET_RESERVEDOUTPUT1), + MenuItem(MENUITEM, _GETCS(s_csRESERVEDOUTPUT3 ), IDCMD_ANALOGCONTROLTARGET_RESERVEDOUTPUT2), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_csFPMAPPING), IDCMD_FPMAPPING_SETFPMAPPING), + //MenuItem(MENUITEM, _GETCS(s_csEDGINGCODE), IDCMD_EDGINGTARGET_EDGING), + MenuItem(END), + + // 系统 ---- 边俊霞 2016-06-08 + MenuItem(POPUP, _GETCS(s_szMENU_SYSTEM)), + MenuItem(BEGIN), + MenuItem(POPUP, _GETCS(s_szMENU_HELP_LANGUAGE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _T("0"), IDCMD_LANGUAGETARGET_LANG0), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_MACH_CONFIG)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _T("0"), IDCMD_CONFIGTARGET_CONFIG0), + MenuItem(END), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_MACH_RECTTUBECONFIG), IDCMD_TUBECTRLTARGET_PARAMSET), + MenuItem(MENUITEM, _GETCS(s_szMENU_MACH_PARAM), IDCMD_PARAMMANAGERTARGET_SHOWPARAM), + MenuItem(MENUITEM, _GETCS(s_szMENU_MACH_PORTS), IDCMD_PORTSTARGET_SETTING), + MenuItem(MENUITEM, _GETCS(s_csFOLLOWCONTROL), IDCMD_CONTROLTARGET_FOLLOWCONTROL), + MenuItem(MENUITEM, _GETCS(s_csFOCUSCONTROL), IDCMD_FOCUSCONTROLTARGET_FOCUSCONTROL), + MenuItem(MENUITEM, _GETCS(s_csWORKBENCHCONTROL), IDCMD_EXCHANGEWORKBENCHTARGET_EXCHANGEWORKBENCH), + MenuItem(MENUITEM, _GETCS(s_csAXESERR), IDCMD_AXESERRTARGET_AXESERR), + MenuItem(MENUITEM, _GETCS(s_csVERTICALITYCORR), IDCMD_VERTICALITYCORRECTION_CORRECTION), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_MAKESETUP), IDCMD_CONFIGTARGET_PACKER), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_PARAMBACKUP), IDCMD_CONFIGTARGET_PARAMBACKUP), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_HELP_LOG), IDCMD_LOGTARGET_LOG), + MenuItem(MENUITEM, _GETCS(s_szMENU_HELP_DIAGNOSE), IDCMD_DIAGNOSETARGET_TESTING), + MenuItem(END), + + // 帮助 ---- 杨开锦 2010-06-07 + MenuItem(POPUP, _GETCS(s_szMENU_HELP)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_SHORTCUTKEY), IDCMD_HELPTARGET_SHORTCUTKEY), + MenuItem(MENUITEM, _GETCS(s_szMENU_USERMANUAL), IDCMD_HELPTARGET_USERMANUAL), + MenuItem(MENUITEM, _GETCS(s_szMENU_DAILYTIPS), IDCMD_HELPTARGET_DAILYTIPS), + _MenuItemWeihongIntro, + MenuItem(MENUITEM, _GETCS(s_szMENU_HELP_DIAGNOSE), IDCMD_DIAGNOSETARGET_TESTING), + MenuItem(MENUITEM, _GETCS(s_szMENU_HELP_ABOUT), ID_APP_ABOUT), + MenuItem(END), + MenuItem(END), + }; + + // 拷贝到m_MenuItems ---- 杨开锦 2010-06-08 + UINT _nCount = _countof(_MenuItems); + bool _bChange = false; + //如果判断得出当前不是保定蜂鸟时,则将备用输出相关的东西不拷贝到m_MenuItems + //并且总数量减去6,包含备用输出,begin,备用输出1,2,3,end。#3968----2017/6/1 张磊 + if(!_bIsReserved) + { + for (UINT _i = 0; _i < _nCount; _i++) + { + if (s_csRESERVEDOUTPUT.szStrings[0] == _MenuItems[_i].szItemName || + s_csRESERVEDOUTPUT.szStrings[1] == _MenuItems[_i].szItemName ) + { + _bChange = true; + } + if (_bChange && _i+6 < _nCount) + { + m_MenuItems[_i] = _MenuItems[_i+6]; + } + else + { + m_MenuItems[_i] = _MenuItems[_i]; + } + + } + m_nValidMenuItem = _nCount - 6; + } + else + { + for (UINT _i = 0; _i < _nCount; _i++) + m_MenuItems[_i] = _MenuItems[_i]; + + m_nValidMenuItem = _nCount; + } + } + else if (_strRunReportWarningAlign == _T("R2")) + { + // IDCMD_FILETARGET_NEW + MenuItem _MenuItems[] = + { + MenuItem(BEGIN), + // 文件 ---- 杨开锦 2010-06-07 + MenuItem(POPUP, _GETCS(s_szMENU_FILE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_NEW), IDCMD_FILETARGET_NEW), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_OPEN), IDCMD_FILETARGET_OPEN), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_IMPORT), IDCMD_IMPORTFILETARGET_IMPORT), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_INSERT), IDCMD_IMPORTFILETARGET_INSERT), + #ifdef _DEBUG + // 导出nce文件为nc文件只能用于研发部内部,切忌不能将此菜单给用户开放 ---- 嘎松卓玛 2012.09.22 + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_EXPORT), IDCMD_EXPORTFILETARGET_EXPORT), + #endif + MenuItem(MENUITEM, _GETCS(s_csEXPORTFEEDBACK), IDCMD_PULSERECORDTARGET_EXPORTFEEDBAK), + MenuItem(MENUITEM, _GETCS(s_csEXPORTSEND), IDCMD_PULSERECORDTARGET_EXPORTSEND), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_SAVE), IDCMD_FILETARGET_SAVE), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_SAVE_AS), IDCMD_FILETARGET_SAVE_AS), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_SAVE_SELECTED_AS), IDCMD_FILETARGET_SAVE_SELECT), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_szMENU_FILE_RECENTFILES_NCE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_RECENTFILES_NONE), IDCMD_FILETARGET_MRUNCE_FIRST), + MenuItem(END), + MenuItem(END), + + // 常用(原对象) ---- 吴畏 2017-02-13 + MenuItem(POPUP, _GETCS(s_szMENU_HOME)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_TRANSLATE), IDCMD_TRANSLATETARGET_TRANSLATE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ROTATE), IDCMD_ROTATETARGET_TRANSLATE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_SCALE), IDCMD_SCALETARGET_TRANSLATE), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_ALIGN)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_LEFT), IDCMD_ALIGNTARGET_ALIGN_LEFT), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_RIGHT), IDCMD_ALIGNTARGET_ALIGN_RIGHT), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_TOP), IDCMD_ALIGNTARGET_ALIGN_TOP), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_BOTTOM), IDCMD_ALIGNTARGET_ALIGN_BOTTOM), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_CENTERPT), IDCMD_ALIGNTARGET_ALIGN_CENTERPOINT), + MenuItem(MENUITEM, _GETCS(S_SZMENU_OBJECT_ALIGN_MIDLINE_H), IDCMD_ALIGNTARGET_ALIGN_MIDLINE_H), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ALIGN_MIDLINE_V), IDCMD_ALIGNTARGET_ALIGN_MIDLINE_V), + MenuItem(MENUITEM, _GETCS(S_SZMENU_OBJECT_ALIGN_DECENTRAL_H), IDCMD_ALIGNTARGET_ALIGN_DECENTRAL_H), + MenuItem(MENUITEM, _GETCS(S_SZMENU_OBJECT_ALIGN_DECENTRAL_V), IDCMD_ALIGNTARGET_ALIGN_DECENTRAL_V), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_GROUPANDBREAK)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_GROUP), IDCMD_GROUPTARGET_GROUP), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_BREAKGROUP), IDCMD_GROUPTARGET_BREAKGROUP), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_COMBINE), IDCMD_JOINTARGET_ONJOIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_EXPLODE), IDCMD_EXPLODETARGET_EXPLODE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_BREAK), IDCMD_ADDBRIDGE_ADDBRIDGE), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_MEASURE), IDCMD_DISTANCETARGET_DISTANCE), + MenuItem(MENUITEM, _GETCS(s_szMUNU_OBJECT_CADCHECK), IDCMD_CADCHECKERTARGET_CADCHECK), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_PREPROCESSING)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_INSTANTPREPROCESSING), IDCMD_CADPREPROCESSINGTARGET_PREPROCESSING), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLIPOVERLAP), IDCMD_OVERLAPTARGET_CLIPOVERLAP), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_DELETESHORTIES), IDCMD_DELETETARGET_DELETESHORTIES), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CURVESMOOTHER), IDCMD_SMOOTHTARGET_SMOOTH), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_TRANSLATETEXT), IDCMD_TRANSLATETEXTTARGET_TRANSLATETEXT), + MenuItem(END), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_CLEAR)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARINTRO), IDCMD_INTROTARGET_CLEARINTRO), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARCRC), IDCMD_CRCTARGET_CLEARCRC), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARSTOPCORNER), IDCMD_STOPCORNERTARGET_CLEARSTOPCORNER), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARMICROJOINT), IDCMD_MICROJOINTTARGET_CLEARMICROJOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARCHAMFER), IDCMD_CHAMFERTARGETR2_CLEARCHAMFER), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARRELEASEANGLE), IDCMD_RELEASEANGLETARGET_CLEARRELEASEANGLE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CLEARCHOP), IDCMD_CHOPTARGET_CLEARCHOP), + MenuItem(END), + MenuItem(END), + + // 选择(原编辑) ---- 吴畏 2017-02-13 + MenuItem(POPUP, _GETCS(s_szMENU_CHOOSE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_UNDO), IDCMD_UNDOREDOTARGET_UNDO), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_REDO), IDCMD_UNDOREDOTARGET_REDO), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_ALL), IDCMD_SELECTTARGET_SELECTALL), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_REV), IDCMD_SELECTTARGET_SELECTREV), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_CLEAR_SELECT), IDCMD_SELECTTARGET_CLEARSELECT), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_UNCLOSE), IDCMD_SELECTTARGET_SELECTUNCLOSE), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_TINY), IDCMD_SELECTTARGET_SELECTTINY), + MenuItem(POPUP, _GETCS(s_szMENU_EDIT_SELECT_BYCOLOR)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _T("0"), IDCMD_SELECTTARGET_SELECTBYCOLOR0), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_EDIT_SELECT_BYTYPE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _T("0"), IDCMD_SELECTTARGET_SELECTBYTYPE0), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_EDIT_SELECT_BYINOUT)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_BYINOUT_IN), IDCMD_FILLTARGET_SELECTINNER), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_BYINOUT_OUT), IDCMD_FILLTARGET_SELECTOUTER), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_SELECT_SIMILAR), IDCMD_SELECTTARGET_SELECTSIMILAR), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_DELETE), IDCMD_DELETETARGET_DELETE), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_CUT), IDCMD_CLIPBOARDTARGET_CUT), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_COPY), IDCMD_CLIPBOARDTARGET_COPY), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_PASTE), IDCMD_CLIPBOARDTARGET_PASTE), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_PASTE_AS_GROUP), IDCMD_CLIPBOARDTARGET_PASTEASGROUP), + MenuItem(MENUITEM, _GETCS(s_szMENU_EDIT_CLEAR_CLIPBOARD), IDCMD_CLIPBOARDTARGET_CLEAR), + MenuItem(END), + + // 视图 ---- 杨开锦 2010-06-07 + MenuItem(POPUP, _GETCS(s_szMENU_VIEW)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_AUTOHIDE), IDCMD_CONTROLTARGET_AUTOHIDE), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_VIEWPORT_TRANSLATE), IDCMD_VIEWPORTTRANSLATEBYDRAGTARGET_TRANSLATEBYDRAG), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_VIEWPORT_ZOOM_BYDRAG), IDCMD_VIEWPORTZOOMBYDRAGTARGET_ZOOMBYDRAG), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_VIEWPORT_ZOOM_BYRECT), IDCMD_VIEWPORTZOOMBYRECTTARGET_ZOOMBYRECT), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_VIEWPORT_FITTOWINDOW), IDCMD_VIEWPORTADJUSTTARGET_FITWINDOW), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_ORDER), IDCMD_OBJECTORDERTARGET_SHOWORDER), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_STARTPOINT), IDCMD_INTROTARGET_SHOWSTARTPOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_DIRECTION), IDCMD_DIRECTIONTARGET_ADDARROW), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_INTRODUCE), IDCMD_INTROTARGET_SHOWINTRO), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_szMENU_VIEW_SHOW_TRACEPATH)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_NOPATH), IDCMD_TRACETARGET_HIDETRACEPATH), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_MACHINGPATH), IDCMD_TRACETARGET_SHOWMACHINGPATH), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_FEEDBACKPATH), IDCMD_TRACETARGET_SHOWFEEDBACKPATH), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_CLEAR_TRACEPATH), IDCMD_TRACETARGET_CLEARTRACEPATH), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SHOW_TRACEPOINT), IDCMD_TRACETARGET_SHOWTRACEPOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_MIDDLE_TRACEPOINT), IDCMD_TRACETARGET_MIDDLETRACEPOINT), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_WIREFRAMEMODE), IDCMD_FILLTARGET_SELECTWIREFRAMEMODE), + MenuItem(MENUITEM, _GETCS(s_szMENE_VIEW_FILLMODE), IDCMD_FILLTARGET_SELECTOPAQUEMODE), + //MenuItem(MENUITEM, _GETCS(s_szMENE_VIEW_DYNFILLMODE), IDCMD_FILLTARGET_SELECTFILLMODE), + MenuItem(END), + + //工艺 ---- 吴畏 2017-03-06 + MenuItem(POPUP, _GETCS(s_szMENU_DRAW)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_STOPCORNER), IDCMD_STOPCORNERTARGET_SETSTOPCORNER), + MenuItem(MENUITEM, _GETCS(s_szRELEASEANGLE), IDCMD_RELEASEANGLETARGET_RELEASEANGLE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CHAMFER), IDCMD_CHAMFERTARGETR2_CHAMFER), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ADDBRIDGE), IDCMD_BRIDGETARGET_BRIDGE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_MICROJOINT), IDCMD_MICROJOINTTARGET_MICROJOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_EXPLODEMICROJOINT), IDCMD_MICROJOINTTARGET_EXPLODEMICROJOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_CHOP), IDCMD_CHOPTARGET_CHOP), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_SCAN)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_LINESCAN), IDCMD_SCANTARGET_LINESCAN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_ARCSCAN), IDCMD_SCANTARGET_ARCSCAN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_SCANLOT), IDCMD_SCANTARGET_SCANLEDONTEXT), + MenuItem(END), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_UNFILLANDFILL)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_FILL), IDCMD_FILLTARGET_FILL), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_UNFILL), IDCMD_FILLTARGET_UNFILL), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_AUTOSETFILL), IDCMD_FILLTARGET_AUTOSETFILL), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMUNU_OBJECT_ORDER)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_AUTOSETORDER), IDCMD_OBJECTORDERTARGET_AUTOSETORDER), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_MANUALSETORDER), IDCMD_OBJECTORDERTARGET_MANUSETORDER), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_MANUALSPECIFYORDER), IDCMD_OBJECTORDERTARGET_MANUSPECIFYORDER), + MenuItem(MENUITEM, _GETCS(s_szMUNU_OBJECT_ORDER_LIST), IDCMD_OBJECTORDERTARGET_SETORDERLIST), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_MACHDIRECTION)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_REVERSEDIRECTION), IDCMD_DIRECTIONTARGET_REVERSEDIRECTION), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_SETDIRECTION), IDCMD_DIRECTIONTARGET_SETDIRECTION), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_LEADLINE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_INTROSTART), IDCMD_INTROTARGET_SETINTROSTART), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_INTRODUCE), IDCMD_INTROTARGET_INTRO), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_INTERSECTINGLINE), IDCMD_INTERSECTINGLINETARGET_INTERSECTINGLINE), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_SETCRC), IDCMD_CRCTARGET_CRC), + MenuItem(MENUITEM, _GETCS(s_szINSTANTSETTING), IDCMD_INSTANTSETTINGTARGET_SETTING), + MenuItem(END), + + // 排版 ---- 吴畏 2017-02-13 + MenuItem(POPUP, _GETCS(s_szMENU_OBJECT_NEST)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_OBJECT_NEST), IDCMD_NESTPROFESSORTARGET_NEST2), + MenuItem(END), + + // 加工 ---- 边俊霞 2016-6-8 + MenuItem(POPUP, _GETCS(s_szMENU_MACH)), + MenuItem(BEGIN), + MenuItem(POPUP, _GETCS(s_csBKREF)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_csBKALL), IDCMD_CONTROLTARGET_BACKR), + MenuItem(MENUITEM, _GETCS(s_csDIRECTSET), IDCMD_CONTROLTARGET_DIRECTSET), + MenuItem(MENUITEM, _GETCS(s_csBKX), IDCMD_CONTROLTARGET_XBACKR), + MenuItem(MENUITEM, _GETCS(s_csBKY), IDCMD_CONTROLTARGET_YBACKR), + MenuItem(MENUITEM, _GETCS(s_csBKZ), IDCMD_CONTROLTARGET_ZBACKR), + MenuItem(MENUITEM, _GETCS(s_csBKW), IDCMD_EXCHANGEWORKBENCHTARGET_BACKR), + MenuItem(MENUITEM, _GETCS(s_csBKWFFOCUS),IDCMD_FOCUSCONTROLTARGET_BACKR ), + MenuItem(MENUITEM, _GETCS(s_csBKDLG), IDCMD_CONTROLTARGET_BACKRDLG), + MenuItem(MENUITEM, _GETCS(s_csDETECT2YERROR), IDCMD_CONTROLTARGET_DETECT2YERROR), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_csMOVETOWORKORIGIN), IDCMD_CONTROLTARGET_BACKW), + MenuItem(MENUITEM, _GETCS(s_csMOVETOFIXEDPOS), IDCMD_CONTROLTARGET_MOVETOFIXPOS), + MenuItem(MENUITEM, NULL), + MenuItem(POPUP, _GETCS(s_csMACHCONTROL)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_csSTART), IDCMD_CONTROLTARGET_START), + MenuItem(MENUITEM, _GETCS(s_csPAUSE), IDCMD_CONTROLTARGET_PAUSE), + MenuItem(MENUITEM, _GETCS(s_csSTOP), IDCMD_CONTROLTARGET_STOP), + MenuItem(MENUITEM, _GETCS(s_csRESUME), IDCMD_CONTROLTARGET_BREAKPOINTRESUME), + MenuItem(MENUITEM, _GETCS(s_csSIMU), IDCMD_CONTROLTARGET_SIMULATE), + MenuItem(MENUITEM, _GETCS(s_csDIRRUN), IDCMD_CONTROLTARGET_DIRRUN), + MenuItem(MENUITEM, _GETCS(s_csSIMUCUTBOUNDRECT), IDCMD_CONTROLTARGET_SIMUCUT), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_csSTARTNEAR), IDCMD_CONTROLTARGET_STARTNEARPOINT), + MenuItem(MENUITEM, _GETCS(s_csCRCRUN), IDCMD_CYCMACHININGTARGET_CYCMACHINING), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_csMARKPOSITION), IDCMD_MARKPOINTTARGET_MARKPOINT), + MenuItem(MENUITEM, _GETCS(s_szMENU_VIEW_SETORIGINPOSITION), IDCMD_SETORIGIN_SET), + MenuItem(POPUP, _GETCS(s_csSetWorkOrigin)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_csSetWorkOriginXY), IDCMD_CONTROLTARGET_CLEARW), + MenuItem(MENUITEM, _GETCS(s_csSetWorkOriginZ), IDCMD_CONTROLTARGET_CLEARWZ), + MenuItem(END), + MenuItem(MENUITEM, _GETCS(s_csWCSAdjust), IDCMD_WCSADJUSTTARGET_SETTING), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _strAjustDlgTitle, IDCMD_ANALOGCONTROLTARGET_ANALOGCONTROL), + MenuItem(MENUITEM, _GETCS(s_csCATCHPOWER), IDCMD_CATCHPOWERTARGET_CATCH), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_csAUTOCLEAN), IDCMD_AUTOCLEANTARGET_AUTOCLEAN), + MenuItem(MENUITEM, _GETCS(s_csAUTOLUBRICATE), IDCMD_LUBRICATETARGET_LUBRICATE), + MenuItem(MENUITEM, _GETCS(s_csFPMAPPING), IDCMD_FPMAPPING_SETFPMAPPING), + MenuItem(END), + + // 管理 ---- 吴畏 2017-02-09 + MenuItem(POPUP, _GETCS(s_szMENU_MANAGE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_MACH_STATISTICS), IDCMD_RUNREPORTTARGET_SHOWSTATISTICS), + MenuItem(MENUITEM, _GETCS(s_szMENU_HELP_LOG), IDCMD_LOGTARGET_LOG), + MenuItem(END), + + // 系统 ---- 边俊霞 2016-06-08 + MenuItem(POPUP, _GETCS(s_szMENU_SYSTEM)), + MenuItem(BEGIN), + MenuItem(POPUP, _GETCS(s_szMENU_HELP_LANGUAGE)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _T("0"), IDCMD_LANGUAGETARGET_LANG0), + MenuItem(END), + MenuItem(POPUP, _GETCS(s_szMENU_MACH_CONFIG)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _T("0"), IDCMD_CONFIGTARGET_CONFIG0), + MenuItem(END), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_MACH_RECTTUBECONFIG), IDCMD_TUBECTRLTARGET_PARAMSET), + MenuItem(MENUITEM, _GETCS(s_szMENU_MACH_PARAM), IDCMD_PARAMMANAGERTARGET_SHOWPARAM), + MenuItem(MENUITEM, _GETCS(s_szMENU_MACH_PORTS), IDCMD_PORTSTARGET_SETTING), + MenuItem(MENUITEM, _GETCS(s_csFOLLOWCONTROL), IDCMD_CONTROLTARGET_FOLLOWCONTROL), + MenuItem(MENUITEM, _GETCS(s_csFOCUSCONTROL), IDCMD_FOCUSCONTROLTARGET_FOCUSCONTROL), + MenuItem(MENUITEM, _GETCS(s_csWORKBENCHCONTROL), IDCMD_EXCHANGEWORKBENCHTARGET_EXCHANGEWORKBENCH), + MenuItem(MENUITEM, _GETCS(s_csAXESERR), IDCMD_AXESERRTARGET_AXESERR), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_MAKESETUP), IDCMD_CONFIGTARGET_PACKER), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_PARAMBACKUP), IDCMD_CONFIGTARGET_PARAMBACKUP), + MenuItem(MENUITEM, _GETCS(s_szMENU_HELP_DIAGNOSE), IDCMD_DIAGNOSETARGET_TESTING), + MenuItem(END), + + // 维护 ---- 吴畏 2017-02-09 + MenuItem(POPUP, _GETCS(s_szMENU_MAINTAIN)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_PHONECALL), IDCMD_APPEXITTARGET_PHONEHELP), + MenuItem(MENUITEM, _GETCS(s_szMENU_REMOTE), IDCMD_APPEXITTARGET_REMOTE), + MenuItem(MENUITEM, NULL), + MenuItem(MENUITEM, _GETCS(s_szMENU_APPEXIT_RESTARTSOFTWARE), IDCMD_APPEXITTARGET_RESTARTSOFTWARE), + MenuItem(MENUITEM, _GETCS(s_szMENU_APPEXIT_SHUTDOWNOPERATESYSTEM), IDCMD_APPEXITTARGET_SHUTDOWMSYSTEM), + MenuItem(MENUITEM, _GETCS(s_szMENU_APPEXIT_REBOOTOPERATESYSTEM), IDCMD_APPEXITTARGET_REBOOTSYSTEM), + MenuItem(MENUITEM, _GETCS(s_szMENU_APPEXIT_SHOWDESKTOP), IDCMD_APPEXITTARGET_SHOWDESKTOP), + MenuItem(MENUITEM, _GETCS(s_szMENU_FILE_EXIT), ID_APP_EXIT), + MenuItem(END), + + // 帮助 ---- 杨开锦 2010-06-07 + MenuItem(POPUP, _GETCS(s_szMENU_HELP)), + MenuItem(BEGIN), + MenuItem(MENUITEM, _GETCS(s_szMENU_SHORTCUTKEY), IDCMD_HELPTARGET_SHORTCUTKEY), + MenuItem(MENUITEM, _GETCS(s_szMENU_USERMANUAL), IDCMD_HELPTARGET_USERMANUAL), + MenuItem(MENUITEM, _GETCS(s_szMENU_DAILYTIPS), IDCMD_HELPTARGET_DAILYTIPS), + _MenuItemWeihongIntro, + MenuItem(MENUITEM, _GETCS(s_szMENU_HELP_DIAGNOSE), IDCMD_DIAGNOSETARGET_TESTING), + MenuItem(MENUITEM, _GETCS(s_szMENU_HELP_ABOUT), ID_APP_ABOUT), + MenuItem(END), + MenuItem(END), + }; + + // 拷贝到m_MenuItems ---- 杨开锦 2010-06-08 + UINT _nCount = _countof(_MenuItems); + for (UINT _i = 0; _i < _nCount; _i++) + m_MenuItems[_i] = _MenuItems[_i]; + + m_nValidMenuItem = _nCount; + } + else + { + ASSERT(FALSE); + } + + return TRUE; +} diff --git a/src/GCodeSemanticAnalyser.cpp b/src/GCodeSemanticAnalyser.cpp new file mode 100644 index 0000000..896a94b --- /dev/null +++ b/src/GCodeSemanticAnalyser.cpp @@ -0,0 +1,2175 @@ +#include "stdafx.h" +#include "ParserModuleHeader.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +using namespace NcInterpAxes3; + +// 这里列出的是对于省略G地址字的情况下,由相应的地址字可以推导出的G代码列表 +// 可以省略的G地址字目前包括:G 0, 1, 2, 3, 7, 73, 74, 76, 81, 82, 83, 84, 85, 86, 87, 88, 89 +// 由m_pParserModule->m_ModalData.m_nGNumber标示,下表仅仅用于检查有效性。 +// +// 下列中,在V8,V9的基础上修改过的指令有: +// TK_ADR_H原对应{TK_ADR_H, 7, -1},说明:G7指令中并不包含H,仅G43,G49,M902,M903包含,且会在实现中被Match +// TK_ADR_I/TK_ADR_J原对应{TK_ADR_I, 2, 3, 76, -1},说明:G76的格式中并不包含I,J,G76 X_Y_Z_R_Q_P_F_K_ +// TK_ADR_P原对应{TK_ADR_P, 74, 76, 82, 84, 89, -1},意味着可以同一位置重复打孔,暂停时间不同,同理G87,G88可以支持 +const int CGCodeSemanticAnalyser::m_MatchGScope[][32] = +{ + {TK_ADR_FIRST, -1}, + {TK_ADR_A, -1}, + {TK_ADR_B, -1}, + {TK_ADR_C, -1}, + {TK_ADR_D, -1}, + {TK_ADR_E, -1}, + {TK_ADR_F, -1}, + {TK_ADR_G, -1}, + {TK_ADR_H, -1}, + {TK_ADR_I, 2, 3, -1}, + {TK_ADR_J, 2, 3, -1}, + {TK_ADR_K, 2, 3, -1}, + {TK_ADR_L, -1}, + {TK_ADR_M, -1}, + {TK_ADR_N, -1}, + {TK_ADR_O, -1}, + {TK_ADR_P, 74, 76, 82, 84, 87, 88, 89, -1}, + {TK_ADR_Q, 73, 83, -1}, + {TK_ADR_R, 2, 3, -1}, + {TK_ADR_S, -1}, + {TK_ADR_T, -1}, + {TK_ADR_U, -1}, + {TK_ADR_V, -1}, + {TK_ADR_W, -1}, + {TK_ADR_X, 0, 1, 2, 3, 7, 73, 74, 76, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1}, + {TK_ADR_Y, 0, 1, 2, 3, 7, 73, 74, 76, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1}, + {TK_ADR_Z, 0, 1, 2, 3, 7, 73, 74, 76, 81, 82, 83, 84, 85, 86, 87, 88, 89, -1}, + {TK_ADR_FX, -1}, + {TK_ADR_FY, -1}, + {TK_ADR_FZ, -1}, + {TK_ADR_FA, -1}, + {TK_ADR_FB, -1}, + {TK_ADR_FC, -1}, + {TK_ADR_LEVEL, -1}, + {TK_ADR_LX, -1}, + {TK_ADR_LY, -1}, + {TK_ADR_LZ, -1}, + {TK_ADR_LA, -1}, + {TK_ADR_LB, -1}, + {TK_ADR_LC, -1}, + {TK_ADR_MSG, -1}, + {TK_ADR_PLC, -1}, + {TK_ADR_PX, -1}, + {TK_ADR_PY, -1}, + {TK_ADR_PZ, -1}, + {TK_ADR_PA, -1}, + {TK_ADR_PB, -1}, + {TK_ADR_PC, -1}, + {TK_ADR_SYNCPOS, -1}, + {TK_ADR_LAST, -1}, +}; + +// Note:为了提高查找的效率,最常用的规则放在最前边! +const CGCodeSemanticAnalyser::rule_t CGCodeSemanticAnalyser::m_RuleList_Pre[] = +{ + // token, value, func + {TK_ADR_G, 53, &G53}, + {TK_ADR_G, 54, &SelectWorkCoor}, + {TK_ADR_G, 55, &SelectWorkCoor}, + {TK_ADR_G, 56, &SelectWorkCoor}, + {TK_ADR_G, 57, &SelectWorkCoor}, + {TK_ADR_G, 58, &SelectWorkCoor}, + {TK_ADR_G, 59, &SelectWorkCoor}, + {TK_ADR_G, 68, &G68}, + {TK_ADR_G, 69, &G69}, + + {TK_ADR_G, 90, &G90_G91}, + {TK_ADR_G, 91, &G90_G91}, + + {TK_ADR_G, 17, &G17_G18_G19}, + {TK_ADR_G, 18, &G17_G18_G19}, + {TK_ADR_G, 19, &G17_G18_G19}, + + {TK_ADR_G, 20, &G20_G21_G70_G71}, + {TK_ADR_G, 21, &G20_G21_G70_G71}, + {TK_ADR_G, 70, &G20_G21_G70_G71}, + {TK_ADR_G, 71, &G20_G21_G70_G71}, + + {TK_ADR_S, -1, &SpindleRev}, + {TK_ADR_F, -1, &FeedRate}, + + {TK_ADR_G, 98, &G98_G99}, + {TK_ADR_G, 99, &G98_G99}, + + {TK_ADR_G, 40, &G40}, + {TK_ADR_G, 41, &G41_G42}, + {TK_ADR_G, 42, &G41_G42}, + {TK_ADR_G, 43, &G43_G44}, + {TK_ADR_G, 44, &G43_G44}, + {TK_ADR_G, 49, &G49}, + + {TK_ADR_G, 50, &G50}, + {TK_ADR_G, 51, &G51}, + {TK_ADR_G, 50.1, &G50_1}, + {TK_ADR_G, 51.1, &G51_1}, + + {TK_ADR_G, 92, &G92}, + {TK_ADR_G, 992, &G992}, + {TK_ADR_G, 921, &G921}, + {TK_ADR_G, 922, &G922}, + {TK_ADR_G, 923, &G923}, + + {TK_ADR_G, 905, &G905}, + {TK_ADR_G, 907, &G907}, + {TK_ADR_G, 908, &G908}, + {TK_ADR_M, 0, &M0_M1}, + {TK_ADR_M, 1, &M0_M1}, + {TK_ADR_M, 2, &M2_M30}, + {TK_ADR_M, 3, &M3_M4_M5}, + {TK_ADR_M, 4, &M3_M4_M5}, + {TK_ADR_M, 5, &M3_M4_M5}, + {TK_ADR_M, 801, &M801}, + {TK_ADR_M, 802, &M802}, + {TK_ADR_M, 901, &M901}, + {TK_ADR_M, 902, &M902}, + {TK_ADR_M, 903, &M903}, + {TK_ADR_M, 904, &M904_M905}, + {TK_ADR_M, 905, &M904_M905}, +}; + +const CGCodeSemanticAnalyser::rule_t CGCodeSemanticAnalyser::m_RuleList_Normal[] = +{ + // token, value, func + {TK_ADR_G, 1, &G0_G1}, + {TK_ADR_G, 0, &G0_G1}, + {TK_ADR_G, 2, &G2_G3}, + {TK_ADR_G, 3, &G2_G3}, + {TK_ADR_G, 4, &G4}, + {TK_ADR_G, 7, &G7}, + {TK_ADR_G, 28, &G28}, + {TK_ADR_G, 65, &G65_M98}, + + {TK_ADR_G, 34, &G34_G36}, + {TK_ADR_G, 35, &G35}, + {TK_ADR_G, 36, &G34_G36}, + {TK_ADR_G, 37, &G37}, + + {TK_ADR_G, 73, &FixedCycle}, + {TK_ADR_G, 74, &FixedCycle}, + {TK_ADR_G, 75, &FixedCycle}, + {TK_ADR_G, 76, &FixedCycle}, + {TK_ADR_G, 77, &FixedCycle}, + {TK_ADR_G, 78, &FixedCycle}, + {TK_ADR_G, 79, &FixedCycle}, + {TK_ADR_G, 80, &G80}, + {TK_ADR_G, 81, &FixedCycle}, + {TK_ADR_G, 82, &FixedCycle}, + {TK_ADR_G, 83, &FixedCycle}, + {TK_ADR_G, 84, &FixedCycle}, + {TK_ADR_G, 85, &FixedCycle}, + {TK_ADR_G, 86, &FixedCycle}, + {TK_ADR_G, 87, &FixedCycle}, + {TK_ADR_G, 88, &FixedCycle}, + {TK_ADR_G, 89, &FixedCycle}, + + {TK_ADR_G, 903, &G903}, + {TK_ADR_G, 904, &G904}, + {TK_ADR_G, 906, &G906}, + {TK_ADR_G, 925, &G925_G926}, + {TK_ADR_G, 926, &G925_G926}, + {TK_ADR_G, 927, &G927}, + {TK_ADR_SYNCPOS, -1, &SyncPos}, + {TK_ADR_G, 9, &G9}, +}; + +const CGCodeSemanticAnalyser::rule_t CGCodeSemanticAnalyser::m_RuleList_Post[] = +{ + {TK_ADR_X, -1, &MatchG}, + {TK_ADR_Y, -1, &MatchG}, + {TK_ADR_Z, -1, &MatchG}, + {TK_ADR_T, -1, &M6_T}, + {TK_ADR_H, -1, &Rule_Error}, + {TK_ADR_I, -1, &MatchG}, + {TK_ADR_J, -1, &MatchG}, + {TK_ADR_K, -1, &MatchG}, + {TK_ADR_L, -1, &Rule_Error}, + {TK_ADR_LX, -1, &Rule_Error}, + {TK_ADR_LY, -1, &Rule_Error}, + {TK_ADR_LZ, -1, &Rule_Error}, + {TK_ADR_M, 6, &M6_T}, + {TK_ADR_M, 17, &M17_M99}, + {TK_ADR_M, 98, &G65_M98}, + {TK_ADR_M, 99, &M17_M99}, + {TK_ADR_M, 30, &M2_M30}, + {TK_ADR_MSG, -1, &Rule_Error}, + {TK_ADR_P, -1, &MatchG}, + {TK_ADR_PX, -1, &Rule_Error}, + {TK_ADR_PY, -1, &Rule_Error}, + {TK_ADR_PZ, -1, &Rule_Error}, + {TK_ADR_Q, -1, &MatchG}, + {TK_ADR_R, -1, &MatchG}, + {TK_ADR_D, -1, &Rule_Error}, + {TK_ADR_FX, -1, &Rule_Error}, + {TK_ADR_FY, -1, &Rule_Error}, + {TK_ADR_FZ, -1, &Rule_Error}, + {TK_ADR_PLC, -1, &Ignore}, + {TK_ADR_LEVEL, -1, &Ignore}, + {TK_ADR_A, -1, &Ignore}, + {TK_ADR_B, -1, &Ignore}, + {TK_ADR_C, -1, &Ignore}, + {TK_ADR_U, -1, &Ignore}, + {TK_ADR_V, -1, &Ignore}, + {TK_ADR_W, -1, &Ignore}, + + {TK_ADR_G, -1, &GUnknown}, + {TK_ADR_M, -1, &MUnknown}, +}; + +CGCodeSemanticAnalyser::CGCodeSemanticAnalyser(CParserModule* pParserModule_, const CCodeBuffer* pCodeBuffer_) +: CGCodeSyntaxAnalyser(pParserModule_, pCodeBuffer_) +, m_bIs1stMovingCode(true) +{ + // set in base-class' construction + ASSERT(m_pInterpEngine); + ASSERT(m_pParserModule); +#ifdef G00MOVING + m_bCallBack = false; + m_nCurEntityIndex = 0; +#endif + + m_FlagsForCurrentEntity.Reset(); + m_Position.nAnchorType = ANCH_FILEPOS; + m_Position.nFilePos = 0; + m_Position.nStatementCount = 0; + + for (int _i = 0, _size = _countof(m_MatchGScope); _i < _size; ++_i) + ASSERT (m_MatchGScope[_i][0] - TK_ADR_FIRST == _i); +} + +CGCodeSemanticAnalyser::~CGCodeSemanticAnalyser() +{ +} + +void CGCodeSemanticAnalyser::Reset() +{ + CGCodeSyntaxAnalyser::Reset(); + m_FlagsForCurrentEntity.Reset(); + m_bIs1stMovingCode = true; +#ifdef G00MOVING + m_bCallBack = false; + m_nCurEntityIndex = 0; +#endif + m_Position.nAnchorType = ANCH_FILEPOS; + m_Position.nFilePos = 0; + m_Position.nStatementCount = 0; +} + +// 类的主要功能实现函数,更新文件位置,分析G代码,生成NcCode +// -fangmin 2010/01/25 +void CGCodeSemanticAnalyser::ReadCode() +{ + m_Entities.Reset(); + + if (IsMainParser()) + { + int _nFilePos = (int)GetPosition(); + m_pParserModule->m_CodePosition.nFilePos = _nFilePos; + } + do + { + if (GetPosition() >= m_nLength) + break; + + m_Position.nFilePos = (int)GetPosition(); + m_Position.nStatementCount++; + m_pParserModule->m_CodePosition.nStatementCount++; + Statement(); + } while (m_Entities.GetCount() == 0); + + if (m_Entities.GetCount() > 0) + { +#ifdef G00MOVING + if (m_nCurEntityIndex >= m_Entities.GetCount()) + ASSERT(false); + m_Entities.SetCurIndex(m_nCurEntityIndex); +#endif + AnalyseEntities(); + } +} + +void CGCodeSemanticAnalyser::AnalyseEntities() +{ + int _nSizeOfListOld = m_pParserModule->m_pNCCodeOutputList->GetCount(); + CFilePosition _FilePosBk = m_pParserModule->m_CodePosition; + + while (true) + { +#ifdef G00MOVING + m_nCurEntityIndex = m_Entities.GetCurIndex(); + AnalyseCurrentEntity(); + if (!m_Entities.MoveForWard()) + { + m_nCurEntityIndex = 0; + break; + } +#else + AnalyseCurrentEntity(); + if (!m_Entities.MoveForWard()) + break; +#endif + } + + int _nSizeOfListNew = m_pParserModule->m_pNCCodeOutputList->GetCount(); + // 调用子程序前,更新文件位置 + // -fangmin 2010/01/25 + if (!m_pInterpEngine->IsTracking() && (_nSizeOfListNew == _nSizeOfListOld)) + { + CNcFilePosition _NcFilePos(NCFCFILEPOSITION, _FilePosBk); + m_pParserModule->AddTailCode(_NcFilePos); + } +} + +void CGCodeSemanticAnalyser::AnalyseCurrentEntity() +{ + CParserModule::_speed _SpeedOld = m_pParserModule->m_SpeedRecord.Speed; + m_MatchedGroups.Reset(); + + const rule_t* _pRule = NULL; + + CTaggedEntity& _CurEntity = m_Entities.GetCurrentEntity(); + int _nSize = _CurEntity.GetCount(); + ASSERT(_nSize > 0); + + int _i; + + // pre rule + for (_i = 0; _i < _nSize; _i++) + { + if (_CurEntity[_i].m_bDeleted) + continue; + + _pRule = GetRule_Pre(_CurEntity[_i].m_nToken, _CurEntity[_i].m_nValue); + if (_pRule) + { + (this->*_pRule->pFunction) (&_CurEntity[_i]); +#ifdef G00MOVING + if (m_bCallBack) + { + ASSERT(false); + // 这里不应直接使用到,优先级最高的规则,一般不会调用子程序 + // -fangmin -2010-02-01 + m_bCallBack = false; + return; + } +#endif + } + } + + // normal rule + for (_i = 0; _i < _nSize; _i++) + { + if (_CurEntity[_i].m_bDeleted) + continue; + + _pRule = GetRule_Normal(_CurEntity[_i].m_nToken, _CurEntity[_i].m_nValue); + if (_pRule) + { + (this->*_pRule->pFunction) (&_CurEntity[_i]); +#ifdef G00MOVING + if (m_bCallBack) + { + m_bCallBack = false; + return; + } +#endif + } + } + + // post rule + for (_i = 0; _i < _nSize; _i++) + { + if (_CurEntity[_i].m_bDeleted) + continue; + + _pRule = GetRule_Post(_CurEntity[_i].m_nToken, _CurEntity[_i].m_nValue); + if (_pRule) + { + (this->*_pRule->pFunction) (&_CurEntity[_i]); +#ifdef G00MOVING + if (m_bCallBack) + { + ASSERT(false); + // 这里目前不会使用到,但是可以支持使用 + // 如果修改G65的调用规则,使用m_nCurEntityIndex,就可以支持此类指令 + // G01 X10; G65 P"TOORG" L1; G01 X10 + // 目前对于该指令的解析,G01 X10这句是不执行的 + // -fangmin -2010-02-01 + m_bCallBack = false; + return; + } +#endif + } + else + { + m_strTemp.Format(c_szERROR_UNKOWN_TOKEN, + GetTokenAlias(_CurEntity[_i].m_nToken), + (int) (_CurEntity[_i].m_nValue)); + ErrorHandler(m_strTemp); + } + } + + // G53,G903,G905,G907,G908仅对本条语句有效 + m_FlagsForCurrentEntity.Reset(); + // 处理G905仅对本条语句有效,恢复原速度 + if(!m_pParserModule->m_SpeedRecord.bModal) + { + m_pParserModule->SetSpeed(_SpeedOld); + m_pParserModule->m_SpeedRecord.bModal = true; + } + + return; +} + +// Forward rules +void CGCodeSemanticAnalyser::G0_G1(CTaggedData* pTaggedData_) +{ + if (!m_MatchedGroups.SetMatched(G_GROUP_MOVE)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + int _nGNumber = m_pParserModule->m_ModalData.GetGNumber(G_GROUP_MOVE); + NC_FUNCTION_TAG _nTag = (_nGNumber == 1) ? NCFGLINEARINTERP : NCFGRAPIDTRAVERSE; + if (TK_ADR_G == pTaggedData_->m_nToken) + { + int _nGNumberNew = (int) pTaggedData_->m_nValue; + _nTag = (_nGNumberNew == 1) ? NCFGLINEARINTERP : NCFGRAPIDTRAVERSE; +#ifdef G00MOVING + // 条件1是防止G00-LEAVE、G00-ENTER子程序中含有运动指令,重复判断,形成死循环 + // -fangmin 2010-02-01 + if (m_pParserModule->m_nLastCodeTag == _nGNumber && + m_pParserModule->m_nLastCodeTag != _nGNumberNew) + { + if (m_pParserModule->m_nLastCodeTag == NCFGRAPIDTRAVERSE) + { + m_bCallBack = true; + m_pParserModule->MakeCall("G00-LEAVE", 1, m_Position.nFilePos, m_nCurEntityIndex); + } + else if (_nGNumberNew == NCFGRAPIDTRAVERSE) + { + m_bCallBack = true; + m_pParserModule->MakeCall("G00-ENTER", 1, m_Position.nFilePos, m_nCurEntityIndex); + } + m_pParserModule->m_nLastCodeTag = _nGNumberNew; + if (m_bCallBack) + return; + } +#endif + _nGNumber = _nGNumberNew; + MatchTaggedData(TK_ADR_G, _nGNumber); + m_pParserModule->ChangeModal(G_GROUP_MOVE, _nGNumber); + } + + INTERPDOUBLE _nxStartPos = m_pParserModule->m_nxJumpPos; + + RetrieveDestPosition(); + m_pParserModule->m_nxJumpPos = m_pParserModule->m_nxDestPos; + + double _nSpeed = m_pParserModule->m_SpeedRecord.Speed.nSpeedG00; + m_pParserModule->m_SpeedRecord.bValidG00 = true; + if (_nGNumber == 1) + { + _nSpeed = m_pParserModule->m_SpeedRecord.Speed.nSpeedGxx; + m_pParserModule->m_SpeedRecord.bValidG00 = false; + } + + m_pParserModule->UpdateCutterCompStatus(); + + CNcLine _NcLine(_nTag, _nSpeed, m_pParserModule->m_CodePosition); + _NcLine.OrigSetStartPos(_nxStartPos); + _NcLine.OrigSetEndPos(m_pParserModule->m_nxDestPos); + _NcLine.m_bFrpIs100 = m_FlagsForCurrentEntity.m_bFrpIs100; + _NcLine.m_bTrackShortCut = m_FlagsForCurrentEntity.m_bTrackShortCut; + + if (m_pParserModule->m_bRevolving && m_bIs1stMovingCode && (NCFGRAPIDTRAVERSE == _nTag)) + { + _NcLine.m_bTrackShortCut = true; + } + // 与V9不同的处理,认为无论是否满足上个if的条件,经过了本函数过均不能作为第一条指令 + // m_bIs1stMovingCode的判断默认了用户开始加工后,加工范围在周长之内,中间的定位不需要作最短路径处理 + m_bIs1stMovingCode = false; + + m_pParserModule->AddTailCode(_NcLine); + return; +} + +//顺时针(G02)逆时针(G03)加工圆弧 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G2_G3(CTaggedData* pTaggedData_) +{ + if (!m_MatchedGroups.SetMatched(G_GROUP_MOVE)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + int _nGNumber = m_pParserModule->m_ModalData.GetGNumber(G_GROUP_MOVE); + NC_FUNCTION_TAG _nTag = (_nGNumber == 3) ? NCFGARCINTERPCCW : NCFGARCINTERPCW; + if (TK_ADR_G == pTaggedData_->m_nToken) + { + int _nGNumberNew = (int) pTaggedData_->m_nValue; + _nTag = (_nGNumberNew == 3) ? NCFGARCINTERPCCW : NCFGARCINTERPCW; +#ifdef G00MOVING + // 条件1是防止G00-LEAVE、G00-ENTER子程序中含有运动指令,重复判断,形成死循环 + // -fangmin 2010-02-01 + if (m_pParserModule->m_nLastCodeTag == _nGNumber && + m_pParserModule->m_nLastCodeTag != _nGNumberNew) + { + if (m_pParserModule->m_nLastCodeTag == NCFGRAPIDTRAVERSE) + { + m_bCallBack = true; + m_pParserModule->MakeCall("G00-LEAVE", 1, m_Position.nFilePos, m_nCurEntityIndex); + } + m_pParserModule->m_nLastCodeTag = _nGNumberNew; + if (m_bCallBack) + return; + } +#endif + _nGNumber = _nGNumberNew; + MatchTaggedData(TK_ADR_G, _nGNumber); + m_pParserModule->ChangeModal(G_GROUP_MOVE, _nGNumber); + } + + m_pParserModule->UpdateCutterCompStatus(); + INTERPDOUBLE _nxStartPos = m_pParserModule->m_nxJumpPos; + + RetrieveDestPosition(); + m_pParserModule->m_nxJumpPos = m_pParserModule->m_nxDestPos; + + m_pParserModule->m_SpeedRecord.bValidG00 = false; + + CNcArc _NcArc(_nTag, + m_pParserModule->m_SpeedRecord.Speed.nSpeedGxx, + m_pParserModule->m_CodePosition); + try + { + RetrieveArcParameters(&_NcArc); + m_pParserModule->AddTailCode(_NcArc); + } + catch (CEngineError pe) + { + throw pe; + } + + m_bIs1stMovingCode = false; + return; +} + +//加工样条 未实现 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G7(CTaggedData* pTaggedData_) +{ + if (!m_MatchedGroups.SetMatched(G_GROUP_MOVE)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + ErrorHandler(c_szERROR_DONOTSUPPORTNURBSINTERP); + ///////////////////////////////////////////////////////////////// + // When deal with NORM Rule instruction, + // The PRE instruction were disappeared all, + // Only POST && NORM are all right. + int _nGNumber = m_pParserModule->m_ModalData.GetGNumber(G_GROUP_MOVE); + NC_FUNCTION_TAG _nTag = NCFGNURBS; + if (TK_ADR_G == pTaggedData_->m_nToken) + { + _nGNumber = (int) pTaggedData_->m_nValue; + MatchTaggedData(TK_ADR_G, _nGNumber); + m_pParserModule->ChangeModal(G_GROUP_MOVE, _nGNumber); + } + + INTERPDOUBLE _nxStartPos = m_pParserModule->m_nxJumpPos; + + RetrieveDestPosition(); + + m_pParserModule->m_SpeedRecord.bValidG00 = false; + m_pParserModule->m_nxJumpPos = m_pParserModule->m_nxDestPos; + + //CNcNurbs _NcNurbs(m_pInterpEngine, NCFGNURBS, m_pParserModule->m_SpeedRecord.Speed.nSpeedGxx, + // m_pParserModule->m_CodePosition); + //_NcNurbs.SetStartPos(_nxStartPos); + //_NcNurbs.SetEndPos(m_pParserModule->m_nxDestPos); + //_NcNurbs.m_bFrpIs100 = m_FlagsForCurrentEntity.m_bFrpIs100; + //m_pParserModule->AddTailCode(_NcNurbs); + m_bIs1stMovingCode = false; + + return; +} + +//处理暂停指令 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G4(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 4); + //UNREFERENCED_PARAMETER(pTaggedData_); + + if (!m_MatchedGroups.SetMatched(G_GROUP_PAUSE)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + MatchTaggedData(TK_ADR_G, 4); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_P)) + { + m_strTemp.Format(c_szERROR_NOENOUGHPARAMETERS, "G04"); + ErrorHandler(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_P); + + int _nPauseTime = (int)m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + m_pParserModule->AddPauseCode(_nPauseTime); + + return; +} + +void CGCodeSemanticAnalyser::G9(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 9); + UNREFERENCED_PARAMETER(pTaggedData_); + + if (!m_MatchedGroups.SetMatched(G_GROUP_CORRECTPOSITION)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + MatchTaggedData(TK_ADR_G, 9); + + if (!m_pInterpEngine->IsMachining()) + return; + if (m_pParserModule->IsJumping()) + return; + + CNcCode _NcCorrectPosition(NCFGCORRECTPOSITION, + m_pParserModule->m_CodePosition); + m_pParserModule->AddTailCode(_NcCorrectPosition); + + return; +} + +//确定加工平面 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G17_G18_G19(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int) pTaggedData_->m_nValue; + ASSERT(_nGNumber == 17 || _nGNumber == 18 || _nGNumber == 19); + + if (!m_MatchedGroups.SetMatched(G_GROUP_PLANE)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + MatchTaggedData(TK_ADR_G, _nGNumber); + m_pParserModule->ChangeModal(G_GROUP_PLANE, _nGNumber); +} + +//确定加工单位是公制还是英制 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G20_G21_G70_G71(CTaggedData* pTaggedData_) +{ + if (!m_MatchedGroups.SetMatched(G_GROUP_UNIT)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + int _nGNumber = (int) pTaggedData_->m_nValue; + MatchTaggedData(TK_ADR_G, _nGNumber); + m_pParserModule->ChangeModal(G_GROUP_UNIT, _nGNumber); +} + +// Go to machine zero reference through middle point for specified axis. +void CGCodeSemanticAnalyser::G28(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 28); + UNREFERENCED_PARAMETER(pTaggedData_); + + if (!m_MatchedGroups.SetMatched(G_GROUP_MOVE)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + +#ifdef G00MOVING + if (m_pParserModule->m_nLastCodeTag != NCFGRAPIDTRAVERSE) + { + m_bCallBack = true; + m_pParserModule->MakeCall("G00-ENTER", 1, m_Position.nFilePos, m_nCurEntityIndex); + m_pParserModule->m_nLastCodeTag = NCFGRAPIDTRAVERSE; + return; + } +#endif + MatchTaggedData(TK_ADR_G, 28); + + INTERPBOOL _axFind(false, false, false); + for (int _i = 0, _nIndex; _i < c_nNUMOF_AXIS; _i++) + { + token_t _token = c_tkAxisToken[_i]; + if (SearchTaggedData(&_nIndex, _token)) + _axFind[_i] = true; + } + + RetrieveDestPosition(); + + if (m_pParserModule->IsJumping() || m_pInterpEngine->IsTracking()) + return; + + INTERPDOUBLE _nxMidPos = m_pParserModule->m_nxDestPos; + + for (int _nAxis = 0; _nAxis < c_nNUMOF_AXIS; _nAxis++) + { + if (_axFind[_nAxis]) + m_pParserModule->m_nxDestPosOrig[_nAxis] = m_pParserModule->m_nxRef[_nAxis]; + } + + _Transform(m_pParserModule->m_nxDestPosOrig, m_pParserModule->m_nxDestPos); + CheckWCSLimit(m_pParserModule->m_nxCurPos, m_pParserModule->m_nxDestPos); + + INTERPDOUBLE _nxEndPos = m_pParserModule->m_nxDestPos; + + CNcLine _NcLine(NCFGRAPIDTRAVERSE, + m_pParserModule->m_SpeedRecord.Speed.nSpeedG00, + m_pParserModule->m_CodePosition); + _NcLine.OrigSetStartPos(m_pParserModule->m_nxJumpPos); + _NcLine.OrigSetEndPos(_nxMidPos); + m_pParserModule->m_nxJumpPos = _nxMidPos; + _NcLine.m_bFrpIs100 = m_FlagsForCurrentEntity.m_bFrpIs100; + m_pParserModule->AddTailCode(_NcLine); + + _NcLine.OrigSetStartPos(m_pParserModule->m_nxJumpPos); + _NcLine.OrigSetEndPos(_nxEndPos); + _NcLine.m_bFrpIs100 = m_FlagsForCurrentEntity.m_bFrpIs100; + m_pParserModule->AddTailCode(_NcLine); + m_pParserModule->m_nxJumpPos = _nxEndPos; + m_bIs1stMovingCode = false; + + return; +} + +//取消刀具半径补偿 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G40(CTaggedData* pTaggedData_) +{ + int _nGNumber = int(pTaggedData_->m_nValue); + MatchTaggedData(pTaggedData_->m_nToken, _nGNumber); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(_nGNumber == 40); + UNREFERENCED_PARAMETER(pTaggedData_); + m_pParserModule->ChangeModal(G_GROUP_CRC, _nGNumber); +} + +//刀具半径左补偿(G41),或刀具半径右补偿(G42) wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G41_G42(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int) pTaggedData_->m_nValue; + ASSERT(_nGNumber == 41 || _nGNumber == 42); + + if (!m_MatchedGroups.SetMatched(G_GROUP_CRC)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + MatchTaggedData(TK_ADR_G, _nGNumber); + m_pParserModule->ChangeModal(G_GROUP_CRC, _nGNumber); + + // 刀补指令中没有指令D字时,默认使用1号刀 + int _nToolIndex; + int _nIndex; + if (SearchTaggedData(&_nIndex, TK_ADR_D)) + { + MatchTaggedData(_nIndex, TK_ADR_D); + _nToolIndex = (int) m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + if (_nToolIndex < 0 || _nToolIndex >= m_pParserModule->m_nToolLibSize) + { + ErrorHandler(c_szERROR_TOOLNUMBEROVERFLOW); + } + } + else + { + _nToolIndex = 1; + NcInterpAxes3::ShowMessage(c_szERROR_G41G42D); + } + + CNcChangeCRC _NcChangeCRC(m_pParserModule->m_CodePosition); + _NcChangeCRC.m_nCRCRadius = fabs(m_pParserModule->m_nToolDiameter[_nToolIndex] / 2.); + m_pParserModule->AddTailCode(_NcChangeCRC); +} + +//刀具长度正向补偿(G43),刀具长度负向补偿(G44) wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G43_G44(CTaggedData* pTaggedData_) +{ + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int) pTaggedData_->m_nValue; + ASSERT(_nGNumber == 43 || _nGNumber == 44); + UNREFERENCED_PARAMETER(pTaggedData_); + + if (!m_MatchedGroups.SetMatched(G_GROUP_CLC)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_H)) + { + m_strTemp.Format(c_szERROR_NOENOUGHPARAMETERS, "G43/G44"); + ErrorHandler(m_strTemp); + } + m_pParserModule->ChangeModal(G_GROUP_CLC, _nGNumber); + + MatchTaggedData(_nIndex, TK_ADR_H); + int _nToolIndex = (int) m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + if (_nToolIndex < 0 || _nToolIndex >= m_pParserModule->m_nToolLibSize) + { + ErrorHandler(c_szERROR_TOOLNUMBEROVERFLOW); + } + double _nLength = m_pParserModule->m_nToolLength[_nToolIndex]; + CNcChangeCLC _NcChangeCLC(m_pParserModule->m_CodePosition); + _NcChangeCLC.m_nCLCLength = _nLength; + m_pParserModule->AddTailCode(_NcChangeCLC); +} + +//取消刀具长度补偿 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G49(CTaggedData* pTaggedData_) +{ + int _nGNumber = int(pTaggedData_->m_nValue); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(_nGNumber == 49); + MatchTaggedData(TK_ADR_G, _nGNumber); + m_pParserModule->ChangeModal(G_GROUP_CLC, _nGNumber); + + int _nIndex; + if (SearchTaggedData(&_nIndex, TK_ADR_H)) + MatchTaggedData(_nIndex, TK_ADR_H); +} + +//取消比例功能 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G50(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 50); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + m_pParserModule->ChangeModal(G_GROUP_ZOOM, 50); + + if (!m_pParserModule->KillNearTransform(CTransform::TF_ZOOM)) + ErrorHandler(c_szERROR_G51_50_NOTMATCH); + + _MoveCurPosToRespPos(); + + return; +} + +//启用比例功能 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G51(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 51); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + if (!m_MatchedGroups.SetMatched(G_GROUP_ZOOM)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + m_pParserModule->ChangeModal(G_GROUP_ZOOM, 51); + + _StoreZoomInf(pTaggedData_); + _MoveCurPosToRespPos(); + + return; +} + +//取消镜象功能 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G50_1(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ + && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 50.1); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + // Find out mirror transform + int _size = m_pParserModule->m_arrPTransform.GetSize(); + if (0 == _size) + return; + + int _i; + CMirrorTransform* _pMirrorTrans = NULL; + for (_i = 0; _i < _size; ++_i) + { + if (m_pParserModule->m_arrPTransform[_i]->m_nTransformType == CTransform::TF_MIRROR) + { + ASSERT(!_pMirrorTrans); + _pMirrorTrans = (CMirrorTransform*)m_pParserModule->m_arrPTransform[_i]; + } + } + ASSERT(_pMirrorTrans == m_pParserModule->m_arrPTransform[0]); + + bool _bSucess = false; + int _nIndex; + for (int _i = 0; _i < c_nNUMOF_AXIS; _i++) + { + token_t _token = c_tkAxisToken[_i]; + if (SearchTaggedData(&_nIndex, _token)) + { + _bSucess = true; + MatchTaggedData(_nIndex, _token); + _pMirrorTrans->m_bxMirror[_i] = false; + } + } + + if (!_bSucess || + (!_pMirrorTrans->m_bxMirror[axis::x] + && !_pMirrorTrans->m_bxMirror[axis::y] + && !_pMirrorTrans->m_bxMirror[axis::z])) + { + if (!m_pParserModule->KillNearTransform(CTransform::TF_MIRROR)) + ErrorHandler(c_szERROR_G51D1_50D1_NOTMATCH); + } + + _MoveCurPosToRespPos(); +} + +//启用镜象功能 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G51_1(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 51.1); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + if (!m_MatchedGroups.SetMatched(G_GROUP_MIRROR)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + _StoreMirrorInf(pTaggedData_); + _MoveCurPosToRespPos(); + + return; +} + +//使用机床坐标系 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G53(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 53); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + UNREFERENCED_PARAMETER(pTaggedData_); + m_FlagsForCurrentEntity.m_bUseMachineOrigin = true; +} + +//选择工件坐标系号 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::SelectWorkCoor(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nNumber = (int) pTaggedData_->m_nValue; + ASSERT(_nNumber >= 54 && _nNumber <= 59); + MatchTaggedData(pTaggedData_->m_nToken, _nNumber); + m_pParserModule->m_nWorkcoorNo = _nNumber - 54; + m_pParserModule->ChangeModal(G_GROUP_WORKCOOR, _nNumber); +} + +//子程序调用 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G65_M98(CTaggedData* pTaggedData_) +{ + ASSERT ((pTaggedData_->m_nToken == TK_ADR_G && pTaggedData_->m_nValue == 65) + || (pTaggedData_->m_nToken == TK_ADR_M && pTaggedData_->m_nValue == 98)); + + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + if (!m_MatchedGroups.SetMatched(G_GROUP_CALL)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_P)) + { + m_strTemp.Format(c_szERROR_NOENOUGHPARAMETERS, "G65/M98"); + ErrorHandler(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_P); + int _nSubProgramNo = (int) m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + LPCTSTR _pszSubProgramName = m_Entities.GetCurrentEntity()[_nIndex].m_pszValue; + + int _nCallingTimes = 1; + if (SearchTaggedData(&_nIndex, TK_ADR_L)) + { + MatchTaggedData(_nIndex, TK_ADR_L); + _nCallingTimes = (int) m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + } + + if (_nCallingTimes == 0) + return; + + if (_nSubProgramNo > 0) + m_pParserModule->MakeCall(_nSubProgramNo, _nCallingTimes); + else + m_pParserModule->MakeCall(_pszSubProgramName, _nCallingTimes); +} + +//旋转功能开 wangwenbo 2010.01.28 +void CGCodeSemanticAnalyser::G68(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 68); + MatchTaggedData(TK_ADR_G, 68); + if (!m_MatchedGroups.SetMatched(G_GROUP_G68G69)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + _StoreRevInf(pTaggedData_); + _MoveCurPosToRespPos(); + + return; +} + +//旋转功能关 wangwenbo 2010.01.28 +void CGCodeSemanticAnalyser::G69(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_ && pTaggedData_->m_nToken == TK_ADR_G + && pTaggedData_->m_nValue == 69); + MatchTaggedData(TK_ADR_G, 69); + + if (!m_pParserModule->KillNearTransform(CTransform::TF_REV)) + ErrorHandler(c_szERROR_G68_69_NOTMATCH); + + _MoveCurPosToRespPos(); + + return; +} + +//取消固定循环功能 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G80(CTaggedData* pTaggedData_) +{ + ASSERT(int(pTaggedData_->m_nValue) == 80); + MatchTaggedData(TK_ADR_G, 80); + m_pParserModule->ChangeModal(G_GROUP_FIXEDCYCLE, 80); +} + +//绝对坐标编程 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G90_G91(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int)pTaggedData_->m_nValue; + ASSERT(_nGNumber == 90 || _nGNumber == 91); + if (!m_MatchedGroups.SetMatched(G_GROUP_ABSREL)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + MatchTaggedData(TK_ADR_G, _nGNumber); + m_pParserModule->ChangeModal(G_GROUP_ABSREL, _nGNumber); +} + +//复归到初始点(G98),复归到R点(G99) wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G98_G99(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int)pTaggedData_->m_nValue; + ASSERT(_nGNumber == 98 ||_nGNumber == 99); + + if (!m_MatchedGroups.SetMatched(G_GROUP_G98G99)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + MatchTaggedData(TK_ADR_G, _nGNumber); + m_pParserModule->ChangeModal(G_GROUP_G98G99, _nGNumber); +} + +// 修改了实现,没有必要同步 +// 且原实现计算出的工件偏置错误,未考虑公共偏置与刀具偏置,与内核中的实现不一致 +void CGCodeSemanticAnalyser::G92(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 92); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(92 == pTaggedData_->m_nValue); + + int _nGNo = (int)pTaggedData_->m_nValue; + + if (!m_MatchedGroups.SetMatched(G_GROUP_SETWORKCOOR)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + INTERPDOUBLE _nxCurPos = m_pParserModule->m_nxJumpPos; + int _nWorkCoorNo = m_pParserModule->m_nWorkcoorNo; + INTERPDOUBLE _nxWorkcoorOffset = m_pParserModule->m_nxWorkcoorOffset[_nWorkCoorNo]; + INTERPDOUBLE _nxOffset = m_pParserModule->GetTempOffset(_nWorkCoorNo); + INTERPDOUBLE _nxDelta(0., 0., 0.); + CNcSetWorkCoor_G92 _NcSetWorkCoor_G92(m_pParserModule->m_CodePosition); + int _nIndex; + for (int _axis = axis::x; _axis < c_nNUMOF_AXIS; ++_axis) + { + token_t _token = c_tkAxisToken[_axis]; + if (SearchTaggedData(&_nIndex, _token)) + { + MatchTaggedData(_nIndex, _token); + double _nValue = m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + _NcSetWorkCoor_G92.m_nxCoordinate[_axis] = _nValue; + _nxOffset[_axis] = 0.; + m_pParserModule->m_nxWorkcoorOffset[_nWorkCoorNo][_axis] = + _nxCurPos[_axis] - _nValue - + m_pParserModule->m_nxPublicOffset[_axis] - + m_pParserModule->m_nxToolOffset[_axis]; + _nxDelta[_axis] = m_pParserModule->m_nxWorkcoorOffset[_nWorkCoorNo][_axis] - _nxWorkcoorOffset[_axis]; + } + } + for (int _i = CCoorManager::WORKCOOR_G54; _i < CCoorManager::c_nNUMOF_WPCOOR; _i++) + { + if (_i == _nWorkCoorNo) + continue; + m_pParserModule->m_nxWorkcoorOffset[_i] += _nxDelta; + } + m_pParserModule->AddTailCode(_NcSetWorkCoor_G92); + m_pParserModule->SetTempOffset(_nxOffset, _nWorkCoorNo); + + return; +} + +//临时工件坐标系设定 wangwenbo 2010.01.28 +void CGCodeSemanticAnalyser::G992(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 992); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(992 == pTaggedData_->m_nValue); + + int _nGNo = (int)pTaggedData_->m_nValue; + + if (!m_MatchedGroups.SetMatched(G_GROUP_SETWORKCOOR)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + INTERPDOUBLE _nxCurPos = m_pParserModule->m_nxJumpPos; + int _nWorkCoorNo = m_pParserModule->m_nWorkcoorNo; + INTERPDOUBLE _nxOffset = m_pParserModule->GetTempOffset(_nWorkCoorNo); + for (int _axis = axis::x; _axis < c_nNUMOF_AXIS; _axis++) + { + token_t _tokenXYZ = c_tkAxisToken[_axis]; + token_t _tokenIJK = c_tkIJKToken[_axis]; + + int _nIndex; + if (SearchTaggedData(&_nIndex, _tokenXYZ)) + { + MatchTaggedData(_nIndex, _tokenXYZ); + double _nValue = m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + double _nOriginCoor = + m_pParserModule->m_nxWorkcoorOffset[_nWorkCoorNo][_axis] + + m_pParserModule->m_nxPublicOffset[_axis] + + m_pParserModule->m_nxToolOffset[_axis]; + _nxOffset[_axis] = _nxCurPos[_axis] - _nOriginCoor - _nValue; + } + else if (SearchTaggedData(&_nIndex, _tokenIJK)) + { + MatchTaggedData(_nIndex, _tokenIJK); + double _nValue = m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + _nxOffset[_axis] += _nValue; + } + } + m_pParserModule->SetTempOffset(_nxOffset, _nWorkCoorNo); + return; +} + +//指定当前工件坐标系当前坐标值 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G921(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 921); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(921 == pTaggedData_->m_nValue); + + int _nGNo = (int)pTaggedData_->m_nValue; + + if (!m_MatchedGroups.SetMatched(G_GROUP_SETWORKCOOR)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + INTERPDOUBLE _nxCurPos = m_pParserModule->m_nxJumpPos; + int _nWorkcoorNo = m_pParserModule->m_nWorkcoorNo; + int _nToolIndex = m_pParserModule->m_nToolIndex; + INTERPDOUBLE _nxOffset = m_pParserModule->GetTempOffset(_nWorkcoorNo); + + CNcSetWorkCoor_G921 _NcSetWorkCoor_G921(m_pParserModule->m_CodePosition); + int _nIndex; + for (int _axis = axis::x; _axis < c_nNUMOF_AXIS; ++_axis) + { + token_t _token = c_tkAxisToken[_axis]; + if (SearchTaggedData(&_nIndex, _token)) + { + MatchTaggedData(_nIndex, _token); + double _nValue = m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + _NcSetWorkCoor_G921.m_nxCoordinate[_axis] = _nValue; + _nxOffset[_axis] = 0.; + m_pParserModule->m_nxWorkcoorOffset[_nWorkcoorNo][_axis] = + _nxCurPos[_axis] - _nValue - + m_pParserModule->m_nxPublicOffset[_axis] - + m_pParserModule->m_nxToolOffset[_axis]; + } + } + m_pParserModule->AddTailCode(_NcSetWorkCoor_G921); + m_pParserModule->SetTempOffset(_nxOffset, _nWorkcoorNo); + return; +} + +// 直接设置工件偏置或公共偏置 +void CGCodeSemanticAnalyser::G922(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 922); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(922 == pTaggedData_->m_nValue); + + int _nGNo = (int)pTaggedData_->m_nValue; + + if (!m_MatchedGroups.SetMatched(G_GROUP_SETWORKCOOR)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + //// 在这里,至少有两种实现方法,现在我选择了遵照愿意的方法,比较笨拙;Modify later[calf] + INTERPDOUBLE _nxCurPos = m_pParserModule->IsJumping() + ? m_pParserModule->m_nxJumpPos + : m_pParserModule->m_nxCurPos; + + CNcSetWorkCoor_G922 _NcSetWorkCoor_G922(m_pParserModule->m_CodePosition); + + int _nIndex; + for (int _axis = axis::x; _axis < c_nNUMOF_AXIS; ++_axis) + { + token_t _token = c_tkAxisToken[_axis]; + if (SearchTaggedData(&_nIndex, _token)) + { + MatchTaggedData(_nIndex, _token); + double _nValue = m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + _NcSetWorkCoor_G922.m_nxOrg[_axis] = _nValue; + } + } + if (SearchTaggedData(&_nIndex, TK_ADR_P)) + { + MatchTaggedData(_nIndex, TK_ADR_P); + int _nWCNo = (int)m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + + if (_nWCNo != CCoorManager::_WORKCOOR_CURRENT + && _nWCNo != CCoorManager::WORKCOOR_EXT + && _nWCNo != CCoorManager::WORKCOOR_G54 + && _nWCNo != CCoorManager::WORKCOOR_G55 + && _nWCNo != CCoorManager::WORKCOOR_G56 + && _nWCNo != CCoorManager::WORKCOOR_G57 + && _nWCNo != CCoorManager::WORKCOOR_G58 + && _nWCNo != CCoorManager::WORKCOOR_G59) + { + ASSERT(false); + m_strTemp.Format(c_szERROR_INVALID_WORKCOORNO, _nWCNo); + ErrorHandler(m_strTemp); + } + + _NcSetWorkCoor_G922.m_nWorkcoorNo = _nWCNo; + } + + for (int _axis = axis::x; _axis < c_nNUMOF_AXIS; ++_axis) + { + if (IsInvalidDouble(_NcSetWorkCoor_G922.m_nxOrg[_axis])) + continue; + if (_NcSetWorkCoor_G922.m_nWorkcoorNo == CCoorManager::WORKCOOR_EXT) + m_pParserModule->m_nxPublicOffset[_axis] = _NcSetWorkCoor_G922.m_nxOrg[_axis]; + else + { + int _nWorkcoorNo = _NcSetWorkCoor_G922.m_nWorkcoorNo; + if (_nWorkcoorNo == CCoorManager::_WORKCOOR_CURRENT) + _nWorkcoorNo = m_pParserModule->m_nWorkcoorNo; + m_pParserModule->m_nxWorkcoorOffset[_nWorkcoorNo][_axis] = _NcSetWorkCoor_G922.m_nxOrg[_axis]; + } + } + m_pParserModule->AddTailCode(_NcSetWorkCoor_G922); + + return; +} + +// 从实现上看,该指令一般写在程序的最后,或者后面紧接着同步指令 +void CGCodeSemanticAnalyser::G923(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 923); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(923 == pTaggedData_->m_nValue); + int _nGNo = (int)pTaggedData_->m_nValue; + + if (!m_MatchedGroups.SetMatched(G_GROUP_SETWORKCOOR)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + CNcSetToolOffset _NcSetToolOffset(m_pParserModule->m_CodePosition); + int _nIndex; + for (int _axis = axis::x; _axis < c_nNUMOF_AXIS; ++_axis) + { + token_t _token = c_tkAxisToken[_axis]; + if (SearchTaggedData(&_nIndex, _token)) + { + MatchTaggedData(_nIndex, _token); + double _nValue = m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + _NcSetToolOffset.m_nxOffset[_axis] = _nValue; + } + } + if (SearchTaggedData(&_nIndex, TK_ADR_P)) + { + MatchTaggedData(_nIndex, TK_ADR_P); + int _nToolIndex = (int)m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + if (_nToolIndex < 0 || _nToolIndex >= CTool::NUMOFTOOL) + { + ErrorHandler(c_szERROR_TOOLNUMBEROVERFLOW); + } + else + { + _NcSetToolOffset.m_nToolNo = _nToolIndex; + } + } + else + _NcSetToolOffset.m_nToolNo = m_pParserModule->m_nToolIndex; + m_pParserModule->AddTailCode(_NcSetToolOffset); + + return; +} + +//强制进给倍率指令 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G903(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 903); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 903); + UNREFERENCED_PARAMETER(pTaggedData_); + m_FlagsForCurrentEntity.m_bFrpIs100 = true; +} + +//条件移动指令 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G904(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 904); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + if (!m_MatchedGroups.SetMatched(G_GROUP_MOVE)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + CNcConditionMoveXYZ _NcConditionMoveXYZ(m_pParserModule->m_CodePosition); + for (int _loop = 0; _loop < c_nNUMOF_AXIS; _loop++) + { + int _nIndex; + if (SearchTaggedData(&_nIndex, c_tkConditionTagToken[_loop][0])) + { + double _nSpeed = m_Entities.GetCurrentEntity()[_nIndex].m_nValue / 60.0; + if (DOUBLE_EQU_ZERO(_nSpeed)) + ErrorHandler(c_szERROR_G904_SPEEDERROR); + _NcConditionMoveXYZ.m_nxSpeed[_loop] = _nSpeed; + MatchTaggedData(_nIndex, c_tkConditionTagToken[_loop][0]); + + if (!SearchTaggedData(&_nIndex, c_tkConditionTagToken[_loop][1])) + ErrorHandler(c_szERROR_G904_ERROR_MISSADDR); + MatchTaggedData(_nIndex, c_tkConditionTagToken[_loop][1]); + _NcConditionMoveXYZ.m_nxCondIndex[_loop] = (BYTE)_round(m_Entities.GetCurrentEntity()[_nIndex].m_nValue); + + if (!SearchTaggedData(&_nIndex, c_tkConditionTagToken[_loop][2])) + ErrorHandler(c_szERROR_G904_ERROR_MISSADDR); + MatchTaggedData(_nIndex, c_tkConditionTagToken[_loop][2]); + _NcConditionMoveXYZ.m_nxCondValue[_loop] = (m_Entities.GetCurrentEntity()[_nIndex].m_nValue != 0.0); + + if (SearchTaggedData(&_nIndex, c_tkConditionTagToken[_loop][3])) + { + MatchTaggedData(_nIndex, c_tkConditionTagToken[_loop][3]); + double _nDist = m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + if (DOUBLE_LESS_ZERO(_nDist)) + ErrorHandler(c_szERROR_G904_DISTERROR); + _NcConditionMoveXYZ.m_nxDistance[_loop] = _nDist; + } + } + } + + if (m_pInterpEngine->IsSimulating() || m_pInterpEngine->IsTracking()) + return; + + m_pParserModule->AddTailCode(_NcConditionMoveXYZ); + + // Sync pos automatically, so need not to change public.dat + CNcSyncPos _NcSyncPos(m_pParserModule->m_CodePosition); + m_pParserModule->AddTailCode(_NcSyncPos); + return; +} + +//强制进给速率指令 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G905(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 905); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + m_FlagsForCurrentEntity.m_bForcedFeedrate = true; + m_pParserModule->m_SpeedRecord.bModal = false; +} + +//同步位置 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::SyncPos(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_SYNCPOS); + ASSERT(pTaggedData_->m_nValue == -1); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + if (!m_pInterpEngine->IsMachining()) + return; + + CNcSyncPos _NcSyncPos(m_pParserModule->m_CodePosition); + m_pParserModule->AddTailCode(_NcSyncPos); +} + +//同步指令 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::G906(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 906); + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + + int _nIndex = 0; + int _nPlcAddress = 0; + bool _nPortValue = false; + int _nWaitTime = INT_MAX; + + bool _bWaitPort = SearchTaggedData(&_nIndex, TK_ADR_PLC); + if (_bWaitPort) + { + MatchTaggedData(_nIndex, TK_ADR_PLC); + _nPlcAddress = int(m_Entities.GetCurrentEntity()[_nIndex].m_nValue); + + //端口电平值 + if (!SearchTaggedData(&_nIndex, TK_ADR_LEVEL)) + { + m_strTemp.Format(c_szERROR_NOENOUGHPARAMETERS, "G906"); + ErrorHandler(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_LEVEL); + int _val = _round(m_Entities.GetCurrentEntity()[_nIndex].m_nValue); + _nPortValue = _val ? true : false; + + if (SearchTaggedData(&_nIndex, TK_ADR_P)) + { + MatchTaggedData(_nIndex, TK_ADR_P); + _nWaitTime = _round(m_Entities.GetCurrentEntity()[_nIndex].m_nValue); + } + } + + if (!m_pInterpEngine->IsMachining()) + return; + + if (_bWaitPort) + { + CNcWaitPort _NcWaitPort(m_pParserModule->m_CodePosition); + _NcWaitPort.m_nPlcAddress = _nPlcAddress; + _NcWaitPort.m_bPortValue = _nPortValue; + _NcWaitPort.m_nTimeOut = _nWaitTime; + m_pParserModule->AddTailCode(_NcWaitPort); + } + else + { + CNcG906 _NcG906(m_pParserModule->m_CodePosition); + m_pParserModule->AddTailCode(_NcG906); + } +} + +//以最短路径运动指令 wangwenbo 2010.01.28 +void CGCodeSemanticAnalyser::G907(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 907); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 907); + UNREFERENCED_PARAMETER(pTaggedData_); + m_FlagsForCurrentEntity.m_bTrackShortCut = true; + return; +} + +//强制以角度为单位编程 wangwenbo 2010.01.28 +void CGCodeSemanticAnalyser::G908(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_G, 908); + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 908); + UNREFERENCED_PARAMETER(pTaggedData_); + m_FlagsForCurrentEntity.m_bUnitIsDegree = true; + return; +} + +void CGCodeSemanticAnalyser::G925_G926(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + int _nGNumber = (int) pTaggedData_->m_nValue; + ASSERT(_nGNumber == 925 || _nGNumber == 926); + + if (!m_MatchedGroups.SetMatched(G_GROUP_COUNT)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + MatchTaggedData(TK_ADR_G, _nGNumber); + if (_nGNumber == 926) + { + CNcTakeCount _NcTakeCount(m_pParserModule->m_CodePosition); + m_pParserModule->AddTailCode(_NcTakeCount); + } + m_pParserModule->ChangeModal(G_GROUP_COUNT, _nGNumber); +} + +//程序停止,计划停止 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::M0_M1(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + int _nNumber = int(pTaggedData_->m_nValue); + ASSERT(_nNumber == 0 || _nNumber == 1); + MatchTaggedData(TK_ADR_M, pTaggedData_->m_nValue); + UNREFERENCED_PARAMETER(pTaggedData_); + if (!m_MatchedGroups.SetMatched(M_GROUP_PLAN)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + if (!m_pInterpEngine->IsMachining()) + return; + + if (!m_pParserModule->IsJumping()) + { + SetPositionToNextEntity(); + CNcCode _NcStop((_nNumber == 0) ? NCFMSTOP : NCFMSTOPPLAN, + m_pParserModule->m_CodePosition); + m_pParserModule->AddTailCode(_NcStop); + } +} + +// 遇到此指令应该结束加工任务,并把文件指针指向程序文件头。 +void CGCodeSemanticAnalyser::M2_M30(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, pTaggedData_->m_nValue); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(2 == pTaggedData_->m_nValue || 30 == pTaggedData_->m_nValue); + if (!m_MatchedGroups.SetMatched(M_GROUP_ROUTINE)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + if (m_pParserModule->m_ModalData.m_bTakeCount) + { + // 此时计数加工工件 + CNcTakeCount _NcTakeCount(m_pParserModule->m_CodePosition); + m_pParserModule->AddTailCode(_NcTakeCount); + } + m_pParserModule->SetFinished(); +} + +//主轴顺时针旋转,逆时针旋转,停止 wangwenbo 2010.01.28 +void CGCodeSemanticAnalyser::M3_M4_M5(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, pTaggedData_->m_nValue); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + int _nNumber = (int)pTaggedData_->m_nValue; + ASSERT(3 == _nNumber || _nNumber == 4 || _nNumber == 5); + if (!m_MatchedGroups.SetMatched(M_GROUP_PRIAXIS)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + if (!m_pInterpEngine->IsMachining()) + return; + + //if (m_pParserModule->IsJumping()) + //{ + // m_pParserModule->m_nJumpM345 = _nNumber; + //} + //else + if (!m_pParserModule->IsJumping()) + { + m_strTemp.Format("M%d", _nNumber); + m_pParserModule->MakeCall(m_strTemp, 1); + } +} + +// [calf, 2008/09/08] +// 该处提出了一个问题: 仿真的时候哪些指令应该支持,哪些不应该支持。 +void CGCodeSemanticAnalyser::M6_T(CTaggedData* pTaggedData_) +{ + ASSERT((pTaggedData_->m_nToken == TK_ADR_M && pTaggedData_->m_nValue == 6) + || pTaggedData_->m_nToken == TK_ADR_T); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (SearchTaggedData(&_nIndex, TK_ADR_M)) + { + MatchTaggedData(_nIndex, TK_ADR_M); + } + + int _nToolIndex = m_pParserModule->m_nToolIndex; + if (SearchTaggedData(&_nIndex, TK_ADR_T)) + { + _nToolIndex = (int)m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + MatchTaggedData(_nIndex, TK_ADR_T); + } + + if (_nToolIndex < 0 || _nToolIndex >= m_pParserModule->m_nToolLibSize) + { + ErrorHandler(c_szERROR_TOOLNUMBEROVERFLOW); + } + + if (!m_pParserModule->IsJumping()) + { + SetPositionToNextEntity(); + + if (m_pParserModule->m_bPromptingToolChanger) + { + CNcSendRawString _NcSendRawString(m_pParserModule->m_CodePosition); + _NcSendRawString.m_strString = c_szCHANGE_TOOL_MESSAGE; + m_pParserModule->AddTailCode(_NcSendRawString); + + // 此处通知内核需要换刀并使用新的刀具位置偏置功能 + CNcChangeTool _NcChangeTool(m_pParserModule->m_CodePosition); + _NcChangeTool.m_nToolIndexNew = _nToolIndex; + m_pParserModule->AddTailCode(_NcChangeTool); + + CNcCode _NcStop(NCFMSTOP, m_pParserModule->m_CodePosition); + m_pParserModule->AddTailCode(_NcStop); + } + else + { + if (0 < m_pParserModule->m_pParserPublic->GetSubProg("CHANGETOOL")) + { + // 设置新旧刀号 + m_pParserModule->SetNamedVariable("#1", _nToolIndex); + m_pParserModule->SetNamedVariable("#2", m_pParserModule->m_nToolIndex); + + int _nAbsolute = 1; + if (!m_pParserModule->m_ModalData.m_bAbsolute) + _nAbsolute = 0; + m_pParserModule->SetNamedVariable("#3", _nAbsolute); + + m_pParserModule->MakeCall("CHANGETOOL", 1); + } + else + { + // 此处通知内核需要换刀并使用新的刀具位置偏置功能 + CNcChangeTool _NcChangeTool(m_pParserModule->m_CodePosition); + _NcChangeTool.m_nToolIndexNew = _nToolIndex; + m_pParserModule->AddTailCode(_NcChangeTool); + + // 等待完成,发送同步指令 + CNcG906 _NcG906(m_pParserModule->m_CodePosition); + m_pParserModule->AddTailCode(_NcG906); + } + } + } + + return; +} + +static int s_FixedCycName[] = +{ + '37G', + '47G', + '57G', + '67G', + '77G', + '87G', + '97G', + '18G', + '28G', + '38G', + '48G', + '58G', + '68G', + '78G', + '88G', + '98G', +}; + +//子程序返回 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::M17_M99(CTaggedData* pTaggedData_) +{ + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 17 || pTaggedData_->m_nValue == 99); + if (!m_MatchedGroups.SetMatched(M_GROUP_ROUTINE)) + ErrorHandler(c_szERROR_DUPLICATE_CODE_OF_SAME_GROUP); + + StackItem _si; + if (!m_pParserModule->m_Stack.Pop(&_si)) + { + if (m_pParserModule->GetActiveParser() == m_pParserModule->m_pParserTask + && !m_pInterpEngine->IsTracking()) // 读取轨迹时不反复进行 + { + // 此处认为是在主程序使用M99,返回到主程序的开头继续执行 + // 参见FANUC 0i -MC 操作说明书 (B-64124CM/01) + + if (m_pParserModule->m_ModalData.m_bTakeCount) + { + // 此时计数加工工件 + CNcTakeCount _NcTakeCount(m_pParserModule->m_CodePosition); + m_pParserModule->AddTailCode(_NcTakeCount); + } + + // [calf, 2008/06/26] + // 当用户在加工文件末尾添加M17指令的时候,现在的处理有些问题: + // 1、如果是断点继续,是从文件头还是从断点继续位置开始加工? + // 2、如果选择的加工范围不止一个,是否该从头再来? + // 3、如果上述两种情况同时发生,该如何处理? + // 4、现在是设置到文件头、加工范围头上。 + + // 当用户在加工文件末尾添加M17指令的时候,处理如下: + // 设置到文件头上,加工范围也设置的文件头上 + // 原因是,选择加工大文件的最后几句,每次返回到加工范围头上, + // 加工范围前的指令还需要从文件中解析出来,但不在加工范围内, + // 不被实际使用,该处消耗了大量的CPU + // fangmin -2009.7.24 + m_pInterpEngine->m_FieldList.RemoveAll(); + __int64 _nStartFilePos = 0; + __int64 _nEndFilePos = m_pInterpEngine->m_pCodeBuffer->GetLength(); + m_pInterpEngine->m_FieldList.AddHead(LCRO_FIELD(_nStartFilePos, _nEndFilePos)); + m_pParserModule->GetActiveParser()->Reset(); + } + else + m_pParserModule->SetFinished(); + + return; + } + + if (_si.siLoop == 1) + { + if (_si.siMode == StackItem::CIRCYC) + { + SFC_ProcStack(&_si); + } + else + { + ASSERT (_si.siMode == StackItem::NORMAL); + m_pParserModule->SetActiveParser(_si.siParserPointer); + m_pParserModule->GetActiveParser()->SetPosition(_si.siPos); +#ifdef G00MOVING + if (m_pParserModule->m_CodePosition.nAnchorType == ANCH_FILEPOS) + ((CGCodeSemanticAnalyser*)m_pParserModule->GetActiveParser())->m_nCurEntityIndex = _si.siIndex; +#endif + } + + // G73~G89为固定循环子程序,此处对固定循环子程序进行注销。 + C_ASSERT(sizeof(int) == 4); + union + { + int nValue; + TCHAR szBuf[4]; + } _test; + memset(&_test, 0, sizeof(_test)); + + _tcsupr_s(_si.siProgName); + if (3 == _tcslen(_si.siProgName)) + { + _tcsncpy_s(_test.szBuf, _countof(_test.szBuf), _si.siProgName, 3); + for (int _i = 0, _size = _countof(s_FixedCycName); _i < _size; ++_i) + { + if (s_FixedCycName[_i] == _test.nValue) + { + ASSERT(_si.siProgNo == 0); + m_pParserModule->m_bInFixedCycle = false; + m_pParserModule->m_ModalData.SetMotionType(CGModalData::MT_FIXEDCYC); + } + } + } + } + else + { + ASSERT(_si.siLoop > 0); + _si.siLoop--; + m_pParserModule->m_Stack.Push(_si); + + //此处原来有错误: + // 当调用多次时,第一次加工完毕后应该再次返回到子程序开头 + // 以前是由主程序完成的,实际上应该在此完成 + + long _pos; + if (_si.siProgNo > 0) + _pos = GetSubProg(_si.siProgNo); + else + _pos = GetSubProg(_si.siProgName); + ASSERT(_pos >= 0); + SetPosition(_pos); + } +} + +//各模块间传递字符串信息 wangwenbo 2010.01.28 +void CGCodeSemanticAnalyser::M801(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, 801); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 801); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_MSG)) + { + m_strTemp.Format(c_szERROR_NOENOUGHPARAMETERS, "M801"); + ErrorHandler(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_MSG); + + CNcSendRawString _NcSendRawString(m_pParserModule->m_CodePosition); + _NcSendRawString.m_strString = m_Entities.GetCurrentEntity()[_nIndex].m_pszValue; + m_pParserModule->AddTailCode(_NcSendRawString); +} + +//模块间传递整数信息 wangwenbo 2010.01.27 +void CGCodeSemanticAnalyser::M802(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, 802); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 802); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_P)) + { + m_strTemp.Format(c_szERROR_NOENOUGHPARAMETERS, "M802"); + ErrorHandler(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_P); + UINT _nValue = (UINT) m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + + CNcSendRawInt _NcSendRawInt(m_pParserModule->m_CodePosition); + _NcSendRawInt.m_nInteger = _nValue; + m_pParserModule->AddTailCode(_NcSendRawInt); +} + +//直接输出指令 wangwenbo 2010.01.28 +void CGCodeSemanticAnalyser::M901(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, 901); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 901); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_PLC)) + { + m_strTemp.Format(c_szERROR_NOENOUGHPARAMETERS, "M901"); + ErrorHandler(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_PLC); + int _nPlcAddress = int(m_Entities.GetCurrentEntity()[_nIndex].m_nValue); + + _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_LEVEL)) + { + m_strTemp.Format(c_szERROR_NOENOUGHPARAMETERS, "M901"); + ErrorHandler(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_LEVEL); + + if (!m_pInterpEngine->IsMachining()) + return; + + int _val = _round(m_Entities.GetCurrentEntity()[_nIndex].m_nValue); + bool _nPortValue = _val ? true : false; + CNcDirectPort _NcDirectPort(m_pParserModule->m_CodePosition); + _NcDirectPort.m_nPlcAddress = _nPlcAddress; + _NcDirectPort.m_bPortValue = _nPortValue; + m_pParserModule->AddTailCode(_NcDirectPort); +} + +//回零结束指令 wangwenbo 2010.01.28 +void CGCodeSemanticAnalyser::M902(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, 902); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 902); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_H)) + { + m_strTemp.Format(c_szERROR_NOENOUGHPARAMETERS, "M902"); + ErrorHandler(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_H); + + if (!m_pInterpEngine->IsMachining()) + return; + + int _nAxisNo = (int) m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + if (_nAxisNo < 0 || _nAxisNo >= c_nNUMOF_AXIS) + { + m_strTemp.Format(c_szERROR_M902_AXISNO, _nAxisNo); + ErrorHandler(m_strTemp); + } + CNcToRefFinished _NcToRefFinished(m_pParserModule->m_CodePosition); + _NcToRefFinished.m_nAxis = _nAxisNo; + m_pParserModule->AddTailCode(_NcToRefFinished); +} + +//更改当前刀号 wangwenbo 2010.01.28 +void CGCodeSemanticAnalyser::M903(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_M, 903); + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 903); + UNREFERENCED_PARAMETER(pTaggedData_); + + int _nIndex; + if (!SearchTaggedData(&_nIndex, TK_ADR_H)) + { + m_strTemp.Format(c_szERROR_NOENOUGHPARAMETERS, "M903"); + ErrorHandler(m_strTemp); + } + MatchTaggedData(_nIndex, TK_ADR_H); + + int _nToolIndex = (int) m_Entities.GetCurrentEntity()[_nIndex].m_nValue; + if (_nToolIndex < 0 || _nToolIndex >= m_pParserModule->m_nToolLibSize) + { + ErrorHandler(c_szERROR_TOOLNUMBEROVERFLOW); + } + CNcChangeTool _NcChangeTool(m_pParserModule->m_CodePosition); + _NcChangeTool.m_nToolIndexNew = _nToolIndex; + m_pParserModule->AddTailCode(_NcChangeTool); +} + +void CGCodeSemanticAnalyser::M904_M905(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_M); + ASSERT(pTaggedData_->m_nValue == 904 || pTaggedData_->m_nValue == 905); + + MatchTaggedData(TK_ADR_M, pTaggedData_->m_nValue); + m_pParserModule->ChangeModal(G_GROUP_G00LEAVEENTER, _round(pTaggedData_->m_nValue)); + return; +} + +//泄压延时 +//调用子程序TrackEnd, +//子程序实现的功能是: +//水切割,加工完一个文件后,先关掉其他的阀门,延时一段时间后再关掉水阀 +//通常在一个文件翻译完毕后条用G927 +//---------------------------------------------xiangyanjun +void CGCodeSemanticAnalyser::G927(CTaggedData* pTaggedData_) +{ + ASSERT(pTaggedData_->m_nToken == TK_ADR_G); + ASSERT(pTaggedData_->m_nValue == 927); + + MatchTaggedData(pTaggedData_->m_nToken, pTaggedData_->m_nValue); + if(0 < m_pParserModule->m_pParserPublic->GetSubProg("TrackEnd")) + { + m_pParserModule->MakeCall("TrackEnd", 1); + } +} + +void CGCodeSemanticAnalyser::FeedRate(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_F, c_nINVALID_DOUBLE); + if (m_pInterpEngine->IsTracking()) + return; + + CGCodeMeaning::assignspeed_t _nAssignSpeedType = m_pParserModule->m_nAssignSpeedType; + if (m_FlagsForCurrentEntity.m_bForcedFeedrate) + _nAssignSpeedType = CGCodeMeaning::AS_FILE; + + // If speed of file is invalid, user can change paramter from AS_FILE/AS_PRORATION + // to AS_DEFAULT to working. [calf] + switch (_nAssignSpeedType) + { + case CGCodeMeaning::AS_FILE: + //case CGCodeMeaning::AS_PRORATION: + { + double _nSpeed = MMPerMin_To_MMPerSec(pTaggedData_->m_nValue); // from mm/min to mm/s + if (!_IsValidSpeed(_nSpeed)) + { + m_strTemp.Format(c_szERR_SPEED_OUTOFRANGE, pTaggedData_->m_nValue); + ErrorHandler(m_strTemp); + + ASSERT(false); // Maye ErrorHandler will be changed + return; + } + + // Not CMemoryCodeBuffer + //if (CGCodeMeaning::AS_PRORATION == _nAssignSpeedType /*&& m_pCodeBuffer == &GetNcKernel()->m_FileCodeBuffer*/) + //{ + // CGFileCodeBuffer* _pFileCodeBuff = (CGFileCodeBuffer*)m_pCodeBuffer; + // double _nMaxSpeedSetting = max(m_pParserModule->m_nSpeedGxx, m_pParserModule->m_nSpeedG00); + // double _nMaxSpeedScan = _pFileCodeBuff->m_nMaxSpeedScan; + // if (_nMaxSpeedScan > _nMaxSpeedSetting) + // _nSpeed *= _nMaxSpeedSetting / _nMaxSpeedScan; + //} + + if (_IsCurSpeedBelongToG00()) + m_pParserModule->m_SpeedRecord.Speed.nSpeedG00 = _nSpeed; + else + m_pParserModule->m_SpeedRecord.Speed.nSpeedGxx = _nSpeed; + } + + break; + + case CGCodeMeaning::AS_DEFAULT: + m_pParserModule->m_SpeedRecord.Speed.nSpeedG00 = m_pParserModule->m_nSpeedG00; + m_pParserModule->m_SpeedRecord.Speed.nSpeedGxx = m_pParserModule->m_nSpeedGxx; + break; + + default: + ASSERT(false); + break; + }; + return; +} + +void CGCodeSemanticAnalyser::SpindleRev(CTaggedData* pTaggedData_) +{ + MatchTaggedData(TK_ADR_S, pTaggedData_->m_nValue); + if (!m_pParserModule->m_bIgnoreProgSpindleRev) + { + int _nSpindleRev = int(pTaggedData_->m_nValue); + CNcChangSpindleRev _NcChangSpindleRev(m_pParserModule->m_CodePosition); + _NcChangSpindleRev.m_nSpindleRev = _nSpindleRev; + _NcChangSpindleRev.m_nType = 0; + m_pParserModule->AddTailCode(_NcChangSpindleRev); + } +} + +void CGCodeSemanticAnalyser::GUnknown(CTaggedData* pTaggedData_) +{ + if (m_pInterpEngine->IsTracking()) + { + int _nIndex; + SearchTaggedData(&_nIndex, TK_ADR_G); + MatchTaggedData(_nIndex, TK_ADR_G); + return; + } + + m_strTemp.Format("G%d", int(pTaggedData_->m_nValue)); + if (0 > m_pParserModule->m_pParserPublic->GetSubProg(m_strTemp)) + { + GInvalid(pTaggedData_); + } + else + { + m_pParserModule->MakeCall(m_strTemp, 1); + } +} + +void CGCodeSemanticAnalyser::MUnknown(CTaggedData* pTaggedData_) +{ + if (m_pInterpEngine->IsTracking()) + { + int _nIndex; + SearchTaggedData(&_nIndex, TK_ADR_M); + MatchTaggedData(_nIndex, TK_ADR_M); + return; + } + + m_strTemp.Format("M%d", int(pTaggedData_->m_nValue)); + if (0 > m_pParserModule->m_pParserPublic->GetSubProg(m_strTemp)) + { + MInvalid(pTaggedData_); + } + else + { + m_pParserModule->MakeCall(m_strTemp, 1); + } +} + +void CGCodeSemanticAnalyser::MatchG(CTaggedData* pTaggedData_) +{ + // 首先检查有效性 + int _nGNo = m_pParserModule->m_ModalData.GetGNumber(G_GROUP_MOVE); + if (m_pParserModule->m_ModalData.GetMotionType() == CGModalData::MT_FIXEDCYC) + _nGNo = m_pParserModule->m_ModalData.GetGNumber(G_GROUP_FIXEDCYCLE); + + int _nIndex = pTaggedData_->m_nToken - TK_ADR_FIRST; + ASSERT(m_MatchGScope[_nIndex][0] == pTaggedData_->m_nToken); + bool _bValid = false; + for (const int*_pMatchNos = &m_MatchGScope[_nIndex][1]; + *_pMatchNos != -1; + _pMatchNos++) + { + if (*_pMatchNos == _nGNo) + { + _bValid = true; + break; + } + } + + if (!_bValid) + { + ErrorHandler(c_szERROR_MATCH_BACKWARDRULE); + } + + const rule_t* _pRule = GetRule(TK_ADR_G, _nGNo); + if (_pRule) + { + (this->*_pRule->pFunction) (pTaggedData_); + } + else + { + ErrorHandler(c_szERROR_MATCH_BACKWARDRULE); + } +} + +void CGCodeSemanticAnalyser::Ignore(CTaggedData* pTaggedData_) +{ + TRACE2("Ignore instruction:%s%f", + GetTokenAlias(pTaggedData_->m_nToken), + pTaggedData_->m_nValue); +} + +void CGCodeSemanticAnalyser::Rule_Error(CTaggedData* pTaggedData_) +{ + TRACE1("Rule_Error for Token: %s\n", GetTokenAlias(pTaggedData_->m_nToken)); + m_strTemp.Format(c_szERROR_UNEXPECTED_TAGGEDDATA, + GetTokenAlias(pTaggedData_->m_nToken)); + ErrorHandler(m_strTemp); +} + +void CGCodeSemanticAnalyser::GInvalid(CTaggedData* pTaggedData_) +{ + int _nIndex; + SearchTaggedData(&_nIndex, TK_ADR_G); + MatchTaggedData(_nIndex, TK_ADR_G); + m_strTemp.Format(c_szERROR_INVALID_GCODE, pTaggedData_->m_nValue); + ErrorHandler(m_strTemp); +} + +void CGCodeSemanticAnalyser::MInvalid(CTaggedData* pTaggedData_) +{ + int _nIndex; + SearchTaggedData(&_nIndex, TK_ADR_M); + MatchTaggedData(_nIndex, TK_ADR_M); + int _nValue = (int) pTaggedData_->m_nValue; + m_strTemp.Format(c_szERROR_INVALID_MCODE, _nValue); + PARSEENGINEWARNING(m_strTemp); +} + +const CGCodeSemanticAnalyser::rule_t* CGCodeSemanticAnalyser::GetRule_Pre(token_t tkAddr_, double nTagValue_) +{ + for (int _i = 0; _i < _countof(m_RuleList_Pre); _i++) + { + if (m_RuleList_Pre[_i].tkAddr == tkAddr_) + { + if (m_RuleList_Pre[_i].nTagValue == -1 + || m_RuleList_Pre[_i].nTagValue == nTagValue_) + { + return &m_RuleList_Pre[_i]; + } + } + } + + return NULL; +} + +const CGCodeSemanticAnalyser::rule_t* CGCodeSemanticAnalyser::GetRule_Normal(token_t tkAddr_, double nTagValue_) +{ + for (int _i = 0; _i < _countof(m_RuleList_Normal); _i++) + { + if (m_RuleList_Normal[_i].tkAddr == tkAddr_) + { + if (m_RuleList_Normal[_i].nTagValue == -1 + || m_RuleList_Normal[_i].nTagValue == nTagValue_) + { + return &m_RuleList_Normal[_i]; + } + } + } + + return NULL; +} + +const CGCodeSemanticAnalyser::rule_t* CGCodeSemanticAnalyser::GetRule_Post(token_t tkAddr_, double nTagValue_) +{ + for (int _i = 0; _i < _countof(m_RuleList_Post); _i++) + { + if (m_RuleList_Post[_i].tkAddr == tkAddr_) + { + if (m_RuleList_Post[_i].nTagValue == -1 + || m_RuleList_Post[_i].nTagValue == nTagValue_) + { + return &m_RuleList_Post[_i]; + } + } + } + + return NULL; +} + +const CGCodeSemanticAnalyser::rule_t* CGCodeSemanticAnalyser::GetRule(token_t tkAddr_, double nTagValue_) +{ + const CGCodeSemanticAnalyser::rule_t* _pRule = GetRule_Pre(tkAddr_, nTagValue_); + if (_pRule) + return _pRule; + _pRule = GetRule_Normal(tkAddr_, nTagValue_); + if (_pRule) + return _pRule; + _pRule = GetRule_Post(tkAddr_, nTagValue_); + return _pRule; +} + +//确定当前加工区域 wangwenbo 2010.01.28 +CCodeParser::fieldpos_t CGCodeSemanticAnalyser::GetCurPosField() +{ + __int64 _nPos = GetPosition(); + codeparser_t _type = GetParserType(); + + ASSERT(_type == CM_G); + // left closed right open + fieldpos_t _filepos = FP_MIDDLE; + if (_nPos < m_CurField.from) + _filepos = FP_LEFT; + else if (_nPos >= m_CurField.to) + _filepos = FP_RIGHT; + + return _filepos; +} \ No newline at end of file diff --git a/src/GlobalParamDlg.cpp b/src/GlobalParamDlg.cpp new file mode 100644 index 0000000..6deb324 --- /dev/null +++ b/src/GlobalParamDlg.cpp @@ -0,0 +1,2198 @@ +// ************************************************************************** // +// GlobalParamDlg.cpp : implementation of the CGlobalParamDlg class +// Copyright(c)2015 WeiHong Company. All rights reserved. +// +// Abstract: +// 本文件实现CGlobalParamDlg类。 +// *********************************************** ---- 黄海燕 2015-05-07***** // +#include "stdafx.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define WM_GETDATAVALID 0x0369A +#define WM_INITCANCELDATA 0x0369B +#define WM_UPDATELOADLAYER 0x0369C + +CS_T s_csINVALIDINPUT = _DEFCS(_CSV(18501), + _CHINESE("输入参数格式不正确,请重新输入。") + _ENGLISH("The input parameter is invalid, please reset again.")); +CS_T s_csModifyParamError = _DEFCS(_CSV(18481), + _CHINESE("参数修改错误!\n参数名称: %s\n错误原因: %s") + _ENGLISH("Modify Parameter Error!\nParamName: %s\nErrorInfo: %s")); +CS_T s_csReStartupTip = _DEFCS(_CSV(18482), + _CHINESE("您修改的参数中包含需重启生效的参数,请重启软件!") + _ENGLISH("Some Parameters are valid after you restart your software!")); +CS_T s_csErrorPrompt = _DEFCS(_CSV(18483), + _CHINESE("错误提示框") + _ENGLISH("Error Prompt")); +CS_T s_csUNAVAILIBLEPARAM = _DEFCS(_CSV(18484), + _CHINESE("不可用") + _ENGLISH("N/A")); +CS_T s_csNotInputPrompt = _DEFCS(_CSV(18485), + _CHINESE("系统忙,当前加工状态无法修改该参数!") + _ENGLISH("System is busy, can not change the parameters!")); +CS_T s_szNONE = _DEFCS(_CSV(18486), + _CHINESE("不切膜") + _ENGLISH("No Film Cut")); +CS_T s_szCUTFILMINDIVIDUAL = _DEFCS(_CSV(18487), + _CHINESE("逐个切膜") + _ENGLISH("Cut Single")); +CS_T s_szCUTFILMINGROUPS = _DEFCS(_CSV(18488), + _CHINESE("分组切膜") + _ENGLISH("Cut Group")); +CS_T s_szCUTFILMINWHOLE = _DEFCS(_CSV(18489), + _CHINESE("全局切膜") + _ENGLISH("Cut globally")); +CS_T s_szCOLON = _DEFCS(_CSV(18490), + _CHINESE(":") + _ENGLISH(":")); +CS_T s_csCUTFILM = _DEFCS(_CSV(18491), + _CHINESE("带膜切割:") + _ENGLISH("Cut Film:")); +CS_T s_csPLCSETTING = _DEFCS(_CSV(18492), + _CHINESE("PLC高级设置") + _ENGLISH("PLC Setting")); +CS_T s_csAIR = _DEFCS(_CSV(18493), + _CHINESE("空气") + _ENGLISH("Air")); +CS_T s_csNITROGEN = _DEFCS(_CSV(18494), + _CHINESE("氮气") + _ENGLISH("N2")); +CS_T s_csOXYGEN = _DEFCS(_CSV(18495), + _CHINESE("氧气") + _ENGLISH("O2")); +CS_T s_csDUTYCYCLE = _DEFCS(_CSV(18496), + _CHINESE("占空比") + _ENGLISH("Duty")); +CS_T s_csANALOG = _DEFCS(_CSV(18497), + _CHINESE("模拟量") + _ENGLISH("Analog")); +CS_T s_csNOMOTION = _DEFCS(_CSV(18498), + _CHINESE("不动") + _ENGLISH("No Motion")); +CS_T s_csBACKFIXPOS = _DEFCS(_CSV(18499), + _CHINESE("回固定点") + _ENGLISH("Fixed Point")); +CS_T s_csBACKWORKORG = _DEFCS(_CSV(18500), + _CHINESE("回工件原点") + _ENGLISH("Work Origin")); +CS_T s_csMOTIONCONTROLPARAM = _DEFCS(_CSV(18502), + _CHINESE("机床运动参数") + _ENGLISH("Motion Control Parameters")); +CS_T s_csLASERPARAM = _DEFCS(_CSV(18503), + _CHINESE("激光器参数") + _ENGLISH("Laser Device Parameters")); +CS_T s_csFOLLOWCONTROLPARAM = _DEFCS(_CSV(18504), + _CHINESE("随动控制") + _ENGLISH("Follow Control")); +CS_T s_csPRESSURECONTROL = _DEFCS(_CSV(18505), + _CHINESE("气压控制") + _ENGLISH("Pressure Control")); +CS_T s_csTARSKENDMOTION = _DEFCS(_CSV(18506), + _CHINESE("加工后行为") + _ENGLISH("Post-task Actions ")); +CS_T s_csADVANCED= _DEFCS(_CSV(18507), + _CHINESE("高级") + _ENGLISH("Advanced")); +CS_T s_csRAYCUS = _DEFCS(_CSV(18508), + _CHINESE("锐科") + _ENGLISH("Raycus")); +// 按工作项#2500新增激光器类型 +CS_T s_csLIANPIN = _DEFCS(_CSV(18633), + _CHINESE("联品") + _ENGLISH("LIANPIN")); +CS_T s_csMAX = _DEFCS(_CSV(18634), + _CHINESE("创鑫") + _ENGLISH("MAX")); +CS_T s_csZKZM = _DEFCS(_CSV(18635), + _CHINESE("中科") + _ENGLISH("ZKZM")); +CS_T s_csTXSTAR = _DEFCS(_CSV(18636), + _CHINESE("天星") + _ENGLISH("TXSTAR")); + +CS_T s_csAMERICAN = _DEFCS(_CSV(18637), + _CHINESE("IPG(美国版)") + _ENGLISH("IPG(US)")); +CS_T s_csGERMERN = _DEFCS(_CSV(18638), + _CHINESE("IPG(德国版)") + _ENGLISH("IPG(DE)")); + +CS_T s_csGETFIXEDPOS = _DEFCS(_CSV(18509), + _CHINESE("获取定高位置") + _ENGLISH("Get Fixed Pos")); +CS_T s_csCUTFROMOUTSIDE = _DEFCS(_CSV(18515), + _CHINESE("板外跟随,板外切割高度:") + _ENGLISH("Outside Cut Height:")); +CS_T s_csSETEDGECUTTINGHEIGHT = _DEFCS(_CSV(18516), + _CHINESE("跟随至板外高度并保存") + _ENGLISH("Set Outside Height")); +CS_T s_csCANNOTSAVEOUTSIDEHEIGHT = _DEFCS(_CSV(18517), + _CHINESE("当前系统状态不空闲,不能保存板外高度!") + _ENGLISH("Current system state is not idle, save outside height failed!")); +CS_T s_csGETFOLLOWHEIGHTFAILED = _DEFCS(_CSV(18518), + _CHINESE("获取跟随高度失败!") + _ENGLISH("Failed to get follow height!")); +CS_T s_csSETFOLLOWHEIGHTFAILED = _DEFCS(_CSV(18549), + _CHINESE("设置跟随高度失败!") + _ENGLISH("Failed to set follow height!")); +CS_T s_csSAVEOUTSIDEHEIGHTFAILED = _DEFCS(_CSV(18520), + _CHINESE("板外高度保存失败!") + _ENGLISH("Failed to save outside height!")); +CS_T s_csSAVEOUTSIDEHEIGHTSUCCESS = _DEFCS(_CSV(18521), + _CHINESE("板外高度保存成功!") + _ENGLISH("Save outside height Successfully!")); +CS_T s_csNOTSAVEOUTSIDEHEIGHT = _DEFCS(_CSV(18522), + _CHINESE("未保存") + _ENGLISH("Not Save")); +CS_T s_csMARKPOINT = _DEFCS(_CSV(18551), + _CHINESE("回标记点%d") + _ENGLISH("Mark Point%d")); +CS_T s_csWORKINGMODE = _DEFCS(_CSV(18601), + _CHINESE("工作方式:") + _ENGLISH("Working Mode:")); +CS_T s_csCOMINICATMODE = _DEFCS(_CSV(18602), + _CHINESE("通信串口:") + _ENGLISH("Serial Commu:")); +CS_T s_csRATEDPOWER = _DEFCS(_CSV(18604), + _CHINESE("额定功率:") + _ENGLISH("Rated Power:")); +CS_T s_csLASERRESET = _DEFCS(_CSV(18605), + _CHINESE("激光器复位") + _ENGLISH("Reset Laser")); +CS_T s_csCONTEXT = _DEFCS(_CSV(18605), + _CHINESE("加加速度(低通): 加速度变化率,值越大,代表机械刚性越好,加减速能力越强。") + _ENGLISH("Jerk (LP): The change rate of acceleration. A larger value means better rigidity and stonger ability to accelerate or decelerate.")); +CS_T s_csCONTEXT1 = _DEFCS(_CSV(18605), + _CHINESE("轨迹平滑: 值越大,越能减轻机械振动,但同时将削弱某些尖角细节。") + _ENGLISH("Path smoothing: A larger value means better ability to remove vibration while some details at acute corner will be weakened.")); +CS_T s_csCONTEXT_NK = _DEFCS(_CSV(18605), + _CHINESE("加加速度(低通): 加速度变化率,值越大,代表机械刚性越好,加减速能力越强,推荐值10G/s。") + _ENGLISH("Jerk (LP): The change rate of acceleration. A larger value means better rigidity and stonger ability to accelerate or decelerate. Recommended: 10G/s")); +CS_T s_csCONTEXT1_NK = _DEFCS(_CSV(18605), + _CHINESE("轨迹平滑: 值越大,越能减轻机械振动,但同时将削弱某些尖角细节,推荐值40ms。") + _ENGLISH("Path smoothing: A larger value means better ability to remove vibration while some details at acute corner will be weakened. Recommended: 40ms")); +CS_T s_csNOMODE = _DEFCS(_CSV(18606), + _CHINESE("无") + _ENGLISH("None")); +CS_T s_szCUTGASNAME = _DEFCS(_CSV(18609), + _CHINESE("CutGas%d_CHN") + _ENGLISH("CutGas%d_ENG")); + +using namespace mach; + +const char c_szParamGroupUnit[] = "ParamGroupUnit"; +const char c_szSpeedUnit[] = "SpeedUnit"; +const char c_szAccUnit[] = "AccUnit"; +const char c_szTimeUnit[] = "TimeUnit"; + +static void FormatDoubleParamer(CString& pSrc_) +{ + pSrc_.TrimRight('0'); + if (pSrc_.IsEmpty()) + pSrc_ = _T("0"); + if (pSrc_[pSrc_.GetLength() - 1] == _T('.')) + pSrc_.Delete(pSrc_.GetLength() - 1); +} + +IMPLEMENT_DYNAMIC(CGlobalParamDlg, CDialog) +BEGIN_MESSAGE_MAP(CGlobalParamDlg, CDialog) + ON_WM_TIMER() + ON_WM_PAINT() + ON_MESSAGE(WM_KICKIDLE, OnKickIdle) + ON_MESSAGE(WM_GETDATAVALID, OnDataValid) + ON_MESSAGE(WM_INITCANCELDATA, OnInitCancelData) + ON_MESSAGE(WM_UPDATELOADLAYER, OnLoadLayer) + ON_UPDATE_COMMAND_UI(IDC_CHECK_FROGLEAPING, OnUpdateFrogLeap) + ON_UPDATE_COMMAND_UI(IDC_CHECK_ENABLEREFCIRCLE, OnUpdateCircleLimit) + ON_CBN_SELCHANGE(IDC_COMBO_CUTFILM, OnSelectCutFilm) + ON_CBN_SELCHANGE(IDC_COMBO_TARSKENDACTION, OnSelTaskEndMotion) + ON_CONTROL_RANGE(EN_KILLFOCUS, IDC_EDIT_GLOBALPARAM_BEGIN, IDC_EDIT_GLOBALPARAM_END, OnKillFocusEdits) + ON_CONTROL_RANGE(EN_SETFOCUS, IDC_EDIT_GLOBALPARAM_BEGIN, IDC_EDIT_GLOBALPARAM_END, OnSetFocusEdits) + ON_CONTROL_RANGE(CBN_SELCHANGE, IDC_COMBO_GLOBALPARAM_BEGIN, IDC_COMBO_GLOBALPARAM_END, OnSelectComb) + ON_COMMAND_RANGE(IDC_CHECK_GLOBALPARAM_BEGIN, IDC_CHECK_GLOBALPARAM_END, OnClickCheckBoxes) + ON_COMMAND(IDC_BTN_GETFIXHEIGHTCUTPOS, OnGetFixedCutHeight) + ON_COMMAND(IDC_BTN_SAVEREFERHEIGHT, OnSaveEdgeCuttingHeight) + ON_COMMAND(IDC_BTN_LASERRESET, OnResetLaser) + ON_UPDATE_COMMAND_UI(IDC_BTN_LASERRESET, OnUpdateResetLaser) + ON_WM_CTLCOLOR() +END_MESSAGE_MAP() + +CGlobalParamDlg::CGlobalParamDlg(CWnd* pParent /*=NULL*/) +: CDialog(IDD_DLG_GLOBALPARAM, pParent), m_bBackUp(false), m_bSavingOutsideHeight(false) +{ + // Edit + // 这里的单位允许是NULL的,所以在调用的时候一定要先判断下。 ---- 黄海燕 2015-05-23 + static const ParamInfoE _s_cParamInfo[] = + { + {IDC_STATIC_G00SPEEDX, IDC_EDIT_G00SPEEDX, IDC_STATIC_G00SPEED, "GP_SpeedG00"}, + {IDC_STATIC_GOOACCSPEEDX, IDC_EDIT_GOOACCSPEEDX, IDC_STATIC_GOOACCSPEEDXUNIT, "GP_AccG00"}, + {IDC_STATIC_SIMUCUTSPEED, IDC_EDIT_SIMUCUTSPEED, IDC_STATIC_SIMUCUTSPEEDUNIT, "GP_SimuCutSpeed"}, + {IDC_STATIC_MACHACCSPEED, IDC_EDIT_MACHACCSPEED, IDC_STATIC_ACCSPEEDUNIT, "GP_AccGxx"}, + {IDC_STATIC_ACCACCSPEED, IDC_EDIT_ACCACCSPEED, IDC_STATIC_ACCACCSPEEDUNIT, "GP_AccAcc"}, + {IDC_STATIC_ACCACCSPEEDG00, IDC_EDIT_ACCACCSPEEDG00, IDC_STATIC_ACCACCSPEEDUNITGOO, "GP_AccAccG00"}, + {IDC_STATIC_ACROSSACCSPEED, IDC_EDIT_ACROSSACCSPEED, IDC_STATIC_ACROSSACCSPEEDUNIT, "GP_AngleAcc"}, + {IDC_STATIC_REFCIRCLESPEED, IDC_EDIT_REFCIRCLESPEED, IDC_STATIC_REFCIRCLESPEEDUNIT, "GP_RefMaxSpeed"}, + {IDC_STATIC_SPEEDSLIDER, IDC_EDIT_SPEEDSLIDER, IDC_STATIC_SPEEDSLIDERUNIT, "GP_SpeedSlideTime"}, + {IDC_STATIC_PATHSLIDER, IDC_EDIT_PATHSLIDER, IDC_STATIC_PATHSLIDERUNIT, "GP_TrackSlideTime"}, + {IDC_STATIC_SHARPANGLESPEED, IDC_EDIT_SHARPANGLESPEED, IDC_STATIC_SHARPANGLESPEEDUNIT, "GP_ArcTransitionPrecision"}, + {IDC_STATIC_MINPULSEWIDTH, IDC_EDIT_MINPULSEWIDTH, NULL, "GP_MinPulseWidth"}, + {IDC_STATIC_FROGLEAPMINLEN, IDC_EDIT_FROGLEAPMINLEN, IDC_STATIC_FROGLEAPMINLENUNIT, "GP_MinLeapingLength"}, + {IDC_STATIC_DEFAULTPRESSURE, IDC_EDIT_DEFAULTPRESSURE, IDC_STATIC_DEFAULTPRESSUREUNIT, "GP_DefaultSVC"}, + {IDC_STATIC_ZBERTHPOS, IDC_EDIT_ZBERTHPOS, IDC_STATIC_ZBERTHPOSUNIT, "GP_ZDockPosition"}, + {IDC_STATIC_MAXPOWERSVC, IDC_EDIT_MAXPOWERSVC, IDC_STATIC_MAXPOWERSVCUNIT, "GP_MaxPowerSvc"}, + {IDC_STATIC_JOGPOWER, IDC_EDIT_JOGPOWER, IDC_STATIC_JOGPOWERUNIT, "GP_JogPower"}, + {IDC_STATIC_MAXFOLLOWHEIGHT, IDC_EDIT_MAXFOLLOWHEIGHT, IDC_STATIC_MAXFOLLOWHEIGHTUNIT, "GP_MaxFollowHeight"}, + {IDC_STATIC_CHANGEGASDELAY, IDC_EDIT_CHANGEGASDELAY, IDC_STATIC_CHANGEGASDELAYUNIT, "GP_CLEARGASDELAY"}, + {IDC_STATIC_FIXEDHEIGHT, IDC_EDIT_FIXHEIGHTCUTHEIGHT, IDC_STATIC_FIXHEIGHTCUTHEIGHTUNIT, "GP_FixedHeight"}, + {IDC_STATIC_GASONDELAY, IDC_EDIT_GASONDELAY, IDC_STATIC_GASONDELAYUNIT, "GP_GasOnDelay"}, + {IDC_STATIC_GASONFIRSTDELAY, IDC_EDIT_GASONFIRSTDELAY, IDC_STATIC_GASONFIRSTDELAYUNIT, "GP_GasOnFirstDelay"}, + {IDC_STATIC_JOGFREQ, IDC_EDIT_JOGFREQ, IDC_STATIC_JOGFREQUNIT, "GP_JogFreq"}, + {IDC_STATIC_JOGDUTYCYCLE, IDC_EDIT_JOGDUTYCYCLE, IDC_STATIC_JOGDUTYCYCLEUNIT, "GP_JogDutyCycle"}, + {IDC_STATIC_JOGLASERTIME, IDC_EDIT_JOGLASERTIME, IDC_STATIC_JOGLASERTIMEUNIT, "GP_JogTime"}, + {IDC_STC_LASERRATEDPOWER, IDC_EDIT_LASERRATEDPOWER, IDC_STATIC_LASERRATEDPOWERUNIT, "GP_LaserRatedPower"}, + {IDC_STC_REVSPEEDG00, IDC_EDIT_REVSPEEDG00, IDC_STATIC_REVSPEEDG00UNIT, "GP_RevSpeedG00"}, + }; + + CParamManager* _pParamManager = mach::GetParamManager(); + for (int _i = 0; _i < _countof(_s_cParamInfo); _i++) + { + m_listParamInEdit.push_back(_s_cParamInfo[_i]); + Parameter _param; + if (_pParamManager + && _pParamManager->GetParameter(_s_cParamInfo[_i].strIdentifier, &_param)) + { + InitParamItem _item; + _item.strIdentifier = _s_cParamInfo[_i].strIdentifier; + _item.nIniValue = _ConverParameterValueToDouble(&_param.Value); + m_listInitParamItems.push_back(_item); + } + } + + m_bDataValid = true; + m_bCancelData = false; + + // ComBox + ParamInfoComb _ParamItem; + _ParamItem.nIDCaption = IDC_STATIC_DEFUALTBLOWGAS; + _ParamItem.nIDValue = IDC_COMBO_DEFUALTBLOWGAS; + _ParamItem.strIdentifier = "GP_DefaultBlowType"; + CmbItem _item; + CString _strCount = NceGetPrivateProfileString("ParamGroup", _T("CutGasCount"), "0"); + int _nCount = atoi(_strCount); + for (int _i = 0; _i < _nCount; _i++) + { + _item.nIndex = _i; + CString _strKey; + _strKey.Format(_T("CutGas%d_Value"), _i); + _item.nValue = atoi(NceGetPrivateProfileString("ParamGroup", _strKey, "")); + _strKey.Format(_GETCS(s_szCUTGASNAME), _i); + _item.strCaption = NceGetPrivateProfileString("ParamGroup", _strKey, ""); + _ParamItem.Items.push_back(_item); + } + m_listParamInConb.push_back(_ParamItem); + + _ParamItem.nIDCaption = IDC_STATIC_POWERADJUSTMODE; + _ParamItem.nIDValue = IDC_COMBO_POWERADJUSTMODE; + _ParamItem.strIdentifier = "GP_AdjustPowerMode"; + _ParamItem.Items.clear(); + _item.nIndex = 0; + _item.nValue = 0; + _item.strCaption = _GETCS(s_csANALOG); + _ParamItem.Items.push_back(_item); + _item.nIndex = 1; + _item.nValue = 1; + _item.strCaption = _GETCS(s_csDUTYCYCLE); + _ParamItem.Items.push_back(_item); + m_listParamInConb.push_back(_ParamItem); + + _ParamItem.nIDCaption = IDC_STATIC_TARSKENDACTION; + _ParamItem.nIDValue = IDC_COMBO_TARSKENDACTION; + _ParamItem.strIdentifier = "GP_TaskEndAdditionalAction"; + _ParamItem.Items.clear(); + _item.nIndex = 0; + _item.nValue = 0; + _item.strCaption = _GETCS(s_csNOMOTION); + _ParamItem.Items.push_back(_item); + _item.nIndex = 1; + _item.nValue = 1; + _item.strCaption = _GETCS(s_csBACKFIXPOS); + _ParamItem.Items.push_back(_item); + _item.nIndex = 2; + _item.nValue = 2; + _item.strCaption = _GETCS(s_csBACKWORKORG); + _ParamItem.Items.push_back(_item); + CMarkPointTarget* _pMarkPointTarget = GetMarkPointTarget(); + if (_pMarkPointTarget) + { + int _nCount = _pMarkPointTarget->GetMarkPoints(); + for (int _i = 0; _i < _nCount; _i++) + { + CString _strCaption; + _strCaption.Format(_GETCS(s_csMARKPOINT), _i + 1); + _item.nIndex = _i + 3; + _item.nValue = _i + 3; + _item.strCaption = _strCaption; + _ParamItem.Items.push_back(_item); + } + } + m_listParamInConb.push_back(_ParamItem); + + _ParamItem.nIDCaption = IDC_STATIC_LASERMACHINETYPE; + _ParamItem.nIDValue = IDC_COMBO_LASERMACHTYPE; + _ParamItem.strIdentifier = "GP_LaserDevice"; + _ParamItem.Items.clear(); + + CString _strUserStyle = NceGetPrivateProfileString(_T("Theme"), _T("UserStyle"), _T("None")); + bool _bIsDNE = (_strUserStyle == _T("DNE")); + if (_bIsDNE) + { + _item.nIndex = 0; + _item.nValue = 0; + _item.strCaption = _T("IPG"); + _ParamItem.Items.push_back(_item); + _item.nIndex = 1; + _item.nValue = 8; + _item.strCaption = _GETCS(s_csAMERICAN); + _ParamItem.Items.push_back(_item); + _item.nIndex = 2; + _item.nValue = 9; + _item.strCaption = _GETCS(s_csGERMERN); + _ParamItem.Items.push_back(_item); + } + else + { + _item.nIndex = 0; + _item.nValue = 0; + _item.strCaption = _T("IPG"); + _ParamItem.Items.push_back(_item); + _item.nIndex = 1; + _item.nValue = 1; + _item.strCaption = _GETCS(s_csRAYCUS); + _ParamItem.Items.push_back(_item); + _item.nIndex = 2; + _item.nValue = 2; + _item.strCaption = _T("EO"); + _ParamItem.Items.push_back(_item); + _item.nIndex = 3; + _item.nValue = 3; + _item.strCaption = _T("SPI"); + _ParamItem.Items.push_back(_item); + _item.nIndex = 4; + _item.nValue = 4; + _item.strCaption = _GETCS(s_csLIANPIN); + _ParamItem.Items.push_back(_item); + _item.nIndex = 5; + _item.nValue = 5; + _item.strCaption = _GETCS(s_csMAX); + _ParamItem.Items.push_back(_item); + _item.nIndex = 6; + _item.nValue = 6; + _item.strCaption = _GETCS(s_csZKZM); + _ParamItem.Items.push_back(_item); + _item.nIndex = 7; + _item.nValue = 7; + _item.strCaption = _GETCS(s_csTXSTAR); + _ParamItem.Items.push_back(_item); + _item.nIndex = 8; + _item.nValue = 8; + _item.strCaption = _GETCS(s_csAMERICAN); + _ParamItem.Items.push_back(_item); + _item.nIndex = 9; + _item.nValue = 9; + _item.strCaption = _GETCS(s_csGERMERN); + _ParamItem.Items.push_back(_item); + } + m_listParamInConb.push_back(_ParamItem); + + // 通信串口。 + int _nCountCOM = 0; + CString _strCOM; + CString _strCOMCount = NceGetPrivateProfileString(_T("ParamGroup"), _T("COMCount"), _T("0")); + if (!_strCOMCount.IsEmpty()) + { + _nCountCOM = atoi(_strCOMCount); + } + _ParamItem.nIDCaption = IDC_STATIC_COMUNICATIONCOM; + _ParamItem.nIDValue = IDC_COMBO_COMUNICATIONTYPE; + _ParamItem.strIdentifier = "GP_CommunicationType"; + _ParamItem.Items.clear(); + _item.nIndex = 0; + _item.nValue = 0; + _item.strCaption = _GETCS(s_csNOMODE); + _ParamItem.Items.push_back(_item); + _item.nIndex = 1; + _item.nValue = 1; + _item.strCaption = "EX30A"; + _ParamItem.Items.push_back(_item); + for (int _i = 0; _i < _nCountCOM; _i++) + { + _item.nIndex = _i + 2; + _item.nValue = _i + 2; + _item.strCaption.Format("COM%d", _i + 1); + _ParamItem.Items.push_back(_item); + } + m_listParamInConb.push_back(_ParamItem); + + _ParamItem.nIDCaption = IDC_STATIC_WORKINGMODE; + _ParamItem.nIDValue = IDC_COMBO_WORKINGMODE; + _ParamItem.strIdentifier = "GP_WorkingMode"; + _ParamItem.Items.clear(); + m_listParamInConb.push_back(_ParamItem); + for (ParamListComb::iterator _it = m_listParamInConb.begin(); _it != m_listParamInConb.end(); _it++) + { + Parameter _param; + if (_pParamManager + && _pParamManager->GetParameter((*_it).strIdentifier, &_param)) + { + InitParamItem _item; + _item.strIdentifier = (*_it).strIdentifier; + _item.nIniValue = _ConverParameterValueToDouble(&_param.Value); + m_listInitParamItems.push_back(_item); + } + } + + // CheckBox + static const ParamInfoChck _s_cParamInfoInCheck[] = + { + {IDC_CHECK_FROGLEAPING, "GP_EnableFrogLeap"}, + {IDC_CHECK_ENABLEREFCIRCLE, "GP_EnableCircleLimit"}, + }; + for (int _i = 0; _i < _countof(_s_cParamInfoInCheck); _i++) + { + m_listParamInChck.push_back(_s_cParamInfoInCheck[_i]); + Parameter _param; + if (_pParamManager + && _pParamManager->GetParameter(_s_cParamInfoInCheck[_i].strIdentifier, &_param)) + { + InitParamItem _item; + _item.strIdentifier = _s_cParamInfoInCheck[_i].strIdentifier; + _item.nIniValue = _ConverParameterValueToDouble(&_param.Value); + m_listInitParamItems.push_back(_item); + } + } + + // 定高 + Parameter _param; + if (_pParamManager + && _pParamManager->GetParameter("GP_FixedHeight", &_param)) + { + InitParamItem _FixedHeight; + _FixedHeight.strIdentifier = "GP_FixedHeight"; + _FixedHeight.nIniValue = _ConverParameterValueToDouble(&_param.Value); + m_listInitParamItems.push_back(_FixedHeight); + } + + // 板外跟随 + if (_pParamManager + && _pParamManager->GetParameter("GP_OutsideCutPos", &_param)) + { + InitParamItem _OutsidePos; + _OutsidePos.strIdentifier = "GP_OutsideCutPos"; + _OutsidePos.nIniValue = _ConverParameterValueToDouble(&_param.Value); + m_listInitParamItems.push_back(_OutsidePos); + + CString _strOutsideHeight = NceGetPrivateProfileString(_T("OutsideCutting"), _T("OutsideHeight")); + m_nIniOutsideHeight = _strOutsideHeight.IsEmpty() ? -1 : atof(_strOutsideHeight); + } + m_strFollowPort = NceGetPrivateProfileString(_T("OutsideCutting"), _T("FollowPort")); + m_strFollowReadyPort = NceGetPrivateProfileString(_T("OutsideCutting"), _T("FollowReadyPort")); + + // 切膜 + CString _strFilmType = NceGetPrivateProfileString(_T("ParamGroup"), _T("CutFilmType"), _T("0")); + m_nIniCutFilmType = atoi(_strFilmType); + // 通信方式,为了还原配置 ---- 吴畏 2016-08-18 + CString _strCommunicationType = NceGetPrivateProfileString(_T("ParamGroup"), _T("CommunicationType"), _T("0")); + m_nIniCommunicationType = atoi(_strCommunicationType); +} + +CGlobalParamDlg::~CGlobalParamDlg() +{ + // 如果有需要重启的参数则提示重启。 ---- 黄海燕 2015-05-17 + CParamManager* _pParamManager = mach::GetParamManager(); + for (InitParamItemList::iterator _it = m_listInitParamItems.begin(); _it != m_listInitParamItems.end(); _it++) + { + Parameter _param; + if (_pParamManager + && _pParamManager->GetParameter(_it->strIdentifier, &_param) + && _it->nIniValue != _ConverParameterValueToDouble(&_param.Value) + && _param.nEffectType == Parameter::ET_RESTART) + { + AfxMessageBox(_GETCS(s_csReStartupTip)); + break; + } + } + + // 系统参数对话框关掉后,让参数保存一次,以防断电丢失 ---- 边俊霞 2016-01-28 + SendTargetMessage(ID_TARGET_PARAMMANAGER, TM_PARAM_SAVETOFILE, 0, 0); +} + +LRESULT CGlobalParamDlg::OnDataValid(WPARAM wParam_, LPARAM lParam_) +{ + m_bDataValid = true; + if (this->GetFocus() != NULL) + { + OnKillFocusEdits(this->GetFocus()->GetDlgCtrlID()); + } + return m_bDataValid ? 1L : 0L; +} + +// 载入工艺的时候刷新所需要的 ---- 彭朋 2017-04-21 +LRESULT CGlobalParamDlg::OnLoadLayer(WPARAM wParam_, LPARAM lParam_) +{ + // 保留其他只刷新想要的。 + nce::CParam* _pParam = (nce::CParam*)wParam_; + CString _strVal = _pParam->GetKey(_T("CutFilmType")); + if (!_strVal.IsEmpty()) + NceWritePrivateProfileString(_T("ParamGroup"), _T("CutFilmType"), _strVal); + CComboBox* _pComb = (CComboBox*)GetDlgItem(IDC_COMBO_CUTFILM); + CString _strTypeOrg = NceGetPrivateProfileString(_T("ParamGroup"), _T("CutFilmType"), _T("0")); + if (_strTypeOrg.IsEmpty()) + _pComb->SetCurSel(0); + else + { + int _nType = atoi(_strTypeOrg); + ASSERT(_nType >= 0 && _nType <= 3); + _pComb->SetCurSel(_nType); + } + return 0L; +} + +LRESULT CGlobalParamDlg::OnKickIdle(WPARAM wParam_, LPARAM lParam_) +{ + if (!IsWindowVisible()) + return 0L; + UpdateDialogControls(this, (BOOL)wParam_); + return 0L; +} + +void CGlobalParamDlg::DoDataExchange(CDataExchange* pDX_) +{ + CDialog::DoDataExchange(pDX_); +} + +void CGlobalParamDlg::OnOK() +{ + CString _flag = NceGetPrivateProfileString(_T("GasCheck"), _T("GNGasCheck"), _T("0")); + if ("1" == _flag) + { + CParamManager* _pParamManager = GetParamManager(); + Parameter _param; + if (_pParamManager->GetParameter("GP_DefaultBlowType", &_param)) + { + double _nValue = _ConverParameterValueToDouble(&_param.Value); + if (0 == _nValue) + { + bool _bAir = true; + CString _strCheckAir("EnableCheckAir"); + SendTargetMessage(ID_TARGET_PARAMMANAGER, TM_SET_PARAMVALUE, WPARAM(_strCheckAir.GetBuffer()), (LPARAM)&_bAir); + } + else if ((1 == _nValue) || (3 == _nValue)) + { + bool _bNitrogen = true; + CString _strCheckNitrogen("EnableCheckNitrogen"); + SendTargetMessage(ID_TARGET_PARAMMANAGER, TM_SET_PARAMVALUE, WPARAM(_strCheckNitrogen.GetBuffer()), (LPARAM)&_bNitrogen); + } + else if ((2 == _nValue) || (4 == _nValue)) + { + bool _bOxygen = true; + CString _strCheckOxygen("EnableCheckOxygen"); + SendTargetMessage(ID_TARGET_PARAMMANAGER, TM_SET_PARAMVALUE, WPARAM(_strCheckOxygen.GetBuffer()), (LPARAM)&_bOxygen); + } + } + } + + m_bDataValid = true; +} + +LRESULT CGlobalParamDlg::OnInitCancelData(WPARAM wParam_, LPARAM lParam_) +{ + m_bCancelData = false; + return 0L; +} + +void CGlobalParamDlg::OnCancel() +{ + m_bCancelData = true; + + // 还原系统参数 + for (InitParamItemList::iterator _it = m_listInitParamItems.begin(); _it != m_listInitParamItems.end(); _it++) + { + CParamManager* _pParamManager = GetParamManager(); + Parameter _param; + if (_pParamManager->GetParameter(_it->strIdentifier, &_param) + && !DOUBLE_EQU(_ConverParameterValueToDouble(&_param.Value), _it->nIniValue)) + { + _ConverDoubelToParameterValue(_it->nIniValue, &_param.Value); + _pParamManager->SetParameterValue(_it->strIdentifier, &_param.Value); + + if (_it->strIdentifier == "GP_OutsideCutPos") + { + CString _strOutsidePos; + if (m_nIniOutsideHeight >=0) + _strOutsidePos.Format(_T("%.3f"), _it->nIniValue); + if (_strOutsidePos != NceGetPrivateProfileString(_T("OutsideCutting"), _T("OutsidePos"))) + NceWritePrivateProfileString(_T("OutsideCutting"), _T("OutsidePos"), _strOutsidePos); + } + + if (_it->strIdentifier == "GP_TaskEndAdditionalAction" + && _it->nIniValue >= 3 + && _it->nIniValue <=10) + { + CMarkPointTarget* _pMarkPointTarget = GetMarkPointTarget(); + ASSERT(_pMarkPointTarget); + _pMarkPointTarget->SetTaskEndMarkPoint(int(_it->nIniValue - 3)); + } + } + } + + // 还原配置信息 + CString _strNew = NceGetPrivateProfileString(_T("OutsideCutting"), _T("OutsideHeight")); + CString _strOrg; + if (m_nIniOutsideHeight >= 0) _strOrg.Format(_T("%.3f"), m_nIniOutsideHeight); + if (_strOrg != _strNew) + NceWritePrivateProfileString(_T("OutsideCutting"), _T("OutsideHeight"), _strOrg); + _strNew = NceGetPrivateProfileString(_T("ParamGroup"), _T("CutFilmType"), _T("0")); + _strOrg.Format(_T("%d"), m_nIniCutFilmType); + if (_strOrg != _strNew) + NceWritePrivateProfileString(_T("ParamGroup"), _T("CutFilmType"), _strOrg); + _strNew = NceGetPrivateProfileString(_T("ParamGroup"), _T("CommunicationType"), _T("0")); + _strOrg.Format(_T("%d"), m_nIniCommunicationType); + if (_strOrg != _strNew) + NceWritePrivateProfileString(_T("ParamGroup"), _T("CommunicationType"), _strOrg); +} + +HBRUSH CGlobalParamDlg::OnCtlColor(CDC* pDC_, CWnd* pWnd_, UINT nCtlColor_) +{ + HBRUSH _hbr = __super::OnCtlColor(pDC_, pWnd_, nCtlColor_); + if (pWnd_->GetDlgCtrlID() == IDC_STC_NOTECONTEXT + || pWnd_->GetDlgCtrlID() == IDC_STC_NOTECONTEXT1) + { + // Set the text color to green + pDC_->SetTextColor(RGB(0, 128, 0)); + } + + return _hbr; +} + +BOOL CGlobalParamDlg::OnInitDialog() +{ + BOOL _bRet = __super::OnInitDialog(); + + for (ParamListComb::iterator _it = m_listParamInConb.begin(); _it != m_listParamInConb.end(); _it++) + { + CComboBox* _pComb = (CComboBox*)GetDlgItem(_it->nIDValue); + for (CmbItemList::iterator _iter = _it->Items.begin(); _iter != _it->Items.end(); _iter++) + { + _pComb->InsertString(_iter->nIndex, _iter->strCaption); + } + } + + //带膜切割。 + SetDlgItemText(IDC_STATIC_CUTFILM, _GETCS(s_csCUTFILM)); + CComboBox* _pComb = (CComboBox*)GetDlgItem(IDC_COMBO_CUTFILM); + _pComb->InsertString(0, _GETCS(s_szNONE)); + _pComb->InsertString(1, _GETCS(s_szCUTFILMINDIVIDUAL)); + _pComb->InsertString(2,_GETCS(s_szCUTFILMINGROUPS)); + _pComb->InsertString(3, _GETCS(s_szCUTFILMINWHOLE)); + CString _strTypeOrg = NceGetPrivateProfileString(_T("ParamGroup"), _T("CutFilmType"), _T("0")); + if (_strTypeOrg.IsEmpty()) + _pComb->SetCurSel(0); + else + { + int _nType = atoi(_strTypeOrg); + ASSERT(_nType >= 0 && _nType <= 3); + _pComb->SetCurSel(_nType); + } + + SetDlgItemText(IDC_STATIC_MACHBASEPARAM, _GETCS(s_csMOTIONCONTROLPARAM)); + SetDlgItemText(IDC_STATIC_LASERDEVICEPARAM, _GETCS(s_csLASERPARAM)); + SetDlgItemText(IDC_STATIC_FOLLOWCONTROL, _GETCS(s_csFOLLOWCONTROLPARAM)); + SetDlgItemText(IDC_STATIC_PRESSURECONTROL, _GETCS(s_csPRESSURECONTROL)); + SetDlgItemText(IDC_STATIC_TASKENDMOTIONS, _GETCS(s_csTARSKENDMOTION)); + SetDlgItemText(IDC_STATIC_ADVANCED, _GETCS(s_csADVANCED)); + SetDlgItemText(IDC_BTN_PLCADVANCED, _GETCS(s_csPLCSETTING)); + SetDlgItemText(IDC_BTN_GETFIXHEIGHTCUTPOS, _GETCS(s_csGETFIXEDPOS)); + SetDlgItemText(IDC_STATIC_CUTFROMOUTSIDE, _GETCS(s_csCUTFROMOUTSIDE)); + SetDlgItemText(IDC_BTN_SAVEREFERHEIGHT, _GETCS(s_csSETEDGECUTTINGHEIGHT)); + SetDlgItemText(IDC_STATIC_WORKINGMODE, _GETCS(s_csWORKINGMODE)); + SetDlgItemText(IDC_STATIC_COMUNICATIONCOM, _GETCS(s_csCOMINICATMODE)); + SetDlgItemText(IDC_STC_LASERRATEDPOWER, _GETCS(s_csRATEDPOWER)); + SetDlgItemText(IDC_BTN_LASERRESET, _GETCS(s_csLASERRESET)); + + CString _strUser = NceGetPrivateProfileString(_T("User"), _T("User"), _T("0")); + BOOL _bisTJNK = _strUser == _T("TJNK"); + CString _strRecommend = NceGetPrivateProfileString(_T("User"), _T("ShowRecommend"), _T("0")); + BOOL _bRecommend = _strRecommend == _T("1"); + + if (_bisTJNK && _bRecommend) + { + SetDlgItemText(IDC_STC_NOTECONTEXT, _GETCS(s_csCONTEXT_NK)); + SetDlgItemText(IDC_STC_NOTECONTEXT1, _GETCS(s_csCONTEXT1_NK)); + } + else + { + SetDlgItemText(IDC_STC_NOTECONTEXT, _GETCS(s_csCONTEXT)); + SetDlgItemText(IDC_STC_NOTECONTEXT1, _GETCS(s_csCONTEXT1)); + } + + // 还没有的功能先灰掉。 + GetDlgItem(IDC_BTN_PLCADVANCED)->EnableWindow(FALSE); + + // 如果是管材配置就隐藏走边框速度,显示旋转轴空程速度。反之则反 ---- DingQiang 2016-12-08 + CTubeTarget* _pTubeTarget = GetTubeTarget(); + if (_pTubeTarget && _pTubeTarget->IsEnable()) + { + GetDlgItem(IDC_STATIC_SIMUCUTSPEED)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_SIMUCUTSPEED)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_EDIT_SIMUCUTSPEED)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_SIMUCUTSPEED)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_STATIC_SIMUCUTSPEEDUNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_SIMUCUTSPEEDUNIT)->ShowWindow(SW_HIDE); + } + else + { + GetDlgItem(IDC_STC_REVSPEEDG00)->EnableWindow(FALSE); + GetDlgItem(IDC_STC_REVSPEEDG00)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_EDIT_REVSPEEDG00)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_REVSPEEDG00)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_STATIC_REVSPEEDG00UNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_REVSPEEDG00UNIT)->ShowWindow(SW_HIDE); + } + + Update(); + SetTimer(101, 100, NULL); + + return _bRet; +} + +void CGlobalParamDlg::OnKillFocusEdits(UINT nID_) +{ + //用户取消 ---- 彭朋 2016-07-21 + if (m_bCancelData) + { + return; + } + + for (ParamListE::iterator _it = m_listParamInEdit.begin(); _it != m_listParamInEdit.end(); _it++) + { + if (nID_ != _it->nIDValue) + continue; + + // 如果内容没有变则不用更新。 ---- 黄海燕 2015-09-18 + for (int _i = 0; _i < _countof(m_LastTextItems); _i++) + { + if (m_LastTextItems[_i].nID != nID_) + continue; + CString _strText; + GetDlgItemText(_it->nIDValue, _strText); + if ((m_LastTextItems[_i].strLastText == _strText) && _IsNumber(_strText)) + return; + break; + } + + CParamManager* _pParamManager = GetParamManager(); + m_bDataValid = true; + + // 将参数值设进去。 + if (_CanModify()) + { + if (!_SetParam(&(*_it))) + { + m_bDataValid = false; + GetDlgItem(_it->nIDValue)->SetFocus(); + } + } + + Parameter _param; + if (!_pParamManager->GetParameter(_it->strIdentifier, &_param)) + { + // 拿不到参数则显示参数不可用,且灰掉。 + GetDlgItem(_it->nIDCaption)->EnableWindow(FALSE); + SetDlgItemText(_it->nIDValue, _GETCS(s_csUNAVAILIBLEPARAM)); + GetDlgItem(_it->nIDValue)->EnableWindow(FALSE); + if (_it->nIDUnit != NULL) + GetDlgItem(_it->nIDUnit)->EnableWindow(FALSE); + break; + } + CString _strCaption(_param.szName); + _strCaption += _GETCS(s_szCOLON); + SetDlgItemText(_it->nIDCaption, _strCaption); + if (_it->nIDUnit != NULL) + _ShowUnit(&(*_it)); + _SetDlgItemText(_it->nIDValue, ConverToUiUnit(_param)); + GetDlgItem(_it->nIDCaption)->EnableWindow(TRUE); + GetDlgItem(_it->nIDValue)->EnableWindow(TRUE); + if (_it->nIDUnit != NULL) + GetDlgItem(_it->nIDUnit)->EnableWindow(TRUE); + break; + } +} + +void CGlobalParamDlg::OnSetFocusEdits(UINT nID_) +{ + ASSERT(_countof(m_LastTextItems) >= 2); + m_LastTextItems[1].nID = m_LastTextItems[0].nID; + m_LastTextItems[1].strLastText = m_LastTextItems[0].strLastText; + m_LastTextItems[0].nID = nID_; + GetDlgItemText(nID_, m_LastTextItems[0].strLastText); +} + +void CGlobalParamDlg::OnSelTaskEndMotion() +{ + CComboBox* _pComb = (CComboBox*)GetDlgItem(IDC_COMBO_TARSKENDACTION); + CParamManager* _pParamManager = GetParamManager(); + for (ParamListComb::iterator _it = m_listParamInConb.begin(); _it != m_listParamInConb.end(); _it++) + { + if (IDC_COMBO_TARSKENDACTION != _it->nIDValue) + continue; + + Parameter _param; + if (!_pParamManager->GetParameter(_it->strIdentifier, &_param)) + { + ASSERT(FALSE); + return; + } + + if (!_CanModify()) + { + AfxMessageBox(_GETCS(s_csNotInputPrompt)); + double _nValue = _ConverParameterValueToDouble(&_param.Value); + for (CmbItemList::iterator _iter = _it->Items.begin(); _iter != _it->Items.end(); _iter++) + { + if (DOUBLE_EQU(_nValue, _iter->nValue)) + { + _pComb->SetCurSel(_iter->nIndex); + break; + } + } + return; + } + + int _nIndex = _pComb->GetCurSel(); + CmbItemList::iterator _itTarget = _it->Items.end(); + for (CmbItemList::iterator _iter = _it->Items.begin(); _iter != _it->Items.end(); _iter++) + { + if (_iter->nIndex == _nIndex) + { + _itTarget = _iter; + break; + } + } + if (_itTarget == _it->Items.end()) + { + ASSERT(FALSE); + return; + } + + _ConverDoubelToParameterValue(_itTarget->nValue, &_param.Value); + bool _bSuccess = _pParamManager->SetParameterValue(_it->strIdentifier, &_param.Value); + ASSERT(_bSuccess); + // 设置标记点坐标。 --- 黄海燕 2015-12-21 + if (_bSuccess && _itTarget->nValue > 2) + { + CMarkPointTarget* _pMarkPointTarget = GetMarkPointTarget(); + if (_pMarkPointTarget) + { + _pMarkPointTarget->SetTaskEndMarkPoint(int(_itTarget->nValue - 3)); + } + } + break; + } +} + +void CGlobalParamDlg::OnSelectComb(UINT nID_) +{ + CComboBox* _pComb = (CComboBox*)GetDlgItem(nID_); + + if (nID_ == IDC_COMBO_COMUNICATIONTYPE) + { + int _nIndex = _pComb->GetCurSel(); + CString _strCommunicationType; + _strCommunicationType.Format("%d", _nIndex); + NceWritePrivateProfileString(_T("ParamGroup"), _T("CommunicationType"), _strCommunicationType); + } + + CParamManager* _pParamManager = GetParamManager(); + for (ParamListComb::iterator _it = m_listParamInConb.begin(); _it != m_listParamInConb.end(); _it++) + { + if (nID_ != _it->nIDValue) + continue; + + Parameter _param; + if (!_pParamManager->GetParameter(_it->strIdentifier, &_param)) + { + ASSERT(FALSE); + return; + } + + if (!_CanModify()) + { + AfxMessageBox(_GETCS(s_csNotInputPrompt)); + double _nValue = _ConverParameterValueToDouble(&_param.Value); + for (CmbItemList::iterator _iter = _it->Items.begin(); _iter != _it->Items.end(); _iter++) + { + if (DOUBLE_EQU(_nValue, _iter->nValue)) + { + _pComb->SetCurSel(_iter->nIndex); + break; + } + } + return; + } + + int _nIndex = _pComb->GetCurSel(); + CmbItemList::iterator _itTarget = _it->Items.end(); + for (CmbItemList::iterator _iter = _it->Items.begin(); _iter != _it->Items.end(); _iter++) + { + if (_iter->nIndex == _nIndex) + { + _itTarget = _iter; + break; + } + } + if (_itTarget == _it->Items.end()) + { + ASSERT(FALSE); + return; + } + + _ConverDoubelToParameterValue(_itTarget->nValue, &_param.Value); + bool _bSuccess = _pParamManager->SetParameterValue(_it->strIdentifier, &_param.Value); + ASSERT(_bSuccess); + break; + } +} + +void CGlobalParamDlg::OnClickCheckBoxes(UINT nID_) +{ + CParamManager* _pParamManager = GetParamManager(); + if (!_pParamManager) + { + ASSERT(FALSE); + return; + } + + for (ParamListChck::iterator _it = m_listParamInChck.begin(); _it != m_listParamInChck.end(); _it++) + { + if (_it->nID != nID_) + continue; + + Parameter _param; + if (!_pParamManager->GetParameter(_it->strIdentifier, &_param)) + { + GetDlgItem(_it->nID)->EnableWindow(FALSE); + continue; + } + GetDlgItem(_it->nID)->EnableWindow(TRUE); + ASSERT(_param.Value.nType == ParameterValue::VT_BOOL); + if (!_CanModify()) + { + ((CButton*)GetDlgItem(_it->nID))->SetCheck(_param.Value.bValue ? BST_CHECKED : BST_UNCHECKED); + AfxMessageBox(_GETCS(s_csNotInputPrompt)); + break; + } + _param.Value.bValue = !_param.Value.bValue; + bool _bSuccess = _pParamManager->SetParameterValue(_it->strIdentifier, &_param.Value); + ASSERT(_bSuccess); + break; + } +} + +// 带膜切割: +// 保存在ini文件中的切膜类型含义 +// CutFilm=X ----- 指定某一图层为切膜图层 +// CutFilmType=0 ---- 不带膜切割 +// CutFilmType=1 ---- 逐个切膜 +// CutFilmType=2 ---- 分组切膜 +// CutFilmType=3 ---- 全局切膜 +// ---- 黄海燕 2015-05-13 +void CGlobalParamDlg::OnSelectCutFilm() +{ + CComboBox* _pComb = (CComboBox*)GetDlgItem(IDC_COMBO_CUTFILM); + if (!_CanModify()) + { + AfxMessageBox(_GETCS(s_csNotInputPrompt)); + CString _strTypeOrg = NceGetPrivateProfileString(_T("ParamGroup"), _T("CutFilmType"), _T("0")); + if (_strTypeOrg.IsEmpty()) + _pComb->SetCurSel(0); + else + { + int _nType = atoi(_strTypeOrg); + ASSERT(_nType >= 0); + _pComb->SetCurSel(_nType); + } + return; + } + + int _nIndex = _pComb->GetCurSel(); + CString _strCutFilmType; + _strCutFilmType.Format("%d", _nIndex); + NceWritePrivateProfileString(_T("ParamGroup"), _T("CutFilmType"), _strCutFilmType); +} + +void CGlobalParamDlg::OnResetLaser() +{ + CPortsManager* _pPortsManager = GetPortsManager(); + if (!_pPortsManager) + { + return; + } + + // 从NcEditor.ini里读入配置信息,如果ResetLaser字段值为Port**则对相应的端口执行开闭操作 ---- 边俊霞 2016-05-25 + static CString _s_strResetLaser = NceGetPrivateProfileString(_T("PGLayerDlg"), _T("ResetLaser")); + static CString _s_strResetLaserDelay = NceGetPrivateProfileString(_T("PGLayerDlg"), _T("ResetLaserDelay")); + int _nResetLaserDelay = min(max(50, atoi(_s_strResetLaserDelay)), 1000); + + if (_s_strResetLaser.Left(4) == _T("Port")) + { + CString _strIdentifier = _s_strResetLaser.Mid(4); + BitPort _Port; + _pPortsManager->GetBitPort(_strIdentifier, &_Port); + _Port.bValue = TRUE; + _pPortsManager->SetBitPort(_strIdentifier, &_Port); + Sleep(_nResetLaserDelay); + _Port.bValue = FALSE; + _pPortsManager->SetBitPort(_strIdentifier, &_Port); + } +} + +void CGlobalParamDlg::OnUpdateResetLaser(CCmdUI* pCmd_) +{ + ASSERT(pCmd_); + + // 从NcEditor.ini里读入配置信息,如果ResetLaser字段值为Disable或空字符则将“激光器复位”按钮灰显掉 ---- 边俊霞 2016-05-25 + static CString _s_strResetLaser = NceGetPrivateProfileString(_T("PGLayerDlg"), _T("ResetLaser")); + if (_s_strResetLaser == _T("") || _s_strResetLaser == _T("Disable")) + { + pCmd_->Enable(FALSE); + } +} + +void CGlobalParamDlg::OnUpdateFrogLeap(CCmdUI* pCmd_) +{ +} + +void CGlobalParamDlg::OnUpdateCircleLimit(CCmdUI* pCmd_) +{ +} + +void CGlobalParamDlg::OnGetFixedCutHeight() +{ + ParamInfoE _item; + _item.strIdentifier = "GP_FixedHeight"; + _item.nIDCaption = IDC_BTN_GETFIXHEIGHTCUTPOS; + _item.nIDValue = IDC_EDIT_FIXHEIGHTCUTHEIGHT; + _item.nIDUnit = IDC_STATIC_FIXHEIGHTCUTHEIGHTUNIT; + CParamManager* _pParamManager = mach::GetParamManager(); + ParameterValue _paramZPos; + ParameterValue _paramFixedHeight; + if (_pParamManager + && _pParamManager->GetParameterValue("Dyn_Axis2_Pos", &_paramZPos) + && _paramZPos.nType == ParameterValue::VT_DOUBLE + && _pParamManager->GetParameterValue(_item.strIdentifier, &_paramFixedHeight) + && _paramFixedHeight.nType == _paramZPos.nType) + { + _paramFixedHeight.dValue = _paramZPos.dValue; + _pParamManager->SetParameterValue(_item.strIdentifier, &_paramFixedHeight); + _pParamManager->GetParameterValue(_item.strIdentifier, &_paramFixedHeight); + _SetDlgItemText(_item.nIDValue, &_paramFixedHeight); + return; + } + + SetDlgItemText(_item.nIDValue, _GETCS(s_csUNAVAILIBLEPARAM)); +} + +void CGlobalParamDlg::OnSaveEdgeCuttingHeight() +{ + CStateManager* _pStateManager = mach::GetStateManager(); + CStateManager::State _nState = CStateManager::Idle; + if (_pStateManager && _pStateManager->GetState(&_nState) + && _nState != CStateManager::Idle) + { + AfxMessageBox(_GETCS(s_csCANNOTSAVEOUTSIDEHEIGHT)); + Update(); + return; + } + + // 上次保存参照高度还没完,本次不允许进入。 ---- 黄海燕 2015-08-01 + if (m_bSavingOutsideHeight) + return; + + // 设置板外高度为跟随高度。 ---- 黄海燕 2015-08-01 + CParamManager* _pParamManager = mach::GetParamManager(); + if (!_pParamManager) + { + ASSERT(FALSE); + Update(); + return; + } + Parameter _FollowHeight; + if (!_pParamManager->GetParameter("GP_FollowHeight", &_FollowHeight)) + { + AfxMessageBox(_GETCS(s_csGETFOLLOWHEIGHTFAILED)); + Update(); + return; + } + + ASSERT(_FollowHeight.Value.nType == ParameterValue::VT_DOUBLE); + CString _strText; + GetDlgItemText(IDC_EDIT_OUTSIDECUTHEIGHT, _strText); + if (!_IsNumber(_strText)) + { + AfxMessageBox(_GETCS(s_csINVALIDINPUT)); + Update(); + return; + } + + double _nHeight = atof(_strText); + if (!DOUBLE_EQU(_FollowHeight.Value.dValue, _nHeight)) + { + m_nIniFollowHeight = _FollowHeight.Value.dValue; + _FollowHeight.Value.dValue = _nHeight; + if (!_pParamManager->SetParameterValue("GP_FollowHeight", &_FollowHeight.Value)) + { + CString _strPrompt; + _strPrompt.Format(_GETCS(s_csModifyParamError), _FollowHeight.szName, CString(_pParamManager->FormateLastError(_pParamManager->GetLastError()))); + MessageBox(_strPrompt, _GETCS(s_csErrorPrompt), MB_OK); + Update(); + return; + } + m_bBackUp = true; + } + + if (m_strFollowPort.IsEmpty() || m_strFollowReadyPort.IsEmpty()) + { + ASSERT(FALSE); + _FollowHeight.Value.dValue = m_nIniFollowHeight; + _pParamManager->SetParameterValue("GP_FollowHeight", &_FollowHeight.Value); + m_bBackUp = false; + Update(); + return; + } + + mach::CPortsManager* _pPortsManager = mach::GetPortsManager(); + if (!_pPortsManager) + { + ASSERT(FALSE); + _FollowHeight.Value.dValue = m_nIniFollowHeight; + _pParamManager->SetParameterValue("GP_FollowHeight", &_FollowHeight.Value); + m_bBackUp = false; + Update(); + return; + } + + // 打开随动。 ---- 黄海燕 2015-08-01 + mach::BitPort _BitPort; + memset(&_BitPort, 0, sizeof(mach::BitPort)); + _pPortsManager->GetBitPort(m_strFollowPort, &_BitPort); + if (!_BitPort.bValue) + { + _BitPort.bValue = true; + _pPortsManager->SetBitPort(m_strFollowPort, &_BitPort); + } + m_bSavingOutsideHeight = true; +} + +void CGlobalParamDlg::OnTimer(UINT_PTR nIDEvent_) +{ + // 检查图层单位切换。 ---- 黄海燕 2015-09-01 + int _nSpeedUnit = atoi(NceGetPrivateProfileString(c_szParamGroupUnit, c_szSpeedUnit, "0")); + int _nAccUnit = atoi(NceGetPrivateProfileString(c_szParamGroupUnit, c_szAccUnit, "0")); + int _nTimeUnit = atoi(NceGetPrivateProfileString(c_szParamGroupUnit, c_szTimeUnit, "0")); + static int _s_nLastSpeedUnit = _nSpeedUnit; + static int _s_nLastAccUnit = _nAccUnit; + static int _s_nLastTimeUnit = _nTimeUnit; + if (_nSpeedUnit != _s_nLastSpeedUnit + || _nAccUnit != _s_nLastAccUnit + || _nTimeUnit != _s_nLastTimeUnit) + { + Update(); + } + _s_nLastSpeedUnit = _nSpeedUnit; + _s_nLastAccUnit = _nAccUnit; + _s_nLastTimeUnit = _nTimeUnit; + + // 跟随到板外高度100ms之后才去检查跟随到位没。 ---- 黄海燕 2015-08-01 + static bool _bLast = m_bSavingOutsideHeight; + if (_bLast == false && m_bSavingOutsideHeight == true) + { + _bLast = m_bSavingOutsideHeight; + return; + } + _bLast = m_bSavingOutsideHeight; + if (!m_bSavingOutsideHeight) + return; + + mach::CPortsManager* _pPortsManager = mach::GetPortsManager(); + if (!_pPortsManager) + { + ASSERT(FALSE); + return; + } + + mach::BitPort _FollowPort; + memset(&_FollowPort, 0, sizeof(mach::BitPort)); + _pPortsManager->GetBitPort(m_strFollowPort, &_FollowPort); + mach::BitPort _FollowReady; + memset(&_FollowReady, 0, sizeof(mach::BitPort)); + _pPortsManager->GetBitPort(m_strFollowReadyPort, &_FollowReady); + static int _s_nReadyCount = 0; + if (_FollowPort.bValue && _FollowReady.bValue) + { + _s_nReadyCount++; + + if (_s_nReadyCount > 10000) + _s_nReadyCount = 10000; + } + else + { + _s_nReadyCount = 0; + } + + // 到位1s之后开始记录坐标。---- 黄海燕 2015-08-10 + if (10 == _s_nReadyCount) + { + _s_nReadyCount = 0; + // 保存参照高度坐标值。 ---- 黄海燕 2015-08-01 + CParamManager* _pParamManager = mach::GetParamManager(); + ParameterValue _FollowHeight; + if (!_pParamManager + || !_pParamManager->GetParameterValue("GP_FollowHeight", &_FollowHeight) + || _FollowHeight.nType != ParameterValue::VT_DOUBLE) + { + Update(); + return; + } + // 本次保存参照高度动作结束。 ---- 黄海燕 2015-08-01 + m_bSavingOutsideHeight = false; + + ParameterValue _paramZPos; + ParameterValue _OutsideCutPos; + if (_pParamManager + && _pParamManager->GetParameterValue("Dyn_Axis2_Pos", &_paramZPos) + && _paramZPos.nType == ParameterValue::VT_DOUBLE + && _pParamManager->GetParameterValue("GP_OutsideCutPos", &_OutsideCutPos)) + { + _OutsideCutPos.dValue = _paramZPos.dValue; + if (!_pParamManager->SetParameterValue("GP_OutsideCutPos", &_OutsideCutPos)) + { + AfxMessageBox(_GETCS(s_csSAVEOUTSIDEHEIGHTFAILED)); + } + else + { + AfxMessageBox(_GETCS(s_csSAVEOUTSIDEHEIGHTSUCCESS)); + CString _strHeight; + _strHeight.Format("%.3f", _FollowHeight.dValue); + if (NceGetPrivateProfileString(_T("OutsideCutting"), _T("OutsideHeight")) != _strHeight) + NceWritePrivateProfileString(_T("OutsideCutting"), _T("OutsideHeight"), _strHeight); + CString _strCurZPos; + _strCurZPos.Format(_T("%.3f"), _OutsideCutPos.dValue); + if (_strCurZPos != NceGetPrivateProfileString(_T("OutsideCutting"), _T("OutsidePos"))) + NceWritePrivateProfileString(_T("OutsideCutting"), _T("OutsidePos"), _strCurZPos); + } + } + else + { + AfxMessageBox(_GETCS(s_csSAVEOUTSIDEHEIGHTFAILED)); + } + + // 关闭随动。 ---- 黄海燕 2015-08-01 + _FollowPort.bValue = false; + _pPortsManager->SetBitPort(m_strFollowPort, &_FollowPort); + + // 还原跟随高度。 ---- 黄海燕 2015-08-01 + if (m_bBackUp) + { + m_bBackUp = false; + _FollowHeight.dValue = m_nIniFollowHeight; + _pParamManager->SetParameterValue("GP_FollowHeight", &_FollowHeight); + } + Update(); + } +} + +bool CGlobalParamDlg::_SetParam(const ParamInfoE* pInfo_) +{ + CParamManager* _pParamManager = GetParamManager(); + if (!_pParamManager || !pInfo_) + { + ASSERT(FALSE); + return false; + } + + Parameter _param; + if (!_pParamManager->GetParameter(pInfo_->strIdentifier, &_param)) + { + ASSERT(FALSE); + return false; + } + + CString _strText; + GetDlgItemText(pInfo_->nIDValue, _strText); + // 检查是否数字。 + if (!_IsNumber(_strText)) + { + double _nOldValue = ConverToUiUnit(_param); + if (!m_bCancelData) + { + m_bCancelData = true; + AfxMessageBox(_GETCS(s_csINVALIDINPUT)); + m_bCancelData = false; + } + _SetDlgItemText(pInfo_->nIDValue, _nOldValue);// 还原之前设置。 + return false; + } + + double _nValue = atof(_strText.GetBuffer()); + _strText.ReleaseBuffer(); + + // -0 则为0。 + if (!_strText.IsEmpty() && _strText[0] == _T('-') && DOUBLE_EQU_ZERO(_nValue)) + { + _nValue = 0; + } + + Parameter _value = _param; + _value.Value.nType = ParameterValue::VT_DOUBLE; + _value.Value.dValue = _nValue; + double _nAfterConvet = ConverToSysUnit(_value); + Parameter _ValueToSet= _param; + _ConverDoubelToParameterValue(_nAfterConvet, &_ValueToSet.Value); + if (!memcmp(&_ValueToSet.Value, &_param.Value, sizeof(ParameterValue))) + return true; + + if (!_CanModify()) + { + double _nOldValue = ConverToUiUnit(_param); + m_bCancelData = true; + AfxMessageBox(_GETCS(s_csNotInputPrompt)); + m_bCancelData = false; + _SetDlgItemText(pInfo_->nIDValue, _nOldValue); // 还原之前设置。 + return false; + } + + if (!_pParamManager->SetParameterValue(pInfo_->strIdentifier, &_ValueToSet.Value)) + { + CString _strPrompt; + _strPrompt.Format(_GETCS(s_csModifyParamError), _param.szName, CString(_pParamManager->FormateLastError(_pParamManager->GetLastError()))); + _strPrompt = ConverPromptUnit(_param, _strPrompt); + double _nOldValue = ConverToUiUnit(_param); + m_bCancelData = true; + MessageBox(_strPrompt, _GETCS(s_csErrorPrompt), MB_OK); + m_bCancelData = false; + _SetDlgItemText(pInfo_->nIDValue, _nOldValue); // 还原之前设置。 + return false; + } + return true; +} + +void CGlobalParamDlg::_SetDlgItemText(UINT nID_, const ParameterValue* pPValue_) +{ + if (!pPValue_) + return; + + CString _strText; + static TCHAR _ch[128] = {0}; + switch(pPValue_->nType) + { + case mach::ParameterValue::VT_BOOL: + pPValue_->bValue ? strcpy_s(_ch, 128, "1") : strcpy_s(_ch, 128, "0"); + _strText = _ch; + break; + case mach::ParameterValue::VT_SHORT: + _strText.Format("%d", pPValue_->sValue); + break; + case mach::ParameterValue::VT_INT: + _strText.Format("%d", pPValue_->iValue); + break; + case mach::ParameterValue::VT_FLOAT: + _strText.Format("%.6f", pPValue_->fValue); + FormatDoubleParamer(_strText); + break; + case mach::ParameterValue::VT_DOUBLE: + _strText.Format("%.10f", pPValue_->dValue); + FormatDoubleParamer(_strText); + break; + default: + ASSERT(FALSE); + break; + } + + // 不显示-0。 ---- 黄海燕 2015-05-22 + double _nValue = _ConverParameterValueToDouble(pPValue_); + if (DOUBLE_EQU_ZERO(_nValue) && !_strText.IsEmpty() && _strText[0] == _T('-')) + _strText.Delete(0); + + SetDlgItemText(nID_, _strText); +} + +bool CGlobalParamDlg::_IsNumber(LPCTSTR pszText_) +{ + if(!pszText_) + return false; + + CString _strText(pszText_); + if (_strText.IsEmpty()) + return false; + int _nDotCount = 0; + for (int _i = 0; _i < _strText.GetLength(); _i++) + { + if (_i == 0 && (_strText[_i] == '-' || _strText[_i] == '+')) + continue; + + if (!isdigit(_strText[_i]) && _strText[_i] != '.') + return false; + + if (_strText[_i] == '.') + _nDotCount++; + } + if (_nDotCount > 1) + return false; + + return true; +} + +void CGlobalParamDlg::Update() +{ + UpdateEdits(); + + CParamManager* _pParamManager = GetParamManager(); + for (ParamListComb::iterator _it = m_listParamInConb.begin(); _it != m_listParamInConb.end(); _it++) + { + Parameter _param; + if (!_pParamManager->GetParameter(_it->strIdentifier, &_param)) + { + GetDlgItem(_it->nIDCaption)->EnableWindow(FALSE); + GetDlgItem(_it->nIDValue)->EnableWindow(FALSE); + continue; + } + GetDlgItem(_it->nIDCaption)->EnableWindow(TRUE); + GetDlgItem(_it->nIDValue)->EnableWindow(TRUE); + CString _strCaption(_param.szName); + _strCaption += _GETCS(s_szCOLON); + SetDlgItemText(_it->nIDCaption, _strCaption); + double _nValue = _ConverParameterValueToDouble(&_param.Value); + CComboBox* _pComb = (CComboBox*)GetDlgItem(_it->nIDValue); + if (IsInvalidDouble(_nValue)) + { + _pComb->SetCurSel(-1); + continue; + } + + for (CmbItemList::iterator _iter = _it->Items.begin(); _iter != _it->Items.end(); _iter++) + { + if (DOUBLE_EQU(_nValue, _iter->nValue)) + { + _pComb->SetCurSel(_iter->nIndex); + break; + } + } + } + + for (ParamListChck::iterator _it = m_listParamInChck.begin(); _it != m_listParamInChck.end(); _it++) + { + Parameter _param; + if (!_pParamManager->GetParameter(_it->strIdentifier, &_param)) + { + GetDlgItem(_it->nID)->EnableWindow(FALSE); + continue; + } + GetDlgItem(_it->nID)->EnableWindow(TRUE); + SetDlgItemText(_it->nID, _param.szName); + ParameterValue _value = _param.Value; + double _nValue = _ConverParameterValueToDouble(&_value); + if (IsInvalidDouble(_nValue)) + { + ASSERT(FALSE); + continue; + } + ((CButton*)GetDlgItem(_it->nID))->SetCheck(DOUBLE_EQU_ZERO(_nValue) ? BST_UNCHECKED : BST_CHECKED); + } + + CString _strOutsideHeight = NceGetPrivateProfileString(_T("OutsideCutting"), _T("OutsideHeight")); + if (_strOutsideHeight.IsEmpty()) + SetDlgItemText(IDC_EDIT_OUTSIDECUTHEIGHT, _GETCS(s_csNOTSAVEOUTSIDEHEIGHT)); + else + { + _strOutsideHeight.TrimRight('0'); + if (_strOutsideHeight.IsEmpty()) + _strOutsideHeight = "0"; + else if (_strOutsideHeight[_strOutsideHeight.GetLength() - 1] == '.') + _strOutsideHeight.Delete(_strOutsideHeight.GetLength() - 1); + else + { + // do nothing + } + SetDlgItemText(IDC_EDIT_OUTSIDECUTHEIGHT, _strOutsideHeight); + } +} + +void CGlobalParamDlg::UpdateEdits() +{ + CParamManager* _pParamManager = GetParamManager(); + for (ParamListE::iterator _it = m_listParamInEdit.begin(); _it != m_listParamInEdit.end(); _it++) + { + Parameter _param; + if (!_pParamManager->GetParameter(_it->strIdentifier, &_param)) + { + // 拿不到参数则显示参数不可以,且灰掉。 + GetDlgItem(_it->nIDCaption)->EnableWindow(FALSE); + SetDlgItemText(_it->nIDValue, _GETCS(s_csUNAVAILIBLEPARAM)); + GetDlgItem(_it->nIDValue)->EnableWindow(FALSE); + if (_it->nIDUnit != NULL) + GetDlgItem(_it->nIDUnit)->EnableWindow(FALSE); + continue; + } + GetDlgItem(_it->nIDCaption)->EnableWindow(TRUE); + GetDlgItem(_it->nIDValue)->EnableWindow(TRUE); + if (_it->nIDUnit != NULL) + GetDlgItem(_it->nIDUnit)->EnableWindow(TRUE); + CString _strCaption(_param.szName); + _strCaption += _GETCS(s_szCOLON); + SetDlgItemText(_it->nIDCaption, _strCaption); + if (_it->nIDUnit != NULL) + _ShowUnit(&(*_it)); + _SetDlgItemText(_it->nIDValue, ConverToUiUnit(_param)); + } +} + +double CGlobalParamDlg::_ConverParameterValueToDouble(const mach::ParameterValue* PValue_) +{ + if (!PValue_) + { + ASSERT(FALSE); + return ncmath::c_nINVALID_DOUBLE; + } + + double _nValue = ncmath::c_nINVALID_DOUBLE; + switch(PValue_->nType) + { + case ParameterValue::VT_BOOL: + _nValue = PValue_->bValue; + break; + case ParameterValue::VT_SHORT: + _nValue = PValue_->sValue; + break; + case ParameterValue::VT_INT: + _nValue = PValue_->iValue; + break; + case ParameterValue::VT_FLOAT: + _nValue = PValue_->fValue; + break; + case ParameterValue::VT_DOUBLE: + _nValue = PValue_->dValue; + break; + case ParameterValue::VT_INT64: + ASSERT(FALSE); // 暂不考虑64位的参数。 + break; + default: + ASSERT(FALSE); + break; + } + + return _nValue; +} + +void CGlobalParamDlg::_ConverDoubelToParameterValue(const double _nDValue_, OUT mach::ParameterValue* PValue_) +{ + if (!PValue_) + { + ASSERT(FALSE); + return; + } + + switch(PValue_->nType) + { + case ParameterValue::VT_BOOL: + PValue_->bValue = !DOUBLE_EQU_ZERO(_nDValue_); + break; + case ParameterValue::VT_SHORT: + PValue_->sValue = (short)_nDValue_; + break; + case ParameterValue::VT_INT: + PValue_->iValue = (int)_nDValue_; + break; + case ParameterValue::VT_FLOAT: + PValue_->fValue = (float)_nDValue_; + break; + case ParameterValue::VT_DOUBLE: + PValue_->dValue = _nDValue_; + break; + case ParameterValue::VT_INT64: + PValue_->i64Value = (INT64)_nDValue_; + break; + default: + ASSERT(FALSE); + break; + } +} + +bool CGlobalParamDlg::_CanModify() +{ + CStateManager* _pStateManager = mach::GetStateManager(); + CStateManager::State _nState = CStateManager::Idle; + if (_pStateManager && _pStateManager->GetState(&_nState) + && _nState != mach::CStateManager::Invalid + && _nState != CStateManager::Idle + && _nState != CStateManager::Estop) + { + return false; + } + + return true; +} + +void CGlobalParamDlg::ConverUnit(Units nFrom_, Units nTo_, double IN nOrg_, double& OUT nTarget_) +{ + if (nFrom_ == nTo_) + { + nTarget_ = nOrg_; + return; + } + + if (nFrom_ == Speed_MMperS && nTo_ == Speed_MMperMin) + { + nTarget_ = nOrg_ * 60.0; + return; + } + + if (nFrom_ == Speed_MMperS && nTo_ == Speed_MperMin) + { + nTarget_ = nOrg_ * 60.0 / 1000.0; + return; + } + + if (nFrom_ == Speed_MMperS && nTo_ == Speed_INperMin) + { + nTarget_ = nOrg_ * 60 / 25.39999918; + return; + } + + if (nFrom_ == Speed_MMperMin && nTo_ == Speed_MMperS) + { + nTarget_ = nOrg_ / 60.0; + return; + } + + if (nFrom_ == Speed_MMperMin && nTo_ == Speed_MperMin) + { + nTarget_ = nOrg_ / 1000.0; + return; + } + + if (nFrom_ == Speed_MMperMin && nTo_ == Speed_INperMin) + { + nTarget_ = nOrg_ / 25.39999918; + return; + } + + if (nFrom_ == Speed_INperMin && nTo_ == Speed_MMperS) + { + nTarget_ = nOrg_ * 25.39999918 / 60.0; + return; + } + + if (nFrom_ == Speed_INperMin && nTo_ == Speed_MMperMin) + { + nTarget_ = nOrg_ * 25.39999918; + return; + } + + if (nFrom_ == Speed_INperMin && nTo_ == Speed_MperMin) + { + nTarget_ = nOrg_ * 25.39999918 / 1000.0; + return; + } + + if (nFrom_ == Speed_MperMin && nTo_ == Speed_MMperS) + { + nTarget_ = nOrg_ * 1000.0 / 60.0; + return; + } + + if (nFrom_ == Speed_MperMin && nTo_ == Speed_MMperMin) + { + nTarget_ = nOrg_ * 1000.0; + return; + } + + if (nFrom_ == Speed_MperMin && nTo_ == Speed_INperMin) + { + nTarget_ = nOrg_ * 1000.0 / 25.39999918; + return; + } + + if (nFrom_ == Time_MS && nTo_ == Time_S) + { + nTarget_ = nOrg_ / 1000.0; + return; + } + + if (nFrom_ == Time_S && nTo_ ==Time_MS) + { + nTarget_ = nOrg_ * 1000.0; + return; + } + + if (nFrom_ == Acc_MMperS2 && nTo_ == ACC_MperMin2) + { + nTarget_ = nOrg_ * 3600 /1000.0; + return; + } + + if (nFrom_ == Acc_MMperS2 && nTo_ == Acc_10MperS2) + { + nTarget_ = nOrg_ / 10000; + return; + } + + if (nFrom_ == ACC_MperMin2 && nTo_ == Acc_MMperS2) + { + nTarget_ = nOrg_ * 1000.0 / 3600; + return; + } + + if (nFrom_ == ACC_MperMin2 && nTo_ == Acc_10MperS2) + { + nTarget_ = nOrg_ / 36000; + return; + } + + if (nFrom_ == Acc_10MperS2 && nTo_ == Acc_MMperS2) + { + nTarget_ = nOrg_ * 10 * 1000; + return; + } + + if (nFrom_ == Acc_10MperS2 && nTo_ == ACC_MperMin2) + { + nTarget_ = nOrg_ * 10 * 3600; + return; + } + + // 没有做转换。 ---- 黄海燕 2015-09-02 + ASSERT(FALSE); + nTarget_ = nOrg_; +} + +CGlobalParamDlg::Units CGlobalParamDlg::GetCurSpeedUnit() +{ + CString _strSpeedUnit = NceGetPrivateProfileString(c_szParamGroupUnit, c_szSpeedUnit, "0"); + if (_strSpeedUnit == "0") + return Speed_MMperMin; + if (_strSpeedUnit == "1") + return Speed_MMperS; + if (_strSpeedUnit == "2") + return Speed_MperMin; + if (_strSpeedUnit == "3") + return Speed_INperMin; + + return None; +} + +CGlobalParamDlg::Units CGlobalParamDlg::GetCurAccUnit() +{ + CString _strAccUnit = NceGetPrivateProfileString(c_szParamGroupUnit, c_szAccUnit, "0"); + if (_strAccUnit == "0") + return Acc_MMperS2; + if (_strAccUnit == "1") + return ACC_MperMin2; + if (_strAccUnit == "2") + return Acc_10MperS2; + + return None; +} + +CGlobalParamDlg::Units CGlobalParamDlg::GetCurTimeUnit() +{ + CString _strTimeUnit = NceGetPrivateProfileString(c_szParamGroupUnit, c_szTimeUnit, "0"); + if (_strTimeUnit == "0") + return Time_MS; + if (_strTimeUnit == "1") + return Time_S; + + return None; +} + +CString CGlobalParamDlg::GetUnitName(const Units nUnit_) +{ + CString _strUnit; + switch(nUnit_) + { + case Length_MM: + _strUnit = "mm"; + break; + case Length_M: + _strUnit = "m"; + break; + case Speed_MMperS: + _strUnit = "mm/s"; + break; + case Speed_MMperMin: + _strUnit = "mm/min"; + break; + case Speed_MperMin: + _strUnit = "m/min"; + break; + case Speed_INperMin: + _strUnit = "in/min"; + break; + case Acc_MMperS2: + _strUnit = "mm/s^2"; + break; + case ACC_MperMin2: + _strUnit = "m/min^2"; + break; + case Acc_10MperS2: + _strUnit = "G"; + break; + case Time_MS: + _strUnit = "ms"; + break; + case Time_S: + _strUnit = "s"; + break; + default: + _strUnit = ""; + break; + } + + return _strUnit; +} + +CGlobalParamDlg::Units CGlobalParamDlg::GetUnitByName(LPCTSTR pszName_) +{ + Units _nUnit; + CString _strUnit = pszName_; + if (_strUnit == "mm") + { + _nUnit = Length_MM; + } + else if (_strUnit == "m") + { + _nUnit = Length_M; + } + else if (_strUnit == "mm/s") + { + _nUnit = Speed_MMperS; + } + else if (_strUnit == "mm/min") + { + _nUnit = Speed_MMperMin; + } + else if (_strUnit == "m/min") + { + _nUnit = Speed_MperMin; + } + else if (_strUnit == "in/min") + { + _nUnit = Speed_INperMin; + } + else if (_strUnit == "mm/s^2") + { + _nUnit = Acc_MMperS2; + } + else if (_strUnit == "m/min^2") + { + _nUnit = ACC_MperMin2; + } + else if (_strUnit == "G") + { + _nUnit = Acc_10MperS2; + } + else if (_strUnit == "ms") + { + _nUnit = Time_MS; + } + else if (_strUnit == "s") + { + _nUnit = Time_S; + } + else + { + _nUnit = None; + } + + return _nUnit; +} + +void CGlobalParamDlg::_ShowUnit(const ParamInfoE* pInfo_) +{ + CParamManager* _pParamManager = GetParamManager(); + if (!_pParamManager) + return; + Parameter _param; + if (!_pParamManager->GetParameter(pInfo_->strIdentifier, &_param)) + return; + + CString _strParamUnit = _param.szUnit; + if (_strParamUnit == "mm/s" + || _strParamUnit == "mm/min" + || _strParamUnit == "m/min") + { + CString _strSpeedUnit = GetUnitName(GetCurSpeedUnit()); + CString _strText; + GetDlgItemText(pInfo_->nIDUnit, _strText); + if (_strSpeedUnit != _strText) + SetDlgItemText(pInfo_->nIDUnit, _strSpeedUnit); + return; + } + + if (_strParamUnit == "mm/s^2" + || _strParamUnit == "m/min^2" + || _strParamUnit == "G") + { + CString _strAccUnit = GetUnitName(GetCurAccUnit()); + CString _strText; + GetDlgItemText(pInfo_->nIDUnit, _strText); + if (_strAccUnit != _strText) + SetDlgItemText(pInfo_->nIDUnit, _strAccUnit); + return; + } + + if (_strParamUnit == "ms" + || _strParamUnit == "s") + { + CString _strTimeUnit = GetUnitName(GetCurTimeUnit()); + CString _strText; + GetDlgItemText(pInfo_->nIDUnit, _strText); + if (_strTimeUnit != _strText) + SetDlgItemText(pInfo_->nIDUnit, _strTimeUnit); + return; + } + + // 这里做一下特殊处理,当加速度单位是G时把加加速度单位转换成G/s ---- DingQiang 2016-10-25 + if (_strParamUnit == "mm/s^3" + || _strParamUnit == "G/s") + { + CString _strAccUnit; + if (GetCurAccUnit() == Acc_10MperS2) + { + _strAccUnit = "G/s"; + } + else + { + _strAccUnit = "mm/s^3"; + } + CString _strText; + GetDlgItemText(pInfo_->nIDUnit, _strText); + if (_strAccUnit != _strText) + SetDlgItemText(pInfo_->nIDUnit, _strAccUnit); + return; + } + + CString _strText; + GetDlgItemText(pInfo_->nIDUnit, _strText); + if (!_strParamUnit.IsEmpty() && _strParamUnit != _strText) + SetDlgItemText(pInfo_->nIDUnit, _strParamUnit); +} + +double CGlobalParamDlg::ConverToUiUnit(mach::Parameter& param_) +{ + Units _nFrom = None; + Units _nTo = None; + CString _strParamUnit = param_.szUnit; + if (_strParamUnit == "mm/s" + || _strParamUnit == "mm/min" + || _strParamUnit == "m/min") + { + _nFrom = GetUnitByName(_strParamUnit); + _nTo = GetCurSpeedUnit(); + } + else if (_strParamUnit == "mm/s^2" + || _strParamUnit == "m/min^2" + || _strParamUnit == "G") + { + _nFrom = GetUnitByName(_strParamUnit); + _nTo = GetCurAccUnit(); + } + else if (_strParamUnit == "ms" + || _strParamUnit == "s") + { + _nFrom = GetUnitByName(_strParamUnit); + _nTo = GetCurTimeUnit(); + } + else if (_strParamUnit == "mm/s^3" && GetCurAccUnit() == Acc_10MperS2) + { + // 这里做一下特殊处理,当加速度单位是G时把加加速度转换成G/s ---- DingQiang 2016-10-25 + ASSERT(param_.Value.nType == mach::ParameterValue::VT_DOUBLE); + return param_.Value.dValue / 10000; + } + else + return _ConverParameterValueToDouble(¶m_.Value); + + double _nValue = 0; + switch(param_.Value.nType) + { + case mach::ParameterValue::VT_SHORT: + ConverUnit(_nFrom, _nTo, param_.Value.sValue, _nValue); + break; + case mach::ParameterValue::VT_INT: + ConverUnit(_nFrom, _nTo, param_.Value.iValue, _nValue); + break; + case mach::ParameterValue::VT_FLOAT: + ConverUnit(_nFrom, _nTo, param_.Value.fValue, _nValue); + break; + case mach::ParameterValue::VT_DOUBLE: + ConverUnit(_nFrom, _nTo, param_.Value.dValue, _nValue); + break; + default: + ASSERT(FALSE); + break; + } + + return _nValue; +} + +double CGlobalParamDlg::ConverToSysUnit(mach::Parameter& param_) +{ + Units _nFrom = None; + Units _nTo = None; + CString _strParamUnit = param_.szUnit; + if (_strParamUnit == "mm/s" + || _strParamUnit == "mm/min" + || _strParamUnit == "m/min") + { + _nFrom = GetCurSpeedUnit(); + _nTo = GetUnitByName(_strParamUnit); + } + else if (_strParamUnit == "mm/s^2" + || _strParamUnit == "m/min^2" + || _strParamUnit == "G") + { + _nFrom = GetCurAccUnit(); + _nTo = GetUnitByName(_strParamUnit); + } + else if (_strParamUnit == "ms" + || _strParamUnit == "s") + { + _nFrom = GetCurTimeUnit(); + _nTo = GetUnitByName(_strParamUnit); + } + else if (_strParamUnit == "mm/s^3" && GetCurAccUnit() == Acc_10MperS2) + { + // 当加速度单位是G时,这时加加速度单位是G/s,需要转换成mm/s^3 ---- DingQiang 2016-10-25 + ASSERT(param_.Value.nType == mach::ParameterValue::VT_DOUBLE); + return param_.Value.dValue * 10000; + } + else + return _ConverParameterValueToDouble(¶m_.Value); + + double _nValue = 0; + switch(param_.Value.nType) + { + case mach::ParameterValue::VT_SHORT: + ConverUnit(_nFrom, _nTo, param_.Value.sValue, _nValue); + break; + case mach::ParameterValue::VT_INT: + ConverUnit(_nFrom, _nTo, param_.Value.iValue, _nValue); + break; + case mach::ParameterValue::VT_FLOAT: + ConverUnit(_nFrom, _nTo, param_.Value.fValue, _nValue); + break; + case mach::ParameterValue::VT_DOUBLE: + ConverUnit(_nFrom, _nTo, param_.Value.dValue, _nValue); + break; + default: + ASSERT(FALSE); + break; + } + + return _nValue; +} + +CString CGlobalParamDlg::ConverPromptUnit(mach::Parameter& param_, LPCTSTR pszPrompt_) +{ + CString _strPrompt(pszPrompt_); + Units _nFrom = None; + Units _nTo = None; + CString _strParamUnit = param_.szUnit; + if (_strParamUnit == "mm/s" + || _strParamUnit == "mm/min" + || _strParamUnit == "m/min") + { + _nFrom = GetUnitByName(_strParamUnit); + _nTo = GetCurSpeedUnit(); + } + else if (_strParamUnit == "mm/s^2" + || _strParamUnit == "m/min^2" + || _strParamUnit == "G") + { + _nFrom = GetUnitByName(_strParamUnit); + _nTo = GetCurAccUnit(); + } + else if (_strParamUnit == "ms" + || _strParamUnit == "s") + { + _nFrom = GetUnitByName(_strParamUnit); + _nTo = GetCurTimeUnit(); + } + + if (_nFrom == None || _nTo == None) + return _strPrompt; + + CString _strFormat; + CString _strNumber; + + for (int _i = 0; _i < _strPrompt.GetLength(); _i++) + { + bool _bCurIsNum = _strPrompt[_i] >= 48 && _strPrompt[_i] <= 57; + bool _bNextIsNum = (_i < _strPrompt.GetLength() - 1) + && _strPrompt[_i + 1] >= 48 + && _strPrompt[_i + 1] <= 57; + if (_bCurIsNum + || (!_strNumber.IsEmpty() && _strPrompt[_i] == _T('.') && _bNextIsNum) + || (_strNumber.IsEmpty() && (_strPrompt[_i] == _T('+') || _strPrompt[_i] == _T('-')) && _bNextIsNum)) + { + _strNumber += _strPrompt[_i]; + } + else + { + if (!_strNumber.IsEmpty()) + { + double _nNumber = atof(_strNumber); + _strFormat += _T("%s"); + + ConverUnit(_nFrom, _nTo, _nNumber, _nNumber); + _strNumber.Format(_T("%.3f"), _nNumber); + FormatDoubleParamer(_strNumber); + CString _strOutput; + _strOutput.Format(_strFormat, _strNumber); + _strFormat = _strOutput; + _strNumber = ""; + } + _strFormat += _strPrompt[_i]; + } + } + + if (!_strNumber.IsEmpty()) + { + double _nNumber = atof(_strNumber); + _strFormat += _T("%s"); + + ConverUnit(_nFrom, _nTo, _nNumber, _nNumber); + _strNumber.Format(_T("%.3f"), _nNumber); + FormatDoubleParamer(_strNumber); + CString _strOutput; + _strOutput.Format(_strFormat, _strNumber); + _strFormat = _strOutput; + _strNumber = ""; + } + return _strFormat; +} + +void CGlobalParamDlg::_SetDlgItemText(UINT nID_, const double nValue_) +{ + CString _strText; + _strText.Format("%.3f", nValue_); + FormatDoubleParamer(_strText); + CString _strOld; + GetDlgItemText(nID_, _strOld); + if (_strOld != _strText) + SetDlgItemText(nID_, _strText); +} diff --git a/src/Intersect.cpp b/src/Intersect.cpp new file mode 100644 index 0000000..325a979 --- /dev/null +++ b/src/Intersect.cpp @@ -0,0 +1,1832 @@ +// ************************************************************************** // +// Copyright(c)2010 Naiky Company. All rights reserved. +// +// Abstract: +// Cad对象求交函数的实现 +// ********************************************* ---- 吴阳明 2010-09-08 ***** // +#include "stdafx.h" +#include "Intersect.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +using namespace ncmath; + +// 总接口定义 --- 吴阳明 2010 09 10 +int nce::GetIntersection(IN const CCadObject* pCadObject1_, + IN const CCadObject* pCadObject2_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadObject1_); + ASSERT(pCadObject2_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + // 用两个变量转存入口形参,并保证_pCadObject1对象的Type值不大于_pCadObject2 + // 对象的Type值。 ---- 杨开锦 2010-09-14 + const CCadObject* _pCadObject1 = pCadObject1_; + const CCadObject* _pCadObject2 = pCadObject2_; + if ((UINT)_pCadObject1->GetType() > (UINT)_pCadObject2->GetType()) + { + _pCadObject1 = pCadObject2_; + _pCadObject2 = pCadObject1_; + } + + // 用32位整数表示参数_pCadObject1与_pCadObject2的类型(结合方式),设前者的 + // 类型为Type1,后者的类型为Type2,则结合类型为 (Type1 << 16 | Type2)。本种 + // 表示方式依赖于所有对象的Type值不超过0xFFFF。 ---- 杨开锦 2010-09-14 + UINT _nType1 = _pCadObject1->GetType(); + UINT _nType2 = _pCadObject2->GetType(); + ASSERT(_nType1 < 0xFFFF && _nType2 < 0xFFFF); + + // 按结合类型分类求解,该switch-case实际上是一个二维表,以_nType1和_nType2为 + // 该表的索引值,查询对应的处理路径(即函数入口)。 + // 由于A与B求交的结果理应等同于B与A求交的结果,因此,为减小本表查询项的数 + // 量和所提供函数的数量,此处只查询表的左上角块(_nType1<=_nType2),右下角块 + // 被镜像到左上角相应位置(这在前面的代码中已完成)。 ---- 杨开锦 2010-09-14 + int _nResult = 0; + ASSERT(_nType1 <= _nType2); + switch(_nType1 << 16 | _nType2) + { + // 线段和线段 --- 吴阳明 2010 09 19 + case (cadline << 16 | cadline): + { + C_ASSERT(cadline <= cadline); + + const CCadLine* _pCadLine1 = dynamic_cast(_pCadObject1); + const CCadLine* _pCadLine2 = dynamic_cast(_pCadObject2); + _nResult = Intersect_CadLineWithCadLine(_pCadLine1, _pCadLine2, pvectorIntersect_); + } + break; + + // 线段和直线 --- 吴阳明 2010 09 19 + case (cadline << 16 | cadbeeline): + { + C_ASSERT(cadline <= cadbeeline); + + const CCadLine* _pCadLine = dynamic_cast(_pCadObject1); + const CCadBeeline* _pCadBeeline = dynamic_cast(_pCadObject2); + _nResult = Intersect_CadLineWithCadBeeline(_pCadLine, _pCadBeeline, pvectorIntersect_); + } + break; + + // 线段和圆 --- 吴阳明 2010 09 19 + case (cadline << 16 | cadcircle): + { + C_ASSERT(cadline <= cadcircle); + + const CCadLine* _pCadLine = dynamic_cast(_pCadObject1); + const CCadCircle* _pCadCircle = dynamic_cast(_pCadObject2); + _nResult = Intersect_CadLineWithCadCircle(_pCadLine, _pCadCircle, pvectorIntersect_); + } + break; + + // 线段和圆弧 --- 吴阳明 2010 09 19 + case (cadline << 16 | cadarc): + { + C_ASSERT(cadline <= cadarc); + + const CCadLine* _pCadLine = dynamic_cast(_pCadObject1); + const CCadArc * _pCadArc = dynamic_cast(_pCadObject2); + _nResult = Intersect_CadLineWithCadArc(_pCadLine, _pCadArc, pvectorIntersect_); + } + break; + + // 线段和椭圆 --- 吴阳明 2010 09 19 + case (cadline << 16 | cadellipse): + { + C_ASSERT(cadline <= cadellipse); + + const CCadLine* _pCadLine = dynamic_cast(_pCadObject1); + const CCadEllipse* _pCadEllipse = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadLineWithCadEllipse(_pCadLine, _pCadEllipse, pvectorIntersect_); + } + break; + + // 线段和椭圆弧 --- 吴阳明 2010 09 19 + case (cadline << 16 | cadellipsearc): + { + C_ASSERT(cadline <= cadellipsearc); + + const CCadLine* _pCadLine = dynamic_cast(_pCadObject1); + const CCadEllipseArc* _pCadEllipseArc = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadLineWithCadEllipseArc(_pCadLine, _pCadEllipseArc, pvectorIntersect_); + } + break; + + // 线段和多段线 --- 吴阳明 2010 09 19 + case (cadline << 16 | cadmultisegments): + case (cadline << 16 | cadrectangle): + case (cadline << 16 | cadstar): + case (cadline << 16 | cadpolygon): + case (cadline << 16 | cadpolyline): + { + C_ASSERT(cadline <= cadmultisegments && + cadline <= cadrectangle && + cadline <= cadstar && + cadline <= cadpolygon && + cadline <= cadpolyline); + + const CCadLine* _pCadLine = dynamic_cast(_pCadObject1); + const CCadMultiSegments* _pCadMultiSegments = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadLineWithCadMultiSegments(_pCadLine, _pCadMultiSegments, pvectorIntersect_); + } + break; + + // 线段和群组 --- 吴阳明 2010 10 21 + case (cadline << 16 | cadgroup): + { + C_ASSERT(cadline <= cadgroup); + + const CCadLine* _pCadLine = dynamic_cast (_pCadObject1); + const CCadGroup* _pCadGroup = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadGroup(_pCadLine, _pCadGroup, pvectorIntersect_); + } + break; + + // 线段和文字 --- 吴阳明 2010 10 21 + case (cadline << 16 | cadtext): + { + C_ASSERT(cadline <= cadtext); + + const CCadLine* _pCadLine = dynamic_cast (_pCadObject1); + const CCadText* _pCadText = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadText(_pCadLine, _pCadText, pvectorIntersect_); + } + break; + + // 直线和直线 --- 吴阳明 2010 09 19 + case (cadbeeline << 16 | cadbeeline): + { + C_ASSERT(cadbeeline <= cadbeeline); + + const CCadBeeline* _pCadBeeline1 = dynamic_cast (_pCadObject1); + const CCadBeeline* _pCadBeeline2 = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadBeelineWithCadBeeline(_pCadBeeline1, _pCadBeeline2, pvectorIntersect_); + } + break; + + // 直线和圆 --- 吴阳明 2010 09 19 + case (cadbeeline << 16 | cadcircle): + { + C_ASSERT(cadbeeline <= cadcircle); + + const CCadBeeline* _pCadBeeline = dynamic_cast (_pCadObject1); + const CCadCircle* _pCadCircle = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadBeelineWithCadCircle(_pCadBeeline, _pCadCircle, pvectorIntersect_); + } + break; + + // 直线和圆弧 --- 吴阳明 2010 09 19 + case (cadbeeline << 16 | cadarc): + { + C_ASSERT(cadbeeline <= cadarc); + + const CCadBeeline* _pCadBeeline = dynamic_cast (_pCadObject1); + const CCadArc* _pCadArc = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadBeelineWithCadArc(_pCadBeeline, _pCadArc, pvectorIntersect_); + } + break; + + // 直线和椭圆 --- 吴阳明 2010 09 19 + case (cadbeeline << 16 | cadellipse): + { + C_ASSERT(cadbeeline <= cadellipse); + + const CCadBeeline* _pCadBeeline = dynamic_cast (_pCadObject1); + const CCadEllipse* _pCadEllipse = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadBeelineWithCadEllipse(_pCadBeeline, _pCadEllipse, pvectorIntersect_); + } + break; + + // 直线和椭圆弧 --- 吴阳明 2010 09 19 + case (cadbeeline << 16 | cadellipsearc): + { + C_ASSERT(cadbeeline <= cadellipsearc); + + const CCadBeeline* _pCadBeeline = dynamic_cast (_pCadObject1); + const CCadEllipseArc* _pCadEllipseArc = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadBeelineWithCadEllipseArc(_pCadBeeline, _pCadEllipseArc, pvectorIntersect_); + } + break; + + // 直线和多段线 --- 吴阳明 2010 09 19 + case (cadbeeline << 16 | cadmultisegments): + case (cadbeeline << 16 | cadrectangle): + case (cadbeeline << 16 | cadstar): + case (cadbeeline << 16 | cadpolygon): + case (cadbeeline << 16 | cadpolyline): + { + C_ASSERT(cadbeeline <= cadmultisegments && + cadbeeline <= cadrectangle && + cadbeeline <= cadstar && + cadbeeline <= cadpolygon && + cadbeeline <= cadpolyline); + + const CCadBeeline* _pCadBeeline = dynamic_cast(_pCadObject1); + const CCadMultiSegments* _pCadMultiSegments = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadBeelineWithCadMultiSegments(_pCadBeeline, _pCadMultiSegments, pvectorIntersect_); + } + break; + + // 直线和群组 --- 吴阳明 2010 10 21 + case (cadbeeline << 16 | cadgroup): + { + C_ASSERT(cadbeeline <= cadgroup); + + const CCadBeeline* _pCadBeeline = dynamic_cast(_pCadObject1); + const CCadGroup* _pCadGroup = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadGroup(_pCadBeeline, _pCadGroup, pvectorIntersect_); + } + break; + + // 直线和文字 --- 吴阳明 2010 10 21 + case (cadbeeline << 16 | cadtext): + { + C_ASSERT(cadbeeline <= cadtext); + + const CCadBeeline* _pCadBeeline = dynamic_cast(_pCadObject1); + const CCadText* _pCadText = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadText(_pCadBeeline, _pCadText, pvectorIntersect_); + } + break; + + // 圆和圆 --- 吴阳明 2010 09 19 + case (cadcircle << 16 | cadcircle): + { + C_ASSERT(cadcircle <= cadcircle); + + const CCadCircle* _pCadCircle1 = dynamic_cast (_pCadObject1); + const CCadCircle* _pCadCircle2 = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadCircleWithCadCircle(_pCadCircle1, _pCadCircle2, pvectorIntersect_); + } + break; + + // 圆和圆弧 --- 吴阳明 2010 09 19 + case (cadcircle << 16 | cadarc): + { + C_ASSERT(cadcircle <= cadarc); + + const CCadCircle* _pCadCircle = dynamic_cast (_pCadObject1); + const CCadArc* _pCadArc = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadArcWithCadCircle(_pCadArc, _pCadCircle, pvectorIntersect_); + } + break; + + // 圆和椭圆 --- 吴阳明 2010 09 19 + case (cadcircle << 16 | cadellipse): + { + C_ASSERT(cadcircle <= cadellipse); + + const CCadCircle* _pCadCircle = dynamic_cast (_pCadObject1); + const CCadEllipse* _pCadEllipse = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadCircleWithCadEllipse(_pCadCircle, _pCadEllipse, pvectorIntersect_); + } + break; + + // 圆和椭圆弧 --- 吴阳明 2010 09 19 + case (cadcircle << 16 | cadellipsearc): + { + C_ASSERT(cadcircle <= cadellipsearc); + + const CCadCircle* _pCadCircle = dynamic_cast (_pCadObject1); + const CCadEllipseArc* _pCadEllipseArc = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadCircleWithCadEllipseArc(_pCadCircle, _pCadEllipseArc, pvectorIntersect_); + } + break; + + // 圆和多段线 --- 吴阳明 2010 09 19 + case (cadcircle << 16 | cadmultisegments): + case (cadcircle << 16 | cadrectangle): + case (cadcircle << 16 | cadstar): + case (cadcircle << 16 | cadpolygon): + case (cadcircle << 16 | cadpolyline): + { + C_ASSERT(cadcircle <= cadmultisegments && + cadcircle <= cadrectangle && + cadcircle <= cadstar && + cadcircle <= cadpolygon && + cadcircle <= cadpolyline); + + const CCadCircle* _pCadCircle = dynamic_cast (_pCadObject1); + const CCadMultiSegments* _pCadMultiSegments = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadCircleWithCadMultiSegments(_pCadCircle, _pCadMultiSegments, pvectorIntersect_); + } + break; + + // 圆和群组 --- 吴阳明 2010 10 21 + case (cadcircle << 16 | cadgroup): + { + C_ASSERT(cadcircle <= cadgroup); + + const CCadCircle* _pCadCircle = dynamic_cast (_pCadObject1); + const CCadGroup* _pCadGroup = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadGroup(_pCadCircle, _pCadGroup, pvectorIntersect_); + } + break; + + // 圆和文字 --- 吴阳明 2010 10 21 + case (cadcircle<< 16 | cadtext): + { + C_ASSERT(cadcircle <= cadtext); + + const CCadCircle* _pCadCircle = dynamic_cast (_pCadObject1); + const CCadText* _pCadText = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadText(_pCadCircle, _pCadText, pvectorIntersect_); + } + break; + + // 圆弧和圆弧 --- 吴阳明 2010 09 19 + case (cadarc << 16 | cadarc): + { + C_ASSERT(cadarc <= cadarc); + + const CCadArc* _pCadArc1 = dynamic_cast (_pCadObject1); + const CCadArc* _pCadArc2 = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadArcWithCadArc(_pCadArc1, _pCadArc2, pvectorIntersect_); + } + break; + + // 圆弧和椭圆 --- 吴阳明 2010 09 19 + case (cadarc << 16 | cadellipse): + { + C_ASSERT(cadarc <= cadellipse); + + const CCadArc* _pCadArc = dynamic_cast (_pCadObject1); + const CCadEllipse* _pCadEllipse = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadArcWithCadEllipse(_pCadArc, _pCadEllipse, pvectorIntersect_); + } + break; + + // 圆弧和椭圆弧 --- 吴阳明 2010 09 19 + case (cadarc << 16 | cadellipsearc): + { + C_ASSERT(cadarc <= cadellipsearc); + + const CCadArc* _pCadArc = dynamic_cast (_pCadObject1); + const CCadEllipseArc* _pCadEllipseArc = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadArcWithCadEllipseArc(_pCadArc, _pCadEllipseArc, pvectorIntersect_); + } + break; + + // 圆弧和多段线 --- 吴阳明 2010 09 19 + case (cadarc << 16 | cadmultisegments): + case (cadarc << 16 | cadrectangle): + case (cadarc << 16 | cadstar): + case (cadarc << 16 | cadpolygon): + case (cadarc << 16 | cadpolyline): + { + C_ASSERT(cadarc <= cadmultisegments && + cadarc <= cadrectangle && + cadarc <= cadstar && + cadarc <= cadpolygon && + cadarc <= cadpolyline); + + const CCadArc* _pCadArc = dynamic_cast (_pCadObject1); + const CCadMultiSegments* _pCadMultiSegments = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadArcWithCadMultiSegments(_pCadArc, _pCadMultiSegments, pvectorIntersect_); + } + break; + + // 圆弧和群组 --- 吴阳明 2010 10 21 + case (cadarc << 16 | cadgroup): + { + C_ASSERT(cadarc <= cadgroup); + + const CCadArc* _pCadArc = dynamic_cast (_pCadObject1); + const CCadGroup* _pCadGroup = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadGroup(_pCadArc, _pCadGroup, pvectorIntersect_); + } + break; + + // 圆弧和文字 --- 吴阳明 2010 10 21 + case (cadarc<< 16 | cadtext): + { + C_ASSERT(cadarc <= cadtext); + + const CCadArc* _pCadArc = dynamic_cast (_pCadObject1); + const CCadText* _pCadText = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadText(_pCadArc, _pCadText, pvectorIntersect_); + } + break; + + // 椭圆和椭圆 --- 吴阳明 2010 09 19 + case (cadellipse << 16 | cadellipse): + { + C_ASSERT(cadellipse <= cadellipse); + + const CCadEllipse* _pCadEllipse1 = dynamic_cast (_pCadObject1); + const CCadEllipse* _pCadEllipse2 = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadEllipseWithCadEllipse(_pCadEllipse1, _pCadEllipse2, pvectorIntersect_); + } + break; + + // 椭圆和椭圆弧 --- 吴阳明 2010 09 19 + case (cadellipse << 16 | cadellipsearc): + { + C_ASSERT(cadellipse <= cadellipsearc); + + const CCadEllipse* _pCadEllipse = dynamic_cast (_pCadObject1); + const CCadEllipseArc* _pCadEllipseArc = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadEllipseWithCadEllipseArc(_pCadEllipse, _pCadEllipseArc, pvectorIntersect_); + } + break; + + // 椭圆和多段线 --- 吴阳明 2010 09 19 + case (cadellipse << 16 | cadmultisegments): + case (cadellipse << 16 | cadrectangle): + case (cadellipse << 16 | cadstar): + case (cadellipse << 16 | cadpolygon): + case (cadellipse << 16 | cadpolyline): + { + C_ASSERT(cadellipse <= cadmultisegments && + cadellipse <= cadrectangle && + cadellipse <= cadstar && + cadellipse <= cadpolygon && + cadellipse <= cadpolyline); + + const CCadEllipse* _pCadEllipse = dynamic_cast (_pCadObject1); + const CCadMultiSegments* _pCadMultiSegments = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadMultiSegmentsWithCadEllipse(_pCadMultiSegments, _pCadEllipse, pvectorIntersect_); + } + break; + + // 椭圆和群组 --- 吴阳明 2010 10 21 + case (cadellipse << 16 | cadgroup): + { + C_ASSERT(cadellipse <= cadgroup); + + const CCadEllipse* _pCadEllipse = dynamic_cast (_pCadObject1); + const CCadGroup* _pCadGroup = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadGroup(_pCadEllipse, _pCadGroup, pvectorIntersect_); + } + break; + + // 椭圆和文字 --- 吴阳明 2010 10 21 + case (cadellipse<< 16 | cadtext): + { + C_ASSERT(cadellipse <= cadtext); + + const CCadEllipse* _pCadEllipse = dynamic_cast (_pCadObject1); + const CCadText* _pCadText = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadText(_pCadEllipse, _pCadText, pvectorIntersect_); + } + break; + + // 椭圆弧和椭圆弧 --- 吴阳明 2010 09 19 + case (cadellipsearc << 16 | cadellipsearc): + { + C_ASSERT(cadellipsearc <= cadellipsearc); + + const CCadEllipseArc* _pCadEllipseArc1 = dynamic_cast (_pCadObject1); + const CCadEllipseArc* _pCadEllipseArc2 = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadEllipseArcWithCadEllipseArc(_pCadEllipseArc1, _pCadEllipseArc2, pvectorIntersect_); + } + break; + + // 椭圆弧和多段线 --- 吴阳明 2010 09 19 + case (cadellipsearc << 16 | cadmultisegments): + case (cadellipsearc << 16 | cadrectangle): + case (cadellipsearc << 16 | cadstar): + case (cadellipsearc << 16 | cadpolygon): + case (cadellipsearc << 16 | cadpolyline): + { + C_ASSERT(cadellipsearc <= cadmultisegments && + cadellipsearc <= cadrectangle && + cadellipsearc <= cadstar && + cadellipsearc <= cadpolygon && + cadellipsearc <= cadpolyline); + + const CCadEllipseArc* _pCadEllipseArc = dynamic_cast (_pCadObject1); + const CCadMultiSegments* _pCadMultiSegments = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadMultiSegmentsWithCadEllipseArc(_pCadMultiSegments, _pCadEllipseArc, pvectorIntersect_); + } + break; + + // 椭圆弧和群组 --- 吴阳明 2010 10 21 + case (cadellipsearc << 16 | cadgroup): + { + C_ASSERT(cadellipsearc <= cadgroup); + + const CCadEllipseArc* _pCadEllipseArc = dynamic_cast (_pCadObject1); + const CCadGroup* _pCadGroup = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadGroup(_pCadEllipseArc, _pCadGroup, pvectorIntersect_); + } + break; + + // 椭圆弧和文字 --- 吴阳明 2010 10 21 + case (cadellipsearc<< 16 | cadtext): + { + C_ASSERT(cadellipsearc <= cadtext); + + const CCadEllipseArc* _pCadEllipseArc = dynamic_cast (_pCadObject1); + const CCadText* _pCadText = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadText(_pCadEllipseArc, _pCadText, pvectorIntersect_); + } + break; + + // 多段线和多段线 --- 吴阳明 2010 09 19 + case (cadmultisegments << 16 | cadmultisegments): + case (cadmultisegments << 16 | cadrectangle): + case (cadmultisegments << 16 | cadpolygon): + case (cadmultisegments << 16 | cadstar): + case (cadmultisegments << 16 | cadpolyline): + case (cadrectangle << 16 | cadrectangle): + case (cadrectangle << 16 | cadpolygon): + case (cadrectangle << 16 | cadstar): + case (cadrectangle << 16 | cadpolyline): + case (cadpolygon << 16 | cadpolygon): + case (cadpolygon << 16 | cadstar): + case (cadpolygon << 16 | cadpolyline): + case (cadstar << 16 | cadstar): + case (cadstar << 16 | cadpolyline): + case (cadpolyline << 16 | cadpolyline): + { + C_ASSERT(cadmultisegments <= cadrectangle && + cadrectangle <= cadpolygon && + cadpolygon <= cadstar && + cadstar <= cadpolyline); + + const CCadMultiSegments* _pCadMultiSegments1 = dynamic_cast (_pCadObject1); + const CCadMultiSegments* _pCadMultiSegments2 = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadMultiSegmentsWithCadMultiSegments(_pCadMultiSegments1, _pCadMultiSegments2, pvectorIntersect_); + } + break; + + // 多段线和群组 --- 吴阳明 2010 10 21 + case (cadmultisegments << 16 | cadgroup): + case (cadrectangle << 16 | cadgroup): + case (cadpolygon << 16 | cadgroup): + case (cadstar << 16 | cadgroup): + case (cadpolyline << 16 | cadgroup): + { + C_ASSERT(cadmultisegments <= cadgroup && + cadrectangle <= cadgroup && + cadpolygon <= cadgroup && + cadstar <= cadgroup && + cadpolyline <= cadgroup); + + const CCadMultiSegments* _pCadMultiSegments = dynamic_cast (_pCadObject1); + const CCadGroup* _pCadGroup = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadGroup(_pCadMultiSegments, _pCadGroup, pvectorIntersect_); + } + break; + + // 多段线和文字 --- 吴阳明 2010 10 21 + case (cadmultisegments << 16 | cadtext): + case (cadrectangle << 16 | cadtext): + case (cadpolygon << 16 | cadtext): + case (cadstar << 16 | cadtext): + case (cadpolyline << 16 | cadtext): + { + C_ASSERT(cadmultisegments <= cadtext && + cadrectangle <= cadtext && + cadpolygon <= cadtext && + cadstar <= cadtext && + cadpolyline <= cadtext); + + const CCadMultiSegments* _pCadMultiSegments = dynamic_cast (_pCadObject1); + const CCadText* _pCadText = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadObjectWithCadText(_pCadMultiSegments, _pCadText, pvectorIntersect_); + } + break; + + // 椭圆弧和群组 --- 吴阳明 2010 10 21 + case (cadgroup << 16 | cadgroup): + { + C_ASSERT(cadgroup <= cadgroup); + + const CCadGroup* _pCadGroup1 = dynamic_cast (_pCadObject1); + const CCadGroup* _pCadGroup2 = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadGroupWithCadGroup(_pCadGroup1, _pCadGroup2, pvectorIntersect_); + } + break; + + // 群组和文字 --- 吴阳明 2010 10 21 + case (cadgroup<< 16 | cadtext): + { + C_ASSERT(cadgroup <= cadtext); + + const CCadGroup* _pCadGroup = dynamic_cast (_pCadObject1); + const CCadText* _pCadText = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadGroupWithCadText(_pCadGroup, _pCadText, pvectorIntersect_); + } + break; + + // 文字和文字 --- 吴阳明 2010 10 21 + case (cadtext<< 16 | cadtext): + { + C_ASSERT(cadgroup <= cadtext); + + const CCadText* _pCadText1 = dynamic_cast (_pCadObject1); + const CCadText* _pCadText2 = dynamic_cast (_pCadObject2); + _nResult = Intersect_CadTextWithCadText(_pCadText1, _pCadText2, pvectorIntersect_); + } + break; + + default: + break; + } + + return _nResult; +} + +int nce::Intersect_CadArcWithCadArc(IN const CCadArc* pCadArc1_, + IN const CCadArc* pCadArc2_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadArc1_); + ASSERT(pCadArc2_); + ASSERT(pvectorIntersect_== NULL || pvectorIntersect_->empty()); + ASSERT(DOUBLE_GREAT_ZERO(pCadArc1_->GetLength())); + ASSERT(DOUBLE_GREAT_ZERO(pCadArc2_->GetLength())); + + // 圆弧信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptArc1Center = pCadArc1_->GetCenterPoint(); + DPOINT2 _ptArc2Center = pCadArc2_->GetCenterPoint(); + + double _nArc1Radius = pCadArc1_->GetRadius(); + double _nArc2Radius = pCadArc2_->GetRadius(); + + double _nArc1StartAngle = pCadArc1_->GetStartAngle(); + double _nArc2StartAngle = pCadArc2_->GetStartAngle(); + + double _nFactor1 = pCadArc1_->IsNormalDir() ? 1 : -1; + double _nFactor2 = pCadArc2_->IsNormalDir() ? 1 : -1; + + double _nArc1CentralAngle = pCadArc1_->GetCentralAngle() * _nFactor1; + double _nArc2CentralAngle = pCadArc2_->GetCentralAngle() * _nFactor2; + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + return ncmath::Intersect_ArcWithArc(_ptArc1Center, _nArc1Radius, _nArc1StartAngle, _nArc1CentralAngle, + _ptArc2Center, _nArc2Radius, _nArc2StartAngle, _nArc2CentralAngle, *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadArcWithCadCircle(IN const CCadArc* pCadArc_, + IN const CCadCircle* pCadCircle_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadArc_); + ASSERT(pCadCircle_); + ASSERT(pvectorIntersect_== NULL || pvectorIntersect_->empty()); + ASSERT(DOUBLE_GREAT_ZERO(pCadArc_->GetLength())); + ASSERT(DOUBLE_GREAT_ZERO(pCadCircle_->GetLength())); + + // 圆心 --- 吴阳明 2010 09 09 + DPOINT2 _ptArcCenter = pCadArc_->GetCenterPoint(); + DPOINT2 _ptCircleCenter = pCadCircle_->GetCenterPoint(); + + // 半径 --- 吴阳明 2010 09 09 + double _nArcRadius = pCadArc_->GetRadius(); + double _nCircleRadius = pCadCircle_->GetRadius(); + + // 圆弧起始角和中心角 --- 吴阳明 2010 09 09 + double _nArcStartAngle = pCadArc_->GetStartAngle(); + double _nArcCentralAngle = pCadArc_->GetCentralAngle(); + + // 将中心角赋予方向 --- 吴阳明 2010 09 09 + double _nFactor = pCadArc_->IsNormalDir() ? 1 : -1; + _nArcCentralAngle *= _nFactor; + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + return ncmath::Intersect_CircleWithArc(_ptCircleCenter, _nCircleRadius, _ptArcCenter, + _nArcRadius, _nArcStartAngle, _nArcCentralAngle, *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadArcWithCadEllipse(IN const CCadArc* pCadArc_, + IN const CCadEllipse* pCadEllipse_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadArc_); + ASSERT(pCadEllipse_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + // 圆弧信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptArcCenter = pCadArc_->GetCenterPoint(); + double _nRadius = pCadArc_->GetRadius(); + double _nArcStartAngle = pCadArc_->GetStartAngle(); + double _nArcSweptAngle = pCadArc_->GetCentralAngle(); + if (!pCadArc_->IsNormalDir()) + _nArcSweptAngle *= -1; + + // 椭圆信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptEllipseCenter = pCadEllipse_->GetCenterPoint(); + double _nLongRadius = pCadEllipse_->GetLongRadius(); + double _nShortRadius = pCadEllipse_->GetShortRadius(); + double _nAngle = pCadEllipse_->GetAngle(); + + int _nRet = 0; + if (!pvectorIntersect_) + { + _nRet = Intersect_ArcWithEllipse(_ptArcCenter, _nRadius, _nArcStartAngle, _nArcSweptAngle, + _ptEllipseCenter, _nLongRadius, _nShortRadius, _nAngle); + } + else + { + _nRet = Intersect_ArcWithEllipse(_ptArcCenter, _nRadius, _nArcStartAngle, _nArcSweptAngle, + _ptEllipseCenter, _nLongRadius, _nShortRadius, _nAngle, *pvectorIntersect_); + } + + return _nRet; +} + +int nce::Intersect_CadArcWithCadEllipseArc(IN const CCadArc* pCadArc_, + IN const CCadEllipseArc* pCadEllipseArc_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadArc_); + ASSERT(pCadEllipseArc_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + // 圆弧信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptArcCenter = pCadArc_->GetCenterPoint(); + double _nRadius = pCadArc_->GetRadius(); + double _nArcStartAngle = pCadArc_->GetStartAngle(); + double _nArcSweptAngle = pCadArc_->GetCentralAngle(); + if (!pCadArc_->IsNormalDir()) + _nArcSweptAngle *= -1; + + // 椭圆弧信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptEllipseArcCenter = pCadEllipseArc_->GetCenterPoint(); + double _nLongRadius = pCadEllipseArc_->GetLongRadius(); + double _nShortRadius = pCadEllipseArc_->GetShortRadius(); + double _nAngle = pCadEllipseArc_->GetAngle(); + double _nEllipseArcStartAngle = pCadEllipseArc_->GetStartAngle(); + double _nEllipseArcSweptAngle = pCadEllipseArc_->GetCentralAngle(); + if (!pCadEllipseArc_->IsNormalDir()) + _nEllipseArcSweptAngle *= -1; + + int _nRet = 0; + if (!pvectorIntersect_) + { + _nRet = Intersect_ArcWithEllipseArc( + _ptArcCenter, _nRadius, _nArcStartAngle, _nArcSweptAngle, + _ptEllipseArcCenter, _nLongRadius, _nShortRadius, _nAngle, + _nEllipseArcStartAngle, _nEllipseArcSweptAngle); + } + else + { + _nRet = Intersect_ArcWithEllipseArc( + _ptArcCenter, _nRadius, _nArcStartAngle, _nArcSweptAngle, + _ptEllipseArcCenter, _nLongRadius, _nShortRadius, _nAngle, + _nEllipseArcStartAngle, _nEllipseArcSweptAngle, *pvectorIntersect_); + } + + return _nRet; +} + +int nce::Intersect_CadArcWithCadMultiSegments(IN const CCadArc* pCadArc_, + IN const CCadMultiSegments* pCadMultiSegments_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadArc_); + ASSERT(pCadMultiSegments_); + ASSERT(pvectorIntersect_== NULL || pvectorIntersect_->empty()); + ASSERT(DOUBLE_GREAT_ZERO(pCadArc_->GetLength())); + ASSERT(DOUBLE_GREAT_ZERO(pCadMultiSegments_->GetLength())); + + // 信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptArc1Center = pCadArc_->GetCenterPoint(); + double _nArc1Radius = pCadArc_->GetRadius(); + double _nArc1StartAngle = pCadArc_->GetStartAngle(); + + double _nFactor = pCadArc_->IsNormalDir() ? 1 : -1; + double _nArc1CentralAngle = _nFactor * pCadArc_->GetCentralAngle(); + + int _nResult = 0; + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + // 将圆弧同多段线个片段求交 --- 吴阳明 2010 09 19 + for (int _i = 0; _i != pCadMultiSegments_->GetSegmentCount(); ++_i) + { + SEGMENT _Segment = pCadMultiSegments_->GetSegment(_i); + std::vector _vectorTemp; + + switch(_Segment.nType) + { + // 圆弧求交 --- 吴阳明 2010 09 19 + case SEGMENT::ARC: + { + DPOINT2 _ptArc2Center(ncmath::c_nINVALID_DOUBLE, ncmath::c_nINVALID_DOUBLE); + double _nArc2Radius = 0.0; + double _nArc2StartAngle = 0.0; + double _nArc2CentralAngle = 0.0; + + SEGMENT::SolveArc(_Segment.ptStart, _Segment.ptEnd, _Segment.nBulge, + &_ptArc2Center, &_nArc2Radius, &_nArc2StartAngle, &_nArc2CentralAngle); + + _nResult += ncmath::Intersect_ArcWithArc(_ptArc1Center, _nArc1Radius, _nArc1StartAngle, + _nArc1CentralAngle, _ptArc2Center, _nArc2Radius, + _nArc2StartAngle, _nArc2CentralAngle, _vectorTemp, + _nNeed); + } + break; + + // 线段求交 --- 吴阳明 2010 09 19 + case SEGMENT::LINE: + { + _nResult += ncmath::Intersect_LineWithArc(_Segment.ptStart, _Segment.ptEnd, _ptArc1Center, + _nArc1Radius, _nArc1StartAngle, _nArc1CentralAngle, _vectorTemp, _nNeed); + } + break; + + // 不支持的格式 --- 吴阳明 2010 09 19 + case SEGMENT::BEZIER: + default: + ASSERT(false); + } + + if (pvectorIntersect_ != NULL && !_vectorTemp.empty()) + copy(_vectorTemp.begin(), _vectorTemp.end(), back_inserter(*pvectorIntersect_)); + } + return _nResult; +} + +int nce::Intersect_CadBeelineWithCadArc(IN const CCadBeeline* pCadBeeline_, + IN const CCadArc* pCadArc_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadArc_); + ASSERT(pCadBeeline_); + ASSERT(pvectorIntersect_== NULL || pvectorIntersect_->empty()); + ASSERT(DOUBLE_GREAT_ZERO(pCadArc_->GetLength())); + + //直线和圆弧信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptBeeline = pCadBeeline_->GetPoint(); + double _nAngle = pCadBeeline_->GetAngle(); + + DPOINT2 _ptArcCenter = pCadArc_->GetCenterPoint(); + double _nArcRadius = pCadArc_->GetRadius(); + double _nArcStartAngle = pCadArc_->GetStartAngle(); + + double _nFactor = pCadArc_->IsNormalDir() ? 1 : -1; + double _nArcCentralAngle = _nFactor * pCadArc_->GetCentralAngle(); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + return ncmath::Intersect_BeelineWithArc(_ptBeeline, _nAngle, _ptArcCenter,_nArcRadius, + _nArcStartAngle, _nArcCentralAngle, *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadBeelineWithCadBeeline(IN const CCadBeeline* pCadBeeline1_, + IN const CCadBeeline* pCadBeeline2_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadBeeline1_); + ASSERT(pCadBeeline2_); + ASSERT(pvectorIntersect_== NULL || pvectorIntersect_->empty()); + + // 直线信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptBeeline1 = pCadBeeline1_->GetPoint(); + double _nAngle1 = pCadBeeline1_->GetAngle(); + + DPOINT2 _ptBeeline2 = pCadBeeline2_->GetPoint(); + double _nAngle2 = pCadBeeline2_->GetAngle(); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + return ncmath::Intersect_BeelineWithBeeline(_ptBeeline1, _nAngle1, + _ptBeeline2, _nAngle2, *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadBeelineWithCadCircle(IN const CCadBeeline* pCadBeeline_, + IN const CCadCircle* pCadCircle_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadBeeline_); + ASSERT(pCadCircle_); + ASSERT(pvectorIntersect_== NULL || pvectorIntersect_->empty()); + ASSERT(DOUBLE_GREAT_ZERO(pCadCircle_->GetLength())); + + DPOINT2 _ptBeeline = pCadBeeline_->GetPoint(); + double _nAngle = pCadBeeline_->GetAngle(); + + DPOINT2 _ptCircleCenter = pCadCircle_->GetCenterPoint(); + double _nCircleRadius = pCadCircle_->GetRadius(); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + return ncmath::Intersect_BeelineWithCircle(_ptBeeline, _nAngle,_ptCircleCenter, + _nCircleRadius, *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadBeelineWithCadEllipse(IN const CCadBeeline* pCadBeeline_, + IN const CCadEllipse* pCadEllipse_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadBeeline_); + ASSERT(pCadEllipse_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + + // 直线和椭圆信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptBeeline = pCadBeeline_->GetPoint(); + double _nAngle = pCadBeeline_->GetAngle(); + + DPOINT2 _ptCenter = pCadEllipse_->GetCenterPoint(); + double _nLRadius = pCadEllipse_->GetLongRadius(); + double _nSRadius = pCadEllipse_->GetShortRadius(); + double _nUAngle = pCadEllipse_->GetAngle(); + + return ncmath::Intersect_BeelineWithEllipse(_ptBeeline, _nAngle, _ptCenter, _nLRadius, + _nSRadius, _nUAngle, *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadBeelineWithCadEllipseArc(IN const CCadBeeline* pCadBeeline_, + IN const CCadEllipseArc* pCadEllipseArc_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadBeeline_); + ASSERT(pCadEllipseArc_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + + // 直线信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptBeeline = pCadBeeline_->GetPoint(); + double _nAngle = pCadBeeline_->GetAngle(); + + // 椭圆弧信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptCenter = pCadEllipseArc_->GetCenterPoint(); + double _nLRadius = pCadEllipseArc_->GetLongRadius(); + double _nSRadius = pCadEllipseArc_->GetShortRadius(); + double _nUAngle = pCadEllipseArc_->GetAngle(); + double _nStartAngle = pCadEllipseArc_->GetStartAngle(); + double _nFactor = pCadEllipseArc_->IsNormalDir() ? 1 : -1; + double _nCentralAngle = pCadEllipseArc_->GetCentralAngle() * _nFactor; + + return ncmath::Intersect_BeelineWithEllipseArc(_ptBeeline, _nAngle, _ptCenter, _nLRadius, _nSRadius, + _nUAngle,_nStartAngle, _nCentralAngle, *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadBeelineWithCadMultiSegments(IN const CCadBeeline* pCadBeeline_, + IN const CCadMultiSegments* pCadMultiSegments_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadBeeline_); + ASSERT(pCadMultiSegments_); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + ASSERT(DOUBLE_GREAT_ZERO(pCadMultiSegments_->GetLength())); + + DPOINT2 _ptBeeline = pCadBeeline_->GetPoint(); + double _nAngle = pCadBeeline_->GetAngle(); + + int _nResult = 0; + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + for (int _i = 0; _i < pCadMultiSegments_->GetSegmentCount(); ++_i) + { + SEGMENT _Segment = pCadMultiSegments_->GetSegment(_i); + std::vector _vectorTemp; + + switch(_Segment.nType) + { + case SEGMENT::ARC: + { + DPOINT2 _ptArcCenter(ncmath::c_nINVALID_DOUBLE, ncmath::c_nINVALID_DOUBLE); + double _nArcRadius = 0.0; + double _nArcStartAngle = 0.0; + double _nArcCentralAngle = 0.0; + + SEGMENT::SolveArc(_Segment.ptStart, _Segment.ptEnd, _Segment.nBulge, + &_ptArcCenter, &_nArcRadius, &_nArcStartAngle, &_nArcCentralAngle); + + _nResult += ncmath::Intersect_BeelineWithArc(_ptBeeline, _nAngle, _ptArcCenter, + _nArcRadius, _nArcStartAngle, _nArcCentralAngle, _vectorTemp, _nNeed); + } + break; + + case SEGMENT::LINE: + { + _nResult += ncmath::Intersect_BeelineWithLine(_ptBeeline, _nAngle, _Segment.ptStart, + _Segment.ptEnd, _vectorTemp, _nNeed); + } + break; + default: + ASSERT(false); + } + + // 有交点且需要存储则存储到容器中 --- 吴阳明 2010 09 19 + if (pvectorIntersect_ != NULL && !_vectorTemp.empty()) + copy(_vectorTemp.begin(), _vectorTemp.end(), back_inserter(*pvectorIntersect_)); + } + + return _nResult; +} + +int nce::Intersect_CadCircleWithCadCircle(IN const CCadCircle* pCadCircle1_, + IN const CCadCircle* pCadCircle2_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadCircle1_ != NULL); + ASSERT(pCadCircle1_ != NULL); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + return ncmath::Intersect_CircleWithCircle(pCadCircle1_->GetCenterPoint(), pCadCircle1_->GetRadius(), + pCadCircle2_->GetCenterPoint(), pCadCircle2_->GetRadius(), *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadCircleWithCadEllipse(IN const CCadCircle* pCadCircle_, + IN const CCadEllipse* pCadEllipse_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadCircle_); + ASSERT(pCadEllipse_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + DPOINT2 _ptCircleCenter = pCadCircle_->GetCenterPoint(); + double _nRadius = pCadCircle_->GetRadius(); + DPOINT2 _ptEllipseCenter = pCadEllipse_->GetCenterPoint(); + double _nLongRadius = pCadEllipse_->GetLongRadius(); + double _nShortRadius = pCadEllipse_->GetShortRadius(); + double _nAngle = pCadEllipse_->GetAngle(); + + int _nRet = 0; + if (!pvectorIntersect_) + { + _nRet = Intersect_CircleWithEllipse(_ptCircleCenter, _nRadius, _ptEllipseCenter, + _nLongRadius, _nShortRadius, _nAngle); + } + else + { + _nRet = Intersect_CircleWithEllipse(_ptCircleCenter, _nRadius, _ptEllipseCenter, + _nLongRadius, _nShortRadius, _nAngle, *pvectorIntersect_); + } + + return _nRet; +} + +int nce::Intersect_CadCircleWithCadEllipseArc(IN const CCadCircle* pCadCircle_, + IN const CCadEllipseArc* pCadEllipseArc_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadCircle_); + ASSERT(pCadEllipseArc_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + DPOINT2 _ptCircleCenter = pCadCircle_->GetCenterPoint(); + double _nRadius = pCadCircle_->GetRadius(); + DPOINT2 _ptEllipseArcCenter = pCadEllipseArc_->GetCenterPoint(); + double _nLongRadius = pCadEllipseArc_->GetLongRadius(); + double _nShortRadius = pCadEllipseArc_->GetShortRadius(); + double _nAngle = pCadEllipseArc_->GetAngle(); + double _nStartAngle = pCadEllipseArc_->GetStartAngle(); + double _nSweptAngle = pCadEllipseArc_->GetCentralAngle(); + + if (!pCadEllipseArc_->IsNormalDir()) + _nSweptAngle *= -1; + + int _nRet = 0; + if (!pvectorIntersect_) + { + _nRet = Intersect_CircleWithEllipseArc(_ptCircleCenter, _nRadius, _ptEllipseArcCenter, + _nLongRadius, _nShortRadius, _nAngle, _nStartAngle, _nSweptAngle); + } + else + { + _nRet = Intersect_CircleWithEllipseArc(_ptCircleCenter, _nRadius, _ptEllipseArcCenter, + _nLongRadius, _nShortRadius, _nAngle,_nStartAngle, _nSweptAngle, *pvectorIntersect_); + } + + return _nRet; +} + +int nce::Intersect_CadCircleWithCadMultiSegments(IN const CCadCircle* pCadCircle_, + IN const CCadMultiSegments* pCadMultiSegments_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadCircle_ != NULL); + ASSERT(pCadMultiSegments_ != NULL); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + int _nResult = 0; + int _nSegCount = pCadMultiSegments_->GetSegmentCount(); + for (int _i = 0; _i < _nSegCount; ++_i) + { + std::vector _vecTmp; + + SEGMENT _segTmp = pCadMultiSegments_->GetSegment(_i); + switch (_segTmp.nType) + { + case SEGMENT::ARC: + { + + DPOINT2 _ptArcCenter(ncmath::c_nINVALID_DOUBLE, ncmath::c_nINVALID_DOUBLE); + double _nArcRadius = 0.0; + double _nArcStartAngle = 0.0, _nArcCentralAngle = 0.0; + + SEGMENT::SolveArc(_segTmp.ptStart, _segTmp.ptEnd, _segTmp.nBulge, + &_ptArcCenter, &_nArcRadius, &_nArcStartAngle, &_nArcCentralAngle); + + _nResult += ncmath::Intersect_CircleWithArc(pCadCircle_->GetCenterPoint(), pCadCircle_->GetRadius(), + _ptArcCenter, _nArcRadius, _nArcStartAngle, _nArcCentralAngle, _vecTmp); + } + break; + + case SEGMENT::LINE: + _nResult += ncmath::Intersect_LineWithCircle(_segTmp.ptStart, _segTmp.ptEnd, + pCadCircle_->GetCenterPoint(), pCadCircle_->GetRadius(), _vecTmp); + break; + + case SEGMENT::BEZIER: + default: + // 这里可以选择抛出异常 --- wanghong 2010 09 12 + ASSERT(false); + } + + if (pvectorIntersect_ != NULL && !_vecTmp.empty()) + std::copy(_vecTmp.begin(), _vecTmp.end(), std::back_inserter(*pvectorIntersect_)); + } + + return _nResult; +} + +int nce::Intersect_CadEllipseWithCadEllipse(IN const CCadEllipse* pCadEllipse1_, + IN const CCadEllipse* pCadEllipse2_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadEllipse1_); + ASSERT(pCadEllipse2_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + // 提取几何参数。椭圆所需的几何参数有:中心点、长半轴、短半轴、长半轴对X正向 + // 的倾角。 ---- 杨开锦 2010-09-14 + DPOINT2 _ptCenter1 = pCadEllipse1_->GetCenterPoint(); + double _nURadius1 = pCadEllipse1_->GetLongRadius(); + double _nVRadius1 = pCadEllipse1_->GetShortRadius(); + double _nUAngle1 = pCadEllipse1_->GetAngle(); + DPOINT2 _ptCenter2 = pCadEllipse2_->GetCenterPoint(); + double _nURadius2 = pCadEllipse2_->GetLongRadius(); + double _nVRadius2 = pCadEllipse2_->GetShortRadius(); + double _nUAngle2 = pCadEllipse2_->GetAngle(); + + // 调用数学函数计算交点 ---- 杨开锦 2010-09-14 + int _nRet = 0; + if (pvectorIntersect_ == NULL) + { + _nRet = ncmath::Intersect_EllipseWithEllipse( + _ptCenter1, _nURadius1, _nVRadius1, _nUAngle1, + _ptCenter2, _nURadius2, _nVRadius2, _nUAngle2); + } + else + { + _nRet = ncmath::Intersect_EllipseWithEllipse( + _ptCenter1, _nURadius1, _nVRadius1, _nUAngle1, + _ptCenter2, _nURadius2, _nVRadius2, _nUAngle2, + *pvectorIntersect_); + } + + return _nRet; +} + +int nce::Intersect_CadEllipseWithCadEllipseArc(IN const CCadEllipse* pCadEllipse_, + IN const CCadEllipseArc* pCadEllipseArc_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadEllipse_); + ASSERT(pCadEllipseArc_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + // 提取几何参数。椭圆所需的几何参数有:中心点、长半轴、短半轴、长半轴对X正向 + // 的倾角;椭圆弧所需的几何参数有:中心点、长半轴、短半轴、长半轴对X正向的倾 + // 角、起始角、扫过角。 ---- 杨开锦 2010-09-14 + DPOINT2 _ptCenter1 = pCadEllipse_->GetCenterPoint(); + double _nURadius1 = pCadEllipse_->GetLongRadius(); + double _nVRadius1 = pCadEllipse_->GetShortRadius(); + double _nUAngle1 = pCadEllipse_->GetAngle(); + DPOINT2 _ptCenter2 = pCadEllipseArc_->GetCenterPoint(); + double _nURadius2 = pCadEllipseArc_->GetLongRadius(); + double _nVRadius2 = pCadEllipseArc_->GetShortRadius(); + double _nUAngle2 = pCadEllipseArc_->GetAngle(); + double _nStartAngle2 = pCadEllipseArc_->GetStartAngle(); + double _nSweptAngle2 = pCadEllipseArc_->GetCentralAngle(); + if (!pCadEllipseArc_->IsNormalDir()) + { + // 数学函数中只接受逆时针椭圆弧 ---- 杨开锦 2010-09-14 + _nStartAngle2 -= _nSweptAngle2; + + while (_nStartAngle2 < 0.0) + { + _nStartAngle2 += 2.0 * c_nPIE; + } + + while (_nStartAngle2 >= 2.0 * c_nPIE) + { + _nStartAngle2 -= 2.0 * c_nPIE; + } + } + + // 调用数学函数计算交点 ---- 杨开锦 2010-09-14 + int _nRet = 0; + if (pvectorIntersect_ == NULL) + { + _nRet = ncmath::Intersect_EllipseWithEllipseArc( + _ptCenter1, _nURadius1, _nVRadius1, _nUAngle1, + _ptCenter2, _nURadius2, _nVRadius2, _nUAngle2, _nStartAngle2, _nSweptAngle2); + } + else + { + _nRet = ncmath::Intersect_EllipseWithEllipseArc( + _ptCenter1, _nURadius1, _nVRadius1, _nUAngle1, + _ptCenter2, _nURadius2, _nVRadius2, _nUAngle2, _nStartAngle2, _nSweptAngle2, + *pvectorIntersect_); + } + + return _nRet; +} + +int nce::Intersect_CadEllipseArcWithCadEllipseArc(IN const CCadEllipseArc* pCadEllipseArc1_, + IN const CCadEllipseArc* pCadEllipseArc2_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadEllipseArc1_); + ASSERT(pCadEllipseArc2_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + // 提取几何参数。椭圆弧所需的几何参数有:中心点、长半轴、短半轴、长半轴对X正 + // 向的倾角、起始角、扫过角。 ---- 杨开锦 2010-09-14 + DPOINT2 _ptCenter1 = pCadEllipseArc1_->GetCenterPoint(); + double _nURadius1 = pCadEllipseArc1_->GetLongRadius(); + double _nVRadius1 = pCadEllipseArc1_->GetShortRadius(); + double _nUAngle1 = pCadEllipseArc1_->GetAngle(); + double _nStartAngle1 = pCadEllipseArc1_->GetStartAngle(); + double _nSweptAngle1 = pCadEllipseArc1_->GetCentralAngle(); + if (!pCadEllipseArc1_->IsNormalDir()) + { + // 数学函数中只接受逆时针椭圆弧 ---- 杨开锦 2010-09-14 + _nStartAngle1 -= _nSweptAngle1; + + while (_nStartAngle1 < 0.0) + { + _nStartAngle1 += 2.0 * c_nPIE; + } + + while (_nStartAngle1 >= 2.0 * c_nPIE) + { + _nStartAngle1 -= 2.0 * c_nPIE; + } + } + + // 同上 ---- 杨开锦 2010-09-14 + DPOINT2 _ptCenter2 = pCadEllipseArc2_->GetCenterPoint(); + double _nURadius2 = pCadEllipseArc2_->GetLongRadius(); + double _nVRadius2 = pCadEllipseArc2_->GetShortRadius(); + double _nUAngle2 = pCadEllipseArc2_->GetAngle(); + double _nStartAngle2 = pCadEllipseArc2_->GetStartAngle(); + double _nSweptAngle2 = pCadEllipseArc2_->GetCentralAngle(); + if (!pCadEllipseArc2_->IsNormalDir()) + { + _nStartAngle2 -= _nSweptAngle2; + + while (_nStartAngle2 < 0.0) + { + _nStartAngle2 += 2.0 * c_nPIE; + } + + while (_nStartAngle2 >= 2.0 * c_nPIE) + { + _nStartAngle2 -= 2.0 * c_nPIE; + } + } + + // 调用数学函数计算交点 ---- 杨开锦 2010-09-14 + int _nRet = 0; + if (pvectorIntersect_ == NULL) + { + _nRet = ncmath::Intersect_EllipseArcWithEllipseArc( + _ptCenter1, _nURadius1, _nVRadius1, _nUAngle1, _nStartAngle1, _nSweptAngle1, + _ptCenter2, _nURadius2, _nVRadius2, _nUAngle2, _nStartAngle2, _nSweptAngle2); + } + else + { + _nRet = ncmath::Intersect_EllipseArcWithEllipseArc( + _ptCenter1, _nURadius1, _nVRadius1, _nUAngle1, _nStartAngle1, _nSweptAngle1, + _ptCenter2, _nURadius2, _nVRadius2, _nUAngle2, _nStartAngle2, _nSweptAngle2, + *pvectorIntersect_); + } + + return _nRet; +} + +int nce::Intersect_CadLineWithCadArc(IN const CCadLine* pCadLine_, + IN const CCadArc* pCadArc_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadLine_); + ASSERT(pCadArc_); + ASSERT(pvectorIntersect_== NULL || pvectorIntersect_->empty()); + ASSERT(DOUBLE_GREAT_ZERO(pCadLine_->GetLength())); + ASSERT(DOUBLE_GREAT_ZERO(pCadArc_->GetLength())); + + // 线段信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptLineStart = pCadLine_->GetStartPoint(); + DPOINT2 _ptLineEnd = pCadLine_->GetEndPoint(); + + // 圆弧信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptArcCenter = pCadArc_->GetCenterPoint(); + double _nArcRadius = pCadArc_->GetRadius(); + double _nArcStartAngle = pCadArc_->GetStartAngle(); + + double _nArcCentralAngle = pCadArc_->GetCentralAngle(); + double _nFactor = pCadArc_->IsNormalDir() ? 1 : -1; + _nArcCentralAngle *= _nFactor; + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + return ncmath::Intersect_LineWithArc(_ptLineStart, _ptLineEnd, _ptArcCenter,_nArcRadius, + _nArcStartAngle, _nArcCentralAngle, *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadLineWithCadBeeline(IN const CCadLine* pCadLine_, + IN const CCadBeeline* pCadBeeline_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadLine_ != NULL); + ASSERT(pCadBeeline_ != NULL); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + return ncmath::Intersect_BeelineWithLine(pCadBeeline_->GetPoint(), pCadBeeline_->GetAngle(), + pCadLine_->GetStartPoint(), pCadLine_->GetEndPoint(), *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadLineWithCadCircle(IN const CCadLine* pCadLine_, + IN const CCadCircle* pCadCircle_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadLine_ != NULL); + ASSERT(pCadCircle_ != NULL); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + return ncmath::Intersect_LineWithCircle(pCadLine_->GetStartPoint(), pCadLine_->GetEndPoint(), + pCadCircle_->GetCenterPoint(), pCadCircle_->GetRadius(), *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadLineWithCadEllipse(IN const CCadLine* pCadLine_, + IN const CCadEllipse* pCadEllipse_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadLine_ && pCadEllipse_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + + // 线段信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptStart = pCadLine_->GetStartPoint(); + DPOINT2 _ptEnd = pCadLine_->GetEndPoint(); + + // 椭圆信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptCenter = pCadEllipse_->GetCenterPoint(); + double _nLRadius = pCadEllipse_->GetLongRadius(); + double _nSRadius = pCadEllipse_->GetShortRadius(); + double _nUAngle = pCadEllipse_->GetAngle(); + + return ncmath::Intersect_LineWithEllipse(_ptStart, _ptEnd, + _ptCenter, _nLRadius, _nSRadius, _nUAngle, + *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadLineWithCadEllipseArc(IN const CCadLine* pCadLine_, + IN const CCadEllipseArc* pCadEllipseArc_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadLine_ && pCadEllipseArc_); + ASSERT(!pvectorIntersect_ || pvectorIntersect_->empty()); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + + // 线段信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptStart = pCadLine_->GetStartPoint(); + DPOINT2 _ptEnd = pCadLine_->GetEndPoint(); + + // 椭圆信息求取 --- 吴阳明 2010 09 19 + DPOINT2 _ptCenter = pCadEllipseArc_->GetCenterPoint(); + double _nLRadius = pCadEllipseArc_->GetLongRadius(); + double _nSRadius = pCadEllipseArc_->GetShortRadius(); + double _nUAngle = pCadEllipseArc_->GetAngle(); + double _nStartAngle = pCadEllipseArc_->GetStartAngle(); + double _nFactor = pCadEllipseArc_->IsNormalDir() ? 1 : -1; + double _nCentralAngle = pCadEllipseArc_->GetCentralAngle() * _nFactor; + + return ncmath::Intersect_LineWithEllipseArc(_ptStart, _ptEnd, + _ptCenter, _nLRadius, _nSRadius, _nUAngle, _nStartAngle, _nCentralAngle, + *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadLineWithCadLine(IN const CCadLine* pCadLine1_, + IN const CCadLine* pCadLine2_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadLine1_); + ASSERT(pCadLine2_); + ASSERT(pvectorIntersect_== NULL || pvectorIntersect_->empty()); + ASSERT(DOUBLE_GREAT_ZERO(pCadLine1_->GetLength())); + ASSERT(DOUBLE_GREAT_ZERO(pCadLine2_->GetLength())); + + // 线段信息提取 --- 吴阳明 2010 09 19 + DPOINT2 _ptLine1Start = pCadLine1_->GetStartPoint(); + DPOINT2 _ptLine2Start = pCadLine2_->GetStartPoint(); + DPOINT2 _ptLine1End = pCadLine1_->GetEndPoint(); + DPOINT2 _ptLine2End = pCadLine2_->GetEndPoint(); + + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + return ncmath::Intersect_LineWithLine(_ptLine1Start, _ptLine1End, + _ptLine2Start, _ptLine2End, *pvectorIntersect_, _nNeed); +} + +int nce::Intersect_CadLineWithCadMultiSegments(IN const CCadLine* pCadLine_, + IN const CCadMultiSegments* pCadMultiSegments_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadLine_ != NULL); + ASSERT(pCadMultiSegments_ != NULL); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + int _nResult = 0; + // 需要交点个数 0代表不需要,而-1代表尽可能多 --- 吴阳明 2010 09 19 + int _nNeed = (pvectorIntersect_ == NULL) ? 0 : -1; + int _nSegCount = pCadMultiSegments_->GetSegmentCount(); + for (int _i = 0; _i < _nSegCount; ++_i) + { + std::vector _vecTmp; + + SEGMENT _segTmp = pCadMultiSegments_->GetSegment(_i); + switch (_segTmp.nType) + { + case SEGMENT::ARC: + { + DPOINT2 _ptArcCenter(ncmath::c_nINVALID_DOUBLE, ncmath::c_nINVALID_DOUBLE); + double _nArcRadius = 0.0; + double _nArcStartAngle = 0.0, _nArcCentralAngle = 0.0; + + SEGMENT::SolveArc(_segTmp.ptStart, _segTmp.ptEnd, _segTmp.nBulge, + &_ptArcCenter, &_nArcRadius, &_nArcStartAngle, &_nArcCentralAngle); + + _nResult += ncmath::Intersect_LineWithArc(pCadLine_->GetStartPoint(), pCadLine_->GetEndPoint(), + _ptArcCenter, _nArcRadius, _nArcStartAngle, _nArcCentralAngle, _vecTmp, _nNeed); + } + break; + + case SEGMENT::LINE: + _nResult += ncmath::Intersect_LineWithLine(pCadLine_->GetStartPoint(), pCadLine_->GetEndPoint(), + _segTmp.ptStart, _segTmp.ptEnd, _vecTmp, _nNeed); + break; + + case SEGMENT::BEZIER: + default: + // 这里可以选择抛出异常 --- wanghong 2010 09 12 + ASSERT(false); + } + + if (pvectorIntersect_ != NULL && !_vecTmp.empty()) + std::copy(_vecTmp.begin(), _vecTmp.end(), std::back_inserter(*pvectorIntersect_)); + } + + return _nResult; +} + +int nce::Intersect_CadObjectWithCadGroup(IN const CCadObject* pCadObject_, + IN const CCadGroup* pCadGroup_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadObject_ && pCadGroup_); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + ASSERT(pCadObject_->GetType() != cadgroup); + + int _nResult = 0; + for (int _i = 0; _i != pCadGroup_->GetNumOfChild(); ++_i) + { + const CCadObject* _pCadObjectTemp = pCadGroup_->GetAt(_i); + int _nNum = 0; + + if (pvectorIntersect_ != NULL) + { + std::vector _vecTmp; + if (_nNum = GetIntersection(pCadObject_, _pCadObjectTemp, &_vecTmp)) + { + _nResult += _nNum; + copy(_vecTmp.begin(), _vecTmp.end(), back_inserter(*pvectorIntersect_)); + } + } + else + { + if (_nNum = GetIntersection(pCadObject_, _pCadObjectTemp, NULL)) + _nResult += _nNum; + } + } + + return _nResult; +} + +int nce::Intersect_CadObjectWithCadText(IN const CCadObject* pCadObject_, + IN const CCadText* pCadText_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadObject_ && pCadText_); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + ASSERT(pCadObject_->GetType() != cadtext); + + const CCadGroup* _pCadGroup = pCadText_->GetTextGroup(); + return GetIntersection(pCadObject_, _pCadGroup, pvectorIntersect_); +} + +// 群组与群组求交 +int nce::Intersect_CadGroupWithCadGroup(IN const CCadGroup* pCadGroup1_, + IN const CCadGroup* pCadGroup2_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadGroup1_ && pCadGroup1_->GetType() == cadgroup); + ASSERT(pCadGroup2_ && pCadGroup2_->GetType() == cadgroup); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + int _nResult = 0; + for (int _i = 0; _i != pCadGroup1_->GetNumOfChild(); ++_i) + { + const CCadObject* _pCadObjectTemp = pCadGroup1_->GetAt(_i); + int _nNum = 0; + + if (pvectorIntersect_ != NULL) + { + std::vector _vecTmp; + if (_nNum = GetIntersection(_pCadObjectTemp, pCadGroup2_, &_vecTmp)) + { + _nResult += _nNum; + copy(_vecTmp.begin(), _vecTmp.end(), back_inserter(*pvectorIntersect_)); + } + } + else + { + if (_nNum = GetIntersection(_pCadObjectTemp, pCadGroup2_, NULL)) + _nResult += _nNum; + } + } + + return _nResult; +} + +// 群组与文字求交 +int nce::Intersect_CadGroupWithCadText(IN const CCadGroup* pCadGroup_, + IN const CCadText* pCadText_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadGroup_ && pCadGroup_->GetType() == cadgroup); + ASSERT(pCadText_ && pCadText_->GetType() == cadtext); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + int _nResult = 0; + for (int _i = 0; _i != pCadGroup_->GetNumOfChild(); ++_i) + { + const CCadObject* _pCadObjectTemp = pCadGroup_->GetAt(_i); + int _nNum = 0; + + if (pvectorIntersect_ != NULL) + { + std::vector _vecTmp; + if (_nNum = GetIntersection(_pCadObjectTemp, pCadText_, &_vecTmp)) + { + _nResult += _nNum; + copy(_vecTmp.begin(), _vecTmp.end(), back_inserter(*pvectorIntersect_)); + } + } + else + { + if (_nNum = GetIntersection(_pCadObjectTemp, pCadText_, NULL)) + _nResult += _nNum; + } + } + + return _nResult; +} + +// 群组与文字求交 +int nce::Intersect_CadTextWithCadText(IN const CCadText* pCadText1_, + IN const CCadText* pCadText2_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadText1_ && pCadText1_->GetType() == cadtext); + ASSERT(pCadText2_ && pCadText2_->GetType() == cadtext); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + const CCadGroup* _pCadGroup1 = pCadText1_->GetTextGroup(); + const CCadGroup* _pCadGroup2 = pCadText2_->GetTextGroup(); + + return Intersect_CadGroupWithCadGroup(_pCadGroup1, _pCadGroup2, pvectorIntersect_); +} + +int nce::Intersect_CadMultiSegmentsWithCadEllipse(IN const CCadMultiSegments* pCadMultiSegments_, + IN const CCadEllipse* pCadEllipse_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadMultiSegments_ != NULL); + ASSERT(pCadEllipse_ != NULL); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + int _nResult = 0; + // 多段线中的各段与椭圆进行求交 --- 吴阳明 2010 09 19 + for (int _i = 0; _i != pCadMultiSegments_->GetSegmentCount(); ++_i) + { + SEGMENT _SegmentOut = pCadMultiSegments_->GetSegment(_i); + std::vector _vectorTemp; + + switch(_SegmentOut.nType) + { + case SEGMENT::LINE: + { + CCadLine _CadLine(_SegmentOut.ptStart, _SegmentOut.ptEnd); + + if (pvectorIntersect_ != NULL) + _nResult += Intersect_CadLineWithCadEllipse(&_CadLine, pCadEllipse_, &_vectorTemp); + else + _nResult += Intersect_CadLineWithCadEllipse(&_CadLine, pCadEllipse_, NULL); + } + break; + + case SEGMENT::ARC: + { + DPOINT2 _ptArcCenter(ncmath::c_nINVALID_DOUBLE, ncmath::c_nINVALID_DOUBLE); + double _nArcRadius = 0.0; + double _nArcStartAngle = 0.0, _nArcCentralAngle = 0.0; + + SEGMENT::SolveArc(_SegmentOut.ptStart, _SegmentOut.ptEnd, _SegmentOut.nBulge, + &_ptArcCenter, &_nArcRadius, &_nArcStartAngle, &_nArcCentralAngle); + CCadArc _CadArc(_ptArcCenter, _nArcRadius, _nArcStartAngle, fabs(_nArcCentralAngle), _SegmentOut.nBulge > 0); + + if (pvectorIntersect_ != NULL) + _nResult += Intersect_CadArcWithCadEllipse(&_CadArc, pCadEllipse_, &_vectorTemp); + else + _nResult += Intersect_CadArcWithCadEllipse(&_CadArc, pCadEllipse_, NULL); + } + break; + + case SEGMENT::BEZIER: + default: + ASSERT(false); + } + + // 需要求取交点,且求取交点不为空则进行存储 --- 吴阳明 2010 09 19 + if (pvectorIntersect_ != NULL && !_vectorTemp.empty()) + { + copy(_vectorTemp.begin(), _vectorTemp.end(), back_inserter(*pvectorIntersect_)); + } + } + return _nResult; +} + +int nce::Intersect_CadMultiSegmentsWithCadEllipseArc(IN const CCadMultiSegments* pCadMultiSegments_, + IN const CCadEllipseArc* pCadEllipseArc_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadMultiSegments_ != NULL); + ASSERT(pCadEllipseArc_ != NULL); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + int _nResult = 0; + // 多段线中的各段同椭圆弧进行求交 --- 吴阳明 2010 09 19 + for (int _i = 0; _i != pCadMultiSegments_->GetSegmentCount(); ++_i) + { + SEGMENT _SegmentOut = pCadMultiSegments_->GetSegment(_i); + std::vector _vectorTemp; + + switch(_SegmentOut.nType) + { + case SEGMENT::LINE: + { + CCadLine _CadLine(_SegmentOut.ptStart, _SegmentOut.ptEnd); + + if (pvectorIntersect_ != NULL) + _nResult += Intersect_CadLineWithCadEllipseArc(&_CadLine, pCadEllipseArc_, &_vectorTemp); + else + _nResult += Intersect_CadLineWithCadEllipseArc(&_CadLine, pCadEllipseArc_, NULL); + } + break; + + case SEGMENT::ARC: + { + DPOINT2 _ptArcCenter(ncmath::c_nINVALID_DOUBLE, ncmath::c_nINVALID_DOUBLE); + double _nArcRadius = 0.0; + double _nArcStartAngle = 0.0, _nArcCentralAngle = 0.0; + + SEGMENT::SolveArc(_SegmentOut.ptStart, _SegmentOut.ptEnd, _SegmentOut.nBulge, + &_ptArcCenter, &_nArcRadius, &_nArcStartAngle, &_nArcCentralAngle); + CCadArc _CadArc(_ptArcCenter, _nArcRadius, _nArcStartAngle, fabs(_nArcCentralAngle), _SegmentOut.nBulge > 0); + + if (pvectorIntersect_ != NULL) + _nResult += Intersect_CadArcWithCadEllipseArc(&_CadArc, pCadEllipseArc_, &_vectorTemp); + else + _nResult += Intersect_CadArcWithCadEllipseArc(&_CadArc, pCadEllipseArc_, NULL); + } + break; + + case SEGMENT::BEZIER: + default: + ASSERT(false); + } + + if (pvectorIntersect_ != NULL && !_vectorTemp.empty()) + { + copy(_vectorTemp.begin(), _vectorTemp.end(), back_inserter(*pvectorIntersect_)); + } + } + return _nResult; +} + +int nce::Intersect_CadMultiSegmentsWithCadMultiSegments(IN const CCadMultiSegments* pCadMultiSegments1_, + IN const CCadMultiSegments* pCadMultiSegments2_, + OUT std::vector* pvectorIntersect_) +{ + ASSERT(pCadMultiSegments1_ != NULL); + ASSERT(pCadMultiSegments2_ != NULL); + ASSERT(pvectorIntersect_ == NULL || pvectorIntersect_->empty()); + + int _nResult = 0; + // 将多段线中的各段同多段线进行求交 --- 吴阳明 2010 09 19 + for (int _i = 0; _i != pCadMultiSegments1_->GetSegmentCount(); ++_i) + { + SEGMENT _SegmentOut = pCadMultiSegments1_->GetSegment(_i); + + CCadObject* _pCadObjectOut = NULL; + if (!GetCadObjectFromSegment(_SegmentOut, &_pCadObjectOut)) + continue; + + std::vector _vectorTemp; + int _j = pCadMultiSegments1_->GetID() == pCadMultiSegments2_->GetID() ? _i + 1 : 0; + for (; _j < pCadMultiSegments2_->GetSegmentCount(); ++_j) + { + SEGMENT _SegmentIn = pCadMultiSegments2_->GetSegment(_j); + + CCadObject* _pCadObjectIn = NULL; + if (!GetCadObjectFromSegment(_SegmentIn, &_pCadObjectIn)) + continue; + + std::vector _vectorTemp; + if (pvectorIntersect_ != NULL) + _nResult += GetIntersection(_pCadObjectOut, _pCadObjectIn, &_vectorTemp); + else + _nResult += GetIntersection(_pCadObjectOut, _pCadObjectIn, NULL); + + if (pvectorIntersect_ != NULL && !_vectorTemp.empty()) + { + copy(_vectorTemp.begin(), _vectorTemp.end(), back_inserter(*pvectorIntersect_)); + } + delete _pCadObjectIn; + } + delete _pCadObjectOut; + } + return _nResult; +} + +bool nce::GetCadObjectFromSegment(IN const SEGMENT& Segment_, OUT CCadObject** ppCadObject_) +{ + ASSERT(IsValidDouble(Segment_.ptStart.x)); + ASSERT(IsValidDouble(Segment_.ptStart.y)); + ASSERT(IsValidDouble(Segment_.ptEnd.x)); + ASSERT(IsValidDouble(Segment_.ptEnd.y)); + ASSERT(IsValidDouble(Segment_.nBulge)); + ASSERT(*ppCadObject_ == NULL); + + switch(Segment_.nType) + { + case SEGMENT::LINE: + { + CCadLine _CadLine(Segment_.ptStart, Segment_.ptEnd); + *ppCadObject_ = _CadLine.Clone(); + } + break; + + case SEGMENT::ARC: + { + DPOINT2 _ptArcCenter(ncmath::c_nINVALID_DOUBLE, ncmath::c_nINVALID_DOUBLE); + double _nArcRadius = 0.0; + double _nArcStartAngle = 0.0, _nArcCentralAngle = 0.0; + + SEGMENT::SolveArc(Segment_.ptStart, Segment_.ptEnd, Segment_.nBulge, + &_ptArcCenter, &_nArcRadius, &_nArcStartAngle, &_nArcCentralAngle); + CCadArc _CadArc(_ptArcCenter, _nArcRadius, _nArcStartAngle, fabs(_nArcCentralAngle), Segment_.nBulge > 0); + + *ppCadObject_ = _CadArc.Clone(); + } + break; + + // 不支持的类型 --- 吴阳明 2010 09 19 + case SEGMENT::BEZIER: + default: + return false; + } + + return true; +} diff --git a/src/IntersectingLineDoer.cpp b/src/IntersectingLineDoer.cpp new file mode 100644 index 0000000..628e472 --- /dev/null +++ b/src/IntersectingLineDoer.cpp @@ -0,0 +1,1640 @@ +// ************************************************************************** // +// IntersectingLineDoer.cpp : implementation of the CIntersectingLineDoer class +// Copyright(c)2011 Naiky Company. All rights reserved. +// +// Abstract: +// 本文件实现CIntersectingLineDoer类 +// ************************************************************************** // +#include "StdAfx.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +using namespace ncmath; +using namespace nce; +using namespace intersectingline; + +const CHAR c_szINTERSECT_AXIS_DIR[] = "INTERSECT_AXIS_DIR"; +const CHAR c_szINTERSECT_AXIS_X[] = "INTERSECT_AXIS_X"; +const CHAR c_szINTERSECT_AXIS_Y[] = "INTERSECT_AXIS_Y"; +const CHAR c_szINTERSECT_STEELTUBEDIA[] = "INTERSECT_STEELTUBEDIA"; +const CHAR c_szINTERSECT_CUTPRECISION[] = "INTERSECT_CUTPRECISION"; +double _GetEllipsePerimeter(double nLongRadius_,double nShortRadius_); + +CIntersectingLineDoer::CIntersectingLineDoer() +{ +} + +CIntersectingLineDoer::~CIntersectingLineDoer() +{ +} + +CIntersectingLinePath* CIntersectingLineDoer::TranslateCad2IntersectingPath(IN const CCadObject* pCadObjectSour_, + IN const IntersectingLineInfo& IntersectingLineInfo_) +{ + if (!pCadObjectSour_) + { + ASSERT(FALSE); + return NULL; + } + + switch (pCadObjectSour_->GetType()) + { + case cadline: + { + return TranslateLine2IntersectingPath((CCadLine*)pCadObjectSour_, IntersectingLineInfo_); + } + break; + + case cadarc: + { + return TranslateArc2IntersectingPath((CCadArc*)pCadObjectSour_, IntersectingLineInfo_); + } + break; + + case cadellipsearc: + { + return TranslateEllipseArc2IntersectingPath((CCadEllipseArc*)pCadObjectSour_, IntersectingLineInfo_); + } + break; + + case cadcircle: + { + return TranslateCircle2IntersectingPath((CCadCircle*)pCadObjectSour_, IntersectingLineInfo_); + } + break; + + case cadellipse: + { + return TranslateEllipse2IntersectingPath((CCadEllipse*)pCadObjectSour_, IntersectingLineInfo_); + } + break; + + case cadrectangle: + case cadpolyline: + case cadpolygon: + case cadstar: + { + return TranslateMultiSegments2IntersectingPath((CCadMultiSegments*)pCadObjectSour_, IntersectingLineInfo_); + } + break; + + default: + { + ASSERT(FALSE); + return NULL; + } + break; + } +} + +void CIntersectingLineDoer::AddLinetoIntersectPath(CIntersectingLinePath* pIntersectLine_, + DPOINT2 ptStart_, DPOINT2 ptEnd_, double nPrecision_) +{ + if (!pIntersectLine_) + { + ASSERT(FALSE); + return; + } + + // 如果线段是水平的或竖直的,则无需分割。要注意,本函数是为相贯线功能而设计。 --- 吴典 2011 9 1 + if (DOUBLE_EQU(ptStart_.x, ptEnd_.x) || DOUBLE_EQU(ptStart_.y, ptEnd_.y)) + { + pIntersectLine_->AddtoPath(ptStart_); + pIntersectLine_->AddtoPath(ptEnd_); + } + else + { + double _nLength = (ptEnd_ - ptStart_).GetLength(); + const int _nCirculations = (int)(_nLength / nPrecision_); // 分割的段数 + if (_nCirculations <= 0) + return; + + double _nStepLength = _nLength / _nCirculations; // 步长 + DPOINT2 _vec = ptEnd_ - ptStart_; + _vec.Unify(); + for (int _i = 0; _i < _nCirculations; ++_i) + { + DPOINT2 _pt = ptStart_ + _vec * (_nStepLength * _i); + pIntersectLine_->AddtoPath(_pt); + } + pIntersectLine_->AddtoPath(ptEnd_); + } +} + +void CIntersectingLineDoer::AddArctoIntersectPath(CIntersectingLinePath* pIntersectLine_, + DPOINT2 ptCenter_, double nRadius_, + double nStartAngle_, double nEndAngle_, double nPrecision_) +{ + if (!pIntersectLine_ || DOUBLE_EQU_ZERO(nRadius_) || DOUBLE_EQU(nStartAngle_, nEndAngle_)) + { + ASSERT(FALSE); + return; + } + + int _nSign = (nEndAngle_ - nStartAngle_) >= 0 ? 1 : -1; + double _nLength = nRadius_ * _nSign * (nEndAngle_ - nStartAngle_); + ASSERT(DOUBLE_GREAT_ZERO(_nLength)); + const int _nCirculations = (int)(_nLength / nPrecision_); + if (_nCirculations <= 0) + return; + + double _nStepAngle = (nEndAngle_ - nStartAngle_) / _nCirculations; // 每一小段圆弧对应的角 + for (int _i = 0; _i < _nCirculations; ++_i) + { + double _nAngle = nStartAngle_ + _nStepAngle * (_i); + DPOINT2 _pt = ptCenter_ + DPOINT2(cos(_nAngle), sin(_nAngle)) * nRadius_; + pIntersectLine_->AddtoPath(_pt); + } + DPOINT2 _ptEnd = ptCenter_ + DPOINT2(cos(nEndAngle_), sin(nEndAngle_)) * nRadius_; + pIntersectLine_->AddtoPath(_ptEnd); +} + +CIntersectingLinePath* CIntersectingLineDoer::TranslateLine2IntersectingPath(IN const nce::CCadLine* pCadLine_, + IN const IntersectingLineInfo& IntersectInfo_) +{ + if (!pCadLine_) + { + ASSERT(FALSE); + return NULL; + } + + DPOINT2 _ptStart = pCadLine_->GetStartPoint(); + DPOINT2 _ptEnd = pCadLine_->GetEndPoint(); + CIntersectingLinePath* _pIntersectingLinePath = new CIntersectingLinePath; + AddLinetoIntersectPath(_pIntersectingLinePath, _ptStart, _ptEnd, IntersectInfo_.nCutPrecision); + + return _pIntersectingLinePath; +} + +CIntersectingLinePath* CIntersectingLineDoer::TranslateArc2IntersectingPath(IN const CCadArc* pCadArc_, + IN const IntersectingLineInfo& IntersectInfo_) +{ + if (!pCadArc_) + { + ASSERT(FALSE); + return NULL; + } + + DPOINT2 _ptCenter = pCadArc_->GetCenterPoint(); + double _nRadius = pCadArc_->GetRadius(); + double _nStartAngle = pCadArc_->GetStartAngle(); + double _nSweepAngle = pCadArc_->GetCentralAngle(); + double _nEndAngle; + if (pCadArc_->IsNormalDir()) + _nEndAngle = _nStartAngle + _nSweepAngle; + else + _nEndAngle = _nStartAngle - _nSweepAngle; + + CIntersectingLinePath* _pIntersectingLinePath = new CIntersectingLinePath; + AddArctoIntersectPath(_pIntersectingLinePath, _ptCenter, _nRadius, _nStartAngle, _nEndAngle, IntersectInfo_.nCutPrecision); + return _pIntersectingLinePath; +} + +CIntersectingLinePath* CIntersectingLineDoer::TranslateCircle2IntersectingPath(IN const CCadCircle* pCircle_, + IN const IntersectingLineInfo& IntersectingLineInfo_) +{ + // 生成IntersectingLinePath对象 卢伟 2011-12-21 + if (!pCircle_ || DOUBLE_EQU_ZERO(pCircle_->GetRadius())) + { + ASSERT(FALSE); + return NULL; + } + DPOINT2 _ptCenter = pCircle_->GetCenterPoint(); + double _nRadius = pCircle_->GetRadius(); + CIntersectingLinePath* _pIntersectingLinePath = new CIntersectingLinePath; + if (pCircle_->IsNormalDir()) + { + AddArctoIntersectPath(_pIntersectingLinePath, _ptCenter, _nRadius, 0., c_nPIE, IntersectingLineInfo_.nCutPrecision); + AddArctoIntersectPath(_pIntersectingLinePath, _ptCenter, _nRadius, c_nPIE, 2 * c_nPIE, IntersectingLineInfo_.nCutPrecision); + } + else + { + AddArctoIntersectPath(_pIntersectingLinePath, _ptCenter, _nRadius, 0., -c_nPIE, IntersectingLineInfo_.nCutPrecision); + AddArctoIntersectPath(_pIntersectingLinePath, _ptCenter, _nRadius, -c_nPIE, -2 * c_nPIE, IntersectingLineInfo_.nCutPrecision); + } + + return _pIntersectingLinePath; +} + +CIntersectingLinePath* CIntersectingLineDoer::TranslateEllipseArc2IntersectingPath(IN const CCadEllipseArc* pCadEllipseArc_, + IN const IntersectingLineInfo& IntersectInfo_) +{ + if (!pCadEllipseArc_ || DOUBLE_EQU_ZERO(pCadEllipseArc_->GetLongRadius()) + || DOUBLE_EQU_ZERO(pCadEllipseArc_->GetShortRadius())) + { + ASSERT(FALSE); + return NULL; + } + + const int _nCirculations = (int)(pCadEllipseArc_->GetLength() / IntersectInfo_.nCutPrecision); + if (_nCirculations <= 0) + return NULL; + + double _nSweepAngle = pCadEllipseArc_->GetCentralAngle(); + double _nStepAngle = _nSweepAngle / _nCirculations; + CIntersectingLinePath* _pIntersectingLinePath = new CIntersectingLinePath; + for (int _i = 0; _i < _nCirculations; ++_i) + { + double _nAngle = _nStepAngle * _i; + DPOINT2 _pt = pCadEllipseArc_->GetPoint_XY(_nAngle); + _pIntersectingLinePath->AddtoPath(_pt); + } + + DPOINT2 _ptEnd = pCadEllipseArc_->GetEndPoint(); + _pIntersectingLinePath->AddtoPath(_ptEnd); + + return _pIntersectingLinePath; +} +// 将椭圆转换为很多小直线段处理 卢伟 2011-12-20 +CIntersectingLinePath* CIntersectingLineDoer::TranslateEllipse2IntersectingPath(IN const CCadEllipse* pEllipse_, + IN const IntersectingLineInfo& IntersectInfo_) +{ + if (!pEllipse_ || (pEllipse_->GetLongRadius() == 0) || (pEllipse_->GetShortRadius() == 0)) + { + ASSERT(FALSE); + return NULL; + } + + const int _nCirculations = (int)(pEllipse_->GetLength() / IntersectInfo_.nCutPrecision); + if (_nCirculations <= 0) + return NULL; + // 生成IntersectingLinePath对象 卢伟 2011-12-21 + CIntersectingLinePath* _pIntersectingLinePath = new CIntersectingLinePath; + if (pEllipse_->IsNormalDir()) + { + double _nStepRadian = 2. * c_nPIE / _nCirculations; + for (int _i = 0; _i < _nCirculations; _i++) + { + double _nAngle = _nStepRadian * _i; + DPOINT2 _pt = pEllipse_->GetPoint_XY(_nAngle); + _pIntersectingLinePath->AddtoPath(_pt); + } + } + else + { + double _nStepRadian = -2. * c_nPIE / _nCirculations; + for (int _i = 0; _i < _nCirculations; _i++) + { + double _nAngle = _nStepRadian * _i; + _nAngle = RegularizeRadian(_nAngle); + DPOINT2 _pt = pEllipse_->GetPoint_XY(_nAngle); + _pIntersectingLinePath->AddtoPath(_pt); + } + } + + DPOINT2 _ptEnd = pEllipse_->GetPoint_XY(0.); + _pIntersectingLinePath->AddtoPath(_ptEnd); + + return _pIntersectingLinePath; +} + +CIntersectingLinePath* CIntersectingLineDoer::TranslateMultiSegments2IntersectingPath(IN const CCadMultiSegments* pMultiSegments_, + IN const IntersectingLineInfo& IntersectingLineInfo_) +{ + if (!pMultiSegments_) + { + ASSERT(FALSE); + return NULL; + } + + // 生成IntersectingLinePath对象 卢伟 2011-12-21 + CIntersectingLinePath* _pIntersectingLinePath = new CIntersectingLinePath; + + int _nCount = pMultiSegments_->GetSegmentCount(); + // 多段线在反向时会将图形的内部数据反转,所以此处不需要考虑 + // 方向的true或false 卢伟 2011-12-22 + int _nSegIndex = 0; + while (_nSegIndex < _nCount) + { + SEGMENT _segment = pMultiSegments_->GetSegment(_nSegIndex++); + if (_segment.nType == SEGMENT::LINE) + { + DPOINT2 _ptStart = _segment.ptStart; + DPOINT2 _ptEnd = _segment.ptEnd; + AddLinetoIntersectPath(_pIntersectingLinePath, _ptStart, _ptEnd, IntersectingLineInfo_.nCutPrecision); + } + else + { + DPOINT2 _ptStart = _segment.ptStart; + DPOINT2 _ptEnd = _segment.ptEnd; + double _nBulge = _segment.nBulge; + DPOINT2 _ptCenter; + double _nRadius; + double _nStartAngle; + double _nSweepAngle; + SEGMENT::SolveArc(_ptStart, _ptEnd, _nBulge, &_ptCenter, &_nRadius, &_nStartAngle, &_nSweepAngle); + double _nEndAngle = _nStartAngle + _nSweepAngle; + AddArctoIntersectPath(_pIntersectingLinePath, _ptCenter, _nRadius, _nStartAngle, _nEndAngle, + IntersectingLineInfo_.nCutPrecision); + } + } + + return _pIntersectingLinePath; +} + +CCadObject* CIntersectingLineDoer::TranslateIntersectingPath2Cad(IN const CIntersectingLinePath* pIntersectingLinePathSour_) +{ + if (!pIntersectingLinePathSour_ || (pIntersectingLinePathSour_->m_vecPointVector.size() == 0)) + { + ASSERT(FALSE); + return NULL; + } + + CCadPolyline* _pPolyline = new CCadPolyline; + DPOINT2 _ptStart = pIntersectingLinePathSour_->m_ptStart; + ASSERT(IsValidDouble(_ptStart.x) && IsValidDouble(_ptStart.y)); + _pPolyline->SetStartPoint(_ptStart); + int _nSize = (int)pIntersectingLinePathSour_->m_vecPointVector.size(); + ASSERT(_nSize != 0); + DPOINT2 _ptEnd = pIntersectingLinePathSour_->m_vecPointVector[0]; + DPOINT2 _ptLast = _ptEnd; + int _nSegNo = 1; + while (_nSegNo < _nSize) + { + DPOINT2 _pt = pIntersectingLinePathSour_->m_vecPointVector[_nSegNo]; + if (D2GetPointToLineDistance(_pt, _ptStart, _ptEnd) > 0.001) + { + _pPolyline->AddLine(_ptLast); + _ptStart = _ptLast; + _ptEnd = _pt; + } + _ptLast = _pt; + + _nSegNo++; + } + + _ptEnd = pIntersectingLinePathSour_->m_vecPointVector[_nSize - 1]; + _pPolyline->AddLine(_ptEnd); + + delete pIntersectingLinePathSour_; + pIntersectingLinePathSour_ = NULL; + + return _pPolyline; +} +void CIntersectingLineDoer::SetIntersectingInfotoCad(CCadObject* pCadObject_, + IN const IntersectingLineInfo& IntersectingLineInfo_) +{ + if (!pCadObject_ || IntersectingLineInfo_.dwSize != sizeof(IntersectingLineInfo)) + { + ASSERT(FALSE); + return; + } + + if (pCadObject_->GetType() == cadgroup) + { + CCadGroup* _pGroup = (CCadGroup*)pCadObject_; + for (CadObjectList::iterator _it = _pGroup->GetObjectsList()->begin(); + _it != _pGroup->GetObjectsList()->end(); _it++) + { + SetIntersectingInfotoCad(*_it, IntersectingLineInfo_); + } + } + else if (pCadObject_->GetType() == cadtext) + { + CCadText* _pCadText = (CCadText*)pCadObject_; + for (CadObjectList::iterator _it = _pCadText->GetTextGroup()->GetObjectsList()->begin(); + _it != _pCadText->GetTextGroup()->GetObjectsList()->end(); _it++) + { + SetIntersectingInfotoCad(*_it, IntersectingLineInfo_); + } + } + else + { + DRECT _rectBound = pCadObject_->GetBoundRect(); + axis_t _nAxis = IntersectingLineInfo_.nAxis; + if (_nAxis == axis::x && DOUBLE_GE(_rectBound.width, IntersectingLineInfo_.nSteelTubeDiameter)) + { + _nAxis = axis::none; + } + if (_nAxis == axis::y && DOUBLE_GE(_rectBound.height, IntersectingLineInfo_.nSteelTubeDiameter)) + { + _nAxis = axis::none; + } + + if (_nAxis == axis::x) + { + pCadObject_->SetKey(c_szINTERSECT_AXIS_DIR, c_szINTERSECT_AXIS_X); + pCadObject_->SetKey_DBL(c_szINTERSECT_STEELTUBEDIA, IntersectingLineInfo_.nSteelTubeDiameter); + pCadObject_->SetKey_DBL(c_szINTERSECT_CUTPRECISION, IntersectingLineInfo_.nCutPrecision); + } + else if (_nAxis == axis::y) + { + pCadObject_->SetKey(c_szINTERSECT_AXIS_DIR, c_szINTERSECT_AXIS_Y); + pCadObject_->SetKey_DBL(c_szINTERSECT_STEELTUBEDIA, IntersectingLineInfo_.nSteelTubeDiameter); + pCadObject_->SetKey_DBL(c_szINTERSECT_CUTPRECISION, IntersectingLineInfo_.nCutPrecision); + } + else + { + pCadObject_->SetKey(c_szINTERSECT_AXIS_DIR, NULL); + pCadObject_->SetKey(c_szINTERSECT_STEELTUBEDIA, NULL); + pCadObject_->SetKey(c_szINTERSECT_CUTPRECISION, NULL); + } + } +} + +bool CIntersectingLineDoer::GetIntersectingInfofromCad(IN const CCadObject* pCadObject_, + OUT IntersectingLineInfo& IntersectingLineInfo_) +{ + // 非封闭图形没有相贯线信息 卢伟 2011-12-20 + if (!pCadObject_) + { + ASSERT(FALSE); + return false; + } + + CString _str = pCadObject_->GetKey(c_szINTERSECT_AXIS_DIR); + if (_str.IsEmpty()) + IntersectingLineInfo_.nAxis = axis::none; + else if (_str == c_szINTERSECT_AXIS_X) + IntersectingLineInfo_.nAxis = axis::x; + else if (_str == c_szINTERSECT_AXIS_Y) + IntersectingLineInfo_.nAxis = axis::y; + else + ASSERT(FALSE); + + double _nSteelTubeDiameter = pCadObject_->GetKey_DBL(c_szINTERSECT_STEELTUBEDIA); + if (IsInvalidDouble(_nSteelTubeDiameter)) + IntersectingLineInfo_.nSteelTubeDiameter = 0; + else + IntersectingLineInfo_.nSteelTubeDiameter = _nSteelTubeDiameter; + double _nCutPrecision = pCadObject_->GetKey_DBL(c_szINTERSECT_CUTPRECISION); + if (IsInvalidDouble(_nCutPrecision)) + IntersectingLineInfo_.nCutPrecision = -1; + else + IntersectingLineInfo_.nCutPrecision = _nCutPrecision; + + // 没有设置相贯线 卢伟 2011-12-28 + if (IntersectingLineInfo_.nAxis == axis::none || DOUBLE_EQU_ZERO(IntersectingLineInfo_.nSteelTubeDiameter) || + DOUBLE_EQU_ZERO(IntersectingLineInfo_.nCutPrecision)) + return false; + + return true; +} + +CCadObject* CIntersectingLineDoer::DoIntersecting(IN const CCadObject* pCadObject_) +{ + if (!pCadObject_) + { + ASSERT(FALSE); + return NULL; + } + + IntersectingLineInfo _IntersectingLineInfo; + // 不存在相贯线数据,则不需要重新计算 卢伟 2011-12-21 + if (!GetIntersectingInfofromCad(pCadObject_, _IntersectingLineInfo)) + { + return NULL; + } + + CIntersectingLinePath* _pIntersectingLinePathSour = + TranslateCad2IntersectingPath(pCadObject_, _IntersectingLineInfo); + if (!_pIntersectingLinePathSour) + { + ASSERT(FALSE); + return NULL; + } + + CIntersectingLineCore* _pIntersectingLineCore = NULL; + if (_IntersectingLineInfo.nAxis == axis::x) + _pIntersectingLineCore = new CIntersectingLineCore_X; + else if (_IntersectingLineInfo.nAxis == axis::y) + _pIntersectingLineCore = new CIntersectingLineCore_Y; + else + { + if (_pIntersectingLinePathSour) + { + delete _pIntersectingLinePathSour; + _pIntersectingLinePathSour = NULL; + } + ASSERT(FALSE); + return NULL; + } + + CCadObject* _pCadObject = NULL; + //此处需要更新相贯线数据中的段号和段比例 卢伟 2011-12-21 + CIntersectingLinePath* _pIntersectingLinePathDest = NULL; + if (_pIntersectingLineCore && + _pIntersectingLineCore->Initialze(&_IntersectingLineInfo) && + _pIntersectingLineCore->DoIntersectingLine(_pIntersectingLinePathSour, + &_pIntersectingLinePathDest)) + { + if (_pIntersectingLinePathDest) + { + _pCadObject = TranslateIntersectingPath2Cad(_pIntersectingLinePathDest); + _pCadObject->SetParamIndex(pCadObject_->GetParamIndex()); + } + } + + if (_pIntersectingLinePathSour) + { + delete _pIntersectingLinePathSour; + _pIntersectingLinePathSour; + } + + if (_pIntersectingLineCore) + { + delete _pIntersectingLineCore; + _pIntersectingLineCore = NULL; + } + + return _pCadObject; +} + +//////////////////////////////////////////////////////////////////////////////// +// Functions for Version 2 ---- 杨开锦 2012-08-31 +// +#include "IntersectingLine.h" +#ifdef _DEBUG + #pragma comment(lib, "IntersectingLineSd.lib") +#else + #pragma comment(lib, "IntersectingLineS.lib") +#endif + +CCadObject* CIntersectingLineDoer::GetIntersectingLine(const IntersectingInfo* pInfo_) +{ + if (!pInfo_ || pInfo_->nSize < sizeof(IntersectingInfo)) + { + return NULL; + } + + if (pInfo_->nType == IntersectingInfo::CircleCut) + { + return _GetIntersectingLine_1((IntersectingInfo_1*)pInfo_); + } + else if (pInfo_->nType == IntersectingInfo::PrimerCircleCut) + { + return _GetIntersectingLine_2((IntersectingInfo_2*)pInfo_); + } + else if (pInfo_->nType == IntersectingInfo::AuxiliaryCircleCut) + { + return _GetIntersectingLine_3((IntersectingInfo_3*)pInfo_); + } + else if (pInfo_->nType == IntersectingInfo::PrimerRectCut) + { + return _GetIntersectingLine_4((IntersectingInfo_4*)pInfo_); + } + else if (pInfo_->nType == IntersectingInfo::PrimerSymmetricCut) + { + return _GetIntersectingLine_5((IntersectingInfo_2*)pInfo_); + } + else if (pInfo_->nType == IntersectingInfo::RectCut) + { + return _GetIntersectingLine_6((IntersectingInfo_6*)pInfo_); + } + else if (pInfo_->nType == IntersectingInfo::EllipseCut) + { + return _GetIntersectingLine_7((IntersectingInfo_7*)pInfo_); + } + else + { + return NULL; + } +} + +CCadObject* CIntersectingLineDoer::_GetIntersectingLine_1(const IntersectingInfo_1* pInfo_) +{ + if (!pInfo_ || pInfo_->nSize != sizeof(IntersectingInfo_1) || pInfo_->nType != 1 + || (pInfo_->nAxis != 'X' && pInfo_->nAxis != 'Y') + || pInfo_->nRadius <= 0 + || pInfo_->nAngle <= 0 || 180 <= pInfo_->nAngle + || pInfo_->nPrecision < 0) + { + ASSERT(FALSE); + return NULL; + } + + // 生成一根直投影切断圆管的直线 ---- 杨开锦 2012-08-31 + intersecting::CPolyline _Polyline; + if (pInfo_->nAxis == 'X') + { + _Polyline.m_nStartX = DOUBLE_EQU(pInfo_->nAngle, 90) ? 0 : -1 * pInfo_->nRadius / tan(pInfo_->nAngle * c_nPIE / 180); + _Polyline.m_nStartY = -1 * pInfo_->nRadius; + _Polyline.m_vectorNodes.push_back(intersecting::CPolyline::NODE( + DOUBLE_EQU(pInfo_->nAngle, 90) ? 0 : pInfo_->nRadius / tan(pInfo_->nAngle * c_nPIE / 180), + pInfo_->nRadius)); + } + else + { + _Polyline.m_nStartX = -1 * pInfo_->nRadius; + _Polyline.m_nStartY = DOUBLE_EQU(pInfo_->nAngle, 90) ? 0 : -1 * pInfo_->nRadius / tan(pInfo_->nAngle * c_nPIE / 180); + _Polyline.m_vectorNodes.push_back(intersecting::CPolyline::NODE( + pInfo_->nRadius, + DOUBLE_EQU(pInfo_->nAngle, 90) ? 0 : pInfo_->nRadius / tan(pInfo_->nAngle * c_nPIE / 180))); + } + + // 求相贯线 ---- 杨开锦 2012-08-31 + intersecting::InfoV1 _info; + memset(&_info, 0, sizeof(intersecting::InfoV1)); + _info.nSize = sizeof(intersecting::InfoV1); + _info.nVersion = 'V1'; + _info.nAxis = 0x80000000 | pInfo_->nAxis; + _info.nRadius = pInfo_->nRadius; + _info.nProjectAngle = 90; + _info.nPrecision = min(max(2e-9, pInfo_->nPrecision), pInfo_->nRadius / 10) / 2; + intersecting::CPolyline _PolylineOut; + if (!intersecting::DoProjectPolyline(&_Polyline, &_PolylineOut, &_info)) + { + return NULL; + } + + // 组装为多义线,直投影切断的相贯曲线是轴对称的 ---- 杨开锦 2012-08-31 + ASSERT(_PolylineOut.m_vectorNodes.size() > 0); + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + _pCadPolyline->SetStartPoint(DPOINT2(_PolylineOut.m_nStartX, _PolylineOut.m_nStartY)); + for (size_t _i = 0; _i < _PolylineOut.m_vectorNodes.size(); _i++) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = _PolylineOut.m_vectorNodes[_i].nEndX; + _node.ptEnd.y = _PolylineOut.m_vectorNodes[_i].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + for (size_t _i = _PolylineOut.m_vectorNodes.size(); _i > 0; _i--) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = pInfo_->nAxis == 'X' ? _PolylineOut.m_vectorNodes[_i - 1].nEndX + : c_nPIE * pInfo_->nRadius - _PolylineOut.m_vectorNodes[_i - 1].nEndX; + _node.ptEnd.y = pInfo_->nAxis == 'Y' ? _PolylineOut.m_vectorNodes[_i - 1].nEndY + : c_nPIE * pInfo_->nRadius - _PolylineOut.m_vectorNodes[_i - 1].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + if (_PolylineOut.m_vectorNodes.size() > 0) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = pInfo_->nAxis == 'X' ? _PolylineOut.m_nStartX + : c_nPIE * pInfo_->nRadius - _PolylineOut.m_nStartX; + _node.ptEnd.y = pInfo_->nAxis == 'Y' ? _PolylineOut.m_nStartY + : c_nPIE * pInfo_->nRadius - _PolylineOut.m_nStartY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + + // 多义线段数精简 ---- 杨开锦 2012-08-31 + _ReducePolyline(_pCadPolyline, _info.nPrecision); + + return _pCadPolyline; +} + +CCadObject* CIntersectingLineDoer::_GetIntersectingLine_2(const IntersectingInfo_2* pInfo_) +{ + // 在生成对称孔时会调用到本函数,所以消除对对称孔类型的限制。 ---- 黄海燕 2013-09-28 + if (!pInfo_ || pInfo_->nSize != sizeof(IntersectingInfo_2) + || (pInfo_->nType != 2 && pInfo_->nType != 5) + || (pInfo_->nAxis != 'X' && pInfo_->nAxis != 'Y') + || pInfo_->nTrunkRadius <= 0 + || pInfo_->nBranchRadius <= 0 || pInfo_->nBranchRadius > pInfo_->nTrunkRadius + || abs(pInfo_->nEccentricLength) > pInfo_->nTrunkRadius - pInfo_->nBranchRadius + || pInfo_->nIntersectingAngle <= 0 || 180 <= pInfo_->nIntersectingAngle + || pInfo_->nPrecision < 0) + { + ASSERT(FALSE); + return NULL; + } + + // 构造一个圆 ---- 杨开锦 2012-08-31 + double _nCenterX = pInfo_->nAxis == 'X' ? 0 : pInfo_->nEccentricLength; + double _nCenterY = pInfo_->nAxis == 'Y' ? 0 : pInfo_->nEccentricLength; + double _nRaius = pInfo_->nBranchRadius; + + // 将圆分割为小线段 ---- 杨开锦 2012-09-15 + double _nPrecision = min(max(2e-9, pInfo_->nPrecision), pInfo_->nTrunkRadius / 10) / 2; + double _nAngleStep = min(max(1e-9, _nPrecision), c_nPIE / 180.0) / _nRaius; + int _nSteps = (int)(2.0 * c_nPIE / _nAngleStep + 0.5); + _nAngleStep = 2.0 * c_nPIE / _nSteps; + intersecting::CPolyline _Polyline; + _Polyline.m_nStartX = _nCenterX + _nRaius * cos(0.0); + _Polyline.m_nStartY = _nCenterY + _nRaius * sin(0.0); + for (int _i = 1; _i <= _nSteps; _i++) + { + intersecting::CPolyline::NODE _node; + _node.nEndX = _nCenterX + _nRaius * cos(_nAngleStep * _i); + _node.nEndY = _nCenterY + _nRaius * sin(_nAngleStep * _i); + _Polyline.m_vectorNodes.push_back(_node); + } + + // 求相贯线 ---- 杨开锦 2012-08-31 + intersecting::InfoV1 _info; + memset(&_info, 0, sizeof(intersecting::InfoV1)); + _info.nSize = sizeof(intersecting::InfoV1); + _info.nVersion = 'V1'; + _info.nAxis = 0x80000000 | pInfo_->nAxis; + _info.nRadius = pInfo_->nTrunkRadius; + _info.nProjectAngle = pInfo_->nIntersectingAngle; + _info.nPrecision = _nPrecision * 10; // 不使用内部的精度控制 + intersecting::CPolyline _PolylineOut; + if (!intersecting::DoProjectPolyline(&_Polyline, &_PolylineOut, &_info)) + { + return NULL; + } + + // 组装为多义线 ---- 杨开锦 2012-08-31 + ASSERT(_PolylineOut.m_vectorNodes.size() > 0); + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + _pCadPolyline->SetStartPoint(DPOINT2(_PolylineOut.m_nStartX, _PolylineOut.m_nStartY)); + for (size_t _i = 0; _i < _PolylineOut.m_vectorNodes.size(); _i++) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = _PolylineOut.m_vectorNodes[_i].nEndX; + _node.ptEnd.y = _PolylineOut.m_vectorNodes[_i].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + + // 多义线段数精简 ---- 杨开锦 2012-08-31 + _ReducePolyline(_pCadPolyline, _nPrecision); + + // 这应该是一个封闭图形 ---- 杨开锦 2012-09-03 + ASSERT(DOUBLE_EQU(_pCadPolyline->GetStartPoint().x, _pCadPolyline->GetEndPoint().x) + && DOUBLE_EQU(_pCadPolyline->GetStartPoint().y, _pCadPolyline->GetEndPoint().y)); + _pCadPolyline->SetClosed(true); + + return _pCadPolyline; +} + +CCadObject* CIntersectingLineDoer::_GetIntersectingLine_3(const IntersectingInfo_3* pInfo_) +{ + if (!pInfo_ || pInfo_->nSize != sizeof(IntersectingInfo_3) || pInfo_->nType != 3 + || (pInfo_->nAxis != 'X' && pInfo_->nAxis != 'Y') + || pInfo_->nTrunkRadius <= 0 + || pInfo_->nBranchRadius <= 0 || pInfo_->nBranchRadius > pInfo_->nTrunkRadius + || abs(pInfo_->nEccentricLength) > pInfo_->nTrunkRadius - pInfo_->nBranchRadius + || pInfo_->nIntersectingAngle <= 0 || 180 <= pInfo_->nIntersectingAngle + || pInfo_->nPrecision < 0) + { + ASSERT(FALSE); + return NULL; + } + + // 在主管上截取一段圆弧 ---- 杨开锦 2012-09-03 + double _nStartAngle = asin(-1 * (pInfo_->nEccentricLength + pInfo_->nBranchRadius) / pInfo_->nTrunkRadius); + double _nEndAngle = asin(-1 * (pInfo_->nEccentricLength - pInfo_->nBranchRadius) / pInfo_->nTrunkRadius); + if (pInfo_->nAxis == 'Y') + { + _nStartAngle += c_nPIE / 2.0; + _nEndAngle += c_nPIE / 2.0; + } + ASSERT(_nEndAngle > _nStartAngle); + if (_nStartAngle < 0.0) + { + _nStartAngle += 2.0 * c_nPIE; + _nEndAngle += 2.0 * c_nPIE; + } + + CCadArc _Arc; + _Arc.SetCenterPoint(DPOINT2(0.0, 0.0)); + _Arc.SetRadius(pInfo_->nTrunkRadius); + _Arc.SetStartAngle(_nStartAngle); + _Arc.SetCentralAngle(_nEndAngle - _nStartAngle); + DPOINT2 _ptCenter = (_Arc.GetStartPoint() + _Arc.GetEndPoint()) / 2.0; + TranslateCadObject(&_Arc, _ptCenter * -1); + if (pInfo_->nAxis == 'Y') + { + _Arc.ReverseDir(); + } + + // 将圆弧分割为小线段 ---- 杨开锦 2012-09-15 + double _nPrecision = min(max(2e-9, pInfo_->nPrecision), pInfo_->nBranchRadius / 10) / 2; + double _nAngleStep = min(max(1e-9, _nPrecision), c_nPIE / 180.0) / _Arc.GetRadius(); + int _nSteps = (int)(_Arc.GetCentralAngle() / _nAngleStep + 0.5); + _nAngleStep = _Arc.GetCentralAngle() / _nSteps; + intersecting::CPolyline _Polyline1; // 前切割线 + _Polyline1.m_nStartX = _Arc.GetStartPoint().x; + _Polyline1.m_nStartY = _Arc.GetStartPoint().y; + __CUT(pInfo_->nAxis == 'X' ? _Polyline1.m_nStartY : _Polyline1.m_nStartX, -1 * pInfo_->nBranchRadius, pInfo_->nBranchRadius); + for (int _i = 1; _i <= _nSteps; _i++) + { + intersecting::CPolyline::NODE _node; + DPOINT2 _pt = _Arc.GetPoint(_i * _nAngleStep); + _node.nEndX = _pt.x; + _node.nEndY = _pt.y; + __CUT(pInfo_->nAxis == 'X' ? _node.nEndY : _node.nEndX, -1 * pInfo_->nBranchRadius, pInfo_->nBranchRadius); + _Polyline1.m_vectorNodes.push_back(_node); + } + _Arc.ReverseDir(); + intersecting::CPolyline _Polyline2; // 后切割线 + _Polyline2.m_nStartX = _Arc.GetStartPoint().x; + _Polyline2.m_nStartY = _Arc.GetStartPoint().y; + __CUT(pInfo_->nAxis == 'X' ? _Polyline2.m_nStartY : _Polyline2.m_nStartX, -1 * pInfo_->nBranchRadius, pInfo_->nBranchRadius); + for (int _i = 1; _i <= _nSteps; _i++) + { + intersecting::CPolyline::NODE _node; + DPOINT2 _pt = _Arc.GetPoint(_i * _nAngleStep); + _node.nEndX = _pt.x; + _node.nEndY = _pt.y; + __CUT(pInfo_->nAxis == 'X' ? _node.nEndY : _node.nEndX, -1 * pInfo_->nBranchRadius, pInfo_->nBranchRadius); + _Polyline2.m_vectorNodes.push_back(_node); + } + + // 求相贯线 ---- 杨开锦 2012-09-03 + intersecting::InfoV1 _info; + memset(&_info, 0, sizeof(intersecting::InfoV1)); + _info.nSize = sizeof(intersecting::InfoV1); + _info.nVersion = 'V1'; + _info.nAxis = 0x80000000 | pInfo_->nAxis; + _info.nRadius = pInfo_->nBranchRadius; + _info.nProjectAngle = pInfo_->nIntersectingAngle; + _info.nPrecision = _nPrecision * 10.0; // 不使用内部的精度控制 + intersecting::CPolyline _PolylineOut1; + if (!intersecting::DoProjectPolyline(&_Polyline1, &_PolylineOut1, &_info)) + { + return NULL; + } + intersecting::CPolyline _PolylineOut2; + _info.nProjectAngle = 180 - _info.nProjectAngle; + if (!intersecting::DoProjectPolyline(&_Polyline2, &_PolylineOut2, &_info)) + { + return NULL; + } + + // 组装为多义线 ---- 杨开锦 2012-09-03 + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + ASSERT(_PolylineOut1.m_vectorNodes.size() > 0); + _pCadPolyline->SetStartPoint(DPOINT2(_PolylineOut1.m_nStartX, _PolylineOut1.m_nStartY)); + for (size_t _i = 0; _i < _PolylineOut1.m_vectorNodes.size(); _i++) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = _PolylineOut1.m_vectorNodes[_i].nEndX; + _node.ptEnd.y = _PolylineOut1.m_vectorNodes[_i].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + ASSERT(_PolylineOut2.m_vectorNodes.size() > 0); + ASSERT(DOUBLE_EQU(_pCadPolyline->GetEndPoint().x, _PolylineOut2.m_nStartX) + && DOUBLE_EQU(_pCadPolyline->GetEndPoint().y, _PolylineOut2.m_nStartY)); + for (size_t _i = 1; _i < _PolylineOut2.m_vectorNodes.size(); _i++) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = pInfo_->nAxis == 'X' ? _PolylineOut2.m_vectorNodes[_i].nEndX + : c_nPIE * pInfo_->nBranchRadius - _PolylineOut2.m_vectorNodes[_i].nEndX; + _node.ptEnd.y = pInfo_->nAxis == 'Y' ? _PolylineOut2.m_vectorNodes[_i].nEndY + : c_nPIE * pInfo_->nBranchRadius - _PolylineOut2.m_vectorNodes[_i].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + + // 多义线段数精简 ---- 杨开锦 2012-09-03 + _ReducePolyline(_pCadPolyline, _nPrecision); + + return _pCadPolyline; +} + +CCadObject* CIntersectingLineDoer::_GetIntersectingLine_4(const IntersectingInfo_4* pInfo_) +{ + // 允许用户切长或是宽比主管直径大的孔,偏心距范围为正负主管半径减去较短边的一半 ---- 黄海燕 2013-07-25 + double _nRange = pInfo_->nTrunkRadius - min(pInfo_->nLength, pInfo_->nWidth) / 2.0; + ASSERT(_nRange >= 0.0); + if (!pInfo_ || pInfo_->nSize != sizeof(IntersectingInfo_4) || pInfo_->nType != 4 + || (pInfo_->nAxis != 'X' && pInfo_->nAxis != 'Y') + || pInfo_->nTrunkRadius <= 0 + || pInfo_->nLength <= 0 + || pInfo_->nWidth <= 0 + || pInfo_->nTiltedAngle > c_nPIE + || pInfo_->nTiltedAngle < 0.0 + || abs(pInfo_->nEccentricLength) > _nRange + || pInfo_->nIntersectingAngle <= 0 + || pInfo_->nIntersectingAngle >= 180 + || pInfo_->nPrecision < 0) + { + ASSERT(FALSE); + return NULL; + } + + // 确定矩形中心点,即两条对角线的交点 ---- 黄海燕 2013-07-03 + double _nRectCenterX = pInfo_->nAxis == 'X' ? 0 : pInfo_->nEccentricLength; + double _nRectCenterY = pInfo_->nAxis == 'Y' ? 0 : pInfo_->nEccentricLength; + + // 根据中心点坐标计算矩形左下角点坐标,并与长、宽、倾斜角构造矩形 ---- 黄海燕 2013-07-03 + double _nDiagonalLineLen = sqrt(pInfo_->nLength * pInfo_->nLength + pInfo_->nWidth * pInfo_->nWidth); + double _nSideAngle = pInfo_->nAxis == 'X' ? asin(pInfo_->nWidth / _nDiagonalLineLen) : asin(pInfo_->nLength / _nDiagonalLineLen); + double _nLeftPointAngle = c_nPIE + pInfo_->nTiltedAngle + _nSideAngle; // 矩形左下角点与X轴的夹角 + DPOINT2 _ptFirstPoint; + _ptFirstPoint.x = _nRectCenterX + _nDiagonalLineLen * cos(_nLeftPointAngle) / 2.0; // 第一个点 + _ptFirstPoint.y = _nRectCenterY + _nDiagonalLineLen * sin(_nLeftPointAngle) / 2.0; + CCadRectangle _rect(_ptFirstPoint, pInfo_->nLength, pInfo_->nWidth, pInfo_->nTiltedAngle);// 构造矩形 + if (pInfo_->nAxis == 'Y') + { + _rect.SetWidth(pInfo_->nWidth); + _rect.SetHeight(pInfo_->nLength); + } + + // 将矩形分割成小线段 ---- 黄海燕 2013-07-03 + intersecting::CPolyline _Polyline; + for (int _i = 0; _i < 4; _i++) + { + DPOINT2 _pt = _rect.GetVertex((_i + 1) % 4); + _pt.x = pInfo_->nAxis == 'Y' ? min(max(-1.0 * pInfo_->nTrunkRadius, _pt.x), pInfo_->nTrunkRadius) : _pt.x; + _pt.y = pInfo_->nAxis == 'X' ? min(max(-1.0 * pInfo_->nTrunkRadius, _pt.y), pInfo_->nTrunkRadius) : _pt.y; + _Polyline.m_vectorNodes.push_back(intersecting::CPolyline::NODE(_pt.x, _pt.y)); + } + _Polyline.m_nStartX = _Polyline.m_vectorNodes.back().nEndX; + _Polyline.m_nStartY = _Polyline.m_vectorNodes.back().nEndY; + + // 求相贯线 ---- 黄海燕 2013-07-03 + intersecting::InfoV1 _info; + memset(&_info, 0, sizeof(intersecting::InfoV1)); + _info.nSize = sizeof(intersecting::InfoV1); + _info.nVersion = 'V1'; + _info.nAxis = 0x80000000 | pInfo_->nAxis; + _info.nRadius = pInfo_->nTrunkRadius; + _info.nProjectAngle = pInfo_->nIntersectingAngle; + _info.nPrecision = max(1e-9, pInfo_->nPrecision / 2.0); + intersecting::CPolyline _PolylineOut; + if (!intersecting::DoProjectPolyline(&_Polyline, &_PolylineOut, &_info)) + { + return NULL; + } + + // 组装成多义线 ---- 黄海燕 2013-07-03 + ASSERT(_PolylineOut.m_vectorNodes.size() > 0); + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + _pCadPolyline->SetStartPoint(DPOINT2(_PolylineOut.m_nStartX, _PolylineOut.m_nStartY)); + for (size_t _i = 0; _i < _PolylineOut.m_vectorNodes.size(); _i++) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = _PolylineOut.m_vectorNodes[_i].nEndX; + _node.ptEnd.y = _PolylineOut.m_vectorNodes[_i].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + ASSERT(_pCadPolyline->GetNodeCount() > 0); + + // 多义线段数精简 ---- 黄海燕 2013-07-03 + _ReducePolyline(_pCadPolyline, max(1e-9, pInfo_->nPrecision / 2.0)); + + // 生成的图形应为一个封闭图形 ---- 黄海燕 2013-07-03 + ASSERT(DOUBLE_EQU(_pCadPolyline->GetStartPoint().x, _pCadPolyline->GetEndPoint().x) + && DOUBLE_EQU(_pCadPolyline->GetStartPoint().y, _pCadPolyline->GetEndPoint().y)); + _pCadPolyline->SetClosed(true); + + return _pCadPolyline; +} + +CCadObject* CIntersectingLineDoer::_GetIntersectingLine_5(const IntersectingInfo_2* pInfo_) +{ + // step1:生成第一个孔。 + CCadObject* _pFirstHole = _GetIntersectingLine_2(pInfo_); + ASSERT(_pFirstHole); + + // step2:生成第二个孔。 + // 旋转180°,取第一个孔倾斜角的补角,偏心距取反生成第二个孔。 + IntersectingInfo_2* _pInfo = const_cast(pInfo_); + _pInfo->nEccentricLength = 0.0 - _pInfo->nEccentricLength; + _pInfo->nIntersectingAngle = 180.0 - _pInfo->nIntersectingAngle; + CCadObject* _pSecondHole = _GetIntersectingLine_2(_pInfo); + ASSERT(_pSecondHole); + + DPOINT2 _vecOffset(0.0, 0.0); + if (_pInfo->nAxis == 'Y') + { + _vecOffset.x = c_nPIE * _pInfo->nTrunkRadius; + } + else + { + _vecOffset.y = c_nPIE * _pInfo->nTrunkRadius; + } + nce::TranslateCadObject(_pSecondHole, _vecOffset); + + // step3:将生成的两个Cad图形组合成一个图形。 + CCadGroup* _pCadGroup = new CCadGroup; + _pCadGroup->PushBack(_pFirstHole); + _pCadGroup->PushBack(_pSecondHole); + return _pCadGroup; +} + +CCadObject* CIntersectingLineDoer::_GetIntersectingLine_6(const IntersectingInfo_6* pInfo_) +{ + if (!pInfo_ || pInfo_->nSize != sizeof(IntersectingInfo_6) || pInfo_->nType != 6 + || (/*pInfo_->nAxis != 'X' && */pInfo_->nAxis != 'Y') + || pInfo_->nWidth < pInfo_->nHeight + || pInfo_->nHeight <= 0.0 + || pInfo_->nRadius <= 0.0 + || pInfo_->nThickness <= 0.0 + || pInfo_->nAngleAlpha <= 0.0 || 180.0 <= pInfo_->nAngleAlpha + || pInfo_->nAngleBeta != 90.0 + || pInfo_->nPrecision < 0.0 + || pInfo_->nWeldLength < 0.0) + { + ASSERT(FALSE); + return NULL; + } + + // 90度的直切也没有焊缝补偿 + if (!pInfo_->bWeld || DOUBLE_EQU(pInfo_->nAngleAlpha, 90.0)) + { + // 没有焊缝补偿 + // 生成一根从原点到方管边沿的线 ---- 杨开锦 2016-08-15 + ASSERT(pInfo_->nAxis == 'Y'); + intersecting::CPolyline _Polyline; + _Polyline.m_nStartX = 0.0; + _Polyline.m_nStartY = 0.0; + _Polyline.m_vectorNodes.push_back(intersecting::CPolyline::NODE(pInfo_->nWidth / 2.0, 0.0)); + + // 求投影线 ---- 杨开锦 2016-08-15 + intersecting::InfoV2 _info; + memset(&_info, 0, sizeof(intersecting::InfoV2)); + _info.nSize = sizeof(intersecting::InfoV2); + _info.nAxis = 0x80000000 | pInfo_->nAxis; + _info.nVersion = 'V2'; + _info.nWidth = pInfo_->nWidth; + _info.nHeight = pInfo_->nHeight; + _info.nRadius = pInfo_->nRadius; + _info.nThickness = pInfo_->nThickness; + _info.nProjectAngleAlpha = pInfo_->nAngleAlpha; + _info.nProjectAngleTheta = 0.0; // 沿主展开面切断 + _info.nPrecision = min(max(2e-9, pInfo_->nPrecision), pInfo_->nRadius / 10.0) / 2.0; + intersecting::CPolyline _PolylineOut; + if (!intersecting::DoProjectPolyline(&_Polyline, &_PolylineOut, &_info)) + { + return NULL; + } + + // 组装为多义线,只生成了1/2阳面投影,其他三份是有对称关系的 ---- 杨开锦 2016-08-15 + ASSERT(_PolylineOut.m_vectorNodes.size() > 0); + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + _pCadPolyline->SetStartPoint(DPOINT2(_PolylineOut.m_nStartX, _PolylineOut.m_nStartY)); + for (size_t _i = 0; _i < _PolylineOut.m_vectorNodes.size(); _i++) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = +1.0 * _PolylineOut.m_vectorNodes[_i].nEndX; + _node.ptEnd.y = +1.0 * _PolylineOut.m_vectorNodes[_i].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + for (size_t _i = _PolylineOut.m_vectorNodes.size(); _i > 0; _i--) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = -1.0 * _PolylineOut.m_vectorNodes[_i - 1].nEndX + (pInfo_->nWidth + pInfo_->nHeight); + _node.ptEnd.y = -1.0 * _PolylineOut.m_vectorNodes[_i - 1].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + for (size_t _i = 0; _i < _PolylineOut.m_vectorNodes.size(); _i++) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = +1.0 * _PolylineOut.m_vectorNodes[_i].nEndX + (pInfo_->nWidth + pInfo_->nHeight); + _node.ptEnd.y = -1.0 * _PolylineOut.m_vectorNodes[_i].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + for (size_t _i = _PolylineOut.m_vectorNodes.size(); _i > 0; _i--) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = -1.0 * _PolylineOut.m_vectorNodes[_i - 1].nEndX + 2.0 * (pInfo_->nWidth + pInfo_->nHeight); + _node.ptEnd.y = +1.0 * _PolylineOut.m_vectorNodes[_i - 1].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + if (_PolylineOut.m_vectorNodes.size() > 0) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = -1.0 * _PolylineOut.m_nStartX + 2.0 * (pInfo_->nWidth + pInfo_->nHeight); + _node.ptEnd.y = +1.0 * _PolylineOut.m_nStartY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + + // 多义线段数精简 ---- 杨开锦 2012-08-31 + _ReducePolyline(_pCadPolyline, max(1e-9, _info.nPrecision / 2.0)); + + return _pCadPolyline; + } + else if (pInfo_->bCurve) + { + // 曲线过棱,由以前的曲线加上两条辅助线构成 + ASSERT(!DOUBLE_EQU(pInfo_->nAngleAlpha, 90.0)); + + double _nWidth = pInfo_->nWidth; + double _nHeight = pInfo_->nHeight; + double _nArris = max(pInfo_->nRadius, pInfo_->nThickness); + double _nTan = abs(tan(pInfo_->nAngleAlpha * c_nPIE / 180)); + double _nWeldWidth = _nArris / _nTan; + double _nY = (pInfo_->nHeight - _nArris * 2.0) / _nTan; + + CCadGroup* _pCadGroup = new CCadGroup; + CCadPolyline* _pCadPolyline = new CCadPolyline; + CCadPolyline* _pCadPolylineWeldDowm1 = new CCadPolyline; + CCadPolyline* _pCadPolylineWeldDowm2 = new CCadPolyline; + CCadPolyline* _pCadPolylineWeldUp1 = new CCadPolyline; + CCadPolyline* _pCadPolylineWeldUp2 = new CCadPolyline; + ASSERT(_pCadGroup && _pCadPolyline && _pCadPolylineWeldDowm1 + && _pCadPolylineWeldDowm2 && _pCadPolylineWeldUp1 && _pCadPolylineWeldUp2); + + CCadPolyline::ARCNODE _node; + + // 原截断面 + ASSERT(pInfo_->nAxis == 'Y'); + intersecting::CPolyline _Polyline; + _Polyline.m_nStartX = 0.0; + _Polyline.m_nStartY = 0.0; + _Polyline.m_vectorNodes.push_back(intersecting::CPolyline::NODE(pInfo_->nWidth / 2.0, 0.0)); + + // 求投影线 ---- 杨开锦 2016-08-15 + intersecting::InfoV2 _info; + memset(&_info, 0, sizeof(intersecting::InfoV2)); + _info.nSize = sizeof(intersecting::InfoV2); + _info.nAxis = 0x80000000 | pInfo_->nAxis; + _info.nVersion = 'V2'; + _info.nWidth = pInfo_->nWidth; + _info.nHeight = pInfo_->nHeight; + _info.nRadius = pInfo_->nRadius; + _info.nThickness = pInfo_->nThickness; + _info.nProjectAngleAlpha = pInfo_->nAngleAlpha; + _info.nProjectAngleTheta = 0.0; // 沿主展开面切断 + _info.nPrecision = min(max(2e-9, pInfo_->nPrecision), pInfo_->nRadius / 10.0) / 2.0; + intersecting::CPolyline _PolylineOut; + if (!intersecting::DoProjectPolyline(&_Polyline, &_PolylineOut, &_info)) + { + return NULL; + } + + // 组装为多义线,只生成了1/2阳面投影,其他三份是有对称关系的 ---- 杨开锦 2016-08-15 + ASSERT(_PolylineOut.m_vectorNodes.size() > 0); + + _pCadPolyline->SetStartPoint(DPOINT2(_PolylineOut.m_nStartX, _PolylineOut.m_nStartY)); + for (size_t _i = 0; _i < _PolylineOut.m_vectorNodes.size(); _i++) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = +1.0 * _PolylineOut.m_vectorNodes[_i].nEndX; + _node.ptEnd.y = +1.0 * _PolylineOut.m_vectorNodes[_i].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + for (size_t _i = _PolylineOut.m_vectorNodes.size(); _i > 0; _i--) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = -1.0 * _PolylineOut.m_vectorNodes[_i - 1].nEndX + (pInfo_->nWidth + pInfo_->nHeight); + _node.ptEnd.y = -1.0 * _PolylineOut.m_vectorNodes[_i - 1].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + for (size_t _i = 0; _i < _PolylineOut.m_vectorNodes.size(); _i++) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = +1.0 * _PolylineOut.m_vectorNodes[_i].nEndX + (pInfo_->nWidth + pInfo_->nHeight); + _node.ptEnd.y = -1.0 * _PolylineOut.m_vectorNodes[_i].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + for (size_t _i = _PolylineOut.m_vectorNodes.size(); _i > 0; _i--) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = -1.0 * _PolylineOut.m_vectorNodes[_i - 1].nEndX + 2.0 * (pInfo_->nWidth + pInfo_->nHeight); + _node.ptEnd.y = +1.0 * _PolylineOut.m_vectorNodes[_i - 1].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + if (_PolylineOut.m_vectorNodes.size() > 0) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = -1.0 * _PolylineOut.m_nStartX + 2.0 * (pInfo_->nWidth + pInfo_->nHeight); + _node.ptEnd.y = +1.0 * _PolylineOut.m_nStartY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + + // 多义线段数精简 ---- 杨开锦 2012-08-31 + _ReducePolyline(_pCadPolyline, max(1e-9, _info.nPrecision / 2.0)); + + // 由于此处线的位置不是想要的需要调整,故把补偿线也移动到此处再整体平移 ---- 吴畏 2017-01-11 + double _nBottom = _pCadPolyline->GetBoundRect().GetBottom(); + double _nTop = _pCadPolyline->GetBoundRect().GetTop(); + + // 下方补偿线1 + _pCadPolylineWeldDowm1->SetStartPoint(DPOINT2(_nWidth + _nHeight, _nTop - _nWeldWidth)); + _node.ptEnd.x = _nWidth / 2.0 + _nHeight - _nArris; + _node.ptEnd.y = _nTop - _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolylineWeldDowm1->GetNodes()->push_back(_node); + // 下方补偿线2 + _pCadPolylineWeldDowm2->SetStartPoint(DPOINT2(_nWidth + _nHeight, _nTop - _nWeldWidth)); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight + _nArris; + _node.ptEnd.y = _nTop - _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolylineWeldDowm2->GetNodes()->push_back(_node); + + // 上方补偿线1 + _pCadPolylineWeldUp1->SetStartPoint(DPOINT2(_nWidth * 2.0 + _nHeight * 2.0, _nBottom + _nWeldWidth)); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight * 2.0 - _nArris; + _node.ptEnd.y = _nBottom + _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolylineWeldUp1->GetNodes()->push_back(_node); + + // 上方补偿线2 + _pCadPolylineWeldUp2->SetStartPoint(DPOINT2(0.0, _nBottom + _nWeldWidth)); + _node.ptEnd.x = _nWidth / 2.0 + _nArris; + _node.ptEnd.y = _nBottom + _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolylineWeldUp2->GetNodes()->push_back(_node); + + _pCadGroup->PushBack(_pCadPolylineWeldDowm1); + _pCadGroup->PushBack(_pCadPolylineWeldDowm2); + _pCadGroup->PushBack(_pCadPolyline); + _pCadGroup->PushBack(_pCadPolylineWeldUp1); + _pCadGroup->PushBack(_pCadPolylineWeldUp2); + + return _pCadGroup; + } + else if (DOUBLE_EQU_ZERO(pInfo_->nWeldLength)) + { + // 需要焊缝补偿,缝间距为0 + double _nOverlength = pInfo_->nWeldOverCut; // 为了避免平着切管壁的过切 + double _nWidth = pInfo_->nWidth; + double _nHeight = pInfo_->nHeight; + double _nArris = max(pInfo_->nRadius, pInfo_->nThickness); + double _nTan = abs(tan(pInfo_->nAngleAlpha * c_nPIE / 180)); + double _nWeldWidth = _nArris / _nTan; + double _nY = (pInfo_->nHeight - _nArris * 2.0) / _nTan; + + CCadGroup* _pCadGroup = new CCadGroup; + CCadPolyline* _pCadPolyline = new CCadPolyline; + CCadPolyline* _pCadPolylineWeldDowm1 = new CCadPolyline; + CCadPolyline* _pCadPolylineWeldDowm2 = new CCadPolyline; + CCadPolyline* _pCadPolylineWeldUp1 = new CCadPolyline; + CCadPolyline* _pCadPolylineWeldUp2 = new CCadPolyline; + ASSERT(_pCadGroup && _pCadPolyline && _pCadPolylineWeldDowm1 + && _pCadPolylineWeldDowm2 && _pCadPolylineWeldUp1 && _pCadPolylineWeldUp2); + + CCadPolyline::ARCNODE _node; + + // 下方补偿线1 + _pCadPolylineWeldDowm1->SetStartPoint(DPOINT2(_nWidth + _nHeight, _nY + _nWeldWidth)); + _node.ptEnd.x = _nWidth / 2.0 + _nHeight - _nArris - _nOverlength; + _node.ptEnd.y = _nY + _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolylineWeldDowm1->GetNodes()->push_back(_node); + // 下方补偿线2 + _pCadPolylineWeldDowm2->SetStartPoint(DPOINT2(_nWidth + _nHeight, _nY + _nWeldWidth)); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight + _nArris + _nOverlength; + _node.ptEnd.y = _nY + _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolylineWeldDowm2->GetNodes()->push_back(_node); + + // 上方补偿线1 + _pCadPolylineWeldUp1->SetStartPoint(DPOINT2(_nWidth * 2.0 + _nHeight * 2.0, _nWeldWidth)); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight * 2.0 - _nArris - _nOverlength; + _node.ptEnd.y = _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolylineWeldUp1->GetNodes()->push_back(_node); + + // 上方补偿线2 + _pCadPolylineWeldUp2->SetStartPoint(DPOINT2(0.0, _nWeldWidth)); + _node.ptEnd.x = _nWidth / 2.0 + _nArris + _nOverlength; + _node.ptEnd.y = _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolylineWeldUp2->GetNodes()->push_back(_node); + + _pCadPolyline->SetStartPoint(DPOINT2(0.0, 0.0)); + _node.ptEnd.x = _nWidth / 2.0 + _nArris + _nOverlength; + _node.ptEnd.y = 0.0; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth / 2.0 + _nArris + _nOverlength; + _node.ptEnd.y = _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth / 2.0 + _nHeight - _nArris - _nOverlength; + _node.ptEnd.y = _nY + _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth / 2.0 + _nHeight - _nArris - _nOverlength; + _node.ptEnd.y = _nY + _nWeldWidth * 2.0; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight + _nArris + _nOverlength; + _node.ptEnd.y = _nY + _nWeldWidth * 2.0; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight + _nArris + _nOverlength; + _node.ptEnd.y = _nY + _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight * 2.0 - _nArris - _nOverlength; + _node.ptEnd.y = _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight * 2.0 - _nArris - _nOverlength; + _node.ptEnd.y = 0.0; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 2.0 + _nHeight * 2.0; + _node.ptEnd.y = 0.0; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + + _pCadGroup->PushBack(_pCadPolylineWeldDowm1); + _pCadGroup->PushBack(_pCadPolylineWeldDowm2); + _pCadGroup->PushBack(_pCadPolyline); + _pCadGroup->PushBack(_pCadPolylineWeldUp1); + _pCadGroup->PushBack(_pCadPolylineWeldUp2); + + return _pCadGroup; + } + else + { + // 需要焊缝补偿,缝间距不为0的时候,是两个环 + ASSERT(!DOUBLE_EQU(pInfo_->nAngleAlpha, 90.0)); + + double _nOverlength = pInfo_->nWeldOverCut; // 为了避免平着切管壁的过切 + double _nWidth = pInfo_->nWidth; + double _nHeight = pInfo_->nHeight; + double _nArris = max(pInfo_->nRadius, pInfo_->nThickness); + double _nTan = abs(tan(pInfo_->nAngleAlpha * c_nPIE / 180)); + double _nWeldWidth = _nArris / _nTan; + double _nWeldLength = pInfo_->nWeldLength; + double _nY = (pInfo_->nHeight - _nArris * 2.0) / _nTan; + + CCadGroup* _pCadGroup = new CCadGroup; + CCadPolyline* _pCadPolyline1 = new CCadPolyline; + CCadPolyline* _pCadPolyline2 = new CCadPolyline; + ASSERT(_pCadPolyline1 && _pCadPolyline2); + + CCadPolyline::ARCNODE _node; + + _pCadPolyline1->SetStartPoint(DPOINT2(0.0, 0.0)); + _node.ptEnd.x = _nWidth * 0.5 + _nArris + _nOverlength; + _node.ptEnd.y = 0; + _node.nBulge = 0.0; + _pCadPolyline1->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 0.5 + _nArris + _nOverlength; + _node.ptEnd.y = _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolyline1->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 0.5 + _nHeight - _nArris - _nOverlength; + _node.ptEnd.y = _nWeldWidth + _nY; + _node.nBulge = 0.0; + _pCadPolyline1->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight + _nArris + _nOverlength; + _node.ptEnd.y = _nWeldWidth + _nY; + _node.nBulge = 0.0; + _pCadPolyline1->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight * 2.0 - _nArris - _nOverlength; + _node.ptEnd.y = _nWeldWidth; + _node.nBulge = 0.0; + _pCadPolyline1->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight * 2.0 - _nArris - _nOverlength; + _node.ptEnd.y = 0; + _node.nBulge = 0.0; + _pCadPolyline1->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 2.0 + _nHeight * 2.0; + _node.ptEnd.y = 0; + _node.nBulge = 0.0; + _pCadPolyline1->GetNodes()->push_back(_node); + + _pCadPolyline2->SetStartPoint(DPOINT2(0.0, _nWeldWidth + _nWeldLength)); + _node.ptEnd.x = _nWidth * 0.5 + _nArris + _nOverlength; + _node.ptEnd.y = _nWeldWidth + _nWeldLength; + _node.nBulge = 0.0; + _pCadPolyline2->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 0.5 + _nHeight - _nArris - _nOverlength; + _node.ptEnd.y = _nWeldWidth + _nY + _nWeldLength; + _node.nBulge = 0.0; + _pCadPolyline2->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 0.5 + _nHeight - _nArris - _nOverlength; + _node.ptEnd.y = _nWeldWidth * 2.0+ _nY + _nWeldLength; + _node.nBulge = 0.0; + _pCadPolyline2->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight + _nArris + _nOverlength; + _node.ptEnd.y = _nWeldWidth * 2.0+ _nY + _nWeldLength; + _node.nBulge = 0.0; + _pCadPolyline2->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight + _nArris + _nOverlength; + _node.ptEnd.y = _nWeldWidth + _nY + _nWeldLength; + _node.nBulge = 0.0; + _pCadPolyline2->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 1.5 + _nHeight * 2.0 - _nArris - _nOverlength; + _node.ptEnd.y = _nWeldWidth + _nWeldLength; + _node.nBulge = 0.0; + _pCadPolyline2->GetNodes()->push_back(_node); + _node.ptEnd.x = _nWidth * 2.0 + _nHeight * 2.0; + _node.ptEnd.y = _nWeldWidth + _nWeldLength; + _node.nBulge = 0.0; + _pCadPolyline2->GetNodes()->push_back(_node); + + _pCadGroup->PushBack(_pCadPolyline1); + _pCadGroup->PushBack(_pCadPolyline2); + + return _pCadGroup; + } +} + + +CCadObject* CIntersectingLineDoer::_GetIntersectingLine_7(const IntersectingInfo_7* pInfo_) +{ + if (!pInfo_ || pInfo_->nSize != sizeof(IntersectingInfo_7) || pInfo_->nType != IntersectingInfo::EllipseCut + || (pInfo_->nAxis != 'Y') + || pInfo_->nShortRadius > pInfo_->nLongRadius + || pInfo_->nAngleAlpha <= 0.0 || 180.0 <= pInfo_->nAngleAlpha + || pInfo_->nPrecision < 0.0) + { + ASSERT(FALSE); + return NULL; + } + + ASSERT(pInfo_->nAxis == 'Y'); + double _nCutHeight = pInfo_->nShortRadius / tan(pInfo_->nAngleAlpha / 180 * c_nPIE); + intersecting::CPolyline _Polyline; + _Polyline.m_nStartX = -pInfo_->nShortRadius; + _Polyline.m_nStartY = -_nCutHeight; + _Polyline.m_vectorNodes.push_back(intersecting::CPolyline::NODE(pInfo_->nShortRadius, _nCutHeight)); + + // 求投影线 ---- 彭朋 2017-01-20 + intersecting::InfoV3 _info; + memset(&_info, 0, sizeof(intersecting::InfoV3)); + _info.nSize = sizeof(intersecting::InfoV3); + _info.nAxis = 0x80000000 | pInfo_->nAxis; + _info.nVersion = 'V3'; + _info.nLongRadius = pInfo_->nLongRadius; + _info.nShortRadius = pInfo_->nShortRadius; + _info.nProjectAngleAlpha = 90; + _info.nProjectAngleTheta = 90; + _info.nPrecision = min(max(2e-9, pInfo_->nPrecision), pInfo_->nShortRadius / 200) / 2.0; + intersecting::CPolyline _PolylineOut; + if (!intersecting::DoProjectPolyline(&_Polyline, &_PolylineOut, &_info)) + { + return NULL; + } + + //得到一半 + ASSERT(_PolylineOut.m_vectorNodes.size() > 0); + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + _pCadPolyline->SetStartPoint(DPOINT2(_PolylineOut.m_nStartX, _PolylineOut.m_nStartY)); + for (size_t _i = 0; _i < _PolylineOut.m_vectorNodes.size(); _i++) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = +1.0 * _PolylineOut.m_vectorNodes[_i].nEndX; + _node.ptEnd.y = +1.0 * _PolylineOut.m_vectorNodes[_i].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + + //得到对称的一半 + double _nEllipsePerimeter = _GetEllipsePerimeter(pInfo_->nLongRadius, pInfo_->nShortRadius); + double _nEllipsePerimeter_2 = _nEllipsePerimeter / 2; + for (size_t _i = _PolylineOut.m_vectorNodes.size(); _i > 0; _i--) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = pInfo_->nAxis == 'X' ? _PolylineOut.m_vectorNodes[_i - 1].nEndX + : _nEllipsePerimeter - _PolylineOut.m_vectorNodes[_i - 1].nEndX; + _node.ptEnd.y = pInfo_->nAxis == 'Y' ? _PolylineOut.m_vectorNodes[_i - 1].nEndY + : _nEllipsePerimeter - _PolylineOut.m_vectorNodes[_i - 1].nEndY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + if (_PolylineOut.m_vectorNodes.size() > 0) + { + CCadPolyline::ARCNODE _node; + _node.ptEnd.x = pInfo_->nAxis == 'X' ? _PolylineOut.m_nStartX + : _nEllipsePerimeter - _PolylineOut.m_nStartX; + _node.ptEnd.y = pInfo_->nAxis == 'Y' ? _PolylineOut.m_nStartY + : _nEllipsePerimeter - _PolylineOut.m_nStartY; + _node.nBulge = 0.0; + _pCadPolyline->GetNodes()->push_back(_node); + } + // 多义线段数精简 ---- 彭朋 2017-01-20 + _ReducePolyline(_pCadPolyline, max(1e-9, _info.nPrecision / 2.0)); + + // 除去长度为0的线段。 + double _nx = _pCadPolyline->GetStartPoint().x, _ny = _pCadPolyline->GetStartPoint().y; + for (size_t _i = 0; _i < _pCadPolyline->GetNodes()->size(); _i++) + { + CCadPolyline::ARCNODE& _node = (*_pCadPolyline->GetNodes())[_i]; + if (DOUBLE_EQU(_node.ptEnd.x, _nx) && DOUBLE_EQU(_node.ptEnd.y, _ny)) + { + _pCadPolyline->GetNodes()->erase(_pCadPolyline->GetNodes()->begin() + _i); + _i--; + continue; + } + _nx = _node.ptEnd.x; + _ny = _node.ptEnd.y; + } + + return _pCadPolyline; + +} + +void CIntersectingLineDoer::_ReducePolyline(CCadPolyline* pCadPolyline_, double nPrecision_) +{ + ASSERT(pCadPolyline_ && pCadPolyline_->GetNodeCount() > 0); + ASSERT(pCadPolyline_->GetNodeCount() > 0); + ASSERT(nPrecision_ >= 1e-9); + + // 产出的Node放到中转容器中 ---- 杨开锦 2012-05-05 + CCadPolyline::ArcNodeVector _vectorOutNodes; + + DPOINT2 _ptStart = pCadPolyline_->GetStartPoint(); + int _nSrcNodeCount = pCadPolyline_->GetNodeCount(); + int _nIndex = 0; + while (_nIndex < _nSrcNodeCount) + { + // 跳过圆弧段 + if (DOUBLE_NOT_ZERO(pCadPolyline_->GetAt(_nIndex).nBulge)) + { + _vectorOutNodes.push_back(pCadPolyline_->GetAt(_nIndex)); + _ptStart = _vectorOutNodes.back().ptEnd; + _nIndex++; + continue; + } + + // 收集精简段: 仅线段 + ASSERT(DOUBLE_EQU_ZERO(pCadPolyline_->GetAt(_nIndex).nBulge)); + reducer::CPolyline _Polyline; + _Polyline.m_nStartX = _ptStart.x; + _Polyline.m_nStartY = _ptStart.y; + while (_nIndex < _nSrcNodeCount + && DOUBLE_EQU_ZERO(pCadPolyline_->GetAt(_nIndex).nBulge)) + { + const DPOINT2& _ptEnd = pCadPolyline_->GetAt(_nIndex).ptEnd; + _Polyline.m_vectorNodes.push_back(reducer::CPolyline::NODE(_ptEnd.x, _ptEnd.y)); + _nIndex++; + } + + // 调用CPolylineReducer进行精简 + static const reducer::PolylineReducerParam _param = { + sizeof(reducer::PolylineReducerParam), + nPrecision_,// 长度精度 + 1.0e-1, // 角度精度:约6度 + 1.0e+9, // 最大可精简长度:无限长 + 0.5 // 最大可精简角度:约30度 + }; + reducer::CPolyline _OutPolyline; + reducer::CPolyline* _pOutPolyline = &_Polyline; + if (reducer::ReducePolyline(&_Polyline, &_OutPolyline, &_param)) + { + _pOutPolyline = &_OutPolyline; + } + + // 写入产出容器中 + ASSERT(_pOutPolyline); + for (size_t _i = 0; _i < _pOutPolyline->m_vectorNodes.size(); _i++) + { + _vectorOutNodes.push_back(CCadPolyline::ARCNODE( + DPOINT2(_pOutPolyline->m_vectorNodes[_i].nEndX, _pOutPolyline->m_vectorNodes[_i].nEndY), + 0.0)); + } + + // 添加有新段时更新下个起点 ---- 杨开锦 2012-06-27 + ASSERT(_vectorOutNodes.size() >= _pOutPolyline->m_vectorNodes.size()); + if (_pOutPolyline->m_vectorNodes.size() > 0) + { + ASSERT(_vectorOutNodes.back().ptEnd.x == _pOutPolyline->m_vectorNodes.back().nEndX + && _vectorOutNodes.back().ptEnd.y == _pOutPolyline->m_vectorNodes.back().nEndY); + _ptStart.x = _pOutPolyline->m_vectorNodes.back().nEndX; + _ptStart.y = _pOutPolyline->m_vectorNodes.back().nEndY; + } + } + + // 产出 ---- 杨开锦 2012-05-05 + CCadPolyline::ArcNodeVector* _pvectorArcNodes = pCadPolyline_->GetNodes(); + ASSERT(_pvectorArcNodes); + *_pvectorArcNodes = _vectorOutNodes; +} + +double _GetEllipsePerimeter(double nLongRadius_,double nShortRadius_) +{ + double _nEccentricity = sqrt(pow(nLongRadius_, 2) - pow(nShortRadius_, 2)) / nLongRadius_; + ASSERT((nLongRadius_ >= nShortRadius_) && DOUBLE_GREAT_ZERO(nShortRadius_)); + ASSERT((_nEccentricity >= 0.) && (_nEccentricity <= 1.0)); + if ((_nEccentricity < 0.) || (_nEccentricity > 1.0)) + { + ASSERT(false); + return 0.; + } + + // 第二类完全椭圆积分,从Matlab的ellipke.m中得到 + double m = _nEccentricity * _nEccentricity; + double a0 = 1.0; + double b0 = sqrt(1.0 - m); + double s0 = m; + int i1 = 0; + double a1 = 1.0; + double mm = 1.0; + while (mm > c_nTolerance) + { + a1 = (a0 + b0) * 0.5; + double b1 = sqrt(a0 * b0); + double c1 = (a0 - b0) * 0.5; + double w1 = (2 << i1++) * (c1 * c1); + mm = w1; + s0 += w1; + a0 = a1; + b0 = b1; + } + + double k = M_PI / (2.0 * a1); + double e = k * (1.0 - s0 * 0.5); + + // 椭圆周长 + double _nPerimeter = 4.0 * nLongRadius_ * e; + return _nPerimeter; +} diff --git a/src/Intersection.cpp b/src/Intersection.cpp new file mode 100644 index 0000000..2d6223b --- /dev/null +++ b/src/Intersection.cpp @@ -0,0 +1,3132 @@ +#include "StdAfx.h" +#include "Intersection.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +using namespace ncmath; +#define DIVIDE_BY_ZERO_GUARD 1.E-20 + +// 用几何的方法计算两条直线的交点,此函数是从V9中cvt模块中移植过来的,有疑问请咨询吴阳明 Wanglou 2010-07-30 +bool ncmath::Intersect(IN const LineD2D& line1_, IN const LineD2D& line2_, OUT DPOINT2* pptIntersect_) +{ + double x1,y1,x2,y2; // (x1,y1,x2,y2)第一条直线 + double x3,y3,x4,y4; // (x3,y3,x4,y4)第二条直线 + double x5, y5; // 交点坐标 + x1 = line1_.pt1.x; y1 = line1_.pt1.y; x2 = line1_.pt2.x; y2 = line1_.pt2.y; + x3 = line2_.pt1.x; y3 = line2_.pt1.y; x4 = line2_.pt2.x; y4 = line2_.pt2.y; + + double dvx12, dvy12; // 直线12的方向矢量 + double dvx34, dvy34; // 直线34的方向矢量 + double len12, len34; // 12和34的长度 + double uvx12, uvy12; // 直线12的单位矢 + double uvx34, uvy34; // 直线34的单位矢 + double dvx13, dvy13; // 13连线矢量 + double prj; // 13连线矢量在直线12上的投影 + double prjdvx, prjdvy; // 13连线矢量在直线12上的投影矢量 + double vvx, vvy; // 3到12的垂线矢量 + double vvl; // 垂线长度 + double factor; // 比例因子 + + dvx12 = x2 - x1; dvy12 = y2 - y1; // 12连线矢量 + dvx34 = x4 - x3; dvy34 = y4 - y3; // 34连线矢量 + + // 如果矢量积(×)为0,平行无交点 + if (DOUBLE_EQU_ZERO(dvx12 * dvy34 - dvx34 * dvy12)) + return false; + + len12 = sqrt(dvx12 * dvx12 + dvy12 * dvy12); // 12长度 + len34 = sqrt(dvx34 * dvx34 + dvy34 * dvy34); // 34长度 + + if (DOUBLE_EQU_ZERO(len12) || DOUBLE_EQU_ZERO(len34)) + return false; + + // 如果3正好落在直线12上,交点为 (x3,y3) + if (DOUBLE_EQU_ZERO((x3 - x1) * (y2 - y3) - (x2 - x3) * (y3 - y1))) + { + x5 = x3; + y5 = y3; + } + else + { + uvx12 = dvx12 / len12; uvy12 = dvy12 / len12; // 12单位矢量 + uvx34 = dvx34 / len34; uvy34 = dvy34 / len34; // 34单位矢量 + dvx13 = x3 - x1; dvy13 = y3 - y1; // 13连线矢量 + prj = dvx13 * uvx12 + dvy13 * uvy12; // 13在12上的投影 + prjdvx = prj * uvx12; prjdvy = prj * uvy12; // 13在12上的投影的矢量 + vvx = prjdvx - dvx13; vvy = prjdvy - dvy13; // 3到12的垂线矢量 + vvl = sqrt(vvx * vvx + vvy * vvy); // 3到12的垂线长度 + double nTemp = D2GetProjectionDistance(dvx34, dvy34, vvx, vvy); + if (DOUBLE_EQU_ZERO(nTemp)) + return 0; + factor = vvl / (nTemp + DIVIDE_BY_ZERO_GUARD); // 长度比例因子 + + x5 = x3 + dvx34 * factor; + y5 = y3 + dvy34 * factor; + } + + ASSERT(pptIntersect_ != NULL); + pptIntersect_->x = x5; + pptIntersect_->y = y5; + return true; +} + +namespace +{ + VectorD2D NormalizeVector(const VectorD2D& vecValue_) + { + double _nLength = vecValue_.GetLength(); + ASSERT(DOUBLE_GREAT_ZERO(_nLength)); + return VectorD2D(vecValue_.x / _nLength, vecValue_.y / _nLength); + } +} + +int ncmath::Intersect_BeelineWithBeeline(IN const DPOINT2& pt1_, + IN double nAngle1_, + IN const DPOINT2& pt2_, + IN double nAngle2_, + OUT DPOINT2* pptIntersect_ /* = NULL */) +{ + ASSERT(IsValidDouble(pt1_.x)); + ASSERT(IsValidDouble(pt1_.y)); + ASSERT(IsValidDouble(pt2_.x)); + ASSERT(IsValidDouble(pt2_.y)); + + // 另外一点取x = pt1.x + 1 --- 吴阳明 2010 09 07 + __point2 _pt11(pt1_.x, pt1_.y); + __point2 _pt12(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + + __point2 _pt21(pt2_.x, pt2_.y); + __point2 _pt22(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + + if (DOUBLE_EQU(nAngle1_, c_nPIE / 2) || DOUBLE_EQU(nAngle1_, 3 * c_nPIE / 2)) + { + _pt12 .Set(pt1_.x, pt1_.y + 1); + } + else + { + _pt12.Set(pt1_.x + 1, tan(nAngle1_) + pt1_.y); + } + + if (DOUBLE_EQU(nAngle2_, c_nPIE / 2) || DOUBLE_EQU(nAngle2_, 3 * c_nPIE / 2)) + { + _pt22.Set(pt2_.x, pt2_.y + 1); + } + else + { + _pt22.Set(pt2_.x + 1, tan(nAngle2_) + pt2_.y); + } + + // 自坐标原点到两条直线的端点的向量 ---wanghong 2010 09 07 + VectorD2D _vec1x(_pt11), _vec1y(_pt12); + VectorD2D _vec2x(_pt21), _vec2y(_pt22); + // 两条直线的向量 ---wanghong 2010 09 07 + VectorD2D _vecA(_vec1y - _vec1x), _vecB(_vec2y - _vec2x); + // 第二条直线的垂直向量 ---wanghong 2010 09 07 + VectorD2D _vecBPlumb(-_vecB.y, _vecB.x); + + if (DOUBLE_EQU_ZERO(NormalizeVector(_vecA) * NormalizeVector(_vecBPlumb))) + { + // 平行或重合 ---wanghong 2010 09 07 + return 0; + } + + double _n = (_vec2x * _vecBPlumb - _vec1x * _vecBPlumb) / (_vecA * _vecBPlumb); + if (pptIntersect_ != NULL) + { + pptIntersect_->x = _vec1x.x + _n * _vecA.x; + pptIntersect_->y = _vec1x.y + _n * _vecA.y; + } + + return 1; +} + +int ncmath::Intersect_BeelineWithBeeline(IN const DPOINT2& pt1_, + IN double nAngle1_, + IN const DPOINT2& pt2_, + IN double nAngle2_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_ /* = 1 */) +{ + ASSERT(IsValidDouble(pt1_.x)); + ASSERT(IsValidDouble(pt1_.y)); + ASSERT(IsValidDouble(pt2_.x)); + ASSERT(IsValidDouble(pt2_.y)); + + if (nIntersectsNeed_ == 0) + { + double _nCompare1 = c_nINVALID_DOUBLE; + if (DOUBLE_EQU(nAngle1_, c_nPIE / 2) || DOUBLE_EQU(nAngle1_, 3 * c_nPIE / 2)) + { + // 当斜率为90度时,取x值作为比较 --- 吴阳明 2010 09 19 + _nCompare1 = pt1_.x; + } + else + { + // 当x为零时,两条直线所对应的y值 --- 吴阳明 2010 09 06 + _nCompare1 = pt1_.y - tan(nAngle1_) * pt1_.x; + } + + double _nCompare2 = c_nINVALID_DOUBLE; + if (DOUBLE_EQU(nAngle2_, c_nPIE / 2) || DOUBLE_EQU(nAngle2_, 3 * c_nPIE / 2)) + { + _nCompare2 = pt2_.x; + } + else + { + _nCompare2 = pt2_.y - tan(nAngle2_) * pt2_.x; + } + + // 重合,有无数个点 --- 吴阳明 2010 09 06 + if (DOUBLE_EQU(nAngle1_, nAngle2_) && DOUBLE_EQU(_nCompare1, _nCompare2)) + { + return -1; + } + // 平行,有0个点 --- 吴阳明 2010 09 06 + else if (DOUBLE_EQU(nAngle1_, nAngle2_) && !DOUBLE_EQU(_nCompare1, _nCompare2)) + { + return 0; + } + // 相交,有1个点 --- 吴阳明 2010 09 06 + else + { + return 1; + } + } + + DPOINT2 _ptIntersect(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + if (!Intersect_BeelineWithBeeline(pt1_, nAngle1_, pt2_, nAngle2_, &_ptIntersect)) + return 0; + + vectorIntersect_.push_back(_ptIntersect); + return 1; +} + +int ncmath::Intersect_BeelineWithLine(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptLineStart_, + IN const DPOINT2& ptLineEnd_, + OUT DPOINT2* pptIntersect_ /* = NULL */) +{ + ASSERT(IsValidDouble(ptBeeline_.x)); + ASSERT(IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptLineStart_.x)); + ASSERT(IsValidDouble(ptLineStart_.y)); + ASSERT(IsValidDouble(ptLineEnd_.x)); + ASSERT(IsValidDouble(ptLineEnd_.y)); + + DPOINT2 _vecLine(ptLineEnd_ - ptLineStart_); + ASSERT(DOUBLE_GREAT_ZERO(_vecLine.GetLength())); + + double _nAngleLine = D2GetNormalAngle(_vecLine); + DPOINT2 _ptIntersect(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + + // 求相应的直线与直线交点 --- 吴阳明 2010 09 06 + int _nIntersect = Intersect_BeelineWithBeeline(ptBeeline_, + nBeelineAngle_, ptLineStart_, _nAngleLine, &_ptIntersect); + + // 无交点直接返回0 --- 吴阳明 2010 09 06 + if (_nIntersect == 0) + return 0; + + // 如果交点不在线段上,返回0 --- 吴阳明 2010 09 06 + if (!IsPointInLine(_ptIntersect, ptLineStart_, ptLineEnd_)) + return 0; + + if (pptIntersect_ != NULL) + *pptIntersect_ = _ptIntersect; + + return 1; +} + +int ncmath::Intersect_BeelineWithLine(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptLineStart_, + IN const DPOINT2& ptLineEnd_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_ /* = 1 */) +{ + ASSERT(IsValidDouble(ptBeeline_.x)); + ASSERT(IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptLineStart_.x)); + ASSERT(IsValidDouble(ptLineStart_.y)); + ASSERT(IsValidDouble(ptLineEnd_.x)); + ASSERT(IsValidDouble(ptLineEnd_.y)); + + DPOINT2 _vecLine(ptLineEnd_ - ptLineStart_); + ASSERT(DOUBLE_GREAT_ZERO(_vecLine.GetLength())); + double _nAngleLine = D2GetNormalAngle(_vecLine); + + if (nIntersectsNeed_ == 0) + { + double _nNum = Intersect_BeelineWithBeeline(ptBeeline_, + nBeelineAngle_, ptLineStart_, _nAngleLine, vectorIntersect_, 0); + + // 直线及线段所在直线有交点,则判断交点是否在线段上 --- 吴阳明 2010 09 06 + if (_nNum == 1) + { + DPOINT2 _ptIntersect(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + return Intersect_BeelineWithLine(ptBeeline_,nBeelineAngle_, + ptLineStart_, ptLineEnd_, &_ptIntersect); + } + + // 无交点 --- 吴阳明 2010 09 06 + return 0; + } + + DPOINT2 _ptIntersect(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + if (!Intersect_BeelineWithLine(ptBeeline_,nBeelineAngle_, + ptLineStart_, ptLineEnd_, &_ptIntersect)) + { + return 0; + } + + vectorIntersect_.push_back(_ptIntersect); + return 1; +} + +// 该函数主要出自于v9中,只稍作修改 --- 吴阳明 2010 09 07 +int ncmath::Intersect_BeelineWithCircle(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptCenter_, + IN double nRadius_, + OUT DPOINT2* pptIntersect1_ /* = NULL */, + OUT DPOINT2* pptIntersect2_ /* = NULL */) +{ + ASSERT(IsValidDouble(ptBeeline_.x)); + ASSERT(IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptCenter_.x)); + ASSERT(IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + + double x1, y1, x2, y2; // 直线12 + double x3, y3; // 圆心到直线12的投影坐标; + double _nCenterToLineDis; // 圆心到直线12的距离 + double _nPrjToIntersectDis; // 投影点到交点的距离 + double _nLineLength; // 指定线段的长度 + double dvx1c, dvy1c; // 连接点1和圆心的直线的方向矢量 + double prjc; // 连接点1和圆心的直线在12上的投影长度 + + // 为直线两端点赋值 + x1 = ptBeeline_.x; + y1 = ptBeeline_.y; + x2 = c_nINVALID_DOUBLE; + y2 = c_nINVALID_DOUBLE; + + if (DOUBLE_EQU(nBeelineAngle_, c_nPIE / 2) || + DOUBLE_EQU(nBeelineAngle_, 3 * c_nPIE / 2)) + { + x2 = ptBeeline_.x; + y2 = ptBeeline_.y + 1; + } + else + { + x2 = ptBeeline_.x + 1; + y2 = ptBeeline_.y + tan(nBeelineAngle_); + } + + DPOINT2 _ptBeelineEnd(DPOINT2(x2, y2)); + _nLineLength = (_ptBeelineEnd - ptBeeline_).GetLength(); + DPOINT2 _vecLine(_ptBeelineEnd - ptBeeline_); + + if (DOUBLE_EQU_ZERO(nRadius_)) + return -1; + + // 当圆心到直线的距离大于半径时,直线与圆弧没有交点 + _nCenterToLineDis = D2GetPointToLineDistance(ptCenter_, ptBeeline_, _ptBeelineEnd); + if (DOUBLE_GREAT(_nCenterToLineDis, nRadius_)) + return 0; + + dvx1c = ptCenter_.x - x1; + dvy1c = ptCenter_.y - y1; + prjc = D2GetProjectionDistance(dvx1c, dvy1c, _vecLine.x, _vecLine.y); + + _vecLine.Unify(); + x3 = x1 + prjc * _vecLine.x; + y3 = y1 + prjc * _vecLine.y; + + double nTemp = nRadius_ * nRadius_ - _nCenterToLineDis * _nCenterToLineDis; + if (nTemp < 0) + nTemp = 0; + _nPrjToIntersectDis = sqrt(nTemp); + + DPOINT2 _ptIntersect1(x3 - _nPrjToIntersectDis * _vecLine.x, y3 - _nPrjToIntersectDis * _vecLine.y); + DPOINT2 _ptIntersect2(x3 + _nPrjToIntersectDis * _vecLine.x, y3 + _nPrjToIntersectDis * _vecLine.y); + + // 相切情况 --- 吴阳明 2010 09 07 + if (pptIntersect1_ != NULL && DOUBLE_EQU_ZERO((_ptIntersect1 - _ptIntersect2).GetLength())) + { + *pptIntersect1_ = _ptIntersect1; + return 1; + } + + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersect1; + + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersect2; + + return 2; +} + +int ncmath::Intersect_BeelineWithCircle(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptCenter_, + IN double nRadius_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_ /* = 2 */) +{ + ASSERT(IsValidDouble(ptBeeline_.x)); + ASSERT(IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptCenter_.x)); + ASSERT(IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + + DPOINT2 _ptBeelineEnd(DPOINT2(ptBeeline_.x, ptBeeline_.y + 1)); + if (!DOUBLE_EQU(nBeelineAngle_, c_nPIE / 2) && !DOUBLE_EQU(nBeelineAngle_, 3 * c_nPIE / 2)) + _ptBeelineEnd = DPOINT2(ptBeeline_.x + 1, ptBeeline_.y + tan(nBeelineAngle_)); + + if (nIntersectsNeed_ == 0) + { + double _nDis = D2GetPointToLineDistance(ptCenter_, ptBeeline_, _ptBeelineEnd); + + if (DOUBLE_EQU(_nDis, nRadius_)) + { + return 1; + } + else if (DOUBLE_GREAT(_nDis, nRadius_)) + { + return 0; + } + else + { + return 2; + } + } + + DPOINT2 _ptIntersect1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersect2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + double _nNum = Intersect_BeelineWithCircle(ptBeeline_, nBeelineAngle_, + ptCenter_, nRadius_, &_ptIntersect1, &_ptIntersect2); + + if (_nNum == 1) + { + vectorIntersect_.push_back(_ptIntersect1); + return 1; + } + else if (_nNum == 2) + { + vectorIntersect_.push_back(_ptIntersect1); + vectorIntersect_.push_back(_ptIntersect2); + return 2; + } + else + { + return 0; + } +} + +int ncmath::Intersect_BeelineWithArc(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptCenter_, + IN double nRadius_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT DPOINT2* pptIntersect1_ /* = NULL */, + OUT DPOINT2* pptIntersect2_ /* = NULL */) +{ + ASSERT(IsValidDouble(ptBeeline_.x) && IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle_) && DOUBLE_LESS(nStartAngle_, 2 * c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && DOUBLE_LE(fabs(nSweptAngle_), 2 * c_nPIE)); + + DPOINT2 _ptIntersec1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersec2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + // 通过直线与圆弧对应的圆求交,获得“可能是交点”的点集 --- wanghong 2010 09 08 + int _nImageIntersect = Intersect_BeelineWithCircle(ptBeeline_, nBeelineAngle_, ptCenter_, nRadius_, &_ptIntersec1, &_ptIntersec2); + if (_nImageIntersect < 1) + return _nImageIntersect; + + bool _bPt1Exist = IsPointInArc(_ptIntersec1, ptCenter_, nRadius_, nStartAngle_, + fabs(nSweptAngle_), DOUBLE_GREAT_ZERO(nSweptAngle_)); + bool _bPt2Exist = false; + if (_nImageIntersect == 2) + { // 避免相切时重复计算 --- wanghong 2010 09 08 + _bPt2Exist = IsPointInArc(_ptIntersec2, ptCenter_, nRadius_, nStartAngle_, + fabs(nSweptAngle_), DOUBLE_GREAT_ZERO(nSweptAngle_)); + } + // 存在两个交点 --- wanghong 2010 09 08 + if (_bPt1Exist && _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersec1; + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersec2; + return 2; + } + // 存在一个交点 --- wanghong 2010 09 08 + if (_bPt1Exist || _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _bPt1Exist ? _ptIntersec1 : _ptIntersec2; + return 1; + } + + return 0; +} + +int ncmath::Intersect_LineWithCircle(IN const DPOINT2& ptStart_, + IN const DPOINT2& ptEnd_, + IN const DPOINT2& ptCenter_, + IN double nRadius_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptStart_.x)); + ASSERT(IsValidDouble(ptStart_.y)); + ASSERT(IsValidDouble(ptEnd_.x)); + ASSERT(IsValidDouble(ptCenter_.x)); + ASSERT(IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + + DPOINT2 _ptIntersec1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersec2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + // 通过线段所在的直线与圆求交,获得“可能是交点”的点集 --- wanghong 2010 09 08 + int _nImageIntersect = Intersect_BeelineWithCircle(ptStart_, ncmath::D2GetNormalAngle(ptEnd_ - ptStart_), + ptCenter_, nRadius_, &_ptIntersec1, &_ptIntersec2); + if (_nImageIntersect < 1) + return _nImageIntersect; + + bool _bPt1Exist = IsPointInLine(_ptIntersec1, ptStart_, ptEnd_); + bool _bPt2Exist = false; + if (_nImageIntersect == 2) + { // 避免相切时重复计算 --- wanghong 2010 09 08 + _bPt2Exist = IsPointInLine(_ptIntersec2, ptStart_, ptEnd_); + } + // 存在两个交点 --- wanghong 2010 09 08 + if (_bPt1Exist && _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersec1; + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersec2; + return 2; + } + // 存在一个交点 --- wanghong 2010 09 08 + if (_bPt1Exist || _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _bPt1Exist ? _ptIntersec1 : _ptIntersec2; + return 1; + } + + return 0; +} + +int ncmath::Intersect_LineWithCircle(IN const DPOINT2& ptStart_, + IN const DPOINT2& ptEnd_, + IN const DPOINT2& ptCenter_, + IN double nRadius_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 2*/) +{ + ASSERT(IsValidDouble(ptStart_.x)); + ASSERT(IsValidDouble(ptStart_.y)); + ASSERT(IsValidDouble(ptEnd_.x)); + ASSERT(IsValidDouble(ptCenter_.x)); + ASSERT(IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + + DPOINT2 _ptIntersect[2] = {DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE)}; + int _nIntersect = Intersect_LineWithCircle(ptStart_, ptEnd_, ptCenter_, nRadius_, _ptIntersect, _ptIntersect + 1); + // nIntersectsNeed_ 取-1时,由于要求返回所有的交点,等同于值为2的情形 --- wanghong 2010 09 08 + if (nIntersectsNeed_ <= -1) + nIntersectsNeed_ = 2; + + int _nMinIntersect = min(_nIntersect, nIntersectsNeed_); + std::copy(_ptIntersect, _ptIntersect + _nMinIntersect, std::back_inserter(vectorIntersect_)); + + return _nIntersect; +} + +int ncmath::Intersect_BeelineWithArc(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptCenter_, + IN double nRadius_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 2*/) +{ + ASSERT(IsValidDouble(ptBeeline_.x) && IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle_) && DOUBLE_LESS(nStartAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && DOUBLE_LE(fabs(nSweptAngle_), 2 * c_nPIE)); + + DPOINT2 _ptIntersect[2] = {DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE)}; + int _nIntersect = Intersect_BeelineWithArc(ptBeeline_, nBeelineAngle_, ptCenter_, nRadius_, + nStartAngle_, nSweptAngle_, _ptIntersect, _ptIntersect + 1); + // nIntersectsNeed_ 取-1时,由于要求返回所有的交点,等同于值为2的情形 --- wanghong 2010 09 08 + if (nIntersectsNeed_ <= -1) + nIntersectsNeed_ = 2; + + int _nMinIntersect = min(_nIntersect, nIntersectsNeed_); + std::copy(_ptIntersect, _ptIntersect + _nMinIntersect, std::back_inserter(vectorIntersect_)); + + return _nIntersect; +} + +int ncmath::Intersect_LineWithArc(IN const DPOINT2& ptStart_, + IN const DPOINT2& ptEnd_, + IN const DPOINT2& ptCenter_, + IN double nRadius_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptStart_.x) && IsValidDouble(ptStart_.y)); + ASSERT(IsValidDouble(ptEnd_.x) && IsValidDouble(ptEnd_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle_) && DOUBLE_LESS(nStartAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && DOUBLE_LE(fabs(nSweptAngle_), 2 * ncmath::c_nPIE)); + + DPOINT2 _ptIntersec1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersec2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + // 通过线段对应的直线与圆弧对应的圆求交,获得“可能是交点”的点集 --- wanghong 2010 09 08 + int _nImageIntersect = Intersect_BeelineWithCircle(ptStart_, ncmath::D2GetNormalAngle(ptEnd_ - ptStart_), + ptCenter_, nRadius_, &_ptIntersec1, &_ptIntersec2); + if (_nImageIntersect < 1) + return _nImageIntersect; + + bool _bPt1Exist = IsPointInLine(_ptIntersec1, ptStart_, ptEnd_) && + IsPointInArc(_ptIntersec1, ptCenter_, nRadius_, nStartAngle_, fabs(nSweptAngle_), DOUBLE_GREAT_ZERO(nSweptAngle_)); + bool _bPt2Exist = false; + if (_nImageIntersect == 2) + { // 避免相切时重复计算 --- wanghong 2010 09 08 + _bPt2Exist = IsPointInLine(_ptIntersec2, ptStart_, ptEnd_) && + IsPointInArc(_ptIntersec2, ptCenter_, nRadius_, nStartAngle_, fabs(nSweptAngle_), DOUBLE_GREAT_ZERO(nSweptAngle_)); + } + // 存在两个交点 --- wanghong 2010 09 08 + if (_bPt1Exist && _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersec1; + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersec2; + return 2; + } + // 存在一个交点 --- wanghong 2010 09 08 + if (_bPt1Exist || _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _bPt1Exist ? _ptIntersec1 : _ptIntersec2; + return 1; + } + + return 0; +} + +int ncmath::Intersect_LineWithArc(IN const DPOINT2& ptStart_, + IN const DPOINT2& ptEnd_, + IN const DPOINT2& ptCenter_, + IN double nRadius_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 2*/) +{ + ASSERT(IsValidDouble(ptStart_.x) && IsValidDouble(ptStart_.y)); + ASSERT(IsValidDouble(ptEnd_.x) && IsValidDouble(ptEnd_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle_) && DOUBLE_LESS(nStartAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && DOUBLE_LE(fabs(nSweptAngle_), 2 * ncmath::c_nPIE)); + + DPOINT2 _ptIntersect[2] = {DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE)}; + int _nIntersect = Intersect_LineWithArc(ptStart_, ptEnd_, ptCenter_, nRadius_, + nStartAngle_, nSweptAngle_, _ptIntersect, _ptIntersect + 1); + // nIntersectsNeed_ 取-1时,由于要求返回所有的交点,等同于值为2的情形 --- wanghong 2010 09 08 + if (nIntersectsNeed_ <= -1) + nIntersectsNeed_ = 2; + + int _nMinIntersect = min(_nIntersect, nIntersectsNeed_); + std::copy(_ptIntersect, _ptIntersect + _nMinIntersect, std::back_inserter(vectorIntersect_)); + + return _nIntersect; +} + +int ncmath::Intersect_LineWithLine(IN const DPOINT2& ptStart1_, + IN const DPOINT2& ptEnd1_, + IN const DPOINT2& ptStart2_, + IN const DPOINT2& ptEnd2_, + OUT DPOINT2* pptIntersect_ /* = NULL */) +{ + DPOINT2 _vecLine1(ptEnd1_ - ptStart1_); + DPOINT2 _vecLine2(ptEnd2_ - ptStart2_); + + ASSERT(DOUBLE_GREAT_ZERO(_vecLine1.GetLength())); + ASSERT(DOUBLE_GREAT_ZERO(_vecLine2.GetLength())); + + double _nAngle1 = D2GetNormalAngle(_vecLine1); + double _nAngle2 = D2GetNormalAngle(_vecLine2); + + DPOINT2 _ptIntersect(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + int _nNum = Intersect_BeelineWithBeeline(ptStart1_, _nAngle1, + ptStart2_, _nAngle2, &_ptIntersect); + + if (_nNum == 0 || !IsPointInLine(_ptIntersect, ptStart1_, ptEnd1_) || + !IsPointInLine(_ptIntersect, ptStart2_, ptEnd2_)) + { + return 0; + } + + if (pptIntersect_) + *pptIntersect_ = _ptIntersect; + + return 1; +} + +int ncmath::Intersect_LineWithLine(IN const DPOINT2& ptStart1_, + IN const DPOINT2& ptEnd1_, + IN const DPOINT2& ptStart2_, + IN const DPOINT2& ptEnd2_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_ /* = 1 */) +{ + DPOINT2 _vecLine1(ptEnd1_ - ptStart1_); + DPOINT2 _vecLine2(ptEnd2_ - ptStart2_); + + ASSERT(DOUBLE_GREAT_ZERO(_vecLine1.GetLength())); + ASSERT(DOUBLE_GREAT_ZERO(_vecLine2.GetLength())); + + if (nIntersectsNeed_ == 0) + { + // 排斥试验 --- 吴阳明 2010 09 08 + LineD2D _Line1; + _Line1.pt1 = ptStart1_; + _Line1.pt2 = ptEnd1_; + LineD2D _Line2; + _Line2.pt1 = ptStart2_; + _Line2.pt2 = ptEnd2_; + + RealRectD _Rect1 = _Line1.GetBoundRect(); + RealRectD _Rect2 = _Line2.GetBoundRect(); + + if (!_Rect1.Intersect(_Rect2)) + return 0; + + // 跨立试验 : + // 判断P1P2跨立Q1Q2的依据是: + // ( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0 + // 判断Q1Q2跨立P1P2的依据是: + // ( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0 + // --- 吴阳明 2010 09 08 + VectorD2D _vecQ1P1 = ptStart1_ - ptStart2_; + VectorD2D _vecQ1Q2 = ptEnd2_ - ptStart2_; + VectorD2D _vecQ1P2 = ptEnd1_ - ptStart2_; + + VectorD2D _vecP1Q1 = ptStart2_ - ptStart1_; + VectorD2D _vecP1P2 = ptEnd1_ - ptStart1_; + VectorD2D _vecP1Q2 = ptEnd2_ - ptStart1_; + + if (D2CrossMultiply(_vecQ1P1, _vecQ1Q2) * D2CrossMultiply(_vecQ1Q2, _vecQ1P2) < 0 || + D2CrossMultiply(_vecP1Q1, _vecP1P2) * D2CrossMultiply(_vecP1P2, _vecP1Q2) < 0) + return 0; + + return 1; + } + + DPOINT2 _ptIntersect(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + if (Intersect_LineWithLine(ptStart1_, ptEnd1_, ptStart2_, ptEnd2_, &_ptIntersect) == 0) + return 0; + + vectorIntersect_.push_back(_ptIntersect); + return 1; +} + +// 由v9中稍作修改 --- 吴阳明 2010 09 08 +int ncmath::Intersect_CircleWithCircle(IN const DPOINT2& ptCenter1_, + IN double nRadius1_, + IN const DPOINT2& ptCenter2_, + IN double nRadius2_, + OUT DPOINT2* pptIntersect1_ /* = NULL */, + OUT DPOINT2* pptIntersect2_ /* = NULL */) +{ + ASSERT(IsValidDouble(ptCenter1_.x)); + ASSERT(IsValidDouble(ptCenter1_.y)); + ASSERT(IsValidDouble(ptCenter2_.x)); + ASSERT(IsValidDouble(ptCenter2_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius1_)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius2_)); + + double x3, y3; // 12与c1c2交点坐标 + double _nCentersDis; // 两圆弧圆心之间的距离 + double d1; // 交点1到圆心连线的距离 + double l1; // + double _nAngle1c1c2; // 交点1,圆心1,圆心2组成的三角形中,角1c1c2 + + // 计算圆心距 --- 吴阳明 2010 09 08 + _nCentersDis = D2GetDistance(ptCenter1_, ptCenter2_); + + // 相离,相含时,交点个数计为零 --- 吴阳明 2010 09 08 + if (DOUBLE_GREAT(_nCentersDis, (nRadius1_ + nRadius2_)) || + DOUBLE_LESS(_nCentersDis, fabs(nRadius1_ - nRadius2_))) + { + return 0; + } + + if (DOUBLE_EQU_ZERO(_nCentersDis) && DOUBLE_EQU(nRadius1_, nRadius2_)) + return -1; + + double nTemp = (nRadius1_ * nRadius1_ + _nCentersDis * _nCentersDis - nRadius2_ * nRadius2_) / (2 * nRadius1_ * _nCentersDis); + __CUT(nTemp, -1, 1); + _nAngle1c1c2 = acos(nTemp); + d1 = nRadius1_ * cos(_nAngle1c1c2); + l1 = nRadius1_ * sin(_nAngle1c1c2); + + // 圆心连线的方向矢量 --- 吴阳明 2010 09 08 + DPOINT2 _vecCenters(ptCenter2_ - ptCenter1_); + _vecCenters.Unify(); + + // 交点1在两圆心连线上的投影点 + x3 = ptCenter1_.x + d1 * _vecCenters.x; + y3 = ptCenter1_.y + d1 * _vecCenters.y; + + // 单位矢量31 + double uvx31 = -_vecCenters.y; + double uvy31 = _vecCenters.x; + + // 交点坐标 + DPOINT2 _ptIntersect1(x3 + l1 * uvx31, y3 + l1 * uvy31); + DPOINT2 _ptIntersect2(x3 - l1 * uvx31, y3 - l1 * uvy31); + + // 相切情况 --- 吴阳明 2010 09 08 + if (pptIntersect1_ && DOUBLE_EQU_ZERO((_ptIntersect1 - _ptIntersect2).GetLength())) + { + *pptIntersect1_ = _ptIntersect1; + return 1; + } + + if (pptIntersect1_) + *pptIntersect1_ = _ptIntersect1; + + if (pptIntersect2_) + *pptIntersect2_ = _ptIntersect2; + + return 2; +} + +int ncmath::Intersect_CircleWithCircle(IN const DPOINT2& ptCenter1_, + IN double nRadius1_, + IN const DPOINT2& ptCenter2_, + IN double nRadius2_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_ /* = 2 */) +{ + ASSERT(IsValidDouble(ptCenter1_.x)); + ASSERT(IsValidDouble(ptCenter1_.y)); + ASSERT(IsValidDouble(ptCenter2_.x)); + ASSERT(IsValidDouble(ptCenter2_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius1_)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius2_)); + + if (nIntersectsNeed_ == 0) + { + // 圆心距 --- 吴阳明 2010 09 08 + double _nCentersDis = D2GetDistance(ptCenter1_, ptCenter2_); + + // 相离,相含时,交点个数计为零 --- 吴阳明 2010 09 08 + if (DOUBLE_GREAT(_nCentersDis, (nRadius1_ + nRadius2_)) || + DOUBLE_LESS(_nCentersDis, fabs(nRadius1_ - nRadius2_))) + { + return 0; + } + // 重合 --- 吴阳明 2010 09 08 + else if (DOUBLE_EQU_ZERO(_nCentersDis) && DOUBLE_EQU(nRadius1_, nRadius2_)) + { + return -1; + } + // 相切 --- 吴阳明 2010 09 08 + else if (DOUBLE_EQU(_nCentersDis, nRadius1_) || + DOUBLE_EQU(_nCentersDis, nRadius2_) || + DOUBLE_EQU(_nCentersDis, nRadius1_ + nRadius2_)) + { + return 1; + } + else + { + return 2; + } + } + + DPOINT2 _ptIntersect1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersect2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + int _nNum = Intersect_CircleWithCircle(ptCenter1_, nRadius1_,ptCenter2_, + nRadius2_, &_ptIntersect1, &_ptIntersect2); + + switch(_nNum) + { + case 2: + { + vectorIntersect_.push_back(_ptIntersect1); + vectorIntersect_.push_back(_ptIntersect2); + } + break; + + case 1: + { + vectorIntersect_.push_back(_ptIntersect1); + } + break; + + default: + break; + } + + return _nNum; +} + +int ncmath::Intersect_CircleWithArc(IN const DPOINT2& ptCircleCenter_, + IN double nCircleRadius_, + IN const DPOINT2& ptArcCenter_, + IN double nArcRadius_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT DPOINT2* pptIntersect1_ /* = NULL */, + OUT DPOINT2* pptIntersect2_ /* = NULL */) +{ + ASSERT(IsValidDouble(ptCircleCenter_.x)); + ASSERT(IsValidDouble(ptCircleCenter_.y)); + ASSERT(IsValidDouble(ptArcCenter_.x)); + ASSERT(IsValidDouble(ptArcCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nCircleRadius_)); + ASSERT(DOUBLE_GREAT_ZERO(nArcRadius_)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && + DOUBLE_LESS(fabs(nSweptAngle_), 2 * c_nPIE)); + + // 计算圆及圆弧所在圆的交点 --- 吴阳明 2010 09 08 + DPOINT2 _ptIntersect1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersect2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + int _nNum = Intersect_CircleWithCircle(ptCircleCenter_, nCircleRadius_, + ptArcCenter_, nArcRadius_, &_ptIntersect1, &_ptIntersect2); + + switch(_nNum) + { + case 1: + if (IsPointInArc(_ptIntersect1, ptArcCenter_, nArcRadius_, + nStartAngle_, fabs(nSweptAngle_), nSweptAngle_ > 0)) + { + *pptIntersect1_ = _ptIntersect1; + } + else + { + --_nNum; + } + + break; + + case 2: + { + // 判断交点是否在圆弧上 --- 吴阳明 2010 09 08 + bool _bPt1InArc = IsPointInArc(_ptIntersect1, ptArcCenter_, nArcRadius_, + nStartAngle_, fabs(nSweptAngle_), nSweptAngle_ > 0); + + bool _bPt2InArc = (IsPointInArc(_ptIntersect2, ptArcCenter_, nArcRadius_, + nStartAngle_, fabs(nSweptAngle_), nSweptAngle_ > 0)); + + if (_bPt1InArc && _bPt2InArc) + { + if (pptIntersect1_) + *pptIntersect1_ = _ptIntersect1; + if (pptIntersect2_) + *pptIntersect2_ = _ptIntersect2; + } + else if (pptIntersect1_ && _bPt1InArc && !_bPt2InArc) + { + *pptIntersect1_ = _ptIntersect1; + --_nNum; + } + else if (pptIntersect1_ && !_bPt1InArc && _bPt2InArc) + { + *pptIntersect1_ = _ptIntersect2; + --_nNum; + } + else + { + _nNum = 0; + } + } + break; + + case 0: + default: + _nNum = 0; + } + + return _nNum; +} + +namespace +{ + // 判断给定角度是否在(nLeft_, nRight_)内,注意nLeft_可能大于nRight_ --- wanghong 2010 09 09 + inline bool InRange(double nLeft_, double nAngle_, double nRight_) + { + if (nLeft_ < nRight_) + return nLeft_ < nAngle_ && nAngle_ < nRight_; + + return (nLeft_ < nAngle_ && nAngle_ < 2 * ncmath::c_nPIE) || + (0 < nAngle_ && nAngle_ < nRight_); + } + // 对给定的起始角和中心角,得到按逆时针排列的起始角和终止角 --- wanghong 2010 09 09 + void GetLegalAngle(double& nStartAngle_, double& nEndAngle_, double nSweepAngle_) + { + if (DOUBLE_GREAT_ZERO(nSweepAngle_)) + { + nEndAngle_ = nStartAngle_ + nSweepAngle_; + if (DOUBLE_GE(nEndAngle_, 2 * ncmath::c_nPIE)) + nEndAngle_ -= 2 * ncmath::c_nPIE; + } + else + { + nEndAngle_ = nStartAngle_; + nStartAngle_ = nStartAngle_ + nSweepAngle_; + if (DOUBLE_LESS_ZERO(nStartAngle_)) + nStartAngle_ += 2 * ncmath::c_nPIE; + } + } +} + +int ncmath::Intersect_CircleWithArc(IN const DPOINT2& ptCircleCenter_, + IN double nCircleRadius_, + IN const DPOINT2& ptArcCenter_, + IN double nArcRadius_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_ /* = 2 */) +{ + ASSERT(IsValidDouble(ptCircleCenter_.x)); + ASSERT(IsValidDouble(ptCircleCenter_.y)); + ASSERT(IsValidDouble(ptArcCenter_.x)); + ASSERT(IsValidDouble(ptArcCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nCircleRadius_)); + ASSERT(DOUBLE_GREAT_ZERO(nArcRadius_)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && + DOUBLE_LESS(fabs(nSweptAngle_), 2 * c_nPIE)); + + DPOINT2 _ptIntersect1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersect2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + int _nNum = Intersect_CircleWithCircle(ptCircleCenter_, nCircleRadius_, + ptArcCenter_, nArcRadius_, &_ptIntersect1, &_ptIntersect2); + + switch(_nNum) + { + case 2: + { + if (IsPointInArc(_ptIntersect1, ptArcCenter_, nArcRadius_, + nStartAngle_, fabs(nSweptAngle_), nSweptAngle_ > 0)) + { + vectorIntersect_.push_back(_ptIntersect1); + } + else + { + --_nNum; + } + + if (IsPointInArc(_ptIntersect2, ptArcCenter_, nArcRadius_, + nStartAngle_, fabs(nSweptAngle_), nSweptAngle_ > 0)) + { + vectorIntersect_.push_back(_ptIntersect2); + } + else + { + --_nNum; + } + } + break; + + case 1: + { + if (IsPointInArc(_ptIntersect1, ptArcCenter_, nArcRadius_, + nStartAngle_, fabs(nSweptAngle_), nSweptAngle_ > 0)) + { + vectorIntersect_.push_back(_ptIntersect1); + } + else + { + --_nNum; + } + } + break; + + case -1: + { + vectorIntersect_.push_back(GetPointInCircle(ptArcCenter_, nArcRadius_, nStartAngle_)); + double _nEndAngle = RegularizeRadian(nStartAngle_ + nSweptAngle_); + vectorIntersect_.push_back(GetPointInCircle(ptArcCenter_, nArcRadius_, _nEndAngle)); + } + + default: + break; + } + + return _nNum; +} + +int ncmath::Intersect_CircleWithEllipse(IN const DPOINT2& ptCircleCenter_, + IN double nRadius_, + IN const DPOINT2& ptEllipseCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_ /* = 4 */) +{ + ASSERT(vectorIntersect_.empty()); + ASSERT(nIntersectsNeed_ >= -1); + + // 保存交点 + DPOINT2 _ptIntersects[4]; + int _nNeed = (nIntersectsNeed_ < 0 || nIntersectsNeed_ >= 4) ? 4 : nIntersectsNeed_; + + // 调用C风格版 + int _nRet = Intersect_CircleWithEllipse( + ptCircleCenter_, nRadius_, ptEllipseCenter_, nURadius_, nVRadius_, nUAngle_, + _nNeed >= 1 ? &_ptIntersects[0] : NULL, + _nNeed >= 2 ? &_ptIntersects[1] : NULL, + _nNeed >= 3 ? &_ptIntersects[2] : NULL, + _nNeed >= 4 ? &_ptIntersects[3] : NULL); + ASSERT(_nRet >= -1 && _nRet <= 4); + + // 收集交点 + vectorIntersect_.clear(); + for (int _i = 0; _i < _nRet && _i < _nNeed; _i++) + { + ASSERT(IsValidDouble(_ptIntersects[_i].x) && IsValidDouble(_ptIntersects[_i].y)); + vectorIntersect_.push_back(_ptIntersects[_i]); + } + + return _nRet; +} + +int ncmath::Intersect_CircleWithEllipse(IN const DPOINT2& ptCircleCenter_, + IN double nRadius_, + IN const DPOINT2& ptEllipseCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL */, + OUT DPOINT2* pptIntersect2_/* = NULL */, + OUT DPOINT2* pptIntersect3_/* = NULL */, + OUT DPOINT2* pptIntersect4_/* = NULL */) +{ + ASSERT(IsValidDouble(ptCircleCenter_.x)); + ASSERT(IsValidDouble(ptCircleCenter_.y)); + ASSERT(IsValidDouble(nRadius_) && DOUBLE_GE_ZERO(nRadius_)); + ASSERT(IsValidDouble(ptEllipseCenter_.x)); + ASSERT(IsValidDouble(ptEllipseCenter_.y)); + ASSERT(IsValidDouble(nURadius_) && DOUBLE_GE_ZERO(nURadius_)); + ASSERT(IsValidDouble(nVRadius_) && DOUBLE_GE_ZERO(nVRadius_)); + ASSERT(IsValidDouble(nUAngle_)); + + if (DOUBLE_EQU_ZERO(nRadius_) || (DOUBLE_EQU_ZERO(nURadius_) && DOUBLE_EQU_ZERO(nVRadius_))) + return 0; + + int _nRet = 0; + // 椭圆退化成圆的情况下调用圆与圆求交点的函数 Wanglou 2010-09-15 + if (DOUBLE_EQU(nURadius_, nVRadius_)) + { + // 圆与圆在不重合的情况下最多有两个交点 Wanglou 2010-09-16 + _nRet = Intersect_CircleWithCircle(ptCircleCenter_, nRadius_, ptEllipseCenter_, + nURadius_, pptIntersect1_, pptIntersect2_); + } + // 椭圆退化成直线 调用直线与圆求交点的函数 Wanglou 2010-09-15 + else if (DOUBLE_EQU_ZERO(nVRadius_)) + { + // 圆与直线最多也只有两个交点 Wanglou 2010-09-16 + DPOINT2 _ptStart, _ptEnd; + _ptStart.x = ptEllipseCenter_.x + nURadius_ * cos(nUAngle_); + _ptStart.y = ptEllipseCenter_.y + nURadius_ * sin(nUAngle_); + _ptEnd.x = ptEllipseCenter_.x - nURadius_ * cos(nUAngle_); + _ptEnd.y = ptEllipseCenter_.y - nURadius_ * sin(nUAngle_); + _nRet = Intersect_LineWithCircle(_ptStart, _ptEnd, ptCircleCenter_, nRadius_, + pptIntersect1_, pptIntersect2_); + } + else + { + // 通常情况下的把圆看成椭圆,计算交点 Wanglou 2010-09-16 + _nRet = Intersect_EllipseWithEllipse(ptEllipseCenter_, nURadius_, nVRadius_, nUAngle_, ptCircleCenter_, + nRadius_, nRadius_, 0, pptIntersect1_, pptIntersect2_, pptIntersect3_, pptIntersect4_); + } + + return _nRet; +} + +int ncmath::Intersect_CircleWithEllipseArc(IN const DPOINT2& ptCircleCenter_, + IN double nRadius_, + IN const DPOINT2& ptEllipseCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_ /* = 4 */) +{ + ASSERT(vectorIntersect_.empty()); + ASSERT(nIntersectsNeed_ >= -1); + + // 保存交点 + DPOINT2 _ptIntersects[4]; + int _nNeed = (nIntersectsNeed_ < 0 || nIntersectsNeed_ >= 4) ? 4 : nIntersectsNeed_; + + // 调用C风格版 + int _nRet = Intersect_CircleWithEllipseArc( + ptCircleCenter_, nRadius_, ptEllipseCenter_, nURadius_, nVRadius_, nUAngle_, nStartAngle_, nSweptAngle_, + _nNeed >= 1 ? &_ptIntersects[0] : NULL, + _nNeed >= 2 ? &_ptIntersects[1] : NULL, + _nNeed >= 3 ? &_ptIntersects[2] : NULL, + _nNeed >= 4 ? &_ptIntersects[3] : NULL); + ASSERT(_nRet >= -1 && _nRet <= 4); + + // 收集交点 + vectorIntersect_.clear(); + for (int _i = 0; _i < _nRet && _i < _nNeed; _i++) + { + ASSERT(IsValidDouble(_ptIntersects[_i].x) && IsValidDouble(_ptIntersects[_i].y)); + vectorIntersect_.push_back(_ptIntersects[_i]); + } + + return _nRet; +} + +int ncmath::Intersect_CircleWithEllipseArc(IN const DPOINT2& ptCircleCenter_, + IN double nRadius_, + IN const DPOINT2& ptEllipseCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL */, + OUT DPOINT2* pptIntersect2_/* = NULL */, + OUT DPOINT2* pptIntersect3_/* = NULL */, + OUT DPOINT2* pptIntersect4_/* = NULL */) +{ + ASSERT(IsValidDouble(nStartAngle_)); + ASSERT(IsValidDouble(nSweptAngle_)); + + // 如果椭圆弧中心角为0,则认为没有交点 Wanglou 2010-09-16 + if (DOUBLE_EQU_ZERO(nSweptAngle_)) + return 0; + + // 由于圆和椭圆的点不一定在椭圆弧,所以只要要求计算一个圆和椭圆弧的交点,则需要计算圆和椭圆的所有交点 + // Wanglou 2010-09-16 + int _nNum = 0; + DPOINT2 _ptIntersect[4]; + + _nNum = Intersect_CircleWithEllipse(ptCircleCenter_, nRadius_, ptEllipseCenter_, nURadius_, nVRadius_, + nUAngle_, &_ptIntersect[0], &_ptIntersect[1], &_ptIntersect[2], &_ptIntersect[3]); + + int _nCount = 0; + for (int _nIndex = 0; _nIndex < _nNum; _nIndex++) + { + // 把在椭圆弧上的交点保存起来 Wanglou 2010-09-16 + if (IsPointInEllipseArc(_ptIntersect[_nIndex], ptEllipseCenter_, nURadius_, nVRadius_, + nUAngle_, nStartAngle_, nSweptAngle_, true)) + { + _ptIntersect[_nCount] = _ptIntersect[_nIndex]; + _nCount++; + } + } + + // 后面的点置为无效 + for (int _i = _nCount; _i < 4; _i++) + { + _ptIntersect[_i] = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + } + + if (pptIntersect1_) + *pptIntersect1_ = _ptIntersect[0]; + if (pptIntersect2_) + *pptIntersect2_ = _ptIntersect[1]; + if (pptIntersect3_) + *pptIntersect3_ = _ptIntersect[2]; + if (pptIntersect4_) + *pptIntersect4_ = _ptIntersect[3]; + + // 如果部分重合,返回-1 + int _nRet = _nCount; + if (_nNum == -1) + _nRet = -1; + + return _nRet; +} + +int ncmath::Intersect_ArcWithArc(IN const DPOINT2& ptCenter1_, + IN double nRadius1_, + IN double nStartAngle1_, + IN double nSweptAngle1_, + IN const DPOINT2& ptCenter2_, + IN double nRadius2_, + IN double nStartAngle2_, + IN double nSweptAngle2_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptCenter1_.x) && IsValidDouble(ptCenter1_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius1_)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle1_)) && DOUBLE_LE(fabs(nSweptAngle1_), 2 * ncmath::c_nPIE)); + ASSERT(IsValidDouble(ptCenter2_.x) && IsValidDouble(ptCenter2_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius2_)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle2_)) && DOUBLE_LE(fabs(nSweptAngle2_), 2 * ncmath::c_nPIE)); + + // 在圆弧对应的圆重合情形下,计算交点 --- wanghong 2010 09 09 + if (ptCenter1_ == ptCenter2_ && DOUBLE_EQU(nRadius1_, nRadius2_)) + { + double _nLegalStartAngle1 = nStartAngle1_, _nLegalEndAngle1 = c_nINVALID_DOUBLE; + double _nLegalStartAngle2 = nStartAngle2_, _nLegalEndAngle2 = c_nINVALID_DOUBLE; + GetLegalAngle(_nLegalStartAngle1, _nLegalEndAngle1, nSweptAngle1_); + GetLegalAngle(_nLegalStartAngle2, _nLegalEndAngle2, nSweptAngle2_); + + // 部分重合(包括完全重合) --- wanghong 2010 09 09 + // 对于出现两圆弧部分重合,同时相接于一点、出现两段重合区段这两种情况,将随机返回某个区段的端点 --- wanghong 2010 09 10 + bool _bStartInRange = false; + if ((DOUBLE_EQU(_nLegalStartAngle1, _nLegalStartAngle2) && DOUBLE_EQU(_nLegalEndAngle1, _nLegalEndAngle2)) || + (_bStartInRange = InRange(_nLegalStartAngle1, _nLegalStartAngle2, _nLegalEndAngle1)) || + InRange(_nLegalStartAngle1, _nLegalEndAngle2, _nLegalEndAngle1)) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = GetPointInCircle(ptCenter1_, nRadius1_, _bStartInRange ? _nLegalStartAngle2 : _nLegalStartAngle1); + if (pptIntersect2_ != NULL) + *pptIntersect2_ = GetPointInCircle(ptCenter1_, nRadius1_, _bStartInRange ? _nLegalEndAngle1 : _nLegalEndAngle2); + return -1; + } + + // 两圆弧恰好互补,首尾相接 --- wanghong 2010 09 09 + if (DOUBLE_EQU(_nLegalStartAngle1, _nLegalEndAngle2) && DOUBLE_EQU(_nLegalEndAngle1, _nLegalStartAngle2)) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = GetPointInCircle(ptCenter1_, nRadius1_, _nLegalStartAngle1); + if (pptIntersect2_ != NULL) + *pptIntersect2_ = GetPointInCircle(ptCenter1_, nRadius1_, _nLegalEndAngle1); + return 2; + } + // 两圆弧相接于一点 --- wanghong 2010 09 09 + if (DOUBLE_EQU(_nLegalStartAngle1, _nLegalEndAngle2) || DOUBLE_EQU(_nLegalEndAngle1, _nLegalStartAngle2)) + { + if (pptIntersect1_ != NULL) + { + *pptIntersect1_ = GetPointInCircle(ptCenter1_, nRadius1_, + DOUBLE_EQU(_nLegalStartAngle1, _nLegalEndAngle2) ? _nLegalStartAngle1 : _nLegalEndAngle1); + } + return 1; + } + // 无交点 --- wanghong 2010 09 09 + return 0; + } + + DPOINT2 _ptIntersect1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersect2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + // 通过圆弧1对应的圆与圆弧2求交,获得“可能是交点”的点集 --- wanghong 2010 09 09 + int _nImageIntersect = Intersect_CircleWithArc(ptCenter1_, nRadius1_, + ptCenter2_, nRadius2_, nStartAngle2_, nSweptAngle2_, &_ptIntersect1, &_ptIntersect2); + if (_nImageIntersect < 1) + return _nImageIntersect; + + bool _bPt1Exist = + IsPointInArc(_ptIntersect1, ptCenter1_, nRadius1_, nStartAngle1_, fabs(nSweptAngle1_), DOUBLE_GREAT_ZERO(nSweptAngle1_)); + bool _bPt2Exist = false; + if (_nImageIntersect == 2) + { // 避免相切时重复计算 --- wanghong 2010 09 09 + _bPt2Exist = + IsPointInArc(_ptIntersect2, ptCenter1_, nRadius1_, nStartAngle1_, fabs(nSweptAngle1_), DOUBLE_GREAT_ZERO(nSweptAngle1_)); + } + // 存在两个交点 --- wanghong 2010 09 09 + if (_bPt1Exist && _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersect1; + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersect2; + return 2; + } + // 存在一个交点 --- wanghong 2010 09 09 + if (_bPt1Exist || _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _bPt1Exist ? _ptIntersect1 : _ptIntersect2; + return 1; + } + + return 0; +} + +int ncmath::Intersect_ArcWithArc(IN const DPOINT2& ptCenter1_, + IN double nRadius1_, + IN double nStartAngle1_, + IN double nSweptAngle1_, + IN const DPOINT2& ptCenter2_, + IN double nRadius2_, + IN double nStartAngle2_, + IN double nSweptAngle2_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 2*/) +{ + ASSERT(IsValidDouble(ptCenter1_.x) && IsValidDouble(ptCenter1_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius1_)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle1_) && DOUBLE_LESS(nStartAngle1_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle1_)) && DOUBLE_LE(fabs(nSweptAngle1_), 2 * ncmath::c_nPIE)); + ASSERT(IsValidDouble(ptCenter2_.x) && IsValidDouble(ptCenter2_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius2_)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle2_) && DOUBLE_LESS(nStartAngle2_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle2_)) && DOUBLE_LE(fabs(nSweptAngle2_), 2 * ncmath::c_nPIE)); + + DPOINT2 _ptIntersect[2] = {DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE)}; + int _nIntersect = Intersect_ArcWithArc(ptCenter1_, nRadius1_, nStartAngle1_, nSweptAngle1_, + ptCenter2_, nRadius2_, nStartAngle2_, nSweptAngle2_, _ptIntersect, _ptIntersect + 1); + // nIntersectsNeed_ 取-1时,由于要求返回所有的交点,等同于值为2的情形 --- wanghong 2010 09 09 + if (nIntersectsNeed_ <= -1) + nIntersectsNeed_ = 2; + + int _nMinIntersect = min(_nIntersect == -1 ? 2 : _nIntersect, nIntersectsNeed_); + std::copy(_ptIntersect, _ptIntersect + _nMinIntersect, std::back_inserter(vectorIntersect_)); + + return _nIntersect; +} + +int ncmath::Intersect_ArcWithEllipse(IN const DPOINT2& ptArcCenter_, + IN double nRadius_, + IN double nStartAngle_, + IN double nSweptAngle_, + IN const DPOINT2& ptEllipseCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL */, + OUT DPOINT2* pptIntersect2_/* = NULL */, + OUT DPOINT2* pptIntersect3_/* = NULL */, + OUT DPOINT2* pptIntersect4_/* = NULL */) +{ + ASSERT(IsValidDouble(nStartAngle_)); + ASSERT(IsValidDouble(nSweptAngle_)); + + if (DOUBLE_EQU_ZERO(nSweptAngle_)) + return 0; + + int _nNum = 0; + DPOINT2 _ptIntersect[4]; + + _nNum = Intersect_CircleWithEllipse(ptArcCenter_, nRadius_, ptEllipseCenter_, nURadius_, nVRadius_, + nUAngle_, &_ptIntersect[0], &_ptIntersect[1], &_ptIntersect[2], &_ptIntersect[3]); + + int _nCount = 0; + for (int _nIndex = 0; _nIndex < _nNum; _nIndex++) + { + // 把在圆弧上的交点保存起来 Wanglou 2010-09-16 + if (IsPointInArc(_ptIntersect[_nIndex], ptArcCenter_, nRadius_, nStartAngle_, nSweptAngle_, true)) + { + _ptIntersect[_nCount] = _ptIntersect[_nIndex]; + _nCount++; + } + } + + for (int _i = _nCount; _i < 4; _i++) + { + _ptIntersect[_i] = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + } + + if (pptIntersect1_) + *pptIntersect1_ = _ptIntersect[0]; + if (pptIntersect2_) + *pptIntersect2_ = _ptIntersect[1]; + if (pptIntersect3_) + *pptIntersect3_ = _ptIntersect[2]; + if (pptIntersect4_) + *pptIntersect4_ = _ptIntersect[3]; + + // 如果部分重合,返回-1 + int _nRet = _nCount; + if (_nNum == -1) + _nRet = -1; + + return _nRet; +} + +int ncmath::Intersect_ArcWithEllipse(IN const DPOINT2& ptArcCenter_, + IN double nRadius_, + IN double nStartAngle_, + IN double nSweptAngle_, + IN const DPOINT2& ptEllipseCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 4 */) +{ + ASSERT(vectorIntersect_.empty()); + ASSERT(nIntersectsNeed_ >= -1); + + // 保存交点 + DPOINT2 _ptIntersects[4]; + int _nNeed = (nIntersectsNeed_ < 0 || nIntersectsNeed_ >= 4) ? 4 : nIntersectsNeed_; + + // 调用C风格版 + int _nRet = Intersect_ArcWithEllipse( + ptArcCenter_, nRadius_, nStartAngle_, nSweptAngle_, ptEllipseCenter_, nURadius_, nVRadius_, nUAngle_, + _nNeed >= 1 ? &_ptIntersects[0] : NULL, + _nNeed >= 2 ? &_ptIntersects[1] : NULL, + _nNeed >= 3 ? &_ptIntersects[2] : NULL, + _nNeed >= 4 ? &_ptIntersects[3] : NULL); + ASSERT(_nRet >= -1 && _nRet <= 4); + + // 收集交点 + vectorIntersect_.clear(); + for (int _i = 0; _i < _nRet && _i < _nNeed; _i++) + { + ASSERT(IsValidDouble(_ptIntersects[_i].x) && IsValidDouble(_ptIntersects[_i].y)); + vectorIntersect_.push_back(_ptIntersects[_i]); + } + + return _nRet; +} + +int ncmath::Intersect_ArcWithEllipseArc(IN const DPOINT2& ptArcCenter_, + IN double nRadius_, + IN double nArcStartAngle_, + IN double nArcSweptAngle_, + IN const DPOINT2& ptEllipseCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + IN double nEllipseArcStartAngle_, + IN double nEllipseArcSweptAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL */, + OUT DPOINT2* pptIntersect2_/* = NULL */, + OUT DPOINT2* pptIntersect3_/* = NULL */, + OUT DPOINT2* pptIntersect4_/* = NULL */) +{ + ASSERT(IsValidDouble(nArcStartAngle_)); + ASSERT(IsValidDouble(nArcSweptAngle_)); + ASSERT(IsValidDouble(nEllipseArcStartAngle_)); + ASSERT(IsValidDouble(nEllipseArcSweptAngle_)); + + // 如果圆弧的圆心角或者椭圆弧的中心角为0,则认为没有交点 Wanglou 2010-09-16 + if (DOUBLE_EQU_ZERO(nArcSweptAngle_) || DOUBLE_EQU_ZERO(nEllipseArcSweptAngle_)) + return 0; + + int _nNum = 0; + DPOINT2 _ptIntersect[4]; + + _nNum = Intersect_CircleWithEllipse(ptArcCenter_, nRadius_, ptEllipseCenter_, nURadius_, nVRadius_, + nUAngle_, &_ptIntersect[0], &_ptIntersect[1], &_ptIntersect[2], &_ptIntersect[3]); + + int _nCount = 0; + for (int _nIndex = 0; _nIndex < _nNum; _nIndex++) + { + // 把在圆弧上的交点保存起来 Wanglou 2010-09-16 + if (IsPointInArc(_ptIntersect[_nIndex], ptArcCenter_, nRadius_, nArcStartAngle_, nArcSweptAngle_, true) && + IsPointInEllipseArc(_ptIntersect[_nIndex], ptEllipseCenter_, nURadius_, nVRadius_, nUAngle_, + nEllipseArcStartAngle_, nEllipseArcSweptAngle_, true)) + { + _ptIntersect[_nCount] = _ptIntersect[_nIndex]; + _nCount++; + } + } + + for (int _i = _nCount; _i < 4; _i++) + { + _ptIntersect[_i] = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + } + + if (pptIntersect1_) + *pptIntersect1_ = _ptIntersect[0]; + if (pptIntersect2_) + *pptIntersect2_ = _ptIntersect[1]; + if (pptIntersect3_) + *pptIntersect3_ = _ptIntersect[2]; + if (pptIntersect4_) + *pptIntersect4_ = _ptIntersect[3]; + + // 如果部分重合,返回-1 + int _nRet = _nCount; + if (_nNum == -1) + _nRet = -1; + + return _nRet; +} + +int ncmath::Intersect_ArcWithEllipseArc(IN const DPOINT2& ptArcCenter_, + IN double nRadius_, + IN double nArcStartAngle_, + IN double nArcSweptAngle_, + IN const DPOINT2& ptEllipseCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + IN double nEllipseArcStartAngle_, + IN double nEllipseArcSweptAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_ /* = 4 */) + +{ + ASSERT(vectorIntersect_.empty()); + ASSERT(nIntersectsNeed_ >= -1); + + // 保存交点 + DPOINT2 _ptIntersects[4]; + int _nNeed = (nIntersectsNeed_ < 0 || nIntersectsNeed_ >= 4) ? 4 : nIntersectsNeed_; + + // 调用C风格版 + int _nRet = Intersect_ArcWithEllipseArc( + ptArcCenter_, nRadius_, nArcStartAngle_, nArcSweptAngle_, ptEllipseCenter_, + nURadius_, nVRadius_, nUAngle_, nEllipseArcStartAngle_, nEllipseArcSweptAngle_, + _nNeed >= 1 ? &_ptIntersects[0] : NULL, + _nNeed >= 2 ? &_ptIntersects[1] : NULL, + _nNeed >= 3 ? &_ptIntersects[2] : NULL, + _nNeed >= 4 ? &_ptIntersects[3] : NULL); + ASSERT(_nRet >= -1 && _nRet <= 4); + + // 收集交点 + vectorIntersect_.clear(); + for (int _i = 0; _i < _nRet && _i < _nNeed; _i++) + { + ASSERT(IsValidDouble(_ptIntersects[_i].x) && IsValidDouble(_ptIntersects[_i].y)); + vectorIntersect_.push_back(_ptIntersects[_i]); + } + + return _nRet; +} + +namespace +{ + // 已知 acost + bsint = c,求(cost,sint);返回解的个数 + // 方程不处理a、b同时为0的情形 --- wanghong 2010 09 21 + int SolveTrgEquation(double nA_, double nB_, double nC_, DPOINT2 ptRes_[2]) + { + ASSERT(!DOUBLE_EQU_ZERO(nA_) || !DOUBLE_EQU_ZERO(nB_)); + double _nA2 = nA_ * nA_; + double _nB2 = nB_ * nB_; + double _nC2 = nC_ * nC_; + + double _nDst = _nA2 + _nB2 - _nC2; + // 此时无解 --- wanghong 2010 09 25 + if (DOUBLE_LESS_ZERO(_nDst)) + return 0; + + // 记录解的个数 --- wanghong 2010 09 25 + int _nIndex = 0; + + if (DOUBLE_EQU_ZERO(nB_)) + { + ptRes_[_nIndex].x = nA_ * nC_ / (_nA2 + _nB2); + // 这里因为需要判断结果为0.0,因此需要使用容差;如此,会允许出现极小负数的情形, + // 为了正确的使用sqrt,使用了fabs 取其绝对值 --- wanghong 2010 09 25 + ASSERT(DOUBLE_GE_ZERO(1.0 - ptRes_[_nIndex].x * ptRes_[_nIndex].x)); + ptRes_[_nIndex].y = sqrt(fabs(1.0 - ptRes_[_nIndex].x * ptRes_[_nIndex].x)); + _nIndex += 1; + + if (!DOUBLE_EQU_ZERO(ptRes_[_nIndex-1].y)) + { + ptRes_[_nIndex].x = ptRes_[_nIndex-1].x; + ptRes_[_nIndex].y = -ptRes_[_nIndex-1].y; + _nIndex += 1; + } + + return _nIndex; + } + // 此时有1解 --- wanghong 2010 09 25 + if (DOUBLE_EQU_ZERO(_nDst)) + { + ptRes_[_nIndex].x = nA_ * nC_ / (_nA2 + _nB2); + ptRes_[_nIndex].y = (nC_ - nA_ * ptRes_[_nIndex].x) / nB_; + + return ++_nIndex; + } + // 此时有2解 --- wanghong 2010 09 25 + double _nTmp = fabs(nB_) * sqrt(_nDst); + ptRes_[_nIndex].x = (nA_ * nC_ + _nTmp) / (_nA2 + _nB2); + ptRes_[_nIndex].y = (nC_ - nA_ * ptRes_[_nIndex].x) / nB_; + _nIndex += 1; + + ptRes_[_nIndex].x = (nA_ * nC_ - _nTmp) / (_nA2 + _nB2); + ptRes_[_nIndex].y = (nC_ - nA_ * ptRes_[_nIndex].x) / nB_; + _nIndex += 1; + + return _nIndex; + } +} + +namespace +{ + // 获得直线上的一点 --- wanghong 2010 09 19 + DPOINT2 GetSecondPoint(const DPOINT2& ptBeeline_, double nBeelineAngle_) + { + if (DOUBLE_EQU(nBeelineAngle_, ncmath::c_nPIE/2) || DOUBLE_EQU(nBeelineAngle_, ncmath::c_nPIE*3/2)) + { + return DPOINT2(ptBeeline_.x, ptBeeline_.y + 1); + } + + return DPOINT2(ptBeeline_.x + 1, ptBeeline_.y + tan(nBeelineAngle_)); + } +} + +// 首先在UV坐标系中求得交点,再转换到XY坐标系下 --- wanghong 2010 09 13 +int ncmath::Intersect_BeelineWithEllipse(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptBeeline_.x) && IsValidDouble(ptBeeline_.y) + && nBeelineAngle_ >= 0.0 && nBeelineAngle_ < 2.0 * c_nPIE); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y) + && DOUBLE_GREAT_ZERO(nVRadius_) && DOUBLE_GE(nURadius_, nVRadius_) + && nUAngle_ >= 0.0 && nUAngle_ < 2.0 * c_nPIE); + + // 由于后面的计算是通过联立一次曲线方程与二次曲线方程解一元二次方程来求曲线 + // 交点的,而解一元二次方程时的等根判别较为困难,因此,为避免不必要的误差问 + // 题,在此先将相切情况挑出来特殊处理了。 ---- 杨开锦 2010-09-25 + DPOINT2 _ptTangent1; + DPOINT2 _ptTangent2; + GetTangentPointOfEllipse(ptCenter_, nURadius_, nVRadius_, RegularizeIncludedRadian(nUAngle_), + RegularizeIncludedRadian(nBeelineAngle_), &_ptTangent1, &_ptTangent2); + ASSERT(IsValidDouble(_ptTangent1.x) && IsValidDouble(_ptTangent1.y) + && IsValidDouble(_ptTangent2.x) && IsValidDouble(_ptTangent2.y) + && DOUBLE_NOT_ZERO((_ptTangent1 - _ptTangent2).GetLength())); + double _nDist1 = D2GetPointToBeelineDistance(_ptTangent1, ptBeeline_, RegularizeIncludedRadian(nBeelineAngle_)); + if (DOUBLE_EQU_ZERO(_nDist1)) + { + *pptIntersect1_ = _ptTangent1; + *pptIntersect2_ = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + return 1; + } + double _nDist2 = D2GetPointToBeelineDistance(_ptTangent1, ptBeeline_, RegularizeIncludedRadian(nBeelineAngle_)); + if (DOUBLE_EQU_ZERO(_nDist2)) + { + *pptIntersect1_ = _ptTangent2; + *pptIntersect2_ = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + return 1; + } + + // 变换到UV坐标系(即把椭圆变换为标准椭圆) ---- 杨开锦 2010-09-21 + DPOINT2 _ptBeelineUV = CoorTransXYToUV(ptBeeline_, ptCenter_, nUAngle_); + double _nBeelineAngleUV = RegularizeIncludedRadian(nBeelineAngle_ - nUAngle_); + double _a = nURadius_; + double _b = nVRadius_; + double _a2 = _a * _a; + double _b2 = _b * _b; + + // 在UV坐标系上求交点 ---- 杨开锦 2010-09-21 + DPOINT2 _ptIntersects[2] = + { + DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), + DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), + }; + + ASSERT(_nBeelineAngleUV >= 0.0 && _nBeelineAngleUV < c_nPIE); + if (DOUBLE_LE(_nBeelineAngleUV, 0.25 * c_nPIE) || DOUBLE_GE(_nBeelineAngleUV, 0.75 * c_nPIE)) + { + // 直线与X轴夹角较小,此时直线方程可写为 y = kx + d, 联立直线与椭圆方程可 + // 解交点。 + // 将直线方程 y = kx + d, 代入椭圆方程 x^2/a^2 + y^2/b^2 = 1 可得方程 + // (b^2/a^2 + k^2)*x^2 + (2*k*d)*x + (d^2 - b^2) = 0 ---- 杨开锦 2010-09-21 + double _k = tan(_nBeelineAngleUV); + double _d = _ptBeelineUV.y - _k * _ptBeelineUV.x; + double _nA = _b2 / _a2 + _k * _k; + double _nB = 2.0 * _k * _d; + double _nC = _d * _d - _b2; + double _x1; + double _x2; + int _n = SolveQuadraticEquation(_nA, _nB, _nC, &_x1, &_x2); + ASSERT(_n == 0 || _n == 1 || _n == 2); + + if (_n >= 1) + { + _ptIntersects[0].x = _x1; + _ptIntersects[0].y = _k * _x1 + _d; + ASSERT(IsPointInEllipse(_ptIntersects[0], DPOINT2(0.0, 0.0), _a, _b, 0.0)); + } + + if (_n >= 2) + { + _ptIntersects[1].x = _x2; + _ptIntersects[1].y = _k * _x2 + _d; + ASSERT(IsPointInEllipse(_ptIntersects[1], DPOINT2(0.0, 0.0), _a, _b, 0.0)); + } + } + else + { + // 直线与X轴夹角较大,此时直线方程可写为 x = ky + d, 联立直线与椭圆方程可 + // 解交点。 + // 将直线方程 x = ky + d, 代入椭圆方程 x^2/a^2 + y^2/b^2 = 1 可得方程 + // (a^2/b^2 + k^2)*y^2 + (2*k*d)*y + (d^2 - a^2) = 0 ---- 杨开锦 2010-09-21 + double _k = tan(0.5 * c_nPIE - _nBeelineAngleUV); + double _d = _ptBeelineUV.x - _k * _ptBeelineUV.y; + double _nA = _a2 / _b2 + _k * _k; + double _nB = 2.0 * _k * _d; + double _nC = _d * _d - _a2; + double _y1; + double _y2; + int _n = SolveQuadraticEquation(_nA, _nB, _nC, &_y1, &_y2); + ASSERT(_n == 0 || _n == 1 || _n == 2); + + if (_n >= 1) + { + _ptIntersects[0].x = _k * _y1 + _d; + _ptIntersects[0].y = _y1; + ASSERT(IsPointInEllipse(_ptIntersects[0], DPOINT2(0.0, 0.0), _a, _b, 0.0)); + } + + if (_n >= 2) + { + _ptIntersects[1].x = _k * _y2 + _d; + _ptIntersects[1].y = _y2; + ASSERT(IsPointInEllipse(_ptIntersects[1], DPOINT2(0.0, 0.0), _a, _b, 0.0)); + } + } + + // 回到XY坐标 ---- 杨开锦 2010-09-21 + int _nIntersect = 0; + + if (IsValidDouble(_ptIntersects[0].x) && IsValidDouble(_ptIntersects[0].y)) + { + _nIntersect++; + _ptIntersects[0] = CoorTransUVToXY(_ptIntersects[0], ptCenter_, nUAngle_); + } + + if (IsValidDouble(_ptIntersects[1].x) && IsValidDouble(_ptIntersects[1].y)) + { + _nIntersect++; + _ptIntersects[1] = CoorTransUVToXY(_ptIntersects[1], ptCenter_, nUAngle_); + } + + // 产出 ---- 杨开锦 2010-09-21 + *pptIntersect1_ = _ptIntersects[0]; + *pptIntersect2_ = _ptIntersects[1]; + + return _nIntersect; + + // 以下代码有问题,暂屏蔽之,改用上面的求解办法,待其完善后再恢复之 ---- 杨开锦 2010-09-21 + ASSERT(FALSE); + + ASSERT(IsValidDouble(ptBeeline_.x) && IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GE_ZERO(nBeelineAngle_) && DOUBLE_LESS(nBeelineAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(nVRadius_) && DOUBLE_GE(nURadius_, nVRadius_)); + ASSERT(DOUBLE_GE_ZERO(nUAngle_) && DOUBLE_LESS(nUAngle_, 2 * ncmath::c_nPIE)); + + // 从直线上取两点A、B,并转换到UV坐标系,以下运算均在UV坐标系下 --- wanghong 2010 09 13 + DPOINT2 _ptBeelineA = CoorTransXYToUV(ptBeeline_, ptCenter_, nUAngle_); + DPOINT2 _ptBeelineB = CoorTransXYToUV(GetSecondPoint(ptBeeline_, nBeelineAngle_), ptCenter_, nUAngle_); + // 自坐标原点到A、B两点的向量 --- wanghong 2010 09 13 + VectorD2D _vecBeelineA(_ptBeelineA.x, _ptBeelineA.y); + VectorD2D _vecBeelineB(_ptBeelineB.x, _ptBeelineB.y); + // 直线AB的向量以及垂直向量 --- wanghong 2010 09 13 + VectorD2D _vecAB = _vecBeelineB - _vecBeelineA; + VectorD2D _vecABPlumb(-_vecAB.y, _vecAB.x); + // 以下依据[NcMath/Doc/设计说明书-求交函数]中的直线与椭圆求交公式计算交点坐标 --- wanghong 2010 09 19 + DPOINT2 _ptRes[2] = {DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE)}; + // 为了避免产生较大误差,考虑将传入三角方程的系数除以一定倍率 --- wanghong 2010 09 25 + double nDiv = _vecBeelineA * _vecABPlumb; + int _nCount = 0; + if (DOUBLE_EQU_ZERO(nDiv)) + { // 此时倍率计为 nURadius_ * nVRadius_ --- wanghong 2010 09 25 + _nCount = SolveTrgEquation(_vecABPlumb.x / nVRadius_, _vecABPlumb.y / nURadius_, .0, _ptRes); + } + else + { // 此时倍率计为 _vecBeelineA * _vecABPlumb --- wanghong 2010 09 25 + _nCount = SolveTrgEquation(nURadius_ * _vecABPlumb.x / nDiv, nVRadius_ * _vecABPlumb.y / nDiv, 1.0, _ptRes); + } + + if (_nCount == 0) + { + return 0; + } + // 将UV坐标系下的交点转换到XY坐标系下 --- wanghong 2010 09 13 + if (pptIntersect1_ != NULL) + *pptIntersect1_ = CoorTransUVToXY(DPOINT2(nURadius_ * _ptRes[0].x, nVRadius_ * _ptRes[0].y), ptCenter_, nUAngle_); + + if (_nCount == 2) + { + if (pptIntersect2_ != NULL) + *pptIntersect2_ = CoorTransUVToXY(DPOINT2(nURadius_ * _ptRes[1].x, nVRadius_ * _ptRes[1].y), ptCenter_, nUAngle_); + } + + return _nCount; +} + +int ncmath::Intersect_BeelineWithEllipse(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 2*/) +{ + ASSERT(IsValidDouble(ptBeeline_.x) && IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nVRadius_) && DOUBLE_GE(nURadius_, nVRadius_)); + ASSERT(DOUBLE_GE_ZERO(nUAngle_) && DOUBLE_LESS(nUAngle_, 2 * ncmath::c_nPIE)); + + DPOINT2 _ptIntersect[2] = {DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE)}; + int _nIntersect = Intersect_BeelineWithEllipse(ptBeeline_, nBeelineAngle_, + ptCenter_, nURadius_, nVRadius_, nUAngle_, _ptIntersect, _ptIntersect + 1); + // nIntersectsNeed_ 取-1时,由于要求返回所有的交点,等同于值为2的情形 --- wanghong 2010 09 13 + if (nIntersectsNeed_ <= -1) + nIntersectsNeed_ = 2; + + int _nMinIntersect = min(_nIntersect, nIntersectsNeed_); + std::copy(_ptIntersect, _ptIntersect + _nMinIntersect, std::back_inserter(vectorIntersect_)); + + return _nIntersect; +} + +namespace +{ + bool IsPointInEllipseArc_impl(IN const DPOINT2& ptTarget_, + IN const DPOINT2& ptCenter_, + IN double nSlopeAngle_, + IN double nStartAngle_, + IN double nCentralAngle_, + IN bool bIsNormalDir_) + { + // 自椭圆弧中心至目标点的向量角度 --- wanghong 2010 9 16 + double _nTargetAngle = D2GetNormalAngle(ptTarget_ - ptCenter_); + + // 这里需注意,真正需要的起始角并不是nStartAngle_ --- wanghong 2010 09 16 + return IsAngleInSector(_nTargetAngle, nStartAngle_ + nSlopeAngle_, nCentralAngle_, bIsNormalDir_); + } +} + +int ncmath::Intersect_BeelineWithEllipseArc(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptBeeline_.x) && IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nVRadius_) && DOUBLE_GE(nURadius_, nVRadius_)); + ASSERT(DOUBLE_GE_ZERO(nUAngle_) && DOUBLE_LESS(nUAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle_) && DOUBLE_LESS(nStartAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && DOUBLE_LE(fabs(nSweptAngle_), 2 * ncmath::c_nPIE)); + + // 通过直线与椭圆弧所在的椭圆求交,获得“可能是交点”的点集 --- wanghong 2010 09 13 + DPOINT2 _ptIntersect1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersect2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + + int _nImageIntersect = Intersect_BeelineWithEllipse(ptBeeline_, nBeelineAngle_, + ptCenter_, nURadius_, nVRadius_, nUAngle_, &_ptIntersect1, &_ptIntersect2); + + if (_nImageIntersect < 1) + return _nImageIntersect; + + bool _bPt1Exist = + IsPointInEllipseArc_impl(_ptIntersect1, ptCenter_, nUAngle_, + nStartAngle_, fabs(nSweptAngle_), DOUBLE_GREAT_ZERO(nSweptAngle_)); + bool _bPt2Exist = false; + if (_nImageIntersect == 2) + { + _bPt2Exist = + IsPointInEllipseArc_impl(_ptIntersect2, ptCenter_, nUAngle_, + nStartAngle_, fabs(nSweptAngle_), DOUBLE_GREAT_ZERO(nSweptAngle_)); + } + // 存在两个交点 --- wanghong 2010 09 13 + if (_bPt1Exist && _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersect1; + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersect2; + return 2; + } + // 存在一个交点 --- wanghong 2010 09 13 + if (_bPt1Exist || _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _bPt1Exist ? _ptIntersect1 : _ptIntersect2; + return 1; + } + + return 0; +} + +int ncmath::Intersect_BeelineWithEllipseArc(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 2*/) +{ + ASSERT(IsValidDouble(ptBeeline_.x) && IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nURadius_) && DOUBLE_GREAT_ZERO(nVRadius_)); + ASSERT(DOUBLE_GE_ZERO(nUAngle_) && DOUBLE_LESS(nUAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle_) && DOUBLE_LESS(nStartAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && DOUBLE_LE(fabs(nSweptAngle_), 2 * ncmath::c_nPIE)); + + DPOINT2 _ptIntersect[2] = {DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE)}; + int _nIntersect = Intersect_BeelineWithEllipseArc(ptBeeline_, nBeelineAngle_, ptCenter_, nURadius_, nVRadius_, nUAngle_, + nStartAngle_, nSweptAngle_, _ptIntersect, _ptIntersect + 1); + // nIntersectsNeed_ 取-1时,由于要求返回所有的交点,等同于值为2的情形 --- wanghong 2010 09 13 + if (nIntersectsNeed_ <= -1) + nIntersectsNeed_ = 2; + + int _nMinIntersect = min(_nIntersect, nIntersectsNeed_); + std::copy(_ptIntersect, _ptIntersect + _nMinIntersect, std::back_inserter(vectorIntersect_)); + + return _nIntersect; +} + +int ncmath::Intersect_LineWithEllipse(IN const DPOINT2& ptStart_, + IN const DPOINT2& ptEnd_, + IN const DPOINT2& ptCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptStart_.x) && IsValidDouble(ptStart_.y)); + ASSERT(IsValidDouble(ptEnd_.x) && IsValidDouble(ptEnd_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nVRadius_) && DOUBLE_GE(nURadius_, nVRadius_)); + ASSERT(DOUBLE_GE_ZERO(nUAngle_) && DOUBLE_LESS(nUAngle_, 2 * ncmath::c_nPIE)); + + DPOINT2 _ptIntersec1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersec2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + // 通过线段对应的直线与椭圆求交,获得“可能是交点”的点集 --- wanghong 2010 09 14 + int _nImageIntersect = Intersect_BeelineWithEllipse(ptStart_,ncmath::D2GetNormalAngle(ptEnd_ - ptStart_), + ptCenter_, nURadius_, nVRadius_, nUAngle_, &_ptIntersec1, &_ptIntersec2); + if (_nImageIntersect < 1) + return _nImageIntersect; + + bool _bPt1Exist = IsPointInLine(_ptIntersec1, ptStart_, ptEnd_); + bool _bPt2Exist = false; + if (_nImageIntersect == 2) + { + _bPt2Exist = IsPointInLine(_ptIntersec2, ptStart_, ptEnd_); + } + // 存在两个交点 --- wanghong 2010 09 14 + if (_bPt1Exist && _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersec1; + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersec2; + return 2; + } + // 存在一个交点 --- wanghong 2010 09 14 + if (_bPt1Exist || _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _bPt1Exist ? _ptIntersec1 : _ptIntersec2; + return 1; + } + + return 0; +} + +int ncmath::Intersect_LineWithEllipse(IN const DPOINT2& ptStart_, + IN const DPOINT2& ptEnd_, + IN const DPOINT2& ptCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 2*/) +{ + ASSERT(IsValidDouble(ptStart_.x) && IsValidDouble(ptStart_.y)); + ASSERT(IsValidDouble(ptEnd_.x) && IsValidDouble(ptEnd_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nVRadius_) && DOUBLE_GE(nURadius_, nVRadius_)); + ASSERT(DOUBLE_GE_ZERO(nUAngle_) && DOUBLE_LESS(nUAngle_, 2 * ncmath::c_nPIE)); + + DPOINT2 _ptIntersect[2] = {DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE)}; + int _nIntersect = Intersect_LineWithEllipse(ptStart_, ptEnd_, ptCenter_, nURadius_, nVRadius_, nUAngle_, + _ptIntersect, _ptIntersect + 1); + // nIntersectsNeed_ 取-1时,由于要求返回所有的交点,等同于值为2的情形 --- wanghong 2010 09 14 + if (nIntersectsNeed_ <= -1) + nIntersectsNeed_ = 2; + + int _nMinIntersect = min(_nIntersect, nIntersectsNeed_); + std::copy(_ptIntersect, _ptIntersect + _nMinIntersect, std::back_inserter(vectorIntersect_)); + + return _nIntersect; +} + +int ncmath::Intersect_LineWithEllipseArc(IN const DPOINT2& ptStart_, + IN const DPOINT2& ptEnd_, + IN const DPOINT2& ptCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptStart_.x) && IsValidDouble(ptStart_.y)); + ASSERT(IsValidDouble(ptEnd_.x) && IsValidDouble(ptEnd_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nVRadius_) && DOUBLE_GE(nURadius_, nVRadius_)); + ASSERT(DOUBLE_GE_ZERO(nUAngle_) && DOUBLE_LESS(nUAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle_) && DOUBLE_LESS(nStartAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && DOUBLE_LE(fabs(nSweptAngle_), 2 * ncmath::c_nPIE)); + DPOINT2 _ptIntersec1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersec2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + // 通过线段对应的直线与椭圆求交,获得“可能是交点”的点集 --- wanghong 2010 09 14 + int _nImageIntersect = Intersect_BeelineWithEllipseArc(ptStart_,ncmath::D2GetNormalAngle(ptEnd_ - ptStart_), + ptCenter_, nURadius_, nVRadius_, nUAngle_, nStartAngle_, nSweptAngle_, &_ptIntersec1, &_ptIntersec2); + if (_nImageIntersect < 1) + return _nImageIntersect; + + bool _bPt1Exist = IsPointInLine(_ptIntersec1, ptStart_, ptEnd_); + bool _bPt2Exist = false; + if (_nImageIntersect == 2) + { + _bPt2Exist = IsPointInLine(_ptIntersec2, ptStart_, ptEnd_); + } + // 存在两个交点 --- wanghong 2010 09 14 + if (_bPt1Exist && _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersec1; + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersec2; + return 2; + } + // 存在一个交点 --- wanghong 2010 09 14 + if (_bPt1Exist || _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _bPt1Exist ? _ptIntersec1 : _ptIntersec2; + return 1; + } + + return 0; +} + +int ncmath::Intersect_LineWithEllipseArc(IN const DPOINT2& ptStart_, + IN const DPOINT2& ptEnd_, + IN const DPOINT2& ptCenter_, + IN double nURadius_, + IN double nVRadius_, + IN double nUAngle_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 2*/) +{ + ASSERT(IsValidDouble(ptStart_.x) && IsValidDouble(ptStart_.y)); + ASSERT(IsValidDouble(ptEnd_.x) && IsValidDouble(ptEnd_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nVRadius_) && DOUBLE_GE(nURadius_, nVRadius_)); + ASSERT(DOUBLE_GE_ZERO(nUAngle_) && DOUBLE_LESS(nUAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle_) && DOUBLE_LESS(nStartAngle_, 2 * ncmath::c_nPIE)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && DOUBLE_LE(fabs(nSweptAngle_), 2 * ncmath::c_nPIE)); + + DPOINT2 _ptIntersect[2] = {DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE), DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE)}; + int _nIntersect = Intersect_LineWithEllipseArc(ptStart_, ptEnd_, + ptCenter_, nURadius_, nVRadius_, nUAngle_, nStartAngle_, nSweptAngle_, _ptIntersect, _ptIntersect + 1); + // nIntersectsNeed_ 取-1时,由于要求返回所有的交点,等同于值为2的情形 --- wanghong 2010 09 14 + if (nIntersectsNeed_ <= -1) + nIntersectsNeed_ = 2; + + int _nMinIntersect = min(_nIntersect, nIntersectsNeed_); + std::copy(_ptIntersect, _ptIntersect + _nMinIntersect, std::back_inserter(vectorIntersect_)); + + return _nIntersect; +} + +// 以下空间内的函数是供Intersect_EllipseWithEllipse用的局部函数 ---- 杨开锦 2010-09-17 +namespace Intersect_EllipseWithEllipse_Implement +{ + // 椭圆。长半轴应不短于短半轴,长轴倾角在[0, 2PI)。 ---- 杨开锦 2010-09-17 + struct Ellipse + { + DPOINT2 ptCenter; + double nURadius; + double nVRadius; + double nUAngle; + }; + + // 椭圆弧。起始角在[0, 2PI),扫过角在(0, 2PI),仅表示逆时针扫过。起始角表示 + // 相对椭圆长轴倾角的角;起始角、扫过角均指直观角,而不是椭圆参数方程中的角 + // 值Theta。 ---- 杨开锦 2010-09-17 + struct EllipseArc : public Ellipse + { + double nStartAngle; + double nSweptAngle; + }; + + // 将一个椭圆分成四个单调的椭圆弧(y对x单调)。即以x向切线切点、y向切线切点将 + // 椭圆分为四个弧段。 ---- 杨开锦 2010-09-17 + void DivideEllipseIntoFourMonotonousArc( + IN const Ellipse& Ellipse_, + OUT EllipseArc* pEllipseArc1_, + OUT EllipseArc* pEllipseArc2_, + OUT EllipseArc* pEllipseArc3_, + OUT EllipseArc* pEllipseArc4_) + { + // 出口参数检查 ---- 杨开锦 2010-09-17 + ASSERT(pEllipseArc1_ && pEllipseArc2_ && pEllipseArc3_ && pEllipseArc4_); + + // 椭圆参数 ---- 杨开锦 2010-09-17 + DPOINT2 _ptC = Ellipse_.ptCenter; + double _a = Ellipse_.nURadius; + double _b = Ellipse_.nVRadius; + double _nTheta = Ellipse_.nUAngle; + ASSERT(IsValidDouble(_ptC.x) && IsValidDouble(_ptC.y) + && _a >= _b && DOUBLE_GREAT_ZERO(_b) + && _nTheta >= 0 && _nTheta < 2.0 * c_nPIE); + + // 求四个边界点,并求出其对应的四个角 ---- 杨开锦 2010-09-17 + DPOINT2 _ptTangents[4]; + GetTangentPointOfEllipse(_ptC, _a, _b, RegularizeIncludedRadian(_nTheta), 0.0, + &_ptTangents[0], &_ptTangents[2]); + GetTangentPointOfEllipse(_ptC, _a, _b, RegularizeIncludedRadian(_nTheta), 0.5 * c_nPIE, + &_ptTangents[1], &_ptTangents[3]); + double _nAngles[4]; + for (int _i = 0; _i < 4; _i++) + { + DPOINT2 _vec = _ptTangents[_i] - _ptC; + ASSERT(DOUBLE_GREAT_ZERO(_vec.GetLength())); + _nAngles[_i] = D2GetNormalAngle(_vec); + } + + // 求出减去椭圆长轴倾角后的相对倾角值 ---- 杨开锦 2010-09-17 + for (int _i = 0; _i < 4; _i++) + { + double _nAngle = _nAngles[_i] - _nTheta; + NormalizeRadian(_nAngle); + _nAngles[_i] = _nAngle; + } + + // 排序,按相对倾角从小到大排 ---- 杨开锦 2010-09-17 + for (int _i = 0; _i < 4; _i++) + { + for (int _j = _i + 1; _j < 4; _j++) + { + ASSERT(!DOUBLE_EQU(_nAngles[_j], _nAngles[_i])); + if (_nAngles[_j] < _nAngles[_i]) + { + double _nTemp = _nAngles[_i]; + _nAngles[_i] = _nAngles[_j]; + _nAngles[_j] = _nTemp; + } + } + } + + // 构造为椭圆弧段并产出 ---- 杨开锦 2010-09-17 + EllipseArc* _pEllipseArcs[4] = + { + pEllipseArc1_, + pEllipseArc2_, + pEllipseArc3_, + pEllipseArc4_, + }; + for (int _i = 0; _i < 4; _i++) + { + _pEllipseArcs[_i]->ptCenter = _ptC; + _pEllipseArcs[_i]->nURadius = _a; + _pEllipseArcs[_i]->nVRadius = _b; + _pEllipseArcs[_i]->nUAngle = _nTheta; + _pEllipseArcs[_i]->nStartAngle = _nAngles[_i]; + _pEllipseArcs[_i]->nSweptAngle = RegularizeRadian(_nAngles[(_i + 1) % 4] - _nAngles[_i]); + } + } + + // 二分迭代法求两段单调弧的交点,在调用本函数前就已经确定两弧在此x区间有且只 + // 有一个交点。 ---- 杨开锦 2010-09-18 + void Intersect_MonotonousEllipseArcWithMonotonousEllipseArc_OnlyOne( + IN const EllipseArc& EllipseArc1_, + IN const EllipseArc& EllipseArc2_, + IN const double& nXLeft_, + IN const double& nXRight_, + OUT DPOINT2* pptIntersect_) + { + ASSERT(IsValidDouble(nXLeft_) && IsValidDouble(nXRight_) && DOUBLE_LESS(nXLeft_, nXRight_)); + ASSERT(pptIntersect_); + + // 椭圆弧参数 ---- 杨开锦 2010-09-18 + DPOINT2 _ptC1 = EllipseArc1_.ptCenter; + double _a1 = EllipseArc1_.nURadius; + double _b1 = EllipseArc1_.nVRadius; + double _nTheta1 = EllipseArc1_.nUAngle; + double _nStart1 = EllipseArc1_.nStartAngle; + double _nSwept1 = EllipseArc1_.nSweptAngle; + ASSERT(IsValidDouble(_ptC1.x) && IsValidDouble(_ptC1.y) + && _a1 >= _b1 && DOUBLE_GREAT_ZERO(_b1) + && _nTheta1 >= 0 && _nTheta1 < 2.0 * c_nPIE + && _nStart1 >= 0 && _nStart1 < 2.0 * c_nPIE + && DOUBLE_GREAT_ZERO(_nSwept1) && _nSwept1 < 2.0 * c_nPIE); + DPOINT2 _ptC2 = EllipseArc2_.ptCenter; + double _a2 = EllipseArc2_.nURadius; + double _b2 = EllipseArc2_.nVRadius; + double _nTheta2 = EllipseArc2_.nUAngle; + double _nStart2 = EllipseArc2_.nStartAngle; + double _nSwept2 = EllipseArc2_.nSweptAngle; + ASSERT(IsValidDouble(_ptC2.x) && IsValidDouble(_ptC2.y) + && _a2 >= _b2 && DOUBLE_GREAT_ZERO(_b2) + && _nTheta2 >= 0 && _nTheta2 < 2.0 * c_nPIE + && _nStart2 >= 0 && _nStart2 < 2.0 * c_nPIE + && DOUBLE_GREAT_ZERO(_nSwept2) && _nSwept2 < 2.0 * c_nPIE); + + // 两弧的左右端点 ---- 杨开锦 2010-09-18 + DPOINT2 _ptLeft1; + DPOINT2 _ptLeft2; + DPOINT2 _ptRight1; + DPOINT2 _ptRight2; + int _n; + _n = Intersect_BeelineWithEllipseArc(DPOINT2(nXLeft_, 0.0), 0.5 * c_nPIE, + _ptC1, _a1, _b1, _nTheta1, _nStart1, _nSwept1, + &_ptLeft1); + ASSERT(_n == 1); + _n = Intersect_BeelineWithEllipseArc(DPOINT2(nXLeft_, 0.0), 0.5 * c_nPIE, + _ptC2, _a2, _b2, _nTheta2, _nStart2, _nSwept2, + &_ptLeft2); + ASSERT(_n == 1); + _n = Intersect_BeelineWithEllipseArc(DPOINT2(nXRight_, 0.0), 0.5 * c_nPIE, + _ptC1, _a1, _b1, _nTheta1, _nStart1, _nSwept1, + &_ptRight1); + ASSERT(_n == 1); + _n = Intersect_BeelineWithEllipseArc(DPOINT2(nXRight_, 0.0), 0.5 * c_nPIE, + _ptC2, _a2, _b2, _nTheta2, _nStart2, _nSwept2, + &_ptRight2); + ASSERT(_n == 1); + + // 左右端y值差必须为异号 ---- 杨开锦 2010-09-18 + double _nDyLeft = _ptLeft1.y - _ptLeft2.y; + double _nDyRight = _ptRight1.y - _ptRight2.y; + ASSERT(DOUBLE_NOT_ZERO(_nDyLeft) && DOUBLE_NOT_ZERO(_nDyRight) + && DOUBLE_LESS_ZERO(_nDyLeft * _nDyRight)); + + // 二分求解 ---- 杨开锦 2010-09-18 + DPOINT2 _ptMid1; + DPOINT2 _ptMid2; + while (DOUBLE_GREAT(_ptRight1.x, _ptLeft1.x)) + { + double _nMid = (_ptRight1.x + _ptLeft1.x) / 2.0; + int _n = Intersect_BeelineWithEllipseArc(DPOINT2(_nMid, 0.0), 0.5 * c_nPIE, + _ptC1, _a1, _b1, _nTheta1, _nStart1, _nSwept1, &_ptMid1); + ASSERT(_n == 1); + _n = Intersect_BeelineWithEllipseArc(DPOINT2(_nMid, 0.0), 0.5 * c_nPIE, + _ptC2, _a2, _b2, _nTheta2, _nStart2, _nSwept2, &_ptMid2); + ASSERT(_n == 1); + if (DOUBLE_EQU(_ptMid1.y, _ptMid2.y)) + { + break; + } + else if ((_ptLeft1.y - _ptLeft2.y) * (_ptMid1.y - _ptMid2.y) > 0.0) + { + _ptLeft1 = _ptMid1; + _ptLeft2 = _ptMid2; + } + else + { + _ptRight1 = _ptMid1; + _ptRight2 = _ptMid2; + } + } + + ASSERT(DOUBLE_EQU(_ptMid1.x, _ptMid2.x)); + *pptIntersect_ = (_ptMid1 + _ptMid2) / 2.0; + } + + // 已知两个单调椭圆弧,求该两弧的交点。此外不考虑重合的情况,重合须另行处理。 + // 求解办法来自于王搂找到的论文( 《图形系统中实用椭圆求交快速算法的研究和 + // 实现》 华中理工大学 罗年猛等 工程图学学报 2000年 第3期 ),请参见论文,在 + // 此不再赘述。 ---- 杨开锦 2010-09-18 + int Intersect_MonotonousEllipseArcWithMonotonousEllipseArc( + IN const EllipseArc& EllipseArc1_, + IN const EllipseArc& EllipseArc2_, + OUT DPOINT2* pptIntersect1_ = NULL, + OUT DPOINT2* pptIntersect2_ = NULL) + { + // 出口参数检查 ---- 杨开锦 2010-09-18 + ASSERT(pptIntersect1_ && pptIntersect2_ + || pptIntersect1_ && !pptIntersect2_ + || !pptIntersect1_ && !pptIntersect2_); + + // 为方便短路退出,先产出无效值 ---- 杨开锦 2010-09-18 + if (pptIntersect1_) + { + pptIntersect1_->x = c_nINVALID_DOUBLE; + pptIntersect1_->y = c_nINVALID_DOUBLE; + } + + if (pptIntersect2_) + { + pptIntersect2_->x = c_nINVALID_DOUBLE; + pptIntersect2_->y = c_nINVALID_DOUBLE; + } + + // 椭圆弧参数 ---- 杨开锦 2010-09-18 + DPOINT2 _ptC1 = EllipseArc1_.ptCenter; + double _a1 = EllipseArc1_.nURadius; + double _b1 = EllipseArc1_.nVRadius; + double _nTheta1 = EllipseArc1_.nUAngle; + double _nStart1 = EllipseArc1_.nStartAngle; + double _nSwept1 = EllipseArc1_.nSweptAngle; + ASSERT(IsValidDouble(_ptC1.x) && IsValidDouble(_ptC1.y) + && _a1 >= _b1 && DOUBLE_GREAT_ZERO(_b1) + && _nTheta1 >= 0 && _nTheta1 < 2.0 * c_nPIE + && _nStart1 >= 0 && _nStart1 < 2.0 * c_nPIE + && DOUBLE_GREAT_ZERO(_nSwept1) && _nSwept1 < 2.0 * c_nPIE); + DPOINT2 _ptC2 = EllipseArc2_.ptCenter; + double _a2 = EllipseArc2_.nURadius; + double _b2 = EllipseArc2_.nVRadius; + double _nTheta2 = EllipseArc2_.nUAngle; + double _nStart2 = EllipseArc2_.nStartAngle; + double _nSwept2 = EllipseArc2_.nSweptAngle; + ASSERT(IsValidDouble(_ptC2.x) && IsValidDouble(_ptC2.y) + && _a2 >= _b2 && DOUBLE_GREAT_ZERO(_b2) + && _nTheta2 >= 0 && _nTheta2 < 2.0 * c_nPIE + && _nStart2 >= 0 && _nStart2 < 2.0 * c_nPIE + && DOUBLE_GREAT_ZERO(_nSwept2) && _nSwept2 < 2.0 * c_nPIE); + + // 两弧的左右端点 ---- 杨开锦 2010-09-18 + DPOINT2 _ptLeft1 = GetPointInEllipse(_ptC1, _a1, _b1, _nTheta1, _nStart1); + DPOINT2 _ptRight1 = GetPointInEllipse(_ptC1, _a1, _b1, _nTheta1, RegularizeRadian(_nStart1 + _nSwept1)); + if (_ptLeft1.x > _ptRight1.x) + { + DPOINT2 _ptTmp = _ptLeft1; + _ptLeft1 = _ptRight1; + _ptRight1 = _ptTmp; + } + DPOINT2 _ptLeft2 = GetPointInEllipse(_ptC2, _a2, _b2, _nTheta2, _nStart2); + DPOINT2 _ptRight2 = GetPointInEllipse(_ptC2, _a2, _b2, _nTheta2, RegularizeRadian(_nStart2 + _nSwept2)); + if (_ptLeft2.x > _ptRight2.x) + { + DPOINT2 _ptTmp = _ptLeft2; + _ptLeft2 = _ptRight2; + _ptRight2 = _ptTmp; + } + + // 若无重叠的x区域则显然无交 ---- 杨开锦 2010-09-18 + if (DOUBLE_GREAT(_ptLeft1.x, _ptRight2.x) || DOUBLE_GREAT(_ptLeft2.x, _ptRight1.x)) + { + return 0; + } + + // 确定解的x范围 ---- 杨开锦 2010-09-18 + DPOINT2 _ptTemp; + int _nTemp; + // 左端 + _nTemp = Intersect_BeelineWithEllipseArc(_ptLeft1, 0.5 * c_nPIE, + _ptC2, _a2, _b2, _nTheta2, _nStart2, _nSwept2, + &_ptTemp); + ASSERT(_nTemp == 0 || _nTemp == 1); + if (_nTemp == 1) + { + _ptLeft2 = _ptTemp; + } + else + { + _nTemp = Intersect_BeelineWithEllipseArc(_ptLeft2, 0.5 * c_nPIE, + _ptC1, _a1, _b1, _nTheta1, _nStart1, _nSwept1, + &_ptTemp); + ASSERT(_nTemp == 1); + _ptLeft1 = _ptTemp; + } + // 右端 + _nTemp = Intersect_BeelineWithEllipseArc(_ptRight1, 0.5 * c_nPIE, + _ptC2, _a2, _b2, _nTheta2, _nStart2, _nSwept2, + &_ptTemp); + ASSERT(_nTemp == 0 || _nTemp == 1); + if (_nTemp == 1) + { + _ptRight2 = _ptTemp; + } + else + { + _nTemp = Intersect_BeelineWithEllipseArc(_ptRight2, 0.5 * c_nPIE, + _ptC1, _a1, _b1, _nTheta1, _nStart1, _nSwept1, + &_ptTemp); + ASSERT(_nTemp == 1); + _ptRight1 = _ptTemp; + } + + // 若无重叠的y区域则显然无交 ---- 杨开锦 2010-09-18 + if (DOUBLE_GREAT(_ptLeft1.y, _ptLeft2.y) && DOUBLE_GREAT(_ptLeft1.y, _ptRight2.y) + && DOUBLE_GREAT(_ptRight1.y, _ptLeft2.y) && DOUBLE_GREAT(_ptRight1.y, _ptRight2.y) + || DOUBLE_GREAT(_ptLeft2.y, _ptLeft1.y) && DOUBLE_GREAT(_ptLeft2.y, _ptRight1.y) + && DOUBLE_GREAT(_ptRight2.y, _ptLeft1.y) && DOUBLE_GREAT(_ptRight2.y, _ptRight1.y)) + { + return 0; + } + + // 准备出口和返回值 ---- 杨开锦 2010-09-18 + int _nIntersect = 0; + DPOINT2* _pIntersects[2] = + { + pptIntersect1_, + pptIntersect2_, + }; + + // 根据两端的y值差分情况处理 ---- 杨开锦 2010-09-18 + double _nDyLeft = _ptLeft1.y - _ptLeft2.y; + double _nDyRight = _ptRight1.y - _ptRight2.y; + if (DOUBLE_EQU_ZERO(_nDyLeft) || DOUBLE_EQU_ZERO(_nDyRight)) + { + // y值差为0,马上得出交点 ---- 杨开锦 2010-09-18 + if (DOUBLE_EQU_ZERO(_nDyLeft)) + { + *_pIntersects[_nIntersect] = _ptLeft1; + _nIntersect++; + } + + if (DOUBLE_EQU_ZERO(_nDyRight)) + { + *_pIntersects[_nIntersect] = _ptRight1; + _nIntersect++; + } + } + else if (_nDyLeft * _nDyRight < 0.0) + { + // y值差异号,有且仅有一个交点 ---- 杨开锦 2010-09-18 + if (_pIntersects[_nIntersect]) + { + Intersect_MonotonousEllipseArcWithMonotonousEllipseArc_OnlyOne(EllipseArc1_, EllipseArc2_, + _ptLeft1.x, _ptRight1.x, _pIntersects[_nIntersect]); + } + + _nIntersect++; + } + else + { + // y值差同号,根据倾角差分情况处理 ---- 杨开锦 2010-09-18 +#define MyNormalize(x_, b_) { if (DOUBLE_EQU(x_, 0.5 * c_nPIE)) x_ *= (b_ > 0.0) ? 1.0 : -1.0; else if (x_ > 0.5 * c_nPIE) x_ -= c_nPIE; } + double _nAngleLeft1 = GetTangentAngleOfEllipse(_ptC1, _a1, _b1, RegularizeIncludedRadian(_nTheta1), _ptLeft1); + MyNormalize(_nAngleLeft1, _ptRight1.y - _ptLeft1.y); + double _nAngleLeft2 = GetTangentAngleOfEllipse(_ptC2, _a2, _b2, RegularizeIncludedRadian(_nTheta2), _ptLeft2); + MyNormalize(_nAngleLeft2, _ptRight2.y - _ptLeft2.y); + double _nAngleRight1 = GetTangentAngleOfEllipse(_ptC1, _a1, _b1, RegularizeIncludedRadian(_nTheta1), _ptRight1); + MyNormalize(_nAngleRight1, _ptRight1.y - _ptLeft1.y); + double _nAngleRight2 = GetTangentAngleOfEllipse(_ptC2, _a2, _b2, RegularizeIncludedRadian(_nTheta2), _ptRight2); + MyNormalize(_nAngleRight2, _ptRight2.y - _ptLeft2.y); + + if (DOUBLE_EQU_ZERO(_nAngleLeft1 - _nAngleLeft2) + || DOUBLE_EQU_ZERO(_nAngleRight1 - _nAngleRight2) + || (_nAngleLeft1 - _nAngleLeft2) * (_nAngleRight1 - _nAngleRight2) > 0.0) + { + // 倾角差同号,无交点 ---- 杨开锦 2010-09-18 + } + else + { + // 倾角差异号,求倾角相同处的x值,根据此处的y值差判断是否有交 ---- 杨开锦 2010-09-18 + DPOINT2 _ptL1 = _ptLeft1; + DPOINT2 _ptL2 = _ptLeft2; + DPOINT2 _ptR1 = _ptRight1; + DPOINT2 _ptR2 = _ptRight2; + DPOINT2 _ptMid1; + DPOINT2 _ptMid2; + // 二分法求倾角相同处的x值 ---- 杨开锦 2010-09-18 + while (DOUBLE_GREAT(_ptR1.x, _ptL1.x)) + { + double _nMidX = (_ptL1.x + _ptR1.x) / 2.0; + int _n = Intersect_BeelineWithEllipseArc(DPOINT2(_nMidX, 0.0), 0.5 * c_nPIE, + _ptC1, _a1, _b1, _nTheta1, _nStart1, _nSwept1, &_ptMid1); + ASSERT(_n == 1); + _n = Intersect_BeelineWithEllipseArc(DPOINT2(_nMidX, 0.0), 0.5 * c_nPIE, + _ptC2, _a2, _b2, _nTheta2, _nStart2, _nSwept2, &_ptMid2); + ASSERT(_n == 1); + + double _nAngleMid1 = GetTangentAngleOfEllipse(_ptC1, _a1, _b1, RegularizeIncludedRadian(_nTheta1), _ptMid1); + MyNormalize(_nAngleMid1, _ptRight1.y - _ptLeft1.y); + double _nAngleMid2 = GetTangentAngleOfEllipse(_ptC2, _a2, _b2, RegularizeIncludedRadian(_nTheta2), _ptMid2); + MyNormalize(_nAngleMid2, _ptRight2.y - _ptLeft2.y); + if (DOUBLE_EQU(_nAngleMid1, _nAngleMid2)) + { + break; + } + else if ((_nAngleLeft1 - _nAngleLeft2) * (_nAngleMid1 - _nAngleMid2) > 0.0) + { + _ptL1 = _ptMid1; + _ptL2 = _ptMid2; + } + else + { + _ptR1 = _ptMid1; + _ptR2 = _ptMid2; + } + } + ASSERT(DOUBLE_EQU(_ptMid1.x, _ptMid2.x)); + + // 根据倾角相等处的y值差判断交点个数 ---- 杨开锦 2010-09-18 + double _nDyMid = _ptMid1.y - _ptMid2.y; + if (DOUBLE_EQU_ZERO(_nDyMid)) + { + // y值差为零,正好为交点 + if (_pIntersects[_nIntersect]) + { + *_pIntersects[_nIntersect] = _ptMid1; + } + + _nIntersect++; + } + else if (_nDyMid * _nDyLeft > 0.0) + { + // y值差与两端同号,无交点 + } + else + { + // y值差与两端异号,有两个交点,两边各一 + if (_pIntersects[_nIntersect]) + { + Intersect_MonotonousEllipseArcWithMonotonousEllipseArc_OnlyOne(EllipseArc1_, EllipseArc2_, + _ptLeft1.x, _ptMid1.x, _pIntersects[_nIntersect]); + } + _nIntersect++; + + if (_pIntersects[_nIntersect]) + { + Intersect_MonotonousEllipseArcWithMonotonousEllipseArc_OnlyOne(EllipseArc1_, EllipseArc2_, + _ptMid1.x, _ptRight1.x, _pIntersects[_nIntersect]); + } + _nIntersect++; + } + } +#undef MyNormalize + } + + ASSERT(_nIntersect >= 0 && _nIntersect <= 2); + return _nIntersect; + } +} + +// ************************************************************************** // +// 椭圆与椭圆交点。 +// +// ******************** Version 2 ******************* +// 求解办法: +// (1)首先剔除重合情况,对于非重合情况,进入以下步骤处理。 +// (2)对两椭圆各分成4段单调弧(x对y单调),将问题转化为解4X4单调弧交点问题; +// (3)对两单调弧先作x裁剪,将两弧裁剪为同一个x区间。 +// (4)根据弧端点处的y差值关系判别是否有且仅有一个解:若两端y值差乘积为零,则零 +// 差值处有交;若乘积为负,则有且仅有一个解;若乘积为正则进入(5)进一步判断。 +// (5)根据弧端点处的y导数差值(亦即切向倾角差)关系判别是否无解: 若两端倾角差乘 +// 积非负,则无交点;否则进入(6)进一步判断。 +// (6)根据弧中y导数值(倾角值)相同处的y差值关系判别解个数(0,1,2): 首先以二分法 +// 求出y导数值(倾角值)相同处的两点, 若y差值为零,则此处即为交点;若y差值与 +// 两端的y差值同号,则无交点;否则有两个交点,分别在此处的两侧。 +// (7)以上均为解个数判别,对于有解区间,可用二分法迭代求解之。 +// 注:该办法的优点是 - 解正确,不丢失应有的解;没有过于复杂的数学计算,通过将问 +// 题分解为一次曲线与二次曲线求交问题;复杂度很好,使用二分迭代法,复杂度为logN; +// 无解情况可以快速收敛,因为单调弧的外接矩形很容易求,外接矩形无交的两弧必无交。 +// 该算法来自于王搂找到的论文《图形系统中实用椭圆求交快速算法的研究和实现》 华 +// 中理工大学 罗年猛等 工程图学学报 2000年 第3期 , 具体分析与论述请参见该论文。 +// ---- 杨开锦 2010-09-18 +// +// ******************** Version 1 ******************* +// 求解办法: +// (1)做坐标变换,变换到椭圆1的UV坐标系上,即把椭圆1变换为标准椭圆; +// (2)将椭圆2分成N份,即N段椭圆弧,通过弧两端是否在椭圆1的同测判别该弧是否与椭 +// 圆1有交,若有交则保存起来; +// (3)对有交点的椭圆弧段用二分逼近法求出交点。 +// 注:该办法 = 粗分弧段 + 搜索交点。分段办法是对椭圆参数方程中的角度值Theta进行 +// 均分;分段的粒度我选的是1度,即180分之一弧度。 +// 该法的缺点是,很容易丢失相切交点、相距较近的两个交点; 优点是,算法简单,收 +// 敛性可控(基本是定值)。 +// 该办法虽很可能丢失有效交点,但所幸的是,其求出的交点都是正确的交点。 +// ---- 杨开锦 2010-09-14 +// ************************************************************************** // +int ncmath::Intersect_EllipseWithEllipse( + IN const DPOINT2& ptCenter1_, IN double nURadius1_, IN double nVRadius1_, IN double nUAngle1_, + IN const DPOINT2& ptCenter2_, IN double nURadius2_, IN double nVRadius2_, IN double nUAngle2_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/, + OUT DPOINT2* pptIntersect3_/* = NULL*/, + OUT DPOINT2* pptIntersect4_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptCenter1_.x) && IsValidDouble(ptCenter1_.y) + && nURadius1_ >= nVRadius1_ && DOUBLE_GREAT_ZERO(nVRadius1_) + && nUAngle1_ >= 0 && nUAngle1_ < 2.0 * c_nPIE); + ASSERT(IsValidDouble(ptCenter2_.x) && IsValidDouble(ptCenter2_.y) + && nURadius2_ >= nVRadius2_ && DOUBLE_GREAT_ZERO(nVRadius2_) + && nUAngle2_ >= 0 && nUAngle2_ < 2.0 * c_nPIE); + ASSERT(pptIntersect1_ && pptIntersect2_ && pptIntersect3_ && pptIntersect4_ + || pptIntersect1_ && pptIntersect2_ && pptIntersect3_ && !pptIntersect4_ + || pptIntersect1_ && pptIntersect2_ && !pptIntersect3_ && !pptIntersect4_ + || pptIntersect1_ && !pptIntersect2_ && !pptIntersect3_ && !pptIntersect4_ + || !pptIntersect1_ && !pptIntersect2_ && !pptIntersect3_ && !pptIntersect4_); + + // 为方便程序行文中的短路退出,此处先对出口参数产出无效值 ---- 杨开锦 2010-09-15 + DPOINT2* _pptOuts[4]; + _pptOuts[0] = pptIntersect1_; + _pptOuts[1] = pptIntersect2_; + _pptOuts[2] = pptIntersect3_; + _pptOuts[3] = pptIntersect4_; + for (int _i = 0; _i < 4; _i++) + { + if (_pptOuts[_i]) + { + *_pptOuts[_i] = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + } + } + + // 处理椭圆形式的重合 ---- 杨开锦 2010-09-14 + if (DOUBLE_EQU(ptCenter1_.x, ptCenter2_.x) && DOUBLE_EQU(ptCenter1_.y, ptCenter2_.y) + && DOUBLE_EQU(nURadius1_, nURadius2_) && DOUBLE_EQU(nVRadius1_, nVRadius2_) + && (DOUBLE_EQU(nUAngle1_, nUAngle2_) || DOUBLE_EQU(nUAngle1_ + c_nPIE, nUAngle2_) || DOUBLE_EQU(nUAngle1_, nUAngle2_ + c_nPIE))) + { + return -1; + } + + // 处理退化为圆形式的重合 ---- 杨开锦 2010-09-15 + if (DOUBLE_EQU(ptCenter1_.x, ptCenter2_.x) && DOUBLE_EQU(ptCenter1_.y, ptCenter2_.y) + && DOUBLE_EQU(nURadius1_, nVRadius1_) && DOUBLE_EQU(nURadius2_, nVRadius2_) + && DOUBLE_EQU(nURadius1_, nURadius2_)) + { + return -1; + } + + // 两椭圆相离或相含,无交点 ---- 杨开锦 2010-09-16 + double _nCenterDist = (ptCenter2_ - ptCenter1_).GetLength(); + if (DOUBLE_LESS(nURadius1_ + nURadius2_, _nCenterDist) + || DOUBLE_LESS(_nCenterDist + nURadius1_, nVRadius2_) + || DOUBLE_LESS(_nCenterDist + nURadius2_, nVRadius1_)) + { + return 0; + } + + using namespace Intersect_EllipseWithEllipse_Implement; + typedef Intersect_EllipseWithEllipse_Implement::Ellipse Ellipse; + typedef Intersect_EllipseWithEllipse_Implement::EllipseArc EllipseArc; + + // 分解为四段单调弧 ---- 杨开锦 2010-09-18 + Ellipse _Ellipse1; + _Ellipse1.ptCenter = ptCenter1_; + _Ellipse1.nURadius = nURadius1_; + _Ellipse1.nVRadius = nVRadius1_; + _Ellipse1.nUAngle = nUAngle1_; + Ellipse _Ellipse2; + _Ellipse2.ptCenter = ptCenter2_; + _Ellipse2.nURadius = nURadius2_; + _Ellipse2.nVRadius = nVRadius2_; + _Ellipse2.nUAngle = nUAngle2_; + EllipseArc _Ellipse1Arcs[4]; + EllipseArc _Ellipse2Arcs[4]; + DivideEllipseIntoFourMonotonousArc(_Ellipse1, + &_Ellipse1Arcs[0], &_Ellipse1Arcs[1],&_Ellipse1Arcs[2],&_Ellipse1Arcs[3]); + DivideEllipseIntoFourMonotonousArc(_Ellipse2, + &_Ellipse2Arcs[0], &_Ellipse2Arcs[1],&_Ellipse2Arcs[2],&_Ellipse2Arcs[3]); + + // 单调弧间求交 ---- 杨开锦 2010-09-18 + std::vector _vectorIntersects; + for (int _i = 0; _i < 4; _i++) + { + for (int _j = 0; _j < 4; _j++) + { + DPOINT2 _ptIntersect1; + DPOINT2 _ptIntersect2; + int _n = Intersect_MonotonousEllipseArcWithMonotonousEllipseArc( + _Ellipse1Arcs[_i], _Ellipse2Arcs[_j], &_ptIntersect1, &_ptIntersect2); + + if (_n >= 1) + { + _vectorIntersects.push_back(_ptIntersect1); + } + + if (_n >= 2) + { + _vectorIntersects.push_back(_ptIntersect2); + } + } + } + + // 处理分割单调弧时正好在交点处分割的情况 ---- 杨开锦 2010-09-18 + for (std::vector::iterator _it = _vectorIntersects.begin(); + _it != _vectorIntersects.end(); _it++) + { + for (std::vector::iterator _itTemp = _it + 1; + _itTemp != _vectorIntersects.end(); ) + { + DPOINT2& _pt1 = *_it; + DPOINT2& _pt2 = *_itTemp; + if (DOUBLE_EQU(_pt1.x, _pt2.x) && DOUBLE_EQU(_pt1.y, _pt2.y)) + { + _itTemp = _vectorIntersects.erase(_itTemp); + } + else + { + _itTemp++; + } + } + } + ASSERT(_vectorIntersects.size() <= 4); + + // 产出交点 ---- 杨开锦 2010-09-18 + for (UINT _i = 0; _i < 4; _i++) + { + if (_pptOuts[_i]) + { + if (_vectorIntersects.size() > _i) + { + *_pptOuts[_i] = _vectorIntersects[_i]; + } + else + { + _pptOuts[_i]->x = c_nINVALID_DOUBLE; + _pptOuts[_i]->y = c_nINVALID_DOUBLE; + } + } + } + + // 返回交点个数 ---- 杨开锦 2010-09-18 + return (int)(_vectorIntersects.size()); +} + +int ncmath::Intersect_EllipseWithEllipse( + IN const DPOINT2& ptCenter1_, IN double nURadius1_, IN double nVRadius1_, IN double nUAngle1_, + IN const DPOINT2& ptCenter2_, IN double nURadius2_, IN double nVRadius2_, IN double nUAngle2_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 4*/) +{ + ASSERT(vectorIntersect_.empty()); + ASSERT(nIntersectsNeed_ >= -1); + + // 带出交点 ---- 杨开锦 2010-09-14 + DPOINT2 _ptIntersects[4]; + // 需要带出多少个 ---- 杨开锦 2010-09-14 + int _nNeed = (nIntersectsNeed_ < 0 || nIntersectsNeed_ >= 4) ? 4 : nIntersectsNeed_; + + // 调用C风格版 ---- 杨开锦 2010-09-14 + int _nRet = Intersect_EllipseWithEllipse( + ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_, + ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, + _nNeed >= 1 ? &_ptIntersects[0] : NULL, + _nNeed >= 2 ? &_ptIntersects[1] : NULL, + _nNeed >= 3 ? &_ptIntersects[2] : NULL, + _nNeed >= 4 ? &_ptIntersects[3] : NULL); + ASSERT(_nRet >= -1 && _nRet <= 4); + + // 收集交点 ---- 杨开锦 2010-09-14 + vectorIntersect_.clear(); + for (int _i = 0; _i < _nRet && _i < _nNeed; _i++) + { + ASSERT(IsValidDouble(_ptIntersects[_i].x) && IsValidDouble(_ptIntersects[_i].y)); + vectorIntersect_.push_back(_ptIntersects[_i]); + } + + return _nRet; +} + +// 通过调用椭圆与椭圆求交来完成 ---- 杨开锦 2010-09-14 +int ncmath::Intersect_EllipseWithEllipseArc( + IN const DPOINT2& ptCenter1_, IN double nURadius1_, IN double nVRadius1_, IN double nUAngle1_, + IN const DPOINT2& ptCenter2_, IN double nURadius2_, IN double nVRadius2_, IN double nUAngle2_, + IN double nStartAngle_, IN double nSweptAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/, + OUT DPOINT2* pptIntersect3_/* = NULL*/, + OUT DPOINT2* pptIntersect4_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptCenter1_.x) && IsValidDouble(ptCenter1_.y) + && nURadius1_ >= nVRadius1_ && DOUBLE_GREAT_ZERO(nVRadius1_) + && nUAngle1_ >= 0 && nUAngle1_ < 2.0 * c_nPIE); + ASSERT(IsValidDouble(ptCenter2_.x) && IsValidDouble(ptCenter2_.y) + && nURadius2_ >= nVRadius2_ && DOUBLE_GREAT_ZERO(nVRadius2_) + && nUAngle2_ >= 0 && nUAngle2_ < 2.0 * c_nPIE + && nStartAngle_ >= 0 && nStartAngle_ < 2.0 * c_nPIE + && DOUBLE_GREAT_ZERO(nSweptAngle_) && nSweptAngle_ < 2.0 * c_nPIE); + ASSERT(pptIntersect1_ && pptIntersect2_ && pptIntersect3_ && pptIntersect4_ + || pptIntersect1_ && pptIntersect2_ && pptIntersect3_ && !pptIntersect4_ + || pptIntersect1_ && pptIntersect2_ && !pptIntersect3_ && !pptIntersect4_ + || pptIntersect1_ && !pptIntersect2_ && !pptIntersect3_ && !pptIntersect4_ + || !pptIntersect1_ && !pptIntersect2_ && !pptIntersect3_ && !pptIntersect4_); + + // 调用Intersect_EllipseWithEllipse,求两椭圆的交点 ---- 杨开锦 2010-09-14 + DPOINT2 _ptIntersects[4]; + int _nRet = Intersect_EllipseWithEllipse( + ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_, + ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, + &_ptIntersects[0], + &_ptIntersects[1], + &_ptIntersects[2], + &_ptIntersects[3]); + ASSERT(_nRet >= -1 && _nRet <= 4); + + // 求椭圆弧两端点 ---- 杨开锦 2010-09-25 + DPOINT2 _ptStart = GetPointInEllipse(ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, nStartAngle_); + DPOINT2 _ptEnd = GetPointInEllipse(ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, RegularizeRadian(nStartAngle_ + nSweptAngle_)); + + // 判断求出来的交点是否在椭圆弧上,若是则产出 ---- 杨开锦 2010-09-14 + DPOINT2* _pptOuts[4]; + _pptOuts[0] = pptIntersect1_; + _pptOuts[1] = pptIntersect2_; + _pptOuts[2] = pptIntersect3_; + _pptOuts[3] = pptIntersect4_; + int _nIntersect = 0; + for (int _i = 0; _i < _nRet && _i < 4; _i++) + { + // 处理第_i个交点 ---- 杨开锦 2010-09-14 + DPOINT2 _ptCurIntersect = _ptIntersects[_i]; + + // 该交点与椭圆弧中心的倾角 ---- 杨开锦 2010-09-14 + DPOINT2 _vec = _ptCurIntersect - ptCenter2_; + double _nAngle = atan2(_vec.y, _vec.x); + + // 该倾角对椭圆弧的长半轴的夹角 ---- 杨开锦 2010-09-14 + _nAngle = _nAngle - nUAngle2_; + + // 该倾角对椭圆弧起始角的夹角 ---- 杨开锦 2010-09-14 + _nAngle = _nAngle - nStartAngle_; + + // 在椭圆弧上则产出 ---- 杨开锦 2010-09-14 + NormalizeRadian(_nAngle); + if (_nAngle >= 0.0 && _nAngle <= nSweptAngle_ + || DOUBLE_EQU_ZERO((_ptCurIntersect - _ptStart).GetLength()) + || DOUBLE_EQU_ZERO((_ptCurIntersect - _ptEnd).GetLength())) + { + if (_pptOuts[_nIntersect]) + { + *_pptOuts[_nIntersect] = _ptCurIntersect; + } + + _nIntersect++; + } + } + + // 向多余的出口参数产出无效值 ---- 杨开锦 2010-09-15 + for (int _i = _nIntersect; _i < 4; _i++) + { + if (_pptOuts[_i]) + { + *_pptOuts[_i] = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + } + } + + return _nIntersect; +} + +int ncmath::Intersect_EllipseWithEllipseArc( + IN const DPOINT2& ptCenter1_, IN double nURadius1_, IN double nVRadius1_, IN double nUAngle1_, + IN const DPOINT2& ptCenter2_, IN double nURadius2_, IN double nVRadius2_, IN double nUAngle2_, + IN double nStartAngle_, IN double nSweptAngle_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 4*/) +{ + ASSERT(vectorIntersect_.empty()); + ASSERT(nIntersectsNeed_ >= -1); + + // 带出交点 ---- 杨开锦 2010-09-14 + DPOINT2 _ptIntersects[4]; + // 需要带出多少个 ---- 杨开锦 2010-09-14 + int _nNeed = (nIntersectsNeed_ < 0 || nIntersectsNeed_ >= 4) ? 4 : nIntersectsNeed_; + + // 调用C风格版 ---- 杨开锦 2010-09-14 + int _nRet = Intersect_EllipseWithEllipseArc( + ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_, + ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, nStartAngle_, nSweptAngle_, + _nNeed >= 1 ? &_ptIntersects[0] : NULL, + _nNeed >= 2 ? &_ptIntersects[1] : NULL, + _nNeed >= 3 ? &_ptIntersects[2] : NULL, + _nNeed >= 4 ? &_ptIntersects[3] : NULL); + ASSERT(_nRet >= -1 && _nRet <= 4); + + // 收集交点 ---- 杨开锦 2010-09-14 + vectorIntersect_.clear(); + for (int _i = 0; _i < _nRet && _i < _nNeed; _i++) + { + ASSERT(IsValidDouble(_ptIntersects[_i].x) && IsValidDouble(_ptIntersects[_i].y)); + vectorIntersect_.push_back(_ptIntersects[_i]); + } + + return _nRet; +} + +int ncmath::Intersect_EllipseArcWithEllipseArc( + IN const DPOINT2& ptCenter1_, IN double nURadius1_, IN double nVRadius1_, IN double nUAngle1_, + IN double nStartAngle1_, IN double nSweptAngle1_, + IN const DPOINT2& ptCenter2_, IN double nURadius2_, IN double nVRadius2_, IN double nUAngle2_, + IN double nStartAngle2_, IN double nSweptAngle2_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/, + OUT DPOINT2* pptIntersect3_/* = NULL*/, + OUT DPOINT2* pptIntersect4_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptCenter1_.x) && IsValidDouble(ptCenter1_.y) + && nURadius1_ >= nVRadius1_ && DOUBLE_GREAT_ZERO(nVRadius1_) + && nUAngle1_ >= 0 && nUAngle1_ < 2.0 * c_nPIE + && nStartAngle1_ >= 0 && nStartAngle1_ < 2.0 * c_nPIE + && DOUBLE_GREAT_ZERO(nSweptAngle1_) && nSweptAngle1_ < 2.0 * c_nPIE); + ASSERT(IsValidDouble(ptCenter2_.x) && IsValidDouble(ptCenter2_.y) + && nURadius2_ >= nVRadius2_ && DOUBLE_GREAT_ZERO(nVRadius2_) + && nUAngle2_ >= 0 && nUAngle2_ < 2.0 * c_nPIE + && nStartAngle2_ >= 0 && nStartAngle2_ < 2.0 * c_nPIE + && DOUBLE_GREAT_ZERO(nSweptAngle2_) && nSweptAngle2_ < 2.0 * c_nPIE); + ASSERT(pptIntersect1_ && pptIntersect2_ && pptIntersect3_ && pptIntersect4_ + || pptIntersect1_ && pptIntersect2_ && pptIntersect3_ && !pptIntersect4_ + || pptIntersect1_ && pptIntersect2_ && !pptIntersect3_ && !pptIntersect4_ + || pptIntersect1_ && !pptIntersect2_ && !pptIntersect3_ && !pptIntersect4_ + || !pptIntersect1_ && !pptIntersect2_ && !pptIntersect3_ && !pptIntersect4_); + + // 调用Intersect_EllipseWithEllipse,求两椭圆的交点 ---- 杨开锦 2010-09-14 + DPOINT2 _ptIntersects[4]; + int _nRet = Intersect_EllipseWithEllipse( + ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_, + ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, + &_ptIntersects[0], + &_ptIntersects[1], + &_ptIntersects[2], + &_ptIntersects[3]); + ASSERT(_nRet >= -1 && _nRet <= 4); + + DPOINT2* _pptOuts[4]; + _pptOuts[0] = pptIntersect1_; + _pptOuts[1] = pptIntersect2_; + _pptOuts[2] = pptIntersect3_; + _pptOuts[3] = pptIntersect4_; + int _nIntersect = 0; + + if (_nRet == -1) + { + // 对于所在椭圆重合情况须特别讨论,因为为两椭圆弧所在椭圆重合并不能推出该两 + // 椭圆弧一定重合。 ---- 杨开锦 2010-09-25 + DPOINT2 _ptStart1 = GetPointInEllipse(ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_, nStartAngle1_); + DPOINT2 _ptEnd1 = GetPointInEllipse(ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_, + RegularizeRadian(nStartAngle1_ + nSweptAngle1_)); + DPOINT2 _ptStart2 = GetPointInEllipse(ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, nStartAngle2_); + DPOINT2 _ptEnd2 = GetPointInEllipse(ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, + RegularizeRadian(nStartAngle2_ + nSweptAngle2_)); + if (!IsPointInEllipseArc(_ptStart2, ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_, nStartAngle1_, nSweptAngle1_) + && !IsPointInEllipseArc(_ptEnd2, ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_, nStartAngle1_, nSweptAngle1_) + && !IsPointInEllipseArc(_ptStart1, ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, nStartAngle2_, nSweptAngle2_) + && !IsPointInEllipseArc(_ptEnd1, ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, nStartAngle2_, nSweptAngle2_)) + { + // 无交点 + _nIntersect = 0; + } + else if (DOUBLE_EQU_ZERO((_ptStart1 - _ptEnd2).GetLength()) + && DOUBLE_EQU_ZERO((_ptEnd1 - _ptStart2).GetLength())) + { + // 两个交点 + _nIntersect = 2; + + if (_pptOuts[0]) + *_pptOuts[0] = _ptStart1; + + if (_pptOuts[1]) + *_pptOuts[1] = _ptEnd1; + } + else if (DOUBLE_EQU_ZERO((_ptStart1 - _ptEnd2).GetLength()) + && !IsPointInEllipseArc(_ptEnd1, ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, nStartAngle2_, nSweptAngle2_)) + { + // 1头交于2尾 + _nIntersect = 1; + + if (_pptOuts[0]) + *_pptOuts[0] = _ptStart1; + } + else if (DOUBLE_EQU_ZERO((_ptEnd1 - _ptStart2).GetLength()) + && !IsPointInEllipseArc(_ptStart1, ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, nStartAngle2_, nSweptAngle2_)) + { + // 1尾交于2头 + _nIntersect = 1; + + if (_pptOuts[0]) + *_pptOuts[0] = _ptEnd1; + } + else + { + // 重合 + _nIntersect = -1; + } + } + else + { + // 判断求出来的交点是否同时在椭圆弧1和椭圆弧2上,若是则产出 ---- 杨开锦 2010-09-14 + ASSERT(_nRet >= 0 && _nRet <= 4); + for (int _i = 0; _i < _nRet && _i < 4; _i++) + { + // 处理第_i个交点 ---- 杨开锦 2010-09-14 + DPOINT2 _pt = _ptIntersects[_i]; + ASSERT(IsValidDouble(_pt.x) && IsValidDouble(_pt.y)); + ASSERT(IsPointInEllipse(_pt, ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_) + && IsPointInEllipse(_pt, ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_)); + + // 在同时在两椭圆弧上则产出 ---- 杨开锦 2010-09-14 + if (IsPointInEllipseArc(_pt, ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_, nStartAngle1_, nSweptAngle1_) + && IsPointInEllipseArc(_pt, ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, nStartAngle2_, nSweptAngle2_)) + { + if (_pptOuts[_nIntersect]) + { + *_pptOuts[_nIntersect] = _pt; + } + + _nIntersect++; + } + } + } + + // 向多余的出口参数产出无效值 ---- 杨开锦 2010-09-15 + for (int _i = _nIntersect; _i < 4; _i++) + { + if ((_i >= 0 && _i < 4) && _pptOuts[_i]) + { + *_pptOuts[_i] = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + } + } + + return _nIntersect; +} + +int ncmath::Intersect_EllipseArcWithEllipseArc( + IN const DPOINT2& ptCenter1_, IN double nURadius1_, IN double nVRadius1_, IN double nUAngle1_, + IN double nStartAngle1_, IN double nSweptAngle1_, + IN const DPOINT2& ptCenter2_, IN double nURadius2_, IN double nVRadius2_, IN double nUAngle2_, + IN double nStartAngle2_, IN double nSweptAngle2_, + OUT std::vector& vectorIntersect_, + IN int nIntersectsNeed_/* = 4*/) +{ + ASSERT(vectorIntersect_.empty()); + ASSERT(nIntersectsNeed_ >= -1); + + // 带出交点 ---- 杨开锦 2010-09-14 + DPOINT2 _ptIntersects[4]; + // 需要带出多少个 ---- 杨开锦 2010-09-14 + int _nNeed = (nIntersectsNeed_ < 0 || nIntersectsNeed_ >= 4) ? 4 : nIntersectsNeed_; + + // 调用C风格版 ---- 杨开锦 2010-09-14 + int _nRet = Intersect_EllipseArcWithEllipseArc( + ptCenter1_, nURadius1_, nVRadius1_, nUAngle1_, nStartAngle1_, nSweptAngle1_, + ptCenter2_, nURadius2_, nVRadius2_, nUAngle2_, nStartAngle2_, nSweptAngle2_, + _nNeed >= 1 ? &_ptIntersects[0] : NULL, + _nNeed >= 2 ? &_ptIntersects[1] : NULL, + _nNeed >= 3 ? &_ptIntersects[2] : NULL, + _nNeed >= 4 ? &_ptIntersects[3] : NULL); + ASSERT(_nRet >= -1 && _nRet <= 4); + + // 收集交点 ---- 杨开锦 2010-09-14 + vectorIntersect_.clear(); + for (int _i = 0; _i < _nRet && _i < _nNeed; _i++) + { + ASSERT(IsValidDouble(_ptIntersects[_i].x) && IsValidDouble(_ptIntersects[_i].y)); + vectorIntersect_.push_back(_ptIntersects[_i]); + } + + return _nRet; +} diff --git a/src/LayerParamDlg.cpp b/src/LayerParamDlg.cpp new file mode 100644 index 0000000..8e83834 --- /dev/null +++ b/src/LayerParamDlg.cpp @@ -0,0 +1,3170 @@ +// ************************************************************************** // +// LayerParamDlg.cpp : implementation of the CLayerParamDlg class +// Copyright(c)2014 WeiHong Company. All rights reserved. +// +// Abstract: +// 本文件实现CLayerParamDlg类。 +// *********************************************** ---- 黄海燕 2014-12-14***** // +#include "stdafx.h" +#include +#include "LayerControls.h" +using namespace nce; +using namespace spline; +#include "LayerParamDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +const char c_szSection[] = "ParamGroup"; + +CS_T s_szTECHNICPARAMETERS = _DEFCS(_CSV(16560), + _CHINESE("工艺参数") + _ENGLISH("Technic Parameters")); +CS_T s_szSPECIALPARAMETERS = _DEFCS(_CSV(16561), + _CHINESE("特殊工艺") + _ENGLISH("Special Technic Parameters")); +CS_T s_szSPEEDPOWERCURVE = _DEFCS(_CSV(16562), + _CHINESE("功率曲线") + _ENGLISH("Power Curve")); +CS_T s_szRAMARKS = _DEFCS(_CSV(16563), + _CHINESE("用户备注") + _ENGLISH("Remarks")); +CS_T s_szMACHMODE = _DEFCS(_CSV(16564), + _CHINESE("穿孔方式:") + _ENGLISH("Pierce Mode:")); +CS_T s_szCUTSPEED = _DEFCS(_CSV(16565), + _CHINESE("切割速度:") + _ENGLISH("Cut Speed:")); +CS_T s_szCUTPOWER = _DEFCS(_CSV(16566), + _CHINESE("切割电流:") + _ENGLISH("Cut Current:")); +CS_T s_szCUTFREQUENCY = _DEFCS(_CSV(16567), + _CHINESE("切割频率:") + _ENGLISH("Cut Frequency:")); +CS_T s_szDUTYCYCLERATIO = _DEFCS(_CSV(16568), + _CHINESE("切割功率:") + _ENGLISH("Cut Power:")); +CS_T s_szCUTGAS = _DEFCS(_CSV(16569), + _CHINESE("切割气体:") + _ENGLISH("Cut Gas:")); +CS_T s_szCUTPRESSURE = _DEFCS(_CSV(16570), + _CHINESE("切割气压:") + _ENGLISH("Cut Pressure:")); +CS_T s_szFOLLOWINGHEIGHT = _DEFCS(_CSV(16571), + _CHINESE("切割高度:") + _ENGLISH("Cut Height:")); +CS_T s_szBERTHPOSITION = _DEFCS(_CSV(16572), + _CHINESE("停靠位置:") + _ENGLISH("Berth Position:")); +CS_T s_szBEFORELIGHTONDELAY = _DEFCS(_CSV(16573), + _CHINESE("开光前延时:") + _ENGLISH("PreLaserOn:")); +CS_T s_szPOSTLASERONDELAY = _DEFCS(_CSV(16574), + _CHINESE("开光后延时:") + _ENGLISH("PostLaserOn:")); +CS_T s_szCUTFOCUS = _DEFCS(_CSV(16701), + _CHINESE("切割焦点:") + _ENGLISH("Cut Focus:")); + +CS_T s_szPIERCEHEIGHT = _DEFCS(_CSV(16575), + _CHINESE("穿孔高度:") + _ENGLISH("Pierce Height:")); +CS_T s_szPIERCESEGMENT = _DEFCS(_CSV(16576), + _CHINESE("穿孔段数:") + _ENGLISH("Pierce Segments:")); +CS_T s_szPREINCPIERCEDELAY = _DEFCS(_CSV(16577), + _CHINESE("渐进前延时:") + _ENGLISH("Pre-Inc-Pierce Delay:")); +CS_T s_szPIERCEPOWER = _DEFCS(_CSV(16578), + _CHINESE("穿孔电流:") + _ENGLISH("Pierce Current:")); +CS_T s_szPIERCEFREQUENCY = _DEFCS(_CSV(16579), + _CHINESE("穿孔频率:") + _ENGLISH("Pierce Frequency:")); +CS_T s_szPIERCEDUTYCYCLERATIO = _DEFCS(_CSV(16580), + _CHINESE("穿孔功率:") + _ENGLISH("Pierce Power:")); +CS_T s_szPIERCEGAS = _DEFCS(_CSV(16581), + _CHINESE("穿孔气体:") + _ENGLISH("Pierce Gas:")); +CS_T s_szPIERCEPRESSURE = _DEFCS(_CSV(16582), + _CHINESE("穿孔气压:") + _ENGLISH("Pierce Pressure:")); +CS_T s_szPOSTLAEROFFDELAY = _DEFCS(_CSV(16583), + _CHINESE("关光前延时:") + _ENGLISH("PreLaserOff:")); +CS_T s_szPIERCEDIRECTLY = _DEFCS(_CSV(16584), + _CHINESE("直接穿孔") + _ENGLISH("Directly")); +CS_T s_szINCREMENGTPIERCE = _DEFCS(_CSV(16585), + _CHINESE("渐进穿孔") + _ENGLISH("Increment")); +CS_T s_szPIERCEBYSECTION = _DEFCS(_CSV(16586), + _CHINESE("分段穿孔") + _ENGLISH("By-section")); +CS_T s_szPIERCETIME = _DEFCS(_CSV(16595), + _CHINESE("穿孔延时:") + _ENGLISH("Pierce Delay:")); +CS_T s_szPUNCHFOCUS = _DEFCS(_CSV(16702), + _CHINESE("穿孔焦点:") + _ENGLISH("Punch Focus:")); + +CS_T s_szPREPERFORATE = _DEFCS(_CSV(16604), + _CHINESE("预穿孔") + _ENGLISH("Prepierce")); +CS_T s_szNEGLECTTHISLAYER = _DEFCS(_CSV(16587), + _CHINESE("此图层不加工") + _ENGLISH("Neglect This Layer")); +CS_T s_szLOWSPEEDSTARTUP = _DEFCS(_CSV(16588), + _CHINESE("慢速起步") + _ENGLISH("Low-speed Startup")); +CS_T s_szSTARTUPDIS = _DEFCS(_CSV(16589), + _CHINESE("起步距离:") + _ENGLISH("Distance:")); +CS_T s_szSTARTUPSPEED= _DEFCS(_CSV(16590), + _CHINESE("起步速度:") + _ENGLISH("Speed:")); +CS_T s_szPREPIERCE = _DEFCS(_CSV(16591), + _CHINESE("预穿孔") + _ENGLISH("Prepierce")); +CS_T s_szOXYGEN = _DEFCS(_CSV(16592), + _CHINESE("氧气") + _ENGLISH("O2")); +CS_T s_szNITROGEN = _DEFCS(_CSV(16593), + _CHINESE("氮气") + _ENGLISH("N2")); +CS_T s_szAIR = _DEFCS(_CSV(16594), + _CHINESE("空气") + _ENGLISH("Air")); +CS_T s_szDEFAULTGAS = _DEFCS(_CSV(16596), + _CHINESE("默认气体") + _ENGLISH("Default Gas")); +CS_T s_szPREPERLIFTHEIGHT = _DEFCS(_CSV(16633), + _CHINESE("预穿孔上抬高度:") + _ENGLISH("Prepierce Lift H:")); + +CS_T s_szSPEED = _DEFCS(_CSV(16597), + _CHINESE("F") + _ENGLISH("F")); +CS_T s_szPOWER = _DEFCS(_CSV(16598), + _CHINESE("P") + _ENGLISH("P")); +CS_T s_szENABLEFPMAPPING = _DEFCS(_CSV(16605), + _CHINESE("启用速度功率调节") + _ENGLISH("Enable Auto Adjust")); +CS_T s_szEDITFPMAP = _DEFCS(_CSV(16694), + _CHINESE("编辑") + _ENGLISH("Edit")); + +CS_T s_szCUTGASNAME = _DEFCS(_CSV(16559), + _CHINESE("CutGas%d_CHN") + _ENGLISH("CutGas%d_ENG")); +CS_T s_szPERGASNAME = _DEFCS(_CSV(16599), + _CHINESE("PerGas%d_CHN") + _ENGLISH("PerGas%d_ENG")); +CS_T s_szLIFTHEIGHT = _DEFCS(_CSV(16606), + _CHINESE("上抬高度:") + _ENGLISH("Lifting Height:")); +CS_T s_szZUPDELAY = _DEFCS(_CSV(16608), + _CHINESE("Z浮延时:") + _ENGLISH("Z Up Delay:")); +CS_T s_szFOLLOWDELAY = _DEFCS(_CSV(16609), + _CHINESE("随动延时:") + _ENGLISH("Follow Delay:")); +CS_T s_szCONPERSPEED = _DEFCS(_CSV(16611), + _CHINESE("渐进速度:") + _ENGLISH("Increment S:")); + +CS_T s_szIMPORTPARAM = _DEFCS(_CSV(16616), + _CHINESE("导入工艺") + _ENGLISH("Import")); +CS_T s_szSAVEPARAM = _DEFCS(_CSV(16617), + _CHINESE("保存工艺") + _ENGLISH("Save")); +CS_T s_szPARAMFILEEXIST = _DEFCS(_CSV(16612), + _CHINESE("参数文件已经存在,是否覆盖?") + _ENGLISH("Parameter file has existed, replace it?")); +CS_T s_szPARAMFILENOTEXIST = _DEFCS(_CSV(16613), + _CHINESE("参数文件不存在!") + _ENGLISH("Parameter file dose not existed!")); +CS_T s_szPARAMOVERWRITEPROMT = _DEFCS(_CSV(16614), + _CHINESE("导入参数将覆盖当前图层参数,是否继续?") + _ENGLISH("Current technic parameters will be overwrite, continue or not?")); +CS_T s_szDEFUALTPARAMFILENAME = _DEFCS(_CSV(16615), + _CHINESE("材料1.ltp") + _ENGLISH("Material1.ltp")); + +CS_T s_szPATHCOOL = _DEFCS(_CSV(16619), + _CHINESE("二次冷却") + _ENGLISH("Path Cool")); +CS_T s_szEXPLODEPUNCH= _DEFCS(_CSV(16620), + _CHINESE("三级穿孔") + _ENGLISH("3-Segment")); +CS_T s_szCIRCLEOVERCUT = _DEFCS(_CSV(16621), + _CHINESE("回旋过切") + _ENGLISH("Circle Overcut")); +CS_T s_szOVERCUTLENGTH = _DEFCS(_CSV(16622), + _CHINESE("过切长度:") + _ENGLISH("Overcut Len:")); +CS_T s_szOVERCUTANGLE= _DEFCS(_CSV(16623), + _CHINESE("回旋角度:") + _ENGLISH("Bypass Angle:")); +CS_T s_szSPECIALTENICH = _DEFCS(_CSV(16631), + _CHINESE("特殊工艺") + _ENGLISH("Special Technic")); +CS_T s_szFIXEDHEIGHTCUT = _DEFCS(_CSV(16632), + _CHINESE("定高切割") + _ENGLISH("Fixed Height Cut")); +CS_T s_szTECHNICLIBRARY = _DEFCS(_CSV(16639), + _CHINESE("工艺库") + _ENGLISH("TechnicLibrary")); +CS_T s_szCUTTINGFROMOUTSIDE = _DEFCS(_CSV(16656), + _CHINESE("板外跟随") + _ENGLISH("Outside Cutting")); +CS_T s_szNOTSAVEOUTSIDEHEIGHT = _DEFCS(_CSV(16654), + _CHINESE("未设置板外切割高度,不能板外跟随!") + _ENGLISH("Outside cutting is unavailable before saving the outside height!")); +CS_T s_szNOTCLOSEBLOW = _DEFCS(_CSV(16656), + _CHINESE("此图层不关气") + _ENGLISH("Not Close Gas")); +CS_T s_szCOOLDELAY = _DEFCS(_CSV(16656), + _CHINESE("冷却延时:") + _ENGLISH("Cool Delay:")); +CS_T s_szCOOLINGAIR = _DEFCS(_CSV(16656), + _CHINESE("冷却气:") + _ENGLISH("Cooling Air:")); +CS_T s_szPIECESIDEBLOW = _DEFCS(_CSV(16656), + _CHINESE("穿孔时侧吹气") + _ENGLISH("Side Blow When Pierce")); +CS_T s_szMACHSIDEBLOW = _DEFCS(_CSV(16656), + _CHINESE("加工时侧吹气") + _ENGLISH("Side Blow When Mach")); +CS_T s_szENABLELEADSPEED = _DEFCS(_CSV(16656), + _CHINESE("引刀线速度") + _ENGLISH("Enable Lead Speed")); +CS_T s_szLEADINSPEED = _DEFCS(_CSV(16656), + _CHINESE("引入速度:") + _ENGLISH("Lead-in Speed:")); +CS_T s_szLEADOUTSPEED = _DEFCS(_CSV(16656), + _CHINESE("引出速度:") + _ENGLISH("Lead-out Speed:")); +CS_T s_szLAYERNAME = _DEFCS(_CSV(16710), + _CHINESE("Name_CHN") + _ENGLISH("Name_ENG")); +CS_T s_csINVALIDINPUT = _DEFCS(_CSV(16760), + _CHINESE("输入参数格式不正确,请重新输入。") + _ENGLISH("The input parameter is invalid, please reset again.")); + +const int c_nOffset = 5; +const int c_nEffectHeight = 150; +const int c_nEffectWeight = 200; +const double c_nMaxPower = 100; +const double c_nMaxSpeed = 100; +const int c_nSelectTolerance = 2; +const COLORREF c_nLineColor = 16711680; +const COLORREF c_nPointNoSelected = 16711680; +const COLORREF c_nPointSelected = RGB(128, 128, 255); +const int c_nRadiusNoSelected = 2; +const int c_nRadiusSelected = 3; +const char c_szEnableFPMap[] = "FPMapEnable"; +const char c_szRemarks[] = "Remarks"; +const char c_szThreeSegPunch[] = "EnableThreeSegPunch"; +const char c_szFirstSegPunch[] = "FirstSegPunch"; +const char c_szSecondSegPunch[] = "SecondSegPunch"; +const char c_szThirdSegPunch[] = "ThirdSegPunch"; +const char c_szThreeSegPunchRemarks[] = "ThreeSegPunchRemarks"; + +const char c_szParamGroupUnit[] = "ParamGroupUnit"; +const char c_szSpeedUnit[] = "SpeedUnit"; +const char c_szAccUnit[] = "AccUnit"; +const char c_szTimeUnit[] = "TimeUnit"; +const char c_szPressureUnit[] = "PressureUnit"; + +static void FormatDoubleParamer(CString& pSrc_) +{ + pSrc_.TrimRight('0'); + if (pSrc_.IsEmpty()) + pSrc_ = _T("0"); + if (pSrc_[pSrc_.GetLength() - 1] == _T('.')) + pSrc_.Delete(pSrc_.GetLength() - 1); +} + +IMPLEMENT_DYNAMIC(CLayerParamDlg, CDialog) +BEGIN_MESSAGE_MAP(CLayerParamDlg, CDialog) + ON_WM_PAINT() + ON_WM_TIMER() + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDBLCLK() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + ON_CONTROL_RANGE(EN_KILLFOCUS, IDC_EDIT_CUTTINGSPEED, IDC_EDIT_PUNCHFOCUS, OnKillFocusEdit) + ON_CONTROL_RANGE(EN_SETFOCUS, IDC_EDIT_CUTTINGSPEED, IDC_EDIT_PUNCHFOCUS, OnSetFocusEdit) + ON_COMMAND_RANGE(IDC_RADIO_DIRPERFORATE, IDC_RADIO_THREESEGPUNCH, OnClickPerType) + ON_COMMAND(IDC_CHECK_ISIGNORE, OnClickNeglect) + ON_COMMAND(IDC_CHECK_NOTCLOSEBLOW, OnClickNotCloseBlow) + ON_COMMAND(IDC_CHECK_PUNCHSIDEBLOW, OnClickPunchSideBlow) + ON_COMMAND(IDC_CHECK_CUTTINGSIDEBLOW, OnClickCuttingSideBlow) + ON_COMMAND(IDC_CHECK_PREPERFORATE, OnClickPrePerforate) + ON_COMMAND(IDC_CHECK_ISSTARTUPSLOWLY, OnClickSlowlyStartup) + ON_CBN_SELCHANGE(IDC_COMBO_CUTTINGAIR, OnSelectCutGas) + ON_CBN_SELCHANGE(IDC_COMBO_PERFORATEAIR, OnSelectPerGas) + ON_CBN_SELCHANGE(IDC_COMBO_COOLINGAIR, OnSelectCoolingGas) + ON_EN_KILLFOCUS(IDC_EDIT_UESEREMARK, OnKillFocusRemarks) + ON_COMMAND(IDC_CHECK_ENABLEINTROSPEED, OnEnableIntroSpeed) + ON_COMMAND(IDC_CHECK_CIRCLEOVERCUT, OnClickOvercut) + ON_COMMAND(IDC_CHECK_ENABLEFPMAPPING, OnClickEnableFP) + ON_COMMAND(IDC_CHECK_FIXHEIGHTCUT, OnClickFixedHeightCut) + ON_COMMAND(IDC_CHECK_CUTTINGFROMOUTSIDE, OnCutFromOutside) + ON_COMMAND(IDC_BTN_EDITFPMAP, OnClickEditFPMap) +END_MESSAGE_MAP() + +CLayerParamDlg::CLayerParamDlg(CParam* pParam_, CWnd* pParent_) + : CDialog(IDD_DLG_LAYERPARAM, pParent_), m_pParam(pParam_) +{ + m_bSelectPoint = FALSE; + m_nMode = t_valid; + m_bFPEnable = TRUE; + m_nFTCType = 0; + + // 初始化输入数据是有效的 ---- 彭朋 2016-07-20 + m_bDataValid = true; + m_bCancelData = false; + CString _strFTCType = NceGetPrivateProfileString("FTCInfo", "FTCType"); + if (!_strFTCType.IsEmpty()) + { + m_nFTCType = atoi(_strFTCType); + } + + _BuildEditInfo(); + + // 初始化穿孔气体和切割气体。配置方式: + // CutGasCount=1 + // CutGas0_Value=0 + // CutGas0_CHN="空气" + // CutGas0_ENG="Air" + // CutGasXX_CHN是中文名,CutGasXX_ENG是英文名,CutGasXX_Value是对应LayerParam.lua + // 中BlowTypeTable的第一项的值。---- 黄海燕 2015-02-28 + CString _strCount = NceGetPrivateProfileString(c_szSection, _T("CutGasCount"), "0"); + int _nCount = atoi(_strCount); + for (int _i = 0; _i < _nCount; _i++) + { + CombItem _item; + CString _strKey; + _strKey.Format(_T("CutGas%d_Value"), _i); + _item.strValue = NceGetPrivateProfileString(c_szSection, _strKey, ""); + _strKey.Format(_GETCS(s_szCUTGASNAME), _i); + _item.strText = NceGetPrivateProfileString(c_szSection, _strKey, ""); + m_vectCutGas.push_back(_item); + } + + _strCount = NceGetPrivateProfileString(c_szSection, _T("CutGasCount"), "0"); + _nCount = atoi(_strCount); + for (int _i = 0; _i < _nCount; _i++) + { + CombItem _item; + CString _strKey; + _strKey.Format(_T("PerGas%d_Value"), _i); + _item.strValue = NceGetPrivateProfileString(c_szSection, _strKey, ""); + _strKey.Format(_GETCS(s_szPERGASNAME), _i); + _item.strText = NceGetPrivateProfileString(c_szSection, _strKey, ""); + m_vectPerGas.push_back(_item); + } + + // 如果是安装的话放在安装目录的“Weihong”文件夹下,数据分离则放在D盘的“Weihong”下,如果是解压的放在与“config”同级目录下。 ---- 黄海燕 2015-06-15 + CString _strPath = NceGetActiveUserDir(); + int _nIndex = _strPath.Find(_T("\\Weihong")); + if (_nIndex != -1) + { + _strPath = _strPath.Left(_nIndex + 8); + _strPath += _T("\\"); + _strPath += _GETCS(s_szTECHNICLIBRARY); + m_strDefaultFilePath = _strPath; + } + else + { + _nIndex = _strPath.Find(_T("\\config")); + ASSERT(_nIndex >= 0); + _strPath = _strPath.Left(_nIndex + 1); + _strPath += _GETCS(s_szTECHNICLIBRARY); + m_strDefaultFilePath = _strPath; + } + + m_bEnableFocusCtrl = NceGetPrivateProfileString(_T("FocusControl"), _T("Enable")) == _T("1"); +} + +void CLayerParamDlg::_BuildEditInfo() +{ + // 初始化除用户备注之外的编辑框。 ---- 黄海燕 2015-01-23 + bool _bNoF = m_nFTCType == 2; + const EditInfo _s_Edits[] = + { + {"Feedrate", IDC_EDIT_CUTTINGSPEED, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("Feedrate")) ? 1000 : m_pParam->GetKey_DBL("Feedrate"), 1, 100000, true, Speed_MMperMin, 0}, + {"FollowHeight", IDC_EDIT_FOLLOWHEIGHT, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("FollowHeight")) ? 1 : m_pParam->GetKey_DBL("FollowHeight"), 0.01, 100, m_nFTCType != 2, Length_MM, 1}, + {"CutPower", IDC_EDIT_CUTTINGPOWER, 0, IsInvalidDouble(m_pParam->GetKey_DBL("CutPower")) ? 100 : int(m_pParam->GetKey_DBL("CutPower")), NULL, 0, 100, true, Percent, 0}, + {"CutFrequency", IDC_EDIT_CUTTINGFREQ, 0, IsInvalidDouble(m_pParam->GetKey_DBL("CutFrequency")) ? 5000 : int(m_pParam->GetKey_DBL("CutFrequency")), NULL, 0, 100000, true, Frequece, 0}, + {"CutDutyCycle", IDC_EDIT_CUTTINGCYCLE, 0, IsInvalidDouble(m_pParam->GetKey_DBL("CutDutyCycle")) ? 100 : int(m_pParam->GetKey_DBL("CutDutyCycle")), NULL, 0, 100, true, Percent, 0}, + {"CutPressure", IDC_EDIT_CUTTINGPRESSURE, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("CutPressure")) ? 100 : m_pParam->GetKey_DBL("CutPressure"), 0, 100, true, Pressure_Percent, 1}, + {"BeforeLightOnDelay", IDC_EDIT_BEFORELINGHTONDELAY,1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("BeforeLightOnDelay")) ? 100 : m_pParam->GetKey_DBL("BeforeLightOnDelay"), 0, 1800000,true, Time_MS, 0}, + {"AfterLightOnDelay", IDC_EDIT_AFTERLIGHTONDELAY, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("AfterLightOnDelay")) ? 200 : m_pParam->GetKey_DBL("AfterLightOnDelay"), 0, 1800000,true, Time_MS, 0}, + {"PerHeight", IDC_EDIT_PERFORATEHEIGHT, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("PerHeight")) ? 5 : m_pParam->GetKey_DBL("PerHeight"), 0.01, 100, true, Length_MM, 1}, + {"PerTime", IDC_EDIT_PERFORATETIME, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("PerTime")) ? 200 : m_pParam->GetKey_DBL("PerTime"), 100, 180000, true, Time_MS, 0}, + {"PerPower", IDC_EDIT_PERFORATEPOWER, 0, IsInvalidDouble(m_pParam->GetKey_DBL("PerPower")) ? 50 : int(m_pParam->GetKey_DBL("PerPower")), NULL, 0, 100, true, Percent, 0}, + {"PerFrequency", IDC_EDIT_PERFORATEFREQ, 0, IsInvalidDouble(m_pParam->GetKey_DBL("PerFrequency")) ? 1000 : int(m_pParam->GetKey_DBL("PerFrequency")), NULL, 0, 100000, true, Frequece, 0}, + {"PerDutyCycle", IDC_EDIT_PERFORATECYCLE, 0, IsInvalidDouble(m_pParam->GetKey_DBL("PerDutyCycle")) ? 50 : int(m_pParam->GetKey_DBL("PerDutyCycle")), NULL, 0, 100, true, Percent, 0}, + {"PerPressure", IDC_EDIT_PERFORATEPRESSURE, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("PerPressure")) ? 100 : m_pParam->GetKey_DBL("PerPressure"), 0, 100, true, Pressure_Percent, 1}, + {"BeforeLightOffDelay", IDC_EDIT_AFTERLIGHTOFFDELAY,1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("BeforeLightOffDelay")) ? 100 : m_pParam->GetKey_DBL("BeforeLightOffDelay"), 0, 1800000,true, Time_MS, 0}, + {"SlowlyStartupDis", IDC_EDIT_STARTUPDIS, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("SlowlyStartupDis")) ? 2 : m_pParam->GetKey_DBL("SlowlyStartupDis"), 0, 10000, true, Length_MM, 1}, + {"SlowlyStartupSpeed", IDC_EDIT_STARTUPSPEED, 0, IsInvalidDouble(m_pParam->GetKey_DBL("SlowlyStartupSpeed")) ? 180 : int(m_pParam->GetKey_DBL("SlowlyStartupSpeed")),NULL, 0, 100000, true, Speed_MMperMin, 0}, + {"LiftHeight", IDC_EDIT_LIFTHEIGHT, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("LiftHeight")) ? 10 : m_pParam->GetKey_DBL("LiftHeight"), 0, 1000, true, Length_MM, 1}, + {"ZupDelay", IDC_EDIT_ZUPDELAY, 1, NULL,!_bNoF || IsInvalidDouble(m_pParam->GetKey_DBL("ZupDelay")) ? 300 : m_pParam->GetKey_DBL("ZupDelay"), 0, 1800000,m_nFTCType == 2, Time_MS, 0}, + {"FollowDelay", IDC_EDIT_FOLLOWDELAY, 1, NULL,!_bNoF || IsInvalidDouble(m_pParam->GetKey_DBL("FollowDelay")) ? 100 : m_pParam->GetKey_DBL("FollowDelay"), 0, 1800000,m_nFTCType == 2, Time_MS, 0}, + {"ConPerSpeed", IDC_EDIT_CONPERSPEED, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("ConPerSpeed")) ? 5 : m_pParam->GetKey_DBL("ConPerSpeed"), 0.1, 100, true, Speed_MMperS, 1}, + {"OvercutAngle", IDC_EDIT_CIRCLEANGLE, 0, IsInvalidDouble(m_pParam->GetKey_DBL("OvercutAngle")) ? 120 : int(m_pParam->GetKey_DBL("OvercutAngle")),NULL, 0, 150, true, degree, 0}, + {"OvercutLength", IDC_EDIT_OVERCUTLENGTH, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("OvercutLength")) ? 2 : m_pParam->GetKey_DBL("OvercutLength"), 0.1, 100.0, true, Length_MM, 1}, + {"PrePerLiftHeight", IDC_EDIT_PREPERFORATEHEIGHT,1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("PrePerLiftHeight")) ? 2 : m_pParam->GetKey_DBL("PrePerLiftHeight"), 0, 1000.0, m_nFTCType != 2, Length_MM, 1}, + {"EnterIntroSpeed", IDC_EDIT_INSPEED, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("EnterIntroSpeed")) ? 200 : m_pParam->GetKey_DBL("EnterIntroSpeed"), 1, 100000, true, Speed_MMperMin, 0}, + {"ExitIntroSpeed", IDC_EDIT_OUTSPEED, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("ExitIntroSpeed")) ? 200 : m_pParam->GetKey_DBL("ExitIntroSpeed"), 1, 100000, true, Speed_MMperMin, 0}, + {"CutFocusPos", IDC_EDIT_CUTFOCUS, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("CutFocusPos")) ? 0 : m_pParam->GetKey_DBL("CutFocusPos"), -100, 100, true, Length_MM, 1}, + {"PerFocusPos", IDC_EDIT_PUNCHFOCUS, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("PerFocusPos")) ? 0 : m_pParam->GetKey_DBL("PerFocusPos"), -100, 100, true, Length_MM, 1}, + {"StopCornerDelay", IDC_EDIT_STOPCORNERDELAY, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("StopCornerDelay")) ? 400 : m_pParam->GetKey_DBL("StopCornerDelay"), 0, 1800000,true, Time_MS, 0}, + }; + + // 将初始值设进去。 ---- 黄海燕 2015-05-05 + m_listEdits.clear(); + for (size_t _i = 0; _i < _countof(_s_Edits); _i++) + { + EditInfo _item = _s_Edits[_i]; + Units _nCurUnit = GetCurSpeedUnit(); + if ((_item.nUnit == Speed_INperMin + || _item.nUnit == Speed_MMperMin + || _item.nUnit == Speed_MMperS + || _item.nUnit == Speed_MperMin) + && _item.nUnit != _nCurUnit) + { + ConverUnit(_item.nUnit, _nCurUnit, _s_Edits[_i], _item); + } + + _nCurUnit = GetCurAccUnit(); + if ((_item.nUnit == Acc_MMperS2 + || _item.nUnit == ACC_MperMin2 + || _item.nUnit == Acc_10MperS2) + && _item.nUnit !=_nCurUnit) + { + ConverUnit(_item.nUnit, _nCurUnit, _s_Edits[_i], _item); + } + + _nCurUnit = GetCurTimeUnit(); + if ((_item.nUnit == Time_MS + || _item.nUnit == Time_S) + && _item.nUnit != _nCurUnit) + { + ConverUnit(_item.nUnit, _nCurUnit, _s_Edits[_i], _item); + } + + _nCurUnit = GetCurPressureUnit(); + if ((_item.nUnit == Pressure_Percent + || _item.nUnit == Pressure_MPa) + && _item.nUnit != _nCurUnit) + { + ConverUnit(_item.nUnit, _nCurUnit, _s_Edits[_i], _item); + } + + m_listEdits.push_back(_item); + + double _nValue = _s_Edits[_i].nDataType == 0 ? _s_Edits[_i].iValue : _s_Edits[_i].dValue; + if (m_pParam->GetKey_DBL(_s_Edits[_i].strKey) != _nValue) + m_pParam->SetKey_DBL(_s_Edits[_i].strKey, _nValue); + } +} +CLayerParamDlg::~CLayerParamDlg() +{ +} + +CParam* CLayerParamDlg::GetParam() +{ + return m_pParam; +} + +void CLayerParamDlg::SetParam(CParam* pParam_) +{ + m_pParam = pParam_; + + // Enable + CString _strEnableFP = m_pParam->GetKey(LPSTR(c_szEnableFPMap)); + m_bFPEnable = _strEnableFP == "1" ? TRUE : FALSE; + + // 特征点 + m_vectCurLine.clear(); + CString _strFTemp = "FF%d"; + CString _strPTemp = "FP%d"; + for (int _it = 0; _it <= 100; _it++) + { + CString _strF; + _strF.Format(_strFTemp, _it); + CString _strP; + _strP.Format(_strPTemp, _it); + + CStringA _strFValue = m_pParam->GetKey(_strF); + CStringA _strPValue = m_pParam->GetKey(_strP); + if (_strFValue.IsEmpty() || _strPValue.IsEmpty()) + { + break; + } + + FPPoint _FPPoint; + _FPPoint.nSpeed = atoi(_strFValue); + _FPPoint.nPower = atoi(_strPValue); + m_vectCurLine.push_back(_FPPoint); + } + ASSERT(m_vectCurLine.size() >=2 + && m_vectCurLine.front().nSpeed == 0 + && m_vectCurLine.back().nSpeed == 100 + ); + + UpdateData(FALSE); + InvalidateRect(m_rectCoorCanvas, FALSE); +} + +void CLayerParamDlg::BuildDefaultParam(nce::CParam* pParam_) +{ + if (!pParam_) + { + ASSERT(FALSE); + return; + } + + struct DVItem + { + CStringA strKey; + CStringA strDefualtValue; + }; + DVItem _DVItems[] = + { + {"PerforateType", "0"}, + {"Output", "1"}, + {"PrePerforate", "0"}, + {"FixedHeightCut", "0"}, + {"OutsideCutFollow", "0"}, + {"SlowlyStartup", "0"}, + {"CutBlowType", "0"}, + {"PerBlowType", "0"}, + {"Overcut", "0"}, + {"EnableIntroSpeed", "0"}, + {"Feedrate", "1000"}, + {"FollowHeight", "1"}, + {"CutPower", "100"}, + {"CutFrequency", "5000"}, + {"CutDutyCycle", "100"}, + {"CutPressure", "100"}, + {"BeforeLightOnDelay", "100"}, + {"AfterLightOnDelay", "200"}, + {"PerHeight", "5"}, + {"PerTime", "200"}, + {"PerPower", "50"}, + {"PerFrequency", "1000"}, + {"PerDutyCycle", "50"}, + {"PerPressure", "100"}, + {"BeforeLightOffDelay", "100"}, + {"SlowlyStartupDis", "2"}, + {"SlowlyStartupSpeed", "180"}, + {"LiftHeight", "10"}, + {"ZupDelay", "300"}, + {"FollowDelay", "100"}, + {"ConPerSpeed", "5"}, + {"OvercutAngle", "120"}, + {"OvercutLength", "2"}, + {"PrePerLiftHeight", "2"}, + {"EnterIntroSpeed", "200"}, + {"ExitIntroSpeed", "200"}, + {"CutFocusPos", "0"}, + {"PerFocusPos", "0"}, + }; + for (int _i = 0; _i < _countof(_DVItems); _i++) + { + CStringA _strCurValue = pParam_->GetKey(_DVItems[_i].strKey); + if (_strCurValue.IsEmpty()) + pParam_->SetKey(_DVItems[_i].strKey, _DVItems[_i].strDefualtValue); + } +} + +void CLayerParamDlg::SaveFPCurve() +{ + // 是否启用速度功率曲线 ---- DingQiang 2014-12-31 + CString _strFPMapEnable; + _strFPMapEnable += m_bFPEnable ? "1" : "0"; + m_pParam->SetKey(LPSTR(c_szEnableFPMap),_strFPMapEnable); + + // 删除之前的特征点,规定了最多只有101个特征点 ---- DingQiang 2015-01-28 + CString _strParam = m_pParam->GetParamString(); + for (int _i = 0; _i < 101; _i++) + { + CString _strKey; + _strKey.Format("FF%d=", _i); + int _nS = _strParam.Find(_strKey); + if (_nS < 0) + { + continue; + } + + int _nE = _strParam.Find(";", _nS); + ASSERT(_nE >= 0); + _strParam.Delete(_nS, _nE - _nS + 1); + + _strKey.Format("FP%d", _i); + _nS = _strParam.Find(_strKey); + ASSERT(_nS >= 0); + _nE = _strParam.Find(";", _nS); + ASSERT(_nE > 0); + _strParam.Delete(_nS, _nE - _nS + 1); + } + m_pParam->SetParamString(_strParam); + + // 写新的特征点 ---- DingQiang 2015-01-28 + for (size_t _it = 0; _it < m_vectCurLine.size(); _it++) + { + int _nSpeed = m_vectCurLine[_it].nSpeed; + int _nPower = m_vectCurLine[_it].nPower; + ASSERT(_nSpeed >= 0 && _nPower >= 0 && _nSpeed <= 100 && _nPower <= 100); + CString _strKey; + _strKey.Format("FF%d", _it); + CString _strValue; + _strValue.Format("%d", _nSpeed); + m_pParam->SetKey(_strKey, _strValue); + + _strKey.Format("FP%d", _it); + _strValue.Format("%d", _nPower); + m_pParam->SetKey(_strKey, _strValue); + } + // 保持CutPower 和 Power 的一致性。 + double _nCutPower = m_pParam->GetKey_DBL("CutPower"); + m_pParam->SetKey_DBL("Power", _nCutPower); +} + +BOOL CLayerParamDlg::Create(UINT nIDTemplate_, CWnd* pParentWnd_ /* = NULL */) +{ + ::AfxInitRichEdit2(); + return __super::Create(nIDTemplate_, pParentWnd_); +} + +void CLayerParamDlg::DoDataExchange(CDataExchange* pDX_) +{ + //用户取消 ---- 彭朋 2016-07-21 + if (m_bCancelData) + { + return; + } + + __super::DoDataExchange(pDX_); + DDX_Check(pDX_, IDC_CHECK_ENABLEFPMAPPING, m_bFPEnable); + + for (EditItems::iterator _it = m_listEdits.begin(); _it != m_listEdits.end(); _it++) + { + // 不启用的就不更新。 ---- 黄海燕 2015-03-17 + if (!_it->bEnable) + continue; + + if (_it->nDataType == 0) + { + DDX_Text(pDX_, _it->nID, _it->iValue); + DDV_MinMaxInt(pDX_, _it->iValue, int(_it->nMinValue), int(_it->nMaxValue)); + } + else + { + ASSERT(_it->nDataType == 1); + DDX_Text(pDX_, _it->nID, _it->dValue); + DDV_MinMaxDouble(pDX_, _it->dValue, _it->nMinValue, _it->nMaxValue); + } + } +} + +BOOL CLayerParamDlg::OnInitDialog() +{ + BOOL _bRet = __super::OnInitDialog(); + + CHARFORMAT _cf; + memset(&_cf, 0, sizeof(CHARFORMAT)); + _cf.cbSize = sizeof(CHARFORMAT); + _cf.dwMask = CFM_FACE | CFM_OFFSET | CFM_SIZE | CFM_COLOR; + _cf.yOffset = 0; + _cf.yHeight = 180; + _cf.crTextColor = RGB(0, 0, 255); + strcpy(_cf.szFaceName, "宋体"); + CRichEditCtrl* _pRichEdit = (CRichEditCtrl*)GetDlgItem(IDC_EDIT_UESEREMARK); + if (!_pRichEdit->SetDefaultCharFormat(_cf)) + { + ASSERT(FALSE); + } + SetTimer(1, 100,NULL); + + CWnd* _pWnd = GetDlgItem(IDC_STC_FPCANVAS); + _pWnd->GetClientRect(&m_rectCanvas); + _pWnd->GetWindowRect(&m_rectCoorCanvas); + ScreenToClient(&m_rectCoorCanvas); + m_rcEffectRect.left = m_rectCanvas.left + c_nOffset; + m_rcEffectRect.right = m_rectCanvas.left + c_nEffectWeight + c_nOffset; + m_rcEffectRect.top = m_rectCanvas.bottom - c_nOffset - c_nEffectHeight; + m_rcEffectRect.bottom = m_rectCanvas.bottom - c_nOffset; + + CComboBox* _pComb = (CComboBox*)GetDlgItem(IDC_COMBO_CUTTINGAIR); + for (int _i = 0; _i < (int)m_vectCutGas.size(); _i++) + { + _pComb->InsertString(_i, m_vectCutGas[_i].strText); + } + + _pComb = (CComboBox*)GetDlgItem(IDC_COMBO_PERFORATEAIR); + for (int _i = 0; _i < (int)m_vectPerGas.size(); _i++) + { + _pComb->InsertString(_i, m_vectPerGas[_i].strText); + } + + _pComb = (CComboBox*)GetDlgItem(IDC_COMBO_COOLINGAIR); + for (int _i = 0; _i < (int)m_vectPerGas.size(); _i++) + { + _pComb->InsertString(_i, m_vectPerGas[_i].strText); + } + + GetDlgItem(IDC_STATIC_STARTUPDIS)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_STARTUPSPEED)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_STARTUPDISUNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_STARTUPSPEEDUNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_STARTUPDIS)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_STARTUPSPEED)->EnableWindow(FALSE); + GetDlgItem(IDC_CHECK_PATHCOOL)->EnableWindow(FALSE); + + // 如果是其他随动仪,即只是通过随动和Z浮端口控制随动仪,则显示Z浮延时和随动延时参数。 + // 跟随高度、停靠位置、不能用,不显示上抬高度。 ---- 黄海燕 2015-03-13 + GetDlgItem(IDC_STATIC_ZUPDELAY)->ShowWindow(m_nFTCType == 2 ? SW_NORMAL : SW_HIDE); + GetDlgItem(IDC_EDIT_ZUPDELAY)->ShowWindow(m_nFTCType == 2 ? SW_NORMAL : SW_HIDE); + GetDlgItem(IDC_STATIC_ZUPDELAYUNIT)->ShowWindow(m_nFTCType == 2 ? SW_NORMAL : SW_HIDE); + + GetDlgItem(IDC_STATIC_FOLLOWDELAYUNIT)->ShowWindow(m_nFTCType == 2 ? SW_NORMAL : SW_HIDE); + GetDlgItem(IDC_STATIC_FOLLOWDELAY)->ShowWindow(m_nFTCType == 2 ? SW_NORMAL : SW_HIDE); + GetDlgItem(IDC_EDIT_FOLLOWDELAY)->ShowWindow(m_nFTCType == 2 ? SW_NORMAL : SW_HIDE); + + GetDlgItem(IDC_STATIC_LIFTHEIGHT)->ShowWindow(m_nFTCType != 2 ? SW_NORMAL : SW_HIDE); + GetDlgItem(IDC_EDIT_LIFTHEIGHT)->ShowWindow(m_nFTCType != 2 ? SW_NORMAL : SW_HIDE); + GetDlgItem(IDC_STATIC_LIFTHEIGHTUNIT)->ShowWindow(m_nFTCType != 2 ? SW_NORMAL : SW_HIDE); + + GetDlgItem(IDC_STATIC_FOLLOWHEIGHT)->EnableWindow(m_nFTCType != 2); + GetDlgItem(IDC_EDIT_FOLLOWHEIGHT)->EnableWindow(m_nFTCType != 2); + GetDlgItem(IDC_STATIC_FOLLOWHEIGHTUNIT)->EnableWindow(m_nFTCType != 2); + + GetDlgItem(IDC_STATIC_IMPORTAREA)->GetWindowRect(m_rcImportBtn); + GetDlgItem(IDC_STATIC_SAVEBTNRECT)->GetWindowRect(m_rcSaveBtn); + GetDlgItem(IDC_STATIC_IMPORTAREA)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_STATIC_SAVEBTNRECT)->ShowWindow(SW_HIDE); + ScreenToClient(m_rcImportBtn); + ScreenToClient(m_rcSaveBtn); + + // 让INI中可以配置<此图层不关气><侧吹气>是否启用 ---- 杨开锦 2016-01-12 + CString _strENCB = NceGetPrivateProfileString(_T("PGLayerDlg"), _T("EnableNotCloseBlow"), _T("0")); + CString _strESB = NceGetPrivateProfileString(_T("PGLayerDlg"), _T("EnableSideBlow"), _T("0")); + bool _bEnableNotCloseBlow = (atoi(_strENCB) != 0); + bool _bEnableSideBlow = (atoi(_strESB) != 0); + GetDlgItem(IDC_CHECK_NOTCLOSEBLOW)->EnableWindow(_bEnableNotCloseBlow ? TRUE : FALSE); + GetDlgItem(IDC_CHECK_PUNCHSIDEBLOW)->EnableWindow(_bEnableSideBlow ? TRUE : FALSE); + GetDlgItem(IDC_CHECK_CUTTINGSIDEBLOW)->EnableWindow(_bEnableSideBlow ? TRUE : FALSE); + + // 根据是否是简化版本(LA或LT版本)来配置图层里的<预穿孔><三级穿孔><冷却延时><冷却气>是否隐藏 ---- 边俊霞 2016-11-28 + CString _strSV = NceGetPrivateProfileString(_T("PGLayerDlg"), _T("SimplifiedVersion"), _T("0")); + bool _bSimplifiedVersion = (atoi(_strSV) != 0); + GetDlgItem(IDC_CHECK_PREPERFORATE)->ShowWindow(_bSimplifiedVersion ? FALSE : TRUE); + GetDlgItem(IDC_RADIO_THREESEGPUNCH)->ShowWindow(_bSimplifiedVersion ? FALSE : TRUE); + GetDlgItem(IDC_STATIC_COOLDELAY)->ShowWindow(_bSimplifiedVersion ? FALSE : TRUE); + GetDlgItem(IDC_EDIT_STOPCORNERDELAY)->ShowWindow(_bSimplifiedVersion ? FALSE : TRUE); + GetDlgItem(IDC_STATIC_STOPCORNERDELAY)->ShowWindow(_bSimplifiedVersion ? FALSE : TRUE); + GetDlgItem(IDC_STATIC_COOLINGAIR)->ShowWindow(_bSimplifiedVersion ? FALSE : TRUE); + GetDlgItem(IDC_COMBO_COOLINGAIR)->ShowWindow(_bSimplifiedVersion ? FALSE : TRUE); + + SetParam(m_pParam); + SetText(); + Update(); + UpFocusCtrls(); + return _bRet; +} + +void CLayerParamDlg::OnOK() +{ +} + +void CLayerParamDlg::InitCancelData() +{ + m_bCancelData = false; +} + +void CLayerParamDlg::OnCancel() +{ + m_bCancelData = true; +} + +void CLayerParamDlg::SetText() +{ + SetDlgItemText(IDC_CHECK_PREPERFORATE, _GETCS(s_szPREPERFORATE)); + SetDlgItemText(IDC_RADIO_DIRPERFORATE, _GETCS(s_szPIERCEDIRECTLY)); + SetDlgItemText(IDC_RADIO_CONPERORATE, _GETCS(s_szINCREMENGTPIERCE)); + SetDlgItemText(IDC_RADIO_SEGPERFORATE, _GETCS(s_szPIERCEBYSECTION)); + SetDlgItemText(IDC_CHECK_ISIGNORE, _GETCS(s_szNEGLECTTHISLAYER)); + SetDlgItemText(IDC_CHECK_ISSTARTUPSLOWLY, _GETCS(s_szLOWSPEEDSTARTUP)); + SetDlgItemText(IDC_STATIC_TECHNICPARAM, _GETCS(s_szTECHNICPARAMETERS)); + SetDlgItemText(IDC_STATIC_PERFORATETYPE, _GETCS(s_szMACHMODE)); + SetDlgItemText(IDC_STATIC_CUTTINGSPEED, _GETCS(s_szCUTSPEED)); + SetDlgItemText(IDC_STATIC_CUTTINGPOWER, _GETCS(s_szCUTPOWER)); + SetDlgItemText(IDC_STATIC_CUTTINGFREQ, _GETCS(s_szCUTFREQUENCY)); + SetDlgItemText(IDC_STATIC_CUTTINGCYCLE, _GETCS(s_szDUTYCYCLERATIO)); + SetDlgItemText(IDC_STATIC_CUTTINGPRESSURE, _GETCS(s_szCUTPRESSURE)); + SetDlgItemText(IDC_STATIC_CUTTINGAIR, _GETCS(s_szCUTGAS)); + SetDlgItemText(IDC_STATIC_FOLLOWHEIGHT, _GETCS(s_szFOLLOWINGHEIGHT)); + SetDlgItemText(IDC_STATIC_BEFORELIGHTONDELAY, _GETCS(s_szBEFORELIGHTONDELAY)); + SetDlgItemText(IDC_STATIC_AFTERLIGHTONDELAY, _GETCS(s_szPOSTLASERONDELAY)); + SetDlgItemText(IDC_STATIC_CUTFOCUS, _GETCS(s_szCUTFOCUS)); + + SetDlgItemText(IDC_STATIC_PERFORATEHEIGHT, _GETCS(s_szPIERCEHEIGHT)); + SetDlgItemText(IDC_STATIC_PERFORATETIME, _GETCS(s_szPIERCETIME)); + SetDlgItemText(IDC_STATIC_PERFORATEPOWER, _GETCS(s_szPIERCEPOWER)); + SetDlgItemText(IDC_STATIC_PERFORATEFREQ, _GETCS(s_szPIERCEFREQUENCY)); + SetDlgItemText(IDC_STATIC_PERCYCLE, _GETCS(s_szPIERCEDUTYCYCLERATIO)); + SetDlgItemText(IDC_STATIC_PERFORATEAIR, _GETCS(s_szPIERCEGAS)); + SetDlgItemText(IDC_STATIC_PERFORATEPRESSURE, _GETCS(s_szPIERCEPRESSURE)); + SetDlgItemText(IDC_STATIC_AFTERLIGHTOFFDELAY, _GETCS(s_szPOSTLAEROFFDELAY)); + SetDlgItemText(IDC_STATIC_PUNCHFOCUS, _GETCS(s_szPUNCHFOCUS)); + + SetDlgItemText(IDC_STATIC_SPEEDPOWERCURVE, _GETCS(s_szSPEEDPOWERCURVE)); + SetDlgItemText(IDC_STATIC_USERREMARK, _GETCS(s_szRAMARKS)); + SetDlgItemText(IDC_STATIC_SPECIALTECHNICPARAM, _GETCS(s_szSPECIALPARAMETERS)); + SetDlgItemText(IDC_STATIC_STARTUPDIS, _GETCS(s_szSTARTUPDIS)); + SetDlgItemText(IDC_STATIC_STARTUPSPEED, _GETCS(s_szSTARTUPSPEED)); + SetDlgItemText(IDC_STATIC_LIFTHEIGHT, _GETCS(s_szLIFTHEIGHT)); + SetDlgItemText(IDC_STATIC_FOLLOWDELAY, _GETCS(s_szFOLLOWDELAY)); + SetDlgItemText(IDC_STATIC_ZUPDELAY, _GETCS(s_szZUPDELAY)); + SetDlgItemText(IDC_STATIC_CONPERSPEED, _GETCS(s_szCONPERSPEED)); + SetDlgItemText(IDC_STATIC_IMPORTLAYERPARAM, _GETCS(s_szIMPORTPARAM)); + SetDlgItemText(IDC_STATIC_LAYERPARAMSAVE, _GETCS(s_szSAVEPARAM)); + + SetDlgItemText(IDC_CHECK_PATHCOOL, _GETCS(s_szPATHCOOL)); + SetDlgItemText(IDC_RADIO_THREESEGPUNCH, _GETCS(s_szEXPLODEPUNCH)); + SetDlgItemText(IDC_CHECK_CIRCLEOVERCUT, _GETCS(s_szCIRCLEOVERCUT)); + SetDlgItemText(IDC_STATIC_CIRCLEANGLE, _GETCS(s_szOVERCUTANGLE)); + SetDlgItemText(IDC_STATIC_OVERCUTLENGTH, _GETCS(s_szOVERCUTLENGTH)); + SetDlgItemText(IDC_STATIC_SPECIALTENICH, _GETCS(s_szSPECIALTENICH)); + SetDlgItemText(IDC_CHECK_FIXHEIGHTCUT, _GETCS(s_szFIXEDHEIGHTCUT)); + SetDlgItemText(IDC_STATIC_PREPERFORATEHEIGHT, _GETCS(s_szPREPERLIFTHEIGHT)); + SetDlgItemText(IDC_CHECK_CUTTINGFROMOUTSIDE, _GETCS(s_szCUTTINGFROMOUTSIDE)); + + SetDlgItemText(IDC_CHECK_ENABLEFPMAPPING, _GETCS(s_szENABLEFPMAPPING)); + SetDlgItemText(IDC_BTN_EDITFPMAP, _GETCS(s_szEDITFPMAP)); + SetDlgItemText(IDC_CHECK_NOTCLOSEBLOW, _GETCS(s_szNOTCLOSEBLOW)); + SetDlgItemText(IDC_STATIC_COOLDELAY, _GETCS(s_szCOOLDELAY)); + SetDlgItemText(IDC_STATIC_COOLINGAIR, _GETCS(s_szCOOLINGAIR)); + SetDlgItemText(IDC_CHECK_PUNCHSIDEBLOW, _GETCS(s_szPIECESIDEBLOW)); + SetDlgItemText(IDC_CHECK_CUTTINGSIDEBLOW, _GETCS(s_szMACHSIDEBLOW)); + SetDlgItemText(IDC_CHECK_ENABLEINTROSPEED, _GETCS(s_szENABLELEADSPEED)); + SetDlgItemText(IDC_STC_INSPEED, _GETCS(s_szLEADINSPEED)); + SetDlgItemText(IDC_STC_OUTSPEED, _GETCS(s_szLEADOUTSPEED)); +} + +// 用户备注保存在图层参数中,为避免用户输入与图层中某个参数一样以及含特殊字符干扰Lua的解析, +// 特将'\\'、';'、'='、'\"'、'\''、'\r'、'\n'分别替换为ASCII码为0x16、0x07、0x1D、0x1E、0x1F、0x06、0x10。 +// PS:0x16 SYS是一个设备控制指令,同步空闲的。 +// 0x07 是响铃也是个设备控制命令。 +// 0x06 是请求确认,主要用于全双工或半双工的报文通信。 +// 0x10 是数据链路转义,用于网络传输的 +// 0x1D、0x1E、0x1F分别是Linx和Unix平台下AWK文本处理器中的分组符、记录分割符、单元分隔符,我们都是用的Windows的。 +// 以上结论均来自网络,照这样的解释用他们来替换字符应该没有什么负面影响,若发现错误,方便告知下。 +// ---- 黄海燕 2015-02-04 +CString CLayerParamDlg::Normative(LPCTSTR pszValue_) +{ + CString _strRet(pszValue_); + _strRet.Replace('\\', 0x16); + _strRet.Replace(';', 0x07); + _strRet.Replace('=', 0x1D); + _strRet.Replace('\"', 0x1E); + _strRet.Replace('\'', 0x1F); + _strRet.Replace('\r', 0x06); + _strRet.Replace('\n', 0x10); + return _strRet; +} + +// 将0x16、0x07、0x1D、0x1E、0x1F分别替换为'\\'、';'、'='、'\"'、'\'',是Normative的逆过程。 +// ---- 黄海燕 2015-02-04 +CString CLayerParamDlg::ReverseNormative(LPCTSTR pszValue_) +{ + CString _strRet(pszValue_); + _strRet.Replace(0x16, '\\'); + _strRet.Replace(0x07, ';'); + _strRet.Replace(0x1D, '='); + _strRet.Replace(0x1E, '\"'); + _strRet.Replace(0x1F, '\''); + _strRet.Replace(0x06, '\r'); + _strRet.Replace(0x10, '\n'); + return _strRet; +} + +// 输入的数据是否有效 ---- 彭朋 2016-07-20 +bool CLayerParamDlg::IsNumberValid(LPCTSTR pszText_) +{ + if (!pszText_) + { + return false; + } + + CString _strText(pszText_); + if (_strText.IsEmpty()) + { + return false; + } + + int _nDotCount = 0; + for (int _i = 0; _i < _strText.GetLength(); _i++) + { + if (_i == 0 && (_strText[_i] == '-' || _strText[_i] == '+')) + { + continue; + } + + if (!isdigit(_strText[_i]) && _strText[_i] != '.') + { + return false; + } + + if (_strText[_i] == '.') + { + _nDotCount++; + } + } + + if (_nDotCount > 1) + { + return false; + } + + return true; +} + +bool CLayerParamDlg::GetInputValid() +{ + if (this->GetFocus() != NULL) + { + if (!IsInputValid(this->GetFocus()->GetDlgCtrlID())) + { + return false; + } + } + + return true; +} + +bool CLayerParamDlg::IsInputValid(UINT nID_) +{ + bool _bDataValid = true; + for (EditItems::iterator _it = m_listEdits.begin(); _it != m_listEdits.end(); _it++) + { + if (_it->nID != nID_) + continue; + + // 找到了FocusEdit才验证有效性 ---- 彭朋 2016-07-20 + m_bDataValid = false; + _bDataValid = false; + bool _bTempDataValid = true; + + // 输入的数据是否有效 + CString _strText = _T(""); + GetDlgItemText(_it->nID, _strText); + if (!IsNumberValid(_strText)) + { + _bTempDataValid = false; + } + + if (!_bTempDataValid) + { + m_bCancelData = true; + AfxMessageBox(_GETCS(s_csINVALIDINPUT)); + m_bCancelData = false; + } + + // 保存数据。 + if (_bTempDataValid && UpdateData(TRUE)) + { + m_bDataValid = true; + _bDataValid = true; + double _nValue = _it->nDataType == 0 ? _it->iValue : _it->dValue; + Units _nCurUnit = GetCurSpeedUnit(); + if ((_it->nUnit == Speed_INperMin + || _it->nUnit == Speed_MMperMin + || _it->nUnit == Speed_MMperS + || _it->nUnit == Speed_MperMin) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_nCurUnit, _it->nUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurAccUnit(); + if ((_it->nUnit == Acc_MMperS2 + || _it->nUnit == ACC_MperMin2 + || _it->nUnit == Acc_10MperS2) + && _it->nUnit !=_nCurUnit) + { + ConverUnit(_nCurUnit, _it->nUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurTimeUnit(); + if ((_it->nUnit == Time_MS + || _it->nUnit == Time_S) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_nCurUnit, _it->nUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurPressureUnit(); + if ((_it->nUnit == Pressure_Percent + || _it->nUnit == Pressure_MPa) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_nCurUnit, _it->nUnit, _nValue, _nValue); + } + + // 如果是整数则先转换。 ---- 黄海燕 2015-09-23 + if (_it->nInitDataType == 0) + _nValue = (int)_nValue; + + if (m_pParam->GetKey_DBL(_it->strKey) != _nValue) + { + m_pParam->SetKey_DBL(_it->strKey, _nValue); + } + } + + // 格式化显示。 + double _nValue = m_pParam->GetKey_DBL(_it->strKey); + Units _nCurUnit = GetCurSpeedUnit(); + if ((_it->nUnit == Speed_INperMin + || _it->nUnit == Speed_MMperMin + || _it->nUnit == Speed_MMperS + || _it->nUnit == Speed_MperMin) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_it->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurAccUnit(); + if ((_it->nUnit == Acc_MMperS2 + || _it->nUnit == ACC_MperMin2 + || _it->nUnit == Acc_10MperS2) + && _it->nUnit !=_nCurUnit) + { + ConverUnit(_it->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurTimeUnit(); + if ((_it->nUnit == Time_MS + || _it->nUnit == Time_S) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_it->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurPressureUnit(); + if ((_it->nUnit == Pressure_Percent + || _it->nUnit == Pressure_MPa) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_it->nUnit, _nCurUnit, _nValue, _nValue); + } + + if (_it->nDataType == 0) + { + CStringA _str; + _str.Format("%d", int(_nValue)); + SetDlgItemText(_it->nID, _str); + GetDlgItem(_it->nID)->SetFocus(); + } + else + { + CStringA _str; + _str.Format("%.3f", _nValue); + FormatDoubleParamer(_str); + SetDlgItemText(_it->nID, _str); + GetDlgItem(_it->nID)->SetFocus(); + } + + break; + } + + return _bDataValid; +} + +void CLayerParamDlg::OnKillFocusEdit(UINT nID_) +{ + //用户取消 ---- 彭朋 2016-07-21 + if (m_bCancelData) + { + return; + } + + for (EditItems::iterator _it = m_listEdits.begin(); _it != m_listEdits.end(); _it++) + { + if (_it->nID != nID_) + continue; + + // 找到了FocusEdit才验证有效性 ---- 彭朋 2016-07-20 + m_bDataValid = false; + bool _bTempDataValid = true; + + // 输入的数据是否有效 + CString _strText = _T(""); + GetDlgItemText(_it->nID, _strText); + if (!IsNumberValid(_strText)) + { + _bTempDataValid = false; + } + + // 如果内容没有变则不用更新。 ---- 黄海燕 2015-09-18 + for (int _i = 0; _bTempDataValid && (_i < _countof(m_LastTextItems)); _i++) + { + if (m_LastTextItems[_i].nID != nID_) + continue; + + if (m_LastTextItems[_i].strLastText == _strText) + { + m_bDataValid = true; + return; + } + + break; + } + + if (!m_bCancelData) + { + if (!_bTempDataValid) + { + m_bCancelData = true; + AfxMessageBox(_GETCS(s_csINVALIDINPUT)); + m_bCancelData = false; + } + } + + // 保存数据。 + if (_bTempDataValid && UpdateData(TRUE)) + { + m_bDataValid = true; + double _nValue = _it->nDataType == 0 ? _it->iValue : _it->dValue; + Units _nCurUnit = GetCurSpeedUnit(); + if ((_it->nUnit == Speed_INperMin + || _it->nUnit == Speed_MMperMin + || _it->nUnit == Speed_MMperS + || _it->nUnit == Speed_MperMin) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_nCurUnit, _it->nUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurAccUnit(); + if ((_it->nUnit == Acc_MMperS2 + || _it->nUnit == ACC_MperMin2 + || _it->nUnit == Acc_10MperS2) + && _it->nUnit !=_nCurUnit) + { + ConverUnit(_nCurUnit, _it->nUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurTimeUnit(); + if ((_it->nUnit == Time_MS + || _it->nUnit == Time_S) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_nCurUnit, _it->nUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurPressureUnit(); + if ((_it->nUnit == Pressure_Percent + || _it->nUnit == Pressure_MPa) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_nCurUnit, _it->nUnit, _nValue, _nValue); + } + + // 如果是整数则先转换。 ---- 黄海燕 2015-09-23 + if (_it->nInitDataType == 0) + _nValue = (int)_nValue; + + if (m_pParam->GetKey_DBL(_it->strKey) != _nValue) + { + m_pParam->SetKey_DBL(_it->strKey, _nValue); + } + } + + // 格式化显示。 + double _nValue = m_pParam->GetKey_DBL(_it->strKey); + Units _nCurUnit = GetCurSpeedUnit(); + if ((_it->nUnit == Speed_INperMin + || _it->nUnit == Speed_MMperMin + || _it->nUnit == Speed_MMperS + || _it->nUnit == Speed_MperMin) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_it->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurAccUnit(); + if ((_it->nUnit == Acc_MMperS2 + || _it->nUnit == ACC_MperMin2 + || _it->nUnit == Acc_10MperS2) + && _it->nUnit !=_nCurUnit) + { + ConverUnit(_it->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurTimeUnit(); + if ((_it->nUnit == Time_MS + || _it->nUnit == Time_S) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_it->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = GetCurPressureUnit(); + if ((_it->nUnit == Pressure_Percent + || _it->nUnit == Pressure_MPa) + && _it->nUnit != _nCurUnit) + { + ConverUnit(_it->nUnit, _nCurUnit, _nValue, _nValue); + } + + if (_it->nDataType == 0) + { + CStringA _str; + _str.Format("%d", int(_nValue)); + SetDlgItemText(_it->nID, _str); + if (!m_bDataValid) + { + GetDlgItem(_it->nID)->SetFocus(); + } + } + else + { + CStringA _str; + _str.Format("%.3f", _nValue); + FormatDoubleParamer(_str); + SetDlgItemText(_it->nID, _str); + if (!m_bDataValid) + { + GetDlgItem(_it->nID)->SetFocus(); + } + } + + break; + } +} + +void CLayerParamDlg::OnSetFocusEdit(UINT nID_) +{ + ASSERT(_countof(m_LastTextItems) >= 2); + m_LastTextItems[1].nID = m_LastTextItems[0].nID; + m_LastTextItems[1].strLastText = m_LastTextItems[0].strLastText; + m_LastTextItems[0].nID = nID_; + GetDlgItemText(nID_, m_LastTextItems[0].strLastText); +} + +void CLayerParamDlg::OnClickPerType(UINT nID_) +{ + int _nType = 0; + if (nID_ == IDC_RADIO_DIRPERFORATE) + { + _nType = 0; + } + else if (nID_ == IDC_RADIO_CONPERORATE) + { + _nType = 1; + } + else if(nID_ == IDC_RADIO_SEGPERFORATE) + { + _nType = 2; + } + else if (nID_ == IDC_RADIO_THREESEGPUNCH) + { + _nType = 3; + } + else + { + return; + } + + if (_nType != m_pParam->GetKey_DBL("PerforateType")) + { + m_pParam->SetKey_DBL("PerforateType", _nType); + m_pParam->SetKey(c_szFirstSegPunch, _nType == 3 ? "1" : "0"); + m_pParam->SetKey(c_szSecondSegPunch, _nType == 3 ? "1" : "0"); + m_pParam->SetKey(c_szThirdSegPunch, _nType == 3 ? "1" : "0"); + } + + // 如果分段穿孔和渐进穿孔则定高切割、板外跟随不能用。 ---- 黄海燕 2015-06-08 + if (_nType == 1 || _nType == 2 || _nType == 3) + { + if (m_pParam->GetKey_DBL("FixedHeightCut") == 1) + m_pParam->SetKey_DBL("FixedHeightCut", 0); + GetDlgItem(IDC_CHECK_FIXHEIGHTCUT)->EnableWindow(FALSE); + if (m_pParam->GetKey_DBL("OutsideCutFollow") == 1) + m_pParam->SetKey_DBL("OutsideCutFollow", 0); + GetDlgItem(IDC_CHECK_CUTTINGFROMOUTSIDE)->EnableWindow(FALSE); + } + else + { + GetDlgItem(IDC_CHECK_FIXHEIGHTCUT)->EnableWindow(TRUE); + GetDlgItem(IDC_CHECK_CUTTINGFROMOUTSIDE)->EnableWindow(TRUE); + } + + Update(); +} + +void CLayerParamDlg::OnClickNeglect() +{ + CString _strUserStyle = NceGetPrivateProfileString(_T("Theme"), _T("UserStyle"), _T("None")); + bool _bIsDNE = (_strUserStyle == _T("DNE")); + + int _nCurIndex = (int)m_pParam->GetKey_DBL("Index"); + if (_bIsDNE && _nCurIndex == 5) + { + // 第六图层设为不加工图层 + m_pParam->SetKey_DBL("Output", false); + } + else + { + bool _bOutput = m_pParam->GetKey_DBL("Output") != 0; + _bOutput = !_bOutput; + m_pParam->SetKey_DBL("Output", _bOutput); + } +} + +void CLayerParamDlg::OnClickNotCloseBlow() +{ + double _nNCB = m_pParam->GetKey_DBL("NotCloseBlow"); + int _nNewNCB = (IsInvalidDouble(_nNCB) || _nNCB == 0.0) ? 1 : 0; + m_pParam->SetKey_DBL("NotCloseBlow", _nNewNCB); +} + +void CLayerParamDlg::OnClickPunchSideBlow() +{ + // 第一位表示穿孔吹气 + double _nSB = m_pParam->GetKey_DBL("SideBlow"); + int _nValue = IsInvalidDouble(_nSB) ? 0 : (int)_nSB; + // 取反 + _nValue ^= 1; + m_pParam->SetKey_DBL("SideBlow", _nValue); +} + +void CLayerParamDlg::OnClickCuttingSideBlow() +{ + // 第二位表示切割吹气 + double _nSB = m_pParam->GetKey_DBL("SideBlow"); + int _nValue = IsInvalidDouble(_nSB) ? 0 : (int)_nSB; + // 取反 + _nValue ^= 2; + m_pParam->SetKey_DBL("SideBlow", _nValue); +} + +// 预穿孔: +// 提取各个图层第一个出现的穿孔动作作为本图层的预穿孔动作,以图形的加工起点构造一系列CCamHole,构 +// 造的CCamHole对象插入Cam根Group的最前面。以PrePerforate的值标识加工时是否执行预穿孔以及区分哪些 +// 是原图形哪些是构造的图形。 +// 预穿孔标志含义: +// PrePerforate=0 ---- 没有预穿孔 +// PrePerforate=1 ---- 预穿孔 +// PrePerforate=2 ---- 表示次图层动作是造出来的,在这类图层上的图形都是孔,图层动作也是跟穿孔相关的动作。 +// ---- 黄海燕 2014-07-19 +void CLayerParamDlg::OnClickPrePerforate() +{ + bool _bPrePer = m_pParam->GetKey_DBL("PrePerforate") == 1; + _bPrePer = !_bPrePer; + m_pParam->SetKey_DBL("PrePerforate", _bPrePer); + + GetDlgItem(IDC_STATIC_PREPERFORATEHEIGHT)->EnableWindow(_bPrePer); + GetDlgItem(IDC_EDIT_PREPERFORATEHEIGHT)->EnableWindow(_bPrePer); + GetDlgItem(IDC_STATIC_PREPERFORATEHEIGHTUNIT)->EnableWindow(_bPrePer); +} + +void CLayerParamDlg::OnClickSlowlyStartup() +{ + bool _bSlowly = m_pParam->GetKey_DBL("SlowlyStartup") == 1; + _bSlowly = !_bSlowly; + + GetDlgItem(IDC_EDIT_STARTUPDIS)->EnableWindow(_bSlowly); + GetDlgItem(IDC_EDIT_STARTUPSPEED)->EnableWindow(_bSlowly); + GetDlgItem(IDC_STATIC_STARTUPDIS)->EnableWindow(_bSlowly); + GetDlgItem(IDC_STATIC_STARTUPDISUNIT)->EnableWindow(_bSlowly); + GetDlgItem(IDC_STATIC_STARTUPSPEED)->EnableWindow(_bSlowly); + GetDlgItem(IDC_STATIC_STARTUPSPEEDUNIT)->EnableWindow(_bSlowly); + m_pParam->SetKey_DBL("SlowlyStartup", _bSlowly); +} + +void CLayerParamDlg::OnSelectCutGas() +{ + CComboBox* _pComb = (CComboBox*)GetDlgItem(IDC_COMBO_CUTTINGAIR); + int _nIndex = _pComb->GetCurSel(); + ASSERT(_nIndex < (int)m_vectCutGas.size()); + if (_nIndex > -1) + m_pParam->SetKey("CutBlowType", m_vectCutGas[_nIndex].strValue); +} + +void CLayerParamDlg::OnSelectPerGas() +{ + CComboBox* _pComb = (CComboBox*)GetDlgItem(IDC_COMBO_PERFORATEAIR); + int _nIndex = _pComb->GetCurSel(); + ASSERT(_nIndex < (int)m_vectPerGas.size()); + if (_nIndex > -1) + m_pParam->SetKey("PerBlowType", m_vectPerGas[_nIndex].strValue); +} + +void CLayerParamDlg::OnSelectCoolingGas() +{ + CComboBox* _pComb = (CComboBox*)GetDlgItem(IDC_COMBO_COOLINGAIR); + int _nIndex = _pComb->GetCurSel(); + ASSERT(_nIndex < (int)m_vectCutGas.size()); + if (_nIndex > -1) + m_pParam->SetKey("CoolBlowType", m_vectCutGas[_nIndex].strValue); +} + +void CLayerParamDlg::OnKillFocusRemarks() +{ + CStringA _strRemarks; + GetDlgItem(IDC_EDIT_UESEREMARK)->GetWindowText(_strRemarks); + _strRemarks = Normative(_strRemarks); + + // 将备注用引号包围,这样Lua就把它当成一串字符串,不会展开解析。 ---- 黄海燕 2015-02-04 + _strRemarks.Insert(0, "\""); + _strRemarks += "\""; + + if (m_pParam->GetKey(LPSTR(c_szRemarks)) != _strRemarks) + m_pParam->SetKey(LPSTR(c_szRemarks), _strRemarks); +} + +void CLayerParamDlg::OnPaint() +{ + __super::OnPaint(); + _PaintImages(); + CWnd* _pWnd = GetDlgItem(IDC_STC_FPCANVAS); + + CPaintDC _PaintDC(_pWnd); + CDC _MemDC; + _MemDC.CreateCompatibleDC(&_PaintDC); + + CBitmap _bmpMemDC; + _bmpMemDC.CreateCompatibleBitmap(&_PaintDC, m_rectCanvas.Width(),m_rectCanvas.Height()); + CBitmap* _pOldBitmap = _MemDC.SelectObject(&_bmpMemDC); + ASSERT(_pOldBitmap); + _MemDC.Rectangle(0, 0, m_rectCanvas.Width(), m_rectCanvas.Height()); + + // 创建红色画笔对象,画坐标轴 + CPen _PenRed; + _PenRed.CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); + CPen* _pOldPen = _MemDC.SelectObject(&_PenRed); + BOOL _nRet = DrawCoor(&_MemDC); + + _nRet &= DrawLine(&_MemDC, m_vectCurLine); + _nRet &= DrawPoint(&_MemDC, m_vectCurLine); + _nRet &= DrawMouseMoveCoor(&_MemDC); + _PaintDC.BitBlt(0, 0, m_rectCanvas.Width(), m_rectCanvas.Height(), &_MemDC, 0, 0, SRCCOPY); + _MemDC.SelectObject(_pOldBitmap); + _MemDC.DeleteDC(); + _bmpMemDC.DeleteObject(); +} + +void CLayerParamDlg::Update() +{ + UpdateData(FALSE); + + // 更新穿孔方式显示。 ---- 黄海燕 2015-01-23 + double _nPerType = m_pParam->GetKey_DBL("PerforateType"); + UINT _nID = -1; + if (_nPerType == 0 || _nPerType == 3) + { + GetDlgItem(IDC_EDIT_PERFORATEHEIGHT)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_PERFORATETIME)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_PERFORATEPOWER)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_PERFORATEFREQ)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_PERFORATECYCLE)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_PERFORATEPRESSURE)->EnableWindow(FALSE); + GetDlgItem(IDC_COMBO_PERFORATEAIR)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_CONPERSPEED)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PUNCHFOCUS)->EnableWindow(FALSE); + GetDlgItem(IDC_EDIT_PUNCHFOCUS)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PUNCHFOCUSUNIT)->EnableWindow(FALSE); + + GetDlgItem(IDC_STATIC_CONPERSPEED)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_CONPERSPEEDUNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERFORATEPOWER)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERPOWERUNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERFORATEFREQ)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERFREQUNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERCYCLE)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERCYCLEUNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERFORATEPRESSURE)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERPRESSUREUNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERFORATEAIR)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERFORATEHEIGHT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERHEIGHTUNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERFORATETIME)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERDELAYUNIT)->EnableWindow(FALSE); + if (_nPerType == 0) _nID = IDC_RADIO_DIRPERFORATE; + else _nID = IDC_RADIO_THREESEGPUNCH; + } + else if (_nPerType == 1) + { + GetDlgItem(IDC_EDIT_PERFORATEHEIGHT)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PERFORATETIME)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PERFORATEPOWER)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PERFORATEFREQ)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PERFORATECYCLE)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PERFORATEPRESSURE)->EnableWindow(TRUE); + GetDlgItem(IDC_COMBO_PERFORATEAIR)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_CONPERSPEED)->EnableWindow(TRUE); + if (m_bEnableFocusCtrl) + { + GetDlgItem(IDC_STATIC_PUNCHFOCUS)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PUNCHFOCUS)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PUNCHFOCUSUNIT)->EnableWindow(TRUE); + } + + GetDlgItem(IDC_STATIC_CONPERSPEED)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_CONPERSPEEDUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATEPOWER)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERPOWERUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATEFREQ)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFREQUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERCYCLE)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERCYCLEUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATEPRESSURE)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERPRESSUREUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATEAIR)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATEHEIGHT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERHEIGHTUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATETIME)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERDELAYUNIT)->EnableWindow(TRUE); + _nID = IDC_RADIO_CONPERORATE; + } + else if (_nPerType = 2) + { + GetDlgItem(IDC_EDIT_PERFORATEHEIGHT)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PERFORATETIME)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PERFORATEPOWER)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PERFORATEFREQ)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PERFORATECYCLE)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PERFORATEPRESSURE)->EnableWindow(TRUE); + GetDlgItem(IDC_COMBO_PERFORATEAIR)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_CONPERSPEED)->EnableWindow(FALSE); + if (m_bEnableFocusCtrl) + { + GetDlgItem(IDC_STATIC_PUNCHFOCUS)->EnableWindow(TRUE); + GetDlgItem(IDC_EDIT_PUNCHFOCUS)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PUNCHFOCUSUNIT)->EnableWindow(TRUE); + } + + GetDlgItem(IDC_STATIC_CONPERSPEED)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_CONPERSPEEDUNIT)->EnableWindow(FALSE); + GetDlgItem(IDC_STATIC_PERFORATEPOWER)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERPOWERUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATEFREQ)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFREQUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERCYCLE)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERCYCLEUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATEPRESSURE)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERPRESSUREUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATEAIR)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATEHEIGHT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERHEIGHTUNIT)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERFORATETIME)->EnableWindow(TRUE); + GetDlgItem(IDC_STATIC_PERDELAYUNIT)->EnableWindow(TRUE); + _nID = IDC_RADIO_SEGPERFORATE; + } + + static const UINT _s_cBtnIDs[]= + {IDC_RADIO_DIRPERFORATE, + IDC_RADIO_CONPERORATE, + IDC_RADIO_SEGPERFORATE, + IDC_RADIO_THREESEGPUNCH}; + CButton* _pBtn = NULL; + int _nCheck = BST_UNCHECKED; + for (int _i = 0; _i < _countof(_s_cBtnIDs); _i++) + { + _pBtn = (CButton*)GetDlgItem(_s_cBtnIDs[_i]); + int _nCheck = _nID == _s_cBtnIDs[_i] ? BST_CHECKED : BST_UNCHECKED; + if (_pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + } + + // 此图层不加工。 ---- 黄海燕 2015-01-23 + CString _strUserStyle = NceGetPrivateProfileString(_T("Theme"), _T("UserStyle"), _T("None")); + bool _bIsDNE = (_strUserStyle == _T("DNE")); + + _pBtn = (CButton*)GetDlgItem(IDC_CHECK_ISIGNORE); + int _nCurIndex = (int)m_pParam->GetKey_DBL("Index"); + + if (_nCurIndex == 5 && _bIsDNE) + { + _pBtn->SetCheck(TRUE); + _pBtn->EnableWindow(FALSE); + m_pParam->SetKey_DBL("Output", false); + } + else + { + _pBtn->EnableWindow(TRUE); + _nCheck = m_pParam->GetKey_DBL("Output") == 0 ? BST_CHECKED : BST_UNCHECKED; + if (_pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + } + + // 此图层不关气 ---- DingQiang 2015-12-04 + _pBtn = (CButton*)GetDlgItem(IDC_CHECK_NOTCLOSEBLOW); + double _nValueDbl = m_pParam->GetKey_DBL("NotCloseBlow"); + int _nValue = IsInvalidDouble(_nValueDbl) ? 0 : (int)_nValueDbl; + _nCheck = (_nValue == 0) ? BST_UNCHECKED : BST_CHECKED; + if (_pBtn->IsWindowEnabled() && _pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + + // 穿孔开侧吹气 ---- DingQiang 2015-12-04 + _pBtn = (CButton*)GetDlgItem(IDC_CHECK_PUNCHSIDEBLOW); + _nValueDbl = m_pParam->GetKey_DBL("SideBlow"); + _nValue = IsInvalidDouble(_nValueDbl) ? 0 : (int)_nValueDbl; + _nCheck = (_nValue & 1) ? BST_CHECKED : BST_UNCHECKED; + if (_pBtn->IsWindowEnabled() && _pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + + // 加工开侧吹气 ---- DingQiang 2015-12-04 + _pBtn = (CButton*)GetDlgItem(IDC_CHECK_CUTTINGSIDEBLOW); + _nCheck = (_nValue & 2) ? BST_CHECKED : BST_UNCHECKED; + if (_pBtn->IsWindowEnabled() && _pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + + // 预穿孔。简化版本中将预穿孔上抬高度灰掉 ---- 边俊霞 2016-12-02 + _pBtn = (CButton*)GetDlgItem(IDC_CHECK_PREPERFORATE); + CString _strSV = NceGetPrivateProfileString(_T("PGLayerDlg"), _T("SimplifiedVersion"), _T("0")); + bool _bSimplifiedVersion = (atoi(_strSV) != 0); + bool _bPrePer = m_pParam->GetKey_DBL("PrePerforate") == 1; + bool _bShow = _bPrePer && !_bSimplifiedVersion; + + _nCheck = _bShow ? BST_CHECKED : BST_UNCHECKED; + if (_pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + GetDlgItem(IDC_STATIC_PREPERFORATEHEIGHT)->EnableWindow(_bShow); + GetDlgItem(IDC_EDIT_PREPERFORATEHEIGHT)->EnableWindow(_bShow); + GetDlgItem(IDC_STATIC_PREPERFORATEHEIGHTUNIT)->EnableWindow(_bShow); + + // 定高切割。 ---- 黄海燕 2015-06-01 + _pBtn = (CButton*)GetDlgItem(IDC_CHECK_FIXHEIGHTCUT); + _nCheck = m_pParam->GetKey_DBL("FixedHeightCut") == 1 ? BST_CHECKED : BST_UNCHECKED; + if (_pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + _pBtn->EnableWindow(_nPerType == 0); + + // 板外跟随 ---- 黄海燕 2015-07-01 + _pBtn = (CButton*)GetDlgItem(IDC_CHECK_CUTTINGFROMOUTSIDE); + _nCheck = m_pParam->GetKey_DBL("OutsideCutFollow") == 1 ? BST_CHECKED : BST_UNCHECKED; + if (_pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + _pBtn->EnableWindow(_nPerType == 0); + + // 慢速起步。 ---- 黄海燕 2015-01-23 + _pBtn = (CButton*)GetDlgItem(IDC_CHECK_ISSTARTUPSLOWLY); + _nCheck = m_pParam->GetKey_DBL("SlowlyStartup") == 1 ? BST_CHECKED : BST_UNCHECKED; + if (_pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + GetDlgItem(IDC_EDIT_STARTUPDIS)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_EDIT_STARTUPSPEED)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_STATIC_STARTUPDIS)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_STATIC_STARTUPDISUNIT)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_STATIC_STARTUPSPEED)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_STATIC_STARTUPSPEEDUNIT)->EnableWindow(_nCheck == BST_CHECKED); + + // 切割气体。 ---- 黄海燕 2015-01-23 + CString _strGas = m_pParam->GetKey("CutBlowType"); + CComboBox* _pCob = (CComboBox*)GetDlgItem(IDC_COMBO_CUTTINGAIR); + int _nIndex = -1; + for (int _i = 0; _i < (int)m_vectCutGas.size(); _i++) + { + if (m_vectCutGas[_i].strValue == _strGas) + { + _nIndex = _i; + break; + } + } + if (_pCob->GetCurSel() != _nIndex) + _pCob->SetCurSel((int)_nIndex); + + // 穿孔气体。 ---- 黄海燕 2015-01-23 + _strGas = m_pParam->GetKey("PerBlowType"); + _pCob = (CComboBox*)GetDlgItem(IDC_COMBO_PERFORATEAIR); + _nIndex = -1; + for (int _i = 0; _i < (int)m_vectCutGas.size(); _i++) + { + if (m_vectPerGas[_i].strValue == _strGas) + { + _nIndex = _i; + break; + } + } + if (_pCob->GetCurSel() != _nIndex) + _pCob->SetCurSel((int)_nIndex); + + // 冷却气体 ---- 杨开锦 2016-03-09 + _strGas = m_pParam->GetKey("CoolBlowType"); + _pCob = (CComboBox*)GetDlgItem(IDC_COMBO_COOLINGAIR); + _nIndex = 0; + for (int _i = 0; _i < (int)m_vectCutGas.size(); _i++) + { + if (m_vectCutGas[_i].strValue == _strGas) + { + _nIndex = _i; + break; + } + } + if (_pCob->GetCurSel() != _nIndex) + _pCob->SetCurSel((int)_nIndex); + + // 用户备注,将Normative中额外加的引号去掉 ---- 黄海燕 2015-01-23 + CStringA _strRemarks = m_pParam->GetKey(LPSTR(c_szRemarks)); + if (!_strRemarks.IsEmpty() && _strRemarks[0] == '\"') + _strRemarks.Delete(0); + int _nLength = _strRemarks.GetLength(); + if (_nLength > 0 && _strRemarks[_nLength - 1] == '\"') + _strRemarks.Delete(_nLength - 1); + _strRemarks = ReverseNormative(_strRemarks); + SetDlgItemText(IDC_EDIT_UESEREMARK, _strRemarks); + + // 回旋过切。 ---- 黄海燕 2015-04-30 + _pBtn = (CButton*)GetDlgItem(IDC_CHECK_CIRCLEOVERCUT); + _nCheck = m_pParam->GetKey_DBL("Overcut") == 1 ? BST_CHECKED : BST_UNCHECKED; + if (_pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + GetDlgItem(IDC_STATIC_CIRCLEANGLE)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_EDIT_CIRCLEANGLE)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_STATIC_CIRCLEANGLEUNIT)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_STATIC_OVERCUTLENGTH)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_EDIT_OVERCUTLENGTH)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_STATIC_OVERCUTLENGTHUNIT)->EnableWindow(_nCheck == BST_CHECKED); + + // 引刀线速度 ---- DingQiang 2015-09-28 + _pBtn = (CButton*)GetDlgItem(IDC_CHECK_ENABLEINTROSPEED); + _nCheck = m_pParam->GetKey("EnableIntroSpeed") == "1" ? BST_CHECKED : BST_UNCHECKED; + if (_pBtn->GetCheck() != _nCheck) + _pBtn->SetCheck(_nCheck); + GetDlgItem(IDC_STC_INSPEED)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_EDIT_INSPEED)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_STATIC_INSPEEDUNIT)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_STC_OUTSPEED)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_EDIT_OUTSPEED)->EnableWindow(_nCheck == BST_CHECKED); + GetDlgItem(IDC_STATIC_OUTSPEEDUNIT)->EnableWindow(_nCheck == BST_CHECKED); + + // 编辑框更新。 ---- 黄海燕 2015-01-23 + _BuildEditInfo(); + UpDateEdits(); +} + +void CLayerParamDlg::UpDateEdits() +{ + for (EditItems::iterator _it = m_listEdits.begin(); _it != m_listEdits.end(); _it++) + { + if (_it->nDataType == 0) + { + CStringA _strNew; + _strNew.Format(_T("%d"), _it->iValue); + + CStringA _strOrg; + GetDlgItemText(_it->nID, _strOrg); + if (_strOrg != _strNew) + SetDlgItemText(_it->nID, _strNew); + } + else + { + ASSERT(_it->nDataType == 1); + CStringA _strNew; + _strNew.Format(_T("%.3f"), _it->dValue); + + FormatDoubleParamer(_strNew); + CStringA _strOrg; + GetDlgItemText(_it->nID, _strOrg);; + if (_strOrg != _strNew) + SetDlgItemText(_it->nID, _strNew); + } + } + + CString _strNewUnit = GetUnitName(GetCurSpeedUnit()); + CString _strOldUnit; + GetDlgItemText(IDC_STATIC_CUTSPEEDUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_CUTSPEEDUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_CONPERSPEEDUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_CONPERSPEEDUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_STARTUPSPEEDUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_STARTUPSPEEDUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_INSPEEDUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_INSPEEDUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_OUTSPEEDUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_OUTSPEEDUNIT, _strNewUnit); + + _strNewUnit = GetUnitName(GetCurTimeUnit()); + GetDlgItemText(IDC_STATIC_PRELASEROFFDELAY, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_PRELASEROFFDELAY, _strNewUnit); + GetDlgItemText(IDC_STATIC_PRELASERONDELAY, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_PRELASERONDELAY, _strNewUnit); + GetDlgItemText(IDC_STATIC_ZUPDELAYUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_ZUPDELAYUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_FOLLOWDELAYUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_FOLLOWDELAYUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_POSTLASERONDELAY, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_POSTLASERONDELAY, _strNewUnit); + GetDlgItemText(IDC_STATIC_STOPCORNERDELAY, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_STOPCORNERDELAY, _strNewUnit); + GetDlgItemText(IDC_STATIC_PERDELAYUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_PERDELAYUNIT, _strNewUnit); + + _strNewUnit = GetUnitName(GetCurPressureUnit()); + GetDlgItemText(IDC_STATIC_PERPRESSUREUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_PERPRESSUREUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_CUTPRESSUREUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_CUTPRESSUREUNIT, _strNewUnit); +} + +void CLayerParamDlg::UpFocusCtrls() +{ + GetDlgItem(IDC_STATIC_CUTFOCUS)->EnableWindow(m_bEnableFocusCtrl); + GetDlgItem(IDC_EDIT_CUTFOCUS)->EnableWindow(m_bEnableFocusCtrl); + GetDlgItem(IDC_STATIC_CUTFOCUSUNIT)->EnableWindow(m_bEnableFocusCtrl); + CWnd* _pwndDlgItem = GetDlgItem(IDC_STATIC_PUNCHFOCUS); + if (_pwndDlgItem->IsWindowEnabled() && !m_bEnableFocusCtrl) + _pwndDlgItem->EnableWindow(FALSE); + _pwndDlgItem = GetDlgItem(IDC_EDIT_PUNCHFOCUS); + if (_pwndDlgItem->IsWindowEnabled() && !m_bEnableFocusCtrl) + _pwndDlgItem->EnableWindow(FALSE); + _pwndDlgItem = GetDlgItem(IDC_STATIC_PUNCHFOCUSUNIT); + if (_pwndDlgItem->IsWindowEnabled() && !m_bEnableFocusCtrl) + _pwndDlgItem->EnableWindow(FALSE); +} + +void CLayerParamDlg::ConverUnit(Units nFrom_, Units nTo_, double IN nOrg_, double& OUT nTarget_) +{ + if (nFrom_ == nTo_) + { + nTarget_ = nOrg_; + return; + } + + if (nFrom_ == Speed_MMperS && nTo_ == Speed_MMperMin) + { + nTarget_ = nOrg_ * 60.0; + return; + } + + if (nFrom_ == Speed_MMperS && nTo_ == Speed_MperMin) + { + nTarget_ = nOrg_ * 60.0 / 1000.0; + return; + } + + if (nFrom_ == Speed_MMperS && nTo_ == Speed_INperMin) + { + nTarget_ = nOrg_ * 60 / 25.39999918; + return; + } + + if (nFrom_ == Speed_MMperMin && nTo_ == Speed_MMperS) + { + nTarget_ = nOrg_ / 60.0; + return; + } + + if (nFrom_ == Speed_MMperMin && nTo_ == Speed_MperMin) + { + nTarget_ = nOrg_ / 1000.0; + return; + } + + if (nFrom_ == Speed_MMperMin && nTo_ == Speed_INperMin) + { + nTarget_ = nOrg_ / 25.39999918; + return; + } + + if (nFrom_ == Speed_INperMin && nTo_ == Speed_MMperS) + { + nTarget_ = nOrg_ * 25.39999918 / 60.0; + return; + } + + if (nFrom_ == Speed_INperMin && nTo_ == Speed_MMperMin) + { + nTarget_ = nOrg_ * 25.39999918; + return; + } + + if (nFrom_ == Speed_INperMin && nTo_ == Speed_MperMin) + { + nTarget_ = nOrg_ * 25.39999918 / 1000.0; + return; + } + + if (nFrom_ == Speed_MperMin && nTo_ == Speed_MMperS) + { + nTarget_ = nOrg_ * 1000.0 / 60.0; + return; + } + + if (nFrom_ == Speed_MperMin && nTo_ == Speed_MMperMin) + { + nTarget_ = nOrg_ * 1000.0; + return; + } + + if (nFrom_ == Speed_MperMin && nTo_ == Speed_INperMin) + { + nTarget_ = nOrg_ * 1000.0 / 25.39999918; + return; + } + + if (nFrom_ == Time_MS && nTo_ == Time_S) + { + nTarget_ = nOrg_ / 1000.0; + return; + } + + if (nFrom_ == Time_S && nTo_ ==Time_MS) + { + nTarget_ = nOrg_ * 1000.0; + return; + } + + if (nFrom_ == Acc_MMperS2 && nTo_ == ACC_MperMin2) + { + nTarget_ = nOrg_ * 3600 /1000.0; + return; + } + + if (nFrom_ == Acc_MMperS2 && nTo_ == Acc_10MperS2) + { + nTarget_ = nOrg_ / 10000; + return; + } + + if (nFrom_ == ACC_MperMin2 && nTo_ == Acc_MMperS2) + { + nTarget_ = nOrg_ * 1000.0 / 3600; + return; + } + + if (nFrom_ == ACC_MperMin2 && nTo_ == Acc_10MperS2) + { + nTarget_ = nOrg_ / 36000; + return; + } + + if (nFrom_ == Acc_10MperS2 && nTo_ == Acc_MMperS2) + { + nTarget_ = nOrg_ * 10 * 1000; + return; + } + + if (nFrom_ == Acc_10MperS2 && nTo_ == ACC_MperMin2) + { + nTarget_ = nOrg_ * 10 * 3600; + return; + } + + if (nFrom_ == Speed_DperMin && nTo_ == Speed_RperMin) + { + nTarget_ = nOrg_ / 360; + return; + } + + if (nFrom_ == Speed_RperMin && nTo_ == Speed_DperMin) + { + nTarget_ = nOrg_ * 360; + return; + } + + if (nFrom_ == Pressure_Percent && nTo_ == Pressure_MPa) + { + CString _strIdentifer("4_0_MaxPressureMPa"); + double _nMaxMpa = 0.0; + SendTargetMessage(ID_TARGET_PARAMMANAGER, TM_GET_PARAMVALUE, WPARAM(_strIdentifer.GetBuffer()), (WPARAM)&_nMaxMpa); + _strIdentifer.ReleaseBuffer(); + if (_nMaxMpa <= 0.0) + _nMaxMpa = 3; + double _nRatio = _nMaxMpa / 100.f; + nTarget_ = nOrg_ * _nRatio; + return; + } + + if (nFrom_ == Pressure_MPa && nTo_ == Pressure_Percent) + { + CString _strIdentifer("4_0_MaxPressureMPa"); + double _nMaxMpa = 0.0; + SendTargetMessage(ID_TARGET_PARAMMANAGER, TM_GET_PARAMVALUE, WPARAM(_strIdentifer.GetBuffer()), (WPARAM)&_nMaxMpa); + _strIdentifer.ReleaseBuffer(); + if (_nMaxMpa <= 0.0) + _nMaxMpa = 3; + double _nRatio = _nMaxMpa / 100.f; + nTarget_ = nOrg_ / _nRatio; + return; + } + + // 没有做转换。 ---- 黄海燕 2015-09-02 + ASSERT(FALSE); + nTarget_ = nOrg_; +} + +void CLayerParamDlg::ConverUnit(Units nFrom_, Units nTo_, const EditInfo& Org_, EditInfo& Target_) +{ + double _nShowValue = 0; + if (Org_.nDataType == 0) + { + ConverUnit(nFrom_, nTo_, Org_.iValue, _nShowValue); + } + else + { + ConverUnit(nFrom_, nTo_, Org_.dValue, _nShowValue); + } + // 可以切换单位的参数一定要求时double类型的。 + Target_.nDataType = 1; + Target_.dValue = _nShowValue; + ConverUnit(nFrom_, nTo_, Org_.nMinValue, Target_.nMinValue); + ConverUnit(nFrom_, nTo_, Org_.nMaxValue, Target_.nMaxValue); +} + +CLayerParamDlg::Units CLayerParamDlg::GetCurSpeedUnit() +{ + // 参见REM20160412195307 ---- 杨开锦 2016-04-12 + static CLayerParamDlg::Units _s_nCSU = None; + static DWORD _s_nCSU_LU = 0; + DWORD _nTC = ::GetTickCount(); + if (_s_nCSU == None || _s_nCSU_LU > _nTC || _nTC > _s_nCSU_LU + 284) + { + _s_nCSU_LU = _nTC; + CString _strSpeedUnit = NceGetPrivateProfileString(c_szParamGroupUnit, c_szSpeedUnit, "0"); + if (_strSpeedUnit == "0") + _s_nCSU = Speed_MMperMin; + else if (_strSpeedUnit == "1") + _s_nCSU = Speed_MMperS; + else if (_strSpeedUnit == "2") + _s_nCSU = Speed_MperMin; + else if (_strSpeedUnit == "3") + _s_nCSU = Speed_INperMin; + else + _s_nCSU = None; + } + + return _s_nCSU; +} + +CLayerParamDlg::Units CLayerParamDlg::GetCurAccUnit() +{ + // 参见REM20160412195307 ---- 杨开锦 2016-04-12 + static CLayerParamDlg::Units _s_nCAU = None; + static DWORD _s_nCAU_LU = 0; + DWORD _nTC = ::GetTickCount(); + if (_s_nCAU == None || _s_nCAU_LU > _nTC || _nTC > _s_nCAU_LU + 284) + { + _s_nCAU_LU = _nTC; + CString _strAccUnit = NceGetPrivateProfileString(c_szParamGroupUnit, c_szAccUnit, "0"); + if (_strAccUnit == "0") + _s_nCAU = Acc_MMperS2; + else if (_strAccUnit == "1") + _s_nCAU = ACC_MperMin2; + else if (_strAccUnit == "2") + _s_nCAU = Acc_10MperS2; + else + _s_nCAU = None; + } + + return _s_nCAU; +} + +CLayerParamDlg::Units CLayerParamDlg::GetCurTimeUnit() +{ + // 参见REM20160412195307 ---- 杨开锦 2016-04-12 + static CLayerParamDlg::Units _s_nCTU = None; + static DWORD _s_nCTU_LU = 0; + DWORD _nTC = ::GetTickCount(); + if (_s_nCTU == None || _s_nCTU_LU > _nTC || _nTC > _s_nCTU_LU + 284) + { + _s_nCTU_LU = _nTC; + CString _strTimeUnit = NceGetPrivateProfileString(c_szParamGroupUnit, c_szTimeUnit, "0"); + if (_strTimeUnit == "0") + _s_nCTU = Time_MS; + else if (_strTimeUnit == "1") + _s_nCTU = Time_S; + else + _s_nCTU = None; + } + + return _s_nCTU; +} + +CLayerParamDlg::Units CLayerParamDlg::GetCurPressureUnit() +{ + // 参见REM20160412195307 ---- 杨开锦 2016-04-12 + static CLayerParamDlg::Units _s_nCTU = None; + static DWORD _s_nCTU_LU = 0; + DWORD _nTC = ::GetTickCount(); + if (_s_nCTU == None || _s_nCTU_LU > _nTC || _nTC > _s_nCTU_LU + 284) + { + _s_nCTU_LU = _nTC; + CString _strTimeUnit = NceGetPrivateProfileString(c_szParamGroupUnit, c_szPressureUnit, "0"); + if (_strTimeUnit == "0") + _s_nCTU = Pressure_Percent; + else if (_strTimeUnit == "1") + _s_nCTU = Pressure_MPa; + else + _s_nCTU = None; + } + + return _s_nCTU; +} + +CString CLayerParamDlg::GetUnitName(const Units nUnit_) +{ + CString _strUnit; + switch(nUnit_) + { + case Length_MM: + _strUnit = "mm"; + break; + case Length_M: + _strUnit = "m"; + break; + case Speed_MMperS: + _strUnit = "mm/s"; + break; + case Speed_MMperMin: + _strUnit = "mm/min"; + break; + case Speed_MperMin: + _strUnit = "m/min"; + break; + case Speed_INperMin: + _strUnit = "in/min"; + break; + case Acc_MMperS2: + _strUnit = "mm/s^2"; + break; + case ACC_MperMin2: + _strUnit = "m/min^2"; + break; + case Acc_10MperS2: + _strUnit = "G"; + break; + case Time_MS: + _strUnit = "ms"; + break; + case Time_S: + _strUnit = "s"; + break; + case Pressure_Percent: + _strUnit = "%"; + break; + case Pressure_MPa: + _strUnit = "MPa"; + break; + default: + _strUnit = ""; + break; + } + + return _strUnit; +} + +// 画坐标轴,X轴左起点留1个c_nOffset,右终点留2个c_nOffset。Y轴下起点留1个c_nOffset +// 上终点留2个c_nOffset ---- DingQiang 2014-12-29 +BOOL CLayerParamDlg::DrawCoor(CDC* pDC_) +{ + if (!pDC_) + { + ASSERT(FALSE); + return FALSE; + } + + BOOL _bRet = true; + // 绘制垂直、水平坐标轴 + CPoint _ptTopLeft(m_rcEffectRect.left, m_rcEffectRect.top - c_nOffset - 3); + CPoint _ptBottomLeft(m_rcEffectRect.left, m_rcEffectRect.bottom); + CPoint _ptRightBottom(m_rcEffectRect.right + c_nOffset + 3, m_rcEffectRect.bottom); + pDC_->MoveTo(_ptTopLeft); + _bRet &= pDC_->LineTo(_ptBottomLeft); + _bRet &= pDC_->LineTo(_ptRightBottom); + // 绘制X轴方向箭头 + pDC_->MoveTo(_ptRightBottom.x - 5, _ptRightBottom.y - 4); + _bRet &= pDC_->LineTo(_ptRightBottom); + pDC_->MoveTo(_ptRightBottom.x - 5, _ptRightBottom.y + 4); + _bRet &= pDC_->LineTo(_ptRightBottom); + // 绘制Y轴方向箭头 + pDC_->MoveTo(_ptTopLeft.x - 4, _ptTopLeft.y + 5); + _bRet &= pDC_->LineTo(_ptTopLeft); + pDC_->MoveTo(_ptTopLeft.x + 4, _ptTopLeft.y + 5); + _bRet &= pDC_->LineTo(_ptTopLeft); + + // 绘制X方向刻度 + double _nXNumPerScale = m_rcEffectRect.Width() / 20.0; + int _nScaleSize = 3; + const int _nBigScale = 3; + for (int _i = 1; _i <= 20; ++_i) + { + if ((_i % 5) == 0) + { + // 5的倍数 + pDC_->MoveTo((int)(_ptBottomLeft.x + _i * _nXNumPerScale), _ptBottomLeft.y); + _bRet &= pDC_->LineTo((int)(_ptBottomLeft.x + _i * _nXNumPerScale), _ptBottomLeft.y - _nScaleSize - _nBigScale); + } + else + { + pDC_->MoveTo((int)(_ptBottomLeft.x + _i * _nXNumPerScale), _ptBottomLeft.y); + _bRet &= pDC_->LineTo((int)(_ptBottomLeft.x + _i * _nXNumPerScale), _ptBottomLeft.y - _nScaleSize); + } + } + // 绘制Y方向刻度 + double _nYNumPerScale = m_rcEffectRect.Height() / 20.0; + for (int _i = 1; _i <= 20; ++_i) + { + if ((_i % 5) == 0) + { + // 5的倍数 + pDC_->MoveTo(_ptBottomLeft.x, (int)(_ptBottomLeft.y - _i * _nYNumPerScale)); + _bRet &= pDC_->LineTo(_ptBottomLeft.x + _nScaleSize + _nBigScale, (int)(_ptBottomLeft.y - _i * _nYNumPerScale)); + } + else + { + pDC_->MoveTo(_ptBottomLeft.x,(int)(_ptBottomLeft.y - _i * _nYNumPerScale)); + _bRet &= pDC_->LineTo(_ptBottomLeft.x + _nScaleSize, (int)(_ptBottomLeft.y - _i * _nYNumPerScale)); + } + } + + LOGFONT _logfont; + memset(&_logfont, 0, sizeof(LOGFONT)); + _logfont.lfHeight = 14; + _logfont.lfWidth = 5; + CFont _font; + _font.CreateFontIndirect(&_logfont); + CFont* _pOldFont = pDC_->SelectObject(&_font); + pDC_->TextOut(m_rectCanvas.right -c_nOffset - 6, m_rectCanvas.bottom - 28, _GETCS(s_szSPEED)); + pDC_->TextOut(c_nOffset + 8, c_nOffset - 2, _GETCS(s_szPOWER)); + pDC_->SelectObject(_pOldFont); + _font.DeleteObject(); + ASSERT(_bRet); + return _bRet; +} + +BOOL CLayerParamDlg::DrawLine(CDC* pDC_, FPLine pFPLine_) +{ + if (!pDC_) + { + ASSERT(FALSE); + return FALSE; + } + + CSpline _Spline; + unsigned int _nFPSize = (unsigned int)pFPLine_.size(); + unsigned char _pBuffer[64 * 1024]; + ParameterI3BH* _pParam = (ParameterI3BH*)_pBuffer; + _pParam->nSize = sizeof(ParameterI3BH) + (_nFPSize - 1) * 2 * sizeof(double); + _pParam->nVersion = 'I3BH'; + _pParam->nN = _nFPSize; + for (unsigned int _i = 0; _i < _nFPSize; _i++) + { + _pParam->nPoints[_i][0] = pFPLine_[_i].nSpeed; + _pParam->nPoints[_i][1] = pFPLine_[_i].nPower; + } + _Spline.Initialize(_pParam); + + double _nTemp = 0.0; + double _nPower; + _Spline.GetValue(_nTemp, &_nPower); + CPoint _ptRet; + _ptRet.x = (int)(_nTemp / c_nMaxSpeed * m_rcEffectRect.Width() + m_rcEffectRect.left + 0.5); + _ptRet.y = (int)((100 - _nPower) / c_nMaxPower * m_rcEffectRect.Height() + m_rcEffectRect.top - 0.5); + pDC_->MoveTo(_ptRet); + _nTemp += 1; + while(_nTemp <= 100) + { + double _nPower; + _Spline.GetValue(_nTemp, &_nPower); + CPoint _ptRet; + _ptRet.x = (int)(_nTemp / c_nMaxSpeed * m_rcEffectRect.Width() + m_rcEffectRect.left + 0.5); + _ptRet.y = (int)((100 - _nPower) / c_nMaxPower * m_rcEffectRect.Height() + m_rcEffectRect.top - 0.5); + _ptRet.y = _ptRet.y > m_rcEffectRect.bottom ? m_rcEffectRect.bottom : _ptRet.y; + _ptRet.y = _ptRet.y < m_rcEffectRect.top ? m_rcEffectRect.top : _ptRet.y; + + pDC_->LineTo(_ptRet); + _nTemp += 1; + } + + return TRUE; +} + +BOOL CLayerParamDlg::DrawMouseMoveCoor(CDC* pDC_) +{ + if (!m_bMouseInCoorCanvas) + { + return TRUE; + } + + CFont _font; + _font.CreateFont(15, 0, 0, 0, FW_NORMAL, + FALSE, FALSE, 0, ANSI_CHARSET, + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + DEFAULT_PITCH | FF_SWISS, _T("Arial")); + + CString _str; + FPPoint _ptFP = Point2FPPoint(m_ptCurMouse); + _str.Format("(%d,%d)", _ptFP.nSpeed, _ptFP.nPower); + CFont* _pOldFont = pDC_->SelectObject(&_font); + + int nPrevMode = pDC_->SetBkMode( TRANSPARENT ); + + BOOL _bRet = TRUE; + if (_ptFP.nSpeed >= 92 && _ptFP.nPower < 92) + { + _bRet &= pDC_->DrawText(_str, CRect(m_ptCurMouse.x - 50, m_ptCurMouse.y - 15, 0, 0), DT_NOCLIP); + } + else if (_ptFP.nSpeed >= 92 && _ptFP.nPower >= 92) + { + _bRet &= pDC_->DrawText(_str, CRect(m_ptCurMouse.x - 50, m_ptCurMouse.y + 15, 0, 0), DT_NOCLIP); + } + else if (_ptFP.nSpeed < 92 && _ptFP.nPower >= 92) + { + _bRet &= pDC_->DrawText(_str, CRect(m_ptCurMouse.x, m_ptCurMouse.y + 15, 0, 0), DT_NOCLIP); + } + else + { + ASSERT(_ptFP.nSpeed < 92 && _ptFP.nPower < 92); + _bRet &= pDC_->DrawText(_str, CRect(m_ptCurMouse.x, m_ptCurMouse.y - 15, 0, 0), DT_NOCLIP); + } + pDC_->SelectObject(_pOldFont); + pDC_->SetBkMode( nPrevMode ); + + return _bRet; +} + +BOOL CLayerParamDlg::DrawPoint(CDC* pDC_, FPLine pFPLine_) +{ + ASSERT(pDC_); + if (pFPLine_.size() < 1) + { + return TRUE; + } + + BOOL _bRet = TRUE; + for (FPLine::iterator _it = pFPLine_.begin(); _it != pFPLine_.end(); _it++) + { + CPoint _pt = FPPoint2Point(*_it); + CPen _pen; + if (_it->bSelected) + { + _bRet &= _pen.CreatePen(PS_SOLID, 1, c_nPointSelected); + CPen* _pOldPent = pDC_->SelectObject(&_pen); + _bRet &= pDC_->Ellipse(_pt.x - c_nRadiusSelected, _pt.y - c_nRadiusSelected, _pt.x + c_nRadiusSelected, _pt.y + c_nRadiusSelected); + pDC_->SelectObject(_pOldPent); + _pen.DeleteObject(); + } + else + { + _bRet &= _pen.CreatePen(PS_SOLID, 1, c_nPointNoSelected); + CPen* _pOldPent = pDC_->SelectObject(&_pen); + _bRet &= pDC_->Ellipse(_pt.x - c_nRadiusNoSelected, _pt.y - c_nRadiusNoSelected, _pt.x + c_nRadiusNoSelected, _pt.y + c_nRadiusNoSelected); + pDC_->SelectObject(_pOldPent); + _pen.DeleteObject(); + } + } + + return _bRet; +} + +void CLayerParamDlg::OnMouseMove(UINT nFlags, CPoint point) +{ + // 鼠标移到导入、保存按钮外框显示高亮。 ---- 黄海燕 2015-05-07 + if (m_rcImportBtn.PtInRect(point)) + { + GetDlgItem(IDC_STATIC_IMPORTAREA)->ShowWindow(SW_SHOW); + } + else + { + GetDlgItem(IDC_STATIC_IMPORTAREA)->ShowWindow(SW_HIDE); + } + if (m_rcSaveBtn.PtInRect(point)) + { + GetDlgItem(IDC_STATIC_SAVEBTNRECT)->ShowWindow(SW_SHOW); + } + else + { + GetDlgItem(IDC_STATIC_SAVEBTNRECT)->ShowWindow(SW_HIDE); + } + _PaintImages(); + + // 这个点是映射到坐标区域内的点x、y分别是0~100 + m_ptCurMouse = point; + TranslatePoint(m_ptCurMouse); + CWnd* _pWnd = GetDlgItem(IDC_STC_FPCANVAS); + ASSERT(_pWnd); + CRect _rc; + _pWnd->GetWindowRect(_rc); + ScreenToClient(_rc); + BOOL _bMouseInCoorCanvas = FALSE; + if (point.x <= _rc.left || point.x >= _rc.right || point.y >= _rc.bottom || point.y <= _rc.top) + { + _bMouseInCoorCanvas = FALSE; + } + else + { + _bMouseInCoorCanvas = TRUE; + } + if (_bMouseInCoorCanvas != m_bMouseInCoorCanvas) + { + InvalidateRect(m_rectCoorCanvas, FALSE); + m_bMouseInCoorCanvas = _bMouseInCoorCanvas; + } + + if (!_bMouseInCoorCanvas) + { + return; + } + + FPPoint _fpPoint = Point2FPPoint(m_ptCurMouse); + //选中了一个点,并且鼠标移动了则进行拖动模式 ---- DingQiang 2013-05-16 + if (m_bSelectPoint && _fpPoint != m_fpTemp) + { + m_nMode = t_move; + size_t _nTemp = -1; + for (size_t _it = 0; _it < m_vectCurLine.size(); ++_it) + { + if (m_fpTemp.nPower == m_vectCurLine[_it].nPower && m_fpTemp.nSpeed == m_vectCurLine[_it].nSpeed) + { + _nTemp = _it; + } + } + + if (_nTemp != -1) + { + if (m_fpTemp.nSpeed == 0 || m_fpTemp.nSpeed == 100) + { + // 首尾两点单独处理 ---- DingQiang 2013-05-15 + m_vectCurLine[_nTemp].nPower = _fpPoint.nPower; + m_fpTemp = m_vectCurLine[_nTemp]; + } + else + { + if (_fpPoint.nSpeed > m_vectCurLine[_nTemp - 1].nSpeed && _fpPoint.nSpeed < m_vectCurLine[_nTemp + 1].nSpeed) + { + m_vectCurLine[_nTemp] = _fpPoint; + } + m_fpTemp = _fpPoint; + } + } + else + { + //ASSERT(FALSE); + } + } + + InvalidateRect(m_rectCoorCanvas, FALSE); +} + +void CLayerParamDlg::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + TranslatePoint(point); + + if (!m_rectCanvas.PtInRect(point)) + { + return; + } + + FPPoint _ptFP; + _ptFP.nSpeed = int((point.x - m_rcEffectRect.left) * c_nMaxSpeed / double(m_rcEffectRect.Width())); + _ptFP.nPower = int(100 - (point.y - m_rcEffectRect.top) * c_nMaxPower / double(m_rcEffectRect.Height())); + _ptFP.nPower = _ptFP.nPower > 100 ? 100 : _ptFP.nPower; + _ptFP.nPower = _ptFP.nPower < 0 ? 0 : _ptFP.nPower; + _ptFP.nSpeed = _ptFP.nSpeed > 100 ? 100 : _ptFP.nSpeed; + _ptFP.nSpeed = _ptFP.nSpeed < 0 ? 0 : _ptFP.nSpeed; + + BOOL _bRet = FALSE; + FPLine::iterator _itEnd = m_vectCurLine.end(); + _itEnd--; + // 在容差范围内选择最近的点删掉。 ---- 黄海燕 2015-05-15 + for (int _i = 0; _i <= c_nSelectTolerance; _i++) + { + for (FPLine::iterator _it = m_vectCurLine.begin(); _it != m_vectCurLine.end(); _it++) + { + if (_it->bSelected + && (abs(_it->nPower - _ptFP.nPower) <= _i) + && (abs(_it->nSpeed - _ptFP.nSpeed) <= _i) + && _it != m_vectCurLine.begin() + && _it != _itEnd) + { + _it = m_vectCurLine.erase(_it); + _bRet = TRUE; + break; + } + } + + if (_bRet) + break; + } + + if (!_bRet) + { + InsertFPPoint(_ptFP); + SortFPLine(m_vectCurLine); + } + InvalidateRect(m_rectCoorCanvas, FALSE); +} + +void CLayerParamDlg::OnLButtonDown(UINT nFlags, CPoint point) +{ + if (m_rcImportBtn.PtInRect(point)) + { + GetDlgItem(IDC_STATIC_IMPORTAREA)->SetFocus(); + return; + } + if (m_rcSaveBtn.PtInRect(point)) + { + GetDlgItem(IDC_STATIC_SAVEBTNRECT)->SetFocus(); + return; + } + + TranslatePoint(point); + if(m_rectCanvas.PtInRect(point)) + { + GetDlgItem(IDC_STC_FPCANVAS)->SetFocus(); + } + + CRect _rect = m_rcEffectRect; + if (point.x >= _rect.left - 1 && point.x <= _rect.right + 1 && point.y >= _rect.top - 1 && point.y <= _rect.bottom + 1) + { + FPPoint _fpPoint = Point2FPPoint(point); + FPPoint _fpPointHit; + if (!TrySetSelect(&_fpPoint, &_fpPointHit)) + { + m_bSelectPoint = FALSE; + return; + } + + m_fpTemp = _fpPointHit; + m_bSelectPoint = TRUE; + InvalidateRect(m_rectCoorCanvas, FALSE); + } +} + +void CLayerParamDlg::OnLButtonUp(UINT nFlags, CPoint point) +{ + __super::OnLButtonUp(nFlags, point); + + if (m_nMode == t_move) + { + m_nMode = t_valid; + } + + m_bSelectPoint = false; + InvalidateRect(m_rectCoorCanvas, FALSE); + + // 点击导入、保存区域弹出对话框。 ---- 黄海燕 2015-05-07 + if (m_rcImportBtn.PtInRect(point)) + { + OnImportParam(); + return; + } + if (m_rcSaveBtn.PtInRect(point)) + { + OnSaveParam(); + return; + } +} + +void CLayerParamDlg::OnRButtonDown(UINT nFlags, CPoint point) +{ + if (m_nMode == t_move) + { + m_nMode = t_valid; + InvalidateRect(m_rectCoorCanvas, FALSE); + } + m_bSelectPoint = FALSE; +} + +void CLayerParamDlg::OnClickEnableFP() +{ + UpdateData(TRUE); +} + +void CLayerParamDlg::OnClickFixedHeightCut() +{ + bool _bFixedHeightCut = m_pParam->GetKey_DBL("FixedHeightCut") == 1; + _bFixedHeightCut = !_bFixedHeightCut; + m_pParam->SetKey_DBL("FixedHeightCut", _bFixedHeightCut); + + // 定高切割和板外跟随为互斥功能。 ---- 黄海燕 2015-07-02 + if (_bFixedHeightCut && m_pParam->GetKey_DBL("OutsideCutFollow") == 1) + { + m_pParam->SetKey_DBL("OutsideCutFollow", 0); + ((CButton*)GetDlgItem(IDC_CHECK_CUTTINGFROMOUTSIDE))->SetCheck(BST_UNCHECKED); + } +} + +void CLayerParamDlg::OnCutFromOutside() +{ + bool _bCutFromOutside = m_pParam->GetKey_DBL("OutsideCutFollow") == 1; + _bCutFromOutside = !_bCutFromOutside; + CString _strOutsideHeight = NceGetPrivateProfileString(_T("OutsideCutting"), _T("OutsideHeight")); + if (_strOutsideHeight.IsEmpty() && _bCutFromOutside) + { + AfxMessageBox(_GETCS(s_szNOTSAVEOUTSIDEHEIGHT)); + ((CButton*)GetDlgItem(IDC_CHECK_CUTTINGFROMOUTSIDE))->SetCheck(BST_UNCHECKED); + return; + } + + m_pParam->SetKey_DBL("OutsideCutFollow", _bCutFromOutside); + if (_bCutFromOutside && m_pParam->GetKey_DBL("FixedHeightCut") == 1) + { + m_pParam->SetKey_DBL("FixedHeightCut", 0); + ((CButton*)GetDlgItem(IDC_CHECK_FIXHEIGHTCUT))->SetCheck(BST_UNCHECKED); + } +} + +BOOL CLayerParamDlg::CPointToCoorCanvasPoint(IN CPoint pPointIn_, OUT CPoint& pPointOut_) +{ + CWnd* _pWnd = GetDlgItem(IDC_STC_FPCANVAS); + ASSERT(_pWnd); + CRect _rc; + _pWnd->GetWindowRect(_rc); + ScreenToClient(_rc); + if (pPointIn_.x <= _rc.left || pPointIn_.x >= _rc.right || pPointIn_.y >= _rc.bottom || pPointIn_.y <= _rc.top) + { + return FALSE; + } + + _rc.left += c_nOffset; + _rc.right -= 2 * c_nOffset; + _rc.bottom -= c_nOffset; + _rc.top += 2 * c_nOffset; + // 这两个值应该分别是3、2。做对话框的时候就设计好了,x一个刻度是3个像素, + // y一个刻度是2个像素 ---- DingQiang 2014-12-30 + int _nPelsXOneScale = _rc.Width() / 100; + int _nPelsYOneScale = _rc.Height() / 100; + + pPointOut_.x = (pPointIn_.x - _rc.left) / _nPelsXOneScale; + pPointOut_.y = 100 - (pPointIn_.y - _rc.top) / _nPelsXOneScale; + + return TRUE; +} + +FPPoint CLayerParamDlg::Point2FPPoint(CPoint point_) +{ + double _nPelsXOneScale = m_rcEffectRect.Width() / c_nMaxSpeed; + double _nPelsYOneScale =m_rcEffectRect.Height() / c_nMaxPower; + + FPPoint _ptFP; + _ptFP.nSpeed = int((point_.x - m_rcEffectRect.left) / _nPelsXOneScale); + _ptFP.nPower = int(100 - (point_.y - m_rcEffectRect.top) / _nPelsYOneScale); + _ptFP.nSpeed = _ptFP.nSpeed > 100 ? 100 : _ptFP.nSpeed; + _ptFP.nPower = _ptFP.nPower > 100 ? 100 : _ptFP.nPower; + _ptFP.nSpeed = _ptFP.nSpeed < 0 ? 0 : _ptFP.nSpeed; + _ptFP.nPower = _ptFP.nPower < 0 ? 0 : _ptFP.nPower; + return _ptFP; +} + +void CLayerParamDlg::TranslatePoint(CPoint& point_) +{ + CWnd* _pWnd = GetDlgItem(IDC_STC_FPCANVAS); + ASSERT(_pWnd); + + MapWindowPoints(_pWnd, &point_, 1); +} + +void CLayerParamDlg::SortFPLine(FPLine& FPLine_) +{ + // 0个或者1个不用排序 ---- DingQiang 2013-04-12 + if (FPLine_.size() < 2) + { + return; + } + + // 依照速度值,从小到大进行排序 ---- DingQiang 2013-04-12 + for (FPLine::iterator _it = FPLine_.begin(); _it != FPLine_.end(); _it++) + { + for (FPLine::iterator _item = _it + 1; _item != FPLine_.end(); _item++) + { + if (_it->nSpeed > _item->nSpeed) + { + int _nSpeedTemp = _item->nSpeed; + int _nPowerTemp = _item->nPower; + bool _bTemp = _item->bSelected; + + _item->nSpeed = _it->nSpeed; + _item->nPower = _it->nPower; + _item->bSelected = _it->bSelected; + _it->nSpeed = _nSpeedTemp; + _it->nPower = _nPowerTemp; + _it->bSelected = _bTemp; + } + } + } +} + +BOOL CLayerParamDlg::InsertFPPoint(FPPoint fppoint_) +{ + ASSERT(fppoint_.nSpeed >= 0 && fppoint_.nSpeed <= 100 && fppoint_.nPower >= 0 && fppoint_.nPower <= 100); + + for (FPLine::iterator _it = m_vectCurLine.begin(); _it != m_vectCurLine.end();) + { + if (_it->nSpeed == fppoint_.nSpeed) + { + _it = m_vectCurLine.erase(_it); + } + else + { + _it++; + } + } + + m_vectCurLine.push_back(fppoint_); + return TRUE; +} + +CPoint CLayerParamDlg::FPPoint2Point(FPPoint ptFP_) +{ + CPoint _ptRet; + _ptRet.x = (int)(ptFP_.nSpeed / 100. * m_rcEffectRect.Width() + m_rcEffectRect.left + 0.5); + _ptRet.y = (int)((100 - ptFP_.nPower) / 100. * m_rcEffectRect.Height() + m_rcEffectRect.top - 0.5); + + return _ptRet; +} + +BOOL CLayerParamDlg::TrySetSelect(IN FPPoint* fppoint_, OUT FPPoint* fpPointHit_) +{ + ASSERT(fppoint_->nSpeed >= 0 && fppoint_->nSpeed <= 100 && fppoint_->nPower >= 0 && fppoint_->nPower <= 100); + + // 设置一个一个增大,先找最近的点,找不到再放大范围找,直到找到点或者是超过容差范围。 ---- 黄海燕 2015-05-15 + bool _bFind = false; + for (int _i = 0; _i <= c_nSelectTolerance; _i++) + { + for (FPLine::iterator _it = m_vectCurLine.begin(); _it != m_vectCurLine.end(); _it++) + { + if (abs(_it->nSpeed - fppoint_->nSpeed) <= _i && abs(_it->nPower - fppoint_->nPower) <= _i && !_bFind) + { + // 找到一个则返回,即当前只能同时选中一个点 ---- DingQiang 2013-04-11 + _it->bSelected = true; + _bFind = true; + fpPointHit_->nPower = _it->nPower; + fpPointHit_->nSpeed = _it->nSpeed; + } + else + { + _it->bSelected = false; + } + } + + if (_bFind) + break; + } + + return _bFind; +} + +// 保存图层参数。 ---- 黄海燕 2015-04-17 +void CLayerParamDlg::OnSaveParam() +{ + if (!m_pParam) + { + ASSERT(FALSE); + return; + } + + CStringA _strName = m_pParam->GetKey("Name"); + if (!_strName.IsEmpty() && _strName[0] == '\"') _strName.Delete(0); + if (!_strName.IsEmpty() && _strName[_strName.GetLength() - 1] == '\"') _strName.Delete(_strName.GetLength() - 1); + if (_strName.FindOneOf("\\//:*?\"<>| ") != -1) + { + _strName = _GETCS(s_szDEFUALTPARAMFILENAME); + } + else + { + _strName += ".ltp"; + } + + // 弹出文件保存对话框。 + TCHAR _szFileFilter[] = _T("ltp File(*.ltp) |*.ltp"); + CFileDialog _dlg(FALSE, _T(".ltp"), + _strName, + OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + _szFileFilter, this, 0); + + CString _strDefaultFolder = m_strDefaultFilePath; + if (!_strDefaultFolder.IsEmpty()) + { + if (!::PathFileExists(_strDefaultFolder)) + _tmkdir(_strDefaultFolder); + _dlg.GetOFN().lpstrInitialDir = _strDefaultFolder; + } + if (_dlg.DoModal() != IDOK) + { + return; + } + + CString _strDir = _dlg.GetPathName(); + if (_strDir.Right(4) != _T(".ltp")) + _strDir += _T(".ltp"); + + // 将参数保存至文件。 + _SaveParam(_strDir); +} + +// 文件保存格式为: +// [UserRemarks] +// Remarks="" +// [PowerCurve] +// FPMapEnable=0 +// FF0=0 +// FP0=0 +// FF1=100 +// FP1=100 +// ... +// [TechnicParam] +// Index=0 +// ... +// ---- 黄海燕 2015-04-17 +void CLayerParamDlg::_SaveParam(LPCTSTR pszFilePath_) +{ + if (!m_pParam) + { + ASSERT(FALSE); + return; + } + + // 检查文件是否已存在,已存在就提示是否覆盖,如果没有就创建一个。 + if (::PathFileExists(pszFilePath_) + && AfxMessageBox(_GETCS(s_szPARAMFILEEXIST), MB_YESNO | MB_ICONINFORMATION) != IDYES) + { + return; + } + + CFile _file; + if (!_file.Open(pszFilePath_, CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive)) + { + ASSERT(FALSE); + return; + } + + + CString _strWriteParamString; + // 保存用户备注。 + CString _strRemarks = m_pParam->GetKey(LPSTR(c_szRemarks)); + _strWriteParamString += "[UserRemarks]\r\n"; + _strWriteParamString += _GetLine(c_szRemarks, _strRemarks); + + // 保存速度功率曲线 + SaveFPCurve(); + _strWriteParamString += "[PowerCurve]\r\n"; + _strWriteParamString += _GetLine(c_szEnableFPMap, m_pParam->GetKey(LPSTR(c_szEnableFPMap))); + for (int _i = 0; _i <= 100; _i++) + { + CStringA _strFFKey; + _strFFKey.Format("FF%d", _i); + CStringA _strFFValue = m_pParam->GetKey(_strFFKey); + CStringA _strFPKey; + _strFPKey.Format("FP%d", _i); + CStringA _strFPValue = m_pParam->GetKey(_strFPKey); + if (_strFFValue.IsEmpty() || _strFPValue.IsEmpty()) + break; + _strWriteParamString += _GetLine(_strFFKey, _strFFValue); + _strWriteParamString += _GetLine(_strFPKey, _strFPValue); + } + + // 保存其他的工艺参数 + _strWriteParamString += "[TechnicParam]\r\n"; + CStringA _strParam = m_pParam->GetParamString(); + for (int _i = 0; _i < _strParam.GetLength() - 3; ) + { + int _nSemicIndex = _strParam.Find(';', _i); + CStringA _strUnit = _strParam.Mid(_i, _nSemicIndex == -1 ? _strParam.GetLength() : _nSemicIndex - _i); + if (_strUnit.IsEmpty()) + break; + int _nEQIndex = _strUnit.Find('='); + CStringA _strKey = _nEQIndex == -1 ? "" : _strUnit.Left(_nEQIndex); + CStringA _strValue = _nEQIndex == -1 ? "" : _strUnit.Right(_strUnit.GetLength() - _nEQIndex - 1); + if (_strKey.IsEmpty()) + { + _i = _nSemicIndex + 1; + continue; + } + + bool _bIgnore = false; + // 忽略掉速度功率曲线参数。 + if (!_strKey.IsEmpty() && (_strKey.Left(2) == "FF" || _strKey.Left(2) == "FP")) + { + for (int _j = 0; _j <= 100; _j++) + { + CStringA _strFF, _strFP; + _strFF.Format("FF%d", _j); + _strFP.Format("FP%d", _j); + if (_strKey == _strFF || _strKey == _strFP) + { + _bIgnore = true; + break; + } + } + } + if (_strKey == CStringA(c_szEnableFPMap)) + _bIgnore = true; + + // 忽略用户备注。 + if (_strKey == CStringA(c_szRemarks)) + _bIgnore = true; + + if (!_bIgnore) + _strWriteParamString += _GetLine(_strKey, _strValue); + _i = _nSemicIndex + 1; + } + + try + { + _file.Write(_strWriteParamString.GetBuffer(), _strWriteParamString.GetLength() * sizeof(TCHAR)); + _strWriteParamString.ReleaseBuffer(); + } + catch(...) + { + ASSERT(FALSE); + } + _file.Close(); +} + +CString CLayerParamDlg::_GetLine(LPCTSTR pszKey_, LPCTSTR pszValue_) +{ + if (!pszValue_ || !pszKey_) + { + ASSERT(FALSE); + return ""; + } + + CString _strLine; + _strLine += pszKey_; + _strLine += '='; + _strLine += pszValue_; + _strLine += "\r\n"; + return _strLine; +} + +// 导入图层参数。 ---- 黄海燕 2015-04-17 +void CLayerParamDlg::OnImportParam() +{ + if (!m_pParam) + { + ASSERT(FALSE); + return; + } + + // 弹出文件打开对话框。 + TCHAR _szFileFilter[] = _T("ltp File(*.ltp) |*.ltp"); + CFileDialog _dlg(TRUE, _T(".ltp"), NULL, + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR, + _szFileFilter, this, 0); + + CString _strDefaultFolder = m_strDefaultFilePath; + if (!_strDefaultFolder.IsEmpty()) + { + if (!::PathFileExists(_strDefaultFolder)) + _tmkdir(_strDefaultFolder); + _dlg.GetOFN().lpstrInitialDir = _strDefaultFolder; + } + if (_dlg.DoModal() != IDOK) + return; + + // 选中文件之前提示是否覆盖图层参数 + CString _strDir = _dlg.GetPathName(); + if (!::PathFileExists(_strDir.GetBuffer())) + { + AfxMessageBox(_GETCS(s_szPARAMFILENOTEXIST)); + return; + } + + if (AfxMessageBox(_GETCS(s_szPARAMOVERWRITEPROMT), MB_YESNO) != IDYES) + return; + + _LoadParam(_strDir); +} + +void CLayerParamDlg::_LoadParam(LPCTSTR pszFilePath_) +{ + if (!m_pParam) + { + ASSERT(FALSE); + return; + } + + TCHAR _szBuffer[64 * 1024] = {0}; // 假设64K就够了。 + DWORD _nCount = ::GetPrivateProfileString(NULL, NULL, NULL, _szBuffer, sizeof(_szBuffer), pszFilePath_); + std::list _listSections; + CString _strSection; + for(DWORD _i = 0; _i < _nCount; _i++) + { + if (_szBuffer[_i] != '\0') _strSection += _szBuffer[_i]; + if (_szBuffer[_i] == '\0') + { + _listSections.push_back(_strSection); + _strSection = ""; + if (_szBuffer[_i + 1] == '\0') + break; + } + } + + if (_listSections.empty()) + return; + + _ClearFPMapPoints(m_pParam); + memset(_szBuffer, 0, sizeof(_szBuffer)); + for (std::list::iterator _it = _listSections.begin(); _it != _listSections.end(); _it++) + { + DWORD _nKeyCount = ::GetPrivateProfileString((*_it), NULL, NULL, _szBuffer, sizeof(_szBuffer), pszFilePath_); + CString _strKey; + for (DWORD _i = 0; _i < _nKeyCount; _i++) + { + if (_szBuffer[_i] != '\0') _strKey += _szBuffer[_i]; + if (_szBuffer[_i] == '\0') + { + if (!_strKey.IsEmpty()) + { + // 不读入图层颜色信息和图层号。 + if (_strKey != _T("Color") && _strKey != _T("Index")) + { + TCHAR _szValue[64 * 1024] = {0}; + ::GetPrivateProfileString((*_it), _strKey, "", _szValue, sizeof(_szValue), pszFilePath_); + + // 如果是名称和备注的话则用引号引起来,以免导致Lua中解析出错。 ---- 黄海燕 2015-05-21 + CString _strValue(_szValue); + if (_strKey == c_szRemarks + || _strKey == _T("Name") + || _strKey == _GETCS(s_szLAYERNAME) + || _strKey == c_szThreeSegPunchRemarks) + { + if (!_strValue.IsEmpty() && _strValue[0] != _T('\"')) _strValue.Insert(0, _T('\"')); + if (!_strValue.IsEmpty() && _strValue[_strValue.GetLength() - 1] != _T('\"')) _strValue += _T('\"'); + } + + if (m_pParam->GetKey(_strKey) != _strValue) + m_pParam->SetKey(_strKey, _strValue); + } + _strKey = ""; + } + + if (_szBuffer[_i + 1] == '\0') + break; + } + } + } + + Update(); + SetParam(m_pParam); + ((CParamGroupDlg_R3*)GetParent())->Update(); + ((CParamGroupDlg_R3*)GetParent())->UpdateLoadLayer(m_pParam); +} + +void CLayerParamDlg::_ClearFPMapPoints(nce::CParam* pParam_) +{ + if (!pParam_) + { + ASSERT(FALSE); + return; + } + + CString _strFTemp = "FF%d"; + CString _strPTemp = "FP%d"; + for (int _it = 0; _it <= 100; _it++) + { + CString _strF; + _strF.Format(_strFTemp, _it); + CString _strP; + _strP.Format(_strPTemp, _it); + + CStringA _strFValue = m_pParam->GetKey(_strF); + CStringA _strPValue = m_pParam->GetKey(_strP); + if (!_strFValue.IsEmpty()) + pParam_->SetKey(_strF, ""); + if (!_strPValue.IsEmpty()) + pParam_->SetKey(_strP, ""); + } +} + +void CLayerParamDlg::OnEnableIntroSpeed() +{ + bool _bIntroSpeed = m_pParam->GetKey("EnableIntroSpeed") == "1"; + + _bIntroSpeed = !_bIntroSpeed; + + GetDlgItem(IDC_STC_INSPEED)->EnableWindow(_bIntroSpeed); + GetDlgItem(IDC_EDIT_INSPEED)->EnableWindow(_bIntroSpeed); + GetDlgItem(IDC_STATIC_INSPEEDUNIT)->EnableWindow(_bIntroSpeed); + GetDlgItem(IDC_STC_OUTSPEED)->EnableWindow(_bIntroSpeed); + GetDlgItem(IDC_EDIT_OUTSPEED)->EnableWindow(_bIntroSpeed); + GetDlgItem(IDC_STATIC_OUTSPEEDUNIT)->EnableWindow(_bIntroSpeed); + m_pParam->SetKey("EnableIntroSpeed", _bIntroSpeed ? "1" : "0"); +} + +void CLayerParamDlg::OnClickOvercut() +{ + bool _bOvercut = m_pParam->GetKey_DBL("Overcut") == 1; + _bOvercut = !_bOvercut; + + GetDlgItem(IDC_STATIC_CIRCLEANGLE)->EnableWindow(_bOvercut); + GetDlgItem(IDC_EDIT_CIRCLEANGLE)->EnableWindow(_bOvercut); + GetDlgItem(IDC_STATIC_CIRCLEANGLEUNIT)->EnableWindow(_bOvercut); + GetDlgItem(IDC_STATIC_OVERCUTLENGTH)->EnableWindow(_bOvercut); + GetDlgItem(IDC_EDIT_OVERCUTLENGTH)->EnableWindow(_bOvercut); + GetDlgItem(IDC_STATIC_OVERCUTLENGTHUNIT)->EnableWindow(_bOvercut); + m_pParam->SetKey_DBL("Overcut", _bOvercut); +} + +// 给保存、导入按钮贴图。 ---- 黄海燕 2015-05-16 +void CLayerParamDlg::_PaintImages() +{ + CDC* _pDestDC = GetDC(); + CDC _SrcDC; + _SrcDC.CreateCompatibleDC(_pDestDC); + CBitmap _bmpImpot; + _bmpImpot.LoadBitmap(IDB_BITMAP_LAYERPARAMIMPORT); + CBitmap* _pOldBmp = _SrcDC.SelectObject(&_bmpImpot); + CRect _rcPaint; + GetDlgItem(IDC_STATIC_IMPORTIMAGE)->GetWindowRect(_rcPaint); + ScreenToClient(_rcPaint); + _pDestDC->BitBlt(_rcPaint.left, _rcPaint.top, _rcPaint.Width() - 2, _rcPaint.Height() - 2, &_SrcDC, 1, 5, SRCCOPY); + CBitmap _bmpSave; + _bmpSave.LoadBitmap(IDB_BITMAP_LAYERPARAMSAVE); + _SrcDC.SelectObject(&_bmpSave); + GetDlgItem(IDC_STATIC_SAVEIMAGE)->GetWindowRect(_rcPaint); + ScreenToClient(_rcPaint); + _pDestDC->BitBlt(_rcPaint.left, _rcPaint.top, _rcPaint.Width() - 2, _rcPaint.Height() - 1, &_SrcDC, 1, 1, SRCCOPY); + _SrcDC.SelectObject(_pOldBmp); + _SrcDC.DeleteDC(); + _bmpImpot.DeleteObject(); + ReleaseDC(_pDestDC); +} + +void CLayerParamDlg::OnTimer(UINT_PTR nIDEvent_) +{ + _PaintImages(); +} + +void CLayerParamDlg::OnClickEditFPMap() +{ + CFPMappingEditDlg _dlg(m_vectCurLine); + if(_dlg.DoModal() == IDOK) + { + m_vectCurLine = _dlg.m_FPLine; + InvalidateRect(m_rectCoorCanvas, FALSE); + } +} diff --git a/src/MachineControlDlg.cpp b/src/MachineControlDlg.cpp new file mode 100644 index 0000000..fd58632 --- /dev/null +++ b/src/MachineControlDlg.cpp @@ -0,0 +1,2718 @@ +// ************************************************************************** // +// MachineControlDlg.cpp : implementation of the CMachineControlDlg class +// Copyright(c)2011 Naiky Company. All rights reserved. +// +// Abstract: +// 本文件实现CMachineControlDlg类。 +// ********************************************* ---- 杨开锦 2011-10-31 ***** // +#include "stdafx.h" +#include "MachineControlDlg.h" +#include "EditItem.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW +#endif + +CS_T s_csRapidJog = _DEFCS(_CSV(18044), + _CHINESE("高速") + _ENGLISH("Rapid\nJog")); +CS_T s_csSlowJog = _DEFCS(_CSV(18045), + _CHINESE("连续") + _ENGLISH("Jog")); +CS_T s_csJOG = _DEFCS(_CSV(18046), + _CHINESE("点动") + _ENGLISH("Jog")); +CS_T s_csLANGUAGE = _DEFCS(_CSV(18047), + _CHINESE("CHN") + _ENGLISH("ENG")); +CS_T s_csNotInputPrompt = _DEFCS(_CSV(18048), + _CHINESE("系统忙,当前加工状态无法修改该参数!") + _ENGLISH("System is busy, can not change the parameters!")); +CS_T s_csIntDataError = _DEFCS(_CSV(18049), + _CHINESE("输入的参数无效,只能输入正整数,请重新输入!") + _ENGLISH("Data error, it should be a positive integer, Please enter again!")); +CS_T s_csFloatDataError = _DEFCS(_CSV(18050), + _CHINESE("输入的参数无效,请重新输入!") + _ENGLISH("Data error, it should be a number, Please enter again!")); +CS_T s_csFloatDataBoundError = _DEFCS(_CSV(18051), + _CHINESE("参数范围错误,请输入一个“%.1f~%.1f”之间的数!") + _ENGLISH("Please enter a number between %f~%f")); + +CS_T s_csAXES = _DEFCS(_CSV(18052), + _CHINESE("轴") + _ENGLISH("Axes")); +CS_T s_csMACHINECOORDINATE = _DEFCS(_CSV(18053), + _CHINESE("机械坐标") + _ENGLISH("MachCoor")); +CS_T s_csWORKPIECECOORDINATE = _DEFCS(_CSV(18054), + _CHINESE("工件坐标") + _ENGLISH("WorkCoor")); + +CS_T s_csRESUME = _DEFCS(_CSV(18055), + _CHINESE("断点\n继续") + _ENGLISH("Resume")); +CS_T s_csSIMU = _DEFCS(_CSV(18056), + _CHINESE("仿真") + _ENGLISH("Simu")); +CS_T s_csDIRRUN = _DEFCS(_CSV(18057), + _CHINESE("空运行") + _ENGLISH("DryRun")); +CS_T s_csDIRRUNTEXT = _DEFCS(_CSV(18057), + _CHINESE("空运行") + _ENGLISH("Dry Run")); +CS_T s_csSIMUCUTBOUNDRECT = _DEFCS(_CSV(18523), + _CHINESE("走边框") + _ENGLISH("Frame")); +CS_T s_csTipSETWORKORG = _DEFCS(_CSV(18058), + _CHINESE("设置工件原点") + _ENGLISH("Set Work Zero")); +CS_T s_csTipMOVETOWORKORIGIN = _DEFCS(_CSV(18059), + _CHINESE("回工件原点") + _ENGLISH("To Work Zero")); +CS_T s_csTipSIMUCUTBOUNDRECT = _DEFCS(_CSV(18060), + _CHINESE("走边框") + _ENGLISH("Frame")); +CS_T s_csTipSTART = _DEFCS(_CSV(18061), + _CHINESE("开始") + _ENGLISH("Start")); +CS_T s_csTipPAUSE = _DEFCS(_CSV(18062), + _CHINESE("暂停") + _ENGLISH("Pause")); +CS_T s_csTipSTOP = _DEFCS(_CSV(18063), + _CHINESE("停止") + _ENGLISH("Stop")); +CS_T s_csTipRESUME = _DEFCS(_CSV(18063), + _CHINESE("断点继续") + _ENGLISH("Resume")); +CS_T s_csTipGoBackward = _DEFCS(_CSV(18064), + _CHINESE("后退") + _ENGLISH("GoBackward")); +CS_T s_csTipGoForward = _DEFCS(_CSV(18065), + _CHINESE("前进") + _ENGLISH("GoForward")); +CS_T s_csTipFollowSample = _DEFCS(_CSV(18524), + _CHINESE("Z轴标定") + _ENGLISH("Calibrate Z")); +CS_T s_csTipBackAll = _DEFCS(_CSV(18525), + _CHINESE("全部回机械原点") + _ENGLISH("All To Origin")); +CS_T s_csSELECTMACH = _DEFCS(_CSV(18620), + _CHINESE("加工选中图形") + _ENGLISH("Machine Selected")); +CS_T s_csDistanceSet = _DEFCS(_CSV(18066), + _CHINESE("前进后退距离设定") + _ENGLISH("Distance Set")); +CS_T s_szPortNameKey = _DEFCS(_CSV(18067), + _CHINESE("Port%d_ChnName") + _ENGLISH("Port%d_EngName")); +CS_T s_szLaserOnWhenJog = _DEFCS(_CSV(18067), + _CHINESE("点动时开光") + _ENGLISH("Laser ON at Jog")); +CS_T s_szStartSelected = _DEFCS(_CSV(18067), + _CHINESE("加工选中图形") + _ENGLISH("Start for Selection")); +CS_T s_szAutoExchange = _DEFCS(_CSV(18068), + _CHINESE("加工后自动交换") + _ENGLISH("Auto Exchange")); +CS_T s_szAutoCyc = _DEFCS(_CSV(18068), + _CHINESE("循环加工") + _ENGLISH("Cycle Machining")); +CS_T s_szLevel = _DEFCS(_CSV(18067), + _CHINESE("校平\n分中") + _ENGLISH("Top\nCenter")); +CS_T s_szCentering = _DEFCS(_CSV(18067), + _CHINESE("四面\n分中") + _ENGLISH("Faces\nCenter")); +CS_T s_szMUNU_MARKPOINT1 = _DEFCS(_CSV(18640), + _CHINESE("标记点1") + _ENGLISH("Mark point1")); +CS_T s_szMUNU_MARKPOINT2 = _DEFCS(_CSV(18641), + _CHINESE("标记点2") + _ENGLISH("Mark point2")); +CS_T s_szMUNU_MARKPOINT3 = _DEFCS(_CSV(18642), + _CHINESE("标记点3") + _ENGLISH("Mark point3")); +CS_T s_szMUNU_MARKPOINT4 = _DEFCS(_CSV(18643), + _CHINESE("标记点4") + _ENGLISH("Mark point4")); +CS_T s_szMUNU_MARKPOINT5 = _DEFCS(_CSV(18644), + _CHINESE("标记点5") + _ENGLISH("Mark point5")); +CS_T s_szMUNU_MARKPOINT6 = _DEFCS(_CSV(18645), + _CHINESE("标记点6") + _ENGLISH("Mark point6")); +CS_T s_szMUNU_MARKPOINT7 = _DEFCS(_CSV(18646), + _CHINESE("标记点7") + _ENGLISH("Mark point7")); +CS_T s_szMUNU_MARKPOINT8 = _DEFCS(_CSV(18647), + _CHINESE("标记点8") + _ENGLISH("Mark point8")); +CS_T s_szMUNU_MARK = _DEFCS(_CSV(18647), + _CHINESE("标记坐标") + _ENGLISH("Set Mark")); +CS_T s_szMUNU_BACKMARK = _DEFCS(_CSV(18647), + _CHINESE("返回标记") + _ENGLISH("Go Mark")); +CS_T s_szMUNU_MARKNUM = _DEFCS(_CSV(18647), + _CHINESE("标记点") + _ENGLISH("Mark Point")); +CS_T s_szMUNU_BACKORG = _DEFCS(_CSV(18647), + _CHINESE("机械回零") + _ENGLISH("All Origin")); +CS_T s_szMUNU_SETW = _DEFCS(_CSV(18647), + _CHINESE("工件置零") + _ENGLISH("Set Zero")); +CS_T s_szMUNU_BW = _DEFCS(_CSV(18647), + _CHINESE("工件回零") + _ENGLISH("To Zero")); +CS_T s_szMUNU_SAMPLE = _DEFCS(_CSV(18647), + _CHINESE("Z轴标定") + _ENGLISH("Calibrate")); +CS_T s_szMUNU_FORWARD = _DEFCS(_CSV(18647), + _CHINESE("前进 ") + _ENGLISH("Forward ")); +CS_T s_szMUNU_BACK = _DEFCS(_CSV(18647), + _CHINESE(" 后退") + _ENGLISH(" Back")); +CS_T s_csENDACTION = _DEFCS(_CSV(18498), + _CHINESE("加工后行为:") + _ENGLISH("Post-task Actions:")); +CS_T s_csNOMOTION = _DEFCS(_CSV(18498), + _CHINESE(" 不动") + _ENGLISH(" No Motion")); +CS_T s_csBACKFIXPOS = _DEFCS(_CSV(18499), + _CHINESE(" 回固定点") + _ENGLISH(" Fixed Point")); +CS_T s_csBACKWORKORG = _DEFCS(_CSV(18500), + _CHINESE(" 回工件原点") + _ENGLISH(" Work Origin")); +CS_T s_csBACK1 = _DEFCS(_CSV(18500), + _CHINESE(" 回标记点1") + _ENGLISH(" Mark Point1")); +CS_T s_csBACK2 = _DEFCS(_CSV(18500), + _CHINESE(" 回标记点2") + _ENGLISH(" Mark Point2")); +CS_T s_csBACK3 = _DEFCS(_CSV(18500), + _CHINESE(" 回标记点3") + _ENGLISH(" Mark Point3")); +CS_T s_csBACK4 = _DEFCS(_CSV(18500), + _CHINESE(" 回标记点4") + _ENGLISH(" Mark Point4")); +CS_T s_csBACK5 = _DEFCS(_CSV(18500), + _CHINESE(" 回标记点5") + _ENGLISH(" Mark Point5")); +CS_T s_csBACK6 = _DEFCS(_CSV(18500), + _CHINESE(" 回标记点6") + _ENGLISH(" Mark Point6")); +CS_T s_csBACK7 = _DEFCS(_CSV(18500), + _CHINESE(" 回标记点7") + _ENGLISH(" Mark Point7")); +CS_T s_csBACK8 = _DEFCS(_CSV(18500), + _CHINESE(" 回标记点8") + _ENGLISH(" Mark Point8")); +CS_T s_csBLOWAIR = _DEFCS(_CSV(18500), + _CHINESE("气体类型:") + _ENGLISH("Blow Type:")); +CS_T s_csAIR = _DEFCS(_CSV(18500), + _CHINESE(" 空气") + _ENGLISH(" Air")); +CS_T s_csO2 = _DEFCS(_CSV(18500), + _CHINESE(" 氧气") + _ENGLISH(" Oxygen")); +CS_T s_csN2 = _DEFCS(_CSV(18500), + _CHINESE(" 氮气") + _ENGLISH(" Nitrogen")); + +using namespace mach; +using namespace ncmath; +//////////////////////////////////////////////////////////////////////////////// +// CtrlID +enum +{ + CTRLID_BTN_F = psh1, + CTRLID_BTN_CENTER, + CTRLID_BTN_XP, + CTRLID_BTN_XN, + CTRLID_BTN_YP, + CTRLID_BTN_YN, + CTRLID_BTN_ZP, + CTRLID_BTN_ZN, + CTRLID_BTN_WP, + CTRLID_BTN_WN, + CTRLID_BTN_GOFORWARD, + CTRLID_BTN_GOBACKWARD, + CTRLID_BTN_GODISTANCE, + CTRLID_BTN_CHANGECOOR, + + CTRLID_STC_AXES = stc1, + CTRLID_STC_COOR, + CTRLID_STC_PORT0, + CTRLID_STC_PORT1, + CTRLID_STC_PORT2, + CTRLID_STC_PORT3, + CTRLID_STC_PORT4, + CTRLID_STC_PORT5, + CTRLID_STC_PORT6, + CTRLID_STC_PORT7, + CTRLID_STC_PORT8, + CTRLID_STC_PORT9, + CTRLID_STC_PORT10, + CTRLID_STC_PORT11, + CTRLID_BTN_PORT0, + CTRLID_BTN_PORT1, + CTRLID_BTN_PORT2, + CTRLID_BTN_PORT3, + CTRLID_BTN_PORT4, + CTRLID_BTN_PORT5, + CTRLID_BTN_PORT6, + CTRLID_BTN_PORT7, + CTRLID_BTN_PORT8, + CTRLID_BTN_PORT9, + CTRLID_BTN_PORT10, + CTRLID_BTN_PORT11, + + // 标记点按钮和菜单 + CTRLID_BTN_SELMARKPOINT, + CTRLID_BTN_MARKPOINT1, + CTRLID_BTN_MARKPOINT2, + CTRLID_BTN_MARKPOINT3, + CTRLID_BTN_MARKPOINT4, + CTRLID_BTN_MARKPOINT5, + CTRLID_BTN_MARKPOINT6, + CTRLID_BTN_MARKPOINT7, + CTRLID_BTN_MARKPOINT8, + + // 气体选择按钮和菜单 + CTRLID_BTN_SELAIR, + CTRLID_BTN_SELAIR0, + CTRLID_BTN_SELN2, + CTRLID_BTN_SEL02, + + // 结束后动作按钮和菜单 + CTRLID_BTN_ENDACTION, + CTRLID_BTN_NOMOVE, + CTRLID_BTN_BACKFIXPOS, + CTRLID_BTN_BACKWORKORG, + CTRLID_BTN_BACKMAKPOINT1, + CTRLID_BTN_BACKMAKPOINT2, + CTRLID_BTN_BACKMAKPOINT3, + CTRLID_BTN_BACKMAKPOINT4, + CTRLID_BTN_BACKMAKPOINT5, + CTRLID_BTN_BACKMAKPOINT6, + CTRLID_BTN_BACKMAKPOINT7, + CTRLID_BTN_BACKMAKPOINT8, + + CTRLID_STC_XVALUE, + CTRLID_STC_YVALUE, + CTRLID_STC_ZVALUE, + CTRLID_STC_SELECTMACH, + CTRLID_STC_JOGLASER, + CTRLID_STC_AUTOCYC, + CTRLID_STC_WVALUE, + CTRLID_STC_BR, + CTRLID_STC_BRX, + CTRLID_STC_BRY, + CTRLID_STC_BRZ, + CTRLID_STC_BRW, + CTRLID_STC_TITLEZ, + CTRLID_STC_BACKGROUND, + CTRLID_STC_TITLEX, + CTRLID_STC_TITLEY, + CTRLID_STC_F, + CTRLID_STC_AUTOEXCHANGE, + CTRLID_STC_DIRRUN, + CTRLID_SIMULATE, + CTRLID_STC_SIMUCAT, + CTRLID_STC_MARK, + CTRLID_STC_BACKMARK, + CTRLID_STC_MARKNUM, + + CTRLID_STC_BACKORG, + CTRLID_STC_SETW, + CTRLID_STC_BW, + CTRLID_STC_SAMPLE, + CTRLID_STC_FORWARD, + CTRLID_STC_BACK, + CTRLID_STC_STCAIR, + CTRLID_STC_STCENDACTION, + + CTRLID_EDIT_GODISTANCE = edt1, + + CTRLID_SLD_SETF = ctl1, + CTRLID_SLD_F, + + CTRLID_CHX_SELECTMACH = chx1, + CTRLID_CHX_JOGLASER = chx2, + CTRLID_CHX_AUTOCYC = chx3, + CTRLID_CHX_AUTOCYCEXCHANGE, +}; +//////////////////////////////////////////////////////////////////////////////// +// Local function declarations ---- DingQiang 2012-06-25 +static double _FormatInputData(double nInputData_); + +//////////////////////////////////////////////////////////////////////////////// +// CMachineControlDlg +// +// 只需要按类名创建类对象,不需要序列化与版本控制。 ---- 杨开锦 2011-10-31 +IMPLEMENT_SERIAL(CMachineControlDlg, CAgileDialog, 0xFFFF) + +BEGIN_MESSAGE_MAP(CMachineControlDlg, CAgileDialog) + ON_WM_HSCROLL() + ON_WM_LBUTTONDOWN() + ON_MESSAGE(WM_MYDLGMESSAGE, OnEndSpeedDlg) + ON_CONTROL_RANGE(BN_PUSHED, CTRLID_BTN_XP, CTRLID_BTN_WN, OnDirectionBtnPushed) + ON_CONTROL_RANGE(BN_UNPUSHED, CTRLID_BTN_XP, CTRLID_BTN_WN, OnDirectionBtnUnpushed) + ON_CONTROL_RANGE(BN_PUSHED, CTRLID_BTN_GOFORWARD, CTRLID_BTN_GOBACKWARD, OnGFOBBtnPushed) + ON_CONTROL_RANGE(BN_UNPUSHED, CTRLID_BTN_GOFORWARD, CTRLID_BTN_GOBACKWARD, OnGFOBBtnUnpushed) + ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI) + ON_CONTROL(STN_DBLCLK, CTRLID_STC_COOR, OnChangeCoorMode) + ON_MESSAGE(WM_MYEIDTMESSAGE, OnEndEditDistance) + ON_COMMAND(CTRLID_BTN_CHANGECOOR, OnChangeCoorMode) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_CENTER, OnSetManuMode) + ON_CONTROL(BN_DOUBLECLICKED, CTRLID_BTN_CENTER, OnDblClickCenter) + ON_MESSAGE(WM_BITMAPSLIDER_MOVING, OnSliderMoving) + ON_COMMAND(CTRLID_CHX_SELECTMACH, OnSelectMach) + ON_COMMAND(CTRLID_CHX_JOGLASER, OnJogLaser) + ON_COMMAND(CTRLID_CHX_AUTOCYC, OnAutoCyc) + ON_COMMAND(CTRLID_CHX_AUTOCYCEXCHANGE, OnAutoExchange) + ON_COMMAND(CTRLID_BTN_SELMARKPOINT, OnSelMarkPoint) + ON_COMMAND(CTRLID_BTN_SELAIR, OnSelBlowAir) + ON_COMMAND(CTRLID_BTN_ENDACTION, OnSelEndAction) + ON_COMMAND_RANGE(CTRLID_BTN_MARKPOINT1, CTRLID_BTN_MARKPOINT8, OnMarkPointChange) + ON_COMMAND_RANGE(CTRLID_BTN_SELAIR0, CTRLID_BTN_SEL02, OnAirChange) + ON_COMMAND_RANGE(CTRLID_BTN_NOMOVE, CTRLID_BTN_BACKMAKPOINT8, OnEndActionChange) +END_MESSAGE_MAP() + +CMachineControlDlg::CMachineControlDlg(CWnd* pParentWnd_/* = NULL*/) +: CMachineControlDlg_Imp(pParentWnd_) +{ + m_pwndSliderF = NULL; + m_pwndSliderExF = NULL; + m_pwndBtnF = NULL; + m_pwndBtnXP = NULL; + m_pwndBtnXN = NULL; + m_pwndBtnYP = NULL; + m_pwndBtnYN = NULL; + m_pwndBtnZP = NULL; + m_pwndBtnZN = NULL; + m_pwndBtnWP = NULL; + m_pwndBtnWN = NULL; + m_pwndBtnCenter = NULL; + m_pwndStcValueX = NULL; + m_pwndStcValueY = NULL; + m_pwndStcValueZ = NULL; + m_pwndStcValueW= NULL; + m_pSetSpeedDlg = NULL; + m_pwndSliderSetF = NULL; + m_pwndSliderSetExF = NULL; + m_pDistanceEdit = NULL; + m_pwndRunBtn = NULL; + m_pwndDirRunBtn = NULL; + + m_pMenuMark = new CMenu; + m_pMenuMarkPoint = new CMenu; + m_pMenuAir = new CMenu; + + m_nCurIndex = 1; + + memset(m_pwndPortButtons, 0, sizeof(CPortButton*) * _countof(m_pwndPortButtons)); + + m_nCoorMode = 0x00; + + for (int _i = 0; _i < _countof(m_nFValues); _i++) + { + m_nFValues[_i] = _i; + } + + m_strShowAllBKMark = "0"; + m_strBKMarkAttachAxis = "0,1"; + + m_bSliderCtrlG00 = NceGetPrivateProfileString(_T("ControlTarget"), _T("SliderCtrlG00"), _T("0")) == _T("1"); + // 同步GXX和G00的倍率。 ---- 黄海燕 2016-04-19 + if (m_bSliderCtrlG00) + { + if (CParamManager* _pParamManager = GetParamManager()) + { + int _nFrp = 100; + ParameterValue _FrpParamValue; + if (_pParamManager->GetParameterValue("SpeedGxx_Frp", &_FrpParamValue) + && _FrpParamValue.nType == ParameterValue::VT_INT) + { + _nFrp = _FrpParamValue.iValue; + } + + if (_pParamManager->GetParameterValue("SpeedG00_Frp", &_FrpParamValue) + && _FrpParamValue.nType == ParameterValue::VT_INT) + { + _FrpParamValue.iValue = _nFrp; + bool _bRet = _pParamManager->SetParameterValue("SpeedG00_Frp", &_FrpParamValue); + ASSERT(_bRet); + } + } + } + m_bSelectMach = FALSE; + m_bShowSelectMach = FALSE; + m_bShowJogLaser = FALSE; + m_bShowAutoCyc = FALSE; + + // 是否启用方管配置 ---- DingQiang 2016-08-17 + CString _strEnable = NceGetPrivateProfileString(_T("Tube"), _T("Enable"), _T("")); + m_bIsTube = _strEnable == _T("True"); + + // 是否是R2界面 + CString _strUserStyle = NceGetPrivateProfileString(_T("Theme"), _T("UserStyle"), _T("None")); + m_bIsR2 = (_strUserStyle == _T("R2")); + + LOAD_PARAM(this, CMachineControlDlg); +} + +CMachineControlDlg::~CMachineControlDlg() +{ + if (m_pSetSpeedDlg) + { + delete m_pSetSpeedDlg; + m_pSetSpeedDlg = NULL; + } + + if (m_pMenuMark) + { + delete m_pMenuMark; + m_pMenuMark = NULL; + } + + if (m_pMenuMarkPoint) + { + delete m_pMenuMarkPoint; + m_pMenuMarkPoint = NULL; + } + + if (m_pMenuAir) + { + delete m_pMenuAir; + m_pMenuAir = NULL; + } + + SAVE_PARAM(this, CMachineControlDlg); +} + +BOOL CMachineControlDlg::Create(CWnd* pParentWnd_ /* = NULL */) +{ + // 更改窗口风格为子窗口,以便用于贴到NcEditor的右侧栏上。 ---- 杨开锦 2011-10-31 + static struct { DLGTEMPLATE dt; SHORT n1; SHORT n2; SHORT n3; } + _s_EmptyDialogTemplate = { WS_CHILD }; + return CreateIndirect(&_s_EmptyDialogTemplate.dt, pParentWnd_); +} + +void CMachineControlDlg::Update() +{ + UpdateBRFlag(); + UpdateMachCoor(); + UpdateF(); + UpdateManuCenter(); + UpdateGFOBInfo(); + UpdateEnableJogLaser(); + UpdateEnableAutoCyc(); + UpdateEnableAutoExchange(); + + if (m_bIsR2) + { + UpdateAir(); + UpdateEndAction(); + } + + for (int _i = 0; _i < _countof(m_pwndPortButtons); _i++) + { + if (m_pwndPortButtons[_i]) + { + // 定时器更新 ---- 杨开锦 2013-03-11 + m_pwndPortButtons[_i]->Update(); + } + } + m_pwndDirRunBtn->Update(); + m_pwndRunBtn->Update(); +} + +BOOL CMachineControlDlg::OnInitDialog() +{ + __super::OnInitDialog(); + + // 注册取得各控件指针。 ---- 杨开锦 2011-10-31 + RegisterID("stcBackground", CTRLID_STC_BACKGROUND); + RegisterID("stcTitleX", CTRLID_STC_TITLEX); + RegisterID("stcTitleY", CTRLID_STC_TITLEY); + Register("stcCoor", m_pwndStcCoor); + RegisterID("stcCoor", CTRLID_STC_COOR); + RegisterID("stcAxes", CTRLID_STC_AXES); + Register("stcBR", m_pwndStcBR); + RegisterID("stcBR", CTRLID_STC_BR); + Register("stcBRX", m_pwndStcBRX); + RegisterID("stcBRX", CTRLID_STC_BRX); + Register("stcBRY", m_pwndStcBRY); + RegisterID("stcBRY", CTRLID_STC_BRY); + Register("stcBRZ", m_pwndStcBRZ); + RegisterID("stcBRZ", CTRLID_STC_BRZ); + Register("stcBRW", m_pwndStcBRW); + RegisterID("stcBRW", CTRLID_STC_BRW); + Register("stcXValue", m_pwndStcValueX); + Register("stcYValue", m_pwndStcValueY); + Register("stcZValue", m_pwndStcValueZ); + Register("stcWValue", m_pwndStcValueW); + Register("stcTitleZ", m_pwndStcTitleZ); + RegisterID("stcTitleZ", CTRLID_STC_TITLEZ); + Register("stcTitleW", m_pwndStcTitleW); + if (m_bIsR2) + { + Register("sliderF", m_pwndSliderExF); + } + else + { + Register("sliderF", m_pwndSliderF); + } + RegisterID("sliderF", CTRLID_SLD_F); + Register("btnF", m_pwndBtnF); + if (m_bIsR2) + { + Register("sliderSetF", m_pwndSliderSetExF); + } + else + { + Register("sliderSetF", m_pwndSliderSetF); + } + RegisterID("sliderSetF", CTRLID_SLD_SETF); + RegisterID("btnF", CTRLID_BTN_F); + RegisterID("btnChangCoor", CTRLID_BTN_CHANGECOOR); + Register("btnChangCoor", m_pwndChangCoor); + RegisterID("stcXValue", CTRLID_STC_XVALUE); + RegisterID("stcYValue", CTRLID_STC_YVALUE); + RegisterID("stcZValue", CTRLID_STC_ZVALUE); + RegisterID("stcWValue", CTRLID_STC_WVALUE); + Register("stcF", m_pwndStcF); + RegisterID("stcF", CTRLID_STC_F); + Register("stcGoDistance", m_pwndStcGoDistance); + RegisterID("stcGoDistance", CTRLID_BTN_GODISTANCE); + Register("btnCenter", m_pwndBtnCenter); + RegisterID("btnCenter", CTRLID_BTN_CENTER); + Register("btnXP", m_pwndBtnXP); + Register("btnXN", m_pwndBtnXN); + Register("btnYP", m_pwndBtnYP); + Register("btnYN", m_pwndBtnYN); + Register("btnZP", m_pwndBtnZP); + Register("btnZN", m_pwndBtnZN); + Register("btnWP", m_pwndBtnWP); + Register("btnWN", m_pwndBtnWN); + RegisterID("btnXP", CTRLID_BTN_XP); + RegisterID("btnXN", CTRLID_BTN_XN); + RegisterID("btnYP", CTRLID_BTN_YP); + RegisterID("btnYN", CTRLID_BTN_YN); + RegisterID("btnZP", CTRLID_BTN_ZP); + RegisterID("btnZN", CTRLID_BTN_ZN); + RegisterID("btnWP", CTRLID_BTN_WP); + RegisterID("btnWN", CTRLID_BTN_WN); + RegisterID("btnGoForward", CTRLID_BTN_GOFORWARD); + RegisterID("btnGoBackward", CTRLID_BTN_GOBACKWARD); + RegisterID("stcPort0", CTRLID_STC_PORT0); + RegisterID("stcPort1", CTRLID_STC_PORT1); + RegisterID("stcPort2", CTRLID_STC_PORT2); + RegisterID("stcPort3", CTRLID_STC_PORT3); + RegisterID("stcPort4", CTRLID_STC_PORT4); + RegisterID("stcPort5", CTRLID_STC_PORT5); + RegisterID("stcPort6", CTRLID_STC_PORT6); + RegisterID("stcPort7", CTRLID_STC_PORT7); + RegisterID("stcPort8", CTRLID_STC_PORT8); + RegisterID("stcPort9", CTRLID_STC_PORT9); + RegisterID("stcPort10", CTRLID_STC_PORT10); + RegisterID("stcPort11", CTRLID_STC_PORT11); + RegisterID("btnPort0", CTRLID_BTN_PORT0); + RegisterID("btnPort1", CTRLID_BTN_PORT1); + RegisterID("btnPort2", CTRLID_BTN_PORT2); + RegisterID("btnPort3", CTRLID_BTN_PORT3); + RegisterID("btnPort4", CTRLID_BTN_PORT4); + RegisterID("btnPort5", CTRLID_BTN_PORT5); + RegisterID("btnPort6", CTRLID_BTN_PORT6); + RegisterID("btnPort7", CTRLID_BTN_PORT7); + RegisterID("btnPort8", CTRLID_BTN_PORT8); + RegisterID("btnPort9", CTRLID_BTN_PORT9); + RegisterID("btnPort10", CTRLID_BTN_PORT10); + RegisterID("btnPort11", CTRLID_BTN_PORT11); + Register("btnRun", m_pwndRunBtn); + Register("btnDirrun", m_pwndDirRunBtn); + + if (m_bIsR2) + { + RegisterID("stcForward", CTRLID_STC_FORWARD); + RegisterID("stcBack", CTRLID_STC_BACK); + + SetDlgItemText(CTRLID_BTN_GOFORWARD, _GETCS(s_szMUNU_FORWARD)); + SetDlgItemText(CTRLID_BTN_GOBACKWARD, _GETCS(s_szMUNU_BACK)); + } + + m_pwndRunBtn->SetMotionEndType(CCycMachiningTarget::TaskEndNormal); + m_pwndDirRunBtn->SetMotionEndType(CCycMachiningTarget::DryRunEndNormal); + + // PortButton ---- DingQiang 2013-07-23 + for (size_t _i = 0; _i < _countof(m_pwndPortButtons); _i++) + { + // 注册:xaml中如果没配则注册失败,相应指针为NULL ---- DingQiang 2013-07-24 + CString _strPortButtonName; + _strPortButtonName.Format(_T("btnPort%d"), _i); + Register(_strPortButtonName, m_pwndPortButtons[_i]); + + // 初始化控件 ---- DingQiang 2016-07-14 + CString _strPortIndex; + _strPortIndex.Format(_T("Port%d"), _i); + if (!m_pwndPortButtons[_i] || !m_pwndPortButtons[_i]->Initialize(_T("ControlTarget"), _strPortIndex)) + { + continue; + } + + // 设置相应的端口名 ---- 杨开锦 2012-07-05 + CString _strDescriptionNameKey; + _strDescriptionNameKey.Format(_GETCS(s_szPortNameKey), _i); + CString _strDescriptionName = NceGetPrivateProfileString(_T("ControlTarget"), _strDescriptionNameKey); + SetDlgItemText(CTRLID_STC_PORT0 + (int)_i, _strDescriptionName); + } + // 隐藏所有的回机械原点标志----梁艳-2015-02-08 + m_pwndStcBR->ShowWindow(SW_HIDE); + m_pwndStcBRX->ShowWindow(SW_HIDE); + m_pwndStcBRY->ShowWindow(SW_HIDE); + m_pwndStcBRZ->ShowWindow(SW_HIDE); + if (m_pwndStcBRW) + { + m_pwndStcBRW->ShowWindow(SW_HIDE); + } + + //读配置,是否显示所有轴回机械原点标志以及回机械原点关联轴的索引 + //如果可以读到,则使用读到的,否则使用默认的----梁艳-2015-02-08 + CString _strShowAllBKMark = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowAllBKMark")); + CString _strBKMarkAttachAxis = NceGetPrivateProfileString(_T("ControlTarget"), _T("BKMarkAttachAxis")); + if (!_strShowAllBKMark.IsEmpty()) + { + m_strShowAllBKMark = _strShowAllBKMark; + } + if (!_strBKMarkAttachAxis.IsEmpty()) + { + m_strBKMarkAttachAxis = _strBKMarkAttachAxis; + } + + //只显示一个回原点标志时,求出关联轴的索引---梁艳-2015-02-08 + if (m_strShowAllBKMark == "0") + { + CString _strBKMarkAttachAxis = m_strBKMarkAttachAxis; + //关联轴索引 空值或含有非法字符或只有一个非数字字符 + if (_strBKMarkAttachAxis.IsEmpty() + ||_strBKMarkAttachAxis.SpanIncluding(_T(",012")).GetLength() != _strBKMarkAttachAxis.GetLength() + || _strBKMarkAttachAxis.GetLength() == 1 && _strBKMarkAttachAxis.FindOneOf(_T("012")) == -1) + { + _strBKMarkAttachAxis.Empty(); + } + m_strVecAxis.clear(); + while(!_strBKMarkAttachAxis.IsEmpty()) + { + _strBKMarkAttachAxis.TrimLeft(","); + _strBKMarkAttachAxis.TrimRight(","); + int _Index = _strBKMarkAttachAxis.Find(","); + if(_Index == -1) + { + m_strVecAxis.push_back(_strBKMarkAttachAxis); + break; + } + m_strVecAxis.push_back( _strBKMarkAttachAxis.Left(_Index)); + _strBKMarkAttachAxis = _strBKMarkAttachAxis.Right(_strBKMarkAttachAxis.GetLength() - _Index); + } + } + +#define RegisterBtnID(szName_, nID_) { \ + CAgileImageButton* _pwndBtn = NULL; \ + Register(szName_, _pwndBtn); \ + ASSERT(_pwndBtn); \ + ASSERT(IsCmdID(nID_)); \ + _pwndBtn->SetCmdID(nID_); \ + } + RegisterBtnID("btnSetW", IDCMD_CONTROLTARGET_CLEARW); + RegisterBtnID("btnBW", IDCMD_CONTROLTARGET_BACKW); + if(!m_bIsR2) + { + RegisterBtnID("btnMachSel", IDCMD_CONTROLTARGET_MACHSELECTED); + } + + // 在方管下,暂停处按钮指向校平,走边框指向中 ---- 吴畏 2016-11-17 + if (!m_bIsTube) + { + RegisterBtnID("btnSimuCut", IDCMD_CONTROLTARGET_SIMUCUT); + RegisterBtnID("btnPause", IDCMD_CONTROLTARGET_PAUSE); + } + else + { + RegisterBtnID("btnSimuCut", IDCMD_TUBECTRLTARGET_FINDMIDFOURSIDE); + RegisterBtnID("btnPause", IDCMD_TUBECTRLTARGET_ADJUSTHORANDFINDMID); + } + + RegisterBtnID("btnRun", IDCMD_CONTROLTARGET_START); + RegisterBtnID("btnStop", IDCMD_CONTROLTARGET_STOP); + RegisterBtnID("btnBreakpointResume", IDCMD_CONTROLTARGET_BREAKPOINTRESUME); + RegisterBtnID("btnSimulate", IDCMD_CONTROLTARGET_SIMULATE); + RegisterBtnID("btnDirrun", IDCMD_CONTROLTARGET_DIRRUN); + CString _strCutBoundText; + if (NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowSampleBtn")) == _T("1")) + { + RegisterBtnID("btnSample", IDCMD_FOLLOWCTRLTARGET_SAMPLE); + // 走边框放到下一排,按钮上显示字。 ---- 黄海燕 2015-09-10 + _strCutBoundText = _GETCS(s_csSIMUCUTBOUNDRECT); + } + if (NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowBackOrgBtn")) == _T("1")) + RegisterBtnID("btnBackOrg", IDCMD_CONTROLTARGET_BACKR); + + if (m_bIsR2) + { + RegisterID("stcDirrun", CTRLID_STC_DIRRUN); + RegisterID("stcSimulate", CTRLID_SIMULATE); + RegisterID("stcSimuCut", CTRLID_STC_SIMUCAT); + RegisterID("stcMark", CTRLID_STC_MARK); + RegisterID("stcBackMark", CTRLID_STC_BACKMARK); + RegisterID("stcMarkNum", CTRLID_STC_MARKNUM); + RegisterID("stcBackOrg", CTRLID_STC_BACKORG); + RegisterID("stcSetW", CTRLID_STC_SETW); + RegisterID("stcBW", CTRLID_STC_BW); + RegisterID("stcSample", CTRLID_STC_SAMPLE); + RegisterID("stcAir", CTRLID_STC_STCAIR); + RegisterID("stcEndAction", CTRLID_STC_STCENDACTION); + + RegisterBtnID("btnMarkPoint", IDCMD_MARKPOINTTARGET_MARKTHISPOINT); + RegisterBtnID("btnBackMarkPoint", IDCMD_MARKPOINTTARGET_MOVETOMARKPOINT); + RegisterID("btnSelectMarkPoint", CTRLID_BTN_SELMARKPOINT); + RegisterID("btnAir", CTRLID_BTN_SELAIR); + RegisterID("btnEndAction", CTRLID_BTN_ENDACTION); + + SetDlgItemText(CTRLID_STC_DIRRUN, _GETCS(s_csDIRRUNTEXT)); + SetDlgItemText(CTRLID_SIMULATE, _GETCS(s_csSIMU)); + SetDlgItemText(CTRLID_STC_SIMUCAT, _GETCS(s_csSIMUCUTBOUNDRECT)); + SetDlgItemText(CTRLID_STC_MARK, _GETCS(s_szMUNU_MARK)); + SetDlgItemText(CTRLID_STC_BACKMARK, _GETCS(s_szMUNU_BACKMARK)); + SetDlgItemText(CTRLID_STC_MARKNUM, _GETCS(s_szMUNU_MARKNUM)); + SetDlgItemText(CTRLID_STC_BACKORG, _GETCS(s_szMUNU_BACKORG)); + SetDlgItemText(CTRLID_STC_SETW, _GETCS(s_szMUNU_SETW)); + SetDlgItemText(CTRLID_STC_BW, _GETCS(s_szMUNU_BW)); + SetDlgItemText(CTRLID_STC_SAMPLE, _GETCS(s_szMUNU_SAMPLE)); + SetDlgItemText(CTRLID_STC_STCAIR, _GETCS(s_csBLOWAIR)); + SetDlgItemText(CTRLID_STC_STCENDACTION, _GETCS(s_csENDACTION)); + } +#undef RegisterBtnID + + m_bShowSelectMach = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowSelectMach")) == _T("1"); + RegisterID("stcMachSelText", CTRLID_STC_SELECTMACH); + RegisterID("chkMachSel", CTRLID_CHX_SELECTMACH); + CWnd* _pwndSelectMach_Check = GetDlgItem(CTRLID_CHX_SELECTMACH); + CWnd* _pwndSelectMach_Static = GetDlgItem(CTRLID_STC_SELECTMACH); + if (_pwndSelectMach_Check && _pwndSelectMach_Static) + { + CStateManager* _pStateManager = GetStateManager(); + if (_pStateManager) + _pStateManager->SetSelectedMach(m_bSelectMach); + + CButton* _pwndBtn = (CButton*)_pwndSelectMach_Check; + _pwndBtn->SetCheck(m_bSelectMach ? BST_CHECKED : BST_UNCHECKED); + _pwndBtn->ShowWindow(m_bShowSelectMach ? SW_SHOWNORMAL : SW_HIDE); + + CWnd* _pWnd = GetDlgItem(IDCMD_CONTROLTARGET_DIRRUN); + //CFont* _pFont = _pWnd->GetFont(); + //_pwndSelectMach_Static->SetFont(_pFont); + _pwndSelectMach_Static->SetWindowText(_GETCS(s_csSELECTMACH)); + _pwndSelectMach_Static->ShowWindow(m_bShowSelectMach ? SW_SHOWNORMAL : SW_HIDE); + } + + m_bShowJogLaser = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowJogLaser")) == _T("1"); + RegisterID("btnJogWLaser", CTRLID_CHX_JOGLASER); + CButton* _pwndBtn2 = (CButton*)GetDlgItem(CTRLID_CHX_JOGLASER); + RegisterID("chkJogWithLaser", CTRLID_CHX_JOGLASER); + CButton* _pwndBtnChxJogLaser = (CButton*)GetDlgItem(CTRLID_CHX_JOGLASER); + if(_pwndBtn2 && _pwndBtnChxJogLaser) + { + _pwndBtn2->SetWindowText(_GETCS(s_szLaserOnWhenJog)); + _pwndBtn2->ShowWindow(m_bShowJogLaser ? SW_SHOWNORMAL : SW_HIDE); + _pwndBtnChxJogLaser->ShowWindow(m_bShowJogLaser ? SW_SHOWNORMAL : SW_HIDE); + } + + if (m_bIsR2) + { + RegisterID("stcJogWithLaser", CTRLID_STC_JOGLASER); + CWnd* _pwndStatic2 = GetDlgItem(CTRLID_STC_JOGLASER); + if(_pwndStatic2) + { + _pwndStatic2->SetWindowText(_GETCS(s_szLaserOnWhenJog)); + _pwndStatic2->ShowWindow(m_bShowJogLaser ? SW_SHOWNORMAL : SW_HIDE); + } + } + + // 自动循环 + m_bShowAutoCyc = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowAutoCyc")) == _T("1"); + RegisterID("chkAutoCyc", CTRLID_CHX_AUTOCYC); + RegisterID("stcAutoCyc", CTRLID_STC_AUTOCYC); + CButton* _pwndBtn3 = (CButton*)GetDlgItem(CTRLID_CHX_AUTOCYC); + CWnd* _pwndStatic3 = GetDlgItem(CTRLID_STC_AUTOCYC); + if(_pwndBtn3 && _pwndStatic3) + { + _pwndStatic3->SetWindowText(_GETCS(s_szAutoCyc)); + _pwndBtn3->ShowWindow(m_bShowAutoCyc ? SW_SHOWNORMAL : SW_HIDE); + _pwndStatic3->ShowWindow(m_bShowAutoCyc ? SW_SHOWNORMAL : SW_HIDE); + } + + // 加工完自动交换工作台 + BOOL _bShowAutoExchange = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowAutoExchange")) == _T("1"); + if (_bShowAutoExchange) + { + RegisterID("chkExchange", CTRLID_CHX_AUTOCYCEXCHANGE); + RegisterID("stcExchange", CTRLID_STC_AUTOEXCHANGE); + } + CButton* _pwndBtn4 = (CButton*)GetDlgItem(CTRLID_CHX_AUTOCYCEXCHANGE); + CWnd* _pwndStatic4 = GetDlgItem(CTRLID_STC_AUTOEXCHANGE); + if(_pwndBtn4 && _pwndStatic4) + { + _pwndStatic4->SetWindowText(_GETCS(s_szAutoExchange)); + _pwndBtn4->ShowWindow(_bShowAutoExchange ? SW_SHOWNORMAL : SW_HIDE); + _pwndStatic4->ShowWindow(_bShowAutoExchange ? SW_SHOWNORMAL : SW_HIDE); + } + + SetDlgItemText(CTRLID_STC_AXES, _GETCS(s_csAXES)); + SetDlgItemText(CTRLID_STC_COOR, m_nCoorMode == 0x00 ? _GETCS(s_csWORKPIECECOORDINATE) : _GETCS(s_csMACHINECOORDINATE)); + SetDlgItemText(IDCMD_CONTROLTARGET_BREAKPOINTRESUME, _T("")); + + SetDlgItemText(IDCMD_CONTROLTARGET_SIMULATE, m_bIsR2 ? _T("") : _GETCS(s_csSIMU)); + SetDlgItemText(IDCMD_CONTROLTARGET_DIRRUN, m_bIsR2 ? _T("") : _GETCS(s_csDIRRUN)); + SetDlgItemText(IDCMD_CONTROLTARGET_SIMUCUT, m_bIsR2 ? _T("") : _strCutBoundText); + SetDlgItemText(IDCMD_TUBECTRLTARGET_FINDMIDFOURSIDE, _GETCS(s_szCentering)); + SetDlgItemText(IDCMD_TUBECTRLTARGET_ADJUSTHORANDFINDMID, _GETCS(s_szLevel)); + if (!m_bIsR2) + { + SetDlgItemText(IDCMD_CONTROLTARGET_MACHSELECTED, _GETCS(s_csSELECTMACH)); + } + + // 设置功率滑动条范围---- DingQiang 2012-04-28 + if (m_bIsR2) + { + m_pwndSliderSetExF->SetCustomerSetSize(); + m_pwndSliderSetExF->SetBitmapChannel( IDB_BMP_CHANNELBACK_R2, IDB_BMP_CHANNELFORE_R2); + m_pwndSliderSetExF->SetBitmapThumb( IDB_BMP_THUMBNORMAL_R2, IDB_BMP_THUMBPRESS_R2, IDB_BMP_THUMBHOVER_R2); + m_pwndSliderSetExF->SetRange( 0, 120); + m_pwndSliderSetExF->SetPos( 0 ); + } + else + { + m_pwndSliderSetF->SetRange(0, 120); + m_pwndSliderSetF->SetLineSize(5); + m_pwndSliderSetF->SetPageSize(20); + } + + // 倍率显示弧形条 ---- 杨开锦 2011-11-01 + if (m_bIsR2) + { + m_pwndSliderExF->SetRange(0, 120); + m_pwndSliderExF->Init(5, 128, 286, IDB_BMP_ARCSLIDERBK_FEED_R2, RGB(63, 63, 63)); + } + else + { + m_pwndSliderF->SetRange(0, 120); + } + + // 进给倍率是圆形按钮,半径为17px。 ---- 杨开锦 2012-02-21 + ASSERT(m_pwndBtnF); + if (m_bIsR2) + { + m_pwndBtnF->SetShape(::CreateEllipticRgn(0, 0, 31, 31)); + } + else + { + m_pwndBtnF->SetShape(::CreateEllipticRgn(0, 0, 34, 34)); + } + + // 手动中心键为圆形按钮,手动方向键为圆环切割而成,其中X-为左月牙、X+为右月 + // 牙、Y-为下月牙、Y+为上月牙。 + // 中心键半径为34px;方向键所在圆环外径为80px,内径为40px,各键间间隔缝为 + // 宽8px。 + // 此处各区域值为略扩大一点的区域,以便确保能完全包含所画贴图而不产生边界 + // 切割据齿。 ---- 杨开锦 2011-11-02 + ASSERT(m_pwndBtnCenter && m_pwndBtnXP && m_pwndBtnXN && m_pwndBtnYP && m_pwndBtnYN); + + if (m_bIsR2) + { + m_pwndBtnCenter->SetShape(::CreateEllipticRgn(-1, -1, 72, 72)); + + CDC _dc; + CDC* _pDC = GetDC(); + _dc.CreateCompatibleDC(_pDC); + ReleaseDC(_pDC); + _pDC = NULL; + + _dc.BeginPath(); + _dc.MoveTo(135, 21); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 155, 155, 135, 21, 135, 131); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(43, 43, 111, 111, 107, 101, 106, 50); + _dc.LineTo(135, 21); + _dc.EndPath(); + CRgn _rgn; + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-105, -13); + m_pwndBtnXP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(50, 100); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(43, 43, 111, 111, 50, 100, 50, 51); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(-2, -2, 154, 154, 19, 21, 19, 131); + _dc.LineTo(50, 100); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(7, -13); + m_pwndBtnXN->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(24, 20); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 161, 161, 24, 20, 130, 20); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(41, 41, 119, 119, 102, 48, 52, 48); + _dc.LineTo(24, 20); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-24, 7); + m_pwndBtnYP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(135, 139); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 161, 161, 135, 139, 25, 139); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(41, 41, 119, 119, 25, 139, 135, 139); + _dc.LineTo(135, 139); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-26, -111); + m_pwndBtnYN->SetShape((HRGN)_rgn.Detach()); + } + else + { + m_pwndBtnCenter->SetShape(::CreateEllipticRgn(-1, -1, 70, 70)); + + CDC _dc; + CDC* _pDC = GetDC(); + _dc.CreateCompatibleDC(_pDC); + ReleaseDC(_pDC); + _pDC = NULL; + + _dc.BeginPath(); + _dc.MoveTo(139, 25); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 161, 161, 139, 25, 139, 135); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(41, 41, 119, 119, 139, 135, 139, 25); + _dc.LineTo(139, 25); + _dc.EndPath(); + CRgn _rgn; + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-111, -26); + m_pwndBtnXP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(21, 135); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(41, 41, 119, 119, 21, 135, 21, 25); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(-1, -1, 161, 161, 21, 25, 21, 135); + _dc.LineTo(21, 135); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(0, -26); + m_pwndBtnXN->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(25, 21); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 161, 161, 25, 21, 135, 21); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(41, 41, 119, 119, 135, 21, 25, 21); + _dc.LineTo(25, 21); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-26, 0); + m_pwndBtnYP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(135, 139); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 161, 161, 135, 139, 25, 139); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(41, 41, 119, 119, 25, 139, 135, 139); + _dc.LineTo(135, 139); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-26, -111); + m_pwndBtnYN->SetShape((HRGN)_rgn.Detach()); + } + + + m_pSetSpeedDlg = new CSetSpeedDlg(this); + ((CSetSpeedDlg*)m_pSetSpeedDlg)->Create(this); + + m_pwndStcCoor->ModifyStyle(0, SS_NOTIFY); + m_pwndStcValueX->ModifyStyle(0, SS_NOTIFY); + m_pwndStcValueY->ModifyStyle(0, SS_NOTIFY); + m_pwndStcValueZ->ModifyStyle(0, SS_NOTIFY); + //m_pwndStcValueW->ModifyStyle(0, SS_NOTIFY); + + // 这里加一次Update是因为:出现过一个问题,软件启动时横向的进给倍率条显示不 + // 出来,最小化最大化一下才出来。带NcStudio启动才有问题,单NcEditor没问题。 + // 没有查出原因,只是经试验发现这里Update一次就好了,于是就这么干。如果以后 + // 发现这样不是正解请修改。 ---- 杨开锦 2012-05-02 + Update(); + + bool _bEnableZ = IsEnableZUpDown(); + m_pwndBtnZP->EnableWindow(_bEnableZ ? TRUE : FALSE); + m_pwndBtnZN->EnableWindow(_bEnableZ ? TRUE : FALSE); + m_pwndBtnZP->ShowWindow(_bEnableZ ? TRUE : FALSE); + m_pwndBtnZN->ShowWindow(_bEnableZ ? TRUE : FALSE); + m_pwndStcTitleZ->EnableWindow(_bEnableZ ? TRUE : FALSE); + m_pwndStcValueZ->EnableWindow(_bEnableZ ? TRUE : FALSE); + m_pwndStcTitleZ->ShowWindow(_bEnableZ ? TRUE : FALSE); + m_pwndStcValueZ->ShowWindow(_bEnableZ ? TRUE : FALSE); + + // 需要再W轴也在配置文件中选中隐藏或者不隐藏 + bool _bEnableW = IsEnableWUpDown(); + if (_bEnableW) + { + m_pwndBtnWP->EnableWindow(_bEnableW ? TRUE : FALSE); + m_pwndBtnWN->EnableWindow(_bEnableW ? TRUE : FALSE); + m_pwndBtnWP->ShowWindow(_bEnableW ? TRUE : FALSE); + m_pwndBtnWN->ShowWindow(_bEnableW ? TRUE : FALSE); + m_pwndStcTitleW->EnableWindow(_bEnableW ? TRUE : FALSE); + m_pwndStcValueW->EnableWindow(_bEnableW ? TRUE : FALSE); + m_pwndStcTitleW->ShowWindow(_bEnableW ? TRUE : FALSE); + m_pwndStcValueW->ShowWindow(_bEnableW ? TRUE : FALSE); + } + + // 将标记点选择按钮初始化 ---- 边俊霞 2017-03-15 + CString _strCurIndex; + _strCurIndex.Format("%u", m_nCurIndex); + + // 标记点选项菜单 + m_pMenuMark->CreatePopupMenu(); + m_pMenuMark->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT1, _GETCS(s_szMUNU_MARKPOINT1)); + m_pMenuMark->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT2, _GETCS(s_szMUNU_MARKPOINT2)); + m_pMenuMark->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT3, _GETCS(s_szMUNU_MARKPOINT3)); + m_pMenuMark->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT4, _GETCS(s_szMUNU_MARKPOINT4)); + m_pMenuMark->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT5, _GETCS(s_szMUNU_MARKPOINT5)); + m_pMenuMark->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT6, _GETCS(s_szMUNU_MARKPOINT6)); + m_pMenuMark->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT7, _GETCS(s_szMUNU_MARKPOINT7)); + m_pMenuMark->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT8, _GETCS(s_szMUNU_MARKPOINT8)); + + // 加工结束点选项菜单 + m_pMenuMarkPoint->CreatePopupMenu(); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_NOMOVE, _GETCS(s_csNOMOTION)); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_BACKFIXPOS, _GETCS(s_csBACKFIXPOS)); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_BACKWORKORG, _GETCS(s_csBACKWORKORG)); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_BACKMAKPOINT1, _GETCS(s_csBACK1)); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_BACKMAKPOINT2, _GETCS(s_csBACK2)); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_BACKMAKPOINT3, _GETCS(s_csBACK3)); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_BACKMAKPOINT4, _GETCS(s_csBACK4)); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_BACKMAKPOINT5, _GETCS(s_csBACK5)); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_BACKMAKPOINT6, _GETCS(s_csBACK6)); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_BACKMAKPOINT7, _GETCS(s_csBACK7)); + m_pMenuMarkPoint->AppendMenu(MF_STRING, CTRLID_BTN_BACKMAKPOINT8, _GETCS(s_csBACK8)); + + // 气体选择菜单 + m_pMenuAir->CreatePopupMenu(); + m_pMenuAir->AppendMenu(MF_STRING, CTRLID_BTN_SELAIR0, _GETCS(s_csAIR)); + m_pMenuAir->AppendMenu(MF_STRING, CTRLID_BTN_SELN2, _GETCS(s_csN2)); + m_pMenuAir->AppendMenu(MF_STRING, CTRLID_BTN_SEL02, _GETCS(s_csO2)); + + // 界面显示需求,使数字在button上不居中显示 ---- 边俊霞 2017-03-15 + CString _strShowIndex = _strCurIndex + '\n'; + SetDlgItemText(CTRLID_BTN_SELMARKPOINT, _strShowIndex); + + // 更新气体类型 + UpdateAir(); + + // 更新加工后行为 + UpdateEndAction(); + + SetMachineCtrlTips(); + return TRUE; +} + +void CMachineControlDlg::SetMachineCtrlTips() +{ + m_MachineCtrlTips.Create(this); + m_MachineCtrlTips.Activate(TRUE); + m_MachineCtrlTips.SetTipTextColor(RGB(0, 0, 0)); + m_MachineCtrlTips.SetDelayTime(1000); + + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_CLEARW), _GETCS(s_csTipSETWORKORG)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_BACKW), _GETCS(s_csTipMOVETOWORKORIGIN)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_START), _GETCS(s_csTipSTART)); + if (!m_bIsTube) + { + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_PAUSE), _GETCS(s_csTipPAUSE)); + } + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_STOP), _GETCS(s_csTipSTOP)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_BREAKPOINTRESUME), _GETCS(s_csTipRESUME)); + m_MachineCtrlTips.AddTool(GetDlgItem(CTRLID_BTN_GOBACKWARD), _GETCS(s_csTipGoBackward)); + m_MachineCtrlTips.AddTool(GetDlgItem(CTRLID_BTN_GOFORWARD), _GETCS(s_csTipGoForward)); + CWnd* _pwndBtn = GetDlgItem(IDCMD_FOLLOWCTRLTARGET_SAMPLE); + if (_pwndBtn) + m_MachineCtrlTips.AddTool(_pwndBtn, _GETCS(s_csTipFollowSample)); + _pwndBtn = GetDlgItem(IDCMD_CONTROLTARGET_BACKR); + if (_pwndBtn) + m_MachineCtrlTips.AddTool(_pwndBtn, _GETCS(s_csTipBackAll)); +} + +bool CMachineControlDlg::IsEnableZUpDown() +{ + CString _strEnableZ = NceGetPrivateProfileString(_T("ControlTarget"), _T("EnableZ")); + + if ("1" == _strEnableZ) + { + return true; + } + else + { + return false; + } +} + +bool CMachineControlDlg::IsEnableWUpDown() +{ + CString _strEnableW = NceGetPrivateProfileString(_T("ControlTarget"), _T("EnableW")); + + if ("1" == _strEnableW) + { + return true; + } + else + { + return false; + } +} + +BOOL CMachineControlDlg::PreTranslateMessage(MSG* pMsg_) +{ + // 添加此句用于机床控制栏显示提示语 ---- 嘎松卓玛 2012.05.17 + m_MachineCtrlTips.RelayEvent(pMsg_); + + // Let go of Keyboard Message => 此处这么做有几个目的:一个是屏蔽Enter、Esc + // 键引发的OnOK、OnCancel关闭窗口;二是防止焦点在窗口上时,框架上的快捷键被 + // 屏蔽。 ---- 杨开锦 2012-04-08 + if (WM_KEYFIRST <= pMsg_->message && pMsg_->message <= WM_KEYLAST) + { + return FALSE; + } + + if (pMsg_->message == WM_LBUTTONDOWN) + { + UINT _nCtrlID = ::GetDlgCtrlID(pMsg_->hwnd); + if (_nCtrlID == CTRLID_BTN_GODISTANCE) + { + if (OnDistanceLButtonDown(pMsg_->pt)) + { + // 如果不return的话Dialog会响应此消息,此时new出来的编辑框会又马上 + // 响应OnKillFocus导致编辑框一出来就消失 ---- DingQiang 2012-07-19 + return TRUE; + } + } + } + + if (pMsg_->message == WM_MOUSEMOVE) + { + UINT _nCtrlID = ::GetDlgCtrlID(pMsg_->hwnd); + if (_nCtrlID == CTRLID_STC_XVALUE || _nCtrlID == CTRLID_STC_YVALUE + || _nCtrlID == CTRLID_STC_ZVALUE || _nCtrlID == CTRLID_STC_COOR) + { + m_pwndChangCoor->SetMouseOn(); + } + else + m_pwndChangCoor->SetMouseLeave(); + } + + return __super::PreTranslateMessage(pMsg_); +} + +// 设置手动模式 ---- 郭小航 2013-11-07 +void CMachineControlDlg::OnSetManuMode() +{ + DWORD _nBegin = GetTickCount(); + while(true) + { + MSG _msg; + if (::PeekMessage(&_msg, NULL, NULL, NULL, PM_REMOVE)) + { + ::TranslateMessage(&_msg); + ::DispatchMessage(&_msg); + + if (_msg.message == WM_LBUTTONDBLCLK) + { + return; + } + } + + if (GetTickCount() - _nBegin > 200) + { + break; + } + } + + static int _s_nManuMode; + int _nManuMode = _s_nManuMode % 3; + + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + if (_nManuMode == 0) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(false); + } + else if (_nManuMode == 1) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(true); + } + else if (_nManuMode == 2) + { + _pManualTarget->SetManuMode(1); + } + + _s_nManuMode ++; +} + +void CMachineControlDlg::UpdateMachCoor() +{ + // 先更新标题 ---- 杨开锦 2012-07-05 + CString _strNewTitle = m_nCoorMode == 0x00 ? _GETCS(s_csWORKPIECECOORDINATE) : _GETCS(s_csMACHINECOORDINATE); + CString _strTitle; + m_pwndStcCoor->GetWindowText(_strTitle); + if (_strNewTitle != _strTitle) + { + m_pwndStcCoor->SetWindowText(_strNewTitle); + } + + CParamManager* _pParamManager = GetParamManager(); + if (!_pParamManager) + { + return; + } + + // 将控件与相应控件的参数标识符关联创建一个结构体---- DingQiang 2012-01-12 + const struct MachItem + { + DWORD nCoorMode; + CAgileLabel* pwndStcValue; + CString strIdentifier; + } _s_MachItems[] = + { + { 0x00, m_pwndStcValueX, "State_Axis0_WorkcoorPos" }, + { 0x00, m_pwndStcValueY, "State_Axis1_WorkcoorPos" }, + { 0x00, m_pwndStcValueZ, "State_Axis2_WorkcoorPos" }, + { 0x00, m_pwndStcValueW, "State_Axis3_WorkcoorPos" }, + { 0x01, m_pwndStcValueX, "Dyn_Axis0_Pos"}, + { 0x01, m_pwndStcValueY, "Dyn_Axis1_Pos"}, + { 0x01, m_pwndStcValueZ, "Dyn_Axis2_Pos"}, + { 0x01, m_pwndStcValueW, "Dyn_Axis3_Pos"}, + }; + + for(int _i = 0; _i < _countof(_s_MachItems); _i++) + { + const MachItem& _item = _s_MachItems[_i]; + if (_item.nCoorMode != m_nCoorMode + || !_item.pwndStcValue + || !_item.pwndStcValue->IsWindowVisible()) + { + continue; + } + + ParameterValue _PV; + if (!_pParamManager->GetParameterValue(_item.strIdentifier, &_PV) || _PV.nType != ParameterValue::VT_DOUBLE) + { + ASSERT(FALSE); + continue; + } + + CString _strMachCoor; + _strMachCoor.Format("%.3f", _PV.dValue); + if (_strMachCoor == "-0.000") + { + _strMachCoor = "0.000"; + } + + // 若更新前坐标与更新后坐标相等则不更新 ---- DingQiang 2012-01-12 + CString _strBeforeUpdate; + _item.pwndStcValue->GetWindowText(_strBeforeUpdate); + if (_strMachCoor != _strBeforeUpdate) + { + _s_MachItems[_i].pwndStcValue->SetWindowText(_strMachCoor); + } + } +} +// 回机械原点标志,配置方式如下: +// [ControlTarget] +// ShowAllBKMark=1 +// BKMarkAttachAxis=0,1,2 +void CMachineControlDlg::UpdateBRFlag() +{ + // 将轴原点标志控件与相应控件的参数以及轴的索引,关联创建一个结构体,方便以后扩展----梁艳-2015-02-08 + const struct AxisItems + { + CAgileImageLabel* pwndStcBR; + CString strIdentifier; + CString strIndex; + } _s_AxisItems[] = + { + { m_pwndStcBRX, "State_Axis0_IsReferenced", "0" }, + { m_pwndStcBRY, "State_Axis1_IsReferenced", "1" }, + { m_pwndStcBRZ, "State_Axis2_IsReferenced", "2" }, + { m_pwndStcBRW, "State_Axis3_IsReferenced", "3" }, + }; + + CParamManager* _pParamManager = GetParamManager(); + if(!_pParamManager) + return; + + //如果显示所有轴的回机械原点标志,则分别显示各轴的回机械原点标志---梁艳-2015-02-08 + if (m_strShowAllBKMark == _T("1")) + { + for(int _i = 0; _i < _countof(_s_AxisItems); _i++) + { + const AxisItems& _item = _s_AxisItems[_i]; + ParameterValue _PV; + memset(&_PV, 0, sizeof(ParameterValue)); + if (!_pParamManager->GetParameterValue(_item.strIdentifier, &_PV) || _PV.nType != ParameterValue::VT_BOOL) + { + continue; + } + _item.pwndStcBR->ShowWindow(_PV.bValue ? SW_SHOW : SW_HIDE); + } + } + // 如果不显示所有轴的回机械原点标志,则根据关联轴的索引,只显示一个回机械原点标志---梁艳-2015-02-08 + else if(m_strShowAllBKMark == _T("0")) + { + bool _bIsRef = m_strVecAxis.empty()? false : true; + for (std::vector::iterator _it = m_strVecAxis.begin(); _it != m_strVecAxis.end();_it++) + { + int _nCount = 0; + CString _strAxis = *_it; + for(int _j = 0; _j < _countof(_s_AxisItems); _j++) + { + const AxisItems& _item = _s_AxisItems[_j]; + ParameterValue _PV; + memset(&_PV, 0, sizeof(ParameterValue)); + if (!_pParamManager->GetParameterValue(_item.strIdentifier, &_PV) || _PV.nType != ParameterValue::VT_BOOL) + { + ASSERT(FALSE); + continue; + } + if (_item.strIndex == _strAxis) + { + _bIsRef &= _PV.bValue; + break; + } + else + { + _nCount++; + continue; + } + } + //没有匹配项 + if (_nCount == _countof(_s_AxisItems)) + { + _bIsRef = false; + } + } + m_pwndStcBR->ShowWindow(_bIsRef ? SW_SHOW : SW_HIDE); + } +} + + +void CMachineControlDlg::OnDirectionBtnPushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_XP && nID_ <= CTRLID_BTN_WN); + + // 将手动按钮模拟成快捷键导到CManualTarget中 + C_ASSERT(CTRLID_BTN_XP == CTRLID_BTN_XP + 0 + && CTRLID_BTN_XN == CTRLID_BTN_XP + 1 + && CTRLID_BTN_YP == CTRLID_BTN_XP + 2 + && CTRLID_BTN_YN == CTRLID_BTN_XP + 3 + && CTRLID_BTN_ZP == CTRLID_BTN_XP + 4 + && CTRLID_BTN_ZN == CTRLID_BTN_XP + 5 + && CTRLID_BTN_WP == CTRLID_BTN_XP + 6 + && CTRLID_BTN_WN == CTRLID_BTN_XP + 7); + static const UINT _s_nKeys[] = + { + VK_NUMPAD6, + VK_NUMPAD4, + VK_NUMPAD8, + VK_NUMPAD2, + VK_NUMPAD9, + VK_NUMPAD3, + VK_NUMPAD7, + VK_NUMPAD1, + }; + + // 没有W轴,屏蔽W轴快捷键 ---- 吴畏 2016-12-30 + bool _bEnableW = IsEnableWUpDown(); + if (!_bEnableW && (nID_ == CTRLID_BTN_WP || nID_ == CTRLID_BTN_WN)) + { + return; + } + + MSG _msg = { NULL, WM_KEYDOWN, WPARAM(_s_nKeys[nID_ - CTRLID_BTN_XP]), LPARAM(1) }; + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + _pManualTarget->OnKeyMessage(&_msg); +} + +void CMachineControlDlg::OnDirectionBtnUnpushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_XP && nID_ <= CTRLID_BTN_WN); + + // 将手动按钮模拟成快捷键导到CManualTarget中 + C_ASSERT(CTRLID_BTN_XP == CTRLID_BTN_XP + 0 + && CTRLID_BTN_XN == CTRLID_BTN_XP + 1 + && CTRLID_BTN_YP == CTRLID_BTN_XP + 2 + && CTRLID_BTN_YN == CTRLID_BTN_XP + 3 + && CTRLID_BTN_ZP == CTRLID_BTN_XP + 4 + && CTRLID_BTN_ZN == CTRLID_BTN_XP + 5 + && CTRLID_BTN_WP == CTRLID_BTN_XP + 6 + && CTRLID_BTN_WN == CTRLID_BTN_XP + 7); + static const UINT _s_nKeys[] = + { + VK_NUMPAD6, + VK_NUMPAD4, + VK_NUMPAD8, + VK_NUMPAD2, + VK_NUMPAD9, + VK_NUMPAD3, + VK_NUMPAD7, + VK_NUMPAD1, + }; + + // 没有W轴,屏蔽W轴快捷键 ---- 吴畏 2016-12-30 + bool _bEnableW = IsEnableWUpDown(); + if (!_bEnableW && nID_ >= CTRLID_BTN_WP) + { + return; + } + + MSG _msg = { NULL, WM_KEYUP, WPARAM(_s_nKeys[nID_ - CTRLID_BTN_XP]), LPARAM(1) }; + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + _pManualTarget->OnKeyMessage(&_msg); +} + +void CMachineControlDlg::OnGFOBBtnPushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_GOFORWARD && nID_ <= CTRLID_BTN_GOBACKWARD); + + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + if (_pControlTarget->GetGFOBMode() != 0x00) + { + return; + } + + C_ASSERT(CTRLID_BTN_GOFORWARD == CTRLID_BTN_GOFORWARD + 0 + && CTRLID_BTN_GOBACKWARD == CTRLID_BTN_GOFORWARD + 1); + static const UINT _s_nCmdIDs[] = + { + IDCMD_CONTROLTARGET_JOGFORWARD, + IDCMD_CONTROLTARGET_JOGBACKWARD, + }; + AfxGetMainWnd()->SendMessage(WM_COMMAND, _s_nCmdIDs[nID_ - CTRLID_BTN_GOFORWARD], 0); +} + +void CMachineControlDlg::OnGFOBBtnUnpushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_GOFORWARD && nID_ <= CTRLID_BTN_GOBACKWARD); + + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + if (_pControlTarget->GetGFOBMode() == 0x00) + { + AfxGetMainWnd()->SendMessage(WM_COMMAND, IDCMD_CONTROLTARGET_STOP, 0); + return; + } + + C_ASSERT(CTRLID_BTN_GOFORWARD == CTRLID_BTN_GOFORWARD + 0 + && CTRLID_BTN_GOBACKWARD == CTRLID_BTN_GOFORWARD + 1); + static const UINT _s_nCmdIDs[] = + { + IDCMD_CONTROLTARGET_INCFORWARD, + IDCMD_CONTROLTARGET_INCBACKWARD, + }; + AfxGetMainWnd()->SendMessage(WM_COMMAND, _s_nCmdIDs[nID_ - CTRLID_BTN_GOFORWARD], 0); +} + +LRESULT CMachineControlDlg::OnIdleUpdateCmdUI(WPARAM wParam_, LPARAM lParam_) +{ + static const struct ManualBtnItem + { + CButton* pBtnManual; + DWORD nMask; + } _s_cManualBtnItems[] = + { + {m_pwndBtnYN, 0x00000001}, + {m_pwndBtnXN, 0x00000002}, + {m_pwndBtnXP, 0x00000004}, + {m_pwndBtnYP, 0x00000008}, + {m_pwndBtnZP, 0x00000010}, + {m_pwndBtnZN, 0x00000020}, + {m_pwndBtnCenter, 0x00000040}, + {m_pwndBtnWP, 0x00000080}, + {m_pwndBtnWN, 0x00000100}, + }; + + CManualTarget* _pManualTarget = GetManualTarget(); + if (!_pManualTarget) + { + return 0; + } + DWORD _ManualKeyState = _pManualTarget->GetManuKeyState(); + + // 如果不是方管,只能加载前面的,不能加载最后的2个W轴的按钮 ---- 吴畏 2016-12-27 + int _nBtnItems = m_bIsTube ? _countof(_s_cManualBtnItems) : _countof(_s_cManualBtnItems) - 2; + for (int _i = 0; _i < _nBtnItems; _i++) + { + if (_ManualKeyState & _s_cManualBtnItems[_i].nMask) + { + _s_cManualBtnItems[_i].pBtnManual->SetCheck(TRUE); + } + else + _s_cManualBtnItems[_i].pBtnManual->SetCheck(FALSE); + } + + + // 真实前进后退状态和按钮F3、F4按下,只要一个状态为真即将按钮置亮 ---- DingQiang 2014-10-11 + static const struct GOBBtnItem + { + UINT nID; + DWORD nKeyboardMask; + DWORD nRunningStateMask; + } _s_cGOBBtnItems[] = + { + {CTRLID_BTN_GOBACKWARD, 0x00000001, 0x00000100}, + {CTRLID_BTN_GOFORWARD, 0x00000002, 0x00000080}, + }; + + CControlTarget* _pControlTarget = GetControlTarget(); + CStateManager* _pStateManager = GetStateManager(); + if (!_pControlTarget || !_pStateManager) + { + return 0; + } + + DWORD _GOBKeyState = _pControlTarget->GetGOBKeyState(); + DWORD _nRunningState = 0; + _pStateManager->GetRunningState(&_nRunningState); + + for (int _i = 0; _i < _countof(_s_cGOBBtnItems); _i++) + { + BOOL _bCheck = _nRunningState & _s_cGOBBtnItems[_i].nRunningStateMask; + _bCheck |= _GOBKeyState & _s_cGOBBtnItems[_i].nKeyboardMask; + + ((CButton*)GetDlgItem(_s_cGOBBtnItems[_i].nID))->SetCheck(_bCheck); + } + + CWnd* _pwndSelectMach_Check = GetDlgItem(CTRLID_CHX_SELECTMACH); + CWnd* _pwndSelectMach_Static = GetDlgItem(CTRLID_STC_SELECTMACH); + if (_pwndSelectMach_Check + && _pwndSelectMach_Static + && _pwndSelectMach_Check->IsWindowVisible() + && _pwndSelectMach_Static->IsWindowVisible()) + { + CStateManager::State _nState = CStateManager::Idle; + BOOL _bEnable = _pStateManager->GetState(&_nState) && _nState == CStateManager::Idle; + CButton* _pwndChx = (CButton*)_pwndSelectMach_Check; + if (_pwndChx->IsWindowEnabled() != _bEnable) + _pwndChx->EnableWindow(_bEnable); + if (_pwndSelectMach_Static->IsWindowEnabled() != _bEnable) + _pwndSelectMach_Static->EnableWindow(_bEnable); + + // 同步菜单选择。 ---- 黄海燕 2016-09-18 + if (_pStateManager->IsSelectedMach() != (_pwndChx->GetCheck() == BST_CHECKED)) + { + _pwndChx->SetCheck(_pStateManager->IsSelectedMach() ? BST_CHECKED : BST_UNCHECKED); + } + } + + return 1; +} + +void CMachineControlDlg::OnHScroll(UINT nSBCode_, UINT nPos_, CScrollBar* pScrollBar_) +{ + // 跟据滑动条停止时所在位置的值来设置进给倍率 ---- DingQiang 2012-02-07 + if (pScrollBar_ && (void*)pScrollBar_ == (void*)m_pwndSliderSetF) + { + // 更新横向滑动条,以20为步距设置滑块位置 ---- 王斌 2013.07.26 + int _nIndex = m_pwndSliderSetF->GetPos(); + switch(nSBCode_) + { + case TB_PAGEDOWN: + { + m_pwndSliderSetF->SetPos(20 * (_nIndex / 20)); + } + break; + case TB_PAGEUP: + { + m_pwndSliderSetF->SetPos(20* ((_nIndex + 19) / 20)); + } + break; + default: + { + m_pwndSliderSetF->SetPos(_nIndex); + } + } + + _nIndex = m_pwndSliderSetF->GetPos(); + int _nFrp = 100; + _UpdateFValue(_nIndex, &_nFrp); + + // 为安全计,通过CParamManager修改参数都会全部检查所有参数,在此处可能并 + // 非必须的,且全部检查会让进给倍率条显得卡起来,有拖尾。 因此,此处我们 + // 通过造一个Command来绕过全部检查。 ---- 杨开锦 2012-08-17 + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetFrpCommand = "SetFrp"; + CStringA _strFrp; + _strFrp.Format("%d", _nFrp); + _pCommandManager->Execute(_c_strSetFrpCommand, _strFrp, "LPCSTR"); + } + if (m_bSliderCtrlG00) + { + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetG00FrpCommand = "SetG00Frp"; + CStringA _strFrp; + _strFrp.Format("%d", _nFrp); + _pCommandManager->Execute(_c_strSetG00FrpCommand, _strFrp, "LPCSTR"); + } + } + + UpdateF(); + + // 刷新滑动条,否则出现拖尾现象 ---- 王斌 2013.07.26 + m_pwndSliderSetF->Invalidate(FALSE); + } +} + +// 更新进给倍率的显示值 ---- DingQiang 2012-02-07 +void CMachineControlDlg::UpdateF() +{ + _BuildFIVMap(); + + // 从ParamManager中读出进给倍率的当前值,如果读不到,则以设定倍率滑动条上的 + // 值为准。 ---- 杨开锦 2012-02-18 + ASSERT(m_pwndSliderSetF || m_pwndSliderSetExF); + int _nIndex = m_bIsR2 ? m_pwndSliderSetExF->GetPos() : m_pwndSliderSetF->GetPos(); + int _nFrp = 100; + _UpdateFValue(_nIndex, &_nFrp); + if (CParamManager* _pParamManager = GetParamManager()) + { + const CStringA _c_strFrpIdentifier = "SpeedGxx_Frp"; + ParameterValue _FrpParamValue; + if (_pParamManager->GetParameterValue(_c_strFrpIdentifier, &_FrpParamValue) + && _FrpParamValue.nType == ParameterValue::VT_INT) + { + _nFrp = _FrpParamValue.iValue; + _UpdateFIndex(&_nIndex, _nFrp); + } + } + + // 更新横向滑动条 + if (m_bIsR2) + { + // 更新横向滑动条 + ASSERT(m_pwndSliderSetExF); + int _nCurPos_SliderSetF = m_pwndSliderSetExF->GetPos(); + int _nNewPos_SliderSetF = min(_nFrp, m_pwndSliderSetExF->GetRangeMax()); + if (_nNewPos_SliderSetF != _nCurPos_SliderSetF) + { + m_pwndSliderSetExF->SetPos(_nNewPos_SliderSetF); + m_pwndSliderSetExF->Invalidate(); + } + + } + else + { + ASSERT(m_pwndSliderSetF); + int _nCurPos_SliderSetF = m_pwndSliderSetF->GetPos(); + int _nNewPos_SliderSetF = _nIndex; + if (_nNewPos_SliderSetF != _nCurPos_SliderSetF) + { + m_pwndSliderSetF->SetPos(_nNewPos_SliderSetF); + m_pwndSliderSetF->Invalidate(); + } + } + + // 更新弧形旋钮显示 + if (m_bIsR2) + { + ASSERT(m_pwndSliderExF); + int _nCurPos_SliderF = m_pwndSliderExF->GetPos(); + int _nNewPos_SliderF = _nIndex; + + if (_nNewPos_SliderF != _nCurPos_SliderF) + { + m_pwndSliderExF->SetPos(_nNewPos_SliderF); + m_pwndSliderExF->SetSelection(m_pwndSliderExF->GetRangeMin(), _nNewPos_SliderF); + } + } + else + { + ASSERT(m_pwndSliderF); + int _nCurPos_SliderF = m_pwndSliderF->GetPos(); + int _nNewPos_SliderF = _nIndex; + + if (_nNewPos_SliderF != _nCurPos_SliderF) + { + m_pwndSliderF->SetPos(_nNewPos_SliderF); + m_pwndSliderF->SetSelection(m_pwndSliderF->GetRangeMin(), _nNewPos_SliderF); + } + } + + // 更新文本显示 + ASSERT(m_pwndStcF); + CString _strCurValue_StcF; // 当前控件内的字符串 ---- DingQiang 2012-02-07 + CString _strNewValue_StcF; // 要放入控件内的字符串 ---- DingQiang 2012-02-07 + m_pwndStcF->GetWindowText(_strCurValue_StcF); + _strNewValue_StcF.Format(_T("%d%s"), _nFrp, "%"); + if (_strNewValue_StcF != _strCurValue_StcF) + { + m_pwndStcF->SetWindowText(_strNewValue_StcF); + } +} + +void CMachineControlDlg::UpdateManuCenter() +{ + ASSERT(m_pwndBtnCenter); + + // 当前显示的串 ---- 杨开锦 2012-02-21 + CString _strOldText; + m_pwndBtnCenter->GetWindowText(_strOldText); + + // 需要显示的串 ---- 杨开锦 2012-02-21 + CString _strNewText; + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + if (_pManualTarget->IsJogMode() && _pManualTarget->GetJogState()) + { + _strNewText = _GETCS(s_csRapidJog); + } + else if (_pManualTarget->IsJogMode() && !_pManualTarget->GetJogState()) + { + _strNewText = _GETCS(s_csSlowJog); + } + else + { + double _nIncDistance = _pManualTarget->GetIncDistance(); + + if (_nIncDistance >= 1000) + { + _strNewText.Format(_T("%.2f"), _nIncDistance); + } + else if (_nIncDistance >= 100) + { + _strNewText.Format(_T("%.3f"), _nIncDistance); + } + else if (_nIncDistance >= 10) + { + _strNewText.Format(_T("%.4f"), _nIncDistance); + } + else if (_nIncDistance >= 0) + { + _strNewText.Format(_T("%.5f"), _nIncDistance); + } + _strNewText.TrimRight(_T('0')); + _strNewText.TrimRight(_T('.')); + _strNewText += "\nmm"; + } + + // 更新 ---- 杨开锦 2012-02-21 + if (_strNewText != _strOldText) + { + m_pwndBtnCenter->SetWindowText(_strNewText); + } +} + +void CMachineControlDlg::UpdateGFOBInfo() +{ + // 点动时显示“点动”,否则显示指定的距离 ---- 杨开锦 2012-03-10 + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + CString _strGFOBDistance; + if (_pControlTarget->GetGFOBMode() == 0x01) + { + double _nGFOBDistance = _pControlTarget->GetGFOBDistance(); + ASSERT(_nGFOBDistance >= 0); + _strGFOBDistance.Format(_T("%f"), _nGFOBDistance); + _strGFOBDistance.TrimRight(_T('0')); + _strGFOBDistance.TrimRight(_T('.')); + _strGFOBDistance.AppendFormat("mm"); + } + else + { + ASSERT(_pControlTarget->GetGFOBMode() == 0x00); + _strGFOBDistance.Format("%s", _GETCS(s_csJOG)); + } + + // 惰性更新 ---- 杨开锦 2012-03-10 + CString _strOldInfo; + m_pwndStcGoDistance->GetWindowText(_strOldInfo); + if (_strGFOBDistance != _strOldInfo) + { + m_pwndStcGoDistance->SetWindowText(_strGFOBDistance); + } +} + +void CMachineControlDlg::UpdateEnableJogLaser() +{ + CButton* _pwndCheckJogLaser = (CButton*)GetDlgItem(CTRLID_CHX_JOGLASER); + // TFS#2659: 使用Button显示点动时出光,不再使用Label ---- mayazhan 2017-06-19 + if (!_pwndCheckJogLaser) + { + return; + } + + bool _bEnable = false; + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("EnableJogLaser", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_BOOL) + { + _bEnable = _ParamValue.bValue; + } + else + { + return; + } + + bool _bBtnChecked = _pwndCheckJogLaser->GetCheck() == BST_CHECKED ? true : false; + if (_bEnable != _bBtnChecked) + { + _pwndCheckJogLaser->SetCheck(_bEnable ? BST_CHECKED : BST_UNCHECKED); + } +} + +void CMachineControlDlg::UpdateEnableAutoCyc() +{ + CButton* _pwndCheckAutoCyc = (CButton*)GetDlgItem(CTRLID_CHX_AUTOCYC); + CWnd* _pwndStaticAutoCyc = GetDlgItem(CTRLID_STC_AUTOCYC); + if (!_pwndCheckAutoCyc || !_pwndStaticAutoCyc) + { + return; + } + bool _bEnableAutoCyc = false; + + CCycMachiningTarget* _pCycMachingTarget = GetCycMachiningTarget(); + BOOL _bCycEnable= _pCycMachingTarget->GetEnable(); + if(_bCycEnable == TRUE) + { + _bEnableAutoCyc = true; + } + else + { + _bEnableAutoCyc = false; + } + + bool _bBtnChecked = _pwndCheckAutoCyc->GetCheck() == BST_CHECKED ? true : false; + if (_bEnableAutoCyc != _bBtnChecked) + { + _pwndCheckAutoCyc->SetCheck(_bEnableAutoCyc ? BST_CHECKED : BST_UNCHECKED); + } +} + +void CMachineControlDlg::UpdateEnableAutoExchange() +{ + CButton* _pwndCheckAutoExchange = (CButton*)GetDlgItem(CTRLID_CHX_AUTOCYCEXCHANGE); + CWnd* _pwndStaticAutoExchange = GetDlgItem(CTRLID_STC_AUTOEXCHANGE); + if (!_pwndCheckAutoExchange || !_pwndStaticAutoExchange) + { + return; + } + bool _bEnableAutoExchange = false; + + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("AutoExchangeTaskEnd", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_INT) + { + if(_ParamValue.iValue == 1) + { + _bEnableAutoExchange = true; + } + else + { + ASSERT(_ParamValue.iValue == 0); + _bEnableAutoExchange = false; + } + } + else + { + return; + } + + bool _bBtnChecked = _pwndCheckAutoExchange->GetCheck() == BST_CHECKED ? true : false; + if (_bEnableAutoExchange != _bBtnChecked) + { + _pwndCheckAutoExchange->SetCheck(_bEnableAutoExchange ? BST_CHECKED : BST_UNCHECKED); + } +} + +void CMachineControlDlg::UpdateAir() +{ + static CString _strBlowType[3] = + { _GETCS(s_csAIR), + _GETCS(s_csN2), + _GETCS(s_csO2), + }; + + + CParamManager* _pParamManager = GetParamManager(); + //-----------增加的代码-------------------- + if (!_pParamManager) + return; + //--------------end------------------------ + ParameterValue _DefaultBlowType; + _pParamManager->GetParameterValue("GP_DefaultBlowType", &_DefaultBlowType); + int _nBlowType = _DefaultBlowType.iValue; + + // 气体类型 + SetDlgItemText(CTRLID_BTN_SELAIR, _strBlowType[_nBlowType]); +} + +void CMachineControlDlg::UpdateEndAction() +{ + static CString _strEndAction[11] = + { _GETCS(s_csNOMOTION), + _GETCS(s_csBACKFIXPOS), + _GETCS(s_csBACKWORKORG), + _GETCS(s_csBACK1), + _GETCS(s_csBACK2), + _GETCS(s_csBACK3), + _GETCS(s_csBACK4), + _GETCS(s_csBACK5), + _GETCS(s_csBACK6), + _GETCS(s_csBACK7), + _GETCS(s_csBACK8), + }; + + CParamManager* _pParamManager = GetParamManager(); + int _nTaskEndMarkPointIndex = 0; + ParameterValue _PV; + memset(&_PV, 0, sizeof(ParameterValue)); + if (_pParamManager + && _pParamManager->GetParameterValue("GP_TaskEndAdditionalAction", &_PV) + && _PV.nType == ParameterValue::VT_INT) + { + _nTaskEndMarkPointIndex = _PV.iValue; + } + + // 结束后行为 + SetDlgItemText(CTRLID_BTN_ENDACTION, _strEndAction[_nTaskEndMarkPointIndex]); +} + +// 倍率条为120格,映射到0-最大进给倍率,其中100以下为直接对应,100以下可以非线性 +// [0,100] => [0,100] +// [100,120] => [100,MaxFrp] +// 这里假设了 MaxFrp >= 100 +// 对于100以下的部分没什么好说的,此处主要说明100以上的部分如何映射: +// 1) 如果MaxFrp=120,则这部分跟100以下一样,也是线性 +// Value = Index +// 2) 如果MaxFrp<120,则这部分仍以线性方式增长到最大值MaxFrp,到最大值后不增长 +// Value = Index (when Index <= MaxFrp) +// = MaxFrp (when Index >= MaxFrp) +// 3) 如果MaxFrp>120,则这部分以线性叠加指数增长来映射 +// Value = Index * a^(Index - 100) +// 其中 a可由MaxFrp算出,例如 +// MaxFrp = 150 => 150 = 120 * a^(120-100) => a = (1.25)^(0.05) +// ---- 杨开锦 2013-03-26 +void CMachineControlDlg::_BuildFIVMap() +{ + int _nMaxFrp = m_nFValues[120]; + if (CParamManager* _pParamManager = GetParamManager()) + { + const CStringA _c_strMaxFrpIdentifier = "MaxFrp"; + ParameterValue _MaxFrpParamValue; + if (!_pParamManager->GetParameterValue(_c_strMaxFrpIdentifier, &_MaxFrpParamValue) + || _MaxFrpParamValue.nType != ParameterValue::VT_INT + || _MaxFrpParamValue.iValue == _nMaxFrp) + { + // 变化才更新 + return; + } + _nMaxFrp = _MaxFrpParamValue.iValue; + } + + C_ASSERT(_countof(m_nFValues) == 121); + if (_nMaxFrp <= 120) + { + for (int _i = 0; _i < _countof(m_nFValues); _i++) + { + m_nFValues[_i] = min(_i, _nMaxFrp); + } + return; + } + + C_ASSERT(_countof(m_nFValues) == 121); + for (int _i = 0; _i <= 100; _i++) + { + m_nFValues[_i] = _i; + } + double _nA = pow(_nMaxFrp / 120.0, 0.05); + for (int _i = 101; _i < _countof(m_nFValues); _i++) + { + int _nV = (int)(_i * pow(_nA, _i - 100.0) + 0.5); + m_nFValues[_i] = min(_nV, _nMaxFrp); + } +} + +void CMachineControlDlg::_UpdateFValue(int nIndex_, int* pnValue_) +{ + ASSERT(nIndex_ >= 0 && nIndex_ < _countof(m_nFValues) && pnValue_); + *pnValue_ = m_nFValues[nIndex_]; +} + +void CMachineControlDlg::_UpdateFIndex(int* pnIndex_, int nValue_) +{ + ASSERT(pnIndex_ && *pnIndex_ >= 0 && *pnIndex_ < _countof(m_nFValues)); + if (nValue_ == m_nFValues[*pnIndex_]) + { + return; + } + + int _i = 0; + while (_i < _countof(m_nFValues) && m_nFValues[_i] < nValue_) + { + _i++; + } + *pnIndex_ = _i; +} + +LRESULT CMachineControlDlg::OnEndSpeedDlg(WPARAM wParam_, LPARAM lParam_) +{ + m_pSetSpeedDlg->ShowWindow(SW_HIDE); + DWORD _nManuMode = (DWORD)wParam_; + union + { + LPARAM lValue; + float fValue; + } Value; + Value.lValue = lParam_; + double _nValue = (float)Value.fValue; + + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + + // 设置手动低速 ---- 郭小航 2013-11-07 + if (_nManuMode == 0) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(false); + + CParamManager* _pParamManager = GetParamManager(); + if (_pParamManager) + { + ParameterValue _ParamValue; + _pParamManager->GetParameterValue("1_0_JVelocityQuick", &_ParamValue); + if (_nValue > _ParamValue.dValue) + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocityQuick", &_ParamValue); + _pParamManager->SetParameterValue("1_0_JVelocity", &_ParamValue); + } + else + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocity", &_ParamValue); + } + } + } + // 设置手动高速 ---- 郭小航 2013-11-07 + else if (_nManuMode == 1) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(true); + + CParamManager* _pParamManager = GetParamManager(); + if (_pParamManager) + { + ParameterValue _ParamValue; + _pParamManager->GetParameterValue("1_0_JVelocity", &_ParamValue); + if (_nValue < _ParamValue.dValue) + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocity", &_ParamValue); + _pParamManager->SetParameterValue("1_0_JVelocityQuick", &_ParamValue); + } + else + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocityQuick", &_ParamValue); + } + } + } + // 设置步长 ---- 郭小航 2013-11-07 + else if (_nManuMode == 2) + { + _pManualTarget->SetManuMode(1); + _pManualTarget->SetIncDistance(_nValue); + } + + return TRUE; +} + +LRESULT CMachineControlDlg::OnEndEditDistance(WPARAM wParam_, LPARAM lParam_) +{ + ASSERT(lParam_); + CString* _strText = reinterpret_cast(lParam_); + CString _strGetValue = *_strText; + m_pwndStcGoDistance->ShowWindow(SW_SHOW); + if (IsValidDate(_strGetValue, "double", 100000, 0., "mm")) + { + double _nGetValue = _tstof(_strGetValue); + _nGetValue = _FormatInputData(_nGetValue); + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + _pControlTarget->SetGFOBDistance(_nGetValue); + } + + return TRUE; +} + +void CMachineControlDlg::OnLButtonDown(UINT nFlags_, CPoint point_) +{ + if (::IsWindow(m_pDistanceEdit->GetSafeHwnd())) + { + delete m_pDistanceEdit; + m_pDistanceEdit = NULL; + } + else + m_pDistanceEdit = NULL; +} + +// 响应鼠标单击前进后退显示按钮消息。以100/1200处为界,点击前部份:如果是步进模 +// 式则弹出编辑框可编辑前进后退距离,如果是点动模式则不响应。点击后部份:切换前 +// 进后退模式。返回True则表示不再进行消息循环 ---- DingQiang 2012-07-19 +BOOL CMachineControlDlg::OnDistanceLButtonDown(CPoint point_) +{ + CControlTarget* _pControlTarget = GetControlTarget(); + if (!_pControlTarget) + { + return FALSE; + } + + CRect _rcGoDistance; + m_pwndStcGoDistance->GetWindowRect(_rcGoDistance); + double _nWide = _rcGoDistance.Width() * 0.83; + double _nDivide = _rcGoDistance.left + _nWide; + + if (point_.x < _nDivide) + { + if (_pControlTarget->GetGFOBMode() == 0x00) + { + return TRUE; + } + + if (::IsWindow(m_pDistanceEdit->GetSafeHwnd())) + { + // 这样做的目的是防止编辑框已经Create出的时候,又点击到按钮又Create一次 ---- DingQiang 2012-07-20 + return FALSE; + } + + CString _strItemText; + m_pwndStcGoDistance->GetWindowText(_strItemText); + CRect _rect(0, 0, 0, 0); + m_pwndStcGoDistance->GetWindowRect(_rect); + + // new一个编辑框出来,其父窗口为前进后退距离显示框 ---- DingQiang 2012-07-19 + m_pwndStcGoDistance->ScreenToClient(&_rect); + _rect.top += 7; + _rect.bottom -= 6; + _rect.left += 20; + _rect.right -= 20; + DWORD _dwStyle; + _dwStyle = WS_CHILDWINDOW | WS_VISIBLE | WS_BORDER | ES_CENTER | ES_AUTOVSCROLL | ES_NOHIDESEL; + m_pDistanceEdit = new CEditItem(this, _strItemText); + m_pDistanceEdit->Create(_dwStyle, _rect, m_pwndStcGoDistance, CTRLID_EDIT_GODISTANCE); + return TRUE; + } + else + { + DWORD _nSetMode; + if (_pControlTarget->GetGFOBMode() == 0x00) + { + _nSetMode = 0x01; + } + else + _nSetMode = 0x00; + + _pControlTarget->SetGFOBMode(_nSetMode); + return FALSE; + } + + return FALSE; +} + +// 检查数据是否是合法的输入,允许输入正数、小数、单位。不允许负数和字母---- DingQiang 2012-03-07 +bool CMachineControlDlg::IsValidDate(LPCSTR szInPut_, // 输入字符串 + LPCSTR szType_, // 数据类型 + double nMax_, // 允许的最大值 + double nMin_, // 允许的最小值 + LPCSTR szUnit_) // 允许输入单位 +{ + int _nNumDots = 0; // 小数点个数,只允许一个 + CString _strInPut = szInPut_; + CString _strUint = szUnit_; + int _nLength = (int)strlen(_strInPut); // 输入入字符串长度 + int _nUnitLength = (int)strlen(_strUint); // 允许使用的单位字符串长度 + bool b_ContainUnit = false; // 是否包含单位 + + if (0 == _nLength) + { + return false; + } + + // 多于两个小数点则返回false---- DingQiang 2012-03-07 + int _nDotCount = 0; + for (int _i = 0; _i < _nLength; _i++) + { + char _szDot = _strInPut[_i]; + if (_szDot == '.') + { + _nDotCount++; + } + } + + if (_nDotCount > 1) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + + // 先检查字符串后面的_nUnitLength长度是否是数字,如果有一个不是数字则立马判 + // 断后面_nUnitLength个字符是否是单位字符,如果即不是数字也不是单位字符则直 + // 接返回错误信息,不再做其它检查。 ---- DingQiang 2012-03-07 + int _nCheckUint = (_nLength - _nUnitLength) > 0 ? _nLength - _nUnitLength : _nLength; + for (int _j = _nCheckUint; _j < _nLength; _j++) + { + char _szChar = _strInPut[_j]; + if(_szChar < 0 || _szChar > 255) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + if (!isdigit(_szChar)) + { + if (_szChar != '.') + { + if (_strUint.Compare(_strInPut.Right(_nUnitLength)) != 0) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + else + { + b_ContainUnit = true; + } + } + } + } + + // 如果有符号则检查除符号外的字符,如没有符号则全部检查---- DingQiang 2012-03-08 + int _nCheckNum = b_ContainUnit ? _nCheckUint : _nLength; + int _i = 0; + for (; _i < _nCheckNum; _i++) + { + char _c = _strInPut[_i]; + if (!isdigit(_c)) + { + if (0 == strcmp(szType_, "int")) + { + break; + } + else if (0 == strcmp(szType_, "double") || 0 == strcmp(szType_, "float")) + { + if (_c == '.' && _nNumDots == 0) + { + _nNumDots++; + } + else + { + break; + } + } + else + ASSERT(false); + } + } + + if (_i != _nCheckNum && (strcmp(szType_, "int") == 0)) + { + AfxMessageBox(_GETCS(s_csIntDataError)); + return false; + } + + if (_i != _nCheckNum && (strcmp(szType_, "float") == 0 || strcmp(szType_, "double") == 0)) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + + double _nInPut = (double)_tstof(szInPut_); + if ( _nInPut > nMin_ && _nInPut < nMax_) + { + return true; + } + else + { + CString _strErrorShow; + _strErrorShow.Format(_GETCS(s_csFloatDataBoundError), nMin_, nMax_); + AfxMessageBox(_strErrorShow); + return false; + } +} + +void CMachineControlDlg::OnChangeCoorMode() +{ + m_nCoorMode = (m_nCoorMode == 0x00) ? 0x01 : 0x00; + UpdateMachCoor(); +} + +// 格式化输入 ---- DingQiang 2012-06-25 +static double _FormatInputData(double nInputData_) +{ + ASSERT(nInputData_ >= 0); + CString _strTemp; + _strTemp.Format(_T("%f"), nInputData_); + + CString _strOut = _strTemp.Left(6); + + return _tstof(_strOut); +} + +// 设置手动速度 ---- 郭小航 2013-11-07 +void CMachineControlDlg::OnDblClickCenter() +{ + CStateManager* _pStateManager = GetStateManager(); + if (!_pStateManager) + return; + + CStateManager::State _State = mach::CStateManager::Invalid; + if (!_pStateManager->GetState(&_State)) + { + return; + } + + if (_State != mach::CStateManager::Invalid + && _State != mach::CStateManager::Idle + //&& _State != mach::CStateManager::Lock // 仿真时也不能修改速度。 + && _State != mach::CStateManager::Estop) + { + AfxMessageBox(_GETCS(s_csNotInputPrompt)); + return; + } + + ASSERT(m_pwndBtnCenter && ::IsWindow(m_pwndBtnCenter->m_hWnd)); + CRect _rcBtnCenter; + m_pwndBtnCenter->GetWindowRect(&_rcBtnCenter); + ((CSetSpeedDlg*)m_pSetSpeedDlg)->SetBasePosition(_rcBtnCenter.TopLeft()); + m_pSetSpeedDlg->ShowWindow(SW_SHOW); +} + +LRESULT CMachineControlDlg::OnSliderMoving(WPARAM wParam_, LPARAM lParam_) +{ + CParamManager* _pParamManager = mach::GetParamManager(); + if (!_pParamManager) + { + ASSERT(FALSE); + return 0; + } + + if (!m_bIsR2) + { + UINT _nCtrlID = (UINT)wParam_; + int _nIndex = (int)lParam_; + if (wParam_ == CTRLID_SLD_SETF) + { + int _nFrp = 100; + _UpdateFValue(_nIndex, &_nFrp); + + // 为安全计,通过CParamManager修改参数都会全部检查所有参数,在此处可能并 + // 非必须的,且全部检查会让进给倍率条显得卡起来,有拖尾。 因此,此处我们 + // 通过造一个Command来绕过全部检查。 ---- 杨开锦 2012-08-17 + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetFrpCommand = "SetFrp"; + CStringA _strFrp; + _strFrp.Format("%d", _nFrp); + _pCommandManager->Execute(_c_strSetFrpCommand, _strFrp, "LPCSTR"); + } + if (m_bSliderCtrlG00) + { + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetG00FrpCommand = "SetG00Frp"; + CStringA _strFrp; + _strFrp.Format("%d", _nFrp); + _pCommandManager->Execute(_c_strSetG00FrpCommand, _strFrp, "LPCSTR"); + } + } + + UpdateF(); + } + } + + // 跟据滑动条停止时所在位置的值来设置进给倍率 ---- DingQiang 2012-02-07 + if (m_bIsR2 && m_pwndSliderSetExF) + { + int _nIndex = m_pwndSliderSetExF->GetPos(); + + if (_nIndex < 105 && _nIndex >= 95) + { + m_pwndSliderSetExF->SetPos(100); + } + else if(_nIndex < 95) + { + m_pwndSliderSetExF->SetPos(5 * (_nIndex / 5)); + } + + _nIndex = m_pwndSliderSetExF->GetPos(); + int _nFrp = 100; + _UpdateFValue(_nIndex, &_nFrp); + + // 为安全计,通过CParamManager修改参数都会全部检查所有参数,在此处可能并 + // 非必须的,且全部检查会让进给倍率条显得卡起来,有拖尾。 因此,此处我们 + // 通过造一个Command来绕过全部检查。 ---- 杨开锦 2012-08-17 + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetFrpCommand = "SetFrp"; + CStringA _strFrp; + _strFrp.Format("%d", _nFrp); + _pCommandManager->Execute(_c_strSetFrpCommand, _strFrp, "LPCSTR"); + } + if (m_bSliderCtrlG00) + { + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetG00FrpCommand = "SetG00Frp"; + CStringA _strFrp; + _strFrp.Format("%d", _nFrp); + _pCommandManager->Execute(_c_strSetG00FrpCommand, _strFrp, "LPCSTR"); + } + } + + UpdateF(); + + // 刷新滑动条,否则出现拖尾现象 ---- 王斌 2013.07.26 + m_pwndSliderSetExF->Invalidate(FALSE); + } + + return 1; +} + +void CMachineControlDlg::OnSelectMach() +{ + CStateManager* _pStateManager = GetStateManager(); + if (!_pStateManager) + { + ASSERT(FALSE); + return; + } + + int _nCheck = ((CButton*)GetDlgItem(CTRLID_CHX_SELECTMACH))->GetCheck(); + m_bSelectMach = _nCheck == BST_CHECKED; + _pStateManager->SetSelectedMach(m_bSelectMach); + //设置加工选中图形是否勾选的flag于CControlTarget,用于两个界面同步----20170712 张磊 + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + _pControlTarget->SetSelectMach(m_bSelectMach); + +} + +void CMachineControlDlg::OnJogLaser() +{ + bool _bValue = false; + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("EnableJogLaser", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_BOOL) + { + _bValue = _ParamValue.bValue; + } + else + { + ASSERT(FALSE); + return; + } + + _ParamValue.bValue = !_bValue; + _pParamManager->SetParameterValue("EnableJogLaser", &_ParamValue); + UpdateEnableJogLaser(); +} + +void CMachineControlDlg::OnAutoExchange() +{ + bool _bEnableExchange = false; + + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("AutoExchangeTaskEnd", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_INT) + { + if(_ParamValue.iValue == 1) + { + _bEnableExchange = true; + } + else + { + ASSERT(_ParamValue.iValue == 0); + _bEnableExchange = false; + } + } + else + { + return; + } + + // 直接对系统参数取反 ---- 吴畏 2017-05-08 + if(_bEnableExchange) + { + memset(&_ParamValue, 0, sizeof(ParameterValue)); + _ParamValue.nType = ParameterValue::VT_INT; + _ParamValue.iValue = 0; + _pParamManager->SetParameterValue("AutoExchangeTaskEnd", &_ParamValue); + } + else + { + memset(&_ParamValue, 0, sizeof(ParameterValue)); + _ParamValue.nType = ParameterValue::VT_INT; + _ParamValue.iValue = 1; + _pParamManager->SetParameterValue("AutoExchangeTaskEnd", &_ParamValue); + } + + UpdateEnableAutoExchange(); + SendTargetMessage(ID_TARGET_EXCHANGEWORKBENCH, TM_AUTOCYC_CHECK, 0, 0); +} + +void CMachineControlDlg::OnAutoCyc() +{ + bool _bEnableCyc = false; + + CCycMachiningTarget* _pCycMachingTarget = GetCycMachiningTarget(); + BOOL _bCycEnable= _pCycMachingTarget->GetEnable(); + if(_bCycEnable == TRUE) + { + _bEnableCyc = true; + _pCycMachingTarget->SetEnable(FALSE); + } + else + { + _bEnableCyc = false; + _pCycMachingTarget->SetEnable(TRUE); + } + + UpdateEnableAutoCyc(); +} +void CMachineControlDlg::SetSelectMach(bool _bSelectMach) +{ + m_bSelectMach = _bSelectMach; +} + +bool CMachineControlDlg::GetSelectMach() +{ + return m_bSelectMach; +} +void CMachineControlDlg::OnSelMarkPoint() +{ + // 加载标记点选项菜单 ---- 边俊霞 2017-05-11 + CRect _rcRect; + GetDlgItem(CTRLID_BTN_SELMARKPOINT)->GetWindowRect(&_rcRect); + m_pMenuMark->TrackPopupMenu(TPM_LEFTBUTTON, _rcRect.right, _rcRect.bottom, this); +} + +void CMachineControlDlg::OnSelBlowAir() +{ + // 加载标记点选项菜单 ---- 边俊霞 2017-05-11 + CRect _rcRect; + GetDlgItem(CTRLID_BTN_SELAIR)->GetWindowRect(&_rcRect); + m_pMenuAir->TrackPopupMenu(TPM_LEFTBUTTON, _rcRect.right, _rcRect.bottom, this); +} + +void CMachineControlDlg::OnSelEndAction() +{ + // 加载标记点选项菜单 ---- 边俊霞 2017-05-11 + CRect _rcRect; + GetDlgItem(CTRLID_BTN_ENDACTION)->GetWindowRect(&_rcRect); + m_pMenuMarkPoint->TrackPopupMenu(TPM_LEFTBUTTON, _rcRect.right, _rcRect.bottom, this); +} + +void CMachineControlDlg::OnMarkPointChange(UINT ID_) +{ + // 在标记点按钮上显示当前选择的标记点index ---- 边俊霞 2017-03-14 + UINT _nCurIndex = ID_ - CTRLID_BTN_MARKPOINT1 + 1; + m_nCurIndex = _nCurIndex; + CString _strCurIndex; + _strCurIndex.Format("%u", _nCurIndex); + + // 使数字在button上不居中显示 ---- 边俊霞 2017-03-15 + CString _strShowIndex = _strCurIndex + '\n'; + SetDlgItemText(CTRLID_BTN_SELMARKPOINT, _strShowIndex); + + // 将当前选择的标记点index传到MarkPointTarget ---- 边俊霞 2017-03-14 + CMarkPointTarget* _pMarkPointTarget = GetMarkPointTarget(); + ASSERT(_pMarkPointTarget); + _pMarkPointTarget->SetCurMarkIndex(_nCurIndex - 1); +} + +void CMachineControlDlg::OnAirChange(UINT ID_) +{ + // 在标记点按钮上显示当前选择的标记点index ---- 边俊霞 2017-03-14 + int _nCurIndex = ID_ - CTRLID_BTN_SELAIR0; + + CParamManager* _pParamManager = GetParamManager(); + ParameterValue _DefaultBlowType; + memset(&_DefaultBlowType, 0, sizeof(ParameterValue)); + if (_pParamManager->GetParameterValue("GP_DefaultBlowType", &_DefaultBlowType) + && _DefaultBlowType.nType == ParameterValue::VT_INT) + { + _DefaultBlowType.iValue = _nCurIndex; + bool _bRet = _pParamManager->SetParameterValue("GP_DefaultBlowType", &_DefaultBlowType); + ASSERT(_bRet); + } +} + +void CMachineControlDlg::OnEndActionChange(UINT ID_) +{ + // 在标记点按钮上显示当前选择的标记点index ---- 边俊霞 2017-03-14 + UINT _nCurIndex = ID_ - CTRLID_BTN_NOMOVE; + + // 判断一下通用图层中的气体类型 + CParamManager* _pParamManager = GetParamManager(); + + ParameterValue _PV; + memset(&_PV, 0, sizeof(ParameterValue)); + + if (_pParamManager->GetParameterValue("GP_TaskEndAdditionalAction", &_PV) + && _PV.nType == ParameterValue::VT_INT) + { + _PV.iValue = _nCurIndex; + bool _bRet = _pParamManager->SetParameterValue("GP_TaskEndAdditionalAction", &_PV); + ASSERT(_bRet); + } +} \ No newline at end of file diff --git a/src/MachineControlDlg_Bottom.cpp b/src/MachineControlDlg_Bottom.cpp new file mode 100644 index 0000000..c1f20e3 --- /dev/null +++ b/src/MachineControlDlg_Bottom.cpp @@ -0,0 +1,2573 @@ +// ************************************************************************** // +// MachineControlDlg.cpp : implementation of the CMachineControlDlg_Bottom class +// Copyright(c)2011 Naiky Company. All rights reserved. +// +// Abstract: +// 本文件实现CMachineControlDlg_Bottom类。 +// ********************************************* ---- 杨开锦 2011-10-31 ***** // +#include "stdafx.h" +#include "MachineControlDlg_Bottom.h" +#include "EditItem.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW +#endif + +CS_T s_csRapidJog = _DEFCS(_CSV(18552), + _CHINESE("高速") + _ENGLISH("Rapid\nJog")); +CS_T s_csSlowJog = _DEFCS(_CSV(18553), + _CHINESE("连续") + _ENGLISH("Jog")); +CS_T s_csJOG = _DEFCS(_CSV(18554), + _CHINESE("点动") + _ENGLISH("Jog")); +CS_T s_csLANGUAGE = _DEFCS(_CSV(18555), + _CHINESE("CHN") + _ENGLISH("ENG")); +CS_T s_csNotInputPrompt = _DEFCS(_CSV(18556), + _CHINESE("系统忙,当前加工状态无法修改该参数!") + _ENGLISH("System is busy, can not change the parameters!")); +CS_T s_csIntDataError = _DEFCS(_CSV(18557), + _CHINESE("输入的参数无效,只能输入正整数,请重新输入!") + _ENGLISH("Data error, it should be a positive integer, Please enter again!")); +CS_T s_csFloatDataError = _DEFCS(_CSV(18558), + _CHINESE("输入的参数无效,请重新输入!") + _ENGLISH("Data error, it should be a number, Please enter again!")); +CS_T s_csFloatDataBoundError = _DEFCS(_CSV(18559), + _CHINESE("参数范围错误,请输入一个“%.1f~%.1f”之间的数!") + _ENGLISH("Please enter a number between %f~%f")); + +CS_T s_csAXES = _DEFCS(_CSV(18560), + _CHINESE("轴") + _ENGLISH("Axes")); +CS_T s_csMACHINECOORDINATE = _DEFCS(_CSV(18561), + _CHINESE("机械坐标") + _ENGLISH("MachCoor")); +CS_T s_csWORKPIECECOORDINATE = _DEFCS(_CSV(18562), + _CHINESE("工件坐标") + _ENGLISH("WorkCoor")); + +CS_T s_csRESUME = _DEFCS(_CSV(18563), + _CHINESE("断点\n继续") + _ENGLISH("Resume")); +CS_T s_csSIMU = _DEFCS(_CSV(18564), + _CHINESE("仿真") + _ENGLISH("Simu")); +CS_T s_csDIRRUN = _DEFCS(_CSV(18565), + _CHINESE("空运行") + _ENGLISH("DryRun")); +CS_T s_csSIMUCUTBOUNDRECT = _DEFCS(_CSV(18566), + _CHINESE("走边框") + _ENGLISH("Frame")); +CS_T s_csTipSETWORKORG = _DEFCS(_CSV(18567), + _CHINESE("设置工件原点") + _ENGLISH("Set WorkOrg")); +CS_T s_csTipMOVETOWORKORIGIN = _DEFCS(_CSV(18568), + _CHINESE("回工件原点") + _ENGLISH("Work Origin")); +CS_T s_csTipSIMUCUTBOUNDRECT = _DEFCS(_CSV(18569), + _CHINESE("走边框") + _ENGLISH("Frame")); +CS_T s_csTipSTART = _DEFCS(_CSV(18570), + _CHINESE("开始") + _ENGLISH("Start")); +CS_T s_csTipPAUSE = _DEFCS(_CSV(18571), + _CHINESE("暂停") + _ENGLISH("Pause")); +CS_T s_csTipSTOP = _DEFCS(_CSV(18572), + _CHINESE("停止") + _ENGLISH("Stop")); +CS_T s_csTipGoBackward = _DEFCS(_CSV(18573), + _CHINESE("后退") + _ENGLISH("GoBackward")); +CS_T s_csTipGoForward = _DEFCS(_CSV(18574), + _CHINESE("前进") + _ENGLISH("GoForward")); +CS_T s_csTipFollowSample = _DEFCS(_CSV(18575), + _CHINESE("标定") + _ENGLISH("Sample")); +CS_T s_csTipBackAll = _DEFCS(_CSV(18576), + _CHINESE("全部回机械原点") + _ENGLISH("BackAll")); + +CS_T s_csDistanceSet = _DEFCS(_CSV(18577), + _CHINESE("前进后退距离设定") + _ENGLISH("Distance Set")); + +CS_T s_szPortNameKey = _DEFCS(_CSV(18578), + _CHINESE("Port%d_ChnName") + _ENGLISH("Port%d_EngName")); +CS_T s_szMUNU_MARKPOINT1 = _DEFCS(_CSV(18640), + _CHINESE("标记点1") + _ENGLISH("Mark point1")); +CS_T s_szMUNU_MARKPOINT2 = _DEFCS(_CSV(18641), + _CHINESE("标记点2") + _ENGLISH("Mark point2")); +CS_T s_szMUNU_MARKPOINT3 = _DEFCS(_CSV(18642), + _CHINESE("标记点3") + _ENGLISH("Mark point3")); +CS_T s_szMUNU_MARKPOINT4 = _DEFCS(_CSV(18643), + _CHINESE("标记点4") + _ENGLISH("Mark point4")); +CS_T s_szMUNU_MARKPOINT5 = _DEFCS(_CSV(18644), + _CHINESE("标记点5") + _ENGLISH("Mark point5")); +CS_T s_szMUNU_MARKPOINT6 = _DEFCS(_CSV(18645), + _CHINESE("标记点6") + _ENGLISH("Mark point6")); +CS_T s_szMUNU_MARKPOINT7 = _DEFCS(_CSV(18646), + _CHINESE("标记点7") + _ENGLISH("Mark point7")); +CS_T s_szMUNU_MARKPOINT8 = _DEFCS(_CSV(18647), + _CHINESE("标记点8") + _ENGLISH("Mark point8")); + +using namespace mach; +using namespace ncmath; + +struct CRunReportTarget::CCache +{ + mach::CStateManager::State State; + mach::CStateManager::Speed Speed; + mach::CStateManager::FileInformation FileInfo; + mach::CStateManager::CLInformation CLInfo; +}; +//////////////////////////////////////////////////////////////////////////////// +// CtrlID +enum +{ + CTRLID_BTN_F = psh1, + CTRLID_BTN_CENTER, + CTRLID_BTN_XP, + CTRLID_BTN_XN, + CTRLID_BTN_YP, + CTRLID_BTN_YN, + CTRLID_BTN_ZP, + CTRLID_BTN_ZN, + CTRLID_BTN_WP, + CTRLID_BTN_WN, + CTRLID_BTN_GOFORWARD, + CTRLID_BTN_GOBACKWARD, + CTRLID_BTN_GODISTANCE, + CTRLID_BTN_CHANGECOOR, + CTRLID_BTN_MACHSELECTED, + CTRLID_BTN_JOGLASER, + CTRLID_BTN_AUTOCYC, + CTRLID_BTN_SELMARKPOINT, + CTRLID_BTN_MARKPOINT1, + CTRLID_BTN_MARKPOINT2, + CTRLID_BTN_MARKPOINT3, + CTRLID_BTN_MARKPOINT4, + CTRLID_BTN_MARKPOINT5, + CTRLID_BTN_MARKPOINT6, + CTRLID_BTN_MARKPOINT7, + CTRLID_BTN_MARKPOINT8, + CTRLID_BTN_AUTOEXCHANGE, + CTRLID_BTN_CYC, + + CTRLID_STC_AXES = stc1, + CTRLID_STC_COOR, + CTRLID_STC_PORT0, + CTRLID_STC_PORT1, + CTRLID_STC_PORT2, + CTRLID_STC_PORT3, + CTRLID_STC_PORT4, + CTRLID_STC_PORT5, + CTRLID_STC_PORT6, + CTRLID_STC_PORT7, + CTRLID_STC_PORT8, + CTRLID_STC_PORT9, + CTRLID_STC_PORT10, + CTRLID_STC_PORT11, + CTRLID_STC_PORT12, + CTRLID_STC_PORT13, + CTRLID_STC_PORT14, + CTRLID_STC_PORT15, + CTRLID_STC_XVALUE, + CTRLID_STC_YVALUE, + CTRLID_STC_ZVALUE, + CTRLID_STC_WVALUE, + CTRLID_STC_MACHCOOR, + CTRLID_STC_WORKCOOR, + //CTRLID_STC_SELMARKPOINT, + + CTRLID_EDIT_GODISTANCE = edt1, + + CTRLID_SLD_SETF = ctl1, + CTRLID_SLD_SETP, + CTRLID_SLD_SETFH +}; +//////////////////////////////////////////////////////////////////////////////// +// Local function declarations ---- DingQiang 2012-06-25 +static double _FormatInputData(double nInputData_); + +//////////////////////////////////////////////////////////////////////////////// +// CMachineControlDlg_Bottom +// +// 只需要按类名创建类对象,不需要序列化与版本控制。 ---- 杨开锦 2011-10-31 +IMPLEMENT_SERIAL(CMachineControlDlg_Bottom, CAgileDialog, 0xFFFF) + +BEGIN_MESSAGE_MAP(CMachineControlDlg_Bottom, CAgileDialog) + ON_WM_HSCROLL() + ON_WM_LBUTTONDOWN() + ON_MESSAGE(WM_MYDLGMESSAGE, OnEndSpeedDlg) + ON_CONTROL_RANGE(BN_PUSHED, CTRLID_BTN_XP, CTRLID_BTN_WN, OnDirectionBtnPushed) + ON_CONTROL_RANGE(BN_UNPUSHED, CTRLID_BTN_XP, CTRLID_BTN_WN, OnDirectionBtnUnpushed) + ON_CONTROL_RANGE(BN_PUSHED, CTRLID_BTN_GOFORWARD, CTRLID_BTN_GOBACKWARD, OnGFOBBtnPushed) + ON_CONTROL_RANGE(BN_UNPUSHED, CTRLID_BTN_GOFORWARD, CTRLID_BTN_GOBACKWARD, OnGFOBBtnUnpushed) + ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI) + ON_CONTROL(STN_DBLCLK, CTRLID_STC_COOR, OnChangeCoorMode) + ON_MESSAGE(WM_MYEIDTMESSAGE, OnEndEditDistance) + ON_COMMAND(CTRLID_BTN_CHANGECOOR, OnChangeCoorMode) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_CENTER, OnSetManuMode) + ON_CONTROL(BN_DOUBLECLICKED, CTRLID_BTN_CENTER, OnDblClickCenter) + ON_MESSAGE(WM_BITMAPSLIDER_MOVING, OnSliderMoving) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_MACHSELECTED, OnClickMachSelected) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_JOGLASER, OnClickJogLaser) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_AUTOCYC, OnClickAutoCyc) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_AUTOEXCHANGE, OnClickAutoExchange) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_CYC, OnClickCyc) + ON_COMMAND(CTRLID_BTN_SELMARKPOINT, OnSelMarkPoint) + ON_COMMAND_RANGE(CTRLID_BTN_MARKPOINT1, CTRLID_BTN_MARKPOINT8, OnMarkPointChange) +END_MESSAGE_MAP() + +CMachineControlDlg_Bottom::CMachineControlDlg_Bottom(CWnd* pParentWnd_/* = NULL*/) +: CMachineControlDlg_Imp(pParentWnd_) +{ + m_pwndSliderF = NULL; + m_pwndBtnXP = NULL; + m_pwndBtnXN = NULL; + m_pwndBtnYP = NULL; + m_pwndBtnYN = NULL; + m_pwndBtnZP = NULL; + m_pwndBtnZN = NULL; + m_pwndBtnWP = NULL; + m_pwndBtnWN = NULL; + m_pwndBtnCenter = NULL; + m_pwndStcValueWorkX = NULL; + m_pwndStcValueWorkY = NULL; + m_pwndStcValueWorkZ = NULL; + m_pwndStcValueWorkW= NULL; + m_pwndStcValueMachX = NULL; + m_pwndStcValueMachY= NULL; + m_pwndStcValueMachZ = NULL; + m_pwndStcValueMachW = NULL; + m_pwndStcSpeed = NULL; + m_pwndStcPower = NULL; + m_pwndStcFollowHeight = NULL; + m_pSetSpeedDlg = NULL; + m_pwndSliderSetF = NULL; + m_pwndSliderSetP = NULL; + m_pwndSliderSetFH = NULL; + m_pDistanceEdit = NULL; + m_pwndRunBtn = NULL; + m_pwndDirRunBtn = NULL; + + m_pMenu = new CMenu; + + memset(m_pwndPortButtons, 0, sizeof(CPortButton*) * _countof(m_pwndPortButtons)); + + m_nCoorMode = 0x00; + m_bSelectMach = FALSE; + + for (int _i = 0; _i < _countof(m_nFValues); _i++) + { + m_nFValues[_i] = _i; + } + + m_strShowAllBKMark = "0"; + m_strBKMarkAttachAxis = "0,1"; + + m_nArcSliderFHMax = 15; + + m_bSliderCtrlG00 = NceGetPrivateProfileString(_T("ControlTarget"), _T("SliderCtrlG00"), _T("0")) == _T("1"); + // 同步GXX和G00的倍率。 ---- 黄海燕 2016-04-19 + if (m_bSliderCtrlG00) + { + if (CParamManager* _pParamManager = GetParamManager()) + { + int _nFrp = 100; + ParameterValue _FrpParamValue; + if (_pParamManager->GetParameterValue("SpeedGxx_Frp", &_FrpParamValue) + && _FrpParamValue.nType == ParameterValue::VT_INT) + { + _nFrp = _FrpParamValue.iValue; + } + + if (_pParamManager->GetParameterValue("SpeedG00_Frp", &_FrpParamValue) + && _FrpParamValue.nType == ParameterValue::VT_INT) + { + _FrpParamValue.iValue = _nFrp; + bool _bRet = _pParamManager->SetParameterValue("SpeedG00_Frp", &_FrpParamValue); + ASSERT(_bRet); + } + } + } + + m_bShowSelectMach = FALSE; + m_bShowJogLaser = FALSE; + m_bShowAutoCyc = FALSE; + m_bSelectMach = FALSE; + m_nCurIndex = 1; + m_bShowCurValue = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowCurValue"), _T("0")) == _T("1"); + + LOAD_PARAM(this, CMachineControlDlg_Bottom); +} + +CMachineControlDlg_Bottom::~CMachineControlDlg_Bottom() +{ + if (m_pSetSpeedDlg) + { + delete m_pSetSpeedDlg; + m_pSetSpeedDlg = NULL; + } + + if (m_pMenu) + { + delete m_pMenu; + m_pMenu = NULL; + } + + SAVE_PARAM(this, CMachineControlDlg_Bottom); +} + +BOOL CMachineControlDlg_Bottom::Create(CWnd* pParentWnd_ /* = NULL */) +{ + // 更改窗口风格为子窗口,以便用于贴到NcEditor的右侧栏上。 ---- 杨开锦 2011-10-31 + static struct { DLGTEMPLATE dt; SHORT n1; SHORT n2; SHORT n3; } + _s_EmptyDialogTemplate = { WS_CHILD }; + return CreateIndirect(&_s_EmptyDialogTemplate.dt, pParentWnd_); +} + +void CMachineControlDlg_Bottom::Update() +{ + UpdateBRFlag(); + UpdateMachCoor(); + UpdateF(); + UpdateP(); + UpdateFH(); + UpdateSpeed(); + UpdateManuCenter(); + UpdateGFOBInfo(); + UpdateEnableJogLaser(); + UpdateEnableAutoCyc(); + UpdateEnableAutoExchange(); + UpdateEnableCyc(); + + UpdateEnableBoardSupport(); + for (int _i = 0; _i < _countof(m_pwndPortButtons); _i++) + { + if (m_pwndPortButtons[_i]) + { + // 定时器更新 ---- 杨开锦 2013-03-11 + m_pwndPortButtons[_i]->Update(); + } + } + m_pwndDirRunBtn->Update(); + m_pwndRunBtn->Update(); +} + +BOOL CMachineControlDlg_Bottom::OnInitDialog() +{ + __super::OnInitDialog(); + + // 注册取得各控件指针。 ---- 杨开锦 2011-10-31 + Register("stcWorkCoor", m_pwndStcWorkCoor); + Register("stcMachCoor", m_pwndStcMachCoor); + RegisterID("stcWorkCoor", CTRLID_STC_WORKCOOR); + RegisterID("stcMachCoor", CTRLID_STC_MACHCOOR); + RegisterID("stcAxes", CTRLID_STC_AXES); + RegisterID("stcCoor", CTRLID_STC_COOR); + Register("stcBR", m_pwndStcBR); + Register("stcBRX", m_pwndStcBRX); + Register("stcBRY", m_pwndStcBRY); + Register("stcBRZ", m_pwndStcBRZ); + Register("stcBRW", m_pwndStcBRW); + Register("stcXValue_Work", m_pwndStcValueWorkX); + Register("stcYValue_Work", m_pwndStcValueWorkY); + Register("stcZValue_Work", m_pwndStcValueWorkZ); + Register("stcWValue_Work", m_pwndStcValueWorkW); + Register("stcXValue_Mach", m_pwndStcValueMachX); + Register("stcYValue_Mach", m_pwndStcValueMachY); + Register("stcZValue_Mach", m_pwndStcValueMachZ); + Register("stcWValue_Mach", m_pwndStcValueMachW); + Register("stcSpeedValue", m_pwndStcSpeed); + Register("stcPowerValue", m_pwndStcPower); + Register("stcFollowHeightValue", m_pwndStcFollowHeight); + Register("sliderF", m_pwndSliderF); + Register("sliderP", m_pwndSliderP); + Register("sliderFH", m_pwndSliderFH); + Register("sliderSetF", m_pwndSliderSetF); + Register("sliderSetP", m_pwndSliderSetP); + Register("sliderSetFH", m_pwndSliderSetFH); + RegisterID("sliderSetF", CTRLID_SLD_SETF); + RegisterID("sliderSetP", CTRLID_SLD_SETP); + RegisterID("sliderSetFH", CTRLID_SLD_SETFH); + RegisterID("btnF", CTRLID_BTN_F); + RegisterID("stcXValue", CTRLID_STC_XVALUE); + RegisterID("stcYValue", CTRLID_STC_YVALUE); + RegisterID("stcZValue", CTRLID_STC_ZVALUE); + RegisterID("stcWValue", CTRLID_STC_WVALUE); + Register("btnXP", m_pwndBtnXP); + Register("btnXN", m_pwndBtnXN); + Register("btnYP", m_pwndBtnYP); + Register("btnYN", m_pwndBtnYN); + Register("btnZP", m_pwndBtnZP); + Register("btnZN", m_pwndBtnZN); + Register("btnWP", m_pwndBtnWP); + Register("btnWN", m_pwndBtnWN); + Register("stcGoDistance", m_pwndStcGoDistance); + RegisterID("stcGoDistance", CTRLID_BTN_GODISTANCE); + Register("btnCenter", m_pwndBtnCenter); + RegisterID("btnCenter", CTRLID_BTN_CENTER); + RegisterID("btnXP", CTRLID_BTN_XP); + RegisterID("btnXN", CTRLID_BTN_XN); + RegisterID("btnYP", CTRLID_BTN_YP); + RegisterID("btnYN", CTRLID_BTN_YN); + RegisterID("btnZP", CTRLID_BTN_ZP); + RegisterID("btnZN", CTRLID_BTN_ZN); + RegisterID("btnWP", CTRLID_BTN_WP); + RegisterID("btnWN", CTRLID_BTN_WN); + RegisterID("btnGoForward", CTRLID_BTN_GOFORWARD); + RegisterID("btnGoBackward", CTRLID_BTN_GOBACKWARD); + RegisterID("stcPort0", CTRLID_STC_PORT0); + RegisterID("stcPort1", CTRLID_STC_PORT1); + RegisterID("stcPort2", CTRLID_STC_PORT2); + RegisterID("stcPort3", CTRLID_STC_PORT3); + RegisterID("stcPort4", CTRLID_STC_PORT4); + RegisterID("stcPort5", CTRLID_STC_PORT5); + RegisterID("stcPort6", CTRLID_STC_PORT6); + RegisterID("stcPort7", CTRLID_STC_PORT7); + RegisterID("stcPort8", CTRLID_STC_PORT8); + RegisterID("stcPort9", CTRLID_STC_PORT9); + RegisterID("stcPort10", CTRLID_STC_PORT10); + RegisterID("stcPort11", CTRLID_STC_PORT11); + RegisterID("stcPort12", CTRLID_STC_PORT12); + RegisterID("stcPort13", CTRLID_STC_PORT13); + RegisterID("stcPort14", CTRLID_STC_PORT14); + RegisterID("stcPort15", CTRLID_STC_PORT15); + RegisterID("btnSelMarkPoint", CTRLID_BTN_SELMARKPOINT); + //RegisterID("stcSelMarkPoint", CTRLID_STC_SELMARKPOINT); + Register("btnRun", m_pwndRunBtn); + Register("btnDirrun", m_pwndDirRunBtn); + +#define RegisterBtnID(szName_, nID_) { \ + CAgileImageButton* _pwndBtn = NULL; \ + Register(szName_, _pwndBtn); \ + ASSERT(_pwndBtn); \ + ASSERT(IsCmdID(nID_)); \ + _pwndBtn->SetCmdID(nID_); \ + } + CString _strEnable = NceGetPrivateProfileString(_T("Tube"), _T("Enable"), _T("")); + BOOL _bIsTube = _strEnable == _T("True"); + if (_bIsTube) + { + RegisterBtnID("FindMid4Face", IDCMD_TUBECTRLTARGET_FINDMIDFOURSIDE); + RegisterBtnID("AdjustFindMid", IDCMD_TUBECTRLTARGET_ADJUSTHORANDFINDMID); + } + + // 将标记点选择按钮初始化 ---- 边俊霞 2017-03-15 + CString _strCurIndex; + _strCurIndex.Format("%u", m_nCurIndex); + + // 标记点选项菜单 + m_pMenu->CreatePopupMenu(); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT1, _GETCS(s_szMUNU_MARKPOINT1)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT2, _GETCS(s_szMUNU_MARKPOINT2)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT3, _GETCS(s_szMUNU_MARKPOINT3)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT4, _GETCS(s_szMUNU_MARKPOINT4)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT5, _GETCS(s_szMUNU_MARKPOINT5)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT6, _GETCS(s_szMUNU_MARKPOINT6)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT7, _GETCS(s_szMUNU_MARKPOINT7)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT8, _GETCS(s_szMUNU_MARKPOINT8)); + + + // 界面显示需求,使数字在button上不居中显示 ---- 边俊霞 2017-03-15 + CString _strShowIndex = _strCurIndex + '\n'; + SetDlgItemText(CTRLID_BTN_SELMARKPOINT, _strShowIndex); + + m_bShowSelectMach = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowSelectMach")) == _T("1"); + RegisterID("btnMachSelected", CTRLID_BTN_MACHSELECTED); + CButton* _pBtnSelMach = (CButton*)GetDlgItem(CTRLID_BTN_MACHSELECTED); + _pBtnSelMach->ShowWindow(m_bShowSelectMach ? SW_SHOWNORMAL : SW_HIDE); + + if (_pBtnSelMach) + { + _pBtnSelMach->EnableWindow(m_bShowSelectMach); + _pBtnSelMach->SetCheck(m_bSelectMach ? BST_CHECKED : BST_UNCHECKED); + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + _pStateManager->SetSelectedMach(m_bSelectMach); + } + + // 点动出光 ---- 边俊霞 2016-12-26 + m_bShowJogLaser = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowJogLaser")) == _T("1"); + RegisterID("btnJogWithLaser", CTRLID_BTN_JOGLASER); + CButton* _pBtnJogLaser = (CButton*)GetDlgItem(CTRLID_BTN_JOGLASER); + if (_pBtnJogLaser) + { + _pBtnJogLaser->EnableWindow(m_bShowJogLaser); + _pBtnJogLaser->SetCheck(m_bShowJogLaser ? BST_CHECKED : BST_UNCHECKED); + } + + BOOL _bIsTJNK = NceGetPrivateProfileString(_T("User"), _T("User")) == _T("TJNK"); + if (_bIsTJNK) + { + // 【循环加工】 ---- 李振宇 2017-06-22 + m_bShowCyc = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowAutoCyc")) == _T("1"); + if (m_bShowCyc) + { + RegisterID("btnCyc", CTRLID_BTN_CYC); + } + CButton* _pBtnAutoCyc = (CButton*)GetDlgItem(CTRLID_BTN_CYC); + if (_pBtnAutoCyc) + { + _pBtnAutoCyc->EnableWindow(m_bShowCyc); + } + + // 【自动交换】 ---- 李振宇 2017-06-22 + m_bShowAutoExchange = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowAutoExchange")) == _T("1"); + if (m_bShowAutoExchange) + { + RegisterID("btnAutoExchange", CTRLID_BTN_AUTOEXCHANGE); + } + CButton* _pBtnAutoExchange = (CButton*)GetDlgItem(CTRLID_BTN_AUTOEXCHANGE); + if (_pBtnAutoExchange) + { + _pBtnAutoExchange->EnableWindow(m_bShowAutoExchange); + } + } + else + { + // 自动循环 ---- 陈思 2017-1-10 + m_bShowAutoCyc = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowAutoCyc")) == _T("1"); + RegisterID("btnAutoCycle", CTRLID_BTN_AUTOCYC); + CButton* _pBtnAutoCyc = (CButton*)GetDlgItem(CTRLID_BTN_AUTOCYC); + if (_pBtnAutoCyc) + { + _pBtnAutoCyc->EnableWindow(m_bShowAutoCyc); + _pBtnAutoCyc->SetCheck(m_bShowAutoCyc ? BST_CHECKED : BST_UNCHECKED); + } + } + + m_pwndRunBtn->SetMotionEndType(CCycMachiningTarget::TaskEndNormal); + m_pwndDirRunBtn->SetMotionEndType(CCycMachiningTarget::DryRunEndNormal); + + // PortButton ---- DingQiang 2013-07-23 + for (size_t _i = 0; _i < _countof(m_pwndPortButtons); _i++) + { + // 注册:xaml中如果没配则注册失败,相应指针为NULL ---- DingQiang 2013-07-24 + CString _strPortButtonName; + _strPortButtonName.Format(_T("btnPort%d"), _i); + Register(_strPortButtonName, m_pwndPortButtons[_i]); + + // 初始化控件 ---- DingQiang 2016-07-14 + CString _strPortIndex; + _strPortIndex.Format(_T("Port%d"), _i); + if (!m_pwndPortButtons[_i] || !m_pwndPortButtons[_i]->Initialize(_T("ControlTarget"), _strPortIndex)) + { + continue; + } + + // 设置相应的端口名 ---- 杨开锦 2012-07-05 + CString _strDescriptionNameKey; + _strDescriptionNameKey.Format(_GETCS(s_szPortNameKey), _i); + CString _strDescriptionName = NceGetPrivateProfileString(_T("ControlTarget"), _strDescriptionNameKey); + SetDlgItemText(CTRLID_STC_PORT0 + (int)_i, _strDescriptionName); + } + + // 隐藏所有的回机械原点标志----梁艳-2015-02-08 + m_pwndStcBR->ShowWindow(SW_HIDE); + m_pwndStcBRX->ShowWindow(SW_HIDE); + m_pwndStcBRY->ShowWindow(SW_HIDE); + m_pwndStcBRZ->ShowWindow(SW_HIDE); + if (m_pwndStcBRW) + { + m_pwndStcBRW->ShowWindow(SW_HIDE); + } + + //读配置,是否显示所有轴回机械原点标志以及回机械原点关联轴的索引 + //如果可以读到,则使用读到的,否则使用默认的----梁艳-2015-02-08 + CString _strShowAllBKMark = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowAllBKMark")); + CString _strBKMarkAttachAxis = NceGetPrivateProfileString(_T("ControlTarget"), _T("BKMarkAttachAxis")); + if (!_strShowAllBKMark.IsEmpty()) + { + m_strShowAllBKMark = _strShowAllBKMark; + } + if (!_strBKMarkAttachAxis.IsEmpty()) + { + m_strBKMarkAttachAxis = _strBKMarkAttachAxis; + } + + //只显示一个回原点标志时,求出关联轴的索引---梁艳-2015-02-08 + if (m_strShowAllBKMark == "0") + { + CString _strBKMarkAttachAxis = m_strBKMarkAttachAxis; + //关联轴索引 空值或含有非法字符或只有一个非数字字符 + if (_strBKMarkAttachAxis.IsEmpty() + ||_strBKMarkAttachAxis.SpanIncluding(_T(",012")).GetLength() != _strBKMarkAttachAxis.GetLength() + || _strBKMarkAttachAxis.GetLength() == 1 && _strBKMarkAttachAxis.FindOneOf(_T("012")) == -1) + { + _strBKMarkAttachAxis.Empty(); + } + m_strVecAxis.clear(); + while(!_strBKMarkAttachAxis.IsEmpty()) + { + _strBKMarkAttachAxis.TrimLeft(","); + _strBKMarkAttachAxis.TrimRight(","); + int _Index = _strBKMarkAttachAxis.Find(","); + if(_Index == -1) + { + m_strVecAxis.push_back(_strBKMarkAttachAxis); + break; + } + m_strVecAxis.push_back( _strBKMarkAttachAxis.Left(_Index)); + _strBKMarkAttachAxis = _strBKMarkAttachAxis.Right(_strBKMarkAttachAxis.GetLength() - _Index); + } + } + +#define RegisterBtnID(szName_, nID_) { \ + CAgileImageButton* _pwndBtn = NULL; \ + Register(szName_, _pwndBtn); \ + ASSERT(_pwndBtn); \ + ASSERT(IsCmdID(nID_)); \ + _pwndBtn->SetCmdID(nID_); \ + } + RegisterBtnID("btnSetW", IDCMD_CONTROLTARGET_CLEARW); + RegisterBtnID("btnBW", IDCMD_CONTROLTARGET_BACKW); + RegisterBtnID("btnSimuCut", IDCMD_CONTROLTARGET_SIMUCUT); + RegisterBtnID("btnRun", IDCMD_CONTROLTARGET_START); + RegisterBtnID("btnPause", IDCMD_CONTROLTARGET_PAUSE); + RegisterBtnID("btnStop", IDCMD_CONTROLTARGET_STOP); + RegisterBtnID("btnBreakpointResume", IDCMD_CONTROLTARGET_BREAKPOINTRESUME); + RegisterBtnID("btnSimulate", IDCMD_CONTROLTARGET_SIMULATE); + RegisterBtnID("btnDirrun", IDCMD_CONTROLTARGET_DIRRUN); + + RegisterBtnID("btnBackFixed", IDCMD_CONTROLTARGET_BACKWZ); + + if((NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowCleanJet")) == _T("1"))) + { + RegisterBtnID("btnCleanJet", IDCMD_AUTOCLEANTARGET_STARTAUTOCLEAN); + } + RegisterBtnID("btnMarkPoint", IDCMD_MARKPOINTTARGET_MARKTHISPOINT); + RegisterBtnID("btnBackMarkPoint", IDCMD_MARKPOINTTARGET_MOVETOMARKPOINT); + CString _strCutBoundText; + if (NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowSampleBtn")) == _T("1")) + { + RegisterBtnID("btnSample", IDCMD_FOLLOWCTRLTARGET_SAMPLE); + // 走边框放到下一排,按钮上显示字。 ---- 黄海燕 2015-09-10 + _strCutBoundText = _GETCS(s_csSIMUCUTBOUNDRECT); + } + if (NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowBackOrgBtn")) == _T("1")) + RegisterBtnID("btnBackOrg", IDCMD_CONTROLTARGET_BACKR); +#undef RegisterBtnID + + SetDlgItemText(CTRLID_STC_AXES, _GETCS(s_csAXES)); + SetDlgItemText(CTRLID_STC_MACHCOOR, _GETCS(s_csMACHINECOORDINATE)); // 机械坐标 ---- 吴畏 2016-10-27 + SetDlgItemText(CTRLID_STC_WORKCOOR, _GETCS(s_csWORKPIECECOORDINATE)); // 工件坐标 ---- 吴畏 2016-10-27 + SetDlgItemText(CTRLID_STC_COOR, m_nCoorMode == 0x00 ? _GETCS(s_csWORKPIECECOORDINATE) : _GETCS(s_csMACHINECOORDINATE)); + //SetDlgItemText(IDCMD_CONTROLTARGET_BREAKPOINTRESUME, _GETCS(s_csRESUME)); + //SetDlgItemText(IDCMD_CONTROLTARGET_SIMULATE, _GETCS(s_csSIMU)); + //SetDlgItemText(IDCMD_CONTROLTARGET_DIRRUN, _GETCS(s_csDIRRUN)); + //SetDlgItemText(IDCMD_CONTROLTARGET_SIMUCUT, _strCutBoundText); + + // 设置功率滑动条范围---- DingQiang 2012-04-28 + CString _strIsGrayBottom = NceGetPrivateProfileString(_T("ControlTarget"), _T("IsGrayBottom"), _T(0)); + BOOL _bIsGrayBottom = atoi(_strIsGrayBottom); + + CString _strSliderStyle = NceGetPrivateProfileString(_T("Theme"), _T("SliderStyle"), _T("None")); + bool _bIsBD = (_strSliderStyle == _T("BD")); + + m_pwndSliderSetF->SetCustomerSetSize(); + if (_bIsGrayBottom) + { + // 加载灰色背景竖屏滑动条配色 ---- 边俊霞 2017-01-11 + m_pwndSliderSetF->SetBitmapChannel( IDB_BMP_GRAY_CHANNELBACK, IDB_BMP_GRAY_CHANNELFORE); + m_pwndSliderSetF->SetBitmapThumb( IDB_BMP_GRAY_THUMBNORMAL, IDB_BMP_GRAY_THUMBPRESS, IDB_BMP_GRAY_THUMBHOVER); + } + else + { + m_pwndSliderSetF->SetBitmapChannel( IDB_BMP_CHANNELBACK, IBP_BMP_CHANNELFORE); + m_pwndSliderSetF->SetBitmapThumb( IDB_BMP_THUMBNORMAL, IDB_BMP_THUMBPRESS, IDB_BMP_THUMBHOVER); + } + m_pwndSliderSetF->SetRange( 0, 100); + m_pwndSliderSetF->SetPos( 0 ); + + m_pwndSliderSetP->SetCustomerSetSize(); + if (_bIsGrayBottom) + { + // 加载灰色背景竖屏滑动条配色 ---- 边俊霞 2017-01-11 + m_pwndSliderSetP->SetBitmapChannel( IDB_BMP_GRAY_CHANNELBACK, IDB_BMP_GRAY_CHANNELFORE); + m_pwndSliderSetP->SetBitmapThumb( IDB_BMP_GRAY_THUMBNORMAL, IDB_BMP_GRAY_THUMBPRESS, IDB_BMP_GRAY_THUMBHOVER); + } + else + { + m_pwndSliderSetP->SetBitmapChannel( IDB_BMP_CHANNELBACK, IBP_BMP_CHANNELFORE); + m_pwndSliderSetP->SetBitmapThumb( IDB_BMP_THUMBNORMAL, IDB_BMP_THUMBPRESS, IDB_BMP_THUMBHOVER); + } + m_pwndSliderSetP->SetRange( 0, 100); + m_pwndSliderSetP->SetPos( 0 ); + + m_pwndSliderSetFH->SetCustomerSetSize(); + if (_bIsGrayBottom) + { + // 加载灰色背景竖屏滑动条配色 ---- 边俊霞 2017-01-11 + m_pwndSliderSetFH->SetBitmapChannel( IDB_BMP_GRAY_CHANNELBACK, IDB_BMP_GRAY_CHANNELFORE); + m_pwndSliderSetFH->SetBitmapThumb( IDB_BMP_GRAY_THUMBNORMAL, IDB_BMP_GRAY_THUMBPRESS, IDB_BMP_GRAY_THUMBHOVER); + } + else + { + m_pwndSliderSetFH->SetBitmapChannel( IDB_BMP_CHANNELBACK, IBP_BMP_CHANNELFORE); + m_pwndSliderSetFH->SetBitmapThumb( IDB_BMP_THUMBNORMAL, IDB_BMP_THUMBPRESS, IDB_BMP_THUMBHOVER); + } + m_pwndSliderSetFH->SetRange( 0, 80); + m_pwndSliderSetFH->SetPos( 0 ); + + // 仪表盘 ---- 吴畏 2017-04-12 + if (_bIsGrayBottom) + { + m_pwndSliderF->SetRange(0, 100); + m_pwndSliderF->Init(2, 90, 260, IDB_BMP_ARCSLIDERBK_GRAY_FEED, RGB(255, 255, 255)); + m_pwndSliderP->Init(2, 90, 260, IDB_BMP_ARCSLIDERBK_GRAY_POWER, RGB(255, 255, 255)); + } + else if (_bIsBD) + { + m_pwndSliderF->SetRange(0, 100); + m_pwndSliderF->Init(2, 90, 255, IDB_BMP_ARCSLIDERBK_FEED_BD, RGB(255, 255, 255)); + m_pwndSliderP->Init(2, 90, 255, IDB_BMP_ARCSLIDERBK_POWER_BD, RGB(255, 255, 255)); + } + else + { + m_pwndSliderF->SetRange(0, 120); + m_pwndSliderF->Init(2, 142, 257, IDB_BMP_ARCSLIDERBK_FEED, RGB(255, 255, 255)); + m_pwndSliderP->Init(2, 142, 257, IDB_BMP_ARCSLIDERBK_POWER, RGB(255, 255, 255)); + } + m_pwndSliderSetFH->SetRange(0, 80); + + _BuildFHIVMap(); + m_pwndSliderFH->SetRange(0, 80); + if (_bIsGrayBottom) + { + m_pwndSliderFH->Init(2, 90, 260, IDB_BMP_ARCSLIDERBK_GRAY_FOLLOWHEIGHT, RGB(255, 255, 255)); + } + else if (_bIsBD) + { + m_pwndSliderFH->Init(2, 90, 260, IDB_BMP_ARCSLIDERBK_FOLLOWHEIGHT_BD, RGB(255, 255, 255)); + } + else + { + m_pwndSliderFH->Init(2, 142, 257, IDB_BMP_ARCSLIDERBK_FOLLOWHEIGHT, RGB(255, 255, 255)); + } + // 手动中心键为圆形按钮,手动方向键为圆环切割而成,其中X-为左月牙、X+为右月 + // 牙、Y-为下月牙、Y+为上月牙。 + // 中心键半径为34px;方向键所在圆环外径为80px,内径为40px,各键间间隔缝为 + // 宽8px。 + // 此处各区域值为略扩大一点的区域,以便确保能完全包含所画贴图而不产生边界 + // 切割据齿。 ---- 杨开锦 2011-11-02 + ASSERT(m_pwndBtnCenter && m_pwndBtnXP && m_pwndBtnXN && m_pwndBtnYP && m_pwndBtnYN); + + if (_bIsBD) + { + bool _bEnableW = IsEnableWUpDown(); + if (!_bEnableW) + { + m_pwndBtnCenter->SetShape(::CreateEllipticRgn(-1, -1, 77, 77)); + CDC _dc; + CDC* _pDC = GetDC(); + _dc.CreateCompatibleDC(_pDC); + ReleaseDC(_pDC); + _pDC = NULL; + _dc.BeginPath(); + _dc.MoveTo(147, 28); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 170, 170, 147, 28, 147, 143); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(40, 40, 128, 128, 118, 113, 118, 57); + _dc.LineTo(147, 28); + _dc.EndPath(); + CRgn _rgn; + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-120, -27); + m_pwndBtnXP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(52, 114); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(40, 40, 130, 130, 52, 114, 52, 58); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(-1, -1, 170, 170, 22, 30, 22, 142); + _dc.LineTo(52, 114); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(18, -27); + m_pwndBtnXN->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(26, 23); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-3, -3, 170, 170, 26, 23, 143, 23); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(45, 45, 130, 130, 115, 56, 54, 56); + _dc.LineTo(26, 23); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-1, 16); + m_pwndBtnYP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(140, 148); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 173, 173, 140, 148, 28, 148); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(39, 39, 129, 129, 57, 116, 112, 116); + _dc.LineTo(140, 148); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(0, -117); + m_pwndBtnYN->SetShape((HRGN)_rgn.Detach()); + } + else + { + m_pwndBtnCenter->SetShape(::CreateEllipticRgn(-1, -1, 67, 67)); + CDC _dc; + CDC* _pDC = GetDC(); + _dc.CreateCompatibleDC(_pDC); + ReleaseDC(_pDC); + _pDC = NULL; + _dc.BeginPath(); + _dc.MoveTo(130, 16); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 152, 152, 130, 19, 133, 129); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(39, 38, 107, 107, 98, 98, 101, 45); + _dc.LineTo(130, 16); + _dc.EndPath(); + CRgn _rgn; + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-99, -22); + m_pwndBtnXP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(49, 96); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(42, 40, 112, 110, 49, 96, 49, 49); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(-1, -1, 152, 152, 17, 17, 18, 127); + _dc.LineTo(49, 96); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(8, -24); + m_pwndBtnXN->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(21, 17); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 150, 150, 21, 17, 125, 18); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(44, 42, 110, 108, 100, 47, 48, 47); + _dc.LineTo(21, 17); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-24, 8); + m_pwndBtnYP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(125, 126); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(1, -1, 150, 150, 125, 126, 26, 127); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(36, 32, 112, 108, 51, 98, 100, 100); + _dc.LineTo(125, 126); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-26, -100); + m_pwndBtnYN->SetShape((HRGN)_rgn.Detach()); + } + } + else + { + m_pwndBtnCenter->SetShape(::CreateEllipticRgn(-1, -1, 77, 77)); + CDC _dc; + CDC* _pDC = GetDC(); + _dc.CreateCompatibleDC(_pDC); + ReleaseDC(_pDC); + _pDC = NULL; + _dc.BeginPath(); + _dc.MoveTo(165, 41); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 205, 205, 165, 41, 165, 164); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(72, 72, 132, 132, 132, 132, 132, 73); + _dc.LineTo(165, 41); + _dc.EndPath(); + CRgn _rgn; + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-136, -43); + m_pwndBtnXP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(72, 132); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(72, 72, 132, 132, 72, 132, 72, 73); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(-1, -1, 205, 205, 39, 41, 39, 164); + _dc.LineTo(72, 132); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(0, -43); + m_pwndBtnXN->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(39, 41); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 205, 205, 39, 41, 165, 41); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(72, 72, 132, 132, 132, 73, 72, 73); + _dc.LineTo(39, 41); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-20, 0); + m_pwndBtnYP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(165, 164); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 205, 205, 165, 164, 39, 164); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(72, 72, 132, 132, 72, 132, 132, 132); + _dc.LineTo(135, 139); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-8, -134); + m_pwndBtnYN->SetShape((HRGN)_rgn.Detach()); + } + + m_pSetSpeedDlg = new CSetSpeedDlg(this); + ((CSetSpeedDlg*)m_pSetSpeedDlg)->Create(this); + + // 这里加一次Update是因为:出现过一个问题,软件启动时横向的进给倍率条显示不 + // 出来,最小化最大化一下才出来。带NcStudio启动才有问题,单NcEditor没问题。 + // 没有查出原因,只是经试验发现这里Update一次就好了,于是就这么干。如果以后 + // 发现这样不是正解请修改。 ---- 杨开锦 2012-05-02 + Update(); + + bool _bEnableZ = IsEnableZUpDown(); + m_pwndBtnZP->EnableWindow(_bEnableZ ? TRUE : FALSE); + m_pwndBtnZN->EnableWindow(_bEnableZ ? TRUE : FALSE); + m_pwndBtnZP->ShowWindow(_bEnableZ ? TRUE : FALSE); + m_pwndBtnZN->ShowWindow(_bEnableZ ? TRUE : FALSE); + SetMachineCtrlTips(); + return TRUE; +} + +void CMachineControlDlg_Bottom::SetMachineCtrlTips() +{ + m_MachineCtrlTips.Create(this); + m_MachineCtrlTips.Activate(TRUE); + m_MachineCtrlTips.SetTipTextColor(RGB(0, 0, 0)); + m_MachineCtrlTips.SetDelayTime(1000); + + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_CLEARW), _GETCS(s_csTipSETWORKORG)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_BACKW), _GETCS(s_csTipMOVETOWORKORIGIN)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_START), _GETCS(s_csTipSTART)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_PAUSE), _GETCS(s_csTipPAUSE)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_STOP), _GETCS(s_csTipSTOP)); + m_MachineCtrlTips.AddTool(GetDlgItem(CTRLID_BTN_GOBACKWARD), _GETCS(s_csTipGoBackward)); + m_MachineCtrlTips.AddTool(GetDlgItem(CTRLID_BTN_GOFORWARD), _GETCS(s_csTipGoForward)); + CWnd* _pwndBtn = GetDlgItem(IDCMD_FOLLOWCTRLTARGET_SAMPLE); + if (_pwndBtn) + m_MachineCtrlTips.AddTool(_pwndBtn, _GETCS(s_csTipFollowSample)); + _pwndBtn = GetDlgItem(IDCMD_CONTROLTARGET_BACKR); + if (_pwndBtn) + m_MachineCtrlTips.AddTool(_pwndBtn, _GETCS(s_csTipBackAll)); +} + +bool CMachineControlDlg_Bottom::IsEnableZUpDown() +{ + return true; + CString _strEnableZ = NceGetPrivateProfileString(_T("ControlTarget"), _T("EnableZ")); + + if ("1" == _strEnableZ) + { + return true; + } + else + { + return false; + } +} + +bool CMachineControlDlg_Bottom::IsEnableWUpDown() +{ + CString _strEnableW = NceGetPrivateProfileString(_T("ControlTarget"), _T("EnableW")); + + if ("1" == _strEnableW) + { + return true; + } + else + { + return false; + } +} + +BOOL CMachineControlDlg_Bottom::PreTranslateMessage(MSG* pMsg_) +{ + // 添加此句用于机床控制栏显示提示语 ---- 嘎松卓玛 2012.05.17 + m_MachineCtrlTips.RelayEvent(pMsg_); + + // Let go of Keyboard Message => 此处这么做有几个目的:一个是屏蔽Enter、Esc + // 键引发的OnOK、OnCancel关闭窗口;二是防止焦点在窗口上时,框架上的快捷键被 + // 屏蔽。 ---- 杨开锦 2012-04-08 + if (WM_KEYFIRST <= pMsg_->message && pMsg_->message <= WM_KEYLAST) + { + return FALSE; + } + + if (pMsg_->message == WM_LBUTTONDOWN) + { + UINT _nCtrlID = ::GetDlgCtrlID(pMsg_->hwnd); + if (_nCtrlID == CTRLID_BTN_GODISTANCE) + { + if (OnDistanceLButtonDown(pMsg_->pt)) + { + // 如果不return的话Dialog会响应此消息,此时new出来的编辑框会又马上 + // 响应OnKillFocus导致编辑框一出来就消失 ---- DingQiang 2012-07-19 + return TRUE; + } + } + } + + return __super::PreTranslateMessage(pMsg_); +} + +// 设置手动模式 ---- 郭小航 2013-11-07 +void CMachineControlDlg_Bottom::OnSetManuMode() +{ + DWORD _nBegin = GetTickCount(); + while(true) + { + MSG _msg; + if (::PeekMessage(&_msg, NULL, NULL, NULL, PM_REMOVE)) + { + ::TranslateMessage(&_msg); + ::DispatchMessage(&_msg); + + if (_msg.message == WM_LBUTTONDBLCLK) + { + return; + } + } + + if (GetTickCount() - _nBegin > 200) + { + break; + } + } + + static int _s_nManuMode; + int _nManuMode = _s_nManuMode % 3; + + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + if (_nManuMode == 0) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(false); + } + else if (_nManuMode == 1) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(true); + } + else if (_nManuMode == 2) + { + _pManualTarget->SetManuMode(1); + } + + _s_nManuMode ++; +} + +void CMachineControlDlg_Bottom::UpdateMachCoor() +{ + CParamManager* _pParamManager = GetParamManager(); + if (!_pParamManager) + { + return; + } + + // 将控件与相应控件的参数标识符关联创建一个结构体---- DingQiang 2012-01-12 + const struct MachItem + { + CAgileLabel* pwndStcValue; + CString strIdentifier; + } _s_MachItems[] = + { + { m_pwndStcValueWorkX, "State_Axis0_WorkcoorPos" }, + { m_pwndStcValueWorkY, "State_Axis1_WorkcoorPos" }, + { m_pwndStcValueWorkZ, "State_Axis2_WorkcoorPos" }, + { m_pwndStcValueWorkW, "State_Axis3_WorkcoorPos" }, + { m_pwndStcValueMachX, "Dyn_Axis0_Pos"}, + { m_pwndStcValueMachY, "Dyn_Axis1_Pos"}, + { m_pwndStcValueMachZ, "Dyn_Axis2_Pos"}, + { m_pwndStcValueMachW, "Dyn_Axis3_Pos"}, + }; + + for(int _i = 0; _i < _countof(_s_MachItems); _i++) + { + const MachItem& _item = _s_MachItems[_i]; + if (!_item.pwndStcValue || !_item.pwndStcValue->IsWindowVisible()) + { + continue; + } + + ParameterValue _PV; + if (!_pParamManager->GetParameterValue(_item.strIdentifier, &_PV) || _PV.nType != ParameterValue::VT_DOUBLE) + { + ASSERT(FALSE); + continue; + } + + CString _strMachCoor; + _strMachCoor.Format("%.3f", _PV.dValue); + if (_strMachCoor == "-0.000") + { + _strMachCoor = "0.000"; + } + + // 若更新前坐标与更新后坐标相等则不更新 ---- DingQiang 2012-01-12 + CString _strBeforeUpdate; + _item.pwndStcValue->GetWindowText(_strBeforeUpdate); + if (_strMachCoor != _strBeforeUpdate) + { + _s_MachItems[_i].pwndStcValue->SetWindowText(_strMachCoor); + } + } +} +// 回机械原点标志,配置方式如下: +// [ControlTarget] +// ShowAllBKMark=1 +// BKMarkAttachAxis=0,1,2 +void CMachineControlDlg_Bottom::UpdateBRFlag() +{ + // 将轴原点标志控件与相应控件的参数以及轴的索引,关联创建一个结构体,方便以后扩展----梁艳-2015-02-08 + const struct AxisItems + { + CAgileImageLabel* pwndStcBR; + CString strIdentifier; + CString strIndex; + } _s_AxisItems[] = + { + { m_pwndStcBRX, "State_Axis0_IsReferenced", "0" }, + { m_pwndStcBRY, "State_Axis1_IsReferenced", "1" }, + { m_pwndStcBRZ, "State_Axis2_IsReferenced", "2" }, + //{ m_pwndStcBRW, "State_Axis3_IsReferenced", "3" }, + }; + + CParamManager* _pParamManager = GetParamManager(); + if(!_pParamManager) + return; + + //如果显示所有轴的回机械原点标志,则分别显示各轴的回机械原点标志---梁艳-2015-02-08 + if (m_strShowAllBKMark == _T("1")) + { + int _nAllAxis = _countof(_s_AxisItems); + bool _bEnableW = IsEnableWUpDown(); + //int _nCount = _bEnableW ? (_nAllAxis - 1) : _nAllAxis; + for(int _i = 0; _i < _nAllAxis; _i++) + { + const AxisItems& _item = _s_AxisItems[_i]; + ParameterValue _PV; + memset(&_PV, 0, sizeof(ParameterValue)); + if (!_pParamManager->GetParameterValue(_item.strIdentifier, &_PV) || _PV.nType != ParameterValue::VT_BOOL) + { + ASSERT(FALSE); + continue; + } + _item.pwndStcBR->ShowWindow(_PV.bValue ? SW_SHOW : SW_HIDE); + } + } + // 如果不显示所有轴的回机械原点标志,则根据关联轴的索引,只显示一个回机械原点标志---梁艳-2015-02-08 + else if(m_strShowAllBKMark == _T("0")) + { + bool _bIsRef = m_strVecAxis.empty()? false : true; + for (std::vector::iterator _it = m_strVecAxis.begin(); _it != m_strVecAxis.end();_it++) + { + int _nCount = 0; + CString _strAxis = *_it; + for(int _j = 0; _j < _countof(_s_AxisItems); _j++) + { + const AxisItems& _item = _s_AxisItems[_j]; + ParameterValue _PV; + memset(&_PV, 0, sizeof(ParameterValue)); + if (!_pParamManager->GetParameterValue(_item.strIdentifier, &_PV) || _PV.nType != ParameterValue::VT_BOOL) + { + ASSERT(FALSE); + continue; + } + if (_item.strIndex == _strAxis) + { + _bIsRef &= _PV.bValue; + break; + } + else + { + _nCount++; + continue; + } + } + //没有匹配项 + if (_nCount == _countof(_s_AxisItems)) + { + _bIsRef = false; + } + } + m_pwndStcBR->ShowWindow(_bIsRef ? SW_SHOW : SW_HIDE); + } +} + + +void CMachineControlDlg_Bottom::OnDirectionBtnPushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_XP && nID_ <= CTRLID_BTN_WN); + + // 将手动按钮模拟成快捷键导到CManualTarget中 + C_ASSERT(CTRLID_BTN_XP == CTRLID_BTN_XP + 0 + && CTRLID_BTN_XN == CTRLID_BTN_XP + 1 + && CTRLID_BTN_YP == CTRLID_BTN_XP + 2 + && CTRLID_BTN_YN == CTRLID_BTN_XP + 3 + && CTRLID_BTN_ZP == CTRLID_BTN_XP + 4 + && CTRLID_BTN_ZN == CTRLID_BTN_XP + 5 + && CTRLID_BTN_WP == CTRLID_BTN_XP + 6 + && CTRLID_BTN_WN == CTRLID_BTN_XP + 7); + static const UINT _s_nKeys[] = + { + VK_NUMPAD6, + VK_NUMPAD4, + VK_NUMPAD8, + VK_NUMPAD2, + VK_NUMPAD9, + VK_NUMPAD3, + VK_NUMPAD7, + VK_NUMPAD1, + }; + + // 没有W轴,屏蔽W轴快捷键 ---- 吴畏 2016-12-30 + bool _bEnableW = IsEnableWUpDown(); + if (!_bEnableW && (nID_ == CTRLID_BTN_WP || nID_ == CTRLID_BTN_WN)) + { + return; + } + + MSG _msg = { NULL, WM_KEYDOWN, WPARAM(_s_nKeys[nID_ - CTRLID_BTN_XP]), LPARAM(1) }; + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + _pManualTarget->OnKeyMessage(&_msg); +} + +void CMachineControlDlg_Bottom::OnDirectionBtnUnpushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_XP && nID_ <= CTRLID_BTN_WN); + + // 将手动按钮模拟成快捷键导到CManualTarget中 + C_ASSERT(CTRLID_BTN_XP == CTRLID_BTN_XP + 0 + && CTRLID_BTN_XN == CTRLID_BTN_XP + 1 + && CTRLID_BTN_YP == CTRLID_BTN_XP + 2 + && CTRLID_BTN_YN == CTRLID_BTN_XP + 3 + && CTRLID_BTN_ZP == CTRLID_BTN_XP + 4 + && CTRLID_BTN_ZN == CTRLID_BTN_XP + 5 + && CTRLID_BTN_WP == CTRLID_BTN_XP + 6 + && CTRLID_BTN_WN == CTRLID_BTN_XP + 7); + static const UINT _s_nKeys[] = + { + VK_NUMPAD6, + VK_NUMPAD4, + VK_NUMPAD8, + VK_NUMPAD2, + VK_NUMPAD9, + VK_NUMPAD3, + VK_NUMPAD7, + VK_NUMPAD1, + }; + + // 没有W轴,屏蔽W轴快捷键 ---- 吴畏 2016-12-30 + bool _bEnableW = IsEnableWUpDown(); + if (!_bEnableW && nID_ >= CTRLID_BTN_WP) + { + return; + } + + MSG _msg = { NULL, WM_KEYUP, WPARAM(_s_nKeys[nID_ - CTRLID_BTN_XP]), LPARAM(1) }; + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + _pManualTarget->OnKeyMessage(&_msg); +} + +void CMachineControlDlg_Bottom::OnGFOBBtnPushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_GOFORWARD && nID_ <= CTRLID_BTN_GOBACKWARD); + + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + if (_pControlTarget->GetGFOBMode() != 0x00) + { + return; + } + + C_ASSERT(CTRLID_BTN_GOFORWARD == CTRLID_BTN_GOFORWARD + 0 + && CTRLID_BTN_GOBACKWARD == CTRLID_BTN_GOFORWARD + 1); + static const UINT _s_nCmdIDs[] = + { + IDCMD_CONTROLTARGET_JOGFORWARD, + IDCMD_CONTROLTARGET_JOGBACKWARD, + }; + AfxGetMainWnd()->SendMessage(WM_COMMAND, _s_nCmdIDs[nID_ - CTRLID_BTN_GOFORWARD], 0); +} + +void CMachineControlDlg_Bottom::OnGFOBBtnUnpushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_GOFORWARD && nID_ <= CTRLID_BTN_GOBACKWARD); + + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + if (_pControlTarget->GetGFOBMode() == 0x00) + { + AfxGetMainWnd()->SendMessage(WM_COMMAND, IDCMD_CONTROLTARGET_STOP, 0); + return; + } + + C_ASSERT(CTRLID_BTN_GOFORWARD == CTRLID_BTN_GOFORWARD + 0 + && CTRLID_BTN_GOBACKWARD == CTRLID_BTN_GOFORWARD + 1); + static const UINT _s_nCmdIDs[] = + { + IDCMD_CONTROLTARGET_INCFORWARD, + IDCMD_CONTROLTARGET_INCBACKWARD, + }; + AfxGetMainWnd()->SendMessage(WM_COMMAND, _s_nCmdIDs[nID_ - CTRLID_BTN_GOFORWARD], 0); +} + +LRESULT CMachineControlDlg_Bottom::OnIdleUpdateCmdUI(WPARAM wParam_, LPARAM lParam_) +{ + static const struct ManualBtnItem + { + CButton* pBtnManual; + DWORD nMask; + } _s_cManualBtnItems[] = + { + {m_pwndBtnYN, 0x00000001}, + {m_pwndBtnXN, 0x00000002}, + {m_pwndBtnXP, 0x00000004}, + {m_pwndBtnYP, 0x00000008}, + {m_pwndBtnZP, 0x00000010}, + {m_pwndBtnZN, 0x00000020}, + {m_pwndBtnCenter, 0x00000040}, + {m_pwndBtnWP, 0x00000080}, + {m_pwndBtnWN, 0x00000100}, + }; + + CManualTarget* _pManualTarget = GetManualTarget(); + if (!_pManualTarget) + { + return 0; + } + DWORD _ManualKeyState = _pManualTarget->GetManuKeyState(); + + // 如果不是方管,只能加载前面的,不能加载最后的2个W轴的按钮 ---- 吴畏 2016-12-27 + bool _bEnableW = IsEnableWUpDown(); + int _nBtnItems = _bEnableW ? _countof(_s_cManualBtnItems) : _countof(_s_cManualBtnItems) - 2; + for (int _i = 0; _i < _nBtnItems; _i++) + { + if (_ManualKeyState & _s_cManualBtnItems[_i].nMask) + { + _s_cManualBtnItems[_i].pBtnManual->SetCheck(TRUE); + } + else + _s_cManualBtnItems[_i].pBtnManual->SetCheck(FALSE); + } + + + // 真实前进后退状态和按钮F3、F4按下,只要一个状态为真即将按钮置亮 ---- DingQiang 2014-10-11 + static const struct GOBBtnItem + { + UINT nID; + DWORD nKeyboardMask; + DWORD nRunningStateMask; + } _s_cGOBBtnItems[] = + { + {CTRLID_BTN_GOBACKWARD, 0x00000001, 0x00000100}, + {CTRLID_BTN_GOFORWARD, 0x00000002, 0x00000080}, + }; + + CControlTarget* _pControlTarget = GetControlTarget(); + CStateManager* _pStateManager = GetStateManager(); + if (!_pControlTarget || !_pStateManager) + { + return 0; + } + + DWORD _GOBKeyState = _pControlTarget->GetGOBKeyState(); + DWORD _nRunningState = 0; + _pStateManager->GetRunningState(&_nRunningState); + + for (int _i = 0; _i < _countof(_s_cGOBBtnItems); _i++) + { + BOOL _bCheck = _nRunningState & _s_cGOBBtnItems[_i].nRunningStateMask; + _bCheck |= _GOBKeyState & _s_cGOBBtnItems[_i].nKeyboardMask; + + ((CButton*)GetDlgItem(_s_cGOBBtnItems[_i].nID))->SetCheck(_bCheck); + } + + // 更新加工选中图形。 ---- 黄海燕 2016-09-19 + CButton* _pBtnSelMach = (CButton*)GetDlgItem(CTRLID_BTN_MACHSELECTED); + if (_pBtnSelMach + && _pBtnSelMach->IsWindowVisible()) + { + // 同步菜单选择。 ---- 黄海燕 2016-09-18 + if (_pStateManager->IsSelectedMach() != (_pBtnSelMach->GetCheck() == BST_CHECKED)) + { + _pBtnSelMach->SetCheck(_pStateManager->IsSelectedMach() ? BST_CHECKED : BST_UNCHECKED); + } + } + + return 1; +} + +void CMachineControlDlg_Bottom::OnHScroll(UINT nSBCode_, UINT nPos_, CScrollBar* pScrollBar_) +{ + +} + +// 更新进给倍率的显示值 ---- DingQiang 2012-02-07 +void CMachineControlDlg_Bottom::UpdateF() +{ + _BuildFIVMap(); + + // 从ParamManager中读出进给倍率的当前值,如果读不到,则以设定倍率滑动条上的 + // 值为准。 ---- 杨开锦 2012-02-18 + ASSERT(m_pwndSliderSetF); + int _nIndex = m_pwndSliderSetF->GetPos(); + int _nFrp = 100; + _UpdateFValue(_nIndex, &_nFrp); + if (CParamManager* _pParamManager = GetParamManager()) + { + const CStringA _c_strFrpIdentifier = "SpeedGxx_Frp"; + ParameterValue _FrpParamValue; + if (_pParamManager->GetParameterValue(_c_strFrpIdentifier, &_FrpParamValue) + && _FrpParamValue.nType == ParameterValue::VT_INT) + { + _nFrp = _FrpParamValue.iValue; + _UpdateFIndex(&_nIndex, _nFrp); + } + } + + // 更新横向滑动条 + ASSERT(m_pwndSliderSetF); + int _nCurPos_SliderSetF = m_pwndSliderSetF->GetPos(); + int _nNewPos_SliderSetF = min(_nFrp, m_pwndSliderSetF->GetRangeMax()); + if (_nNewPos_SliderSetF != _nCurPos_SliderSetF) + { + m_pwndSliderSetF->SetPos(_nNewPos_SliderSetF); + m_pwndSliderSetF->Invalidate(); + } + + // 更新弧形旋钮显示 + ASSERT(m_pwndSliderF); + int _nCurPos_SliderF = m_pwndSliderF->GetPos(); + int _nNewPos_SliderF = _nIndex; + if (m_bShowCurValue) + { + double _nSpeed = 0.0; + if (const CSpeedometerTarget* _pST = GetSpeedometerTarget()) + { + // 直接拉计数器的XY速度来显示 ---- 杨开锦 2015-11-25 + _nSpeed = _pST->GetRealSpeedXY() * 60; + } + + CString _strValue; + _strValue.Format("%d", (int)_nSpeed); + CString _strOldInfo; + m_pwndStcSpeed->GetWindowText(_strOldInfo); + if (_strValue != _strOldInfo) + { + m_pwndSliderF->SetPos((_nSpeed / 10000) * 100); + m_pwndSliderF->SetSelection(m_pwndSliderF->GetRangeMin(), (_nSpeed / 10000) * 100); + } + } + else + { + if (_nNewPos_SliderF != _nCurPos_SliderF) + { + m_pwndSliderF->SetPos(_nNewPos_SliderF); + m_pwndSliderF->SetSelection(m_pwndSliderF->GetRangeMin(), _nNewPos_SliderF); + } + } +} + +void CMachineControlDlg_Bottom::UpdateP() +{ + CParamManager* _pParamManager = mach::GetParamManager(); + if (!_pParamManager) + { + return; + } + Parameter _DutyCycle; + if (!_pParamManager->GetParameter("PWM_DutyCycle", &_DutyCycle)) + { + return; + } + ASSERT(_DutyCycle.Value.nType == ParameterValue::VT_INT); + + // 定制功能,仅当激光端口打开时才显示功率值,否则为0 + bool _bPEnableWhenLightOn = NceGetPrivateProfileString(_T("ControlTarget"), _T("PEnableWhenLightOn")) == _T("1"); + if (_bPEnableWhenLightOn) + { + mach::CPortsManager* _pPortsManager = mach::GetPortsManager(); + mach::BitPort _BitPort; + _pPortsManager->GetBitPort("10018", &_BitPort); + if (!_BitPort.bValue) + { + _DutyCycle.Value.iValue = 0; + } + } + + Parameter _RatedPower; + if (!_pParamManager->GetParameter("GP_LaserRatedPower", &_RatedPower)) + { + return; + } + ASSERT(_RatedPower.Value.nType == ParameterValue::VT_INT); + + CString _strOldInfo; + m_pwndStcPower->GetWindowText(_strOldInfo); + + CString _strValue; + _strValue.Format("%d", _DutyCycle.Value.iValue * _RatedPower.Value.iValue / 100); + if (_strValue != _strOldInfo) + { + m_pwndStcPower->SetWindowText(_strValue); + } + + // 更新横向滑动条 + ASSERT(m_pwndSliderSetP); + int _nCurPos_SliderSetP = m_pwndSliderSetP->GetPos(); + int _nNewPos_SliderSetP = _DutyCycle.Value.iValue; + if (_nNewPos_SliderSetP != _nCurPos_SliderSetP) + { + m_pwndSliderSetP->SetPos(_nNewPos_SliderSetP); + m_pwndSliderSetP->Invalidate(); + } + + // 更新弧形旋钮显示 + ASSERT(m_pwndSliderP); + int _nCurPos_SliderP = m_pwndSliderP->GetPos(); + int _nNewPos_SliderP = _DutyCycle.Value.iValue; + if (_nNewPos_SliderP != _nCurPos_SliderP) + { + m_pwndSliderP->SetPos(_nNewPos_SliderP); + m_pwndSliderP->SetSelection(m_pwndSliderF->GetRangeMin(), _nNewPos_SliderP); + } +} + +void CMachineControlDlg_Bottom::_BuildFHIVMap() +{ + for (int _i = 0; _i <= 10; _i++) + { + m_nFHValues[_i] = _i * 0.02; + } + + for (int _i = 11; _i <= 20; _i++) + { + m_nFHValues[_i] = m_nFHValues[10] + (_i - 10) * 0.03; + } + + for (int _i = 21; _i <= 30; _i++) + { + m_nFHValues[_i] = m_nFHValues[20] + (_i - 20) * 0.03; + } + + for (int _i = 31; _i <= 40; _i++) + { + m_nFHValues[_i] = m_nFHValues[30] + (_i - 30) * 0.02; + } + + for (int _i = 41; _i <= 50; _i++) + { + m_nFHValues[_i] = m_nFHValues[40] + (_i - 40) * 0.1; + } + + for (int _i = 51; _i <= 60; _i++) + { + m_nFHValues[_i] = m_nFHValues[50] + (_i - 50) * 0.3; + } + + for (int _i = 61; _i <= 70; _i++) + { + m_nFHValues[_i] = m_nFHValues[60] + (_i - 60) * 0.5; + } + + for (int _i = 71; _i <= 80; _i++) + { + m_nFHValues[_i] = m_nFHValues[70] + (_i - 70) * 0.5; + } +} + +void CMachineControlDlg_Bottom::_UpdateFHValue(int nIndex_, double* pnVaue_) +{ + ASSERT(nIndex_ >= 0 && nIndex_ <= 80); + *pnVaue_ = m_nFHValues[nIndex_]; + return; +} + +void CMachineControlDlg_Bottom::_UpdateFHindex(int* pnIndex_, double nValue_) +{ + ASSERT(nValue_ >= 0); + for (int i = 0; i < _countof(m_nFHValues); i++) + { + if (DOUBLE_EQU(nValue_, m_nFHValues[i])) + { + *pnIndex_ = i; + return; + } + + if (nValue_ < m_nFHValues[i]) + { + ASSERT(i > 0); + *pnIndex_ = i - 1; + return; + } + } +} + +void CMachineControlDlg_Bottom::UpdateFH() +{ + CParamManager* _pParamManager = mach::GetParamManager(); + if (!_pParamManager) + { + return; + } + Parameter _FollowHeight; + if (!_pParamManager->GetParameter("GP_FollowHeight", &_FollowHeight)) + { + return; + } + + CString _strOldInfo; + m_pwndStcFollowHeight->GetWindowText(_strOldInfo); + + CString _strValue; + _strValue.Format("%.2f", _FollowHeight.Value.dValue); + if (_strValue != _strOldInfo) + { + m_pwndStcFollowHeight->SetWindowText(_strValue); + } + + double _nFollowHeigth = (min(_FollowHeight.Value.dValue, m_nArcSliderFHMax)); + + int _nIndex; + _UpdateFHindex(&_nIndex, _nFollowHeigth); + + // 更新横向滑动条 + ASSERT(m_pwndSliderSetFH); + int _nCurPos_SliderSetFH = m_pwndSliderSetFH->GetPos(); + int _nNewPos_SliderSetFH = _nIndex; + if (_nNewPos_SliderSetFH != _nCurPos_SliderSetFH) + { + m_pwndSliderSetFH->SetPos(_nNewPos_SliderSetFH); + m_pwndSliderSetFH->Invalidate(); + } + + // 更新弧形旋钮显示 + ASSERT(m_pwndSliderFH); + int _nCurPos_SliderFH = m_pwndSliderFH->GetPos(); + int _nNewPos_SliderFH = _nIndex; + if (_nNewPos_SliderFH != _nCurPos_SliderFH) + { + m_pwndSliderFH->SetPos(_nNewPos_SliderFH); + m_pwndSliderFH->SetSelection(m_pwndSliderF->GetRangeMin(), _nNewPos_SliderFH); + } +} + +void CMachineControlDlg_Bottom::UpdateManuCenter() +{ + ASSERT(m_pwndBtnCenter); + + // 当前显示的串 ---- 杨开锦 2012-02-21 + CString _strOldText; + m_pwndBtnCenter->GetWindowText(_strOldText); + + // 需要显示的串 ---- 杨开锦 2012-02-21 + CString _strNewText; + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + if (_pManualTarget->IsJogMode() && _pManualTarget->GetJogState()) + { + _strNewText = _GETCS(s_csRapidJog); + } + else if (_pManualTarget->IsJogMode() && !_pManualTarget->GetJogState()) + { + _strNewText = _GETCS(s_csSlowJog); + } + else + { + double _nIncDistance = _pManualTarget->GetIncDistance(); + + if (_nIncDistance >= 1000) + { + _strNewText.Format(_T("%.2f"), _nIncDistance); + } + else if (_nIncDistance >= 100) + { + _strNewText.Format(_T("%.3f"), _nIncDistance); + } + else if (_nIncDistance >= 10) + { + _strNewText.Format(_T("%.4f"), _nIncDistance); + } + else if (_nIncDistance >= 0) + { + _strNewText.Format(_T("%.5f"), _nIncDistance); + } + _strNewText.TrimRight(_T('0')); + _strNewText.TrimRight(_T('.')); + _strNewText += "\nmm"; + } + + // 更新 ---- 杨开锦 2012-02-21 + if (_strNewText != _strOldText) + { + m_pwndBtnCenter->SetWindowText(_strNewText); + } +} + +void CMachineControlDlg_Bottom::UpdateGFOBInfo() +{ + // 点动时显示“点动”,否则显示指定的距离 ---- 杨开锦 2012-03-10 + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + CString _strGFOBDistance; + if (_pControlTarget->GetGFOBMode() == 0x01) + { + double _nGFOBDistance = _pControlTarget->GetGFOBDistance(); + ASSERT(_nGFOBDistance >= 0); + _strGFOBDistance.Format(_T("%f"), _nGFOBDistance); + _strGFOBDistance.TrimRight(_T('0')); + _strGFOBDistance.TrimRight(_T('.')); + _strGFOBDistance.AppendFormat("mm"); + } + else + { + ASSERT(_pControlTarget->GetGFOBMode() == 0x00); + _strGFOBDistance.Format("%s", _GETCS(s_csJOG)); + } + + // 惰性更新 ---- 杨开锦 2012-03-10 + CString _strOldInfo; + m_pwndStcGoDistance->GetWindowText(_strOldInfo); + if (_strGFOBDistance != _strOldInfo) + { + m_pwndStcGoDistance->SetWindowText(_strGFOBDistance); + } +} + +void CMachineControlDlg_Bottom::UpdateSpeed() +{ + double _nSpeed = 0.0; + if (const CSpeedometerTarget* _pST = GetSpeedometerTarget()) + { + // 直接拉计数器的XY速度来显示 ---- 杨开锦 2015-11-25 + _nSpeed = _pST->GetRealSpeedXY() * 60; + } + + CString _strValue; + _strValue.Format("%d", (int)_nSpeed); + CString _strOldInfo; + m_pwndStcSpeed->GetWindowText(_strOldInfo); + if (_strValue != _strOldInfo) + { + m_pwndStcSpeed->SetWindowText(_strValue); + } +} + +void CMachineControlDlg_Bottom::UpdateEnableJogLaser() +{ + CButton* _pwndCheckJogLaser = (CButton*)GetDlgItem(CTRLID_BTN_JOGLASER); + if (!_pwndCheckJogLaser) + { + return; + } + + bool _bEnable = false; + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("EnableJogLaser", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_BOOL) + { + _bEnable = _ParamValue.bValue; + } + else + { + return; + } + + bool _bBtnChecked = _pwndCheckJogLaser->GetCheck() == BST_CHECKED ? true : false; + if (_bEnable != _bBtnChecked) + { + _pwndCheckJogLaser->SetCheck(_bEnable ? BST_CHECKED : BST_UNCHECKED); + } +} + +void CMachineControlDlg_Bottom::UpdateEnableBoardSupport() +{ + // 板顶料 + bool _bBoardSupport = NceGetPrivateProfileString(_T("ControlTarget"), _T("BoardSupport")) == _T("1"); + if (_bBoardSupport) + { + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + CStateManager::State _nState = CStateManager::Idle; + BOOL _bEnable = _pStateManager->GetState(&_nState) && _nState == CStateManager::Idle; + if (m_pwndPortButtons[8]->GetCheck() && _nState == CStateManager::Lock) + { + return; + } + else + { + m_pwndPortButtons[8]->EnableWindow(_bEnable); + } + } +} + +// 倍率条为120格,映射到0-最大进给倍率,其中100以下为直接对应,100以下可以非线性 +// [0,100] => [0,100] +// [100,120] => [100,MaxFrp] +// 这里假设了 MaxFrp >= 100 +// 对于100以下的部分没什么好说的,此处主要说明100以上的部分如何映射: +// 1) 如果MaxFrp=120,则这部分跟100以下一样,也是线性 +// Value = Index +// 2) 如果MaxFrp<120,则这部分仍以线性方式增长到最大值MaxFrp,到最大值后不增长 +// Value = Index (when Index <= MaxFrp) +// = MaxFrp (when Index >= MaxFrp) +// 3) 如果MaxFrp>120,则这部分以线性叠加指数增长来映射 +// Value = Index * a^(Index - 100) +// 其中 a可由MaxFrp算出,例如 +// MaxFrp = 150 => 150 = 120 * a^(120-100) => a = (1.25)^(0.05) +// ---- 杨开锦 2013-03-26 +void CMachineControlDlg_Bottom::_BuildFIVMap() +{ + int _nMaxFrp = m_nFValues[120]; + if (CParamManager* _pParamManager = GetParamManager()) + { + const CStringA _c_strMaxFrpIdentifier = "MaxFrp"; + ParameterValue _MaxFrpParamValue; + if (!_pParamManager->GetParameterValue(_c_strMaxFrpIdentifier, &_MaxFrpParamValue) + || _MaxFrpParamValue.nType != ParameterValue::VT_INT + || _MaxFrpParamValue.iValue == _nMaxFrp) + { + // 变化才更新 + return; + } + _nMaxFrp = _MaxFrpParamValue.iValue; + } + + C_ASSERT(_countof(m_nFValues) == 121); + if (_nMaxFrp <= 120) + { + for (int _i = 0; _i < _countof(m_nFValues); _i++) + { + m_nFValues[_i] = min(_i, _nMaxFrp); + } + return; + } + + C_ASSERT(_countof(m_nFValues) == 121); + for (int _i = 0; _i <= 100; _i++) + { + m_nFValues[_i] = _i; + } + double _nA = pow(_nMaxFrp / 120.0, 0.05); + for (int _i = 101; _i < _countof(m_nFValues); _i++) + { + int _nV = (int)(_i * pow(_nA, _i - 100.0) + 0.5); + m_nFValues[_i] = min(_nV, _nMaxFrp); + } +} + +void CMachineControlDlg_Bottom::_UpdateFValue(int nIndex_, int* pnValue_) +{ + ASSERT(nIndex_ >= 0 && nIndex_ < _countof(m_nFValues) && pnValue_); + *pnValue_ = m_nFValues[nIndex_]; +} + +void CMachineControlDlg_Bottom::_UpdateFIndex(int* pnIndex_, int nValue_) +{ + ASSERT(pnIndex_ && *pnIndex_ >= 0 && *pnIndex_ < _countof(m_nFValues)); + if (nValue_ == m_nFValues[*pnIndex_]) + { + return; + } + + int _i = 0; + while (_i < _countof(m_nFValues) && m_nFValues[_i] < nValue_) + { + _i++; + } + *pnIndex_ = _i; +} + +LRESULT CMachineControlDlg_Bottom::OnEndSpeedDlg(WPARAM wParam_, LPARAM lParam_) +{ + m_pSetSpeedDlg->ShowWindow(SW_HIDE); + DWORD _nManuMode = (DWORD)wParam_; + union + { + LPARAM lValue; + float fValue; + } Value; + Value.lValue = lParam_; + double _nValue = (float)Value.fValue; + + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + + // 设置手动低速 ---- 郭小航 2013-11-07 + if (_nManuMode == 0) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(false); + + CParamManager* _pParamManager = GetParamManager(); + if (_pParamManager) + { + ParameterValue _ParamValue; + _pParamManager->GetParameterValue("1_0_JVelocityQuick", &_ParamValue); + if (_nValue > _ParamValue.dValue) + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocityQuick", &_ParamValue); + _pParamManager->SetParameterValue("1_0_JVelocity", &_ParamValue); + } + else + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocity", &_ParamValue); + } + } + } + // 设置手动高速 ---- 郭小航 2013-11-07 + else if (_nManuMode == 1) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(true); + + CParamManager* _pParamManager = GetParamManager(); + if (_pParamManager) + { + ParameterValue _ParamValue; + _pParamManager->GetParameterValue("1_0_JVelocity", &_ParamValue); + if (_nValue < _ParamValue.dValue) + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocity", &_ParamValue); + _pParamManager->SetParameterValue("1_0_JVelocityQuick", &_ParamValue); + } + else + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocityQuick", &_ParamValue); + } + } + } + // 设置步长 ---- 郭小航 2013-11-07 + else if (_nManuMode == 2) + { + _pManualTarget->SetManuMode(1); + _pManualTarget->SetIncDistance(_nValue); + } + + return TRUE; +} + +LRESULT CMachineControlDlg_Bottom::OnEndEditDistance(WPARAM wParam_, LPARAM lParam_) +{ + ASSERT(lParam_); + CString* _strText = reinterpret_cast(lParam_); + CString _strGetValue = *_strText; + m_pwndStcGoDistance->ShowWindow(SW_SHOW); + if (IsValidDate(_strGetValue, "double", 100000, 0., "mm")) + { + double _nGetValue = _tstof(_strGetValue); + _nGetValue = _FormatInputData(_nGetValue); + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + _pControlTarget->SetGFOBDistance(_nGetValue); + } + + return TRUE; +} + +void CMachineControlDlg_Bottom::OnLButtonDown(UINT nFlags_, CPoint point_) +{ + if (::IsWindow(m_pDistanceEdit->GetSafeHwnd())) + { + delete m_pDistanceEdit; + m_pDistanceEdit = NULL; + } + else + m_pDistanceEdit = NULL; +} + +// 响应鼠标单击前进后退显示按钮消息。以100/1200处为界,点击前部份:如果是步进模 +// 式则弹出编辑框可编辑前进后退距离,如果是点动模式则不响应。点击后部份:切换前 +// 进后退模式。返回True则表示不再进行消息循环 ---- DingQiang 2012-07-19 +BOOL CMachineControlDlg_Bottom::OnDistanceLButtonDown(CPoint point_) +{ + CControlTarget* _pControlTarget = GetControlTarget(); + if (!_pControlTarget) + { + return FALSE; + } + + CRect _rcGoDistance; + m_pwndStcGoDistance->GetWindowRect(_rcGoDistance); + double _nWide = _rcGoDistance.Width() * 0.83; + double _nDivide = _rcGoDistance.left + _nWide; + + if (point_.x < _nDivide) + { + if (_pControlTarget->GetGFOBMode() == 0x00) + { + return TRUE; + } + + if (::IsWindow(m_pDistanceEdit->GetSafeHwnd())) + { + // 这样做的目的是防止编辑框已经Create出的时候,又点击到按钮又Create一次 ---- DingQiang 2012-07-20 + return FALSE; + } + + CString _strItemText; + m_pwndStcGoDistance->GetWindowText(_strItemText); + CRect _rect(0, 0, 0, 0); + m_pwndStcGoDistance->GetWindowRect(_rect); + + // new一个编辑框出来,其父窗口为前进后退距离显示框 ---- DingQiang 2012-07-19 + m_pwndStcGoDistance->ScreenToClient(&_rect); + _rect.top += 7; + _rect.bottom -= 6; + _rect.left += 20; + _rect.right -= 20; + DWORD _dwStyle; + _dwStyle = WS_CHILDWINDOW | WS_VISIBLE | WS_BORDER | ES_CENTER | ES_AUTOVSCROLL | ES_NOHIDESEL; + m_pDistanceEdit = new CEditItem(this, _strItemText); + m_pDistanceEdit->Create(_dwStyle, _rect, m_pwndStcGoDistance, CTRLID_EDIT_GODISTANCE); + return TRUE; + } + else + { + DWORD _nSetMode; + if (_pControlTarget->GetGFOBMode() == 0x00) + { + _nSetMode = 0x01; + } + else + _nSetMode = 0x00; + + _pControlTarget->SetGFOBMode(_nSetMode); + return FALSE; + } + + return FALSE; +} + +// 检查数据是否是合法的输入,允许输入正数、小数、单位。不允许负数和字母---- DingQiang 2012-03-07 +bool CMachineControlDlg_Bottom::IsValidDate(LPCSTR szInPut_, // 输入字符串 + LPCSTR szType_, // 数据类型 + double nMax_, // 允许的最大值 + double nMin_, // 允许的最小值 + LPCSTR szUnit_) // 允许输入单位 +{ + int _nNumDots = 0; // 小数点个数,只允许一个 + CString _strInPut = szInPut_; + CString _strUint = szUnit_; + int _nLength = (int)strlen(_strInPut); // 输入入字符串长度 + int _nUnitLength = (int)strlen(_strUint); // 允许使用的单位字符串长度 + bool b_ContainUnit = false; // 是否包含单位 + + if (0 == _nLength) + { + return false; + } + + // 多于两个小数点则返回false---- DingQiang 2012-03-07 + int _nDotCount = 0; + for (int _i = 0; _i < _nLength; _i++) + { + char _szDot = _strInPut[_i]; + if (_szDot == '.') + { + _nDotCount++; + } + } + + if (_nDotCount > 1) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + + // 先检查字符串后面的_nUnitLength长度是否是数字,如果有一个不是数字则立马判 + // 断后面_nUnitLength个字符是否是单位字符,如果即不是数字也不是单位字符则直 + // 接返回错误信息,不再做其它检查。 ---- DingQiang 2012-03-07 + int _nCheckUint = (_nLength - _nUnitLength) > 0 ? _nLength - _nUnitLength : _nLength; + for (int _j = _nCheckUint; _j < _nLength; _j++) + { + char _szChar = _strInPut[_j]; + if(_szChar < 0 || _szChar > 255) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + if (!isdigit(_szChar)) + { + if (_szChar != '.') + { + if (_strUint.Compare(_strInPut.Right(_nUnitLength)) != 0) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + else + { + b_ContainUnit = true; + } + } + } + } + + // 如果有符号则检查除符号外的字符,如没有符号则全部检查---- DingQiang 2012-03-08 + int _nCheckNum = b_ContainUnit ? _nCheckUint : _nLength; + int _i = 0; + for (; _i < _nCheckNum; _i++) + { + char _c = _strInPut[_i]; + if (!isdigit(_c)) + { + if (0 == strcmp(szType_, "int")) + { + break; + } + else if (0 == strcmp(szType_, "double") || 0 == strcmp(szType_, "float")) + { + if (_c == '.' && _nNumDots == 0) + { + _nNumDots++; + } + else + { + break; + } + } + else + ASSERT(false); + } + } + + if (_i != _nCheckNum && (strcmp(szType_, "int") == 0)) + { + AfxMessageBox(_GETCS(s_csIntDataError)); + return false; + } + + if (_i != _nCheckNum && (strcmp(szType_, "float") == 0 || strcmp(szType_, "double") == 0)) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + + double _nInPut = (double)_tstof(szInPut_); + if ( _nInPut > nMin_ && _nInPut < nMax_) + { + return true; + } + else + { + CString _strErrorShow; + _strErrorShow.Format(_GETCS(s_csFloatDataBoundError), nMin_, nMax_); + AfxMessageBox(_strErrorShow); + return false; + } +} + +void CMachineControlDlg_Bottom::OnChangeCoorMode() +{ + m_nCoorMode = (m_nCoorMode == 0x00) ? 0x01 : 0x00; + UpdateMachCoor(); +} + +// 格式化输入 ---- DingQiang 2012-06-25 +static double _FormatInputData(double nInputData_) +{ + ASSERT(nInputData_ >= 0); + CString _strTemp; + _strTemp.Format(_T("%f"), nInputData_); + + CString _strOut = _strTemp.Left(6); + + return _tstof(_strOut); +} + +// 设置手动速度 ---- 郭小航 2013-11-07 +void CMachineControlDlg_Bottom::OnDblClickCenter() +{ + CStateManager* _pStateManager = GetStateManager(); + if (!_pStateManager) + return; + + CStateManager::State _State = mach::CStateManager::Invalid; + if (!_pStateManager->GetState(&_State)) + { + return; + } + + if (_State != mach::CStateManager::Invalid + && _State != mach::CStateManager::Idle + //&& _State != mach::CStateManager::Lock // 仿真时也不能修改速度。 + && _State != mach::CStateManager::Estop) + { + AfxMessageBox(_GETCS(s_csNotInputPrompt)); + return; + } + + ASSERT(m_pwndBtnCenter && ::IsWindow(m_pwndBtnCenter->m_hWnd)); + CRect _rcBtnCenter; + m_pwndBtnCenter->GetWindowRect(&_rcBtnCenter); + ((CSetSpeedDlg*)m_pSetSpeedDlg)->SetBasePosition(_rcBtnCenter.TopLeft()); + m_pSetSpeedDlg->ShowWindow(SW_SHOW); +} + +LRESULT CMachineControlDlg_Bottom::OnSliderMoving(WPARAM wParam_, LPARAM lParam_) +{ + CParamManager* _pParamManager = mach::GetParamManager(); + if (!_pParamManager) + { + ASSERT(FALSE); + return 0; + } + + UINT _nCtrlID = (UINT)wParam_; + int _nIndex = (int)lParam_; + if (wParam_ == CTRLID_SLD_SETF) + { + int _nFrp = 100; + _UpdateFValue(_nIndex, &_nFrp); + + // 为安全计,通过CParamManager修改参数都会全部检查所有参数,在此处可能并 + // 非必须的,且全部检查会让进给倍率条显得卡起来,有拖尾。 因此,此处我们 + // 通过造一个Command来绕过全部检查。 ---- 杨开锦 2012-08-17 + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetFrpCommand = "SetFrp"; + CStringA _strFrp; + _strFrp.Format("%d", _nFrp); + _pCommandManager->Execute(_c_strSetFrpCommand, _strFrp, "LPCSTR"); + } + if (m_bSliderCtrlG00) + { + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetG00FrpCommand = "SetG00Frp"; + CStringA _strFrp; + _strFrp.Format("%d", _nFrp); + _pCommandManager->Execute(_c_strSetG00FrpCommand, _strFrp, "LPCSTR"); + } + } + + UpdateF(); + } + + if (wParam_ == CTRLID_SLD_SETFH) + { + double _nValue; + _UpdateFHValue(_nIndex, &_nValue); + ParameterValue _Value; + memset(&_Value, 0, sizeof(ParameterValue)); + _pParamManager->GetParameterValue("ActualSampleLength", &_Value); + if (_Value.nType != ParameterValue::VT_DOUBLE) + { + return 0; + } + _nValue = min(_nValue, _Value.dValue); + + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetFHCommand = "SetFollowHeight"; + CStringA _strFH; + _strFH.Format("%.3f", _nValue); + _pCommandManager->Execute(_c_strSetFHCommand, _strFH, "LPCSTR"); + } + UpdateFH(); + } + + if (wParam_ == CTRLID_SLD_SETP) + { + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetPowerCommand = "SetDutyCycles"; + CStringA _strPower; + _strPower.Format("%d", _nIndex); + _pCommandManager->Execute(_c_strSetPowerCommand, _strPower, "LPCSTR"); + } + UpdateP(); + } + return 1; +} + +void CMachineControlDlg_Bottom::OnClickMachSelected() +{ + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + CStateManager::State _nState = CStateManager::Idle; + BOOL _bEnable = _pStateManager->GetState(&_nState) && _nState == CStateManager::Idle; + if (!_bEnable) + return; + + CButton* _pBtn = (CButton*)GetDlgItem(CTRLID_BTN_MACHSELECTED); + BOOL _bMachSelected = _pBtn->GetCheck() == BST_CHECKED; + _bMachSelected = !_bMachSelected; + m_bSelectMach = _bMachSelected; + _pStateManager->SetSelectedMach(m_bSelectMach); + _pBtn->SetCheck(_bMachSelected ? BST_CHECKED : BST_UNCHECKED); +} + +void CMachineControlDlg_Bottom::OnClickJogLaser() +{ + bool _bValue = false; + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("EnableJogLaser", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_BOOL) + { + _bValue = _ParamValue.bValue; + } + else + { + ASSERT(FALSE); + return; + } + + _ParamValue.bValue = !_bValue; + _pParamManager->SetParameterValue("EnableJogLaser", &_ParamValue); + UpdateEnableJogLaser(); +} + +void CMachineControlDlg_Bottom::OnSelMarkPoint() +{ + // 加载标记点选项菜单 ---- 边俊霞 2017-05-11 + CRect _rcRect; + GetDlgItem(CTRLID_BTN_SELMARKPOINT)->GetWindowRect(&_rcRect); + m_pMenu->TrackPopupMenu(TPM_LEFTBUTTON, _rcRect.right, _rcRect.bottom, this); +} + +void CMachineControlDlg_Bottom::OnMarkPointChange(UINT ID_) +{ + // 在标记点按钮上显示当前选择的标记点index ---- 边俊霞 2017-03-14 + UINT _nCurIndex = ID_ - CTRLID_BTN_MARKPOINT1 + 1; + m_nCurIndex = _nCurIndex; + CString _strCurIndex; + _strCurIndex.Format("%u", _nCurIndex); + + // 使数字在button上不居中显示 ---- 边俊霞 2017-03-15 + CString _strShowIndex = _strCurIndex + '\n'; + SetDlgItemText(CTRLID_BTN_SELMARKPOINT, _strShowIndex); + + // 将当前选择的标记点index传到MarkPointTarget ---- 边俊霞 2017-03-14 + CMarkPointTarget* _pMarkPointTarget = GetMarkPointTarget(); + ASSERT(_pMarkPointTarget); + _pMarkPointTarget->SetCurMarkIndex(_nCurIndex - 1); +} + +void CMachineControlDlg_Bottom::OnClickAutoCyc() +{ + bool _bEnableCyc = false; + + CCycMachiningTarget* _pCycMachingTarget = GetCycMachiningTarget(); + BOOL _bCycEnable= _pCycMachingTarget->GetEnable(); + if(_bCycEnable == TRUE) + { + _bEnableCyc = true; + _pCycMachingTarget->SetEnable(FALSE); + } + else + { + _bEnableCyc = false; + _pCycMachingTarget->SetEnable(TRUE); + } + UpdateEnableAutoCyc(); +} + +void CMachineControlDlg_Bottom::UpdateEnableAutoCyc() +{ + CButton* _pwndCheckAutoCyc = (CButton*)GetDlgItem(CTRLID_BTN_AUTOCYC); + if (!_pwndCheckAutoCyc) + { + return; + } + + bool _bEnableAutoCyc = false; + CCycMachiningTarget* _pCycMachingTarget = GetCycMachiningTarget(); + BOOL _bCycEnable= _pCycMachingTarget->GetEnable(); + if(_bCycEnable == TRUE) + { + _bEnableAutoCyc = true; + } + else + { + _bEnableAutoCyc = false; + } + + bool _bBtnChecked = _pwndCheckAutoCyc->GetCheck() == BST_CHECKED ? true : false; + if (_bEnableAutoCyc != _bBtnChecked) + { + _pwndCheckAutoCyc->SetCheck(_bEnableAutoCyc ? BST_CHECKED : BST_UNCHECKED); + } +} + +//【循环加工】 李振宇 2017-06-22 +void CMachineControlDlg_Bottom::OnClickCyc() +{ + bool _bEnableCyc = false; + + CCycMachiningTarget* _pCycMachingTarget = GetCycMachiningTarget(); + BOOL _bCycEnable= _pCycMachingTarget->GetEnable(); + if(_bCycEnable == TRUE) + { + _bEnableCyc = true; + _pCycMachingTarget->SetEnable(FALSE); + } + else + { + _bEnableCyc = false; + _pCycMachingTarget->SetEnable(TRUE); + } + + UpdateEnableCyc(); +} + +void CMachineControlDlg_Bottom::UpdateEnableCyc() +{ + CButton* _pwndCheckAutoCyc = (CButton*)GetDlgItem(CTRLID_BTN_CYC); + if (!_pwndCheckAutoCyc) + { + return; + } + bool _bEnableAutoCyc = false; + + CCycMachiningTarget* _pCycMachingTarget = GetCycMachiningTarget(); + BOOL _bCycEnable= _pCycMachingTarget->GetEnable(); + if(_bCycEnable == TRUE) + { + _bEnableAutoCyc = true; + } + else + { + _bEnableAutoCyc = false; + } + + bool _bBtnChecked = _pwndCheckAutoCyc->GetCheck() == BST_CHECKED ? true : false; + if (_bEnableAutoCyc != _bBtnChecked) + { + _pwndCheckAutoCyc->SetCheck(_bEnableAutoCyc ? BST_CHECKED : BST_UNCHECKED); + } +} + +//【自动交换】 李振宇 2017-06-22 +void CMachineControlDlg_Bottom::OnClickAutoExchange() +{ + bool _bEnableExchange = false; + + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("AutoExchangeTaskEnd", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_INT) + { + if(_ParamValue.iValue == 1) + { + _bEnableExchange = true; + } + else + { + ASSERT(_ParamValue.iValue == 0); + _bEnableExchange = false; + } + } + else + { + return; + } + + // 直接对系统参数取反 + if(_bEnableExchange) + { + memset(&_ParamValue, 0, sizeof(ParameterValue)); + _ParamValue.nType = ParameterValue::VT_INT; + _ParamValue.iValue = 0; + _pParamManager->SetParameterValue("AutoExchangeTaskEnd", &_ParamValue); + } + else + { + memset(&_ParamValue, 0, sizeof(ParameterValue)); + _ParamValue.nType = ParameterValue::VT_INT; + _ParamValue.iValue = 1; + _pParamManager->SetParameterValue("AutoExchangeTaskEnd", &_ParamValue); + } + + UpdateEnableAutoExchange(); + SendTargetMessage(ID_TARGET_EXCHANGEWORKBENCH, TM_AUTOCYC_CHECK, 0, 0); +} + +void CMachineControlDlg_Bottom::UpdateEnableAutoExchange() +{ + CButton* _pwndCheckAutoExchange = (CButton*)GetDlgItem(CTRLID_BTN_AUTOEXCHANGE); + if (!_pwndCheckAutoExchange) + { + return; + } + bool _bEnableAutoExchange = false; + + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("AutoExchangeTaskEnd", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_INT) + { + if(_ParamValue.iValue == 1) + { + _bEnableAutoExchange = true; + } + else + { + ASSERT(_ParamValue.iValue == 0); + _bEnableAutoExchange = false; + } + } + else + { + return; + } + + bool _bBtnChecked = _pwndCheckAutoExchange->GetCheck() == BST_CHECKED ? true : false; + if (_bEnableAutoExchange != _bBtnChecked) + { + _pwndCheckAutoExchange->SetCheck(_bEnableAutoExchange ? BST_CHECKED : BST_UNCHECKED); + } +} diff --git a/src/MachineControlDlg_Left.cpp b/src/MachineControlDlg_Left.cpp new file mode 100644 index 0000000..5594ac0 --- /dev/null +++ b/src/MachineControlDlg_Left.cpp @@ -0,0 +1,2436 @@ +// ************************************************************************** // +// MachineControlDlg.cpp : implementation of the CMachineControlDlg_Left class +// Copyright(c)2011 Naiky Company. All rights reserved. +// +// Abstract: +// 本文件实现CMachineControlDlg_Left类。 +// ********************************************* ---- 杨开锦 2011-10-31 ***** // +#include "stdafx.h" +#include "MachineControlDlg_Left.h" +#include "EditItem.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW +#endif + +CS_T s_csRapidJog = _DEFCS(_CSV(18552), + _CHINESE("高速") + _ENGLISH("Rapid\nJog")); +CS_T s_csSlowJog = _DEFCS(_CSV(18553), + _CHINESE("连续") + _ENGLISH("Jog")); +CS_T s_csJOG = _DEFCS(_CSV(18554), + _CHINESE("点动") + _ENGLISH("Jog")); +CS_T s_csLANGUAGE = _DEFCS(_CSV(18555), + _CHINESE("CHN") + _ENGLISH("ENG")); +CS_T s_csNotInputPrompt = _DEFCS(_CSV(18556), + _CHINESE("系统忙,当前加工状态无法修改该参数!") + _ENGLISH("System is busy, can not change the parameters!")); +CS_T s_csIntDataError = _DEFCS(_CSV(18557), + _CHINESE("输入的参数无效,只能输入正整数,请重新输入!") + _ENGLISH("Data error, it should be a positive integer, Please enter again!")); +CS_T s_csFloatDataError = _DEFCS(_CSV(18558), + _CHINESE("输入的参数无效,请重新输入!") + _ENGLISH("Data error, it should be a number, Please enter again!")); +CS_T s_csFloatDataBoundError = _DEFCS(_CSV(18559), + _CHINESE("参数范围错误,请输入一个“%.1f~%.1f”之间的数!") + _ENGLISH("Please enter a number between %f~%f")); + +CS_T s_csAXES = _DEFCS(_CSV(18560), + _CHINESE("轴") + _ENGLISH("Axes")); +CS_T s_csMACHINECOORDINATE = _DEFCS(_CSV(18561), + _CHINESE("机械坐标") + _ENGLISH("MachCoor")); +CS_T s_csWORKPIECECOORDINATE = _DEFCS(_CSV(18562), + _CHINESE("工件坐标") + _ENGLISH("WorkCoor")); + +CS_T s_csRESUME = _DEFCS(_CSV(18563), + _CHINESE("断点\n继续") + _ENGLISH("Resume")); +CS_T s_csSIMU = _DEFCS(_CSV(18564), + _CHINESE("仿真") + _ENGLISH("Simu")); +CS_T s_csDIRRUN = _DEFCS(_CSV(18565), + _CHINESE("空运行") + _ENGLISH("DryRun")); +CS_T s_csSIMUCUTBOUNDRECT = _DEFCS(_CSV(18566), + _CHINESE("走边框") + _ENGLISH("Frame")); +CS_T s_csTipSETWORKORG = _DEFCS(_CSV(18567), + _CHINESE("设置工件原点") + _ENGLISH("Set WorkOrg")); +CS_T s_csTipMOVETOWORKORIGIN = _DEFCS(_CSV(18568), + _CHINESE("回工件原点") + _ENGLISH("Work Origin")); +CS_T s_csTipSIMUCUTBOUNDRECT = _DEFCS(_CSV(18569), + _CHINESE("走边框") + _ENGLISH("Frame")); +CS_T s_csTipSTART = _DEFCS(_CSV(18570), + _CHINESE("开始") + _ENGLISH("Start")); +CS_T s_csTipPAUSE = _DEFCS(_CSV(18571), + _CHINESE("暂停") + _ENGLISH("Pause")); +CS_T s_csTipSTOP = _DEFCS(_CSV(18572), + _CHINESE("停止") + _ENGLISH("Stop")); +CS_T s_csTipGoBackward = _DEFCS(_CSV(18573), + _CHINESE("后退") + _ENGLISH("GoBackward")); +CS_T s_csTipGoForward = _DEFCS(_CSV(18574), + _CHINESE("前进") + _ENGLISH("GoForward")); +CS_T s_csTipFollowSample = _DEFCS(_CSV(18575), + _CHINESE("标定") + _ENGLISH("Sample")); +CS_T s_csTipBackAll = _DEFCS(_CSV(18576), + _CHINESE("全部回机械原点") + _ENGLISH("BackAll")); +CS_T s_csDistanceSet = _DEFCS(_CSV(18577), + _CHINESE("前进后退距离设定") + _ENGLISH("Distance Set")); +CS_T s_szPortNameKey = _DEFCS(_CSV(18578), + _CHINESE("Port%d_ChnName") + _ENGLISH("Port%d_EngName")); +CS_T s_szLaserOnWhenJog = _DEFCS(_CSV(18067), + _CHINESE("点动时出激光:") + _ENGLISH("Laser ON at Jog:")); +CS_T s_csSELECTMACH = _DEFCS(_CSV(18620), + _CHINESE("加工选中图形:") + _ENGLISH("Machine Selected:")); + +CS_T s_szMUNU_MARKPOINT1 = _DEFCS(_CSV(18640), + _CHINESE("标记点1") + _ENGLISH("Mark point1")); +CS_T s_szMUNU_MARKPOINT2 = _DEFCS(_CSV(18641), + _CHINESE("标记点2") + _ENGLISH("Mark point2")); +CS_T s_szMUNU_MARKPOINT3 = _DEFCS(_CSV(18642), + _CHINESE("标记点3") + _ENGLISH("Mark point3")); +CS_T s_szMUNU_MARKPOINT4 = _DEFCS(_CSV(18643), + _CHINESE("标记点4") + _ENGLISH("Mark point4")); +CS_T s_szMUNU_MARKPOINT5 = _DEFCS(_CSV(18644), + _CHINESE("标记点5") + _ENGLISH("Mark point5")); +CS_T s_szMUNU_MARKPOINT6 = _DEFCS(_CSV(18645), + _CHINESE("标记点6") + _ENGLISH("Mark point6")); +CS_T s_szMUNU_MARKPOINT7 = _DEFCS(_CSV(18646), + _CHINESE("标记点7") + _ENGLISH("Mark point7")); +CS_T s_szMUNU_MARKPOINT8 = _DEFCS(_CSV(18647), + _CHINESE("标记点8") + _ENGLISH("Mark point8")); + +using namespace mach; +using namespace ncmath; + +struct CRunReportTarget::CCache +{ + mach::CStateManager::State State; + mach::CStateManager::Speed Speed; + mach::CStateManager::FileInformation FileInfo; + mach::CStateManager::CLInformation CLInfo; +}; +//////////////////////////////////////////////////////////////////////////////// +// CtrlID +enum +{ + CTRLID_BTN_F = psh1, + CTRLID_BTN_CENTER, + CTRLID_BTN_XP, + CTRLID_BTN_XN, + CTRLID_BTN_YP, + CTRLID_BTN_YN, + CTRLID_BTN_ZP, + CTRLID_BTN_ZN, + CTRLID_BTN_GOFORWARD, + CTRLID_BTN_GOBACKWARD, + CTRLID_BTN_GODISTANCE, + CTRLID_BTN_CHANGECOOR, + CTRLID_BTN_MACHSELECTEDON, + CTRLID_BTN_MACHSELECTEDOFF, + CTRLID_BTN_JOGLASERON, + CTRLID_BTN_JOGLASEROFF, + CTRLID_BTN_AUTOCYC, + CTRLID_BTN_SELMARKPOINT, + CTRLID_BTN_CYCMACH, + CTRLID_BTN_MAX, + CTRLID_BTN_MARKPOINT1, + CTRLID_BTN_MARKPOINT2, + CTRLID_BTN_MARKPOINT3, + CTRLID_BTN_MARKPOINT4, + CTRLID_BTN_MARKPOINT5, + CTRLID_BTN_MARKPOINT6, + CTRLID_BTN_MARKPOINT7, + CTRLID_BTN_MARKPOINT8, + + CTRLID_STC_AXES = stc1, + CTRLID_STC_COOR, + CTRLID_STC_PORT0, + CTRLID_STC_PORT1, + CTRLID_STC_PORT2, + CTRLID_STC_PORT3, + CTRLID_STC_PORT4, + CTRLID_STC_PORT5, + CTRLID_STC_PORT6, + CTRLID_STC_PORT7, + CTRLID_STC_PORT8, + CTRLID_STC_PORT9, + CTRLID_STC_PORT10, + CTRLID_STC_PORT11, + CTRLID_STC_PORT12, + CTRLID_STC_PORT13, + CTRLID_STC_PORT14, + CTRLID_STC_PORT15, + CTRLID_STC_XVALUE, + CTRLID_STC_YVALUE, + CTRLID_STC_ZVALUE, + CTRLID_STC_MACHCOOR, + CTRLID_STC_WORKCOOR, + CTRLID_STC_SELECTMACH, + CTRLID_STC_JOGLASER, + + CTRLID_EDIT_GODISTANCE = edt1, + + CTRLID_SLD_SETF = ctl1, + CTRLID_SLD_SETP, + CTRLID_SLD_SETFH, +}; +//////////////////////////////////////////////////////////////////////////////// +// Local function declarations ---- DingQiang 2012-06-25 +static double _FormatInputData(double nInputData_); + +//////////////////////////////////////////////////////////////////////////////// +// CMachineControlDlg_Left +// +// 只需要按类名创建类对象,不需要序列化与版本控制。 ---- 杨开锦 2011-10-31 +IMPLEMENT_SERIAL(CMachineControlDlg_Left, CAgileDialog, 0xFFFF) + +BEGIN_MESSAGE_MAP(CMachineControlDlg_Left, CAgileDialog) + ON_WM_PAINT() + ON_WM_ERASEBKGND() + ON_WM_CTLCOLOR() + ON_WM_HSCROLL() + ON_WM_LBUTTONDOWN() + ON_MESSAGE(WM_MYDLGMESSAGE, OnEndSpeedDlg) + ON_CONTROL_RANGE(BN_PUSHED, CTRLID_BTN_XP, CTRLID_BTN_ZN, OnDirectionBtnPushed) + ON_CONTROL_RANGE(BN_UNPUSHED, CTRLID_BTN_XP, CTRLID_BTN_ZN, OnDirectionBtnUnpushed) + ON_CONTROL_RANGE(BN_PUSHED, CTRLID_BTN_GOFORWARD, CTRLID_BTN_GOBACKWARD, OnGFOBBtnPushed) + ON_CONTROL_RANGE(BN_UNPUSHED, CTRLID_BTN_GOFORWARD, CTRLID_BTN_GOBACKWARD, OnGFOBBtnUnpushed) + ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI) + ON_CONTROL(STN_DBLCLK, CTRLID_STC_COOR, OnChangeCoorMode) + ON_MESSAGE(WM_MYEIDTMESSAGE, OnEndEditDistance) + ON_COMMAND(CTRLID_BTN_CHANGECOOR, OnChangeCoorMode) + ON_COMMAND(CTRLID_BTN_MAX, OnMaxSize) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_CENTER, OnSetManuMode) + ON_CONTROL(BN_DOUBLECLICKED, CTRLID_BTN_CENTER, OnDblClickCenter) + ON_MESSAGE(WM_BITMAPSLIDER_MOVING, OnSliderMoving) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_MACHSELECTEDON, OnCloseMachSelected) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_MACHSELECTEDOFF, OnOpenMachSelected) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_JOGLASERON, OnCloseJogLaser) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_JOGLASEROFF, OnOpenJogLaser) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_AUTOCYC, OnClickAutoCyc) + ON_CONTROL(BN_CLICKED, CTRLID_BTN_CYCMACH, OnClickCycMach) + ON_COMMAND(CTRLID_BTN_SELMARKPOINT, OnSelMarkPoint) + ON_COMMAND_RANGE(CTRLID_BTN_MARKPOINT1, CTRLID_BTN_MARKPOINT8, OnMarkPointChange) + +END_MESSAGE_MAP() + +CMachineControlDlg_Left::CMachineControlDlg_Left(CWnd* pParentWnd_/* = NULL*/) +: CMachineControlDlg_Imp(pParentWnd_) +{ + //m_pwndSliderF = NULL; + m_pwndBtnXP = NULL; + m_pwndBtnXN = NULL; + m_pwndBtnYP = NULL; + m_pwndBtnYN = NULL; + m_pwndBtnZP = NULL; + m_pwndBtnZN = NULL; + m_pwndBtnCenter = NULL; + m_pwndStcValueWorkX = NULL; + m_pwndStcValueWorkY = NULL; + m_pwndStcValueWorkZ = NULL; + m_pwndStcValueMachX = NULL; + m_pwndStcValueMachY= NULL; + m_pwndStcValueMachZ = NULL; + m_pwndStcSpeed = NULL; + m_pwndStcPower = NULL; + m_pwndStcFollowHeight = NULL; + m_pSetSpeedDlg = NULL; + m_pwndSliderSetF = NULL; + m_pwndSliderSetP = NULL; + m_pwndSliderSetFH = NULL; + m_pDistanceEdit = NULL; + m_pwndRunBtn = NULL; + m_pwndDirRunBtn = NULL; + m_pwndBtnSelMachOn = NULL; + m_pwndBtnSelMachOff = NULL; + m_pwndBtnJogLaserOn = NULL; + m_pwndBtnJogLaserOff = NULL; + m_pwndBtnMoveIn = NULL; // 交换工作台 + m_pwndBtnMoveOut = NULL; // 释放工作台 + m_pwndBtnMax = NULL; + + m_pMenu = new CMenu; + + memset(m_pwndPortButtons, 0, sizeof(CPortButton*) * _countof(m_pwndPortButtons)); + + m_nCoorMode = 0x00; + m_bSelectMach = FALSE; + + for (int _i = 0; _i < _countof(m_nFValues); _i++) + { + m_nFValues[_i] = _i; + } + + m_strShowAllBKMark = "0"; + m_strBKMarkAttachAxis = "0,1"; + + m_nArcSliderFHMax = 15; + + m_bSliderCtrlG00 = NceGetPrivateProfileString(_T("ControlTarget"), _T("SliderCtrlG00"), _T("0")) == _T("1"); + // 同步GXX和G00的倍率。 ---- 黄海燕 2016-04-19 + if (m_bSliderCtrlG00) + { + if (CParamManager* _pParamManager = GetParamManager()) + { + int _nFrp = 100; + ParameterValue _FrpParamValue; + if (_pParamManager->GetParameterValue("SpeedGxx_Frp", &_FrpParamValue) + && _FrpParamValue.nType == ParameterValue::VT_INT) + { + _nFrp = _FrpParamValue.iValue; + } + + if (_pParamManager->GetParameterValue("SpeedG00_Frp", &_FrpParamValue) + && _FrpParamValue.nType == ParameterValue::VT_INT) + { + _FrpParamValue.iValue = _nFrp; + bool _bRet = _pParamManager->SetParameterValue("SpeedG00_Frp", &_FrpParamValue); + ASSERT(_bRet); + } + } + } + + m_bShowSelectMach = FALSE; + m_bShowJogLaser = FALSE; + m_bShowAutoCyc = FALSE; + m_bSelectMach = FALSE; + m_nCurIndex = 1; + + LOAD_PARAM(this, CMachineControlDlg_Left); +} + +CMachineControlDlg_Left::~CMachineControlDlg_Left() +{ + if (m_pSetSpeedDlg) + { + delete m_pSetSpeedDlg; + m_pSetSpeedDlg = NULL; + } + + if (m_pMenu) + { + delete m_pMenu; + m_pMenu = NULL; + } + + SAVE_PARAM(this, CMachineControlDlg_Left); +} + +BOOL CMachineControlDlg_Left::Create(CWnd* pParentWnd_ /* = NULL */) +{ + // 更改窗口风格为子窗口,以便用于贴到NcEditor的右侧栏上。 ---- 杨开锦 2011-10-31 + static struct { DLGTEMPLATE dt; SHORT n1; SHORT n2; SHORT n3; } + _s_EmptyDialogTemplate = { WS_CHILD }; + return CreateIndirect(&_s_EmptyDialogTemplate.dt, pParentWnd_); +} + +void CMachineControlDlg_Left::Update() +{ + UpdateBRFlag(); + UpdateMachCoor(); + UpdateF(); + UpdateP(); + UpdateFH(); + UpdateSpeed(); + UpdateManuCenter(); + UpdateGFOBInfo(); + UpdateEnableJogLaser(); + UpdateEnableAutoCyc(); + UpdateCycMach(); + + for (int _i = 0; _i < _countof(m_pwndPortButtons); _i++) + { + if (m_pwndPortButtons[_i]) + { + // 定时器更新 ---- 杨开锦 2013-03-11 + m_pwndPortButtons[_i]->Update(); + } + } + m_pwndDirRunBtn->Update(); + m_pwndRunBtn->Update(); +} + +BOOL CMachineControlDlg_Left::OnInitDialog() +{ + __super::OnInitDialog(); + + // 注册取得各控件指针。 ---- 杨开锦 2011-10-31 + Register("stcCoor", m_pwndStcCoor); + RegisterID("stcCoor", CTRLID_STC_COOR); + RegisterID("btnChangCoor", CTRLID_BTN_CHANGECOOR); + Register("stcXValue", m_pwndStcValueX); + Register("stcYValue", m_pwndStcValueY); + Register("stcZValue", m_pwndStcValueZ); + Register("stcTitleZ", m_pwndStcTitleZ); + Register("stcBR", m_pwndStcBR); + Register("stcBRX", m_pwndStcBRX); + Register("stcBRY", m_pwndStcBRY); + Register("stcBRZ", m_pwndStcBRZ); + Register("stcSpeedValue", m_pwndStcSpeed); + Register("stcPowerValue", m_pwndStcPower); + Register("stcFollowHeightValue", m_pwndStcFollowHeight); + Register("sliderSetF", m_pwndSliderSetF); + Register("sliderSetP", m_pwndSliderSetP); + Register("sliderSetFH", m_pwndSliderSetFH); + RegisterID("sliderSetF", CTRLID_SLD_SETF); + RegisterID("sliderSetP", CTRLID_SLD_SETP); + RegisterID("sliderSetFH", CTRLID_SLD_SETFH); + RegisterID("btnF", CTRLID_BTN_F); + RegisterID("stcXValue", CTRLID_STC_XVALUE); + RegisterID("stcYValue", CTRLID_STC_YVALUE); + RegisterID("stcZValue", CTRLID_STC_ZVALUE); + Register("btnXP", m_pwndBtnXP); + Register("btnXN", m_pwndBtnXN); + Register("btnYP", m_pwndBtnYP); + Register("btnYN", m_pwndBtnYN); + Register("btnZP", m_pwndBtnZP); + Register("btnZN", m_pwndBtnZN); + Register("stcGoDistance", m_pwndStcGoDistance); + RegisterID("stcGoDistance", CTRLID_BTN_GODISTANCE); + Register("btnCenter", m_pwndBtnCenter); + RegisterID("btnCenter", CTRLID_BTN_CENTER); + RegisterID("btnXP", CTRLID_BTN_XP); + RegisterID("btnXN", CTRLID_BTN_XN); + RegisterID("btnYP", CTRLID_BTN_YP); + RegisterID("btnYN", CTRLID_BTN_YN); + RegisterID("btnZP", CTRLID_BTN_ZP); + RegisterID("btnZN", CTRLID_BTN_ZN); + RegisterID("btnGoForward", CTRLID_BTN_GOFORWARD); + RegisterID("btnGoBackward", CTRLID_BTN_GOBACKWARD); + RegisterID("stcPort0", CTRLID_STC_PORT0); + RegisterID("stcPort1", CTRLID_STC_PORT1); + RegisterID("stcPort2", CTRLID_STC_PORT2); + RegisterID("stcPort3", CTRLID_STC_PORT3); + RegisterID("stcPort4", CTRLID_STC_PORT4); + RegisterID("stcPort5", CTRLID_STC_PORT5); + RegisterID("stcPort6", CTRLID_STC_PORT6); + RegisterID("stcPort7", CTRLID_STC_PORT7); + RegisterID("stcPort8", CTRLID_STC_PORT8); + RegisterID("stcPort9", CTRLID_STC_PORT9); + RegisterID("stcPort10", CTRLID_STC_PORT10); + RegisterID("stcPort11", CTRLID_STC_PORT11); + /*RegisterID("stcPort12", CTRLID_STC_PORT12);*/ + RegisterID("stcPort13", CTRLID_STC_PORT13); + RegisterID("stcPort14", CTRLID_STC_PORT14); + RegisterID("stcPort15", CTRLID_STC_PORT15); + RegisterID("btnSelMarkPoint", CTRLID_BTN_SELMARKPOINT); + Register("btnRun", m_pwndRunBtn); + Register("btnDirrun", m_pwndDirRunBtn); + + // 将标记点选择按钮初始化 ---- 边俊霞 2017-03-15 + CString _strCurIndex; + _strCurIndex.Format("%u", m_nCurIndex); + + // 标记点选项菜单 + m_pMenu->CreatePopupMenu(); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT1, _GETCS(s_szMUNU_MARKPOINT1)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT2, _GETCS(s_szMUNU_MARKPOINT2)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT3, _GETCS(s_szMUNU_MARKPOINT3)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT4, _GETCS(s_szMUNU_MARKPOINT4)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT5, _GETCS(s_szMUNU_MARKPOINT5)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT6, _GETCS(s_szMUNU_MARKPOINT6)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT7, _GETCS(s_szMUNU_MARKPOINT7)); + m_pMenu->AppendMenu(MF_STRING, CTRLID_BTN_MARKPOINT8, _GETCS(s_szMUNU_MARKPOINT8)); + + + // 界面显示需求,使数字在button上不居中显示 ---- 边俊霞 2017-03-15 + CString _strShowIndex = _strCurIndex + '\n'; + SetDlgItemText(CTRLID_BTN_SELMARKPOINT, _strShowIndex); + + RegisterID("btnCycMach", CTRLID_BTN_CYCMACH); + Register("btnCycMach", m_pwndBtnCycMach); + Register("btnPort6", m_pwndBtnMoveIn); + Register("btnPort7", m_pwndBtnMoveOut); + + RegisterID("btnMax", CTRLID_BTN_MAX); + Register("btnMax", m_pwndBtnMax); + m_pwndBtnMax->ShowWindow(SW_HIDE); + + CString _strUserStyle = NceGetPrivateProfileString(_T("PortSet"), _T("MoveInOut"), _T("TRUE")); + if(_strUserStyle == _T("FALSE")) + { + m_pwndBtnMoveIn->EnableWindow(FALSE); + m_pwndBtnMoveOut->EnableWindow(FALSE); + } + + m_bShowSelectMach = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowSelectMach")) == _T("1"); + RegisterID("btnSelMachOn", CTRLID_BTN_MACHSELECTEDON); + Register("btnSelMachOn", m_pwndBtnSelMachOn); + RegisterID("btnSelMachOff", CTRLID_BTN_MACHSELECTEDOFF); + Register("btnSelMachOff", m_pwndBtnSelMachOff); + + RegisterID("stcMachSelText", CTRLID_STC_SELECTMACH); + CWnd* _pwndSelectMach_Static = GetDlgItem(CTRLID_STC_SELECTMACH); + if (_pwndSelectMach_Static) + { + _pwndSelectMach_Static->SetWindowText(_GETCS(s_csSELECTMACH)); + } + + m_pwndBtnSelMachOn->ShowWindow(m_bSelectMach ? SW_SHOW : SW_HIDE); + m_pwndBtnSelMachOff->ShowWindow(m_bSelectMach ? SW_HIDE : SW_SHOW); + + // 点动出光 ---- 边俊霞 2016-12-26 + m_bShowJogLaser = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowJogLaser")) == _T("1"); + RegisterID("btnJogLaserOn", CTRLID_BTN_JOGLASERON); + Register("btnJogLaserOn", m_pwndBtnJogLaserOn); + RegisterID("btnJogLaserOff", CTRLID_BTN_JOGLASEROFF); + Register("btnJogLaserOff", m_pwndBtnJogLaserOff); + RegisterID("stcJogWithLaser", CTRLID_STC_JOGLASER); + CWnd* _pwndStatic2 = GetDlgItem(CTRLID_STC_JOGLASER); + if(_pwndStatic2) + { + _pwndStatic2->SetWindowText(_GETCS(s_szLaserOnWhenJog)); + } + + m_pwndBtnJogLaserOn->ShowWindow(SW_HIDE); + m_pwndBtnJogLaserOff->ShowWindow(SW_SHOW); + + + UpdateCycMach(); + + // 自动循环 ---- 陈思 2017-1-10 + m_bShowAutoCyc = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowAutoCyc")) == _T("1"); + RegisterID("btnAutoCycle", CTRLID_BTN_AUTOCYC); + CButton* _pBtnAutoCyc = (CButton*)GetDlgItem(CTRLID_BTN_AUTOCYC); + if (_pBtnAutoCyc) + { + _pBtnAutoCyc->SetCheck(m_bShowAutoCyc ? BST_CHECKED : BST_UNCHECKED); + } + + m_pwndRunBtn->SetMotionEndType(CCycMachiningTarget::TaskEndNormal); + m_pwndDirRunBtn->SetMotionEndType(CCycMachiningTarget::DryRunEndNormal); + + // PortButton ---- DingQiang 2013-07-23 + for (size_t _i = 0; _i < _countof(m_pwndPortButtons); _i++) + { + // 注册:xaml中如果没配则注册失败,相应指针为NULL ---- DingQiang 2013-07-24 + CString _strPortButtonName; + _strPortButtonName.Format(_T("btnPort%d"), _i); + Register(_strPortButtonName, m_pwndPortButtons[_i]); + + // 初始化控件 ---- DingQiang 2016-07-14 + CString _strPortIndex; + _strPortIndex.Format(_T("Port%d"), _i); + if (!m_pwndPortButtons[_i] || !m_pwndPortButtons[_i]->Initialize(_T("ControlTarget"), _strPortIndex)) + { + continue; + } + + // 设置相应的端口名 ---- 杨开锦 2012-07-05 + CString _strDescriptionNameKey; + _strDescriptionNameKey.Format(_GETCS(s_szPortNameKey), _i); + CString _strDescriptionName = NceGetPrivateProfileString(_T("ControlTarget"), _strDescriptionNameKey); + SetDlgItemText(CTRLID_STC_PORT0 + (int)_i, _strDescriptionName); + } + + // 隐藏所有的回机械原点标志----梁艳-2015-02-08 + m_pwndStcBR->ShowWindow(SW_HIDE); + m_pwndStcBRX->ShowWindow(SW_HIDE); + m_pwndStcBRY->ShowWindow(SW_HIDE); + m_pwndStcBRZ->ShowWindow(SW_HIDE); + + //读配置,是否显示所有轴回机械原点标志以及回机械原点关联轴的索引 + //如果可以读到,则使用读到的,否则使用默认的----梁艳-2015-02-08 + CString _strShowAllBKMark = NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowAllBKMark")); + CString _strBKMarkAttachAxis = NceGetPrivateProfileString(_T("ControlTarget"), _T("BKMarkAttachAxis")); + if (!_strShowAllBKMark.IsEmpty()) + { + m_strShowAllBKMark = _strShowAllBKMark; + } + if (!_strBKMarkAttachAxis.IsEmpty()) + { + m_strBKMarkAttachAxis = _strBKMarkAttachAxis; + } + + //只显示一个回原点标志时,求出关联轴的索引---梁艳-2015-02-08 + if (m_strShowAllBKMark == "0") + { + CString _strBKMarkAttachAxis = m_strBKMarkAttachAxis; + //关联轴索引 空值或含有非法字符或只有一个非数字字符 + if (_strBKMarkAttachAxis.IsEmpty() + ||_strBKMarkAttachAxis.SpanIncluding(_T(",012")).GetLength() != _strBKMarkAttachAxis.GetLength() + || _strBKMarkAttachAxis.GetLength() == 1 && _strBKMarkAttachAxis.FindOneOf(_T("012")) == -1) + { + _strBKMarkAttachAxis.Empty(); + } + m_strVecAxis.clear(); + while(!_strBKMarkAttachAxis.IsEmpty()) + { + _strBKMarkAttachAxis.TrimLeft(","); + _strBKMarkAttachAxis.TrimRight(","); + int _Index = _strBKMarkAttachAxis.Find(","); + if(_Index == -1) + { + m_strVecAxis.push_back(_strBKMarkAttachAxis); + break; + } + m_strVecAxis.push_back( _strBKMarkAttachAxis.Left(_Index)); + _strBKMarkAttachAxis = _strBKMarkAttachAxis.Right(_strBKMarkAttachAxis.GetLength() - _Index); + } + } + +#define RegisterBtnID(szName_, nID_) { \ + CAgileImageButton* _pwndBtn = NULL; \ + Register(szName_, _pwndBtn); \ + ASSERT(_pwndBtn); \ + ASSERT(IsCmdID(nID_)); \ + _pwndBtn->SetCmdID(nID_); \ + } + RegisterBtnID("btnSetW", IDCMD_CONTROLTARGET_CLEARW); + RegisterBtnID("btnBW", IDCMD_CONTROLTARGET_BACKW); + RegisterBtnID("btnSimuCut", IDCMD_CONTROLTARGET_SIMUCUT); + RegisterBtnID("btnRun", IDCMD_CONTROLTARGET_START); + RegisterBtnID("btnPause", IDCMD_CONTROLTARGET_PAUSE); + RegisterBtnID("btnStop", IDCMD_CONTROLTARGET_STOP); + RegisterBtnID("btnBreakpointResume", IDCMD_CONTROLTARGET_BREAKPOINTRESUME); + RegisterBtnID("btnSimulate", IDCMD_CONTROLTARGET_SIMULATE); + RegisterBtnID("btnDirrun", IDCMD_CONTROLTARGET_DIRRUN); + RegisterBtnID("btnBackFixed", IDCMD_CONTROLTARGET_BACKWZ); + RegisterBtnID("btnMarkPoint", IDCMD_MARKPOINTTARGET_MARKTHISPOINT); + RegisterBtnID("btnBackMarkPoint", IDCMD_MARKPOINTTARGET_MOVETOMARKPOINT); + RegisterBtnID("btnCleanJet", IDCMD_AUTOCLEANTARGET_STARTAUTOCLEAN); + CString _strCutBoundText; + if (NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowSampleBtn")) == _T("1")) + { + RegisterBtnID("btnSample", IDCMD_FOLLOWCTRLTARGET_SAMPLE); + // 走边框放到下一排,按钮上显示字。 ---- 黄海燕 2015-09-10 + _strCutBoundText = _GETCS(s_csSIMUCUTBOUNDRECT); + } + if (NceGetPrivateProfileString(_T("ControlTarget"), _T("ShowBackOrgBtn")) == _T("1")) + RegisterBtnID("btnBackOrg", IDCMD_CONTROLTARGET_BACKR); +#undef RegisterBtnID + + SetDlgItemText(CTRLID_STC_MACHCOOR, _GETCS(s_csMACHINECOORDINATE)); // 机械坐标 ---- 吴畏 2016-10-27 + SetDlgItemText(CTRLID_STC_WORKCOOR, _GETCS(s_csWORKPIECECOORDINATE)); // 工件坐标 ---- 吴畏 2016-10-27 + SetDlgItemText(CTRLID_STC_COOR, m_nCoorMode == 0x00 ? _GETCS(s_csWORKPIECECOORDINATE) : _GETCS(s_csMACHINECOORDINATE)); + + // 设置功率滑动条范围---- DingQiang 2012-04-28 + CString _strIsGrayBottom = NceGetPrivateProfileString(_T("ControlTarget"), _T("IsGrayBottom"), _T(0)); + BOOL _bIsGrayBottom = atoi(_strIsGrayBottom); + m_pwndSliderSetF->SetCustomerSetSize(); + if (_bIsGrayBottom) + { + // 加载灰色背景竖屏滑动条配色 ---- 边俊霞 2017-01-11 + m_pwndSliderSetF->SetBitmapChannel( IDB_BMP_GRAY_CHANNELBACK, IDB_BMP_GRAY_CHANNELFORE); + m_pwndSliderSetF->SetBitmapThumb( IDB_BMP_GRAY_THUMBNORMAL, IDB_BMP_GRAY_THUMBPRESS, IDB_BMP_GRAY_THUMBHOVER); + } + else + { + m_pwndSliderSetF->SetBitmapChannel( IDB_BMP_CHANNELBACK, IBP_BMP_CHANNELFORE); + m_pwndSliderSetF->SetBitmapThumb( IDB_BMP_THUMBNORMAL, IDB_BMP_THUMBPRESS, IDB_BMP_THUMBHOVER); + } + m_pwndSliderSetF->SetRange( 0, 100); + m_pwndSliderSetF->SetPos( 0 ); + + m_pwndSliderSetP->SetCustomerSetSize(); + if (_bIsGrayBottom) + { + // 加载灰色背景竖屏滑动条配色 ---- 边俊霞 2017-01-11 + m_pwndSliderSetP->SetBitmapChannel( IDB_BMP_GRAY_CHANNELBACK, IDB_BMP_GRAY_CHANNELFORE); + m_pwndSliderSetP->SetBitmapThumb( IDB_BMP_GRAY_THUMBNORMAL, IDB_BMP_GRAY_THUMBPRESS, IDB_BMP_GRAY_THUMBHOVER); + } + else + { + m_pwndSliderSetP->SetBitmapChannel( IDB_BMP_CHANNELBACK, IBP_BMP_CHANNELFORE); + m_pwndSliderSetP->SetBitmapThumb( IDB_BMP_THUMBNORMAL, IDB_BMP_THUMBPRESS, IDB_BMP_THUMBHOVER); + } + m_pwndSliderSetP->SetRange( 0, 100); + m_pwndSliderSetP->SetPos( 0 ); + + m_pwndSliderSetFH->SetCustomerSetSize(); + if (_bIsGrayBottom) + { + // 加载灰色背景竖屏滑动条配色 ---- 边俊霞 2017-01-11 + m_pwndSliderSetFH->SetBitmapChannel( IDB_BMP_GRAY_CHANNELBACK, IDB_BMP_GRAY_CHANNELFORE); + m_pwndSliderSetFH->SetBitmapThumb( IDB_BMP_GRAY_THUMBNORMAL, IDB_BMP_GRAY_THUMBPRESS, IDB_BMP_GRAY_THUMBHOVER); + } + else + { + m_pwndSliderSetFH->SetBitmapChannel( IDB_BMP_CHANNELBACK, IBP_BMP_CHANNELFORE); + m_pwndSliderSetFH->SetBitmapThumb( IDB_BMP_THUMBNORMAL, IDB_BMP_THUMBPRESS, IDB_BMP_THUMBHOVER); + } + m_pwndSliderSetFH->SetRange( 0, 80); + m_pwndSliderSetFH->SetPos( 0 ); + + _BuildFHIVMap(); + + // 手动中心键为圆形按钮,手动方向键为圆环切割而成,其中X-为左月牙、X+为右月 + // 牙、Y-为下月牙、Y+为上月牙。 + // 中心键半径为34px;方向键所在圆环外径为80px,内径为40px,各键间间隔缝为 + // 宽8px。 + // 此处各区域值为略扩大一点的区域,以便确保能完全包含所画贴图而不产生边界 + // 切割据齿。 ---- 杨开锦 2011-11-02 + ASSERT(m_pwndBtnCenter && m_pwndBtnXP && m_pwndBtnXN && m_pwndBtnYP && m_pwndBtnYN); + m_pwndBtnCenter->SetShape(::CreateEllipticRgn(-1, -1, 77, 77)); + CDC _dc; + CDC* _pDC = GetDC(); + _dc.CreateCompatibleDC(_pDC); + ReleaseDC(_pDC); + _pDC = NULL; + _dc.BeginPath(); + _dc.MoveTo(147, 28); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 170, 170, 147, 28, 147, 143); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(40, 40, 130, 130, 118, 113, 118, 57); + _dc.LineTo(147, 28); + _dc.EndPath(); + CRgn _rgn; + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-120, -27); + m_pwndBtnXP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(52, 114); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(40, 40, 130, 130, 52, 114, 52, 58); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(-1, -1, 170, 170, 22, 30, 22, 142); + _dc.LineTo(52, 114); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(18, -27); + m_pwndBtnXN->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(28, 23); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(0, 0, 170, 170, 28, 23, 141, 23); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(40, 40, 130, 130, 112, 53, 57, 53); + _dc.LineTo(28, 23); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(-1, 16); + m_pwndBtnYP->SetShape((HRGN)_rgn.Detach()); + + _dc.BeginPath(); + _dc.MoveTo(140, 148); + _dc.SetArcDirection(AD_CLOCKWISE); + _dc.ArcTo(-1, -1, 170, 170, 140, 148, 28, 148); + _dc.SetArcDirection(AD_COUNTERCLOCKWISE); + _dc.ArcTo(39, 39, 129, 129, 57, 116, 112, 116); + _dc.LineTo(140, 148); + _dc.EndPath(); + _rgn.CreateFromPath(&_dc); + _rgn.OffsetRgn(0, -117); + m_pwndBtnYN->SetShape((HRGN)_rgn.Detach()); + + m_pSetSpeedDlg = new CSetSpeedDlg(this); + ((CSetSpeedDlg*)m_pSetSpeedDlg)->Create(this); + + m_pwndStcCoor->ModifyStyle(0, SS_NOTIFY); + m_pwndStcValueX->ModifyStyle(0, SS_NOTIFY); + m_pwndStcValueY->ModifyStyle(0, SS_NOTIFY); + m_pwndStcValueZ->ModifyStyle(0, SS_NOTIFY); + + // 这里加一次Update是因为:出现过一个问题,软件启动时横向的进给倍率条显示不 + // 出来,最小化最大化一下才出来。带NcStudio启动才有问题,单NcEditor没问题。 + // 没有查出原因,只是经试验发现这里Update一次就好了,于是就这么干。如果以后 + // 发现这样不是正解请修改。 ---- 杨开锦 2012-05-02 + Update(); + + bool _bEnableZ = IsEnableZUpDown(); + m_pwndBtnZP->EnableWindow(_bEnableZ ? TRUE : FALSE); + m_pwndBtnZN->EnableWindow(_bEnableZ ? TRUE : FALSE); + m_pwndBtnZP->ShowWindow(_bEnableZ ? TRUE : FALSE); + m_pwndBtnZN->ShowWindow(_bEnableZ ? TRUE : FALSE); + SetMachineCtrlTips(); + return TRUE; +} + +void CMachineControlDlg_Left::SetMachineCtrlTips() +{ + m_MachineCtrlTips.Create(this); + m_MachineCtrlTips.Activate(TRUE); + m_MachineCtrlTips.SetTipTextColor(RGB(0, 0, 0)); + m_MachineCtrlTips.SetDelayTime(1000); + + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_CLEARW), _GETCS(s_csTipSETWORKORG)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_BACKW), _GETCS(s_csTipMOVETOWORKORIGIN)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_START), _GETCS(s_csTipSTART)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_PAUSE), _GETCS(s_csTipPAUSE)); + m_MachineCtrlTips.AddTool(GetDlgItem(IDCMD_CONTROLTARGET_STOP), _GETCS(s_csTipSTOP)); + m_MachineCtrlTips.AddTool(GetDlgItem(CTRLID_BTN_GOBACKWARD), _GETCS(s_csTipGoBackward)); + m_MachineCtrlTips.AddTool(GetDlgItem(CTRLID_BTN_GOFORWARD), _GETCS(s_csTipGoForward)); + CWnd* _pwndBtn = GetDlgItem(IDCMD_FOLLOWCTRLTARGET_SAMPLE); + if (_pwndBtn) + m_MachineCtrlTips.AddTool(_pwndBtn, _GETCS(s_csTipFollowSample)); + _pwndBtn = GetDlgItem(IDCMD_CONTROLTARGET_BACKR); + if (_pwndBtn) + m_MachineCtrlTips.AddTool(_pwndBtn, _GETCS(s_csTipBackAll)); +} + +bool CMachineControlDlg_Left::IsEnableZUpDown() +{ + return true; + CString _strEnableZ = NceGetPrivateProfileString(_T("ControlTarget"), _T("EnableZ")); + + if ("1" == _strEnableZ) + { + return true; + } + else + { + return false; + } +} + +BOOL CMachineControlDlg_Left::PreTranslateMessage(MSG* pMsg_) +{ + // 添加此句用于机床控制栏显示提示语 ---- 嘎松卓玛 2012.05.17 + m_MachineCtrlTips.RelayEvent(pMsg_); + + // Let go of Keyboard Message => 此处这么做有几个目的:一个是屏蔽Enter、Esc + // 键引发的OnOK、OnCancel关闭窗口;二是防止焦点在窗口上时,框架上的快捷键被 + // 屏蔽。 ---- 杨开锦 2012-04-08 + if (WM_KEYFIRST <= pMsg_->message && pMsg_->message <= WM_KEYLAST) + { + return FALSE; + } + + if (pMsg_->message == WM_LBUTTONDOWN) + { + UINT _nCtrlID = ::GetDlgCtrlID(pMsg_->hwnd); + if (_nCtrlID == CTRLID_BTN_GODISTANCE) + { + if (OnDistanceLButtonDown(pMsg_->pt)) + { + // 如果不return的话Dialog会响应此消息,此时new出来的编辑框会又马上 + // 响应OnKillFocus导致编辑框一出来就消失 ---- DingQiang 2012-07-19 + return TRUE; + } + } + } + + return __super::PreTranslateMessage(pMsg_); +} + +// 设置手动模式 ---- 郭小航 2013-11-07 +void CMachineControlDlg_Left::OnSetManuMode() +{ + DWORD _nBegin = GetTickCount(); + while(true) + { + MSG _msg; + if (::PeekMessage(&_msg, NULL, NULL, NULL, PM_REMOVE)) + { + ::TranslateMessage(&_msg); + ::DispatchMessage(&_msg); + + if (_msg.message == WM_LBUTTONDBLCLK) + { + return; + } + } + + if (GetTickCount() - _nBegin > 200) + { + break; + } + } + + static int _s_nManuMode; + int _nManuMode = _s_nManuMode % 3; + + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + if (_nManuMode == 0) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(false); + } + else if (_nManuMode == 1) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(true); + } + else if (_nManuMode == 2) + { + _pManualTarget->SetManuMode(1); + } + + _s_nManuMode ++; +} + +void CMachineControlDlg_Left::UpdateMachCoor() +{ + // 先更新标题 ---- 杨开锦 2012-07-05 + CString _strNewTitle = m_nCoorMode == 0x00 ? _GETCS(s_csWORKPIECECOORDINATE) : _GETCS(s_csMACHINECOORDINATE); + CString _strTitle; + m_pwndStcCoor->GetWindowText(_strTitle); + if (_strNewTitle != _strTitle) + { + m_pwndStcCoor->SetWindowText(_strNewTitle); + } + + CParamManager* _pParamManager = GetParamManager(); + if (!_pParamManager) + { + return; + } + + // 将控件与相应控件的参数标识符关联创建一个结构体---- DingQiang 2012-01-12 + const struct MachItem + { + DWORD nCoorMode; + CAgileLabel* pwndStcValue; + CString strIdentifier; + } _s_MachItems[] = + { + { 0x00, m_pwndStcValueX, "State_Axis0_WorkcoorPos" }, + { 0x00, m_pwndStcValueY, "State_Axis1_WorkcoorPos" }, + { 0x00, m_pwndStcValueZ, "State_Axis2_WorkcoorPos" }, + { 0x01, m_pwndStcValueX, "Dyn_Axis0_Pos"}, + { 0x01, m_pwndStcValueY, "Dyn_Axis1_Pos"}, + { 0x01, m_pwndStcValueZ, "Dyn_Axis2_Pos"} + }; + + for(int _i = 0; _i < _countof(_s_MachItems); _i++) + { + const MachItem& _item = _s_MachItems[_i]; + if (_item.nCoorMode != m_nCoorMode + || !_item.pwndStcValue + || !_item.pwndStcValue->IsWindowVisible()) + { + continue; + } + + ParameterValue _PV; + if (!_pParamManager->GetParameterValue(_item.strIdentifier, &_PV) || _PV.nType != ParameterValue::VT_DOUBLE) + { + ASSERT(FALSE); + continue; + } + + CString _strMachCoor; + _strMachCoor.Format("%.3f", _PV.dValue); + if (_strMachCoor == "-0.000") + { + _strMachCoor = "0.000"; + } + + // 若更新前坐标与更新后坐标相等则不更新 ---- DingQiang 2012-01-12 + CString _strBeforeUpdate; + _item.pwndStcValue->GetWindowText(_strBeforeUpdate); + if (_strMachCoor != _strBeforeUpdate) + { + _s_MachItems[_i].pwndStcValue->SetWindowText(_strMachCoor); + } + } +} +// 回机械原点标志,配置方式如下: +// [ControlTarget] +// ShowAllBKMark=1 +// BKMarkAttachAxis=0,1,2 +void CMachineControlDlg_Left::UpdateBRFlag() +{ + // 将轴原点标志控件与相应控件的参数以及轴的索引,关联创建一个结构体,方便以后扩展----梁艳-2015-02-08 + const struct AxisItems + { + CAgileImageLabel* pwndStcBR; + CString strIdentifier; + CString strIndex; + } _s_AxisItems[] = + { + { m_pwndStcBRX, "State_Axis0_IsReferenced", "0" }, + { m_pwndStcBRY, "State_Axis1_IsReferenced", "1" }, + { m_pwndStcBRZ, "State_Axis2_IsReferenced", "2" } + }; + + CParamManager* _pParamManager = GetParamManager(); + if(!_pParamManager) + return; + + //如果显示所有轴的回机械原点标志,则分别显示各轴的回机械原点标志---梁艳-2015-02-08 + if (m_strShowAllBKMark == _T("1")) + { + for(int _i = 0; _i < _countof(_s_AxisItems); _i++) + { + const AxisItems& _item = _s_AxisItems[_i]; + ParameterValue _PV; + memset(&_PV, 0, sizeof(ParameterValue)); + if (!_pParamManager->GetParameterValue(_item.strIdentifier, &_PV) || _PV.nType != ParameterValue::VT_BOOL) + { + ASSERT(FALSE); + continue; + } + _item.pwndStcBR->ShowWindow(_PV.bValue ? SW_SHOW : SW_HIDE); + } + } + // 如果不显示所有轴的回机械原点标志,则根据关联轴的索引,只显示一个回机械原点标志---梁艳-2015-02-08 + else if(m_strShowAllBKMark == _T("0")) + { + bool _bIsRef = m_strVecAxis.empty()? false : true; + for (std::vector::iterator _it = m_strVecAxis.begin(); _it != m_strVecAxis.end();_it++) + { + int _nCount = 0; + CString _strAxis = *_it; + for(int _j = 0; _j < _countof(_s_AxisItems); _j++) + { + const AxisItems& _item = _s_AxisItems[_j]; + ParameterValue _PV; + memset(&_PV, 0, sizeof(ParameterValue)); + if (!_pParamManager->GetParameterValue(_item.strIdentifier, &_PV) || _PV.nType != ParameterValue::VT_BOOL) + { + ASSERT(FALSE); + continue; + } + if (_item.strIndex == _strAxis) + { + _bIsRef &= _PV.bValue; + break; + } + else + { + _nCount++; + continue; + } + } + //没有匹配项 + if (_nCount == _countof(_s_AxisItems)) + { + _bIsRef = false; + } + } + m_pwndStcBR->ShowWindow(_bIsRef ? SW_SHOW : SW_HIDE); + } +} + + +void CMachineControlDlg_Left::OnDirectionBtnPushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_XP && nID_ <= CTRLID_BTN_ZN); + + // 将手动按钮模拟成快捷键导到CManualTarget中 + C_ASSERT(CTRLID_BTN_XP == CTRLID_BTN_XP + 0 + && CTRLID_BTN_XN == CTRLID_BTN_XP + 1 + && CTRLID_BTN_YP == CTRLID_BTN_XP + 2 + && CTRLID_BTN_YN == CTRLID_BTN_XP + 3 + && CTRLID_BTN_ZP == CTRLID_BTN_XP + 4 + && CTRLID_BTN_ZN == CTRLID_BTN_XP + 5); + static const UINT _s_nKeys[] = + { + VK_NUMPAD6, + VK_NUMPAD4, + VK_NUMPAD8, + VK_NUMPAD2, + VK_NUMPAD9, + VK_NUMPAD3, + }; + MSG _msg = { NULL, WM_KEYDOWN, WPARAM(_s_nKeys[nID_ - CTRLID_BTN_XP]), LPARAM(1) }; + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + _pManualTarget->OnKeyMessage(&_msg); +} + +void CMachineControlDlg_Left::OnDirectionBtnUnpushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_XP && nID_ <= CTRLID_BTN_ZN); + + // 将手动按钮模拟成快捷键导到CManualTarget中 + C_ASSERT(CTRLID_BTN_XP == CTRLID_BTN_XP + 0 + && CTRLID_BTN_XN == CTRLID_BTN_XP + 1 + && CTRLID_BTN_YP == CTRLID_BTN_XP + 2 + && CTRLID_BTN_YN == CTRLID_BTN_XP + 3 + && CTRLID_BTN_ZP == CTRLID_BTN_XP + 4 + && CTRLID_BTN_ZN == CTRLID_BTN_XP + 5); + static const UINT _s_nKeys[] = + { + VK_NUMPAD6, + VK_NUMPAD4, + VK_NUMPAD8, + VK_NUMPAD2, + VK_NUMPAD9, + VK_NUMPAD3, + }; + MSG _msg = { NULL, WM_KEYUP, WPARAM(_s_nKeys[nID_ - CTRLID_BTN_XP]), LPARAM(1) }; + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + _pManualTarget->OnKeyMessage(&_msg); +} + +void CMachineControlDlg_Left::OnGFOBBtnPushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_GOFORWARD && nID_ <= CTRLID_BTN_GOBACKWARD); + + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + if (_pControlTarget->GetGFOBMode() != 0x00) + { + return; + } + + C_ASSERT(CTRLID_BTN_GOFORWARD == CTRLID_BTN_GOFORWARD + 0 + && CTRLID_BTN_GOBACKWARD == CTRLID_BTN_GOFORWARD + 1); + static const UINT _s_nCmdIDs[] = + { + IDCMD_CONTROLTARGET_JOGFORWARD, + IDCMD_CONTROLTARGET_JOGBACKWARD, + }; + AfxGetMainWnd()->SendMessage(WM_COMMAND, _s_nCmdIDs[nID_ - CTRLID_BTN_GOFORWARD], 0); +} + +void CMachineControlDlg_Left::OnGFOBBtnUnpushed(UINT nID_) +{ + ASSERT(nID_ >= CTRLID_BTN_GOFORWARD && nID_ <= CTRLID_BTN_GOBACKWARD); + + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + if (_pControlTarget->GetGFOBMode() == 0x00) + { + AfxGetMainWnd()->SendMessage(WM_COMMAND, IDCMD_CONTROLTARGET_STOP, 0); + return; + } + + C_ASSERT(CTRLID_BTN_GOFORWARD == CTRLID_BTN_GOFORWARD + 0 + && CTRLID_BTN_GOBACKWARD == CTRLID_BTN_GOFORWARD + 1); + static const UINT _s_nCmdIDs[] = + { + IDCMD_CONTROLTARGET_INCFORWARD, + IDCMD_CONTROLTARGET_INCBACKWARD, + }; + AfxGetMainWnd()->SendMessage(WM_COMMAND, _s_nCmdIDs[nID_ - CTRLID_BTN_GOFORWARD], 0); +} + +LRESULT CMachineControlDlg_Left::OnIdleUpdateCmdUI(WPARAM wParam_, LPARAM lParam_) +{ + static const struct ManualBtnItem + { + CButton* pBtnManual; + DWORD nMask; + } _s_cManualBtnItems[] = + { + {m_pwndBtnYN, 0x00000001}, + {m_pwndBtnXN, 0x00000002}, + {m_pwndBtnXP, 0x00000004}, + {m_pwndBtnYP, 0x00000008}, + {m_pwndBtnZP, 0x00000010}, + {m_pwndBtnZN, 0x00000020}, + {m_pwndBtnCenter, 0x00000040}, + }; + + CManualTarget* _pManualTarget = GetManualTarget(); + if (!_pManualTarget) + { + return 0; + } + DWORD _ManualKeyState = _pManualTarget->GetManuKeyState(); + + for (int _i = 0; _i < _countof(_s_cManualBtnItems); _i++) + { + if (_ManualKeyState & _s_cManualBtnItems[_i].nMask) + { + _s_cManualBtnItems[_i].pBtnManual->SetCheck(TRUE); + } + else + _s_cManualBtnItems[_i].pBtnManual->SetCheck(FALSE); + } + + + // 真实前进后退状态和按钮F3、F4按下,只要一个状态为真即将按钮置亮 ---- DingQiang 2014-10-11 + static const struct GOBBtnItem + { + UINT nID; + DWORD nKeyboardMask; + DWORD nRunningStateMask; + } _s_cGOBBtnItems[] = + { + {CTRLID_BTN_GOBACKWARD, 0x00000001, 0x00000100}, + {CTRLID_BTN_GOFORWARD, 0x00000002, 0x00000080}, + }; + + CControlTarget* _pControlTarget = GetControlTarget(); + CStateManager* _pStateManager = GetStateManager(); + if (!_pControlTarget || !_pStateManager) + { + return 0; + } + + DWORD _GOBKeyState = _pControlTarget->GetGOBKeyState(); + DWORD _nRunningState = 0; + _pStateManager->GetRunningState(&_nRunningState); + + for (int _i = 0; _i < _countof(_s_cGOBBtnItems); _i++) + { + BOOL _bCheck = _nRunningState & _s_cGOBBtnItems[_i].nRunningStateMask; + _bCheck |= _GOBKeyState & _s_cGOBBtnItems[_i].nKeyboardMask; + + ((CButton*)GetDlgItem(_s_cGOBBtnItems[_i].nID))->SetCheck(_bCheck); + } + + return 1; +} + +void CMachineControlDlg_Left::OnHScroll(UINT nSBCode_, UINT nPos_, CScrollBar* pScrollBar_) +{ + +} + +// 更新进给倍率的显示值 ---- DingQiang 2012-02-07 +void CMachineControlDlg_Left::UpdateF() +{ + _BuildFIVMap(); + + // 从ParamManager中读出进给倍率的当前值,如果读不到,则以设定倍率滑动条上的 + // 值为准。 ---- 杨开锦 2012-02-18 + ASSERT(m_pwndSliderSetF); + int _nIndex = m_pwndSliderSetF->GetPos(); + int _nFrp = 100; + _UpdateFValue(_nIndex, &_nFrp); + if (CParamManager* _pParamManager = GetParamManager()) + { + const CStringA _c_strFrpIdentifier = "SpeedGxx_Frp"; + ParameterValue _FrpParamValue; + if (_pParamManager->GetParameterValue(_c_strFrpIdentifier, &_FrpParamValue) + && _FrpParamValue.nType == ParameterValue::VT_INT) + { + _nFrp = _FrpParamValue.iValue; + _UpdateFIndex(&_nIndex, _nFrp); + } + } + + // 更新横向滑动条 + ASSERT(m_pwndSliderSetF); + int _nCurPos_SliderSetF = m_pwndSliderSetF->GetPos(); + int _nNewPos_SliderSetF = min(_nFrp, m_pwndSliderSetF->GetRangeMax()); + if (_nNewPos_SliderSetF != _nCurPos_SliderSetF) + { + m_pwndSliderSetF->SetPos(_nNewPos_SliderSetF); + m_pwndSliderSetF->Invalidate(); + } +} + +void CMachineControlDlg_Left::UpdateP() +{ + CParamManager* _pParamManager = mach::GetParamManager(); + if (!_pParamManager) + { + return; + } + Parameter _DutyCycle; + if (!_pParamManager->GetParameter("PWM_DutyCycle", &_DutyCycle)) + { + return; + } + ASSERT(_DutyCycle.Value.nType == ParameterValue::VT_INT); + Parameter _RatedPower; + if (!_pParamManager->GetParameter("GP_LaserRatedPower", &_RatedPower)) + { + return; + } + ASSERT(_RatedPower.Value.nType == ParameterValue::VT_INT); + + CString _strOldInfo; + m_pwndStcPower->GetWindowText(_strOldInfo); + + CString _strValue; + _strValue.Format("%d", _DutyCycle.Value.iValue * _RatedPower.Value.iValue / 100); + if (_strValue != _strOldInfo) + { + m_pwndStcPower->SetWindowText(_strValue); + } + + // 更新横向滑动条 + ASSERT(m_pwndSliderSetP); + int _nCurPos_SliderSetP = m_pwndSliderSetP->GetPos(); + int _nNewPos_SliderSetP = _DutyCycle.Value.iValue; + if (_nNewPos_SliderSetP != _nCurPos_SliderSetP) + { + m_pwndSliderSetP->SetPos(_nNewPos_SliderSetP); + m_pwndSliderSetP->Invalidate(); + } +} + +void CMachineControlDlg_Left::_BuildFHIVMap() +{ + for (int _i = 0; _i <= 10; _i++) + { + m_nFHValues[_i] = _i * 0.02; + } + + for (int _i = 11; _i <= 20; _i++) + { + m_nFHValues[_i] = m_nFHValues[10] + (_i - 10) * 0.03; + } + + for (int _i = 21; _i <= 30; _i++) + { + m_nFHValues[_i] = m_nFHValues[20] + (_i - 20) * 0.03; + } + + for (int _i = 31; _i <= 40; _i++) + { + m_nFHValues[_i] = m_nFHValues[30] + (_i - 30) * 0.02; + } + + for (int _i = 41; _i <= 50; _i++) + { + m_nFHValues[_i] = m_nFHValues[40] + (_i - 40) * 0.1; + } + + for (int _i = 51; _i <= 60; _i++) + { + m_nFHValues[_i] = m_nFHValues[50] + (_i - 50) * 0.3; + } + + for (int _i = 61; _i <= 70; _i++) + { + m_nFHValues[_i] = m_nFHValues[60] + (_i - 60) * 0.5; + } + + for (int _i = 71; _i <= 80; _i++) + { + m_nFHValues[_i] = m_nFHValues[70] + (_i - 70) * 0.5; + } +} + +void CMachineControlDlg_Left::_UpdateFHValue(int nIndex_, double* pnVaue_) +{ + ASSERT(nIndex_ >= 0 && nIndex_ <= 80); + *pnVaue_ = m_nFHValues[nIndex_]; + return; +} + +void CMachineControlDlg_Left::_UpdateFHindex(int* pnIndex_, double nValue_) +{ + ASSERT(nValue_ >= 0); + for (int i = 0; i < _countof(m_nFHValues); i++) + { + if (DOUBLE_EQU(nValue_, m_nFHValues[i])) + { + *pnIndex_ = i; + return; + } + + if (nValue_ < m_nFHValues[i]) + { + ASSERT(i > 0); + *pnIndex_ = i - 1; + return; + } + } +} + +void CMachineControlDlg_Left::UpdateFH() +{ + CParamManager* _pParamManager = mach::GetParamManager(); + if (!_pParamManager) + { + return; + } + Parameter _FollowHeight; + if (!_pParamManager->GetParameter("GP_FollowHeight", &_FollowHeight)) + { + return; + } + + CString _strOldInfo; + m_pwndStcFollowHeight->GetWindowText(_strOldInfo); + + CString _strValue; + _strValue.Format("%.2f", _FollowHeight.Value.dValue); + if (_strValue != _strOldInfo) + { + m_pwndStcFollowHeight->SetWindowText(_strValue); + } + + double _nFollowHeigth = (min(_FollowHeight.Value.dValue, m_nArcSliderFHMax)); + + int _nIndex; + _UpdateFHindex(&_nIndex, _nFollowHeigth); + + // 更新横向滑动条 + ASSERT(m_pwndSliderSetFH); + int _nCurPos_SliderSetFH = m_pwndSliderSetFH->GetPos(); + int _nNewPos_SliderSetFH = _nIndex; + if (_nNewPos_SliderSetFH != _nCurPos_SliderSetFH) + { + m_pwndSliderSetFH->SetPos(_nNewPos_SliderSetFH); + m_pwndSliderSetFH->Invalidate(); + } + + //// 更新弧形旋钮显示 + //ASSERT(m_pwndSliderFH); + //int _nCurPos_SliderFH = m_pwndSliderFH->GetPos(); + //int _nNewPos_SliderFH = _nIndex; + //if (_nNewPos_SliderFH != _nCurPos_SliderFH) + //{ + // m_pwndSliderFH->SetPos(_nNewPos_SliderFH); + // m_pwndSliderFH->SetSelection(m_pwndSliderF->GetRangeMin(), _nNewPos_SliderFH); + //} +} + +void CMachineControlDlg_Left::UpdateManuCenter() +{ + ASSERT(m_pwndBtnCenter); + + // 当前显示的串 ---- 杨开锦 2012-02-21 + CString _strOldText; + m_pwndBtnCenter->GetWindowText(_strOldText); + + // 需要显示的串 ---- 杨开锦 2012-02-21 + CString _strNewText; + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + if (_pManualTarget->IsJogMode() && _pManualTarget->GetJogState()) + { + _strNewText = _GETCS(s_csRapidJog); + } + else if (_pManualTarget->IsJogMode() && !_pManualTarget->GetJogState()) + { + _strNewText = _GETCS(s_csSlowJog); + } + else + { + double _nIncDistance = _pManualTarget->GetIncDistance(); + + if (_nIncDistance >= 1000) + { + _strNewText.Format(_T("%.2f"), _nIncDistance); + } + else if (_nIncDistance >= 100) + { + _strNewText.Format(_T("%.3f"), _nIncDistance); + } + else if (_nIncDistance >= 10) + { + _strNewText.Format(_T("%.4f"), _nIncDistance); + } + else if (_nIncDistance >= 0) + { + _strNewText.Format(_T("%.5f"), _nIncDistance); + } + _strNewText.TrimRight(_T('0')); + _strNewText.TrimRight(_T('.')); + _strNewText += "\nmm"; + } + + // 更新 ---- 杨开锦 2012-02-21 + if (_strNewText != _strOldText) + { + m_pwndBtnCenter->SetWindowText(_strNewText); + } +} + +void CMachineControlDlg_Left::UpdateGFOBInfo() +{ + // 点动时显示“点动”,否则显示指定的距离 ---- 杨开锦 2012-03-10 + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + CString _strGFOBDistance; + if (_pControlTarget->GetGFOBMode() == 0x01) + { + double _nGFOBDistance = _pControlTarget->GetGFOBDistance(); + ASSERT(_nGFOBDistance >= 0); + _strGFOBDistance.Format(_T("%f"), _nGFOBDistance); + _strGFOBDistance.TrimRight(_T('0')); + _strGFOBDistance.TrimRight(_T('.')); + _strGFOBDistance.AppendFormat("mm"); + } + else + { + ASSERT(_pControlTarget->GetGFOBMode() == 0x00); + _strGFOBDistance.Format("%s", _GETCS(s_csJOG)); + } + + // 惰性更新 ---- 杨开锦 2012-03-10 + CString _strOldInfo; + m_pwndStcGoDistance->GetWindowText(_strOldInfo); + if (_strGFOBDistance != _strOldInfo) + { + m_pwndStcGoDistance->SetWindowText(_strGFOBDistance); + } +} + +void CMachineControlDlg_Left::UpdateSpeed() +{ + double _nSpeed = 0.0; + if (const CSpeedometerTarget* _pST = GetSpeedometerTarget()) + { + // 直接拉计数器的XY速度来显示 ---- 杨开锦 2015-11-25 + _nSpeed = _pST->GetRealSpeedXY() * 60; + } + + CString _strValue; + _strValue.Format("%d", (int)_nSpeed); + CString _strOldInfo; + m_pwndStcSpeed->GetWindowText(_strOldInfo); + if (_strValue != _strOldInfo) + { + m_pwndStcSpeed->SetWindowText(_strValue); + } +} + +void CMachineControlDlg_Left::UpdateEnableJogLaser() +{ + bool _bEnable = false; + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("EnableJogLaser", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_BOOL) + { + _bEnable = _ParamValue.bValue; + } + else + { + return; + } + + m_pwndBtnJogLaserOn->ShowWindow(_bEnable ? SW_SHOW : SW_HIDE); + m_pwndBtnJogLaserOff->ShowWindow(_bEnable ? SW_HIDE : SW_SHOW); +} + +void CMachineControlDlg_Left::UpdateEnableAutoCyc() +{ + CButton* _pwndCheckAutoCyc = (CButton*)GetDlgItem(CTRLID_BTN_AUTOCYC); + if (!_pwndCheckAutoCyc) + { + return; + } + + bool _bEnable1 = false; + bool _bEnable2 = false; + + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("AutoExchangeTaskEnd", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_INT) + { + if(_ParamValue.iValue == 1) + { + _bEnable1 = true; + } + else + { + ASSERT(_ParamValue.iValue == 0); + _bEnable1 = false; + } + } + else + { + return; + } + + CCycMachiningTarget* _pCycMachingTarget = GetCycMachiningTarget(); + int _nCycTimes = _pCycMachingTarget->GetCycTimes(); + BOOL _bCycEnable= _pCycMachingTarget->GetEnable(); + if(_bCycEnable == TRUE) + { + _bEnable2 = true; + } + else + { + _bEnable2 = false; + } + bool _bEnable = _bEnable1 && _bEnable2; + + bool _bBtnChecked = _pwndCheckAutoCyc->GetCheck() == BST_CHECKED ? true : false; + if (_bEnable != _bBtnChecked) + { + _pwndCheckAutoCyc->SetCheck(_bEnable ? BST_CHECKED : BST_UNCHECKED); + } +} + +// 倍率条为120格,映射到0-最大进给倍率,其中100以下为直接对应,100以下可以非线性 +// [0,100] => [0,100] +// [100,120] => [100,MaxFrp] +// 这里假设了 MaxFrp >= 100 +// 对于100以下的部分没什么好说的,此处主要说明100以上的部分如何映射: +// 1) 如果MaxFrp=120,则这部分跟100以下一样,也是线性 +// Value = Index +// 2) 如果MaxFrp<120,则这部分仍以线性方式增长到最大值MaxFrp,到最大值后不增长 +// Value = Index (when Index <= MaxFrp) +// = MaxFrp (when Index >= MaxFrp) +// 3) 如果MaxFrp>120,则这部分以线性叠加指数增长来映射 +// Value = Index * a^(Index - 100) +// 其中 a可由MaxFrp算出,例如 +// MaxFrp = 150 => 150 = 120 * a^(120-100) => a = (1.25)^(0.05) +// ---- 杨开锦 2013-03-26 +void CMachineControlDlg_Left::_BuildFIVMap() +{ + int _nMaxFrp = m_nFValues[120]; + if (CParamManager* _pParamManager = GetParamManager()) + { + const CStringA _c_strMaxFrpIdentifier = "MaxFrp"; + ParameterValue _MaxFrpParamValue; + if (!_pParamManager->GetParameterValue(_c_strMaxFrpIdentifier, &_MaxFrpParamValue) + || _MaxFrpParamValue.nType != ParameterValue::VT_INT + || _MaxFrpParamValue.iValue == _nMaxFrp) + { + // 变化才更新 + return; + } + _nMaxFrp = _MaxFrpParamValue.iValue; + } + + C_ASSERT(_countof(m_nFValues) == 121); + if (_nMaxFrp <= 120) + { + for (int _i = 0; _i < _countof(m_nFValues); _i++) + { + m_nFValues[_i] = min(_i, _nMaxFrp); + } + return; + } + + C_ASSERT(_countof(m_nFValues) == 121); + for (int _i = 0; _i <= 100; _i++) + { + m_nFValues[_i] = _i; + } + double _nA = pow(_nMaxFrp / 120.0, 0.05); + for (int _i = 101; _i < _countof(m_nFValues); _i++) + { + int _nV = (int)(_i * pow(_nA, _i - 100.0) + 0.5); + m_nFValues[_i] = min(_nV, _nMaxFrp); + } +} + +void CMachineControlDlg_Left::_UpdateFValue(int nIndex_, int* pnValue_) +{ + ASSERT(nIndex_ >= 0 && nIndex_ < _countof(m_nFValues) && pnValue_); + *pnValue_ = m_nFValues[nIndex_]; +} + +void CMachineControlDlg_Left::_UpdateFIndex(int* pnIndex_, int nValue_) +{ + ASSERT(pnIndex_ && *pnIndex_ >= 0 && *pnIndex_ < _countof(m_nFValues)); + if (nValue_ == m_nFValues[*pnIndex_]) + { + return; + } + + int _i = 0; + while (_i < _countof(m_nFValues) && m_nFValues[_i] < nValue_) + { + _i++; + } + *pnIndex_ = _i; +} + +LRESULT CMachineControlDlg_Left::OnEndSpeedDlg(WPARAM wParam_, LPARAM lParam_) +{ + m_pSetSpeedDlg->ShowWindow(SW_HIDE); + DWORD _nManuMode = (DWORD)wParam_; + union + { + LPARAM lValue; + float fValue; + } Value; + Value.lValue = lParam_; + double _nValue = (float)Value.fValue; + + CManualTarget* _pManualTarget = GetManualTarget(); + ASSERT(_pManualTarget); + + // 设置手动低速 ---- 郭小航 2013-11-07 + if (_nManuMode == 0) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(false); + + CParamManager* _pParamManager = GetParamManager(); + if (_pParamManager) + { + ParameterValue _ParamValue; + _pParamManager->GetParameterValue("1_0_JVelocityQuick", &_ParamValue); + if (_nValue > _ParamValue.dValue) + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocityQuick", &_ParamValue); + _pParamManager->SetParameterValue("1_0_JVelocity", &_ParamValue); + } + else + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocity", &_ParamValue); + } + } + } + // 设置手动高速 ---- 郭小航 2013-11-07 + else if (_nManuMode == 1) + { + _pManualTarget->SetManuMode(0); + _pManualTarget->SetJogState(true); + + CParamManager* _pParamManager = GetParamManager(); + if (_pParamManager) + { + ParameterValue _ParamValue; + _pParamManager->GetParameterValue("1_0_JVelocity", &_ParamValue); + if (_nValue < _ParamValue.dValue) + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocity", &_ParamValue); + _pParamManager->SetParameterValue("1_0_JVelocityQuick", &_ParamValue); + } + else + { + _ParamValue.dValue = _nValue; + _pParamManager->SetParameterValue("1_0_JVelocityQuick", &_ParamValue); + } + } + } + // 设置步长 ---- 郭小航 2013-11-07 + else if (_nManuMode == 2) + { + _pManualTarget->SetManuMode(1); + _pManualTarget->SetIncDistance(_nValue); + } + + return TRUE; +} + +LRESULT CMachineControlDlg_Left::OnEndEditDistance(WPARAM wParam_, LPARAM lParam_) +{ + ASSERT(lParam_); + CString* _strText = reinterpret_cast(lParam_); + CString _strGetValue = *_strText; + m_pwndStcGoDistance->ShowWindow(SW_SHOW); + if (IsValidDate(_strGetValue, "double", 100000, 0., "mm")) + { + double _nGetValue = _tstof(_strGetValue); + _nGetValue = _FormatInputData(_nGetValue); + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + _pControlTarget->SetGFOBDistance(_nGetValue); + } + + return TRUE; +} + +void CMachineControlDlg_Left::OnLButtonDown(UINT nFlags_, CPoint point_) +{ + if (::IsWindow(m_pDistanceEdit->GetSafeHwnd())) + { + delete m_pDistanceEdit; + m_pDistanceEdit = NULL; + } + else + m_pDistanceEdit = NULL; +} + +// 响应鼠标单击前进后退显示按钮消息。以100/1200处为界,点击前部份:如果是步进模 +// 式则弹出编辑框可编辑前进后退距离,如果是点动模式则不响应。点击后部份:切换前 +// 进后退模式。返回True则表示不再进行消息循环 ---- DingQiang 2012-07-19 +BOOL CMachineControlDlg_Left::OnDistanceLButtonDown(CPoint point_) +{ + CControlTarget* _pControlTarget = GetControlTarget(); + if (!_pControlTarget) + { + return FALSE; + } + + CRect _rcGoDistance; + m_pwndStcGoDistance->GetWindowRect(_rcGoDistance); + double _nWide = _rcGoDistance.Width() * 0.83; + double _nDivide = _rcGoDistance.left + _nWide; + + if (point_.x < _nDivide) + { + if (_pControlTarget->GetGFOBMode() == 0x00) + { + return TRUE; + } + + if (::IsWindow(m_pDistanceEdit->GetSafeHwnd())) + { + // 这样做的目的是防止编辑框已经Create出的时候,又点击到按钮又Create一次 ---- DingQiang 2012-07-20 + return FALSE; + } + + CString _strItemText; + m_pwndStcGoDistance->GetWindowText(_strItemText); + CRect _rect(0, 0, 0, 0); + m_pwndStcGoDistance->GetWindowRect(_rect); + + // new一个编辑框出来,其父窗口为前进后退距离显示框 ---- DingQiang 2012-07-19 + m_pwndStcGoDistance->ScreenToClient(&_rect); + _rect.top += 7; + _rect.bottom -= 6; + _rect.left += 2; + _rect.right -= 2; + DWORD _dwStyle; + _dwStyle = WS_CHILDWINDOW | WS_VISIBLE | WS_BORDER | ES_CENTER | ES_AUTOVSCROLL | ES_NOHIDESEL; + m_pDistanceEdit = new CEditItem(this, _strItemText); + m_pDistanceEdit->Create(_dwStyle, _rect, m_pwndStcGoDistance, CTRLID_EDIT_GODISTANCE); + return TRUE; + } + else + { + DWORD _nSetMode; + if (_pControlTarget->GetGFOBMode() == 0x00) + { + _nSetMode = 0x01; + } + else + _nSetMode = 0x00; + + _pControlTarget->SetGFOBMode(_nSetMode); + return FALSE; + } + + return FALSE; +} + +// 检查数据是否是合法的输入,允许输入正数、小数、单位。不允许负数和字母---- DingQiang 2012-03-07 +bool CMachineControlDlg_Left::IsValidDate(LPCSTR szInPut_, // 输入字符串 + LPCSTR szType_, // 数据类型 + double nMax_, // 允许的最大值 + double nMin_, // 允许的最小值 + LPCSTR szUnit_) // 允许输入单位 +{ + int _nNumDots = 0; // 小数点个数,只允许一个 + CString _strInPut = szInPut_; + CString _strUint = szUnit_; + int _nLength = (int)strlen(_strInPut); // 输入入字符串长度 + int _nUnitLength = (int)strlen(_strUint); // 允许使用的单位字符串长度 + bool b_ContainUnit = false; // 是否包含单位 + + if (0 == _nLength) + { + return false; + } + + // 多于两个小数点则返回false---- DingQiang 2012-03-07 + int _nDotCount = 0; + for (int _i = 0; _i < _nLength; _i++) + { + char _szDot = _strInPut[_i]; + if (_szDot == '.') + { + _nDotCount++; + } + } + + if (_nDotCount > 1) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + + // 先检查字符串后面的_nUnitLength长度是否是数字,如果有一个不是数字则立马判 + // 断后面_nUnitLength个字符是否是单位字符,如果即不是数字也不是单位字符则直 + // 接返回错误信息,不再做其它检查。 ---- DingQiang 2012-03-07 + int _nCheckUint = (_nLength - _nUnitLength) > 0 ? _nLength - _nUnitLength : _nLength; + for (int _j = _nCheckUint; _j < _nLength; _j++) + { + char _szChar = _strInPut[_j]; + if(_szChar < 0 || _szChar > 255) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + if (!isdigit(_szChar)) + { + if (_szChar != '.') + { + if (_strUint.Compare(_strInPut.Right(_nUnitLength)) != 0) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + else + { + b_ContainUnit = true; + } + } + } + } + + // 如果有符号则检查除符号外的字符,如没有符号则全部检查---- DingQiang 2012-03-08 + int _nCheckNum = b_ContainUnit ? _nCheckUint : _nLength; + int _i = 0; + for (; _i < _nCheckNum; _i++) + { + char _c = _strInPut[_i]; + if (!isdigit(_c)) + { + if (0 == strcmp(szType_, "int")) + { + break; + } + else if (0 == strcmp(szType_, "double") || 0 == strcmp(szType_, "float")) + { + if (_c == '.' && _nNumDots == 0) + { + _nNumDots++; + } + else + { + break; + } + } + else + ASSERT(false); + } + } + + if (_i != _nCheckNum && (strcmp(szType_, "int") == 0)) + { + AfxMessageBox(_GETCS(s_csIntDataError)); + return false; + } + + if (_i != _nCheckNum && (strcmp(szType_, "float") == 0 || strcmp(szType_, "double") == 0)) + { + AfxMessageBox(_GETCS(s_csFloatDataError)); + return false; + } + + double _nInPut = (double)_tstof(szInPut_); + if ( _nInPut > nMin_ && _nInPut < nMax_) + { + return true; + } + else + { + CString _strErrorShow; + _strErrorShow.Format(_GETCS(s_csFloatDataBoundError), nMin_, nMax_); + AfxMessageBox(_strErrorShow); + return false; + } +} + +void CMachineControlDlg_Left::OnChangeCoorMode() +{ + m_nCoorMode = (m_nCoorMode == 0x00) ? 0x01 : 0x00; + UpdateMachCoor(); +} + +// 格式化输入 ---- DingQiang 2012-06-25 +static double _FormatInputData(double nInputData_) +{ + ASSERT(nInputData_ >= 0); + CString _strTemp; + _strTemp.Format(_T("%f"), nInputData_); + + CString _strOut = _strTemp.Left(6); + + return _tstof(_strOut); +} + +// 设置手动速度 ---- 郭小航 2013-11-07 +void CMachineControlDlg_Left::OnDblClickCenter() +{ + CStateManager* _pStateManager = GetStateManager(); + if (!_pStateManager) + return; + + CStateManager::State _State = mach::CStateManager::Invalid; + if (!_pStateManager->GetState(&_State)) + { + return; + } + + if (_State != mach::CStateManager::Invalid + && _State != mach::CStateManager::Idle + //&& _State != mach::CStateManager::Lock // 仿真时也不能修改速度。 + && _State != mach::CStateManager::Estop) + { + AfxMessageBox(_GETCS(s_csNotInputPrompt)); + return; + } + + ASSERT(m_pwndBtnCenter && ::IsWindow(m_pwndBtnCenter->m_hWnd)); + CRect _rcBtnCenter; + m_pwndBtnCenter->GetWindowRect(&_rcBtnCenter); + ((CSetSpeedDlg*)m_pSetSpeedDlg)->SetBasePosition(_rcBtnCenter.TopLeft()); + m_pSetSpeedDlg->ShowWindow(SW_SHOW); +} + +LRESULT CMachineControlDlg_Left::OnSliderMoving(WPARAM wParam_, LPARAM lParam_) +{ + CParamManager* _pParamManager = mach::GetParamManager(); + if (!_pParamManager) + { + ASSERT(FALSE); + return 0; + } + + UINT _nCtrlID = (UINT)wParam_; + int _nIndex = (int)lParam_; + if (wParam_ == CTRLID_SLD_SETF) + { + int _nFrp = 100; + _UpdateFValue(_nIndex, &_nFrp); + + // 为安全计,通过CParamManager修改参数都会全部检查所有参数,在此处可能并 + // 非必须的,且全部检查会让进给倍率条显得卡起来,有拖尾。 因此,此处我们 + // 通过造一个Command来绕过全部检查。 ---- 杨开锦 2012-08-17 + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetFrpCommand = "SetFrp"; + CStringA _strFrp; + _strFrp.Format("%d", _nFrp); + _pCommandManager->Execute(_c_strSetFrpCommand, _strFrp, "LPCSTR"); + } + if (m_bSliderCtrlG00) + { + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetG00FrpCommand = "SetG00Frp"; + CStringA _strFrp; + _strFrp.Format("%d", _nFrp); + _pCommandManager->Execute(_c_strSetG00FrpCommand, _strFrp, "LPCSTR"); + } + } + + UpdateF(); + } + + if (wParam_ == CTRLID_SLD_SETFH) + { + double _nValue; + _UpdateFHValue(_nIndex, &_nValue); + ParameterValue _Value; + memset(&_Value, 0, sizeof(ParameterValue)); + _pParamManager->GetParameterValue("ActualSampleLength", &_Value); + if (_Value.nType != ParameterValue::VT_DOUBLE) + { + return 0; + } + _nValue = min(_nValue, _Value.dValue); + + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetFHCommand = "SetFollowHeight"; + CStringA _strFH; + _strFH.Format("%.3f", _nValue); + _pCommandManager->Execute(_c_strSetFHCommand, _strFH, "LPCSTR"); + } + UpdateFH(); + } + + if (wParam_ == CTRLID_SLD_SETP) + { + if (CCommandManager* _pCommandManager = GetCommandManager()) + { + const CStringA _c_strSetPowerCommand = "SetDutyCycles"; + CStringA _strPower; + _strPower.Format("%d", _nIndex); + _pCommandManager->Execute(_c_strSetPowerCommand, _strPower, "LPCSTR"); + } + UpdateP(); + } + return 1; +} + +void CMachineControlDlg_Left::OnClickMachSelected() +{ + //CStateManager* _pStateManager = GetStateManager(); + //ASSERT(_pStateManager); + //CStateManager::State _nState = CStateManager::Idle; + //BOOL _bEnable = _pStateManager->GetState(&_nState) && _nState == CStateManager::Idle; + //if (!_bEnable) + // return; + + //CButton* _pBtn = (CButton*)GetDlgItem(CTRLID_BTN_MACHSELECTED); + //BOOL _bMachSelected = _pBtn->GetCheck() == BST_CHECKED; + //_bMachSelected = !_bMachSelected; + //m_bSelectMach = _bMachSelected; + //_pStateManager->SetSelectedMach(m_bSelectMach); + //_pBtn->SetCheck(_bMachSelected ? BST_CHECKED : BST_UNCHECKED); +} + +void CMachineControlDlg_Left::OnCloseMachSelected() +{ + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + CStateManager::State _nState = CStateManager::Idle; + BOOL _bEnable = _pStateManager->GetState(&_nState) && _nState == CStateManager::Idle; + if (!_bEnable) + return; + + ASSERT(m_bSelectMach == TRUE); + m_bSelectMach = FALSE; + _pStateManager->SetSelectedMach(m_bSelectMach); + m_pwndBtnSelMachOn->ShowWindow(m_bSelectMach ? SW_SHOW : SW_HIDE); + m_pwndBtnSelMachOff->ShowWindow(m_bSelectMach ? SW_HIDE : SW_SHOW); +} + +void CMachineControlDlg_Left::OnOpenMachSelected() +{ + CStateManager* _pStateManager = GetStateManager(); + ASSERT(_pStateManager); + CStateManager::State _nState = CStateManager::Idle; + BOOL _bEnable = _pStateManager->GetState(&_nState) && _nState == CStateManager::Idle; + if (!_bEnable) + return; + + ASSERT(m_bSelectMach == FALSE); + m_bSelectMach = TRUE; + _pStateManager->SetSelectedMach(m_bSelectMach); + m_pwndBtnSelMachOn->ShowWindow(m_bSelectMach ? SW_SHOW : SW_HIDE); + m_pwndBtnSelMachOff->ShowWindow(m_bSelectMach ? SW_HIDE : SW_SHOW); +} + +void CMachineControlDlg_Left::OnClickJogLaser() +{ + bool _bValue = false; + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("EnableJogLaser", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_BOOL) + { + _bValue = _ParamValue.bValue; + } + else + { + ASSERT(FALSE); + return; + } + + _ParamValue.bValue = !_bValue; + _pParamManager->SetParameterValue("EnableJogLaser", &_ParamValue); + UpdateEnableJogLaser(); +} + +void CMachineControlDlg_Left::OnCloseJogLaser() +{ + bool _bValue = false; + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("EnableJogLaser", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_BOOL) + { + _bValue = _ParamValue.bValue; + // ASSERT(_bValue = TRUE); + } + else + { + ASSERT(FALSE); + return; + } + + _ParamValue.bValue = FALSE; + _pParamManager->SetParameterValue("EnableJogLaser", &_ParamValue); + + m_pwndBtnJogLaserOn->ShowWindow(SW_HIDE); + m_pwndBtnJogLaserOff->ShowWindow(SW_SHOW); + + UpdateEnableJogLaser(); +} + +void CMachineControlDlg_Left::OnOpenJogLaser() +{ + bool _bValue = false; + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("EnableJogLaser", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_BOOL) + { + _bValue = _ParamValue.bValue; + //ASSERT(_bValue = FALSE); + } + else + { + ASSERT(FALSE); + return; + } + + _ParamValue.bValue = TRUE; + _pParamManager->SetParameterValue("EnableJogLaser", &_ParamValue); + + m_pwndBtnJogLaserOn->ShowWindow(SW_SHOW); + m_pwndBtnJogLaserOff->ShowWindow(SW_HIDE); + + UpdateEnableJogLaser(); +} + +void CMachineControlDlg_Left::OnClickAutoCyc() +{ + bool _bEnable1 = false; + bool _bEnable2 = false; + + CParamManager* _pParamManager = GetParamManager(); + ASSERT(_pParamManager); + ParameterValue _ParamValue; + memset(&_ParamValue, 0, sizeof(ParameterValue)); + if(_pParamManager->GetParameterValue("AutoExchangeTaskEnd", &_ParamValue) + && _ParamValue.nType == mach::ParameterValue::VT_INT) + { + if(_ParamValue.iValue == 1) + { + _bEnable1 = true; + } + else + { + ASSERT(_ParamValue.iValue == 0); + _bEnable1 = false; + } + } + else + { + return; + } + + CCycMachiningTarget* _pCycMachingTarget = GetCycMachiningTarget(); + int _nCycTimes = _pCycMachingTarget->GetCycTimes(); + BOOL _bCycEnable= _pCycMachingTarget->GetEnable(); + if(_bCycEnable == TRUE) + { + _bEnable2 = true; + } + else + { + _bEnable2 = false; + } + + bool _bEnable = _bEnable1 && _bEnable2; + + + if(_bEnable) + { + memset(&_ParamValue, 0, sizeof(ParameterValue)); + _ParamValue.nType = ParameterValue::VT_INT; + _ParamValue.iValue = 0; + _pParamManager->SetParameterValue("AutoExchangeTaskEnd", &_ParamValue); + + _pCycMachingTarget->SetEnable(FALSE); + } + else + { + memset(&_ParamValue, 0, sizeof(ParameterValue)); + _ParamValue.nType = ParameterValue::VT_INT; + _ParamValue.iValue = 1; + _pParamManager->SetParameterValue("AutoExchangeTaskEnd", &_ParamValue); + + _pCycMachingTarget->SetEnable(TRUE); + } + UpdateEnableAutoCyc(); + SendTargetMessage(ID_TARGET_EXCHANGEWORKBENCH, TM_AUTOCYC_CHECK, 0, 0); +} + +void CMachineControlDlg_Left::OnClickCycMach() +{ + CCycMachiningTarget* _pCycMachiningTarget = GetCycMachiningTarget(); + ASSERT(_pCycMachiningTarget); + + bool _bCycMach = _pCycMachiningTarget->GetEnable(); + _bCycMach = !_bCycMach; + + _pCycMachiningTarget->SetEnable(_bCycMach); + m_pwndBtnCycMach->SetCheck(_bCycMach); +} + +void CMachineControlDlg_Left::UpdateCycMach() +{ + // 循环加工 + CCycMachiningTarget* _pCycMachiningTarget = GetCycMachiningTarget(); + ASSERT(_pCycMachiningTarget); + + bool _bCycMach = _pCycMachiningTarget->GetEnable(); + m_pwndBtnCycMach->SetCheck(_bCycMach); +} + +HBRUSH CMachineControlDlg_Left::OnCtlColor(CDC* pDC_, CWnd* pWnd_, UINT nCtlColor_) +{ + HBRUSH _hBrush = __super::OnCtlColor(pDC_, pWnd_, nCtlColor_); + + //COLORREF _clrTextColor; + //if (CNceTheme::GetElement("ToolbarTextColor", &_clrTextColor)) + //{ + // pDC_->SetTextColor(_clrTextColor); + //} + + //if (m_brush) + //{ + // pDC_->SetBkMode(TRANSPARENT); + // return m_brush; + //} + + //return _hBrush; + + //pDC_->SetBkMode(TRANSPARENT); + return m_brush; +} + +BOOL CMachineControlDlg_Left::OnEraseBkgnd(CDC* pDC) +{ + // 绘制黑色背景 ---- 吴畏 2017-03-29 + CPaintDC dc(this); + CRect _rect; + GetClientRect(_rect); + CBrush _brush; + _brush.CreateSolidBrush(COLORREF(RGB(0, 0, 0))); + dc.FillRect(&_rect,&_brush); + _brush.DeleteObject(); + + return TRUE; +} + +void CMachineControlDlg_Left::BufferDraw(CDC* pDC) +{ + BITMAP bmp;//储存位图信息的结构体 + CRect rect; + GetClientRect(rect);//获取客户区域的矩形 + bufferdc.CreateCompatibleDC(NULL);//创建兼容DC + bufferbmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());//创建兼容位图 + bufferdc.SelectObject(&bufferbmp);//将位图选入内存区域 + CBitmap *pOldBit = bufferdc.SelectObject(&bufferbmp); + bufferbmp.GetBitmap(&bmp);//获取内存位图的信息 + //在此处添加绘制代码 + + + SetStretchBltMode(pDC->m_hDC, STRETCH_HALFTONE); + pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &bufferdc, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);//将内存中的内容复制到设备 + bufferdc.DeleteDC(); //删除DC + bufferbmp.DeleteObject(); //删除位图 +} + +void CMachineControlDlg_Left::OnDraw(CDC* pDC) +{ + /*CDocument* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + if (!pDoc) + return;*/ + BufferDraw(pDC); +} + +void CMachineControlDlg_Left::OnPaint() +{ + CRect PaintRect; + CPaintDC dc(this); + CDC MemDC; + CBitmap MemBitmap; + + // 双缓冲绘图 + GetClientRect(PaintRect); + if (MemDC.CreateCompatibleDC(&dc)) + { + if (MemBitmap.CreateCompatibleBitmap(&dc, PaintRect.Width(), PaintRect.Height())) + { + if (HGDIOBJ OldObject = MemDC.SelectObject(MemBitmap)) + { + // 拷贝背景图, 以处理透明色 + if (MemDC.BitBlt(0, 0, PaintRect.Width(), PaintRect.Height(), &dc, 0, 0, SRCCOPY)) + { + Gdiplus::Graphics g(MemDC); + + // Paint here ... + + dc.BitBlt(0, 0, PaintRect.Width(), PaintRect.Height(), &MemDC, 0, 0, SRCCOPY); + } + MemDC.SelectObject(OldObject); + } + MemBitmap.DeleteObject(); + } + MemDC.DeleteDC(); + } +} + +void CMachineControlDlg_Left::OnMinSize() +{ + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + + if (_pControlTarget->GetMinSize()) + { + return; + } + + CRect _rect; + GetClientRect(&_rect); + int _width = _rect.Width(); + int _nHeight = _rect.Height(); + + HWND _hwnd = GetSafeHwnd(); + ASSERT(_hwnd); + ::MoveWindow(_hwnd, 0, 0, 20, _nHeight, true); + + _pControlTarget->SetMinSize(true); + m_pwndBtnMax->ShowWindow(SW_SHOW); +} + +void CMachineControlDlg_Left::OnMaxSize() +{ + CControlTarget* _pControlTarget = GetControlTarget(); + ASSERT(_pControlTarget); + + if (!_pControlTarget->GetMinSize()) + { + return; + } + + HWND _hwnd = GetSafeHwnd(); + ASSERT(_hwnd); + CRect _rect; + GetClientRect(&_rect); + int _width = _rect.Width(); + int _nHeight = _rect.Height(); + + ::MoveWindow(_hwnd, 0, 0, 536, _nHeight, true); + + _pControlTarget->SetMinSize(false); + + m_pwndBtnMax->ShowWindow(SW_HIDE); +} + +void CMachineControlDlg_Left::OnSelMarkPoint() +{ + // 加载标记点选项菜单 ---- 边俊霞 2017-05-11 + CRect _rcRect; + GetDlgItem(CTRLID_BTN_SELMARKPOINT)->GetWindowRect(&_rcRect); + m_pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_LEFTBUTTON, _rcRect.right, _rcRect.bottom, this); +} + +void CMachineControlDlg_Left::OnMarkPointChange(UINT ID_) +{ + // 在标记点按钮上显示当前选择的标记点index ---- 边俊霞 2017-03-14 + UINT _nCurIndex = ID_ - CTRLID_BTN_MARKPOINT1 + 1; + m_nCurIndex = _nCurIndex; + CString _strCurIndex; + _strCurIndex.Format("%u", _nCurIndex); + + // 使数字在button上不居中显示 ---- 边俊霞 2017-03-15 + CString _strShowIndex = _strCurIndex + '\n'; + SetDlgItemText(CTRLID_BTN_SELMARKPOINT, _strShowIndex); + + // 将当前选择的标记点index传到MarkPointTarget ---- 边俊霞 2017-03-14 + CMarkPointTarget* _pMarkPointTarget = GetMarkPointTarget(); + ASSERT(_pMarkPointTarget); + _pMarkPointTarget->SetCurMarkIndex(_nCurIndex - 1); +} diff --git a/src/MicroJointTarget.cpp b/src/MicroJointTarget.cpp new file mode 100644 index 0000000..27f95c3 --- /dev/null +++ b/src/MicroJointTarget.cpp @@ -0,0 +1,2791 @@ +// ************************************************************************** // +// MicroJointTarget.cpp : implementation of the CMicroJointTarget class +// Copyright(c)2016 WeiHong Company. All rights reserved. +// +// Abstract: +// 本文件实现CMicroJointTarget类。 +// *********************************************** ---- 丁强 2016-03-09***** // +#include "stdafx.h" +#include "IntroPosCalculator.h" +#include "ExplodeMicrJointAction.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +using namespace nce; +using namespace std; +using namespace ncmath; + +CS_T s_szManualSetFailed = _DEFCS(_CSV(16347), + _CHINESE("|E|此处不能设置微连点,请重新选择!") + _ENGLISH("|E|This place can't set microjoint,Please select again!")); +CS_T s_szNoSelectedObject = _DEFCS(_CSV(16347), + _CHINESE("|E|没有选中对象,自动微连失败!") + _ENGLISH("|E|No seleceted objects, Auto micro-joint failed!")); +CS_T s_szAutoSetFailed = _DEFCS(_CSV(16347), + _CHINESE("|E|没有可自动微连的图形,自动微连失败!") + _ENGLISH("|E|No object can micro joint,Auto micro-joint failed!")); + +const CHAR c_szMJ[] = "MJ%d"; +const CHAR c_szMJFormat[] = "(%d,%lf,%lf)"; +const CHAR c_szScanCamGXXNodes[] = "ScanCamGxxNodes"; + +IMPLEMENT_DYNAMIC(CMicroJointTarget, CMouseMsgTarget) +BEGIN_MESSAGE_MAP(CMicroJointTarget, CMouseMsgTarget) + ON_COMMAND(IDCMD_MICROJOINTTARGET_MICROJOINT, OnMicroJoint) + ON_UPDATE_COMMAND_UI(IDCMD_MICROJOINTTARGET_MICROJOINT, OnUpdateMicroJoint) + ON_COMMAND(IDCMD_MICROJOINTTARGET_CLEARMICROJOINT, OnClearMicroJoint) + ON_UPDATE_COMMAND_UI(IDCMD_MICROJOINTTARGET_CLEARMICROJOINT, OnUpdateClearMicroJoint) + ON_COMMAND(IDCMD_MICROJOINTTARGET_EXPLODEMICROJOINT, OnExplodeMicroJoint) + ON_UPDATE_COMMAND_UI(IDCMD_MICROJOINTTARGET_EXPLODEMICROJOINT, OnUpdateExplodeMicroJoint) + ON_TARGET_NOTIFY(TN_CADDIR_CHANGE, OnCadDirChanged) +END_MESSAGE_MAP() + +static bool FindObjectByID(IN CCadObject* pCadObj_, IN int nID_, OUT CCadObject** ppResult_); +static double GetCadLength(IN const CCadObject* pCadObj_); + +CMicroJointTarget* CMicroJointTarget::ms_pMicroJointTarget = NULL; +CMicroJointTarget* GetMicroJointTarget() +{ + return CMicroJointTarget::ms_pMicroJointTarget; +} + +CMicroJointTarget::CMicroJointTarget() +{ + ASSERT(ms_pMicroJointTarget == NULL); + ms_pMicroJointTarget = this; + m_nMicroJointLength = 1; + m_bNoPause = FALSE; + LOAD_PARAM(this,CMicroJointTarget); + Reset(); + m_hCursor = AfxGetApp()->LoadCursor(IDC_CUR_ADDBRIDGE); +} + +CMicroJointTarget::~CMicroJointTarget() +{ + SAVE_PARAM(this, CMicroJointTarget); +} + +CCadObject* CMicroJointTarget::CreateToolPath(const nce::CCadObject* pCadObject_) +{ + CStringA _strKey; + _strKey.Format(c_szMJ, 0); + if (pCadObject_->GetKey(_strKey).IsEmpty()) + { + return NULL; + } + + switch (pCadObject_->GetType()) + { + case cadline: + return m_bNoPause ? _CreateLineToolPath2((CCadLine*)pCadObject_) : _CreateLineToolPath((CCadLine*)pCadObject_); + break; + case cadcircle: + return m_bNoPause ? _CreateCircleToolPath2((CCadCircle*)pCadObject_) : _CreateCircleToolPath((CCadCircle*)pCadObject_); + break; + case cadarc: + return m_bNoPause ? _CreateArcToolPath2((CCadArc*)pCadObject_) : _CreateArcToolPath((CCadArc*)pCadObject_); + break; + case cadellipse: + return m_bNoPause ? _CreateEllipseToolPath2((CCadEllipse*)pCadObject_) : _CreateEllipseToolPath((CCadEllipse*)pCadObject_); + break; + case cadellipsearc: + return m_bNoPause ? _CreateEllipseArcToolPath2((CCadEllipseArc*)pCadObject_) : _CreateEllipseArcToolPath((CCadEllipseArc*)pCadObject_); + break; + case cadpath: + case cadpolygon: + case cadpolyline: + case cadstar: + case cadrectangle: + return m_bNoPause ? _CreateMultiSegmentToolPath2((CCadMultiSegments*)pCadObject_) : _CreateMultiSegmentToolPath((CCadMultiSegments*)pCadObject_); + break; + } + + return NULL; +} + +CCadObject* CMicroJointTarget::_CreateLineToolPath(const nce::CCadLine* pCadLine_) +{ + CCadGroup* _pCadGroup = new CCadGroup; + + int _nIndex = 0; + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadLine_->GetKey(_strKeyMJ); + DPOINT2 _ptStartPoint = pCadLine_->GetStartPoint(); + + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + DPOINT2 _ptEndPoint = (pCadLine_->GetEndPoint() - pCadLine_->GetStartPoint()) * _nRatio + pCadLine_->GetStartPoint(); + + if (_ptStartPoint != _ptEndPoint) + { + CCadLine* _pCadLine = new CCadLine(_ptStartPoint, _ptEndPoint); + _pCadGroup->PushBack(_pCadLine); + } + + _ptStartPoint = pCadLine_->GetStartPoint() + (pCadLine_->GetEndPoint() - pCadLine_->GetStartPoint()) * (_nRatio + _nLength / pCadLine_->GetLength()); + + _nIndex++; + _strKeyMJ.Format(c_szMJ, _nIndex); + _strValueTemp = pCadLine_->GetKey(_strKeyMJ); + } + + if (_ptStartPoint != pCadLine_->GetEndPoint()) + { + _pCadGroup->PushBack(new CCadLine(_ptStartPoint, pCadLine_->GetEndPoint())); + } + + if (_pCadGroup->GetNumOfChild() == 0) + { + delete _pCadGroup; + _pCadGroup = NULL; + } + return _pCadGroup; +} + +CCadObject* CMicroJointTarget::_CreateCircleToolPath(const CCadCircle* pCadCircle_) +{ + CCadGroup* _pCadGroup = new CCadGroup; + + int _nIndex = 0; + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadCircle_->GetKey(_strKeyMJ); + double _nStartAngle = 0; + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + + double _nCenterAngle = 2 * c_nPIE * _nRatio - _nStartAngle; + if (!DOUBLE_EQU_ZERO(_nCenterAngle)) + { + //修改顺时针情况下,加微连的圆加工轨迹不正确的修改----2017-4-27 张磊 + if(!pCadCircle_->IsNormalDir()) + { + CCadArc* _pCadArc = new CCadArc(pCadCircle_->GetCenterPoint(), pCadCircle_->GetRadius(), + _nStartAngle+_nCenterAngle, _nCenterAngle, pCadCircle_->IsNormalDir()); + _pCadGroup->PushFront(_pCadArc); + } + else + { + CCadArc* _pCadArc = new CCadArc(pCadCircle_->GetCenterPoint(), pCadCircle_->GetRadius(), + _nStartAngle, _nCenterAngle, pCadCircle_->IsNormalDir()); + _pCadGroup->PushBack(_pCadArc); + } + } + + _nStartAngle = _nStartAngle + _nCenterAngle + (_nLength / pCadCircle_->GetLength()) * 2 * c_nPIE; + + _nIndex++; + _strKeyMJ.Format(c_szMJ, _nIndex); + _strValueTemp = pCadCircle_->GetKey(_strKeyMJ); + } + + if (DOUBLE_LESS(_nStartAngle, 2 * c_nPIE)) + { + //修改顺时针情况下,加微连的圆加工轨迹不正确的修改----2017-4-27 张磊 + if(!pCadCircle_->IsNormalDir()) + { + _pCadGroup->PushFront(new CCadArc(pCadCircle_->GetCenterPoint(), pCadCircle_->GetRadius(),0, 2 * c_nPIE - _nStartAngle, pCadCircle_->IsNormalDir())); + } + else + { + _pCadGroup->PushBack(new CCadArc(pCadCircle_->GetCenterPoint(), pCadCircle_->GetRadius(),_nStartAngle, 2 * c_nPIE - _nStartAngle, pCadCircle_->IsNormalDir())); + } + } + + if (_pCadGroup->GetNumOfChild() == 0) + { + delete _pCadGroup; + _pCadGroup = NULL; + } + return _pCadGroup; +} + +CCadObject* CMicroJointTarget::_CreateArcToolPath(const nce::CCadArc* pCadArc_) +{ + CCadGroup* _pCadGroup = new CCadGroup; + + int _nIndex = 0; + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadArc_->GetKey(_strKeyMJ); + double _nStartAngle = pCadArc_->GetStartAngle(); + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + double _nCenterAngle = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + if (pCadArc_->IsNormalDir()) + { + _nCenterAngle = (pCadArc_->GetCentralAngle() * _nRatio + pCadArc_->GetStartAngle()) - _nStartAngle; + } + //顺时针方向弧度计算,与之前逆时针方向反过来计算,因为startangle是从大到小的变化 + else + { + _nCenterAngle = pCadArc_->GetCentralAngle() * _nRatio - (pCadArc_->GetStartAngle() - _nStartAngle); + } + + NormalizeRadian(_nCenterAngle); + if (!DOUBLE_EQU_ZERO(_nCenterAngle)) + { + CCadArc* _pCadArc = new CCadArc(pCadArc_->GetCenterPoint(), pCadArc_->GetRadius(), + _nStartAngle, _nCenterAngle, pCadArc_->IsNormalDir()); + _pCadGroup->PushBack(_pCadArc); + } + if(pCadArc_->IsNormalDir()) + { + _nStartAngle = _nStartAngle + _nCenterAngle + (_nLength / pCadArc_->GetLength()) * pCadArc_->GetCentralAngle(); + } + //因为顺时针方向角度是逐渐减小,所以算下一个角度应该是上一个角度减去相对应的偏移角度 + else + { + _nStartAngle = _nStartAngle - _nCenterAngle - (_nLength / pCadArc_->GetLength()) * pCadArc_->GetCentralAngle(); + } + + NormalizeRadian(_nStartAngle); + + _nIndex++; + _strKeyMJ.Format(c_szMJ, _nIndex); + _strValueTemp = pCadArc_->GetKey(_strKeyMJ); + } + + if (!DOUBLE_EQU(_nStartAngle, pCadArc_->GetEndAngle())) + { + double _nCenterAngle = 0.; + if (pCadArc_->IsNormalDir()) + { + _nCenterAngle = pCadArc_->GetEndAngle() - _nStartAngle; + } + else + { + _nCenterAngle = _nStartAngle- pCadArc_->GetEndAngle(); + } + + if (_nCenterAngle < 0.) + { + _nCenterAngle += 2 * c_nPIE; + } + _pCadGroup->PushBack(new CCadArc(pCadArc_->GetCenterPoint(), pCadArc_->GetRadius(),_nStartAngle, _nCenterAngle, pCadArc_->IsNormalDir())); + } + + if (_pCadGroup->GetNumOfChild() == 0) + { + delete _pCadGroup; + _pCadGroup = NULL; + } + return _pCadGroup; +} + +CCadObject* CMicroJointTarget::_CreateMultiSegmentToolPath(const nce::CCadMultiSegments* pCadMultiSegments_) +{ + CCadGroup* _pCadGroup = new CCadGroup; + int _nIndex = 0; + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadMultiSegments_->GetKey(_strKeyMJ); + DPOINT2 _ptStartPoint = pCadMultiSegments_->GetStartPoint(); + int _nSegmentCount = pCadMultiSegments_->GetSegmentCount(); // 多段线的总段数 ---- yangxiaobin 2017-05-16 + int _nTailSegCount = 0; + double _nTaliRatio = 0.; + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + + if (_nSeg >= _nSegmentCount) + { + TRACE("EXCEPTION: MJ %s out of _nSegmentCount=%d at CMicroJointTarget:%d.\n", _strValueTemp, _nSegmentCount, __LINE__); + // ASSERT(_nSeg < _nSegmentCount); + break; + } + + if(_nTailSegCount >= _nSegmentCount) + { + TRACE("EXCEPTION: MJ %s out of _nSegmentCount=%d at CMicroJointTarget:%d.\n", _strValueTemp, _nSegmentCount, __LINE__); + // ASSERT(_nTailSegCount < _nSegmentCount); + break; + } + + CCadPolyline* _pCadPolyline = new CCadPolyline; + _pCadPolyline->SetStartPoint(_ptStartPoint); + while(_nTailSegCount < _nSeg) + { + SEGMENT _Segment = pCadMultiSegments_->GetSegment(_nTailSegCount); + // 如果开头单独的那段圆弧或者线段过短,为了方便解析器处理,我们就直接认为这部分不存在,把它算到之前微连的部分上 + if (_Segment.GetLength() * (1 - _nTaliRatio) > 1e-6) + { + if (_Segment.nType == SEGMENT::LINE) + { + _pCadPolyline->AddLine(_Segment.ptEnd); + } + else if (_Segment.nType == SEGMENT::ARC) + { + DPOINT2 _ptCenter; + double _nRadius,_nStartAngle,_nSweptAngele; + SEGMENT::SolveArc(_Segment.ptStart, + _Segment.ptEnd, + _Segment.nBulge, + &_ptCenter, + &_nRadius, + &_nStartAngle, + &_nSweptAngele); + + // 实际加工发现光限制长度不合适,如果圆弧半径过大任然可能出现凸度在1e-10的情况,所以 + // 还要算下凸度,如果足够小,就当成线段处理 + if (abs(tan((1 - _nTaliRatio) * _nSweptAngele / 4)) > 1e-9) + { + _pCadPolyline->AddArc(_Segment.ptEnd, tan((1 - _nTaliRatio) * _nSweptAngele / 4)); + } + else + { + _pCadPolyline->AddLine(_Segment.ptEnd); + } + } + else + { + ASSERT(FALSE); + } + } + // 如果过短,如果是线段,直接加上去,如果是弧,直接变为线段加上去,取消小圆弧 + else + { + _pCadPolyline->AddLine(_Segment.ptEnd); + + } + _nTaliRatio = 0; + _nTailSegCount++; + } + SEGMENT _Segment = pCadMultiSegments_->GetSegment(_nTailSegCount); + if (_Segment.nType == SEGMENT::LINE) + { + _pCadPolyline->AddLine(_Segment.GetPoint(_nRatio)); + } + else if (_Segment.nType == SEGMENT::ARC) + { + DPOINT2 _ptCenter; + double _nRadius,_nStartAngle,_nSweptAngele; + SEGMENT::SolveArc(_Segment.ptStart, + _Segment.ptEnd, + _Segment.nBulge, + &_ptCenter, + &_nRadius, + &_nStartAngle, + &_nSweptAngele); + + _pCadPolyline->AddArc(_Segment.GetPoint(_nRatio), tan(_nSweptAngele * (_nRatio - _nTaliRatio) / 4)); + } + else + { + ASSERT(FALSE); + } + + if (_pCadPolyline->GetNodeCount() <= 0) + { + delete _pCadPolyline; + _pCadPolyline = NULL; + } + else + { + _pCadGroup->PushBack(_pCadPolyline); + } + _nTaliRatio = _nRatio; + + double _nNeedLength = _Segment.GetLength() * _nRatio + _nLength; + while(DOUBLE_GREAT(_nLength, 0) && _nTailSegCount < pCadMultiSegments_->GetSegmentCount()) + { + SEGMENT _Segment = pCadMultiSegments_->GetSegment(_nTailSegCount); + double _nSegLength =_Segment.GetLength(); + if (_nSegLength > _nNeedLength) + { + _ptStartPoint =_Segment.GetPoint(_nNeedLength / _nSegLength); + _nTaliRatio = _nNeedLength / _nSegLength; + break; + } + + _nNeedLength -= _nSegLength; + _nTailSegCount++; + } + + _nIndex++; + _strKeyMJ.Format(c_szMJ, _nIndex); + _strValueTemp = pCadMultiSegments_->GetKey(_strKeyMJ); + } + + if (_ptStartPoint != pCadMultiSegments_->GetEndPoint() + && _nTailSegCount < pCadMultiSegments_->GetSegmentCount()) + { + CCadPolyline* _pCadPolyine = new CCadPolyline; + _pCadPolyine->SetStartPoint(pCadMultiSegments_->GetSegment(_nTailSegCount).GetPoint(_nTaliRatio)); + bool _bFirst = true; + while(_nTailSegCount < pCadMultiSegments_->GetSegmentCount()) + { + SEGMENT _Segment = pCadMultiSegments_->GetSegment(_nTailSegCount); + + // 第一段是最后一个微连加上后剩下的边角料 + if (_bFirst) + { + // 如果这段长度不能忽略,就老老实实加进去 + if(_Segment.GetLength() * (1 - _nTaliRatio) > 1e-6) + { + if (_Segment.nType == SEGMENT::LINE) + { + _pCadPolyine->AddLine(_Segment.ptEnd); + } + else if (_Segment.nType == SEGMENT::ARC) + { + DPOINT2 _ptCenter; + double _nRadius,_nStartAngle,_nSweptAngele; + SEGMENT::SolveArc(_Segment.ptStart, + _Segment.ptEnd, + _Segment.nBulge, + &_ptCenter, + &_nRadius, + &_nStartAngle, + &_nSweptAngele); + // 实际加工发现光限制长度不合适,如果圆弧半径过大任然可能出现凸度在1e-10的情况,所以 + // 还要算下凸度,如果足够小,就当成线段处理 + if (abs(tan(_nSweptAngele * (1-_nTaliRatio) / 4)) > 1e-9) + { + _pCadPolyine->AddArc(_Segment.ptEnd, tan(_nSweptAngele * (1-_nTaliRatio) / 4)); + } + else + { + _pCadPolyine->AddLine(_Segment.ptEnd); + } + } + else + { + ASSERT(FALSE); + } + } + else + { + //同上,如果过短,如果是线段,直接加上去,如果是弧,直接变为线段加上去 + _pCadPolyine->AddLine(_Segment.ptEnd); + } + _bFirst = false; + } + + // 后面的就直接把整段加进去 + else + { + if (_Segment.nType == SEGMENT::LINE) + { + _pCadPolyine->AddLine(_Segment.ptEnd); + } + else if (_Segment.nType == SEGMENT::ARC) + { + _pCadPolyine->AddArc(_Segment.ptEnd, _Segment.nBulge); + } + else + { + ASSERT(FALSE); + } + } + + _nTailSegCount++; + } + if (_pCadPolyine->GetNodeCount() <= 0) + { + delete _pCadPolyine; + _pCadPolyine = NULL; + } + else + { + _pCadGroup->PushBack(_pCadPolyine); + } + } + + if (_pCadGroup->GetNumOfChild() == 0) + { + delete _pCadGroup; + _pCadGroup = NULL; + } + return _pCadGroup; +} + + +CCadObject* CMicroJointTarget::_CreateEllipseToolPath(const CCadEllipse* pCadEllipse_) +{ + CCadPolyline* _pCadPolyline = TranslateObjectToPolyline(pCadEllipse_); + _pCadPolyline->SetParamString(pCadEllipse_->GetParamString()); + CCadMultiSegments* _pCadMultiSegments = (CCadMultiSegments*)(_pCadPolyline); + // 椭圆里存的比率是把椭圆当作一段来处理的,也就是存的是整体比率,转换成多义 + // 线的时候要把这个比率转换成多义线里的段号和比率 ---- DingQiang 2016-04-27 + int _nIndex = 0; + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadEllipse_->GetKey(_strKeyMJ); + DPOINT2 _ptStartPoint = _pCadMultiSegments->GetStartPoint(); + int _nTailSegCount = 0; + double _nTaliRatio = 0.; + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + double _nTargetLength = _pCadMultiSegments->GetLength() * _nRatio; + double _nLengthTemp = 0.; + int _nSegTemp = 0; + while(_nLengthTemp < _nTargetLength && _nSegTemp < _pCadMultiSegments->GetSegmentCount()) + { + SEGMENT _segment = _pCadMultiSegments->GetSegment(_nSegTemp); + if (_nLengthTemp + _segment.GetLength() >= _nTargetLength) + { + double _nRatio = (_nTargetLength - _nLengthTemp) / _segment.GetLength(); + _strValueTemp.Format(c_szMJFormat, _nSegTemp, _nRatio, _nLength); + _pCadMultiSegments->SetKey(_strKeyMJ, _strValueTemp); + break; + } + _nLengthTemp += _segment.GetLength(); + _nSegTemp++; + } + _nIndex++; + _strKeyMJ.Format(c_szMJ, _nIndex); + _strValueTemp = _pCadMultiSegments->GetKey(_strKeyMJ); + } + + CCadObject* _pObjectRet = _CreateMultiSegmentToolPath(_pCadMultiSegments); + delete _pCadPolyline; + _pCadPolyline = NULL; + return _pObjectRet; +} + +CCadObject* CMicroJointTarget::_CreateEllipseArcToolPath(const nce::CCadEllipseArc* pCadEllipseArc_) +{ + CCadPolyline* _pCadPolyline = TranslateObjectToPolyline(pCadEllipseArc_); + _pCadPolyline->SetParamString(pCadEllipseArc_->GetParamString()); + CCadMultiSegments* _pCadMultiSegments = (CCadMultiSegments*)(_pCadPolyline); + // 椭圆里存的比率是把椭圆当作一段来处理的,也就是存的是整体比率,转换成多义 + // 线的时候要把这个比率转换成多义线里的段号和比率 ---- DingQiang 2016-04-27 + int _nIndex = 0; + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadEllipseArc_->GetKey(_strKeyMJ); + DPOINT2 _ptStartPoint = _pCadMultiSegments->GetStartPoint(); + int _nTailSegCount = 0; + double _nTaliRatio = 0.; + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + double _nTargetLength = _pCadMultiSegments->GetLength() * _nRatio; + double _nLengthTemp = 0.; + int _nSegTemp = 0; + while(_nLengthTemp < _nTargetLength && _nSegTemp < _pCadMultiSegments->GetSegmentCount()) + { + SEGMENT _segment = _pCadMultiSegments->GetSegment(_nSegTemp); + if (_nLengthTemp + _segment.GetLength() >= _nTargetLength) + { + double _nRatio = (_nTargetLength - _nLengthTemp) / _segment.GetLength(); + _strValueTemp.Format(c_szMJFormat, _nSegTemp, _nRatio, _nLength); + _pCadMultiSegments->SetKey(_strKeyMJ, _strValueTemp); + break; + } + _nLengthTemp += _segment.GetLength(); + _nSegTemp++; + } + _nIndex++; + _strKeyMJ.Format(c_szMJ, _nIndex); + _strValueTemp = _pCadMultiSegments->GetKey(_strKeyMJ); + } + + CCadObject* _pObjectRet = _CreateMultiSegmentToolPath(_pCadMultiSegments); + delete _pCadPolyline; + _pCadPolyline = NULL; + return _pObjectRet; +} + +// 相对于_CreateLineToolPath的函数,这里的_CreateLineToolPath2函数是把刀路生成为 +// 飞行切割的形式。 +// 即,比如一个线段,加了5个微连,则生成11段的Path,其中第1、3、5、7、9段是不 +// 开光的,而要把0、2、4、6、8、10段标为要开光的。 +// ---- 杨开锦 2016-10-24 +CCadObject* CMicroJointTarget::_CreateLineToolPath2(const nce::CCadLine* pCadLine_) +{ + ASSERT(pCadLine_); + if (DOUBLE_LE_ZERO(pCadLine_->GetLength())) + { + return NULL; + } + + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + DPOINT2 _ptStart = pCadLine_->GetStartPoint(); + DPOINT2 _ptEnd = pCadLine_->GetEndPoint(); + _pCadPolyline->SetStartPoint(_ptStart); + + CStringA _strGXXNodes; + DPOINT2 _ptSegStart = _ptStart; + for (int _nMJIndex = 0; _nMJIndex < 10000; _nMJIndex++) + { + CStringA _strMJKey; + _strMJKey.Format(c_szMJ, _nMJIndex); + CStringA _strMJValue = pCadLine_->GetKey(_strMJKey); + if (_strMJValue.IsEmpty()) + break; + + int _nSeg = 0; + double _nRatio = 0.0; + double _nLength = 0.0; + VERIFY(3 == sscanf_s(_strMJValue, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + ASSERT(_nSeg == 0); + DPOINT2 _ptGxxEnd = _ptStart + (_ptEnd - _ptStart) * _nRatio; + if (!DOUBLE_EQU(_ptGxxEnd.x, _ptSegStart.x) || !DOUBLE_EQU(_ptGxxEnd.y, _ptSegStart.y)) + { + _pCadPolyline->AddLine(_ptGxxEnd); + _strGXXNodes.AppendFormat("%d,", _pCadPolyline->GetNodeCount() - 1); + } + + DPOINT2 _ptG00End = _ptStart + (_ptEnd - _ptStart) * (_nRatio + _nLength / pCadLine_->GetLength()); + if (!DOUBLE_EQU(_ptG00End.x, _ptGxxEnd.x) || !DOUBLE_EQU(_ptG00End.y, _ptGxxEnd.y)) + { + _pCadPolyline->AddLine(_ptG00End); + } + + _ptSegStart = _ptG00End; + } + + if (!DOUBLE_EQU(_ptSegStart.x, _ptEnd.x) || !DOUBLE_EQU(_ptSegStart.y, _ptEnd.y)) + { + _pCadPolyline->AddLine(_ptEnd); + _strGXXNodes.AppendFormat("%d,", _pCadPolyline->GetNodeCount() - 1); + } + + _pCadPolyline->SetParamIndex(pCadLine_->GetParamIndex()); + _pCadPolyline->SetParamString(pCadLine_->GetParamString()); + _pCadPolyline->SetKey(c_szScanCamGXXNodes, _strGXXNodes); + return _pCadPolyline; +} + +CCadObject* CMicroJointTarget::_CreateCircleToolPath2(const CCadCircle* pCadCircle_) +{ + ASSERT(pCadCircle_); + if (DOUBLE_LE_ZERO(pCadCircle_->GetLength())) + { + return NULL; + } + + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + DPOINT2 _ptStart = pCadCircle_->GetPoint(0.0); + DPOINT2 _ptEnd = _ptStart; + _pCadPolyline->SetStartPoint(_ptStart); + + CStringA _strGXXNodes; + double _nSegStartAngle = 0.0; + for (int _nMJIndex = 0; _nMJIndex < 10000; _nMJIndex++) + { + CStringA _strMJKey; + _strMJKey.Format(c_szMJ, _nMJIndex); + CStringA _strMJValue = pCadCircle_->GetKey(_strMJKey); + if (_strMJValue.IsEmpty()) + break; + + int _nSeg = 0; + double _nRatio = 0.0; + double _nLength = 0.0; + VERIFY(3 == sscanf_s(_strMJValue, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + ASSERT(_nSeg == 0); + double _nGxxEndAngle = 2 * c_nPIE * _nRatio * (pCadCircle_->IsNormalDir() ? 1.0 : -1.0); + double _nGxxCenterAngle = _nGxxEndAngle - _nSegStartAngle; + if (DOUBLE_GREAT_ZERO(_nGxxCenterAngle)) + { + DPOINT2 _ptGxxEnd = pCadCircle_->GetPoint(RegularizeRadian(_nGxxEndAngle)); + double _nGxxBulge = tan(_nGxxCenterAngle / 4.0); + _pCadPolyline->AddArc(_ptGxxEnd, _nGxxBulge); + _strGXXNodes.AppendFormat("%d,", _pCadPolyline->GetNodeCount() - 1); + } + + double _nG00CenterAngle = (_nLength / pCadCircle_->GetLength()) * 2 * c_nPIE * (pCadCircle_->IsNormalDir() ? 1.0 : -1.0); + double _nG00EngAngle = _nGxxEndAngle + _nG00CenterAngle; + if (DOUBLE_GREAT_ZERO(_nG00CenterAngle)) + { + DPOINT2 _ptG00End = pCadCircle_->GetPoint(RegularizeRadian(_nG00EngAngle)); + double _nG00Bulge = tan(_nG00CenterAngle / 4.0); + _pCadPolyline->AddArc(_ptG00End, _nG00Bulge); + } + + _nSegStartAngle = _nG00EngAngle; + } + + if (DOUBLE_LESS(_nSegStartAngle, 2 * c_nPIE)) + { + double _nBulge = tan((2 * c_nPIE - _nSegStartAngle) * (pCadCircle_->IsNormalDir() ? 1.0 : -1.0) / 4.0); + _pCadPolyline->AddArc(_ptEnd, _nBulge); + _strGXXNodes.AppendFormat("%d,", _pCadPolyline->GetNodeCount() - 1); + } + + _pCadPolyline->SetParamIndex(pCadCircle_->GetParamIndex()); + _pCadPolyline->SetParamString(pCadCircle_->GetParamString()); + _pCadPolyline->SetKey(c_szScanCamGXXNodes, _strGXXNodes); + return _pCadPolyline; +} + +CCadObject* CMicroJointTarget::_CreateArcToolPath2(const nce::CCadArc* pCadArc_) +{ + ASSERT(pCadArc_); + if (DOUBLE_LE_ZERO(pCadArc_->GetLength())) + { + return NULL; + } + + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + DPOINT2 _ptStart = pCadArc_->GetStartPoint(); + DPOINT2 _ptEnd = pCadArc_->GetEndPoint(); + _pCadPolyline->SetStartPoint(_ptStart); + + CStringA _strGXXNodes; + double _nSegStartAngle = 0; + for (int _nMJIndex = 0; _nMJIndex < 10000; _nMJIndex++) + { + CStringA _strMJKey; + _strMJKey.Format(c_szMJ, _nMJIndex); + CStringA _strMJValue = pCadArc_->GetKey(_strMJKey); + if (_strMJValue.IsEmpty()) + break; + + int _nSeg = 0; + double _nRatio = 0.0; + double _nLength = 0.0; + VERIFY(3 == sscanf_s(_strMJValue, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + ASSERT(_nSeg == 0); + double _nGxxEndAngle = pCadArc_->GetCentralAngle() * _nRatio; + double _nGxxCenterAngle = _nGxxEndAngle - _nSegStartAngle; + if (DOUBLE_GREAT_ZERO(_nGxxCenterAngle)) + { + DPOINT2 _ptGxxEnd = pCadArc_->GetPoint(_nGxxEndAngle); + double _nGxxBulge = tan(0.25 * _nGxxCenterAngle * (pCadArc_->IsNormalDir() ? 1.0 : -1.0)); + _pCadPolyline->AddArc(_ptGxxEnd, _nGxxBulge); + _strGXXNodes.AppendFormat("%d,", _pCadPolyline->GetNodeCount() - 1); + } + + double _nG00CenterAngle = (_nLength / pCadArc_->GetLength()) * pCadArc_->GetCentralAngle(); + double _nG00EngAngle = _nGxxEndAngle + _nG00CenterAngle; + if (DOUBLE_GREAT_ZERO(_nG00CenterAngle)) + { + DPOINT2 _ptG00End = pCadArc_->GetPoint(_nG00EngAngle); + double _nG00Bulge = tan(0.25 * _nG00CenterAngle * (pCadArc_->IsNormalDir() ? 1.0 : -1.0)); + _pCadPolyline->AddArc(_ptG00End, _nG00Bulge); + } + + _nSegStartAngle = _nG00EngAngle; + } + + if (DOUBLE_LESS(_nSegStartAngle, pCadArc_->GetCentralAngle())) + { + double _nBulge = tan(0.25 * (pCadArc_->GetCentralAngle() - _nSegStartAngle) * (pCadArc_->IsNormalDir() ? 1.0 : -1.0)); + _pCadPolyline->AddArc(_ptEnd, _nBulge); + _strGXXNodes.AppendFormat("%d,", _pCadPolyline->GetNodeCount() - 1); + } + + _pCadPolyline->SetParamIndex(pCadArc_->GetParamIndex()); + _pCadPolyline->SetParamString(pCadArc_->GetParamString()); + _pCadPolyline->SetKey(c_szScanCamGXXNodes, _strGXXNodes); + return _pCadPolyline; +} + +CCadObject* CMicroJointTarget::_CreateMultiSegmentToolPath2(const nce::CCadMultiSegments* pCadMultiSegments_) +{ + // 借助炸开微连来做刀路生成 + // TODO: 应该把这部分逻辑抽取出来做成Doer + CadObjectList _listCads; + if (!_ExplodeMultiSegmentMicroJoint(pCadMultiSegments_, &_listCads)) + { + return NULL; + } + + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + CStringA _strGXXNodes; + for (CadObjectList::iterator _it = _listCads.begin(); _it != _listCads.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad && _pCad->GetType() == cadpolyline); + CCadPolyline* _pPol = (CCadPolyline*)_pCad; + ASSERT(_pPol->GetNodeCount() > 0); + if (_pCadPolyline->GetNodeCount() <= 0) + _pCadPolyline->SetStartPoint(_pPol->GetStartPoint()); + else + _pCadPolyline->AddLine(_pPol->GetStartPoint()); + + for (int _i = 0; _i < _pPol->GetNodeCount(); _i++) + { + const CCadPolyline::ARCNODE& _node = _pPol->GetAt(_i); + _pCadPolyline->AddArc(_node.ptEnd, _node.nBulge); + _strGXXNodes.AppendFormat("%d,", _pCadPolyline->GetNodeCount() - 1); + } + } + + _pCadPolyline->SetParamIndex(pCadMultiSegments_->GetParamIndex()); + _pCadPolyline->SetParamString(pCadMultiSegments_->GetParamString()); + _pCadPolyline->SetKey(c_szScanCamGXXNodes, _strGXXNodes); + return _pCadPolyline; +} + +CCadObject* CMicroJointTarget::_CreateEllipseToolPath2(const nce::CCadEllipse* pCadEllipse_) +{ + CadObjectList _listCads; + if (!_ExplodeEllipseMicroJoint(pCadEllipse_, &_listCads)) + { + return NULL; + } + + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + CStringA _strGXXNodes; + for (CadObjectList::iterator _it = _listCads.begin(); _it != _listCads.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad && _pCad->GetType() == cadpolyline); // TODO: 椭圆微连的炸开有可能会改 + CCadPolyline* _pPol = (CCadPolyline*)_pCad; + ASSERT(_pPol->GetNodeCount() > 0); + if (_pCadPolyline->GetNodeCount() <= 0) + _pCadPolyline->SetStartPoint(_pPol->GetStartPoint()); + else + _pCadPolyline->AddLine(_pPol->GetStartPoint()); + + for (int _i = 0; _i < _pPol->GetNodeCount(); _i++) + { + const CCadPolyline::ARCNODE& _node = _pPol->GetAt(_i); + _pCadPolyline->AddArc(_node.ptEnd, _node.nBulge); + _strGXXNodes.AppendFormat("%d,", _pCadPolyline->GetNodeCount() - 1); + } + } + + _pCadPolyline->SetParamIndex(pCadEllipse_->GetParamIndex()); + _pCadPolyline->SetParamString(pCadEllipse_->GetParamString()); + _pCadPolyline->SetKey(c_szScanCamGXXNodes, _strGXXNodes); + return _pCadPolyline; +} + +CCadObject* CMicroJointTarget::_CreateEllipseArcToolPath2(const nce::CCadEllipseArc* pCadEllipseArc_) +{ + CadObjectList _listCads; + if (!_ExplodeEllipseArcMicroJoint(pCadEllipseArc_, &_listCads)) + { + return NULL; + } + + CCadPolyline* _pCadPolyline = new CCadPolyline; + ASSERT(_pCadPolyline); + CStringA _strGXXNodes; + for (CadObjectList::iterator _it = _listCads.begin(); _it != _listCads.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad && _pCad->GetType() == cadpolyline); // TODO: 椭圆微连的炸开有可能会改 + CCadPolyline* _pPol = (CCadPolyline*)_pCad; + ASSERT(_pPol->GetNodeCount() > 0); + if (_pCadPolyline->GetNodeCount() <= 0) + _pCadPolyline->SetStartPoint(_pPol->GetStartPoint()); + else + _pCadPolyline->AddLine(_pPol->GetStartPoint()); + + for (int _i = 0; _i < _pPol->GetNodeCount(); _i++) + { + const CCadPolyline::ARCNODE& _node = _pPol->GetAt(_i); + _pCadPolyline->AddArc(_node.ptEnd, _node.nBulge); + _strGXXNodes.AppendFormat("%d,", _pCadPolyline->GetNodeCount() - 1); + } + } + + _pCadPolyline->SetParamIndex(pCadEllipseArc_->GetParamIndex()); + _pCadPolyline->SetParamString(pCadEllipseArc_->GetParamString()); + _pCadPolyline->SetKey(c_szScanCamGXXNodes, _strGXXNodes); + return _pCadPolyline; +} + +BOOL CMicroJointTarget::OnLButtonDown(UINT nFlags_, DPOINT2 point_) +{ + if (!IsActive()) + { + return FALSE; + } + + CFileTarget* _pFileTarget = GetFileTarget(); + if (!_pFileTarget) + { + ASSERT(FALSE); + return FALSE; + } + CCadGroup* _pCurrentGroup = _pFileTarget->GetCurrentCadGroup(); + if (_pCurrentGroup == NULL) + return FALSE; + + SendTargetMessage(ID_TARGET_CATCH, TM_CATCH_REQUEST, CR_CATCH, (LPARAM)&point_); + CCadObject* _pCadObject = NULL; + Pos _pos; + if (FindCadPositionByPoint(_pCurrentGroup, point_, &_pCadObject, _pos)) + { + if (_pCadObject->GetType() == caddot + || _pCadObject->GetType() == cadtext) + { + NceShowMessage(_GETCS(s_szManualSetFailed)); + return TRUE; + } + + CadObjectList _CadObjectListBefore; + CadObjectList _CadObjectListAfter; + CCadObject* _pCadObjectSrc = _pCadObject->Clone(); + if (!SetMicroJoint(_pCadObjectSrc, _pos.nID, _pos.nOffect, m_nMicroJointLength)) + { + delete _pCadObjectSrc; + _pCadObjectSrc = NULL; + return TRUE; + } + + _CadObjectListBefore.push_back(_pCadObject); + _CadObjectListAfter.push_back(_pCadObjectSrc); + if (CAction::NoAction != CMicroJointAction::Do(&_CadObjectListBefore, &_CadObjectListAfter)) + { + UpdateAllVisions(); + } + } + else + { + NceShowMessage(_GETCS(s_szManualSetFailed)); + } + return TRUE; +} + +BOOL CMicroJointTarget::OnRButtonUp(UINT nFlags_, DPOINT2 point_) +{ + if (!IsActive()) + { + return FALSE; + } + Exit(); + return TRUE; +} + +BOOL CMicroJointTarget::OnMouseMove(UINT nFlags_, DPOINT2 point_) +{ + if (!IsActive()) + { + return FALSE; + } + CFileTarget* _pFileTarget = GetFileTarget(); + if (!_pFileTarget) + { + ASSERT(FALSE); + return FALSE; + } + CCadGroup* _pCurrentGroup = _pFileTarget->GetCurrentCadGroup(); + if (_pCurrentGroup == NULL) + return FALSE; + + SendTargetMessage(ID_TARGET_CATCH, TM_CATCH_REQUEST, CR_CATCH, (LPARAM)&point_); + + return TRUE; +} + +void CMicroJointTarget::Reset() +{ +} + +void CMicroJointTarget::OnMicroJoint() +{ + CMicroJointDlg_R2 _dlg; + if (_dlg.DoModal() != IDOK) + { + return; + } + m_bNoPause = _dlg.GetIfNoPause(); + + // TODO:应该把这样的信息存到文件中,修改这些参数时就去写文件改动标记。 + // 这里的UpdateAllVisions是必要的,因为CToolPathTarget::Update中会读取和使用 + // 上面的m_bNoPause值(即微连实现方式)。 ---- 杨开锦 2016-10-25 + UpdateAllVisions(); + + if (_dlg.GetMode() == 0) + { + m_nMicroJointLength = _dlg.GetAutoMicroJointLength(); + m_nMicroJointCounts = _dlg.GetAutoMicroJointCounts(); + AutoMicroJointByCounts(); + } + else if (_dlg.GetMode() == 1) + { + m_nMicroJointLength = _dlg.GetAutoMicroJointLength(); + m_nMicroJointSpace = _dlg.GetAutoMicroJointSpace(); + AutoMicroJointBySpace(); + } + else if (_dlg.GetMode() == 2) + { + m_nMicroJointLength = _dlg.GetManualMicroJointLength(); + ManualMicroJoint(); + } +} + +void CMicroJointTarget::ManualMicroJoint() +{ + if (IsActive()) + Exit(); + + Activate(); +} + +void CMicroJointTarget::AutoMicroJointBySpace() +{ + CSelectTarget* _pSelectTarget = GetSelectTarget(); + if (!_pSelectTarget) + return; + CadObjectList* _plistSelectObjects = const_cast(_pSelectTarget->GetSelectedCadObjects()); + if (_plistSelectObjects->size() == 0) + { + NceShowMessage(_GETCS(s_szNoSelectedObject)); + return; + } + + CadObjectList _CadObjectListBefore; + CadObjectList _CadObjectListAfter; + + for (CadObjectList::iterator _it = _plistSelectObjects->begin(); _it != _plistSelectObjects->end(); _it++) + { + CCadObject* _pNewCadObject = NULL; + if (_AutoMicroJointBySpace(*_it, &_pNewCadObject)) + { + _CadObjectListBefore.push_back(*_it); + _CadObjectListAfter.push_back(_pNewCadObject); + } + } + + if (_CadObjectListAfter.size() <= 0) + { + NceShowMessage(_GETCS(s_szAutoSetFailed)); + return; + } + + if (_CadObjectListAfter.size() >= 0 + && CAction::NoAction != CMicroJointAction::Do(&_CadObjectListBefore, &_CadObjectListAfter)) + { + UpdateAllVisions(); + } +} + +void CMicroJointTarget::AutoMicroJointByCounts() +{ + CSelectTarget* _pSelectTarget = GetSelectTarget(); + if (!_pSelectTarget) + return; + CadObjectList* _plistSelectObjects = const_cast(_pSelectTarget->GetSelectedCadObjects()); + if (_plistSelectObjects->size() == 0) + { + NceShowMessage(_GETCS(s_szNoSelectedObject)); + return; + } + + CadObjectList _CadObjectListBefore; + CadObjectList _CadObjectListAfter; + + for (CadObjectList::iterator _it = _plistSelectObjects->begin(); _it != _plistSelectObjects->end(); _it++) + { + CCadObject* _pNewCadObject = NULL; + if (_AutoMicroJointByCounts(*_it, &_pNewCadObject)) + { + _CadObjectListBefore.push_back(*_it); + _CadObjectListAfter.push_back(_pNewCadObject); + } + } + + if (_CadObjectListAfter.size() <= 0) + { + NceShowMessage(_GETCS(s_szAutoSetFailed)); + return; + } + + if (_CadObjectListAfter.size() >= 0 + && CAction::NoAction != CMicroJointAction::Do(&_CadObjectListBefore, &_CadObjectListAfter)) + { + UpdateAllVisions(); + } +} + +bool CMicroJointTarget::_AutoMicroJointBySpace(IN const nce::CCadObject* pCadObjectSrc_, OUT nce::CCadObject** ppCadObjectDes_) +{ + switch(pCadObjectSrc_->GetType()) + { + case cadgroup: + return false; + case cadline: + case cadcircle: + case cadarc: + case cadellipse: + case cadellipsearc: + return _AutoMicroJointBySpaceOneSeg(pCadObjectSrc_, ppCadObjectDes_); + case cadpath: + case cadpolygon: + case cadpolyline: + case cadstar: + case cadrectangle: + return _AutoMicroJointBySpaceMulSeg((const CCadMultiSegments*)pCadObjectSrc_, ppCadObjectDes_); + } + + return false; +} + +bool CMicroJointTarget::_AutoMicroJointBySpaceOneSeg(IN const nce::CCadObject* pCadObjectSrc_, OUT nce::CCadObject** ppCadObjectDes_) +{ + ASSERT(pCadObjectSrc_ && ppCadObjectDes_ && *ppCadObjectDes_ == NULL); + double _nCadLength = GetCadLength(pCadObjectSrc_); + if (_nCadLength <= m_nMicroJointSpace + m_nMicroJointLength) + { + // 不够1个微连就返回 ---- DingQiang 2016-05-18 + *ppCadObjectDes_ = NULL; + return false; + } + + CCadObject* _pCadObject = pCadObjectSrc_->Clone(); + ClearMicroJoint(_pCadObject); + double _nRemindLength = _nCadLength; + CStringA _strSetKey; + CStringA _strSetValue; + int _nCountIndex = 0; + double _nRatio; + double _nHeadLength = m_nMicroJointSpace; + while (_nRemindLength > m_nMicroJointSpace + m_nMicroJointLength) + { + _nRatio = _nHeadLength / _nCadLength; + _strSetKey.Format(c_szMJ, _nCountIndex); + _strSetValue.Format(c_szMJFormat, 0, _nRatio, m_nMicroJointLength); + _pCadObject->SetKey(_strSetKey, _strSetValue); + _nCountIndex++; + _nRemindLength -= m_nMicroJointSpace + m_nMicroJointLength; + _nHeadLength += m_nMicroJointLength + m_nMicroJointSpace; + } + + *ppCadObjectDes_ = _pCadObject; + return true; +} + +bool CMicroJointTarget::_AutoMicroJointBySpaceMulSeg(IN const nce::CCadMultiSegments* pCadCadMultiSegmentsSrc_, OUT nce::CCadObject** ppCadObjectDes_) +{ + ASSERT(pCadCadMultiSegmentsSrc_ && ppCadObjectDes_ && *ppCadObjectDes_ == NULL); + double _nCadLength = pCadCadMultiSegmentsSrc_->GetLength(); + if (_nCadLength <= m_nMicroJointSpace + m_nMicroJointLength) + { + // 不够1个微连就返回 ---- DingQiang 2016-05-18 + *ppCadObjectDes_ = NULL; + return false; + } + + CCadObject* _pCadObject = pCadCadMultiSegmentsSrc_->Clone(); + ClearMicroJoint(_pCadObject); + double _nRemindLength = _nCadLength; + CStringA _strSetTemp; + int _nCountIndex = 0; + double _nRatio; + double _nHeadLength = m_nMicroJointSpace; + while (_nRemindLength > m_nMicroJointSpace + m_nMicroJointLength) + { + double _nAddlength = 0; + int _nSeg = 0; + while(_nAddlength < _nHeadLength && _nSeg < pCadCadMultiSegmentsSrc_->GetSegmentCount()) + { + SEGMENT _segment = pCadCadMultiSegmentsSrc_->GetSegment(_nSeg); + if (_nAddlength + _segment.GetLength() >= _nHeadLength) + { + _nRatio = (_nHeadLength - _nAddlength) / _segment.GetLength(); + break; + } + _nAddlength += _segment.GetLength(); + _nSeg++; + } + + if (_nSeg >= pCadCadMultiSegmentsSrc_->GetSegmentCount()) + { + ASSERT(FALSE); + break; + } + + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nCountIndex); + CStringA _strValue; + _strValue.Format(c_szMJFormat, _nSeg, _nRatio, m_nMicroJointLength); + _pCadObject->SetKey(_strKeyMJ, _strValue); + _nCountIndex++; + _nRemindLength -= m_nMicroJointSpace + m_nMicroJointLength; + _nHeadLength += m_nMicroJointLength + m_nMicroJointSpace; + } + + *ppCadObjectDes_ = _pCadObject; + return true; +} + +bool CMicroJointTarget::_AutoMicroJointByCounts(IN const nce::CCadObject* pCadObjectSrc_, OUT nce::CCadObject** ppCadObjectDes_) +{ + switch(pCadObjectSrc_->GetType()) + { + case cadgroup: + return false; + case cadline: + case cadcircle: + case cadarc: + case cadellipse: + case cadellipsearc: + return _AutoMicroJointByCountsOneSeg(pCadObjectSrc_, ppCadObjectDes_); + case cadpath: + case cadpolygon: + case cadpolyline: + case cadstar: + case cadrectangle: + return _AutoMicroJointByCountsMulSeg((const CCadMultiSegments*)pCadObjectSrc_, ppCadObjectDes_); + } + + return false; +} + +bool CMicroJointTarget::_AutoMicroJointByCountsOneSeg(IN const nce::CCadObject* pCadObjectSrc_, OUT nce::CCadObject** ppCadObjectDes_) +{ + ASSERT(pCadObjectSrc_ && ppCadObjectDes_ && *ppCadObjectDes_ == NULL); + double _nCadLength = GetCadLength(pCadObjectSrc_); + if (_nCadLength <= m_nMicroJointLength * m_nMicroJointCounts) + { + // 不够长就返回 ---- DingQiang 2016-05-18 + *ppCadObjectDes_ = NULL; + return false; + } + + CCadObject* _pCadObject = pCadObjectSrc_->Clone(); + ClearMicroJoint(_pCadObject); + + // 微连后生成的段数 ---- DingQiang 2016-05-18 + int _nNewCounts = m_nMicroJointCounts; + if (!_pCadObject->IsClose()) + { + _nNewCounts++; + } + + double _nEachSegLength = (_nCadLength - m_nMicroJointLength * m_nMicroJointCounts) / _nNewCounts; + int _nCountIndex = 0; + CStringA _strSetKey; + CStringA _strSetValue; + double _nRatio = -1; + double _nHeadLength = _nEachSegLength; + while(_nCountIndex < m_nMicroJointCounts) + { + _nRatio = _nHeadLength / _nCadLength; + _nRatio = _nHeadLength / _nCadLength; + _strSetKey.Format(c_szMJ, _nCountIndex); + _strSetValue.Format(c_szMJFormat, 0, _nRatio, m_nMicroJointLength); + _pCadObject->SetKey(_strSetKey, _strSetValue); + _nHeadLength += _nEachSegLength + m_nMicroJointLength; + _nCountIndex++; + } + + *ppCadObjectDes_ = _pCadObject; + return true; +} + +bool CMicroJointTarget::_AutoMicroJointByCountsMulSeg(IN const nce::CCadMultiSegments* pCadObjectSrc_, OUT nce::CCadObject** ppCadObjectDes_) +{ + ASSERT(pCadObjectSrc_ && ppCadObjectDes_ && *ppCadObjectDes_ == NULL); + double _nCadLength = GetCadLength(pCadObjectSrc_); + if (_nCadLength <= m_nMicroJointLength * m_nMicroJointCounts) + { + // 不够长就返回 ---- DingQiang 2016-05-18 + *ppCadObjectDes_ = NULL; + return false; + } + + CCadObject* _pCadObject = pCadObjectSrc_->Clone(); + ClearMicroJoint(_pCadObject); + + // 微连后生成的段数 ---- DingQiang 2016-05-18 + int _nNewCounts = m_nMicroJointCounts; + if (!_pCadObject->IsClose()) + { + _nNewCounts++; + } + + double _nEachSegLength = (_nCadLength - m_nMicroJointLength * m_nMicroJointCounts) / _nNewCounts; + int _nCountIndex = 0; + CStringA _strSetTemp; + double _nRatio = -1; + double _nHeadLength = _nEachSegLength; + while(_nCountIndex < m_nMicroJointCounts) + { + double _nAddlength = 0; + int _nSeg = 0; + while(_nAddlength < _nHeadLength && _nSeg < pCadObjectSrc_->GetSegmentCount()) + { + SEGMENT _segment = pCadObjectSrc_->GetSegment(_nSeg); + if (_nAddlength + _segment.GetLength() >= _nHeadLength) + { + _nRatio = (_nHeadLength - _nAddlength) / _segment.GetLength(); + break; + } + _nAddlength += _segment.GetLength(); + _nSeg++; + } + if (_nSeg >= pCadObjectSrc_->GetSegmentCount()) + { + break; + } + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nCountIndex); + CStringA _strValue; + _strValue.Format(c_szMJFormat, _nSeg, _nRatio, m_nMicroJointLength); + _pCadObject->SetKey(_strKeyMJ, _strValue); + _nCountIndex++; + _nHeadLength += _nEachSegLength + m_nMicroJointLength; + } + + *ppCadObjectDes_ = _pCadObject; + return true; +} + +void CMicroJointTarget::OnUpdateMicroJoint(CCmdUI* pCmdUI_) +{ + CFileTarget* _pFileTarget = GetFileTarget(); + if (!_pFileTarget) + return; + CCadGroup* _pCadGroup = _pFileTarget->GetCurrentCadGroup(); + BOOL _bEnable = FALSE; + if (_pCadGroup && (_pCadGroup->GetNumOfChild() != 0)) + _bEnable = TRUE; + pCmdUI_->Enable(_bEnable); +} + +void CMicroJointTarget::OnClearMicroJoint() +{ + CSelectTarget* _pSelectTarget = GetSelectTarget(); + if (!_pSelectTarget) + return; + CadObjectList* _plistSelectObjects = const_cast(_pSelectTarget->GetSelectedCadObjects()); + + CadObjectList _CadObjectListBefore; + CadObjectList _CadObjectListAfter; + + for (CadObjectList::iterator _it = _plistSelectObjects->begin(); _it != _plistSelectObjects->end(); _it++) + { + if (CanClearMicroJoint(*_it)) + { + CCadObject* _pNewObject = (*_it)->Clone(); + _CadObjectListBefore.push_back(*_it); + if(ClearMicroJoint(_pNewObject)) + { + _CadObjectListAfter.push_back(_pNewObject); + } + } + } + + if (_CadObjectListAfter.size() >= 0 + && CAction::NoAction != CMicroJointAction::Do(&_CadObjectListBefore, &_CadObjectListAfter)) + { + UpdateAllVisions(); + } +} + +void CMicroJointTarget::OnUpdateClearMicroJoint(CCmdUI* pCmdUI_) +{ + CSelectTarget* _pSelectTarget = GetSelectTarget(); + if (!_pSelectTarget) + return; + CadObjectList* _plistSelectObjects = const_cast(_pSelectTarget->GetSelectedCadObjects()); + ASSERT(_plistSelectObjects); + BOOL _bEnable = FALSE; + if (_plistSelectObjects->size() > 0) + _bEnable = TRUE; + pCmdUI_->Enable(_bEnable); +} + +void CMicroJointTarget::OnExplodeMicroJoint() +{ + CSelectTarget* _pSelectTarget = GetSelectTarget(); + if (!_pSelectTarget) + return; + CadObjectList* _plistSelectObjects = const_cast(_pSelectTarget->GetSelectedCadObjects()); + + ExplodeMicroJointItemList _listExplodeItems; + for (CadObjectList::iterator _it = _plistSelectObjects->begin(); _it != _plistSelectObjects->end(); _it++) + { + + if (CanExplodeMicroJoint(*_it)) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + ExplodeMicroJointItem _item = {_pCad}; + if (ExplodeMicroJoint(_item.pSrcCadObject, &_item.listDstCadObjects)) + { + _listExplodeItems.push_back(_item); + } + } + } + + if (_listExplodeItems.empty()) + { + return; + } + + CExplodeMicroJointAction::Do(&_listExplodeItems); + UpdateAllVisions(); +} + +void CMicroJointTarget::OnUpdateExplodeMicroJoint(CCmdUI* pCmdUI_) +{ + CSelectTarget* _pSelectTarget = GetSelectTarget(); + if (!_pSelectTarget) + return; + CadObjectList* _plistSelectObjects = const_cast(_pSelectTarget->GetSelectedCadObjects()); + ASSERT(_plistSelectObjects); + BOOL _bEnable = FALSE; + if (_plistSelectObjects->size() > 0) + _bEnable = TRUE; + pCmdUI_->Enable(_bEnable); +} + +bool CMicroJointTarget::FindCadPositionByPoint(IN nce::CCadGroup* pCadGroup_, IN const DPOINT2 ptCurrent_, + IN nce::CCadObject** pCadObject_, Pos& PosInfo_) +{ + CIntroPosCalculator _IntroPosCalculator; + _IntroPosCalculator.Init(pCadGroup_, &ptCurrent_, GetSelectTarget()->GetSelectToleranceLP()); + IntroPos _nIntroPos; + if (!_IntroPosCalculator.CalculatePosition(&_nIntroPos, false)) + return false; + + ASSERT(*pCadObject_ == NULL); + if (!FindObjectByID(pCadGroup_, _nIntroPos.nID, pCadObject_)) + return false; + + PosInfo_.nID = _nIntroPos.nSegmentNo; + PosInfo_.nOffect = _nIntroPos.nRate; + return true; +} + +// 改变加工方向 ---- 彭朋 2017-03-06 +void CMicroJointTarget::OnCadDirChanged(WPARAM wParam_, LPARAM lParam_) +{ + CadObjectList* _pCadObjectList = (CadObjectList*)wParam_; + for (CadObjectList::iterator _it = _pCadObjectList->begin(); _it != _pCadObjectList->end(); ++_it) + { + OnCadDirChanged(*_it); + } +} + +void CMicroJointTarget::OnCadDirChanged(nce::CCadObject* pCadObject_) +{ + // 改变加工方向 + ASSERT(pCadObject_); + switch(pCadObject_->GetType()) + { + case cadgroup: + { + CCadGroup* _CadGroup = (CCadGroup*)pCadObject_; + for (int _i = 0; _i < _CadGroup->GetNumOfChild(); ++_i) + { + CCadObject* _pCadObject = _CadGroup->GetAt(_i); + OnCadDirChanged(_pCadObject); + } + } + break; + + case cadtext: + { + CCadText* _pCadText = (CCadText*)pCadObject_; + OnCadDirChanged(_pCadText->GetTextGroup()); + } + break; + + case cadline: + { + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadObject_->GetKey(_strKey); + if(!_strValueTemp.IsEmpty()) + { + // 先收集微连点 + std::vector _vectMJItem; + int _nIndex = 0; + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadObject_->GetKey(_strKeyMJ); + while(!_strValueTemp.IsEmpty()) + { + MJItem _item; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_item.nSeg, &_nRatio, &_nLength)); + _item.nRatio = _nRatio; + _item.nLength = _nLength; + + _vectMJItem.push_back(_item); + _nIndex++; + _strKeyMJ.Format(c_szMJ, _nIndex); + _strValueTemp = pCadObject_->GetKey(_strKeyMJ); + } + + std::sort(_vectMJItem.begin(), _vectMJItem.end()); + std::vector _vectChangeMJItems; + double _nCadLen = GetCadLength(pCadObject_); + for (size_t _i = 0; _i < _vectMJItem.size(); _i++) + { + MJItem _MJItem = _vectMJItem[_i]; + MJItem _MJChangeItem; + ASSERT(_MJItem.nSeg == 0); + ASSERT(_MJItem.nRatio >= 0.0 && _MJItem.nRatio <= 1.0); + double _nRatio = _MJItem.nLength / _nCadLen; + _MJChangeItem.nSeg = 0; + _MJChangeItem.nRatio = 1.0 - _MJItem.nRatio - _nRatio; + if (_MJChangeItem.nRatio < 0) + _MJChangeItem.nRatio = 0; + _MJChangeItem.nLength = _MJItem.nLength; + _vectChangeMJItems.push_back(_MJChangeItem); + } + std::sort(_vectChangeMJItems.begin(), _vectChangeMJItems.end()); + for (size_t _i = 0; _i < _vectChangeMJItems.size(); _i++) + { + MJItem _MJItem = _vectChangeMJItems[_i]; + CStringA _strSetKey; + _strSetKey.Format(c_szMJ, _i); + CStringA _strValue; + _strValue.Format(c_szMJFormat, _MJItem.nSeg, _MJItem.nRatio, _MJItem.nLength); + pCadObject_->SetKey(_strSetKey, _strValue); + } + } + } + break; + + default: + { + if ((pCadObject_->GetType() & 0xFF00) != cadmultisegments) + return; + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadObject_->GetKey(_strKey); + if(!_strValueTemp.IsEmpty()) + { + // 先收集微连点 + std::vector _vectMJItem; + int _nIndex = 0; + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadObject_->GetKey(_strKeyMJ); + while(!_strValueTemp.IsEmpty()) + { + MJItem _item; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_item.nSeg, &_nRatio, &_nLength)); + _item.nRatio = _nRatio; + _item.nLength = _nLength; + + _vectMJItem.push_back(_item); + _nIndex++; + _strKeyMJ.Format(c_szMJ, _nIndex); + _strValueTemp = pCadObject_->GetKey(_strKeyMJ); + } + + std::sort(_vectMJItem.begin(), _vectMJItem.end()); + std::vector _vectChangeMJItems; + CCadMultiSegments* _pCadMS = (CCadMultiSegments*)pCadObject_; + UINT _nSegCount = _pCadMS->GetSegmentCount(); + ASSERT(_nSegCount > 0); + for (size_t _i = 0; _i < _vectMJItem.size(); _i++) + { + MJItem _MJItem = _vectMJItem[_i]; + MJItem _MJChangeItem; + ASSERT(_MJItem.nSeg >= 0 && _MJItem.nSeg < _nSegCount); + ASSERT(_MJItem.nRatio >= 0.0 && _MJItem.nRatio <= 1.0); + double _nItemLen = _pCadMS->GetSegment((_nSegCount - 1) - _MJItem.nSeg).GetLength(); + double _nRatio = _MJItem.nLength / _nItemLen; + _MJChangeItem.nSeg = (_nSegCount - 1) - _MJItem.nSeg; + _MJChangeItem.nRatio = 1.0 - _MJItem.nRatio - _nRatio; + if (_MJChangeItem.nRatio < 0) + _MJChangeItem.nRatio = 0; + _MJChangeItem.nLength = _MJItem.nLength; + _vectChangeMJItems.push_back(_MJChangeItem); + } + std::sort(_vectChangeMJItems.begin(), _vectChangeMJItems.end()); + + // 合并微连 ---- DingQiang 2016-03-11 + //CombineMicroJoint(pCadObject_, _vectChangeMJItems); + + for (size_t _i = 0; _i < _vectChangeMJItems.size(); _i++) + { + MJItem _MJItem = _vectChangeMJItems[_i]; + CStringA _strSetKey; + _strSetKey.Format(c_szMJ, _i); + CStringA _strValue; + _strValue.Format(c_szMJFormat, _MJItem.nSeg, _MJItem.nRatio, _MJItem.nLength); + pCadObject_->SetKey(_strSetKey, _strValue); + } + } + } + break; + } +} + +// 设置微连 +bool CMicroJointTarget::SetMicroJoint(CCadObject* pCadObject_, UINT nSeg_, double nRatio_, double nLength_) +{ + MJItem _SrcItem; + _SrcItem.nSeg = nSeg_; + _SrcItem.nRatio = nRatio_; + _SrcItem.nLength = nLength_; + + // 先收集微连点 + std::vector _vectMJItem; + int _nIndex = 0; + CStringA _strKeyMJ; + _strKeyMJ.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadObject_->GetKey(_strKeyMJ); + while(!_strValueTemp.IsEmpty()) + { + MJItem _item; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_item.nSeg, &_nRatio, &_nLength)); + _item.nRatio = _nRatio; + _item.nLength = _nLength; + + _vectMJItem.push_back(_item); + _nIndex++; + _strKeyMJ.Format(c_szMJ, _nIndex); + _strValueTemp = pCadObject_->GetKey(_strKeyMJ); + } + + std::sort(_vectMJItem.begin(), _vectMJItem.end()); + bool _bInsert = false; + for (std::vector::iterator _it = _vectMJItem.begin(); _it != _vectMJItem.end(); _it++) + { + MJItem _MJItem = *_it; + // 已经存在 + if (_MJItem == _SrcItem) + { + if (DOUBLE_EQU(_MJItem.nLength, _SrcItem.nLength)) + { + return false; + } + else + { + _it->nLength = _SrcItem.nLength; + return true; + } + } + + if (_SrcItem < _MJItem) + { + _vectMJItem.insert(_it, _SrcItem); + _bInsert = true; + break; + } + } + if (!_bInsert) + { + _vectMJItem.push_back(_SrcItem); + } + + // 合并微连 ---- DingQiang 2016-03-11 + CombineMicroJoint(pCadObject_, _vectMJItem); + + for (size_t _i = 0; _i < _vectMJItem.size(); _i++) + { + MJItem _MJItem = _vectMJItem[_i]; + CStringA _strSetKey; + _strSetKey.Format(c_szMJ, _i); + CStringA _strValue; + _strValue.Format(c_szMJFormat, _MJItem.nSeg, _MJItem.nRatio, _MJItem.nLength); + pCadObject_->SetKey(_strSetKey, _strValue); + } + + return true; +} + +bool CMicroJointTarget::CanClearMicroJoint(const CCadObject* pCadObject_) +{ + bool _bRet = false; + ASSERT(pCadObject_); + + if (pCadObject_->GetType() == cadgroup) + { + CCadGroup* _pCadGroup = (CCadGroup*)pCadObject_; + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + _bRet |= CanClearMicroJoint(_pCadGroup->GetAt(_i)); + } + } + else + { + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadObject_->GetKey(_strKey); + double _nStartAngle = 0; + while(!_strValueTemp.IsEmpty()) + { + return true; + } + } + + return _bRet; +} + +bool CMicroJointTarget::ClearMicroJoint(nce::CCadObject* pCadObject_) +{ + bool _bRet = false; + ASSERT(pCadObject_); + + if (pCadObject_->GetType() == cadgroup) + { + CCadGroup* _pCadGroup = (CCadGroup*)pCadObject_; + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + _bRet |= ClearMicroJoint(_pCadGroup->GetAt(_i)); + } + } + else + { + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadObject_->GetKey(_strKey); + double _nStartAngle = 0; + while(!_strValueTemp.IsEmpty()) + { + pCadObject_->SetKey(_strKey, NULL); + _bRet = true; + _nIndex++; + _strKey.Format(c_szMJ, _nIndex); + _strValueTemp = pCadObject_->GetKey(_strKey); + } + } + + return _bRet; +} + +bool CMicroJointTarget::CanExplodeMicroJoint(const nce::CCadObject* pCadObject_) +{ + bool _bRet = false; + ASSERT(pCadObject_); + + if (pCadObject_->GetType() == cadgroup) + { + CCadGroup* _pCadGroup = (CCadGroup*)pCadObject_; + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + _bRet |= CanExplodeMicroJoint(_pCadGroup->GetAt(_i)); + } + } + else + { + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadObject_->GetKey(_strKey); + while(!_strValueTemp.IsEmpty()) + { + return true; + } + } + + return _bRet; +} + +bool CMicroJointTarget::ExplodeMicroJoint(const CCadObject* pCadObjectSrc_, CadObjectList* pCadObjectListDes_) +{ + if (pCadObjectSrc_->GetType() == cadgroup) + { + CCadGroup* _pCadGroup = (CCadGroup*)pCadObjectSrc_; + *pCadObjectListDes_ = *_pCadGroup->GetObjectsList(); + } + else + { + switch(pCadObjectSrc_->GetType()) + { + case cadline: + return _ExplodeLineMicroJoint((CCadLine*)pCadObjectSrc_, pCadObjectListDes_); + break; + case cadcircle: + return _ExplodeCircleMicroJoint((CCadCircle*)pCadObjectSrc_, pCadObjectListDes_); + break; + case cadarc: + return _ExplodeArcMicroJoint((CCadArc*)pCadObjectSrc_, pCadObjectListDes_); + break; + case cadellipse: + return _ExplodeEllipseMicroJoint((CCadEllipse*)pCadObjectSrc_, pCadObjectListDes_); + break; + case cadellipsearc: + return _ExplodeEllipseArcMicroJoint((CCadEllipseArc*)pCadObjectSrc_, pCadObjectListDes_); + break; + case cadpath: + case cadpolygon: + case cadpolyline: + case cadstar: + case cadrectangle: + return _ExplodeMultiSegmentMicroJoint((const CCadMultiSegments*)pCadObjectSrc_, pCadObjectListDes_); + break; + } + } + + return !pCadObjectListDes_->empty(); +} + +bool CMicroJointTarget::_ExplodeLineMicroJoint(const nce::CCadLine* pCadLine_, nce::CadObjectList* pCadObjectListDes_) +{ + size_t _nOldSize = pCadObjectListDes_->size(); + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadLine_->GetKey(_strKey); + DPOINT2 _ptStartPoint = pCadLine_->GetStartPoint(); + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + DPOINT2 _ptEndPoint = (pCadLine_->GetEndPoint() - pCadLine_->GetStartPoint()) * _nRatio + pCadLine_->GetStartPoint(); + + if (_ptStartPoint != _ptEndPoint) + { + CCadLine* _pCadLine = new CCadLine(_ptStartPoint, _ptEndPoint); + + _pCadLine->Select(pCadLine_->IsSelected()); + _pCadLine->SetParamIndex(pCadLine_->GetParamIndex()); + _pCadLine->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadLine_)); + pCadObjectListDes_->push_back(_pCadLine); + } + + _ptStartPoint = pCadLine_->GetStartPoint() + (pCadLine_->GetEndPoint() - pCadLine_->GetStartPoint()) * (_nRatio + _nLength / pCadLine_->GetLength()); + + _nIndex++; + _strKey.Format(c_szMJ, _nIndex); + _strValueTemp = pCadLine_->GetKey(_strKey); + } + + if (_ptStartPoint != pCadLine_->GetEndPoint()) + { + CCadLine* _pCadLine = new CCadLine(_ptStartPoint, pCadLine_->GetEndPoint()); + _pCadLine->Select(pCadLine_->IsSelected()); + _pCadLine->SetParamIndex(pCadLine_->GetParamIndex()); + _pCadLine->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadLine_)); + pCadObjectListDes_->push_back(_pCadLine); + } + + return pCadObjectListDes_->size() > _nOldSize; +} + +bool CMicroJointTarget::_ExplodeCircleMicroJoint(const nce::CCadCircle* pCadCircle_, nce::CadObjectList* pCadObjectListDes_) +{ + size_t _nOldSize = pCadObjectListDes_->size(); + + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadCircle_->GetKey(_strKey); + double _nStartAngle = 0; + bool _bFirstSegment = true; + CCadArc* _pFirstArc = NULL; + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + + double _nCenterAngle = 2 * c_nPIE * _nRatio - _nStartAngle; + if (!DOUBLE_EQU_ZERO(_nCenterAngle)) + { + if (_bFirstSegment) + { + _pFirstArc = new CCadArc(pCadCircle_->GetCenterPoint(), pCadCircle_->GetRadius(), + _nStartAngle, _nCenterAngle, pCadCircle_->IsNormalDir()); + _pFirstArc->Select(pCadCircle_->IsSelected()); + _pFirstArc->SetParamIndex(pCadCircle_->GetParamIndex()); + _pFirstArc->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadCircle_)); + } + else + { + CCadArc* _pCadArc = new CCadArc(pCadCircle_->GetCenterPoint(), pCadCircle_->GetRadius(), + _nStartAngle, _nCenterAngle, pCadCircle_->IsNormalDir()); + _pCadArc->Select(pCadCircle_->IsSelected()); + _pCadArc->SetParamIndex(pCadCircle_->GetParamIndex()); + _pCadArc->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadCircle_)); + pCadObjectListDes_->push_back(_pCadArc); + } + } + + _bFirstSegment = false; + + _nStartAngle = _nStartAngle + _nCenterAngle + (_nLength / pCadCircle_->GetLength()) * 2 * c_nPIE; + + _nIndex++; + _strKey.Format(c_szMJ, _nIndex); + _strValueTemp = pCadCircle_->GetKey(_strKey); + } + + if (!DOUBLE_EQU(_nStartAngle, 2 * c_nPIE)) + { + double _nCenterAngle = 2 * c_nPIE - _nStartAngle; + if (_pFirstArc) + { + _nCenterAngle += _pFirstArc->GetCentralAngle(); + delete _pFirstArc; + _pFirstArc = NULL; + } + CCadArc* _pCadArc = new CCadArc(pCadCircle_->GetCenterPoint(), pCadCircle_->GetRadius(), + _nStartAngle, _nCenterAngle, pCadCircle_->IsNormalDir()); + _pCadArc->Select(pCadCircle_->IsSelected()); + _pCadArc->SetParamIndex(pCadCircle_->GetParamIndex()); + _pCadArc->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadCircle_)); + pCadObjectListDes_->push_back(_pCadArc); + } + else + { + if (_pFirstArc) + { + pCadObjectListDes_->push_back(_pFirstArc); + } + } + + return pCadObjectListDes_->size() > _nOldSize; +} + +bool CMicroJointTarget::_ExplodeArcMicroJoint(const nce::CCadArc* pCadArc_, nce::CadObjectList* pCadObjectListDes_) +{ + size_t _nOldSize = pCadObjectListDes_->size(); + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadArc_->GetKey(_strKey); + double _nStartAngle = pCadArc_->GetStartAngle(); + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + + double _nCenterAngle = (pCadArc_->GetCentralAngle() * _nRatio + pCadArc_->GetStartAngle()) - _nStartAngle; + NormalizeRadian(_nCenterAngle); + if (!DOUBLE_EQU_ZERO(_nCenterAngle)) + { + CCadArc* _pCadArc = new CCadArc(pCadArc_->GetCenterPoint(), pCadArc_->GetRadius(), + _nStartAngle, _nCenterAngle, pCadArc_->IsNormalDir()); + _pCadArc->Select(pCadArc_->IsSelected()); + _pCadArc->SetParamIndex(pCadArc_->GetParamIndex()); + _pCadArc->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadArc_)); + pCadObjectListDes_->push_back(_pCadArc); + } + + _nStartAngle = _nStartAngle + _nCenterAngle + (_nLength / pCadArc_->GetLength()) * pCadArc_->GetCentralAngle(); + NormalizeRadian(_nStartAngle); + _nIndex++; + _strKey.Format(c_szMJ, _nIndex); + _strValueTemp = pCadArc_->GetKey(_strKey); + } + + if (!DOUBLE_EQU(_nStartAngle, pCadArc_->GetEndAngle())) + { + double _nCenterAngle = pCadArc_->GetEndAngle() - _nStartAngle; + if (_nCenterAngle < 0.) + { + _nCenterAngle += 2 * c_nPIE; + } + CCadArc* _pCadArc = new CCadArc(pCadArc_->GetCenterPoint(), pCadArc_->GetRadius(), + _nStartAngle, _nCenterAngle, pCadArc_->IsNormalDir()); + _pCadArc->Select(pCadArc_->IsSelected()); + _pCadArc->SetParamIndex(pCadArc_->GetParamIndex()); + _pCadArc->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadArc_)); + pCadObjectListDes_->push_back(_pCadArc); + } + + return pCadObjectListDes_->size() > _nOldSize; +} + +bool CMicroJointTarget::_ExplodeEllipseMicroJoint(const nce::CCadEllipse* pCadEllipse_, nce::CadObjectList* pCadObjectListDes_) +{ + CCadPolyline* _pCadPolyline = TranslateObjectToPolyline(pCadEllipse_); + _pCadPolyline->SetParamString(pCadEllipse_->GetParamString()); + _pCadPolyline->Select(pCadEllipse_->IsSelected()); + _pCadPolyline->SetParamIndex(pCadEllipse_->GetParamIndex()); + CCadMultiSegments* _pCadMultiSegments = (CCadMultiSegments*)(_pCadPolyline); + // 椭圆里存的比率是把椭圆当作一段来处理的,也就是存的是整体比率,转换成多义 + // 线的时候要把这个比率转换成多义线里的段号和比率 ---- DingQiang 2016-04-27 + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = _pCadMultiSegments->GetKey(_strKey); + DPOINT2 _ptStartPoint = _pCadMultiSegments->GetStartPoint(); + int _nTailSegCount = 0; + double _nTaliRatio = 0.; + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + double _nTargetLength = _pCadMultiSegments->GetLength() * _nRatio; + double _nLengthTemp = 0.; + int _nSegTemp = 0; + while(_nLengthTemp < _nTargetLength && _nSegTemp < _pCadMultiSegments->GetSegmentCount()) + { + SEGMENT _segment = _pCadMultiSegments->GetSegment(_nSegTemp); + if (_nLengthTemp + _segment.GetLength() >= _nTargetLength) + { + _nRatio = (_nTargetLength - _nLengthTemp) / _segment.GetLength(); + _strValueTemp.Format(c_szMJFormat, _nSegTemp, _nRatio, _nLength); + _pCadMultiSegments->SetKey(_strKey, _strValueTemp); + break; + } + _nLengthTemp += _segment.GetLength(); + _nSegTemp++; + } + _nIndex++; + _strKey.Format(c_szMJ, _nIndex); + _strValueTemp = _pCadMultiSegments->GetKey(_strKey); + } + + bool _bRet = _ExplodeMultiSegmentMicroJoint(_pCadMultiSegments, pCadObjectListDes_); + delete _pCadPolyline; + _pCadPolyline = NULL; + return _bRet; +} + +bool CMicroJointTarget::_ExplodeEllipseArcMicroJoint(const nce::CCadEllipseArc* pCadEllipseArc_, nce::CadObjectList* pCadObjectListDes_) +{ + CCadPolyline* _pCadPolyline = TranslateObjectToPolyline(pCadEllipseArc_); + _pCadPolyline->SetParamString(pCadEllipseArc_->GetParamString()); + _pCadPolyline->Select(pCadEllipseArc_->IsSelected()); + _pCadPolyline->SetParamIndex(pCadEllipseArc_->GetParamIndex()); + CCadMultiSegments* _pCadMultiSegments = (CCadMultiSegments*)(_pCadPolyline); + // 椭圆里存的比率是把椭圆当作一段来处理的,也就是存的是整体比率,转换成多义 + // 线的时候要把这个比率转换成多义线里的段号和比率 ---- DingQiang 2016-04-27 + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = _pCadMultiSegments->GetKey(_strKey); + DPOINT2 _ptStartPoint = _pCadMultiSegments->GetStartPoint(); + int _nTailSegCount = 0; + double _nTaliRatio = 0.; + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + double _nTargetLength = _pCadMultiSegments->GetLength() * _nRatio; + double _nLengthTemp = 0.; + int _nSegTemp = 0; + while(_nLengthTemp < _nTargetLength && _nSegTemp < _pCadMultiSegments->GetSegmentCount()) + { + SEGMENT _segment = _pCadMultiSegments->GetSegment(_nSegTemp); + if (_nLengthTemp + _segment.GetLength() >= _nTargetLength) + { + _nRatio = (_nTargetLength - _nLengthTemp) / _segment.GetLength(); + _strValueTemp.Format(c_szMJFormat, _nSegTemp, _nRatio, _nLength); + _pCadMultiSegments->SetKey(_strKey, _strValueTemp); + break; + } + _nLengthTemp += _segment.GetLength(); + _nSegTemp++; + } + _nIndex++; + _strKey.Format(c_szMJ, _nIndex); + _strValueTemp = _pCadMultiSegments->GetKey(_strKey); + } + + bool _bRet = _ExplodeMultiSegmentMicroJoint(_pCadMultiSegments, pCadObjectListDes_); + delete _pCadPolyline; + _pCadPolyline = NULL; + return _bRet; +} + +bool CMicroJointTarget::_ExplodeMultiSegmentMicroJoint(const nce::CCadMultiSegments* pCadMultiSegments_, nce::CadObjectList* pCadObjectListDes_) +{ + size_t _nOldSize = pCadObjectListDes_->size(); + int _nIndex = 0; + CStringA _strKey; + _strKey.Format(c_szMJ, _nIndex); + CStringA _strValueTemp = pCadMultiSegments_->GetKey(_strKey); + DPOINT2 _ptStartPoint = pCadMultiSegments_->GetStartPoint(); + int _nSegmentCount = pCadMultiSegments_->GetSegmentCount(); + int _nTailSegCount = 0; + double _nTaliRatio = 0.; + bool _bFirstSegment = true; + CCadPolyline* _pCadFirstPolyline = NULL; + while(!_strValueTemp.IsEmpty()) + { + int _nSeg = 0; + double _nRatio = 0.; + double _nLength = 0.; + VERIFY(3 == sscanf_s(_strValueTemp, c_szMJFormat, &_nSeg, &_nRatio, &_nLength)); + + if(_nTailSegCount >= _nSegmentCount) + { + TRACE("EXCEPTION: _nTailSegCount=%d out of _nSegmentCount=%d at CMicroJointTarget:%d.\n", _nTailSegCount, _nSegmentCount, __LINE__); + // ASSERT(_nTailSegCount < _nSegmentCount); + break; + } + + CCadPolyline* _pCadPolyline = new CCadPolyline; + _pCadPolyline->SetStartPoint(_ptStartPoint); + while(_nTailSegCount < _nSeg) + { + SEGMENT _Segment = pCadMultiSegments_->GetSegment(_nTailSegCount); + if (_Segment.nType == SEGMENT::LINE) + { + _pCadPolyline->AddLine(_Segment.ptEnd); + _nTaliRatio = 0; + } + else if (_Segment.nType == SEGMENT::ARC) + { + DPOINT2 _ptCenter; + double _nRadius,_nStartAngle,_nSweptAngele; + SEGMENT::SolveArc(_Segment.ptStart, + _Segment.ptEnd, + _Segment.nBulge, + &_ptCenter, + &_nRadius, + &_nStartAngle, + &_nSweptAngele); + _pCadPolyline->AddArc(_Segment.ptEnd, tan((1 - _nTaliRatio) * _nSweptAngele / 4)); + _nTaliRatio = 0; + } + else + { + ASSERT(FALSE); + } + + _nTailSegCount++; + + // TFS#3741:某些图形附有异常的MJ(即微连所处段号>=多义线段数,可能是简化或合并图形时未考虑MJ所致) + // 此时,_nTailSegCount++会导致后续执行GetSegment的代码越界崩溃。 + // 故在此判断一下多义线的段数,对于异常的MJ视作不存在(前提是异常MJ不显示) ---- yangxiaobin 2017-05-16 + if (_nTailSegCount >= _nSegmentCount) + { + TRACE("EXCEPTION: _nTailSegCount=%d out of _nSegmentCount=%d at CMicroJointTarget:%d!\n", _nTailSegCount, _nSegmentCount, __LINE__); + // ASSERT(_nTailSegCount < _nSegmentCount); + break; + } + } + // TFS#3741:防止因异常的MJ而导致的GetSegment越界 ---- yangxiaobin 2017-05-16 + // 对微连所处的Segment打断为段头(SS)---微连始(MJS)--微连末(MJE)----段尾(SE) + double _nNeedLength = 0.0; + if (_nTailSegCount < _nSegmentCount) + { + SEGMENT _Segment = pCadMultiSegments_->GetSegment(_nTailSegCount); + _nNeedLength = _Segment.GetLength() * _nRatio + _nLength; //MJE所在的位置 + if (_Segment.nType == SEGMENT::LINE) + { + _pCadPolyline->AddLine(_Segment.GetPoint(_nRatio)); + } + else if (_Segment.nType == SEGMENT::ARC) + { + DPOINT2 _ptCenter; + double _nRadius,_nStartAngle,_nSweptAngele; + SEGMENT::SolveArc(_Segment.ptStart, + _Segment.ptEnd, + _Segment.nBulge, + &_ptCenter, + &_nRadius, + &_nStartAngle, + &_nSweptAngele); + + _pCadPolyline->AddArc(_Segment.GetPoint(_nRatio), tan(_nSweptAngele * (_nRatio - _nTaliRatio) / 4)); + } + else + { + ASSERT(FALSE); + } + } + + if (_pCadPolyline->GetNodeCount() <= 0) + { + delete _pCadPolyline; + _pCadPolyline = NULL; + } + else + { + if (_bFirstSegment && pCadMultiSegments_->IsClose()) + { + _pCadFirstPolyline = _pCadPolyline; + } + else + { + _pCadPolyline->Select(pCadMultiSegments_->IsSelected()); + _pCadPolyline->SetParamIndex(pCadMultiSegments_->GetParamIndex()); + _pCadPolyline->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadMultiSegments_)); + pCadObjectListDes_->push_back(_pCadPolyline); + } + } + _nTaliRatio = _nRatio; + + _bFirstSegment = false; + + while(DOUBLE_GREAT(_nLength, 0) && _nTailSegCount < pCadMultiSegments_->GetSegmentCount()) + { + SEGMENT _Segment = pCadMultiSegments_->GetSegment(_nTailSegCount); + double _nSegLength =_Segment.GetLength(); + if (_nSegLength > _nNeedLength) + { + _ptStartPoint =_Segment.GetPoint(_nNeedLength / _nSegLength); + _nTaliRatio = _nNeedLength / _nSegLength; + break; + } + + _nNeedLength -= _nSegLength; + _nTailSegCount++; + } + + _nIndex++; + _strKey.Format(c_szMJ, _nIndex); + _strValueTemp = pCadMultiSegments_->GetKey(_strKey); + } + + if (_ptStartPoint != pCadMultiSegments_->GetEndPoint() + && _nTailSegCount < pCadMultiSegments_->GetSegmentCount()) + { + CCadPolyline* _pCadPolyine = new CCadPolyline; + _pCadPolyine->SetStartPoint(pCadMultiSegments_->GetSegment(_nTailSegCount).GetPoint(_nTaliRatio)); + bool _bFirst = true; + while(_nTailSegCount < pCadMultiSegments_->GetSegmentCount()) + { + SEGMENT _Segment = pCadMultiSegments_->GetSegment(_nTailSegCount); + if (_Segment.nType == SEGMENT::LINE) + { + _pCadPolyine->AddLine(_Segment.ptEnd); + _bFirst = false; + } + else if (_Segment.nType == SEGMENT::ARC) + { + if (_bFirst) + { + DPOINT2 _ptCenter; + double _nRadius,_nStartAngle,_nSweptAngele; + SEGMENT::SolveArc(_Segment.ptStart, + _Segment.ptEnd, + _Segment.nBulge, + &_ptCenter, + &_nRadius, + &_nStartAngle, + &_nSweptAngele); + _pCadPolyine->AddArc(_Segment.ptEnd, tan(_nSweptAngele * (1-_nTaliRatio) / 4)); + _bFirst = false; + } + else + { + _pCadPolyine->AddArc(_Segment.ptEnd, _Segment.nBulge); + } + } + else + { + ASSERT(FALSE); + } + _nTailSegCount++; + } + if (_pCadPolyine->GetNodeCount() <= 0) + { + delete _pCadPolyine; + _pCadPolyine = NULL; + if (_pCadFirstPolyline) + { + _pCadFirstPolyline->Select(pCadMultiSegments_->IsSelected()); + _pCadFirstPolyline->SetParamIndex(pCadMultiSegments_->GetParamIndex()); + _pCadFirstPolyline->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadMultiSegments_)); + pCadObjectListDes_->push_back(_pCadFirstPolyline); + } + } + else + { + if (_pCadFirstPolyline) + { + ASSERT(_pCadFirstPolyline->GetStartPoint() == _pCadPolyine->GetEndPoint()); + for (int i = 0; i < _pCadFirstPolyline->GetSegmentCount(); i++) + { + CCadPolyline::ARCNODE _Segment = _pCadFirstPolyline->GetAt(i); + if (_Segment.nBulge == 0.) + { + _pCadPolyine->AddLine(_Segment.ptEnd); + } + else + { + _pCadPolyine->AddArc(_Segment.ptEnd, _Segment.nBulge); + } + } + } + _pCadPolyine->Select(pCadMultiSegments_->IsSelected()); + _pCadPolyine->SetParamIndex(pCadMultiSegments_->GetParamIndex()); + _pCadPolyine->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadMultiSegments_)); + pCadObjectListDes_->push_back(_pCadPolyine); + } + } + else if (_pCadFirstPolyline) + { + _pCadFirstPolyline->Select(pCadMultiSegments_->IsSelected()); + _pCadFirstPolyline->SetParamIndex(pCadMultiSegments_->GetParamIndex()); + _pCadFirstPolyline->SetParamString(_GetCadObjectParamExceptMicroJoint(pCadMultiSegments_)); + pCadObjectListDes_->push_back(_pCadFirstPolyline); + } + + return pCadObjectListDes_->size() > _nOldSize; +} + +CStringA CMicroJointTarget::_GetCadObjectParamExceptMicroJoint(const nce::CCadObject* pCadObject_) +{ + CCadObject* _pCadObject = pCadObject_->Clone(); + ClearMicroJoint(_pCadObject); + CString _strParam = _pCadObject->GetParamString(); + delete _pCadObject; + _pCadObject = NULL; + return _strParam; +} + +void CMicroJointTarget::CombineMicroJoint(nce::CCadObject* pCadObject_, std::vector& vectMJItem_) +{ + switch(pCadObject_->GetType()) + { + case cadline: + _CombineLineMicroJoint((CCadLine*)pCadObject_, vectMJItem_); + break; + case cadcircle: + _CombineCircleMicroJoint((CCadCircle*)pCadObject_, vectMJItem_); + break; + case cadarc: + _CombineArcMicroJoint((CCadArc*)pCadObject_, vectMJItem_); + break; + case cadellipse: + _CombineEllipseMicroJoint((CCadEllipse*)pCadObject_, vectMJItem_); + break; + case cadellipsearc: + _CombineEllipseArcMicroJoint((CCadEllipseArc*)pCadObject_, vectMJItem_); + break; + case cadpolygon: + case cadpolyline: + case cadstar: + case cadrectangle: + _CombineMultiSegmentMicroJoint((CCadMultiSegments*)pCadObject_, vectMJItem_); + break; + case caddot: + ASSERT(FALSE); + break; + } +} + +void CMicroJointTarget::_CombineLineMicroJoint(nce::CCadLine* pCadLine_, std::vector& vectMJItem_) +{ + ASSERT(vectMJItem_.size() > 0); + + double _nTotleLength = pCadLine_->GetLength(); + vector::iterator _itLast = vectMJItem_.begin(); + for (vector::iterator _itThis = vectMJItem_.begin(); _itThis != vectMJItem_.end(); _itThis++) + { + if (_itThis == vectMJItem_.begin()) + { + if (_itThis->nLength > _nTotleLength * (1 - _itThis->nRatio)) + { + _itThis->nLength = _nTotleLength * (1 - _itThis->nRatio); + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itLast = _itThis = vectMJItem_.begin(); + } + break; + } + + continue; + } + + // 微连长度为0或者当前微连起点落在前一个的微连范围内则去除掉当前微连点 ---- DingQiang 2016-03-11 + if (_itThis->nRatio < _itLast->nRatio + _itLast->nLength / _nTotleLength) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + // 剩余距离不够微连长度,则把微连长度调整为剩余距离的长度 ---- DingQiang 2016-03-11 + if (_itThis->nLength > _nTotleLength * (1 - _itThis->nRatio)) + { + _itThis->nLength = _nTotleLength * (1 - _itThis->nRatio); + } + + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + _itLast = _itThis; + } +} + +void CMicroJointTarget::_CombineCircleMicroJoint(nce::CCadCircle* pCadCircle_, std::vector& vectMJItem_) +{ + ASSERT(vectMJItem_.size() > 0); + + double _nTotleLength = pCadCircle_->GetLength(); + vector::iterator _itLast = vectMJItem_.begin(); + for (vector::iterator _itThis = vectMJItem_.begin(); _itThis != vectMJItem_.end(); _itThis++) + { + if (_itThis == vectMJItem_.begin()) + { + if (_itThis->nLength > _nTotleLength * (1 - _itThis->nRatio)) + { + _itThis->nLength = _nTotleLength * (1 - _itThis->nRatio); + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itLast = _itThis = vectMJItem_.begin(); + } + break; + } + + continue; + } + + // 微连长度为0或者当前微连起点落在前一个的微连范围内则去除掉当前微连点 ---- DingQiang 2016-03-11 + if (_itThis->nRatio < _itLast->nRatio + _itLast->nLength / _nTotleLength) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + // 剩余距离不够微连长度,则把微连长度调整为剩余距离的长度 ---- DingQiang 2016-03-11 + if (_itThis->nLength > _nTotleLength * (1 - _itThis->nRatio)) + { + _itThis->nLength = _nTotleLength * (1 - _itThis->nRatio); + } + + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + _itLast = _itThis; + } +} + +void CMicroJointTarget::_CombineArcMicroJoint(nce::CCadArc* pCadArc_, std::vector& vectMJItem_) +{ + ASSERT(vectMJItem_.size() > 0); + + double _nTotleLength = pCadArc_->GetLength(); + vector::iterator _itLast = vectMJItem_.begin(); + for (vector::iterator _itThis = vectMJItem_.begin(); _itThis != vectMJItem_.end(); _itThis++) + { + if (_itThis == vectMJItem_.begin()) + { + if (_itThis->nLength > _nTotleLength * (1 - _itThis->nRatio)) + { + _itThis->nLength = _nTotleLength * (1 - _itThis->nRatio); + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itLast = _itThis = vectMJItem_.begin(); + } + break; + } + + continue; + } + + // 当前微连起点落在前一个的微连范围内则去除掉当前微连点 ---- DingQiang 2016-03-11 + if (_itThis->nRatio < _itLast->nRatio + _itLast->nLength / _nTotleLength) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + // 剩余距离不够微连长度,则把微连长度调整为剩余距离的长度 ---- DingQiang 2016-03-11 + if (_itThis->nLength > _nTotleLength * (1 - _itThis->nRatio)) + { + _itThis->nLength = _nTotleLength * (1 - _itThis->nRatio); + } + + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + _itLast = _itThis; + } +} + +void CMicroJointTarget::_CombineMultiSegmentMicroJoint(nce::CCadMultiSegments* pMultiSegment_, std::vector& vectMJItem_) +{ + ASSERT(vectMJItem_.size() > 0); + int _nSegmentCounts = pMultiSegment_->GetSegmentCount(); + double _nTotleLength = pMultiSegment_->GetLength(); + vector::iterator _itLast = vectMJItem_.begin(); + for (vector::iterator _itThis = vectMJItem_.begin(); _itThis != vectMJItem_.end(); _itThis++) + { + double _nHeadLength; + double _nTailLength; + _GetMultiSenmentDivdeLength(pMultiSegment_, _itThis->nSeg, _itThis->nRatio, _nHeadLength, _nTailLength); + if (_itThis == vectMJItem_.begin()) + { + if (_itThis->nLength > _nTailLength) + { + _itThis->nLength = _nTailLength; + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itLast = _itThis = vectMJItem_.begin(); + } + break; + } + + continue; + } + + + // 判断这一个微连段是不是落在上一个微连的空程中 + MJItem _nLastEnd; + bool _bFind = false; + double _nLastSegRemained = pMultiSegment_->GetSegment(_itLast->nSeg).GetLength() * (1 - _itLast->nRatio); + if (_nLastSegRemained >= _itLast->nLength) + { + _nLastEnd.nSeg = _itLast->nSeg; + _nLastEnd.nRatio = _itLast->nRatio + _itLast->nLength / pMultiSegment_->GetSegment(_itLast->nSeg).GetLength(); + _bFind = true; + } + else + { + // 上一段不足够 + double _nTempLength = _itLast->nLength - _nLastSegRemained; + int _nSegNo = _itLast->nSeg + 1; + while(_nSegNo < pMultiSegment_->GetSegmentCount()) + { + if (_nTempLength < pMultiSegment_->GetSegment(_nSegNo).GetLength()) + { + _nLastEnd.nSeg = _nSegNo; + _nLastEnd.nRatio = _nTempLength / pMultiSegment_->GetSegment(_nSegNo).GetLength(); + _bFind = true; + break; + } + _nSegNo++; + if (_nSegNo < pMultiSegment_->GetSegmentCount()) + { + _nTempLength -= pMultiSegment_->GetSegment(_nSegNo).GetLength(); + } + } + } + ASSERT(_bFind); + + // 当前微连起点落在前一个的微连范围内则去除掉当前微连点 ---- DingQiang 2016-03-11 + if (!_bFind || *_itThis < _nLastEnd ) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + // 剩余距离不够微连长度,则把微连长度调整为剩余距离的长度 ---- DingQiang 2016-03-11 + if (_itThis->nLength > _nTailLength) + { + _itThis->nLength = _nTailLength; + } + + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + _itLast = _itThis; + } +} + + +void CMicroJointTarget::_GetMultiSenmentDivdeLength(IN nce::CCadMultiSegments* pMultiSegment_, IN UINT nSegNo_, IN double nRatio_, + OUT double& nHeadLength_, OUT double& nTailLength_) +{ + UINT _nSegIndex = 0; + nHeadLength_ = 0.; + if (nSegNo_ >= (UINT)pMultiSegment_->GetSegmentCount()) + { + ASSERT(FALSE); + return; + } + + while (_nSegIndex < nSegNo_) + { + SEGMENT _segment = pMultiSegment_->GetSegment(_nSegIndex++); + nHeadLength_ += _segment.GetLength(); + } + ASSERT(_nSegIndex == nSegNo_); + SEGMENT _segment = pMultiSegment_->GetSegment(_nSegIndex); + nHeadLength_ += _segment.GetLength() * nRatio_; + nTailLength_ = pMultiSegment_->GetLength() - nHeadLength_; +} + +void CMicroJointTarget::_CombineEllipseMicroJoint(nce::CCadEllipse* pCadEllipse_, std::vector& vectMJItem_) +{ + ASSERT(vectMJItem_.size() > 0); + + double _nTotleLength = pCadEllipse_->GetLength(); + vector::iterator _itLast = vectMJItem_.begin(); + for (vector::iterator _itThis = vectMJItem_.begin(); _itThis != vectMJItem_.end(); _itThis++) + { + if (_itThis == vectMJItem_.begin()) + { + if (_itThis->nLength > _nTotleLength * (1 - _itThis->nRatio)) + { + _itThis->nLength = _nTotleLength * (1 - _itThis->nRatio); + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itLast = _itThis = vectMJItem_.begin(); + } + break; + } + + continue; + } + + // 微连长度为0或者当前微连起点落在前一个的微连范围内则去除掉当前微连点 ---- DingQiang 2016-03-11 + if (_itThis->nRatio < _itLast->nRatio + _itLast->nLength / _nTotleLength) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + // 剩余距离不够微连长度,则把微连长度调整为剩余距离的长度 ---- DingQiang 2016-03-11 + if (_itThis->nLength > _nTotleLength * (1 - _itThis->nRatio)) + { + _itThis->nLength = _nTotleLength * (1 - _itThis->nRatio); + } + + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + _itLast = _itThis; + } +} + +void CMicroJointTarget::_CombineEllipseArcMicroJoint(nce::CCadEllipseArc* pCadEllipseArc_, std::vector& vectMJItem_) +{ + ASSERT(vectMJItem_.size() > 0); + + double _nTotleLength = pCadEllipseArc_->GetLength(); + vector::iterator _itLast = vectMJItem_.begin(); + for (vector::iterator _itThis = vectMJItem_.begin(); _itThis != vectMJItem_.end(); _itThis++) + { + if (_itThis == vectMJItem_.begin()) + { + if (_itThis->nLength > _nTotleLength * (1 - _itThis->nRatio)) + { + _itThis->nLength = _nTotleLength * (1 - _itThis->nRatio); + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itLast = _itThis = vectMJItem_.begin(); + } + break; + } + + continue; + } + + // 当前微连起点落在前一个的微连范围内则去除掉当前微连点 ---- DingQiang 2016-03-11 + if (_itThis->nRatio < _itLast->nRatio + _itLast->nLength / _nTotleLength) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + // 剩余距离不够微连长度,则把微连长度调整为剩余距离的长度 ---- DingQiang 2016-03-11 + if (_itThis->nLength > _nTotleLength * (1 - _itThis->nRatio)) + { + _itThis->nLength = _nTotleLength * (1 - _itThis->nRatio); + } + + if (DOUBLE_EQU(_itThis->nLength, 0)) + { + vectMJItem_.erase(_itThis); + _itThis = _itLast; + continue; + } + + _itLast = _itThis; + } +} + +static bool FindObjectByID(IN CCadObject* pCadObj_, IN int nID_, OUT CCadObject** ppResult_) +{ + if (pCadObj_->GetID() == nID_) + { + *ppResult_ = pCadObj_; + return true; + } + + if (pCadObj_->GetType() == cadgroup) + { + CCadGroup* _pCadGroup = dynamic_cast(pCadObj_); + ASSERT(_pCadGroup); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCad = _pCadGroup->GetAt(_i); + if (FindObjectByID(_pCad, nID_, ppResult_)) + return true; + } + } + + return false; +} + +static double GetCadLength(IN const CCadObject* pCadObj_) +{ + switch(pCadObj_->GetType()) + { + case cadgroup: + return -1; + case cadline: + return ((const CCadLine*)pCadObj_)->GetLength(); + case cadcircle: + return ((const CCadCircle*)pCadObj_)->GetLength(); + case cadarc: + return ((const CCadArc*)pCadObj_)->GetLength(); + case cadellipse: + return ((const CCadEllipse*)pCadObj_)->GetLength(); + case cadellipsearc: + return ((const CCadEllipseArc*)pCadObj_)->GetLength(); + case cadpolygon: + return ((const CCadPolygon*)pCadObj_)->GetLength(); + case cadpolyline: + return ((const CCadPolyline*)pCadObj_)->GetLength(); + case cadstar: + return ((const CCadStar*)pCadObj_)->GetLength(); + case cadrectangle: + return ((const CCadRectangle*)pCadObj_)->GetLength(); + } + + return false; +} diff --git a/src/NcBoardPcimc85A.cpp b/src/NcBoardPcimc85A.cpp new file mode 100644 index 0000000..96a2397 --- /dev/null +++ b/src/NcBoardPcimc85A.cpp @@ -0,0 +1,2205 @@ +#include "stdafx.h" +#include "NcAdpt.h" +#include "Device.h" +#include "NccmdDispatcher85A.h" + +#define FILE_ID 'NBP8' + +//////////////////////////////////////////////////////////////////////////////// +// SynPort +// +class ISynPort +{ +public: + ISynPort(); + virtual ~ISynPort(); + virtual void Synchronize() = 0; +protected: + static ISynPort* ms_pSysPorts[64]; + friend class CSynPortManager; +}; + +ISynPort* ISynPort::ms_pSysPorts[64] = {NULL}; +ISynPort::ISynPort() +{ + for (int _i = 0; _i < _countof(ms_pSysPorts); _i++) + { + if (ms_pSysPorts[_i] == NULL) + { + ms_pSysPorts[_i] = this; + break; + } + } +} + +ISynPort::~ISynPort() +{ + for (int _i = 0; _i < _countof(ms_pSysPorts); _i++) + { + if (ms_pSysPorts[_i] == this) + { + ms_pSysPorts[_i] = NULL; + break; + } + } +} + +CSynPortManager* CSynPortManager::ms_pInstance = NULL; +CSynPortManager* GetSynPortManager() +{ + return CSynPortManager::ms_pInstance; +} + +CSynPortManager::CSynPortManager() +{ + CHECK_PARAM(ms_pInstance == NULL); + ms_pInstance = this; +} + +CSynPortManager::~CSynPortManager() +{ + CHECK_PARAM(ms_pInstance == this); + ms_pInstance = NULL; +} + +void CSynPortManager::Synchronize() +{ + for (int _i = 0; _i < _countof(ISynPort::ms_pSysPorts); _i++) + { + if (ISynPort::ms_pSysPorts[_i]) + ISynPort::ms_pSysPorts[_i]->Synchronize(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// CLambdaAnalogOutPort +// +class CLambdaAnalogOutPort : public CAnalogOutPort +{ +public: + CLambdaAnalogOutPort(const char* pszName_) : CAnalogOutPort(pszName_){ TRACE("CLambdaAnalogOutPort\n"); } +protected: + virtual void OutByte(UINT nAddr_, BYTE nData_); +}; + +void CLambdaAnalogOutPort::OutByte(UINT nAddr_, BYTE nData_) +{ +#if defined (SIMUDRIVER) + return __super::OutByte(nAddr_, nData_); +#endif + CHECK_PARAM(GetBlockFrom32Addr(nAddr_) == 0x01); + ((CNcBoardPcimc85A*)GetDevice())->SetOutPortMap(GetOffsetFrom32Addr(nAddr_), nData_); +} + +//////////////////////////////////////////////////////////////////////////////// +// CLambdaAnalogPort +// +class CLambdaAnalogPort : public CAnalogPort +{ +public: + CLambdaAnalogPort(const char* pszName_) : CAnalogPort(pszName_) { TRACE("CLambdaAnalogPort\n"); } + virtual ~CLambdaAnalogPort() { m_analogPortInfo.nType = APT_INVALID; } // 析构函数调不到子类的虚函数 +protected: + virtual bool InBit(UINT64 nAddr_); + virtual void OutBit(UINT64 nAddr_, bool bValue_); + virtual BYTE InByte(UINT nAddr_); + virtual void OutByte(UINT nAddr_, BYTE nData_); +}; + +bool CLambdaAnalogPort::InBit(UINT64 nAddr_) +{ +#if defined (SIMUDRIVER) + return __super::InBit(nAddr_); +#endif + CHECK_PARAM(GetBlockFrom64Addr(nAddr_) == 0x01); + BYTE _val = InByte(GetOffsetFrom64Addr(nAddr_)); + DWORD _bit = GetBitFrom64Addr(nAddr_); + BYTE _mask = 1 << _bit; + + return (_val & _mask) != 0; +} + +void CLambdaAnalogPort::OutBit(UINT64 nAddr_, bool bValue_) +{ +#if defined (SIMUDRIVER) + return __super::OutBit(nAddr_, bValue_); +#endif + CHECK_PARAM(GetBlockFrom64Addr(nAddr_) == 0x01); + UINT32 _addr = GetOffsetFrom64Addr(nAddr_); + DWORD _bit = GetBitFrom64Addr(nAddr_); + BYTE _mask = 1 << _bit; + + CNcBoardPcimc85A* _pDevice = (CNcBoardPcimc85A*)GetDevice(); + BYTE _map = _pDevice->GetOutPortMap(_addr); + if (bValue_) + _map |= _mask; + else + _map &= ~_mask; + + _pDevice->SetOutPortMap(_addr, _map); +} + +BYTE CLambdaAnalogPort::InByte(UINT nAddr_) +{ +#if defined (SIMUDRIVER) + return __super::InByte(nAddr_); +#endif + CHECK_PARAM(GetBlockFrom32Addr(nAddr_) == 0x01); + CNcBoardPcimc85A* _pDevice = (CNcBoardPcimc85A*)GetDevice(); + return _pDevice->GetInPortMap(GetOffsetFrom32Addr(nAddr_)); +} + +void CLambdaAnalogPort::OutByte(UINT nAddr_, BYTE nData_) +{ +#if defined (SIMUDRIVER) + return __super::OutByte(nAddr_, nData_); +#endif + + CHECK_PARAM(GetBlockFrom32Addr(nAddr_) == 0x01); + CNcBoardPcimc85A* _pDevice = (CNcBoardPcimc85A*)GetDevice(); + _pDevice->SetOutPortMap(GetOffsetFrom32Addr(nAddr_), nData_); +} + +//////////////////////////////////////////////////////////////////////////////// +// CLambdaInputPort +// +class CLambdaInputPort : public CInputPort +{ +public: + CLambdaInputPort(const char* pszName_) : CInputPort(pszName_) { TRACE("CLambdaInputPort\n"); } +protected: + virtual BYTE InByte(UINT nAddr_); + virtual void OutByte(UINT nAddr_, BYTE nData_); +}; + +BYTE CLambdaInputPort::InByte(UINT nAddr_) +{ +#if defined (SIMUDRIVER) + return __super::InByte(nAddr_); +#endif + CHECK_PARAM(GetBlockFrom32Addr(nAddr_) == 0x01); + CNcBoardPcimc85A* _pDevice = (CNcBoardPcimc85A*)GetDevice(); + return ~_pDevice->GetInPortMap(GetOffsetFrom32Addr(nAddr_)); +} + +void CLambdaInputPort::OutByte(UINT nAddr_, BYTE nData_) +{ + FatalError(FILE_ID, __LINE__); +} + +//////////////////////////////////////////////////////////////////////////////// +// CLambdaOutputPort +// +class CLambdaOutputPort : public COutputPort +{ +public: + CLambdaOutputPort(const char* pszName_) : COutputPort(pszName_) { TRACE("CLambdaOutputPort\n"); } +protected: + virtual BYTE InByte(UINT nAddr_); + virtual void OutByte(UINT nAddr_, BYTE nData_); +}; + +BYTE CLambdaOutputPort::InByte(UINT nAddr_) +{ +#if defined (SIMUDRIVER) + return __super::InByte(nAddr_); +#endif + // 这里是为了得到初值的,对于Lambda的通信方案,输入和输出是分立的,一个端口 + // 即使既可以输入也可以输出,也不保证其输入和输出地址是一样的。所以初值就不 + // 要去读取来了,统一就是0就行了。 ---- 杨开锦 2014-02-11 + return ~BYTE(0); +} + +void CLambdaOutputPort::OutByte(UINT nAddr_, BYTE nData_) +{ +#if defined (SIMUDRIVER) + return __super::OutByte(nAddr_, nData_); +#endif + CHECK_PARAM(GetBlockFrom32Addr(nAddr_) == 0x01); + CNcBoardPcimc85A* _pDevice = (CNcBoardPcimc85A*)GetDevice(); + _pDevice->SetOutPortMap(GetOffsetFrom32Addr(nAddr_), ~nData_); +} + +//////////////////////////////////////////////////////////////////////////////// +// CLambdaRS232 +// +class CLambdaRS232 : public CLambdaPacketFifo +{ +public: + struct Info + { + CRS232Fifo* pTxFifo; + CRS232Fifo* pRxFifo; + unsigned short nID; + unsigned char nBRCode; + }; + CLambdaRS232(CLambdaController* pCtrl_, Info* pInfo_); + virtual ~CLambdaRS232(); + virtual bool Update(int nUs_); + virtual bool Dispatch(PACKAGE* pPackage_); +protected: + static const WORD c_nPnnRS232BR = 0x2200; + static const WORD c_nPnnRS232TR = 0x2300; + Info* m_pInfo; + unsigned char m_nBRCode; +}; + +CLambdaRS232::CLambdaRS232(CLambdaController* pCtrl_, Info* pInfo_) +{ + TRACE("CLambdaRS232 ID=0x%04X\n", pInfo_->nID); + m_pInfo = pInfo_; + m_nBRCode = 0xFF; + pCtrl_->Add(this); +} + +CLambdaRS232::~CLambdaRS232() +{ + TRACE("~CLambdaRS232 ID=0x%04X\n", m_pInfo->nID); + GetController()->Remove(this); +} + +bool CLambdaRS232::Update(int nUs_) +{ + if (!GetController()) + return false; + if (!m_pInfo) + return false; + + // 先设置波特率 ---- 杨开锦 2014-09-022 + if (m_nBRCode != m_pInfo->nBRCode) + { + PACKAGE _p; + _p.nPnnCmd = DCMD_APPINFO; + _p.nPnnLength = 6; + _p.nPnnSubcmd = c_nPnnRS232BR + (m_pInfo->nID & 0xFF); + _p.nPnnData[0] = m_pInfo->nBRCode; + if (!GetController()->WritePacket(&_p, NULL)) + { + TRACE("CLambdaRS232::Update => ID=0x%04X send BRCode error\n", m_pInfo->nID); + return false; + } + m_nBRCode = m_pInfo->nBRCode; + TRACE("CLambdaRS232::Update => ID=0x%04X BRCode=0x%02X\n", m_pInfo->nID, m_pInfo->nBRCode); + } + + // 再发数据 ---- 杨开锦 2014-09-22 + if (GetController()->GetDownFreeSpace() < 256) + return false; + if (m_pInfo->pTxFifo->GetCount() > 0) + { + BYTE _nDataLen = min(m_pInfo->pTxFifo->GetCount(), 16); + PACKAGE _p; + _p.nPnnCmd = DCMD_APPINFO; + _p.nPnnLength = _nDataLen + 5; + _p.nPnnSubcmd = c_nPnnRS232TR + (m_pInfo->nID & 0xFF); + m_pInfo->pTxFifo->Read((BYTE*)_p.nPnnData, _nDataLen); + if (!GetController()->WritePacket(&_p, NULL)) + { + TRACE("CLambdaRS232::Update => ID=0x%04X Tx error\n", m_pInfo->nID); + return false; + } + TRACE("CLambdaRS232::Update => ID=0x%04X Tx", m_pInfo->nID); + TRACE_HEX(_p.nPnnData, _nDataLen); + } + + return true; +} + +bool CLambdaRS232::Dispatch(PACKAGE* pPackage_) +{ + if (!GetController()) + return false; + if (!m_pInfo) + return false; + + if (pPackage_ == NULL) + return false; + if (pPackage_->nPnnCmd != DCMD_APPINFO) + return false; + if (pPackage_->nPnnLength < 6) + return false; + if ((pPackage_->nPnnSubcmd & 0xFF00) != c_nPnnRS232TR) + return false; + if ((pPackage_->nPnnSubcmd & 0x00FF) != (m_pInfo->nID & 0xFF)) + return false; + + BYTE _nDataLen = pPackage_->nPnnLength - 5; + m_pInfo->pRxFifo->Write((BYTE*)pPackage_->nPnnData, _nDataLen); + TRACE("CLambdaRS232::Update => ID=0x%04X Rx", m_pInfo->nID); + TRACE_HEX(pPackage_->nPnnData, _nDataLen); + return true; +} + +class CLambdaRS232Manager : public CRS232 +{ +public: + CLambdaRS232Manager(const char* pszName_); + virtual ~CLambdaRS232Manager(); +protected: + CLambdaRS232* m_pRS232[15]; + virtual void DoTransmission(); + virtual void DoReception() {} +}; + +CLambdaRS232Manager::CLambdaRS232Manager(const char* pszName_) : CRS232(pszName_) +{ + TRACE("CLambdaRS232Manager constructor...\n"); + TRACE_INDENT; + for (int _i = 0; _i < _countof(m_pRS232); _i++) + { + m_pRS232[_i] = NULL; + } +} + +CLambdaRS232Manager::~CLambdaRS232Manager() +{ + TRACE("CLambdaRS232Manager destructor...\n"); + TRACE_INDENT; + for (int _i = 0; _i < _countof(m_pRS232); _i++) + { + if (m_pRS232[_i]) + { + delete m_pRS232[_i]; + m_pRS232[_i] = NULL; + } + } +} + +void CLambdaRS232Manager::DoTransmission() +{ + C_ASSERT(_countof(m_pRS232) == _countof(m_rs232InfoSlots)); + C_ASSERT(sizeof(__super::RS232Info) >= sizeof(CLambdaRS232::Info)); + C_ASSERT(FIELD_OFFSET(__super::RS232Info, pTxFifo) == FIELD_OFFSET(CLambdaRS232::Info, pTxFifo)); + C_ASSERT(RTL_FIELD_SIZE(__super::RS232Info, pTxFifo) == RTL_FIELD_SIZE(CLambdaRS232::Info, pTxFifo)); + C_ASSERT(FIELD_OFFSET(__super::RS232Info, pRxFifo) == FIELD_OFFSET(CLambdaRS232::Info, pRxFifo)); + C_ASSERT(RTL_FIELD_SIZE(__super::RS232Info, pRxFifo) == RTL_FIELD_SIZE(CLambdaRS232::Info, pRxFifo)); + C_ASSERT(FIELD_OFFSET(__super::RS232Info, nID) == FIELD_OFFSET(CLambdaRS232::Info, nID)); + C_ASSERT(RTL_FIELD_SIZE(__super::RS232Info, nID) == RTL_FIELD_SIZE(CLambdaRS232::Info, nID)); + C_ASSERT(FIELD_OFFSET(__super::RS232Info, nBRCode) == FIELD_OFFSET(CLambdaRS232::Info, nBRCode)); + C_ASSERT(RTL_FIELD_SIZE(__super::RS232Info, nBRCode) == RTL_FIELD_SIZE(CLambdaRS232::Info, nBRCode)); + for (int _i = 0; _i < _countof(m_rs232InfoSlots); _i++) + { + CLambdaRS232::Info* _pInfo = (CLambdaRS232::Info*)(m_rs232InfoSlots + _i); + if (_pInfo->pTxFifo == NULL && _pInfo->pRxFifo == NULL) + continue; + if (m_pRS232[_i] != NULL) + continue; + CNcBoardPcimc85A* _pDevice = (CNcBoardPcimc85A*)GetDevice(); + if (_pDevice == NULL || _pDevice->m_pAdapter == NULL) + continue; + CLambdaBus* _pBus = _pDevice->m_pAdapter->GetBus(HIBYTE(_pInfo->nID) >> 4); + if (_pBus == NULL || _pBus->GetEnable() == false) + continue; + CLambdaController* _pCtrl = _pBus->GetController(HIBYTE(_pInfo->nID) & 0x0F); + if (_pCtrl == NULL || _pCtrl->GetEnable() == false) + continue; + m_pRS232[_i] = new CLambdaRS232(_pCtrl, _pInfo); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// CCounter85A +// +class CCounter85A : public CFnap, public CCounter +{ +public: + CCounter85A(const char* pszName_); + virtual ~CCounter85A(); + + virtual void Initialize(UINT nAddr_); + virtual void Update(); + virtual int GetCount(); + +private: + UINT m_nAddr; + int* m_pnCountInSW; + NTSTATUS FnapConfigureCounter(FNAP_CONFIGURE_COUNTER* pFnap_); +}; + +CCounter85A::CCounter85A(const char* pszName_) : CFnap(pszName_) +{ + m_nAddr = Make32Addr(250); + m_pnCountInSW = (int*)GetSwitchArea()->Allocate(sizeof(int)); + if (!m_pnCountInSW) + FatalError(FILE_ID, __LINE__); + GetFnapManager()->Register(this, "FnapConfigureCounter", (PFNAP_FUNC)&CCounter85A::FnapConfigureCounter, true); +} + +CCounter85A::~CCounter85A() +{ + GetSwitchArea()->Free(m_pnCountInSW); +} + +// 手轮计数是InMap中的上行数据,占4个字节 ---- 杨开锦 2014-05-22 +int CCounter85A::GetCount() +{ + CHECK_PARAM(GetBlockFrom32Addr(m_nAddr) == 0x01); + CNcBoardPcimc85A* _pDevice = (CNcBoardPcimc85A*)GetDevice(); + + union + { + BYTE buffer[4]; + UINT32 val; + }_val; + + _val.buffer[0] = _pDevice->GetInPortMap(GetOffsetFrom32Addr(m_nAddr)); + _val.buffer[1] = _pDevice->GetInPortMap(GetOffsetFrom32Addr(m_nAddr) + 1 ); + _val.buffer[2] = _pDevice->GetInPortMap(GetOffsetFrom32Addr(m_nAddr) + 2 ); + _val.buffer[3] = _pDevice->GetInPortMap(GetOffsetFrom32Addr(m_nAddr) + 3 ); + + return _val.val; +} + +void CCounter85A::Initialize(UINT nAddr_) +{ + m_nAddr = nAddr_; +} + +void CCounter85A::Update() +{ + // No need to update +} + +NTSTATUS CCounter85A::FnapConfigureCounter(FNAP_CONFIGURE_COUNTER* pFnap_) +{ + CHECK_PARAM(pFnap_->nInSize == sizeof(FNAP_HEADER)); + CHECK_PARAM(pFnap_->nOutSize == sizeof(FNAP_CONFIGURE_COUNTER)); + pFnap_->pnCountInSW = (::GetSwitchArea()->ConvertToR3Address(m_pnCountInSW)); + return STATUS_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////// +// CFpgaUpdate 更新板卡的Fpga程序 ---- 杨开锦 2014-05-30 +// +class CFpgaUpdateFifo : public CRingBuffer +{ +public: + bool HasPacket() + { + if (GetCount() < 3) + return false; + BYTE _nLen = m_data[(m_nReadIndex + 1) % c_nN]; + return (GetCount() >= _nLen); + } +}; +#pragma pack(push,8) +struct FNAP_FPGA_UPDATE : FNAP_HEADER +{ + DWORD nType; // [传入信息],1->控制卡,2->端子板 + DWORD nNA; // [传入信息],保留 + void* __ptr32 pFifo; // [返回信息],数据缓冲区 + BYTE* __ptr32 pnStatusBits; // [返回信息],更新状态位 +}; +#pragma pack(pop) +class CFpgaUpdate : public CFnap +{ +public: + CFpgaUpdate(const char* pszName_); + virtual ~CFpgaUpdate(); + +protected: + PUCHAR m_pDataPort; + PUCHAR m_pStatusPort; + PUCHAR m_pCommandPort; + CPortFifo m_UpFifo; + CPortFifo m_DownFifo; + BYTE* m_pnStatusBits; + CFpgaUpdateFifo* m_pFifo; + KEVENT m_eventURTerminator; + static void UpdateRoutine1(PVOID pData_); + static void UpdateRoutine2(PVOID pData_); + static int UR2_ReadUp(CFpgaUpdate* pFU_); + static int UR2_WriteDown(CFpgaUpdate* pFU_); + + WORD m_nStage; + NTSTATUS FnapBeginUpdate(FNAP_FPGA_UPDATE* pFnap_); + NTSTATUS FnapEndUpdate(FNAP_HEADER* pFnap_); +}; + +CFpgaUpdate::CFpgaUpdate(const char* pszName_) + : CFnap(pszName_) +{ + TRACE("Driver::CFpgaUpdate::Constructor\n"); + + m_nStage = 0; + KeInitializeEvent(&m_eventURTerminator, NotificationEvent, FALSE); + + m_pnStatusBits = (BYTE*)GetSwitchArea()->Allocate(sizeof(BYTE)); + if (!m_pnStatusBits) + FatalError(FILE_ID, __LINE__); + *m_pnStatusBits = 0; + m_pFifo = (CFpgaUpdateFifo*)GetSwitchArea()->Allocate(sizeof(CFpgaUpdateFifo)); + if (!m_pFifo) + FatalError(FILE_ID, __LINE__); + m_pFifo->CFpgaUpdateFifo::CFpgaUpdateFifo(); + + CNcBoardPcimc85A* _pDevice = (CNcBoardPcimc85A*)GetDevice(); + CLambdaAdapter* _pAdapter = _pDevice->m_pAdapter; + ADAPTER_BASE_INFO_V2* _pABI = _pAdapter->GetAdapterBaseInfo(); + CHECK_PARAM(_pDevice); + CHECK_PARAM(_pAdapter); + CHECK_PARAM(_pABI); + + m_UpFifo.Bind( + _pAdapter->GetCHType(), + _pAdapter->GetPortBase() + _pABI->Ctrls[0].nUpFifoPort, + _pABI->Ctrls[0].nUpFifoLength); + + m_DownFifo.Bind( + _pAdapter->GetCHType(), + _pAdapter->GetPortBase() + _pABI->Ctrls[0].nDownFifoPort, + _pABI->Ctrls[0].nDownFifoLength); + + m_pDataPort = _pAdapter->GetPortBase() + _pABI->nAdapterFifoPort; + + m_pStatusPort = m_pDataPort + 1; + m_pCommandPort = m_pDataPort + 2; + + GetFnapManager()->Register(this, "FnapBeginUpdate", (PFNAP_FUNC)&CFpgaUpdate::FnapBeginUpdate, true); + GetFnapManager()->Register(this, "FnapEndUpdate", (PFNAP_FUNC)&CFpgaUpdate::FnapEndUpdate, true); +} + +CFpgaUpdate::~CFpgaUpdate() +{ + if (KeSetEvent(&m_eventURTerminator, 1, FALSE) == 0) + { + SleepAtPassiveLevel(40); + } + + GetSwitchArea()->Free(m_pFifo); + GetSwitchArea()->Free(m_pnStatusBits); + + TRACE("Driver::CFpgaUpdate::Destructor\n"); +} + +void CFpgaUpdate::UpdateRoutine1(PVOID pData_) +{ + CHECK_PARAM(pData_ != NULL); + TRACE("CFpgaUpdate::UpdateRoutine1 begin...\n"); + + CFpgaUpdate* _pFU = (CFpgaUpdate*)pData_; + + // 这是更新的主函数,在独立线程中运行,负责下传数据并更新状态 ---- 杨开锦 2014-06-07 + // BeginUpdate时创建此线程,EndUpdate时停掉 + // 循环从缓冲区读,写入到硬件 + // 一个周期最多工作5ms,周期间隔1ms + // 线程切换是操作系统决定的,很可能达不到1ms切换,此处的意思是尽快回来 + // 硬件写Flash的速度约为5us/Byte + // 但硬件中做的是先写入,再读出校验,可能会再慢一些 + // 由于线程切换,有效工作时间不长,实际速度是此值的若干分之一,假设是1/4 + // 我们目前的FPGA程序一般为300-500K + // 但写入的是帧数据,有效载荷会少一些 + // 以每帧16Byte载荷为例,载荷比为 16/24 + // 可推知,更新过程大概要15秒(算上了3s擦除时间),这应该是可以的 + int _nWriteCount = 0; + __int64 _nWaitTime = -10000; // 1ms + while (STATUS_TIMEOUT == KeWaitForSingleObject(&_pFU->m_eventURTerminator, + Executive, KernelMode, FALSE, (LARGE_INTEGER*)&_nWaitTime)) + { + int _nWC = 0; + LARGE_INTEGER _freq; + __int64 _tickBegin = KeQueryPerformanceCounter(&_freq).QuadPart; + __int64 _tickCurrent = _tickBegin; + __int64 _tickBusy = _tickBegin; + while (_tickCurrent - _tickBegin < _freq.QuadPart * 5 / 1000) + { + _tickCurrent = KeQueryPerformanceCounter(NULL).QuadPart; + UCHAR _nStatus = READ_PORT_UCHAR(_pFU->m_pStatusPort); + BYTE _nSBits = *_pFU->m_pnStatusBits; + if ((_nStatus & 0x01) == 0) _nSBits |= 0x80; // 向R3提供的状态字只有三个位 + if ((_nStatus & 0x02) == 0) _nSBits |= 0x02; // Bit0:擦除完成、Bit1:更新完成、Bit7更新错误 + if ((_nStatus & 0x04) == 0) _nSBits |= 0x01; // 对于Crc8错误也算到更新错误中 + if ((_nStatus & 0x08) == 0) _nSBits |= 0x80; // 且换算为正逻辑,即1有效 + *_pFU->m_pnStatusBits = _nSBits; + if (_nSBits & 0x82) + { + break; + } + + if (_pFU->m_pFifo->IsEmpty()) + break; + + // Bit4: FIFO空,高有效 + // Bit5: FIFO满,高有效 + if ((_nStatus & 0x20) != 0) + { + if (_tickCurrent - _tickBusy < _freq.QuadPart * 1 / 1000) + continue; + else + break; + } + _tickBusy = _tickCurrent; + + BYTE _nData; + _pFU->m_pFifo->Read(&_nData); + WRITE_PORT_UCHAR(_pFU->m_pDataPort, _nData); + _nWC++; + } + + _nWriteCount += _nWC; + if (_nWC > 0) TRACE("CFpgaUpdate::UpdateRoutine1 => _nWC=%d\n", _nWC); + } + + TRACE("CFpgaUpdate::UpdateRoutine1 => _nWriteCount=%d\n", _nWriteCount); + TRACE("CFpgaUpdate::UpdateRoutine1 end.\n"); + PsTerminateSystemThread(STATUS_SUCCESS); +} + +void CFpgaUpdate::UpdateRoutine2(PVOID pData_) +{ + CHECK_PARAM(pData_ != NULL); + TRACE("CFpgaUpdate::UpdateRoutine2 begin...\n"); + NTSTATUS _nRet = STATUS_SUCCESS; + + CFpgaUpdate* _pFU = (CFpgaUpdate*)pData_; + + int _nReadPacket = 0; + int _nWritePacket = 0; + __int64 _nWaitTime = 0; + while (STATUS_TIMEOUT == KeWaitForSingleObject(&_pFU->m_eventURTerminator, + Executive, KernelMode, FALSE, (LARGE_INTEGER*)&_nWaitTime)) + { + LARGE_INTEGER _freq; + __int64 _tickBegin = KeQueryPerformanceCounter(&_freq).QuadPart; + __int64 _tickCurrent = _tickBegin; + int _nIdleCount = 0; + while (_tickCurrent - _tickBegin < _freq.QuadPart * 5 / 1000 && _nIdleCount < 5) + { + _tickCurrent = KeQueryPerformanceCounter(NULL).QuadPart; + + // 先读状态 ---- 杨开锦 2014-06-07 + int _nR = UR2_ReadUp(_pFU); + if (_nR < 0) + { + _nRet = STATUS_UNSUCCESSFUL; + break; + } + _nReadPacket += _nR; + + // 再写数据 ---- 杨开锦 2014-06-07 + int _nW = 0; + if (_nWritePacket - _nReadPacket < 11) // 限流 + _nW = UR2_WriteDown(_pFU); + _nWritePacket += _nW; + _nIdleCount = (_nW > 0) ? 0 : _nIdleCount + 1; + } + + if (_nRet != STATUS_SUCCESS) + break; + } + + TRACE("CFpgaUpdate::UpdateRoutine2 => _nReadPacket=%d\n", _nReadPacket); + TRACE("CFpgaUpdate::UpdateRoutine2 => _nWritePacket=%d\n", _nWritePacket); + TRACE("CFpgaUpdate::UpdateRoutine2 end. _nRet = 0x%02X\n", _nRet); + PsTerminateSystemThread(_nRet); +} + +int CFpgaUpdate::UR2_ReadUp(CFpgaUpdate* pFU_) +{ + CHECK_PARAM(pFU_); + int _nRet = 0; + + #pragma pack(push, 1) + struct _PACKAGE + { + BYTE nHead; + BYTE nLength; + WORD nPnn; + BYTE nStatus; + BYTE nCRC8; + }; + #pragma pack(pop) + while (BYTE* _p = pFU_->m_UpFifo.Read()) + { + BYTE _nLen = _p[1]; + if (_nLen < 2) + { + TRACE("CFpgaUpdate::UR2_ReadUp => _nLen < 2\n"); + _nRet = -1; + break; + } + + while (_p[0] == UCMD_TUNNEL_NONRT || _p[0] == UCMD_TUNNEL_DISRT || _p[0] == UCMD_TUNNEL_UNDRT) + { + if (_p[_nLen - 1] != CalculateCRC8(_p, _nLen - 1)) + { + TRACE("CFpgaUpdate::UR2_ReadUp => TUNNEL CRC Error\n"); + TRACE_INDENT; + TRACE_HEX(_p, _nLen); + _nRet = -1; + break; + } + _p += 2; + _nLen = _p[1]; + } + if (_nRet < 0) + break; + + if (_p[_nLen - 1] != CalculateCRC8(_p, _nLen - 1)) + { + TRACE("CFpgaUpdate::UR2_ReadUp => CRC Error\n"); + TRACE_INDENT; + TRACE_HEX(_p, _nLen); + _nRet = -1; + break; + } + + _PACKAGE* _pSYS = (_PACKAGE*)_p; + if (_pSYS->nHead != UCMD_SYSINFO) + continue; + if (_pSYS->nPnn != 0xFF00 && _pSYS->nPnn != 0xFF01 && _pSYS->nPnn != 0xFF02) + continue; + if (_pSYS->nLength != sizeof(_PACKAGE)) + { + TRACE("CFpgaUpdate::UR2_ReadUp => _pSYS->nLength Error\n"); + TRACE_INDENT; + TRACE_HEX(_pSYS, _pSYS->nLength); + _nRet = -1; + break; + } + + _nRet++; + pFU_->m_nStage = _pSYS->nPnn; + *pFU_->m_pnStatusBits = _pSYS->nStatus; + } + + return _nRet; +} + +int CFpgaUpdate::UR2_WriteDown(CFpgaUpdate* pFU_) +{ + CHECK_PARAM(pFU_); + + int _nRet = 0; + while (_nRet < 4 && pFU_->m_pFifo->HasPacket() && pFU_->m_DownFifo.GetFree() >= 256) + { + BYTE _p[256]; + pFU_->m_pFifo->Read(_p + 0); + pFU_->m_pFifo->Read(_p + 1); + for (int _i = 2; _i < _p[1]; _i++) + { + pFU_->m_pFifo->Read(_p + _i); + } + + _nRet++; + pFU_->m_DownFifo.Write(_p); + } + + return _nRet; +} + +NTSTATUS CFpgaUpdate::FnapBeginUpdate(FNAP_FPGA_UPDATE* pFnap_) +{ + CHECK_PARAM(pFnap_->nInSize == sizeof(FNAP_FPGA_UPDATE)); + CHECK_PARAM(pFnap_->nOutSize == sizeof(FNAP_FPGA_UPDATE)); + CHECK_PARAM(pFnap_->nType == 1 || pFnap_->nType == 2); + CHECK_PARAM(pFnap_->nNA == 0); + CHECK_PARAM(pFnap_->pFifo == NULL); + CHECK_PARAM(pFnap_->pnStatusBits == NULL); + TRACE("CFpgaUpdate::FnapBeginUpdate begin...\n"); + TRACE_INDENT; + + if (pFnap_->nType == 1) + { + // 初始化: ---- 杨开锦 2014-05-30 + // 1.切换到非更新状态 + // 2.清除缓冲区 + // 3.切换到更新状态 + // 控制字 + // Bit0: 更新使能,低有效 + // Bit1: 清除FIFO,高有效 + WRITE_PORT_UCHAR(m_pCommandPort, 0x01); + SleepAtPassiveLevel(10); + WRITE_PORT_UCHAR(m_pCommandPort, 0x03); + SleepAtPassiveLevel(10); + WRITE_PORT_UCHAR(m_pCommandPort, 0x00); + } + + // 开一个工作线程来进行数据下行传输 ---- 杨开锦 2014-06-07 + // 先结束上一次的更新Routine(应用层可能没调FnapEndUpdate) + // 再创建一个新的线程 + // 系统线程不能被杀掉只能自己退出 + // 通过设置事件的方式叫线程函数退出 + KeSetEvent(&m_eventURTerminator, 1, FALSE); + SleepAtPassiveLevel(40); + m_pFifo->Reset(); + *m_pnStatusBits = 0; + m_nStage = 0; + KeClearEvent(&m_eventURTerminator); + HANDLE _hThread; + NTSTATUS _nStatus = PsCreateSystemThread( + &_hThread, + THREAD_ALL_ACCESS, + NULL, + NULL, + NULL, + pFnap_->nType == 1 ? CFpgaUpdate::UpdateRoutine1 : CFpgaUpdate::UpdateRoutine2, + this); + if (!NT_SUCCESS(_nStatus)) + { + TRACE("PsCreateSystemThread failed\n"); + KeSetEvent(&m_eventURTerminator, 1, FALSE); + return _nStatus; + } + ZwClose(_hThread); + + // 将更新的状态通过状态位告知给上层应用程序 ---- 杨开锦 2014-09-05 + // 这里的状态码即为硬件给上来状态码 + // 所有位全0表示正确,有非0表示异常 + pFnap_->pFifo = (::GetSwitchArea()->ConvertToR3Address(m_pFifo)); + pFnap_->pnStatusBits = (BYTE*)::GetSwitchArea()->ConvertToR3Address(m_pnStatusBits); + return STATUS_SUCCESS; +} + +NTSTATUS CFpgaUpdate::FnapEndUpdate(FNAP_HEADER* pFnap_) +{ + CHECK_PARAM(pFnap_->nInSize == sizeof(FNAP_HEADER)); + CHECK_PARAM(pFnap_->nOutSize == 0); + TRACE("CFpgaUpdate::FnapEndUpdate begin...\n"); + TRACE_INDENT; + + bool _bSucceed = (*m_pnStatusBits == 0x00 && m_nStage == 0xFF02); + + // 结束线程函数 ---- 杨开锦 2014-06-07 + KeSetEvent(&m_eventURTerminator, 1, FALSE); + SleepAtPassiveLevel(40); + m_pFifo->Reset(); + *m_pnStatusBits = 0; + m_nStage = 0; + + // 使硬件退出在线更新的状态 ---- 杨开锦 2014-05-31 + WRITE_PORT_UCHAR(m_pCommandPort, 0x01); + + // 擦除正确且更新完成,则是成功,否则失败 ---- 杨开锦 2014-05-31 + return _bSucceed ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; +} + +//////////////////////////////////////////////////////////////////////////////// +// CSynPort,实现Lambda主控结点以外结点的同步端口控制 ---- 杨开锦 2015-03-09 +// +#pragma pack(push,8) +struct FNAP_SYN_PORT : FNAP_HEADER +{ + bool* __ptr32 pbEnable; // [返回信息],使能 + int nCount; // [传入信息],缓冲数 + DWORD nAddr; // [传入信息],端口地址 + DWORD nMask; // [传入信息],端口位掩码 +}; +#pragma pack(pop) +class CSynPort : public CFnap, public ISynPort, public CLambdaPacketFifo +{ +public: + CSynPort(const char* pszName_, CLambdaAdapter* pAdapter_); + virtual ~CSynPort(); + +protected: + bool* m_pbEnable; + BYTE m_nCount; + DWORD m_nAddr; + DWORD m_nMask; + DWORD m_nCache; + int m_nDifference; // in 1/1000000;正=>要补;负=>要扔 + CLambdaAdapter* m_pAdapter; + NTSTATUS FnapConfigureSynPort(FNAP_SYN_PORT* pFnap_); + + BYTE m_nLastBuffer; + CRingBuffer m_SoftBuffer; + virtual void Synchronize(); + + static const BYTE c_nPnn = 0x07; + BYTE m_nHardBufferCount; + virtual bool Update(int nUs_); + virtual bool Dispatch(PACKAGE* pPackage_); +}; + +CSynPort::CSynPort(const char* pszName_, CLambdaAdapter* pAdapter_) : CFnap(pszName_) +{ + TRACE("Driver::CSynPort::Constructor\n"); + m_pbEnable = (bool*)GetSwitchArea()->Allocate(sizeof(bool)); + if (!m_pbEnable) + FatalError(FILE_ID, __LINE__); + *m_pbEnable = false; + m_nCount = 0; + m_nAddr = 0; + m_nMask = 0; + m_nCache = 0; + m_nDifference = 0; + m_pAdapter = pAdapter_; + m_nLastBuffer = 0; + m_SoftBuffer.Reset(); + m_nHardBufferCount = 0; + GetFnapManager()->Register(this, "FnapConfigureSynPort", (PFNAP_FUNC)&CSynPort::FnapConfigureSynPort, true); +} + +CSynPort::~CSynPort() +{ + CLambdaController* _pCtrl = GetController(); + if (_pCtrl) + { + _pCtrl->Remove(this); + SetController(NULL); + } + + GetSwitchArea()->Free(m_pbEnable); + TRACE("Driver::CSynPort::Destructor\n"); +} + +NTSTATUS CSynPort::FnapConfigureSynPort(FNAP_SYN_PORT* pFnap_) +{ + CHECK_PARAM(pFnap_); + CHECK_PARAM(pFnap_->nInSize == sizeof(FNAP_SYN_PORT)); + CHECK_PARAM(pFnap_->nOutSize == sizeof(FNAP_SYN_PORT)); + TRACE("CSynPort::FnapConfigureSynPort begin...\n"); + TRACE_INDENT; + if (pFnap_->pbEnable || pFnap_->nCount <= 0 || pFnap_->nCount >= 128) + { + return STATUS_UNSUCCESSFUL; + } + + WORD _offset = LOWORD(pFnap_->nAddr); + BYTE _nBus = HIBYTE(_offset) >> 4; + BYTE _nCtrl = HIBYTE(_offset) & 0x0F; + BYTE _nByte = LOBYTE(_offset); + CHECK_PARAM(_nBus < 4 && _nBus >= 0); + CHECK_PARAM(_nCtrl < 8 && _nCtrl >= 0); + CHECK_PARAM(_nByte < 256 && _nByte >= 0); + if (m_pAdapter == NULL + || m_pAdapter->GetBus(_nBus) == NULL + || m_pAdapter->GetBus(_nBus)->GetController(_nCtrl) == NULL) + { + return STATUS_UNSUCCESSFUL; + } + +#ifndef SIMUDRIVER + if (!GetController()) + m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->Add(this); + if (GetController()->GetOrder() != _nCtrl || GetController()->GetOwnerBus()->GetBusNo() != _nBus) + return STATUS_UNSUCCESSFUL; +#endif + + pFnap_->pbEnable = (bool*)::GetSwitchArea()->ConvertToR3Address(m_pbEnable); + m_nCount = BYTE(pFnap_->nCount); + m_nAddr = pFnap_->nAddr; + m_nMask = pFnap_->nMask; + TRACE("Bus = %d\n", _nBus); + TRACE("Ctrl = %d\n", _nCtrl); + TRACE("Byte = %d\n", _nByte); + TRACE("Count = %d\n", m_nCount); + return STATUS_SUCCESS; +} + +void CSynPort::Synchronize() +{ +#if defined (SIMUDRIVER) + return; +#else + CLambdaController* _pCtrl = GetController(); + if (!_pCtrl || !_pCtrl->IsInitialized()) + return; + + BYTE _nPortValue = 0; + if (m_SoftBuffer.IsFull()) + m_SoftBuffer.Read(&_nPortValue); + _nPortValue = _pCtrl->GetSendPulse()->GetSynOut(m_nAddr & 0xFF); + + // 在 CMDDN_SYNPORT::nReserved 中记录了这个开关端口的准确时刻的小数部分 + // 大小是 0-15,单位是 1/16,量纲是毫秒(准确的说是控制周期) + // 现实现为 0-7则前半个控制周期开/关,8-15则后半个控制周期开/关 + CSynPortManager* _pSynPortManager = GetSynPortManager(); + CHECK_PARAM(_pSynPortManager); + if (_pSynPortManager->GetSynPortReserved(m_nAddr) <= 7) + m_SoftBuffer.Write(&_nPortValue); + else + m_SoftBuffer.Write(&m_nLastBuffer); + + m_SoftBuffer.Write(&_nPortValue); + m_nLastBuffer = _nPortValue; +#endif +} + +bool CSynPort::Update(int nUs_) +{ +#if defined (SIMUDRIVER) + return false; +#else + CLambdaController* _pCtrl = GetController(); + if (!_pCtrl || !_pCtrl->IsInitialized()) + return false; + + // 缓存Cache中前三个BYTE分别是参数包中的三个分量:开关、字节序、位掩码 ---- 杨开锦 2015-03-09 + BYTE _nEN = *m_pbEnable ? 0x81 : 0; + BYTE _nAddr = m_nAddr & 0xFF; + BYTE _nMask = m_nMask & 0xFF; + DWORD _nCache = (DWORD(_nEN) << 0) | (DWORD(_nAddr) << 8) | (DWORD(_nMask) << 16); + if (_nCache != m_nCache) + { + BYTE _p[] = { DCMD_APPINFO, 9, c_nPnn, 0x00, _nEN, _nAddr, _nMask, 0x01, 0x00 }; + if (_pCtrl->GetDownFreeSpace() < sizeof(_p) + 3 * 7) + return false; + _pCtrl->WritePacket((PACKAGE*)_p, NULL); + + // 请求返回30A当前缓冲区组数 ---- DingQiang 2015-05-20 + BYTE _pReadBufferCount[] = { DCMD_APPINFO, 6, 0x03, c_nPnn, 0x01, 0x00}; + _pCtrl->WritePacket((PACKAGE*)_pReadBufferCount, NULL); + m_nCache = _nCache; + } + + // 发数据,维持硬件中有稳定的组数 ---- 杨开锦 2015-03-09 + // 设置一个低通滤波器,以避免有时补上了过一会又还回去的情况。 + // 公式: Y(n) = A*X(n) + (1-A)*Y(n-1) + // 其中 X(n) -- 本次采样 + // Y(n-1) -- 上次滤波输出 + // A -- 滤波系数,通常远小于1 + // Y(n) -- 本次滤波输出 + // 此滤波公式用于模拟具有较大惯性的低通滤波器功能 + // 截止频率: fL = A/(2PI*t) (t为采样周期)。 + // 现在此功能的应用场景是Lambda5S+EX30A,在EX30A上添加此端口缓冲区 + // 硬件上EX30A和Lambda的晶振选型是一样的,83.3MHz + // 且已把EX30A的中断Tick数改成跟Lambda的脉冲周期Tick数一致,16384*5 + // 故不一致的地方应该是晶振的个体差异,从说明书上看到是正负50ppm + // 计算得 50ppm*2=100ppm=1/10000 => 10000ms差1ms => 10s差1ms + // 即最快10s会差一个控制周期,考虑滤波截止频率为0.2Hz + // A = fL * (2PI*t) = 0.2Hz * 2 * 3.14 * 0.001s = 0.001256 + // + // 修改:硬件上把EX30A的端口控制频率从1KHz改为2KHz ---- 杨开锦 2015-04-17 + // 目的是期望能把端口与脉冲的同步做到更精准 + // 软件上需要把一个1ms的端口数据分为两份控制数据来发入缓冲区 + // 并可以做到1ms端口状态的前0.5ms和后0.5ms不同,相当于其控制周期做到了0.5ms + if (m_SoftBuffer.GetCount() > 10) + TRACE("CSynPort::Update => SoftBuffer.Count=%d > 10", m_SoftBuffer.GetCount()); + int _nCount = (int)m_SoftBuffer.GetCount(); + int _nNeed = ((int)m_nHardBufferCount >= m_nCount) ? 0 : (m_nCount - (int)m_nHardBufferCount); + int _nSend = _nCount; + const int c_n1 = 1000000; + const int c_nA = 1256; + m_nDifference = int(((__int64)c_nA * (_nNeed - _nCount) * c_n1 + (__int64)(c_n1 - c_nA) * m_nDifference) / c_n1); + if (m_nDifference >= c_n1) + { + CHECK_PARAM(_nSend < 255); + _nSend++; + m_nDifference -= c_n1; + TRACE("CSynPort::Update => Count=%d Need=%d Send=%d", _nCount, _nNeed, _nSend); + } + if (m_nDifference <= -c_n1) + { + CHECK_PARAM(_nSend > 0); + _nSend--; + m_nDifference += c_n1; + TRACE("CSynPort::Update => Count=%d Need=%d Send=%d", _nCount, _nNeed, _nSend); + } + BYTE _pPush[] = { DCMD_APPINFO, 6, 0x04, c_nPnn, _pCtrl->GetSendPulse()->GetSynOut(_nAddr), 0x00 }; + for (int _i = 0; _i < _nSend; _i++) + { + if (_pCtrl->GetDownFreeSpace() < sizeof(_pPush) + 3 * 7) + { + TRACE("CSynPort::Update => _pCtrl->GetDownFreeSpace() < sizeof(_pPush) + 3 * 7"); + break; + } + m_nHardBufferCount++; + m_SoftBuffer.Read(_pPush + 4); + _pCtrl->WritePacket((PACKAGE*)_pPush, NULL); + } + m_SoftBuffer.Reset(); + return true; +#endif +} + +bool CSynPort::Dispatch(PACKAGE* pPackage_) +{ + if (!pPackage_ + || pPackage_->nPnnCmd != DCMD_APPINFO + || pPackage_->nPnnLength != 6 + || pPackage_->nPnnSubcmd != MAKEWORD(0x03, c_nPnn)) + { + return false; + } + + m_nHardBufferCount = pPackage_->nPnnData[0]; + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// FeedbackStream +// +#pragma pack(push, 8) +struct FNAP_FEEDBACK_STREAM : FNAP_HEADER +{ + BYTE nBusNo; // [传入信息],总线序号 + BYTE nReserved[2]; // [传入信息],保留 + BYTE nNumofAxes; // [返回信息],轴数 + void* __ptr32 pFeedbackFifo; // [返回信息],缓冲区指针 +}; +C_ASSERT(sizeof(FNAP_FEEDBACK_STREAM) == 72); +template +struct FeedbackNode +{ + DWORD nReserved; // 保留 + DWORD nTimeStamp; // 时间戳 + DWORD nNccmdSN; // 当前发送到的脉冲序号 + DWORD nFeedback[N]; // 编码器反馈计数(原始值) +}; +class CFeedbackFifo : public CRingBuffer, 8 * 1024> {}; +#pragma pack(pop) + +class CFeedbackStream : public CFnap, public CLambdaPacketFifo +{ +public: + CFeedbackStream(const char* pszName_, CLambdaAdapter* pAdapter_); + virtual ~CFeedbackStream(); + +protected: + BYTE m_nReserved[2]; + CLambdaAdapter* m_pAdapter; + CFeedbackFifo* m_pFeedbackFifo; + NTSTATUS FnapConfigureFeedbackStream(FNAP_FEEDBACK_STREAM* pFnap_); + + virtual bool Dispatch(PACKAGE* pPackage_); +}; + +CFeedbackStream::CFeedbackStream(const char* pszName_, CLambdaAdapter* pAdapter_) : CFnap(pszName_) +{ + TRACE("Driver::CFeedbackStream::Constructor\n"); + m_nReserved[0] = 0; + m_nReserved[1] = 0; + m_pAdapter = pAdapter_; + m_pFeedbackFifo = (CFeedbackFifo*)GetSwitchArea()->Allocate(sizeof(CFeedbackFifo)); + if (!m_pFeedbackFifo) + FatalError(FILE_ID, __LINE__); + m_pFeedbackFifo->CFeedbackFifo::CFeedbackFifo(); + GetFnapManager()->Register(this, "FnapConfigureFeedbackStream", (PFNAP_FUNC)&CFeedbackStream::FnapConfigureFeedbackStream, true); +} + +CFeedbackStream::~CFeedbackStream() +{ + CLambdaController* _pCtrl = GetController(); + if (_pCtrl) + { + _pCtrl->Remove(this); + SetController(NULL); + } + + GetSwitchArea()->Free(m_pFeedbackFifo); + TRACE("Driver::CFeedbackStream::Destructor\n"); +} + +NTSTATUS CFeedbackStream::FnapConfigureFeedbackStream(FNAP_FEEDBACK_STREAM* pFnap_) +{ + CHECK_PARAM(pFnap_); + CHECK_PARAM(pFnap_->nInSize == sizeof(FNAP_FEEDBACK_STREAM)); + CHECK_PARAM(pFnap_->nOutSize == sizeof(FNAP_FEEDBACK_STREAM)); + CHECK_PARAM(pFnap_->nBusNo == 0); + TRACE("CFeedbackStream::FnapConfigureFeedbackStream begin...\n"); + TRACE_INDENT; + if (pFnap_->nNumofAxes != 0) + return STATUS_UNSUCCESSFUL; + if (pFnap_->pFeedbackFifo != NULL) + return STATUS_UNSUCCESSFUL; + +#ifndef SIMUDRIVER + if (!GetController()) + m_pAdapter->GetBus(pFnap_->nBusNo)->GetController(0)->Add(this); + if (GetController()->GetOrder() != 0 || GetController()->GetOwnerBus()->GetBusNo() != pFnap_->nBusNo) + return STATUS_UNSUCCESSFUL; +#endif + + m_nReserved[0] = pFnap_->nReserved[0]; + m_nReserved[1] = pFnap_->nReserved[1]; + pFnap_->nNumofAxes = 5; + pFnap_->pFeedbackFifo = GetSwitchArea()->ConvertToR3Address(m_pFeedbackFifo); + return STATUS_SUCCESS; +} + +bool CFeedbackStream::Dispatch(PACKAGE* pPackage_) +{ + CLambdaController* _pCtrl = GetController(); + if (!_pCtrl || !_pCtrl->IsInitialized() || _pCtrl->GetControllerBaseInfo()->nNumofAxis != 5) + return false; + + if (!pPackage_ || pPackage_->nCmd != UCMD_FEEDBACK) + return false; + + #pragma pack(push, 1) + struct Feedback + { + BYTE nCmd; + BYTE nLenght; + UINT32 nTimestamp; + UINT32 nNccmdSN; + UINT32 nFeedback[1]; + //BYTE nCRC; + }; + #pragma pack(pop) + int _nSize = sizeof(Feedback) + sizeof(UINT32) * (5 - 1) + 1; + if(pPackage_->nLength != _nSize) + { + GetController()->SetErrorCode('CE'); + return false; + } + + // 随反馈脉冲流提上去OUTMAP中一个指定的Byte ---- 杨开锦 2015-05-13 + // 使用 FNAP_FEEDBACK_STREAM 中的 nReserved 保留字节(2bytes) + // nReserved[0] = 0x80 => 锁存Outmap一个Byte + // nReserved[1] = Bus(1bit) | Ctrl(3bits) | Byte(4bits) + // 锁到的Byte值通过 FeedbackNode 中的 nReserved 传上去 + // FeedbackNode::nReserved 为 DWORD + // 置其第0个Byte为0x80,表示这是此处锁存的信息 + // 置其第3个Byte为锁到的值 + // 其中第1、2个Byte留空为0不予使用 + DWORD _nReserved = 0; + if ((m_nReserved[0] & 0xF0) == 0x80) + { + #ifndef SIMUDRIVER + int _nBusNo = (m_nReserved[1] >> 7) & 0x01; + int _nCtrlOrder = (m_nReserved[1] >> 4) & 0x07; + int _nByteIndex = (m_nReserved[1] >> 0) & 0x0F; + CLambdaBus* _pBus = m_pAdapter ? m_pAdapter->GetBus(_nBusNo) : NULL; + CLambdaController* _pCtrl = _pBus ? _pBus->GetController(_nCtrlOrder) : NULL; + CLambdaOutput* _pOutput = _pCtrl ? _pCtrl->GetOutput() : NULL; + if (_pOutput) + { + BYTE* _pReserved = (BYTE*)&_nReserved; + _pReserved[0] = 0x80; + _pReserved[3] = _pOutput->Get(_nByteIndex); + } + #endif + } + + // 添加EX30A电容值的提取,用保留位的第1个Byte的高4Bit表示,0x40表示锁输入端 + // 口中的4个Byte。 + // nReserved[0] = 0x40 => 锁存Inmap四个Byte + // nReserved[1] = Bus(1bit)|Ctrl(3bits)|Byte(4bits) ---- 杨开锦 2015-10-29 + if (m_nReserved[0] == 0x40) + { + #ifndef SIMUDRIVER + int _nBusNo = (m_nReserved[1] >> 7) & 0x01; + int _nCtrlOrder = (m_nReserved[1] >> 4) & 0x07; + int _nByteIndex = (m_nReserved[1] >> 0) & 0x0F; + CLambdaBus* _pBus = m_pAdapter ? m_pAdapter->GetBus(_nBusNo) : NULL; + CLambdaController* _pCtrl = _pBus ? _pBus->GetController(_nCtrlOrder) : NULL; + CLambdaInput* _pInput = _pCtrl ? _pCtrl->GetInput() : NULL; + if (_pInput) + { + BYTE* _pReserved = (BYTE*)&_nReserved; + _pReserved[0] = _pInput->Get(_nByteIndex + 0); + _pReserved[1] = _pInput->Get(_nByteIndex + 1); + _pReserved[2] = _pInput->Get(_nByteIndex + 2); + _pReserved[3] = _pInput->Get(_nByteIndex + 3); + } + #endif + } + + // 添加EX30A调试位的提取,用保留位的第1个Byte的低4Bit来表示,0x04相当于就固 + // 定了。0x04的Bit是 0100,表示Bus0、Ctrl1、Byte00起的两个Byte。 + // 让它可以一下锁两个Byte是为扩展方便,可能有的数据是2Byte的,就本次来说 + // 确实只用其Byte1而不用Byte0。 ---- 杨开锦 2015-10-29 + if ((m_nReserved[0] & 0x0F) == 0x04) + { + #ifndef SIMUDRIVER + CLambdaBus* _pBus = m_pAdapter ? m_pAdapter->GetBus(0) : NULL; + CLambdaController* _pCtrl = _pBus ? _pBus->GetController(1) : NULL; + CLambdaInput* _pInput = _pCtrl ? _pCtrl->GetInput() : NULL; + if (_pInput) + { + BYTE* _pReserved = (BYTE*)&_nReserved; + _pReserved[0] |= 0x04; + _pReserved[1] = _pInput->Get(0); + _pReserved[2] = _pInput->Get(1); + } + #endif + } + + if (!m_pFeedbackFifo->IsFull()) + { + FeedbackNode<5> _node; + memset(&_node, 0, sizeof(FeedbackNode<5>)); + Feedback* _pFeedback = (Feedback*)pPackage_; + _node.nReserved = _nReserved; + _node.nTimeStamp = _pFeedback->nTimestamp; + _node.nNccmdSN = _pFeedback->nNccmdSN; + memcpy(_node.nFeedback, _pFeedback->nFeedback, sizeof(UINT32) * 5); + m_pFeedbackFifo->Write(&_node); + } + + return true; +} + +#include "NcBoardPcimc85A_PnnPacketFifo.inl" + +//////////////////////////////////////////////////////////////////////////////// +// CNcBoardPcimc85A +// +CNcBoardPcimc85A::CNcBoardPcimc85A(PDEVICE_OBJECT pFdo_, PDEVICE_OBJECT pPdo_, const char* pszName_) + : CDevice(pFdo_, pPdo_, pszName_) +{ + TRACE0("CNcBoardPcimc85A::CNcBoardPcimc85A begin ...\n"); + TRACE_INDENT; + + m_pAdapter = CLambdaAdapterFactory::Create(); + + m_bNccmdToSendValid = false; + memset(m_nNccmdToSend, 0, sizeof(m_nNccmdToSend)); + memset(m_bNccmdToSend, 0, sizeof(m_bNccmdToSend)); + m_bRS232ToSendValid = false; + memset(m_nRS232ToSend, 0, sizeof(m_nRS232ToSend)); + m_bEnableNcboardBuffer = true; + + for (int _i = 0; _i < _countof(m_nSynPortReserved); _i++) + { + m_nSynPortReserved[_i][0] = 0; + m_nSynPortReserved[_i][1] = 0; + } + + // 替换掉m_pSpindlePort ---- 杨开锦 2014-02-11 + if (m_pSpindlePort) + { + char _szName[c_nFNAP_OBJNAME_LENGTH] = {0}; + strcpy(_szName, m_pSpindlePort->GetName()); + delete m_pSpindlePort; + m_pSpindlePort = new CLambdaAnalogOutPort(_szName); + } + + m_pAppSysDown = NULL; + m_pAppSysUp = NULL; + + GetFnapManager()->Register(this, "FnapWritePackage",(PFNAP_FUNC)&CNcBoardPcimc85A::FnapWritePackage,true); + GetFnapManager()->Register(this, "FnapConfigAppSysFifo",(PFNAP_FUNC)&CNcBoardPcimc85A::FnapConfigAppSysFifo, false); +} + +CNcBoardPcimc85A::~CNcBoardPcimc85A() +{ + TRACE0("CNcBoardPcimc85A::~CNcBoardPcimc85A begin ...\n"); + TRACE_INDENT; + + if(m_pAppSysDown != NULL) + { + GetSwitchArea()->Free(m_pAppSysDown); + m_pAppSysDown = NULL; + } + + if(m_pAppSysUp != NULL) + { + GetSwitchArea()->Free(m_pAppSysUp); + m_pAppSysUp = NULL; + } +} + +NTSTATUS CNcBoardPcimc85A::SetIoBaseAddress(PVOID pIoBaseAddress_, int nLength_, int nIndex_/* = 0*/) +{ + TRACE0("CNcBoardPcimc85A::SetIoBaseAddress begin ...\n"); + TRACE_INDENT; + + // PM85A只会有一块地址,6A、75A也都是 + // NC65A和PM95A是两块地址 + // 我们只使用第一块 + if (nIndex_ > 0) + { + return STATUS_SUCCESS; + } + + m_pAdapter->SetPortBase((PUCHAR)pIoBaseAddress_); + return __super::SetIoBaseAddress(pIoBaseAddress_, nLength_, nIndex_); +} + +CFnap* CNcBoardPcimc85A::AllocResource(FNAP_RESOURCE_ALLOC* _pResourceAlloc) +{ + TRACE0("CNcBoardPcimc85A::AllocResource begin ...\n"); + TRACE_INDENT; + if(_pResourceAlloc->m_nResource == dir_resource_type_t::RES_ANALOG_OUT_PORT) + { + return new CLambdaAnalogOutPort(_pResourceAlloc->szComponentName); + } + if(_pResourceAlloc->m_nResource == dir_resource_type_t::RES_ANALOG_PORT) + { + return new CLambdaAnalogPort(_pResourceAlloc->szComponentName); + } + if(_pResourceAlloc->m_nResource == dir_resource_type_t::RES_RS232) + { + return new CLambdaRS232Manager(_pResourceAlloc->szComponentName); + } + if(_pResourceAlloc->m_nResource == dir_resource_type_t::RES_FPGA_UPDATE) + { + return new CFpgaUpdate(_pResourceAlloc->szComponentName); + } + if(_pResourceAlloc->m_nResource == dir_resource_type_t::RES_SYN_PORT) + { + return new CSynPort(_pResourceAlloc->szComponentName, m_pAdapter); + } + if(_pResourceAlloc->m_nResource == dir_resource_type_t::RES_FEEDBACK_STREAM) + { + return new CFeedbackStream(_pResourceAlloc->szComponentName, m_pAdapter); + } + if(_pResourceAlloc->m_nResource == dir_resource_type_t::RES_PNN_PACKET_FIFO) + { + return new CPnnPacketFifo(_pResourceAlloc->szComponentName, m_pAdapter); + } + return __super::AllocResource(_pResourceAlloc); +} + +void CNcBoardPcimc85A::FreeResource(CFnap* pFnap, dir_resource_type_t _dirResourceType) +{ + TRACE0("CNcBoardPcimc85A::FreeResource begin ...\n"); + TRACE_INDENT; + if(_dirResourceType == dir_resource_type_t::RES_ANALOG_OUT_PORT) + { + delete (CLambdaAnalogOutPort*)pFnap; + return; + } + if(_dirResourceType == dir_resource_type_t::RES_ANALOG_PORT) + { + delete (CLambdaAnalogPort*)pFnap; + return; + } + if(_dirResourceType == dir_resource_type_t::RES_RS232) + { + delete (CLambdaRS232Manager*)pFnap; + return; + } + if(_dirResourceType == dir_resource_type_t::RES_FPGA_UPDATE) + { + delete (CFpgaUpdate*)pFnap; + return; + } + if(_dirResourceType == dir_resource_type_t::RES_SYN_PORT) + { + delete (CSynPort*)pFnap; + return; + } + if(_dirResourceType == dir_resource_type_t::RES_FEEDBACK_STREAM) + { + delete (CFeedbackStream*)pFnap; + return; + } + if(_dirResourceType == dir_resource_type_t::RES_PNN_PACKET_FIFO) + { + delete (CPnnPacketFifo*)pFnap; + return; + } + __super::FreeResource(pFnap, _dirResourceType); +} + +void CNcBoardPcimc85A::DeviceError(IN ULONG_PTR nParam1_, IN ULONG_PTR nParam2_, IN ULONG_PTR nParam3_, IN ULONG_PTR nParam4_) +{ + TRACE("CNcBoardPcimc85A::DeviceError => {0x%X, 0x%X, 0x%X, 0x%X}\n", nParam1_, nParam2_, nParam3_, nParam4_); + + // 把驱动置为紧停,提示类型为硬件错误,提示的额外信息为文件行号 ---- 杨开锦 2014-08-12 + CResourceSolt* _pRS = GetDevice()->GetResourceSolt(dir_resource_type_t::RES_CHANNEL); + if (_pRS) + { + for (int _i = 0; _i < _pRS->GetCount(); _i++) + { + TRACE("CNcBoardPcimc85A::DeviceError => _i = %d\n", _i); + CChannel* _pChannel = (CChannel*)_pRS->GetIndex(_i); + _pChannel->SetState(true, drv_state_t::ESTOP_STATE, ncprompt_t::NCPROMPT_ESTOP_DEVICEERROR, nParam2_); + } + } +} + +void CNcBoardPcimc85A::Initialize() // 初始化必备的资源描 +{ + TRACE0("CNcBoardPcimc85A::Initialize begin ...\n"); + TRACE_INDENT; + SetInputPort(new CLambdaInputPort("InputPort")); + SetOutputPort(new CLambdaOutputPort("OutputPort")); + m_pCounter = new CCounter85A("Counter0"); + + __super::Initialize(); + + if(m_pAppSysDown == NULL) + { + m_pAppSysDown = (CCmdInfoBuffer*)GetSwitchArea()->Allocate(sizeof(CCmdInfoBuffer)); + if (!m_pAppSysDown) + FatalError(FILE_ID, __LINE__); + + m_pAppSysDown->CCmdInfoBuffer::CCmdInfoBuffer(); + } + + if(m_pAppSysUp == NULL) + { + m_pAppSysUp = (CCmdInfoBuffer*)GetSwitchArea()->Allocate(sizeof(CCmdInfoBuffer)); + if (!m_pAppSysUp) + FatalError(FILE_ID, __LINE__); + + m_pAppSysUp->CCmdInfoBuffer::CCmdInfoBuffer(); + } + + m_pFuncServiceRoutine = (PKSERVICE_ROUTINE)CCh365::Ncadpt_InterruptHandler; + +#if !defined (SIMUDRIVER) + m_Guid = NCADPT_GUID_85A; +#endif + + SetNccmdDispatcher(new CNccmdDispatcher85A("NccmdDispatcher")); +} + +NTSTATUS CNcBoardPcimc85A::OnStartDevice() +{ + TRACE0("CNcBoardPcimc85A::OnStartDevice begin ...\n"); + TRACE_INDENT; + + // Mase时钟 ---- 杨开锦 2014-03-29 + GetPortManager()->OutBit(Make64Addr(2, 0x02), false); + + NTSTATUS _status = __super::OnStartDevice(); + if(!NT_SUCCESS(_status)) + return _status; + + if (m_pAdapter->GetCHType() == CH_CH36x) + m_pAdapter->SetCHType(CH_CH365); + m_pAdapter->SetOwnerDevice(this); + m_pAdapter->SetTimeOut(60); + m_pAdapter->Initialize(false); + return _status; +} + +NTSTATUS CNcBoardPcimc85A::OnCreateDevice() +{ + TRACE0("CNcBoardPcimc85A::OnCreateDevice begin ...\n"); + TRACE_INDENT; + + NTSTATUS _nStatus = __super::OnCreateDevice(); + if (_nStatus == STATUS_UNSUCCESSFUL) + { + TRACE("CNcBoardPcimc85A::OnCreateDevice => STATUS_UNSUCCESSFUL\n"); + return _nStatus; + } + + if(!m_pAdapter->Initialize(true)) + return STATUS_UNSUCCESSFUL; + + return _nStatus; +} + +NTSTATUS CNcBoardPcimc85A::ConnectInterrupt() +{ + TRACE0("CNcBoardPcimc85A::ConnectInterrupt begin ...\n"); + TRACE_INDENT; + + return __super::ConnectInterrupt(); +} + +NTSTATUS CNcBoardPcimc85A::OnCloseDevice() +{ + TRACE0("CNcBoardPcimc85A::OnCloseDevice begin ...\n"); + TRACE_INDENT; + + m_pAdapter->UnInitialize(); + return __super::OnCloseDevice(); +} + +void CNcBoardPcimc85A::DisableBoard() +{ + TRACE0("CNcBoardPcimc85A::DisableBoard begin ...\n"); + TRACE_INDENT; + ASSERT_IRQL(DISPATCH_LEVEL); + WriteSynchPortBit(Make64Addr(1, 0x00), 0x1); +} + +void CNcBoardPcimc85A::EnableBoard() +{ + TRACE0("CNcBoardPcimc85A::EnableBoard begin ...\n"); + TRACE_INDENT; + ASSERT_IRQL(DISPATCH_LEVEL); + WriteSynchPortBit(Make64Addr(1, 0x00), 0x0); +} + +bool CNcBoardPcimc85A::GetBoardState() +{ + TRACE0("CNcBoardPcimc85A::GetBoardState begin ...\n"); + TRACE_INDENT; + ASSERT_IRQL(DISPATCH_LEVEL); + return !ReadSynchPortBit(Make64Addr(1, 0x00)); +} + +UINT CNcBoardPcimc85A::GetMaseFreqence() +{ + return 4166666; +} + +UINT64 CNcBoardPcimc85A::GetMaseDataClkAddr() +{ + return Make64Addr(2, 0x02); +} + +UINT64 CNcBoardPcimc85A::GetMaseDataInAddr() +{ + return Make64Addr(1, 0x02); +} + +UINT64 CNcBoardPcimc85A::GetMaseResetAddr() +{ + return Make64Addr(0, 0x02); +} + +UINT64 CNcBoardPcimc85A::GetMaseDataOutAddr() +{ + return Make64Addr(0, 0x11); +} + +UINT64 CNcBoardPcimc85A::GetEepromDataOutAddr() +{ + return Make64Addr(0, 0x10); +} + +UINT64 CNcBoardPcimc85A::GetEepromDataInAddr() +{ + return Make64Addr(0, 0x01); +} + +UINT64 CNcBoardPcimc85A::GetEepromChipSelectedAddr() +{ + return Make64Addr(2, 0x01); +} + +UINT64 CNcBoardPcimc85A::GetEepromClockAddr() +{ + return Make64Addr(1, 0x01); +} + +UINT32 CNcBoardPcimc85A::GetRtcStart() +{ + return Make32Addr(B85A_RTC_CTRL); +} + +UINT32 CNcBoardPcimc85A::GetSpindleDataAddr() +{ + // 在Lambda协议下,输出是一整个映像,一般会把模拟量排在最前面。 + // 但这里是使用2字节的,低字节在前,高10位有效(芯片宽度是10位)。 + // 可以继续沿用8位,只用高8位,这样只相当于降低了一点精度。 + // 以Lambda5S为例: ..2#112#.... 后一个2#为SVC。 + // ---- 杨开锦 2014-08-21 + return Make32Addr(0x07); +} + +UINT32 CNcBoardPcimc85A::GetHandwheelEncoderDataAddr() +{ + // 暂不考虑手轮,用250标示这个无效的地址 ---- 杨开锦 2014-05-22 + return Make32Addr(250); +} + +int CNcBoardPcimc85A::GetHandwheelEncoder() +{ + return 0; +} + +int CNcBoardPcimc85A::GetEncoderFeedbackByAxis(int nIndex_) +{ + CHECK_PARAM(nIndex_ >= 0 && nIndex_ < c_nMAX_NUM_OF_AXES_85A); +#if defined (SIMUDRIVER) + return 0; +#else + // 所有轴的编号是这样编的: + // 把Bus0上各Controller上的轴依次排上,再排Bus1上的 + // 排完后得到的轴数组,具体某轴在数组中的下标就是其轴号 + const ADAPTER_BASE_INFO_V2* _pAdpInfo = m_pAdapter->GetAdapterBaseInfo(); + int _nBusCount = 1 + _pAdpInfo->nNumofAuxiliary; + for (int _nBusNo = 0; _nBusNo < _nBusCount; _nBusNo++) + { + CLambdaBus* _pBus = m_pAdapter->GetBus(_nBusNo); + if (!_pBus || !_pBus->IsInitialized() ||!_pBus->GetEnable()) + break; + + for (int _nCtrlOder = 0; _nCtrlOder < 8; _nCtrlOder++) + { + CLambdaController* _pCtrl = _pBus->GetController(_nCtrlOder); + if (!_pCtrl || !_pCtrl->IsInitialized() || !_pCtrl->GetEnable()) + break; + + const CONTROLLER_BASE_INFO_V2* _pInfo = _pCtrl->GetControllerBaseInfo(); + if (nIndex_ >= _pInfo->nNumofAxis) + { + nIndex_ -= _pInfo->nNumofAxis; + continue; + } + + return _pCtrl->GetFeedback()->Get(nIndex_); + } + } + + ASSERT(FALSE); + return 0; +#endif +} + +int CNcBoardPcimc85A::GetSendPulseByAxis(int nIndex) +{ + return 0; +} + +const char* CNcBoardPcimc85A::GetBoardType() +{ + return "WH-PCIMC85A"; +} + +DWORD CNcBoardPcimc85A::GetBoardTypeId() +{ + return '85A'; +} + +int CNcBoardPcimc85A::GetCycleTimeUs() +{ + return 1000; +} + +int CNcBoardPcimc85A::GetMaxPPC() +{ + return 1000; +} + +int CNcBoardPcimc85A::GetMaxNumOfAxes() +{ + return c_nMAX_NUM_OF_AXES_85A; +} + +int CNcBoardPcimc85A::GetMaxNumOfChannel() +{ + return c_nMAX_NUM_OF_CHANNEL_85A; +} + +BOOLEAN CNcBoardPcimc85A::OnInterrupt() +{ +#if defined (SIMUDRIVER) + m_bNccmdToSendValid = false; + __super::OnInterrupt(); + return true; +#else + m_pAdapter->Update(1000); + return true; +#endif +} + +#pragma pack(push, 8) +struct FNAP_LAMBDA_PACKAGE : FNAP_HEADER +{ + BYTE nBusIndex; + BYTE nControllerIndex; + BYTE nNA0[2]; + BYTE nHeader; + BYTE nNA2; + BYTE nDataLength; + BYTE pData[1]; +}; +#pragma pack(pop) +NTSTATUS CNcBoardPcimc85A::FnapWritePackage(FNAP_LAMBDA_PACKAGE* pFnap_) +{ + CHECK_PARAM(pFnap_->nInSize == sizeof(FNAP_LAMBDA_PACKAGE) + pFnap_->nDataLength - 1); + CHECK_PARAM(pFnap_->nOutSize == 0); + TRACE0("CNcBoardPcimc85A::FnapWritePackage: begin ...\n"); + TRACE_INDENT; + if (pFnap_->nBusIndex >= 4) // 最多4路总线通道 + return STATUS_UNSUCCESSFUL; + if (pFnap_->nControllerIndex >= 8) // 每路总线最多级联8级 + return STATUS_UNSUCCESSFUL; + if (pFnap_->nBusIndex != 0) // 暂不支持 + return STATUS_UNSUCCESSFUL; + + PACKAGE _packAge; + memset(&_packAge, 0, sizeof(PACKAGE)); + _packAge.nCmd = pFnap_->nHeader; + _packAge.nLength = pFnap_->nDataLength + 3; + memcpy(_packAge.data, pFnap_->pData, (int)pFnap_->nDataLength); + + if(!m_pAdapter->GetBus(pFnap_->nBusIndex)->GetController(pFnap_->nControllerIndex)->WritePacket(&_packAge, NULL)) + return STATUS_UNSUCCESSFUL; + + TRACE_HEX(_packAge.buffer, _packAge.nLength); + return STATUS_SUCCESS; +} + +#pragma pack(push,8) +struct FNAP_CONFIG_APPSYSFIFO : FNAP_HEADER +{ + CCmdInfoBuffer* __ptr32 pDownFifo; // R0R3下行缓冲区 + CCmdInfoBuffer* __ptr32 pUpFifo; // R0R3上行缓冲区 +}; +#pragma pack(pop) + +NTSTATUS CNcBoardPcimc85A::FnapConfigAppSysFifo( FNAP_CONFIG_APPSYSFIFO* pFnap_ ) +{ + CHECK_PARAM(pFnap_->nInSize == sizeof(FNAP_CONFIG_APPSYSFIFO)); + CHECK_PARAM(pFnap_->nOutSize == sizeof(FNAP_CONFIG_APPSYSFIFO)); + TRACE0("CNcBoardPcimc85A::FnapConfigAppSysFifo: begin ...\n"); + TRACE_INDENT; + + pFnap_->pDownFifo = (CCmdInfoBuffer*)GetSwitchArea()->ConvertToR3Address(m_pAppSysDown); + pFnap_->pUpFifo = (CCmdInfoBuffer*)GetSwitchArea()->ConvertToR3Address(m_pAppSysUp); + +#ifndef SIMUDRIVER + if (m_pAppSysDown != NULL) + { + m_pAppSysDown->Reset(); + } + + if (m_pAppSysUp != NULL) + { + m_pAppSysUp->Reset(); + } + + ASSERT(m_pAdapter); + ASSERT(m_pAdapter->GetBus(0)); + ASSERT(m_pAdapter->GetBus(0)->GetController(0)); + ASSERT(m_pAdapter->GetBus(0)->GetController(0)->GetSendPulse()); + + CLambdaBus* _pBus = m_pAdapter->GetBus(0); + CLambdaController* _pCtl = _pBus->GetController(0); + CLambdaAppSysFifo* _pAppSys = _pCtl->GetAppSysFifo(); + + _pAppSys->Set(m_pAppSysDown, m_pAppSysUp); +#endif + + return STATUS_SUCCESS; +} + +BYTE CNcBoardPcimc85A::GetInPortMap(UINT32 nAddr_) +{ + WORD _offset = LOWORD(nAddr_); + + BYTE _nBus = HIBYTE(_offset) >> 4; + BYTE _nCtrl = HIBYTE(_offset) & 0x0F; + BYTE _nByte = LOBYTE(_offset); + ASSERT(_nBus < 4 && _nBus >= 0); + ASSERT(_nCtrl < 8 && _nCtrl >= 0); + ASSERT(_nByte < 256 && _nByte >= 0); + +#if defined (SIMUDRIVER) + return 0x00; +#else + ASSERT(m_pAdapter); + ASSERT(m_pAdapter->GetBus(_nBus)); + ASSERT(m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)); + ASSERT(m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->GetInput()); + return m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->GetInput()->Get(_nByte); +#endif +} + +BYTE CNcBoardPcimc85A::GetOutPortMap(UINT32 nAddr_) +{ + WORD _offset = LOWORD(nAddr_); + + BYTE _nBus = HIBYTE(_offset) >> 4; + BYTE _nCtrl = HIBYTE(_offset) & 0x0F; + BYTE _nByte = LOBYTE(_offset); + ASSERT(_nBus < 4 && _nBus >= 0); + ASSERT(_nCtrl < 8 && _nCtrl >= 0); + ASSERT(_nByte < 256 && _nByte >= 0); + +#if defined (SIMUDRIVER) + return 0x00; +#else + ASSERT(m_pAdapter); + ASSERT(m_pAdapter->GetBus(_nBus)); + ASSERT(m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)); + ASSERT(m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->GetOutput()); + return m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->GetOutput()->Get(_nByte); +#endif +} + +void CNcBoardPcimc85A::SetOutPortMap(UINT32 nAddr_, BYTE nValue_) +{ + WORD _offset = LOWORD(nAddr_); + + BYTE _nBus = HIBYTE(_offset) >> 4; + BYTE _nCtrl = HIBYTE(_offset) & 0x0F; + BYTE _nByte = LOBYTE(_offset); + ASSERT(_nBus < 4 && _nBus >= 0); + ASSERT(_nCtrl < 8 && _nCtrl >= 0); + ASSERT(_nByte < 256 && _nByte >= 0); + +#if defined (SIMUDRIVER) + return; +#else + ASSERT(m_pAdapter); + ASSERT(m_pAdapter->GetBus(_nBus)); + ASSERT(m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)); + ASSERT(m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->GetOutput()); + m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->GetOutput()->Set(_nByte, nValue_); +#endif +} + +BYTE CNcBoardPcimc85A::GetSynPortMap(UINT32 nAddr_) +{ + WORD _offset = LOWORD(nAddr_); + + BYTE _nBus = HIBYTE(_offset) >> 4; + BYTE _nCtrl = HIBYTE(_offset) & 0x0F; + BYTE _nByte = LOBYTE(_offset); + ASSERT(_nBus < 4 && _nBus >= 0); + ASSERT(_nCtrl < 8 && _nCtrl >= 0); + ASSERT(_nByte < 256 && _nByte >= 0); + +#if defined (SIMUDRIVER) + return 0x00; +#else + ASSERT(m_pAdapter); + ASSERT(m_pAdapter->GetBus(_nBus)); + ASSERT(m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)); + ASSERT(m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->GetSendPulse()); + return m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->GetSendPulse()->GetSynOut(_nByte); +#endif +} + +void CNcBoardPcimc85A::SetSynPortMap(UINT32 nAddr_, BYTE nValue_) +{ + WORD _offset = LOWORD(nAddr_); + + BYTE _nBus = HIBYTE(_offset) >> 4; + BYTE _nCtrl = HIBYTE(_offset) & 0x0F; + BYTE _nByte = LOBYTE(_offset); + ASSERT(_nBus < 4 && _nBus >= 0); + ASSERT(_nCtrl < 8 && _nCtrl >= 0); + ASSERT(_nByte < 256 && _nByte >= 0); + +#if defined (SIMUDRIVER) + return; +#else + ASSERT(m_pAdapter); + ASSERT(m_pAdapter->GetBus(_nBus)); + ASSERT(m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)); + ASSERT(m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->GetSendPulse()); + m_pAdapter->GetBus(_nBus)->GetController(_nCtrl)->GetSendPulse()->SetSynOut(_nByte, nValue_); +#endif +} + +bool CNcBoardPcimc85A::Update() +{ + m_bNccmdToSendValid = false; + + #if !defined (SIMUDRIVER) + // for EX33A, 实现INMAP&OUTMAP的端口重定位 ---- 杨开锦 2016-12-23 + // 判别条件:如果用了EX33A上的Z轴,则表明在使用二代随动 + // 在驱动里实现把一代随动和二代随动的INMAP、OUTMAP空间的同步映射 + // 以便应用层可以不用去重配端口,使用相同地址的端口就可以包管一代和二代随动 + // 具体为: + // LD5S INMAP '..2#114###........' OUTMAP '..2#112#....' + // LD5S-04 INMAP '..2#114###........2#' OUTMAP '..2#112#....2#2#.' + // EX30A INMAP '..4###2#.2#2#2#' OUTMAP '..2#2#2#11..' + // EX33A INMAP '..4###2#.2#2#2#2#' OUTMAP '..2#2#2#11...2#2#..' + CLambdaController* _pCtrl00 = m_pAdapter->GetBus(0)->GetController(0); + CLambdaController* _pCtrl01 = m_pAdapter->GetBus(0)->GetController(1); + bool _bEX33A = false; + if (_pCtrl01) + { + const CONTROLLER_BASE_INFO_V2* _pInfo = _pCtrl01->GetControllerBaseInfo(); + const char* _pName = _pInfo->szName; + if (_pName[0] == 'E' && _pName[1] == 'X' && _pName[2] == '3' && _pName[3] == '3' && _pName[4] == '\0') + { + _bEX33A = true; + } + } + + // 映射OUTMAP + if (_bEX33A) + { + // 随动相关 + BYTE _nLDOUTByte12 = _pCtrl00->GetOutput()->Get(12); + BYTE _nLDOUTByte13 = _pCtrl00->GetOutput()->Get(13); + BYTE _nLDOUTByte14 = _pCtrl00->GetOutput()->Get(14); + BYTE _nLDOUTByte15 = _pCtrl00->GetOutput()->Get(15); + BYTE _nLDOUTByte16 = _pCtrl00->GetOutput()->Get(16); + _pCtrl01->GetOutput()->Set(13, _nLDOUTByte12); + _pCtrl01->GetOutput()->Set(14, _nLDOUTByte13); + _pCtrl01->GetOutput()->Set(15, _nLDOUTByte14); + _pCtrl01->GetOutput()->Set(16, _nLDOUTByte15); + // _pCtrl01->GetOutput()->Set(17, _nLDOUTByte16); + + // 轴相关: 伺服使能 & 伺服清除 + // LD5S.Byte9.Bit3 => EX33A.Byte18.Bit0 + // LD5S.Byte10.Bit3 => EX33A.Byte18.Bit4 + /*BYTE _nLDOUTByte9 = _pCtrl00->GetOutput()->Get(9); + BYTE _nLDOUTByte10 = _pCtrl00->GetOutput()->Get(10); + BYTE _nEX33OUTByte18 = _pCtrl01->GetOutput()->Get(18); + _nEX33OUTByte18 = ((_nLDOUTByte9 & 0x08) >> 3) + ((_nLDOUTByte10 & 0x08) >> 3); + _pCtrl01->GetOutput()->Set(18, _nEX33OUTByte18);*/ + } + + // 映射INMAP + if (_bEX33A) + { + // 随动相关 + BYTE _nEX33INByte15 = _pCtrl01->GetInput()->Get(15); + BYTE _nEX33INByte16 = _pCtrl01->GetInput()->Get(16); + _pCtrl00->GetInput()->Set(18, _nEX33INByte15); + _pCtrl00->GetInput()->Set(19, _nEX33INByte16); + + // 轴相关: 伺服使能 & 伺服清除 + // EX33A.Byte17.Bit0 => LD5S.Byte12.Bit3 + // EX33A.Byte17.Bit4 => LD5S.Byte13.Bit3 + /*BYTE _nEX33INByte17 = _pCtrl01->GetInput()->Get(17); + BYTE _nLDINByte12 = _pCtrl00->GetInput()->Get(12); + BYTE _nLDINByte13 = _pCtrl00->GetInput()->Get(13); + _nLDINByte12 = (_nLDINByte12 & 0xF7) | ((_nEX33INByte17 & 0x01) << 3); + _pCtrl00->GetInput()->Set(12, _nLDINByte12); + _nLDINByte13 = (_nLDINByte13 & 0xF7) | ((_nEX33INByte17 & 0x10) >> 1); + _pCtrl00->GetInput()->Set(13, _nLDINByte13);*/ + } + #endif + + CDevice::OnInterrupt(); + + Synchronize(); + return m_bNccmdToSendValid; +} + +bool CNcBoardPcimc85A::GetEnableBuffer() +{ + return m_bEnableNcboardBuffer; +} + +bool CNcBoardPcimc85A::GetOutPortMapIsValid() +{ + return !GetOutputPort()->GetForceUpdated(); +} + +// 约定:一定是先发Ctrl0的脉冲,再发Ctrl1的脉冲,再Ctrl2,依此类推 +// 总的有无数据的标志是 m_bNccmdToSendValid +// 各轴分别的数据标志是 m_bNccmdToSend[N] +// CNccmdDispatcher85A填数据的时候是一起填进去的,所以总的标志跟分标志是同步的 +// 此处发送时,是逐个Controller发的,当所有填了数据的轴脉冲都发完了总标志就复位 +// ---- 杨开锦 2012-12-23 +bool CNcBoardPcimc85A::GetNccmd(int nIndex_, int* _pnPulse, int _nLength, BYTE* _pSynOutMap, int _nSynOutMapLength) +{ + if(!m_bNccmdToSendValid) + return false; + + int _nBegin = 0; // Begin Axis Index + int _nBusNo = (nIndex_ & 0xF0) >> 4; + int _nCtrlOder = (nIndex_ & 0x0F); + CLambdaBus* _pBus = m_pAdapter->GetBus(_nBusNo); + for (int _i = 0; _i < _nCtrlOder; _i++) + { + CLambdaController* _pCtrlI = _pBus->GetController(_i); + const CONTROLLER_BASE_INFO_V2* _pInfo = _pCtrlI->GetControllerBaseInfo(); + _nBegin += _pInfo->nNumofAxis; + } + + bool _bRet = false; + C_ASSERT(_countof(m_nNccmdToSend) == _countof(m_bNccmdToSend)); + CHECK_PARAM(_nBegin + _nLength <= _countof(m_nNccmdToSend)); + for (int _i = 0; _i < _nLength; _i++) + { + // 向CLambdaDeviceProvider提供数据时,其单位是1/128 ---- 杨开锦 2014-09-13 + // Phoenix协议上,共有三种脉冲包: + // 1.零脉冲包,各轴脉冲均为0,不需要携带脉冲数据; + // 2.整数脉冲包,各轴脉冲均为整数,每轴的脉冲占2字节; + // 3.小数脉冲包,名轴脉冲不均为整数,每轴脉冲占4字节,低7位为小数。 + // 因此,向CLambdaDeviceProvider提供时统一以1/128单位提交; + // 发送脉冲处,可以根据收到的数据决定以哪种包形式进行下发。 + _pnPulse[_i] = m_nNccmdToSend[_nBegin + _i] * 128; + if (m_bNccmdToSend[_nBegin + _i]) + _bRet = true; + + m_bNccmdToSend[_nBegin + _i] = false; + } + + bool _bHasMore = false; // 所有轴都发完了就清总标志 + for (int _i = _nBegin + _nLength; _i < _countof(m_nNccmdToSend); _i++) + { + if (m_bNccmdToSend[_i]) + { + _bHasMore = true; + break; + } + } + if (!_bHasMore) + { + m_bNccmdToSendValid = false; + } + + return _bRet; +} + +NTSTATUS CNcBoardPcimc85A::FnapGetVersion(FNAP_GET_VERSION* pFnap_) +{ + NTSTATUS _nRet = __super::FnapGetVersion(pFnap_); + m_pAdapter->GetTestString(pFnap_->BoardInfo.szSelfTest, sizeof(pFnap_->BoardInfo.szSelfTest)); + return _nRet; +} + +BYTE CNcBoardPcimc85A::GetSynPortReserved(UINT32 nAddr_) +{ + for (int _i = 0; _i < _countof(m_nSynPortReserved); _i++) + { + if (m_nSynPortReserved[_i][0] == nAddr_) + return (BYTE)m_nSynPortReserved[_i][1]; + } + + return 0; +} + +void CNcBoardPcimc85A::SetSynPortReserved(UINT32 nAddr_, BYTE nReserved_) +{ + for (int _i = 0; _i < _countof(m_nSynPortReserved); _i++) + { + if (m_nSynPortReserved[_i][0] == 0) + m_nSynPortReserved[_i][0] = nAddr_; + if (m_nSynPortReserved[_i][0] == nAddr_) + m_nSynPortReserved[_i][1] = (UINT32)nReserved_; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// CNcBoardPciemc85A +// +CNcBoardPciemc85A::CNcBoardPciemc85A(PDEVICE_OBJECT pFdo_, PDEVICE_OBJECT pPdo_, const char* pszName_) + : CNcBoardPcimc85A(pFdo_, pPdo_, pszName_) +{ + TRACE0("CNcBoardPciemc85A::CNcBoardPciemc85A begin ...\n"); + TRACE_INDENT; +} + +CNcBoardPciemc85A::~CNcBoardPciemc85A() +{ + TRACE0("CNcBoardPciemc85A::~CNcBoardPciemc85A begin ...\n"); + TRACE_INDENT; +} + +void CNcBoardPciemc85A::Initialize() +{ + TRACE0("CNcBoardPciemc85A::Initialize begin ...\n"); + TRACE_INDENT; + __super::Initialize(); + m_pFuncServiceRoutine = (PKSERVICE_ROUTINE)CCh367::Ncadpt_InterruptHandler; +} + +NTSTATUS CNcBoardPciemc85A::OnStartDevice() +{ + TRACE0("CNcBoardPciemc85A::OnStartDevice begin ...\n"); + TRACE_INDENT; + CCh367::InitializeBaseAddress(this->GetIoBaseAddress()); + m_pAdapter->SetCHType(CH_CH367); + return __super::OnStartDevice(); +} + +NTSTATUS CNcBoardPciemc85A::OnCloseDevice() +{ + TRACE0("CNcBoardPciemc85A::OnCloseDevice begin ...\n"); + TRACE_INDENT; + CCh367::InitializeBaseAddress(NULL); + return __super::OnCloseDevice(); +} + +NTSTATUS CNcBoardPciemc85A::ConnectInterrupt() +{ + CCh367::PrepareConnectInterrupt(); + return __super::ConnectInterrupt(); +} + +NTSTATUS CNcBoardPciemc85A::DisconnectInterrupt() +{ + CCh367::PrepareDisconnectInterrupt(); + return __super::DisconnectInterrupt(); +} + +const char* CNcBoardPciemc85A::GetBoardType() +{ + return "WH-NC65A"; +} + +DWORD CNcBoardPciemc85A::GetBoardTypeId() +{ + return '65A'; +} + +UINT CNcBoardPciemc85A::GetMaseFreqence() +{ + return 1488095; +} diff --git a/src/Nce3DViewImp_V1.cpp b/src/Nce3DViewImp_V1.cpp new file mode 100644 index 0000000..d6bab28 --- /dev/null +++ b/src/Nce3DViewImp_V1.cpp @@ -0,0 +1,2656 @@ +// ************************************************************************** // +// Nce3DViewImp.cpp : implementation of the CNce3DViewImp_V1 class +// Copyright(c)2013 Weihong Company. All rights reserved. +// +// Abstract: +// 本文件实现Nce3DViewImp实用函数。 +// *********************************************** ---- 彭朋 2016-10-10****** // +#include "StdAfx.h" +#include "Nce3DViewImp_V1.h" + + +#define MaxBitmapWidth 2048 // 1024 的3倍 +#define MinBitmapWidth 256 +using namespace Nce3DView; + +// 利用 GPC 库 用来辅助转化3D cut off +class GPCConvertHelper +{ +public: + typedef std::vector std_vertex_list; + typedef std::vector gpc_polygon_list; + typedef std::vector std_polygon_list; + enum ExpandType_t{Expand_One, Expand_4V4 , Expand_All}; + enum ConvertType_t{Convert_All, Convert_Part1_4}; + +public: + GPCConvertHelper() : m_pRootAreaData(NULL){}; + ~GPCConvertHelper(){}; + +public: + void Initialize(Transform3DList& listData_, double nWidth_); + void ConvertCutOffArea(IN const Polyline2DList& listRecords_, OUT Polygon3DListGroup& listCutOffDatas_, ExpandType_t nExpandType_); + +protected: + void _convertArea(IN const TransformData3D& area_, OUT std_vertex_list& listvertexs_); + void _convertPolygon(IN const Polyline2DList& listPolylines_, OUT std_polygon_list& listPolygons_); + void _gpc_convert_tristrip(IN std_vertex_list& polygon_, double nMin_, double nMax_, + OUT Polygon3DListGroup& listCutOffDatas_, ConvertType_t nConvertType_); + void _get_MinMax_width(IN std_vertex_list& polygon_, double& nMin_, double& nMax_); + void _set_offset_polygon(IN OUT std_vertex_list& polygonSrc_, double nOffset_); + inline int _IsInArea(int id_, double& nMin_, double& nMax_); + +protected: + Transform3DList* m_pRootAreaData; + std_polygon_list m_vectorBaseArea; + double m_nWidth; +}; +static GPCConvertHelper g_gpcConvertHelper; +Vector4 GLPick(Vector4& vt_); +Vector4 UnGLPick(Vector4& vt_); +Vector4 GetNormalVector(const Vector4 &vec1_, const Vector4 &vec2_, const Vector4 &vec3_); +double GetEllipsePerimeter(double nLongRadius_,double nShortRadius_); +void SolveArc(IN Vector4 ptStart_, + IN Vector4 ptEnd_, + IN double nBulge_, + OUT Vector4* pptCenter_, + OUT double* pnRadius_, + OUT double* pnStartAngle_, + OUT double* pnSweptAngle_); + +CNce3DViewImp_V1::CNce3DViewImp_V1() +{ + m_hWnd = NULL; + m_hDC = NULL; + m_hRC = NULL; + m_nZNearAndFar = 50; + m_clrBackground = RGB(0, 0, 0); + m_clrAlpha = RGB(255, 254, 255); + m_pBmpTexture = NULL; + m_nBmpWidth = 0; + m_nBmpHeight = 0; + m_nBmpZoomRatio = 1; + m_pRGBAData = NULL; + m_pBmpDC = NULL; + m_nTextureID = -1; + m_bMaterialLight = false; + m_bBlend = false; + m_nBaseZoom = 1.f; + m_nRotate = 0; + m_nOffsetY = 0.f; + m_nZoom = 1.f; + m_nBaseZoomRatio = 1.f; + m_nTubeType = QuadTube; + m_nPosition = LOOKAT_FRONT; + m_bShowCoordinate = false; + m_nOpenglWidth = 100.f; + m_nOpenglHeight = 100.f; + m_nAuxiliaryWidth = 0.f; + m_nTubeWidth = 10; + m_nTubeHeight = 100; + m_nMaxWidth = 100; + m_bDrawTube = true; + m_nCadMinHeight = 0; + m_nCadMaxHeight = 0; + m_nCadMinWidth = 0; + m_nCadMaxWidth = 0; +} + +CNce3DViewImp_V1::~CNce3DViewImp_V1() +{ + wglMakeCurrent(NULL, NULL); + if (m_hRC != NULL) + wglDeleteContext(m_hRC); + if (m_hDC != NULL) + ReleaseDC(m_hWnd, m_hDC); + if (m_pBmpTexture != NULL) + delete m_pBmpTexture; + if (m_pRGBAData != NULL) + delete[] m_pRGBAData; + if (m_pBmpDC != NULL) + delete m_pBmpDC; + if( m_nTextureID != -1) + glDeleteTextures(1, &m_nTextureID); +} + +void CNce3DViewImp_V1::DrawTube(bool bSwitch_) +{ + m_bDrawTube = bSwitch_; +} + +// 初始化openGL环境 ---- 彭朋 2016-08-10 +bool CNce3DViewImp_V1::Initialize(HWND hWnd_) +{ + ASSERT(hWnd_); + int _nPixelFormat = 0; + m_hDC = GetDC(hWnd_); + m_hWnd = hWnd_; + PIXELFORMATDESCRIPTOR _pfd = + { + sizeof(PIXELFORMATDESCRIPTOR), // 此结构的大小 + 2, // 此结构的版本 + PFD_DRAW_TO_WINDOW | // 在窗口上绘图(而不是在位图上) + PFD_SUPPORT_OPENGL | // 在窗口中支持使用OpenGL + PFD_DOUBLEBUFFER, // 使用双缓冲模式 + PFD_TYPE_RGBA, // 使用RGBA色彩模式 + 24, // 存储颜色数据的位数 + 0,0,0,0,0,0, + 0,0, + 0,0,0,0,0, + 32, // 深度缓冲区大小 + 0, + 0, + PFD_MAIN_PLANE, // 在主平面上绘图 + 0, + 0,0, + }; + + // 根据设备选择最佳的像素格式 + _nPixelFormat = ChoosePixelFormat(m_hDC, &_pfd); + if (_nPixelFormat == 0) + { + return false; + } + + // 根据ChoosePixelFormat的结果,设置设备的像素格式 + SetPixelFormat(m_hDC, _nPixelFormat, &_pfd); + + // 创建OpenGL窗口句柄 + m_hRC = ::wglCreateContext(m_hDC); + if (m_hRC == NULL) + { + TRACE(_T("OpenGl rendering context fail!")); + return false; + } + + if (!wglMakeCurrent(m_hDC, m_hRC)) + { + TRACE(_T("OpenGl rendering context fail!")); + return false ; + } + + glMatrixMode(GL_PROJECTION ); + glShadeModel(GL_SMOOTH); // 设置着色为平滑模式,采用颜色差值算法进行绘制 + //glEnable(GL_POINT_SMOOTH); + //glEnable(GL_LINE_SMOOTH); + //glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // Make round points, not square points + //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Antialias the lines + glEnable(GL_DEPTH_TEST); // 允许Z_Buffer深度测试 + glEnable(GL_COLOR_MATERIAL); // 材料的颜色材质 + glClearColor(0, 0, 0, 0); // 可用于设置背景颜色 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 要同时清除颜色和深度 + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glLoadIdentity(); // 初始化坐标 + EnableMaterialLight(true); + EnableBlend(true); + //GLint _nTextureMaxSize; + //glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_nTextureMaxSize); + return true; +} + +void CNce3DViewImp_V1::ShowCoordinate(bool bSwitch_) +{ + m_bShowCoordinate = bSwitch_; +} + +bool CNce3DViewImp_V1::IsShowCoordinate() +{ + return m_bShowCoordinate; +} + +bool CNce3DViewImp_V1::IsMaterialLight() +{ + return m_bMaterialLight; +} + +void CNce3DViewImp_V1::EnableBlend(bool bSwitch_) +{ + if (m_bBlend == bSwitch_) + return; + m_bBlend = bSwitch_; + if (m_bBlend) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else + { + glDisable(GL_BLEND); + } +} + +void CNce3DViewImp_V1::EnableMaterialLight(bool bSwitch_) +{ + if (m_bMaterialLight == bSwitch_) + return; + m_bMaterialLight = bSwitch_; + if (m_bMaterialLight) + { + glEnable(GL_NORMALIZE); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + const static GLfloat _nMatAmbient[] = {1.0f,1.0f,1.0f,1.0f}; // 环境光 + const static GLfloat _nMatDiffuse[] = {1.0f,1.0f,1.0f,1.0f}; // 漫反射 + const static GLfloat _nMatSpecular[] = {1.0f,1.0f,1.0f,1.0f}; // 镜面反射 + const static GLfloat _nMat_emission[] = {0.0,0.0,0.0,1.0f}; // 辐射光 + glMaterialfv(GL_FRONT, GL_AMBIENT, _nMatAmbient); + glMaterialfv(GL_FRONT, GL_DIFFUSE, _nMatDiffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, _nMatSpecular); + glMaterialfv(GL_FRONT, GL_EMISSION, _nMat_emission); + glMaterialf (GL_FRONT, GL_SHININESS, 128); + glPushMatrix(); + glLoadIdentity(); + const static GLfloat _nLightAmbient[] = {0.15f, 0.15f, 0.15f, 1.0f}; // 环境光 + const static GLfloat _nLightDiffuse[] = {0.75f, 0.75f, 0.75f, 1.0f}; // 漫射光 + const static GLfloat _nLightSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f}; // 镜面光 + const static GLfloat _nLightPosition[] = {0.0f, 50.0f, 50.0f, 0.0f}; // 光源位置 + const static GLfloat _nSpotLightDirectin[] = {0.0f, 0.0f, -1.0f, 1.0f}; // 聚光灯的方向 + glLightfv(GL_LIGHT0, GL_AMBIENT, _nLightAmbient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, _nLightDiffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, _nLightSpecular); + glLightfv(GL_LIGHT0, GL_POSITION, _nLightPosition); + glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, _nSpotLightDirectin); + glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0); + glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180); + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.0f); + glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHTING); + glPopMatrix(); + } + else + { + glDisable(GL_NORMALIZE); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_LIGHT0); + glDisable(GL_LIGHTING); + } +} + +// 以中心点缩放 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::ScaleCentre(int nX_, int nY_, double nValue_) +{ + Vector4 _vtStart(0., (m_nBmpHeight / m_nBmpZoomRatio) * 0.5, 0., 1.); + Vector4 _vtEnd(0., -(m_nBmpHeight / m_nBmpZoomRatio) * 0.5, 0., 1.); + Vector4 _winStart = UnGLPick(_vtStart); + Vector4 _winEnd = UnGLPick(_vtEnd); + if (nY_ < _winStart.y || nY_ > _winEnd.y) + { + Scale(nValue_); + return; + } + double _nk = (nY_ - _winStart.y) / (_winStart.y - _winEnd.y); + double _nGLY1 = _nk * (_vtStart.y - _vtEnd.y) + _vtStart.y; + Scale(nValue_); + _winStart = UnGLPick(_vtStart); + _winEnd = UnGLPick(_vtEnd); + _nk = (nY_ - _winStart.y) / (_winStart.y - _winEnd.y); + double _nGLY2 = _nk * (_vtStart.y - _vtEnd.y) + _vtStart.y; + double _nOffsetY = _nGLY2 - _nGLY1; + Translate(_nOffsetY); +} + +// 最佳缩放和FollowHeightShow一起用 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::OptimumScale() +{ + double _nRatio = double(2) / (m_nTubeWidth + 20); + Scale(_nRatio / m_nZoom); + //FollowHeightABS(m_nTubeHeight / 2); +} + +void CNce3DViewImp_V1::OptimumView() +{ + // 目前商定的是区域最左面为显示中心。 + double _nMinHeight = max(m_nCadMinHeight, 0); + double _nMaxHeight = min(m_nCadMaxHeight, m_nTubeHeight); + double _nMinWidth = max(m_nCadMinWidth, 0); + double _nMaxWidth = min(m_nCadMaxWidth, m_nMaxWidth); + double _nStepHeight = fabs(m_nCadMaxHeight - m_nCadMinHeight); + if (_nStepHeight > 0 || m_nCadMinHeight > 0) + { + LoadIdentity(); + double _nRot = (_nMinWidth) / m_nMaxWidth *360; + RotateABS(_nRot); + double _nRatio = double(2) / (_nStepHeight + 20) * m_nBaseZoomRatio; + double _nRatioW = double(2) / (m_nTubeWidth + 20); + if (_nRatio > _nRatioW) + _nRatio = _nRatioW; + if (_nRatio < m_nBaseZoom) + _nRatio = m_nBaseZoom; + Scale(_nRatio); + double _nFollowHeight = (_nMinHeight + _nMaxHeight) / 2; + FollowHeightABS(_nFollowHeight); + } + else + { + LookAt(GetLookAtType()); + } +} + +double CNce3DViewImp_V1::GetRotateAngle() +{ + return m_nRotate; +} + +// 跟随高度显示最佳视图 ---- 彭朋 2016-10-28 +bool CNce3DViewImp_V1::FollowHeightShow(double nHeight_) +{ + double _nHeight = m_nBmpHeight / m_nBmpZoomRatio; + double _nOffsetHeight = _nHeight * 0.5 - nHeight_; + if (fabs(_nOffsetHeight) > (_nHeight / 2 + 20)) + return false; + Vector4 _vtStart(0.,_nOffsetHeight, 0., 1.); + Vector4 _winStart = UnGLPick(_vtStart); + if (_winStart.y < 20 || _winStart.y > m_nOpenglHeight - 20) + { + glLoadIdentity(); + glScaled(m_nZoom, m_nZoom, m_nZoom); + glRotated(m_nRotate, 0, 1, 0); + m_nOffsetY = 0; + Translate(-_nOffsetHeight); + return true; + } + return false; +} + +// 不判断 决对移动 ---- 彭朋 2016-12-06 +void CNce3DViewImp_V1::FollowHeightABS(double nHeight_) +{ + double _nHeight = m_nTubeHeight; + double _nOffsetHeight = _nHeight * 0.5 - nHeight_; + glLoadIdentity(); + glScaled(m_nZoom, m_nZoom, m_nZoom); + glRotated(m_nRotate, 0, 1, 0); + m_nOffsetY = 0; + Translate(-_nOffsetHeight); +} + +// 缩放 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::Scale(double nValue_) +{ + double _nZoom = m_nZoom * nValue_; + double _nWidthRatio = double(2) / (m_nTubeWidth + 20); + double _nMinRatio = _nZoom / m_nBaseZoom; + double _nMaxRatio = _nZoom / _nWidthRatio; + if (_nMaxRatio > 10 || _nMinRatio < 0.2) + return; + m_nZoom *= nValue_; + glScaled(nValue_, nValue_, nValue_); + m_nOffsetY /= nValue_; +} + +// 平移 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::Translate(double nValue_) +{ + m_nOffsetY += nValue_; + glTranslated(0, nValue_, 0); +} + +// 旋转 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::Rotate(double nAngle_) +{ + glRotated(nAngle_, 0, 1, 0); + m_nRotate += nAngle_; + m_nRotate = fmod(m_nRotate, 360); + if (m_nRotate < 0.0) + { + m_nRotate += 360.0; + } + if (m_nRotate >= 360.0) + { + m_nRotate -= 360.0; + } + ASSERT(m_nRotate >= 0.0 && m_nRotate < 360.0); +} + +void CNce3DViewImp_V1::RotateABS(double nAngle_) +{ + Rotate((360 - m_nRotate) + (360 - nAngle_)); +} + +void CNce3DViewImp_V1::DragUp(double nStep_) +{ + double _nOffset = m_nOffsetY; + double _nHeight = m_nBmpHeight; + Vector4 _vtEnd(0., -(m_nBmpHeight / m_nBmpZoomRatio) * 0.5, 0., 1.); + Vector4 _vtWin = UnGLPick(_vtEnd); + if (_vtWin.y < m_nOpenglHeight * 0.5) + return; + + double _nStepHeight = m_nBmpHeight / m_nOpenglHeight; + if (m_nBmpZoomRatio > 0) + _nStepHeight = _nStepHeight / m_nBmpZoomRatio; + if (m_nPosition == LOOKAT_UP) + _nStepHeight = _nStepHeight / sin(M_PI / 9); + double _nStep = fabs(nStep_) / m_nZoom * m_nBaseZoom * _nStepHeight; + _nOffset += _nStep; + Translate(_nOffset - m_nOffsetY); +} + +void CNce3DViewImp_V1::DragDown(double nStep_) +{ + double _nOffset = m_nOffsetY; + double _nHeight = m_nBmpHeight; + Vector4 _vtEnd(0., (m_nBmpHeight / m_nBmpZoomRatio) * 0.5, 0., 1.); + Vector4 _vtWin = UnGLPick(_vtEnd); + if (_vtWin.y > m_nOpenglHeight * 0.5) + return; + + double _nStepHeight = m_nBmpHeight / m_nOpenglHeight; + if (m_nBmpZoomRatio > 0) + _nStepHeight = _nStepHeight / m_nBmpZoomRatio; + if (m_nPosition == LOOKAT_UP) + _nStepHeight = _nStepHeight / sin(M_PI / 9); + double _nStep = fabs(nStep_) / m_nZoom * m_nBaseZoom * _nStepHeight; + _nOffset -= _nStep; + Translate(_nOffset - m_nOffsetY); +} + +void CNce3DViewImp_V1::RotateLeft(double nSpeed_/* = 1.f*/) +{ + double _nWidthRatio = double(2) / (m_nTubeWidth + 20); + double _nMaxRatio = m_nZoom / _nWidthRatio; + double _nRot = 1.0; + if (_nMaxRatio > 1) + _nRot = (1 / _nMaxRatio) + (_nMaxRatio / 30); + Rotate(-2 * nSpeed_ * _nRot); +} + +void CNce3DViewImp_V1::RotateRight(double nSpeed_/* = 1.f*/) +{ + double _nWidthRatio = double(2) / (m_nTubeWidth + 20); + double _nMaxRatio = m_nZoom / _nWidthRatio; + double _nRot = 1.0; + if (_nMaxRatio > 1) + _nRot = (1 / _nMaxRatio) + (_nMaxRatio / 30); + Rotate(2 * nSpeed_ * _nRot); +} + +void CNce3DViewImp_V1::ZoomIn(double nSpeed_/* = 1.f*/) +{ + Scale(nSpeed_ * 1.01); +} + +void CNce3DViewImp_V1::ZoomOut(double nSpeed_/* = 1.f*/) +{ + Scale(nSpeed_ * 0.99); +} + +void CNce3DViewImp_V1::LoadIdentity() +{ + glLoadIdentity(); + m_nRotate = 0; + m_nOffsetY = 0.0f; + m_nZoom = 1.0f; +} + +void CNce3DViewImp_V1::LookAt(LookAtType_t nPosition_) +{ + ASSERT(nPosition_ == LOOKAT_FRONT || nPosition_ == LOOKAT_UP); + if (nPosition_ == LOOKAT_FRONT) + { + LoadIdentity(); + Scale(m_nBaseZoom); + m_nPosition = nPosition_; + } + else if(nPosition_ == LOOKAT_UP) + { + LoadIdentity(); + glRotated(290, 1, 0, 0); + if (m_nTubeHeight > m_nTubeWidth) + { + if ((m_nTubeHeight / m_nTubeWidth) > (m_nOpenglHeight / m_nOpenglWidth)) + Scale(m_nBaseZoom * min(2.0, (m_nTubeHeight / m_nTubeWidth) / (m_nOpenglHeight / m_nOpenglWidth))); + else + Scale(m_nBaseZoom); + } + else + Scale(m_nBaseZoom); + m_nPosition = nPosition_; + } + else + { + return; + } +} + +LookAtType_t CNce3DViewImp_V1::GetLookAtType() +{ + return m_nPosition; +} + +TubeType_t CNce3DViewImp_V1::GetTubeType() +{ + return m_nTubeType; +} + +void CNce3DViewImp_V1::Resize(int nX_, int nY_, int nWidth_, int nHeight_) +{ + if (nWidth_ * nHeight_ == 0) + return; + glPushMatrix(); + glViewport((GLint)nX_, (GLint)nY_, (GLint)nWidth_, (GLint)nHeight_); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (nWidth_ <= nHeight_) + glOrtho(-1.0, 1.0, -1.0 * (GLfloat)nHeight_ / (GLfloat)nWidth_, 1.0 * (GLfloat)nHeight_ / (GLfloat)nWidth_, -m_nZNearAndFar, m_nZNearAndFar); + else + glOrtho(-1.0 * (GLfloat)nWidth_ / (GLfloat)nHeight_, 1.0 * (GLfloat)nWidth_ / (GLfloat)nHeight_, -1.0, 1.0, -m_nZNearAndFar, m_nZNearAndFar); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + m_nOpenglWidth = nWidth_; + m_nOpenglHeight = nHeight_; + CalculateBaseZoom(); +} + +void CNce3DViewImp_V1::SetParams(TubeType_t nTubeType_, BaseTubeParams* pParamDatas_) +{ + ASSERT(pParamDatas_); + ASSERT(nTubeType_ == QuadTube || nTubeType_ == CircularTube + || nTubeType_ == RoundRectTube || nTubeType_ == EllipseTube); + m_nTubeType = nTubeType_; + if (nTubeType_ == QuadTube) + { + QuadTubeParams* _pParamData = (QuadTubeParams*)pParamDatas_; + _SetQuadTubeParams(_pParamData); + } + else if (nTubeType_ == CircularTube) + { + CircularTubeParams* _pParamData = (CircularTubeParams*)pParamDatas_; + _SetCircularTubeParams(_pParamData); + } + else if (nTubeType_ == RoundRectTube) + { + RoundRectTubeParams* _pParamData = (RoundRectTubeParams*)pParamDatas_; + _SetRoundRectTubeParams(_pParamData); + } + else if (nTubeType_ == EllipseTube) + { + EllipseTubeParams* _pParamData = (EllipseTubeParams*)pParamDatas_; + _SetEllipseTubeParams(_pParamData); + } + else + { + ASSERT(false); + } + CalculateAuxiliary(); + LookAt(GetLookAtType()); +} + +void CNce3DViewImp_V1::CalculateBaseZoom() +{ + double _nRatio = (m_nOpenglWidth < m_nOpenglHeight) ? (m_nOpenglHeight / m_nOpenglWidth) : 1.f; + if (m_nTubeHeight > m_nTubeWidth) + { + _nRatio = (m_nOpenglWidth < m_nOpenglHeight) ? (m_nOpenglHeight / m_nOpenglWidth) : 1.f; + if ((m_nTubeHeight / m_nTubeWidth) < (m_nOpenglHeight / m_nOpenglWidth)) + { + _nRatio *= (m_nTubeHeight / m_nTubeWidth) / (m_nOpenglHeight / m_nOpenglWidth); + } + } + else + { + _nRatio = (m_nOpenglHeight < m_nOpenglWidth) ? (m_nOpenglWidth / m_nOpenglHeight) : 1.f; + } + m_nBaseZoomRatio = _nRatio; + double _nMaxZoom = max(m_nTubeHeight + 20, m_nTubeWidth + 20); + m_nBaseZoom = double(2) / _nMaxZoom * _nRatio; +} + +// 设方管参数 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::_SetQuadTubeParams(QuadTubeParams* pParamDatas_) +{ + ASSERT(pParamDatas_); + m_QPData.nA = pParamDatas_->nA; + m_QPData.nB = pParamDatas_->nB; + m_QPData.nH = pParamDatas_->nH; + m_QPData.nR = pParamDatas_->nR; + _CreateQuadTubeBitmap(); + LoadIdentity(); + m_nTubeWidth = max(pParamDatas_->nA, pParamDatas_->nB); + m_nTubeHeight = pParamDatas_->nH; + m_nMaxWidth = m_nBmpWidth / m_nBmpZoomRatio; + CalculateBaseZoom(); + Scale(m_nBaseZoom); + _CalculateQuadTubeData(); +} + +// 设圆管参数 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::_SetCircularTubeParams(CircularTubeParams* pParamDatas_) +{ + ASSERT(pParamDatas_); + m_CPData.nR = pParamDatas_->nR; + m_CPData.nH = pParamDatas_->nH; + _CreateCircularTubeBitmap(); + LoadIdentity(); + m_nTubeWidth = pParamDatas_->nR * 2; + m_nTubeHeight = pParamDatas_->nH; + m_nMaxWidth = m_nBmpWidth / m_nBmpZoomRatio; + CalculateBaseZoom(); + Scale(m_nBaseZoom); + _CalculateCircularTubeData(); +} + +// 设腰型管参数 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::_SetRoundRectTubeParams(RoundRectTubeParams* pParamDatas_) +{ + ASSERT(pParamDatas_); + m_RPData.nA = pParamDatas_->nA; + m_RPData.nB = pParamDatas_->nB; + m_RPData.nH = pParamDatas_->nH; + _CreateRoundRectTubeBitmap(); + LoadIdentity(); + m_nTubeWidth = max(pParamDatas_->nA, pParamDatas_->nB); + m_nTubeHeight = pParamDatas_->nH; + m_nMaxWidth = m_nBmpWidth / m_nBmpZoomRatio; + CalculateBaseZoom(); + Scale(m_nBaseZoom); + _CalculateRoundRectTubeData(); +} + +// 设椭圆管参数 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::_SetEllipseTubeParams(EllipseTubeParams* pParamDatas_) +{ + // 椭圆周长 + ASSERT(pParamDatas_); + m_EPData.nA = pParamDatas_->nA; + m_EPData.nB = pParamDatas_->nB; + m_EPData.nH = pParamDatas_->nH; + double _nb = min(m_EPData.nA, m_EPData.nB); + double _na = max(m_EPData.nA, m_EPData.nB); + double _nL = GetEllipsePerimeter(_na, _nb); + _CreateEllipseTubeBitmap(); + LoadIdentity(); + m_nTubeWidth = max(pParamDatas_->nA * 2, pParamDatas_->nB * 2); + m_nTubeHeight = pParamDatas_->nH; + m_nMaxWidth = m_nBmpWidth / m_nBmpZoomRatio; + CalculateBaseZoom(); + Scale(m_nBaseZoom); + _CalculateEllipseTubeData(); +} + +void CNce3DViewImp_V1::_CreateBaseTubeBitmap() +{ + if (m_pBmpTexture != NULL) + { + delete m_pBmpTexture; + } + m_pBmpTexture = new CBitmap; + CDC* _pGLDC = new CDC; + HDC _hDC = ::GetDC(NULL); + _pGLDC->Attach(_hDC); + //在这里做了修动 图片加大了,用来支持管材的辅助面 ---- 彭朋 2016-10-19 + m_pBmpTexture->CreateCompatibleBitmap(_pGLDC, (int)(m_nBmpWidth + m_nAuxiliaryWidth), (int)m_nBmpHeight); + if (m_pBmpDC != NULL) + { + delete m_pBmpDC; + } + m_pBmpDC = new CDC; + m_pBmpDC->CreateCompatibleDC(_pGLDC); + m_pBmpDC->SelectObject(m_pBmpTexture); + m_pBmpDC->FillSolidRect(0, 0, (int)(m_nBmpWidth + m_nAuxiliaryWidth), (int)m_nBmpHeight, RGB(255, 254, 253)); + BitmapToOpenGLData(m_pBmpDC, m_pBmpTexture, (int)m_nBmpWidth, (int)m_nBmpHeight); + CreateTextures((int)m_nBmpWidth, (int)m_nBmpHeight); + ::ReleaseDC(NULL, _hDC); + delete _pGLDC; +} + +// 生成方管的bitmap ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::_CreateQuadTubeBitmap() +{ + double _nWidth = (m_QPData.nA + m_QPData.nB) * 2; + double _nHeight = m_QPData.nH; + m_vecOrigin.x = 0.f; + m_vecOrigin.y = 0.f; + double _nMin = min(_nWidth, _nHeight); + double _nMax = max(_nWidth, _nHeight); + double _nMaxWidth = MaxBitmapWidth; + if (_nMax > _nMaxWidth) + { + m_nBmpZoomRatio = _nMaxWidth / _nMax; + } + else + { + if (_nMin < MinBitmapWidth) + { + m_nBmpZoomRatio = min(_nMaxWidth / _nMax, MinBitmapWidth / _nMin); + } + else + { + m_nBmpZoomRatio = 1; + } + } + m_nBmpWidth = _nWidth * m_nBmpZoomRatio; + m_nBmpHeight = _nHeight * m_nBmpZoomRatio; + m_nAuxiliaryWidth = m_nBmpZoomRatio * m_QPData.nA; + _CreateBaseTubeBitmap(); +} + +// 生成圆管的bitmap ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::_CreateCircularTubeBitmap() +{ + double _nWidth = m_CPData.nR * 2 * M_PI; + double _nHeight = m_CPData.nH; + m_vecOrigin.x = 0.f; + m_vecOrigin.y = 0.f; + double _nMax = max(_nWidth, _nHeight); + double _nMaxWidth = MaxBitmapWidth; + if (_nMax > _nMaxWidth) + { + m_nBmpZoomRatio = _nMaxWidth / _nMax; + } + else + { + m_nBmpZoomRatio = 1; + } + m_nBmpWidth = _nWidth * m_nBmpZoomRatio; + m_nBmpHeight = _nHeight * m_nBmpZoomRatio; + m_nAuxiliaryWidth = m_nBmpWidth * 0.25; + _CreateBaseTubeBitmap(); +} + +// 生成腰形管的bitmap ---- 彭朋 2016-11-01 +void CNce3DViewImp_V1::_CreateRoundRectTubeBitmap() +{ + double _nWidth = m_RPData.nB * M_PI + m_RPData.nA * 2; //数据暂定 + double _nHeight = m_RPData.nH; + m_vecOrigin.x = 0.f; + m_vecOrigin.y = 0.f; + double _nMax = max(_nWidth, _nHeight); + double _nMaxWidth = MaxBitmapWidth; + if (_nMax > _nMaxWidth) + { + m_nBmpZoomRatio = _nMaxWidth / _nMax; + } + else + { + m_nBmpZoomRatio = 1; + } + m_nBmpWidth = _nWidth * m_nBmpZoomRatio; + m_nBmpHeight = _nHeight * m_nBmpZoomRatio; + m_nAuxiliaryWidth = m_nBmpWidth * 0.25; + _CreateBaseTubeBitmap(); +} + +void CNce3DViewImp_V1::_CreateEllipseTubeBitmap() +{ + // 椭圆周长 + double _nb = min(m_EPData.nA, m_EPData.nB); + double _na = max(m_EPData.nA, m_EPData.nB); + double _nL = GetEllipsePerimeter(_na, _nb); + double _nWidth = _nL; //数据暂定 + double _nHeight = m_EPData.nH; + m_vecOrigin.x = 0.f; + m_vecOrigin.y = 0.f; + double _nMax = max(_nWidth, _nHeight); + double _nMaxWidth = MaxBitmapWidth; + if (_nMax > _nMaxWidth) + { + m_nBmpZoomRatio = _nMaxWidth / _nMax; + } + else + { + m_nBmpZoomRatio = 1; + } + m_nBmpWidth = _nWidth * m_nBmpZoomRatio; + m_nBmpHeight = _nHeight * m_nBmpZoomRatio; + m_nAuxiliaryWidth = m_nBmpWidth * 0.25; + _CreateBaseTubeBitmap(); +} + +// 计算方管的数据 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::_CalculateQuadTubeData() +{ + m_vectorTexs.clear(); + m_vectorVTs.clear(); + m_vectorNormals.clear(); + m_vectorTransform3D.clear(); + double _nStepLong = m_QPData.nA - 2 * m_QPData.nR; + double _nStepWidth = m_QPData.nB - 2 * m_QPData.nR; + double _nSrcX = m_QPData.nA / 2; + double _nSrcZ = m_QPData.nB / 2; + double _nx = _nStepLong / 2; + double _ny = m_QPData.nH / 2; + double _nz = _nStepWidth / 2; + Vector4 _vecVTs[21]; + int _nSlices = 20 * ((m_QPData.nR <= 0) ? 0 : 1); + double _nStepR = 2 * m_QPData.nR; //m_QPData.nR * M_PI * 0.5; + double _nWidth = (_nStepLong + _nStepWidth) * 2 + 4 * _nStepR; + double _nHeight = m_QPData.nH; + double _nTexStart = _nStepR / 2; + double _nStartTexCood = _nTexStart / _nWidth; + double _nEndTexCood = (_nTexStart + _nStepLong) / _nWidth; + double _nStepAngle = M_PI_2 / _nSlices; + double _nTexStep = _nStepR / _nSlices; + + // 角1 + for (int _i = 0; _i <= _nSlices / 2; _i++) + { + _vecVTs[_i].z = _nz - sin(M_PI * 1.25 + _nStepAngle * _i) * m_QPData.nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = -_nx + cos(M_PI * 1.25 + _nStepAngle * _i) * m_QPData.nR; + } + for (int _i = 0; _i < _nSlices / 2; _i++) + { + _nStartTexCood =(_i * _nTexStep) / _nWidth; + _nEndTexCood = ((_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + // 面1 + _nStartTexCood = _nTexStart / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong) / _nWidth; + PushVector3D(Vector4(-_nx, -_ny, _nSrcZ), Vector4(_nx, -_ny, _nSrcZ), _nStartTexCood, _nEndTexCood); + + // 角2 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = _nz - sin(M_PI_2 * 3 + _nStepAngle * _i) * m_QPData.nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = _nx + cos(M_PI_2 * 3 + _nStepAngle * _i) * m_QPData.nR; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood = (_nTexStart + _nStepLong + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + // 面2 + _nStartTexCood =(_nTexStart + _nStepLong + _nStepR) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong + _nStepR + _nStepWidth) / _nWidth; + PushVector3D(Vector4(_nSrcX, -_ny, _nz), Vector4(_nSrcX, -_ny, -_nz), _nStartTexCood, _nEndTexCood); + + // 角3 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = -_nz - sin(_nStepAngle * _i) * m_QPData.nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = _nx + cos(_nStepAngle * _i) * m_QPData.nR; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood = (_nTexStart + _nStepLong + _nStepR + _nStepWidth + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong + _nStepR + _nStepWidth + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + // 面3 + _nStartTexCood =(_nTexStart + _nStepLong + _nStepWidth + _nStepR * 2) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth + _nStepR *2) / _nWidth; + PushVector3D(Vector4(_nx, -_ny, -_nSrcZ), Vector4(-_nx, -_ny, -_nSrcZ), _nStartTexCood, _nEndTexCood); + + // 角4 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = -_nz - sin(M_PI_2 + _nStepAngle * _i) * m_QPData.nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = -_nx + cos(M_PI_2 + _nStepAngle * _i) * m_QPData.nR; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth + _nStepR * 2 + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth + _nStepR * 2 + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + // 面4 + _nStartTexCood =(_nTexStart + _nStepLong * 2 + _nStepWidth +_nStepR * 3) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth * 2 +_nStepR * 3) / _nWidth; + PushVector3D(Vector4(-_nSrcX, -_ny, -_nz), Vector4(-_nSrcX, -_ny, _nz), _nStartTexCood, _nEndTexCood); + + // 角1 + for (int _i = 0; _i <= _nSlices / 2; _i++) + { + _vecVTs[_i].z = _nz - sin(M_PI + _nStepAngle * _i) * m_QPData.nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = -_nx + cos(M_PI + _nStepAngle * _i) * m_QPData.nR; + } + for (int _i = 0; _i < _nSlices / 2; _i++) + { + _nStartTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth * 2 +_nStepR * 3 + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth *2 +_nStepR * 3 + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } +} + +// 计算腰形管的数据 ---- 彭朋 2016-11-01 +void CNce3DViewImp_V1::_CalculateRoundRectTubeData() +{ + m_vectorTexs.clear(); + m_vectorVTs.clear(); + m_vectorNormals.clear(); + m_vectorTransform3D.clear(); + double _nStepLong = m_RPData.nA; + double _nStepWidth = 0; + double _nSrcX = m_RPData.nA / 2; + double _nSrcZ = m_RPData.nB / 2; + double _nR = m_RPData.nB * 0.5; + double _nx = _nStepLong * 0.5; + double _ny = m_RPData.nH * 0.5; + double _nz = _nStepWidth * 0.5; + Vector4 _vecVTs[21]; + int _nSlices = 20; + double _nStepR = _nR * M_PI_2; + double _nWidth = _nStepLong * 2 + 4 * _nStepR; + double _nHeight = m_RPData.nH; + + double _nTexStart = 0; + double _nStartTexCood = _nTexStart / _nWidth; + double _nEndTexCood = (_nTexStart + _nStepLong) / _nWidth; + double _nStepAngle = M_PI_2 / _nSlices; + double _nTexStep = _nStepR / _nSlices; + + // 面1 这个面要分成两个 + _nStartTexCood = _nTexStart / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong / 2) / _nWidth; + PushVector3D(Vector4(-_nx, -_ny, _nSrcZ), Vector4(0, -_ny, _nSrcZ), _nStartTexCood, _nEndTexCood); + + _nStartTexCood = (_nTexStart + _nStepLong / 2) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong) / _nWidth; + PushVector3D(Vector4(0, -_ny, _nSrcZ), Vector4(_nx, -_ny, _nSrcZ), _nStartTexCood, _nEndTexCood); + + // 角2 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = _nz - sin(M_PI_2 * 3 + _nStepAngle * _i) * _nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = _nx + cos(M_PI_2 * 3 + _nStepAngle * _i) * _nR; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood = (_nTexStart + _nStepLong + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + + // 角3 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = -_nz - sin(_nStepAngle * _i) * _nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = _nx + cos(_nStepAngle * _i) * _nR; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood = (_nTexStart + _nStepLong + _nStepR + _nStepWidth + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong + _nStepR + _nStepWidth + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + // 面3 这个也要分成两个 + _nStartTexCood =(_nTexStart + _nStepLong + _nStepWidth + _nStepR * 2) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong * 1.5 + _nStepWidth + _nStepR *2) / _nWidth; + PushVector3D(Vector4(_nx, -_ny, -_nSrcZ), Vector4(0, -_ny, -_nSrcZ), _nStartTexCood, _nEndTexCood); + + _nStartTexCood = _nEndTexCood; + _nEndTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth + _nStepR *2) / _nWidth; + PushVector3D(Vector4(0, -_ny, -_nSrcZ), Vector4(-_nx, -_ny, -_nSrcZ), _nStartTexCood, _nEndTexCood); + + // 角4 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = -_nz - sin(M_PI_2 + _nStepAngle * _i) * _nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = -_nx + cos(M_PI_2 + _nStepAngle * _i) * _nR; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth + _nStepR * 2 + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth + _nStepR * 2 + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + + // 角1 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = _nz - sin(M_PI + _nStepAngle * _i) * _nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = -_nx + cos(M_PI + _nStepAngle * _i) * _nR; + } + for (int _i = 0; _i < _nSlices ; _i++) + { + _nStartTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth * 2 +_nStepR * 3 + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepLong * 2 + _nStepWidth *2 +_nStepR * 3 + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } +} + +double CNce3DViewImp_V1::_GetEllipseSlices(double nA_, double nB_, double nSlices_) +{ + double _nSlicesD = (2 * M_PI) / (nSlices_ * 4); + double _nSlicesSize = nSlices_ * 4; + double _nSlicesLen = 0; + for (int _i = 1; _i <= _nSlicesSize; _i++) + { + double _nDx = sin(_nSlicesD * _i) * nB_ - sin(_nSlicesD * (_i - 1)) * nB_; + double _nDy = cos(_nSlicesD * _i) * nA_ - cos(_nSlicesD * (_i - 1)) * nA_; + _nSlicesLen += sqrt((_nDx * _nDx) + (_nDy * _nDy)); + } + return _nSlicesLen; +} + +void CNce3DViewImp_V1::_CalculateEllipseTubeData() +{ + m_vectorTexs.clear(); + m_vectorVTs.clear(); + m_vectorNormals.clear(); + m_vectorTransform3D.clear(); + double _nA = m_EPData.nA; + double _nB = m_EPData.nB; + double _nx = 0; + double _ny = m_EPData.nH / 2; + double _nz = 0; + Vector4 _vecVTs[51]; + int _nSlices = 40; + double _nb = min(m_EPData.nA, m_EPData.nB); + double _na = max(m_EPData.nA, m_EPData.nB); + double _nL = _GetEllipseSlices(_na, _nb, _nSlices); + double _nStepR = _nL * 0.25; + double _nWidth = _nL; + double _nHeight = m_EPData.nH; + double _nTexStart = _nStepR; + double _nStartTexCood = _nTexStart / _nWidth; + double _nEndTexCood = _nTexStart / _nWidth; + double _nStepAngle = M_PI_2 / _nSlices; + double _nTexStep = _nStepR / _nSlices; + double _nSummationLen = 0; + // 角1 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = _nz - sin(M_PI_2 * 3 + _nStepAngle * _i) * _nB; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = _nx + cos(M_PI_2 * 3 + _nStepAngle * _i) * _nA; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood =_nSummationLen / _nWidth; + _nSummationLen += sqrt((_vecVTs[_i + 1].x - _vecVTs[_i].x) * (_vecVTs[_i + 1].x - _vecVTs[_i].x) + + (_vecVTs[_i + 1].z - _vecVTs[_i].z) * (_vecVTs[_i + 1].z - _vecVTs[_i].z)); + _nEndTexCood = _nSummationLen / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + + // 角2 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = -_nz - sin(_nStepAngle * _i) * _nB; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = _nx + cos(_nStepAngle * _i) * _nA; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood =_nSummationLen / _nWidth; + _nSummationLen += sqrt((_vecVTs[_i + 1].x - _vecVTs[_i].x) * (_vecVTs[_i + 1].x - _vecVTs[_i].x) + + (_vecVTs[_i + 1].z - _vecVTs[_i].z) * (_vecVTs[_i + 1].z - _vecVTs[_i].z)); + _nEndTexCood = _nSummationLen / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + + // 角3 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = -_nz - sin(M_PI_2 + _nStepAngle * _i) * _nB; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = -_nx + cos(M_PI_2 + _nStepAngle * _i) * _nA; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood =_nSummationLen / _nWidth; + _nSummationLen += sqrt((_vecVTs[_i + 1].x - _vecVTs[_i].x) * (_vecVTs[_i + 1].x - _vecVTs[_i].x) + + (_vecVTs[_i + 1].z - _vecVTs[_i].z) * (_vecVTs[_i + 1].z - _vecVTs[_i].z)); + _nEndTexCood = _nSummationLen / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + + // 角4 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = _nz - sin(M_PI + _nStepAngle * _i) * _nB; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = -_nx + cos(M_PI + _nStepAngle * _i) * _nA; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood =_nSummationLen / _nWidth; + _nSummationLen += sqrt((_vecVTs[_i + 1].x - _vecVTs[_i].x) * (_vecVTs[_i + 1].x - _vecVTs[_i].x) + + (_vecVTs[_i + 1].z - _vecVTs[_i].z) * (_vecVTs[_i + 1].z - _vecVTs[_i].z)); + _nEndTexCood = _nSummationLen / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } +} + +// 计算圆管的数据 ---- 彭朋 2016-10-28 +void CNce3DViewImp_V1::_CalculateCircularTubeData() +{ + m_vectorTexs.clear(); + m_vectorVTs.clear(); + m_vectorNormals.clear(); + m_vectorTransform3D.clear(); + double _nR = m_CPData.nR; + double _nx = 0; + double _ny = m_CPData.nH / 2; + double _nz = 0; + Vector4 _vecVTs[51]; + int _nSlices = 50; + double _nStepR = m_CPData.nR * M_PI * 0.5; + double _nWidth = 4 * _nStepR; + double _nHeight = m_CPData.nH; + double _nTexStart = _nStepR; + double _nStartTexCood = _nTexStart / _nWidth; + double _nEndTexCood = _nTexStart / _nWidth; + double _nStepAngle = M_PI_2 / _nSlices; + double _nTexStep = _nStepR / _nSlices; + + // 角1 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = _nz - sin(M_PI_2 * 3 + _nStepAngle * _i) * _nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = _nx + cos(M_PI_2 * 3 + _nStepAngle * _i) * _nR; + } + + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood =(_i * _nTexStep) / _nWidth; + _nEndTexCood = ((_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + + // 角2 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = -_nz - sin(_nStepAngle * _i) * _nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = _nx + cos(_nStepAngle * _i) * _nR; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood = (_nTexStart + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + + // 角3 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = -_nz - sin(M_PI_2 + _nStepAngle * _i) * _nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = -_nx + cos(M_PI_2 + _nStepAngle * _i) * _nR; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood = (_nTexStart + _nStepR + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepR + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } + + // 角4 + for (int _i = 0; _i <= _nSlices; _i++) + { + _vecVTs[_i].z = _nz - sin(M_PI + _nStepAngle * _i) * _nR; + _vecVTs[_i].y = -_ny; + _vecVTs[_i].x = -_nx + cos(M_PI + _nStepAngle * _i) * _nR; + } + for (int _i = 0; _i < _nSlices; _i++) + { + _nStartTexCood = (_nTexStart + _nStepR * 2 + _i * _nTexStep) / _nWidth; + _nEndTexCood = (_nTexStart + _nStepR * 2 + (_i + 1) * _nTexStep) / _nWidth; + PushVector3D(_vecVTs[_i], _vecVTs[_i + 1], _nStartTexCood, _nEndTexCood); + } +} + +void CNce3DViewImp_V1::_DrawCircularTube() +{ + int _nCutSize = static_cast(m_vectorCutData3D.size()); + ASSERT(m_vectorTexs.size() == m_vectorVTs.size()); + int _nSize = (int)m_vectorTexs.size(); + ASSERT(_nCutSize == _nSize / 4); + // 用来处理加镂空时 ---- 彭朋 2016-10-14 + int _nOffset = 0; + int _nStep = (_nSize / 4); + double _nStepAngle = double(_nStep) / 90.f; // 每个角度代表的格数 + _nOffset = _nStep - int(_nStepAngle * m_nRotate); + if (_nOffset < 0) + _nOffset = _nOffset + _nSize; + _nOffset = _nOffset - _nOffset % 4; // 必须是4的倍数 一个面有4个顶点。 + + ASSERT(_nOffset % 4 == 0); + _DrawShareTube(_nOffset, _nCutSize, _nSize); +} + +void CNce3DViewImp_V1::_DrawRoundRectTube() +{ + +} + +void CNce3DViewImp_V1::_DrawEllipseTube() +{ + +} + +void CNce3DViewImp_V1::_DrawQuadTube() +{ + int _nCutSize = static_cast(m_vectorCutData3D.size()); + ASSERT(m_vectorTexs.size() == m_vectorVTs.size()); + int _nSize = (int)m_vectorTexs.size(); + ASSERT(_nCutSize == _nSize / 4); + // 用来处理加镂空时 ---- 彭朋 2016-10-14 + // 保存先后有序镂空效果最佳。 + int _nOffset = 0; + int _nStep = (_nSize / 4); + if (m_nRotate < 90) + _nOffset = _nStep; + else if (m_nRotate < 180) + _nOffset = 0; + else if (m_nRotate < 270) + _nOffset = _nStep * 3; + else if (m_nRotate < 360) + _nOffset = _nStep * 2; + ASSERT(_nOffset % 4 == 0); + _DrawShareTube(_nOffset, _nCutSize, _nSize); +} + +void CNce3DViewImp_V1::_DrawShareTube(int nOffset_, int nCutSize_, int nMainSize_) +{ + int _nSize = nMainSize_; + int _nOffset = nOffset_; + int _nCutSize = nCutSize_; + ASSERT(_nCutSize == _nSize / 4); + ASSERT(_nOffset % 4 == 0); + int _nCutOffset = _nOffset / 4; + int _nHalfSize = _nSize / 2; + int _nCutHalfSize = _nCutSize / 2; + + // 后面的一半 cut object + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset( 1., 1.); + glColor4ub(255, 0, 0, 0); + for (int _i = 0; _i < _nCutHalfSize; _i++) + { + int _nStart = _nCutOffset + _i; + if (_nStart >= _nCutSize) + { + _nStart = _nStart - _nCutSize; + } + ASSERT(_nStart < _nCutSize); + Polygon3DList& _tempPolygonList = m_vectorCutData3D[_nStart]; + int _nPolygonSize = static_cast(_tempPolygonList.size()); + for (int _j = 0; _j < _nPolygonSize; _j++) + { + Polygon3D& _Polygon = _tempPolygonList[_j]; + int _nPointSize = static_cast(_Polygon.size()); + glBegin(GL_TRIANGLE_STRIP); + for (int _k = 0; _k < _nPointSize; _k++) + { + glVertex3d(_Polygon[_k].x, _Polygon[_k].y, _Polygon[_k].z); + } + glEnd(); + } + } + //glDisable(GL_POLYGON_OFFSET_FILL); + + glPolygonOffset( 2., 5.); + glColor4ub(255, 255, 255, 255); + glBegin(GL_QUADS); + for (int _i = 0; _i < _nHalfSize; _i++) + { + int _nStart = _nOffset + _i; + if (_nStart >= _nSize) + { + _nStart = _nStart - _nSize; + } + if (_nStart % 4 == 0) + glNormal3d(m_vectorNormals[_nStart / 4].x, m_vectorNormals[_nStart / 4].y, m_vectorNormals[_nStart / 4].z); + glTexCoord2d(m_vectorTexs[_nStart].x, m_vectorTexs[_nStart].y); + glVertex4d(m_vectorVTs[_nStart].x, m_vectorVTs[_nStart].y, m_vectorVTs[_nStart].z, m_vectorVTs[_nStart].w); + } + glEnd(); + + // 前面的一半 cut object + //glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset( 1., 1.); + glColor4ub(255, 0, 0, 0); + for (int _i = _nCutHalfSize; _i < _nCutSize; _i++) + { + int _nStart = _nCutOffset + _i; + if (_nStart >= _nCutSize) + { + _nStart = _nStart - _nCutSize; + } + ASSERT(_nStart < _nCutSize); + Polygon3DList& _tempPolygonList = m_vectorCutData3D[_nStart]; + int _nPolygonSize = static_cast(_tempPolygonList.size()); + for (int _j = 0; _j < _nPolygonSize; _j++) + { + Polygon3D& _Polygon = _tempPolygonList[_j]; + int _nPointSize = static_cast(_Polygon.size()); + glBegin(GL_TRIANGLE_STRIP); + for (int _k = 0; _k < _nPointSize; _k++) + { + glVertex3d(_Polygon[_k].x, _Polygon[_k].y, _Polygon[_k].z); + } + glEnd(); + } + } + + glPolygonOffset( 2., 5.); + glColor4ub(255, 255, 255, 255); + glBegin(GL_QUADS); + for (int _i = _nHalfSize; _i < _nSize; _i++) + { + int _nStart = _nOffset + _i; + if (_nStart >= _nSize) + { + _nStart = _nStart - _nSize; + } + if (_nStart % 4 == 0) + glNormal3d(m_vectorNormals[_nStart / 4].x, m_vectorNormals[_nStart / 4].y, m_vectorNormals[_nStart / 4].z); + glTexCoord2d(m_vectorTexs[_nStart].x, m_vectorTexs[_nStart].y); + glVertex4d(m_vectorVTs[_nStart].x, m_vectorVTs[_nStart].y, m_vectorVTs[_nStart].z, m_vectorVTs[_nStart].w); + } + glEnd(); + glDisable(GL_POLYGON_OFFSET_FILL); +} + +// 转成opengl可以识别的数据流 ---- 彭朋 2016-10-14 +void CNce3DViewImp_V1::BitmapToOpenGLData(CDC* pBmpDC_, CBitmap* pBitmap_, int nWidth_, int nHeight_) +{ + ASSERT(pBmpDC_ && pBitmap_ && nWidth_ && nHeight_); + int _nBufsize =nWidth_ * nHeight_ * 4; + if (m_pRGBAData != NULL) + { + delete[] m_pRGBAData; + } + + m_pRGBAData = new BYTE[_nBufsize]; + memset(m_pRGBAData, 255, sizeof(BYTE) * _nBufsize); + struct + { + BITMAPINFOHEADER bih; + RGBQUAD col[2]; + }_bic; + BITMAPINFO *_pInfo = (BITMAPINFO*)&_bic; + _pInfo->bmiHeader.biSize = sizeof(_pInfo->bmiHeader); + _pInfo->bmiHeader.biWidth = nWidth_; + _pInfo->bmiHeader.biHeight = nHeight_; + _pInfo->bmiHeader.biPlanes = 1; + _pInfo->bmiHeader.biBitCount = 32; + _pInfo->bmiHeader.biCompression = BI_RGB; + _pInfo->bmiHeader.biSizeImage = _nBufsize; + _pInfo->bmiHeader.biXPelsPerMeter = 1; + _pInfo->bmiHeader.biYPelsPerMeter = 1; + _pInfo->bmiHeader.biClrUsed = 0; + _pInfo->bmiHeader.biClrImportant = 0; + _pInfo->bmiColors[0].rgbBlue = 8; + _pInfo->bmiColors[0].rgbGreen = 8; + _pInfo->bmiColors[0].rgbRed = 8; + _pInfo->bmiColors[0].rgbReserved = 8; + GetDIBits(pBmpDC_->GetSafeHdc(), (HBITMAP)pBitmap_->GetSafeHandle(), 0, nHeight_, m_pRGBAData, _pInfo, DIB_RGB_COLORS); + COLORREF _clr = m_clrAlpha; + BYTE _r = GetRValue(m_clrAlpha), _g = GetGValue(m_clrAlpha), _b = GetBValue(m_clrAlpha); + for (int _i = 0; _i < nHeight_; _i++) + { + for (int _j = 0; _j < nWidth_; _j++) + { + int _nk =int(_i * nWidth_ * 4 + _j * 4); + if (m_pRGBAData[_nk] == _b && m_pRGBAData[_nk + 1] == _g && m_pRGBAData[_nk + 2] == _r) + { + m_pRGBAData[_nk + 3] = 0; + } + else + { + m_pRGBAData[_nk + 3] = 255; + } + } + } +} + +// 生成openg纹理图 ---- 彭朋 2016-10-14 +void CNce3DViewImp_V1::CreateTextures(int nWidth_, int nHeight_) +{ + ASSERT(m_pRGBAData); + ASSERT(nWidth_ * nHeight_); + if (m_nTextureID != -1) + { + glDeleteTextures(1, &m_nTextureID); + m_nTextureID = -1; + } + glGenTextures(1, &m_nTextureID); + ASSERT(m_nTextureID != -1); + if (m_nTextureID <= 0) + return; + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glBindTexture(GL_TEXTURE_2D, m_nTextureID); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + gluBuild2DMipmaps(GL_TEXTURE_2D, 4, nWidth_, nHeight_, GL_BGRA_EXT, GL_UNSIGNED_BYTE, m_pRGBAData); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, m_nTextureID); +} + +void CNce3DViewImp_V1::ReviseCoord(Polyline2DList& listRecords_, Polyline2DList& listRevise_) +{ + for (Polyline2DList::iterator _it = listRecords_.begin(); _it != listRecords_.end(); _it++) + { + Polyline2DItem _item = *_it; + Polyline2D& _polylineItem = _item.PolylineNode; + _polylineItem.nStartX *= m_nBmpZoomRatio; + _polylineItem.nStartY *= m_nBmpZoomRatio; + size_t _nSize = _polylineItem.vectorNodes.size(); + for (size_t _i = 0; _i < _nSize; _i++) + { + _polylineItem.vectorNodes[_i].nEndX *= m_nBmpZoomRatio; + _polylineItem.vectorNodes[_i].nEndY *= m_nBmpZoomRatio; + } + listRevise_.push_back(_item); + } +} + +Vector4 CNce3DViewImp_V1::ReviseCoord(Vector4& vecPoint2D_) +{ + Vector4 _retVector; + _retVector.x = vecPoint2D_.x * m_nBmpZoomRatio; + _retVector.y =vecPoint2D_.y * m_nBmpZoomRatio; + return _retVector; +} + +void CNce3DViewImp_V1::TrackClear() +{ + m_vectorAddDatas.clear(); +} + +void CNce3DViewImp_V1::GetDataMaxRect(Polyline2DList& listRecords_, double& nMinWidth_, double& nMaxWidth_, + double& nMinHeight_, double& nMaxHeight_) +{ + bool _bInit = false; + Polyline2DList *_plistCalculateRevise = &listRecords_; + for (Polyline2DList::iterator _it = _plistCalculateRevise->begin(); _it != _plistCalculateRevise->end(); _it++) + { + Polyline2D& _polylineItem = _it->PolylineNode; + int _nSize = (int)(_polylineItem.vectorNodes.size()); + nMinWidth_ = _bInit ? min(_polylineItem.nStartX, nMinWidth_) : _polylineItem.nStartX; + nMaxWidth_ = _bInit ? max(_polylineItem.nStartX, nMaxWidth_) : _polylineItem.nStartX; + nMinHeight_ = _bInit ? min(_polylineItem.nStartY ,nMinHeight_) : _polylineItem.nStartY; + nMaxHeight_ = _bInit ? max(_polylineItem.nStartY ,nMaxHeight_) : _polylineItem.nStartY; + _bInit = true; + for (int _i = 0;_i < _nSize; _i++) + { + nMinWidth_ = min(_polylineItem.vectorNodes[_i].nEndX, nMinWidth_); + nMaxWidth_ = max(_polylineItem.vectorNodes[_i].nEndX, nMaxWidth_); + nMinHeight_ = min(_polylineItem.vectorNodes[_i].nEndY ,nMinHeight_); + nMaxHeight_ = max(_polylineItem.vectorNodes[_i].nEndY ,nMaxHeight_); + } + } +} + +// 用来处理切去(镂空)的数据 ---- 彭朋 2016-12-01 +void CNce3DViewImp_V1::FillCutOffDataGDI2D(Polyline2DList& listRecords_, double nOffset_) +{ + Polyline2DList *_plistCalculateRevise = &listRecords_; + for (Polyline2DList::iterator _it = _plistCalculateRevise->begin(); _it != _plistCalculateRevise->end(); _it++) + { + Polyline2D& _polylineItem = _it->PolylineNode; + int _nSize = (int)(_polylineItem.vectorNodes.size()); + POINT* _pPolygonData = new POINT[_nSize + 1]; + _pPolygonData[0].x = (int)((_polylineItem.nStartX + nOffset_)* m_nBmpZoomRatio); + _pPolygonData[0].y = (int)(_polylineItem.nStartY * m_nBmpZoomRatio); + for (int _i = 0;_i < _nSize; _i++) + { + _pPolygonData[_i+1].x = (int)((_polylineItem.vectorNodes[_i].nEndX + nOffset_) * m_nBmpZoomRatio); + _pPolygonData[_i+1].y = (int)(_polylineItem.vectorNodes[_i].nEndY * m_nBmpZoomRatio); + } + CPen _pen(PS_SOLID, 1, m_clrAlpha); + CBrush _brush(m_clrAlpha); + m_pBmpDC->SelectObject(_pen); + m_pBmpDC->SelectObject(_brush); + m_pBmpDC->Polygon(_pPolygonData, _nSize + 1); + delete[] _pPolygonData; + } +} + +void CNce3DViewImp_V1::SetCutOffData(Polyline2DList& listRecords_) +{ + m_pBmpDC->FillSolidRect(0, 0, (int)(m_nBmpWidth + m_nAuxiliaryWidth), (int)m_nBmpHeight, RGB(255, 255, 255)); + // 在无限扩展面的时候要特殊处理。 + if (m_nTubeType == CircularTube) + { + double _nMinWidth = 0, _nMaxWidth = 0, _nMinHeight = 0, _nMaxHeight = 0; + GetDataMaxRect(listRecords_, _nMinWidth, _nMaxWidth, _nMinHeight, _nMaxHeight); + int _nStart = 0; + int _nEnd = 0; + double _nDiv = _nMinWidth / m_nMaxWidth; + _nStart = (int)floor(_nDiv); + _nDiv = _nMaxWidth / m_nMaxWidth; + _nEnd = (int)floor(_nDiv); + for (int _i = _nStart; _i <= _nEnd; _i++) + { + FillCutOffDataGDI2D(listRecords_, -_i * m_nMaxWidth); + } + } + else + FillCutOffDataGDI2D(listRecords_, 0); + // 同样也要处理辅助面。 + TransparentBlt(m_pBmpDC->m_hDC, 0, 0, (int)(m_nAuxiliaryWidth), (int)(m_nBmpHeight), + m_pBmpDC->m_hDC, (int)m_nBmpWidth, 0, + (int)(m_nAuxiliaryWidth), (int)(m_nBmpHeight), + RGB(255, 255, 255)); + BitmapToOpenGLData(m_pBmpDC, m_pBmpTexture, (int)m_nBmpWidth, (int)m_nBmpHeight); + CreateTextures((int)m_nBmpWidth, (int)m_nBmpHeight); +} + +void CNce3DViewImp_V1::Point2DToPoint3D(IN OUT Polygon3DListGroup& PolygonSrc_) +{ + int _nSize = static_cast(PolygonSrc_.size()); + ASSERT(_nSize < static_cast(m_vectorTransform3D.size())); + for (int _i = 0; _i < _nSize; _i++) + { + Polygon3DList& _tempPolygonList = PolygonSrc_[_i]; + int _nPolygonSize = static_cast(_tempPolygonList.size()); + for (int _j = 0; _j < _nPolygonSize; _j++) + { + Polygon3D& _Polygon = _tempPolygonList[_j]; + int _nPointSize = static_cast(_Polygon.size()); + for (int _k = 0; _k < _nPointSize; _k++) + { + _Polygon[_k] = m_vectorTransform3D[_i].Point2DToPoint3D(_Polygon[_k]); + } + } + } +} + +void CNce3DViewImp_V1::Point2DToPoint3D(IN Polyline3DList& PointsSrc_,OUT Polyline3DList& PointsDst_) +{ + int _nSize = static_cast(PointsSrc_.size()); + int _nTransformSize = static_cast(m_vectorTransform3D.size()); + for (int _i = 0; _i < _nSize; _i++) + { + Line3DItem& _ptItem = PointsSrc_[_i]; + Line3DItem _newPtItem; + _newPtItem.clrPenColor = _ptItem.clrPenColor; + ASSERT(_ptItem.vectorLines.size() == 1); + Vector4& _pt = _ptItem.vectorLines[0]; + for (int _j = 0; _j < _nTransformSize; _j++) + { + if (m_vectorTransform3D[_j].Contain(_pt)) + { + _newPtItem.vectorLines.push_back(m_vectorTransform3D[_j].Point2DToPoint3D(_pt)); + break; + } + } + if (_newPtItem.vectorLines.size() > 0) + { + PointsDst_.push_back(_newPtItem); + } + } +} + +void CNce3DViewImp_V1::SetCutOffData_GPC(Polyline2DList& listRecords_) +{ + ASSERT(m_vectorTransform3D.size() % 5 == 0); + m_vectorCutData3D.clear(); + m_vectorCutData3D.resize(m_vectorTransform3D.size() / 5 * 4); + if (m_nTubeType == CircularTube) + { + g_gpcConvertHelper.ConvertCutOffArea(listRecords_, m_vectorCutData3D, GPCConvertHelper::Expand_All); + } + else if(m_nTubeType == QuadTube) + { + g_gpcConvertHelper.ConvertCutOffArea(listRecords_, m_vectorCutData3D, GPCConvertHelper::Expand_4V4); + } + else + g_gpcConvertHelper.ConvertCutOffArea(listRecords_, m_vectorCutData3D, GPCConvertHelper::Expand_One); + Point2DToPoint3D(m_vectorCutData3D); +} + +void CNce3DViewImp_V1::SetData(DrawDataType_t nType_, Polyline2DList& listRecords_) +{ + ASSERT(nType_ ==DDT_TRACK || nType_ == DDT_CADOBJ || nType_ == DDT_CUTOFF); + ASSERT(m_pBmpTexture !=NULL && m_pBmpDC != NULL); + if (m_pBmpTexture ==NULL || m_pBmpDC == NULL) + return; + + Polyline2DList *_plistCalculateRevise = &listRecords_; + Polyline3DList _newPolyline3DList; + Polyline3DList _newAllPlaneList; + Polyline3DList _newPointList; + for (Polyline2DList::iterator _it = _plistCalculateRevise->begin(); _it != _plistCalculateRevise->end(); _it++) + { + CalculatePolyline2D(_it->PolylineNode, _it->clrPenColor, _newPolyline3DList, _newPointList); + } + + // 圆管的无限扩展面的处理 + if (m_nTubeType == CircularTube) + { + TransformForAllPlane2D(_newPolyline3DList, _newAllPlaneList); + } + else if (m_nTubeType == QuadTube) + { + TransformForPlane4V4(_newPolyline3DList, _newAllPlaneList); + //TransformForAllPlane2D(_newPolyline3DList, _newAllPlaneList); + } + else + { + _newAllPlaneList = _newPolyline3DList; + } + + if (nType_ == DDT_CADOBJ) + { + m_vectorBaseDatas.clear(); + m_vectorBasePoints.clear(); + m_nCadMinWidth = 0; + m_nCadMaxWidth = 0; + m_nCadMinHeight = 0; + m_nCadMaxHeight = 0; + // 转化点信息 + Point2DToPoint3D(_newPointList, m_vectorBasePoints); + GetDataMaxRect(listRecords_, m_nCadMinWidth, m_nCadMaxWidth, m_nCadMinHeight, m_nCadMaxHeight); + // 转化线信息 + TransformLine2DTOLine3D(_newAllPlaneList, m_vectorBaseDatas); + } + else if (nType_ == DDT_TRACK) + { + m_vectorAddDatas.clear(); + TransformLine2DTOLine3D(_newAllPlaneList, m_vectorAddDatas); + } + else if (nType_ == DDT_CUTOFF) + { + //SetCutOffData(listRecords_); + SetCutOffData_GPC(listRecords_); + } + else + { + ASSERT(false); + } +} + +void CNce3DViewImp_V1::DrawPolylineGDI2D(Polyline3DList& parentList_) +{ + int _nSize = (int)parentList_.size(); + for (int _i = 0; _i< _nSize; _i++) + { + Line3DItem& _lineItem = parentList_[_i]; + int _nLineSize = (int)_lineItem.vectorLines.size(); + CPen _pen(PS_SOLID, 1, _lineItem.clrPenColor); + m_pBmpDC->SelectObject(_pen); + for(int _j = 0;_j < _nLineSize; _j = _j + 2) + { + Vector4 _startPoint = ReviseCoord(_lineItem.vectorLines[_j]); + Vector4 _endPoint = ReviseCoord(_lineItem.vectorLines[_j + 1]); + m_pBmpDC->MoveTo((int)_startPoint.x, (int)_startPoint.y); + m_pBmpDC->LineTo((int)_endPoint.x, (int)_endPoint.y); + } + } +} + +// 转化方管 扩展面两边各4个面 +void CNce3DViewImp_V1::TransformForPlane4V4(Polyline3DList& SrcList_, Polyline3DList& DstList_) +{ + int _nSize = (int)SrcList_.size(); + for (int _i = 0; _i< _nSize; _i++) + { + Line3DItem& _lineItem = SrcList_[_i]; + Line3DItem _newItem; + _newItem.clrPenColor = _lineItem.clrPenColor; + int _nLineSize = (int)_lineItem.vectorLines.size(); + for(int _j = 0; _j < _nLineSize; _j = _j + 2) + { + Vector4 _startPoint = _lineItem.vectorLines[_j]; + Vector4 _endPoint = _lineItem.vectorLines[_j + 1]; + if (_startPoint.x <= _endPoint.x) + TransformLine4V4(_startPoint, _endPoint, _newItem.vectorLines); + else + TransformLine4V4(_endPoint, _startPoint, _newItem.vectorLines); + } + DstList_.push_back(_newItem); + } +} + +void CNce3DViewImp_V1::TransformLine4V4(Vector4& ptStart_, Vector4& ptEnd_, std::vector& DstList_) +{ + double _nWidth = m_nMaxWidth; + double _nHeight = m_nTubeHeight; + double _nStart = ptStart_.x; + double _nEnd = ptEnd_.x; + double _nRatio = 0; + int _nRatioType = 0; + double _nStep = 0; + + Vector4 _newStartPoint(ptStart_.x, ptStart_.y); + Vector4 _newEndPoint(ptEnd_.x, ptEnd_.y); + if (!DOUBLE_EQU_ZERO(_newEndPoint.x - _newStartPoint.x)) + { + _nRatio = (_newEndPoint.y - _newStartPoint.y) / (_newEndPoint.x - _newStartPoint.x); + _nRatioType = 1; + } + + // 不在44范围内 + if ((_nStart > 2 * _nWidth) || (_nEnd < -_nWidth)) + return; + // 前期处理 把它移到范围内。 + // 第一个点是否在范围内。 + _nStep = 0; + if (_nStart <= -_nWidth) + { + _nStep = -_nWidth - _nStart; + } + Vector4 _itemStart = _newStartPoint; + if (_nStep == 0) // 在其中没有截取 + { + _itemStart.x = _newStartPoint.x; + _itemStart.y = _newStartPoint.y; + } + else + { + _itemStart.x = _newStartPoint.x + _nStep; + _itemStart.y = (_nRatioType == 1) ? (_itemStart.y + _nStep * _nRatio) : _itemStart.y; + } + + // 第二个点是否在范围内。 + _nStep = 0; + if (_nEnd >= 2 * _nWidth) + { + _nStep = 2 * _nWidth - _nStart; + } + Vector4 _itemEnd; + if (_nStep == 0) // 在其中没有截取 + { + _itemEnd.x = _newEndPoint.x; + _itemEnd.y = _newEndPoint.y; + } + else + { + _itemEnd.x = _newStartPoint.x + _nStep; + _itemEnd.y = (_nRatioType == 1) ? (_newStartPoint.y + _nStep * _nRatio) : _newStartPoint.y; + } + + TransformLine2D(_itemStart, _itemEnd, DstList_); +} + +// 用来处理辅助面很多的情况 ---- 彭朋 2016-12-01 +void CNce3DViewImp_V1::TransformForAllPlane2D(Polyline3DList& SrcList_, Polyline3DList& DstList_) +{ + int _nSize = (int)SrcList_.size(); + for (int _i = 0; _i< _nSize; _i++) + { + Line3DItem& _lineItem = SrcList_[_i]; + Line3DItem _newItem; + _newItem.clrPenColor = _lineItem.clrPenColor; + int _nLineSize = (int)_lineItem.vectorLines.size(); + for(int _j = 0; _j < _nLineSize; _j = _j + 2) + { + Vector4 _startPoint = _lineItem.vectorLines[_j]; + Vector4 _endPoint = _lineItem.vectorLines[_j + 1]; + if (_startPoint.x <= _endPoint.x) + TransformLine2D(_startPoint, _endPoint, _newItem.vectorLines); + else + TransformLine2D(_endPoint, _startPoint, _newItem.vectorLines); + } + DstList_.push_back(_newItem); + } +} + +// 把所有的线都转到一个单位平面内,一个圆的周长为一个单位平面。 +void CNce3DViewImp_V1::TransformLine2D(Vector4& ptStart_, Vector4& ptEnd_, std::vector& DstList_) +{ + double _nWidth = m_nMaxWidth; + double _nHeight = m_nTubeHeight; + double _nStart = ptStart_.x; + double _nEnd = ptEnd_.x; + double _nRatio = 0; + int _nRatioType = 0; + double _nStep = 0; + // 前期处理 把它移到范围内。 + if (_nStart < 0) + { + double _nMod = fmod(_nStart, _nWidth); + if (_nMod < 0) + { + _nMod = _nMod + _nWidth; + } + _nStep = _nMod - _nStart; + } + + if (_nStart >= _nWidth) + { + double _nMod = fmod(_nStart, _nWidth); + if (_nMod >= _nWidth) + { + _nMod = _nMod - _nWidth; + } + _nStep = _nMod - _nStart; + } + + Vector4 _newStartPoint(ptStart_.x + _nStep, ptStart_.y); + Vector4 _newEndPoint(ptEnd_.x + _nStep, ptEnd_.y); + _nStart = _newStartPoint.x; + _nEnd = _newEndPoint.x; + _nRatio = 0; + _nRatioType = 0; + if (!DOUBLE_EQU_ZERO(_newEndPoint.x - _newStartPoint.x)) + { + _nRatio = (_newEndPoint.y - _newStartPoint.y) / (_newEndPoint.x - _newStartPoint.x); + _nRatioType = 1; + } + + // 都转成宽度范围之内。 + if (_nEnd <= _nWidth) + { + DstList_.push_back(_newStartPoint); + DstList_.push_back(_newEndPoint); + } + else + { + Vector4 _itemStart = _newStartPoint; + Vector4 _itemEnd; + _itemEnd.x = _nWidth; + _itemEnd.y = (_nRatioType == 1) ? (_itemStart.y + (_nWidth - _itemStart.x) * _nRatio) : _itemStart.y; + DstList_.push_back(_itemStart); + DstList_.push_back(_itemEnd); + TransformLine2D(_itemEnd, _newEndPoint, DstList_); + } +} + +void CNce3DViewImp_V1::CalculateCutLine(Vector4& ptStart_, Vector4& ptEnd_, std::vector& DstList_) +{ + int _nTransformSize = (int)m_vectorTransform3D.size(); + Vector4 _startPoint = ptStart_; + Vector4 _endPoint = ptEnd_; + for (int _i = 0; _i< _nTransformSize; _i++) + { + double _nStart = ptStart_.x; + double _nEnd = ptEnd_.x; + double _nRatio = 0; + int _nRatioType = 0; + if (!DOUBLE_EQU_ZERO(ptEnd_.x - ptStart_.x)) + { + _nRatio = (ptEnd_.y - ptStart_.y) / (ptEnd_.x - ptStart_.x); + _nRatioType = 1; + } + + TransformData3D _nDate = m_vectorTransform3D[_i]; + Vector4 _itemStart; + Vector4 _itemEnd; + if (_nDate.Contain(_startPoint.x) == 0) //在其中 + { + _itemStart.x = _startPoint.x; + _itemStart.y = _startPoint.y; + int _nRetContain = _nDate.Contain(_endPoint.x); + if (_nRetContain == 0) // 右边也在其中 + { + _itemEnd.x = _endPoint.x; + _itemEnd.y = _endPoint.y; + if (_itemStart.y > m_nTubeHeight && _itemEnd.y > m_nTubeHeight) + { + return; + } + + Vector4 _pt3D = _nDate.Point2DToPoint3D(_itemStart); + DstList_.push_back(_pt3D); + _pt3D = _nDate.Point2DToPoint3D(_itemEnd); + DstList_.push_back(_pt3D); + return; + } + else + { + _itemEnd.x = _nDate.nEndX2D; + _itemEnd.y = (_nRatioType == 1) ? (_startPoint.y + (_nDate.nEndX2D - _startPoint.x) * _nRatio) : _startPoint.y; + + if (_itemStart.y > m_nTubeHeight && _itemEnd.y > m_nTubeHeight) + { + _startPoint = _itemEnd; + continue; + } + Vector4 _pt3D = _nDate.Point2DToPoint3D(_itemStart); + DstList_.push_back(_pt3D); + _pt3D = _nDate.Point2DToPoint3D(_itemEnd); + DstList_.push_back(_pt3D); + _startPoint = _itemEnd; + } + } + else if (_nDate.Contain(_startPoint.x) == -2) // 右边出了 + { + continue; + } + else // 左边超出了 + { + if (_nDate.Contain(_endPoint.x) == -1) // 都出左边了 + return; + _itemEnd.x = _nDate.nStartX2D; + _itemEnd.y = (_nRatioType == 1) ? (_startPoint.y + (_nDate.nStartX2D - _startPoint.x) * _nRatio) : _startPoint.y; + _startPoint = _itemEnd; + _i--; + } + } +} + +void CNce3DViewImp_V1::TransformLine2DTOLine3D(Polyline3DList& SrcList_, Polyline3DList& DstList_) +{ + int _nSize = (int)SrcList_.size(); + for (int _i = 0; _i< _nSize; _i++) + { + Line3DItem& _lineItem = SrcList_[_i]; + Line3DItem _newItem; + _newItem.clrPenColor = _lineItem.clrPenColor; + int _nLineSize = (int)_lineItem.vectorLines.size(); + for(int _j = 0; _j < _nLineSize; _j = _j + 2) + { + Vector4 _startPoint = _lineItem.vectorLines[_j]; + Vector4 _endPoint = _lineItem.vectorLines[_j + 1]; + if (_startPoint.x <= _endPoint.x) + CalculateCutLine(_startPoint, _endPoint, _newItem.vectorLines); + else + CalculateCutLine(_endPoint, _startPoint, _newItem.vectorLines); + } + DstList_.push_back(_newItem); + } +} + +void CNce3DViewImp_V1::CalculatePolyline2D(const Polyline2D& polylineItem_, COLORREF penColor_, Polyline3DList& lineList_, Polyline3DList& pointList_) +{ + size_t _nSize = polylineItem_.vectorNodes.size(); + Line3DItem _lineItem; + _lineItem.clrPenColor = penColor_; + if (polylineItem_.vectorNodes.size() == 0) // 一个点。 + { + Vector4 _startPoint(polylineItem_.nStartX, polylineItem_.nStartY); + _lineItem.vectorLines.push_back(_startPoint); + pointList_.push_back(_lineItem); + return; + } + else + { + Vector4 _startPoint(polylineItem_.nStartX, polylineItem_.nStartY); + Vector4 _vecStart(polylineItem_.nStartX, - polylineItem_.nStartY); + for (size_t _i = 0; _i < _nSize; _i++) + { + NODE2D _segment = polylineItem_.vectorNodes[_i]; + if (_segment.nBulge == 0.0) + { + Vector4 _endPoint(polylineItem_.vectorNodes[_i].nEndX, polylineItem_.vectorNodes[_i].nEndY); + _lineItem.vectorLines.push_back(_startPoint); + _lineItem.vectorLines.push_back(_endPoint); + _startPoint = Vector4(_endPoint.x, _endPoint.y); + } + else + { + Vector4 _vecEnd(_segment.nEndX, -_segment.nEndY); + Vector4 _ptCenter(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + double _nRadius = c_nINVALID_DOUBLE; + double _nStartAngle = c_nINVALID_DOUBLE; + double _nSweptAngle = c_nINVALID_DOUBLE; + + SolveArc(_vecStart, _vecEnd, _segment.nBulge, + &_ptCenter, &_nRadius, &_nStartAngle, &_nSweptAngle); + ASSERT(IsValidDouble(_ptCenter.x) && IsValidDouble(_ptCenter.y)); + ASSERT(IsValidDouble(_nRadius) && DOUBLE_GREAT_ZERO(_nRadius)); + ASSERT(IsValidDouble(_nStartAngle) && 0. <= _nStartAngle && _nStartAngle < 2. * M_PI); + ASSERT(IsValidDouble(_nSweptAngle) && -2. * M_PI <= _nSweptAngle && DOUBLE_LESS(_nSweptAngle, 2. * M_PI)); + + // 取段步长为2个象素,角步长在 PIE/180 ~ PIE/3 之间,对圆弧进行折线 + // 拟合,用画折线的办法代替画圆弧。在3D可能要加点数据。 + int _nN = Round((2. * abs(_nSweptAngle) * _nRadius) / 2.f); + int _nMinN = max(3, Round(3. * abs(_nSweptAngle) / M_PI)); + int _nMaxN = max(3, Round(180. * abs(_nSweptAngle) / M_PI)); + _nN = min(max(_nMinN, _nN), _nMaxN); + double _nDeltaAngle = _nSweptAngle / (double)_nN; + for (int _i = 1; _i <= _nN; _i++) + { + double _nAngle = _nStartAngle + (double)_i * _nDeltaAngle; + Vector4 _pt(_ptCenter.x + _nRadius * cos(_nAngle), _ptCenter.y + _nRadius * sin(_nAngle)); + //m_pBmpDC->LineTo((int)_pt.x, -(int)_pt.y); + Vector4 _endPoint(_pt.x, - _pt.y); + _lineItem.vectorLines.push_back(_startPoint); + _lineItem.vectorLines.push_back(_endPoint); + _startPoint = Vector4(_endPoint.x, _endPoint.y); + } + } + _vecStart = Vector4(_segment.nEndX, -_segment.nEndY); + } + } + lineList_.push_back(_lineItem); +} + +void CNce3DViewImp_V1::DrawPolyline2D(const Polyline2D& polylineItem_) +{ + size_t _nSize = polylineItem_.vectorNodes.size(); + if (polylineItem_.vectorNodes.size() == 0) // 一个点。 + { + m_pBmpDC->Ellipse((int)polylineItem_.nStartX, (int)polylineItem_.nStartY, (int)polylineItem_.nStartX + 1, (int)polylineItem_.nStartY + 1); + } + else + { + m_pBmpDC->MoveTo((int)polylineItem_.nStartX, (int)polylineItem_.nStartY); + Vector4 _vecStart(polylineItem_.nStartX, -polylineItem_.nStartY); + for (size_t _i = 0; _i < _nSize; _i++) + { + NODE2D _segment = polylineItem_.vectorNodes[_i]; + if (_segment.nBulge == 0.0) + { + m_pBmpDC->LineTo((int)polylineItem_.vectorNodes[_i].nEndX, (int)polylineItem_.vectorNodes[_i].nEndY); + } + else + { + Vector4 _vecEnd(_segment.nEndX, -_segment.nEndY); + Vector4 _ptCenter(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + double _nRadius = c_nINVALID_DOUBLE; + double _nStartAngle = c_nINVALID_DOUBLE; + double _nSweptAngle = c_nINVALID_DOUBLE; + + SolveArc(_vecStart, _vecEnd, _segment.nBulge, + &_ptCenter, &_nRadius, &_nStartAngle, &_nSweptAngle); + ASSERT(IsValidDouble(_ptCenter.x) && IsValidDouble(_ptCenter.y)); + ASSERT(IsValidDouble(_nRadius) && DOUBLE_GREAT_ZERO(_nRadius)); + ASSERT(IsValidDouble(_nStartAngle) && 0. <= _nStartAngle && _nStartAngle < 2. * M_PI); + ASSERT(IsValidDouble(_nSweptAngle) && -2. * M_PI <= _nSweptAngle && DOUBLE_LESS(_nSweptAngle, 2. * M_PI)); + + // 取段步长为2个象素,角步长在 PIE/180 ~ PIE/3 之间,对圆弧进行折线 + // 拟合,用画折线的办法代替画圆弧。 + int _nN = Round((2. * abs(_nSweptAngle) * _nRadius) / 2.f); + int _nMinN = max(3, Round(3. * abs(_nSweptAngle) / M_PI)); + int _nMaxN = max(3, Round(180. * abs(_nSweptAngle) / M_PI)); + _nN = min(max(_nMinN, _nN), _nMaxN); + double _nDeltaAngle = _nSweptAngle / (double)_nN; + for (int _i = 1; _i <= _nN; _i++) + { + double _nAngle = _nStartAngle + (double)_i * _nDeltaAngle; + Vector4 _pt(_ptCenter.x + _nRadius * cos(_nAngle), _ptCenter.y + _nRadius * sin(_nAngle)); + m_pBmpDC->LineTo((int)_pt.x, -(int)_pt.y); + } + } + _vecStart = Vector4(_segment.nEndX, -_segment.nEndY); + } + } +} + +void CNce3DViewImp_V1::DrawPolyline3D(Polyline3DList& listLines3D_, float nLineWidth_) +{ + glDisable(GL_LIGHT0); + glDisable(GL_LIGHTING); + glLineWidth(nLineWidth_); + int _nSize = (int)listLines3D_.size(); + glBegin(GL_LINES); + for (int _i = 0; _i< _nSize; _i++) + { + Line3DItem& _lineItem = listLines3D_[_i]; + glColor4ub(GetRValue(_lineItem.clrPenColor), GetGValue(_lineItem.clrPenColor), + GetBValue(_lineItem.clrPenColor), 255); + int _nLineSize = (int)_lineItem.vectorLines.size(); + for (int _j = 0; _j < _nLineSize; _j++) + { + Vector4 _pt = _lineItem.vectorLines[_j]; + glVertex4d(_pt.x, _pt.y, _pt.z, 1.0); + } + } + glEnd(); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHTING); +} + +void CNce3DViewImp_V1::DrawPoint3D(Polyline3DList& listPoints3D_, float nPointSize_) +{ + glDisable(GL_LIGHT0); + glDisable(GL_LIGHTING); + glPointSize(nPointSize_); + int _nSize = (int)listPoints3D_.size(); + glBegin(GL_POINTS); + for (int _i = 0; _i< _nSize; _i++) + { + Line3DItem& _lineItem = listPoints3D_[_i]; + glColor4ub(GetRValue(_lineItem.clrPenColor), GetGValue(_lineItem.clrPenColor), + GetBValue(_lineItem.clrPenColor), 255); + int _nPointSize = (int)_lineItem.vectorLines.size(); + for (int _j = 0; _j < _nPointSize; _j++) + { + Vector4 _pt = _lineItem.vectorLines[_j]; + glVertex4d(_pt.x, _pt.y, _pt.z, 1.0); + } + } + glEnd(); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHTING); +} + +void CNce3DViewImp_V1::DrawXYZ() +{ + double _nzoom = 2000000; + glLineWidth(1); + glColor4ub(255, 255, 255, 255); + glBegin(GL_LINES); + glVertex4d(1 * _nzoom, 0, 0, 1.0); + glVertex4d(-1 * _nzoom, 0, 0, 1.0); + glColor4ub(255, 0, 0, 255); + glVertex4d(0, 1 * _nzoom, 0, 1.0); + glVertex4d(0, -1 * _nzoom, 0, 1.0); + glColor4ub(255, 0, 255, 255); + glVertex4d(0, 0, 1 * _nzoom, 1.0); + glVertex4d(0, 0, -1 * _nzoom, 1.0); + glEnd(); +} + +// 处理辅助面的问题 加1/4 还是两边各加4个面。 +void CNce3DViewImp_V1::CalculateAuxiliary() +{ + // 方管两边各加4个面 + //if (m_nTubeType == RoundRectTube) + //{ + + // return; + //} + // 处理第五个面的问题。 + int _nSize = (int)m_vectorTransform3D.size(); + int _nAuxiSize = _nSize / 4; + //先把基本的4个面放进去。 + g_gpcConvertHelper.Initialize(m_vectorTransform3D, m_nMaxWidth); + // 第五个面和第一个面相同 + for (int _i = 0; _i< _nAuxiSize; _i++) + { + TransformData3D _itemData = m_vectorTransform3D[_i]; + _itemData.nStartX2D += m_nMaxWidth; + _itemData.nEndX2D += m_nMaxWidth; + m_vectorTransform3D.push_back(_itemData); + } + + // 要镂空的对象数据 + m_vectorCutData3D.clear(); + m_vectorCutData3D.resize(_nSize); +} + +void CNce3DViewImp_V1::PushVector3D(Vector4 vecStart_, Vector4 vecEnd_, double nStartTexCood_, double nEndTexCood_) +{ + m_vectorTexs.push_back(Vector4(nStartTexCood_, 0)); + m_vectorTexs.push_back(Vector4(nStartTexCood_, 1)); + m_vectorTexs.push_back(Vector4(nEndTexCood_, 1)); + m_vectorTexs.push_back(Vector4(nEndTexCood_, 0)); + Vector4 _vecVTs[3]; + Vector4 _vecVt = vecStart_; + m_vectorVTs.push_back(_vecVt); + _vecVTs[0] = _vecVt; + _vecVt.y = -_vecVt.y; + m_vectorVTs.push_back(_vecVt); + _vecVTs[1] = _vecVt; + _vecVt = vecEnd_; + _vecVt.y = -_vecVt.y; + m_vectorVTs.push_back(_vecVt); + _vecVTs[2] = _vecVt; + _vecVt.y = -_vecVt.y; + m_vectorVTs.push_back(_vecVt); + m_vectorNormals.push_back(GetNormalVector(_vecVTs[0], _vecVTs[1], _vecVTs[2])); + + // 转换数据 + TransformData3D _tData3D; + _tData3D.nStartX2D = nStartTexCood_ * m_nMaxWidth; + _tData3D.nEndX2D = nEndTexCood_ * m_nMaxWidth; + _tData3D.nX3D = vecStart_.x; + _tData3D.nZ3D = vecStart_.z; + double _nStep2D = _tData3D.nEndX2D - _tData3D.nStartX2D; + double _nStepX2D = vecEnd_.x - vecStart_.x; + double _nStepZ2D = vecEnd_.z - vecStart_.z; + if (DOUBLE_EQU_ZERO(_nStep2D)) + return; + _tData3D.nXRatio = _nStepX2D / _nStep2D; + _tData3D.nZRatio = _nStepZ2D / _nStep2D; + _tData3D.nY = m_nTubeHeight; + m_vectorTransform3D.push_back(_tData3D); +} + +void CNce3DViewImp_V1::Redraw() +{ + glClearColor(GLfloat(GetRValue(m_clrBackground)) / 255.0f, + GLfloat(GetGValue(m_clrBackground)) / 255.0f, GLfloat(GetBValue(m_clrBackground)) / 255.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + if (m_bMaterialLight) + { + glPushMatrix(); + glLoadIdentity(); + const static GLfloat _nLightPosition[] = {0.0f, 35.0f, 50.0f, 0.0f}; // 光源位置 + const static GLfloat _nSpotLightDirectin[] = {0.0f, 0.0f, -1.0f, 1.0f}; // 聚光灯的方向 + glLightfv(GL_LIGHT0, GL_POSITION, _nLightPosition); + glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, _nSpotLightDirectin); + glPopMatrix(); + } + + if (m_bDrawTube) + { + if (m_nTubeType == QuadTube) + _DrawQuadTube(); + else if (m_nTubeType == CircularTube) + _DrawCircularTube(); + else if (m_nTubeType == RoundRectTube) + _DrawQuadTube(); + else if (m_nTubeType == EllipseTube) + _DrawCircularTube(); + else + ASSERT(false); + } + DrawPoint3D(m_vectorBasePoints, 2); + glPushMatrix(); + glScaled(1.005, 1., 1.005); + DrawPolyline3D(m_vectorAddDatas, 3); + glPopMatrix(); + DrawPolyline3D(m_vectorBaseDatas, 2); + if (m_bShowCoordinate) + DrawXYZ(); + ::SwapBuffers(m_hDC); +} + +inline void VectorNormalize(Vector4& vec_) +{ + double _nNormalize = 1.0f; + _nNormalize =(double)sqrt(vec_.x * vec_.x + vec_.y * vec_.y + vec_.z * vec_.z); + if (IsZero(_nNormalize)) + { + return; + } + _nNormalize = 1 / _nNormalize; + vec_.x *= _nNormalize; + vec_.y *= _nNormalize; + vec_.z *= _nNormalize; +} + +inline Vector4 VectorCross(const Vector4 &vec1_, const Vector4 &vec2_) +{ + Vector4 _vecRet; + _vecRet.x = vec1_.y * vec2_.z - vec2_.y * vec1_.z; + _vecRet.y = vec1_.z * vec2_.x - vec1_.x * vec2_.z; + _vecRet.z = vec1_.x * vec2_.y - vec2_.x * vec1_.y; + return _vecRet; +} + +inline double VectortLength(const Vector4 &vec_) +{ + double _nValue = vec_.x * vec_.x + + vec_.y * vec_.y + + vec_.z * vec_.z; + return sqrt(_nValue); +} + +inline Vector4 VectorSub(const Vector4 &vec1_, const Vector4 &vec2_) +{ + Vector4 _vecRet; + _vecRet.x = vec1_.x - vec2_.x; + _vecRet.y = vec1_.y - vec2_.y; + _vecRet.z = vec1_.z - vec2_.z; + return _vecRet; +} + +inline Vector4 VectorAdd(const Vector4 &vec1_, const Vector4 &vec2_) +{ + Vector4 _vecRet; + _vecRet.x = vec1_.x + vec2_.x; + _vecRet.y = vec1_.y + vec2_.y; + _vecRet.z = vec1_.z + vec2_.z; + return _vecRet; +} + +inline Vector4 VectorMultiply(const Vector4 &vec1_, const double nNum_) +{ + Vector4 _vecRet; + _vecRet.x = vec1_.x * nNum_; + _vecRet.y = vec1_.y * nNum_; + _vecRet.z = vec1_.z * nNum_; + return _vecRet; +} + +Vector4 GetNormalVector(const Vector4 &vec1_, const Vector4 &vec2_, const Vector4 &vec3_) +{ + Vector4 _vec1 = VectorSub(vec1_, vec2_); + Vector4 _vec2 = VectorSub(vec3_, vec2_); + Vector4 _vecRet = VectorCross(_vec1, _vec2); + VectorNormalize(_vecRet); + return _vecRet; +} + +void SolveArc(IN Vector4 ptStart_, + IN Vector4 ptEnd_, + IN double nBulge_, + OUT Vector4* pptCenter_, + OUT double* pnRadius_, + OUT double* pnStartAngle_, + OUT double* pnSweptAngle_) +{ + // 参数检查 + if (DOUBLE_LE_ZERO(VectortLength(VectorSub(ptEnd_, ptStart_))) || DOUBLE_EQU_ZERO(nBulge_)) + { + ASSERT(FALSE); + return; + } + + if (!pptCenter_ && !pnRadius_ && !pnStartAngle_ && !pnSweptAngle_) + return; + + // 弦及弦长 + Vector4 _vecChord =VectorSub(ptEnd_, ptStart_); + double _nChordLen = VectortLength(_vecChord); + ASSERT(DOUBLE_GREAT_ZERO(_nChordLen)); + + // 中心角,即展开角 + double _nAlpha = 4. * atan(nBulge_); + ASSERT(DOUBLE_NOT_ZERO(_nAlpha)); + ASSERT(_nAlpha < 2. * M_PI && _nAlpha > -2. * M_PI); + if (pnSweptAngle_) + *pnSweptAngle_ = _nAlpha; + + // 半径 + double _nRadius = abs((_nChordLen * 0.5) / sin(_nAlpha * 0.5)); + if (pnRadius_) + *pnRadius_ = _nRadius; + + // 圆心 + double _nCenterToChord = abs(_nRadius * cos(_nAlpha * 0.5)); + Vector4 _ptMidChord = VectorMultiply(VectorAdd(ptStart_, ptEnd_), 0.5); + Vector4 _vecMidChordToCenter(-1. * _vecChord.y, _vecChord.x); + VectorNormalize(_vecMidChordToCenter); + _vecMidChordToCenter = VectorMultiply(_vecMidChordToCenter, _nCenterToChord); + if (nBulge_ < 0.0 && nBulge_ > -1.0 || + nBulge_ > 0.0 && nBulge_ > 1.0) + { + _vecMidChordToCenter = VectorMultiply(_vecMidChordToCenter, -1.); + } + + Vector4 _ptCenter = VectorAdd(_ptMidChord, _vecMidChordToCenter); + if (pptCenter_) + *pptCenter_ = _ptCenter; + + // 起始角 + double _nStartAngle = atan2(ptStart_.y - _ptCenter.y, ptStart_.x - _ptCenter.x); + ASSERT(IsValidDouble(_nStartAngle) && _nStartAngle <= M_PI && _nStartAngle >= -1.0 * M_PI); + _nStartAngle += 2.0 * M_PI; + if (_nStartAngle >= 2.0 * M_PI) + _nStartAngle -= 2.0 * M_PI; + + ASSERT(_nStartAngle >= 0.0 && _nStartAngle < 2.0 * M_PI); + if (pnStartAngle_) + *pnStartAngle_ = _nStartAngle; +} + +Vector4 UnGLPick(Vector4& vt_) +{ + Vector4 _vtRet; + double _nWinX = 0; + double _nWinY = 0; + double _nWinZ = 0; + int _nViewport[4]; + double _nModelMatrix[16], _nProjMatrix[16]; + glReadBuffer(GL_BACK); + glGetIntegerv(GL_VIEWPORT, _nViewport); + glGetDoublev(GL_MODELVIEW_MATRIX, _nModelMatrix); + glGetDoublev(GL_PROJECTION_MATRIX, _nProjMatrix); + gluProject(vt_.x, vt_.y, vt_.z, _nModelMatrix, _nProjMatrix, _nViewport, &_nWinX, &_nWinY, &_nWinZ); + _vtRet.x = _nWinX; + _vtRet.y = _nViewport[3] - _nWinY; //左上角为坐标原点 - 修正值 + return _vtRet; +} + +// 屏幕上的坐标 pick top point ---- 彭朋 2016-11-07 +Vector4 GLPick(Vector4& vt_) +{ + int _nViewport[4]; + double _nModelMatrix[16], _nProjMatrix[16]; + Vector4 _vtRet; + glReadBuffer(GL_BACK); + glGetIntegerv(GL_VIEWPORT, _nViewport); + glGetDoublev(GL_MODELVIEW_MATRIX, _nModelMatrix); + glGetDoublev(GL_PROJECTION_MATRIX, _nProjMatrix); + double _nGLX = 0, _nGLY = 0, _nGLZ = 0; + gluUnProject(vt_.x, _nViewport[3] - vt_.y, 0, _nModelMatrix, _nProjMatrix, _nViewport, &_nGLX, &_nGLY, &_nGLZ); + _vtRet = Vector4(_nGLX, _nGLY,_nGLZ,1); + return _vtRet; +} + +double GetEllipsePerimeter(double nLongRadius_,double nShortRadius_) +{ + double _nEccentricity = sqrt(pow(nLongRadius_, 2) - pow(nShortRadius_, 2)) / nLongRadius_; + ASSERT((nLongRadius_ >= nShortRadius_) && DOUBLE_GREAT_ZERO(nShortRadius_)); + ASSERT((_nEccentricity >= 0.) && (_nEccentricity <= 1.0)); + if ((_nEccentricity < 0.) || (_nEccentricity > 1.0)) + { + ASSERT(false); + return 0.; + } + + // 第二类完全椭圆积分,从Matlab的ellipke.m中得到 + double m = _nEccentricity * _nEccentricity; + double a0 = 1.0; + double b0 = sqrt(1.0 - m); + double s0 = m; + int i1 = 0; + double a1 = 1.0; + double mm = 1.0; + while (mm > c_nTolerance) + { + a1 = (a0 + b0) * 0.5; + double b1 = sqrt(a0 * b0); + double c1 = (a0 - b0) * 0.5; + double w1 = (2 << i1++) * (c1 * c1); + mm = w1; + s0 += w1; + a0 = a1; + b0 = b1; + } + + double k = M_PI / (2.0 * a1); + double e = k * (1.0 - s0 * 0.5); + + // 椭圆周长 + double _nPerimeter = 4.0 * nLongRadius_ * e; + return _nPerimeter; +} + +int TransformData3D::Contain(double x) +{ + if (x < nStartX2D) //左边超出 + return -1; + else if(x > nEndX2D) // 右边超出 + return -2; + return 0; +} + +bool TransformData3D::Contain(Vector4& pt_) +{ + if (pt_.x >= nStartX2D && pt_.x <= nEndX2D && pt_.y >= 0 && pt_.y <= nY) + return true; + return false; +} + +Vector4 TransformData3D::Point2DToPoint3D(Vector4& pt_) +{ + Vector4 _retPt3D; + double _nStep = (pt_.x - nStartX2D); + _retPt3D.x = nX3D + nXRatio * _nStep; + _retPt3D.z = nZ3D + nZRatio * _nStep; + _retPt3D.y = nY * 0.5 - pt_.y; + if (_retPt3D.y > nY * 0.5) + _retPt3D.y = nY * 0.5; + if (_retPt3D.y < -nY * 0.5) + _retPt3D.y = -nY * 0.5; + return _retPt3D; +} + +// 转化成用于计算的多边形 ---- 彭朋 2016-12-19 +void GPCConvertHelper::_convertPolygon(IN const Polyline2DList& listPolylines_, OUT std_polygon_list& listPolygons_) +{ + for (Polyline2DList::const_iterator _it = listPolylines_.begin(); _it != listPolylines_.end(); _it++) + { + const Polyline2D& _polylineItem = _it->PolylineNode; + int _nSize = (int)(_polylineItem.vectorNodes.size()); + std_vertex_list _gpcPolygon; + gpc_vertex _gpcPoint; + _gpcPoint.x = _polylineItem.nStartX; + _gpcPoint.y = _polylineItem.nStartY; + _gpcPolygon.push_back(_gpcPoint); + for (int _i = 0;_i < _nSize; _i++) + { + _gpcPoint.x = _polylineItem.vectorNodes[_i].nEndX; + _gpcPoint.y = _polylineItem.vectorNodes[_i].nEndY; + _gpcPolygon.push_back(_gpcPoint); + } + listPolygons_.push_back(_gpcPolygon); + } +} + +void GPCConvertHelper::_get_MinMax_width(IN std_vertex_list& polygon_, double& nMin_, double& nMax_) +{ + int _nSize = static_cast(polygon_.size()); + ASSERT(_nSize > 0); + nMax_ = nMin_ = polygon_[0].x; + for (int _i = 0; _i < _nSize; _i++) + { + nMax_ = max(polygon_[_i].x, nMax_); + nMin_ = min(polygon_[_i].x, nMin_); + } +} + +inline int GPCConvertHelper::_IsInArea(int id_, double& nMin_, double& nMax_) +{ + ASSERT(m_pRootAreaData); + ASSERT(id_ >= 0 && id_ < static_cast(m_pRootAreaData->size())); + TransformData3D& _Transform3DItem = (*m_pRootAreaData)[id_]; + if (_Transform3DItem.Contain(nMin_) == -2) //右边 + return 1; + if (_Transform3DItem.Contain(nMax_) == -1) //左边 + return 2; + return 0; +} + +void GPCConvertHelper::_set_offset_polygon(IN OUT std_vertex_list& polygonSrc_, double nOffset_) +{ + int _nSize = static_cast(polygonSrc_.size()); + for (int _i = 0; _i < _nSize; _i++) + { + polygonSrc_[_i].x = polygonSrc_[_i].x + nOffset_; + } +} + +// 转化成三角 opengl 只能识别凸多边形,把三角放到对应分割区域内 ---- 彭朋 2016-12-19 +void GPCConvertHelper::_gpc_convert_tristrip(IN std_vertex_list& polygon_, double nMin_, double nMax_, + OUT Polygon3DListGroup& listCutOffDatas_, ConvertType_t nConvertType_) +{ + ASSERT(m_vectorBaseArea.size() > 0); + ASSERT(listCutOffDatas_.size() == m_vectorBaseArea.size()); + ASSERT(nConvertType_ == Convert_All || nConvertType_ == Convert_Part1_4); + int _nSize = static_cast(m_vectorBaseArea.size()); + ASSERT(_nSize % 4 == 0); + if (nConvertType_ == Convert_Part1_4) + _nSize = _nSize / 4; + for (int _i = 0; _i < _nSize; _i++) + { + int _nRet = _IsInArea(_i, nMin_, nMax_); + if (_nRet == 1) // 右边 + continue; + if (_nRet == 2) // 左边 + break; + std_vertex_list& _item = m_vectorBaseArea[_i]; + gpc_vertex_list _gpc_src; + gpc_vertex_list _gpc_dst; + gpc_polygon _polygonSrc; + gpc_polygon _polygonDst; + gpc_tristrip _result_tristrip; + _gpc_src.num_vertices = static_cast(polygon_.size()); + _gpc_src.vertex = &polygon_[0]; + _polygonSrc.hole = NULL; + _polygonSrc.num_contours = 1; + _polygonSrc.contour = &_gpc_src; + _gpc_dst.num_vertices = static_cast(_item.size()); + _gpc_dst.vertex = &_item[0]; + _polygonDst.hole = NULL; + _polygonDst.num_contours = 1; + _polygonDst.contour = &_gpc_dst; + gpc_tristrip_clip(GPC_INT, &_polygonSrc, &_polygonDst, &_result_tristrip); + for (int _j = 0; _j < _result_tristrip.num_strips; _j++) + { + Polygon3D _newPolygon3D; + Vector4 _point3D; + for (int _k = 0; _k < _result_tristrip.strip[_j].num_vertices; _k++) + { + _point3D.x = _result_tristrip.strip[_j].vertex[_k].x; + _point3D.y = _result_tristrip.strip[_j].vertex[_k].y; + _newPolygon3D.push_back(_point3D); + } + // 放到相同的分区 + listCutOffDatas_[_i].push_back(_newPolygon3D); + } + gpc_free_tristrip(&_result_tristrip); + } +} + +// 把2维的数据转成3维 cut off 数据 ---- 彭朋 2016-12-16 +void GPCConvertHelper::ConvertCutOffArea(IN const Polyline2DList& listRecords_, OUT Polygon3DListGroup& listCutOffDatas_, ExpandType_t nExpandType_) +{ + ASSERT(listCutOffDatas_.size() == m_vectorBaseArea.size()); + ASSERT(nExpandType_ == Expand_One || nExpandType_ == Expand_All || nExpandType_ == Expand_4V4); + std_polygon_list _listPolygons; + _convertPolygon(listRecords_, _listPolygons); + int _nSize = static_cast(_listPolygons.size()); + for (int _i = 0; _i < _nSize; _i++) + { + double _nMinWidth = 0 , _nMaxWidth = 0; + _get_MinMax_width(_listPolygons[_i], _nMinWidth, _nMaxWidth); + if (nExpandType_ == Expand_One) // 有一个面 + { + _gpc_convert_tristrip(_listPolygons[_i], _nMinWidth, _nMaxWidth, listCutOffDatas_, Convert_All); + if (_nMaxWidth > m_nWidth) + { + _set_offset_polygon(_listPolygons[_i], -m_nWidth); + _gpc_convert_tristrip(_listPolygons[_i], _nMinWidth - m_nWidth, _nMaxWidth - m_nWidth, listCutOffDatas_, Convert_Part1_4); + } + } + else if(nExpandType_ == Expand_4V4) // 左边右边各4个面 + { + _set_offset_polygon(_listPolygons[_i], m_nWidth); + _gpc_convert_tristrip(_listPolygons[_i], _nMinWidth + m_nWidth, _nMaxWidth + m_nWidth, listCutOffDatas_, Convert_All); + + _set_offset_polygon(_listPolygons[_i], -m_nWidth); + _gpc_convert_tristrip(_listPolygons[_i], _nMinWidth, _nMaxWidth, listCutOffDatas_, Convert_All); + + _set_offset_polygon(_listPolygons[_i], -m_nWidth); + _gpc_convert_tristrip(_listPolygons[_i], _nMinWidth - m_nWidth, _nMaxWidth - m_nWidth, listCutOffDatas_, Convert_All); + } + else // 所有的面 + { + int _nStart = 0; + int _nEnd = 0; + double _nDiv = _nMinWidth / m_nWidth; + _nStart = (int)floor(_nDiv); + _nDiv = _nMaxWidth / m_nWidth; + _nEnd = (int)floor(_nDiv); + _set_offset_polygon(_listPolygons[_i], -_nStart * m_nWidth); + for (int _j = _nStart; _j <= _nEnd; _j++) + { + _gpc_convert_tristrip(_listPolygons[_i],_nMinWidth - _j * m_nWidth, _nMaxWidth - _j * m_nWidth, listCutOffDatas_, Convert_All); + _set_offset_polygon(_listPolygons[_i], -m_nWidth); + } + } + } +} + +void GPCConvertHelper::_convertArea(IN const TransformData3D& area_, OUT std_vertex_list& areaVertexs_) +{ + gpc_vertex _gpcPoint; + _gpcPoint.x = area_.nStartX2D; + _gpcPoint.y = 0; + areaVertexs_.push_back(_gpcPoint); + _gpcPoint.x = area_.nStartX2D; + _gpcPoint.y = area_.nY; + areaVertexs_.push_back(_gpcPoint); + _gpcPoint.x = area_.nEndX2D; + _gpcPoint.y = area_.nY; + areaVertexs_.push_back(_gpcPoint); + _gpcPoint.x = area_.nEndX2D; + _gpcPoint.y = 0; + areaVertexs_.push_back(_gpcPoint); + _gpcPoint.x = area_.nStartX2D; + _gpcPoint.y = 0; + areaVertexs_.push_back(_gpcPoint); +} + +void GPCConvertHelper::Initialize(Transform3DList& listData_, double nWidth_) +{ + m_pRootAreaData = &listData_; + m_vectorBaseArea.clear(); + int _nSize = static_cast(listData_.size()); + for (int _i = 0; _i < _nSize; _i++) + { + TransformData3D& _item = listData_[_i]; + std_vertex_list _newArea; + _convertArea(_item, _newArea); + m_vectorBaseArea.push_back(_newArea); + } + m_nWidth = nWidth_; +} \ No newline at end of file diff --git a/src/NceCommands.cpp b/src/NceCommands.cpp new file mode 100644 index 0000000..363e897 --- /dev/null +++ b/src/NceCommands.cpp @@ -0,0 +1,2827 @@ +// ************************************************************************** // +// NceCommands.cpp : implementation of the NcEditor Extended Commands +// Copyright(c)2012 Naiky Company. All rights reserved. +// +// Abstract: +// 本文件实现若干为NcEditor扩展的命令。 +// ********************************************* ---- 杨开锦 2012-07-24 ***** // +#include "stdafx.h" +#include "IZMotion.h" +#include "IBeginStop.h" +#include "ActionParser.h" +#include "TubeComponent.cpp" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW +#endif + +#ifdef _DEBUG + #using "mscorlib.dll" + #using "System.Xml.dll" + #using ".\\NcStudio\\Debug\\Weihong.MotionControl.Core.dll" + #using ".\\NcStudio\\Debug\\Weihong.Utility.dll" + #using ".\\NcStudio\\Debug\\Weihong.Motion.IDE.dll" + #using ".\\NcStudio\\Debug\\ZFollowSystemUI.dll" +#else + #using "mscorlib.dll" + #using "System.Xml.dll" + #using ".\\NcStudio\\Release\\Weihong.MotionControl.Core.dll" + #using ".\\NcStudio\\Release\\Weihong.Utility.dll" + #using ".\\NcStudio\\Release\\Weihong.Motion.IDE.dll" + #using ".\\NcStudio\\Release\\ZFollowSystemUI.dll" +#endif +using namespace System; +using namespace System::Threading; +using namespace Weihong::MotionControl::Core; +using namespace Weihong::Utility; +using namespace Weihong::Motion::IDE; +using namespace ZFollowSystemUI::Commands; + +//////////////////////////////////////////////////////////////////////////////// +// Global function declarations ---- 黄海燕 2013-06-05 +// +namespace NcEditor +{ + extern void _CloseScanCutting(); +} +extern bool _SetParameterValue(IParameterNode^ Param_, const mach::ParameterValue* pParamValue_); +extern bool _GetParameterValue(IParameterNode^ Param_, mach::ParameterValue* pParamValue_); +extern bool _GetParameterValue(String^ strParam_, double* pParam_); + +//////////////////////////////////////////////////////////////////////////////// +// 定义一个专门用于暂停、暂停继续动作解析的全局变量。 ---- 黄海燕 2015-10-29 +// +static NcEditor::CActionParser g_sPauseActionParser; + +//////////////////////////////////////////////////////////////////////////////// +// Additional Commands ---- 杨开锦 2012-02-04 +//////////////////////////////////////////////////////////////////////////////// +namespace NcEditor +{ + //////////////////////////////////////////////////////////////////////////// + // 通用设置参数:在配置文件中配置指令名和需要修改的参数名,在需要的地方造指令,参 + // 数值就可以绕过全部的检查,将值直接Set进去。参数配置格式如下: + // + // 该办法一般用于解决滑动条拖动时由于参数检查引起的卡、有拖尾问题。---- 黄海燕 2013-06-06 + // + public ref class CSetParameterCommand : public CommandBase + { + public: + CSetParameterCommand() + { + m_strParameterName = ""; + } + + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + Xml::XmlElement^ _xmlElement = addInType_->Element; + m_strParameterName = _xmlElement->GetAttribute("Parameter"); + + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + if (parameter_->GetType()->FullName != "System.String") + { + return false; + } + + IParameterNode^ _ParamNode = + MCRuntime::Instance != nullptr && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager->GetParaemterNode(m_strParameterName) : nullptr; + + if (_ParamNode == nullptr) + { + return false; + } + + // 只处理bool,char,short,int,int64,float,double这个几个类型的数据 ---- 黄海燕 2013-06-06 + mach::ParameterValue _ParameterValue; + memset(&_ParameterValue, 0, sizeof(mach::ParameterValue)); + if (!_GetParameterValue(_ParamNode, &_ParameterValue)) + { + return false; + } + + return true; + } + + virtual void Execute(Object^ parameter_) override + { + IParameterNode^ _ParamNode = + MCRuntime::Instance != nullptr && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager->GetParaemterNode(m_strParameterName) : nullptr; + if (_ParamNode == nullptr) + { + ASSERT(false); + return; + } + + // 将字符串形式的参数转换为相应类型的参数值 ---- 黄海燕 2013-06-06 + mach::ParameterValue _ParameterValue; + memset(&_ParameterValue, 0, sizeof(mach::ParameterValue)); + _GetParameterValue(_ParamNode, &_ParameterValue); + String^ _FullName = _ParamNode->Value->GetType()->FullName; + if (_ParameterValue.nType == mach::ParameterValue::VT_BOOL) + { + _ParameterValue.bValue = Convert::ToBoolean(parameter_); + } + else if (_ParameterValue.nType == mach::ParameterValue::VT_CHAR) + { + _ParameterValue.cValue = Convert::ToByte(parameter_); + } + else if (_ParameterValue.nType == mach::ParameterValue::VT_SHORT) + { + _ParameterValue.sValue = Convert::ToInt16(parameter_); + } + else if (_ParameterValue.nType == mach::ParameterValue::VT_INT) + { + _ParameterValue.iValue = Convert::ToInt32(parameter_); + } + else if (_ParameterValue.nType == mach::ParameterValue::VT_INT64) + { + _ParameterValue.i64Value = Convert::ToInt64(parameter_); + } + else if (_ParameterValue.nType == mach::ParameterValue::VT_FLOAT) + { + _ParameterValue.fValue = Convert::ToSingle(parameter_); + } + else if (_ParameterValue.nType == mach::ParameterValue::VT_DOUBLE) + { + _ParameterValue.dValue = Convert::ToDouble(parameter_); + } + + // 将参数值Set到内核中 ---- 黄海燕 2013-06-06 + _SetParameterValue(_ParamNode, &_ParameterValue); + } + + protected: + // 需要修改的参数的参数名 ---- 黄海燕 2013-06-06 + String^ m_strParameterName; + }; + + //////////////////////////////////////////////////////////////////////////// + // 设置手动高速。 + // + public ref class CSetJogTurboCommand : public CommandBase + { + public: + virtual bool CanExecute(Object^ parameter_) override + { + IParameterNode^ _ParamNode = + MCRuntime::Instance != nullptr && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager->GetParaemterNode("ManuSpeedComponent1_IsTurboOn") : nullptr; + if (_ParamNode == nullptr || _ParamNode->Value->GetType()->FullName != "System.Boolean") + { + return false; + } + + // 合法值:""、"True"、"False"、"Switch" ---- 杨开锦 2012-11-17 + if (parameter_->GetType()->FullName != "System.String" + || parameter_->ToString() != "" + && parameter_->ToString() != "True" + && parameter_->ToString() != "False" + && parameter_->ToString() != "Switch") + { + return false; + } + + return true; + } + + virtual void Execute(Object^ parameter_) override + { + IParameterNode^ _ParamNode = + MCRuntime::Instance != nullptr && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager->GetParaemterNode("ManuSpeedComponent1_IsTurboOn") : nullptr; + if (_ParamNode == nullptr || _ParamNode->Value->GetType()->FullName != "System.Boolean") + { + return; + } + + if (parameter_->GetType()->FullName != "System.String") + { + return; + } + + if (parameter_->ToString() == "") // 默认表示开高速 + _ParamNode->Value = true; + else if (parameter_->ToString() == "True") // 开高速 + _ParamNode->Value = true; + else if (parameter_->ToString() == "False") // 关高速 + _ParamNode->Value = false; + else if (parameter_->ToString() == "Switch")// 切换 + _ParamNode->Value = !_ParamNode->Value; + else + ASSERT(FALSE); + + // 同步更新通道1手动连续模式。 ---- 黄海燕 2014-06-25 + _ParamNode = + MCRuntime::Instance != nullptr && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager->GetParaemterNode("JogMotion1_IsTurboOn") : nullptr; + if (_ParamNode == nullptr || _ParamNode->Value->GetType()->FullName != "System.Boolean") + { + return; + } + + if (parameter_->GetType()->FullName != "System.String") + { + return; + } + + if (parameter_->ToString() == "") // 默认表示开高速 + _ParamNode->Value = true; + else if (parameter_->ToString() == "True") // 开高速 + _ParamNode->Value = true; + else if (parameter_->ToString() == "False") // 关高速 + _ParamNode->Value = false; + else if (parameter_->ToString() == "Switch")// 切换 + _ParamNode->Value = !_ParamNode->Value; + else + ASSERT(FALSE); + + // 同步更新通道2手动连续模式。这里应该以引用组件的方式来获取jogmotion, + // 直接用参数写得太死了 ---- DingQiang 2017-02-15 + _ParamNode = + MCRuntime::Instance != nullptr && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager->GetParaemterNode("JogMotion2_IsTurboOn") : nullptr; + if (_ParamNode == nullptr || _ParamNode->Value->GetType()->FullName != "System.Boolean") + { + return; + } + + if (parameter_->GetType()->FullName != "System.String") + { + return; + } + + if (parameter_->ToString() == "") // 默认表示开高速 + _ParamNode->Value = true; + else if (parameter_->ToString() == "True") // 开高速 + _ParamNode->Value = true; + else if (parameter_->ToString() == "False") // 关高速 + _ParamNode->Value = false; + else if (parameter_->ToString() == "Switch")// 切换 + _ParamNode->Value = !_ParamNode->Value; + else + ASSERT(FALSE); + } + }; + + //////////////////////////////////////////////////////////////////////////// + // 手动连续 + // + public ref class CJogCommand : public CommandBase + { + public: + CJogCommand() + { + m_nAxis = -1; + m_nDir = 0; + m_strMotionPath = "/Kernel0/Channel0/JogMotion0"; + m_strSpeedParam = ""; + } + + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + Xml::XmlElement^ _xmlElement = addInType_->Element; + + // Axis + String^ _strAxis = _xmlElement->GetAttribute("Axis"); + if (_strAxis->Equals("0") || _strAxis->Equals("x") || _strAxis->Equals("X")) + m_nAxis = 0; + else if (_strAxis->Equals("1") || _strAxis->Equals("y") || _strAxis->Equals("Y")) + m_nAxis = 1; + else if (_strAxis->Equals("2") || _strAxis->Equals("z") || _strAxis->Equals("Z")) + m_nAxis = 2; + else + return false; + + // Direction + String^ _strDir = _xmlElement->GetAttribute("Dir"); + if (_strDir->Equals("N")) + m_nDir = -1; + else if (_strDir->Equals("S")) + m_nDir = 0; + else if (_strDir->Equals("P")) + m_nDir = 1; + else + return false; + + m_strSpeedParam = _xmlElement->GetAttribute("Speed"); + + // Motion + String^ _strMotionPath = _xmlElement->GetAttribute("Motion"); + if (!_strMotionPath->Equals("")) + m_strMotionPath = _strMotionPath; + if (GetJogMotion() == nullptr) + return false; + + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + IJogMotion^ _JogMotion = GetJogMotion(); + IAutoReleaseLimit^ _autoReleaseLimitJog = dynamic_cast(_JogMotion); + AbstractMotion^ _Motion = dynamic_cast(_JogMotion); + Channel^ _channel = _Motion != nullptr ? _Motion->Owner : nullptr; + if (_channel == nullptr) + { + return false; + } + + Direction _dir = Direction::Undefined; + if (m_nDir == -1) _dir = Direction::Negative; + if (m_nDir == 1) _dir = Direction::Positive; + if (_channel->ChannelState == ChannelState::Idle + || (_channel->ChannelState == ChannelState::Running + && _channel->CurrentMotion == _JogMotion) + || (_channel->ChannelState == ChannelState::Estop + && _autoReleaseLimitJog != nullptr + && _autoReleaseLimitJog->CanReleaseLimit(_dir, m_nAxis))) + { + return true; + } + + return false; + } + + virtual void Execute(Object^ parameter_) override + { + TRACE("CJogCommand::Execute => Axis=%d, Dir=%d\n", m_nAxis, m_nDir); + + // 取到手动连续功能部件 ---- 杨开锦 2012-02-04 + IJogMotion^ _JogMotion = GetJogMotion(); + if (_JogMotion == nullptr) + { + TRACE("CJogCommand::Execute => JogMotion Not Found.\n"); + return; + } + + // 调用手动连续命令 ---- 杨开锦 2012-02-04 + if (m_nAxis != 0 && m_nAxis != 1 && m_nAxis != 2 + || m_nDir != -1 && m_nDir != 0 && m_nDir != 1) + { + TRACE("CJogCommand::Execute => ErrorParameter.\n"); + return; + } + + if (m_nDir == 0 && !_JogMotion->IsEntered) + { + TRACE("CJogCommand::Execute => AlreadyStop.\n"); + return; + } + + if (!_JogMotion->IsEntered && !_JogMotion->Enter()) + { + TRACE("CJogCommand::Execute => ErrorState.\n"); + return; + } + + // 拿速度参数 + double _nVelocity = 0; + if (m_strSpeedParam->Length != 0) + { + using System::Runtime::InteropServices::Marshal; + mach::ParameterValue _SpeedValue; + memset(&_SpeedValue, 0, sizeof(mach::ParameterValue)); + mach::CParamManager* _pParamManager = mach::GetParamManager(); + if (_pParamManager + && _pParamManager->GetParameterValue((LPCSTR)(Marshal::StringToHGlobalAnsi(m_strSpeedParam)).ToPointer(), &_SpeedValue) + && _SpeedValue.nType == mach::ParameterValue::VT_DOUBLE) + { + _nVelocity = _SpeedValue.dValue / 60; + } + else + { + using System::Runtime::InteropServices::Marshal; + const char* _szParameter = (const char*)(Marshal::StringToHGlobalAnsi(m_strSpeedParam)).ToPointer(); + if (_szParameter && _szParameter[0]) + { + _nVelocity = atof(_szParameter); + } + + Marshal::FreeHGlobal(IntPtr((void*)_szParameter)); + } + } + + if (_nVelocity > 0.) + { + // 如果拿到了速度值,就使用拿到的,否则使用默认的 ---- DingQiang 2014-12-30 + if (_JogMotion->IsTurboOn) + { + if (_nVelocity < _JogMotion->Velocity) + { + _JogMotion->Velocity = _nVelocity; + } + _JogMotion->VelocityQuick = _nVelocity; + } + else + { + if (_nVelocity > _JogMotion->VelocityQuick) + { + _JogMotion->VelocityQuick = _nVelocity; + } + _JogMotion->Velocity = _nVelocity; + } + } + + Direction _dir = Direction::Undefined; + if (m_nDir == -1) _dir = Direction::Negative; + if (m_nDir == 1) _dir = Direction::Positive; + _JogMotion->RunAxis(_dir, m_nAxis); + } + + protected: + int m_nAxis; // 0:x; 1:y; 2:z + int m_nDir; // -1:Negative; 0-Stop; 1-Positive + String^ m_strMotionPath; // MotionPath, Default => /Kernel0/Channel0/JogMotion0 + String^ m_strSpeedParam; // 速度参数,不是必须的(可以是一个值,也可以是一个参数名) + + // 从CSharp中获取IIncreaseMotion对象 ---- 杨开锦 2012-02-04 + IJogMotion^ GetJogMotion() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent(m_strMotionPath); + } + }; + + public ref class CJogCommand_Laser : public CJogCommand + { + public: + CJogCommand_Laser() + { + m_strRefBitPort = ""; + m_strEnableParam = ""; + m_nVelocity = 0.0; // 速度 + m_nBlowType = 0; // 吹气类型 + m_nFollowHeight = 0.0; // 跟随高度 + m_nFocusPos = 0.0; // 焦点位置 + } + + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + Xml::XmlElement^ _xmlElement = addInType_->Element; + + // Axis + String^ _strBitPort = _xmlElement->GetAttribute("RefBitPort"); + if (_strBitPort->Length > 0) + { + m_strRefBitPort = _strBitPort; + } + + String^ _strEnableParam = _xmlElement->GetAttribute("EnableParam"); + if (_strEnableParam->Length > 0) + { + m_strEnableParam = _strEnableParam; + } + + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + return __super::CanExecute(parameter_); + } + + virtual void Execute(Object^ parameter_) override + { + mach::CParamManager* _pParamManager = mach::GetParamManager(); + mach::ParameterValue _EnableParam; + memset(&_EnableParam, 0, sizeof(mach::ParameterValue)); + _pParamManager->GetParameterValue("EnableJogLaser", &_EnableParam); + if (_EnableParam.nType == mach::ParameterValue::VT_BOOL && _EnableParam.bValue == true) + { + IMCBitPort^ _BitPort = MCRuntime::Instance->GetComponent("/Kernel0/BitPortManager0")->GetBitPort(m_strRefBitPort); + ASSERT(_BitPort != nullptr); + if (m_nDir == 0) + { + // 停止关端口 + _BitPort->Value = false; + } + else + { + _BitPort->Value = true; + } + } + else + { + __super::Execute(parameter_); + } + } + protected: + String^ m_strRefBitPort; + String^ m_strEnableParam; + double m_nVelocity; // 速度 + int m_nBlowType; // 吹气类型 + double m_nFollowHeight; // 跟随高度 + double m_nFocusPos; // 焦点位置 + }; + + //////////////////////////////////////////////////////////////////////////// + // 手动步进 + // + public ref class CIncCommand : public CommandBase + { + public: + CIncCommand() + { + m_nAxis = -1; + m_nDir = 0; + m_strMotionPath = "/Kernel0/Channel0/IncreaseMotion0"; + } + + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + Xml::XmlElement^ _xmlElement = addInType_->Element; + + // Axis + String^ _strAxis = _xmlElement->GetAttribute("Axis"); + if (_strAxis->Equals("0") || _strAxis->Equals("x") || _strAxis->Equals("X")) + m_nAxis = 0; + else if (_strAxis->Equals("1") || _strAxis->Equals("y") || _strAxis->Equals("Y")) + m_nAxis = 1; + else if (_strAxis->Equals("2") || _strAxis->Equals("z") || _strAxis->Equals("Z")) + m_nAxis = 2; + else + return false; + + // Dir + String^ _strDir = _xmlElement->GetAttribute("Dir"); + if (_strDir->Equals("N")) + m_nDir = -1; + else if (_strDir->Equals("S")) + m_nDir = 0; + else if (_strDir->Equals("P")) + m_nDir = 1; + else + return false; + + // Motion + String^ _strMotionPath = _xmlElement->GetAttribute("Motion"); + if (!_strMotionPath->Equals("")) + m_strMotionPath = _strMotionPath; + if (GetIncreaseMotion() == nullptr) + return false; + + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + IIncreaseMotion^ _IncMotion = GetIncreaseMotion(); + AbstractMotion^ _Motion = dynamic_cast(_IncMotion); + Channel^ _channel = _Motion != nullptr ? _Motion->Owner : nullptr; + if (_channel == nullptr) + { + return false; + } + + // 把不能开始下次运动的条件改为IsBusy就不能开始 ---- 杨开锦 2014-12-23 + // 之前这里的条件是 IsBusy && is not CurrentMotion 不清楚为什么 + // 看起来只要IsBusy就不应该再开始下个运动才对,所以这里就改掉它了 + // 下面的CIncParamerCommand同理也改了,如果谁发现是我没考虑全改错的,请告诉我 + //if (_IncMotion->IsBusy && _channel->CurrentMotion != _IncMotion) + if (_IncMotion->IsBusy) + { + return false; + } + + ChannelState _state = _channel->ChannelState; + if (_state == ChannelState::Estop) + { + return false; + } + + return true; + } + + virtual void Execute(Object^ parameter_) override + { + TRACE("CIncCommand::Execute => Axis=%d, Dir=%d\n", m_nAxis, m_nDir); + + // 取到手动步进功能部件 ---- 丁强 2012-02-07 + IIncreaseMotion^ _IIncreaseMotion = GetIncreaseMotion(); + if (_IIncreaseMotion == nullptr) + { + TRACE("CIncCommand::Execute => IncreaseMotion Not Found.\n"); + return; + } + + // 先检查轴和方向参数是否正确 ---- 丁强 2012-02-07 + if (m_nAxis != 0 && m_nAxis != 1 && m_nAxis != 2 + || m_nDir != -1 && m_nDir != 0 && m_nDir != 1) + { + TRACE("CIncCommand::Execute => ErrorParameter.\n"); + return; + } + + // 步长参数 ---- 杨开锦 2012-02-23 + double _nDistance = 0.0; + if (parameter_ != nullptr && parameter_->GetType()->FullName == "System.String") + { + using System::Runtime::InteropServices::Marshal; + const char* _szParameter = (const char*)(Marshal::StringToHGlobalAnsi(parameter_->ToString())).ToPointer(); + if (_szParameter && _szParameter[0]) + { + _nDistance = atof(_szParameter); + } + + Marshal::FreeHGlobal(IntPtr((void*)_szParameter)); + } + + if ((_nDistance < 0.001 || 10e+9 < _nDistance) && m_nDir != 0) + { + TRACE("CIncCommand::Execute => ErrorParameter: Distance = %.6f\n", _nDistance); + return; + } + + if (m_nDir == 0 && !_IIncreaseMotion->IsEntered) + { + TRACE("CIncCommand::Execute => AlreadyStop.\n"); + return; + } + + // 调用手动步进命令 ---- 丁强 2012-02-07 + if (!_IIncreaseMotion->IsEntered && !_IIncreaseMotion->Enter()) + { + TRACE("CIncCommand::Execute => ErrorState.\n"); + return; + } + + _IIncreaseMotion->Distance = _nDistance; + Direction _dir = Direction::Undefined; + if (m_nDir == -1) _dir = Direction::Negative; + if (m_nDir == 1) _dir = Direction::Positive; + _IIncreaseMotion->RunAxis(_dir, m_nAxis); + } + + protected: + int m_nAxis; // 0-x; 1-y; 2-z + int m_nDir; // -1:Negative; 0-Stop; 1-Positive + String^ m_strMotionPath; // MotionPath, Default => /Kernel0/Channel0/IncreaseMotion0 + + // 从CSharp中获取IIncreaseMotion对象 ---- 丁强 2012-02-07 + IIncreaseMotion^ GetIncreaseMotion() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent(m_strMotionPath); + } + }; + + // 步长以角度来度量的步进运动命令。最终还是调用的以长度来度量的步进运动,这个 + // 类负责把角度转换成弧长后调用步进运动 ---- DingQiang 2016-08-09 + public ref class CIncCommand_Degree : public CommandBase + { + public: + CIncCommand_Degree() + { + m_nAxis = -1; + m_nDir = 0; + m_strMotionPath = "/Kernel0/Channel0/IncreaseMotion0"; + } + + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + Xml::XmlElement^ _xmlElement = addInType_->Element; + + // Axis + String^ _strAxis = _xmlElement->GetAttribute("Axis"); + if (_strAxis->Equals("0") || _strAxis->Equals("x") || _strAxis->Equals("X")) + m_nAxis = 0; + else if (_strAxis->Equals("1") || _strAxis->Equals("y") || _strAxis->Equals("Y")) + m_nAxis = 1; + else if (_strAxis->Equals("2") || _strAxis->Equals("z") || _strAxis->Equals("Z")) + m_nAxis = 2; + else + return false; + + // Dir + String^ _strDir = _xmlElement->GetAttribute("Dir"); + if (_strDir->Equals("N")) + m_nDir = -1; + else if (_strDir->Equals("S")) + m_nDir = 0; + else if (_strDir->Equals("P")) + m_nDir = 1; + else + return false; + + // Motion + String^ _strMotionPath = _xmlElement->GetAttribute("Motion"); + if (!_strMotionPath->Equals("")) + m_strMotionPath = _strMotionPath; + if (GetIncreaseMotion() == nullptr) + return false; + + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + IIncreaseMotion^ _IncMotion = GetIncreaseMotion(); + AbstractMotion^ _Motion = dynamic_cast(_IncMotion); + Channel^ _channel = _Motion != nullptr ? _Motion->Owner : nullptr; + if (_channel == nullptr) + { + return false; + } + + // 把不能开始下次运动的条件改为IsBusy就不能开始 ---- 杨开锦 2014-12-23 + // 之前这里的条件是 IsBusy && is not CurrentMotion 不清楚为什么 + // 看起来只要IsBusy就不应该再开始下个运动才对,所以这里就改掉它了 + // 下面的CIncParamerCommand同理也改了,如果谁发现是我没考虑全改错的,请告诉我 + //if (_IncMotion->IsBusy && _channel->CurrentMotion != _IncMotion) + if (_IncMotion->IsBusy) + { + return false; + } + + ChannelState _state = _channel->ChannelState; + if (_state == ChannelState::Estop) + { + return false; + } + + double _nType; + bool _bRet = _GetParameterValue("#TubeComponent1_TubeType", &_nType); + ASSERT(_bRet); + // 管材类型为方管时,随动打开不能执行W轴手动步进。 + ASSERT(GetAbstractBitPortManager() + && GetAbstractBitPortManager()->GetBitPort("SBP.Follow")); + if (_nType == 1 + && GetAbstractBitPortManager()->GetBitPort("SBP.Follow")->Value) + { + return false; + } + + return true; + } + + virtual void Execute(Object^ parameter_) override + { + TRACE("CIncCommand::Execute => Axis=%d, Dir=%d\n", m_nAxis, m_nDir); + + // 取到手动步进功能部件 ---- 丁强 2012-02-07 + IIncreaseMotion^ _IIncreaseMotion = GetIncreaseMotion(); + if (_IIncreaseMotion == nullptr) + { + TRACE("CIncCommand::Execute => IncreaseMotion Not Found.\n"); + return; + } + + // 先检查轴和方向参数是否正确 ---- 丁强 2012-02-07 + if (m_nAxis != 0 && m_nAxis != 1 && m_nAxis != 2 + || m_nDir != -1 && m_nDir != 0 && m_nDir != 1) + { + TRACE("CIncCommand::Execute => ErrorParameter.\n"); + return; + } + + // 步长参数 ---- 杨开锦 2012-02-23 + double _nDistance = 0.0; + if (parameter_ != nullptr && parameter_->GetType()->FullName == "System.String") + { + using System::Runtime::InteropServices::Marshal; + const char* _szParameter = (const char*)(Marshal::StringToHGlobalAnsi(parameter_->ToString())).ToPointer(); + if (_szParameter && _szParameter[0]) + { + _nDistance = atof(_szParameter); + } + + Marshal::FreeHGlobal(IntPtr((void*)_szParameter)); + } + + if ((_nDistance < 0.001 || 10e+9 < _nDistance) && m_nDir != 0) + { + TRACE("CIncCommand::Execute => ErrorParameter: Distance = %.6f\n", _nDistance); + return; + } + + if (m_nDir == 0 && !_IIncreaseMotion->IsEntered) + { + TRACE("CIncCommand::Execute => AlreadyStop.\n"); + return; + } + + // 调用手动步进命令 ---- 丁强 2012-02-07 + if (!_IIncreaseMotion->IsEntered && !_IIncreaseMotion->Enter()) + { + TRACE("CIncCommand::Execute => ErrorState.\n"); + return; + } + + // 当前轴一定是旋转轴 ---- DingQiang 2016-08-09 + AbstractMotion^ _AbstractMotion = GetAbstractMotion(); + ASSERT(_AbstractMotion != nullptr); + AbstractAxis^ _AbstractAxis = _AbstractMotion->Owner->Axes[m_nAxis]; + ASSERT(_AbstractAxis != nullptr && _AbstractAxis->IsRotary); + MockRotaryAxis^ _MockRotaryAxis = (MockRotaryAxis^)_AbstractAxis; + ASSERT(_MockRotaryAxis != nullptr); + + // 角度转换成弧度 ---- DingQiang 2016-08-09 + _IIncreaseMotion->Distance = _MockRotaryAxis->AngleToArc(_nDistance); + Direction _dir = Direction::Undefined; + if (m_nDir == -1) _dir = Direction::Negative; + if (m_nDir == 1) _dir = Direction::Positive; + _IIncreaseMotion->RunAxis(_dir, m_nAxis); + } + + protected: + int m_nAxis; // 0-x; 1-y; 2-z + int m_nDir; // -1:Negative; 0-Stop; 1-Positive + String^ m_strMotionPath; // MotionPath, Default => /Kernel0/Channel0/IncreaseMotion0 + + // 从CSharp中获取IIncreaseMotion对象 ---- 丁强 2012-02-07 + IIncreaseMotion^ GetIncreaseMotion() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent(m_strMotionPath); + } + + AbstractMotion^ GetAbstractMotion() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent(m_strMotionPath); + } + + AbstractBitPortManager^ GetAbstractBitPortManager() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent("/Kernel0/BitPortManager0"); + } + }; + + // 旋转轴的手动连续。 ---- 黄海燕 2017-04-20 + public ref class CJogCommand_Degree : public CJogCommand + { + public: + virtual bool CanExecute(Object^ parameter_) override + { + bool _bCabExecute = __super::CanExecute(parameter_); + ASSERT(GetAbstractBitPortManager() + && GetAbstractBitPortManager()->GetBitPort("SBP.Follow")); + double _nType; + bool _bRet = _GetParameterValue("#TubeComponent1_TubeType", &_nType); + ASSERT(_bRet); + if (_nType == 1 + && GetAbstractBitPortManager()->GetBitPort("SBP.Follow")->Value) + { + return false; + } + + return _bCabExecute; + } + + AbstractBitPortManager^ GetAbstractBitPortManager() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent("/Kernel0/BitPortManager0"); + } + }; + + // 指定步长和速度的步进Command ---- DingQiang 2013-09-16 + public ref class CIncParamerCommand : public CommandBase + { + public: + CIncParamerCommand() + { + m_nAxis = -1; + m_nDir = 0; + m_strMotionPath = "/Kernel0/Channel1/IncreaseMotion1"; + m_strIncParam = ""; + m_strIncVelocity = ""; + } + + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + Xml::XmlElement^ _xmlElement = addInType_->Element; + + // Axis + String^ _strAxis = _xmlElement->GetAttribute("Axis"); + if (_strAxis->Equals("0") || _strAxis->Equals("x") || _strAxis->Equals("X")) + m_nAxis = 0; + else if (_strAxis->Equals("1") || _strAxis->Equals("y") || _strAxis->Equals("Y")) + m_nAxis = 1; + else if (_strAxis->Equals("2") || _strAxis->Equals("z") || _strAxis->Equals("Z")) + m_nAxis = 2; + else + return false; + + // Dir + String^ _strDir = _xmlElement->GetAttribute("Dir"); + if (_strDir->Equals("N")) + m_nDir = -1; + else if (_strDir->Equals("S")) + m_nDir = 0; + else if (_strDir->Equals("P")) + m_nDir = 1; + else + return false; + + // Inc + m_strIncParam = _xmlElement->GetAttribute("ParameterInc"); + m_strIncVelocity = _xmlElement->GetAttribute("ParameterVelocity"); + + // Motion + String^ _strMotionPath = _xmlElement->GetAttribute("Motion"); + if (!_strMotionPath->Equals("")) + m_strMotionPath = _strMotionPath; + if (GetIncreaseMotion() == nullptr) + return false; + + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + IIncreaseMotion^ _IncMotion = GetIncreaseMotion(); + AbstractMotion^ _Motion = dynamic_cast(_IncMotion); + Channel^ _channel = _Motion != nullptr ? _Motion->Owner : nullptr; + if (_channel == nullptr) + { + return false; + } + + // 参见上 CIncCommand::CanExecute ---- 杨开锦 2014-12-23 + //if (_IncMotion->IsBusy && _channel->CurrentMotion != _IncMotion) + if (_IncMotion->IsBusy) + { + return false; + } + + ChannelState _state = _channel->ChannelState; + if (_state == ChannelState::Estop) + { + return false; + } + + return true; + } + + virtual void Execute(Object^ parameter_) override + { + TRACE("CIncCommand::Execute => Axis=%d, Dir=%d\n", m_nAxis, m_nDir); + + // 取到手动步进功能部件 ---- 丁强 2012-02-07 + IIncreaseMotion^ _IIncreaseMotion = GetIncreaseMotion(); + if (_IIncreaseMotion == nullptr) + { + TRACE("CIncCommand::Execute => IncreaseMotion Not Found.\n"); + return; + } + + // 先检查轴和方向参数是否正确 ---- 丁强 2012-02-07 + if (m_nAxis != 0 && m_nAxis != 1 && m_nAxis != 2 + || m_nDir != -1 && m_nDir != 0 && m_nDir != 1) + { + TRACE("CIncCommand::Execute => ErrorParameter.\n"); + return; + } + + if (m_strIncParam->Equals("")) + { + return; + } + + double _nDistance = 0.0; + + // 先按参数的方式来拿步长 ---- DingQiang 2013-09-05 + IParameterNode^ _ParamNode = + MCRuntime::Instance != nullptr && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager->GetParaemterNode(m_strIncParam) : nullptr; + if (_ParamNode != nullptr) + { + mach::ParameterValue _ParameterValue; + memset(&_ParameterValue, 0, sizeof(mach::ParameterValue)); + if (!_GetParameterValue(_ParamNode, &_ParameterValue)) + { + return; + } + + ASSERT(_ParameterValue.nType == mach::ParameterValue::VT_DOUBLE); + _nDistance = _ParameterValue.dValue; + } + else + { + using System::Runtime::InteropServices::Marshal; + const char* _szParameter = (const char*)(Marshal::StringToHGlobalAnsi(m_strIncParam)).ToPointer(); + if (_szParameter && _szParameter[0]) + { + _nDistance = atof(_szParameter); + } + + Marshal::FreeHGlobal(IntPtr((void*)_szParameter)); + } + + double _nVelocity = 0; + _ParamNode = MCRuntime::Instance != nullptr && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager->GetParaemterNode(m_strIncVelocity) : nullptr; + // 先按参数的方式来拿速度 ---- DingQiang 2013-09-05 + if (_ParamNode != nullptr) + { + mach::ParameterValue _ParameterValue; + memset(&_ParameterValue, 0, sizeof(mach::ParameterValue)); + if (!_GetParameterValue(_ParamNode, &_ParameterValue)) + { + return; + } + + ASSERT(_ParameterValue.nType == mach::ParameterValue::VT_DOUBLE); + _nVelocity = _ParameterValue.dValue; + } + else + { + using System::Runtime::InteropServices::Marshal; + const char* _szParameter = (const char*)(Marshal::StringToHGlobalAnsi(m_strIncVelocity)).ToPointer(); + if (_szParameter && _szParameter[0]) + { + _nVelocity = atof(_szParameter); + } + + Marshal::FreeHGlobal(IntPtr((void*)_szParameter)); + } + + if (_nVelocity > 0) + { + _IIncreaseMotion->Velocity = _nVelocity / 60; + } + + if (_nDistance < 0.001 || 10e+9 < _nDistance) + { + TRACE("CIncCommand::Execute => ErrorParameter: Distance = %.6f\n", _nDistance); + return; + } + + if (m_nDir == 0 && !_IIncreaseMotion->IsEntered) + { + TRACE("CIncCommand::Execute => AlreadyStop.\n"); + return; + } + + // 调用手动步进命令 ---- 丁强 2012-02-07 + if (!_IIncreaseMotion->IsEntered && !_IIncreaseMotion->Enter()) + { + TRACE("CIncCommand::Execute => ErrorState.\n"); + return; + } + + _IIncreaseMotion->Distance = _nDistance; + Direction _dir = Direction::Undefined; + if (m_nDir == -1) _dir = Direction::Negative; + if (m_nDir == 1) _dir = Direction::Positive; + _IIncreaseMotion->RunAxis(_dir, m_nAxis); + } + + protected: + int m_nAxis; // 0-x; 1-y; 2-z + int m_nDir; // -1:Negative; 0-Stop; 1-Positive + String^ m_strMotionPath; // MotionPath, Default => /Kernel0/Channel0/IncreaseMotion0 + String^ m_strIncParam; // 步长 + String^ m_strIncVelocity; // 速度 + + // 从CSharp中获取IIncreaseMotion对象 ---- 丁强 2012-02-07 + IIncreaseMotion^ GetIncreaseMotion() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent(m_strMotionPath); + } + }; + + //////////////////////////////////////////////////////////////////////////// + // 通过解析器做的手动步进 ---- 杨开锦 2012-07-24 + // + public ref class CIncCommand_ViaInterp : public CommandBase + { + public: + CIncCommand_ViaInterp() + { + m_nAxis = -1; + m_nDir = 0; + m_strSpeedParam = ""; + m_strMotionType = "G01"; + } + + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + // Axis & Dir + Xml::XmlElement^ _xmlElement = addInType_->Element; + String^ _strAxis = _xmlElement->GetAttribute("Axis"); + if (_strAxis->Equals("x") || _strAxis->Equals("X")) + m_nAxis = 0; + else if (_strAxis->Equals("y") || _strAxis->Equals("Y")) + m_nAxis = 1; + else if (_strAxis->Equals("z") || _strAxis->Equals("Z")) + m_nAxis = 2; + else + return false; + + String^ _strDir = _xmlElement->GetAttribute("Dir"); + if (_strDir->Equals("N")) + m_nDir = -1; + else if (_strDir->Equals("S")) + m_nDir = 0; + else if (_strDir->Equals("P")) + m_nDir = 1; + else + return false; + + m_strSpeedParam = _xmlElement->GetAttribute("Speed"); + + // 配置手动步进是G00还是G01 ---- DingQiang 2016-10-20 + String^ _strMotionType = _xmlElement->GetAttribute("MotionType"); + if (!String::IsNullOrEmpty(_strMotionType)) + { + if (String::Compare(_strMotionType, "G00", true) == 0 || String::Compare(_strMotionType, "G01", true) == 0) + { + m_strMotionType = _strMotionType; + } + else + { + ASSERT(FALSE); + return false; + } + } + + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + bool _bCanExecute = false; + if (mach::CCommandManager* _pCommandManager = mach::GetCommandManager()) + { + if (m_nDir == 0) + { + _pCommandManager->CanExecute("Stop", &_bCanExecute); + } + else + { + CStringA _strGCode = _GetGCode(parameter_); + _pCommandManager->CanExecute("RunGCode", _strGCode, "LPCSTR", &_bCanExecute); + } + } + + return _bCanExecute; + } + + virtual void Execute(Object^ parameter_) override + { + TRACE("CIncCommand::Execute => Axis=%d, Dir=%d\n", m_nAxis, m_nDir); + + if (mach::CCommandManager* _pCommandManager = mach::GetCommandManager()) + { + if (m_nDir == 0) + { + _pCommandManager->Execute("Stop"); + } + else + { + CStringA _strGCode = _GetGCode(parameter_); + _pCommandManager->Execute("RunGCode", _strGCode, "LPCSTR"); + } + } + } + + protected: + int m_nAxis; // 0-x; 1-y; 2-z + int m_nDir; // -1:Negative; 0-Stop; 1-Positive + String^ m_strSpeedParam; // 速度参数,不是必须的(可以是一个值,也可以是一个参数名) + String^ m_strMotionType; // 运动类型,默认G01,可配置成G00 + CStringA _GetGCode(Object^ parameter_) + { + // 步长参数 ---- 杨开锦 2012-07-24 + double _nDistance = 0.0; + if (parameter_ != nullptr && parameter_->GetType()->FullName == "System.String") + { + using System::Runtime::InteropServices::Marshal; + const char* _szParameter = (const char*)(Marshal::StringToHGlobalAnsi(parameter_->ToString())).ToPointer(); + if (_szParameter && _szParameter[0]) + { + _nDistance = atof(_szParameter); + } + + Marshal::FreeHGlobal(IntPtr((void*)_szParameter)); + } + ASSERT(_nDistance > 0); + + // 拿速度参数 + double _nVelocity = 0; + + if (m_strSpeedParam->Length == 0) + { + // 步进速度 ---- 杨开锦 2012-07-24 + mach::ParameterValue _SpeedValue; + memset(&_SpeedValue, 0, sizeof(mach::ParameterValue)); + mach::CParamManager* _pParamManager = mach::GetParamManager(); + if (!_pParamManager + || !_pParamManager->GetParameterValue("SpeedInc", &_SpeedValue) + || _SpeedValue.nType != mach::ParameterValue::VT_DOUBLE) + { + ASSERT(FALSE); + return ""; + } + ASSERT(_SpeedValue.dValue > 0); + _nVelocity = _SpeedValue.dValue; + } + else + { + using System::Runtime::InteropServices::Marshal; + mach::ParameterValue _SpeedValue; + memset(&_SpeedValue, 0, sizeof(mach::ParameterValue)); + mach::CParamManager* _pParamManager = mach::GetParamManager(); + if (_pParamManager + && _pParamManager->GetParameterValue((LPCSTR)(Marshal::StringToHGlobalAnsi(m_strSpeedParam)).ToPointer(), &_SpeedValue) + && _SpeedValue.nType == mach::ParameterValue::VT_DOUBLE) + { + _nVelocity = _SpeedValue.dValue; + } + else + { + using System::Runtime::InteropServices::Marshal; + const char* _szParameter = (const char*)(Marshal::StringToHGlobalAnsi(m_strSpeedParam)).ToPointer(); + if (_szParameter && _szParameter[0]) + { + _nVelocity = atof(_szParameter); + } + + Marshal::FreeHGlobal(IntPtr((void*)_szParameter)); + } + } + + ASSERT(_nVelocity > 0.); + + // 生成GCode ---- 杨开锦 2012-07-24 + ASSERT(m_nAxis == 0 || m_nAxis == 1 || m_nAxis == 2); + ASSERT(m_nDir == -1 || m_nDir == 1); + static const CStringA _s_strGCodes[] = + { + "N01 G905 G91 %s X%f F%d\n", + "N01 G905 G91 %s Y%f F%d\n", + "N01 G905 G91 %s Z%f F%d\n", + }; + CStringA _strGCode; + _strGCode.Format(_s_strGCodes[m_nAxis], m_strMotionType, m_nDir * _nDistance, int(_nVelocity)); + return _strGCode; + } + }; + + //////////////////////////////////////////////////////////////////////////// + // 带有预动作的开始继续 + // + public ref class TaskStartOrContineCommand_PreAction: public TaskStartOrContineCommand + { + public: + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + // 样例:PreAction="OpenPort(OUT11) Delay(200) OpenPort(OIL) Delay(100) OpenPort(SPIN) Delay(60)" + m_strPreAction = addInType_->Element->GetAttribute("PreAction"); + m_action = gcnew Action(this, &TaskStartOrContineCommand_PreAction::Continue); + return __super::Build(addInType_, buildError_); + } + + virtual void Execute(Object^ parameter) override + { + if (this->AbstractTaskMotion->Owner->ChannelState == ChannelState::Pausing + && GetAbstractBitPortManager()->GetBitPort("SBP.MotionGxx")->Value) + { + this->m_action->BeginInvoke(parameter, nullptr, nullptr); + } + else + { + __super::Execute(parameter); + } + } + + protected: + void Continue(Object^ parameter) + { + try + { + array^ _arraySplitChars = {' ', ';', '\t', '\r', '\n'}; + array^ _arrayActions = m_strPreAction->Split(_arraySplitChars); + for (int _i = 0; _i < _arrayActions->Length; _i++) + { + if (!CanExecute(parameter)) + { + return; + } + + String^ _strAction = _arrayActions[_i]; + DoAction(_strAction); + } + } + catch (Exception^ e_) + { + MCRuntime::Instance->Application->BeginCall(gcnew Action(this, &TaskStartOrContineCommand_PreAction::ThrowException), gcnew cli::array {e_}); + } + + if (__super::CanExecute(parameter)) + { + __super::Execute(parameter); + } + } + + void ThrowException(Exception^ e_) + { + throw gcnew Exception(e_->ToString()); + } + + void DoAction(String^ strAction_) + { + if (strAction_ == nullptr) + { + return; + } + + array^ _arrayTrimChars = {'=', '(', ')'}; + if (strAction_->StartsWith("Delay")) + { + String^ _strDelayTime = strAction_->Substring(5)->Trim(_arrayTrimChars); + ASSERT(_strDelayTime->Length > 0); + int _nDelayMS = 0; + try + { + _nDelayMS = Int32::Parse(_strDelayTime); + } + catch (...) + { + // 支持#打开的方式引用命名变量 ---- 杨开锦 2012-08-29 + ASSERT(_nDelayMS == 0); + ASSERT(_strDelayTime->Substring(0, 1)->Equals("#")); + _nDelayMS = GetNamedParameter_Int32(_strDelayTime->Substring(1)); + } + + Thread::Sleep(_nDelayMS); + } + else if (strAction_->StartsWith("OpenPort")) + { + String^ _strPortIdentifier = strAction_->Substring(8)->Trim(_arrayTrimChars); + GetAbstractBitPortManager()->GetBitPort(_strPortIdentifier)->Value = true; + } + else if (strAction_->StartsWith("ClosePort")) + { + String^ _strPortIdentifier = strAction_->Substring(9)->Trim(_arrayTrimChars); + GetAbstractBitPortManager()->GetBitPort(_strPortIdentifier)->Value = false; + } + else if (strAction_->StartsWith("WaitPort")) + { + String^ _strWaitItem= strAction_->Substring(8)->Trim(_arrayTrimChars); + array^ _arrayParams = _strWaitItem->Split(','); + if (_arrayParams->Length != 2 && _arrayParams->Length != 3) + { + ASSERT(FALSE); + return; + } + + ASSERT(_arrayParams[1] == "0" || _arrayParams[1] == "1"); + String^ _strWaitPortIdentifier = _arrayParams[0]; + bool _bWaitState = (_arrayParams[1] != "0"); + int _nWaitTime = 24 * 3600 * 1000; // 以一天作为无限等待的时间 ---- DingQiang 2012-10-25 + if (_arrayParams->Length == 3) + { + String^ _strWaitTime = _arrayParams[2]; + try + { + _nWaitTime = Int32::Parse(_strWaitTime); + } + catch (...) + { + // 支持#打开的方式引用命名变量 ---- 杨开锦 2012-08-29 + ASSERT(_nWaitTime == 24 * 3600 * 1000); + ASSERT(_strWaitTime->Substring(0, 1)->Equals("#")); + _nWaitTime = GetNamedParameter_Int32(_strWaitTime->Substring(1)); + } + } + + IMCBitPort^ _BitPort = GetAbstractBitPortManager()->GetBitPort(_strWaitPortIdentifier); + if (_BitPort == nullptr) + { + ASSERT(FALSE); + return; + } + + DWORD _nBeginTime = ::GetTickCount(); + while(true) + { + if(_BitPort->Value == _bWaitState) + { + break; + } + + if (::GetTickCount() - _nBeginTime >= (DWORD)_nWaitTime) + { + break; + } + + Thread::Sleep(20); + } + } + else if (strAction_->StartsWith("#")) + { + int _nEqualIndex = strAction_->IndexOf("="); + String^ _strParamName = strAction_->Substring(0, _nEqualIndex)->Trim('#'); + String^ _strValue = strAction_->Substring(_nEqualIndex + 1, strAction_->Length - (_nEqualIndex + 1)); + int _nValue = 0; + if (_strValue->Substring(0, 1) != "#") + { + _nValue = Int32::Parse(_strValue); + } + else + { + _strValue = _strValue->Trim('#'); + _nValue = GetNamedParameter_Int32(_strValue); + } + + SetNamedParameter_Int32(_strParamName, _nValue); + } + } + + AbstractBitPortManager^ GetAbstractBitPortManager() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent("/Kernel0/BitPortManager0"); + } + + void SetNamedParameter_Int32(String^ strParamName_, int nValue_) + { + // Get Parameter Node ---- 杨开锦 2012-08-29 + MCDataManager^ _DataManager = + MCRuntime::Instance != nullptr + && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager : nullptr; + if (_DataManager == nullptr) + { + return; + } + + IParameterNode^ _ParamNode = _DataManager->GetParaemterNode(strParamName_); + if (_ParamNode == nullptr) + { + return; + } + + if (_ParamNode->Value->GetType()->FullName == "System.Int32") + { + _ParamNode->Value = nValue_; + } + else if (_ParamNode->Value->GetType()->FullName == "System.Boolean") + { + _ParamNode->Value = safe_cast(nValue_); + } + } + + int GetNamedParameter_Int32(String^ strParamName_) + { + // Get Parameter Node ---- 杨开锦 2012-08-29 + MCDataManager^ _DataManager = + MCRuntime::Instance != nullptr + && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager : nullptr; + if (_DataManager == nullptr) + { + return 0; + } + + IParameterNode^ _ParamNode = _DataManager->GetParaemterNode(strParamName_); + if (_ParamNode == nullptr) + { + return 0; + } + + // Get Parameter Value ---- 杨开锦 2012-08-29 + int _nParamValue = 0; + if (_ParamNode->Value->GetType()->FullName == "System.Int32") + { + _nParamValue = safe_cast(_ParamNode->Value); + } + else if (_ParamNode->Value->GetType()->FullName == "System.Boolean") + { + bool _nValue = safe_cast(_ParamNode->Value); + if (_nValue) + { + _nParamValue = 1; + } + else + { + _nParamValue = 0; + } + } + + return _nParamValue; + } + + private: + Action^ m_action; + String^ m_strPreAction; + }; + + //////////////////////////////////////////////////////////////////////////// + // 带有预动作的开始继续,预动作通过Lua文件配置而来。 + // ---- 黄海燕 2015-09-14 + public ref class TaskStartOrContineCommand_PreActionInLua: public TaskStartOrContineCommand + { + public: + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + m_action = gcnew Action(this, &TaskStartOrContineCommand_PreActionInLua::Continue); + m_bContinuing = false; + m_strZMotionType = addInType_->Element->GetAttribute("ZMotionType"); + return __super::Build(addInType_, buildError_); + } + + virtual void Execute(Object^ parameter) override + { + if (!CanExecute(parameter)) + return; + + AbstractBitPortManager^ _pBitPortManager = GetAbstractBitPortManager(); + IMCBitPort^ _pGxx = _pBitPortManager == nullptr ? nullptr : _pBitPortManager->GetBitPort("SBP.MotionGxx"); + if (this->AbstractTaskMotion->Owner->ChannelState == ChannelState::Pausing + && _pGxx && _pGxx->Value) + { + this->m_action->BeginInvoke(parameter, nullptr, nullptr); + } + else + { + __super::Execute(parameter); + } + } + + protected: + void Continue(Object^ parameter) + { + if (m_bContinuing) + return; + m_bContinuing = true; + + CString _strParam; + _BuildParam(_strParam); + + CPPLuaState* _pLuaState = GetPPLuaState(); + CString _strContinueAction; + if (!_pLuaState + || !_pLuaState->Lua_GetActionCode(_strParam, "GetContinueActions", &_strContinueAction) + || _strContinueAction.IsEmpty()) + { + ASSERT(FALSE); + } + + g_sPauseActionParser.Reset(); + g_sPauseActionParser.DoParser(_strContinueAction); + AbstractBitPortManager^ _pBitPortManager = GetAbstractBitPortManager(); + IMCBitPort^ _pGxx = _pBitPortManager == nullptr ? nullptr : _pBitPortManager->GetBitPort("SBP.MotionGxx"); + while (!g_sPauseActionParser.IsIdle()) + { + if (!CanExecute(parameter) + || _pGxx == nullptr + || !_pGxx->Value) + { + g_sPauseActionParser.Reset(); + break; + } + g_sPauseActionParser.OnStep(); + } + + if (__super::CanExecute(parameter)) + { + __super::Execute(parameter); + } + + m_bContinuing = false; + } + + void _BuildParam(CString& strParam_) + { + CString _strParameter; + if (!GetCurLayerParam(&_strParameter)) + { + ASSERT(FALSE); + } + double _nZMotionType = 0.0; + if (m_strZMotionType + && m_strZMotionType->Length > 0 + && _GetParameterValue(m_strZMotionType, &_nZMotionType)) + { + CString _str; + _str.Format("PunchState=%d", int(_nZMotionType)); + _strParameter.Append(_str); + } + strParam_ = _strParameter; + } + + AbstractBitPortManager^ GetAbstractBitPortManager() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent("/Kernel0/BitPortManager0"); + } + + private: + Action^ m_action; + String^ m_strPreAction; + bool m_bContinuing; + String^ m_strZMotionType; + }; + + //////////////////////////////////////////////////////////////////////////////// + // 带有后动作的暂停 + // + public ref class TaskPauseCommand_PostAction : public TaskPauseCommand + { + public: + TaskPauseCommand_PostAction():m_bPause(false){} + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + // 样例:PostAction="ClosePort(SPIN) ClosePort(OIL) ClosePort(OUT11) OpenPort(OUT12) Delay(300) ClosePort(OUT12)" + m_strPostAction = addInType_->Element->GetAttribute("PostAction"); + m_action = gcnew Action(this, &TaskPauseCommand_PostAction::Pause); + return __super::Build(addInType_, buildError_); + } + + virtual void Execute(Object^ parameter_) override + { + // 进到这里的认为是暂停命令来了,接下来通道出现的暂停状态是暂停指令的。 ---- 黄海燕 2014-06-20 + _CloseScanCutting(); + m_bPause = true; + __super::Execute(parameter_); + } + + protected: + virtual void Initialize() override + { + __super::Initialize(); + + if (this->AbstrackTask != nullptr) + { + this->AbstrackTask->Owner->StateChanged += gcnew EventHandler(this,&TaskPauseCommand_PostAction::channel_StateChanged); + } + } + + void Pause() + { + try + { + array^ _arraySplitChars = {' ', ';', '\t', '\r', '\n'}; + array^ _arrayActions = m_strPostAction->Split(_arraySplitChars); + for (int _i = 0; _i < _arrayActions->Length; _i++) + { + String^ _strAction = _arrayActions[_i]; + DoAction(_strAction); + } + } + catch (Exception^ e_) + { + MCRuntime::Instance->Application->BeginCall(gcnew Action(this, &TaskPauseCommand_PostAction::ThrowException), gcnew cli::array {e_}); + } + } + + void ThrowException(Exception^ e_) + { + throw gcnew Exception(e_->ToString()); + } + + void DoAction(String^ strAction_) + { + if (strAction_ == nullptr) + { + return; + } + + if (this->AbstractTaskMotion != this->AbstractTaskMotion->Owner->CurrentMotion + || !GetAbstractBitPortManager()->GetBitPort("SBP.MotionGxx")->Value) + { + return; + } + + array^ _arrayTrimChars = {'=', '(', ')'}; + if (strAction_->StartsWith("Delay")) + { + String^ _strDelayTime = strAction_->Substring(5)->Trim(_arrayTrimChars); + ASSERT(_strDelayTime->Length > 0); + int _nDelayMS = 0; + try + { + _nDelayMS = Int32::Parse(_strDelayTime); + } + catch (...) + { + // 支持#打开的方式引用命名变量 ---- 杨开锦 2012-08-29 + ASSERT(_nDelayMS == 0); + ASSERT(_strDelayTime->Substring(0, 1)->Equals("#")); + _nDelayMS = GetNamedParameter_Int32(_strDelayTime->Substring(1)); + } + + Thread::Sleep(_nDelayMS); + } + else if (strAction_->StartsWith("OpenPort")) + { + String^ _strPortIdentifier = strAction_->Substring(8)->Trim(_arrayTrimChars); + GetAbstractBitPortManager()->GetBitPort(_strPortIdentifier)->Value = true; + } + else if (strAction_->StartsWith("ClosePort")) + { + String^ _strPortIdentifier = strAction_->Substring(9)->Trim(_arrayTrimChars); + GetAbstractBitPortManager()->GetBitPort(_strPortIdentifier)->Value = false; + } + else if (strAction_->StartsWith("WaitPort")) + { + String^ _strWaitItem= strAction_->Substring(8)->Trim(_arrayTrimChars); + array^ _arrayParams = _strWaitItem->Split(','); + if (_arrayParams->Length != 2 && _arrayParams->Length != 3) + { + ASSERT(FALSE); + return; + } + + ASSERT(_arrayParams[1] == "0" || _arrayParams[1] == "1"); + String^ _strWaitPortIdentifier = _arrayParams[0]; + bool _bWaitState = (_arrayParams[1] != "0"); + int _nWaitTime = 24 * 3600 * 1000; // 以一天作为无限等待的时间 ---- DingQiang 2012-10-25 + if (_arrayParams->Length == 3) + { + String^ _strWaitTime = _arrayParams[2]; + try + { + _nWaitTime = Int32::Parse(_strWaitTime); + } + catch (...) + { + // 支持#打开的方式引用命名变量 ---- 杨开锦 2012-08-29 + ASSERT(_nWaitTime == 24 * 3600 * 1000); + ASSERT(_strWaitTime->Substring(0, 1)->Equals("#")); + _nWaitTime = GetNamedParameter_Int32(_strWaitTime->Substring(1)); + } + } + + IMCBitPort^ _BitPort = GetAbstractBitPortManager()->GetBitPort(_strWaitPortIdentifier); + if (_BitPort == nullptr) + { + ASSERT(FALSE); + return; + } + + DWORD _nBeginTime = ::GetTickCount(); + while(true) + { + if(_BitPort->Value == _bWaitState) + { + break; + } + + if (::GetTickCount() - _nBeginTime >= (DWORD)_nWaitTime) + { + break; + } + + Thread::Sleep(20); + } + } + else if (strAction_->StartsWith("#")) + { + int _nEqualIndex = strAction_->IndexOf("="); + String^ _strParamName = strAction_->Substring(0, _nEqualIndex)->Trim('#'); + String^ _strValue = strAction_->Substring(_nEqualIndex + 1, strAction_->Length - (_nEqualIndex + 1)); + int _nValue = 0; + if (_strValue->Substring(0, 1) != "#") + { + _nValue = Int32::Parse(_strValue); + } + else + { + _strValue = _strValue->Trim('#'); + _nValue = GetNamedParameter_Int32(_strValue); + } + + SetNamedParameter_Int32(_strParamName, _nValue); + } + } + + AbstractBitPortManager^ GetAbstractBitPortManager() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent("/Kernel0/BitPortManager0"); + } + + void SetNamedParameter_Int32(String^ strParamName_, int nValue_) + { + // Get Parameter Node ---- 杨开锦 2012-08-29 + MCDataManager^ _DataManager = + MCRuntime::Instance != nullptr + && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager : nullptr; + if (_DataManager == nullptr) + { + return; + } + + IParameterNode^ _ParamNode = _DataManager->GetParaemterNode(strParamName_); + if (_ParamNode == nullptr) + { + return; + } + + if (_ParamNode->Value->GetType()->FullName == "System.Int32") + { + _ParamNode->Value = nValue_; + } + else if (_ParamNode->Value->GetType()->FullName == "System.Boolean") + { + _ParamNode->Value = safe_cast(nValue_); + } + } + + int GetNamedParameter_Int32(String^ strParamName_) + { + // Get Parameter Node ---- 杨开锦 2012-08-29 + MCDataManager^ _DataManager = + MCRuntime::Instance != nullptr + && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager : nullptr; + if (_DataManager == nullptr) + { + return 0; + } + + IParameterNode^ _ParamNode = _DataManager->GetParaemterNode(strParamName_); + if (_ParamNode == nullptr) + { + return 0; + } + + // Get Parameter Value ---- 杨开锦 2012-08-29 + int _nParamValue = 0; + if (_ParamNode->Value->GetType()->FullName == "System.Int32") + { + _nParamValue = safe_cast(_ParamNode->Value); + } + else if (_ParamNode->Value->GetType()->FullName == "System.Boolean") + { + bool _bValue = safe_cast(_ParamNode->Value); + if (_bValue) + { + _nParamValue = 1; + } + else + { + _nParamValue = 0; + } + } + + return _nParamValue; + } + + void channel_StateChanged(Object^ sender_, ChannelStateChangeEventArgs^ e_) + { + if (e_->NewState == ChannelState::Running + || e_->NewState == ChannelState::Lock + || e_->NewState == ChannelState::Estop) + { + m_bPause = false; + } + + if (m_bPause && e_->NewState == ChannelState::Pausing) + { + this->m_action->BeginInvoke(nullptr, nullptr); + } + } + + private: + bool m_bPause; // 是否暂停,用于区别停止。 + Action^ m_action; + String^ m_strPostAction; + }; + + //////////////////////////////////////////////////////////////////////////////// + // 带有后动作的暂停,动作通过lua配置而来。 + // ---- 黄海燕 2015-09-22 + public ref class TaskPauseCommand_PostActionInLua : public TaskPauseCommand + { + public: + TaskPauseCommand_PostActionInLua():m_bPause(false){} + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + m_action = gcnew Action(this, &TaskPauseCommand_PostActionInLua::Pause); + m_arrBrachChannels = gcnew array{}; + return __super::Build(addInType_, buildError_); + } + + virtual void Execute(Object^ parameter_) override + { + // 进到这里的认为是暂停命令来了,接下来通道出现的暂停状态是暂停指令的。 ---- 黄海燕 2014-06-20 + m_bPause = true; + __super::Execute(parameter_); + + // 停止其他辅通道的运动。 ---- 黄海燕 2016-01-22 + if (m_arrBrachChannels == nullptr) + return; + for (int _i = 0; _i < m_arrBrachChannels->Length; _i++) + { + Channel^ _chanel = m_arrBrachChannels[_i]; + if (_chanel == nullptr) + continue; + IMotion^ _motion = _chanel->CurrentMotion; + if (_motion != nullptr + && _motion->IsEntered + && !_motion->IsLeaving) + { + _motion->BeginLeave(false,nullptr,nullptr); + } + } + } + + protected: + virtual void Initialize() override + { + __super::Initialize(); + + if (this->AbstrackTask != nullptr) + { + this->AbstrackTask->Owner->StateChanged += gcnew EventHandler(this,&TaskPauseCommand_PostActionInLua::channel_StateChanged); + } + + for (int _i = 0; _i < 10; _i++) + { + String^ _strName = String::Format("BranchChannel{0}", _i); + Channel^ _channel = this->MCRefComponentManager->GetComponent(_strName); + if (_channel == nullptr) + break; + m_arrBrachChannels->Resize(m_arrBrachChannels, _i + 1); + m_arrBrachChannels[_i] = _channel; + } + } + + void Pause() + { + CString _strCurLayerParam; + if (!GetCurLayerParam(&_strCurLayerParam)) + { + ASSERT(FALSE); + return; + } + CPPLuaState* _pLuaState = GetPPLuaState(); + if (!_pLuaState) + { + ASSERT(FALSE); + return; + } + + CString _strContinueAction; + if (!_pLuaState->Lua_GetActionCode(_strCurLayerParam, "GetPauseActions", &_strContinueAction) + || _strContinueAction.IsEmpty()) + { + ASSERT(FALSE); + return; + } + + g_sPauseActionParser.Reset(); + g_sPauseActionParser.DoParser(_strContinueAction); + while (!g_sPauseActionParser.IsIdle() + && GetAbstractBitPortManager()->GetBitPort("SBP.MotionGxx")->Value) + { + g_sPauseActionParser.OnStep(); + } + } + + void channel_StateChanged(Object^ sender_, ChannelStateChangeEventArgs^ e_) + { + if (e_->NewState == ChannelState::Running + || e_->NewState == ChannelState::Lock + || e_->NewState == ChannelState::Estop) + { + m_bPause = false; + } + + if (m_bPause && e_->NewState == ChannelState::Pausing) + { + this->m_action->BeginInvoke(nullptr, nullptr); + } + } + + AbstractBitPortManager^ GetAbstractBitPortManager() + { + if (MCRuntime::Instance == nullptr) + { + return nullptr; + } + + return MCRuntime::Instance->GetComponent("/Kernel0/BitPortManager0"); + } + + private: + bool m_bPause; // 是否暂停,用于区别停止。 + Action^ m_action; // 暂停动作。 + array^ m_arrBrachChannels;// 辅助通道。 + }; + + //////////////////////////////////////////////////////////////////////////////// + // 停止全部通道的当前运动的命令 ---- 李涛 2014-12-25 + // + public ref class SystemStopCommand_AllChannel : public CommandBase + { + // 这个停止命令的策略是: + // 1、当主通道有运动的时候,就直接停止主通道的运动,然后主通道运动的NextReady运动来停止其他通道。 + // 2、主通道没有运动的时候,直接停止其他通道的运动。 + // 这样做的原因: + // 1、为什么需要NextReady?因为没有他,有一定几率其他通道停止不下来。分析:只有主通道有运动, + // 辅通道没有运动,点击停止主通道发送End指令,辅通道停止一瞬完成。但是主通道在End指令前恰巧有一条辅通道 + // 运行的命令。这样辅通道就继续运行了。所以需要在NextReady中停止辅通道运动。 + // 2、为什么停止逻辑不是每个通道直接BeginLeave。因为这样做,可能会有卡停止时,卡一会的情况。分析:主通道 + // 停止后运行NextReady,其中执行辅通道BeginLeave。同时,停止的Execute也执行辅通道的BeginLeave。可能 + // 会存在状态更改。导致卡。 ---- 李涛 2014-12-31 + public: + virtual bool CanExecute(Object^ parameter_) override + { + bool _bCanExecute = false; + for (int i = 0;i < m_arrayChannels->Length;i++) + { + Channel^ _curChannel = m_arrayChannels[i]; + if(_curChannel != nullptr) + { + if (_curChannel->ChannelState == ChannelState::Pausing + ||_curChannel->ChannelState == ChannelState::Running) + { + _bCanExecute = true; + } + } + } + + return _bCanExecute; + } + + virtual void Execute(Object^ parameter_) override + { + _CloseScanCutting(); + if (m_IBeginStop != nullptr) + { + m_IBeginStop->BeginStop(); + } + + if(m_mainChannel->CurrentMotion != nullptr + && m_mainChannel->CurrentMotion->IsEntered + && !m_mainChannel->CurrentMotion->IsLeaving) + { + // 在停止主通道之后,下一个主通道NextReady就BeginLeave辅通道。 ---- 黄海燕 2015-11-21 + m_mainChannel->CurrentMotion->BeginLeave(false,nullptr,nullptr); + m_bLeaveBinaryChannel = true; + return; + } + + //停止非m_mainChannel通道正在运行的运动 + for (int i = 0;i < m_arrayChannels->Length;i++) + { + IMotion^ _curMotion = m_arrayChannels[i]->CurrentMotion; + if (_curMotion != nullptr + && _curMotion->IsEntered + && !_curMotion->IsLeaving) + { + if(m_mainChannel->CurrentMotion == _curMotion) + { + continue; + } + _curMotion->BeginLeave(false,nullptr,nullptr); + } + } + } + + protected: + virtual void Initialize() override + { + m_bLeaveBinaryChannel = false; + m_arrayChannels = MCRuntime::Instance->CurrentKernel->Channels; + m_mainChannel = MCRefComponentManager->GetComponent("MainChannel"); + m_IBeginStop = MCRefComponentManager->GetComponent("IBeginStop"); + if(m_mainChannel == nullptr) + { + m_mainChannel = m_arrayChannels[0]; + } + m_mainChannel->CurrentMotionNextReady += gcnew System::EventHandler(_NextReady); + __super::Initialize(); + } + + private: + //主通道 + static Channel^ m_mainChannel; + + //所有通道 + static array^ m_arrayChannels; + + // 开始停止接口 + IBeginStop^ m_IBeginStop; + + // 主通道NextReady来时是否需要BeginLeave辅通道。 + static bool m_bLeaveBinaryChannel = false; + + //一个运动准备好了事件逻辑 + static void _NextReady(Object^ sender_, MotionNextReadyEventArgs^ e_) + { + if (!m_bLeaveBinaryChannel) + return; + + //停止非m_mainChannel通道正在运行的运动。 + for (int i = 0;i < m_arrayChannels->Length;i++) + { + IMotion^ _curMotion = m_arrayChannels[i]->CurrentMotion; + if (_curMotion != nullptr + && _curMotion->IsEntered + && !_curMotion->IsLeaving) + { + if( m_mainChannel->CurrentMotion == _curMotion) + { + continue; + } + _curMotion->BeginLeave(false,nullptr,nullptr); + } + } + m_bLeaveBinaryChannel = false; + } + }; + + //////////////////////////////////////////////////////////////////////////////// + // 奥森迪科停止命令:停止主通道运动和随动仪运动。 ---- 黄海燕 2015-03-24 + // + public ref class SystemStopCommand_Au3tech : public CommandBase + { + public: + virtual bool CanExecute(Object^ parameter_) override + { + bool _bCanExecute = false; + if (m_mainChannel) + { + if (m_mainChannel->ChannelState == ChannelState::Pausing + || m_mainChannel->ChannelState == ChannelState::Running) + { + _bCanExecute = true; + } + } + + mach::CCommandManager* _pCommandManager = mach::GetCommandManager(); + bool _bCanZStop = false; + if (_pCommandManager && _pCommandManager->CanExecute("ZStop", &_bCanZStop)) + { + _bCanExecute |= _bCanZStop; + } + + return _bCanExecute; + } + + virtual void Execute(Object^ parameter_) override + { + // 停止主通道的运动 + if(m_mainChannel + && m_mainChannel->CurrentMotion != nullptr + && m_mainChannel->CurrentMotion->IsEntered + && !m_mainChannel->CurrentMotion->IsLeaving) + { + m_mainChannel->CurrentMotion->BeginLeave(false,nullptr,nullptr); + } + + //停止奥森随动仪的运动。---- 黄海燕 2015-03-24 + mach::CCommandManager* _pCommandManager = mach::GetCommandManager(); + if (_pCommandManager) + { + _pCommandManager->Execute("ZStop"); + } + } + + protected: + virtual void Initialize() override + { + m_mainChannel = MCRefComponentManager->GetComponent("MainChannel"); + __super::Initialize(); + } + + private: + //主通道 + static Channel^ m_mainChannel; + }; + + //////////////////////////////////////////////////////////////////////////////// + // 工件坐标系清零指令,可以配置实现清零时不清本通道中的某些轴,配置方式形如: + // ExcludeAxes="1,2",轴之间只能用逗号隔开。 ---- 黄海燕 2015-03-12 + public ref class CClearWorkCoorZeroCommand : public GWorkcoorCommandAbstract + { + public: + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + String^ _strAxes = addInType_->Element->GetAttribute("ExcludeAxes"); + array^ _arrayAxes =_strAxes->Split(','); + for (int _i = 0; _i < _arrayAxes->Length;_i++) + { + String^ _str = _arrayAxes[_i]; + int _nAxis = -1; + if (INT32::TryParse(_str, _nAxis)) + { + m_nExcludeAxes->Resize(m_nExcludeAxes, _i + 1); + m_nExcludeAxes[_i] = _nAxis; + } + } + + return __super::Build(addInType_, buildError_); + } + + virtual void Execute(Object^ parameter) override + { + TRACE("WorkcoorClearZeroCommand ---> Begin"); + GWorkcoor^ _pWorkCoor = (GWorkcoor^)Coor; + + if (parameter == nullptr) + { + int _nCount = _pWorkCoor->Owner->Axes->Length; + bool _bCanClear = true; + for (int _i = 0; _i < _nCount; _i++) + { + if (m_nExcludeAxes) + { + for (int _j = 0; _j < m_nExcludeAxes->Length; _j++) + { + if (m_nExcludeAxes[_j] == _i) + { + _bCanClear = false; + break; + } + } + } + + if (_bCanClear) + _pWorkCoor->SetWorkcoor(_i, 0); + } + } + else if (parameter != nullptr) + { + int _index = -1; + try + { + _index = Convert::ToInt32(parameter); + } + catch(...) + { + ASSERT(FALSE); + return; + } + + if (_index < 0 && _index >= _pWorkCoor->Owner->Axes->Length) + { + ASSERT(FALSE); + return; + } + + bool _bCanClear = true; + if (m_nExcludeAxes) + { + for (int _j = 0; _j < m_nExcludeAxes->Length; _j++) + { + if (m_nExcludeAxes[_j] == _index) + { + _bCanClear = false; + break; + } + } + } + + if (_bCanClear) + _pWorkCoor->SetWorkcoor(_index, 0); + } + TRACE("WorkcoorClearZeroCommand --->Finsh"); + } + + protected: + array^ m_nExcludeAxes; + }; + + //////////////////////////////////////////////////////////////////////////////// + // 工件坐标、机械坐标同时清零 + public ref class RectTubeClearZeroCommand : public GWorkcoorCommandAbstract + { + public: + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + return __super::Build(addInType_, buildError_); + } + + virtual void Execute(Object^ parameter) override + { + GWorkcoor^ _pWorkCoor = (GWorkcoor^)Coor; + _pWorkCoor->SetWorkcoor(0, 0); + _pWorkCoor->SetWorkcoor(1, 0); + _pWorkCoor->SetWorkcoor(2, 0); + } + }; + + //////////////////////////////////////////////////////////////////////////////// + // Z轴走到指定机械坐标指令。 ---- 黄海燕 2015-07-02 + // + public ref class CMoveToGivenMachCoor : public CommandBase + { + public: + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + String^ _strMotionPath = addInType_->Element->GetAttribute("MotionPath"); + if (_strMotionPath->Length > 0) + m_pZMotion = MCRuntime::Instance == nullptr ? nullptr : MCRuntime::Instance->GetComponent(_strMotionPath); + String^ _strCoor = addInType_->Element->GetAttribute("MachCoor"); + if (_strCoor->Length > 0) + m_strMachCoor = _strCoor; + String^ _strSpeed = addInType_->Element->GetAttribute("Speed"); + if (_strSpeed->Length > 0) + m_strSpeed = _strSpeed; + + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + double _nCoor; + return m_pZMotion && _GetParam(m_strMachCoor, &_nCoor); + } + virtual void Execute(Object^ parameter_) override + { + if (!m_pZMotion || m_strMachCoor->Length == 0) + return; + + double _nMachCoor; + if (!_GetParam(m_strMachCoor, &_nMachCoor)) + return; + + double _nSpeed; + bool _bRet = _GetParam(m_strSpeed, &_nSpeed); + _nSpeed = _bRet ? _nSpeed : 150; + m_pZMotion->MoveToFixPosM(_nMachCoor, _nSpeed); + } + + protected: + String^ m_strMachCoor; + String^ m_strSpeed; + IZMotion^ m_pZMotion; + bool _GetParam(String^ strParam_, double* nParam_) + { + if (strParam_ == nullptr || strParam_->Length == 0) + return false; + + // 解析立即数。 + if (strParam_->Substring(0, 1) != "#") + { + try + { + *nParam_ = Double::Parse(strParam_); + } + catch(...) + { + return false; + } + return true; + } + + String^ _strParamName = strParam_->Substring(1); + MCDataManager^ _DataManager = + MCRuntime::Instance != nullptr + && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager : nullptr; + if (_DataManager == nullptr) + { + return false; + } + + IParameterNode^ _ParamNode = _DataManager->GetParaemterNode(_strParamName); + if (_ParamNode == nullptr) + { + return false; + } + + // 如果是mm/min则统一换算成mm/s。 ---- 黄海燕 2015-07-22 + *nParam_ = _ParamNode->Unit == ParameterUnit::VelocityMinute ? + Double::Parse(_ParamNode->Value->ToString()) / 60.0 : Double::Parse(_ParamNode->Value->ToString()); + return true; + } + }; + + //////////////////////////////////////////////////////////////////////////////// + // Z轴上抬指令。 ---- 黄海燕 2015-09-28 + // + public ref class CZUpDownCommand : public CommandBase + { + public: + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + String^ _strMotionPath = addInType_->Element->GetAttribute("MotionPath"); + if (_strMotionPath->Length > 0) + m_pZMotion = MCRuntime::Instance == nullptr ? nullptr : MCRuntime::Instance->GetComponent(_strMotionPath); + String^ _strCoor = addInType_->Element->GetAttribute("Distance"); + if (_strCoor->Length > 0) + m_strDistance = _strCoor; + String^ _strSpeed = addInType_->Element->GetAttribute("Speed"); + if (_strSpeed->Length > 0) + m_strSpeed = _strSpeed; + + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + double _nCoor; + return m_pZMotion && _GetParam(m_strDistance, &_nCoor); + } + virtual void Execute(Object^ parameter_) override + { + if (!m_pZMotion || m_strDistance->Length == 0) + return; + + double _nDistance; + if (!_GetParam(m_strDistance, &_nDistance)) + return; + + double _nSpeed; + bool _bRet = _GetParam(m_strSpeed, &_nSpeed); + _nSpeed = _bRet ? _nSpeed : 150; + m_pZMotion->MoveGivenDis(_nDistance, _nSpeed); + } + + protected: + String^ m_strDistance; + String^ m_strSpeed; + IZMotion^ m_pZMotion; + bool _GetParam(String^ strParam_, double* nParam_) + { + if (strParam_ == nullptr || strParam_->Length == 0) + return false; + + // 解析立即数。 + if (strParam_->Substring(0, 1) != "#") + { + try + { + *nParam_ = Double::Parse(strParam_); + } + catch(...) + { + return false; + } + return true; + } + + String^ _strParamName = strParam_->Substring(1); + MCDataManager^ _DataManager = + MCRuntime::Instance != nullptr + && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager : nullptr; + if (_DataManager == nullptr) + { + return false; + } + + IParameterNode^ _ParamNode = _DataManager->GetParaemterNode(_strParamName); + if (_ParamNode == nullptr) + { + return false; + } + + // 如果是mm/min则统一换算成mm/s。 ---- 黄海燕 2015-07-22 + *nParam_ = _ParamNode->Unit == ParameterUnit::VelocityMinute ? + Double::Parse(_ParamNode->Value->ToString()) / 60.0 : Double::Parse(_ParamNode->Value->ToString()); + return true; + } + }; + + //////////////////////////////////////////////////////////////////////////////// + // 管材校平指令:根据不同的管材调用不同的校平子程序进行校平。 + // ---- 黄海燕 2016-12-17 + public ref class CAjustHorizonCommand : public CommandBase + { + public: + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + m_strKeyOfTubeType = addInType_->Element->GetAttribute("TubeType"); + + m_strAjustHorCircular = gcnew String(NceGetPrivateProfileString(_T("Tube"), _T("AjustHorCircular"))); + m_strAjustHorRect = gcnew String(NceGetPrivateProfileString(_T("Tube"), _T("AjustHorRect"))); + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + // 通道0位主通道,主通道为空闲时才能执行校平。 ---- 黄海燕 2016-12-17 + return MCRuntime::Instance->CurrentKernel->Channels[0]->ChannelState == ChannelState::Idle; + } + + virtual void Execute(Object^ parameter_) override + { + if (String::IsNullOrEmpty(m_strAjustHorCircular) + || String::IsNullOrEmpty(m_strAjustHorRect)) + return; + + MCDataManager^ _DataManager = + MCRuntime::Instance != nullptr + && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager : nullptr; + if (_DataManager == nullptr) + { + return; + } + + IParameterNode^ _ParamNode = _DataManager->GetParaemterNode(m_strKeyOfTubeType); + if (_ParamNode == nullptr) + { + return; + } + ASSERT(_ParamNode->Value->GetType()->FullName == "System.Int32"); + int _nTubeType = 0; + try + { + _nTubeType = Int32::Parse(_ParamNode->Value->ToString()); + } + catch (...) + { + ASSERT(FALSE); + return; + } + + if (_nTubeType != 0 && _nTubeType != 1) + { + ASSERT(FALSE); + return; + } + + mach::CCommandManager* _pCommandManager = mach::GetCommandManager(); + if (!_pCommandManager) + return; + + CStringA _strCode; + if (_nTubeType == 0) + { + _strCode.Format("G65 P\"%s\" L1\n", m_strAjustHorCircular); + } + else + { + _strCode.Format("G65 P\"%s\" L1\n", m_strAjustHorRect); + } + _pCommandManager->Execute("RunGCode", _strCode, "LPCSTR"); + } + + private: + String^ m_strKeyOfTubeType; + + String^ m_strAjustHorCircular; + String^ m_strAjustHorRect; + }; + + //////////////////////////////////////////////////////////////////////////////// + // 管材分中指令:用于方管分中 + // ---- 黄海燕 2016-12-17 + public ref class CFindMidCommand : public CommandBase + { + public: + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + m_strKeyOfTubeType = addInType_->Element->GetAttribute("TubeType"); + + m_strCodes = gcnew String(NceGetPrivateProfileString(_T("Tube"), _T("FindMidFourSide"))); + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + // 通道0位主通道,主通道为空闲时才能执行分中。 ---- 黄海燕 2016-12-17 + if (MCRuntime::Instance->CurrentKernel->Channels[0]->ChannelState != ChannelState::Idle) + return false; + + MCDataManager^ _DataManager = + MCRuntime::Instance != nullptr + && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager : nullptr; + if (_DataManager == nullptr) + { + return false; + } + + IParameterNode^ _ParamNode = _DataManager->GetParaemterNode(m_strKeyOfTubeType); + if (_ParamNode == nullptr) + { + return false; + } + ASSERT(_ParamNode->Value->GetType()->FullName == "System.Int32"); + int _nTubeType = 0; + try + { + _nTubeType = Int32::Parse(_ParamNode->Value->ToString()); + } + catch (...) + { + ASSERT(FALSE); + return false; + } + + return _nTubeType == 1; + } + + virtual void Execute(Object^ parameter_) override + { + if (String::IsNullOrEmpty(m_strCodes)) + return; + + MCDataManager^ _DataManager = + MCRuntime::Instance != nullptr + && MCRuntime::Instance->DataManager != nullptr + ? MCRuntime::Instance->DataManager : nullptr; + if (_DataManager == nullptr) + { + return; + } + + IParameterNode^ _ParamNode = _DataManager->GetParaemterNode(m_strKeyOfTubeType); + if (_ParamNode == nullptr) + { + return; + } + ASSERT(_ParamNode->Value->GetType()->FullName == "System.Int32"); + int _nTubeType = 0; + try + { + _nTubeType = Int32::Parse(_ParamNode->Value->ToString()); + } + catch (...) + { + ASSERT(FALSE); + return; + } + + mach::CCommandManager* _pCommandManager = mach::GetCommandManager(); + if (!_pCommandManager) + return; + + CStringA _strCode; + _strCode.Format("G65 P\"%s\" L1\n", m_strCodes); + _pCommandManager->Execute("RunGCode", _strCode, "LPCSTR"); + } + + private: + String^ m_strKeyOfTubeType; + + String^ m_strCodes; + }; + + public ref class CCutTubeWorkcoorCommand : public CommandBase + { + public: + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override + { + // 通道0位主通道,主通道为空闲时才能执行分中。 ---- 黄海燕 2016-12-17 + if (MCRuntime::Instance->CurrentKernel->Channels[0]->ChannelState != ChannelState::Idle) + return false; + return true; + } + + virtual void Execute(Object^ parameter_) override + { + CTubeComponent^ _pTube = MCRefComponentManager->GetComponent("TubeComponent"); + _pTube->CutWorkcoor(); + } + }; + + //////////////////////////////////////////////////////////////////////////////// + // 选择加工指令:IDE中的选择加工指令只能用于真实加工, + // 这里重写一个能用于仿真的选择加工的。 ---- 黄海燕 2016-09-03 + public ref class CTaskSelectWithoutDlg : public TaskSelectionWithoutDialog + { + public: + virtual bool CanExecute(Object^ parameter) override + { + return TaskCommandAbstract::CanExecute(parameter) + && this->AbstrackTask->IsIdle + && this->AbstrackTask->Owner != nullptr + && this->AbstrackTask->Owner->ChannelState == ChannelState::Idle + && this->AbstrackTask->CodeFileInformation->IsLoad + && (this->AbstrackTask->Owner->IsRefered || !this->IsRefered) + && this->AbstractTaskMotion != nullptr + && parameter != nullptr + && __super::TryConvert((String^)parameter, nullptr); + } + }; + + //////////////////////////////////////////////////////////////////////////////// + // W轴回原。 + // ---- 黄海燕 2017-05-11 + public ref class CWBackMachineOrgin : public TwoTaskChainCommand + { + public: + virtual bool CanExecute(Object^ parameter) override + { + // 有其中一个通道紧停,则不能执行。 ---- 黄海燕 2017-05-11 + int _nLength = MCRuntime::Instance->CurrentKernel->Channels->Length; + for (int _i = 0; _i < _nLength; _i++) + { + if (MCRuntime::Instance->CurrentKernel->Channels[_i]->ChannelState == ChannelState::Estop) + return false; + } + return __super::CanExecute(parameter); + } + }; + + //////////////////////////////////////////////////////////////////////////// + // NcEditor命令(像菜单那样仅带一个ID的Command命令) ---- 杨开锦 2012-03-01 + // + public ref class CNceCommand : public CommandBase + { + public: + CNceCommand() { m_nID = 0; } + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + Xml::XmlElement^ _xmlElement = addInType_->Element; + String^ _strID = _xmlElement->GetAttribute("ID"); + m_nID = UInt32::Parse(_strID); + ASSERT(m_nID > 0); + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override { return true; } + virtual void Execute(Object^ parameter_) override + { + TRACE("CNceCommand::Execute => ID = 0x%08X(%d)\n", m_nID, m_nID); + AfxGetMainWnd()->SendMessage(WM_COMMAND, m_nID); + } + + protected: + UINT m_nID; // 命令的ID + }; + + //////////////////////////////////////////////////////////////////////////// + // NcEditor命名命令(已注册了名字的Command命令,区别于ID型的命令) ---- 杨开锦 2012-03-01 + // + public ref class CNceNamedCommand : public CommandBase + { + public: + CNceNamedCommand() { m_strTarget = ""; m_strCommand = ""; } + virtual bool Build(IAddInType^ addInType_, String^% buildError_) override + { + Xml::XmlElement^ _xmlElement = addInType_->Element; + m_strTarget = _xmlElement->GetAttribute("Target"); + m_strCommand = _xmlElement->GetAttribute("Command"); + ASSERT(!String::IsNullOrEmpty(m_strTarget) && !String::IsNullOrEmpty(m_strCommand)); + return __super::Build(addInType_, buildError_); + } + + virtual bool CanExecute(Object^ parameter_) override { return true; } + virtual void Execute(Object^ parameter_) override + { + using System::Runtime::InteropServices::Marshal; + const char* _szTarget = (const char*)(Marshal::StringToHGlobalAnsi(m_strTarget)).ToPointer(); + const char* _szCommand = (const char*)(Marshal::StringToHGlobalAnsi(m_strCommand)).ToPointer(); + ASSERT(_szTarget && _szTarget[0] && _szCommand && _szCommand[0]); + TRACE("CNceNamedCommand::Execute => Target = %s, Comand = %s\n", _szTarget, _szCommand); + SendTargetMessage(0/*ID_TARGET_BROADCAST*/, TN_NAMEDCOMMAND, (WPARAM)(PCSTR)_szTarget, (LPARAM)(PCSTR)_szCommand); + Marshal::FreeHGlobal(IntPtr((void*)_szTarget)); + Marshal::FreeHGlobal(IntPtr((void*)_szCommand)); + } + + protected: + String^ m_strTarget; // 目标Target类名 + String^ m_strCommand; // 注册的命令名 + }; +} diff --git a/src/NceParser.cpp b/src/NceParser.cpp new file mode 100644 index 0000000..6a9eb89 --- /dev/null +++ b/src/NceParser.cpp @@ -0,0 +1,2077 @@ +#include "stdafx.h" +#include "ParserModuleHeader.h" +#include "..\NcFile\NcFile.h" +#include "..\CamWrapper\CamHoleWrapper.h" +#include "..\CamWrapper\CamPathWrapper.h" +#include "..\CamWrapper\CamSplineWrapper.h" +#include "..\CamWrapper\CamWrapperSearcher.h" +#include "..\CamWrapper\OverEdgeAdjust.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +using namespace NcInterpAxes3; + +const CHAR c_szScanGxxNodes[] = "ScanCamGxxNodes"; + +////////////////////////////////////////////////////////////////////////// +void RetrieveArcInf(const DPOINT2& nxStart_, const DPOINT2& nxEnd_, double nBulge_, + DPOINT2& nxCenter_, double& nStartAngle_, double& nEndAngle_, double& nRadius_) +{ + DPOINT2 _nxFromTo = nxEnd_ - nxStart_; + double _nChordLen = _nxFromTo.GetLength(); + ASSERT(DOUBLE_GE_ZERO(_nChordLen)); + if (DOUBLE_EQU_ZERO(_nChordLen)) + { + // 弦长比较短的圆弧当作点处理 + nxCenter_ = nxStart_; + nStartAngle_ = 0.; + nEndAngle_ = 0.; + nRadius_ = 0.; + return; + } + + // Central angle + double _nCentralAngle = atan(nBulge_) * 4.0; + ASSERT(DOUBLE_NOT_ZERO(_nCentralAngle)); + + // 1) Radius + double _nRadius = _nChordLen * 0.5 / sin(_nCentralAngle * 0.5); + nRadius_ = fabs(_nRadius); + + // 2) Center + // 2-1) proportional translate + double _nAlpha = _nRadius / _nChordLen; + + DPOINT2 _nxByPropTrans; + _nxByPropTrans.x = _nxFromTo.x * _nAlpha; + _nxByPropTrans.y = _nxFromTo.y * _nAlpha; + + // 2-2) revolving transform + double _nTheta = (c_nPIE - _nCentralAngle) * 0.5; + DPOINT2 _nxByRevTrans; + _nxByRevTrans.x = cos(_nTheta) * _nxByPropTrans.x - sin(_nTheta) * _nxByPropTrans.y; + _nxByRevTrans.y = sin(_nTheta) * _nxByPropTrans.x + cos(_nTheta) * _nxByPropTrans.y; + + // 2-3) Get circle center + nxCenter_.x = nxStart_.x + _nxByRevTrans.x; + nxCenter_.y = nxStart_.y + _nxByRevTrans.y; + + // 3) Start angle + nStartAngle_ = _compute_angle(nxStart_.x - nxCenter_.x, nxStart_.y - nxCenter_.y); + + // 4) End angle + nEndAngle_ = nStartAngle_ + _nCentralAngle; +} + +////////////////////////////////////////////////////////////////////////// +// class CNceParser +////////////////////////////////////////////////////////////////////////// +CNceParser::CNceParser(CParserModule* pParserModule_, const CCodeBuffer* pCodeBuffer_) + : CCodeParser(pParserModule_, pCodeBuffer_) + , m_pCamObject(NULL) + , m_bIsFisrtValidMotion(false) + , m_bPrePostActionValid(false) + , m_bPrelude(true) + , m_pCamWrapperSearcher(NULL) + , m_nSystemMaxSpeed(c_nINVALID_DOUBLE) + , m_bEnableSlowlyStart(false) + , m_nSlowlyStartSumLen(0.) + , m_bScanPath(false) + , m_bMergeable(true) +{ + m_pCamObject = reinterpret_cast(pCodeBuffer_->GetDataBuffer()); + m_pCamParams = reinterpret_cast(pCodeBuffer_->GetCamParams()); + Reset(); +} + +CNceParser::~CNceParser() +{ + m_pCamObject = NULL; + if (NULL != m_pCamWrapperSearcher) + { + delete m_pCamWrapperSearcher; + m_pCamWrapperSearcher = NULL; + } + + while (m_listPreAction.GetCount()) + { + delete m_listPreAction.RemoveHead(); + } + + while (m_listPostAction.GetCount()) + { + delete m_listPostAction.RemoveHead(); + } +} + +////////////////////////////////////////////////////////////////////////// +// public function +void CNceParser::ReadCode() +{ + if (m_pCamObject == NULL || m_nStartID == 0 || m_nEndID == 0) + { + ASSERT(false); + // 强制写加工范围为已完成,此时起始位置与终止位置相同,需多次调整文件位置到完成。 + m_nCurPosToField = FP_RIGHT; + return; + } + + try + { + const_CamObjCollector _pCamObj = m_pCamWrapperSearcher->GetNextCamObj(); + if (_pCamObj != NULL) + AnalyseObject(_pCamObj); + else + { + // 如果未找到Cam对象,则抛出提示信息,并停止解析 ---- duquan 2017-07-10 + // 附:这里只是防止Nce解析死循环,出现这种情况一般是外部传入的加工数据和加工范围不一致 + NcInterpAxes3::ShowMessage(c_szERROR_CAMDADTAOUTRANGE); + throw(CForceStop()); + } + } + catch (CPause) + { + m_bAnalyse = false; + m_nStartID = m_nEntityID; + } +} + +void CNceParser::Reset() +{ + m_nEntityID = 0; + m_nIndexOff = 0; + m_nStartID = 0; + m_nEndID = 0; + m_bAnalyse = false; + __super::Reset(); + + m_bPrelude = true; + reset_ParseParam(m_pInterpEngine); +} + +bool CNceParser::Eof() +{ + // 不通过超出区间来超越文件尾,让调试去尝试到没有区间或加工再结束 ---- 杨开锦 2012-05-14 + return false; +} + +__int64 CNceParser::GetPosition() const +{ + NceFilePos _NcePos; + GetNceFilePos(m_nEntityID, m_nIndexOff, 0., _NcePos); + + return __int64(_NcePos)/*MAKE_NCE_POS(m_nEntityID, m_nIndexOff)*/; +} + +void CNceParser::SetPosition(__int64 nPos_) +{ + NceFilePos _NcePos; + _NcePos = nPos_; + + m_nEntityID = _NcePos.GetID()/*GET_ID_FROM_NCEPOS(nPos_)*/; + m_nIndexOff = _NcePos.GetOffset()/*GET_OFFSET_FROM_NCEPOS(nPos_)*/; +} + +CCodeParser::fieldpos_t CNceParser::GetCurPosField() +{ + // 只使用ID和OFFSET作为比较范围,因为每段NcCode取出来的文件位置的Rate值均为0 + // lingshu 20120226 + NceFilePos _nCurFieldTo, _nCurFieldFrom; + GetNceFilePos(m_CurField.idoff_to.nID, m_CurField.idoff_to.nOffset, 0., _nCurFieldTo); + GetNceFilePos(m_CurField.idoff_from.nID, m_CurField.idoff_from.nOffset, 0., _nCurFieldFrom); + + __int64 _nPos = GetPosition(); + if (_nPos == _nCurFieldTo) + { + // 当from == to时 + ASSERT(m_nCurPosToField == FP_LEFT || m_nCurPosToField == FP_START || m_nCurPosToField == FP_END); + m_nCurPosToField = FP_END; + } + else if (_nPos == _nCurFieldFrom) + { + ASSERT(m_nCurPosToField == FP_LEFT || m_nCurPosToField == FP_START); + m_nCurPosToField = FP_START; + } + else + { + if (m_nCurPosToField == FP_END) + m_nCurPosToField = FP_RIGHT; + } + + return m_nCurPosToField; +} + +void CNceParser::SetField(const LCRO_FIELD& Field_) +{ + __super::SetField(Field_); + m_nStartID = Field_.idoff_from.nID; + m_nEndID = Field_.idoff_to.nID; + m_pParserModule->m_bIsJumping = true; + + // 到来一个新区间,首跳与首PreAction要重置 ---- 杨开锦 2012-05-14 + m_bIsFisrtValidMotion = false; + m_bPrePostActionValid = false; +} + +////////////////////////////////////////////////////////////////////////// +// protected function +void CNceParser::AnalyseGroup(const nce::CCamGroup* pGroup_) +{ + if (NULL == pGroup_) + { + ASSERT(false); + return; + } + + camwrapper::CCamGroupWrapper _CamGroupWrapper(pGroup_); + for (int i = 0, _nCount = _CamGroupWrapper.GetCount(); i < _nCount; ++i) + { + const nce::CCamObject* _pObject = _CamGroupWrapper.GetAt(i); + AnalyseObject(_pObject); + } +} + +void CNceParser::AnalyseObject(const nce::CCamObject* pObject_) +{ + if (NULL == pObject_) + { + ASSERT(false); + return; + } + + ResetSlowStartInfo(); + + switch (pObject_->GetType()) + { + case nce::camhole: + AnalyseHole(reinterpret_cast(pObject_)); + break; + + case nce::campath: + AnalysePath(reinterpret_cast(pObject_)); + break; + + // 不必遍历组内成员,由外部的Searcher负责遍历 lingshu 20120605 + case nce::camgroup: + //_AnalyseGroup(reinterpret_cast(pObject_)); + break; + + case nce::camscanlines: + default: + ASSERT(false); + break; + } +} + +void CNceParser::AnalysePath(const nce::CCamPath* pPath_) +{ + if (NULL == pPath_) + { + ASSERT(false); + return; + } + + ASSERT(m_pParserModule->m_CodePosition.nAnchorType == ANCH_IDOFFSET); + if (!CheckStartField(pPath_->GetID())) + return; + + // 区分是否是扫描切割:扫描切割前会将段数及各段的起点偏移以非字符串形式发送 + m_bScanPath = IsScanCutPath(pPath_); + + // 用于补偿偏心导致的过棱长度 + bool _bEnable = static_cast(m_pParserModule->GetNamedVariable("#NceExtParam1_OverEdgeOffsetEnable")); + nce::CParam* _pParamForMidXOffset = GetAt_ParamVector(m_pCamParams, pPath_->GetParamIndex()); + if (_bEnable) + { + m_pParserModule->m_pOverEdgeAdjust->SetOverEdgeInfo(pPath_, _pParamForMidXOffset); + } + // 使用CCamSplineWrapper(其中支持巡边)对样条的几何信息进行访问 ---- 杨开锦 2015-08-25 + camwrapper::CCamSplineWrapper _CamSplineWrapper(pPath_, m_pParserModule->m_pWCSAdjust); + camwrapper::CCamPathWrapper _CamPathWrapper(pPath_, m_pParserModule->m_pWCSAdjust, m_pParserModule->m_pAngleToArc, m_pParserModule->m_pOverEdgeAdjust, _bEnable); + nce::CParam* _pParam = BeforeAnalysePath(pPath_, &_CamSplineWrapper, _CamPathWrapper.GetStartPoint()); + + VECINT _vecScanGXXIndex; + StopCornerInfo _StopCornerInfo; + if (m_bScanPath) + { + // 扫描切割: + // 1.没有角点停顿 + // 2.没有慢速起步 + // 3.圆扫描时标识可以单轴联动的空程 + GetScanGXXIndex(pPath_, _vecScanGXXIndex); + } + else + { + // 获取角点停顿信息 + GetStopCornerInfo(pPath_, _pParam, _StopCornerInfo); + // 初始化慢速起步信息 + InitSlowStartInfo(); + } + + // 区分是否包含样条:包含样条的路径从字符串中解析加工数据 + if (_CamSplineWrapper.IsSpline()) + { + // 只支持XY平面上的图形 + AnalyseNurbsPath(pPath_, &_CamSplineWrapper, _vecScanGXXIndex, _StopCornerInfo); + } + else + { + AnalyseNormalPath(pPath_, &_CamPathWrapper, _vecScanGXXIndex, _StopCornerInfo); + } + + ResetSlowStartInfo(); + AfterAnalysePath(pPath_, _StopCornerInfo); +} + +void CNceParser::SendCamObjStartRateCode() +{ + // ForwardParser + CNcSendRawInt _NcRawInt(m_pParserModule->m_CodePosition); + short _nRatio = 0; + _NcRawInt.m_nInteger = MAKELONG(_nRatio, RIH_BROKEN_RATIO); + AddTailCode(_NcRawInt); +} + +void CNceParser::SendCamObjEndRateCode() +{ + // ForwardParser + CNcSendRawInt _NcRawInt(m_pParserModule->m_CodePosition); +#define RATIO_MULTIPLE 10000 + short _nRatio = RATIO_MULTIPLE; +#undef RATIO_MULTIPLE + _NcRawInt.m_nInteger = MAKELONG(_nRatio, RIH_BROKEN_RATIO); + AddTailCode(_NcRawInt); +} + +double CNceParser::GetMaxSpeedFromPathParam() +{ + double _nMaxSpeed = m_pParserModule->m_nSpeedGxx; + + if (m_pParserModule->m_nAssignSpeedType == CGCodeMeaning::AS_FILE) + { + if (m_ParamPath.m_FeedRate.IsValid() && DOUBLE_NOT_ZERO(m_ParamPath.m_FeedRate.m_nValue)) + { + _nMaxSpeed = m_ParamPath.m_FeedRate.m_nValue; + __CUT(_nMaxSpeed, 0, m_pParserModule->m_nSpeedG00); + } + } + + return _nMaxSpeed; +} + +void CNceParser::GetSlowlyStartParam(const nce::CParam* pParam_) +{ + ASSERT(pParam_ != NULL); + + // 获取慢速起步图层参数 + m_SlowlyStartLayerParam = SlowlyStartLayerParam(); + if (pParam_->GetKey_DBL("SlowlyStartup") == 1) + { + m_SlowlyStartLayerParam.m_bSlowlyStart = true; + m_SlowlyStartLayerParam.m_nSlowlyStartLen = pParam_->GetKey_DBL("SlowlyStartupDis"); + m_SlowlyStartLayerParam.m_nSlowlyStartSpeed = pParam_->GetKey_DBL("SlowlyStartupSpeed") / 60.0; + ASSERT(m_SlowlyStartLayerParam.m_nSlowlyStartLen >= 0.); + ASSERT(m_SlowlyStartLayerParam.m_nSlowlyStartSpeed >= 0.); + } +} + +void CNceParser::GetPathMergeableParam(const nce::CCamPath* pPath_) +{ + ASSERT(pPath_ != NULL); + + // 获取Path中的运动指令是否可合并 + m_bMergeable = (pPath_->GetKey("MergeNodes").Compare("Disable") == 0) ? false : true; +} + +void CNceParser::GetOverArrisSpeedParam(const nce::CParam* pParam_) +{ + ASSERT(pParam_ != NULL); + + // 仅当加工方管时,才获取过棱速度 ---- duquan 2017-05-07 + CStringA _strTubeParam = pParam_->GetKey("TubeParam"); + if (_strTubeParam.IsEmpty()) + { + ASSERT(IsInvalidDouble(m_pParserModule->m_nOverArrisSpeed)); + return; + } + + ASSERT((_strTubeParam.GetLength() > 2) && (_strTubeParam.Left(1) == "\"") && (_strTubeParam.Right(1) == "\"")); + _strTubeParam = _strTubeParam.Mid(1, _strTubeParam.GetLength() - 2); + ASSERT(_strTubeParam.FindOneOf("=;\"") == -1); + _strTubeParam.Replace('@', '='); + _strTubeParam.Replace('$', ';'); + + CStringA _strType = pParam_->GetKey_FromString(_strTubeParam, "Type"); + ASSERT(!_strType.IsEmpty()); + + // 暂时只支持这几种管材:0为圆管,1为方管,2为椭圆管,3为腰形管 + int _nType = atoi(_strType); + ASSERT((_nType >= 0) && (_nType <= 3)); + if (_nType != 1) + { + m_pParserModule->m_nOverArrisSpeed = c_nINVALID_DOUBLE; + return; + } + + // 把图层的过棱速度由角度转换成弧度 ---- DingQiang 2016-08-25 + if (!pParam_->GetKey("OverArrisSpeed").IsEmpty()) + { + double _nOverArrisSpeed = pParam_->GetKey_DBL("OverArrisSpeed"); + ASSERT(DOUBLE_GREAT_ZERO(_nOverArrisSpeed)); + ASSERT(m_pParserModule->m_pAngleToArc != NULL); + m_pParserModule->m_nOverArrisSpeed = m_pParserModule->m_pAngleToArc->AngleToArc(_nOverArrisSpeed, axis::z) / 60.0; + + // 限制过棱速度不大于旋转轴空程速度 ---- duquan 2016.12.07 + if (m_pParserModule->m_nOverArrisSpeed > m_pParserModule->m_nSpeedG00Rev) + m_pParserModule->m_nOverArrisSpeed = m_pParserModule->m_nSpeedG00Rev; + } +} + +void CNceParser::RetrieveRespPos(const DPOINT3& nxPosBefore_, INTERPDOUBLE* pnxPosAfter_) +{ + (*pnxPosAfter_)[NcInterpAxes3::axis::x] = m_pParserModule->WorkCoorToMachineCoor(nxPosBefore_.x, NcInterpAxes3::axis::x); + (*pnxPosAfter_)[NcInterpAxes3::axis::y] = m_pParserModule->WorkCoorToMachineCoor(nxPosBefore_.y, NcInterpAxes3::axis::y); + (*pnxPosAfter_)[NcInterpAxes3::axis::z] = m_pParserModule->WorkCoorToMachineCoor(nxPosBefore_.z, NcInterpAxes3::axis::z); +} + +void CNceParser::GotoHeadPos(const INTERPDOUBLE& nxDestPos_) +{ + INTERPDOUBLE _nxCurPos = m_pParserModule->m_nxJumpPos; + + // 加载轨迹时当前点无效 + if (IsInvalidDouble(_nxCurPos[axis::x]) || IsInvalidDouble(_nxCurPos[axis::y]) || IsInvalidDouble(_nxCurPos[axis::z])) + return; + + double _nLen = (nxDestPos_ - _nxCurPos).GetLength(); + if (DOUBLE_EQU_ZERO(_nLen)) + return; + + MoveToDestPos(nxDestPos_); +} + +void CNceParser::UpdateCurrentPos(int nID_, int nOffset_) +{ + m_pParserModule->m_CodePosition.nID = m_nEntityID = nID_; + m_pParserModule->m_CodePosition.nOffset = m_nIndexOff = nOffset_; +} + +bool CNceParser::CheckStartField(int nID_) +{ + if (m_bAnalyse) + UpdateCurrentPos(nID_, -1); + else if (m_nStartID == nID_) + { + m_bAnalyse = true; + UpdateCurrentPos(nID_, -1); + } + + return m_bAnalyse; +} + +void CNceParser::CheckEndField(int nID_) +{ + UpdateCurrentPos(nID_, -1); // 用于更新文件位置,更新Field标志 + GetCurPosField(); + if (m_bAnalyse && (m_nEndID == m_nEntityID)) + throw(CPause()); +} + +void CNceParser::GenerateNode(const spline::SplineVector& vectorSplines_, int nNurbsIndex_, int nPointIndex_, nce::CCamPath::NODE& node_) +{ + if (DOUBLE_EQU_ZERO(vectorSplines_[nNurbsIndex_].vecControlPoint[nPointIndex_].nBulge)) + { + ASSERT(0.0 == vectorSplines_[nNurbsIndex_].vecControlPoint[nPointIndex_].nBulge); + node_.nType = nce::CCamPath::nt_line_xy; + node_.nBulge = 0.; + } + else + { + node_.nType = nce::CCamPath::nt_arc_xy; + node_.nBulge = vectorSplines_[nNurbsIndex_].vecControlPoint[nPointIndex_].nBulge; + } + + node_.ptStart = DPOINT3(vectorSplines_[nNurbsIndex_].vecControlPoint[nPointIndex_ - 1].nEndX, + vectorSplines_[nNurbsIndex_].vecControlPoint[nPointIndex_ - 1].nEndY, + 0.); + node_.ptEnd = DPOINT3(vectorSplines_[nNurbsIndex_].vecControlPoint[nPointIndex_].nEndX, + vectorSplines_[nNurbsIndex_].vecControlPoint[nPointIndex_].nEndY, + 0.); +} + +void CNceParser::GenerateNurbsNode(const spline::SplineVector& vectorSplines_, int nNurbsIndex_, NurbsInfo& NurbsInfo_) +{ + // NURBS曲线的幂次 + NurbsInfo_.nLevel = 3; + + // NURBS曲线的节点矢量 + int _nKnotNum = vectorSplines_[nNurbsIndex_].vecKnot.size(); + NurbsInfo_.vecKnot.clear(); + NurbsInfo_.vecKnot.reserve(_nKnotNum); + for (int i = 0; i < _nKnotNum; ++i) + NurbsInfo_.vecKnot.push_back(vectorSplines_[nNurbsIndex_].vecKnot[i]); + + // NURBS曲线的控制点 + int _nPointNum = vectorSplines_[nNurbsIndex_].vecControlPoint.size(); + NurbsInfo_.vecControlPoint.clear(); + NurbsInfo_.vecControlPoint.reserve(_nPointNum); + for (int i = 0; i < _nPointNum; ++i) + { + NurbsInfo_.vecControlPoint.push_back(INTERPDOUBLE(vectorSplines_[nNurbsIndex_].vecControlPoint[i].nEndX, + vectorSplines_[nNurbsIndex_].vecControlPoint[i].nEndY, 0.)); + } + + // NURBS曲线控制点的权值 + NurbsInfo_.vecWeight.clear(); + NurbsInfo_.vecWeight.reserve(_nPointNum); + int _nWeightNum = vectorSplines_[nNurbsIndex_].vecWeight.size(); + for (int i = 0; i < _nWeightNum; ++i) + NurbsInfo_.vecWeight.push_back(vectorSplines_[nNurbsIndex_].vecWeight[i]); +} + +void CNceParser::GenerateSpindleRevCode() +{ + if (m_pParserModule->m_bIgnoreProgSpindleRev) + return; + + int _nSpindleRev = 0; + if (RetrieveSpindleRevFromPathParam(&_nSpindleRev)) + { + CNcChangSpindleRev _NcChangSpindleRev(m_pParserModule->m_CodePosition); + _NcChangSpindleRev.m_nSpindleRev = _nSpindleRev; + _NcChangSpindleRev.m_nType = 0; + AddTailCode(_NcChangSpindleRev); + } +} + +void CNceParser::MotionCodeByNodeType(const nce::CCamPath::NODE& node_, const ScanCutInfo& ScanCutInfo_) +{ + switch (node_.nType) + { + case nce::CCamPath::nt_line_x: + case nce::CCamPath::nt_line_y: + case nce::CCamPath::nt_line_z: + case nce::CCamPath::nt_line_xy: + case nce::CCamPath::nt_line_yz: + case nce::CCamPath::nt_line_zx: + case nce::CCamPath::nt_line_xyz: + LineCode(node_, ScanCutInfo_); + break; + + case nce::CCamPath::nt_arc_xy: + case nce::CCamPath::nt_arc_yz: + case nce::CCamPath::nt_arc_zx: + ArcCode(node_, ScanCutInfo_); + break; + + case nce::CCamPath::nt_circle_xy_cw: + case nce::CCamPath::nt_circle_xy_ccw: + case nce::CCamPath::nt_circle_yz_cw: + case nce::CCamPath::nt_circle_yz_ccw: + case nce::CCamPath::nt_circle_zx_cw: + case nce::CCamPath::nt_circle_zx_ccw: + CircleCode(node_, ScanCutInfo_); + break; + + default: + ASSERT(false); + break; + } +} + +void CNceParser::LineCode(const nce::CCamPath::NODE& node_, const ScanCutInfo& ScanCutInfo_) +{ + ASSERT((node_.nType & nce::CCamPath::nt_line) == nce::CCamPath::nt_line); + ASSERT(node_.nBulge == 0.); + + CNcLine _NcLine(NCFGLINEARINTERP, m_nSystemMaxSpeed, m_pParserModule->m_CodePosition); + _NcLine.m_bIsScanCut = ScanCutInfo_.bIsScanCut; + _NcLine.m_bIsArcScanG0 = ScanCutInfo_.bIsArcScanCutG0; + _NcLine.m_nRadialRadius = ScanCutInfo_.nRadialRadius; + _NcLine.m_bIsMergeable = m_bMergeable; + if (_NcLine.m_bIsArcScanG0) + _NcLine.m_nPlane = ScanCutInfo_.nPlane; + + // 反向解析调整起始终止比率 lingshu 20120222 + if (Reverse_Parse == GetParserDir()) + _NcLine.SetReverseMotion(); + + // 起点和终点 + INTERPDOUBLE _nxStart; + INTERPDOUBLE _nxEnd; + RetrieveRespPos(node_.ptStart, &_nxStart); + RetrieveRespPos(node_.ptEnd, &_nxEnd); + _NcLine.OrigSetStartPos(_nxStart); + _NcLine.OrigSetEndPos(_nxEnd); + + CheckWCSLimit(_nxStart, _nxEnd); + ModifyMotionCodeRate(&_NcLine); + SplitMotionBySlowStart(_NcLine); +} + +void CNceParser::ArcCode(const nce::CCamPath::NODE& node_, const ScanCutInfo& ScanCutInfo_) +{ + ASSERT((node_.nType & nce::CCamPath::nt_arc) == nce::CCamPath::nt_arc); + ASSERT(DOUBLE_NOT_ZERO(node_.nBulge)); + + NC_FUNCTION_TAG _tag = node_.nBulge < 0 ? NCFGARCINTERPCW : NCFGARCINTERPCCW; + CNcArc _NcArc(_tag, m_nSystemMaxSpeed, m_pParserModule->m_CodePosition); + _NcArc.m_nSpiralPitch = 0.; + _NcArc.m_bIsScanCut = ScanCutInfo_.bIsScanCut; + _NcArc.m_bIsMergeable = m_bMergeable; + + // 反向解析调整起始终止比率 lingshu 20120222 + if (Reverse_Parse == GetParserDir()) + _NcArc.SetReverseMotion(); + + // 坐标平面 + GetArcPlane(node_, &_NcArc); + + // 起点和终点 + INTERPDOUBLE _nxStart; + INTERPDOUBLE _nxEnd; + RetrieveRespPos(node_.ptStart, &_nxStart); + RetrieveRespPos(node_.ptEnd, &_nxEnd); + _NcArc.OrigSetStartPos(_nxStart); + _NcArc.OrigSetEndPos(_nxEnd); + ASSERT(_nxStart[_NcArc.m_nPlane.GetThirdAxis()] == _nxEnd[_NcArc.m_nPlane.GetThirdAxis()]); + + // 圆心与起始角、终止角 + int _nAxisX = _NcArc.m_nPlane.GetLeftAxis(); + int _nAxisY = _NcArc.m_nPlane.GetRightAxis(); + DPOINT2 _ptStart(node_.ptStart[_nAxisX], node_.ptStart[_nAxisY]); + DPOINT2 _ptEnd(node_.ptEnd[_nAxisX], node_.ptEnd[_nAxisY]); + DPOINT2 _ptCenter2; + double _nAngleStart = 0.; + double _nAngleEnd = 0.; + double _nRadius = 0.; + RetrieveArcInf(_ptStart, _ptEnd, node_.nBulge, _ptCenter2, _nAngleStart, _nAngleEnd, _nRadius); + + // 检查是否为微小的圆弧,如果是,当作直线处理 ---- duquan 2017-03-29 + // 原因:防止圆弧在修正角度时将微小的劣弧修正为较大的优弧 + if (CheckTinyArc(fabs(_nAngleEnd - _nAngleStart), _nRadius)) + { + nce::CCamPath::NODE _lineNode; + _lineNode.nType = nce::CCamPath::nt_line; + _lineNode.nBulge = 0.; + _lineNode.ptStart = node_.ptStart; + _lineNode.ptEnd = node_.ptEnd; + LineCode(_lineNode, ScanCutInfo_); + return; + } + + DPOINT3 _ptCenter; + _ptCenter[_nAxisX] = _ptCenter2.x; + _ptCenter[_nAxisY] = _ptCenter2.y; + _ptCenter[_NcArc.m_nPlane.GetThirdAxis()] = _nxStart[_NcArc.m_nPlane.GetThirdAxis()]; + INTERPDOUBLE _nxCenter; + RetrieveRespPos(_ptCenter, &_nxCenter); + _NcArc.SetCenterPos(_nxCenter); + + _NcArc.OrigSetStartAngle(_nAngleStart); + _NcArc.OrigSetEndAngle(_nAngleEnd); + _NcArc.SetRadius(_nRadius); + _NcArc.ReviseAngle(); + + CheckWCSLimitForArc(&_NcArc); + ModifyMotionCodeRate(&_NcArc); + SplitMotionBySlowStart(_NcArc); +} + +void CNceParser::CircleCode(const nce::CCamPath::NODE& node_, const ScanCutInfo& ScanCutInfo_) +{ + ASSERT((node_.nType & nce::CCamPath::nt_circle) == nce::CCamPath::nt_circle); + + CNcArc _NcArc(NCFGARCINTERPCCW, m_nSystemMaxSpeed, m_pParserModule->m_CodePosition); + _NcArc.m_nSpiralPitch = 0.; + _NcArc.m_bIsScanCut = ScanCutInfo_.bIsScanCut; + _NcArc.m_bIsMergeable = m_bMergeable; + + // 反向解析调整起始终止比率 lingshu 20120222 + if (Reverse_Parse == GetParserDir()) + _NcArc.SetReverseMotion(); + + // 平面及方向 + GetCirclePlaneAndDirectory(node_, &_NcArc); + + // 起始点、终止点 + INTERPDOUBLE _nxStart; + RetrieveRespPos(node_.ptStart, &_nxStart); + _NcArc.OrigSetStartPos(_nxStart); + _NcArc.OrigSetEndPos(_nxStart); + + // 圆心 + DPOINT3 _ptCenter = node_.ptCenter; + INTERPDOUBLE _nxCenter; + RetrieveRespPos(_ptCenter, &_nxCenter); + _NcArc.SetCenterPos(_nxCenter); + + // 起始角和终止角 + _NcArc.SetRadius(node_.nRadius); + _NcArc.ReviseShape(); + + CheckWCSLimitForArc(&_NcArc); + ModifyMotionCodeRate(&_NcArc); + SplitMotionBySlowStart(_NcArc); +} + +void CNceParser::NurbsCode(NurbsInfo& NurbsInfo_, const ScanCutInfo& ScanCutInfo_) +{ + ASSERT(!NurbsInfo_.vecKnot.empty() && !NurbsInfo_.vecControlPoint.empty()); + ASSERT(NurbsInfo_.vecWeight.empty() || (NurbsInfo_.vecWeight.size() == NurbsInfo_.vecControlPoint.size())); + ASSERT(NurbsInfo_.vecKnot.size() == NurbsInfo_.nLevel + NurbsInfo_.vecControlPoint.size() + 1); + + // 将控制点坐标转换为机械坐标 + int _nPointNum = NurbsInfo_.vecControlPoint.size(); + for (int i = 0; i < _nPointNum; ++i) + { + DPOINT3 _nxTempPoint(NurbsInfo_.vecControlPoint[i][axis::x], NurbsInfo_.vecControlPoint[i][axis::y], NurbsInfo_.vecControlPoint[i][axis::z]); + RetrieveRespPos(_nxTempPoint, &NurbsInfo_.vecControlPoint[i]); + } + + CNcNurbs _NcNurbs(NCFGNURBS, m_nSystemMaxSpeed, m_pParserModule->m_CodePosition); + _NcNurbs.m_bIsScanCut = ScanCutInfo_.bIsScanCut; + _NcNurbs.m_bIsMergeable = m_bMergeable; + _NcNurbs.SetLevel(NurbsInfo_.nLevel); + _NcNurbs.SetKnots(NurbsInfo_.vecKnot); + _NcNurbs.SetControlPoints(NurbsInfo_.vecControlPoint); + _NcNurbs.SetWeights(NurbsInfo_.vecWeight); + + // 反向解析调整起始终止比率 + if (Reverse_Parse == GetParserDir()) + _NcNurbs.SetReverseMotion(); + + // 起点和终点 + _NcNurbs.OrigSetStartPos(NurbsInfo_.vecControlPoint.front()); + _NcNurbs.OrigSetEndPos(NurbsInfo_.vecControlPoint.back()); + + CheckWCSLimitForNurbs(NurbsInfo_.vecControlPoint); + ModifyMotionCodeRate(&_NcNurbs); + + // NURBS曲线:设置参数 + _NcNurbs.SetInterpPeriod(m_pInterpEngine->m_pInterpData->m_nT); + _NcNurbs.SetNurbsParams(); + + SplitMotionBySlowStart(_NcNurbs); +} + +void CNceParser::AddTailCode(CNcCode& NcCode_, bool bIgnoreFP_) +{ + bool _bMotionCode = NcCode_.IsMotion(); + CCodeParser::fieldpos_t _fp = GetCurPosField(); + if (!(_fp & CCodeParser::FP_MIDDLE) && !bIgnoreFP_) + { + if (_bMotionCode) + m_pParserModule->m_nxJumpPos = ((CNcMotion&)NcCode_).MachGetEndPos(); + return; + } + + // 非运动指令允许加入队列?临时处理,防止添加速度指令时修改了m_bIsJumping的值,从而导致不能正确插入 + // 首条跳转指令 lingshu 20120226 + if (m_pParserModule->m_bIsJumping) + { + if (NcCode_.m_nFunTag == NCFGRAPIDTRAVERSE) + return; + m_pParserModule->m_bIsJumping = false; + } + + while (true) + { + if (m_bIsFisrtValidMotion) + break; + + // 第一次遇到有效运动指令时,应做的一些处理 lingshu 20120319 + if (m_pParserModule->m_bIsJumping || !_bMotionCode) + break; + + m_bIsFisrtValidMotion = true; + + // 在整个加工开始的时候,将起始文件范围发送出去,修正记录值 lingshu 20120301 + if (!m_pInterpEngine->IsTracking()) + { + CFilePosition _startFP; + _startFP.nAnchorType = ANCH_IDOFFSET; + _startFP.nID = m_pInterpEngine->m_FieldList.GetHead().idoff_from.nID; + _startFP.nOffset = m_pInterpEngine->m_FieldList.GetHead().idoff_from.nOffset; + _startFP.nRate = m_pInterpEngine->m_FieldList.GetHead().idoff_from.nRate; + + CNcFilePosition _NcFilePos(NCFCFILEPOSITION, _startFP); + m_pParserModule->AddTailCode(_NcFilePos); + } + + if (_bMotionCode) + m_pParserModule->m_nxJumpPos = ((CNcMotion&)NcCode_).MachGetStartPos(); + + if (!m_pInterpEngine->IsTracking()) + { + m_pParserModule->InsertSafeJumpInstruction(); + if (m_bPrelude) + { + m_pParserModule->InsertPreludeCode(); + m_bPrelude = false; + } + + // 第一次进入有效指令时,强行插入preCode + InsertPreActionCode(true); + } + + break; + } + + if (_bMotionCode) + m_pParserModule->m_nxJumpPos = ((CNcMotion&)NcCode_).MachGetEndPos(); + + m_pParserModule->AddTailCode(NcCode_); +} + +bool CNceParser::IsScanCutPath(const nce::CCamPath* pPath_) const +{ + return !(pPath_->GetKey(c_szScanGxxNodes).IsEmpty()); +} + +void CNceParser::GetScanGXXIndex(const nce::CCamPath* pPath_, VECINT& vecGXXIndex_) +{ + vecGXXIndex_.clear(); + + CStringA _strScanFlag = pPath_->GetKey(c_szScanGxxNodes); + if (_strScanFlag.IsEmpty()) + return; + + // 解析GXX对应的索引集 + int _nLength = _strScanFlag.GetLength(); + vecGXXIndex_.reserve(_nLength >> 1); + + int _nStartIndex = 0; + for (int i = 0; i < _nLength; ++i) + { + if (_strScanFlag[i] != ',') + continue; + + CStringA _strSubString = _strScanFlag.Mid(_nStartIndex, i - _nStartIndex); + if (_strSubString.IsEmpty()) + continue; + + vecGXXIndex_.push_back(atoi(_strSubString)); + _nStartIndex = i + 1; + } +} + +void CNceParser::GetNurbsScanCutInfo(const VECINT& vecGXXIndex_, ScanCutInfo& ScanCutInfo_) +{ + ASSERT(m_bScanPath == !vecGXXIndex_.empty()); + if (vecGXXIndex_.empty()) + return; + + // 扫描切割 + ScanCutInfo_.bIsScanCut = true; +} + +void CNceParser::GetScanCutInfo(const camwrapper::CCamPathWrapper* pCamPathWrapper_, + const VECINT& vecGXXIndex_, + int nCurIndex_, + ScanCutInfo& ScanCutInfo_) +{ + ASSERT(m_bScanPath == !vecGXXIndex_.empty()); + + if (vecGXXIndex_.empty()) + return; + + // 扫描切割 + ScanCutInfo_.bIsScanCut = true; + + VECINT::const_iterator _iter = find(vecGXXIndex_.begin(), vecGXXIndex_.end(), nCurIndex_); + if (_iter != vecGXXIndex_.end()) + return; + + if ((0 == nCurIndex_) || (pCamPathWrapper_->GetNodeCount() == nCurIndex_ + 1)) + return; + + nce::CCamPath::NODE _preNode = pCamPathWrapper_->GetNode(nCurIndex_ - 1); + nce::CCamPath::NODE _curNode = pCamPathWrapper_->GetNode(nCurIndex_); + nce::CCamPath::NODE _nextNode = pCamPathWrapper_->GetNode(nCurIndex_ + 1); + + GetScanCutInfo(_preNode, _curNode, _nextNode, ScanCutInfo_); +} + +void CNceParser::GetScanCutInfo(const camwrapper::CCamSplineWrapper* pCamSplineWrapper_, + const VECINT& vecGXXIndex_, + const nce::CCamPath::NODE& curNode_, + int nNurbsIndex_, + int nPointIndex_, + int nCurIndex_, + ScanCutInfo& ScanCutInfo_) +{ + ASSERT(m_bScanPath == !vecGXXIndex_.empty()); + + if (vecGXXIndex_.empty()) + return; + + // 扫描切割 + ScanCutInfo_.bIsScanCut = true; + + VECINT::const_iterator _iter = find(vecGXXIndex_.begin(), vecGXXIndex_.end(), nCurIndex_); + if (_iter != vecGXXIndex_.end()) + return; + + const spline::SplineVector _vecSplines = pCamSplineWrapper_->GetSplines(); + const int _nNodeCount = pCamSplineWrapper_->GetSegmentCount(); + if ((nNurbsIndex_ == 0 && nPointIndex_ == 1) + || (nNurbsIndex_ == _vecSplines.size() - 1 && nPointIndex_ == _vecSplines[nNurbsIndex_].vecControlPoint.size() - 1)) + return; + + // 检查上一个节点 + nce::CCamPath::NODE _preNode; + if (nPointIndex_ > 1) + { + GenerateNode(_vecSplines, nNurbsIndex_, nPointIndex_ - 1, _preNode); + } + else + { + ASSERT(nNurbsIndex_ > 0); + if (!_vecSplines[nNurbsIndex_ - 1].vecKnot.empty()) + return; + + GenerateNode(_vecSplines, nNurbsIndex_ - 1, _vecSplines[nNurbsIndex_ - 1].vecControlPoint.size() - 1, _preNode); + } + + // 检查下一个节点 + nce::CCamPath::NODE _nextNode; + if (nPointIndex_ < static_cast(_vecSplines[nNurbsIndex_].vecControlPoint.size()) - 1) + { + GenerateNode(_vecSplines, nNurbsIndex_, nPointIndex_ + 1, _nextNode); + } + else + { + ASSERT(nNurbsIndex_ < static_cast(_vecSplines.size()) - 1); + if (!_vecSplines[nNurbsIndex_ + 1].vecKnot.empty()) + return; + + GenerateNode(_vecSplines, nNurbsIndex_ + 1, 1, _nextNode); + } + + GetScanCutInfo(_preNode, curNode_, _nextNode, ScanCutInfo_); +} + +void CNceParser::GetScanCutInfo(const nce::CCamPath::NODE& preNode_, + const nce::CCamPath::NODE& curNode_, + const nce::CCamPath::NODE& nextNode_, + ScanCutInfo& ScanCutInfo_) +{ + // 计算前后三段节点的向心向量:如果是直线,则为零向量;如果是圆弧,则为从连接点指向圆心的向量 + INTERPDOUBLE _nxPreEntad = GetArcEntadVector(preNode_, preNode_.ptEnd); + INTERPDOUBLE _nxCurEntad = GetArcEntadVector(curNode_, curNode_.ptStart); + INTERPDOUBLE _nxNextEntad = GetArcEntadVector(nextNode_, nextNode_.ptStart); + + // 满足以下条件才会对圆扫描中的空程进行单轴联动: + // 1.当前段为直线,并且其前一段和后一段都为圆弧 + // 2.前一段和后一段的圆弧半径相同,并且在直线的同一侧 + // 3.前一段和后一段的圆弧与直线相切 + if (DOUBLE_NOT_ZERO(_nxCurEntad.GetLength())) + return; + + if (DOUBLE_EQU_ZERO(_nxPreEntad.GetLength()) || DOUBLE_NOT_ZERO((_nxPreEntad - _nxNextEntad).GetLength())) + return; + + // 判断圆弧与直线相切 + INTERPDOUBLE _nxLineVector = INTERPDOUBLE( + curNode_.ptEnd.x - curNode_.ptStart.x, + curNode_.ptEnd.y - curNode_.ptStart.y, + curNode_.ptEnd.z - curNode_.ptStart.z); + double _nDotProduct = _nxLineVector[axis::x] * _nxNextEntad[axis::x] + + _nxLineVector[axis::y] * _nxNextEntad[axis::y] + + _nxLineVector[axis::z] * _nxNextEntad[axis::z]; + if (DOUBLE_NOT_ZERO(_nDotProduct)) + return; + + // 圆扫描中的直线空程 + ScanCutInfo_.bIsArcScanCutG0 = true; + ScanCutInfo_.nRadialRadius = _nxPreEntad.GetLength(); + + // 获取圆弧所在平面 + ASSERT(preNode_.nType == nextNode_.nType); + switch (preNode_.nType) + { + case nce::CCamPath::nt_arc_xy: + case nce::CCamPath::nt_circle_xy_ccw: + case nce::CCamPath::nt_circle_xy_cw: + ScanCutInfo_.nPlane.SetAxis(axis::x, axis::y); + break; + case nce::CCamPath::nt_arc_yz: + case nce::CCamPath::nt_circle_yz_ccw: + case nce::CCamPath::nt_circle_yz_cw: + ScanCutInfo_.nPlane.SetAxis(axis::y, axis::z); + break; + case nce::CCamPath::nt_arc_zx: + case nce::CCamPath::nt_circle_zx_ccw: + case nce::CCamPath::nt_circle_zx_cw: + ScanCutInfo_.nPlane.SetAxis(axis::z, axis::x); + break; + default: + ASSERT(false); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +// private function +void CNceParser::AnalyseHole(const nce::CCamHole* pHole_) +{ + if (NULL == pHole_) + { + ASSERT(false); + return; + } + + ASSERT(m_pParserModule->m_CodePosition.nAnchorType == ANCH_IDOFFSET); + if (!CheckStartField(pHole_->GetID())) + return; + + camwrapper::CCamHoleWrapper _CamHoleWrapper(pHole_, m_pParserModule->m_pWCSAdjust, m_pParserModule->m_pAngleToArc); + + // 插入安全跳转指令 + INTERPDOUBLE _nxCurPos; + RetrieveRespPos(_CamHoleWrapper.GetStart(), &_nxCurPos); + GotoHeadPos(_nxCurPos); + + double _nEndZ = _CamHoleWrapper.GetEndZ(); + double _nDepth = _CamHoleWrapper.GetDepth(); + double _nInc = pHole_->GetIncreaseDist(); + double _nBack = pHole_->GetBackDist(); + double _nPauseTime = pHole_->GetPauseTime(); // ms + // 根据以上参数确定打孔方式 + + const nce::CParam* _pParam = GetAt_ParamVector(m_pCamParams, pHole_->GetParamIndex()); + ParseParam_Hole(m_pInterpEngine, pHole_, _pParam, &m_ParamHole); + // 1.解析PrePostCode + GetPrePostActionCode(m_ParamHole.m_PreActionCode, m_ParamHole.m_PostActionCode); + UpdateCurrentPos(pHole_->GetID(), 0); + + // 将Cam信息发出去, + SendCamObjInfo(pHole_); + + // 1.1 试图插入preCode + InsertPreActionCode(false); + + m_nSystemMaxSpeed = GetMaxSpeedFromPathParam(); + + // MakeFake for InsertSafeJumpInstruction ---- 杨开锦 2013-02-25 + CNcLine _NcLine_MF(NCFGLINEARINTERP, m_nSystemMaxSpeed, m_pParserModule->m_CodePosition); + CheckWCSLimit(_nxCurPos, _nxCurPos); + _NcLine_MF.OrigSetStartPos(_nxCurPos); + _NcLine_MF.OrigSetEndPos(_nxCurPos); + AddTailCode(_NcLine_MF); + + // 激光打孔,可能只有XY位置信息,直接在上面打一个孔就可以了,用长度为0的NcLine表示 + if (IsInvalidDouble(_nEndZ)) + { + // 更新孔的文件位置。激光打孔的长度为0,携带的文件位置会被删除 + CNcFilePosition _NcFilePos(NCFCFILEPOSITION, m_pParserModule->m_CodePosition); + AddTailCode(_NcFilePos); + // 更新起始比率(正向为0,反向为1) + SendCamObjStartRateCode(); + CNcLine _NcLine(NCFGLINEARINTERP, m_nSystemMaxSpeed, m_pParserModule->m_CodePosition); + CheckWCSLimit(_nxCurPos, _nxCurPos); + _NcLine.OrigSetStartPos(_nxCurPos); + _NcLine.OrigSetEndPos(_nxCurPos); + AddTailCode(_NcLine); + // 更新起始比率(正向为1,反向为0) + SendCamObjEndRateCode(); + } + else + { + // 更新孔的文件位置。激光打孔的长度为0,携带的文件位置会被删除 + CNcFilePosition _NcFilePos(NCFCFILEPOSITION, m_pParserModule->m_CodePosition); + AddTailCode(_NcFilePos); + // 更新起始比率(正向为0,反向为1) + SendCamObjStartRateCode(); + { + INTERPDOUBLE _nxTemp = _nxCurPos; + _nxTemp[NcInterpAxes3::axis::z] -= _nEndZ; + CheckWCSLimit(_nxCurPos, _nxTemp); + CheckWCSLimit(_nxTemp, _nxCurPos); + } + // XY位置,和孔深,是必然存在的有用信息,当缺少其他尺寸信息的时候不进行回退再进给,一刀打到底 + if (IsInvalidDouble(_nInc) || IsInvalidDouble(_nBack)) + { + CNcLine _NcLine(NCFGLINEARINTERP, m_nSystemMaxSpeed, m_pParserModule->m_CodePosition); + _NcLine.OrigSetStartPos(_nxCurPos); + INTERPDOUBLE _nxTemp = _nxCurPos; + _nxTemp[NcInterpAxes3::axis::z] -= _nEndZ; + _NcLine.OrigSetEndPos(_nxTemp); + AddTailCode(_NcLine); + + CNcLine _NcLine2(NCFGRAPIDTRAVERSE, m_pParserModule->m_nSpeedG00, m_pParserModule->m_CodePosition); + _NcLine2.OrigSetStartPos(_nxTemp); + _NcLine2.OrigSetEndPos(_nxCurPos); + AddTailCode(_NcLine2); + } + // 将孔加工参数记为:R = 加工起点, Q = 每次进给的深度, D = 每次进给后回 + // 退的距离,Z = 孔底的目标Z坐标, P = 在孔底的暂停时间。 则孔加工方式大都 + // 为: + // (1)移动到孔上方Z轴安全高度 + // (2)快速移动定位到R点 + // (3)向下加工进给Q切削量深度 + // (4)快速上升D高度 + // (5)向下加工进给D+Q切削深度 + // (6)重复(4)、(5)至到达洞底Z坐标处 + // (7)暂停P毫秒的时间 + // (8)快速上升至Z轴安全高度 + // 在第6步中所说的“至到达洞底Z坐标处”是指,如果向下加工进给时,还没有进给到Q + // (或D+Q)的深度就已经到达洞底,或者进给了Q(或D+Q)的深度后达到了洞底,都将 + // 结束加工进给,进入7步骤。 + else + { + // 目前当前点位置已经是R点 + double _nCurDepth = 0; + double _nCurZ = _nxCurPos[NcInterpAxes3::axis::z]; + // 步骤3 + { + CNcLine _NcLineDown(NCFGLINEARINTERP, m_nSystemMaxSpeed, m_pParserModule->m_CodePosition); + _NcLineDown.OrigSetStartPos(_nxCurPos); + _NcLineDown.OrigSetStartPos(_nCurZ, NcInterpAxes3::axis::z); + _nCurDepth = DOUBLE_GE(_nCurDepth + _nInc, _nDepth) ? _nDepth : _nCurDepth + _nInc; + _nCurZ = _nxCurPos[NcInterpAxes3::axis::z] - _nCurDepth; + _NcLineDown.OrigSetEndPos(_nxCurPos); + _NcLineDown.OrigSetEndPos(_nCurZ, NcInterpAxes3::axis::z); + AddTailCode(_NcLineDown); + } + while (DOUBLE_LESS(_nCurDepth, _nDepth)) + { + // 步骤4 + CNcLine _NcLineUp(NCFGRAPIDTRAVERSE, m_pParserModule->m_nSpeedG00, m_pParserModule->m_CodePosition); + _NcLineUp.OrigSetStartPos(_nxCurPos); + _NcLineUp.OrigSetStartPos(_nCurZ, NcInterpAxes3::axis::z); + _nCurDepth -= _nBack; + _nCurZ = _nxCurPos[NcInterpAxes3::axis::z] - _nCurDepth; + _NcLineUp.OrigSetEndPos(_nxCurPos); + _NcLineUp.OrigSetEndPos(_nCurZ, NcInterpAxes3::axis::z); + AddTailCode(_NcLineUp); + + // 步骤5 + CNcLine _NcLineDown(NCFGLINEARINTERP, m_nSystemMaxSpeed, m_pParserModule->m_CodePosition); + _NcLineDown.OrigSetStartPos(_nxCurPos); + _NcLineDown.OrigSetStartPos(_nCurZ, NcInterpAxes3::axis::z); + _nCurDepth = DOUBLE_GE(_nCurDepth + _nInc + _nBack, _nDepth) ? _nDepth : _nCurDepth + _nInc + _nBack; + _nCurZ = _nxCurPos[NcInterpAxes3::axis::z] - _nCurDepth; + _NcLineDown.OrigSetEndPos(_nxCurPos); + _NcLineDown.OrigSetEndPos(_nCurZ, NcInterpAxes3::axis::z); + AddTailCode(_NcLineDown); + } + + // 步骤7,缺少孔底暂停时间的时候可以不影响打孔 + if (IsValidDouble(_nPauseTime)) + { + CNcPause _NcPause(m_pParserModule->m_CodePosition); + _NcPause.m_nTime = (int)(_nPauseTime); + AddTailCode(_NcPause); + } + + // 步骤8 + { + CNcLine _NcLineUp(NCFGRAPIDTRAVERSE, m_pParserModule->m_nSpeedG00, m_pParserModule->m_CodePosition); + _NcLineUp.OrigSetStartPos(_nxCurPos); + _NcLineUp.OrigSetStartPos(_nCurZ, NcInterpAxes3::axis::z); + _NcLineUp.OrigSetEndPos(_nxCurPos); + ASSERT(DOUBLE_EQU(_NcLineUp.MachGetLength(), _nDepth)); + AddTailCode(_NcLineUp); + } + } + // 更新起始比率(正向为1,反向为0) + SendCamObjEndRateCode(); + } + + // 插入postcode + InsertPostActionCode(); + CheckEndField(pHole_->GetID()); +} + +void CNceParser::AnalyseNormalPath(const nce::CCamPath* pPath_, + const camwrapper::CCamPathWrapper* pCamPathWrapper_, + const VECINT& vecScanGXXIndex_, + StopCornerInfo& StopCornerInfo_) +{ + const int _nNodeCount = pCamPathWrapper_->GetNodeCount(); + for (int i = 0; i < _nNodeCount; ++i) + { + UpdateCurrentPos(pPath_->GetID(), i); + GenerateStopCornerCode(StopCornerInfo_, _nNodeCount, i); + + // 获取扫描切割信息 + ScanCutInfo _ScanCutInfo; + GetScanCutInfo(pCamPathWrapper_, vecScanGXXIndex_, i, _ScanCutInfo); + MotionCodeByNodeType(pCamPathWrapper_->GetNode(i), _ScanCutInfo); + } +} + +void CNceParser::AnalyseNurbsPath(const nce::CCamPath* pPath_, + const camwrapper::CCamSplineWrapper* pCamSplineWrapper_, + const VECINT& vecScanGXXIndex_, + StopCornerInfo& StopCornerInfo_) +{ + const spline::SplineVector& _vecSplines = pCamSplineWrapper_->GetSplines(); + const int _nNodeCount = pCamSplineWrapper_->GetSegmentCount(); + + int _nOffset = 0; + for (int i = 0, _nSize = _vecSplines.size(); i < _nSize; ++i) + { + if (!_vecSplines[i].vecKnot.empty()) + { + // NURBS曲线 + ASSERT(_nOffset < _nNodeCount); + UpdateCurrentPos(pPath_->GetID(), _nOffset++); + GenerateStopCornerCode(StopCornerInfo_, _nNodeCount, _nOffset - 1); + + NurbsInfo _NurbsInfo; + GenerateNurbsNode(_vecSplines, i, _NurbsInfo); + + // 获取扫描切割信息 + ScanCutInfo _ScanCutInfo; + GetNurbsScanCutInfo(vecScanGXXIndex_, _ScanCutInfo); + NurbsCode(_NurbsInfo, _ScanCutInfo); + continue; + } + + // 直线/圆弧 + int _nNodeNum = _vecSplines[i].vecControlPoint.size(); + for (int j = 1; j < _nNodeNum; ++j) + { + ASSERT(_nOffset < _nNodeCount); + UpdateCurrentPos(pPath_->GetID(), _nOffset++); + GenerateStopCornerCode(StopCornerInfo_, _nNodeCount, _nOffset - 1); + + nce::CCamPath::NODE _node; + GenerateNode(_vecSplines, i, j, _node); + + // 获取扫描切割信息 + ScanCutInfo _ScanCutInfo; + GetScanCutInfo(pCamSplineWrapper_, vecScanGXXIndex_, _node, i, j, _nOffset - 1, _ScanCutInfo); + MotionCodeByNodeType(_node, _ScanCutInfo); + } + } + + ASSERT(_nOffset == _nNodeCount); +} + +nce::CParam* CNceParser::BeforeAnalysePath(const nce::CCamPath* pPath_, + const camwrapper::CCamSplineWrapper* pCamSplineWrapper_, + const DPOINT3& ptStartPoint_) +{ + ASSERT(Forward_Parse == GetParserDir()); + + // 插入安全跳转指令 + INTERPDOUBLE _nxCurPos; + RetrieveRespPos(ptStartPoint_, &_nxCurPos); + GotoHeadPos(_nxCurPos); + + // 外部定义的工艺参数 + nce::CParam* _pParam = GetAt_ParamVector(m_pCamParams, pPath_->GetParamIndex()); + ParseParam_Path(m_pInterpEngine, pPath_, _pParam, &m_ParamPath); + + GetPrePostActionCode(m_ParamPath.m_PreActionCode, m_ParamPath.m_PostActionCode); + UpdateCurrentPos(pPath_->GetID(), 0); + + GenerateSpindleRevCode(); + + // 将Cam信息发出去 + SendCamObjInfo(pPath_, pCamSplineWrapper_); + + // 试图插入preCode + InsertPreActionCode(false); + + // 获取系统最大加工速度 + m_nSystemMaxSpeed = GetMaxSpeedFromPathParam(); + + GetSlowlyStartParam(_pParam); + GetPathMergeableParam(pPath_); + GetOverArrisSpeedParam(_pParam); + + return _pParam; +} + +void CNceParser::AfterAnalysePath(const nce::CCamPath* pPath_, StopCornerInfo& StopCornerInfo_) +{ + // 插入postcode + InsertPostActionCode(); + CheckEndField(pPath_->GetID()); + + while (StopCornerInfo_.listStopCornerCode.GetCount()) + { + delete StopCornerInfo_.listStopCornerCode.RemoveHead(); + } +} + +void CNceParser::GetNceFilePos(int nID_, int nOffset_, double nRate_, NceFilePos& NceFilePos_) const +{ + NceFilePos_.SetID(nID_); + NceFilePos_.SetOffset(nOffset_); + NceFilePos_.SetRate(nRate_); +} + +void CNceParser::GetPrePostActionCode(PARAM_CSTRING& PreCode, PARAM_CSTRING& PostCode) +{ + while (m_listPreAction.GetCount()) + delete m_listPreAction.RemoveHead(); + + while (m_listPostAction.GetCount()) + delete m_listPostAction.RemoveHead(); + + if (m_pInterpEngine->IsTracking()) + return; + + if (PreCode.IsValid()) + ParsePrePostAction(PreCode.m_nValue, m_listPreAction); + + if (PostCode.IsValid()) + ParsePrePostAction(PostCode.m_nValue, m_listPostAction); +} + +void CNceParser::ParsePrePostAction(LPCTSTR szParseCode_, NCCODE_LIST& listPrePostCode_) +{ + CStringA _strSource = (CStringA)szParseCode_; + // 不发送有效文件标志位,原因同G00EnterLeave + CFilePosition _CurFP = m_pParserModule->m_CodePosition; + _CurFP.bIsMainParser = false; + if (_strSource.IsEmpty()) + return; + + int _nStart = 0; + int _nEnd = 0; + CStringA _strTemp; + bool _bBreak = false; + int _nIntValue = 0; + float _nDoubleValue = 0.; + char _nCharValue = 0; + CStringA _strOut; + + while (true) + { + if (_bBreak) + break; + + _nEnd = _strSource.Find('\n', _nStart); + if (_nEnd != -1) + { + _strTemp = _strSource.Mid(_nStart, _nEnd - _nStart); + } + else + { + _strTemp = _strSource.Right(_strSource.GetLength() - _nStart); + _strTemp.TrimRight(); + _bBreak = true; + } + + _nStart = _nEnd + 1; + if (_strTemp.IsEmpty()) + continue; + + _strOut.Empty(); + _nIntValue = 0; + int _nAddress = 0; + int _nLevel = 0; + int _nTime = 0; + if (1 == sscanf_s(_strTemp, "OpenPort(%d)", &_nIntValue)) + { + CNcDirectPort _NcDirectPort(_CurFP); + _NcDirectPort.m_nPlcAddress = _nIntValue; + _NcDirectPort.m_bPortValue = 1; + listPrePostCode_.AddTail(_NcDirectPort.Clone()); + } + else if (1 == sscanf_s(_strTemp, "ClosePort(%d)", &_nIntValue)) + { + CNcDirectPort _NcDirectPort(_CurFP); + _NcDirectPort.m_nPlcAddress = _nIntValue; + _NcDirectPort.m_bPortValue = 0; + listPrePostCode_.AddTail(_NcDirectPort.Clone()); + } + else if (1 == sscanf_s(_strTemp, "Delay(%d)", &_nIntValue)) + { + CNcPause _NcPause(_CurFP); + _NcPause.m_nTime = (int)(_nIntValue); + listPrePostCode_.AddTail(_NcPause.Clone()); + } + else if (1 == sscanf_s(_strTemp, "Power(%d)", &_nIntValue)) + { + if (!m_pParserModule->m_bIgnoreProgSpindleRev) + { + if (_strTemp.Right(2) == _T("%)")) + { + _nIntValue = static_cast(m_pParserModule->GetNamedVariable("#SpindlePort_ProgramRpm") * _nIntValue / 100); + CNcChangSpindleRev _NcChangSpindleRev(m_pParserModule->m_CodePosition); + _NcChangSpindleRev.m_nSpindleRev = _nIntValue; + _NcChangSpindleRev.m_nType = 0; + listPrePostCode_.AddTail(_NcChangSpindleRev.Clone()); + } + else + { + CNcChangSpindleRev _NcChangSpindleRev(m_pParserModule->m_CodePosition); + _NcChangSpindleRev.m_nSpindleRev = _nIntValue; + _NcChangSpindleRev.m_nType = 0; + listPrePostCode_.AddTail(_NcChangSpindleRev.Clone()); + } + } + } + else if (1 == sscanf_s(_strTemp, "Pressure(%d)", &_nIntValue)) + { + CNcChangSpindleRev _NcChangSpindleRev(m_pParserModule->m_CodePosition); + _NcChangSpindleRev.m_nSpindleRev = _nIntValue; + _NcChangSpindleRev.m_nType = 1; + listPrePostCode_.AddTail(_NcChangSpindleRev.Clone()); + } + else if (2 == sscanf_s(_strTemp, "PWM(%d,%d)", &_nIntValue, &_nLevel)) + { + ASSERT(_strTemp.Right(2) == _T("%)")); + CNcChangSpindleRev _NcChangSpindleRev(m_pParserModule->m_CodePosition); + _NcChangSpindleRev.m_nSpindleRev = _nIntValue; + _NcChangSpindleRev.m_nType = 2; + listPrePostCode_.AddTail(_NcChangSpindleRev.Clone()); + + _NcChangSpindleRev.m_nSpindleRev = _nLevel; + _NcChangSpindleRev.m_nType = 3; + listPrePostCode_.AddTail(_NcChangSpindleRev.Clone()); + } + else if (1 == sscanf_s(_strTemp, "MaxPower(%d)", &_nIntValue)) + { + CNcChangSpindleRev _NcChangSpindleRev(m_pParserModule->m_CodePosition); + _NcChangSpindleRev.m_nSpindleRev = _nIntValue; + _NcChangSpindleRev.m_nType = 4; + listPrePostCode_.AddTail(_NcChangSpindleRev.Clone()); + } + else if (3 == sscanf_s(_strTemp, "ReservedSVC%d(%d%c", &_nLevel, &_nIntValue, &_nCharValue) && _nCharValue == ')') + { + // 增加备用模拟量指令,Pressure在图层动作中已经被叫做备用模拟量 + // 这里增的备用模拟量都从1开始:备用模拟量1、备用模拟量2....... + // m_nType从11开始,预留10组模拟量。指定ReservedSVC1的m_nType应 + // 为11,ReservedSVC10的m_nType应为20 ---- DingQiang 2015-01-04 + ASSERT(_nLevel >=1 && _nLevel <= 10); + CNcChangSpindleRev _NcChangSpindleRev(m_pParserModule->m_CodePosition); + _NcChangSpindleRev.m_nSpindleRev = _nIntValue; + _NcChangSpindleRev.m_nType = (_nLevel + 10); + listPrePostCode_.AddTail(_NcChangSpindleRev.Clone()); + } + else if (2 == sscanf_s(_strTemp, "ReservedSVC%d(%f)", &_nLevel, &_nDoubleValue)) + { + // 小数扩大10倍再发下去,并且type从20开始计 ---- DingQiang 2016-04-12 + ASSERT(_nLevel >=1 && _nLevel <= 10); + CNcChangSpindleRev _NcChangSpindleRev(m_pParserModule->m_CodePosition); + _NcChangSpindleRev.m_nSpindleRev = static_cast(_nDoubleValue * 10 + 0.5); + _NcChangSpindleRev.m_nType = (_nLevel + 20); + listPrePostCode_.AddTail(_NcChangSpindleRev.Clone()); + } + else if (3 == sscanf_s(_strTemp, "WaitPort(%d,%d,%d)", &_nAddress, &_nLevel, &_nTime)) + { + // 增加等待端口 ---- DingQiang 2012-09-22 + CNcWaitPort _NcWaitPort(_CurFP); + _NcWaitPort.m_nPlcAddress = _nAddress; + _NcWaitPort.m_bPortValue = (_nLevel != 0); + _NcWaitPort.m_nTimeOut = _nTime; + listPrePostCode_.AddTail(_NcWaitPort.Clone()); + } + else if (2 == sscanf_s(_strTemp, "WaitPort(%d,%d)", &_nAddress, &_nLevel)) + { + // 增加等待端口 ---- DingQiang 2012-09-22 + CNcWaitPort _NcWaitPort(_CurFP); + _NcWaitPort.m_nPlcAddress = _nAddress; + _NcWaitPort.m_bPortValue = (_nLevel != 0); + _NcWaitPort.m_nTimeOut = INT_MAX; + listPrePostCode_.AddTail(_NcWaitPort.Clone()); + } + else if (-1 != _strTemp.Find("OpenPort")) + { + int _nS = _strTemp.Find('(') + 1; + int _nE = _strTemp.Find(')'); + _strOut = _strTemp.Mid(_nS, _nE - _nS); + _strOut.TrimLeft(); + _strOut.TrimRight(); + int _nPortAdd = static_cast(m_pParserModule->GetNamedVariable(_strOut)); + CNcDirectPort _NcDirectPort(_CurFP); + _NcDirectPort.m_nPlcAddress = _nPortAdd; + _NcDirectPort.m_bPortValue = 1; + listPrePostCode_.AddTail(_NcDirectPort.Clone()); + } + else if (-1 != _strTemp.Find("ClosePort")) + { + int _nS = _strTemp.Find('(') + 1; + int _nE = _strTemp.Find(')'); + _strOut = _strTemp.Mid(_nS, _nE - _nS); + _strOut.TrimLeft(); + _strOut.TrimRight(); + int _nPortAdd = static_cast(m_pParserModule->GetNamedVariable(_strOut)); + CNcDirectPort _NcDirectPort(_CurFP); + _NcDirectPort.m_nPlcAddress = _nPortAdd; + _NcDirectPort.m_bPortValue = 0; + listPrePostCode_.AddTail(_NcDirectPort.Clone()); + } + else if (-1 != _strTemp.Find("WaitPort")) + { + int _nS = _strTemp.Find('(') + 1; + int _nE = _strTemp.Find(')'); + _strOut = _strTemp.Mid(_nS, _nE - _nS); + _strOut.TrimLeft(); + _strOut.TrimRight(); + + // 端口地址 + _nS = _strOut.Find(','); + CStringA _strPortAdd = _strOut.Left(_nS); + int _nPortAdd = static_cast(m_pParserModule->GetNamedVariable(_strPortAdd)); + _nS += 1; + + // 端口值 + CString _strLevel; + _nE = _strOut.Find(',', _nS); + if (_nE == -1) + { + _strLevel = _strOut.Mid(_nS, _strOut.GetLength() - _nS); + _nLevel = atoi(_strLevel); + _nTime = INT_MAX; + } + else + { + _strLevel = _strOut.Mid(_nS, _nE - _nS); + _nLevel = atoi(_strLevel); + _nE += 1; + + // 等待时间 + CString _strTime = _strOut.Mid(_nE, _strOut.GetLength() - _nE); + _nTime = atoi(_strTime); + } + + CNcWaitPort _NcWaitPort(_CurFP); + _NcWaitPort.m_nPlcAddress = _nPortAdd; + _NcWaitPort.m_bPortValue = (_nLevel != 0); + _NcWaitPort.m_nTimeOut = _nTime; + listPrePostCode_.AddTail(_NcWaitPort.Clone()); + } + else if (-1 != _strTemp.Find("MSG")) + { + CNcSendRawString _NcSendRawString(_CurFP); + + int _nS = _strTemp.Find('(') + 1; + int _nE = _strTemp.Find(')'); + _strOut = _strTemp.Mid(_nS, _nE - _nS); + _NcSendRawString.m_strString = _strOut; + listPrePostCode_.AddTail(_NcSendRawString.Clone()); + } + else if (-1 != _strTemp.Find("Delay")) + { + int _nS = _strTemp.Find('(') + 1; + int _nE = _strTemp.Find(')'); + _strOut = _strTemp.Mid(_nS, _nE - _nS); + _strOut.TrimLeft(); + _strOut.TrimRight(); + int _nTime = static_cast(m_pParserModule->GetNamedVariable(_strOut)); + CNcPause _NcPause(_CurFP); + _NcPause.m_nTime = (int)_nTime; + listPrePostCode_.AddTail(_NcPause.Clone()); + } + } +} + +void CNceParser::InsertPreActionCode(bool bForce_/* = false*/) +{ + if (m_listPreAction.IsEmpty()) + return; + + POSITION _pos = m_listPreAction.GetHeadPosition(); + bool _bNeedClear = false; + + if (!bForce_ && m_bPrePostActionValid) + { + // 非断点继续时判断写入队列 + while (_pos != NULL) + AddTailCode(*m_listPreAction.GetNext(_pos)); + + _bNeedClear = true; + } + else if (bForce_) + { + // 断点继续时当前断点继续所在图形的precode需要强行写入队列 + while (_pos != NULL) + m_pParserModule->AddTailCode(*m_listPreAction.GetNext(_pos)); + + _bNeedClear = true; + // 第一次强行插入PreAction后,意味着以后的Pre_PostAction可以正常插入了 lingshu 20120328 + m_bPrePostActionValid = true; + } + + if (_bNeedClear) + { + while (m_listPreAction.GetCount()) + delete m_listPreAction.RemoveHead(); + } +} + +void CNceParser::InsertPostActionCode() +{ + if (m_listPostAction.IsEmpty()) + return; + + if (m_bPrePostActionValid) + { + POSITION _pos = m_listPostAction.GetHeadPosition(); + while (_pos != NULL) + m_pParserModule->AddTailCode(*m_listPostAction.GetNext(_pos)); + + while (m_listPostAction.GetCount()) + delete m_listPostAction.RemoveHead(); + } +} + +void CNceParser::GetArcPlane(const nce::CCamPath::NODE& node_, CNcArc* pArcCode_) +{ + switch (node_.nType) + { + case nce::CCamPath::nt_arc_xy: + pArcCode_->m_nPlane.SetAxis(axis::x, axis::y); + break; + + case nce::CCamPath::nt_arc_yz: + pArcCode_->m_nPlane.SetAxis(axis::y, axis::z); + break; + + case nce::CCamPath::nt_arc_zx: + pArcCode_->m_nPlane.SetAxis(axis::z, axis::x); + break; + + default: + ASSERT(false); + break; + } +} + +void CNceParser::GetCirclePlaneAndDirectory(const nce::CCamPath::NODE& node_, CNcArc* pArcCode_) +{ + switch (node_.nType) + { + case nce::CCamPath::nt_circle_xy_cw: + pArcCode_->m_nPlane.SetAxis(axis::x, axis::y); + pArcCode_->m_nFunTag = NCFGARCINTERPCW; + break; + + case nce::CCamPath::nt_circle_xy_ccw: + pArcCode_->m_nPlane.SetAxis(axis::x, axis::y); + pArcCode_->m_nFunTag = NCFGARCINTERPCCW; + break; + + case nce::CCamPath::nt_circle_yz_cw: + pArcCode_->m_nPlane.SetAxis(axis::y, axis::z); + pArcCode_->m_nFunTag = NCFGARCINTERPCW; + break; + + case nce::CCamPath::nt_circle_yz_ccw: + pArcCode_->m_nPlane.SetAxis(axis::y, axis::z); + pArcCode_->m_nFunTag = NCFGARCINTERPCCW; + break; + + case nce::CCamPath::nt_circle_zx_cw: + pArcCode_->m_nPlane.SetAxis(axis::z, axis::x); + pArcCode_->m_nFunTag = NCFGARCINTERPCW; + break; + + case nce::CCamPath::nt_circle_zx_ccw: + pArcCode_->m_nPlane.SetAxis(axis::z, axis::x); + pArcCode_->m_nFunTag = NCFGARCINTERPCCW; + break; + + default: + ASSERT(false); + break; + } +} + +bool CNceParser::RetrieveSpindleRevFromPathParam(OUT int* pnSpindleRev_) +{ + int _nSpindleRev = 0; + if (m_ParamPath.m_Power.IsValid() && DOUBLE_NOT_ZERO(m_ParamPath.m_Power.m_nValue)) + { + _nSpindleRev = int(m_ParamPath.m_Power.m_nValue); + _nSpindleRev = static_cast(m_pParserModule->GetNamedVariable("#SpindlePort_ProgramRpm") * _nSpindleRev / 100); + } + else + return false; + + *pnSpindleRev_ = _nSpindleRev; + return true; +} + +bool CNceParser::CheckTinyArc(double nCentralAngle_, double nRadius_) +{ + ASSERT((nCentralAngle_ > 0.) && (nRadius_ > 0.)); + + // 超过1/4圆弧 + if (nCentralAngle_ >= 0.5 * c_nPIE) + return false; + + // 检查弓高误差 + const static double _s_nMaxChordError = 1.e-6; + double _nChordError = nRadius_ - nRadius_ * cos(0.5 * nCentralAngle_); + ASSERT(_nChordError >= 0.); + if (_nChordError > _s_nMaxChordError) + return false; + + return true; +} + +void CNceParser::ModifyMotionCodeRate(CNcMotion* pMotionCode_) +{ + // 根据外部传入的起始和终止比率,修改所在段生成的NcMotion的加工比率 + if ((m_nEntityID == m_CurField.idoff_from.nID) && (m_nIndexOff == m_CurField.idoff_from.nOffset) + && DOUBLE_NOT_ZERO(m_CurField.idoff_from.nRate)) + pMotionCode_->m_MachineField.nFrom = m_CurField.idoff_from.nRate; + + if ((m_nEntityID == m_CurField.idoff_to.nID) && (m_nIndexOff == m_CurField.idoff_to.nOffset) + && DOUBLE_NOT_ZERO(m_CurField.idoff_to.nRate)) + pMotionCode_->m_MachineField.nTo = m_CurField.idoff_to.nRate; +} + +void CNceParser::CheckWCSLimitForArc(const CNcArc* pArcCode_) +{ + if (!IsMainParser()) + return; + + INTERPDOUBLE _nxMCSMin; + INTERPDOUBLE _nxMCSMax; + pArcCode_->GetCoorMinMax(_nxMCSMin, _nxMCSMax); + + CheckWCSLimit(_nxMCSMin, _nxMCSMax); + CheckWCSLimit(_nxMCSMax, _nxMCSMin); +} + +void CNceParser::CheckWCSLimitForNurbs(const VECINTERDOUBLE& vecControlPoint_) +{ + if (!IsMainParser() || vecControlPoint_.empty()) + return; + + INTERPDOUBLE _nxMCSMin = vecControlPoint_.front(); + INTERPDOUBLE _nxMCSMax = vecControlPoint_.front(); + for (int i = 1, _nSize = vecControlPoint_.size(); i < _nSize; ++i) + { + for (int j = axis::x; j <= axis::z; ++j) + { + if (_nxMCSMin[j] > vecControlPoint_[i][j]) + _nxMCSMin[j] = vecControlPoint_[i][j]; + if (_nxMCSMax[j] < vecControlPoint_[i][j]) + _nxMCSMax[j] = vecControlPoint_[i][j]; + } + } + + CheckWCSLimit(_nxMCSMin, _nxMCSMax); + CheckWCSLimit(_nxMCSMax, _nxMCSMin); +} + +void CNceParser::MoveToDestPos(const INTERPDOUBLE& nxDestPos_) +{ + INTERPDOUBLE _nxCurPos = m_pParserModule->m_nxJumpPos; + // 加载轨迹时当前点无效 + if (IsInvalidDouble(_nxCurPos[NcInterpAxes3::axis::x]) + || IsInvalidDouble(_nxCurPos[NcInterpAxes3::axis::y]) + || IsInvalidDouble(_nxCurPos[NcInterpAxes3::axis::z])) + return; + + double _nOffset = (nxDestPos_ - _nxCurPos).GetLength(); + if (DOUBLE_EQU_ZERO(_nOffset)) + return; + + CNcLine _NcLine(NCFGRAPIDTRAVERSE, m_pParserModule->m_nSpeedG00, m_pParserModule->m_CodePosition); + _NcLine.OrigSetStartPos(_nxCurPos); + _NcLine.OrigSetEndPos(nxDestPos_); + _NcLine.m_bFromProgram = false; + AddTailCode(_NcLine); +} + +void CNceParser::SendCamObjInfo(const nce::CCamObject* pCamObject_, const camwrapper::CCamSplineWrapper* pCamSplineWrapper_ /* = NULL */) +{ + // CamType + CNcSendRawString _NcSendRawString(m_pParserModule->m_CodePosition); + static const struct CTItem + { + CString strStringName; + nce::cam_t nEnumName; + } _s_cCTItem[] = + { + {"camobject", nce::camobject}, + {"camhole", nce::camhole}, + {"campath", nce::campath}, + {"camgroup", nce::camgroup}, + {"camscanlines", nce::camscanlines}, + }; + + for (int _i = 0; _i < _countof(_s_cCTItem); _i++) + { + if (pCamObject_->GetType() == _s_cCTItem[_i].nEnumName) + { + _NcSendRawString.m_strString.Format("${ext:CamType=%s}", _s_cCTItem[_i].strStringName); + AddTailCode(_NcSendRawString, true); + break; + } + } + + // CamID + _NcSendRawString.m_strString.Format("${ext:CamID=%d}", pCamObject_->GetID()); + AddTailCode(_NcSendRawString, true); + + // CamParamIndex + _NcSendRawString.m_strString.Format("${ext:CamParamIndex=%d}", pCamObject_->GetParamIndex()); + AddTailCode(_NcSendRawString, true); + + // CamParamString + RecordScanNodePos(pCamObject_, pCamSplineWrapper_); + + // 每次发送200,发多了不行,驱动校验不过 ---- DingQiang 2015-03-14 + const int _nEverySendCounts = 200; + CString _strParamString = pCamObject_->GetParamString(); + int _nSendCounts = 0; + int _nNeedSendCounts = _strParamString.GetLength(); + int _nPackageIndex = 0; + while (_nSendCounts <= _nNeedSendCounts) + { + if (_nNeedSendCounts - _nSendCounts >= _nEverySendCounts) + { + _NcSendRawString.m_strString.Format("${ext:CamParamString%d=%s}", + _nPackageIndex, _strParamString.Mid(_nSendCounts, _nEverySendCounts)); + } + else + { + _NcSendRawString.m_strString.Format("${ext:CamParamString%d=%s}", + _nPackageIndex, _strParamString.Mid(_nSendCounts, _nNeedSendCounts - _nSendCounts)); + } + + AddTailCode(_NcSendRawString, true); + _nSendCounts += _nEverySendCounts; + _nPackageIndex++; + } + + _NcSendRawString.m_strString.Format("${ext:CamParamString%d=%s}", _nPackageIndex,""); + AddTailCode(_NcSendRawString, true); +} + +void CNceParser::RecordScanNodePos(const nce::CCamObject* pCamObject_, const camwrapper::CCamSplineWrapper* pCamSplineWrapper_) +{ + ASSERT(pCamObject_); + if ((pCamObject_->GetType() != nce::campath) || !m_bScanPath) + return; + + nce::CCamPath* _pCamPath = (nce::CCamPath*)pCamObject_; + if (pCamSplineWrapper_ && pCamSplineWrapper_->IsSpline() && (pCamSplineWrapper_->GetSegmentCount() > 0)) + { + // 样条拟合路径 + CString _strKey = "NodeCount"; + CString _strValue; + _strValue.Format("%d", pCamSplineWrapper_->GetSegmentCount()); + _pCamPath->SetKey(_strKey, _strValue); + + _strKey = "NodeDeltaPos"; + _strValue.Empty(); + DPOINT3 _ptStart = _pCamPath->GetStartPoint(); + const spline::SplineVector& _vecSplines = pCamSplineWrapper_->GetSplines(); + ASSERT(DOUBLE_EQU(_ptStart.x, _vecSplines.front().vecControlPoint.front().nEndX)); + ASSERT(DOUBLE_EQU(_ptStart.y, _vecSplines.front().vecControlPoint.front().nEndY)); + for (int i = 0, _nSize = _vecSplines.size(); i < _nSize; ++i) + { + if (_vecSplines[i].vecKnot.empty()) + { + // 直线/圆弧 + int _nNodeNum = _vecSplines[i].vecControlPoint.size(); + for (int j = 0; j < _nNodeNum - 1; ++j) + { + double _nDeltaX = _vecSplines[i].vecControlPoint[j].nEndX - _ptStart.x; + double _nDeltaY = _vecSplines[i].vecControlPoint[j].nEndY - _ptStart.y; + _strValue.AppendFormat("(%.4f,%.4f)", _nDeltaX, _nDeltaY); + } + } + else + { + // NURBS曲线 + ASSERT(!_vecSplines[i].vecControlPoint.empty()); + double _nDeltaX = _vecSplines[i].vecControlPoint.front().nEndX - _ptStart.x; + double _nDeltaY = _vecSplines[i].vecControlPoint.front().nEndY - _ptStart.y; + _strValue.AppendFormat("(%.4f,%.4f)", _nDeltaX, _nDeltaY); + } + } + + _pCamPath->SetKey(_strKey, _strValue); + } + else + { + CString _strKey = "NodeCount"; + CString _strValue; + _strValue.Format("%d", _pCamPath->GetNodeCount()); + _pCamPath->SetKey(_strKey, _strValue); + + _strKey = "NodeDeltaPos"; + _strValue.Empty(); + DPOINT3 _ptStart = _pCamPath->GetStartPoint(); + for (int _i = 0; _i < static_cast(_pCamPath->GetNodeCount()); _i++) + { + DPOINT3 _ptDelta = _pCamPath->GetNode(_i).ptStart - _ptStart; + _strValue.AppendFormat("(%.4f,%.4f)", _ptDelta.x, _ptDelta.y); + } + + _pCamPath->SetKey(_strKey, _strValue); + } +} + +INTERPDOUBLE CNceParser::GetArcEntadVector(const nce::CCamPath::NODE& node_, const DPOINT3& nxConnectPoint_) +{ + INTERPDOUBLE _nxArcEntadVector(0., 0., 0.); + switch (node_.nType) + { + case nce::CCamPath::nt_arc_xy: + case nce::CCamPath::nt_arc_yz: + case nce::CCamPath::nt_arc_zx: + { + int _nFirstIndex = 0; + int _nSecondIndex = 0; + if (nce::CCamPath::nt_arc_xy == node_.nType) + { + _nFirstIndex = axis::x; + _nSecondIndex = axis::y; + } + else if (nce::CCamPath::nt_arc_yz == node_.nType) + { + _nFirstIndex = axis::y; + _nSecondIndex = axis::z; + } + else + { + _nFirstIndex = axis::z; + _nSecondIndex = axis::x; + } + + DPOINT2 _ptStart(node_.ptStart[_nFirstIndex], node_.ptStart[_nSecondIndex]); + DPOINT2 _ptEnd(node_.ptEnd[_nFirstIndex], node_.ptEnd[_nSecondIndex]); + DPOINT2 _ptCenter; + double _nStartAngle = 0.; + double _nEndAngle = 0.; + double _nRadius = 0.; + RetrieveArcInf(_ptStart, _ptEnd, node_.nBulge, _ptCenter, _nStartAngle, _nEndAngle, _nRadius); + + INTERPDOUBLE _nxConnectPoint(nxConnectPoint_.x, nxConnectPoint_.y, nxConnectPoint_.z); + _nxArcEntadVector[_nFirstIndex] = _ptCenter.x - _nxConnectPoint[_nFirstIndex]; + _nxArcEntadVector[_nSecondIndex] = _ptCenter.y - _nxConnectPoint[_nSecondIndex]; + } + break; + + case nce::CCamPath::nt_circle_xy_cw: + case nce::CCamPath::nt_circle_xy_ccw: + case nce::CCamPath::nt_circle_yz_cw: + case nce::CCamPath::nt_circle_yz_ccw: + case nce::CCamPath::nt_circle_zx_cw: + case nce::CCamPath::nt_circle_zx_ccw: + { + _nxArcEntadVector = INTERPDOUBLE( + node_.ptCenter.x - node_.ptStart.x, + node_.ptCenter.y - node_.ptStart.y, + node_.ptCenter.z - node_.ptStart.z); + } + break; + + default: + break; + } + + return _nxArcEntadVector; +} + +void CNceParser::GetStopCornerInfo(const nce::CCamPath* pPath_, const nce::CParam* pParam_, StopCornerInfo& StopCornerInfo_) +{ + // 角点停顿功能 ---- 杨开锦 2015-11-30 + // 在CAM对象中的信息形如 StopCorner=1,5,256; + // 在图层中的信息形如 StopCornerDelay=1000; + StopCornerInfo_.strStopCornerIndex = pPath_->GetKey("StopCorner"); + StopCornerInfo_.nStopCornerIndex = StopCornerInfo_.strStopCornerIndex.IsEmpty() ? -1 : atoi(StopCornerInfo_.strStopCornerIndex); + ASSERT(StopCornerInfo_.nStopCornerIndex == -1 + || StopCornerInfo_.nStopCornerIndex > 0 + && StopCornerInfo_.nStopCornerIndex <= (int)pPath_->GetNodeCount()); + + CStringA _strStopCorner; // 角点停顿的动作写到lua中 ---- 杨开锦 2016-03-09 + ParseParam_GetActionString(m_pInterpEngine, pPath_, pParam_, "getStringCoolingAction", &_strStopCorner); + ParsePrePostAction(_strStopCorner, StopCornerInfo_.listStopCornerCode); +} + +void CNceParser::GenerateStopCornerCode(StopCornerInfo& StopCornerInfo_, int nNodeCount_, int nNodeIndex_) +{ + if (StopCornerInfo_.nStopCornerIndex != nNodeIndex_) + return; + + // 角点处的停顿算是对下一段的加工预处理,即,理解为先要冷却再开始切下一段 ---- 杨开锦 2015-11-30 + if (m_bPrePostActionValid) + { + POSITION _pos = StopCornerInfo_.listStopCornerCode.GetHeadPosition(); + while (_pos) + { + AddTailCode(*StopCornerInfo_.listStopCornerCode.GetNext(_pos)); + } + } + + StopCornerInfo_.nStopCornerIndex = StopCornerInfo_.strStopCornerIndex.Find(","); + if (StopCornerInfo_.nStopCornerIndex >= 0) + { + StopCornerInfo_.strStopCornerIndex = StopCornerInfo_.strStopCornerIndex.Mid(StopCornerInfo_.nStopCornerIndex + 1); + StopCornerInfo_.nStopCornerIndex = StopCornerInfo_.strStopCornerIndex.IsEmpty() ? -1 : atoi(StopCornerInfo_.strStopCornerIndex); + } + + ASSERT(StopCornerInfo_.nStopCornerIndex == -1 + || StopCornerInfo_.nStopCornerIndex > 0 + && StopCornerInfo_.nStopCornerIndex <= nNodeCount_); +} + +void CNceParser::InitSlowStartInfo() +{ + ASSERT(IsValidDouble(m_nSystemMaxSpeed) && DOUBLE_GREAT_ZERO(m_nSystemMaxSpeed)); + + // 慢速起步生效条件: + // 1.正向解析 + // 2.启用慢速起步功能 + // 3.慢速起步距离大于零 + // 4.慢速起步速度大于零 + // 5.慢速起步速度小于系统允许的最大速度 + m_bEnableSlowlyStart = (GetParserDir() == Forward_Parse) + && m_pInterpEngine->m_pInterpData->m_bSlowlyStart + && m_SlowlyStartLayerParam.m_bSlowlyStart + && DOUBLE_GREAT_ZERO(m_SlowlyStartLayerParam.m_nSlowlyStartLen) + && DOUBLE_GREAT_ZERO(m_SlowlyStartLayerParam.m_nSlowlyStartSpeed) + && DOUBLE_LESS(m_SlowlyStartLayerParam.m_nSlowlyStartSpeed, m_nSystemMaxSpeed); + m_nSlowlyStartSumLen = 0.; +} + +void CNceParser::ResetSlowStartInfo() +{ + m_bEnableSlowlyStart = false; + m_nSlowlyStartSumLen = 0.; +} + +void CNceParser::SplitMotionBySlowStart(CNcMotion& MotionCode_) +{ + // 断点继续时跳过已经加工的段 + if (!(GetCurPosField() & CCodeParser::FP_MIDDLE)) + { + m_pParserModule->m_nxJumpPos = MotionCode_.MachGetEndPos(); + return; + } + + if (!m_bEnableSlowlyStart || DOUBLE_GE(m_nSlowlyStartSumLen, m_SlowlyStartLayerParam.m_nSlowlyStartLen)) + { + AddTailCode(MotionCode_); + return; + } + + ASSERT(!MotionCode_.IsConverseMotion()); + if (DOUBLE_LE(m_nSlowlyStartSumLen + MotionCode_.MachGetLength(), m_SlowlyStartLayerParam.m_nSlowlyStartLen)) + { + // 将运动指令的最大速度调整为慢速起步速度 + ASSERT(DOUBLE_LE(m_SlowlyStartLayerParam.m_nSlowlyStartSpeed, MotionCode_.m_nMaxSpeed)); + MotionCode_.m_nMaxSpeed = m_SlowlyStartLayerParam.m_nSlowlyStartSpeed; + m_nSlowlyStartSumLen += MotionCode_.MachGetLength(); + AddTailCode(MotionCode_); + return; + } + + double _nSplitLength = m_SlowlyStartLayerParam.m_nSlowlyStartLen - m_nSlowlyStartSumLen; + ASSERT(DOUBLE_GREAT_ZERO(_nSplitLength) && DOUBLE_LESS(_nSplitLength, MotionCode_.MachGetLength())); + m_nSlowlyStartSumLen += _nSplitLength; + SplitMotionByLength(this, MotionCode_, _nSplitLength); +} diff --git a/src/NestProfessorDlg.cpp b/src/NestProfessorDlg.cpp new file mode 100644 index 0000000..effe60b --- /dev/null +++ b/src/NestProfessorDlg.cpp @@ -0,0 +1,1781 @@ +// ************************************************************************** // +// NestProfessorDlg.cpp : implementation of the CNestProfessorDlg class +// Copyright(c)2016 WeiHong Company. All rights reserved. +// +// Abstract: +// 本文件实现CNestProfessorDlg类。 +// ********************************************* ---- 杨开锦 2016-06-12 ***** // +#include "stdafx.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// 对话框Dialog +CS_T s_szTITLE = _DEFCS(_CSV(16449), + _CHINESE("排版") + _ENGLISH("Nest")); +CS_T s_szTITLE_NoLicense = _DEFCS(_CSV(16449), + _CHINESE("排版 -- [未授权]") + _ENGLISH("Nest -- [No License]")); +CS_T s_szGROUPTEXTPARTS = _DEFCS(_CSV(16449), + _CHINESE("零件") + _ENGLISH("Parts")); +CS_T s_szGROUPTEXTMAT = _DEFCS(_CSV(16449), + _CHINESE("材料") + _ENGLISH("Materials")); +CS_T s_szGROUPTEXTSHEET = _DEFCS(_CSV(16449), + _CHINESE("结果") + _ENGLISH("Sheets")); +CS_T s_szEDIT = _DEFCS(_CSV(16449), + _CHINESE("编辑") + _ENGLISH("Edit")); +CS_T s_szDELETE = _DEFCS(_CSV(16449), + _CHINESE("删除") + _ENGLISH("Delete")); +CS_T s_szNEWMAT = _DEFCS(_CSV(16449), + _CHINESE("新建材料") + _ENGLISH("New Material")); +CS_T s_szIMPORTMAT = _DEFCS(_CSV(16449), + _CHINESE("导入材料") + _ENGLISH("Import Material")); +CS_T s_szSAVESHEET = _DEFCS(_CSV(16449), + _CHINESE("保存结果") + _ENGLISH("Save Sheet")); +CS_T s_szCALCREMMAT = _DEFCS(_CSV(16449), + _CHINESE("生成余料") + _ENGLISH("Calcremmat")); +CS_T s_szSETPARAM = _DEFCS(_CSV(16449), + _CHINESE("参数设置") + _ENGLISH("Setting")); +CS_T s_szEXECUTE = _DEFCS(_CSV(16449), + _CHINESE("开始") + _ENGLISH("Execute")); +CS_T s_szSTOP = _DEFCS(_CSV(16449), + _CHINESE("停止") + _ENGLISH("Stop")); +CS_T s_szOK = _DEFCS(_CSV(16449), + _CHINESE("确定") + _ENGLISH("OK")); +CS_T s_szCANCEL = _DEFCS(_CSV(16449), + _CHINESE("取消") + _ENGLISH("Cancel")); +// 零件ListCtrl +CS_T s_szNP_PARTNAME = _DEFCS(_CSV(16449), + _CHINESE("名称") + _ENGLISH("Name")); +CS_T s_szNP_PARTNESTPRIORITY = _DEFCS(_CSV(16449), + _CHINESE("优先级") + _ENGLISH("Priority")); +CS_T s_szNP_PARTNESTCOUNT = _DEFCS(_CSV(16449), + _CHINESE("排版数量") + _ENGLISH("Nested")); +CS_T s_szNP_PARTAVAILABLECOUNT = _DEFCS(_CSV(16449), + _CHINESE("可用数量") + _ENGLISH("Available")); +CS_T s_szNP_PARTROTATEANGLE = _DEFCS(_CSV(16449), + _CHINESE("旋转角度") + _ENGLISH("Rotate Angle")); +CS_T s_szNP_PARTSIZE = _DEFCS(_CSV(16449), + _CHINESE("零件尺寸") + _ENGLISH("Part Size")); +CS_T s_szPARTNAME = _DEFCS(_CSV(16449), + _CHINESE("零件%d") + _ENGLISH("Part%d")); +CS_T s_szNESTPART_FREEROTATE = _DEFCS(_CSV(16449), + _CHINESE("随机旋转") + _ENGLISH("Free Rotate")); +CS_T s_szNESTPART_90INCREMENT = _DEFCS(_CSV(16449), + _CHINESE("90°递增") + _ENGLISH("90°Increment")); +CS_T s_szNESTPART_180INCREMENT = _DEFCS(_CSV(16449), + _CHINESE("180°递增") + _ENGLISH("180°Increment")); +CS_T s_szNESTPART_0FIXED = _DEFCS(_CSV(16449), + _CHINESE("0°") + _ENGLISH("0°Fixed")); +CS_T s_szNESTPART_90FIXED = _DEFCS(_CSV(16449), + _CHINESE("90°") + _ENGLISH("90°Fixed")); +CS_T s_szNESTPART_180FIXED = _DEFCS(_CSV(16449), + _CHINESE("180°") + _ENGLISH("180°Fixed")); +CS_T s_szNESTPART_270FIXED = _DEFCS(_CSV(16449), + _CHINESE("270°") + _ENGLISH("270°Fixed")); +// 材料ListCtrl +CS_T s_szNP_MATERIALNAME = _DEFCS(_CSV(16449), + _CHINESE("名称") + _ENGLISH("Name")); +CS_T s_szNP_MATERIALTYPE = _DEFCS(_CSV(16449), + _CHINESE("类型") + _ENGLISH("Type")); +CS_T s_szNP_MATERIALWIDTH = _DEFCS(_CSV(16449), + _CHINESE("宽度") + _ENGLISH("Width")); +CS_T s_szNP_MATERIALHEIGHT = _DEFCS(_CSV(16449), + _CHINESE("高度") + _ENGLISH("Height")); +CS_T s_szNP_MATERIALCOUNT = _DEFCS(_CSV(16449), + _CHINESE("可用数量") + _ENGLISH("Available")); +CS_T s_szNP_MATERIALNESTCOUNT = _DEFCS(_CSV(16449), + _CHINESE("排版数量") + _ENGLISH("Nested")); +CS_T s_szMATERIALNAME = _DEFCS(_CSV(16449), + _CHINESE("材料%d") + _ENGLISH("Material%d")); +CS_T s_szDEFAULTMATERIAL = _DEFCS(_CSV(16449), + _CHINESE("默认材料") + _ENGLISH("Default")); +CS_T s_szNP_RECTANGLEMATERIAL = _DEFCS(_CSV(16449), + _CHINESE("矩形材料") + _ENGLISH("Rectangle")); +// 结果ListCtrl +CS_T s_szNP_SHEETNAME = _DEFCS(_CSV(16449), + _CHINESE("名称") + _ENGLISH("Name")); +CS_T s_szNP_SHEETCOUNT = _DEFCS(_CSV(16449), + _CHINESE("数量") + _ENGLISH("Count")); +CS_T s_szNP_MATNAME = _DEFCS(_CSV(16449), + _CHINESE("材料名称") + _ENGLISH("Material Name")); +CS_T s_szNP_UTILIZATION = _DEFCS(_CSV(16449), + _CHINESE("材料利用率") + _ENGLISH("Utilization")); +CS_T s_szNP_SHEETNAMEFORMAT = _DEFCS(_CSV(16449), + _CHINESE("结果%d") + _ENGLISH("Sheet%d")); +// 提示语 +CS_T s_csNOPART = _DEFCS(_CSV(16449), + _CHINESE("没有零件。") + _ENGLISH("No parts.")); +CS_T s_csNOMATERIAL = _DEFCS(_CSV(16449), + _CHINESE("没有材料。") + _ENGLISH("No materials.")); +CS_T s_csNESTERROR = _DEFCS(_CSV(16449), + _CHINESE("排版失败。") + _ENGLISH("Fail to nest.")); +CS_T s_szNOEFFCTIVELICENCE = _DEFCS(_CSV(16449), + _CHINESE("没有检测到有效的许可证,请联系道软公司。") + _ENGLISH("Valid licence not found. please contact TAOSoft Corporation.")); +CS_T s_szLICENCEISEXPIRED = _DEFCS(_CSV(16449), + _CHINESE("许可证已过期,请联系道软公司。") + _ENGLISH("The licence is expired. please contact TAOSoft Corporation.")); +CS_T s_szCANCELTIPS = _DEFCS(_CSV(16449), + _CHINESE("正在执行排版,不能退出。") + _ENGLISH("Nesting... Can not exit.")); +// Others +CS_T s_szLANGUAGE = _DEFCS(_CSV(16449), + _CHINESE("CHN") + _ENGLISH("ENG")); + +using namespace nce; + +//////////////////////////////////////////////////////////////////////////////// +// Local function declarations ---- DingQiang 2016-06-29 +// +static CString _FormatSize(double nWidth_, double nHeight_, int nLength_); +static bool _IsTimeOut(DWORD nStartTime_, DWORD nCurrentTime_, DWORD& nWaitTime_, bool bResultExist_); +static const CCadObject* _GetAt(const CadObjectList& listCadObject_, int nIndex_); +static int _GetIndex(const CadObjectList& listCadObject_, const CCadObject* pCadObject_); +template static void _UpdateListCtrlSize(ParamVector& vectorNestParams_, size_t nSize_); +static void _UpdateListCtrlData(CParamGroupsListCtrl& wndListCtrl_, CadObjectList& listCadDatas_, ParamVector& vectorNestParams_, CNestProfessorDlg* pDlg_); +static void _UpdateListCtrlSelected(CParamGroupsListCtrl& wndListCtrl_, CadObjectList& listCadDatas_, const CCadObject* pCadSelected_); + +//////////////////////////////////////////////////////////////////////////////// +// CNestParam(s) declarations +// +class CNestParam : public CParam +{ +public: + CCadObject* m_pCadObject; + int m_nIndex; + CNestProfessorDlg* m_pNestProfessorDlg; + CNestParam(CCadObject* pCadObject_) : m_pCadObject(pCadObject_), m_nIndex(0), m_pNestProfessorDlg(NULL) {} + virtual void Serialize(CZipArchive& ar_) { ASSERT(FALSE); __super::Serialize(ar_); }; + virtual const CStringA& GetParamString() const { ASSERT(FALSE); return __super::GetParamString(); } + virtual void SetParamString(PCSTR pszParamStr_) { ASSERT(FALSE); __super::SetParamString(pszParamStr_); } + virtual double GetKey_DBL(PCSTR pszKey_) const { ASSERT(FALSE); return __super::GetKey_DBL(pszKey_); } + virtual void SetKey_DBL(PCSTR pszKey_, double nVal_) { ASSERT(FALSE); __super::SetKey_DBL(pszKey_, nVal_); } +}; + +class CPartParam : public CNestParam +{ +public: + CPartParam(CCadObject* pCadObject_) : CNestParam(pCadObject_) {} + virtual CStringA GetKey(PCSTR pszKey_) const; + virtual void SetKey(PCSTR pszKey_, PCSTR pszVal_); +}; + +class CMaterialParam : public CNestParam +{ +public: + CMaterialParam(CCadObject* pCadObject_) : CNestParam(pCadObject_) {} + virtual CStringA GetKey(PCSTR pszKey_) const; + virtual void SetKey(PCSTR pszKey_, PCSTR pszVal_); +}; + +class CSheetParam : public CNestParam +{ +public: + CSheetParam(CCadObject* pCadObject_) : CNestParam(pCadObject_) {} + virtual CStringA GetKey(PCSTR pszKey_) const; + virtual void SetKey(PCSTR pszKey_, PCSTR pszVal_) { ASSERT(FALSE); __super::SetKey(pszKey_, pszVal_); } +}; + +//////////////////////////////////////////////////////////////////////////////// +// CNestProfessorDlg +// +IMPLEMENT_DYNAMIC(CNestProfessorDlg, CDialog) +BEGIN_MESSAGE_MAP(CNestProfessorDlg, CDialog) + ON_WM_DESTROY() + ON_WM_TIMER() + ON_WM_ENTERIDLE() + ON_MESSAGE(WM_KICKIDLE, OnKickIdle) + ON_NOTIFY_RANGE(LVN_ITEMCHANGED, lst1, lst3, OnItemChanged) + ON_COMMAND(IDC_BTN_EDITPART, OnEditPart) + ON_COMMAND(IDC_BTN_DELETEPART, OnDeletePart) + ON_COMMAND(IDC_BTN_NEWMAT, OnNewMataterial) + ON_COMMAND(IDC_BTN_IMPORTMAT, OnImportMataterial) + ON_COMMAND(IDC_BTN_EDITMAT, OnEditMataterial) + ON_COMMAND(IDC_BTN_DELETEMAT, OnDeleteMataterial) + ON_COMMAND(IDC_BTN_SAVESHEET, OnSaveSheet) + ON_COMMAND(IDC_BTN_CALCREMMAT, OnGenerateRemnant) + ON_COMMAND(IDC_BTN_SETNESTPARAM, OnSetParameter) + ON_COMMAND(IDC_BTN_EXECUTENEST, OnStartOrStop) + ON_UPDATE_COMMAND_UI(IDC_BTN_EXECUTENEST, OnUpdateStartOrStop) + ON_UPDATE_COMMAND_UI(IDOK, OnUpdateOK) +END_MESSAGE_MAP() + +CNestProfessorDlg::CNestProfessorDlg() +: CDialog(IDD_DLG_NESTPROFESSOR) +{ + CStringA _strDMName(_GETCS(s_szDEFAULTMATERIAL)); + memset(m_szDefaultMaterialName, 0, sizeof(m_szDefaultMaterialName)); + strncpy_s(m_szDefaultMaterialName, _strDMName, sizeof(m_szDefaultMaterialName) - 1); + m_nDefaultMaterialWidth = 1500.0; + m_nDefaultMaterialHerght = 3000.0; + LOAD_PARAM(this, CNestProfessorDlg); + + // Default material ---- 杨开锦 2016-06-23 + CCadRectangle* _pRectMat = new CCadRectangle; + ASSERT(_pRectMat); + _pRectMat->SetLocation(DPOINT2(0.0, 0.0)); + _pRectMat->SetWidth(m_nDefaultMaterialWidth); + _pRectMat->SetHeight(m_nDefaultMaterialHerght); + CCadGroup* _pHull = new CCadGroup; + _pHull->PushBack(_pRectMat); + _pHull->SetKey_DBL("ID", (UINT_PTR)_pHull); + _pHull->SetKey_DBL("Count", 1); + _pHull->SetKey("MaterialName", m_szDefaultMaterialName); + _pHull->SetKey("UsedCount", "-"); + m_listMaterials.push_back(_pHull); + + m_pCadSelected = NULL; + memset(m_cacheItems, 0, sizeof(m_cacheItems)); + + // 上来是没有工作线程的,Start的时候才去创建 ---- 杨开锦 2016-06-30 + m_pNestProcessor = NULL; +} + +CNestProfessorDlg::~CNestProfessorDlg() +{ + if (m_listMaterials.size() > 0) + { + CCadGroup* _pGroup = (CCadGroup*)m_listMaterials.front(); + ASSERT(_pGroup->GetType() == cadgroup); + ASSERT(_pGroup->GetNumOfChild() == 1 && _pGroup->GetAt(0)->GetType() == cadrectangle); + CCadRectangle* _pRectMaterial = (CCadRectangle*)_pGroup->GetAt(0); + ASSERT(_pRectMaterial && _pRectMaterial->GetType() == cadrectangle); + CStringA _strDMName(_pGroup->GetKey("MaterialName")); + memset(m_szDefaultMaterialName, 0, sizeof(m_szDefaultMaterialName)); + strncpy_s(m_szDefaultMaterialName, _strDMName, sizeof(m_szDefaultMaterialName) - 1); + m_nDefaultMaterialWidth = _pRectMaterial->GetWidth(); + m_nDefaultMaterialHerght = _pRectMaterial->GetHeitht(); + } + SAVE_PARAM(this, CNestProfessorDlg); + + // 零件是按Group来装的,套的Group壳是new出来,按照交给谁谁负责释放空间 ---- 杨开锦 2016-06-22 + while (!m_listParts.empty()) + { + ASSERT(m_listParts.front() && m_listParts.front()->GetType() == cadgroup); + CCadGroup* _pHull = (CCadGroup*)m_listParts.front(); + ASSERT(_pHull && _pHull->GetNumOfChild() > 0); + _pHull->PickOffAll(); + delete _pHull; + _pHull = NULL; + m_listParts.pop_front(); + } + + // 材料本来就是对话框里创建出来的,然后要释放 ---- 杨开锦 2016-06-22 + while (!m_listMaterials.empty()) + { + CCadObject* _pCad = m_listMaterials.front(); + ASSERT(_pCad); + delete _pCad; + _pCad = NULL; + m_listMaterials.pop_front(); + } + + // 套料结果(同样有壳)按理是由外部取掉的,但考虑如果外部不取这里也应该释放 ---- 杨开锦 2016-06-22 + while (!m_listSheets.empty()) + { + ASSERT(m_listSheets.front() && m_listSheets.front()->GetType() == cadgroup); + CCadGroup* _pHull = (CCadGroup*)m_listSheets.front(); + ASSERT(_pHull && _pHull->GetNumOfChild() > 0); + for (int _i = 0; _i < _pHull->GetNumOfChild(); _i++) + { + ASSERT(_pHull->GetAt(_i) && _pHull->GetAt(_i)->GetType() == cadgroup); + ASSERT(((CCadGroup*)_pHull->GetAt(_i))->GetNumOfChild() == 0); // Hull only + } + delete _pHull; + _pHull = NULL; + m_listSheets.pop_front(); + } + + // 用于CParamGroupsListCtrl的ParamVector里面的参数也要释放掉,如果有的话。 ---- 黄海燕 2016-06-30 + while(!m_vectorPartParams.empty()) + { + ASSERT(m_vectorPartParams.back()); + delete m_vectorPartParams.back(); + m_vectorPartParams.pop_back(); + } + while(!m_vectorMaterialParams.empty()) + { + ASSERT(m_vectorMaterialParams.back()); + delete m_vectorMaterialParams.back(); + m_vectorMaterialParams.pop_back(); + } + while(!m_vectorSheetParams.empty()) + { + ASSERT(m_vectorSheetParams.back()); + delete m_vectorSheetParams.back(); + m_vectorSheetParams.pop_back(); + } + + // 回收缓存的预览位图 ---- 杨开锦 2016-06-29 + ClearCache(NULL); + + if (m_pNestProcessor) + { + delete m_pNestProcessor; + m_pNestProcessor = NULL; + } +} + +bool CNestProfessorDlg::SetInput(const CadObjectList* plistParts_) +{ + ASSERT(plistParts_ && plistParts_->size() > 0); + for (CadObjectList::const_iterator _it = plistParts_->begin(); _it != plistParts_->end(); _it++) + { + ASSERT(*_it && (*_it)->GetType() == cadgroup); + ASSERT(((CCadGroup*)*_it)->GetNumOfChild()); + } + + ASSERT(m_listParts.empty()); + m_listParts = *plistParts_; + + // 给零件以默认设置 ---- 杨开锦 2016-06-24 + for (CadObjectList::const_iterator _it = m_listParts.begin(); _it != m_listParts.end(); _it++) + { + CCadObject* _pCadPart = *_it; + ASSERT(_pCadPart && _pCadPart->GetType() == cadgroup); + ASSERT((UINT_PTR)_pCadPart->GetKey_DBL("ID") == (UINT_PTR)_pCadPart); + _pCadPart->SetKey_DBL("Count", 10); + _pCadPart->SetKey_DBL("Priority", 10); + _pCadPart->SetKey_DBL("RotationStyle", 0); + _pCadPart->SetKey("UsedCount", "-"); + } + + return true; +} + +bool CNestProfessorDlg::GetOutput(CadObjectList* plistSheets_) +{ + ASSERT(plistSheets_ && plistSheets_->empty()); + for (CadObjectList::const_iterator _it = plistSheets_->begin(); _it != plistSheets_->end(); _it++) + { + ASSERT(m_listSheets.front() && m_listSheets.front()->GetType() == cadgroup); + CCadGroup* _pHull = (CCadGroup*)m_listSheets.front(); + ASSERT(_pHull && _pHull->GetNumOfChild() > 0); + for (int _i = 0; _i < _pHull->GetNumOfChild(); _i++) + { + ASSERT(_pHull->GetAt(_i) && _pHull->GetAt(_i)->GetType() == cadgroup); + ASSERT(((CCadGroup*)_pHull->GetAt(_i))->GetNumOfChild() == 0); // Hull only + } + } + + ASSERT(m_listSheets.size() > 0); + *plistSheets_ = m_listSheets; + m_listSheets.clear(); // 交给谁谁释放 + return true; +} + +void CNestProfessorDlg::SetItemsText() +{ + SetWindowText(_GETCS(s_szTITLE)); + if (_GETCS(s_szLANGUAGE) == _T("ENG")) + { + // 英文下调整控件长度 ---- DingQiang 2016-07-05 + CRect _rc; + CWnd* _pWnd = GetDlgItem(IDC_STC_GROUPMAT); + _pWnd->GetWindowRect(_rc); + _rc.right += 18; + ScreenToClient(_rc); + _pWnd->MoveWindow(_rc); + _pWnd = GetDlgItem(IDC_STC_GROUPSHEET); + _pWnd->GetWindowRect(_rc); + _rc.right += 8; + ScreenToClient(_rc); + _pWnd->MoveWindow(_rc); + } + SetDlgItemText(IDC_STC_GROUPPART, _GETCS(s_szGROUPTEXTPARTS)); + SetDlgItemText(IDC_STC_GROUPMAT, _GETCS(s_szGROUPTEXTMAT)); + SetDlgItemText(IDC_STC_GROUPSHEET, _GETCS(s_szGROUPTEXTSHEET)); + SetDlgItemText(IDC_BTN_EDITPART, _GETCS(s_szEDIT)); + SetDlgItemText(IDC_BTN_DELETEPART, _GETCS(s_szDELETE)); + SetDlgItemText(IDC_BTN_NEWMAT, _GETCS(s_szNEWMAT)); + SetDlgItemText(IDC_BTN_IMPORTMAT, _GETCS(s_szIMPORTMAT)); + SetDlgItemText(IDC_BTN_EDITMAT, _GETCS(s_szEDIT)); + SetDlgItemText(IDC_BTN_DELETEMAT, _GETCS(s_szDELETE)); + SetDlgItemText(IDC_BTN_SAVESHEET, _GETCS(s_szSAVESHEET)); + SetDlgItemText(IDC_BTN_CALCREMMAT, _GETCS(s_szCALCREMMAT)); + SetDlgItemText(IDC_BTN_SETNESTPARAM, _GETCS(s_szSETPARAM)); + SetDlgItemText(IDC_BTN_EXECUTENEST, _GETCS(s_szEXECUTE)); + SetDlgItemText(IDOK, _GETCS(s_szOK)); + SetDlgItemText(IDCANCEL, _GETCS(s_szCANCEL)); +} + +// 如果是没有授权,在标题上显示" -- 未授权" +// 调排版函数时可以得到一个关于授权的反馈 +// 除此之外,还可以单独获取授权信息 +// ---- 杨开锦 2017-01-05 +void CNestProfessorDlg::UpdateDlgTitle(int nErrorCode_/* = -1*/) +{ + bool _bNoLicense = (nErrorCode_ == CNestProfessorDoer::CResult::EC_NOLICENSE); + if (nErrorCode_ == -1) + { + nest::LicenseInfo _li; + if (nest::GetLicenseInfo(&_li) == CNestProfessorDoer::CResult::EC_NOLICENSE) + _bNoLicense = true; + } + + CString _strNewTitle = _bNoLicense ? _GETCS(s_szTITLE_NoLicense) : _GETCS(s_szTITLE); + CString _strCurTitle; + GetWindowText(_strCurTitle); + if (_strNewTitle != _strCurTitle) + { + SetWindowText(_strNewTitle); + } +} + +BOOL CNestProfessorDlg::OnInitDialog() +{ + BOOL _bReturn = __super::OnInitDialog(); + + CRect _rcListCtrl(8, 28, 488, 196); + ASSERT(m_listParts.size() > 0); // 一开始应该有零件进来 + InitializeListCtrlParts(); + UpdateListCtrlParts(); + m_wndListCtrlParts.SetAssociatedParamGroups(&m_vectorPartParams); + m_wndListCtrlParts.SetParamGroupsMask(0x7FFFFFFF); + m_wndListCtrlParts.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | LVS_NOSCROLL, _rcListCtrl, this, lst1); + m_wndListCtrlParts.SetColumnWidth(0, 0); // 不显示图层序号。 + m_wndListCtrlParts.SetColumnWidth(1, 0); // 不显示颜色。 + m_wndListCtrlParts.ShowScrollBar(SB_VERT, TRUE); + + _rcListCtrl = CRect(8, 250, 488, 334); + ASSERT(m_listMaterials.size() > 0); // 一开始应该有材料进来 + InitializeListCtrlMaterials(); + UpdateListCtrlMaterials(); + m_wndListCtrlMaterials.SetAssociatedParamGroups(&m_vectorMaterialParams); + m_wndListCtrlMaterials.SetParamGroupsMask(0x7FFFFFFF); + m_wndListCtrlMaterials.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | LVS_NOSCROLL, _rcListCtrl, this, lst2); + m_wndListCtrlMaterials.SetColumnWidth(0, 0); // 不显示图层序号。 + m_wndListCtrlMaterials.SetColumnWidth(1, 0); // 不显示颜色。 + m_wndListCtrlMaterials.ShowScrollBar(SB_VERT, TRUE); + + _rcListCtrl = CRect(8, 388, 488, 493); + ASSERT(m_listSheets.size() == 0); // 一开始没有排版结果 + InitializeListCtrlSheets(); + UpdateListCtrlSheets(); + m_wndListCtrlSheets.SetAssociatedParamGroups(&m_vectorSheetParams); + m_wndListCtrlSheets.SetParamGroupsMask(0x7FFFFFFF); + m_wndListCtrlSheets.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | LVS_NOSCROLL, _rcListCtrl, this, lst3); + m_wndListCtrlSheets.SetColumnWidth(0, 0); // 不显示图层序号。 + m_wndListCtrlSheets.SetColumnWidth(1, 0); // 不显示颜色。 + m_wndListCtrlSheets.ShowScrollBar(SB_VERT, TRUE); + + SetItemsText(); + UpdateDlgTitle(-1); + + // 加载.gif图片 ---- DingQiang 2016-07-01 + m_wndProgress.Load(MAKEINTRESOURCE(IDR_GIF_PROGRESSBAR), _T("GIFTYPE")); + m_wndProgress.Draw(); + + // 100ms定时器 ---- DingQiang 2016-06-30 + SetTimer(1, 100, NULL); + + // 默认显示第一个零件的预览图 ---- 杨开锦 2016-06-29 + m_pCadSelected = m_listParts.front(); + UpdateListCtrlSelected(); + ASSERT(m_pCadSelected && m_listParts.size() > 0 && m_pCadSelected == m_listParts.front()); + UpdatePreview(); + + return _bReturn; +} + +void CNestProfessorDlg::DoDataExchange(CDataExchange* pDX_) +{ + DDX_Control(pDX_, IDC_STC_PREVIEW, m_wndPreview); + DDX_Control(pDX_, IDC_PIC_PROGRESS, m_wndProgress); +} + +void CNestProfessorDlg::OnDestroy() +{ + KillTimer(1); + __super::OnDestroy(); +} + +void CNestProfessorDlg::OnTimer(UINT_PTR nIDEvent_) +{ + static bool _s_bIn = false; + if (_s_bIn) + { + return; + } + _s_bIn = true; + + // 线程运行结束时回收线程 ---- 杨开锦 2016-08-09 + if (m_pNestProcessor && m_pNestProcessor->IsStopped() && !m_pNestProcessor->HasBetterResult()) + { + CNestProfessorDoer::CResult _result; + m_pNestProcessor->GetResult(&_result); + delete m_pNestProcessor; + m_pNestProcessor = NULL; + UpdateDlgTitle(_result.m_nErrorCode); + UpdateDialogControls(this, FALSE); + + if (_result.m_nErrorCode != 0) + { + ASSERT(_result.m_listSheets.empty()); + ASSERT(_result.m_nErrorCode != CNestProfessorDoer::CResult::EC_SUCCESS); + if (_result.m_nErrorCode == CNestProfessorDoer::CResult::EC_NOLICENSE) + AfxMessageBox(_GETCS(s_szNOEFFCTIVELICENCE)); + else if (_result.m_nErrorCode == CNestProfessorDoer::CResult::EC_LICENSEEXPIRED) + AfxMessageBox(_GETCS(s_szLICENCEISEXPIRED)); + else + AfxMessageBox(_GETCS(s_csNESTERROR)); + } + } + + // 内部计算线程算出了更好的结果,及时显示出来 ---- 杨开锦 2016-08-09 + if (m_pNestProcessor && m_pNestProcessor->HasBetterResult()) + { + Update(); + ASSERT(m_pNestProcessor); + if (m_listSheets.size() > 0) + { + m_pCadSelected = m_listSheets.front(); + UpdateListCtrlSelected(); + UpdatePreview(); + } + } + + // 超时自动停止掉,分几档:1分钟、3分钟、10分钟、30分钟 ---- 杨开锦 2016-08-10 + static DWORD _s_nStartTime = -1; + static DWORD _s_nWaitTime = 60 * 1000; + DWORD _nTC = ::GetTickCount(); + bool _bRunning = (m_pNestProcessor != NULL && !m_pNestProcessor->IsStopped()); + bool _bResultExist = m_listSheets.size() > 0; + if (!_bRunning) + { + _s_nStartTime = -1; + _s_nWaitTime = 60 * 1000; + } + if (_bRunning && _s_nStartTime == -1) + { + _s_nStartTime = _nTC; + _s_nWaitTime = 60 * 1000; + } + if (_bRunning && _IsTimeOut(_s_nStartTime, _nTC, _s_nWaitTime, _bResultExist)) + { + Stop(); + _s_nStartTime = -1; + _s_nWaitTime = 60 * 1000; + } + + _s_bIn = false; +} + +void CNestProfessorDlg::OnEnterIdle(UINT nWhy_, CWnd* pWho_) +{ + if (IsWindowVisible()) + UpdateDialogControls(this, FALSE); + __super::OnEnterIdle(nWhy_, pWho_); +} + +LRESULT CNestProfessorDlg::OnKickIdle(WPARAM wParam_, LPARAM lParam_) +{ + if (IsWindowVisible()) + UpdateDialogControls(this, (BOOL)wParam_); + return 0L; +} + +void CNestProfessorDlg::OnItemChanged(UINT nID_, NMHDR* pNMHDR_, LRESULT* pResult_) +{ + ASSERT(nID_ >= lst1 && nID_ <= lst3); + ASSERT(pNMHDR_ && pResult_); + NMLISTVIEW* _pNMListView = (NMLISTVIEW*)pNMHDR_; + if (_pNMListView->iItem == -1) + { + return; + } + + // 控件与数据的关联 ---- DingQiang 2016-07-06 + CadObjectList* _pCadObjectLists[] = {&m_listParts, &m_listMaterials, &m_listSheets}; + CadObjectList* _pCadObjectList = _pCadObjectLists[nID_ - lst1]; + ASSERT(_pCadObjectList); + + // 原来的选中项 ---- DingQiang 2016-07-06 + const CCadObject* _pNewCadObject = m_pCadSelected; + + // 选中新的项 ---- DingQiang 2016-06-30 + int _nLineItem = _pNMListView->iItem; + if (_pNMListView->uNewState & LVIS_SELECTED) + { + ASSERT(!(_pNMListView->uOldState & LVIS_SELECTED)); + const CCadObject* _pCadObject = _GetAt(*_pCadObjectList, _nLineItem); + if (_pNewCadObject != _pCadObject) + { + _pNewCadObject = _pCadObject; + } + } + + // 删除旧的项 ---- DingQiang 2016-06-30 + if (_pNMListView->uOldState & LVIS_SELECTED) + { + ASSERT(!(_pNMListView->uNewState & LVIS_SELECTED)); + const CCadObject* _pCadObject = _GetAt(*_pCadObjectList, _nLineItem); + if (_pNewCadObject == _pCadObject) + { + _pNewCadObject = NULL; + } + } + + if (_pNewCadObject != m_pCadSelected) + { + m_pCadSelected = _pNewCadObject; + UpdatePreview(); + UpdateListCtrlSelected(); + } +} + +void CNestProfessorDlg::OnEditPart() +{ + if (_GetIndex(m_listParts, m_pCadSelected) == -1) + { + // 没有选中对象 ---- DingQiang 2016-07-04 + return; + } + + ASSERT(m_pCadSelected->GetType() == cadgroup); + CCadGroup* _pCadGroup = (CCadGroup*)m_pCadSelected; + ASSERT(_pCadGroup->GetNumOfChild() >= 1); // 至少有一个cad对象 + + // 弹出对话框修改 ---- DingQiang 2016-07-04 + CPartDlg _dlg; + _dlg.SetCount((int)_pCadGroup->GetKey_DBL("Count")); + _dlg.SetPriority((int)_pCadGroup->GetKey_DBL("Priority")); + _dlg.SetRotateAngle((int)_pCadGroup->GetKey_DBL("RotationStyle")); + if (_dlg.DoModal() == IDOK) + { + _pCadGroup->SetKey_DBL("Count", (double)_dlg.GetCount()); + _pCadGroup->SetKey_DBL("Priority", (double)_dlg.GetPriority()); + _pCadGroup->SetKey_DBL("RotationStyle", (double)_dlg.GetRotateAngle()); + UpdateListCtrlMaterials(); + ClearCache(m_pCadSelected); + UpdatePreview(); + } +} + +void CNestProfessorDlg::OnDeletePart() +{ + if (!m_pCadSelected) + { + return; + } + + CadObjectList::iterator _it = find(m_listParts.begin(), m_listParts.end(), m_pCadSelected); + if (_it != m_listParts.end()) + { + _it = m_listParts.erase(_it); + + // 删除一行时清除对应的预览图缓存 ---- 杨开锦 2016-07-05 + ClearCache(m_pCadSelected); + ASSERT(m_pCadSelected->GetType() == cadgroup); + CCadGroup* _pCadGroup = (CCadGroup*)m_pCadSelected; + _pCadGroup->PickOffAll(); + delete _pCadGroup; + _pCadGroup = NULL; + m_pCadSelected = NULL; + + // 如果下一个还有就把选中图形设为下一个 ---- DingQiang 2016-06-30 + if (_it != m_listParts.end()) + { + m_pCadSelected = *_it; + } + + UpdateListCtrlParts(); + UpdateListCtrlSelected(); + UpdatePreview(); + } +} + +void CNestProfessorDlg::OnNewMataterial() +{ + CMaterialDlg _dlg; + if (_dlg.DoModal() == IDOK) + { + CCadRectangle* _pRectMat = new CCadRectangle; + ASSERT(_pRectMat); + _pRectMat->SetLocation(DPOINT2(0.0, 0.0)); + _pRectMat->SetWidth(_dlg.GetWidth()); + _pRectMat->SetHeight(_dlg.GetHeight()); + CCadGroup* _pHull = new CCadGroup; + _pHull->PushBack(_pRectMat); + _pHull->SetKey_DBL("ID", (UINT_PTR)_pHull); + _pHull->SetKey_DBL("Count", (double)_dlg.GetCount()); + _pHull->SetKey("MaterialName", (PCSTR)_dlg.GetName()); + _pHull->SetKey("UsedCount", "-"); + m_listMaterials.push_back(_pHull); + UpdateListCtrlMaterials(); + } +} + +void CNestProfessorDlg::OnImportMataterial() +{ + +} + +void CNestProfessorDlg::OnEditMataterial() +{ + if (_GetIndex(m_listMaterials, m_pCadSelected) == -1) + { + // 没有选中对象 ---- DingQiang 2016-07-01 + return; + } + + ASSERT(m_pCadSelected->GetType() == cadgroup); + CCadGroup* _pCadGroup = (CCadGroup*)m_pCadSelected; + ASSERT(_pCadGroup->GetNumOfChild() == 1); + CCadObject* _pCadOjbect = _pCadGroup->GetFront(); + ASSERT(_pCadOjbect->GetType() == cadrectangle); + CCadRectangle* _pCadRectangle = (CCadRectangle*)_pCadOjbect; + + // 弹出对话框修改 ---- DingQiang 2016-07-01 + CMaterialDlg _dlg; + _dlg.SetName((LPCTSTR)_pCadGroup->GetKey("MaterialName")); + _dlg.SetCount((int)_pCadGroup->GetKey_DBL("Count")); + _dlg.SetWidth(_pCadRectangle->GetWidth()); + _dlg.SetHeight(_pCadRectangle->GetHeitht()); + if (_dlg.DoModal() == IDOK) + { + _pCadGroup->SetKey("MaterialName", (PCSTR)_dlg.GetName()); + _pCadGroup->SetKey_DBL("Count", (double)_dlg.GetCount()); + _pCadRectangle->SetWidth(_dlg.GetWidth()); + _pCadRectangle->SetHeight(_dlg.GetHeight()); + UpdateListCtrlMaterials(); + ClearCache(m_pCadSelected); + UpdatePreview(); + } +} + +void CNestProfessorDlg::OnDeleteMataterial() +{ + if (!m_pCadSelected) + { + return; + } + + CadObjectList::iterator _it = find(m_listMaterials.begin(), m_listMaterials.end(), m_pCadSelected); + if (_it != m_listMaterials.end()) + { + _it = m_listMaterials.erase(_it); + + // 删除一行时清除对应的预览图缓存 ---- 杨开锦 2016-07-05 + ClearCache(m_pCadSelected); + delete m_pCadSelected; + m_pCadSelected = NULL; + + // 如果下一个还有就把选中图形设为下一个 ---- DingQiang 2016-06-30 + if (_it != m_listMaterials.end()) + { + m_pCadSelected = *_it; + } + + UpdateListCtrlMaterials(); + UpdateListCtrlSelected(); + UpdatePreview(); + } +} + +void CNestProfessorDlg::OnSaveSheet() +{ + +} + +void CNestProfessorDlg::OnGenerateRemnant() +{ + +} + +void CNestProfessorDlg::OnSetParameter() +{ + CNestParamDlg _dlg(&m_param, this); + if (_dlg.DoModal() == IDOK) + { + SAVE_PARAM(this, CNestProfessorDlg); + } +} + +void CNestProfessorDlg::OnStartOrStop() +{ + // 拒绝频繁点击,可避免不必要的时序麻烦 ---- 杨开锦 2016-08-09 + static DWORD _s_nLastTime = 0; + DWORD _nTC = ::GetTickCount(); + if (_nTC >= _s_nLastTime && _nTC < _s_nLastTime + 500) + { + return; + } + _s_nLastTime = _nTC; + + if (!m_pNestProcessor) + { + Start(); + return; + } + + if (m_pNestProcessor && !m_pNestProcessor->IsStopped()) + { + Stop(); + return; + } +} + +// 关于开始/停止的更新,包含以下三个方面 ---- 杨开锦 2016-07-03 +// 1.正在计算时,显示滚动条 +// 2.正在计算时,按钮显示“停止” +// 3.按钮显示的功能发生切换时,让按钮灰显一小段时间 +void CNestProfessorDlg::OnUpdateStartOrStop(CCmdUI* pCmdUI_) +{ + ASSERT(pCmdUI_ && pCmdUI_->m_pOther); + + bool _bRunning = (m_pNestProcessor != NULL); + + // 滚动条,只跟是否正在计算有关 ---- 杨开锦 2016-07-03 + BOOL _bShowProgress = _bRunning ? TRUE : FALSE; + if (m_wndProgress.IsWindowVisible() != _bShowProgress) + { + m_wndProgress.ShowWindow(_bShowProgress); + } + + // “开始”按钮,也只跟是否正在计算有关 ---- 杨开锦 2016-07-03 + static bool _s_bLastRunning = false; + static DWORD _s_nLastChangedTime = 0; + DWORD _nTC = ::GetTickCount(); + if (_bRunning != _s_bLastRunning) + { + _s_bLastRunning = _bRunning; + _s_nLastChangedTime = _nTC; + } + + BOOL _bEnableButton = (_nTC >= _s_nLastChangedTime && _nTC < _s_nLastChangedTime + 700) ? FALSE : TRUE; + if (pCmdUI_->m_pOther->IsWindowEnabled() != _bEnableButton) + { + pCmdUI_->m_pOther->EnableWindow(_bEnableButton); + } + + CString _strText = (_bRunning && (_nTC < _s_nLastChangedTime || _nTC >= _s_nLastChangedTime + 200)) + || (!_bRunning && (_nTC >= _s_nLastChangedTime && _nTC < _s_nLastChangedTime + 200)) + ? _GETCS(s_szSTOP) : _GETCS(s_szEXECUTE); + CString _strOldText; + pCmdUI_->m_pOther->GetWindowText(_strOldText); + if (_strOldText != _strText) + { + pCmdUI_->m_pOther->SetWindowText(_strText); + } +} + +void CNestProfessorDlg::OnOK() +{ + bool _bRunning = (m_pNestProcessor != NULL); + if (_bRunning) + { + return; + } + + __super::OnOK(); +} + +void CNestProfessorDlg::OnUpdateOK(CCmdUI* pCmdUI_) +{ + ASSERT(pCmdUI_ && pCmdUI_->m_pOther); + + // 确定按钮,没有数据时不能点确定,正在计算时也不能点确定 ---- DingQiang 2016-07-05 + bool _bHasResult = m_listSheets.size() > 0; + bool _bRunning = (m_pNestProcessor != NULL); + BOOL _bEnableButton = (_bHasResult && !_bRunning) ? TRUE : FALSE; + if (pCmdUI_->m_pOther->IsWindowEnabled() != _bEnableButton) + { + pCmdUI_->m_pOther->EnableWindow(_bEnableButton); + } +} + +void CNestProfessorDlg::OnCancel() +{ + if (m_pNestProcessor && !m_pNestProcessor->IsStopped()) + { + AfxMessageBox(_GETCS(s_szCANCELTIPS), MB_ICONEXCLAMATION); + return; + } + + __super::OnCancel(); +} + +void CNestProfessorDlg::InitializeListCtrlParts() +{ + ParamItemVector _vectorParamItems; + + // 名称 + CParamItem_CONSTSTR* _pParam_Name = new CParamItem_CONSTSTR; + _pParam_Name->SetParamName(CString(_GETCS(s_szNP_PARTNAME)) + _T(":75")); + _pParam_Name->SetParamValue(_T("NoName")); + _pParam_Name->SetKey("PartName"); + _pParam_Name->SetValue("NoName"); + _vectorParamItems.push_back(_pParam_Name); + + // 优先级 + CParamItem_INT* _pParam_Priority = new CParamItem_INT; + _pParam_Priority->SetParamName(CString(_GETCS(s_szNP_PARTNESTPRIORITY)) + _T(":70")); + _pParam_Priority->SetRange(1, 10); + _pParam_Priority->SetParamValue(_T("10")); + _pParam_Priority->SetKey("Priority"); + _pParam_Priority->SetValue("10"); + _vectorParamItems.push_back(_pParam_Priority); + + // 可用排版数量 + CParamItem_INT* _pParam_Count = new CParamItem_INT; + _pParam_Count->SetParamName(CString(_GETCS(s_szNP_PARTAVAILABLECOUNT)) + _T(":64")); + _pParam_Count->SetRange(1, 10000000); + _pParam_Count->SetParamValue(_T("10")); + _pParam_Count->SetKey("Count"); + _pParam_Count->SetValue("10"); + _vectorParamItems.push_back(_pParam_Count); + + // 已用数量 + CParamItem_CONSTSTR* _pParam_UsedCount = new CParamItem_CONSTSTR; + _pParam_UsedCount->SetParamName(CString(_GETCS(s_szNP_PARTNESTCOUNT)) + _T(":60")); + _pParam_UsedCount->SetParamValue(_T("-")); + _pParam_UsedCount->SetKey("UsedCount"); + _pParam_UsedCount->SetValue("-"); + _vectorParamItems.push_back(_pParam_UsedCount); + + // 旋转角度 + CParamItem_ENUM* _pParam_RotationStyle = new CParamItem_ENUM; + CParamItem_ENUM::EnumItemVector _RotationStyleEnums; + _RotationStyleEnums.push_back(CParamItem_ENUM::EnumItem(_GETCS(s_szNESTPART_FREEROTATE), "0")); + _RotationStyleEnums.push_back(CParamItem_ENUM::EnumItem(_GETCS(s_szNESTPART_90INCREMENT), "1")); + _RotationStyleEnums.push_back(CParamItem_ENUM::EnumItem(_GETCS(s_szNESTPART_180INCREMENT), "2")); + _RotationStyleEnums.push_back(CParamItem_ENUM::EnumItem(_GETCS(s_szNESTPART_0FIXED), "3")); + _RotationStyleEnums.push_back(CParamItem_ENUM::EnumItem(_GETCS(s_szNESTPART_90FIXED), "4")); + _RotationStyleEnums.push_back(CParamItem_ENUM::EnumItem(_GETCS(s_szNESTPART_180FIXED), "5")); + _RotationStyleEnums.push_back(CParamItem_ENUM::EnumItem(_GETCS(s_szNESTPART_270FIXED), "6")); + _pParam_RotationStyle->SetEnumItems(_RotationStyleEnums); + _pParam_RotationStyle->SetParamName(CString(_GETCS(s_szNP_PARTROTATEANGLE)) + _T(":90")); + _pParam_RotationStyle->SetParamValue(_GETCS(s_szNESTPART_FREEROTATE)); + _pParam_RotationStyle->SetParamUnit(_T("")); + _pParam_RotationStyle->SetKey("RotationStyle"); + _pParam_RotationStyle->SetValue("0"); + _vectorParamItems.push_back(_pParam_RotationStyle); + + // 大小 + CParamItem_CONSTSTR* _pParam_Size = new CParamItem_CONSTSTR; + _pParam_Size->SetParamName(CString(_GETCS(s_szNP_PARTSIZE)) + _T(":102")); + _pParam_Size->SetParamValue(_T("100*100")); + _pParam_Size->SetKey("Size"); + _pParam_Size->SetValue("100*100"); + _vectorParamItems.push_back(_pParam_Size); + + m_wndListCtrlParts.SetParamItems(&_vectorParamItems); +} + +void CNestProfessorDlg::InitializeListCtrlMaterials() +{ + ParamItemVector _vectorParamItems; + + // 材料名称 + CParamItem_CONSTSTR* _pParam_Name = new CParamItem_CONSTSTR; + _pParam_Name->SetParamName(CString(_GETCS(s_szNP_SHEETNAME)) + _T(":75")); + _pParam_Name->SetParamValue(CString(_GETCS(s_szMATERIALNAME))); + _pParam_Name->SetKey("MaterialName"); + _pParam_Name->SetValue(CString(_GETCS(s_szMATERIALNAME))); + _vectorParamItems.push_back(_pParam_Name); + + // 材料类型 + CParamItem_CONSTSTR* _pParam_Type = new CParamItem_CONSTSTR; + _pParam_Type->SetParamName(CString(_GETCS(s_szNP_MATERIALTYPE)) + _T(":70")); + _pParam_Type->SetParamValue(CString(_GETCS(s_szNP_RECTANGLEMATERIAL))); + _pParam_Type->SetKey("MaterialType"); + _pParam_Type->SetValue(CString(_GETCS(s_szNP_RECTANGLEMATERIAL))); + _vectorParamItems.push_back(_pParam_Type); + + // 可用数量 + CParamItem_INT* _pParam_Count = new CParamItem_INT; + _pParam_Count->SetParamName(CString(_GETCS(s_szNP_MATERIALCOUNT)) + _T(":64")); + _pParam_Count->SetRange(1, 10000000); + _pParam_Count->SetParamValue(_T("1")); + _pParam_Count->SetKey("Count"); + _pParam_Count->SetValue("1"); + _vectorParamItems.push_back(_pParam_Count); + + // 已用数量 + CParamItem_CONSTSTR* _pParam_UsedCount = new CParamItem_CONSTSTR; + _pParam_UsedCount->SetParamName(CString(_GETCS(s_szNP_MATERIALNESTCOUNT)) + _T(":60")); + _pParam_UsedCount->SetParamValue(_T("-")); + _pParam_UsedCount->SetKey("UsedCount"); + _pParam_UsedCount->SetValue("-"); + _vectorParamItems.push_back(_pParam_UsedCount); + + // 材料宽度 + CParamItem_DBL* _pParam_Width = new CParamItem_DBL; + _pParam_Width->SetRange(0.1, 1000000.0); + _pParam_Width->SetParamName(CString(_GETCS(s_szNP_MATERIALWIDTH)) + _T(":96")); + _pParam_Width->SetParamValue(_T("100")); + _pParam_Width->SetParamUnit(_T("")); + _pParam_Width->SetKey("MaterialWidth"); + _pParam_Width->SetValue(_T("100")); + _vectorParamItems.push_back(_pParam_Width); + + // 材料高度 + CParamItem_DBL* _pParam_Height = new CParamItem_DBL; + _pParam_Height->SetRange(0.1, 1000000.0); + _pParam_Height->SetParamName(CString(_GETCS(s_szNP_MATERIALHEIGHT)) + _T(":96")); + _pParam_Height->SetParamValue(_T("100")); + _pParam_Height->SetParamUnit(_T("")); + _pParam_Height->SetKey("MaterialHeight"); + _pParam_Height->SetValue(_T("100")); + _vectorParamItems.push_back(_pParam_Height); + + m_wndListCtrlMaterials.SetParamItems(&_vectorParamItems); +} + +void CNestProfessorDlg::InitializeListCtrlSheets() +{ + ParamItemVector _vectorParamItems; + + // 结果名 + CParamItem_CONSTSTR* _pParam_Name = new CParamItem_CONSTSTR; + _pParam_Name->SetParamName(CString(_GETCS(s_szNP_SHEETNAME)) + _T(":75")); + _pParam_Name->SetParamValue(_T("Sheet1")); + _pParam_Name->SetKey("SheetName"); + _pParam_Name->SetValue(_T("Sheet1")); + _vectorParamItems.push_back(_pParam_Name); + + // 结果数量 + CParamItem_CONSTSTR* _pParam_Count = new CParamItem_CONSTSTR; + _pParam_Count->SetParamName(CString(_GETCS(s_szNP_SHEETCOUNT)) + _T(":70")); + _pParam_Count->SetParamValue(_T("10")); + _pParam_Count->SetKey("Count"); + _pParam_Count->SetValue(_T("10")); + _vectorParamItems.push_back(_pParam_Count); + + // 材料名称 + CParamItem_CONSTSTR* _pParam_MaterialName = new CParamItem_CONSTSTR; + _pParam_MaterialName->SetParamName(CString(_GETCS(s_szNP_MATNAME)) + _T(":185")); + _pParam_MaterialName->SetParamValue(_T("Material1")); + _pParam_MaterialName->SetKey("MaterialName"); + _pParam_MaterialName->SetValue(_T("Material1")); + _vectorParamItems.push_back(_pParam_MaterialName); + + // 材料利用率 + CParamItem_CONSTSTR* _pParam_Utilization = new CParamItem_CONSTSTR; + _pParam_Utilization->SetParamName(CString(_GETCS(s_szNP_UTILIZATION)) + _T(":131")); + _pParam_Utilization->SetParamValue(_T("100.0%")); + _pParam_Utilization->SetKey("Utilization"); + _pParam_Utilization->SetValue(_T("100.0%")); + _vectorParamItems.push_back(_pParam_Utilization); + + m_wndListCtrlSheets.SetParamItems(&_vectorParamItems); +} + +void CNestProfessorDlg::UpdateListCtrlParts() +{ + _UpdateListCtrlSize(m_vectorPartParams, m_listParts.size()); + _UpdateListCtrlData(m_wndListCtrlParts, m_listParts, m_vectorPartParams, this); +} + +void CNestProfessorDlg::UpdateListCtrlMaterials() +{ + _UpdateListCtrlSize(m_vectorMaterialParams, m_listMaterials.size()); + _UpdateListCtrlData(m_wndListCtrlMaterials, m_listMaterials, m_vectorMaterialParams, this); +} + +void CNestProfessorDlg::UpdateListCtrlSheets() +{ + _UpdateListCtrlSize(m_vectorSheetParams, m_listSheets.size()); + _UpdateListCtrlData(m_wndListCtrlSheets, m_listSheets, m_vectorSheetParams, this); +} + +// 用当前选中的m_pCadSelected来更新界面的选中行 ---- DingQiang 2016-06-30 +void CNestProfessorDlg::UpdateListCtrlSelected() +{ + _UpdateListCtrlSelected(m_wndListCtrlParts, m_listParts, m_pCadSelected); + _UpdateListCtrlSelected(m_wndListCtrlMaterials, m_listMaterials, m_pCadSelected); + _UpdateListCtrlSelected(m_wndListCtrlSheets, m_listSheets, m_pCadSelected); +} + +void CNestProfessorDlg::ClearUsedInformation() +{ + // 零件 + for (CadObjectList::iterator _it = m_listParts.begin(); _it != m_listParts.end(); _it++) + { + CCadObject* _pCadObject = *_it; + ASSERT(_pCadObject->GetType() == cadgroup); + _pCadObject->SetKey("UsedCount", "-"); + } + + // 板材 + for (CadObjectList::iterator _it = m_listMaterials.begin(); _it != m_listMaterials.end(); _it++) + { + CCadObject* _pCadObject = *_it; + ASSERT(_pCadObject->GetType() == cadgroup); + _pCadObject->SetKey("UsedCount", "-"); + } +} + +void CNestProfessorDlg::UpdateUsedInformation() +{ + ClearUsedInformation(); + for (CadObjectList::iterator _it = m_listSheets.begin(); _it != m_listSheets.end(); _it++) + { + CCadObject* _pCadOjbect = *_it; + ASSERT(_pCadOjbect->GetType() == cadgroup); + CCadGroup* _pSheetHull = (CCadGroup*)_pCadOjbect; + + // 找到对应的板材,把使用的数量累加上去 ---- DingQiang 2016-07-05 + CStringA _strMaterialID = _pSheetHull->GetKey("MaterialID"); + ASSERT(!_strMaterialID.IsEmpty()); + CCadGroup* _pCadMaterial = (CCadGroup*)(UINT_PTR)atol(_strMaterialID); + ASSERT(_pCadMaterial && _pCadMaterial->GetType() == cadgroup && _pCadMaterial->GetNumOfChild() > 0); + ASSERT(_pCadMaterial->GetKey("ID") == _strMaterialID); + int _nThisCount = (int)_pSheetHull->GetKey_DBL("Count"); // 当前sheet用掉的板材数 + ASSERT(_nThisCount > 0); + ASSERT(!_pCadMaterial->GetKey("UsedCount").IsEmpty()); + int _nUsedCount = (int)_pCadMaterial->GetKey_DBL("UsedCount"); // 已经用掉的 + _nUsedCount += _nThisCount; + _pCadMaterial->SetKey_DBL("UsedCount", (double)_nUsedCount); + + // 找到对应的零件,把使用的数量累加上去 ---- DingQiang 2016-07-05 + for (int _it = 0; _it < _pSheetHull->GetNumOfChild(); _it++) + { + CCadObject* _pCadPartHull = _pSheetHull->GetAt(_it); + ASSERT(_pCadPartHull->GetType() == cadgroup); + CCadGroup* _pCadGroupPartHull = (CCadGroup*)_pCadPartHull; + CStringA _strPartID = _pCadGroupPartHull->GetKey("PartID"); + ASSERT(!_strPartID.IsEmpty()); + CCadGroup* _pCadPartGroup = (CCadGroup*)(UINT_PTR)atol(_strPartID); + ASSERT(_GetIndex(m_listParts, _pCadPartGroup) != -1); // 一定能找到 + ASSERT(!_pCadPartGroup->GetKey("UsedCount").IsEmpty()); + int _nUsedCount = (int)_pCadPartGroup->GetKey_DBL("UsedCount"); + //根据_nThisCount判断有多少重复的sheet,此前的处理是当出现重复的sheet时,只计算一个sheet + //导致最后零件的排版数量计算不准确。#ID:3435 + if (_nThisCount > 1) + { + _nUsedCount = _nUsedCount + _nThisCount; + } + else + { + _nUsedCount++; + } + _pCadPartGroup->SetKey_DBL("UsedCount", (double)_nUsedCount); + } + } +} + +// 清除并释放缓存中对应图形的预览图 ---- 杨开锦 2016-06-29 +// 给出Cad指针,是只清除跟这个图对应的 +// 给的Cad指针为NULL,则表示清除所有预览图 +// 注:清除所有用于闭关对话框时,清除个别可用于图形被修改时 +void CNestProfessorDlg::ClearCache(const nce::CCadObject* pCad_) +{ + for (int _i = 0; _i < _countof(m_cacheItems); _i++) + { + CacheItem& _item = m_cacheItems[_i]; + if (pCad_ && pCad_ != _item.pCad) + continue; + + if (_item.hBmp) + DeleteObject(_item.hBmp); + + _item.pCad = NULL; + _item.hBmp = NULL; + } +} + +// 生成给定图形的预览图 ---- 杨开锦 2016-06-29 +// 预览图会缓存,先查缓存,查不到再重新生成 +// 同理新生成的预览图要进缓存,以便可供下次查 +// 缓存有上限,但也应做到确定不用的缓存要清除掉 +// 不管指针是否为空,都将生成预览图 +// 对空指针生成空的图,即全是白底没有画线条的 +// 并且空的图也存入缓存,即缓存是以位图为主键的 +HBITMAP CNestProfessorDlg::UpdateCache(const nce::CCadObject* pCad_) +{ + // 查缓存 + HBITMAP _hBitmap = NULL; + for (int _i = 0; _i < _countof(m_cacheItems); _i++) + { + const CacheItem& _item = m_cacheItems[_i]; + ASSERT(_item.hBmp != NULL || _item.pCad == NULL); + if (_item.hBmp != NULL && _item.pCad == pCad_) + { + _hBitmap = _item.hBmp; + break; + } + } + if(_hBitmap) + { + return _hBitmap; + } + + // 生成预览 + const int c_nBmpW = 250; // 假设预览图那个框是死的,固定宽度 + const int c_nBmpH = 500; // 假设预览图那个框是死的,固定高度 + HDC _hDC = ::GetDC(NULL); + ASSERT(_hDC); + CDC* _pDC = CDC::FromHandle(_hDC); + ASSERT(_pDC); + CDC _dcMemory; + _dcMemory.CreateCompatibleDC(_pDC); + CBitmap _bmpOut; + _bmpOut.CreateCompatibleBitmap(_pDC, c_nBmpW, c_nBmpH); + CBitmap* _pOldBmp = _dcMemory.SelectObject(&_bmpOut); + ASSERT(_pOldBmp); + _dcMemory.FillSolidRect(0, 0, c_nBmpW, c_nBmpH, RGB(255, 255, 255)); // 白底黑线 + if (pCad_) + { + CNestDrawer _drawer; + _drawer.SetViewportDP(CRect(20, 40, c_nBmpW - 20, c_nBmpH - 40)); + _drawer.DrawCadObject(&_dcMemory, pCad_); + } + _dcMemory.SelectObject(_pOldBmp); + _dcMemory.DeleteDC(); + ::ReleaseDC(NULL, _hDC); + _hDC = NULL; + _pDC = NULL; + _hBitmap = (HBITMAP)(_bmpOut); + _bmpOut.Detach(); + + // 存入缓存 + int _nNextIndex = 0; + while (_nNextIndex < _countof(m_cacheItems)) + { + const CacheItem& _item = m_cacheItems[_nNextIndex]; + ASSERT(_item.hBmp != NULL || _item.pCad == NULL); + if (_item.hBmp == NULL && _item.pCad == NULL) + { + break; + } + + _nNextIndex++; + } + ASSERT(_nNextIndex < _countof(m_cacheItems)); + m_cacheItems[_nNextIndex].pCad = pCad_; + m_cacheItems[_nNextIndex].hBmp = _hBitmap; + _nNextIndex = (_nNextIndex + 1) % _countof(m_cacheItems); + if (m_cacheItems[_nNextIndex].hBmp) + DeleteObject(m_cacheItems[_nNextIndex].hBmp); + m_cacheItems[_nNextIndex].pCad = NULL; + m_cacheItems[_nNextIndex].hBmp = NULL; + + return _hBitmap; +} + +// 根据当前选中的行(对应m_pCadSelected)更新预览图 ---- 杨开锦 2016-06-29 +void CNestProfessorDlg::UpdatePreview() +{ + HBITMAP _hBitmap = UpdateCache(m_pCadSelected); + ASSERT(_hBitmap); + + HBITMAP _hOldBmp = NULL; + if (m_wndPreview.GetBitmap() != _hBitmap) + { + _hOldBmp = m_wndPreview.SetBitmap(_hBitmap); + } +} + +void CNestProfessorDlg::Start() +{ + // 开始前选清空上次排版结果(如果有的话),以避免误解 + if (find(m_listSheets.begin(), m_listSheets.end(), m_pCadSelected) != m_listSheets.end()) + { + m_pCadSelected = NULL; + UpdatePreview(); + } + while (!m_listSheets.empty()) + { + CCadObject* _pCadSheet = m_listSheets.front(); + ClearCache(_pCadSheet); + delete _pCadSheet; + _pCadSheet = NULL; + m_listSheets.pop_front(); + } + UpdateListCtrlSheets(); + + ClearUsedInformation(); + UpdateListCtrlParts(); + UpdateListCtrlMaterials(); + + ASSERT(m_pNestProcessor == NULL); + m_pNestProcessor = new CNestProfessorDoer::CProcessor(NULL); + CNestProfessorDoer::CTask _task; + _task.m_pParam = &m_param; + _task.m_listParts = m_listParts; + _task.m_listMaterials = m_listMaterials; + CNestProfessorDoer _doer; + bool _bRet = _doer.DoNest(&_task, m_pNestProcessor); + ASSERT(_bRet); +} + +void CNestProfessorDlg::Stop() +{ + ASSERT(m_pNestProcessor && !m_pNestProcessor->IsStopped()); + m_pNestProcessor->Stop(); +} + +void CNestProfessorDlg::Update() +{ + ASSERT(m_pNestProcessor && m_pNestProcessor->HasBetterResult()); + CNestProfessorDoer::CResult _result; + m_pNestProcessor->GetResult(&_result); + UpdateDlgTitle(_result.m_nErrorCode); + if (_result.m_nErrorCode != 0) + { + ASSERT(_result.m_listSheets.empty()); + return; + } + + // 收集结果数据,主要是把结果的形式做成是Group套Group的 ---- 杨开锦 2016-06-23 + // 已经由Doer中new出来了placement这级Group壳了,仅一个壳 + // 这里需要为每个sheet也new一个Group壳,把参数Set进去 + // 转换出来的结果数据全是Group壳,只含有字符串参数 + ASSERT(_result.m_nErrorCode == CNestProfessorDoer::CResult::EC_SUCCESS); + ASSERT(_result.m_listSheets.size() > 0); + while (!m_listSheets.empty()) + { + CCadObject* _pCadSheet = m_listSheets.front(); + ClearCache(_pCadSheet); + delete _pCadSheet; + _pCadSheet = NULL; + m_listSheets.pop_front(); + } + ASSERT(_result.m_listSheets.size() > 0); + for (CNestProfessorDoer::CResult::SheetList::const_iterator _it = _result.m_listSheets.begin(); + _it != _result.m_listSheets.end(); _it++) + { + const CNestProfessorDoer::CResult::Sheet& _sheet = *_it; + ASSERT(_sheet.nMaterialID != 0); + ASSERT(_sheet.nCount > 0); + ASSERT(_sheet.listPmts.size() > 0); + + CCadGroup* _pSheetHull = new CCadGroup; + ASSERT(_pSheetHull); + m_listSheets.push_back(_pSheetHull); + _pSheetHull->SetKey_DBL("MaterialID", _sheet.nMaterialID); + _pSheetHull->SetKey_DBL("Utilization", _sheet.nUtilization); + _pSheetHull->SetKey_DBL("Count", _sheet.nCount); + for (CadObjectList::const_iterator _itP = _sheet.listPmts.begin(); _itP != _sheet.listPmts.end(); _itP++) + { + ASSERT((*_itP) && (*_itP)->GetType() == cadgroup && ((CCadGroup*)(*_itP))->GetNumOfChild() == 0); + _pSheetHull->PushBack(*_itP); + } + } + + UpdateUsedInformation(); + UpdateListCtrlSheets(); + UpdateListCtrlParts(); + UpdateListCtrlMaterials(); +} + +//////////////////////////////////////////////////////////////////////////////// +// CNestParam(s) implementations +// +CStringA CPartParam::GetKey(PCSTR pszKey_) const +{ + ASSERT(m_pCadObject); + ASSERT(CStringA(pszKey_) == "Color" || CStringA(pszKey_) == "Name" + || CStringA(pszKey_) == "PartName" // 零件名称 + || CStringA(pszKey_) == "Priority" // 优先级 + || CStringA(pszKey_) == "Count" // 数量 + || CStringA(pszKey_) == "UsedCount" // 已用数量 + || CStringA(pszKey_) == "RotationStyle" // 旋转角度 + || CStringA(pszKey_) == "Size"); // 尺寸 + + if (CStringA(pszKey_) == "PartName") + { + CStringA _str; + _str.Format(_GetCS(s_szPARTNAME), m_nIndex); + return _str; + } + + if (CStringA(pszKey_) == "Size") + { + DRECT _rect = m_pCadObject->GetBoundRect(); + return _FormatSize(_rect.width, _rect.height, 13); + } + + return m_pCadObject->GetKey(pszKey_); +} + +void CPartParam::SetKey(PCSTR pszKey_, PCSTR pszVal_) +{ + ASSERT(m_pCadObject); + ASSERT(CStringA(pszKey_) == "Priority" // 优先级 + || CStringA(pszKey_) == "Count" // 数量 + || CStringA(pszKey_) == "RotationStyle");// 旋转角度 + + m_pCadObject->SetKey(pszKey_, pszVal_); +} + +CStringA CMaterialParam::GetKey(PCSTR pszKey_) const +{ + ASSERT(m_pCadObject); + ASSERT(CStringA(pszKey_) == "Color" || CStringA(pszKey_) == "Name" + || CStringA(pszKey_) == "MaterialName" // 材料名称 + || CStringA(pszKey_) == "MaterialType" // 类型 + || CStringA(pszKey_) == "Count" // 可用数量 + || CStringA(pszKey_) == "UsedCount" // 已用数量 + || CStringA(pszKey_) == "MaterialWidth" // 宽度 + || CStringA(pszKey_) == "MaterialHeight"); // 高度 + + // 现在只有矩形材料 ---- DingQiang 2016-06-29 + ASSERT(m_pCadObject->GetType() == cadgroup); + CCadGroup* _pGroup = (CCadGroup*)m_pCadObject; + ASSERT(_pGroup->GetNumOfChild() == 1 && _pGroup->GetAt(0)->GetType() == cadrectangle); + CCadRectangle* _pRectMaterial = (CCadRectangle*)_pGroup->GetAt(0); + + if (CStringA(pszKey_) == "MaterialType" && _pRectMaterial->GetType() == cadrectangle) + { + return _GetCS(s_szNP_RECTANGLEMATERIAL); + } + + if (CStringA(pszKey_) == "MaterialWidth" && _pRectMaterial->GetType() == cadrectangle) + { + double _nWidth = _pRectMaterial->GetWidth(); + CStringA _str; + _str.Format("%.3f", _nWidth); + return _str; + } + + if (CStringA(pszKey_) == "MaterialHeight" && _pRectMaterial->GetType() == cadrectangle) + { + double _nHeight = _pRectMaterial->GetHeitht(); + CStringA _str; + _str.Format("%.3f", _nHeight); + return _str; + } + + return m_pCadObject->GetKey(pszKey_); +} + +void CMaterialParam::SetKey(PCSTR pszKey_, PCSTR pszVal_) +{ + ASSERT(m_pCadObject); + ASSERT(CStringA(pszKey_) == "MaterialName" // 材料名称 + || CStringA(pszKey_) == "Count" // 可用数量 + || CStringA(pszKey_) == "MaterialWidth" // 宽度 + || CStringA(pszKey_) == "MaterialHeight"); // 高度 + + // 现在只有矩形材料 ---- DingQiang 2016-06-29 + ASSERT(m_pCadObject->GetType() == cadgroup); + CCadGroup* _pGroup = (CCadGroup*)m_pCadObject; + ASSERT(_pGroup->GetNumOfChild() == 1 && _pGroup->GetAt(0)->GetType() == cadrectangle); + CCadRectangle* _pRectMaterial = (CCadRectangle*)_pGroup->GetAt(0); + + if (CStringA(pszKey_) == "MaterialWidth" && _pRectMaterial->GetType() == cadrectangle) + { + double _nWidth = atof(pszVal_); + _pRectMaterial->SetWidth(_nWidth); + if (m_pNestProfessorDlg && m_pCadObject == m_pNestProfessorDlg->m_pCadSelected) + { + m_pNestProfessorDlg->ClearCache(m_pCadObject); + m_pNestProfessorDlg->UpdatePreview(); + } + return; + } + + if (CStringA(pszKey_) == "MaterialHeight" && _pRectMaterial->GetType() == cadrectangle) + { + double _nHeight = atof(pszVal_); + _pRectMaterial->SetHeight(_nHeight); + if (m_pNestProfessorDlg && m_pCadObject == m_pNestProfessorDlg->m_pCadSelected) + { + m_pNestProfessorDlg->ClearCache(m_pCadObject); + m_pNestProfessorDlg->UpdatePreview(); + } + return; + } + + m_pCadObject->SetKey(pszKey_, pszVal_); +} + +CStringA CSheetParam::GetKey(PCSTR pszKey_) const +{ + ASSERT(m_pCadObject); + ASSERT(CStringA(pszKey_) == "Color" || CStringA(pszKey_) == "Name" + || CStringA(pszKey_) == "SheetName" // 样张名 + || CStringA(pszKey_) == "Count" // 数量 + || CStringA(pszKey_) == "MaterialName" // 材料名称 + || CStringA(pszKey_) == "Utilization"); // 材料利用率 + + if (CStringA(pszKey_) == "SheetName") + { + CStringA _str; + _str.Format(_GetCS(s_szNP_SHEETNAMEFORMAT), m_nIndex); + return _str; + } + + if (CStringA(pszKey_) == "MaterialName") + { + CStringA _strMaterialID = m_pCadObject->GetKey("MaterialID"); + ASSERT(!_strMaterialID.IsEmpty()); + const CCadGroup* _pCadMaterial = (const CCadGroup*)(UINT_PTR)atol(_strMaterialID); + ASSERT(_pCadMaterial && _pCadMaterial->GetType() == cadgroup && _pCadMaterial->GetNumOfChild() > 0); + ASSERT(_pCadMaterial->GetKey("ID") == _strMaterialID); + CStringA _strMaterialName = _pCadMaterial->GetKey("MaterialName"); + ASSERT(!_strMaterialName.IsEmpty()); + return _strMaterialName; + } + + if (CStringA(pszKey_) == "Utilization") + { + double _nUtilization = m_pCadObject->GetKey_DBL(pszKey_); + ASSERT(_nUtilization >= 0.0 && _nUtilization <= 1.0); + CStringA _str; + _str.Format("%.1f%%", _nUtilization * 100.0); + return _str; + } + + return m_pCadObject->GetKey(pszKey_); +} + +//////////////////////////////////////////////////////////////////////////////// +// Local function implementations ---- DingQiang 2016-06-29 +// +// 将长、宽格式化如下形式,nLength_指定Format的整个长度 +// 2.012*1.215 +// 12.01*12.15 +// 112.0*112.1... +// 1112*11112... +// 由于显示时"."占的宽度和数字不同,会出现对不齐的情况 ---- DingQiang 2016-06-29 +CString _FormatSize(double nWidth_, double nHeight_, int nLength_) +{ + ASSERT(nLength_ % 2 == 1); + CString _strResult; + if (nWidth_ < 10) + { + _strResult.Format(_T("%.3f"), nWidth_); + } + else if (nWidth_ >= 10 && nWidth_ < 100) + { + _strResult.Format(_T("%.2f"), nWidth_); + } + else if (nWidth_ >= 100 && nWidth_ < 1000) + { + _strResult.Format(_T("%.1f"), nWidth_); + } + else + { + ASSERT(nWidth_ >= 1000); + _strResult.Format(_T("%.0f"), nWidth_); + } + + // 不够长在最前插入空格 ---- DingQiang 2016-07-06 + int _nInsertSize = nLength_ / 2 - _strResult.GetLength(); + ASSERT(_nInsertSize >= 0); + for (int _i = 0; _i < _nInsertSize; _i++) + { + _strResult.Insert(0, _T(" ")); + } + + // 中间的*号 ---- DingQiang 2016-07-06 + _strResult.Append(_T("*")); + + if (nHeight_ < 10) + { + _strResult.AppendFormat(_T("%.3f"), nHeight_); + } + else if (nHeight_ >= 10 && nHeight_ < 100) + { + _strResult.AppendFormat(_T("%.2f"), nHeight_); + } + else if (nHeight_ >= 100 && nHeight_ < 1000) + { + _strResult.AppendFormat(_T("%.1f"), nHeight_); + } + else + { + ASSERT(nHeight_ >= 1000); + _strResult.AppendFormat(_T("%.0f"), nHeight_); + } + + // 不够长在最后补上空格 ---- DingQiang 2016-07-06 + int _nAppendSize = nLength_ - _strResult.GetLength(); + ASSERT(_nAppendSize >= 0); + for (int _i = 0; _i < _nAppendSize; _i++) + { + _strResult.Append(_T(" ")); + } + + return _strResult; +} + +// 等待排版结果的超时时间判断,分几档:1分钟、3分钟、10分钟、30分钟 ---- 杨开锦 2016-08-10 +// 很快就出来了结果,等待到满1分钟 +// 1分钟内没有出来结果,等待到3分钟 +// 3分钟内没有出来结果,等待到10分钟 +// 10分钟内没有出来结果,等待到30分钟 +// 注 => 本函数会去修改等待时间WartTime以带回给调用者。 +bool _IsTimeOut(DWORD nStartTime_, DWORD nCurrentTime_, DWORD& nWaitTime_, bool bResultExist_) +{ + // 从开始到现在的时间 + DWORD _nSpanTime = (nCurrentTime_ >= nStartTime_) ? (nCurrentTime_ - nStartTime_) : (DWORD(0xFFFFFFFF) - nStartTime_ + nCurrentTime_); + + // 更新要等待的时间 + if (!bResultExist_) + { + if (nWaitTime_ < 1 * 60 * 1000) + nWaitTime_ = 1 * 60 * 1000; + if (_nSpanTime > 1 * 60 * 1000 && nWaitTime_ < 3 * 60 * 1000) + nWaitTime_ = 3 * 60 * 1000; + if (_nSpanTime > 3 * 60 * 1000 && nWaitTime_ < 10 * 60 * 1000) + nWaitTime_ = 10 * 60 * 1000; + if (_nSpanTime > 10 * 60 * 1000 && nWaitTime_ < 30 * 60 * 1000) + nWaitTime_ = 30 * 60 * 1000; + } + + // 判断超时 + return _nSpanTime > nWaitTime_; +} + +// 从CadObjectList获取指定序号的对象 ---- DingQiang 2016-06-30 +const CCadObject* _GetAt(const CadObjectList& listCadObject_, int nIndex_) +{ + if (nIndex_ >= (int)listCadObject_.size()) + { + return NULL; + } + + int _nIndex = 0; + CadObjectList::const_iterator _it = listCadObject_.begin(); + while(_it != listCadObject_.end()) + { + if (_nIndex == nIndex_) + { + break; + } + _nIndex++; + _it++; + } + + ASSERT(_it != listCadObject_.end()); + const CCadObject* _pCadObject = *_it; + ASSERT(_pCadObject); + return _pCadObject; +} + +// 返回cad对象在链表中的index,如果不在链表中就返回-1 ---- DingQiang 2016-07-01 +int _GetIndex(const CadObjectList& listCadObject_, const CCadObject* pCadObject_) +{ + int _nIndex = 0; + CadObjectList::const_iterator _it = listCadObject_.begin(); + while(_it != listCadObject_.end()) + { + if ((*_it) == pCadObject_) + { + break; + } + _nIndex++; + _it++; + } + + return _nIndex < (int)listCadObject_.size() ? _nIndex : -1; +} + +// 更新Params的项数,用于维持与对应的Cad数据数量一致 ---- 杨开锦 2016-07-05 +template +void _UpdateListCtrlSize(ParamVector& vectorNestParams_, size_t nSize_) +{ + // 少则加 + while (vectorNestParams_.size() < nSize_) + { + NestParamT* _pNestParam = new NestParamT(NULL); + ASSERT(_pNestParam); + vectorNestParams_.push_back(_pNestParam); + } + + // 多则删 + while (vectorNestParams_.size() > nSize_) + { + ASSERT(vectorNestParams_.back()); + delete vectorNestParams_.back(); + vectorNestParams_.pop_back(); + } +} + +// 更新ListCtrl的内容显示,ListCtrl通过NestParam绑定到对应的Cad数据 ---- 杨开锦 2016-07-05 +void _UpdateListCtrlData(CParamGroupsListCtrl& wndListCtrl_, CadObjectList& listCadDatas_, ParamVector& vectorNestParams_, CNestProfessorDlg* pDlg_) +{ + // 更新数据关联 + ASSERT(vectorNestParams_.size() == listCadDatas_.size()); + size_t _nIndex = 0; + for (CadObjectList::iterator _it = listCadDatas_.begin(); _it != listCadDatas_.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + + CNestParam* _pNestParam = (CNestParam*)vectorNestParams_[_nIndex++]; + ASSERT(_pNestParam); + _pNestParam->m_pCadObject = _pCad; + _pNestParam->m_nIndex = (int)_nIndex; + _pNestParam->m_pNestProfessorDlg = pDlg_; + } + + // 已经更新ListCtrl关联的数据,控件显示的更新由内部去做 + wndListCtrl_.Update(); +} + +// 更新ListCtrl的行选中状态,如果当前行应对于选中对象则其显示为选中,否则为不选中 ---- 杨开锦 2016-07-05 +void _UpdateListCtrlSelected(CParamGroupsListCtrl& wndListCtrl_, CadObjectList& listCadDatas_, const CCadObject* pCadSelected_) +{ + int _nIndex = 0; + for (CadObjectList::iterator _it = listCadDatas_.begin(); _it != listCadDatas_.end(); _it++) + { + if ((*_it) == pCadSelected_ && wndListCtrl_.GetItemState(_nIndex, LVIS_SELECTED) != LVIS_SELECTED) + { + wndListCtrl_.SetItemState(_nIndex, LVIS_SELECTED, LVIS_SELECTED); + } + + if ((*_it) != pCadSelected_ && wndListCtrl_.GetItemState(_nIndex, LVIS_SELECTED) == LVIS_SELECTED) + { + wndListCtrl_.SetItemState(_nIndex, 0, -1); + } + + _nIndex++; + } +} diff --git a/src/SelectTarget.cpp b/src/SelectTarget.cpp new file mode 100644 index 0000000..1e35f4a --- /dev/null +++ b/src/SelectTarget.cpp @@ -0,0 +1,2246 @@ +// ************************************************************************** // +// SelectTarget.cpp : implementation of the CSelectTarget class +// Copyright(c)2010 Naiky Company. All rights reserved. +// +// Abstract: +// 本文件中实现了CSelectTarget类,图形的选择功能。 +// +// ******************** Version 1 ******************* +// [维护人员]: 王搂 [维护日期]: 2010-05-20 +// [维护内容]: 建立初版。 +// ************************************************************************** // + +#include "stdafx.h" +#include "SelectTarget.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// 相似图形判断时只精确都小数点后三位。 ---- 黄海燕 2016-01-07 +#define DOUBLE_ROUGHEQU(nX_, nY_) ncmath::IsEqual(nX_, nY_, 1e-3) + +using namespace nce; +using namespace ncmath; + +CS_T s_szLAYERN = _DEFCS(_CSV(17152), + _CHINESE("图层%d") + _ENGLISH("Layer %d")); +CS_T s_szTITLE = _DEFCS(_CSV(17160), + _CHINESE("选择小图形") + _ENGLISH("Select Tiny")); +CS_T s_szSELECT_X = _DEFCS(_CSV(17161), + _CHINESE("X尺寸小于") + _ENGLISH("X less than")); +CS_T s_szSELECT_Y = _DEFCS(_CSV(17162), + _CHINESE("Y尺寸小于") + _ENGLISH("Y less than")); +CS_T s_szOK = _DEFCS(_CSV(17163), + _CHINESE("确定") + _ENGLISH("OK")); +CS_T s_szCANCEL = _DEFCS(_CSV(17164), + _CHINESE("取消") + _ENGLISH("Cancel")); + +//////////////////////////////////////////////////////////////////////////////// +// 选择小图形的对话框 ---- 杨开锦 2015-11-29 +// +class CSelectTinyDlg : public CDialog +{ + DECLARE_DYNAMIC(CSelectTinyDlg) + +public: + CSelectTinyDlg(CWnd* pParent_ = NULL); + virtual ~CSelectTinyDlg(); + + GUARD_BEGIN(CSelectTinyDlg); + double m_nWidth; + double m_nHeight; + GUARD_END(CSelectTinyDlg); + +protected: + virtual void DoDataExchange(CDataExchange* pDX_); + virtual BOOL OnInitDialog(); +}; + +IMPLEMENT_DYNAMIC(CSelectTinyDlg, CDialog) + +CSelectTinyDlg::CSelectTinyDlg(CWnd* pParent_/* = NULL*/) +: CDialog(IDD_DLG_SELECTTINY, pParent_) +{ + m_nWidth = 1.0; + m_nHeight = 1.0; + LOAD_PARAM(this, CSelectTinyDlg); +} + +CSelectTinyDlg::~CSelectTinyDlg() +{ + SAVE_PARAM(this, CSelectTinyDlg); +} + +void CSelectTinyDlg::DoDataExchange(CDataExchange* pDX_) +{ + CDialog::DoDataExchange(pDX_); + + DDX_Text(pDX_, IDC_EDT_SELECTTINY_X, m_nWidth); + DDV_MinMaxDouble(pDX_, m_nWidth, 0.1, 100.0); + DDX_Text(pDX_, IDC_EDT_SELECTTINY_Y, m_nHeight); + DDV_MinMaxDouble(pDX_, m_nHeight, 0.1, 100.0); +} + +BOOL CSelectTinyDlg::OnInitDialog() +{ + if (!__super::OnInitDialog()) + return FALSE; + + // 为对话框添加英文界面 ---- 边俊霞 2016-01-25 + SetWindowText(_GETCS(s_szTITLE)); + SetDlgItemText(IDC_STC_SELECTTINY_X, _GETCS(s_szSELECT_X)); + SetDlgItemText(IDC_STC_SELECTTINY_Y, _GETCS(s_szSELECT_Y)); + SetDlgItemText(IDOK, _GETCS(s_szOK)); + SetDlgItemText(IDCANCEL, _GETCS(s_szCANCEL)); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// Local function declarations +// +// 根据一个给定的观察窗,将给定的一组CAD对象划分为以下三个部分,划分的判断办法是 +// 求对象的外接矩形,然后用外接矩形的包含和相交关系来判断。 +// FullInside : 对象完全在观察窗内 +// PartInside : 对象部分在观察窗内 +// NotInside : 对象完全不在观察窗内 +// 观察窗ViewPort应为有效,即其位置点应为有效,宽高应为非负。三个用于OUT的指针均 +// 可以为NULL,为NULL时表示不需要收集这一部分的对象。 ---- 杨开锦 2011-07-16 +static void _DivideObjectsIntoThree(const CadObjectList* plistSource_, const DRECT& rcViewport_, + CadObjectList* plistFullInside_, CadObjectList* plistPartInside_, CadObjectList* plistNotInside_); + +//////////////////////////////////////////////////////////////////////////////// +// CSelectTarget ---- 杨开锦 2011-07-16 +// +CSelectTarget* CSelectTarget::ms_pSelectTarget = NULL; + +CSelectTarget* GetSelectTarget() +{ + return CSelectTarget::ms_pSelectTarget; +} + +IMPLEMENT_DYNAMIC(CSelectTarget, CMouseMsgTarget) +BEGIN_MESSAGE_MAP(CSelectTarget, CMouseMsgTarget) + ON_COMMAND(IDCMD_SELECTTARGET_SELECT, OnSelect) + ON_UPDATE_COMMAND_UI(IDCMD_SELECTTARGET_SELECT, OnUpdateSelect) + ON_COMMAND(IDCMD_SELECTTARGET_SELECTALL, OnSelectAll) + ON_UPDATE_COMMAND_UI(IDCMD_SELECTTARGET_SELECTALL, OnUpdateSelectAll) + ON_COMMAND(IDCMD_SELECTTARGET_SELECTUNCLOSE, OnSelectUnclose) + ON_UPDATE_COMMAND_UI(IDCMD_SELECTTARGET_SELECTUNCLOSE, OnUpdateSelectUnclose) + ON_COMMAND(IDCMD_SELECTTARGET_SELECTTINY, OnSelectTiny) + ON_UPDATE_COMMAND_UI(IDCMD_SELECTTARGET_SELECTTINY, OnUpdateSelectTiny) + ON_COMMAND_RANGE(IDCMD_SELECTTARGET_SELECTBYCOLOR0, IDCMD_SELECTTARGET_SELECTBYCOLOR7, OnSelectByColor) + ON_UPDATE_COMMAND_UI_RANGE(IDCMD_SELECTTARGET_SELECTBYCOLOR0, IDCMD_SELECTTARGET_SELECTBYCOLOR7, OnUpdateSelectByColor) + ON_COMMAND_RANGE(IDCMD_SELECTTARGET_SELECTBYTYPE0, IDCMD_SELECTTARGET_SELECTBYTYPE15, OnSelectByType) + ON_UPDATE_COMMAND_UI_RANGE(IDCMD_SELECTTARGET_SELECTBYTYPE0, IDCMD_SELECTTARGET_SELECTBYTYPE15, OnUpdateSelectByType) + ON_COMMAND(IDCMD_SELECTTARGET_SELECTREV, OnSelectRev) + ON_UPDATE_COMMAND_UI(IDCMD_SELECTTARGET_SELECTREV, OnUpdateSelectRev) + ON_COMMAND(IDCMD_SELECTTARGET_CLEARSELECT, OnClearSelect) + ON_UPDATE_COMMAND_UI(IDCMD_SELECTTARGET_CLEARSELECT, OnUpdateClearSelect) + ON_TARGET_MESSAGE(TM_SELECT_SELECTALL, SelectAll) + ON_TARGET_MESSAGE(TM_SELECT_SELECTBYCOLORE, SelectByColore) + ON_COMMAND(IDCMD_SELECTTARGET_SELECTSIMILAR, OnSelectSimilar) + ON_UPDATE_COMMAND_UI(IDCMD_SELECTTARGET_SELECTSIMILAR, OnUpdateSelectSimilar) +END_MESSAGE_MAP() + +CSelectTarget::CSelectTarget(CNceDC* pNceDC_) +{ + ASSERT(ms_pSelectTarget == NULL); + ms_pSelectTarget = this; + + m_pFileTarget = NULL; + m_pNceDC = pNceDC_; + m_nSeleToleranceDP = 6; + m_ptLButtonDown = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + m_ptTemp = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + m_rcSelObjsBoundRect = DRECT(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE, c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + + // 右键菜单 ---- 杨开锦 2010-08-16 + m_pRButtonMenu_NoneSelected = NULL; + m_pRButtonMenu_SingleSelected = NULL; + m_pRButtonMenu_MultiSelected = NULL; + + m_hCursor = AfxGetApp()->LoadCursor(IDC_CUR_SELECT); +} + +CSelectTarget::~CSelectTarget() +{ + ASSERT(ms_pSelectTarget == this); + ms_pSelectTarget = NULL; +} + +void CSelectTarget::Initialize() +{ + __super::Initialize(); + + m_pFileTarget = GetFileTarget(); + ASSERT(m_pFileTarget); + + // 把选择Target放在鼠标消息遍历链表的最后,即所有的Target都不处理时再判断选择Target是否处理 + // Wanglou 2010-06-13 + MouseMsgTargetList* _pMsgTargetList = GetMouseMsgTargetList(); + _pMsgTargetList->remove(this); + _pMsgTargetList->push_back(this); +} + +// 更新相关缓存,包括选中对象链表、选中参考线链表、选中对象外接矩形等。 ---- 杨开锦 2011-06-10 +BOOL CSelectTarget::Update(UINT nSenderID_, WPARAM nHint_, LPARAM pObject_) +{ + GetSelectedCadObjects(true); + GetSelectedRefLines(true); + GetSelObjsBoundRect(true); + + // 更新特征信息缓存 ---- 杨开锦 2015-11-29 + m_nCloseCount = 0; + m_nUncloseCount = 0; + m_nColorMask = 0; + m_nTypeMask = 0; + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + ASSERT(_pCadGroup); + int _nCount = _pCadGroup->GetNumOfChild(); + for (int _i = 0; _i < _nCount; _i++) + { + CCadObject* _pCad = _pCadGroup->GetAt(_i); + ASSERT(_pCad); + if (_pCad->IsClose()) + m_nCloseCount++; + else + m_nUncloseCount++; + + m_nColorMask |= (1 << _pCad->GetParamIndex()); + + if (_pCad->GetType() == caddot) m_nTypeMask |= 0x0001; + if (_pCad->GetType() == cadline) m_nTypeMask |= 0x0002; + if (_pCad->GetType() == cadbeeline) m_nTypeMask |= 0x0004; + if (_pCad->GetType() == cadcircle) m_nTypeMask |= 0x0008; + if (_pCad->GetType() == cadarc) m_nTypeMask |= 0x0010; + if (_pCad->GetType() == cadellipse) m_nTypeMask |= 0x0020; + if (_pCad->GetType() == cadellipsearc) m_nTypeMask |= 0x0040; + if (_pCad->GetType() == cadrectangle) m_nTypeMask |= 0x0100; + if (_pCad->GetType() == cadpolygon) m_nTypeMask |= 0x0200; + if (_pCad->GetType() == cadstar) m_nTypeMask |= 0x0400; + if (_pCad->GetType() == cadpolyline) m_nTypeMask |= 0x0800; + if (_pCad->GetType() == cadgroup) m_nTypeMask |= 0x2000; + if (_pCad->GetType() == cadtext) m_nTypeMask |= 0x4000; + } + + return TRUE; +} + +void CSelectTarget::Activate() +{ + // Base class first ---- 杨开锦 2010-07-14 + __super::Activate(); + + // 进入选择模式就是清除所有模式 ---- 杨开锦 2010-05-28 + while (!ms_stackPreMouseMsgTargets.empty()) + ms_stackPreMouseMsgTargets.pop(); +} + +void CSelectTarget::OnSelect() +{ + Activate(); +} + +void CSelectTarget::OnUpdateSelect(CCmdUI *pCmdUI_) +{ + if (IsActive() || GetActiveTarget() == NULL) + pCmdUI_->SetCheck(TRUE); + else + pCmdUI_->SetCheck(FALSE); +} + +void CSelectTarget::OnSelectAll() +{ + // 进入了其他鼠标操作则禁用选择功能 ---- 杨开锦 2010-07-17 + if (!IsActive() && GetActiveTarget() != NULL) + return; + + SelectAll(); + UpdateAllVisions(); +} + +void CSelectTarget::OnUpdateSelectAll(CCmdUI* pCmdUI_) +{ + // 进入了其他鼠标操作则禁用选择功能 ---- 杨开锦 2010-07-17 + if (!IsActive() && GetActiveTarget() != NULL) + { + pCmdUI_->Enable(FALSE); + return; + } + + pCmdUI_->Enable((m_nCloseCount + m_nUncloseCount) > 0); +} + +void CSelectTarget::OnSelectRev() +{ + // 进入了其他鼠标操作则禁用选择功能 ---- 杨开锦 2010-07-17 + if (!IsActive() && GetActiveTarget() != NULL) + return; + + SelectRev(); + UpdateAllVisions(); +} + +void CSelectTarget::OnUpdateSelectRev(CCmdUI* pCmdUI_) +{ + // 进入了其他鼠标操作则禁用选择功能 ---- 杨开锦 2010-07-17 + if (!IsActive() && GetActiveTarget() != NULL) + { + pCmdUI_->Enable(FALSE); + return; + } + + pCmdUI_->Enable((m_nCloseCount + m_nUncloseCount) > 0); +} + +void CSelectTarget::OnClearSelect() +{ + // 进入了其他鼠标操作则禁用选择功能 ---- 杨开锦 2010-07-17 + if (!IsActive() && GetActiveTarget() != NULL) + return; + + ClearSelect(); + UpdateAllVisions(); +} + +void CSelectTarget::OnUpdateClearSelect(CCmdUI* pCmdUI_) +{ + // 进入了其他鼠标操作则禁用选择功能 ---- 杨开锦 2010-07-17 + if (!IsActive() && GetActiveTarget() != NULL) + { + pCmdUI_->Enable(FALSE); + return; + } + + pCmdUI_->Enable(m_listSelectedCadObjects.size() > 0 || GetSelectedRefLines()->size() > 0); +} + +void CSelectTarget::OnSelectUnclose() +{ + if (!IsActive() && GetActiveTarget() != NULL) + return; + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCad = _pCadGroup->GetAt(_i); + ASSERT(_pCad); + _pCad->Select(_pCad->GetType() != cadgroup && !_pCad->IsClose()); + } + + GetSelectedCadObjects(true); + UpdateAllVisions(); +} + +void CSelectTarget::OnUpdateSelectUnclose(CCmdUI* pCmdUI_) +{ + if (!IsActive() && GetActiveTarget() != NULL) + { + pCmdUI_->Enable(FALSE); + return; + } + + pCmdUI_->Enable(m_nUncloseCount > 0); +} + +void CSelectTarget::OnSelectTiny() +{ + if (!IsActive() && GetActiveTarget() != NULL) + return; + + // 要弹出对话框填尺寸 ---- 杨开锦 2015-11-29 + CSelectTinyDlg _dlg; + if (_dlg.DoModal() != IDOK) + return; + + double _nWidth = max(0.1, _dlg.m_nWidth); + double _nHeight = max(0.1, _dlg.m_nHeight); + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCad = _pCadGroup->GetAt(_i); + ASSERT(_pCad); + DRECT _rc = _pCad->GetBoundRect(); + _pCad->Select(DOUBLE_LESS(_rc.width, _nWidth) && DOUBLE_LESS(_rc.height, _nHeight)); + } + + GetSelectedCadObjects(true); + UpdateAllVisions(); +} + +void CSelectTarget::OnUpdateSelectTiny(CCmdUI* pCmdUI_) +{ + if (!IsActive() && GetActiveTarget() != NULL) + { + pCmdUI_->Enable(FALSE); + return; + } + + pCmdUI_->Enable((m_nCloseCount + m_nUncloseCount) > 0); +} + +void CSelectTarget:: OnSelectByColor(UINT nID_) +{ + if (!IsActive() && GetActiveTarget() != NULL) + return; + + // 要选择第几个图层,Base0 ---- 杨开锦 2015-11-29 + int _nParamIndex = nID_ - IDCMD_SELECTTARGET_SELECTBYCOLOR0; + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCad = _pCadGroup->GetAt(_i); + ASSERT(_pCad); + _pCad->Select(_pCad->GetParamIndex() == _nParamIndex); + } + + GetSelectedCadObjects(true); + UpdateAllVisions(); +} + +void CSelectTarget::OnUpdateSelectByColor(CCmdUI* pCmdUI_) +{ + // 更新POPUP菜单 ---- 杨开锦 2015-11-29 + if (pCmdUI_->m_pSubMenu != NULL) + { + bool _bEnable = (IsActive() || GetActiveTarget() == NULL) && m_nColorMask != 0; + pCmdUI_->m_pMenu->EnableMenuItem(pCmdUI_->m_nIndex, MF_BYPOSITION | (_bEnable ? MF_ENABLED : MF_GRAYED)); + return; + } + + if (m_nColorMask == 0) + { + return; + } + + // 更新子菜单时显示当前有哪些颜色的图形 ---- 杨开锦 2015-11-29 + CMenu* pMenu_ = pCmdUI_->m_pMenu; + if (pMenu_ == NULL || pCmdUI_->m_nIndex != 0) + { + return; + } + + for (int _i = 0; _i < 8; _i++) + { + pMenu_->DeleteMenu(IDCMD_SELECTTARGET_SELECTBYCOLOR0 + _i, MF_BYCOMMAND); + } + + for (int _i = 0; _i < 8; _i++) + { + if (!(m_nColorMask & (1 << _i))) + continue; + + CString _strName; + _strName.Format(_GETCS(s_szLAYERN), _i + 1); + pMenu_->InsertMenu(pCmdUI_->m_nIndex++, MF_STRING | MF_BYPOSITION, IDCMD_SELECTTARGET_SELECTBYCOLOR0 + _i, _strName); + } + + // update end menu count + pCmdUI_->m_nIndex--; // point to last menu added + pCmdUI_->m_nIndexMax = pMenu_->GetMenuItemCount(); + + pCmdUI_->m_bEnableChanged = TRUE; // all the added items are enabled +} + +void CSelectTarget::OnSelectByType(UINT nID_) +{ + if (!IsActive() && GetActiveTarget() != NULL) + return; + + // 要选择哪种类型的 ---- 杨开锦 2015-11-29 + cad_t _nType = cadobject; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 0) _nType = caddot; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 1) _nType = cadline; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 2) _nType = cadbeeline; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 3) _nType = cadcircle; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 4) _nType = cadarc; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 5) _nType = cadellipse; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 6) _nType = cadellipsearc; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 8) _nType = cadrectangle; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 9) _nType = cadpolygon; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 10) _nType = cadstar; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 11) _nType = cadpolyline; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 13) _nType = cadgroup; + if (nID_ == IDCMD_SELECTTARGET_SELECTBYTYPE0 + 14) _nType = cadtext; + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCad = _pCadGroup->GetAt(_i); + ASSERT(_pCad); + _pCad->Select(_pCad->GetType() == _nType); + } + + GetSelectedCadObjects(true); + UpdateAllVisions(); +} + +void CSelectTarget:: OnUpdateSelectByType(CCmdUI* pCmdUI_) +{ + // 更新POPUP菜单 ---- 杨开锦 2015-11-29 + if (pCmdUI_->m_pSubMenu != NULL) + { + bool _bEnable = (IsActive() || GetActiveTarget() == NULL) && m_nTypeMask != 0; + pCmdUI_->m_pMenu->EnableMenuItem(pCmdUI_->m_nIndex, MF_BYPOSITION | (_bEnable ? MF_ENABLED : MF_GRAYED)); + return; + } + + if (m_nTypeMask == 0) + { + return; + } + + // 更新子菜单时显示当前有哪些颜色的图形 ---- 杨开锦 2015-11-29 + CMenu* pMenu_ = pCmdUI_->m_pMenu; + if (pMenu_ == NULL || pCmdUI_->m_nIndex != 0) + { + return; + } + + for (int _i = 0; _i < 15; _i++) + { + pMenu_->DeleteMenu(IDCMD_SELECTTARGET_SELECTBYTYPE0 + _i, MF_BYCOMMAND); + } + + static const CString c_sstrNames[] = + { + CCadDot().GetName(), + CCadLine().GetName(), + CCadBeeline().GetName(), + CCadCircle().GetName(), + CCadArc().GetName(), + CCadEllipse().GetName(), + CCadEllipseArc().GetName(), + _T("CadMmultiSegments"), + CCadRectangle().GetName(), + CCadPolygon().GetName(), + CCadStar().GetName(), + CCadPolyline().GetName(), + _T("CadPath"), + CCadGroup().GetName(), + CCadText().GetName(), + _T("CadBmp"), + }; + for (int _i = 0; _i < 15; _i++) + { + if (!(m_nTypeMask & (1 << _i))) + continue; + + CString _strName = c_sstrNames[_i]; + pMenu_->InsertMenu(pCmdUI_->m_nIndex++, MF_STRING | MF_BYPOSITION, IDCMD_SELECTTARGET_SELECTBYTYPE0 + _i, _strName); + } + + // update end menu count + pCmdUI_->m_nIndex--; // point to last menu added + pCmdUI_->m_nIndexMax = pMenu_->GetMenuItemCount(); + + pCmdUI_->m_bEnableChanged = TRUE; // all the added items are enabled +} + +// 鼠标左键按下的响应函数 Wanglou 2010-06-13 +BOOL CSelectTarget::OnLButtonDown(UINT nFlags_, DPOINT2 point_) +{ + if (!IsActive() && GetActiveTarget() != NULL) + return FALSE; + + if (IsInvalidDouble(m_ptLButtonDown.x) || IsInvalidDouble(m_ptLButtonDown.y)) + m_ptLButtonDown = point_; + return TRUE; +} + +// 坐标左键弹起的响应函数 Wanglou 2010-06-13 +BOOL CSelectTarget::OnLButtonUp(UINT nFlags_, DPOINT2 point_) +{ + if (!IsActive() && GetActiveTarget() != NULL) + return FALSE; + + if (IsInvalidDouble(m_ptLButtonDown.x) || IsInvalidDouble(m_ptLButtonDown.y)) + return FALSE; + + CadObjectList _listSelectedCads = *GetSelectedCadObjects(); + CadObjectList _listSelectedRefs = *GetSelectedRefLines(); + + // 放宽鼠标点击的判断条件,点下和弹起的地方可以不是同一个点,但必须足够近, + // 点下和弹起处的距离不超过点选容差的1/2则认为是点击,即认为是点选,否则则 + // 为框选。 ---- 杨开锦 2011-07-16 + double _nTolerance = GetSelectToleranceLP(); + if (abs(m_ptLButtonDown.x - point_.x) <= _nTolerance / 2. + && abs(m_ptLButtonDown.y - point_.y) <= _nTolerance / 2.) + { + SelectByPoint(nFlags_, point_, _nTolerance); + } + else + { + SelectByRect(nFlags_, m_ptLButtonDown, point_); + } + + // 发送消息告诉所有Target选择的对象发生了改变 Wanglou 2010-06-13 + //SendTargetMessage(ID_TARGET_BROADCAST, TN_SELECT_CHANGE, (WPARAM)GetSelectedCadObjects());//&m_listSelectedCadObjects); + Reset(); + + bool _bChanged = _listSelectedCads != *GetSelectedCadObjects() || _listSelectedRefs != *GetSelectedRefLines(); + if (_bChanged) + { + // 因为变化而更新 ---- 王斌 2013.06.17 + UpdateAllVisions(); + } + else + { + // 没有变化也要更新自己(考虑选择框) ---- 王斌 2013.06.17 + UpdateVisions(); + } + return TRUE; +} + +BOOL CSelectTarget::OnRButtonUp(UINT nFlags_, DPOINT2 point_) +{ + if (!IsActive() && GetActiveTarget() != NULL) + return FALSE; + + if (IsValidDouble(m_ptLButtonDown.x) || IsValidDouble(m_ptLButtonDown.y)) + { + Reset(); + UpdateVisions(); + } + else + { + // 求鼠标位置(Screen坐标) ---- 杨开锦 2010-08-16 + ASSERT(m_pNceDC); + CPoint _ptPos = m_pNceDC->LPtoDP_Point(point_); + CWnd* _pWnd = m_pNceDC->GetWindow(); + ASSERT(_pWnd); + _pWnd->ClientToScreen(&_ptPos); + + // 弹出右键菜单 ---- 杨开锦 2010-08-16 + // 添加选中参考线时的右键菜单-------liangyan 2013-10-23 + if (m_listSelectedCadObjects.size() == 0 && m_pRButtonMenu_NoneSelected && m_listSelectedRefLines.size() == 0) + m_pRButtonMenu_NoneSelected->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON , _ptPos.x, _ptPos.y, AfxGetMainWnd()); + else if (m_listSelectedCadObjects.size() == 1 && m_pRButtonMenu_SingleSelected) + m_pRButtonMenu_SingleSelected->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON , _ptPos.x, _ptPos.y, AfxGetMainWnd()); + else if (m_pRButtonMenu_MultiSelected || m_listSelectedRefLines.size() != 0) + m_pRButtonMenu_MultiSelected->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON , _ptPos.x, _ptPos.y, AfxGetMainWnd()); + } + + return TRUE; +} + +BOOL CSelectTarget::OnMouseMove(UINT nFlags_, DPOINT2 point_) +{ + if (!IsActive() && GetActiveTarget() != NULL) + return FALSE; + + if (IsInvalidDouble(m_ptLButtonDown.x) || IsInvalidDouble(m_ptLButtonDown.y)) + return FALSE; + + m_ptTemp = point_; + UpdateVisions(); + return TRUE; +} + +BOOL CSelectTarget::OnKeyDown(UINT nChar_, UINT nRepCnt_, UINT nFlags_) +{ + if (nChar_ == VK_ESCAPE && (IsActive() || GetActiveTarget() == NULL)) + { + // Esc清除选择 ---- 孙彦春 2012-5-27 + ClearSelect(); + UpdateAllVisions(); + return TRUE; + } + + return FALSE; +} + +// 点选功能实现: 首先考虑选择参考线,如果不是选择参考线则根据ctrl、shift键的状态 +// 区分为普通、加选、减选、反选。 +// 点选只考虑一个图形,点到则是1个,点不到则是0个。 ---- 杨开锦 2011-07-16 +// 参考线也根据ctrl、shift键的状态 区分为普通、加选、减选、反选-----liangyan 2013-10-19 +BOOL CSelectTarget::SelectByPoint(UINT nFlags_, const DPOINT2& point_, double nTolerance_) +{ + bool _bCtrlKeyDown = (nFlags_ & MK_CONTROL) != 0; + bool _bShiftKeyDown = (nFlags_ & MK_SHIFT) != 0; + BOOL _nRet = FALSE; + + // 区分点选模式 ---- 杨开锦 2011-07-16 + if (!_bCtrlKeyDown && !_bShiftKeyDown) + { + if (SelectRefLine(point_, nTolerance_)) + _nRet = TRUE; + else + _nRet = _SelectByPoint_Normal(point_, nTolerance_); + } + else if (_bCtrlKeyDown && !_bShiftKeyDown) + { + _nRet = _SelectByPoint_Increase(point_, nTolerance_); + } + else if (!_bCtrlKeyDown && _bShiftKeyDown) + { + _nRet = _SelectByPoint_Decrease(point_, nTolerance_); + } + else + { + ASSERT(_bCtrlKeyDown && _bShiftKeyDown); + _nRet = _SelectByPoint_Reverse(point_, nTolerance_); + } + + // 更新选中对象链表 ---- 杨开锦 2011-07-16 + GetSelectedCadObjects(true); + GetSelectedRefLines(true); + return _nRet; +} + +// 点选--普通模式: 若点到,则选中点到的图形,其他均去选中;若点不到,则所有均去 +// 选中。 +// 首先用点选发生点和点选容差构造一个观察窗矩形,然后根据各图形与这个观察窗的 +// 包含与相交内外关系将所有图形进行分类,考虑相交的图形组的全部、以及包含的图形 +// 组的若干个。 ---- 杨开锦 2011-07-16 +BOOL CSelectTarget::_SelectByPoint_Normal(const DPOINT2& point_, double nTolerance_) +{ + ASSERT(nTolerance_ >= 0.); + ASSERT(m_pFileTarget); + + // 构造观察窗矩形并分类 ---- 杨开锦 2011-07-16 + DRECT _rcViewport(point_.x - nTolerance_, point_.y - nTolerance_, + 2. * nTolerance_, 2. * nTolerance_); + const CadObjectList* _plistCurrentGroup = m_pFileTarget->GetCurrentCadGroup()->GetObjectsList(); + ASSERT(_plistCurrentGroup); + CadObjectList _listFullInside; + CadObjectList _listPartInside; + _DivideObjectsIntoThree(_plistCurrentGroup, _rcViewport, &_listFullInside, &_listPartInside, NULL); + + // 收集考虑的图形集 ---- 杨开锦 2011-07-16 + CadObjectList _listTarget; + const int _c_nMaxCount = 10; // 最多考虑FullInside部分中的N个 + int _nCurCount = 0; + for (CadObjectList::iterator _it = _listFullInside.begin(); _it != _listFullInside.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + _listTarget.push_back(_pCad); + _nCurCount++; + + if (_nCurCount >= _c_nMaxCount) + { + break; + } + } + for (CadObjectList::iterator _it = _listPartInside.begin(); _it != _listPartInside.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + _listTarget.push_back(_pCad); + } + + // 命中测试 ---- 杨开锦 2011-07-16 + CCadObject* _pCadSelected = nce::Hit(&_listTarget, point_, nTolerance_, NULL); + + // Carry out 计算结果 ---- 杨开锦 2011-07-16 + for (CadObjectList::const_iterator _it = _plistCurrentGroup->begin(); _it != _plistCurrentGroup->end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + _pCad->Select(false); + } + + if (_pCadSelected) + { + _pCadSelected->Select(true); + } + + return (_pCadSelected != NULL); +} + +// 点选--加选模式: 若点到,则选中点到的图形;若点不到,则无运作。 +// 因为是加选,仅须考虑当前未选中的图形,已选中的图形不考虑;同前理,用点选发 +// 生点和点选容差构造一个观察窗矩形,然后根据各图形与这个观察窗的包含与相交内外 +// 关系将未选中图形进行分类,考虑相交的图形组的全部、以及包含的图形组的若干个。 +// ---- 杨开锦 2011-07-16 +BOOL CSelectTarget::_SelectByPoint_Increase(const DPOINT2& point_, double nTolerance_) +{ + ASSERT(nTolerance_ >= 0.); + ASSERT(m_pFileTarget); + + // 构造观察窗矩形并分类 ---- 杨开锦 2011-07-16 + DRECT _rcViewport(point_.x - nTolerance_, point_.y - nTolerance_, + 2. * nTolerance_, 2. * nTolerance_); + const CadObjectList* _plistCurrentGroup = m_pFileTarget->GetCurrentCadGroup()->GetObjectsList(); + CCadGroup* _pRefLines = m_pFileTarget->GetCurrentRefLines(); + ASSERT(_plistCurrentGroup || _pRefLines);; + CadObjectList _listFullInside; + CadObjectList _listPartInside; + _DivideObjectsIntoThree(_plistCurrentGroup, _rcViewport, &_listFullInside, &_listPartInside, NULL); + + // 收集考虑的图形集 ---- 杨开锦 2011-07-16 + CadObjectList _listTarget; + const int _c_nMaxCount = 10; // 最多考虑FullInside部分中的N个 + int _nCurCount = 0; + for (CadObjectList::iterator _it = _listFullInside.begin(); _it != _listFullInside.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + if (_pCad->IsSelected()) + { + continue; + } + + _listTarget.push_back(_pCad); + _nCurCount++; + + if (_nCurCount >= _c_nMaxCount) + { + break; + } + } + for (CadObjectList::iterator _it = _listPartInside.begin(); _it != _listPartInside.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + if (!_pCad->IsSelected()) + { + _listTarget.push_back(_pCad); + } + } + // 命中测试 ---- 杨开锦 2011-07-16 + CCadObject* _pCadSelected = nce::Hit(&_listTarget, point_, nTolerance_, NULL); + CCadObject* _pRefLinesSelected = Hit(_pRefLines, point_, nTolerance_); + // 加选时,Cad对象和参考线不能同时选中,如果命中Cad对象,则应先清除所有参考线的选中状态, + // 如果参考线命中,则应清除所有Cad对象的选中状态-----liangyan 2013-10-19 + int _nCount = _pRefLines->GetNumOfChild(); + if (_pCadSelected) + { + for (int _i = 0; _i < _nCount; _i++) + _pRefLines->GetAt(_i)->Select(false); + _pCadSelected->Select(true); + } + if(_pRefLinesSelected) + { + for (CadObjectList::const_iterator _iter = _plistCurrentGroup->begin(); _iter != _plistCurrentGroup->end(); _iter++) + { + if ((*_iter)->IsSelected()) + (*_iter)->Select(false); + } + _pRefLinesSelected->Select(true); + } + return (_pCadSelected != NULL|| _pRefLinesSelected != NULL); +} + +// 点选--减选模式: 若点到,则去选中点到的图形;若点不到,则无运作。 +// 因为是减选,仅须考虑当前已选中的图形,未选中的图形不考虑;同前理,用点选发 +// 生点和点选容差构造一个观察窗矩形,然后根据各图形与这个观察窗的包含与相交内外 +// 关系将已选中图形进行分类,考虑相交的图形组的全部、以及包含的图形组的若干个。 +// ---- 杨开锦 2011-07-16 +BOOL CSelectTarget::_SelectByPoint_Decrease(const DPOINT2& point_, double nTolerance_) +{ + ASSERT(nTolerance_ >= 0.); + ASSERT(m_pFileTarget); + + // 构造观察窗矩形并分类 ---- 杨开锦 2011-07-16 + DRECT _rcViewport(point_.x - nTolerance_, point_.y - nTolerance_, + 2. * nTolerance_, 2. * nTolerance_); + const CadObjectList* _plistSelectedCadObjects = GetSelectedCadObjects(); + CCadGroup* _pRefLines = m_pFileTarget->GetCurrentRefLines(); + ASSERT(_plistSelectedCadObjects || _pRefLines); + CadObjectList _listFullInside; + CadObjectList _listPartInside; + _DivideObjectsIntoThree(_plistSelectedCadObjects, _rcViewport, &_listFullInside, &_listPartInside, NULL); + + // 收集考虑的图形集 ---- 杨开锦 2011-07-16 + CadObjectList _listTarget; + const int _c_nMaxCount = 10; // 最多考虑FullInside部分中的N个 + int _nCurCount = 0; + for (CadObjectList::iterator _it = _listFullInside.begin(); _it != _listFullInside.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + _listTarget.push_back(_pCad); + _nCurCount++; + + if (_nCurCount >= _c_nMaxCount) + { + break; + } + } + for (CadObjectList::iterator _it = _listPartInside.begin(); _it != _listPartInside.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + _listTarget.push_back(_pCad); + } + + // 命中测试 ---- 杨开锦 2011-07-16 + CCadObject* _pCadSelected = nce::Hit(&_listTarget, point_, nTolerance_, NULL); + // Carry out 计算结果 ---- 杨开锦 2011-07-16 + if (_pCadSelected) + { + _pCadSelected->Select(false); + } + // shift键,参考线的减选功能 ---liangyan 2013-10-19 + CCadObject* _pRefLinesSelected = Hit(_pRefLines, point_, nTolerance_); + if (_pRefLinesSelected) + { + _pRefLinesSelected->Select(false); + } + return (_pCadSelected != NULL || _pRefLinesSelected != NULL); +} + +// 点选--反选模式: 若点到,则反转选中状态;若点不到,则无运作。 +// 同前理,用点选发生点和点选容差构造一个观察窗矩形,然后根据各图形与这个观察 +// 窗的包含与相交内外关系将所有图形进行分类,考虑相交的图形组的全部、以及包含的 +// 图形组的若干个。 +// ---- 杨开锦 2011-07-16 +BOOL CSelectTarget::_SelectByPoint_Reverse(const DPOINT2& point_, double nTolerance_) +{ + ASSERT(nTolerance_ >= 0.); + ASSERT(m_pFileTarget); + + // 构造观察窗矩形并分类 ---- 杨开锦 2011-07-16 + DRECT _rcViewport(point_.x - nTolerance_, point_.y - nTolerance_, + 2. * nTolerance_, 2. * nTolerance_); + const CadObjectList* _plistCurrentGroup = m_pFileTarget->GetCurrentCadGroup()->GetObjectsList(); + CCadGroup* _pRefLines = m_pFileTarget->GetCurrentRefLines(); + ASSERT(_plistCurrentGroup || _pRefLines); + CadObjectList _listFullInside; + CadObjectList _listPartInside; + _DivideObjectsIntoThree(_plistCurrentGroup, _rcViewport, &_listFullInside, &_listPartInside, NULL); + + // 收集考虑的图形集 ---- 杨开锦 2011-07-16 + CadObjectList _listTarget; + const int _c_nMaxCount = 10; // 最多考虑FullInside部分中的N个 + int _nCurCount = 0; + for (CadObjectList::iterator _it = _listFullInside.begin(); _it != _listFullInside.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + _listTarget.push_back(_pCad); + _nCurCount++; + + if (_nCurCount >= _c_nMaxCount) + { + break; + } + } + for (CadObjectList::iterator _it = _listPartInside.begin(); _it != _listPartInside.end(); _it++) + { + CCadObject* _pCad = *_it; + ASSERT(_pCad); + _listTarget.push_back(_pCad); + } + + // 命中测试 ---- 杨开锦 2011-07-16 + // ctrl + shift反选时,Cad对象和参考线不能同时选中,如果命中Cad对象,则应先清除所有参考线的选中状态, + // 如果参考线命中,则应清除所有Cad对象的选中状态-----liangyan 2013-10-19 + CCadObject* _pCadSelected = nce::Hit(&_listTarget, point_, nTolerance_, NULL); + CCadObject* _pRefLinesSelected = Hit(_pRefLines, point_, nTolerance_); + int _nCount = _pRefLines->GetNumOfChild(); + if (_pCadSelected) + { + for (int _i = 0; _i < _nCount; _i++) + _pRefLines->GetAt(_i)->Select(false); + _pCadSelected->Select(!_pCadSelected->IsSelected()); + } + if(_pRefLinesSelected) + { + for (CadObjectList::const_iterator _iter = _plistCurrentGroup->begin(); _iter != _plistCurrentGroup->end(); _iter++) + { + if ((*_iter)->IsSelected()) + (*_iter)->Select(false); + } + _pRefLinesSelected->Select(!_pRefLinesSelected->IsSelected()); + } + return (_pCadSelected != NULL || _pRefLinesSelected != NULL); +} + +// 框选功能的实现函数,ptFirst_,ptSecond_,为框选矩形一条对角线的两端点 Wanglou 2010-06-13 +UINT CSelectTarget::SelectByRect(UINT nFlags_, const DPOINT2& ptFirst_, const DPOINT2& ptSecond_) +{ + // 框选不会选中参考线,并且会把参考线的选择状态清除掉 Wanglou 2010-08-21 + ASSERT(m_pFileTarget); + CCadGroup* _pRefLines = m_pFileTarget->GetCurrentRefLines(); + ASSERT(_pRefLines); + for (int _i = 0; _i < _pRefLines->GetNumOfChild(); _i++) + { + CCadObject* _pCad = _pRefLines->GetAt(_i); + ASSERT(_pCad); + _pCad->Select(false); + } + + bool _bCtrlKeyDown = (nFlags_ & MK_CONTROL) != 0; + bool _bShiftKeyDown = (nFlags_ & MK_SHIFT) != 0; + + // 区分框选模式 ---- 杨开锦 2011-07-16 + UINT _nRet = 0; + if (!_bCtrlKeyDown && !_bShiftKeyDown) + { + _nRet = _SelectByRect_Normal(ptFirst_, ptSecond_); + } + else if (_bCtrlKeyDown && !_bShiftKeyDown) + { + _nRet = _SelectByRect_Increase(ptFirst_, ptSecond_); + } + else if (!_bCtrlKeyDown && _bShiftKeyDown) + { + _nRet = _SelectByRect_Decrease(ptFirst_, ptSecond_); + } + else + { + ASSERT(_bCtrlKeyDown && _bShiftKeyDown); + _nRet = _SelectByRect_Reverse(ptFirst_, ptSecond_); + } + + // 更新选中对象链表 ---- 杨开锦 2011-07-16 + GetSelectedCadObjects(true); + GetSelectedRefLines(true); + + return _nRet; +} + +// 框选--普通模式: 图形在选择框内则被选中,否则去选中。 ---- 杨开锦 2011-07-16 +UINT CSelectTarget::_SelectByRect_Normal(const DPOINT2& ptFirst_, const DPOINT2& ptSecond_) +{ + // 框选 ---- 杨开锦 2011-07-16 + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + ASSERT(_pCadGroup); + UINT _nRet = 0; + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if (_SelectCadObjectByRect(_pCadObject, ptFirst_, ptSecond_)) + { + _pCadObject->Select(true); + _nRet++; + } + else + { + _pCadObject->Select(false); + } + } + + return _nRet; +} + +// 框选--加选模式: 图形在选择框内则被选中,否则无动作。 ---- 杨开锦 2011-07-16 +UINT CSelectTarget::_SelectByRect_Increase(const DPOINT2& ptFirst_, const DPOINT2& ptSecond_) +{ + // 加选 ---- 杨开锦 2011-07-16 + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + ASSERT(_pCadGroup); + UINT _nRet = 0; + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if (_SelectCadObjectByRect(_pCadObject, ptFirst_, ptSecond_)) + { + _pCadObject->Select(true); + _nRet++; + } + } + + return _nRet; +} + +// 框选--减选模式: 图形在选择框内则去选中,否则无动作。 ---- 杨开锦 2011-07-16 +UINT CSelectTarget::_SelectByRect_Decrease(const DPOINT2& ptFirst_, const DPOINT2& ptSecond_) +{ + // 减选 ---- 杨开锦 2011-07-16 + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + ASSERT(_pCadGroup); + UINT _nRet = 0; + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if (_SelectCadObjectByRect(_pCadObject, ptFirst_, ptSecond_)) + { + _pCadObject->Select(false); + _nRet++; + } + } + + return _nRet; +} + +// 框选--反选模式: 图形在选择框内则反转选中状态,否则无动作。 ---- 杨开锦 2011-07-16 +UINT CSelectTarget::_SelectByRect_Reverse(const DPOINT2& ptFirst_, const DPOINT2& ptSecond_) +{ + // 反选 ---- 杨开锦 2011-07-16 + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + ASSERT(_pCadGroup); + UINT _nRet = 0; + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if (_SelectCadObjectByRect(_pCadObject, ptFirst_, ptSecond_)) + { + bool _bSelected = _pCadObject->IsSelected(); + _pCadObject->Select(!_bSelected); + _nRet++; + } + } + + return _nRet; +} + +UINT CSelectTarget::_SelectCadObjectByColore(int nColoreIndex_) +{ + ASSERT(m_pFileTarget); + ASSERT(nColoreIndex_ >= 0); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + + UINT _nRet = 0; + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if(_pCadObject->GetParamIndex() == nColoreIndex_) + { + _pCadObject->Select(); + _nRet++; + } + else + { + _pCadObject->Select(false); + } + } + + return _nRet; +} + +LRESULT CSelectTarget::SelectByColore(WPARAM wParam_, LPARAM lParam_) +{ + int _nIndex = (int)wParam_; + ASSERT(_nIndex >= 0); + + return _SelectCadObjectByColore(_nIndex); +} + +void CSelectTarget::OnSelectSimilar() +{ + // 选中相似图形,先指定一个参照图形,不选或者多选或者选中组都不管。 --- 黄海燕 2015-12-22 + const CadObjectList* _plistRefObjs = GetSelectedCadObjects(); + if (_plistRefObjs->size() != 1 + || (*_plistRefObjs->begin())->GetType() == cadgroup + || (*_plistRefObjs->begin())->GetType() == cadtext) + { + return; + } + + CCadObject* _pRefObj = *(_plistRefObjs->begin()); + switch(_pRefObj->GetType()) + { + case caddot: + { + _SelectSimilarDot((CCadDot*)_pRefObj); + break; + } + case cadline: + { + _SelectSimilarLine((CCadLine*)_pRefObj); + break; + } + + case cadcircle: + { + _SelectSimilarCircle((CCadCircle*)_pRefObj); + break; + } + + case cadarc: + { + _SelectSimilarArc((CCadArc*)_pRefObj); + break; + } + + case cadellipse: + { + _SelectSimilarEllipse((CCadEllipse*)_pRefObj); + break; + } + + case cadellipsearc: + { + _SelectSimilarEllipseArc((CCadEllipseArc*)_pRefObj); + break; + } + + case cadrectangle: + { + _SelectSimilarRectangle((CCadRectangle*)_pRefObj); + break; + } + + case cadpolygon: + { + _SelectSimilarPolygon((CCadPolygon*)_pRefObj); + break; + } + + case cadstar: + { + _SelectSimilarStar((CCadStar*)_pRefObj); + break; + } + + case cadpolyline: + { + _SelectSimilarPolyline((CCadPolyline*)_pRefObj); + break; + } + + default: + { + // do noting + } + } + + UpdateAllVisions(); +} + +void CSelectTarget::OnUpdateSelectSimilar(CCmdUI* pCmdUI_) +{ + const CadObjectList* _pSelectObjs = GetSelectedCadObjects(); + pCmdUI_->Enable(_pSelectObjs && _pSelectObjs->size() > 0); +} + +// 所有的点都是相似的。 ---- 黄海燕 2015-12-22 +void CSelectTarget::_SelectSimilarDot(const nce::CCadDot* pRefDot_) +{ + if (!pRefDot_) + { + ASSERT(FALSE); + return; + } + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + UINT _nRet = 0; + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + // 自己肯定长得像自己,不过这里的前提是每个对象的ID是唯一的。 ---- 黄海燕 2016-01-07 + if (_pCadObject->GetID() == pRefDot_->GetID()) + { + _pCadObject->Select(true); + continue; + } + + if(_pCadObject->GetType() == caddot) + { + _pCadObject->Select(); + } + else + { + _pCadObject->Select(false); + } + } +} + +// 平行且长度相等的线为相似图形。 ---- 黄海燕 2015-12-22 +void CSelectTarget::_SelectSimilarLine(const nce::CCadLine* pRefLine_) +{ + if (!pRefLine_) + { + ASSERT(FALSE); + return; + } + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if(_pCadObject->GetType() != cadline) + { + _pCadObject->Select(false); + continue; + } + + // 自己肯定长得像自己,不过这里的前提是每个对象的ID是唯一的。 ---- 黄海燕 2016-01-07 + if (_pCadObject->GetID() == pRefLine_->GetID()) + { + _pCadObject->Select(true); + continue; + } + + CCadLine* _pLine = (CCadLine*)_pCadObject; + DPOINT2 _ptV1 = DPOINT2(_pLine->GetStartPoint() - _pLine->GetEndPoint()); + DPOINT2 _ptV2 = DPOINT2(pRefLine_->GetStartPoint() - pRefLine_->GetEndPoint()); + if (DOUBLE_EQU_ZERO(_ptV1.x * _ptV2.y - _ptV1.y * _ptV2.x) + && DOUBLE_ROUGHEQU(_ptV1.GetLength(), _ptV2.GetLength())) + { + _pLine->Select(); + } + else + { + _pLine->Select(false); + } + } +} + +// 半径相等的圆为相似图形。 ---- 黄海燕 2015-12-22 +void CSelectTarget::_SelectSimilarCircle(const nce::CCadCircle* pRefCircle_) +{ + if (!pRefCircle_) + { + ASSERT(FALSE); + return; + } + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if(_pCadObject->GetType() != cadcircle) + { + _pCadObject->Select(false); + continue; + } + + // 自己肯定长得像自己,不过这里的前提是每个对象的ID是唯一的。 ---- 黄海燕 2016-01-07 + if (_pCadObject->GetID() == pRefCircle_->GetID()) + { + _pCadObject->Select(true); + continue; + } + + CCadCircle* _pCircle = (CCadCircle*)_pCadObject; + if (DOUBLE_ROUGHEQU(_pCircle->GetRadius(), pRefCircle_->GetRadius())) + { + _pCircle->Select(true); + } + else + { + _pCircle->Select(false); + } + } +} + +// 半径相等长度相等的圆弧为相似图形。 ---- 黄海燕 2015-12-22 +void CSelectTarget::_SelectSimilarArc(const nce::CCadArc* pRefArc_) +{ + if (!pRefArc_) + { + ASSERT(FALSE); + return; + } + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if(_pCadObject->GetType() != cadarc) + { + _pCadObject->Select(false); + continue; + } + + // 自己肯定长得像自己,不过这里的前提是每个对象的ID是唯一的。 ---- 黄海燕 2016-01-07 + if (_pCadObject->GetID() == pRefArc_->GetID()) + { + _pCadObject->Select(true); + continue; + } + + CCadArc* _pArc = (CCadArc*)_pCadObject; + if (DOUBLE_ROUGHEQU(_pArc->GetRadius(), pRefArc_->GetRadius()) + && DOUBLE_ROUGHEQU(_pArc->GetLength(), pRefArc_->GetLength())) + { + _pArc->Select(true); + } + else + { + _pArc->Select(false); + } + } +} + +// 长半轴和短半轴相等的椭圆形为相似图形。 ---- 黄海燕 2015-12-22 +void CSelectTarget::_SelectSimilarEllipse(const nce::CCadEllipse* pRefEllipse_) +{ + if (!pRefEllipse_) + { + ASSERT(FALSE); + return; + } + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if(_pCadObject->GetType() != cadellipse) + { + _pCadObject->Select(false); + continue; + } + + // 自己肯定长得像自己,不过这里的前提是每个对象的ID是唯一的。 ---- 黄海燕 2016-01-07 + if (_pCadObject->GetID() == pRefEllipse_->GetID()) + { + _pCadObject->Select(true); + continue; + } + + CCadEllipse* _pEllipse = (CCadEllipse*)_pCadObject; + if ((DOUBLE_ROUGHEQU(_pEllipse->GetLongRadius(), pRefEllipse_->GetLongRadius()) + && DOUBLE_ROUGHEQU(_pEllipse->GetShortRadius(), pRefEllipse_->GetShortRadius()))) + { + _pEllipse->Select(true); + } + else + { + _pEllipse->Select(false); + } + } +} + +// 长半轴、短半轴、倾斜角、起始角和终止角相等的椭圆弧形为相似图形。 ---- 黄海燕 2015-12-22 +void CSelectTarget::_SelectSimilarEllipseArc(const nce::CCadEllipseArc* pRefEllipseArc_) +{ + if (!pRefEllipseArc_) + { + ASSERT(FALSE); + return; + } + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if(_pCadObject->GetType() != cadellipsearc) + { + _pCadObject->Select(false); + continue; + } + + // 自己肯定长得像自己,不过这里的前提是每个对象的ID是唯一的。 ---- 黄海燕 2016-01-07 + if (_pCadObject->GetID() == pRefEllipseArc_->GetID()) + { + _pCadObject->Select(true); + continue; + } + + bool _bSelect = false; + CCadEllipseArc* _pEllipseArc = (CCadEllipseArc*)_pCadObject; + if (DOUBLE_ROUGHEQU(_pEllipseArc->GetLongRadius(), pRefEllipseArc_->GetLongRadius()) + && DOUBLE_ROUGHEQU(_pEllipseArc->GetShortRadius(), pRefEllipseArc_->GetShortRadius()) + && DOUBLE_ROUGHEQU(_pEllipseArc->GetCentralAngle(), pRefEllipseArc_->GetCentralAngle())) + { + if (DOUBLE_ROUGHEQU(_pEllipseArc->GetStartAngle(), pRefEllipseArc_->GetStartAngle()) + && _pEllipseArc->IsNormalDir() == pRefEllipseArc_->IsNormalDir()) + { + _bSelect = true; + } + if (DOUBLE_ROUGHEQU(_pEllipseArc->GetEndAngle(), pRefEllipseArc_->GetStartAngle()) + && _pEllipseArc->IsNormalDir() == !pRefEllipseArc_->IsNormalDir()) + { + _bSelect = true; + } + + double _nStartAngle = _pEllipseArc->GetStartAngle() + ncmath::c_nPIE; + if (_nStartAngle >= 2 * ncmath::c_nPIE) + { + _nStartAngle -= 2 * ncmath::c_nPIE; + } + if (DOUBLE_ROUGHEQU(_nStartAngle, pRefEllipseArc_->GetStartAngle()) + && _pEllipseArc->IsNormalDir() == pRefEllipseArc_->IsNormalDir()) + { + _bSelect = true; + } + if (DOUBLE_ROUGHEQU(_nStartAngle, pRefEllipseArc_->GetEndAngle()) + && _pEllipseArc->IsNormalDir() == !pRefEllipseArc_->IsNormalDir()) + { + _bSelect = true; + } + + _nStartAngle = 2 * ncmath::c_nPIE - _pEllipseArc->GetStartAngle(); + if (_nStartAngle >= 2 * ncmath::c_nPIE) + { + _nStartAngle -= 2 * ncmath::c_nPIE; + } + if (DOUBLE_ROUGHEQU(_nStartAngle, pRefEllipseArc_->GetStartAngle()) + && _pEllipseArc->IsNormalDir() == !pRefEllipseArc_->IsNormalDir()) + { + _bSelect = true; + } + if (DOUBLE_ROUGHEQU(_nStartAngle, pRefEllipseArc_->GetEndAngle()) + && _pEllipseArc->IsNormalDir() == pRefEllipseArc_->IsNormalDir()) + { + _bSelect = true; + } + + _nStartAngle += ncmath::c_nPIE; + if (_nStartAngle >= 2 * ncmath::c_nPIE) + { + _nStartAngle -= 2 * ncmath::c_nPIE; + } + if (DOUBLE_ROUGHEQU(_nStartAngle, pRefEllipseArc_->GetStartAngle()) + && _pEllipseArc->IsNormalDir() == !pRefEllipseArc_->IsNormalDir()) + { + _bSelect = true; + } + if (DOUBLE_ROUGHEQU(_nStartAngle, pRefEllipseArc_->GetEndAngle()) + && _pEllipseArc->IsNormalDir() == pRefEllipseArc_->IsNormalDir()) + { + _bSelect = true; + } + } + _pEllipseArc->Select(_bSelect); + } +} + +// 长和宽相等的矩形为相似图形。 ---- 黄海燕 2015-12-22 +void CSelectTarget::_SelectSimilarRectangle(const nce::CCadRectangle* pRefRectangle_) +{ + if (!pRefRectangle_) + { + ASSERT(FALSE); + return; + } + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if(_pCadObject->GetType() != cadrectangle) + { + _pCadObject->Select(false); + continue; + } + + // 自己肯定长得像自己,不过这里的前提是每个对象的ID是唯一的。 ---- 黄海燕 2016-01-07 + if (_pCadObject->GetID() == pRefRectangle_->GetID()) + { + _pCadObject->Select(true); + continue; + } + + CCadRectangle* _pRectangle = (CCadRectangle*)_pCadObject; + if ((DOUBLE_ROUGHEQU(_pRectangle->GetWidth(), pRefRectangle_->GetWidth()) + && DOUBLE_ROUGHEQU(_pRectangle->GetHeitht(), pRefRectangle_->GetHeitht())) + || (DOUBLE_ROUGHEQU(_pRectangle->GetWidth(), pRefRectangle_->GetHeitht()) + && DOUBLE_ROUGHEQU(_pRectangle->GetHeitht(), pRefRectangle_->GetWidth()))) + { + _pRectangle->Select(true); + } + else + { + _pRectangle->Select(false); + } + } +} + +// 外接圆半径和内接圆半径相同,定点数相等的正多边形为相似图形。 ---- 黄海燕 2015-12-22 +void CSelectTarget::_SelectSimilarPolygon(const nce::CCadPolygon* pRefPolygon_) +{ + if (!pRefPolygon_) + { + ASSERT(FALSE); + return; + } + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if(_pCadObject->GetType() != cadpolygon) + { + _pCadObject->Select(false); + continue; + } + + // 自己肯定长得像自己,不过这里的前提是每个对象的ID是唯一的。 ---- 黄海燕 2016-01-07 + if (_pCadObject->GetID() == pRefPolygon_->GetID()) + { + _pCadObject->Select(true); + continue; + } + + CCadPolygon* _pPolygon = (CCadPolygon*)_pCadObject; + if (_pPolygon->GetNumOfVertexes() == pRefPolygon_->GetNumOfVertexes() + && DOUBLE_ROUGHEQU(_pPolygon->GetCircumRadius(), pRefPolygon_->GetCircumRadius()) + && DOUBLE_ROUGHEQU(_pPolygon->GetInscribedRadius(), pRefPolygon_->GetInscribedRadius())) + { + _pPolygon->Select(true); + } + else + { + _pPolygon->Select(false); + } + } +} + +// 外接圆半径和内接圆半径相同,定点数相等的星型为相似图形。 ---- 黄海燕 2015-12-22 +void CSelectTarget::_SelectSimilarStar(const nce::CCadStar* pRefStar_) +{ + if (!pRefStar_) + { + ASSERT(FALSE); + return; + } + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if(_pCadObject->GetType() != cadstar) + { + _pCadObject->Select(false); + continue; + } + + // 自己肯定长得像自己,不过这里的前提是每个对象的ID是唯一的。 ---- 黄海燕 2016-01-07 + if (_pCadObject->GetID() == pRefStar_->GetID()) + { + _pCadObject->Select(true); + continue; + } + + CCadStar* _pStar = (CCadStar*)_pCadObject; + if (_pStar->GetNumOfVertexes() == pRefStar_->GetNumOfVertexes() + && DOUBLE_ROUGHEQU(_pStar->GetCircumRadius(), pRefStar_->GetCircumRadius()) + && DOUBLE_ROUGHEQU(_pStar->GetInscribedRadius(), pRefStar_->GetInscribedRadius())) + { + _pStar->Select(true); + } + else + { + _pStar->Select(false); + } + } +} + +// 一模一样的多义线才算相似。 ---- 黄海燕 2015-12-22 +void CSelectTarget::_SelectSimilarPolyline(const nce::CCadPolyline* pRefPolyline_) +{ + if (!pRefPolyline_) + { + ASSERT(FALSE); + return; + } + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if(_pCadObject->GetType() != cadpolyline) + { + _pCadObject->Select(false); + continue; + } + + // 自己肯定长得像自己,不过这里的前提是每个对象的ID是唯一的。 ---- 黄海燕 2016-01-07 + if (_pCadObject->GetID() == pRefPolyline_->GetID()) + { + _pCadObject->Select(true); + continue; + } + + // 遍历比较。 + CCadPolyline* _pPolyline = (CCadPolyline*)_pCadObject; + if (_pPolyline->GetNodeCount() != pRefPolyline_->GetNodeCount() + || !DOUBLE_ROUGHEQU(_pPolyline->GetLength(), pRefPolyline_->GetLength())) + { + _pPolyline->Select(false); + continue; + } + + if (_pPolyline->GetNodeCount() == 1) + { + bool _bSelect = false; + CCadPolyline::ARCNODE _node = _pPolyline->GetAt(0); + CCadPolyline::ARCNODE _nodeRef = pRefPolyline_->GetAt(0); + if (!DOUBLE_EQU_ZERO(_node.nBulge) + && DOUBLE_ROUGHEQU(_node.nBulge, _nodeRef.nBulge) + && DOUBLE_ROUGHEQU(_pPolyline->GetLength(), pRefPolyline_->GetLength())) + { + _bSelect = true; + } + + DPOINT2 _ptV1 = _node.ptEnd - _pPolyline->GetStartPoint(); + DPOINT2 _ptV2 = _nodeRef.ptEnd - pRefPolyline_->GetStartPoint(); + if (DOUBLE_EQU_ZERO(_node.nBulge) + && DOUBLE_ROUGHEQU(_node.nBulge, _nodeRef.nBulge) + && DOUBLE_EQU_ZERO(_ptV1.x * _ptV2.y - _ptV1.y * _ptV2.x)) + { + _bSelect = true; + } + _pPolyline->Select(_bSelect); + continue; + } + + // 在进行详细的比对之前,我们需要先确认待判断图形与原图形的起点相对位置是否吻合, + // 是否出现错位(这种情况只有封闭图形会出现)或者顺序颠倒的情况 ---- 陈思 2017-03-17 + bool _bSelect; + CCadPolyline _RefPolylineCopy = *pRefPolyline_; // 原指针存储的对象是const类型的,这里我们用一个副本拷贝原对象,方便颠倒 + int _nCount = _pPolyline->GetNodeCount(); + int _nDeviationRange = 1; + // 如果是非封闭图形就不会存在错位现象了,只考虑方向颠倒,偏移范围为1 + if(_pPolyline->IsClose()) + { + _nDeviationRange = _nCount; + } + for(int _nDeviation = 0; _nDeviation < _nDeviationRange; ++_nDeviation) + { + _bSelect = true; + DPOINT2 _ptStart = _pPolyline->GetStartPoint(); + DPOINT2 _ptStartRef; + if(_nDeviation == 0) + { + _ptStartRef = _RefPolylineCopy.GetStartPoint(); + } + else + { + _ptStartRef = (_RefPolylineCopy.GetAt(_nDeviation - 1)).ptEnd; + } + // 定义一个控制镜像的开关,未知为0,打开为1,关闭为2 + int _nMirror = 0; + for(int _i = 1; _i < _nCount; _i++) + { + CCadPolyline::ARCNODE _nodeFirst = _pPolyline->GetAt(_i - 1); + CCadPolyline::ARCNODE _nodeSecond = _pPolyline->GetAt(_i); + + CCadPolyline::ARCNODE _nodeRefFirst = _RefPolylineCopy.GetAt((_i - 1 + _nDeviation) % _nCount); + CCadPolyline::ARCNODE _nodeRefSecond = _RefPolylineCopy.GetAt((_i + _nDeviation) % _nCount); + + // 如果绝对值都不相等,那肯定不相似 + if (!DOUBLE_ROUGHEQU(abs(_nodeFirst.nBulge), abs(_nodeRefFirst.nBulge))) + { + _bSelect = false; + break; + } + + // 当状态未知时出现绝对值相等的状况时,如果两个对应点的凸度为相反数,则将镜像开关打开,如果两者相等,则关闭 + // 如果两者都为0,还不能判断出到底是不是镜像,所以_nMirror保持为0不变,进入下一次循环重新判断 + if(_nMirror == 0) + { + if(_nodeFirst.nBulge * _nodeRefFirst.nBulge < 0) + { + _nMirror = 1; + } + + if(_nodeFirst.nBulge * _nodeRefFirst.nBulge > 0) + { + _nMirror = 2; + } + continue; + } + + // 在镜像开关打开的时候,如果两个对应点的凸度不等于零且相等,则镜像不成立,跳出 + else if(_nMirror == 1) + { + if(_nodeFirst.nBulge * _nodeRefFirst.nBulge > 0) + { + _bSelect = false; + break; + } + } + // 在镜像开关关闭的时候,如果两个对应点的凸度不为零且互为相反数,则不镜像不成立,跳出 + else + { + if(_nodeFirst.nBulge * _nodeRefFirst.nBulge < 0) + { + _bSelect = false; + break; + } + } + + DPOINT2 _ptFirstV = _nodeFirst.ptEnd - _ptStart; + DPOINT2 _ptSecondV = _nodeSecond.ptEnd - _nodeFirst.ptEnd; + DPOINT2 _ptFirstVRef = _nodeRefFirst.ptEnd - _ptStartRef; + DPOINT2 _ptSecondVRef = _nodeRefSecond.ptEnd - _nodeRefFirst.ptEnd; + if (!DOUBLE_ROUGHEQU(_ptFirstV.GetLength(), _ptFirstVRef.GetLength()) + || !DOUBLE_ROUGHEQU(_ptSecondV.GetLength(), _ptSecondVRef.GetLength())) + { + _bSelect = false; + break; + } + + if (!DOUBLE_ROUGHEQU(ncmath::D2GetIncludeAngle(_ptFirstV, _ptSecondV), ncmath::D2GetIncludeAngle(_ptFirstVRef, _ptSecondVRef))) + { + _bSelect = false; + break; + } + _ptStart = _nodeFirst.ptEnd; + _ptStartRef = _nodeRefFirst.ptEnd; + } + if(_bSelect) + { + break; + } + } + + // 如果第一次对比不吻合,则将待判断图形的方向颠倒一次后再比对 ---- 陈思 2017-03-17 + if(!_bSelect) + { + _RefPolylineCopy.ReverseDir(); + for(int _nDeviation = 0; _nDeviation < _nCount; ++_nDeviation) + { + _bSelect = true; + DPOINT2 _ptStart = _pPolyline->GetStartPoint(); + DPOINT2 _ptStartRef; + if(_nDeviation == 0) + { + _ptStartRef = _RefPolylineCopy.GetStartPoint(); + } + else + { + _ptStartRef = (_RefPolylineCopy.GetAt(_nDeviation - 1)).ptEnd; + } + // 定义一个控制镜像的开关,未知为0,打开为1,关闭为2 + int _nMirror = 0; + for(int _i = 1; _i < _nCount; _i++) + { + CCadPolyline::ARCNODE _nodeFirst = _pPolyline->GetAt(_i - 1); + CCadPolyline::ARCNODE _nodeSecond = _pPolyline->GetAt(_i); + + CCadPolyline::ARCNODE _nodeRefFirst = _RefPolylineCopy.GetAt((_i - 1 + _nDeviation) % _nCount); + CCadPolyline::ARCNODE _nodeRefSecond = _RefPolylineCopy.GetAt((_i + _nDeviation) % _nCount); + + + // 如果绝对值都不相等,那肯定不相似 + if (!DOUBLE_ROUGHEQU(abs(_nodeFirst.nBulge), abs(_nodeRefFirst.nBulge))) + { + _bSelect = false; + break; + } + + // 当状态未知时出现绝对值相等的状况时,如果两个对应点的凸度为相反数,则将镜像开关打开,如果两者相等,则关闭 + // 如果两者都为0,还不能判断出到底是不是镜像,所以_nMirror保持为0不变,进入下一次循环重新判断 + if(_nMirror == 0) + { + if(_nodeFirst.nBulge * _nodeRefFirst.nBulge < 0) + { + _nMirror = 1; + } + + if(_nodeFirst.nBulge * _nodeRefFirst.nBulge > 0) + { + _nMirror = 2; + } + continue; + } + + // 在镜像开关打开的时候,如果两个对应点的凸度不等于零且相等,则镜像不成立,跳出 + else if(_nMirror == 1) + { + if(_nodeFirst.nBulge * _nodeRefFirst.nBulge > 0) + { + _bSelect = false; + break; + } + } + // 在镜像开关关闭的时候,如果两个对应点的凸度不为零且互为相反数,则不镜像不成立,跳出 + else + { + if(_nodeFirst.nBulge * _nodeRefFirst.nBulge < 0) + { + _bSelect = false; + break; + } + } + + DPOINT2 _ptFirstV = _nodeFirst.ptEnd - _ptStart; + DPOINT2 _ptSecondV = _nodeSecond.ptEnd - _nodeFirst.ptEnd; + DPOINT2 _ptFirstVRef = _nodeRefFirst.ptEnd - _ptStartRef; + DPOINT2 _ptSecondVRef = _nodeRefSecond.ptEnd - _nodeRefFirst.ptEnd; + if (!DOUBLE_ROUGHEQU(_ptFirstV.GetLength(), _ptFirstVRef.GetLength()) + || !DOUBLE_ROUGHEQU(_ptSecondV.GetLength(), _ptSecondVRef.GetLength())) + { + _bSelect = false; + break; + } + + if (!DOUBLE_ROUGHEQU(ncmath::D2GetIncludeAngle(_ptFirstV, _ptSecondV), ncmath::D2GetIncludeAngle(_ptFirstVRef, _ptSecondVRef))) + { + _bSelect = false; + break; + } + _ptStart = _nodeFirst.ptEnd; + _ptStartRef = _nodeRefFirst.ptEnd; + } + if(_bSelect) + { + break; + } + } + } + _pPolyline->Select(_bSelect); + } +} + +// 给定的选择框是否选择到图形,区分正选和反选 ---- DingQiang 2011-12-9 +BOOL CSelectTarget::_SelectCadObjectByRect(const nce::CCadObject* pCadObject_, + const DPOINT2& ptFirst_, + const DPOINT2& ptSecond_) +{ + ASSERT(pCadObject_); + DRECT _rcSelect(ptFirst_, ptSecond_); // 选择框矩形 + DRECT _rcBound = pCadObject_->GetBoundRect(); // 图形外接矩形 + + // 如果选择框完全包围图形,则不区分正反选择返回TRUE ---- DingQiang 2011-12-9 + if (_rcSelect.Contains(_rcBound)) + { + return TRUE; + } + + // 如果选择框没有完全包围图形,则区分正反选。如果为正选择则反回FALSE ---- DingQiang 2011-12-9 + if (ptSecond_.x >= ptFirst_.x) + { + return FALSE; + } + + // 如果为反选,则判断选择框和图形的外接矩形是否相交,如果不相交则返回FALSE,由于 + // 水平的线段和垂直的线段外接矩与选择框一定没有交点,所以使宽高增加一点几乎可 + // 忽略的长度,以方便判断其与选择框是否相交 ---- DingQiang 2011-12-9 + if (_rcBound.width == 0) + { + _rcBound.width = 1.0e-9; + } + + if (_rcBound.height == 0) + { + _rcBound.height = 1.0e-9; + } + + if (!_rcSelect.Intersect(_rcBound)) + { + return FALSE; + } + + // 如果为负选且选择框和图形的外接矩形相交,则判断选择框是否和图形相交。先 + // 根据选择框矩形构造一个CAD矩形,再调用GetIntersection函数判断是否与图形 + // 有交点。 ---- DingQiang 2011-12-9 + DPOINT2 _ptPoint0 = ptFirst_; + DPOINT2 _ptPoint1(ptFirst_.x, ptSecond_.y); + DPOINT2 _ptPoint2 = ptSecond_; + DPOINT2 _ptPoint3(ptSecond_.x, ptFirst_.y); + CCadRectangle _CadRectangle(_ptPoint0, _ptPoint1, _ptPoint2, _ptPoint3); + + int _nIntersectionCounts = GetIntersection(&_CadRectangle, pCadObject_, NULL); + return (_nIntersectionCounts > 0); +} + +BOOL CSelectTarget::SelectRefLine(const DPOINT2& point_, double nTolerance_) +{ + ASSERT(m_pFileTarget); + CCadGroup* _pRefLines = m_pFileTarget->GetCurrentRefLines(); + if (!_pRefLines || _pRefLines->IsEmpty()) + return FALSE; + + // 参考线只能选中一个,选择第二个则会清除其他参考线的选中状态 Wanglou 2010-08-21 + int _nCount = _pRefLines->GetNumOfChild(); + for (int _i = 0; _i < _nCount; _i++) + _pRefLines->GetAt(_i)->Select(false); + + CCadObject* _pCadObject = Hit(_pRefLines, point_, nTolerance_); + if (!_pCadObject) + return FALSE; + + // 所有参考线都为直线,如果选择了参考线,则所有的Cad对象的选择状态都会清除 Wanglou 2010-08-21 + ASSERT(_pCadObject->GetType() == cadbeeline); + ClearSelect(); + _pCadObject->Select(true); + return TRUE; +} + +// 全选 +void CSelectTarget::SelectAll() +{ + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + if (_pCadGroup->IsEmpty()) + return; + const CadObjectList* _pCadObjList = _pCadGroup->GetObjectsList(); + bool _bChanged = false; + + // 先清除 ---- DingQiang 2013-09-23 + m_listSelectedCadObjects.clear(); + for (CadObjectList::const_iterator _iter = _pCadObjList->begin(); _iter != _pCadObjList->end(); _iter++) + { + m_listSelectedCadObjects.push_back(*_iter); + if (!(*_iter)->IsSelected()) + { + (*_iter)->Select(true); + _bChanged = true; + } + } +} + +// 反选 +void CSelectTarget::SelectRev() +{ + // 反转各对象的选中状态 ---- 杨开锦 2011-07-18 + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + for (int _i = 0; _i < _pCadGroup->GetNumOfChild(); _i++) + { + CCadObject* _pCad = _pCadGroup->GetAt(_i); + ASSERT(_pCad); + bool _bSelected = _pCad->IsSelected(); + _pCad->Select(!_bSelected); + } + + // 更新选中对象链表 ---- 杨开锦 2011-07-18 + GetSelectedCadObjects(true); +} + +// 清空 +void CSelectTarget::ClearSelect() +{ + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + if (_pCadGroup && !_pCadGroup->IsEmpty()) + { + // 清除Cad对象的选中状态 + const CadObjectList* _pCadObjList = _pCadGroup->GetObjectsList(); + for (CadObjectList::const_iterator _iter = _pCadObjList->begin(); _iter != _pCadObjList->end(); _iter++) + { + if ((*_iter)->IsSelected()) + (*_iter)->Select(false); + } + m_listSelectedCadObjects.clear(); + } + + // 清除参考线的选中状态 + CCadGroup* _pRefLines = m_pFileTarget->GetCurrentRefLines(); + if (_pRefLines && !_pRefLines->IsEmpty()) + { + int _nCount = _pRefLines->GetNumOfChild(); + for (int _i = 0; _i < _nCount; _i++) + _pRefLines->GetAt(_i)->Select(false); + } +} + +const CadObjectList* CSelectTarget::GetSelectedCadObjects(bool bArbitrary_/* = false*/) +{ + // 若为强制更新,则从FileTarget中重新收集 ---- 杨开锦 2011-06-10 + if (bArbitrary_) + { + m_listSelectedCadObjects.clear(); + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + ASSERT(_pCadGroup); + int _nCount = _pCadGroup->GetNumOfChild(); + for (int _i = 0; _i < _nCount; _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if (_pCadObject->IsSelected()) + { + m_listSelectedCadObjects.push_back(_pCadObject); + } + } + } + + return &m_listSelectedCadObjects; +} + +const nce::CadObjectList* CSelectTarget::GetSelectedRefLines(bool bArbitrary_/* = false*/) +{ + // 若为强制更新,则从FileTarget中重新收集 ---- 杨开锦 2011-06-10 + if (bArbitrary_) + { + m_listSelectedRefLines.clear(); + + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentRefLines(); + ASSERT(_pCadGroup); + int _nCount = _pCadGroup->GetNumOfChild(); + for (int _i = 0; _i < _nCount; _i++) + { + CCadObject* _pCadObject = _pCadGroup->GetAt(_i); + ASSERT(_pCadObject); + if (_pCadObject->IsSelected()) + { + m_listSelectedRefLines.push_back(_pCadObject); + } + } + } + + return &m_listSelectedRefLines; +} + +void CSelectTarget::Reset() +{ + m_ptLButtonDown = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + m_ptTemp = DPOINT2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); +} + +DRECT CSelectTarget::GetSelObjsBoundRect(bool bArbitrary_/* = false*/) +{ + // bArbitrary_为true时强制更新缓存。 ---- 杨开锦 2011-06-16 + if (bArbitrary_) + { + // 初始化 + const CadObjectList* _plistSelObjs = GetSelectedCadObjects(); + ASSERT(_plistSelObjs); + DRECT _rcTotalRect(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE, c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + + // 计算 + for (CadObjectList::const_iterator _it = _plistSelObjs->begin(); _it != _plistSelObjs->end(); _it++) + { + DRECT _rect = (*_it)->GetBoundRect(); + if (_it == _plistSelObjs->begin()) + _rcTotalRect = _rect; + else + DRECT::Union(_rcTotalRect, _rcTotalRect, _rect); + } + + // 保存 + m_rcSelObjsBoundRect = _rcTotalRect; + } + + return m_rcSelObjsBoundRect; +} + +DRECT CSelectTarget::GetObjsBoundRect(const CadObjectList* pObjectsList_) +{ + if (!pObjectsList_ || pObjectsList_->empty()) + DRECT(0,0,0,0); + + DRECT _rc; + for (CadObjectList::const_iterator _iter = pObjectsList_->begin(); _iter != pObjectsList_->end(); _iter++) + { + DRECT _rect = (*_iter)->GetBoundRect(); + if (_iter == pObjectsList_->begin()) + _rc = _rect; + else + DRECT::Union(_rc, _rc, _rect); + } + + return _rc; +} + +void CSelectTarget::SetRButtonMenu_NoneSelected(CMenu* pRButtonMenu_) +{ + ASSERT(pRButtonMenu_); + ASSERT(pRButtonMenu_->GetSafeHmenu()); + m_pRButtonMenu_NoneSelected = pRButtonMenu_; +} + +void CSelectTarget::SetRButtonMenu_SingleSelected(CMenu* pRButtonMenu_) +{ + ASSERT(pRButtonMenu_); + ASSERT(pRButtonMenu_->GetSafeHmenu()); + m_pRButtonMenu_SingleSelected = pRButtonMenu_; +} + +void CSelectTarget::SetRButtonMenu_MultiSelected(CMenu* pRButtonMenu_) +{ + ASSERT(pRButtonMenu_); + ASSERT(pRButtonMenu_->GetSafeHmenu()); + m_pRButtonMenu_MultiSelected = pRButtonMenu_; +} + +//////////////////////////////////////////////////////////////////////////////// +// Local function implementations +// +// 根据一个给定的观察窗,将给定的一组CAD对象划分为以下三个部分,划分的判断办法是 +// 求对象的外接矩形,然后用外接矩形的包含和相交关系来判断。 +// FullInside : 对象完全在观察窗内 +// PartInside : 对象部分在观察窗内 +// NotInside : 对象完全不在观察窗内 +// 观察窗ViewPort应为有效,即其位置点应为有效,宽高应为非负。三个用于OUT的指针均 +// 可以为NULL,为NULL时表示不需要收集这一部分的对象。 ---- 杨开锦 2011-07-16 +static void _DivideObjectsIntoThree(IN const CadObjectList* plistSource_, + IN const DRECT& rcViewport_, + OUT CadObjectList* plistFullInside_, + OUT CadObjectList* plistPartInside_, + OUT CadObjectList* plistNotInside_) +{ + ASSERT(plistSource_); + ASSERT(IsValidDouble(rcViewport_.x) && IsValidDouble(rcViewport_.y) + && rcViewport_.width >= 0. && rcViewport_.height >= 0); + + if (!plistFullInside_ && !plistPartInside_ && !plistNotInside_) + { + return; + } + + for (CadObjectList::const_iterator _it = plistSource_->begin(); + _it != plistSource_->end(); _it++) + { + // 求外接矩形 ---- 杨开锦 2011-07-16 + CCadObject* _pCadObject = *_it; + ASSERT(_pCadObject); + DRECT _rcBound = _pCadObject->GetBoundRect(); + + // 先判断包含关系,再判断相交关系 ---- 杨开锦 2011-07-16 + if (rcViewport_.Contains(_rcBound)) + { + if (plistFullInside_) + plistFullInside_->push_back(_pCadObject); + } + else if (rcViewport_.IntersectsWith(_rcBound)) + { + if (plistPartInside_) + plistPartInside_->push_back(_pCadObject); + } + else + { + if (plistNotInside_) + plistNotInside_->push_back(_pCadObject); + } + } +} + +LRESULT CSelectTarget::SelectAll(WPARAM wParam_, LPARAM lParam_) +{ + ASSERT(m_pFileTarget); + CCadGroup* _pCadGroup = m_pFileTarget->GetCurrentCadGroup(); + if (_pCadGroup->IsEmpty()) + return FALSE; + const CadObjectList* _pCadObjList = _pCadGroup->GetObjectsList(); + + // 先清除 ---- DingQiang 2013-09-23 + m_listSelectedCadObjects.clear(); + for (CadObjectList::const_iterator _iter = _pCadObjList->begin(); _iter != _pCadObjList->end(); _iter++) + { + m_listSelectedCadObjects.push_back(*_iter); + if (!(*_iter)->IsSelected()) + { + (*_iter)->Select(true); + } + } + + return TRUE; +} \ No newline at end of file diff --git a/src/ThreeSegPunchParamDlg.cpp b/src/ThreeSegPunchParamDlg.cpp new file mode 100644 index 0000000..22941a4 --- /dev/null +++ b/src/ThreeSegPunchParamDlg.cpp @@ -0,0 +1,1450 @@ +// ************************************************************************** // +// ThreeSegPunchParamDlg.cpp : implementation of the CThreeSegPunchParamDlg class +// Copyright(c)2014 WeiHong Company. All rights reserved. +// +// Abstract: +// 本文件实现CThreeSegPunchParamDlg类。 +// *********************************************** ---- 黄海燕 2014-12-14***** // +#include "stdafx.h" +#include "LayerParamDlg.h" + +using namespace nce; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +CS_T s_szCUTGASNAME = _DEFCS(_CSV(16655), + _CHINESE("CutGas%d_CHN") + _ENGLISH("CutGas%d_ENG")); +CS_T s_szTHREESEGPUNCHPARAM = _DEFCS(_CSV(16657), + _CHINESE("%s-三级穿孔参数") + _ENGLISH("%s-Three Segment Paramters")); +CS_T s_szREMARKS = _DEFCS(_CSV(16658), + _CHINESE("用户备注") + _ENGLISH("Remarks")); + +CS_T s_szFIRSTSEG = _DEFCS(_CSV(16659), + _CHINESE("一级") + _ENGLISH("1st Segment")); +CS_T s_szFIRSTCURRENT = _DEFCS(_CSV(16660), + _CHINESE("一级电流:") + _ENGLISH("Current:")); +CS_T s_szFIRSTFREQU = _DEFCS(_CSV(16661), + _CHINESE("一级频率:") + _ENGLISH("Frequency:")); +CS_T s_szFIRSTPOWER = _DEFCS(_CSV(16662), + _CHINESE("一级功率:") + _ENGLISH("Power:")); +CS_T s_szFIRSTGAS = _DEFCS(_CSV(16663), + _CHINESE("一级气体:") + _ENGLISH("Gas:")); +CS_T s_szFIRSTPRESSURE = _DEFCS(_CSV(16664), + _CHINESE("一级气压:") + _ENGLISH("Pressure:")); +CS_T s_szFIRSTHEIGHT = _DEFCS(_CSV(16665), + _CHINESE("一级高度:") + _ENGLISH("Height:")); +CS_T s_szFIRSTDELAY = _DEFCS(_CSV(16666), + _CHINESE("一级延时:") + _ENGLISH("Delay:")); +CS_T s_szFIRSTSEGFOCUS = _DEFCS(_CSV(16703), + _CHINESE("一级焦点:") + _ENGLISH("Focus:")); + +CS_T s_szSECONDSEG = _DEFCS(_CSV(16667), + _CHINESE("二级") + _ENGLISH("2nd Segment")); +CS_T s_szSECONDCURRENT = _DEFCS(_CSV(16668), + _CHINESE("二级电流:") + _ENGLISH("Current:")); +CS_T s_szSECONDFREQU = _DEFCS(_CSV(16669), + _CHINESE("二级频率:") + _ENGLISH("Frequency:")); +CS_T s_szSECONDPOWER = _DEFCS(_CSV(16670), + _CHINESE("二级功率:") + _ENGLISH("Power:")); +CS_T s_szSECONDGAS = _DEFCS(_CSV(16671), + _CHINESE("二级气体:") + _ENGLISH("Gas:")); +CS_T s_szSECONDPRESSURE = _DEFCS(_CSV(16672), + _CHINESE("二级气压:") + _ENGLISH("Pressure:")); +CS_T s_szSECONDHEIGHT = _DEFCS(_CSV(16673), + _CHINESE("二级高度:") + _ENGLISH("Height:")); +CS_T s_szSECONDDELAY = _DEFCS(_CSV(16674), + _CHINESE("二级延时:") + _ENGLISH("Delay:")); +CS_T s_szSECONDSEGFOCUS = _DEFCS(_CSV(16704), + _CHINESE("二级焦点:") + _ENGLISH("Focus:")); + +CS_T s_szTHIRDSEG = _DEFCS(_CSV(16675), + _CHINESE("三级") + _ENGLISH("3rd Segment")); +CS_T s_szTHIRDCURRENT = _DEFCS(_CSV(16676), + _CHINESE("三级电流:") + _ENGLISH("Current:")); +CS_T s_szTHIRDFREQU = _DEFCS(_CSV(16677), + _CHINESE("三级频率:") + _ENGLISH("Frequency:")); +CS_T s_szTHIRDPOWER = _DEFCS(_CSV(16678), + _CHINESE("三级功率:") + _ENGLISH("Power:")); +CS_T s_szTHIRDGAS = _DEFCS(_CSV(16679), + _CHINESE("三级气体:") + _ENGLISH("Gas:")); +CS_T s_szTHIRDPRESSURE = _DEFCS(_CSV(16680), + _CHINESE("三级气压:") + _ENGLISH("Pressure:")); +CS_T s_szTHIRDHEIGHT = _DEFCS(_CSV(16681), + _CHINESE("三级高度:") + _ENGLISH("Height:")); +CS_T s_szTHIRDDELAY = _DEFCS(_CSV(16682), + _CHINESE("三级延时:") + _ENGLISH("Delay:")); +CS_T s_szTHIRDSEGFOCUS = _DEFCS(_CSV(16705), + _CHINESE("三级焦点:") + _ENGLISH("Focus:")); +CS_T s_csINVALIDINPUT = _DEFCS(_CSV(16750), + _CHINESE("输入参数格式不正确,请重新输入。") + _ENGLISH("The input parameter is invalid, please reset again.")); + +CS_T s_szPIERCESPEED = _DEFCS(_CSV(16705), + _CHINESE("渐进速度:") + _ENGLISH("Increment S:")); +CS_T s_szExtraPuffing= _DEFCS(_CSV(16705), + _CHINESE("停光吹气:") + _ENGLISH("Extra Blow:")); +CS_T s_szSTOPGAS= _DEFCS(_CSV(16705), + _CHINESE("吹气:") + _ENGLISH("Type:")); +CS_T s_szDLG_LANGUAGE = _DEFCS(_CSV(16739), + _CHINESE("CHN") + _ENGLISH("ENG")); + +static void FormatDoubleParamer(CString& pSrc_) +{ + pSrc_.TrimRight('0'); + if (pSrc_.IsEmpty()) + pSrc_ = _T("0"); + if (pSrc_[pSrc_.GetLength() - 1] == _T('.')) + pSrc_.Delete(pSrc_.GetLength() - 1); +} +const char c_szSection[] = "ParamGroup"; +const char c_szFirstSegGasKey[] = "FirstSegBlowType"; +const char c_szSecondSegGasKey[] = "SecondSegBlowType"; +const char c_szThirdSegGasKey[] = "ThirdSegBlowType"; +const char c_szFirstStopSegGasKey[] = "FirstSegStopBlowType"; +const char c_szSecondStopSegGasKey[] = "SecondSegStopBlowType"; +const char c_szThirdStopSegGasKey[] = "ThirdSegStopBlowType"; +const char c_szFirstSegPunch[] = "FirstSegPunch"; +const char c_szSecondSegPunch[] = "SecondSegPunch"; +const char c_szThirdSegPunch[] = "ThirdSegPunch"; +const char c_szFirstSegConSpeed[] = "FirstSegConEnable"; +const char c_szSecondSegConSpeed[] = "SecondSegConEnable"; +const char c_szThirdSegConSpeed[] = "ThirdSegConEnable"; +const char c_szFirstStopLaserBlow[] = "FirstStopLaserBlowEnable"; +const char c_szSecondStopLaserBlow[] = "SecondStopLaserBlowEnable"; +const char c_szThirdStopLaserBlow[] = "ThirdStopLaserBlowEnable"; +const char c_szThreeSegPunchRemarks[] = "ThreeSegPunchRemarks"; + +IMPLEMENT_DYNAMIC(CThreeSegPunchParamDlg, CDialog) +BEGIN_MESSAGE_MAP(CThreeSegPunchParamDlg, CDialog) + ON_CONTROL_RANGE(EN_KILLFOCUS, IDC_EDIT_FIRSTSEGPOWER, IDC_EDIT_THIRDSTOPLASERBLOW, OnKillFocusEdits) + ON_CONTROL_RANGE(EN_SETFOCUS, IDC_EDIT_FIRSTSEGPOWER, IDC_EDIT_THIRDSTOPLASERBLOW, OnSetFocusEdits) + ON_CONTROL_RANGE(CBN_SELCHANGE, IDC_COMBO_FIRSTSEGGAS, IDC_COMBO_THIRDSEGGAS, OnSelectGases) + ON_CONTROL_RANGE(CBN_SELCHANGE, IDC_COMBO_FIRSTSTOPLASERBLOWTYPE, IDC_COMBO_THIRDSTOPLASERBLOWTYPE, OnSelectStopGases) + ON_COMMAND_RANGE(IDC_CHECK_FIRSTSEG, IDC_CHECK_THIRDSEG, OnClickPunchType) + ON_COMMAND_RANGE(IDC_CHECK_FIRSTCONPERSPEED, IDC_CHECK_THIRDCONPERSPEED, OnClickEnableConPer) + ON_COMMAND_RANGE(IDC_CHECK_FIRSTSTOPLASERBLOW, IDC_CHECK_THIRDSTOPLASERBLOW, OnClickEnableCloseLaserBlow) + ON_CONTROL(EN_KILLFOCUS, IDC_EDIT_THREESEGUSERREMARKS, OnKillFocusRemarks) +END_MESSAGE_MAP() + +CThreeSegPunchParamDlg::CThreeSegPunchParamDlg(CParam* pParam_, CWnd* pParent_) +: CDialog(IDD_DLG_THREESEGPUNCHPARAM, pParent_), m_pParam(pParam_) +{ + _BuildEditInfo(); + + // 初始化输入数据是有效的 ---- 彭朋 2016-07-20 + m_bDataValid = true; + m_bCancelData = false; + + // 初始化穿孔气体和切割气体。配置方式: + // CutGasCount=1 + // CutGas0_Value=0 + // CutGas0_CHN="空气" + // CutGas0_ENG="Air" + // CutGasXX_CHN是中文名,CutGasXX_ENG是英文名,CutGasXX_Value是对应LayerParam.lua + // 中BlowTypeTable的第一项的值。---- 黄海燕 2015-02-28 + CString _strCount = NceGetPrivateProfileString(c_szSection, _T("CutGasCount"), "0"); + int _nCount = atoi(_strCount); + for (int _i = 0; _i < _nCount; _i++) + { + CLayerParamDlg::CombItem* _pItem = new CLayerParamDlg::CombItem; + CString _strKey; + _strKey.Format(_T("CutGas%d_Value"), _i); + _pItem->strValue = NceGetPrivateProfileString(c_szSection, _strKey, ""); + _strKey.Format(_GETCS(s_szCUTGASNAME), _i); + _pItem->strText = NceGetPrivateProfileString(c_szSection, _strKey, ""); + m_vectCombItems.push_back(_pItem); + } + + // 用另外一个vector存储停光吹气的气体类型 ---- 吴畏 2017-04-24 + for (int _i = 0; _i < _nCount; _i++) + { + CLayerParamDlg::CombItem* _pItem = new CLayerParamDlg::CombItem; + CString _strKey; + _strKey.Format(_T("CutGas%d_Value"), _i); + _pItem->strValue = NceGetPrivateProfileString(c_szSection, _strKey, ""); + _strKey.Format(_GETCS(s_szCUTGASNAME), _i); + _pItem->strText = NceGetPrivateProfileString(c_szSection, _strKey, ""); + m_vectCombStopItems.push_back(_pItem); + } + + m_bEnableFocusCtrl = NceGetPrivateProfileString(_T("FocusControl"), _T("Enable")) == _T("1"); +} + +CThreeSegPunchParamDlg::~CThreeSegPunchParamDlg() +{ + for (PunchParamList::iterator _it = m_listEdits.begin(); _it != m_listEdits.end(); _it++) + { + if (*_it) + delete (*_it); + } + m_listEdits.clear(); + + for (CombItemVector::iterator _it = m_vectCombItems.begin(); _it != m_vectCombItems.end(); _it++) + { + if (*_it) + delete (*_it); + } + m_vectCombItems.clear(); + + for (CombItemVector::iterator _it = m_vectCombStopItems.begin(); _it != m_vectCombStopItems.end(); _it++) + { + if (*_it) + delete (*_it); + } + m_vectCombStopItems.clear(); +} + +BOOL CThreeSegPunchParamDlg::Create(UINT nIDTemplate_, CWnd* pParentWnd_) +{ + ::AfxInitRichEdit2(); + return __super::Create(nIDTemplate_,pParentWnd_ ); +} + +void CThreeSegPunchParamDlg::SetParam(CParam* pParam_) +{ + m_pParam = pParam_; +} + +void CThreeSegPunchParamDlg::BuildDefaultParam(nce::CParam* pParam_) +{ + if (!pParam_) + { + ASSERT(FALSE); + return; + } + + struct DVItem + { + CStringA strKey; + CStringA strDefualtValue; + }; + DVItem _DVItems[] = + { + {"FirstSegPunch", "1"}, + {"SecondSegPunch", "1"}, + {"ThirdSegPunch", "1"}, + {"FirstSegBlowType", "0"}, + {"SecondSegBlowType", "0"}, + {"ThirdSegBlowType", "0"}, + {"FirstSegStopBlowType", "0"}, // 停光吹气类型 ---- 吴畏 2017-04-24 + {"SecondSegStopBlowType", "0"}, + {"ThirdSegStopBlowType", "0"}, + + {"FirstSegPower", "100"}, + {"FirstSegFreq", "5000"}, + {"FirstSegDutyCycle", "100"}, + {"FirstSegPressure", "100"}, + {"FirstSegHeight", "10"}, + {"FirstSegDelay", "200"}, + {"FirstSegFocusPos", "0"}, + + {"SecondSegPower", "100"}, + {"SecondSegFreq", "5000"}, + {"SecondSegDutyCycle", "100"}, + {"SecondSegPressure", "100"}, + {"SecondSegHeight", "5"}, + {"SecondSegDelay", "200"}, + {"SecondFocusPos", "0"}, + + {"ThirdSegPower", "100"}, + {"ThirdSegFreq", "5000"}, + {"ThirdSegDutyCycle", "100"}, + {"ThirdSegPressure", "100"}, + {"ThirdSegHeight", "2"}, + {"ThirdSegDelay", "200"}, + {"ThirdSegFocusPos", "0"}, + }; + for (int _i = 0; _i < _countof(_DVItems); _i++) + { + CStringA _strCurValue = pParam_->GetKey(_DVItems[_i].strKey); + if (_strCurValue.IsEmpty()) + pParam_->SetKey(_DVItems[_i].strKey, _DVItems[_i].strDefualtValue); + } +} + +void CThreeSegPunchParamDlg::Update() +{ + bool _bIsCHN = _GETCS(s_szDLG_LANGUAGE) == "CHN"; // 判断中英文 + CStringA _strName = _bIsCHN ? m_pParam->GetKey("Name") : m_pParam->GetKey("Name_ENG"); + if (!_strName.IsEmpty() && _strName[0] == '\"') _strName.Delete(0); + if (!_strName.IsEmpty() && _strName[_strName.GetLength() - 1] == '\"') _strName.Delete(_strName.GetLength() - 1); + CString _strTitle; + _strTitle.Format(_GETCS(s_szTHREESEGPUNCHPARAM), _strName); + CString _strCurrentTitle; + GetDlgItemText(IDC_STATIC_THREESEGPUNCHPARAM, _strCurrentTitle); + if (_strTitle != _strCurrentTitle) + { + SetDlgItemText(IDC_STATIC_THREESEGPUNCHPARAM, _strTitle); + } + + // 气体选项更新。 + struct + { + CStringA strParamKey; + CStringA strParamValue; + CComboBox* pComb; + }_Combs[3]; + _Combs[0].strParamKey = c_szFirstSegGasKey; + _Combs[0].strParamValue = m_pParam->GetKey(c_szFirstSegGasKey); + _Combs[0].pComb = (CComboBox*)GetDlgItem(IDC_COMBO_FIRSTSEGGAS); + _Combs[1].strParamKey = c_szSecondSegGasKey; + _Combs[1].strParamValue = m_pParam->GetKey(c_szSecondSegGasKey); + _Combs[1].pComb = (CComboBox*)GetDlgItem(IDC_COMBO_SECONDSEGGAS); + _Combs[2].strParamKey = c_szThirdSegGasKey; + _Combs[2].strParamValue = m_pParam->GetKey(c_szThirdSegGasKey); + _Combs[2].pComb = (CComboBox*)GetDlgItem(IDC_COMBO_THIRDSEGGAS); + for (int _nCombIndex = 0; _nCombIndex < _countof(_Combs); _nCombIndex++) + { + int _nIndex = -1; + for (int _i = 0; _i < (int)m_vectCombItems.size(); _i++) + { + if (m_vectCombItems[_i]->strValue == _Combs[_nCombIndex].strParamValue) + { + _nIndex = _i; + break; + } + + // 没配的则默认用第一个选项。 + if (_Combs[_nCombIndex].strParamValue.IsEmpty()) + { + _nIndex = 0; + m_pParam->SetKey(_Combs[_nCombIndex].strParamKey, m_vectCombItems[0]->strValue); + } + } + if (_Combs[_nCombIndex].pComb->GetCurSel() != _nIndex) + _Combs[_nCombIndex].pComb->SetCurSel(_nIndex); + } + + // 停光吹气气体单独配 ---- 吴畏 2017-04-24 + struct + { + CStringA strParamKey; + CStringA strParamValue; + CComboBox* pComb; + }_StopCombs[3]; + _StopCombs[0].strParamKey = c_szFirstStopSegGasKey; + _StopCombs[0].strParamValue = m_pParam->GetKey(c_szFirstStopSegGasKey); + _StopCombs[0].pComb = (CComboBox*)GetDlgItem(IDC_COMBO_FIRSTSTOPLASERBLOWTYPE); + _StopCombs[1].strParamKey = c_szSecondStopSegGasKey; + _StopCombs[1].strParamValue = m_pParam->GetKey(c_szSecondStopSegGasKey); + _StopCombs[1].pComb = (CComboBox*)GetDlgItem(IDC_COMBO_SECONDSTOPLASERBLOWTYPE); + _StopCombs[2].strParamKey = c_szThirdStopSegGasKey; + _StopCombs[2].strParamValue = m_pParam->GetKey(c_szThirdStopSegGasKey); + _StopCombs[2].pComb = (CComboBox*)GetDlgItem(IDC_COMBO_THIRDSTOPLASERBLOWTYPE); + for (int _nCombIndex = 0; _nCombIndex < _countof(_StopCombs); _nCombIndex++) + { + int _nIndex = -1; + for (int _i = 0; _i < (int)m_vectCombStopItems.size(); _i++) + { + if (m_vectCombStopItems[_i]->strValue == _StopCombs[_nCombIndex].strParamValue) + { + _nIndex = _i; + break; + } + + // 没配的则默认用第一个选项。 + if (_StopCombs[_nCombIndex].strParamValue.IsEmpty()) + { + _nIndex = 0; + m_pParam->SetKey(_StopCombs[_nCombIndex].strParamKey, m_vectCombStopItems[0]->strValue); + } + } + if (_StopCombs[_nCombIndex].pComb->GetCurSel() != _nIndex) + _StopCombs[_nCombIndex].pComb->SetCurSel(_nIndex); + } + + // 穿孔段数更新。 + bool _bPunch = m_pParam->GetKey_DBL(c_szFirstSegPunch) == 1; + CButton* _pwndBtn = (CButton*)GetDlgItem(IDC_CHECK_FIRSTSEG); + int _nCheck = _bPunch ? BST_CHECKED : BST_UNCHECKED; + if (_pwndBtn->GetCheck() != _nCheck) + _pwndBtn->SetCheck(_nCheck); + GetDlgItem(IDC_STATIC_FIRSTSEGPOWER)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_FIRSTSEGPOWER)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGPOWERUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGFREQ)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_FIRSTSEGFREQ)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGFREQUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGDUTYCYCLE)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_FIRSTSEGDUTYCYCLE)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGDUTYCYCLEUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGPRESSUER)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_FIRSTSEGPRESSUER)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGPRESSUERUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGGAS)->EnableWindow(_bPunch); + GetDlgItem(IDC_COMBO_FIRSTSEGGAS)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGHEIGHT)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_FIRSTSEGHEIGHT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGHEIGHTUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGELAY)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_FIRSTSEGDELAY)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGDELAYUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_FIRSTSEGFOCUS)->EnableWindow(_bPunch && m_bEnableFocusCtrl); + GetDlgItem(IDC_EDIT_FIRSTSEGFOCUS)->EnableWindow(_bPunch && m_bEnableFocusCtrl); + GetDlgItem(IDC_STATIC_FIRSTSEGFOCUSUNIT)->EnableWindow(_bPunch && m_bEnableFocusCtrl); + GetDlgItem(IDC_CHECK_FIRSTCONPERSPEED)->EnableWindow(_bPunch); + GetDlgItem(IDC_STC_FIRSTCONPERSPEEDUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_CHECK_FIRSTSTOPLASERBLOW)->EnableWindow(_bPunch); + GetDlgItem(IDC_STC_FIRSTSTOPLASERBLOWUNIT)->EnableWindow(_bPunch); + bool _bConPer = (int)m_pParam->GetKey_DBL(c_szFirstSegConSpeed) == 1; + _pwndBtn = (CButton*)GetDlgItem(IDC_CHECK_FIRSTCONPERSPEED); + _nCheck = _bConPer ? BST_CHECKED : BST_UNCHECKED; + if (_pwndBtn->GetCheck() != _nCheck) + _pwndBtn->SetCheck(_nCheck); + CWnd* _pwndEdit = GetDlgItem(IDC_EDIT_FIRSTCONPERSPEED); + BOOL _bIsWndEnabled = (!_bConPer || !_bPunch) ? FALSE : TRUE; + if (_pwndEdit->IsWindowEnabled() != _bIsWndEnabled) + { + _pwndEdit->EnableWindow(_bIsWndEnabled); + } + + bool _bFirstStopLaserBlow = (int)m_pParam->GetKey_DBL(c_szFirstStopLaserBlow) == 1; + _pwndBtn = (CButton*)GetDlgItem(IDC_CHECK_FIRSTSTOPLASERBLOW); + _nCheck = _bFirstStopLaserBlow ? BST_CHECKED : BST_UNCHECKED; + if (_pwndBtn->GetCheck() != _nCheck) + _pwndBtn->SetCheck(_nCheck); + _pwndEdit = GetDlgItem(IDC_EDIT_FIRSTSTOPLASERBLOW); + CWnd* _pwndCombStop = GetDlgItem(IDC_COMBO_FIRSTSTOPLASERBLOWTYPE); + _bIsWndEnabled = (!_bFirstStopLaserBlow || !_bPunch) ? FALSE : TRUE; + if (_bIsWndEnabled != _pwndEdit->IsWindowEnabled()) + { + _pwndEdit->EnableWindow(_bIsWndEnabled); + _pwndCombStop->EnableWindow(_bIsWndEnabled); + } + + _bPunch = (int)m_pParam->GetKey_DBL(c_szSecondSegPunch) == 1; + _pwndBtn = (CButton*)GetDlgItem(IDC_CHECK_SECONDSEG); + _nCheck = _bPunch ? BST_CHECKED : BST_UNCHECKED; + if (_pwndBtn->GetCheck() != _nCheck) + _pwndBtn->SetCheck(_nCheck); + GetDlgItem(IDC_STATIC_SECONDSEGPOWER)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_SECONDSEGPOWER)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGPOWERUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGFREQ)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_SECONDSEGFREQ)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGFEQUUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGDUTYCYCLE)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_SECONDSEGDUTYCYCLE)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGDUTYCYCLEUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGPRESSUER)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_SECONDSEGPRESSUER)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGPRESSUERUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGGAS)->EnableWindow(_bPunch); + GetDlgItem(IDC_COMBO_SECONDSEGGAS)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGHEIGHT)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_SECONDSEGHEIGHT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGHEIGHTUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGDELAY)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_SECONDSEGDELAY)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGDELAYUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_SECONDSEGFOCUS)->EnableWindow(_bPunch && m_bEnableFocusCtrl); + GetDlgItem(IDC_EDIT_SECONDSEGFOCUS)->EnableWindow(_bPunch && m_bEnableFocusCtrl); + GetDlgItem(IDC_STATIC_SECONDSEGFOCUSUNIT)->EnableWindow(_bPunch && m_bEnableFocusCtrl); + GetDlgItem(IDC_CHECK_SECONDCONPERSPEED)->EnableWindow(_bPunch); + GetDlgItem(IDC_STC_SECONDCONPERSPEEDUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_CHECK_SECONDSTOPLASERBLOW)->EnableWindow(_bPunch); + GetDlgItem(IDC_STC_SECONDSTOPLASERBLOWUNIT)->EnableWindow(_bPunch); + _bConPer = (int)m_pParam->GetKey_DBL(c_szSecondSegConSpeed) == 1; + _pwndBtn = (CButton*)GetDlgItem(IDC_CHECK_SECONDCONPERSPEED); + _nCheck = _bConPer ? BST_CHECKED : BST_UNCHECKED; + if (_pwndBtn->GetCheck() != _nCheck) + _pwndBtn->SetCheck(_nCheck); + _pwndEdit = GetDlgItem(IDC_EDIT_SECONDCONPERSPEED); + _bIsWndEnabled = (!_bConPer || !_bPunch) ? FALSE : TRUE; + if (_pwndEdit->IsWindowEnabled() != _bIsWndEnabled) + { + _pwndEdit->EnableWindow(_bIsWndEnabled); + } + + bool _bSecondStopLaserBlow = (int)m_pParam->GetKey_DBL(c_szSecondStopLaserBlow) == 1; + _pwndBtn = (CButton*)GetDlgItem(IDC_CHECK_SECONDSTOPLASERBLOW); + _nCheck = _bSecondStopLaserBlow ? BST_CHECKED : BST_UNCHECKED; + if (_pwndBtn->GetCheck() != _nCheck) + _pwndBtn->SetCheck(_nCheck); + _pwndEdit = GetDlgItem(IDC_EDIT_SECONDSTOPLASERBLOW); + _pwndCombStop = GetDlgItem(IDC_COMBO_SECONDSTOPLASERBLOWTYPE); + _bIsWndEnabled = (!_bSecondStopLaserBlow || !_bPunch) ? FALSE : TRUE; + if (_pwndEdit->IsWindowEnabled() != _bIsWndEnabled) + { + _pwndEdit->EnableWindow(_bIsWndEnabled); + _pwndCombStop->EnableWindow(_bIsWndEnabled); + } + + _bPunch = (int)m_pParam->GetKey_DBL(c_szThirdSegPunch) == 1; + _pwndBtn = (CButton*)GetDlgItem(IDC_CHECK_THIRDSEG); + _nCheck = _bPunch ? BST_CHECKED : BST_UNCHECKED; + if (_pwndBtn->GetCheck() != _nCheck) + _pwndBtn->SetCheck(_nCheck); + GetDlgItem(IDC_STATIC_THIRDSEGPOWER)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_THIRDSEGPOWER)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGPOWERUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGFREQ)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_THIRDSEGFREQ)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGFREQUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGDUTYCYCLE)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_THIRDDUTYCYCLE)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDDUTYCYCLEUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGPRESSUER)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_THIRDSEGPRESSUER)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGPRESSUERUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGGAS)->EnableWindow(_bPunch); + GetDlgItem(IDC_COMBO_THIRDSEGGAS)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGHEIGHT)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_THIRDSEGHEIGHT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGHEIGHTUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGDELAY)->EnableWindow(_bPunch); + GetDlgItem(IDC_EDIT_THIRDSEGDELAY)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGDELAYUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_STATIC_THIRDSEGFOCUS)->EnableWindow(_bPunch && m_bEnableFocusCtrl); + GetDlgItem(IDC_EDIT_THIRDSEGFOCUS)->EnableWindow(_bPunch && m_bEnableFocusCtrl); + GetDlgItem(IDC_STATIC_THIRDSEGFOCUSUNIT)->EnableWindow(_bPunch && m_bEnableFocusCtrl); + GetDlgItem(IDC_CHECK_THIRDCONPERSPEED)->EnableWindow(_bPunch); + GetDlgItem(IDC_STC_THIRDCONPERSPEEDUNIT)->EnableWindow(_bPunch); + GetDlgItem(IDC_CHECK_THIRDSTOPLASERBLOW)->EnableWindow(_bPunch); + GetDlgItem(IDC_STC_THIRDSTOPLASERBLOWUNIT)->EnableWindow(_bPunch); + _bConPer = (int)m_pParam->GetKey_DBL(c_szThirdSegConSpeed) == 1; + _pwndBtn = (CButton*)GetDlgItem(IDC_CHECK_THIRDCONPERSPEED); + _nCheck = _bConPer ? BST_CHECKED : BST_UNCHECKED; + if (_pwndBtn->GetCheck() != _nCheck) + _pwndBtn->SetCheck(_nCheck); + _pwndEdit = GetDlgItem(IDC_EDIT_THIRDCONPERSPEED); + _bIsWndEnabled = (!_bConPer || !_bPunch) ? FALSE : TRUE; + if (_pwndEdit->IsWindowEnabled() != _bIsWndEnabled) + { + _pwndEdit->EnableWindow(_bIsWndEnabled); + } + + bool _bThirdStopLaserBlow = (int)m_pParam->GetKey_DBL(c_szThirdStopLaserBlow) == 1; + _pwndBtn = (CButton*)GetDlgItem(IDC_CHECK_THIRDSTOPLASERBLOW); + _nCheck = _bThirdStopLaserBlow ? BST_CHECKED : BST_UNCHECKED; + if (_pwndBtn->GetCheck() != _nCheck) + _pwndBtn->SetCheck(_nCheck); + _pwndEdit = GetDlgItem(IDC_EDIT_THIRDSTOPLASERBLOW); + _pwndCombStop = GetDlgItem(IDC_COMBO_THIRDSTOPLASERBLOWTYPE); + if (_pwndEdit->IsWindowEnabled() != (!_bThirdStopLaserBlow || !_bPunch) ? FALSE : TRUE) + { + _pwndEdit->EnableWindow((!_bThirdStopLaserBlow || !_bPunch) ? FALSE : TRUE); + _pwndCombStop->EnableWindow((!_bThirdStopLaserBlow || !_bPunch) ? FALSE : TRUE); + } + + // 编辑框更新。 ---- 黄海燕 2015-01-23 + _BuildEditInfo(); + UpDateEdits(); + + // 备注,将Normative中额外加的引号去掉 ---- 黄海燕 2015-01-23 + CStringA _strRemarks = m_pParam->GetKey(LPSTR(c_szThreeSegPunchRemarks)); + if (!_strRemarks.IsEmpty() && _strRemarks[0] == '\"') + _strRemarks.Delete(0); + int _nLength = _strRemarks.GetLength(); + if (_nLength > 0 && _strRemarks[_nLength - 1] == '\"') + _strRemarks.Delete(_nLength - 1); + _strRemarks = ReverseNormative(_strRemarks); + SetDlgItemText(IDC_EDIT_THREESEGUSERREMARKS, _strRemarks); + + CString _strShowStopBlowType = NceGetPrivateProfileString(c_szSection, _T("EnableStopBlowType"), _T("False")); + bool _bShowStopBlowType = _strShowStopBlowType == _T("True"); + GetDlgItem(IDC_STATIC_FIRSTSTOPLASERBLOWTYPE)->ShowWindow(_bShowStopBlowType ? SW_SHOW : SW_HIDE); + GetDlgItem(IDC_COMBO_FIRSTSTOPLASERBLOWTYPE)->ShowWindow(_bShowStopBlowType ? SW_SHOW : SW_HIDE); + GetDlgItem(IDC_STATIC_SECONDSTOPLASERBLOWTYPE)->ShowWindow(_bShowStopBlowType ? SW_SHOW : SW_HIDE); + GetDlgItem(IDC_COMBO_SECONDSTOPLASERBLOWTYPE)->ShowWindow(_bShowStopBlowType ? SW_SHOW : SW_HIDE); + GetDlgItem(IDC_STATIC_THIRDSTOPLASERBLOWTYPE)->ShowWindow(_bShowStopBlowType ? SW_SHOW : SW_HIDE); + GetDlgItem(IDC_COMBO_THIRDSTOPLASERBLOWTYPE)->ShowWindow(_bShowStopBlowType ? SW_SHOW : SW_HIDE); +} + +void CThreeSegPunchParamDlg::UpDateEdits() +{ + for (PunchParamList::iterator _it = m_listEdits.begin(); _it != m_listEdits.end(); _it++) + { + if ((*_it)->nDataType == 0) + { + CStringA _strNew; + _strNew.Format(_T("%d"), (*_it)->iValue); + CStringA _strOrg; + GetDlgItemText((*_it)->nID, _strOrg);; + if (_strOrg != _strNew) + SetDlgItemText((*_it)->nID, _strNew); + } + else + { + ASSERT((*_it)->nDataType == 1); + CStringA _strNew; + _strNew.Format(_T("%.3f"), (*_it)->dValue); + FormatDoubleParamer(_strNew); + CStringA _strOrg; + GetDlgItemText((*_it)->nID, _strOrg);; + if (_strOrg != _strNew) + SetDlgItemText((*_it)->nID, _strNew); + } + } + + CString _strNewUnit = CLayerParamDlg::GetUnitName(CLayerParamDlg::GetCurTimeUnit()); + CString _strOldUnit; + GetDlgItemText(IDC_STATIC_FIRSTSEGDELAYUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_FIRSTSEGDELAYUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_SECONDSEGDELAYUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_SECONDSEGDELAYUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_THIRDSEGDELAYUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_THIRDSEGDELAYUNIT, _strNewUnit); + GetDlgItemText(IDC_STC_FIRSTSTOPLASERBLOWUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STC_FIRSTSTOPLASERBLOWUNIT, _strNewUnit); + GetDlgItemText(IDC_STC_SECONDSTOPLASERBLOWUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STC_SECONDSTOPLASERBLOWUNIT, _strNewUnit); + GetDlgItemText(IDC_STC_THIRDSTOPLASERBLOWUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STC_THIRDSTOPLASERBLOWUNIT, _strNewUnit); + + // 速度单位切换 + _strNewUnit = CLayerParamDlg::GetUnitName(CLayerParamDlg::GetCurSpeedUnit()); + GetDlgItemText(IDC_STC_FIRSTCONPERSPEEDUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STC_FIRSTCONPERSPEEDUNIT, _strNewUnit); + GetDlgItemText(IDC_STC_SECONDCONPERSPEEDUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STC_SECONDCONPERSPEEDUNIT, _strNewUnit); + GetDlgItemText(IDC_STC_THIRDCONPERSPEEDUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STC_THIRDCONPERSPEEDUNIT, _strNewUnit); + + //气压单位切换 + _strNewUnit = CLayerParamDlg::GetUnitName(CLayerParamDlg::GetCurPressureUnit()); + GetDlgItemText(IDC_STATIC_FIRSTSEGPRESSUERUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_FIRSTSEGPRESSUERUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_SECONDSEGPRESSUERUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_SECONDSEGPRESSUERUNIT, _strNewUnit); + GetDlgItemText(IDC_STATIC_THIRDSEGPRESSUERUNIT, _strOldUnit); + if (_strOldUnit != _strNewUnit) + SetDlgItemText(IDC_STATIC_THIRDSEGPRESSUERUNIT, _strNewUnit); +} + +void CThreeSegPunchParamDlg::DoDataExchange(CDataExchange* pDX_) +{ + //用户取消 ---- 彭朋 2016-07-21 + if (m_bCancelData) + { + return; + } + __super::DoDataExchange(pDX_); + + for (PunchParamList::iterator _it = m_listEdits.begin(); _it != m_listEdits.end(); _it++) + { + // 不启用的就不更新。 ---- 黄海燕 2015-03-17 + if (!(*_it)->bEnable) + continue; + + CString _strText = _T(""); + GetDlgItemText((*_it)->nID, _strText); + if ((*_it)->nDataType == 0) + { + DDX_Text(pDX_, (*_it)->nID, (*_it)->iValue); + DDV_MinMaxInt(pDX_, (*_it)->iValue, int((*_it)->nMinValue), int((*_it)->nMaxValue)); + } + else + { + ASSERT((*_it)->nDataType == 1); + DDX_Text(pDX_, (*_it)->nID, (*_it)->dValue); + DDV_MinMaxDouble(pDX_, (*_it)->dValue, (*_it)->nMinValue, (*_it)->nMaxValue); + } + } +} + +BOOL CThreeSegPunchParamDlg::OnInitDialog() +{ + BOOL _bRet = __super::OnInitDialog(); + + CHARFORMAT _cf; + memset(&_cf, 0, sizeof(CHARFORMAT)); + _cf.cbSize = sizeof(CHARFORMAT); + _cf.dwMask = CFM_FACE | CFM_OFFSET | CFM_SIZE | CFM_COLOR; + _cf.yOffset = 0; + _cf.yHeight = 180; + _cf.crTextColor = RGB(0, 0, 255); + strcpy(_cf.szFaceName, "宋体"); + CRichEditCtrl* _pRichEdit = (CRichEditCtrl*)GetDlgItem(IDC_EDIT_THREESEGUSERREMARKS); + if (!_pRichEdit->SetDefaultCharFormat(_cf)) + { + ASSERT(FALSE); + } + + CComboBox* _pCombFirst = (CComboBox*)GetDlgItem(IDC_COMBO_FIRSTSEGGAS); + CComboBox* _pCombSecond = (CComboBox*)GetDlgItem(IDC_COMBO_SECONDSEGGAS); + CComboBox* _pCombThird = (CComboBox*)GetDlgItem(IDC_COMBO_THIRDSEGGAS); + for (int _i = 0; _i < (int)m_vectCombItems.size(); _i++) + { + _pCombFirst->InsertString(_i, m_vectCombItems[_i]->strText); + _pCombSecond->InsertString(_i, m_vectCombItems[_i]->strText); + _pCombThird->InsertString(_i, m_vectCombItems[_i]->strText); + } + + // 停光吹气的气体类型 ---- 吴畏 2017-04-24 + CComboBox* _pCombStopFirst = (CComboBox*)GetDlgItem(IDC_COMBO_FIRSTSTOPLASERBLOWTYPE); + CComboBox* _pCombStopSecond = (CComboBox*)GetDlgItem(IDC_COMBO_SECONDSTOPLASERBLOWTYPE); + CComboBox* _pCombStopThird = (CComboBox*)GetDlgItem(IDC_COMBO_THIRDSTOPLASERBLOWTYPE); + for (int _i = 0; _i < (int)m_vectCombStopItems.size(); _i++) + { + _pCombStopFirst->InsertString(_i, m_vectCombStopItems[_i]->strText); + _pCombStopSecond->InsertString(_i, m_vectCombStopItems[_i]->strText); + _pCombStopThird->InsertString(_i, m_vectCombStopItems[_i]->strText); + } + + SetText(); + Update(); + UpdateFocusCtrls(); + + return _bRet; +} + +bool CThreeSegPunchParamDlg::IsInputValid(UINT nID_) +{ + bool _bDataValid = true; + for (PunchParamList::iterator _it = m_listEdits.begin(); _it != m_listEdits.end(); _it++) + { + if ((*_it)->nID != nID_) + continue; + + m_bDataValid = false; + _bDataValid = false; + bool _bTempDataValid = true; + + // 输入的数据是否有效 + CString _strText = _T(""); + GetDlgItemText((*_it)->nID, _strText); + if (!IsNumberValid(_strText)) + { + _bTempDataValid = false; + } + + if (!_bTempDataValid) + { + m_bCancelData = true; + AfxMessageBox(_GETCS(s_csINVALIDINPUT)); + m_bCancelData = false; + } + + // 保存数据。 + if (_bTempDataValid && UpdateData(TRUE)) + { + m_bDataValid = true; + _bDataValid = true; + double _nValue = (*_it)->nDataType == 0 ? (*_it)->iValue : (*_it)->dValue; + CLayerParamDlg::Units _nCurUnit = CLayerParamDlg::GetCurSpeedUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Speed_INperMin + || (*_it)->nUnit == CLayerParamDlg::Speed_MMperMin + || (*_it)->nUnit == CLayerParamDlg::Speed_MMperS + || (*_it)->nUnit == CLayerParamDlg::Speed_MperMin) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit(_nCurUnit, (*_it)->nUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurAccUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Acc_MMperS2 + || (*_it)->nUnit == CLayerParamDlg::ACC_MperMin2 + || (*_it)->nUnit == CLayerParamDlg::Acc_10MperS2) + && (*_it)->nUnit !=_nCurUnit) + { + CLayerParamDlg::ConverUnit(_nCurUnit, (*_it)->nUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurTimeUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Time_MS + || (*_it)->nUnit == CLayerParamDlg::Time_S) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit(_nCurUnit, (*_it)->nUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurPressureUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Pressure_Percent + || (*_it)->nUnit == CLayerParamDlg::Pressure_MPa) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit(_nCurUnit, (*_it)->nUnit, _nValue, _nValue); + } + + if ((*_it)->nInitDataType == 0) + _nValue = (int)_nValue; + + if (m_pParam->GetKey_DBL((*_it)->strKey) != _nValue) + { + m_pParam->SetKey_DBL((*_it)->strKey, _nValue); + } + } + + // 格式化显示。 + double _nValue = m_pParam->GetKey_DBL((*_it)->strKey); + CLayerParamDlg::Units _nCurUnit = CLayerParamDlg::GetCurSpeedUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Speed_INperMin + || (*_it)->nUnit == CLayerParamDlg::Speed_MMperMin + || (*_it)->nUnit == CLayerParamDlg::Speed_MMperS + || (*_it)->nUnit == CLayerParamDlg::Speed_MperMin) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit((*_it)->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurAccUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Acc_MMperS2 + || (*_it)->nUnit == CLayerParamDlg::ACC_MperMin2 + || (*_it)->nUnit == CLayerParamDlg::Acc_10MperS2) + && (*_it)->nUnit !=_nCurUnit) + { + CLayerParamDlg::ConverUnit((*_it)->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurTimeUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Time_MS + || (*_it)->nUnit == CLayerParamDlg::Time_S) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit((*_it)->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurPressureUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Pressure_Percent + || (*_it)->nUnit == CLayerParamDlg::Pressure_MPa) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit((*_it)->nUnit, _nCurUnit, _nValue, _nValue); + } + + if ((*_it)->nDataType == 0) + { + CStringA _str; + _str.Format("%d", int(_nValue)); + SetDlgItemText((*_it)->nID, _str); + GetDlgItem((*_it)->nID)->SetFocus(); + } + else + { + CStringA _str; + _str.Format("%.3f", _nValue); + FormatDoubleParamer(_str); + SetDlgItemText((*_it)->nID, _str); + GetDlgItem((*_it)->nID)->SetFocus(); + } + + break; + } + + return _bDataValid; +} + +void CThreeSegPunchParamDlg::UpdateFocusCtrls() +{ + GetDlgItem(IDC_STATIC_FIRSTSEGFOCUS)->EnableWindow(m_bEnableFocusCtrl); + GetDlgItem(IDC_EDIT_FIRSTSEGFOCUS)->EnableWindow(m_bEnableFocusCtrl); + GetDlgItem(IDC_STATIC_FIRSTSEGFOCUSUNIT)->EnableWindow(m_bEnableFocusCtrl); + GetDlgItem(IDC_STATIC_SECONDSEGFOCUS)->EnableWindow(m_bEnableFocusCtrl); + GetDlgItem(IDC_EDIT_SECONDSEGFOCUS)->EnableWindow(m_bEnableFocusCtrl); + GetDlgItem(IDC_STATIC_SECONDSEGFOCUSUNIT)->EnableWindow(m_bEnableFocusCtrl); + GetDlgItem(IDC_STATIC_THIRDSEGFOCUS)->EnableWindow(m_bEnableFocusCtrl); + GetDlgItem(IDC_EDIT_THIRDSEGFOCUS)->EnableWindow(m_bEnableFocusCtrl); + GetDlgItem(IDC_STATIC_THIRDSEGFOCUSUNIT)->EnableWindow(m_bEnableFocusCtrl); +} + +bool CThreeSegPunchParamDlg::GetInputValid() +{ + if (this->GetFocus() != NULL) + { + if (!IsInputValid(this->GetFocus()->GetDlgCtrlID())) + { + return false; + } + } + + return true; +} + +void CThreeSegPunchParamDlg::InitCancelData() +{ + m_bCancelData = false; +} + +void CThreeSegPunchParamDlg::OnOK() +{ +} + +void CThreeSegPunchParamDlg::OnCancel() +{ + m_bCancelData = true; +} + +void CThreeSegPunchParamDlg::_BuildEditInfo() +{ + const CLayerParamDlg::EditInfo _s_Params[] = + { + {"FirstSegConSpeed", IDC_EDIT_FIRSTCONPERSPEED, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("FirstSegConSpeed")) ? 5 : m_pParam->GetKey_DBL("FirstSegConSpeed"), 0.1, 100, true, CLayerParamDlg::Speed_MMperS, 1}, + {"FirstSegPower", IDC_EDIT_FIRSTSEGPOWER, 0, IsInvalidDouble(m_pParam->GetKey_DBL("FirstSegPower")) ? 100 : int(m_pParam->GetKey_DBL("FirstSegPower")), NULL, 0, 100, true, CLayerParamDlg::Percent, 0}, + {"FirstSegFreq", IDC_EDIT_FIRSTSEGFREQ, 0, IsInvalidDouble(m_pParam->GetKey_DBL("FirstSegFreq")) ? 5000 : int(m_pParam->GetKey_DBL("FirstSegFreq")), NULL, 0, 100000, true, CLayerParamDlg::Frequece, 0}, + {"FirstSegDutyCycle", IDC_EDIT_FIRSTSEGDUTYCYCLE, 0, IsInvalidDouble(m_pParam->GetKey_DBL("FirstSegDutyCycle")) ? 100 : int(m_pParam->GetKey_DBL("FirstSegDutyCycle")), NULL, 0, 100, true, CLayerParamDlg::Percent, 0}, + {"FirstSegPressure", IDC_EDIT_FIRSTSEGPRESSUER, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("FirstSegPressure")) ? 100 : m_pParam->GetKey_DBL("FirstSegPressure"), 0, 100, true, CLayerParamDlg::Pressure_Percent, 1}, + {"FirstSegHeight", IDC_EDIT_FIRSTSEGHEIGHT, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("FirstSegHeight")) ? 10 : m_pParam->GetKey_DBL("FirstSegHeight"), 0.1, 500, true, CLayerParamDlg::Length_MM, 1}, + {"FirstSegDelay", IDC_EDIT_FIRSTSEGDELAY, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("FirstSegDelay")) ? 200 : m_pParam->GetKey_DBL("FirstSegDelay"), 0, 100000, true, CLayerParamDlg::Time_MS, 0}, + {"FirstSegFocusPos", IDC_EDIT_FIRSTSEGFOCUS, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("FirstSegFocusPos")) ? 0 : m_pParam->GetKey_DBL("FirstSegFocusPos"), -100, 100, true, CLayerParamDlg::Length_MM, 1}, + {"FirstStopLaserBlowDelay", IDC_EDIT_FIRSTSTOPLASERBLOW,1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("FirstStopLaserBlowDelay")) ? 200 : m_pParam->GetKey_DBL("FirstStopLaserBlowDelay"), 0, 100000, true, CLayerParamDlg::Time_MS, 0}, + + {"SecondSegConSpeed", IDC_EDIT_SECONDCONPERSPEED, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("SecondSegConSpeed")) ? 5 : m_pParam->GetKey_DBL("SecondSegConSpeed"), 0.1, 100, true, CLayerParamDlg::Speed_MMperS, 1}, + {"SecondSegPower", IDC_EDIT_SECONDSEGPOWER, 0, IsInvalidDouble(m_pParam->GetKey_DBL("SecondSegPower")) ? 100 : int(m_pParam->GetKey_DBL("SecondSegPower")), NULL, 0, 100, true, CLayerParamDlg::Percent, 0}, + {"SecondSegFreq", IDC_EDIT_SECONDSEGFREQ, 0, IsInvalidDouble(m_pParam->GetKey_DBL("SecondSegFreq")) ? 5000 : int(m_pParam->GetKey_DBL("SecondSegFreq")), NULL, 0, 100000, true, CLayerParamDlg::Frequece, 0}, + {"SecondSegDutyCycle", IDC_EDIT_SECONDSEGDUTYCYCLE,0, IsInvalidDouble(m_pParam->GetKey_DBL("SecondSegDutyCycle")) ? 100 : int(m_pParam->GetKey_DBL("SecondSegDutyCycle")), NULL, 0, 100, true, CLayerParamDlg::Percent, 0}, + {"SecondSegPressure", IDC_EDIT_SECONDSEGPRESSUER, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("SecondSegPressure")) ? 100 : m_pParam->GetKey_DBL("SecondSegPressure"), 0, 100, true, CLayerParamDlg::Pressure_Percent, 1}, + {"SecondSegHeight", IDC_EDIT_SECONDSEGHEIGHT, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("SecondSegHeight")) ? 5 : m_pParam->GetKey_DBL("SecondSegHeight"), 0.1, 500, true, CLayerParamDlg::Length_MM, 1}, + {"SecondSegDelay", IDC_EDIT_SECONDSEGDELAY, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("SecondSegDelay")) ? 200 : m_pParam->GetKey_DBL("SecondSegDelay"), 0, 100000, true, CLayerParamDlg::Time_MS, 0}, + {"SecondFocusPos", IDC_EDIT_SECONDSEGFOCUS, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("SecondFocusPos")) ? 0 : m_pParam->GetKey_DBL("SecondFocusPos"), -100, 100, true, CLayerParamDlg::Length_MM, 1}, + {"SecondStopLaserBlowDelay",IDC_EDIT_SECONDSTOPLASERBLOW,1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("SecondStopLaserBlowDelay")) ? 200 : m_pParam->GetKey_DBL("SecondStopLaserBlowDelay"), 0, 100000, true, CLayerParamDlg::Time_MS, 0}, + + {"ThirdSegConSpeed", IDC_EDIT_THIRDCONPERSPEED, 1, NULL, IsInvalidDouble(m_pParam->GetKey_DBL("ThirdSegConSpeed")) ? 5 : m_pParam->GetKey_DBL("ThirdSegConSpeed"), 0.1, 100, true, CLayerParamDlg::Speed_MMperS, 1}, + {"ThirdSegPower", IDC_EDIT_THIRDSEGPOWER, 0, IsInvalidDouble(m_pParam->GetKey_DBL("ThirdSegPower")) ? 100 : int(m_pParam->GetKey_DBL("ThirdSegPower")), NULL, 0, 100, true, CLayerParamDlg::Percent, 0}, + {"ThirdSegFreq", IDC_EDIT_THIRDSEGFREQ, 0, IsInvalidDouble(m_pParam->GetKey_DBL("ThirdSegFreq")) ? 5000 : int(m_pParam->GetKey_DBL("ThirdSegFreq")), NULL, 0, 100000, true, CLayerParamDlg::Frequece, 0}, + {"ThirdSegDutyCycle", IDC_EDIT_THIRDDUTYCYCLE, 0, IsInvalidDouble(m_pParam->GetKey_DBL("ThirdSegDutyCycle")) ? 100 : int(m_pParam->GetKey_DBL("ThirdSegDutyCycle")), NULL, 0, 100, true, CLayerParamDlg::Percent, 0}, + {"ThirdSegPressure", IDC_EDIT_THIRDSEGPRESSUER, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("ThirdSegPressure")) ? 100 : m_pParam->GetKey_DBL("ThirdSegPressure"), 0, 100, true, CLayerParamDlg::Pressure_Percent, 1}, + {"ThirdSegHeight", IDC_EDIT_THIRDSEGHEIGHT, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("ThirdSegHeight")) ? 2 : m_pParam->GetKey_DBL("ThirdSegHeight"), 0.1, 500, true, CLayerParamDlg::Length_MM, 1}, + {"ThirdSegDelay", IDC_EDIT_THIRDSEGDELAY, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("ThirdSegDelay")) ? 200 : m_pParam->GetKey_DBL("ThirdSegDelay"), 0, 100000, true, CLayerParamDlg::Time_MS, 0}, + {"ThirdSegFocusPos", IDC_EDIT_THIRDSEGFOCUS, 1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("ThirdSegFocusPos")) ? 0 : m_pParam->GetKey_DBL("ThirdSegFocusPos"), -100, 100, true, CLayerParamDlg::Length_MM, 1}, + {"ThirdStopLaserBlowDelay", IDC_EDIT_THIRDSTOPLASERBLOW,1, NULL,IsInvalidDouble(m_pParam->GetKey_DBL("ThirdStopLaserBlowDelay")) ? 200 : m_pParam->GetKey_DBL("ThirdStopLaserBlowDelay"), 0, 100000, true, CLayerParamDlg::Time_MS, 0}, + }; + + if (m_listEdits.empty()) + { + // 析构时才去释放,别的地方不去释放它,所以只有第一次调用时New。 + for (int _i = 0; _i < _countof(_s_Params); _i++) + { + CLayerParamDlg::EditInfo* _pInfo = new CLayerParamDlg::EditInfo; + m_listEdits.push_back(_pInfo); + } + } + else + { + ASSERT(m_listEdits.size() == _countof(_s_Params)); + } + + // 将初始值设进去。 ---- 黄海燕 2015-08-18 + int _i = 0; + for (PunchParamList::iterator _it = m_listEdits.begin(); _it != m_listEdits.end(); _it++) + { + CLayerParamDlg::EditInfo _item = _s_Params[_i]; + CLayerParamDlg::Units _nCurUnit = CLayerParamDlg::GetCurSpeedUnit(); + if ((_item.nUnit == CLayerParamDlg::Speed_INperMin + || _item.nUnit == CLayerParamDlg::Speed_MMperMin + || _item.nUnit == CLayerParamDlg::Speed_MMperS + || _item.nUnit == CLayerParamDlg::Speed_MperMin) + && _item.nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit(_item.nUnit, _nCurUnit, _s_Params[_i], _item); + } + + _nCurUnit = CLayerParamDlg::GetCurAccUnit(); + if ((_item.nUnit == CLayerParamDlg::Acc_MMperS2 + || _item.nUnit == CLayerParamDlg::ACC_MperMin2 + || _item.nUnit == CLayerParamDlg::Acc_10MperS2) + && _item.nUnit !=_nCurUnit) + { + CLayerParamDlg::ConverUnit(_item.nUnit, _nCurUnit, _s_Params[_i], _item); + } + + _nCurUnit = CLayerParamDlg::GetCurTimeUnit(); + if ((_item.nUnit == CLayerParamDlg::Time_MS + || _item.nUnit == CLayerParamDlg::Time_S) + && _item.nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit(_item.nUnit, _nCurUnit, _s_Params[_i], _item); + } + + _nCurUnit = CLayerParamDlg::GetCurPressureUnit(); + if ((_item.nUnit == CLayerParamDlg::Pressure_Percent + || _item.nUnit == CLayerParamDlg::Pressure_MPa) + && _item.nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit(_item.nUnit, _nCurUnit, _s_Params[_i], _item); + } + + (*_it)->strKey = _item.strKey; + (*_it)->nID = _item.nID; + (*_it)->nDataType = _item.nDataType; + (*_it)->iValue = _item.iValue; + (*_it)->dValue = _item.dValue; + (*_it)->nMinValue = _item.nMinValue; + (*_it)->nMaxValue = _item.nMaxValue; + (*_it)->bEnable = _item.bEnable; + (*_it)->nUnit = _item.nUnit; + (*_it)->nInitDataType = _item.nInitDataType; + + double _nValue = _s_Params[_i].nDataType == 0 ? _s_Params[_i].iValue : _s_Params[_i].dValue; + if (m_pParam->GetKey_DBL(_s_Params[_i].strKey) != _nValue) + m_pParam->SetKey_DBL(_s_Params[_i].strKey, _nValue); + _i++; + } +} + +// 输入的数据是否有效 ---- 彭朋 2016-07-20 +bool CThreeSegPunchParamDlg::IsNumberValid(LPCTSTR pszText_) +{ + if (!pszText_) + { + return false; + } + + CString _strText(pszText_); + if (_strText.IsEmpty()) + { + return false; + } + + int _nDotCount = 0; + for (int _i = 0; _i < _strText.GetLength(); _i++) + { + if (_i == 0 && (_strText[_i] == '-' || _strText[_i] == '+')) + { + continue; + } + + if (!isdigit(_strText[_i]) && _strText[_i] != '.') + { + return false; + } + + if (_strText[_i] == '.') + { + _nDotCount++; + } + } + + if (_nDotCount > 1) + { + return false; + } + + return true; +} + +void CThreeSegPunchParamDlg::OnKillFocusEdits(UINT nID_) +{ + //用户取消 ---- 彭朋 2016-07-21 + if (m_bCancelData) + { + return; + } + + for (PunchParamList::iterator _it = m_listEdits.begin(); _it != m_listEdits.end(); _it++) + { + if ((*_it)->nID != nID_) + continue; + + // 找到了FocusEdit才验证有效性 ---- 彭朋 2016-07-20 + m_bDataValid = false; + bool _bTempDataValid = true; + + // 输入的数据是否有效 + CString _strText = _T(""); + GetDlgItemText((*_it)->nID, _strText); + if (!IsNumberValid(_strText)) + { + _bTempDataValid = false; + } + + // 如果内容没有变则不用更新。 ---- 黄海燕 2015-09-18 + for (int _i = 0; _bTempDataValid && (_i < _countof(m_LastTextItems)); _i++) + { + if (m_LastTextItems[_i].nID != nID_) + continue; + + if (m_LastTextItems[_i].strLastText == _strText) + { + m_bDataValid = true; + return; + } + + break; + } + + if (!m_bCancelData) + { + if(!_bTempDataValid) + { + m_bCancelData = true; + AfxMessageBox(_GETCS(s_csINVALIDINPUT)); + m_bCancelData = false; + } + } + + // 保存数据。 + if (_bTempDataValid && UpdateData(TRUE)) + { + m_bDataValid = true; + double _nValue = (*_it)->nDataType == 0 ? (*_it)->iValue : (*_it)->dValue; + CLayerParamDlg::Units _nCurUnit = CLayerParamDlg::GetCurSpeedUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Speed_INperMin + || (*_it)->nUnit == CLayerParamDlg::Speed_MMperMin + || (*_it)->nUnit == CLayerParamDlg::Speed_MMperS + || (*_it)->nUnit == CLayerParamDlg::Speed_MperMin) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit(_nCurUnit, (*_it)->nUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurAccUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Acc_MMperS2 + || (*_it)->nUnit == CLayerParamDlg::ACC_MperMin2 + || (*_it)->nUnit == CLayerParamDlg::Acc_10MperS2) + && (*_it)->nUnit !=_nCurUnit) + { + CLayerParamDlg::ConverUnit(_nCurUnit, (*_it)->nUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurTimeUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Time_MS + || (*_it)->nUnit == CLayerParamDlg::Time_S) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit(_nCurUnit, (*_it)->nUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurPressureUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Pressure_Percent + || (*_it)->nUnit == CLayerParamDlg::Pressure_MPa) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit(_nCurUnit, (*_it)->nUnit, _nValue, _nValue); + } + + if ((*_it)->nInitDataType == 0) + _nValue = (int)_nValue; + + if (m_pParam->GetKey_DBL((*_it)->strKey) != _nValue) + { + m_pParam->SetKey_DBL((*_it)->strKey, _nValue); + } + } + + // 格式化显示。 + double _nValue = m_pParam->GetKey_DBL((*_it)->strKey); + CLayerParamDlg::Units _nCurUnit = CLayerParamDlg::GetCurSpeedUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Speed_INperMin + || (*_it)->nUnit == CLayerParamDlg::Speed_MMperMin + || (*_it)->nUnit == CLayerParamDlg::Speed_MMperS + || (*_it)->nUnit == CLayerParamDlg::Speed_MperMin) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit((*_it)->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurAccUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Acc_MMperS2 + || (*_it)->nUnit == CLayerParamDlg::ACC_MperMin2 + || (*_it)->nUnit == CLayerParamDlg::Acc_10MperS2) + && (*_it)->nUnit !=_nCurUnit) + { + CLayerParamDlg::ConverUnit((*_it)->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurTimeUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Time_MS + || (*_it)->nUnit == CLayerParamDlg::Time_S) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit((*_it)->nUnit, _nCurUnit, _nValue, _nValue); + } + + _nCurUnit = CLayerParamDlg::GetCurPressureUnit(); + if (((*_it)->nUnit == CLayerParamDlg::Pressure_Percent + || (*_it)->nUnit == CLayerParamDlg::Pressure_MPa) + && (*_it)->nUnit != _nCurUnit) + { + CLayerParamDlg::ConverUnit((*_it)->nUnit, _nCurUnit, _nValue, _nValue); + } + + if ((*_it)->nDataType == 0) + { + CStringA _str; + _str.Format("%d", int(_nValue)); + SetDlgItemText((*_it)->nID, _str); + if (!m_bDataValid) + { + GetDlgItem((*_it)->nID)->SetFocus(); + } + } + else + { + CStringA _str; + _str.Format("%.3f", _nValue); + FormatDoubleParamer(_str); + SetDlgItemText((*_it)->nID, _str); + if (!m_bDataValid) + { + GetDlgItem((*_it)->nID)->SetFocus(); + } + } + + break; + } +} + +void CThreeSegPunchParamDlg::OnSetFocusEdits(UINT nID_) +{ + ASSERT(_countof(m_LastTextItems) >= 2); + m_LastTextItems[1].nID = m_LastTextItems[0].nID; + m_LastTextItems[1].strLastText = m_LastTextItems[0].strLastText; + m_LastTextItems[0].nID = nID_; + GetDlgItemText(nID_, m_LastTextItems[0].strLastText); +} + +void CThreeSegPunchParamDlg::OnSelectGases(UINT nID_) +{ + if (nID_ != IDC_COMBO_FIRSTSEGGAS + && nID_ != IDC_COMBO_SECONDSEGGAS + && nID_ != IDC_COMBO_THIRDSEGGAS) + return; + + CStringA _strKey; + if (nID_ == IDC_COMBO_FIRSTSEGGAS) + { + _strKey = c_szFirstSegGasKey; + } + else if (nID_ == IDC_COMBO_SECONDSEGGAS) + { + _strKey = c_szSecondSegGasKey; + } + else + { + _strKey = c_szThirdSegGasKey; + } + + CComboBox* _pComb = (CComboBox*)GetDlgItem(nID_); + int _nIndex = _pComb->GetCurSel(); + ASSERT(_nIndex < (int)m_vectCombItems.size()); + if (_nIndex > -1) + m_pParam->SetKey(_strKey, m_vectCombItems[_nIndex]->strValue); +} + +void CThreeSegPunchParamDlg::OnSelectStopGases(UINT nID_) +{ + if (nID_ != IDC_COMBO_FIRSTSTOPLASERBLOWTYPE + && nID_ != IDC_COMBO_SECONDSTOPLASERBLOWTYPE + && nID_ != IDC_COMBO_THIRDSTOPLASERBLOWTYPE) + return; + + CStringA _strKey; + if (nID_ == IDC_COMBO_FIRSTSTOPLASERBLOWTYPE) + { + _strKey = c_szFirstStopSegGasKey; + } + else if (nID_ == IDC_COMBO_SECONDSTOPLASERBLOWTYPE) + { + _strKey = c_szSecondStopSegGasKey; + } + else + { + ASSERT(nID_ == IDC_COMBO_THIRDSTOPLASERBLOWTYPE); + _strKey = c_szThirdStopSegGasKey; + } + + CComboBox* _pComb = (CComboBox*)GetDlgItem(nID_); + int _nIndex = _pComb->GetCurSel(); + ASSERT(_nIndex < (int)m_vectCombItems.size()); + if (_nIndex > -1) + m_pParam->SetKey(_strKey, m_vectCombItems[_nIndex]->strValue); +} + +void CThreeSegPunchParamDlg::OnClickPunchType(UINT nID_) +{ + if (nID_ != IDC_CHECK_FIRSTSEG + && nID_ != IDC_CHECK_SECONDSEG + && nID_ != IDC_CHECK_THIRDSEG) + return; + + CStringA _strKey; + if (nID_ == IDC_CHECK_FIRSTSEG) + _strKey = c_szFirstSegPunch; + else if (nID_ == IDC_CHECK_SECONDSEG) + _strKey = c_szSecondSegPunch; + else + _strKey = c_szThirdSegPunch; + bool _bPunch = m_pParam->GetKey_DBL(_strKey) == 1; + _bPunch = !_bPunch; + m_pParam->SetKey_DBL(_strKey, _bPunch); + + Update(); +} + +void CThreeSegPunchParamDlg::OnClickEnableConPer(UINT nID_) +{ + if (nID_ != IDC_CHECK_FIRSTCONPERSPEED + && nID_ != IDC_CHECK_SECONDCONPERSPEED + && nID_ != IDC_CHECK_THIRDCONPERSPEED) + return; + + CStringA _strKey; + if (nID_ == IDC_CHECK_FIRSTCONPERSPEED) + _strKey = c_szFirstSegConSpeed; + else if (nID_ == IDC_CHECK_SECONDCONPERSPEED) + _strKey = c_szSecondSegConSpeed; + else + _strKey = c_szThirdSegConSpeed; + bool _bPunch = m_pParam->GetKey_DBL(_strKey) == 1; + _bPunch = !_bPunch; + m_pParam->SetKey_DBL(_strKey, _bPunch); + + Update(); +} + +void CThreeSegPunchParamDlg::OnClickEnableCloseLaserBlow(UINT nID_) +{ + if (nID_ != IDC_CHECK_FIRSTSTOPLASERBLOW + && nID_ != IDC_CHECK_SECONDSTOPLASERBLOW + && nID_ != IDC_CHECK_THIRDSTOPLASERBLOW) + return; + + CStringA _strKey; + if (nID_ == IDC_CHECK_FIRSTSTOPLASERBLOW) + _strKey = c_szFirstStopLaserBlow; + else if (nID_ == IDC_CHECK_SECONDSTOPLASERBLOW) + _strKey = c_szSecondStopLaserBlow; + else + _strKey = c_szThirdStopLaserBlow; + bool _bPunch = m_pParam->GetKey_DBL(_strKey) == 1; + _bPunch = !_bPunch; + m_pParam->SetKey_DBL(_strKey, _bPunch); + + Update(); +} + +void CThreeSegPunchParamDlg::OnKillFocusRemarks() +{ + CStringA _strRemarks; + GetDlgItem(IDC_EDIT_THREESEGUSERREMARKS)->GetWindowText(_strRemarks); + _strRemarks = Normative(_strRemarks); + + // 将备注用引号包围,这样Lua就把它当成一串字符串,不会展开解析。 ---- 黄海燕 2015-02-04 + _strRemarks.Insert(0, "\""); + _strRemarks += "\""; + + if (m_pParam->GetKey(LPSTR(c_szThreeSegPunchRemarks)) != _strRemarks) + m_pParam->SetKey(LPSTR(c_szThreeSegPunchRemarks), _strRemarks); +} + +// 用户备注保存在图层参数中,为避免用户输入与图层中某个参数一样以及含特殊字符干扰Lua的解析, +// 特将'\\'、';'、'='、'\"'、'\''、'\r'、'\n'分别替换为ASCII码为0x16、0x07、0x1D、0x1E、0x1F、0x06、0x10。 +// PS:0x16 SYS是一个设备控制指令,同步空闲的。 +// 0x07 是响铃也是个设备控制命令。 +// 0x06 是请求确认,主要用于全双工或半双工的报文通信。 +// 0x10 是数据链路转义,用于网络传输的 +// 0x1D、0x1E、0x1F分别是Linx和Unix平台下AWK文本处理器中的分组符、记录分割符、单元分隔符,我们都是用的Windows的。 +// 以上结论均来自网络,照这样的解释用他们来替换字符应该没有什么负面影响,若发现错误,方便告知下。 +// ---- 黄海燕 2015-02-04 +CString CThreeSegPunchParamDlg::Normative(LPCTSTR pszValue_) +{ + CString _strRet(pszValue_); + _strRet.Replace('\\', 0x16); + _strRet.Replace(';', 0x07); + _strRet.Replace('=', 0x1D); + _strRet.Replace('\"', 0x1E); + _strRet.Replace('\'', 0x1F); + _strRet.Replace('\r', 0x06); + _strRet.Replace('\n', 0x10); + return _strRet; +} + +// 将0x16、0x07、0x1D、0x1E、0x1F分别替换为'\\'、';'、'='、'\"'、'\'',是Normative的逆过程。 +// ---- 黄海燕 2015-02-04 +CString CThreeSegPunchParamDlg::ReverseNormative(LPCTSTR pszValue_) +{ + CString _strRet(pszValue_); + _strRet.Replace(0x16, '\\'); + _strRet.Replace(0x07, ';'); + _strRet.Replace(0x1D, '='); + _strRet.Replace(0x1E, '\"'); + _strRet.Replace(0x1F, '\''); + _strRet.Replace(0x06, '\r'); + _strRet.Replace(0x10, '\n'); + return _strRet; +} + +void CThreeSegPunchParamDlg::SetText() +{ + SetDlgItemText(IDC_CHECK_FIRSTSEG, _GETCS(s_szFIRSTSEG)); + SetDlgItemText(IDC_CHECK_SECONDSEG, _GETCS(s_szSECONDSEG)); + SetDlgItemText(IDC_CHECK_THIRDSEG, _GETCS(s_szTHIRDSEG)); + + SetDlgItemText(IDC_CHECK_FIRSTCONPERSPEED, _GETCS(s_szPIERCESPEED)); + SetDlgItemText(IDC_STATIC_FIRSTSEGPOWER, _GETCS(s_szFIRSTCURRENT)); + SetDlgItemText(IDC_STATIC_FIRSTSEGFREQ, _GETCS(s_szFIRSTFREQU)); + SetDlgItemText(IDC_STATIC_FIRSTSEGDUTYCYCLE, _GETCS(s_szFIRSTPOWER)); + SetDlgItemText(IDC_STATIC_FIRSTSEGGAS, _GETCS(s_szFIRSTGAS)); + SetDlgItemText(IDC_STATIC_FIRSTSEGPRESSUER, _GETCS(s_szFIRSTPRESSURE)); + SetDlgItemText(IDC_STATIC_FIRSTSEGHEIGHT, _GETCS(s_szFIRSTHEIGHT)); + SetDlgItemText(IDC_STATIC_FIRSTSEGELAY, _GETCS(s_szFIRSTDELAY)); + SetDlgItemText(IDC_STATIC_FIRSTSEGFOCUS, _GETCS(s_szFIRSTSEGFOCUS)); + SetDlgItemText(IDC_CHECK_FIRSTSTOPLASERBLOW, _GETCS(s_szExtraPuffing)); + SetDlgItemText(IDC_STATIC_FIRSTSTOPLASERBLOWTYPE, _GETCS(s_szSTOPGAS)); + + SetDlgItemText(IDC_CHECK_SECONDCONPERSPEED, _GETCS(s_szPIERCESPEED)); + SetDlgItemText(IDC_STATIC_SECONDSEGPOWER, _GETCS(s_szSECONDCURRENT)); + SetDlgItemText(IDC_STATIC_SECONDSEGFREQ, _GETCS(s_szSECONDFREQU)); + SetDlgItemText(IDC_STATIC_SECONDSEGDUTYCYCLE, _GETCS(s_szSECONDPOWER)); + SetDlgItemText(IDC_STATIC_SECONDSEGGAS, _GETCS(s_szSECONDGAS)); + SetDlgItemText(IDC_STATIC_SECONDSEGPRESSUER, _GETCS(s_szSECONDPRESSURE)); + SetDlgItemText(IDC_STATIC_SECONDSEGHEIGHT, _GETCS(s_szSECONDHEIGHT)); + SetDlgItemText(IDC_STATIC_SECONDSEGDELAY, _GETCS(s_szSECONDDELAY)); + SetDlgItemText(IDC_STATIC_SECONDSEGFOCUS, _GETCS(s_szSECONDSEGFOCUS)); + SetDlgItemText(IDC_CHECK_SECONDSTOPLASERBLOW, _GETCS(s_szExtraPuffing)); + SetDlgItemText(IDC_STATIC_SECONDSTOPLASERBLOWTYPE, _GETCS(s_szSTOPGAS)); + + SetDlgItemText(IDC_CHECK_THIRDCONPERSPEED, _GETCS(s_szPIERCESPEED)); + SetDlgItemText(IDC_STATIC_THIRDSEGPOWER, _GETCS(s_szTHIRDCURRENT)); + SetDlgItemText(IDC_STATIC_THIRDSEGFREQ, _GETCS(s_szTHIRDFREQU)); + SetDlgItemText(IDC_STATIC_THIRDSEGDUTYCYCLE, _GETCS(s_szTHIRDPOWER)); + SetDlgItemText(IDC_STATIC_THIRDSEGGAS, _GETCS(s_szTHIRDGAS)); + SetDlgItemText(IDC_STATIC_THIRDSEGPRESSUER, _GETCS(s_szTHIRDPRESSURE)); + SetDlgItemText(IDC_STATIC_THIRDSEGHEIGHT, _GETCS(s_szTHIRDHEIGHT)); + SetDlgItemText(IDC_STATIC_THIRDSEGDELAY, _GETCS(s_szTHIRDDELAY)); + SetDlgItemText(IDC_STATIC_THIRDSEGFOCUS, _GETCS(s_szTHIRDSEGFOCUS)); + SetDlgItemText(IDC_CHECK_THIRDSTOPLASERBLOW, _GETCS(s_szExtraPuffing)); + SetDlgItemText(IDC_STATIC_THIRDSTOPLASERBLOWTYPE, _GETCS(s_szSTOPGAS)); + + SetDlgItemText(IDC_STATIC_THREESEGUSERREMARKS, _GETCS(s_szREMARKS)); +} diff --git a/src/TrackCtrl.cpp b/src/TrackCtrl.cpp new file mode 100644 index 0000000..544461e --- /dev/null +++ b/src/TrackCtrl.cpp @@ -0,0 +1,3620 @@ +// TraceCtrl.cpp : implementation file +// + +#include "stdafx.h" +#include "TrackCtrl.h" +#include "TraceCtrlCustomizeDlg.h" +#include "TCACCDlg.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +////////////////////////////////////////////////////////////////////// +// Constants and definitions +double g_ratio[RATIO_COUNT] = +{ + 5.0e-2, //5% + 1.0e-1, //10% + 2.0e-1, //20% + 5.0e-1, //50% + 1.0e0, //100% + 2.0e0, //200% + 5.0e0, //500% + 1.0e1, //1000% + 2.0e1, //2000% + 5.0e1, //5000% + 1.0e2, //10000% +}; + +const static TCHAR* s_szNCTRACEVIEW_CLASS[] ={ + _T("s_szNCTRACEVIEW_CLASS_{1E068523-505E-11D6-A9D2-0000E2556D2C}"), + _T("s_szNCTRACEVIEW_CLASS_{34E52D98-BB3F-4B39-91A7-5B19D9CAB4CC}"), + _T("s_szNCTRACEVIEW_CLASS_{F611121E-D9D3-4F5A-B444-45A1D54156FF}"), + _T("s_szNCTRACEVIEW_CLASS_{46C3B512-EE07-4127-AADE-A318F6B7CB7D}"), +}; + +/*********************************************************************** +这个宏,提供了所有CTraceCtrlBase实例同步的方法。FUNCTION是需要做同步动作的 +函数名称。 +**********************************************************************/ + +///////////////////////////////////////////////////////////////////////////// +// + +// TODO zhengzhikai 2017-12-7 优化掉memcpy +inline void _tam(TRANSMATRIX* pP_, TRANSMATRIX* pM1_, TRANSMATRIX* pM2_) +{ + TRANSMATRIX _matrix; + for (int _row = 0; _row < 3; _row++) + for (int _col = 0; _col < 3; _col++) + { + _matrix[_row][_col] = (*pM1_)[_row][0] * (*pM2_)[0][_col] + + (*pM1_)[_row][1] * (*pM2_)[1][_col] + + (*pM1_)[_row][2] * (*pM2_)[2][_col]; + } + memcpy(pP_, &_matrix, sizeof(_matrix)); + return; +} +///////////////////////////////////////////////////////////////////////////// +// CTraceCtrl +IMPLEMENT_DYNAMIC(CTraceCtrl, CWnd) + +BEGIN_MESSAGE_MAP(CTraceCtrl, CWnd) + //{{AFX_MSG_MAP(CTraceCtrl) + ON_WM_CONTEXTMENU() + ON_WM_ERASEBKGND() + ON_WM_SIZE() + ON_WM_SETFOCUS() + ON_WM_KILLFOCUS() + ON_WM_MOUSEMOVE() + ON_WM_GETDLGCODE() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_CREATE() + ON_WM_DESTROY() + ON_WM_SETCURSOR() + ON_WM_PAINT() + ON_WM_TIMER() + ON_WM_KEYDOWN() + ON_WM_SYSKEYDOWN() + ON_WM_WINDOWPOSCHANGED() + ON_WM_MOUSEWHEEL() + ON_COMMAND_RANGE(IDCMD_TRACECTRL_first, IDCMD_TRACECTRL_last, OnCommandRange) + ON_UPDATE_COMMAND_UI_RANGE(IDCMD_TRACECTRL_first, IDCMD_TRACECTRL_last, OnUpdateCommandRange) + ON_COMMAND(IDCMD_TRACECTRL_SYSTEM_CUSTOMIZE, OnToolCustomize) + ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &OnToolTipNeedText) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +GETSTRING DataProvider::GetString = NULL; +VFUNCTION DataProvider::FreeGetStringPtr = NULL; + +CTraceCtrl::CTraceCtrl() + :CTraceCtrlBase(), + m_nxAreaMax(0.0, 0.0, 0.0), + m_nxAreaMin(0.0, 0.0, 0.0), + m_nxWorkcoorOrg(0.0, 0.0, 0.0) +{ + //{{AFX_DATA_FIELD default value + memset(m_clrPens, 0, sizeof(m_clrPens)); // initialize to RGB(0, 0, 0) + m_clrPens[PEN_G00] = RGB(255, 255 , 0); + m_clrPens[PEN_G01] = RGB(0, 255, 255); + m_clrPens[PEN_G02] = RGB(0, 255, 255); + m_clrPens[PEN_G03] = RGB(0, 255, 255); + // + m_clrPens[PEN_G00_SIMU] =RGB(0,0,0);; + m_clrPens[PEN_G01_SIMU] = RGB(0, 0, 128); + m_clrPens[PEN_G02_SIMU] = RGB(0, 0, 128); + m_clrPens[PEN_G03_SIMU] = RGB(0, 0, 128); + // + m_clrPens[PEN_RULER] = RGB(0, 0, 0); + m_clrPens[PEN_GRID] = RGB(128, 0, 128); + // + m_clrPens[PEN_COOR] = RGB(0, 255, 0); + m_clrPens[PEN_COORDARKEN] = RGB(0, 128, 0); + m_clrPens[PEN_SELECTED] = RGB(0, 255, 0); + // + m_clrTrackBkFrom = RGB(0,0,0);//RGB(163, 113, 217); + m_clrTrackLineNum = RGB(0, 0, 0); + m_clrTrackBkTo =RGB(0,0,0); //RGB(0, 0, 128); + m_clrPens[PEN_STARTPOINT] = CLR_TRANSPARENT; + + m_bGradientFill = true; + m_bDrawWorkAreaFrame = true; + m_bShowCoor = true; + m_bDrawGrid = false; + m_b2DMode = false; + m_bIsFileTrackFirst = true; + m_bInitPerDoc = false; + m_bIsShowLineNumber = false; + //}}AFX_DATA_FIELD end + + m_clrBackground = RGB(255,255,255);//GetSysColor(COLOR_3DFACE);改成白色 + m_clrShadow = GetSysColor(COLOR_3DFACE); + m_clrHilit = GetSysColor(COLOR_3DHILIGHT); + + m_clrBorder = CLR_TRANSPARENT; + m_nBorderFormat = 0; + m_nShowSpeed = _SHOW_SPEED_NO; + + // then load the saved parameters + m_ptCross.x = m_ptCross.y = m_ptCross.z = c_nINVALID_NCNODEEX_REAL; + m_WorkAreaMin.x = m_WorkAreaMin.y = m_WorkAreaMin.z = 0.0; + m_WorkAreaMax.x = m_WorkAreaMax.y = m_WorkAreaMax.z = 500.0; + + m_nOperation = MOVE; + m_nSelectMode = CTrackRecorder::OR; + m_bReceiveArrowMsgs = false; + + m_nCoorX = 0; + m_nNumofRecordToPaint = 0; + m_nLastGType = 0; + m_nProjectMode = PROJ_ISOMETRIC_SE; + SetTransformMatrix(m_b2DMode ? PROJ_TOP : PROJ_ISOMETRIC_SE); + + RegisterWndClass(); + + m_dc.m_pGPen = m_pens; + m_dc.m_pSelectedLinePen = &m_pens[PEN_SELECTED]; + + m_HitField.from = m_HitField.to = -1; + + m_bIsSimu = m_bPageFault = false; + m_nFileTrackSize = 0; + m_bSimulating = false; + m_nCompressNccmd_Old = 2; // not accessed yet + m_nTimerCounter = 0; + m_nClassNameIndex = 0; + CreatContextMenu(true); + m_nAccKey = 'S'; + m_bUpdateTrackUI = false; + rectDC=NULL; + rectBmp=NULL; + + m_dataprovider = new DataProvider; + + memset(m_LastNccmd, 0, sizeof(m_LastNccmd)); + + m_bTrackLoaded = false; +} + +CTraceCtrl::~CTraceCtrl() +{ + if(rectDC != NULL) delete rectDC; + if(rectBmp != NULL) delete rectBmp; + if(m_dataprovider!=NULL) delete m_dataprovider; + if(s_szAxisName != NULL) delete[] s_szAxisName; +} + +BOOL CTraceCtrl::RegisterWndClass() +{ + static int _s_nRegister = -1; + + _s_nRegister++; + + if(_s_nRegister > 3) + return false; + + m_nClassNameIndex = _s_nRegister; + + WNDCLASS _wndcls; + memset(&_wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults + _wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + _wndcls.lpfnWndProc = ::DefWindowProc; + _wndcls.hInstance = AfxGetInstanceHandle(); + _wndcls.hCursor = ::LoadCursor(NULL, IDC_ARROW); + _wndcls.hbrBackground =(HBRUSH)(COLOR_WINDOW + 1); + _wndcls.lpszClassName = s_szNCTRACEVIEW_CLASS[m_nClassNameIndex]; + //_wndcls.lpszClassName = s_szNCTRACEVIEW_CLASS; + + //_s_bRegister = RegisterClass(&_wndcls); + return RegisterClass(&_wndcls); +} + +BOOL CTraceCtrl::PreCreateWindow(CREATESTRUCT& cs_) +{ + cs_.lpszClass = s_szNCTRACEVIEW_CLASS[m_nClassNameIndex]; + return CWnd::PreCreateWindow(cs_); +} + +//LPCTSTR CTraceCtrl::GetTraceWndClassName() +//{ +// return s_szNCTRACEVIEW_CLASS; +//} + +void CTraceCtrl::Initialize() +{ + double _naxes = m_dataprovider->GetAxesNumber(); + if(_naxes > 0) + { + m_nAxesNumber = (int)_naxes; + s_szAxisName = new LPCTSTR[(int)_naxes](); + + for(int i = 0 ;i<_naxes;i++) + { + s_szAxisName[i] = m_dataprovider->GetAxisName(i); + } + } + else + { + s_szAxisName = new LPCTSTR[c_nNUMOF_AXIS]; + for(int i=0;iGetCurPos(); + + AXDOUBLE_KERNEL _cur = GetCurPos(); //add yuewenxue + NCNODEEX::POINT3D _pos((NCNODEEX::REAL)_cur[m_nX], + (NCNODEEX::REAL)_cur[m_nY], (NCNODEEX::REAL)_cur[m_nZ]); + + m_ptLastPoint.x = _pos.x; + m_ptLastPoint.y = _pos.y; + m_ptLastPoint.z = _pos.z; + + SetTimer(IDTIMER_READNCCMD, 83, NULL); + SetTimer(IDTIMER_CONTINUE_PLAYBACK, c_nCONTINUEPLAYBACK_TIMER_INTERVAL, NULL); + + if (!m_TrackRecord.IsOpen()) + { + if (!m_TrackRecord.Open()) + ShowMessage(s_csCREATE_TEMPFILE_ERROR,LOG_ERROR); + } + + m_dc.SetLogicalRef(m_ptLastPoint.x, m_ptLastPoint.y); + ClearView(); + CenterCursor(); + OnCommandRange(IDCMD_TRACECTRL_FITWINDOW); + return; +} + +void CTraceCtrl::CreatContextMenu(bool bHasContextMenu_) +{ + if(m_contextMenu != NULL) + { + m_contextMenu.DestroyMenu(); + } + + if(bHasContextMenu_ == true) + { + m_contextMenu.CreatePopupMenu(); + } + + if(IsMenu(this->m_contextMenu)) + { + TCHAR _szTempString[256]; + GetString(L"s_csTRACECTRL_CLEARVIEW",_szTempString, _countof(_szTempString), s_csTRACECTRL_CLEARVIEW); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_CLEARVIEW,_szTempString); + m_contextMenu.AppendMenu(MF_SEPARATOR); + GetString(L"s_csTRACECTRL_MOVE",_szTempString, _countof(_szTempString), s_csTRACECTRL_MOVE); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_MOVE,_szTempString); + GetString(L"s_csTRACECTRL_ZOOMOUT",_szTempString, _countof(_szTempString), s_csTRACECTRL_ZOOMOUT); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_ZOOMOUT,_szTempString); + GetString(L"s_csTRACECTRL_ZOOMIN",_szTempString, _countof(_szTempString), s_csTRACECTRL_ZOOMIN); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_ZOOMIN,_szTempString); + GetString(L"s_csTRACECTRL_CENTER",_szTempString, _countof(_szTempString), s_csTRACECTRL_CENTER); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_CENTER,_szTempString); + GetString(L"s_csTRACECTRL_FITWINDOW",_szTempString, _countof(_szTempString), s_csTRACECTRL_FITWINDOW); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_FITWINDOW,_szTempString); + GetString(L"s_csTRACECTRL_CURRENT",_szTempString, _countof(_szTempString), s_csTRACECTRL_CURRENT); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_CURRENT,_szTempString); + GetString(L"s_csTRACECTRL_CUSTOMIZE",_szTempString, _countof(_szTempString), s_csTRACECTRL_CUSTOMIZE); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_SYSTEM_CUSTOMIZE,_szTempString); + m_contextMenu.AppendMenu(MF_SEPARATOR); + GetString(L"s_csTRACECTRL_PROJ_FRONT",_szTempString, _countof(_szTempString), s_csTRACECTRL_PROJ_FRONT); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_PROJ_FRONT,_szTempString); + GetString(L"s_csTRACECTRL_PROJ_BACK",_szTempString, _countof(_szTempString), s_csTRACECTRL_PROJ_BACK); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_PROJ_BACK,_szTempString); + GetString(L"s_csTRACECTRL_PROJ_TOP",_szTempString, _countof(_szTempString), s_csTRACECTRL_PROJ_TOP); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_PROJ_TOP,_szTempString); + GetString(L"s_csTRACECTRL_PROJ_BOTTOM",_szTempString, _countof(_szTempString), s_csTRACECTRL_PROJ_BOTTOM); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_PROJ_BOTTOM,_szTempString); + GetString(L"s_csTRACECTRL_PROJ_LEFT",_szTempString, _countof(_szTempString), s_csTRACECTRL_PROJ_LEFT); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_PROJ_LEFT,_szTempString); + GetString(L"s_csTRACECTRL_PROJ_RIGHT",_szTempString, _countof(_szTempString), s_csTRACECTRL_PROJ_RIGHT); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_PROJ_RIGHT,_szTempString); + GetString(L"s_csTRACECTRL_PROJ_ISOMETRIC_SW",_szTempString, _countof(_szTempString), s_csTRACECTRL_PROJ_ISOMETRIC_SW); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_PROJ_ISOMETRIC_SW,_szTempString); + GetString(L"s_csTRACECTRL_PROJ_ISOMETRIC_NW",_szTempString, _countof(_szTempString), s_csTRACECTRL_PROJ_ISOMETRIC_NW); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_PROJ_ISOMETRIC_NW,_szTempString); + GetString(L"s_csTRACECTRL_PROJ_ISOMETRIC_SE",_szTempString, _countof(_szTempString), s_csTRACECTRL_PROJ_ISOMETRIC_SE); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_PROJ_ISOMETRIC_SE,_szTempString); + GetString(L"s_csTRACECTRL_PROJ_ISOMETRIC_NE",_szTempString, _countof(_szTempString), s_csTRACECTRL_PROJ_ISOMETRIC_NE); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_PROJ_ISOMETRIC_NE,_szTempString); + m_contextMenu.AppendMenu(MF_SEPARATOR); + GetString(L"s_csTRACECTRL_LOAD_TRACK",_szTempString, _countof(_szTempString), s_csTRACECTRL_LOAD_TRACK); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_LOAD_TRACK,_szTempString); + GetString(L"s_csTRACECTRL_STOP_LOAD_TRACK",_szTempString, _countof(_szTempString), s_csTRACECTRL_STOP_LOAD_TRACK); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_STOP_LOAD_TRACK,_szTempString); + GetString(L"s_csTRACECTRL_CLEAR_TRACK",_szTempString, _countof(_szTempString), s_csTRACECTRL_CLEAR_TRACK); + m_contextMenu.AppendMenu(MF_STRING,IDCMD_TRACECTRL_CLEAR_TRACK,_szTempString); + } +} + +void CTraceCtrl::EnableTimer(bool bOn_) +{ + if (bOn_) + { + UpdateChanges(false); + SetTimer(IDTIMER_CONTINUE_PLAYBACK, c_nCONTINUEPLAYBACK_TIMER_INTERVAL, NULL); + } + else + { + KillTimer(IDTIMER_CONTINUE_PLAYBACK); + + // reset it, so that UpdateChanges() can be called at the next timer on. + m_nTimerCounter = 0; + } +} + +///////////////////////////////////////////////////////////////////////////// +// CTraceCtrl general operations + +void CTraceCtrl::ClearView() +{ + //注释释放内存问题,解决多线程导致写写保护内存。 add yuewenxue + // (0) close the track recorder to free memory + + KillDrawTimer(); + m_TrackRecord.Close(); + if (!m_TrackRecord.Open()) + ShowMessage(s_csCREATE_TEMPFILE_ERROR,LOG_ERROR); + ResetDrawTimer(); + + // (1) clear the track recorder + //清除时不需要记录上个点 add ywx + NCNODEEX _rec; + _rec.bSelected = false; + _rec.nGType = 0; + _rec.pt3D.x = (NCNODEEX::REAL)m_ptLastPoint.x; + _rec.pt3D.y = (NCNODEEX::REAL)m_ptLastPoint.y; + _rec.pt3D.z = (NCNODEEX::REAL)m_ptLastPoint.z; + _rec.nFilePos = m_nLastFP; + _rec.nLineOrID = m_nLastLineNoOrID; + _rec.nOffset = m_nOffset; + _rec.nFileType = m_nFileType; + _rec.pt2D.x = _rec.pt2D.y = -1; + m_TrackRecord.Reset(&_rec); + + // (2) clear the trace bound rectangle + m_TraceArea.Clear(); + + // (3) clear the track bitmap in the playbck DC + m_dc.m_nNextPoint = 0; + + // (4) last, invalidate the whole view + if (m_hWnd) + InvalidateRect(NULL); +} + +void CTraceCtrl::ClearTrackRecordPosInfo() +{ + NCNODEEX* _pRec = m_TrackRecord.GetBase(); + int _nCount = m_TrackRecord.GetSize(); + for (int _i = 0; _i < _nCount; _i++) + { + _pRec->nFilePos = EOF; + _pRec->nLineOrID = 0; + _pRec->nOffset = 0; + _pRec++; + } +} + +void CTraceCtrl::CalculateLayout(int cx_, int cy_) +{ + m_rcSpeed.left = c_nVIEW_EDGE; + m_rcSpeed.top = c_nVIEW_EDGE; + m_rcSpeed.right = cx_ - c_nVIEW_EDGE; + m_rcSpeed.bottom = cy_ - c_nVIEW_EDGE; + + if (m_dc.SetDimension(cx_, cy_) && m_hWnd) + InvalidateRect(NULL); +} + +void CTraceCtrl::UpdateChanges(bool bArbitrary_) +{ + bool _bDirty = bArbitrary_; + bool _AreaChanged = false; + bool _bSimu = IsSimulating(); + + //AXDOUBLE_KERNEL _minArea = m_pTrackProvider->GetAreaMin(); + //AXDOUBLE_KERNEL _maxArea = m_pTrackProvider->GetAreaMax(); add yuewenxue + AXDOUBLE_KERNEL _minArea = GetAreaMin(); + AXDOUBLE_KERNEL _maxArea = GetAreaMax(); //add yuewenxue + if (bArbitrary_ || + (m_nxAreaMax != _maxArea) || + (m_nxAreaMin != _minArea)) + { + m_WorkAreaMax.x = (NCNODEEX::REAL)_maxArea[m_nX]; // in mm + m_WorkAreaMax.y = (NCNODEEX::REAL)_maxArea[m_nY]; // in mm + m_WorkAreaMax.z = (NCNODEEX::REAL)_maxArea[m_nZ]; // in mm + m_WorkAreaMin.x = (NCNODEEX::REAL)_minArea[m_nX]; // in mm + m_WorkAreaMin.y = (NCNODEEX::REAL)_minArea[m_nY]; // in mm + m_WorkAreaMin.z = (NCNODEEX::REAL)_minArea[m_nZ]; // in mm + + ASSERT(m_WorkAreaMax.x >= m_WorkAreaMin.x); + ASSERT(m_WorkAreaMax.y >= m_WorkAreaMin.y); + ASSERT(m_WorkAreaMax.z >= m_WorkAreaMin.z); + + m_WorkAreaVertex[0].x = m_WorkAreaMin.x; + m_WorkAreaVertex[0].y = m_WorkAreaMin.y; + m_WorkAreaVertex[0].z = m_WorkAreaMin.z; + // + m_WorkAreaVertex[1].x = m_WorkAreaMin.x; + m_WorkAreaVertex[1].y = m_WorkAreaMax.y; + m_WorkAreaVertex[1].z = m_WorkAreaMin.z; + // + m_WorkAreaVertex[2].x = m_WorkAreaMax.x; + m_WorkAreaVertex[2].y = m_WorkAreaMin.y; + m_WorkAreaVertex[2].z = m_WorkAreaMin.z; + // + m_WorkAreaVertex[3].x = m_WorkAreaMax.x; + m_WorkAreaVertex[3].y = m_WorkAreaMax.y; + m_WorkAreaVertex[3].z = m_WorkAreaMin.z; + // + m_WorkAreaVertex[4].x = m_WorkAreaMin.x; + m_WorkAreaVertex[4].y = m_WorkAreaMin.y; + m_WorkAreaVertex[4].z = m_WorkAreaMax.z; + // + m_WorkAreaVertex[5].x = m_WorkAreaMin.x; + m_WorkAreaVertex[5].y = m_WorkAreaMax.y; + m_WorkAreaVertex[5].z = m_WorkAreaMax.z; + // + m_WorkAreaVertex[6].x = m_WorkAreaMax.x; + m_WorkAreaVertex[6].y = m_WorkAreaMin.y; + m_WorkAreaVertex[6].z = m_WorkAreaMax.z; + // + m_WorkAreaVertex[7].x = m_WorkAreaMax.x; + m_WorkAreaVertex[7].y = m_WorkAreaMax.y; + m_WorkAreaVertex[7].z = m_WorkAreaMax.z; + + + m_nxAreaMax = _maxArea; + m_nxAreaMin = _minArea; + + _bDirty = true; + _AreaChanged = true; + } + + if (bArbitrary_ ||_bSimu != m_bIsSimu ) + { + m_bIsSimu = _bSimu; + _bDirty = true; + } + + // track recorder status + if (bArbitrary_ || (m_bPageFault != m_TrackRecord.IsPageFault())) + { + m_bPageFault = m_TrackRecord.IsPageFault(); + _bDirty = true; + } + + if (bArbitrary_ || (m_nMemorySize != m_TrackRecord.GetMemorySize())) + { + m_nMemorySize = m_TrackRecord.GetMemorySize(); + _bDirty = true; + } + + bool _bOrgChanged = false; + AXDOUBLE_KERNEL _org = GetWorkcoorOrg(); + if (_org != m_nxWorkcoorOrg) + { + _bOrgChanged = true; + m_nxWorkcoorOrg = _org; + } + + int _ftsize = 0; + if (m_TrackRecordNode.IsOpen() && !m_TrackRecordNode.IsEmpty()) + _ftsize = m_TrackRecordNode.GetSize(); + bool _bTrackChanged = false; + if (_ftsize != m_nFileTrackSize) + { + _bTrackChanged = false; + m_nFileTrackSize = _ftsize; + } + + if (_bOrgChanged || _bTrackChanged || _AreaChanged) + { + // clear the track bitmap in the playbck DC + m_dc.m_nNextPoint = 0; + _bDirty = true; + } + + if (_bDirty && m_hWnd && IsWindowVisible()) + InvalidateRect(NULL); + return; +} + +inline POINTD CTraceCtrl::CubicTransformCenterPointer3D(const NCNODEEX::POINT3D& pt1_, const NCNODEEX::POINT3D& pt2_) +{ + POINTD _pt; + NCNODEEX::POINT3D _pt3; + + _pt3.x = (NCNODEEX::REAL)((pt1_.x + pt2_.x) / 2.); + _pt3.y = (NCNODEEX::REAL)((pt1_.y + pt2_.y) / 2.); + _pt3.z = (NCNODEEX::REAL)((pt1_.z + pt2_.z) / 2.); + _pt = CubicTransform(&_pt3); + return _pt; +} + +POINTD CTraceCtrl::GetWorkpieceCenterPoint() +{ + if (m_bIsFileTrackFirst) + { + if (m_TrackRecordNode.IsOpen()) + { + //AXDOUBLE_KERNEL _org = GetWorkcoorOrg(); + //NCNODEEX::POINT3D _org3D( + // (NCNODEEX::REAL)_org[m_nX], + // (NCNODEEX::REAL)_org[m_nY], + // (NCNODEEX::REAL)_org[m_nZ]); + + NCNODEEX::POINT3D _org3D(0.0,0.0,0.0); + + if (m_traceAreaUpdate.IsMachValid()) + return CubicTransformCenterPointer3D( + m_traceAreaUpdate.ptMachMin + _org3D, + m_traceAreaUpdate.ptMachMax + _org3D); + if (m_traceAreaUpdate.IsMotionValid()) + return CubicTransformCenterPointer3D( + m_traceAreaUpdate.ptMotionMin + _org3D, + m_traceAreaUpdate.ptMotionMax + _org3D); + } + } + + if (m_TraceArea.IsMachValid()) + return CubicTransformCenterPointer3D(m_TraceArea.ptMachMin, m_TraceArea.ptMachMax); + + if (m_TraceArea.IsMotionValid()) + return CubicTransformCenterPointer3D(m_TraceArea.ptMotionMin, m_TraceArea.ptMotionMax); + + return CubicTransformCenterPointer3D(m_WorkAreaMin, m_WorkAreaMax); +} + +///////////////////////////////////////////////////////////////////////////// +// CTraceCtrl drawing + +void CTraceCtrl::CreatePen(CPen* pPen_, COLORREF clr_) +{ + if (clr_ == CLR_TRANSPARENT) + pPen_->CreateStockObject(NULL_PEN); + else + pPen_->CreatePen(PS_SOLID, 0, clr_); +} + +void CTraceCtrl::CreateBrush(CBrush* pBrush_, COLORREF clr_) +{ + if (clr_ == CLR_TRANSPARENT) + pBrush_->CreateStockObject(NULL_BRUSH); + else + pBrush_->CreateSolidBrush(clr_); +} + +void CTraceCtrl::UpdateDrawingTools() +{ + DestroyDrawingTools(); + CreateDrawingTools(); +} + +void CTraceCtrl::DestroyDrawingTools() +{ + // clear old objects + for (int _i = 0; _i < c_nNUMOF_PENS; _i++) + m_pens[_i].DeleteObject(); + + m_brushBackground.DeleteObject(); + m_fontMark.DeleteObject(); +} + +void CTraceCtrl::CreateDrawingTools() +{ + // calculate m_nCharHeight + TEXTMETRIC _tm; + CWindowDC dc(this); + GetTextMetrics(dc,&_tm); + m_nCharHeight = abs(_tm.tmAscent); + + for (int _i = 0; _i < c_nNUMOF_PENS; _i++) + { + if (_i == PEN_GRID) + continue; // skip to create pen for grid, we will create it later. + + CreatePen(m_pens + _i, m_clrPens[_i]); + } + + // create grid pen + LOGBRUSH _lb; + _lb.lbColor = m_clrPens[PEN_GRID]; + _lb.lbHatch = 0; + _lb.lbStyle = BS_SOLID; + m_pens[PEN_GRID].CreatePen(PS_COSMETIC | PS_ALTERNATE, 1, &_lb); + + CreateBrush(&m_brushBackground, m_clrTrackBkFrom); + m_fontMark.CreatePointFont(120, _T("SYSTEM")); + + // in order to clear the track bitmap in the playbck DC + m_dc.m_nNextPoint = 0; +} + +BOOL CTraceCtrl::PreTranslateMessage(MSG* pMsg_) +{ + if (m_ToolTip.m_hWnd && pMsg_->hwnd == m_hWnd) + { + switch(pMsg_->message) + { + case WM_LBUTTONDOWN: + case WM_MOUSEMOVE: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + m_ToolTip.RelayEvent(pMsg_); + break; + } + } + + if ((pMsg_->message == WM_KEYDOWN) + && (GetKeyState(VK_CONTROL) < 0) + && (pMsg_->wParam == VK_BACK)) + { + ShowNextSpeed(); + return TRUE; + } + + if((pMsg_->message == WM_KEYDOWN) + && (GetKeyState(VK_CONTROL) < 0)) + { + if(OnKeyCmd(pMsg_->wParam)) + return true; + } + + return FALSE; +} + +bool CTraceCtrl::OnKeyCmd(UINT nChar_) +{ + switch (nChar_) + { + case 'Z': + OnCommandRange(IDCMD_TRACECTRL_PROJ_ISOMETRIC_SW); + return true; + case 'X': + OnCommandRange(IDCMD_TRACECTRL_PROJ_BOTTOM); + return true; + case 'C': + OnCommandRange(IDCMD_TRACECTRL_PROJ_ISOMETRIC_SE); + return true; + case 'A': + OnCommandRange(IDCMD_TRACECTRL_PROJ_LEFT); + return true; + case 'S': + OnCommandRange(IDCMD_TRACECTRL_PROJ_FRONT); + return true; + case 'B': + OnCommandRange(IDCMD_TRACECTRL_PROJ_BACK); + return true; + case 'D': + OnCommandRange(IDCMD_TRACECTRL_PROJ_RIGHT); + return true; + case 'Q': + OnCommandRange(IDCMD_TRACECTRL_PROJ_ISOMETRIC_NW); + return true; + case 'W': + OnCommandRange(IDCMD_TRACECTRL_PROJ_TOP); + return true; + case 'E': + OnCommandRange(IDCMD_TRACECTRL_PROJ_ISOMETRIC_NE); + return true; + case 'F': + OnCommandRange(IDCMD_TRACECTRL_FITWINDOW); + return true; + case 'N': + OnCommandRange(IDCMD_TRACECTRL_CENTER); + return true; + case 'P': + OnCommandRange(IDCMD_TRACECTRL_CURRENT); + return true; + case 'T': + OnCommandRange(IDCMD_TRACECTRL_CLEARVIEW); + return true; + case 'L': + if(!m_dataprovider->IsLoadFile()) + return true; + + OnCommandRange(IDCMD_TRACECTRL_LOAD_TRACK); + return true; + case 'R': + if(!m_TrackRecordNode.IsOpen()) + return true; + + OnCommandRange(IDCMD_TRACECTRL_CLEAR_TRACK); + return true; + case 'H': + if(!m_bUpdateTrackUI) + return true; + + OnCommandRange(IDCMD_TRACECTRL_STOP_LOAD_TRACK); + return true; + case 'I': + OnCommandRange(IDCMD_TRACECTRL_ZOOMIN); + return true; + case 'O': + OnCommandRange(IDCMD_TRACECTRL_ZOOMOUT); + return true; + case 'V': + OnCommandRange(IDCMD_TRACECTRL_MOVE); + return true; + case 'M': + OnToolCustomize(); + return true; + } + + CPoint _pt(0, 0); + CPoint _pt0(0, 0); + POINTD _pt_lp, _pt0_lp; + + POINTD _ptCenter; + + switch (nChar_) + { + //case '1': + // SetSelectMode(CTrackRecorder::OR); + // break; + //case '2': + // SetSelectMode(CTrackRecorder::NOT); + // break; + //case '3': + // SetSelectMode(CTrackRecorder::XOR); + // break; + ////case 'M': + //// SetOperation(MOVE); + //// break; + ////case 'N': + //// SetOperation(SELECT); + //// break; + //case 0xBE: /* '>', '.' */ + //case VK_ADD: + //case 0xBB: + // ZoomOut(); + // break; + //case 0xBC: /* ' < ', ',' */ + //case VK_SUBTRACT: + //case 0xBD: + // ZoomIn(); + // break; + //case VK_RETURN: + // m_bReceiveArrowMsgs = true; + // if (m_hWnd) + // InvalidateRect(NULL); + // break; + //case VK_ESCAPE: + // m_bReceiveArrowMsgs = false; + // if (m_hWnd) + // InvalidateRect(NULL); + // break; + + case ' ': // space + switch (m_nOperation) + { + case ZOOMOUT: + SetOperation(ZOOMIN); + break; + case ZOOMIN: + SetOperation(MOVE); + break; + case MOVE: + SetOperation(ZOOMOUT); + break; + case SELECT: + SetOperation(MOVE); + break; + } + break; + // + case VK_LEFT: + _pt.x = c_nLINE_STEP; + _pt.y = 0; + goto _MOVE_TRACK; + case VK_UP: + _pt.x = 0; + _pt.y = c_nLINE_STEP; + goto _MOVE_TRACK; + case VK_RIGHT: + _pt.x = -1 * c_nLINE_STEP; + _pt.y = 0; + goto _MOVE_TRACK; + case VK_DOWN: + _pt.x = 0; + _pt.y = -1 * c_nLINE_STEP; + goto _MOVE_TRACK; + + default: + return false; // not a key command + } + + return true; + +_MOVE_TRACK: + m_dc.DPtoLP_SM(&_pt0, &_pt0_lp); + m_dc.DPtoLP_SM(&_pt, &_pt_lp); + OffsetLogicalRef(_pt_lp.x - _pt0_lp.x, _pt_lp.y - _pt0_lp.y); + if (m_hWnd) + InvalidateRect(NULL); + return true; +} + +bool CTraceCtrl::OnKeyCmd1(UINT nChar_) +{ + + CPoint _pt(0, 0); + CPoint _pt0(0, 0); + POINTD _pt_lp, _pt0_lp; + + POINTD _ptCenter; + + switch (nChar_) + { + case ' ': // space + switch (m_nOperation) + { + case ZOOMOUT: + SetOperation(ZOOMIN); + break; + case ZOOMIN: + SetOperation(MOVE); + break; + case MOVE: + SetOperation(ZOOMOUT); + break; + case SELECT: + SetOperation(MOVE); + break; + } + break; + // + case VK_LEFT: + _pt.x = c_nLINE_STEP; + _pt.y = 0; + goto _MOVE_TRACK; + case VK_UP: + _pt.x = 0; + _pt.y = c_nLINE_STEP; + goto _MOVE_TRACK; + case VK_RIGHT: + _pt.x = -1 * c_nLINE_STEP; + _pt.y = 0; + goto _MOVE_TRACK; + case VK_DOWN: + _pt.x = 0; + _pt.y = -1 * c_nLINE_STEP; + goto _MOVE_TRACK; + + default: + return false; // not a key command + } + + return true; + +_MOVE_TRACK: + m_dc.DPtoLP_SM(&_pt0, &_pt0_lp); + m_dc.DPtoLP_SM(&_pt, &_pt_lp); + OffsetLogicalRef(_pt_lp.x - _pt0_lp.x, _pt_lp.y - _pt0_lp.y); + if (m_hWnd) + InvalidateRect(NULL); + return true; +} + + +//0 left 1 up 2 right 3 down +void CTraceCtrl::MoveTrack(UINT id) +{ + CPoint _pt(0, 0); + CPoint _pt0(0, 0); + POINTD _pt_lp, _pt0_lp; + + switch(id) + { + case 0: + _pt.x = c_nLINE_STEP; + _pt.y = 0; + break; + case 1: + _pt.x = 0; + _pt.y = c_nLINE_STEP; + break; + case 2: + _pt.x = -1 * c_nLINE_STEP; + _pt.y = 0; + break; + case 3: + _pt.x = 0; + _pt.y = -1 * c_nLINE_STEP; + break; + default: + return; + } + + m_dc.DPtoLP_SM(&_pt0, &_pt0_lp); + m_dc.DPtoLP_SM(&_pt, &_pt_lp); + OffsetLogicalRef(_pt_lp.x - _pt0_lp.x, _pt_lp.y - _pt0_lp.y); + if (m_hWnd) + InvalidateRect(NULL); +} + +void CTraceCtrl::OnContextMenu(CWnd* pWnd, CPoint point) +{ + if (::IsMenu(m_contextMenu.m_hMenu)) + { + CRect _rc; + GetWindowRect(&_rc); + + if (!PtInRect(&_rc, point)) + point = _rc.CenterPoint(); + + // Display a popup menu as a floating popup menu in the + // client area of the window. + const UINT _c_nFlags = TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON; + + //update menuitem state + CCmdUI _ui; + _ui.m_pMenu = &m_contextMenu; + _ui.m_nIndexMax = m_contextMenu.GetMenuItemCount(); + for (_ui.m_nIndex = 0; _ui.m_nIndex < _ui.m_nIndexMax; _ui.m_nIndex++) + { + _ui.m_nID = m_contextMenu.GetMenuItemID(_ui.m_nIndex); + if (_ui.m_nID == 0) + continue; + _ui.DoUpdate(this, TRUE); + } + + //owner is this trace control + //m_contextMenu.TrackPopupMenu(_c_nFlags, point.x, point.y, GetParentFrame()); + m_contextMenu.TrackPopupMenu(_c_nFlags, point.x, point.y, this); + } +} + +bool CTraceCtrl::OnSysKeyCmd(UINT nChar_) +{ + if (m_b2DMode) + return false; + + POINTD _pt = GetWorkpieceCenterPoint(); + switch (nChar_) + { + case VK_LEFT: + RotateZ(-10 * c_nPIE / 180); + break; + case VK_UP: + RotateX(-10 * c_nPIE / 180); + break; + case VK_RIGHT: + RotateZ(10 * c_nPIE / 180); + break; + case VK_DOWN: + RotateX(10 * c_nPIE / 180); + break; + case VK_PRIOR: + RotateY(10 * c_nPIE / 180); + break; + case VK_NEXT: + RotateY(-10 * c_nPIE / 180); + break; + + default: + return false; + } + + CenterWorkpiece(&_pt); + if (m_hWnd) + { + // if the track is empty and the current point is zero. CenterWorkpiece() + // function does not set m_dc.m_nNextPoint to zero. So we set it now. + // + // clear the track bitmap in the playbck DC + m_dc.m_nNextPoint = 0; + InvalidateRect(NULL); + } + return true; +} + +void CTraceCtrl::DrawRuler(CSimuDCEx* pDC_) +{ + pDC_->GetAreaShowXYZValue(true); + static const CRect _s_rcTest(0, 0, 40, 40); + static const double _s_scale[] = { + 1, 2, 5, + 10, 20, 50, + 100, 200, 500, + 1000, 2000, 5000, + 10000, 20000, 50000, + 100000, 200000, 500000, }; + + if (pDC_->GetAreaXYZ()->IsRectEmpty()) + return; + + int _i; + TCHAR _szBuffer[120]; + RECTD _rcTest; + double _temp, _sub, _end; + int _temp2; + RECTD _rcArea; + CRect _rcRuler(c_RULE_DIP.cx, c_RULE_DIP.cy, c_nDIMRULER - 1, c_nDIMRULER); + int _scale_height = abs(_rcRuler.Height()) / 4; + + // Note: + // Because this function needs to convert the CSimuDCEx mapping mode to workpiece + // coor from its machining coor, it uses a local CSimuDCEx in order to isolate + // the change. + CSimuDCEx _dc; + _dc.CopyAttributes(pDC_); + + pDC_->SelectStockObject(ANSI_VAR_FONT); + pDC_->SetBkMode(TRANSPARENT); + // the text color will be set later + + // convert map mode to workpiece coor. from machining coor. + double _offset[3]; + + AXDOUBLE_KERNEL _org = GetWorkcoorOrg(); + _offset[0] = _org[m_nX]; + _offset[1] = _org[m_nY]; + _offset[2] = _org[m_nZ]; + + + static NCNODEEX::POINT3D _s_vX(1, 0, 0), _s_vY(0, 1, 0), _s_vZ(0, 0, 1); + POINTD _v[3]; + _v[0] = CubicTransform(&_s_vX); + _v[1] = CubicTransform(&_s_vY); + _v[2] = CubicTransform(&_s_vZ); + + bool _valid_x_ruler = false; + bool _valid_y_ruler = false; + double _sign_x = 1; + double _sign_y = 1; + for (_i = 0; _i < 3; _i++) + if (fabs(fabs(_v[_i].x) - 1) < c_nFLOAT_TOLERANCE) + { + pDC_->OffsetLogicalRef(-1 * _offset[_i] * _v[_i].x, 0); + _sign_x = _v[_i].x; + _valid_x_ruler = true; + break; + } + for (_i = 0; _i < 3; _i++) + if (fabs(fabs(_v[_i].y) - 1) < c_nFLOAT_TOLERANCE) + { + pDC_->OffsetLogicalRef(0, -1 * _offset[_i] * _v[_i].y); + _sign_y = _v[_i].y; + _valid_y_ruler = true; + break; + } + + pDC_->DPtoLP_SM(&_s_rcTest /* in DP */, &_rcTest); // to mm + double _scale = fabs(_rcTest.right - _rcTest.left); // to mm + for (_i = 0; _i < _countof(_s_scale); _i++) + { + if (_scale < _s_scale[_i]) + { + _scale = _s_scale[_i]; // to logic coor., i.e. in mm again + break; + } + } + if (_i >= _countof(_s_scale)) + { + ASSERT(FALSE); // out of range + return; + } + CRect _rc(pDC_->GetAreaXYZ()); + _rc.InflateRect(1, 1, 1, 1); + pDC_->DPtoLP_SM(&_rc, &_rcArea); + if (_rcArea.bottom > _rcArea.top) + { + double _t = _rcArea.bottom; + _rcArea.bottom = _rcArea.top; + _rcArea.top = _t; + } + if (_rcArea.left > _rcArea.right) + { + double _t = _rcArea.left; + _rcArea.left = _rcArea.right; + _rcArea.right = _t; + } + + pDC_->SetTextColor(m_clrPens[PEN_RULER]); + pDC_->SelectObject(m_pens[PEN_RULER]); + + ///////////////////// + // first, draw X-ruler + _temp = int(_rcArea.left / _scale) * _scale; + if (_rcArea.left < 0) + _temp -= _scale; + _end = _rcArea.right + _scale; + while (_temp < _end) + { + if ((_temp >= _rcArea.left) &&(_temp < _rcArea.right)) + { + _temp2 = pDC_->LPtoDPx_SM(_temp); + pDC_->MoveTo(_temp2, _rcRuler.top); + pDC_->LineTo(_temp2, _rcRuler.bottom); + + if (_valid_x_ruler && m_bDrawGrid) + { + pDC_->SelectObject(m_pens[PEN_GRID]); + pDC_->LineTo(_temp2, _rc.bottom); + pDC_->SelectObject(m_pens[PEN_RULER]); + } + + if (_valid_x_ruler) + { + _itot_s(_round(_temp * _sign_x), _szBuffer, _countof(_szBuffer), 10); + pDC_->TextOut(_temp2 + 1, _rcRuler.top, _szBuffer, _tcslen(_szBuffer)); + } + } + + // draw sub-scale + _sub = _temp; + _temp += _scale; + _i = 0; + while (_sub < _temp) + { + if ((_sub >= _rcArea.left) && (_sub < _rcArea.right)) + { + _temp2 = pDC_->LPtoDPx_SM(_sub); + if (_i == 5) + pDC_->MoveTo(_temp2, _rcRuler.bottom - _scale_height*2); + else + pDC_->MoveTo(_temp2, _rcRuler.bottom - _scale_height); + pDC_->LineTo(_temp2, _rcRuler.bottom); + if ((_i == 5) && _valid_x_ruler && m_bDrawGrid) + { + pDC_->SelectObject(m_pens[PEN_GRID]); + pDC_->LineTo(_temp2, _rc.bottom); + pDC_->SelectObject(m_pens[PEN_RULER]); + } + } + _i ++; + _sub = _temp - _scale + _scale * _i / 10; + } + } + + ///////////////////// + // then draw Y-ruler + _temp = int(_rcArea.bottom / _scale) * _scale; + if (_rcArea.bottom < 0) + _temp -= _scale; + _end = _rcArea.top + _scale; + while (_temp < _end) + { + if ((_temp >= _rcArea.bottom) &&(_temp < _rcArea.top)) + { + _temp2 = pDC_->LPtoDPy_SM(_temp); + pDC_->MoveTo(_rcRuler.left, _temp2); + pDC_->LineTo(_rcRuler.right, _temp2); + + if (_valid_y_ruler && m_bDrawGrid) + { + pDC_->SelectObject(m_pens[PEN_GRID]); + pDC_->LineTo(_rc.right, _temp2); + pDC_->SelectObject(m_pens[PEN_RULER]); + } + + if (_valid_y_ruler) + { + _itot_s(_round(_temp * _sign_y), _szBuffer, _countof(_szBuffer), 10); + TCHAR* _pch = (TCHAR*)_szBuffer; + while (*_pch) + { + pDC_->TextOut(_rcRuler.left, _temp2, _pch, 1); + _pch++; + _temp2 += m_nCharHeight; + } + } + } + + // draw sub-scale + _sub = _temp; + _temp += _scale; + _i = 0; + while (_sub < _temp) + { + if ((_sub >= _rcArea.bottom) &&(_sub < _rcArea.top)) + { + _temp2 = pDC_->LPtoDPy_SM(_sub); + if (_i == 5) + pDC_->MoveTo(_rcRuler.right - _scale_height*2, _temp2); + else + pDC_->MoveTo(_rcRuler.right - _scale_height, _temp2); + pDC_->LineTo(_rcRuler.right, _temp2); + + if ((_i == 5) && _valid_y_ruler && m_bDrawGrid) + { + pDC_->SelectObject(m_pens[PEN_GRID]); + pDC_->LineTo(_rc.right, _temp2); + pDC_->SelectObject(m_pens[PEN_RULER]); + } + } + _i ++; + _sub = _temp - _scale + _scale * _i / 10; + } + } + + // restore attributes + pDC_->CopyAttributes(&_dc); + + return; +} + +void CTraceCtrl::DrawDecorators() +{ + DrawMarks(&m_dc); + DrawCoor(&m_dc); + DrawCurrentCoor(&m_dc); + + NCNODEEX::POINT3D _lp((NCNODEEX::REAL)m_ptLastPoint.x, + (NCNODEEX::REAL)m_ptLastPoint.y, + (NCNODEEX::REAL)m_ptLastPoint.z); + DrawCrosses(&m_dc, &_lp); + + const CRect* _prcArea = m_dc.GetAreaXYZ(); + + if (!_prcArea->IsRectEmpty()) + { + m_dc.SelectStockObject(ANSI_VAR_FONT); + m_dc.SetTextColor(m_clrPens[PEN_RULER]); + m_dc.SetBkMode(TRANSPARENT); + + int _mem_used = m_TrackRecord.GetMemorySize(); + int _mem_max = m_TrackRecord.GetMaxMemorySize(); + if (m_TrackRecordNode.IsOpen()) + { + _mem_used += m_TrackRecordNode.GetMemorySize(); + _mem_max += m_TrackRecordNode.GetMaxMemorySize(); + } + + TCHAR _szBuffer[256]; + TCHAR _szTempString[256]={0}; + TCHAR _szTempString1[256]={0}; + + GetString(L"s_csTRACKRECORD_INFO",_szTempString, _countof(_szTempString), s_csTRACKRECORD_INFO); + GetString(L"s_csTRACKRECORD_AUTOCLR",_szTempString1, _countof(_szTempString), s_csTRACKRECORD_AUTOCLR); + _sntprintf_s(_szBuffer, _countof(_szBuffer),_szTempString, + _mem_used / (1024 * 1024), + _mem_max / (1024 * 1024), + (m_TrackRecord.IsPageFault() || m_TrackRecordNode.IsPageFault())? _szTempString1 : L""); + + m_dc.TextOut(_prcArea->left + 2, _prcArea->bottom + 2, _szBuffer, _tcslen(_szBuffer)); + } + + CRect _rect; + GetClientRect(&_rect); + DrawBorder(&m_dc, _rect, m_clrBorder, (bf_t)m_nBorderFormat); + + if (GetFocus() == this) + { + CRect _rc; + if (m_bReceiveArrowMsgs) + _rc = _prcArea; + else + GetClientRect(&_rc); + + // DrawFocusFrame(&m_dc, &_rc); // add yuewenxue 注释掉当焦点在控件上时的边框 + } + + return; +} + +void CTraceCtrl::DrawCoor(CSimuDCEx* pDC_) +{ + //static LPCTSTR _s_pszAxis[] = + //{ + // _T("X"), _T("Y"), _T("Z"), + //}; + + const CRect* _pRect = pDC_->GetAreaXYZ(); + if ((_pRect->Width() < 100) || (_pRect->Height() < 100)) + return; + + int _numof = c_nNUMOF_AXIS; + if(m_nAxesNumber < c_nNUMOF_AXIS) + _numof = m_nAxesNumber; + for (int _axis = 0; _axis < _numof; _axis++) + { + if (m_matrixTrans[_axis][1] > c_nFLOAT_TOLERANCE) + { + pDC_->SelectObject(m_pens[PEN_COORDARKEN]); + pDC_->SetTextColor(m_clrPens[PEN_COORDARKEN]); + } + else + { + pDC_->SelectObject(m_pens[PEN_COOR]); + pDC_->SetTextColor(m_clrPens[PEN_COOR]); + } + + pDC_->MoveTo(_pRect->left + 50, _pRect->bottom - 50); + pDC_->LineTo(int(_pRect->left + 50 + m_matrixTrans[_axis][0] * 25), + int(_pRect->bottom - 50 - m_matrixTrans[_axis][2] * 25)); + pDC_->TextOut(int(_pRect->left + 50 + m_matrixTrans[_axis][0] * 30), + int(_pRect->bottom - 50 - m_matrixTrans[_axis][2] * 30), s_szAxisName[_axis]); + } + return; +} + +void CTraceCtrl::DrawCurrentCoor(CSimuDCEx* pDC_) +{ + if (m_bShowCoor == false) + { + return; + } + + const CRect* _pRect = pDC_->GetAreaXYZ(); + if ((_pRect->Width() < 100) || (_pRect->Height() < 100)) + return; + + AXDOUBLE_KERNEL _machcoor = GetCurPos(); + AXDOUBLE_KERNEL _cur; + if(!IsSimulating()) + { + AXDOUBLE_KERNEL _workcoor = _machcoor - GetWorkcoorOrg(); + _cur = _workcoor; + } + else + _cur = _machcoor; + static const int _nLineHeight = 20; + + CRect _rc; + _rc.left = _pRect->right - 170; + _rc.top = _pRect->top + 25; + _rc.right = _pRect->right - 15; + _rc.bottom = _rc.top + _nLineHeight * c_nNUMOF_AXIS; + + pDC_->BitBlt(_rc.left, _rc.top, _rc.Width(), _rc.Height(), + &m_dc.m_CacheDC, + _rc.left, _rc.top, + SRCCOPY); + + CFont _font; + _font.CreateFont(-13, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, _T("Consolas")); + CFont* _pOldFont = pDC_->SelectObject(&_font); + pDC_->SetTextColor(m_clrPens[PEN_COOR]); + + CString _strWC[c_nNUMOF_AXIS]; + int _numof = c_nNUMOF_AXIS; + if(m_nAxesNumber < c_nNUMOF_AXIS) + _numof = m_nAxesNumber; + + for (int _i = 0; _i < _numof; _i++) + { + CString _str; + if (m_nUnitSystem == 0) + _str.Format(_T("%.3f"), _cur[_i]); + else + _str.Format(_T("%.4f"), _cur[_i]); + + //-0.000->0.000 + NormalizeFloatString(_str); + _strWC[_i].Format(_T("%10s:%10s"), s_szAxisName[_i], _str); + pDC_->TextOut(_rc.left, _rc.top + _i * _nLineHeight, _strWC[_i]); + } + + pDC_->SelectObject(_pOldFont); +} + +void CTraceCtrl::DrawLineNoInfo(CSimuDCEx* pDC_) +{ + const CRect* _pRect = pDC_->GetAreaXYZ(); + if ((_pRect->Width() < 100) || (_pRect->Height() < 100)) + return; + + static const int _s_nLineHeight = 20; + + CRect _rect; + _rect.left = _pRect->right - 170; + _rect.top = _pRect->bottom + 2; + _rect.right = _pRect->right - 2; + _rect.bottom = _rect.top + _s_nLineHeight; + + pDC_->BitBlt(_rect.left, + _rect.top, + _rect.Width(), + _rect.Height(), + &m_dc.m_CacheDC, + _rect.left, + _rect.top, + SRCCOPY); + + CFont _font; + _font.CreateFont(-13, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, _T("Consolas")); + CFont* _pOldFont = pDC_->SelectObject(&_font); + if (m_clrTrackLineNum == CLR_TRANSPARENT) + { + pDC_->SetTextColor(0x00FFFFFF); + } + else + { + pDC_->SetTextColor(m_clrTrackLineNum); + } + + pDC_->SetBkMode(TRANSPARENT); + TCHAR _szBuffer[256]={0}; + TCHAR _szTempString[256]={0}; + if (m_HitField.from != -1) + { + NCNODEEX* _pBase = m_TrackRecord.GetBase(); + if (_pBase[m_HitField.from + 1].nFilePos != EOF) + { + if (m_bIsShowLineNumber) + { + GetString(L"s_csHITTRACK_LINENO", _szTempString, _countof(_szTempString), s_csHITTRACK_LINENO); + NCNODEEX& _Node = _pBase[m_HitField.from + 1]; + + if (_Node.nFileType == ENG) + _tcscat_s(_szTempString, _T("-%u")); + + _sntprintf_s(_szBuffer, _countof(_szBuffer), _szTempString, _Node.nLineOrID, _Node.nOffset); + } + } + } + + m_dc.TextOut(_rect.left, _rect.top, _szBuffer, _tcslen(_szBuffer)); + pDC_->SelectObject(_pOldFont); +} + +void CTraceCtrl::EraseCrosses(CSimuDCEx* pDC_) +{ + if (IsValidNcnodeexReal(m_ptCross.x)) + _DrawCrosses(pDC_, &m_ptCross); +} + +void CTraceCtrl::DrawCrosses(CSimuDCEx* pDC_, const NCNODEEX::POINT3D* pPos_) +{ + if (pDC_->GetAreaXYZ()->IsRectEmpty()) + return; + + m_ptCross = *pPos_; + _DrawCrosses(pDC_, pPos_); +} + +void CTraceCtrl::DrawMarks(CSimuDCEx* pDC_) +{ + const CRect* _pRect = pDC_->GetAreaXYZ(); + if ((_pRect->Width() < 100) ||(_pRect->Height() < 100)) + return; + + TCHAR _szTempstring[256]={0}; + CString _str; + GetString(L"s_csMARK_SIMU",_szTempstring, _countof(_szTempstring), s_csMARK_SIMU); + if (IsSimulating()) + _str += _szTempstring; + + switch (m_nProjectMode) + { + case PROJ_ISOMETRIC_SE: + GetString(L"s_csTRACECTRL_VIEW_SE",_szTempstring, _countof(_szTempstring), s_csTRACECTRL_VIEW_SE); + _str+=_szTempstring; + break; + case PROJ_ISOMETRIC_NW: + GetString(L"s_csTRACECTRL_VIEW_NW",_szTempstring, _countof(_szTempstring), s_csTRACECTRL_VIEW_NW); + _str+=_szTempstring; + break; + case PROJ_ISOMETRIC_NE: + GetString(L"s_csTRACECTRL_VIEW_NE",_szTempstring, _countof(_szTempstring), s_csTRACECTRL_VIEW_NE); + _str+=_szTempstring; + break; + case PROJ_ISOMETRIC_SW: + GetString(L"s_csTRACECTRL_VIEW_SW",_szTempstring, _countof(_szTempstring), s_csTRACECTRL_VIEW_SW); + _str+=_szTempstring; + break; + case PROJ_LEFT: + GetString(L"s_csTRACECTRL_VIEW_LEFT",_szTempstring, _countof(_szTempstring), s_csTRACECTRL_VIEW_LEFT); + _str+=_szTempstring; + break; + case PROJ_TOP: + GetString(L"s_csTRACECTRL_VIEW_TOP",_szTempstring, _countof(_szTempstring), s_csTRACECTRL_VIEW_TOP); + _str+=_szTempstring; + break; + case PROJ_RIGHT: + GetString(L"s_csTRACECTRL_VIEW_RIGHT",_szTempstring,_countof(_szTempstring), s_csTRACECTRL_VIEW_RIGHT); + _str+=_szTempstring; + break; + case PROJ_BOTTOM: + GetString(L"s_csTRACECTRL_VIEW_BOTTOM",_szTempstring, _countof(_szTempstring), s_csTRACECTRL_VIEW_BOTTOM); + _str+=_szTempstring; + break; + case PROJ_FRONT: + GetString(L"s_csTRACECTRL_VIEW_FRONT",_szTempstring, _countof(_szTempstring), s_csTRACECTRL_VIEW_FRONT); + _str+=_szTempstring; + break; + case PROJ_BACK: + GetString(L"s_csTRACECTRL_VIEW_BACK",_szTempstring, _countof(_szTempstring), s_csTRACECTRL_VIEW_BACK); + _str+=_szTempstring; + break; + } + + if (m_nShowSpeed != _SHOW_SPEED_NO + && !m_bSimulating) + { + int _i; + for (_i = 0; _i < c_nNUMOF_SHOWSPEEDPROMPT; _i++) + { + if (m_nShowSpeed == (_SHOW_SPEED_NO + _i)) + break; + } + if (_i >= c_nNUMOF_SHOWSPEEDPROMPT) + _i = 0; + + switch (_SHOW_SPEED_NO + _i) + { + case _SHOW_SPEED_NO: + _str += _T(""); + break; + case _SHOW_SPEED_SUM: + GetString(L"s_csMARK_SPEED_SUM",_szTempstring, _countof(_szTempstring), s_csMARK_SPEED_SUM); + _str += _szTempstring; + break; + case _SHOW_SPEED_X: + GetString(L"s_csMARK_SPEED_X",_szTempstring, _countof(_szTempstring), s_csMARK_SPEED_X); + _str += _szTempstring; + break; + case _SHOW_SPEED_Y: + GetString(L"s_csMARK_SPEED_Y",_szTempstring, _countof(_szTempstring), s_csMARK_SPEED_Y); + _str += _szTempstring; + break; + case _SHOW_SPEED_Z: + GetString(L"s_csMARK_SPEED_Z",_szTempstring, _countof(_szTempstring), s_csMARK_SPEED_Z); + _str += _szTempstring; + break; + case _SHOW_SPEED_DELTAX: + GetString(L"s_csMARK_SPEED_DELTAX",_szTempstring, _countof(_szTempstring), s_csMARK_SPEED_DELTAX); + _str += _szTempstring; + break; + case _SHOW_SPEED_DELTAY: + GetString(L"s_csMARK_SPEED_DELTAY",_szTempstring, _countof(_szTempstring), s_csMARK_SPEED_DELTAY); + _str += _szTempstring; + break; + case _SHOW_SPEED_DELTAZ: + GetString(L"s_csMARK_SPEED_DELTAZ",_szTempstring, _countof(_szTempstring), s_csMARK_SPEED_DELTAZ); + _str += _szTempstring; + break; + case _SHOW_DEBUG: + GetString(L"s_csMARK_DEBUG",_szTempstring, _countof(_szTempstring), s_csMARK_DEBUG); + _str += _szTempstring; + break; + default: + ASSERT(false); + } + } + + if (!_str.IsEmpty()) + { + pDC_->SelectObject(&m_fontMark); + pDC_->SetTextColor(m_clrPens[PEN_COOR]); + pDC_->TextOut(_pRect->left + 8, _pRect->top + 8, _str); + } + SetRectDC(); +} + +void CTraceCtrl::_DrawCrosses(CSimuDCEx* pDC_, const NCNODEEX::POINT3D* pPos_) +{ + //DrawCurrentCoor(pDC_); + pDC_->ClipAreaXYZ(); + POINTD _cur = CubicTransform(pPos_); + pDC_->MoveTo_LP(_cur); + pDC_->DrawCross(); + pDC_->ClipNull(); + return; +} + +void CTraceCtrl::FillBackground(CSimuDCEx* pDC_, LPCRECT prc_) +{ + if (!m_bGradientFill) + { + pDC_->FillRect(prc_, &m_brushBackground); + } + else + { + TRIVERTEX _vert[3]; + GRADIENT_RECT _grect; + _vert[0].x = prc_->left; + _vert[0].y = prc_->top; + _vert[0].Red = ((WORD)GetRValue(m_clrTrackBkFrom)) << 8; + _vert[0].Green = ((WORD)GetGValue(m_clrTrackBkFrom)) << 8; + _vert[0].Blue = ((WORD)GetBValue(m_clrTrackBkFrom)) << 8; + _vert[0].Alpha = 0x0000; + + _vert[1].x = prc_->right; + _vert[1].y = prc_->bottom; + _vert[1].Red = ((WORD)GetRValue(m_clrTrackBkTo)) << 8; + _vert[1].Green = ((WORD)GetGValue(m_clrTrackBkTo)) << 8; + _vert[1].Blue = ((WORD)GetBValue(m_clrTrackBkTo)) << 8; + _vert[1].Alpha = 0x0000; + + _vert[2].Red = ((WORD)GetRValue(m_clrTrackLineNum)) << 8; + _vert[2].Green = ((WORD)GetGValue(m_clrTrackLineNum)) << 8; + _vert[2].Blue = ((WORD)GetBValue(m_clrTrackLineNum)) << 8; + _vert[2].Alpha = 0x0000; + + _grect.UpperLeft = 0; + _grect.LowerRight = 1; + ::GradientFill(pDC_->m_hDC, _vert, 2, &_grect, 1, GRADIENT_FILL_RECT_V); + } + return; +} + +void CTraceCtrl::DrawTrack(CSimuDCEx* pDC_) +{ + SIZE _size = m_dc.GetDimension(); + CRect _rect(0, 0, _size.cx, _size.cy); + if (_rect.IsRectEmpty()) + return; + + if (m_dc.m_nNextPoint == 0) // no cached track picture + Playback(); + + pDC_->BitBlt(0, 0, _rect.right, _rect.bottom, + &m_dc.m_CacheDC, + 0, 0, + SRCCOPY); + + int _last_permanent = m_TrackRecord.GetSize() - 1; + // This is the index of the last permanent point. + + // draw the last line, which is un-permanent line. + if ((_last_permanent > 0) && (int(m_dc.m_nNextPoint) == _last_permanent)) + { + NCNODEEX* _pBase = m_TrackRecord.GetBase(); + NCNODEEX* _prec; + POINTD _cur; + + // set clip rectangle + pDC_->ClipAreaXYZ(); + _prec = _pBase + m_dc.m_nNextPoint - 1; + _cur = CubicTransform(&_prec->pt3D); + pDC_->MoveTo_LP(_cur); + _prec->pt2D = pDC_->m_ptLastDP; + + _prec++; + + if (_prec->bSelected) + pDC_->SelectObject(m_pens[PEN_SELECTED]); + else + pDC_->SelectObject(m_pens[_prec->nGType]); + + _cur = CubicTransform(&_prec->pt3D); + pDC_->LineTo_LP(_cur); + _prec->pt2D = pDC_->m_ptLastDP; + pDC_->ClipNull(); + } + return; +} + +void CTraceCtrl::Playback() +{ + // rect for the entire area + SIZE _size = m_dc.GetDimension(); + CRect _rect(0, 0, _size.cx, _size.cy); + if (_rect.IsRectEmpty()) + return; + + // because this function is driven by timer, we set a re-enter guard again. + // First, switch the output DC to the memory DC + m_dc.OutputToMemory(); + + if (m_dc.m_nNextPoint == 0) // case needs to draw the whole track + { + // draw ruler and frame of the track-area + m_dc.ClipNull(); + m_dc.FillSolidRect(&_rect, m_clrBackground); + + // draw background + FillBackground(&m_dc, m_dc.GetAreaXYZ()); + + DrawRuler(&m_dc); + + CRect _rc3dRect(m_dc.GetAreaXYZ()); + _rc3dRect.InflateRect(1, 1, 1, 1); + m_dc.Draw3dRect(&_rc3dRect, m_clrShadow, m_clrHilit); + + m_dc.ClipAreaXYZ(); + if (m_bDrawWorkAreaFrame) + { + const static int _s_cBorderStart[cNUMOF_BORDER] = + {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3}; + const static int _s_cBorderEnd[cNUMOF_BORDER] = + {1, 3, 0, 2, 5, 7, 4, 6, 4, 5, 6, 7}; + POINTD _vertex[8]; + int _i; + for (_i = 0; _i < cNUMOF_VERTEX; _i++) + _vertex[_i] = CubicTransform(m_WorkAreaVertex + _i); + + // calculate the invisible vertex + int _x = m_matrixTrans[0][1] > 0 ? 2 : 0; + int _y = m_matrixTrans[1][1] > 0 ? 1 : 0; + int _z = m_matrixTrans[2][1] > 0 ? 4 : 0; + int _invisible_vertex = _x + _y + _z; + + // first, draw the invisible borders + m_dc.SelectObject(&m_pens[PEN_COORDARKEN]); + for (_i = 0; _i < cNUMOF_BORDER; _i++) + { + int _sv = _s_cBorderStart[_i]; + int _ev = _s_cBorderEnd[_i]; + if ((_sv == _invisible_vertex) ||(_ev == _invisible_vertex)) + { + m_dc.MoveTo_LP(_vertex[_sv]); + m_dc.LineTo_LP(_vertex[_ev]); + } + } + // then, draw the invisible borders + m_dc.SelectObject(&m_pens[PEN_COOR]); + for (_i = 0; _i < cNUMOF_BORDER; _i++) + { + int _sv = _s_cBorderStart[_i]; + int _ev = _s_cBorderEnd[_i]; + if ((_sv != _invisible_vertex) &&(_ev != _invisible_vertex)) + { + m_dc.MoveTo_LP(_vertex[_sv]); + m_dc.LineTo_LP(_vertex[_ev]); + } + } + }// end draw the frame of WorkArea + + // draw the background track if need + if (m_TrackRecordNode.IsOpen() && !m_TrackRecordNode.IsEmpty()) + { + NCNODEEX* _pBase = m_TrackRecordNode.GetBase(); + NCNODEEX* _pMax = _pBase + m_TrackRecordNode.GetSize(); + if (!m_dataprovider->TrackIsIdle()) + _pMax--; + + //AXDOUBLE_KERNEL _org = GetWorkcoorOrg(); + //NCNODEEX::REAL _org_x = (NCNODEEX::REAL)_org[m_nX]; + //NCNODEEX::REAL _org_y = (NCNODEEX::REAL)_org[m_nY]; + //NCNODEEX::REAL _org_z = (NCNODEEX::REAL)_org[m_nZ]; + NCNODEEX::REAL _org_x = 0; + NCNODEEX::REAL _org_y = 0; + NCNODEEX::REAL _org_z = 0; + + NCNODEEX::POINT3D _pt; + _pt.x = _pBase->pt3D.x + _org_x; + _pt.y = _pBase->pt3D.y + _org_y; + _pt.z = _pBase->pt3D.z + _org_z; + + POINTD _cur = CubicTransform(&_pt); + m_dc.MoveTo_LP(_cur); + _pBase->pt2D = m_dc.m_ptLastDP; + m_dc.SetBackupLineType(PEN_G00_SIMU); + m_dc.BeginPolylineTo(); + + for (NCNODEEX* _prec = _pBase + 1; _prec < _pMax; _prec++) + { + int _line_type = _prec->nGType; + if(_line_type & FLG_G02) + _line_type = 2; + else if(_line_type & FLG_G03) + _line_type = 3; + else if(_line_type &FLG_G01) + _line_type=1; + else if(_line_type & FLG_GXX) + _line_type = 0; + + if (m_dc.m_nLineType != PEN_G00_SIMU + _line_type) + { + // before changing pen, flush the buffer + m_dc.FlushPolylineToBuffer(); + m_dc.SetBackupLineType(PEN_G00_SIMU + _line_type); + } + + _pt.x = _prec->pt3D.x + _org_x; + _pt.y = _prec->pt3D.y + _org_y; + _pt.z = _prec->pt3D.z + _org_z; + + POINTD _curt = CubicTransform(&_pt); + m_dc.PolylineTo_LP(_curt); + _prec->pt2D = m_dc.m_ptLastDP; + } + m_dc.EndPolylineTo(); + + // resort m_dc + m_dc.SetBackupLineType(PEN_G00); + + } + + // set the current point of the backup DC in the m_dc + if (m_TrackRecord.IsOpen()) + { + NCNODEEX* _pBase = m_TrackRecord.GetBase(); + POINTD _cur = CubicTransform(&_pBase->pt3D); + m_dc.MoveTo_LP(_cur); + _pBase->pt2D = m_dc.m_ptLastDP; + + m_dc.m_nNextPoint = 1; + m_dc.SetBackupLineType(PEN_G00); + } + } // end background setting and drawing at the first time + + if (m_TrackRecord.IsOpen()) + { + int _nLastPoint = m_TrackRecord.GetSize() - 1; + // This is the index of the last permanent point. This function only paints the + // permanent lines, which are lines between the permanent points. The last line, + // which is a un-permanent line, is painted by CTraceCtrl::DrawTrack(). + + if (int(m_dc.m_nNextPoint) < _nLastPoint) + { + __int64 _tick_start = NcGetTickCount(); + int _records = 0; + NCNODEEX* _pBase = m_TrackRecord.GetBase(); + NCNODEEX* _pMax = _pBase + _nLastPoint; + + m_dc.BeginPolylineTo(); + for (NCNODEEX* _prec = _pBase + m_dc.m_nNextPoint; _prec < _pMax; _prec++) + { + int _line_type = _prec->nGType; + if (_prec->bSelected) + _line_type = -1; + if (m_dc.m_nLineType != _line_type) + { + // before changing pen, flush the buffer + m_dc.FlushPolylineToBuffer(); + m_dc.SetBackupLineType(_line_type); + } + POINTD _cur = CubicTransform(&_prec->pt3D); + m_dc.PolylineTo_LP(_cur); + _prec->pt2D = m_dc.m_ptLastDP; + + // check escaped time + if (!(++_records % 1024)) + { + __int64 _tick_end = NcGetTickCount(); + if (_tick_end - _tick_start > 50) + { + // too lang time at this time, quit this function first, and the function + // ContinuePlayback(), which is called periodly by timer, will call me again. + break; + } + } + } + m_dc.EndPolylineTo(); + m_dc.m_nNextPoint += _records; + } + } + + // switch back the output DC + m_dc.OutputToScreen(); + return; +} + +void CTraceCtrl::ContinuePlayback() +{ + // because this function is driven by timer, we set a re-enter guard again. + if (m_bAlreadyInContinuePlayback) + { + ASSERT(false); + return; + } + CReentryGuard _guard(m_bAlreadyInContinuePlayback); + + int _size = m_TrackRecord.GetSize(); + int _nNextPoint = m_dc.m_nNextPoint; // backup before change + + if ((_nNextPoint >= _size - 1) || + m_dc.GetAreaXYZ()->IsRectEmpty()) + { + // we come here when track-drawing finished or the track-record + // is no changes since the last call. + return; + } + + Playback(); // this call will update m_dc.m_nNextPoint + + if (_nNextPoint <= m_nNumofRecordToPaint - 1) + { + DrawTrack(&m_dc); + + // this is the last time. + if (int(m_dc.m_nNextPoint) >= m_nNumofRecordToPaint - 1) + DrawDecorators(); + } + return; +} + +void CTraceCtrl::DrawAreaXYZ(const NCNODEEX::POINT3D* pPos_, NCNODEEX* pDelta_) +{ + ASSERT(pPos_ && pDelta_); + + if (m_dc.GetAreaXYZ()->IsRectEmpty()) + return; + + m_dc.ClipAreaXYZ(); + POINTD _cur = CubicTransform(pPos_); + m_dc.MoveTo_LP(_cur); + _cur = CubicTransform(&pDelta_->pt3D); + m_dc.LineTo_LP(_cur); + m_dc.ClipNull(); + return; +} + +//画速度波形图 +void CTraceCtrl::ShowCmdType(CMD_HEADER* pCmd_) +{ + if(m_nShowSpeed == _SHOW_SPEED_NO + || (NULL == pCmd_) + || !(pCmd_->nCmd == ID_CMDDN_MOTION ) + || m_bSimulating +/* ||pCmd_->nCmd == ID_CMDAP_FP_G + ||pCmd_->nCmd == ID_CMDAP_STRING*/ + ) + { + return ; + } + + CMD_NODE_MOTION* nodeMotion = NULL; + + WORD _gtype = 0; + if(pCmd_->nCmd == ID_CMDDN_MOTION) + { + nodeMotion = (CMD_NODE_MOTION*)pCmd_; + _gtype = nodeMotion->nFlags & FLG_GXX; + if(nodeMotion->nFlags & FLG_G02) + _gtype = 2; + else if(nodeMotion->nFlags & FLG_G03) + _gtype = 3; + else if(nodeMotion->nFlags & FLG_G01) + _gtype = 1; + else + _gtype = 0; + } + + + int _default_cycle_time_in_us = int(this->GetDeviceT() * 1e6); + + if (m_nShowSpeed != _SHOW_DEBUG) + { + // clear background + if (++m_nCoorX > m_rcSpeed.right) + { + m_nCoorX = 0; + } + + m_dc.SelectStockObject(BLACK_PEN); + m_dc.MoveTo(m_nCoorX, m_rcSpeed.bottom); + m_dc.LineTo(m_nCoorX, m_rcSpeed.bottom - 100); + + // draw NCCMD_KERNEL type + if (pCmd_->nCmd == ID_CMDDN_MOTION) + { + if (_gtype > 3) + _gtype = 1; // default is G01 + m_dc.SelectObject(&m_pens[_gtype]); + } + else + { + m_dc.SelectObject(&m_pens[PEN_COOR]); + } + m_dc.SelectObject(&m_pens[_gtype]); + + m_dc.MoveTo(m_nCoorX, m_rcSpeed.bottom - 2); + m_dc.LineTo(m_nCoorX, m_rcSpeed.bottom - 4); + } + + + //switch(pCmd_->nCmd) + //{ + //case ID_CMDAP_FP_G: + // { + // m_dc.SelectStockObject(WHITE_PEN); + // m_dc.MoveTo(m_nCoorX, m_rcSpeed.bottom - Y_BASE); + // m_dc.LineTo(m_nCoorX, m_rcSpeed.bottom - Y_VAL(50)); + // } + // break; + + //case ID_CMDDN_MOTION: + // { + + if (NULL == nodeMotion) + return; + + static AXDOUBLE_KERNEL _s_nxSpeedLast(0,0,0); + static double _s_lastTime = 0; + CMD_NODE_MOTION* lastMotion = (CMD_NODE_MOTION*)m_LastNccmd; + + AXDOUBLE_KERNEL _nxSpeed; + _nxSpeed[0] = (nodeMotion->nPoint.x - lastMotion->nPoint.x) * 1000000 / nodeMotion->nTime; + _nxSpeed[1] = (nodeMotion->nPoint.y - lastMotion->nPoint.y) * 1000000 / nodeMotion->nTime; + _nxSpeed[2] = (nodeMotion->nPoint.z - lastMotion->nPoint.z) * 1000000 / nodeMotion->nTime; + + int _nCoorY = m_rcSpeed.bottom - 40; + if (_SHOW_SPEED_SUM == m_nShowSpeed) + _nCoorY = m_rcSpeed.bottom - 18; + + int _nDelta = 0; + switch (m_nShowSpeed) + { + case _SHOW_SPEED_SUM: _nDelta = _round(_nxSpeed.GetLength()); break; + case _SHOW_SPEED_X: _nDelta = int(_nxSpeed[m_nX]); break; + case _SHOW_SPEED_Y: _nDelta = int(_nxSpeed[m_nY]); break; + case _SHOW_SPEED_Z: _nDelta = int(_nxSpeed[m_nZ]); break; + case _SHOW_SPEED_DELTAX: _nDelta = int((_nxSpeed[m_nX] - _s_nxSpeedLast[m_nX])*128/ (nodeMotion->nTime/_default_cycle_time_in_us)); break; + case _SHOW_SPEED_DELTAY: _nDelta = int((_nxSpeed[m_nY] - _s_nxSpeedLast[m_nY])*128/ (nodeMotion->nTime/_default_cycle_time_in_us)); break; + case _SHOW_SPEED_DELTAZ: _nDelta = int((_nxSpeed[m_nZ] - _s_nxSpeedLast[m_nZ])*128/ (nodeMotion->nTime/_default_cycle_time_in_us)); break; + case _SHOW_DEBUG: + case _SHOW_SPEED_NO: + default: + _nDelta = 0; + break; + } + + CPen* _ppenOld = NULL; + if ((nodeMotion->nTime < 10) || (lastMotion->nTime < 10)) + _ppenOld = m_dc.SelectObject(&m_pens[PEN_COOR]); + m_dc.MoveTo(m_nCoorX, _nCoorY); + m_dc.LineTo(m_nCoorX, _nCoorY - _nDelta); + if (_ppenOld) + m_dc.SelectObject(_ppenOld); + + memcpy(m_LastNccmd, nodeMotion, nodeMotion->nSize); + memcpy(&_s_nxSpeedLast,&_nxSpeed,sizeof(_nxSpeed)); + _s_lastTime = nodeMotion->nTime; + + // } + // break; + + //case ID_CMDAP_STRING: + // { + // if (m_nShowSpeed == _SHOW_DEBUG) + // { + // // clear background + // if (++m_nCoorX > m_rcSpeed.right) + // m_nCoorX = 0; + // m_dc.SelectStockObject(BLACK_PEN); + // m_dc.MoveTo(m_nCoorX, m_rcSpeed.bottom); + // m_dc.LineTo(m_nCoorX, m_rcSpeed.bottom - 100); + // + // // draw NCCMD_KERNEL type + // m_dc.SelectObject(&m_pens[PEN_COOR]); + // m_dc.MoveTo(m_nCoorX, m_rcSpeed.bottom - 2); + // m_dc.LineTo(m_nCoorX, m_rcSpeed.bottom - 4); + // + // m_dc.MoveTo(m_nCoorX, m_rcSpeed.bottom - Y_BASE); + // __int64 _v = pCmd_->nV64 / 1 - 0; + // m_dc.LineTo(m_nCoorX, m_rcSpeed.bottom - Y_VAL(int(_v))); + // } + // } + // break; + + //default: + // break; + //} + + return; +} + +/*********************************************************************** +读取NCCMD_KERNEL,绘制当前加工轨迹,并且把NCCMD_KERNEL记录到m_TrackRecord里 -曾超 +***********************************************************************/ +void CTraceCtrl::RecordNccmd(CMD_HEADER* pCmd_) +{ + ShowCmdType(pCmd_); + + switch (pCmd_->nCmd) + { + case ID_CMDDN_BEGIN: + { + CMDDN_BEGIN* _begin = (CMDDN_BEGIN*)pCmd_; + if(_begin->nMSN == 0) + { + m_nLastFP = EOF; + m_nLastGType = 0; + m_nLastLineNoOrID = 0; + m_nOffset = 0; + } + + m_bSimulating = m_dataprovider->IsSimulating(); + + if (m_bSimulating) + { + SetTimer(IDTIMER_SIMULATOR, 5, NULL); + } + } + break; + + case ID_CMDDN_END: + { + UpdateTrackWhileSimulating(true); + m_nLastFP = EOF; + m_nLastLineNoOrID = 0; + m_nOffset = 0; + KillTimer(IDTIMER_SIMULATOR); + }; + break; + + case ID_CMDAP_FP_G: + { + CMD_FP_G* _pFpg = (CMD_FP_G*)pCmd_; + m_nLastFP = _pFpg->nFP; + m_nLastLineNoOrID = _pFpg->nStatementCount; + m_nOffset = _pFpg->nOffset; + m_nFileType = _pFpg->nFileType; + } + break; + + case ID_CMDDN_MOTION: + { + CMD_NODE_MOTION* interMotion = (CMD_NODE_MOTION*)pCmd_; + WORD _gtype = interMotion->nFlags & FLG_GXX; + if(interMotion->nFlags & FLG_G02) + _gtype = 2; + else if(interMotion->nFlags & FLG_G03) + _gtype = 3; + else if(interMotion->nFlags &FLG_G01) + _gtype = 1; + else if(interMotion->nFlags & FLG_STARTPOINT) + _gtype = 29; + else + _gtype = 0; + + if (_gtype > CTraceCtrl::PEN_GOTHER && _gtype != CTraceCtrl::PEN_STARTPOINT) + _gtype = CTraceCtrl::PEN_GOTHER; + + NCNODEEX _rec; + _rec.bSelected = false; + _rec.nGType = (BYTE)_gtype; + _rec.pt3D.x = (float)interMotion->nPoint.x; + _rec.pt3D.y = (float)interMotion->nPoint.y; + _rec.pt3D.z = (float)interMotion->nPoint.z; + + _rec.nFilePos = m_nLastFP; + _rec.nLineOrID = m_nLastLineNoOrID; + _rec.nOffset = m_nOffset; + _rec.nFileType = m_nFileType; + _rec.pt2D.x = _rec.pt2D.y = -1; + + + bool _bHasPulse = interMotion->nPoint.x != 0 + || interMotion->nPoint.y != 0 + || interMotion->nPoint.z != 0; + if (_bHasPulse && !m_bSimulating) + { + m_dc.SelectObject(&m_pens[_gtype]); + //擦除前一加工点的轨迹,绘制当前加工点轨迹 -曾超 + NCNODEEX::POINT3D _lp((NCNODEEX::REAL)m_ptLastPoint.x, + (NCNODEEX::REAL)m_ptLastPoint.y, + (NCNODEEX::REAL)m_ptLastPoint.z); + DrawAreaXYZ(&_lp, &_rec); + + } + + if ((m_nLastGType == 0) && (_gtype != 0)) + UpdateTraceMachArea(); // update it before updating m_ptLastPoint. + // it means that m_ptLastPoint is start-point. + + m_ptLastPoint.x = interMotion->nPoint.x; + m_ptLastPoint.y = interMotion->nPoint.y; + m_ptLastPoint.z = interMotion->nPoint.z; + + UpdateTraceMotionArea(); + if (0 != _gtype) + UpdateTraceMachArea(); // update it after updating m_ptLastPoint. + // it means that m_ptLastPoint is end-point. + + m_nLastGType = _gtype; + + // append it to recorder + + if(interMotion->nFlags & FLG_STARTPOINT) + { + CommitRecord(&_rec, CTrackRecorder::UNPACK_ALWAYS); + } + else if (!(interMotion->nFlags & FLG_FIRST)) + { + if (_bHasPulse) + { + if((interMotion->nFlags & FLG_GXX) == 0) + { + CommitRecord(&_rec, CTrackRecorder::PACK_ALWAYS); + } + else if((interMotion->nFlags & FLG_G01)) + { + CommitRecord(&_rec, CTrackRecorder::PACK_ALWAYS); + } + else if((interMotion->nFlags & FLG_G02)) + { + CommitRecord(&_rec, CTrackRecorder::PACK_SMART); + } + else if((interMotion->nFlags & FLG_G03)) + { + CommitRecord(&_rec, CTrackRecorder::PACK_SMART); + } + else if((interMotion->nFlags & FLG_GXX) == 1) + { + CommitRecord(&_rec, CTrackRecorder::PACK_SMART); + } + else + { + ASSERT(false); + } + } + } + else + { + CommitRecord(&_rec, CTrackRecorder::UNPACK_ALWAYS); + } + } + break; + + case ID_CMDDN_DISTOFFSET: + { + ::CMDDN_DISTOFFSET* distOffset = (CMDDN_DISTOFFSET*)pCmd_; + + m_ptLastPoint.x += distOffset->nxDistOffset[0]*360.; + m_ptLastPoint.y += distOffset->nxDistOffset[1]*360.; + m_ptLastPoint.z += distOffset->nxDistOffset[2]*360.; + ASSERT(false); + } + break; + + default: + break; + } + + return; +} +/********************************************************************** +在NCCMD_KERNEL没有的时候,要用这个函数同步当前加工点轨迹.换句话说,在系统空闲, +状态的时候要通过这个函数同步系统的当前点 -曾超 +**********************************************************************/ +void CTraceCtrl::SynchronizeLastPoint() +{ + AXDOUBLE_KERNEL _nxCurPos = GetCurPos(); + + if ((fabs(m_ptLastPoint.x - _nxCurPos[m_nX]) > 10 * m_nPerPulseX) || + (fabs(m_ptLastPoint.y - _nxCurPos[m_nY]) > 10 * m_nPerPulseY) || + (fabs(m_ptLastPoint.z - _nxCurPos[m_nZ]) > 10 * m_nPerPulseZ)) + { + EraseCrosses(&m_dc); + + NCNODEEX _lastrec; + _lastrec.bSelected = false; + _lastrec.nGType = 0; + _lastrec.pt3D.x = (NCNODEEX::REAL)m_ptLastPoint.x; + _lastrec.pt3D.y = (NCNODEEX::REAL)m_ptLastPoint.y; + _lastrec.pt3D.z = (NCNODEEX::REAL)m_ptLastPoint.z; + _lastrec.nFilePos = m_nLastFP; + _lastrec.nLineOrID = m_nLastLineNoOrID; + _lastrec.nOffset = m_nOffset; + _lastrec.nFileType = m_nFileType; + _lastrec.pt2D.x = _lastrec.pt2D.y = -1; + + m_ptLastPoint.x = _nxCurPos[m_nX]; + m_ptLastPoint.y = _nxCurPos[m_nY]; + m_ptLastPoint.z = _nxCurPos[m_nZ]; + + NCNODEEX _rec; + _rec.bSelected = false; + _rec.nGType = 0; + _rec.pt3D.x = (NCNODEEX::REAL)_nxCurPos[m_nX]; + _rec.pt3D.y = (NCNODEEX::REAL)_nxCurPos[m_nY]; + _rec.pt3D.z = (NCNODEEX::REAL)_nxCurPos[m_nZ]; + _rec.nFilePos = m_nLastFP; + _rec.nLineOrID = m_nLastLineNoOrID; + _rec.pt2D.x = _rec.pt2D.y = -1; + //CommitRecord(&_rec, CTrackRecorder::UNPACK_ALWAYS); + + //m_dc.SelectObject(&m_pens[PEN_G00]); + //DrawAreaXYZ(&_lastrec.pt3D, &_rec); + UpdateTraceMotionArea(); + + NCNODEEX::POINT3D _lp((NCNODEEX::REAL)m_ptLastPoint.x, + (NCNODEEX::REAL)m_ptLastPoint.y, + (NCNODEEX::REAL)m_ptLastPoint.z); + DrawCrosses(&m_dc, &_lp); + DrawCurrentCoor(&m_dc); + } + return; +} + +// Description: +// This function provides a rapid way to draw the track if we are in +// simulation mode. +void CTraceCtrl::UpdateTrackWhileSimulating(bool bFinish_) +{ + if (IsSimulating()) + { + int _size = m_TrackRecord.GetSize(); + if (_size < 3) + return; + NCNODEEX* _pBase = m_TrackRecord.GetBase(); + NCNODEEX* _pN_2 = _pBase + _size - 2; + NCNODEEX* _pN_3 = _pBase + _size - 3; + + if (bFinish_) + { + _pN_2++; + _pN_3++; + } + + m_dc.SelectObject(&m_pens[_pN_2->nGType]); + DrawAreaXYZ(&_pN_3->pt3D, _pN_2); + } + return; +} + +void CTraceCtrl::CommitRecord(const NCNODEEX* pRec_, int flag_) +{ + // m_TrackRecord.Commit() returns true if packed, otherwise false. + // packing means that a new point is appended to the m_TrackRecord. + // + // At this case, we update the track if we are in simulation mode. + if (!m_TrackRecord.Commit(pRec_, flag_)) + UpdateTrackWhileSimulating(); + return; +} + +///////////////////////////////////////////////////////////////////////////// +// CTraceCtrl transforming + +void CTraceCtrl::SetZoomRatio(double ratio_) +{ + if (ratio_ < g_ratio[0]) + ratio_ = g_ratio[0]; + if (ratio_ > g_ratio[RATIO_COUNT - 1]) + ratio_ = g_ratio[RATIO_COUNT - 1]; + + if (m_dc.SetZoomRatio(ratio_)) // changed + { + SetOperation(m_nOperation); // update it + InvalidateRect(NULL); + } + return; +} + +double CTraceCtrl::GetFitZoomRatio() +{ + double _xp[2], _yp[2], _zp[2]; + + bool _bInit = false; + if (m_bIsFileTrackFirst) + { + + if (m_TrackRecordNode.IsOpen()) + { + //AXDOUBLE_KERNEL _org = GetWorkcoorOrg(); + //NCNODEEX::REAL _org_x = (NCNODEEX::REAL)_org[m_nX]; + //NCNODEEX::REAL _org_y = (NCNODEEX::REAL)_org[m_nY]; + //NCNODEEX::REAL _org_z = (NCNODEEX::REAL)_org[m_nZ]; + + NCNODEEX::REAL _org_x = 0.0; + NCNODEEX::REAL _org_y = 0.0; + NCNODEEX::REAL _org_z = 0.0; + + if (m_traceAreaUpdate.IsMachValid()) + { + _xp[0] = m_traceAreaUpdate.ptMachMax.x + _org_x; + _xp[1] = m_traceAreaUpdate.ptMachMin.x + _org_x; + _yp[0] = m_traceAreaUpdate.ptMachMax.y + _org_y; + _yp[1] = m_traceAreaUpdate.ptMachMin.y + _org_y; + _zp[0] = m_traceAreaUpdate.ptMachMax.z + _org_z; + _zp[1] = m_traceAreaUpdate.ptMachMin.z + _org_z; + _bInit = true; + } + else if (m_traceAreaUpdate.IsMotionValid()) + { + _xp[0] = m_traceAreaUpdate.ptMotionMax.x + _org_x; + _xp[1] = m_traceAreaUpdate.ptMotionMin.x + _org_x; + _yp[0] = m_traceAreaUpdate.ptMotionMax.y + _org_y; + _yp[1] = m_traceAreaUpdate.ptMotionMin.y + _org_y; + _zp[0] = m_traceAreaUpdate.ptMotionMax.z + _org_z; + _zp[1] = m_traceAreaUpdate.ptMotionMin.z + _org_z; + _bInit = true; + } + } + } + + if (!_bInit) + { + if (m_TraceArea.IsMachValid()) + { + _xp[0] = m_TraceArea.ptMachMax.x; + _xp[1] = m_TraceArea.ptMachMin.x; + _yp[0] = m_TraceArea.ptMachMax.y; + _yp[1] = m_TraceArea.ptMachMin.y; + _zp[0] = m_TraceArea.ptMachMax.z; + _zp[1] = m_TraceArea.ptMachMin.z; + } + else if (m_TraceArea.IsMotionValid()) + { + _xp[0] = m_TraceArea.ptMotionMax.x; + _xp[1] = m_TraceArea.ptMotionMin.x; + _yp[0] = m_TraceArea.ptMotionMax.y; + _yp[1] = m_TraceArea.ptMotionMin.y; + _zp[0] = m_TraceArea.ptMotionMax.z; + _zp[1] = m_TraceArea.ptMotionMin.z; + } + else + { + _xp[0] = m_WorkAreaMax.x; + _xp[1] = m_WorkAreaMin.x; + _yp[0] = m_WorkAreaMax.y; + _yp[1] = m_WorkAreaMin.y; + _zp[0] = m_WorkAreaMax.z; + _zp[1] = m_WorkAreaMin.z; + } + } + + CSimuDCEx _dc; + _dc.CopyAttributes(&m_dc); + _dc.SetZoomRatio(1.0); + + int _x_min = INT_MAX, _y_min = INT_MAX, _x_max = INT_MIN, _y_max = INT_MIN; + for (int _i = 0; _i < cNUMOF_VERTEX; _i++) + { + // get a vetex + NCNODEEX::POINT3D _pt( + (NCNODEEX::REAL)_xp[_i & 0x4 ? 1 : 0], + (NCNODEEX::REAL)_yp[_i & 0x2 ? 1 : 0], + (NCNODEEX::REAL)_zp[_i & 0x1 ? 1 : 0]); + + // convert it to 2D + POINTD _pt2D = CubicTransform(&_pt); + POINT _pt2D_dp; + _dc.LPtoDP_SM(&_pt2D, &_pt2D_dp); + + // get min. and max. + _x_min = min(_x_min, _pt2D_dp.x); + _x_max = max(_x_max, _pt2D_dp.x); + _y_min = min(_y_min, _pt2D_dp.y); + _y_max = max(_y_max, _pt2D_dp.y); + } + + const CRect* _pRect = m_dc.GetAreaXYZ(); + double _nRatio = g_ratio[RATIO_COUNT - 1]; // max ratio + _nRatio = min(_nRatio, (double)(_pRect->Width() - 10) /(_x_max - _x_min)); + _nRatio = min(_nRatio, (double)(_pRect->Height() - 10) /(_y_max - _y_min)); + return _nRatio * 0.8; // best fit is picture holds 80% of the window +} + +void CTraceCtrl::SetOperation(_operation_t operation_) +{ + switch (operation_) + { + case SELECT: + case MOVE: + // do nothing + break; + + case ZOOMIN: + case ZOOMOUT: + if (GetZoomRatio() >= g_ratio[RATIO_COUNT - 1]) + operation_ = ZOOMIN; + else if (GetZoomRatio() <= g_ratio[0]) + operation_ = ZOOMOUT; + break; + + // do nothing + break; + + default: + ASSERT(false); + return; + } + + m_nOperation = operation_; + UpdateCursor(); + return; +} + +void CTraceCtrl::SetSelectMode(CTrackRecorder::select_t operator_) +{ + switch (operator_) + { + case CTrackRecorder::NOT: + case CTrackRecorder::OR: + case CTrackRecorder::XOR: + m_nSelectMode = operator_; + break; + + case CTrackRecorder::NONE: + ASSERT(false); + return; + } + + UpdateCursor(); + return; +} + +bool CTraceCtrl::UpdateCursor() +{ + POINT _pt; + GetCursorPos(&_pt); + ScreenToClient(&_pt); + + if (m_dc.GetAreaXYZ()->PtInRect(_pt)) + { + switch (m_nOperation) + { + case ZOOMOUT: + ::SetCursor(m_hcurZoomout); + return true; + case ZOOMIN: + ::SetCursor(m_hcurZoomin); + return true; + case MOVE: + //::SetCursor(m_hcurMove); + ::SetCursor(m_hcurRelease); + return true; + case SELECT: + if (m_nSelectMode == CTrackRecorder::OR) + ::SetCursor(m_hcurSelectOr); + else if (m_nSelectMode == CTrackRecorder::NOT) + ::SetCursor(m_hcurSelectNot); + else if (m_nSelectMode == CTrackRecorder::XOR) + ::SetCursor(m_hcurSelectXor); + else + { + ASSERT(false); + return false; + } + return true; + default: + ASSERT(false); + return false; + } + } + return false; +} + +// center the workpiece +void CTraceCtrl::CenterWorkpiece(const POINTD* ppt_ /* = NULL */) +{ + double _nOffsetX = 0; + double _nOffsetY = 0; + + if (NULL == ppt_) + { + POINTD _ptL; + CPoint _pt0 = m_dc.GetAreaXYZ()->CenterPoint(); + m_dc.DPtoLP_SM(&_pt0, &_ptL); + + _nOffsetX = _ptL.x; + _nOffsetY = _ptL.y; + } + else + { + _nOffsetX = ppt_->x; + _nOffsetY = ppt_->y; + } + + POINTD _pt = GetWorkpieceCenterPoint(); + OffsetLogicalRef(_pt.x - _nOffsetX, _pt.y - _nOffsetY); + + if (m_hWnd) + InvalidateRect(NULL); +} + +// Center the current cutting pointer +void CTraceCtrl::CenterCursor() +{ + NCNODEEX::POINT3D _lp((NCNODEEX::REAL)m_ptLastPoint.x, + (NCNODEEX::REAL)m_ptLastPoint.y, + (NCNODEEX::REAL)m_ptLastPoint.z); + POINTD _pt = CubicTransform(&_lp); + CPoint _pt0 = m_dc.GetAreaXYZ()->CenterPoint(); + POINTD _ptL; + m_dc.DPtoLP_SM(&_pt0, &_ptL); + OffsetLogicalRef(_pt.x - _ptL.x, _pt.y - _ptL.y); + if (m_hWnd) + InvalidateRect(NULL); +} + +void CTraceCtrl::RotateX(double angle_) +{ + TRANSMATRIX _mt; + _mt[0][0] = 1; + _mt[0][1] = 0; + _mt[0][2] = 0; + _mt[1][0] = 0; + _mt[1][1] = cos(angle_); + _mt[1][2] = sin(angle_); + _mt[2][0] = 0; + _mt[2][1] = -sin(angle_); + _mt[2][2] = cos(angle_); + + _tam(&m_matrixTrans, &m_matrixTrans, &_mt); + return; +} + +void CTraceCtrl::RotateY(double angle_) +{ + TRANSMATRIX _mt; + _mt[0][0] = cos(angle_); + _mt[0][1] = 0; + _mt[0][2] = -sin(angle_); + _mt[1][0] = 0; + _mt[1][1] = 1; + _mt[1][2] = 0; + _mt[2][0] = sin(angle_); + _mt[2][1] = 0; + _mt[2][2] = cos(angle_); + + _tam(&m_matrixTrans, &m_matrixTrans, &_mt); + return; +} + +void CTraceCtrl::RotateZ(double angle_) +{ + TRANSMATRIX _mt; + _mt[0][0] = cos(angle_); + _mt[0][1] = sin(angle_); + _mt[0][2] = 0; + _mt[1][0] = -sin(angle_); + _mt[1][1] = cos(angle_); + _mt[1][2] = 0; + _mt[2][0] = 0; + _mt[2][1] = 0; + _mt[2][2] = 1; + + _tam(&m_matrixTrans, &m_matrixTrans, &_mt); + return; +} + +void CTraceCtrl::SetTransformMatrix(_proj_t mode_) +{ + for (int _row = 0; _row < 3; _row++) + for (int _col = 0; _col < 3; _col++) + m_matrixTrans[_row][_col] = _row == _col ? 1 : 0; + + switch (mode_) + { + case PROJ_ISOMETRIC_SE: + RotateZ(-1 * c_nANGLE_SITA * c_nPIE / 180); + RotateX(c_nANGLE_FAI * c_nPIE / 180); + break; + case PROJ_ISOMETRIC_NW: + RotateZ(c_nANGLE_SITA * c_nPIE / 180); + RotateX(-1 * c_nANGLE_FAI * c_nPIE / 180); + break; + case PROJ_ISOMETRIC_SW: + RotateZ(c_nANGLE_SITA * c_nPIE / 180); + RotateX(c_nANGLE_FAI * c_nPIE / 180); + break; + case PROJ_ISOMETRIC_NE: + RotateZ(-1 * c_nANGLE_SITA * c_nPIE / 180); + RotateX(-1 * c_nANGLE_FAI * c_nPIE / 180); + break; + case PROJ_FRONT: + break; + case PROJ_BACK: + RotateZ(180 * c_nPIE / 180); + break; + case PROJ_LEFT: + RotateZ(90 * c_nPIE / 180); + break; + case PROJ_TOP: + RotateX(90 * c_nPIE / 180); + break; + case PROJ_RIGHT: + RotateZ(-90 * c_nPIE / 180); + break; + case PROJ_BOTTOM: + RotateX(-90 * c_nPIE / 180); + break; + } + + if (m_hWnd) + { + // clear the track bitmap in the playbck DC + m_dc.m_nNextPoint = 0; + InvalidateRect(NULL); + } + return; +} + +///////////////////////////////////////////////////////////////////////////// +// CTraceCtrl message handlers +int CTraceCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + m_hcurRelease = AfxGetApp()->LoadCursor(IDCSR_HAND_RELEASE); + m_hcurCapture = AfxGetApp()->LoadCursor(IDCSR_HAND_CAPTURE); + m_hcurMove = AfxGetApp()->LoadCursor(IDCSR_MOVE); + m_hcurZoomin = AfxGetApp()->LoadCursor(IDCSR_ZOOMIN); + m_hcurZoomout = AfxGetApp()->LoadCursor(IDCSR_ZOOMOUT); + m_hcurSelectOr = AfxGetApp()->LoadCursor(IDCSR_SELECT_OR); + m_hcurSelectNot = AfxGetApp()->LoadCursor(IDCSR_SELECT_NOT); + m_hcurSelectXor = AfxGetApp()->LoadCursor(IDCSR_SELECT_XOR); + m_dc.Bind(::GetDC(m_hWnd)); + + // initialize attributes + // m_dc.SelectObject(&m_pens[PEN_G00]); // pens are not initialized yet + m_dc.SelectStockObject(ANSI_VAR_FONT); + m_dc.SelectStockObject(NULL_BRUSH); + m_dc.SetBkMode(TRANSPARENT); + + EnableToolTips(TRUE); + if (m_ToolTip.CreateEx(this, WS_POPUP | TTS_ALWAYSTIP, WS_EX_TOPMOST)) + { + m_ToolTip.Activate(TRUE); + m_ToolTip.SetMaxTipWidth(SHRT_MAX); + m_ToolTip.SetDelayTime(TTDT_AUTOPOP, SHRT_MAX); + m_ToolTip.SetDelayTime(TTDT_INITIAL, 200); + m_ToolTip.SetDelayTime(TTDT_RESHOW, 200); + m_ToolTip.AddTool(this); + } + + Initialize(); + + SetTimer(IDTIMER_UPDATE_TARCK, c_nCONTINUEPLAYBACK_TIMER_INTERVAL, NULL); + + // Do NOT call LoadTheme() directly, because the window does not finish its + // creating steps yet before this function and its caller returns! Insteadly, + // we use a message(WM_LOADTHEME) to trigger another virtual call after this + // function returns. + //GetTheme()->PostLoadThemeMessage(this); + return 0; +} + +void CTraceCtrl::OnDestroy() +{ + CWnd::OnDestroy(); + + KillTimer(IDTIMER_READNCCMD); + KillTimer(IDTIMER_UPDATE_TARCK); + EnableTimer(false); + MSG _msg; + PeekMessage(&_msg, m_hWnd, WM_TIMER, WM_TIMER, PM_REMOVE); + + DestroyDrawingTools(); + m_TrackRecord.Close(); + m_TrackRecordNode.Close(); + + HDC _hdc = m_dc.Unbind(); + ::DeleteDC(_hdc); + // because this DC was got at OnCreate(), we must delete it here! +} + +void CTraceCtrl::OnSetFocus(CWnd* pOldWnd_) +{ + if (m_hWnd) + InvalidateRect(NULL); + return; +} + +void CTraceCtrl::OnKillFocus(CWnd* pNewWnd_) +{ + m_bReceiveArrowMsgs = false; + if (m_hWnd) + InvalidateRect(NULL); + return; +} + +BOOL CTraceCtrl::OnEraseBkgnd(CDC* pDC) +{ + return TRUE; + // return CWnd::OnEraseBkgnd(pDC); +} + +void CTraceCtrl::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + + if (m_ToolTip.m_hWnd) + { + m_ToolTip.DelTool(this); + + CRect _rc; GetClientRect(&_rc); + m_ToolTip.AddTool(this, LPSTR_TEXTCALLBACK, &_rc, 10); + //m_ToolTip.Activate(TRUE); + } + + CalculateLayout(cx, cy); +} + +BOOL CTraceCtrl::OnToolTipNeedText(UINT id_, NMHDR* pNMHDR_, LRESULT* pResult_) +{ + BOOL _bHandledNotify = FALSE; + + CPoint _point; + ::GetCursorPos(&_point); + ScreenToClient(&_point); + + CRect _rcClient; + GetClientRect(_rcClient); + + // Make certain that the cursor is in the client rect, because the + // mainframe also wants these messages to provide tooltips for the + // toolbar. + if (_rcClient.PtInRect(_point)) + { + TOOLTIPTEXT* _pTTT = (TOOLTIPTEXT*)pNMHDR_; + m_HitField = m_TrackRecord.HitTest(CTrackRecorder::NONE, _point); + + if (m_HitField.from != -1) + { + CString _strLineno; + + NCNODEEX* _pBase = m_TrackRecord.GetBase(); + if (_pBase[m_HitField.from].nFilePos != EOF) + { + //int _nLineno = m_pTrackProvider->GetLinenoFromFilePos(_pBase[m_HitField.from].nFilePos); + + //if (_nLineno != -1) + //{ + // CString _str; _str.Format(L"%d", _nLineno); + // _strLineno.Format(s_csHITTRACK_LINENO, (LPCTSTR)_str); + //} add yuewenxue + } + + // Adjust the text by filling in TOOLTIPTEXT + ::wcscpy_s(_pTTT->szText, _countof(_pTTT->szText), (LPCTSTR)_strLineno + 3); // skip |M| + } + else + { + _pTTT->szText[0] = 0; + } + _bHandledNotify = TRUE; + } + return _bHandledNotify; +} + +void CTraceCtrl::OnMouseMove(UINT nFlags_, CPoint point) +{ + if (!m_dc.GetAreaXYZ()->PtInRect(point)) + return; + + if (nFlags_ & MK_LBUTTON) // left-button is down + { + switch (m_nOperation) + { + case MOVE: + ::SetCursor(m_hcurCapture); + MoveRect(m_ptLButtonDown); + break; + + case SELECT: + SelectRect(m_ptLButtonDown); + break; + + case ZOOMOUT: + case ZOOMIN: + ZoomRect(m_ptLButtonDown); + break; + + default: + ASSERT(false); + break; + } + } + else + { + if (::IsWindow(m_ToolTip.m_hWnd)) + { + LCRO_FIELD _HitField = m_TrackRecord.HitTest(CTrackRecorder::NONE, point); + + if (_HitField != m_HitField) + { + m_HitField = _HitField; + DrawLineNoInfo(&m_dc); + } + } + } + + return; +} + +void CTraceCtrl::OnLButtonDown(UINT nFlags_, CPoint point) +{ + m_ptLButtonDown = point; + + if (m_nOperation == MOVE) + ::SetCursor(m_hcurCapture); + + if (IsWindowEnabled()) + SetFocus(); + CWnd::OnLButtonDown(nFlags_, point); +} + +void CTraceCtrl::OnLButtonUp(UINT nFlags_, CPoint point) +{ + if (m_dc.GetAreaXYZ()->PtInRect(point)) + { + if (m_nOperation == ZOOMIN) + ZoomIn(); + else if (m_nOperation == ZOOMOUT) + ZoomOut(); + else if (m_nOperation == SELECT) + { + ::SetCursor(m_hcurRelease); + SelectPoint(point); + } + } + return; +} + +BOOL CTraceCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) +{ + if (!UpdateCursor()) + return CWnd::OnSetCursor(pWnd, nHitTest, message); + return TRUE; +} + +void CTraceCtrl::OnPaint() +{ + CPaintDC _PaintDC(this); // device context for painting + CRect* _prcClip =(CRect*)&_PaintDC.m_ps.rcPaint; + ASSERT(m_dc.m_hDC == _PaintDC.m_hDC); + // this window has its owned DC + + m_nNumofRecordToPaint = m_TrackRecord.GetSize(); + DrawTrack(&m_dc); + DrawDecorators(); + + m_nCoorX = 0; + return; +} + +void CTraceCtrl::OnKeyDown(UINT nChar_, UINT nRepCnt_, UINT nFlags_) +{ + if (!m_b2DMode && (m_nAccKey == nChar_) && !(GetKeyState(VK_CONTROL) < 0)) + { + CTraceCtrlAccDlg _dlg(this); + if (IDOK ==_dlg.DoModal()) + { + UINT _nVirKey = _dlg.m_nResultVirKey; + if (0 != _nVirKey) + OnKeyCmd(_nVirKey); + } + SetFocus(); + } + else if (!OnKeyCmd1(nChar_)) + { + CWnd::OnKeyDown(nChar_, nRepCnt_, nFlags_); + } +} + +void CTraceCtrl::OnSysKeyDown(UINT nChar_, UINT nRepCnt_, UINT nFlags_) +{ + if (!OnSysKeyCmd(nChar_)) + CWnd::OnSysKeyDown(nChar_, nRepCnt_, nFlags_); +} + +void CTraceCtrl::OnTimer(UINT nIDEvent_) +{ + if ((nIDEvent_ == IDTIMER_READNCCMD) || (nIDEvent_ == IDTIMER_SIMULATOR)) + { + OnReadNccmd(); + } + else if (nIDEvent_ == IDTIMER_CONTINUE_PLAYBACK) + { + ContinuePlayback(); + + if (!((m_nTimerCounter++) % (1000 / c_nCONTINUEPLAYBACK_TIMER_INTERVAL))) + { + // we call it every 1000 ms + UpdateChanges(false); + } + + return; + } + else if (nIDEvent_ == IDTIMER_UPDATE_TARCK) + { + if(m_bUpdateTrackUI && m_dataprovider->TrackIsIdle()) + { + m_bUpdateTrackUI = false; + ASSERT(GetSafeHwnd()); + m_dc.m_nNextPoint = 0; + + //InvalidateRect(NULL, TRUE); + InvalidateRect(NULL,FALSE);//不绘制背景色,直接画。 + } + else if(m_TrackRecordNode.m_bUpdateTrack) + { + m_TrackRecordNode.m_bUpdateTrack=false; + m_dc.m_nNextPoint = 0; + InvalidateRect(NULL,FALSE); + } + } + + CWnd::OnTimer(nIDEvent_); + return; +} + +UINT CTraceCtrl::OnGetDlgCode() +{ + if (m_bReceiveArrowMsgs) + { + return DLGC_WANTARROWS | DLGC_WANTALLKEYS; + } + else + { + const MSG* _pMsg = CWnd::GetCurrentMessage(); + ASSERT(_pMsg->hwnd == m_hWnd); + ASSERT(_pMsg->message == WM_GETDLGCODE); + + if (_pMsg->lParam) + { + __try { + MSG* _pKeyMsg = (MSG*)_pMsg->lParam; + if (_pKeyMsg->message == WM_KEYDOWN) + { + switch (_pKeyMsg->wParam) + { + case VK_ESCAPE: + case VK_RETURN: + return DLGC_WANTALLKEYS; + } + } + } + __except(1) + { + TRACE(_T("错误"),0,0); + } + + return DLGC_STATIC; + } + else // no MSG structure sent with this message + { + return DLGC_WANTALLKEYS; + } + } +} + +void CTraceCtrl::OnWindowPosChanged(WINDOWPOS* pWndPos_) +{ + CWnd::OnWindowPosChanged(pWndPos_); + + if (pWndPos_->flags & SWP_SHOWWINDOW) + { + EnableTimer(IsWindowVisible() == TRUE); + } + else if (pWndPos_->flags & SWP_HIDEWINDOW) + { + EnableTimer(false); + } +} + +void CTraceCtrl::OnReadNccmd() +{ + ReadPulse(); + int i= 0; + if (m_ChannelFifo.IsEmpty() + && m_dataprovider->IsIdleState()) + { + // at some cases, the current position (machine coor.) may change due to the operation + // such as bkref. so we need to synchronize m_ptLastPoint. + SynchronizeLastPoint(); + + } + else if(!m_ChannelFifo.IsEmpty()) //当channelfifo空的时候不必要进入读取和画。 add yuewenxue + { + EraseAssObject(NULL); + CMD_HEADER _header; + CMD_HEADER* _pHeader= (CMD_HEADER*)_malloca(512); + while (true) + { + if (!m_ChannelFifo.PreReadStructHeader(&_header)||i++>=8000) + { + i=0; + break; + } + + ASSERT(_header.nSize<1024); + *_pHeader = _header; + m_ChannelFifo.ReadStruct(_pHeader); + RecordNccmd(_pHeader); + } + + _freea(_pHeader); + i=0; + NCNODEEX::POINT3D _lp((NCNODEEX::REAL)m_ptLastPoint.x, + (NCNODEEX::REAL)m_ptLastPoint.y, + (NCNODEEX::REAL)m_ptLastPoint.z); + DrawAssObject(&_lp); + } + return; +} + +void CTraceCtrl::ShowNextSpeed() +{ + int _i; + for (_i = 0; _i < c_nNUMOF_SHOWSPEEDPROMPT; _i++) + { + if (m_nShowSpeed == (_SHOW_SPEED_NO + _i)) + break; + } + if (++_i >= c_nNUMOF_SHOWSPEEDPROMPT) + _i = 0; + + m_nShowSpeed = (_show_speed_t)(_SHOW_SPEED_NO + _i); + + if(m_nShowSpeed == _SHOW_DEBUG) + { + m_nShowSpeed = _SHOW_SPEED_NO; + } + + if (m_hWnd) + InvalidateRect(NULL); + + //NCADPT_UPDATESIMPLEVAR_INSTRUCT* _psv = &GetNcKernel()->m_ss.m_sv; + //if (m_nShowSpeed != _SHOW_SPEED_NO) + //{ + // if (_psv->bCompressNccmd) + // { + // m_nCompressNccmd_Old = _psv->bCompressNccmd; // true + + // _psv->bCompressNccmd = false; + // GetNcKernel()->UpdateSimpleVar(SV_COMPRESSNCCMD); + // } + //} + //else + //{ + // if (!_psv->bCompressNccmd && (m_nCompressNccmd_Old == 1)) + // { + // _psv->bCompressNccmd = true; + // //GetNcKernel()->UpdateSimpleVar(SV_COMPRESSNCCMD); + // } + + // m_nCompressNccmd_Old = 2; // not accessed + //} + return; +} + +void CTraceCtrl::ZoomRect(POINT pt_) +{ + CPoint _pt; GetCursorPos(&_pt); + ScreenToClient(&_pt); + + CRect _rc(pt_.x, pt_.y, _pt.x, _pt.y); + CRectTracker _tracker(&_rc, CRectTracker::solidLine); + m_dc.SetBkColor(0xFFFFFF); + BOOL _ret = _tracker.TrackRubberBand(this, pt_); + if (_ret) + { + _rc = _tracker.m_rect; + _rc.NormalizeRect(); + + // step1: offset logical ref. point + POINTD _pt0L, _pt1L; + + CPoint _pt0 = m_dc.GetAreaXYZ()->CenterPoint(); + CPoint _pt1 = _rc.CenterPoint(); + m_dc.DPtoLP_SM(&_pt0, &_pt0L); + m_dc.DPtoLP_SM(&_pt1, &_pt1L); + + OffsetLogicalRef(_pt1L.x - _pt0L.x, _pt1L.y - _pt0L.y); + + // step2: get the proper zoom-ratio + const CRect* _pRect = m_dc.GetAreaXYZ(); + double _factor1 =(double)(_pRect->Width() - 10) / _rc.Width(); + double _factor2 =(double)(_pRect->Height() - 10) / _rc.Height(); + double _factor; + if (m_nOperation == ZOOMOUT) + { + _factor = __min(_factor1, _factor2); + } + else + { + _factor1 = 1.0 / _factor1; + _factor2 = 1.0 / _factor2; + _factor = __min(_factor1, _factor2); + } + double _nRatio = GetZoomRatio(); + SetZoomRatio(_nRatio * _factor); + } + return; +} + +void CTraceCtrl::ZoomOut() +{ + SetZoomRatio(GetZoomRatio() * 1.5); +} + +void CTraceCtrl::ZoomIn() +{ + SetZoomRatio(GetZoomRatio() / 1.5); +} + +void CTraceCtrl::MoveRect(POINT pt_) +{ + CRect _rc(-1, -1, pt_.x, pt_.y); + CRectTracker _tracker(&_rc, CRectTracker::solidLine); + m_dc.SetBkColor(0xFFFFFF); + BOOL _ret = _tracker.Track(this, pt_); + if (_ret) + { + RECTD _rcLp; + _rc.left = _tracker.m_rect.right; + _rc.top = _tracker.m_rect.bottom; + m_dc.DPtoLP_SM(&_rc, &_rcLp); + + OffsetLogicalRef(_rcLp.right - _rcLp.left, _rcLp.bottom - _rcLp.top); + if (m_hWnd) + InvalidateRect(NULL); + } + return; +} + +void CTraceCtrl::SelectPoint(POINT pt_) +{ + LCRO_FIELD _hit = m_TrackRecord.HitTest(m_nSelectMode, pt_); + if (!_hit.IsEmpty()) + { + // redraw track + m_dc.m_nNextPoint = 0; + if (m_hWnd) + InvalidateRect(NULL); + } + return; +} + +void CTraceCtrl::SelectRect(POINT pt_) +{ + CPoint _pt; + GetCursorPos(&_pt); + ScreenToClient(&_pt); + + CRect _rc(pt_.x, pt_.y, _pt.x, _pt.y); + CRectTracker _tracker(&_rc, CRectTracker::solidLine); + m_dc.SetBkColor(0xFFFFFF); + BOOL _ret = _tracker.TrackRubberBand(this, pt_); + if (_ret) + { + _rc = _tracker.m_rect; + _rc.NormalizeRect(); + LCRO_FIELD _hit = m_TrackRecord.HitTest(m_nSelectMode, &_rc); + if (!_hit.IsEmpty()) + { + // redraw track + m_dc.m_nNextPoint = 0; + if (m_hWnd) + InvalidateRect(NULL); + } + } +} + +void CTraceCtrl::LoadFile() +{ + //if(m_TrackRecordNode.IsOpen()) + //{ + // KillDrawTimer(); + // m_TrackRecordNode.Close(); + // ResetDrawTimer(); + //} + + if (m_bInitPerDoc) + ClearView(); + + if (m_dataprovider->ClearTrackEnable()) + { + m_TrackRecordNode.Reset(NULL); + m_traceAreaUpdate.Clear(); + m_bTrackLoaded = false; + } + + ClearTrackRecordPosInfo(); + m_dc.m_nNextPoint = 0; + m_bUpdateTrackUI = true; + m_TraceArea.Clear(); +} + +void CTraceCtrl::UnLoadFile() +{ + //if(m_TrackRecordNode.IsOpen()) + //{ + // KillDrawTimer(); + // m_TrackRecordNode.Close(); + // ResetDrawTimer(); + //} + + m_TrackRecordNode.Reset(NULL); + m_dc.m_nNextPoint = 0; + InvalidateRect(NULL, TRUE); + m_bTrackLoaded = false; +} + +void CTraceCtrl::ClearTrack() +{ + if(m_TrackRecordNode.IsOpen()) + { + KillDrawTimer(); + m_TrackRecordNode.Close(); + ResetDrawTimer(); + } + + m_traceAreaUpdate.Clear(); + m_TrackRecordNode.Reset(NULL); + m_dc.m_nNextPoint = 0; + InvalidateRect(NULL, TRUE); + m_bTrackLoaded = false; +} + +void CTraceCtrl::OnCommandRange(UINT id_) +{ + switch (id_) + { + case IDCMD_TRACECTRL_ZOOMOUT: + SetOperation(CTraceCtrl::ZOOMOUT); + ZoomOut(); + return; + case IDCMD_TRACECTRL_ZOOMIN: + SetOperation(CTraceCtrl::ZOOMIN); + ZoomIn(); + return; + case IDCMD_TRACECTRL_MOVE: + SetOperation(CTraceCtrl::MOVE); + return; + case IDCMD_TRACECTRL_CLEARVIEW: + ClearView(); + return; + case IDCMD_TRACECTRL_FITWINDOW: + SetZoomRatio(GetFitZoomRatio()); + CenterWorkpiece(); + return; + case IDCMD_TRACECTRL_CENTER: + CenterWorkpiece(); + return; + case IDCMD_TRACECTRL_CURRENT: + CenterCursor(); + return; + + case IDCMD_TRACECTRL_LOAD_TRACK: + m_dataprovider->ClearTrack(); + ClearTrack(); + m_dataprovider->LockTrack(); + m_bTrackLoaded = true; + return; + case IDCMD_TRACECTRL_STOP_LOAD_TRACK: + m_dataprovider->ClearTrack(); + ClearTrack(); + return; + case IDCMD_TRACECTRL_CLEAR_TRACK: + m_dataprovider->ClearTrack(); + ClearTrack(); + return; + } + + if (m_b2DMode && (id_ != IDCMD_TRACECTRL_PROJ_TOP)) + return; + + POINTD _ptCenter = GetWorkpieceCenterPoint(); + switch (id_) + { + case IDCMD_TRACECTRL_PROJ_ISOMETRIC_SW: + SetTransformMatrix(CTraceCtrl::PROJ_ISOMETRIC_SW); + m_nProjectMode = CTraceCtrl::PROJ_ISOMETRIC_SW; + break; + case IDCMD_TRACECTRL_PROJ_BOTTOM: + SetTransformMatrix(CTraceCtrl::PROJ_BOTTOM); + m_nProjectMode = CTraceCtrl::PROJ_BOTTOM; + break; + case IDCMD_TRACECTRL_PROJ_ISOMETRIC_SE: + SetTransformMatrix(CTraceCtrl::PROJ_ISOMETRIC_SE); + m_nProjectMode = CTraceCtrl::PROJ_ISOMETRIC_SE; + break; + case IDCMD_TRACECTRL_PROJ_LEFT: + SetTransformMatrix(CTraceCtrl::PROJ_LEFT); + m_nProjectMode = CTraceCtrl::PROJ_LEFT; + break; + case IDCMD_TRACECTRL_PROJ_FRONT: + SetTransformMatrix(CTraceCtrl::PROJ_FRONT); + m_nProjectMode = CTraceCtrl::PROJ_FRONT; + break; + case IDCMD_TRACECTRL_PROJ_BACK: + SetTransformMatrix(CTraceCtrl::PROJ_BACK); + m_nProjectMode = CTraceCtrl::PROJ_BACK; + break; + case IDCMD_TRACECTRL_PROJ_RIGHT: + SetTransformMatrix(CTraceCtrl::PROJ_RIGHT); + m_nProjectMode = CTraceCtrl::PROJ_RIGHT; + break; + case IDCMD_TRACECTRL_PROJ_ISOMETRIC_NW: + SetTransformMatrix(CTraceCtrl::PROJ_ISOMETRIC_NW); + m_nProjectMode = CTraceCtrl::PROJ_ISOMETRIC_NW; + break; + case IDCMD_TRACECTRL_PROJ_TOP: + SetTransformMatrix(CTraceCtrl::PROJ_TOP); + m_nProjectMode = CTraceCtrl::PROJ_TOP; + break; + case IDCMD_TRACECTRL_PROJ_ISOMETRIC_NE: + SetTransformMatrix(CTraceCtrl::PROJ_ISOMETRIC_NE); + m_nProjectMode = CTraceCtrl::PROJ_ISOMETRIC_NE; + break; + default: + return; + } + + CenterWorkpiece(&_ptCenter); + return; +} + +void CTraceCtrl::OnUpdateCommandRange(CCmdUI* pCmdUI) +{ + switch (pCmdUI->m_nID) + { + case IDCMD_TRACECTRL_ZOOMOUT: + pCmdUI->SetCheck(m_nOperation == CTraceCtrl::ZOOMOUT); + return; + case IDCMD_TRACECTRL_ZOOMIN: + pCmdUI->SetCheck(m_nOperation == CTraceCtrl::ZOOMIN); + return; + case IDCMD_TRACECTRL_MOVE: + pCmdUI->SetCheck(m_nOperation == CTraceCtrl::MOVE); + return; + case IDCMD_TRACECTRL_CLEARVIEW: + pCmdUI->Enable(!m_TrackRecord.IsEmpty()); + return; + case IDCMD_TRACECTRL_CLEAR_TRACK: + pCmdUI->Enable(!m_TrackRecordNode.IsEmpty()); + return; + case IDCMD_TRACECTRL_LOAD_TRACK: + if(m_dataprovider->IsLoadFile==NULL) + { + pCmdUI->Enable(FALSE); + }else + { + pCmdUI->Enable(m_dataprovider->IsLoadFile()); + pCmdUI->SetCheck(!m_TrackRecordNode.IsEmpty()); + } + return; + case IDCMD_TRACECTRL_STOP_LOAD_TRACK: + pCmdUI->Enable(m_bUpdateTrackUI); + return; + default: + return; + } +} + +void CTraceCtrl::OnToolCustomize() +{ + + CTraceCtrlCustomizeDlg _dlg(this); + + _dlg.m_wndClrBkGround.m_clrCurrent = m_clrTrackBkFrom; + _dlg.m_wndClrBkLineNum.m_clrCurrent = m_clrTrackLineNum; + _dlg.m_wndClrBkGround1.m_clrCurrent = m_clrTrackBkTo; + _dlg.m_wndClrCoor.m_clrCurrent = m_clrPens[PEN_COORDARKEN]; + _dlg.m_wndClrG00.m_clrCurrent = m_clrPens[PEN_G00]; + _dlg.m_wndClrG01.m_clrCurrent = m_clrPens[PEN_G01]; + _dlg.m_wndClrG02.m_clrCurrent = m_clrPens[PEN_G02]; + _dlg.m_wndClrG03.m_clrCurrent = m_clrPens[PEN_G03]; + _dlg.m_wndClrSimuG00.m_clrCurrent = m_clrPens[PEN_G00_SIMU]; + _dlg.m_wndClrSimuG01.m_clrCurrent = m_clrPens[PEN_G01_SIMU]; + _dlg.m_wndClrSimuG02.m_clrCurrent = m_clrPens[PEN_G02_SIMU]; + _dlg.m_wndClrSimuG03.m_clrCurrent = m_clrPens[PEN_G03_SIMU]; + _dlg.m_wndClrGrid.m_clrCurrent = m_clrPens[PEN_GRID]; + _dlg.m_wndClrSelectedTrace.m_clrCurrent = m_clrPens[PEN_SELECTED]; + _dlg.m_bDrawFrame = m_bDrawWorkAreaFrame; + _dlg.m_bShowCoor = m_bShowCoor; + _dlg.m_bLineNumber = m_bIsShowLineNumber; + _dlg.m_bDrawGrid = m_bDrawGrid; + _dlg.m_bIsFileTrackFirst = m_bIsFileTrackFirst; + _dlg.m_bInitPerDoc = m_bInitPerDoc; + if (_dlg.DoModal() == IDOK) + { + m_clrPens[PEN_COORDARKEN] = _dlg.m_wndClrCoor.m_clrCurrent; + m_clrTrackBkFrom = _dlg.m_wndClrBkGround.m_clrCurrent; + m_clrTrackLineNum = _dlg.m_wndClrBkLineNum.m_clrCurrent; + m_clrTrackBkTo = _dlg.m_wndClrBkGround1.m_clrCurrent; + m_clrPens[PEN_G00] = _dlg.m_wndClrG00.m_clrCurrent; + m_clrPens[PEN_G01] = _dlg.m_wndClrG01.m_clrCurrent; + m_clrPens[PEN_G02] = _dlg.m_wndClrG02.m_clrCurrent; + m_clrPens[PEN_G03] = _dlg.m_wndClrG03.m_clrCurrent; + m_clrPens[PEN_G00_SIMU] = _dlg.m_wndClrSimuG00.m_clrCurrent; + m_clrPens[PEN_G01_SIMU] = _dlg.m_wndClrSimuG01.m_clrCurrent; + m_clrPens[PEN_G02_SIMU] = _dlg.m_wndClrSimuG02.m_clrCurrent; + m_clrPens[PEN_G03_SIMU] = _dlg.m_wndClrSimuG03.m_clrCurrent; + + m_clrPens[PEN_GRID] = _dlg.m_wndClrGrid.m_clrCurrent; + m_clrPens[PEN_SELECTED] = _dlg.m_wndClrSelectedTrace.m_clrCurrent; + + m_bShowCoor = _dlg.m_bShowCoor ? true : false; + m_bDrawWorkAreaFrame = _dlg.m_bDrawFrame ? true : false; + m_bIsShowLineNumber = _dlg.m_bLineNumber ? true : false; + m_bDrawGrid = _dlg.m_bDrawGrid == TRUE; + m_bIsFileTrackFirst = _dlg.m_bIsFileTrackFirst == TRUE; + m_bInitPerDoc = _dlg.m_bInitPerDoc == TRUE; + + UpdateDrawingTools(); + this->m_dataprovider->Save(); + } + + this->SetFocus(); +} + +void CTraceCtrl::DrawAssObject(void* pVoid_) +{ + ASSERT(pVoid_); + NCNODEEX::POINT3D* _p3Dpt = (NCNODEEX::POINT3D*)pVoid_; + DrawCrosses(&m_dc, _p3Dpt); + DrawCurrentCoor(&m_dc); +} + +void CTraceCtrl::EraseAssObject(void* pVoid_) +{ + EraseCrosses(&m_dc); +} + +BOOL CTraceCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint point_) +{ + if (zDelta > 0) + ZoomOut(); + else if (zDelta < 0) + ZoomIn(); + + return CWnd::OnMouseWheel(nFlags, zDelta, point_); +} + +INT_PTR CTraceCtrl::OnToolHitTest(CPoint point, TOOLINFO* pTI) const +{ + if (!m_strToolTip.IsEmpty()) + pTI->lpszText = _tcsdup(m_strToolTip); + + return __super::OnToolHitTest(point, pTI); +} + +void CTraceCtrl::SetRectDC() +{ + CSimuDCEx *pDC_=&m_dc; + CRect*_pRect= pDC_->GetAreaShowXYZValue(true); + + CDC* rectOldDC=rectDC; + CBitmap* rectOldBmp=rectBmp; + rectDC = new CDC(); + rectDC->CreateCompatibleDC(pDC_); + rectBmp = new CBitmap(); + rectBmp->CreateCompatibleBitmap(pDC_,_pRect->Width(),_pRect->Height()); + rectDC->SelectObject(rectBmp); + rectDC->BitBlt(0,0,_pRect->Width(),_pRect->Height(),pDC_,_pRect->left,_pRect->top,SRCCOPY); + pDC_->BitBlt(_pRect->left,_pRect->top,_pRect->Width(),_pRect->Height(),rectDC,0,0,SRCCOPY); + if (rectOldBmp!=NULL) + { + rectOldDC->DeleteDC(); + rectOldBmp->DeleteObject(); + + delete rectOldDC; + delete rectOldBmp; + } +} + +// 关闭画图的定时器 +void CTraceCtrl::KillDrawTimer() +{ + KillTimer(IDTIMER_READNCCMD); + KillTimer(IDTIMER_UPDATE_TARCK); + KillTimer(IDTIMER_SIMULATOR); + EnableTimer(false); +} + +//启动画图的定时器 +void CTraceCtrl::ResetDrawTimer() +{ + SetTimer(IDTIMER_READNCCMD, 83, NULL); + SetTimer(IDTIMER_UPDATE_TARCK, c_nCONTINUEPLAYBACK_TIMER_INTERVAL, NULL); + EnableTimer(true); +} + + + diff --git a/src/Triangulation.cpp b/src/Triangulation.cpp new file mode 100644 index 0000000..74d507a --- /dev/null +++ b/src/Triangulation.cpp @@ -0,0 +1,3021 @@ +#include "stdafx.h" +//#include "Geo_Head.h" +//#include "Triangulation.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW +#endif + +namespace leadingline{ + +Point_2 g_ptCurPosition; + +string PointTypeString[]= +{ + "PT_BEGIN", + "PT_END", + "PT_REGULARLEFT", + "PT_REGULARRIGHT", + "PT_MERGE", + "PT_SPLIT", + "PT_NULL" +}; + +turn_dir_t leadingline::GetTurnType(Point_2 ptPre,Point_2 ptCur,Point_2 ptNext)//VectorD2D vec1_, VectorD2D vec2_ +{ + Point_2 vec1_(ptCur.x-ptPre.x ,ptCur.y - ptPre.y); + Point_2 vec2_(ptNext.x-ptCur.x ,ptNext.y - ptCur.y); + double sinVal = vec1_.x*vec2_.y - vec1_.y*vec2_.x; + return GetTurnType(vec1_,vec2_); +} + +turn_dir_t leadingline::GetTurnType(Point_2 vec1_,Point_2 vec2_) +{ + double sinVal = vec1_.x*vec2_.y - vec1_.y*vec2_.x; + + if (abs(sinVal)<1.e-9) //DOUBLE_EQU_ZERO(res) + { + //same direction or opposite direction + double cosVal = vec1_.x*vec2_.x + vec1_.y*vec2_.y; + if (cosVal>0) + { + return turn_same; + } + else if (cosVal<0) + { + return turn_opposite; + } + else + { + _ASSERT(0); //It's impossible here + return turn_null; + } + } + else if (sinVal>0) + { + return turn_left; + } + else if (sinVal<0) + { + return turn_right; + } + _ASSERT(0); + return turn_null; +} + +void leadingline::TransformLineExpressiong(IN Point_2 lineStart_,IN Point_2 lineEnd_,OUT double& A,OUT double& B,OUT double& C) +{ + A = lineEnd_.y - lineStart_.y; + B = lineStart_.x - lineEnd_.x; + C = A*lineStart_.x + B*lineStart_.y; +} + + +bool leadingline::GetLineIntersect(IN Point_2 line1start_, IN Point_2 line1end_, IN Point_2 line2start_, IN Point_2 line2end_,OUT Point_2& ret_) +{ + double A1,A2,B1,B2,C1,C2; + TransformLineExpressiong(line1start_,line1end_,A1,B1,C1); + TransformLineExpressiong(line2start_,line2end_,A2,B2,C2); + double det = A1*B2 - A2*B1; + if(DOUBLE_EQU_ZERO(det)){ //Lines are parallel + return false; + }else{ + ret_.x = (B2*C1 - B1*C2)/det; + ret_.y = (A1*C2 - A2*C1)/det; + } + return true; +} + +double leadingline::Direction(Point_2 Pi,Point_2 Pj,Point_2 Pk) +{ + return (Pj.x - Pi.x)*(Pk.y - Pi.y) - (Pk.x - Pi.x)*(Pj.y - Pi.y); +} + +bool leadingline::OnSegment(const Segment& seg, const Point_2& pt) +{ + if ((min(seg.ptStart.x,seg.ptEnd.x) <= pt.x && pt.x <= max(seg.ptStart.x,seg.ptEnd.x)) + &&(min(seg.ptStart.y,seg.ptEnd.y) <= pt.y && pt.y <= max(seg.ptStart.y,seg.ptEnd.y)) + ) + { + return true; + } + else + return false; +} + +bool leadingline::IsIntersect(const Segment& s1,const Segment& s2) +{ + double d1,d2,d3,d4; + d1 = Direction(s2.ptStart,s2.ptEnd,s1.ptStart); + d2 = Direction(s2.ptStart,s2.ptEnd,s1.ptEnd); + d3 = Direction(s1.ptStart,s1.ptEnd,s2.ptStart); + d4 = Direction(s1.ptStart,s1.ptEnd,s2.ptEnd); + if (DOUBLE_EQU_ZERO(d1) && OnSegment(s2,s1.ptStart)) + { + return true; + } + else if (DOUBLE_EQU_ZERO(d2) && OnSegment(s2,s1.ptEnd)) + { + return true; + } + else if (DOUBLE_EQU_ZERO(d3) && OnSegment(s1,s2.ptStart)) + { + return true; + } + else if (DOUBLE_EQU_ZERO(d4) && OnSegment(s1,s2.ptEnd)) + { + return true; + } + else if (((d1>0 && d2<0) || (d1<0 && d2>0)) + &&((d3>0 && d4<0) || (d3<0 && d4>0))) + { + return true; + } + return false; +} + +bool leadingline::RawSegmentInterSection(const Segment& s1,const Segment& s2,Point_2& ptOut) +{ + if (IsIntersect(s1,s2)) + { + return GetLineIntersect(s1.ptStart,s1.ptEnd,s2.ptStart,s2.ptEnd,ptOut); + } + return false; +} + +bool leadingline::operator<(const Point_2& pt1,const Point_2& pt2) +{ + if (abs(pt1.y - pt2.y)<1.0e-9) + { + if (abs(pt1.x - pt2.x)<1.0e-9) + { + return false; + } + else if (pt1.x < pt2.x) + { + return true; + } + else + return false; + } + else if (pt1.y > pt2.y) + { + return true; + } + else + return false; +} + +bool leadingline::operator==(const Point_2& pt1,const Point_2& pt2) +{ + return (DOUBLE_EQU_ZERO(pt1.x-pt2.x) && DOUBLE_EQU_ZERO(pt1.y-pt2.y)); +} + +bool leadingline::operator<(const DoubleEdge& eg1,const DoubleEdge& eg2) +{ + return (eg1.m_ptStart) < (eg2.m_ptStart) ; +} + + +bool leadingline::PointUpperThan(const Point_2& pt1,const Point_2& pt2) +{ + if (abs(pt1.y-pt2.y)<1.e-9) + { + if (pt1.xpt2.y) + { + return true; + } + else + return false; +} + +bool leadingline::PointLeftOf(const Point_2& pt1,const Point_2& pt2) +{ + if (abs(pt1.x-pt2.x)<1.e-9) + { + if (pt1.ym_edgeId == node2->m_edgeId) + { + return 0; + } + else + { + DoubleEdge* pNext1 = node1->m_pNext; + DoubleEdge* pNext2 = node2->m_pNext; + Point_2 pt1Start = node1->m_ptStart; + Point_2 pt1End = pNext1->m_ptStart; + + Point_2 pt2Start = node2->m_ptStart; + Point_2 pt2End = pNext2->m_ptStart; + + double curY = g_ptCurPosition.y; + double edge1x ,edge2x; + + if ( abs(pt1Start.y-pt1End.y)<1.e-9 ) + { + edge1x = pt1Start.x; + } + else + { + edge1x =( (curY-pt1Start.y)*(pt1End.x-pt1Start.x)/(pt1End.y-pt1Start.y) ) + pt1Start.x ; + } + + if ( abs(pt2Start.y-pt2End.y)<1.e-9 ) + { + edge2x = pt2Start.x; + } + else + { + edge2x =( (curY-pt2Start.y)*(pt2End.x-pt2Start.x)/(pt2End.y-pt2Start.y) ) + pt2Start.x ; + } + + if (edge1x 0.0); + double _temp = X / _Radius; + __CUT(_temp, -1., 1.); + double _angle = acos(_temp); + + // First or second quadrant + if (DOUBLE_GE_ZERO(Y)) + return _angle; + + // Third or fourth quadrant + return 2.0 * c_nPI - _angle; +} + +void RetrieveArcInf(IN const Point_2& ptStart_, + IN const Point_2&ptEnd_, + IN const double& nBulge_, + OUT Point_2* pptCenter_, + OUT double* pnStartAngle_, + OUT double* pnEndAngle_, + OUT double* pnRadius_) +{ + Point_2 _ptFromTo(ptEnd_.x-ptStart_.x,ptEnd_.y-ptStart_.y); + double _nLen = sqrt(_ptFromTo.x*_ptFromTo.x+_ptFromTo.y*_ptFromTo.y); + ASSERT(DOUBLE_GE_ZERO(_nLen)); + if (DOUBLE_EQU_ZERO(_nLen)) + { + *pptCenter_ = ptStart_; + *pnStartAngle_ = 0.; + *pnEndAngle_ = 0.; + *pnRadius_ = 0.; + return; + } + + // Inner angle + double _alpha = atan(nBulge_) * 4.; + ASSERT(DOUBLE_NOT_ZERO(_alpha)); + + // 1) Radius + double _nRadius = _nLen * 0.5 / sin(_alpha * 0.5); + *pnRadius_ = fabs(_nRadius); + + // 2) Circle centre + // 2-1) proportional translate + ASSERT(DOUBLE_NOT_ZERO(_nLen)); + double _nK = _nRadius / _nLen; + + Point_2 _ptByPropTrans; + _ptByPropTrans.x = _ptFromTo.x * _nK; + _ptByPropTrans.y = _ptFromTo.y * _nK; + + // 2-2) revolving transform + double _theta = (c_nPI - _alpha) * 0.5; + Point_2 _ptByRevTrans; + _ptByRevTrans.x = cos(_theta) * _ptByPropTrans.x - sin(_theta) * _ptByPropTrans.y; + _ptByRevTrans.y = sin(_theta) * _ptByPropTrans.x + cos(_theta) * _ptByPropTrans.y; + + // 2-3) Get circle center + pptCenter_->x = ptStart_.x + _ptByRevTrans.x; + pptCenter_->y = ptStart_.y + _ptByRevTrans.y; + + // 3) Start angle + *pnStartAngle_ = _compute_angle(ptStart_.x - pptCenter_->x, ptStart_.y - pptCenter_->y); + + // 4) End angle + *pnEndAngle_ = *pnStartAngle_ + _alpha; + + return; +} + + +double TransformArcToSegments(IN const Point_2& ptStart_, + IN const Point_2& ptEnd_, + IN const double& nBulge_, + IN const double& nGap_, + OUT vector& vectorOut_) +{ + Point_2 _center; + double _nAngleStart, _nAngleEnd, _nRadius; + + RetrieveArcInf(ptStart_, ptEnd_, nBulge_, &_center, &_nAngleStart, &_nAngleEnd, &_nRadius); + + double _nDegreeStep = 4*asin(sqrt(nGap_/(2*_nRadius))); + + + double _nAngleCur = _nAngleStart; + Point_2 _curVertex; + double _delta ; + + vectorOut_.push_back(ptStart_); + int nTotalStep ; + if (_nAngleStart>_nAngleEnd) //顺时针 + { + _delta = _nAngleStart - _nAngleEnd; + nTotalStep = (int)(_delta/fabs(_nDegreeStep)); + if (nTotalStep==0) + { + ++nTotalStep; + } + _nDegreeStep = _delta/nTotalStep; + if (nBulge_<0) + { + _nDegreeStep = -_nDegreeStep; + } + //_nAngleEnd += 2.0 * c_nPI; + //while (_nAngleCur + _nDegreeStep > _nAngleEnd) + for (int i=1;i& vectorOut_) +{ + double _nAngleStart; + + _nAngleStart = atan( (ptStart_.y-ptCenter_.y)/(ptStart_.x - ptCenter_.x) ); + + double _nDegreeStep = 4*asin(sqrt(nGap_/(2*nRadius_)));//= nGap_/nRadius_; + + double _nAngle = 0; + Point_2 _curVertex; + + while (_nAngle + _nDegreeStep < 2*c_nPI) + { + _nAngle += _nDegreeStep; + _curVertex.x = ptCenter_.x + nRadius_*cos(_nAngleStart+_nAngle); + _curVertex.y = ptCenter_.y + nRadius_*sin(_nAngleStart+_nAngle); + vectorOut_.push_back(_curVertex); + } + _curVertex.x = ptStart_.x ; + _curVertex.y = ptStart_.y ; + vectorOut_.push_back(_curVertex); +} + +bool operator ==(const EdgeIndex& EIdx1,const EdgeIndex& EIdx2 ) +{ + if (EIdx1.MajorIndex == EIdx2.MajorIndex && EIdx1.MinorIndex == EIdx2.MinorIndex) + { + return true; + } + return false; +} + + DoubleEdgeFactory* DoubleEdgeFactory::s_pEdgeFactory = NULL; + +DoubleEdge* DoubleEdgeFactory::ConstructLineEdge(const Point_2& ptStart,DoubleEdge* pNext) +{ + DoubleEdge* pNewEdge = new DoubleEdge(ptStart,pNext); + if (pNewEdge) + { + m_EdgeCache.push_back(pNewEdge); + } + pNewEdge->m_edgeId.MajorIndex = GetNextMajorIdCnt(); + pNewEdge->m_edgeId.MinorIndex = -1; + return pNewEdge; +} + +//将圆弧打散成小线段 +int DoubleEdgeFactory::ConstructArcEdge(const Point_2& ptStart,const Point_2& ptEnd,double nBulge,OUT DoubleEdge*& pStartEdge,OUT DoubleEdge*& pEndEdge) +{ + vector vectorOut; + double arcLen = TransformArcToSegments(ptStart,ptEnd,nBulge,0.01,vectorOut); + int nSegCnt = (int)vectorOut.size(); + pStartEdge = ConstructArcSegmentEdge(ptStart,EAET_FIRST); + DoubleEdge* pPreEdge = pStartEdge; + DoubleEdge* pCurEdge; + + for (int i=1;im_pNext = pCurEdge; + pCurEdge->m_pPre = pPreEdge; + pPreEdge = pCurEdge; + } + + pCurEdge = ConstructArcSegmentEdge(vectorOut[nSegCnt-1],EAET_LAST); + pPreEdge->m_pNext = pCurEdge; + pCurEdge->m_pPre = pPreEdge; + pEndEdge = pCurEdge; + ArcInfo arcInfo; + arcInfo.nArcSegNum = nSegCnt; + arcInfo.ptArcStart = ptStart; + arcInfo.ptArcEnd = ptEnd; + arcInfo.nLength = arcLen; + arcInfo.nBulge = nBulge; + m_pTriangulation->m_mpIdxToArcInfo[pCurEdge->m_edgeId.MajorIndex] = arcInfo; + return nSegCnt; +} + +DoubleEdge* DoubleEdgeFactory::ConstructArcSegmentEdge(const Point_2& ptStart,ArcEdgeType ArcEdgeT,DoubleEdge* pNext) +{ + DoubleEdge* pNewEdge = new DoubleEdge(ptStart,pNext); + if (pNewEdge) + { + m_EdgeCache.push_back(pNewEdge); + } + switch(ArcEdgeT) + { + case EAET_FIRST: + { + ClearMinorIdCount(); + pNewEdge->m_edgeId.MajorIndex = GetNextMajorIdCnt(); + pNewEdge->m_edgeId.MinorIndex = GetNextMinorIdCnt(); + } + break; + case EAET_MIDDLE: + { + pNewEdge->m_edgeId.MajorIndex = GetCurrentMajorIdCnt(); + pNewEdge->m_edgeId.MinorIndex = GetNextMinorIdCnt(); + } + break; + case EAET_LAST: + { + pNewEdge->m_edgeId.MajorIndex = GetCurrentMajorIdCnt(); + pNewEdge->m_edgeId.MinorIndex = GetNextMinorIdCnt(); + } + break; + default: + ASSERT(0); + } + return pNewEdge; +} + +DoubleEdgeFactory* DoubleEdgeFactory::GetDoubleEdgeFactory() +{ + if (s_pEdgeFactory==NULL) + { + s_pEdgeFactory = new DoubleEdgeFactory; + s_pEdgeFactory->ClearMajorIdCount(); + s_pEdgeFactory->ClearMinorIdCount(); + } + return s_pEdgeFactory; +} + +void DoubleEdgeFactory::ReleaseEdgeFactory() +{ + if (s_pEdgeFactory) + { + delete s_pEdgeFactory; + s_pEdgeFactory = NULL; + } +} + +bool DoubleEdgeFactory::ReleaseEdges() +{ + list::iterator Iter = m_EdgeCache.begin(), + IterEnd = m_EdgeCache.end(); + while (Iter!=IterEnd) + { + DoubleEdge* pEdge = (*Iter); + if (pEdge) + { + delete pEdge; + } + ++Iter; + } + m_EdgeCache.clear(); + return true; +} + +void DoubleEdgeFactory::ClearMajorIdCount() +{ + GetDoubleEdgeFactory()->m_MajorIdCount = -1; +} + +int DoubleEdgeFactory::GetCurrentMajorIdCnt() +{ + return GetDoubleEdgeFactory()->m_MajorIdCount; +} + +int DoubleEdgeFactory::GetNextMajorIdCnt() +{ + return GetDoubleEdgeFactory()->m_MajorIdCount+=1; +} + +void DoubleEdgeFactory::ClearMinorIdCount() +{ + GetDoubleEdgeFactory()->m_minorIdCount = -1; +} + +int DoubleEdgeFactory::GetCurrentMinorIdCnt() +{ + return GetDoubleEdgeFactory()->m_minorIdCount; +} + +int DoubleEdgeFactory::GetNextMinorIdCnt() +{ + return GetDoubleEdgeFactory()->m_minorIdCount+=1; +} + +DoubleEdgeFactory* GeoGetDoubleEdgeFactory() +{ + return DoubleEdgeFactory::GetDoubleEdgeFactory(); +} + +void GeoReleaseDoubleEdgeFactory() +{ + DoubleEdgeFactory::ReleaseEdgeFactory(); +} + +Surface::Surface() +{ + m_bIsYMonotone = false; + + m_ptEdge = NULL; + m_nEdgeCount = 0; +} + + +Surface::Surface(DoubleEdge* ptEdge,bool IsYMonoTone ):m_ptEdge(ptEdge),m_bIsYMonotone(IsYMonoTone) +{ + m_nEdgeCount = 0; + DoubleEdge* pCurEdge = m_ptEdge; + + do + { + ++m_nEdgeCount; + pCurEdge = pCurEdge->m_pNext; + } while (pCurEdge!=m_ptEdge); +} + +void Surface::CalcPointType() +{ + DoubleEdge* pStartEdge = m_ptEdge; + DoubleEdge* pPre = pStartEdge; + DoubleEdge* pCur ; + DoubleEdge* pNext ; + + int cnt = 0; + do + { + pCur = pPre->m_pNext; + pNext = pCur->m_pNext; + ++cnt; + pCur->m_eType = JudgePointType(pPre->m_ptStart,pCur->m_ptStart,pNext->m_ptStart); + pPre = pCur; + } while (pPre!=pStartEdge); +} + +PointType Surface::JudgePointType(const Point_2& ptPre,const Point_2& ptCur,const Point_2& ptNext) +{ + if (PointUpperThan(ptCur,ptPre) && PointUpperThan(ptCur,ptNext)) + { + turn_dir_t turn = GetTurnType(ptPre,ptCur,ptNext); + if (turn==turn_left) + { + return PT_BEGIN; + } + else + return PT_SPLIT; + + } + if (PointUpperThan(ptPre,ptCur) && PointUpperThan(ptCur,ptNext)) + { + return PT_REGULARLEFT; + } + if (PointUpperThan(ptCur,ptPre) && PointUpperThan(ptNext,ptCur)) + { + return PT_REGULARRIGHT; + } + if (PointUpperThan(ptPre,ptCur) && PointUpperThan(ptNext,ptCur)) + { + turn_dir_t turn = GetTurnType(ptPre,ptCur,ptNext); + if (turn==turn_left) + { + return PT_END; + } + else + return PT_MERGE; + } + //ASSERT(0); + return PT_NULL; +} + +bool Surface::MakeSurface(const Point_2& ptStart_, const vector& vecInput ,const vector& vecBulge) +{ + GeoGetDoubleEdgeFactory()->ClearMajorIdCount(); + GeoGetDoubleEdgeFactory()->ClearMinorIdCount(); + int num = (int)vecInput.size(); + + m_nEdgeCount = 0; + m_ptCurStart = ptStart_; + + for (int i=0;i=1) + OutPutEdgeInfo(); +#endif +#if (_DEBUG_LEVEL==2) + ofstream Ofile; + Ofile.open("D:\\InputPolygon.txt"); + OutPutEdgeForDebug(Ofile); + Ofile.close(); +#endif + if (area<0) + { + return false; + } + else + { + return true; + } +} + +//m_ptEdge 为起点,pt为终点:直线段,直接加入;圆弧先打散,再加入 +void Surface::AddTail(const Point_2& pt,const double& nBulge) +{ + if (DOUBLE_EQU_ZERO(nBulge)) + { + DoubleEdge* pNewEdge = GeoGetDoubleEdgeFactory()->ConstructLineEdge(m_ptCurStart); + m_ptCurStart = pt; + if (m_nEdgeCount==0) + { + m_ptEdge = pNewEdge; + m_ptEdge->m_pNext = m_ptEdge->m_pPre = m_ptEdge; + } + else + { + pNewEdge->m_pNext = m_ptEdge->m_pNext; + m_ptEdge->m_pNext->m_pPre = pNewEdge; + m_ptEdge->m_pNext = pNewEdge; + pNewEdge->m_pPre = m_ptEdge; + m_ptEdge = pNewEdge; + } + m_nEdgeCount++; + } + else + { + DoubleEdge* ptArcStartEdge = NULL; + DoubleEdge* ptArcEndEdge = NULL; + int segCnt = GeoGetDoubleEdgeFactory()->ConstructArcEdge(m_ptCurStart,pt,nBulge,ptArcStartEdge,ptArcEndEdge); + m_ptCurStart = pt; + if (m_nEdgeCount==0) + { + ptArcStartEdge->m_pPre = ptArcEndEdge; + ptArcEndEdge->m_pNext = ptArcStartEdge; + m_ptEdge = ptArcEndEdge; + } + else + { + ptArcEndEdge->m_pNext = m_ptEdge->m_pNext; + m_ptEdge->m_pNext->m_pPre = ptArcEndEdge; + m_ptEdge->m_pNext = ptArcStartEdge; + ptArcStartEdge->m_pPre = m_ptEdge; + m_ptEdge = ptArcEndEdge; + } + + m_nEdgeCount += segCnt; + } + +} + +void Surface::OutPutEdgeInfo(ostream& os) +{ + DoubleEdge* pCurEdge = m_ptEdge; + for (int i=0;im_edgeId.MajorIndex<<" Start is: "; + pCurEdge->m_ptStart.OutPut(os); + os<<"Type is "<m_eType]<m_pNext; + } +} + +void Surface::OutPutEdge(ostream& os) +{ + DoubleEdge* pCurEdge = m_ptEdge; +#if (_DEBUG_LEVEL>=1) + os<<"Polygon is : "<m_nId<<" Start is: "; + pCurEdge->m_ptStart.OutPut(os); + //os<<"Type is "<m_eType]<m_pNext; + } + os<m_pNext; + os<m_ptStart.x<<" "<m_ptStart.y<m_pNext; + } +} + +void Surface::ReverseSurface() +{ + DoubleEdge* pCurEdge = m_ptEdge; + stack st; + + for (int i=0;im_pNext; + } + while (!st.empty()) + { + pCurEdge = st.top(); + st.pop(); + DoubleEdge* pTmp = pCurEdge->m_pNext; + pCurEdge->m_pNext = pCurEdge->m_pPre; + pCurEdge->m_pPre = pTmp; + //pCurEdge->m_nId = m_nEdgeCount-1-pCurEdge->m_nId ; + + } +} + + +bool Surface::DoTriangulate(vector& vecOutput) +{ + if (m_bIsYMonotone==false) + { + return false; + } + if (m_nEdgeCount==3) + { + Surface* pNewSurface = new Surface; + pNewSurface->m_bIsYMonotone = true; + pNewSurface->m_ptEdge = m_ptEdge; + pNewSurface->m_nEdgeCount = m_nEdgeCount; + vecOutput.push_back(pNewSurface); + return true; + } + + set setEdges; + DoubleEdge* pCurEdge = m_ptEdge; + for (int i=0;im_pNext; + } + + set::iterator Iter ; + + //calculate the edge side type + Iter = setEdges.begin(); + DoubleEdgeRep& refEdge = (*Iter); + DoubleEdge* pEdge = refEdge.m_pEdge; + Point_2 ptStart = pEdge->m_ptStart; + DoubleEdge* pNextEdge ; + Point_2 ptEnd ; + do + { + pNextEdge = pEdge->m_pNext; + ptEnd = pNextEdge->m_ptStart; + if (ptStartm_eEdgeSide = ELeftEdge; + pEdge = pNextEdge; + ptStart = ptEnd; + } + else + break; + } while (1); + do + { + pNextEdge = pEdge->m_pNext; + ptEnd = pNextEdge->m_ptStart; + if (ptEndm_eEdgeSide = ERightEdge; + pEdge = pNextEdge; + ptStart = ptEnd; + } + else + break; + } while (1); + //~calculate the edge side type + + stack st; + for (int i=0;i<2;i++) + { + Iter = setEdges.begin(); + DoubleEdgeRep& CurEdge = (*Iter); + st.push(CurEdge); + setEdges.erase(CurEdge); + } + + while (setEdges.size()>0) + { + Iter = setEdges.begin(); + DoubleEdgeRep& CurEdge = (*Iter); + DoubleEdge* pCurEdge = CurEdge.m_pEdge; + setEdges.erase(CurEdge); + + if (pCurEdge->m_pNext->m_pNext==pCurEdge->m_pPre) + { + Surface* pNewSurface = new Surface(pCurEdge,true); + vecOutput.push_back(pNewSurface); + continue; + } + + DoubleEdgeRep lastInStack = st.top(); + + //same side + if (lastInStack.m_pEdge->m_eEdgeSide == pCurEdge->m_eEdgeSide) + { + st.pop(); //弹出栈顶 + DoubleEdgeRep EdgeCanConnect; + + if (pCurEdge->m_eEdgeSide == ELeftEdge) + { + while(!st.empty()) + { + EdgeCanConnect = st.top(); + Point_2 ptCur = pCurEdge->m_ptStart; + Point_2 ptLastInStack = lastInStack.m_pEdge->m_ptStart; + Point_2 ptCanConnect = EdgeCanConnect.m_pEdge->m_ptStart; + Point_2 vec1(ptLastInStack.x - ptCur.x, ptLastInStack.y - ptCur.y); + Point_2 vec2(ptCanConnect.x - ptCur.x, ptCanConnect.y - ptCur.y); + turn_dir_t turnDir = GetTurnType(vec1,vec2); + if ( turnDir == turn_right ) //有可以分割出去的三角形 + { + //DoubleEdge* pCurToCanConnect = new DoubleEdge(ptCur); + //DoubleEdge* pCanConnectToCur = new DoubleEdge(ptCanConnect); + DoubleEdge* pCurToCanConnect = GeoGetDoubleEdgeFactory()->ConstructLineEdge(ptCur); + DoubleEdge* pCanConnectToCur = GeoGetDoubleEdgeFactory()->ConstructLineEdge(ptCanConnect); + + DoubleEdge* pPreCur = pCurEdge->m_pPre; + DoubleEdge* pPreCanConnect = EdgeCanConnect.m_pEdge->m_pPre; + + ConnectThreeEdge(lastInStack.m_pEdge,pCurToCanConnect,EdgeCanConnect.m_pEdge);//当前分割出的三角形 + ConnectThreeEdge(pPreCanConnect,pCanConnectToCur,pCurEdge); + + Surface* pNewSurface = new Surface(pCurToCanConnect,true); + vecOutput.push_back(pNewSurface); + + lastInStack = DoubleEdgeRep(pCanConnectToCur); + st.pop(); + } + else + { + break; + } + } + st.push(lastInStack); + st.push(DoubleEdgeRep(pCurEdge)); + } + else if (pCurEdge->m_eEdgeSide == ERightEdge) + { + while(!st.empty()) + { + EdgeCanConnect = st.top(); + Point_2 ptCur = pCurEdge->m_ptStart; + Point_2 ptLastInStack = lastInStack.m_pEdge->m_ptStart; + Point_2 ptCanConnect = EdgeCanConnect.m_pEdge->m_ptStart; + Point_2 vec1(ptLastInStack.x - ptCur.x, ptLastInStack.y - ptCur.y); + Point_2 vec2(ptCanConnect.x - ptCur.x, ptCanConnect.y - ptCur.y); + turn_dir_t turnDir = GetTurnType(vec1,vec2); + if ( turnDir == turn_left ) + { + //DoubleEdge* pCurToCanConnect = new DoubleEdge(ptCur); + //DoubleEdge* pCanConnectToCur = new DoubleEdge(ptCanConnect); + DoubleEdge* pCurToCanConnect = GeoGetDoubleEdgeFactory()->ConstructLineEdge(ptCur); + DoubleEdge* pCanConnectToCur = GeoGetDoubleEdgeFactory()->ConstructLineEdge(ptCanConnect); + + DoubleEdge* pPreCur = pCurEdge->m_pPre; + DoubleEdge* pPreCanConnect = EdgeCanConnect.m_pEdge->m_pPre; + + ConnectThreeEdge(pPreCanConnect,pCanConnectToCur,pCurEdge);//当前分割出的三角形 + ConnectThreeEdge(pPreCur,pCurToCanConnect,EdgeCanConnect.m_pEdge); + + Surface* pNewSurface = new Surface(pCanConnectToCur,true); + vecOutput.push_back(pNewSurface); + + lastInStack = EdgeCanConnect;//注意左侧和右侧更新是不一样的, + pCurEdge = pCurToCanConnect; + pCurEdge->m_eEdgeSide = ERightEdge; + + st.pop(); + } + else + { + break; + } + } + st.push(lastInStack); + st.push(DoubleEdgeRep(pCurEdge)); + } + } + else //curEdge is on the another side + { + stack newSt; + + while (!st.empty()) + { + newSt.push(st.top()); st.pop(); + } + + DoubleEdgeRep topEdge = newSt.top(); + newSt.pop(); + + while(!newSt.empty()) + { + DoubleEdgeRep EdgeCanConnect = newSt.top(); + newSt.pop(); + + DoubleEdge* pPreCur = pCurEdge->m_pPre; + DoubleEdge* pPreCanConnect = EdgeCanConnect.m_pEdge->m_pPre; + + //DoubleEdge* pCurToCanConnect = new DoubleEdge(pCurEdge->m_ptStart); + //DoubleEdge* pCanConnectToCur = new DoubleEdge(EdgeCanConnect.m_pEdge->m_ptStart); + DoubleEdge* pCurToCanConnect = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pCurEdge->m_ptStart); + DoubleEdge* pCanConnectToCur = GeoGetDoubleEdgeFactory()->ConstructLineEdge(EdgeCanConnect.m_pEdge->m_ptStart); + + ConnectThreeEdge(pPreCur,pCurToCanConnect,EdgeCanConnect.m_pEdge); + ConnectThreeEdge(pPreCanConnect,pCanConnectToCur,pCurEdge); + + DoubleEdge* pNewSurfaceEdge ; + + if (pCurEdge->m_eEdgeSide == ELeftEdge) + { + pNewSurfaceEdge = pCurToCanConnect; + } + else + { + pNewSurfaceEdge = pCanConnectToCur; + pCurEdge = pCurToCanConnect; + pCurEdge->m_eEdgeSide = ERightEdge; + } + Surface* pNewSurface = new Surface(pNewSurfaceEdge,true); + vecOutput.push_back(pNewSurface); + } + if (pCurEdge->m_eEdgeSide==ELeftEdge) + { + //pCurEdge->m_pPre->m_eEdgeSide = ELeftEdge; + st.push(DoubleEdgeRep(pCurEdge->m_pPre)); + st.push(DoubleEdgeRep(pCurEdge)); + } + else + { + st.push(DoubleEdgeRep(pCurEdge->m_pNext)); + st.push(DoubleEdgeRep(pCurEdge)); + } + + } + } + return true; +} + + + +bool StatusLine::InsertNode(DoubleEdge* pEdge) +{ + StatusLineNode* pParentNode = &m_nullNode ; + StatusLineNode* pCurNode = m_pRoot; + +#if (_DEBUG_LEVEL==2) + cout<<"Insert: "<m_edgeId.MajorIndex<<" "<m_edgeId.MinorIndex<m_pData); + if (CompRes == 0) + { + return false; //the node have exist in the tree; + } + else if ( -1 == CompRes ) + { + pCurNode = pCurNode->m_pLeft; + } + else if ( 1 == CompRes ) + { + pCurNode = pCurNode->m_pRight; + } + } + + if (pParentNode == &m_nullNode) //we have no nodes + { + _ASSERT(numSegs==0); + m_pRoot = new StatusLineNode(pEdge,&m_nullNode,&m_nullNode,&m_nullNode,BLACK); + m_nullNode.m_pLeft = m_nullNode.m_pRight = m_pRoot; + ++numSegs; + return true; + } + else + { //now the pCurNode parent Node ,under which we insert our new node + StatusLineNode* pNewNode = new StatusLineNode(pEdge,pParentNode,&m_nullNode,&m_nullNode,RED); + if (1 == CompRes) + { + pParentNode->m_pRight = pNewNode; + } + else + { + pParentNode->m_pLeft = pNewNode; + } + if (pParentNode->color==RED) + { + FixInsertNode(pNewNode); + } + ++numSegs; + return true; + } + +} + + +void StatusLine::FixInsertNode(StatusLineNode* pCurNode) +{ + StatusLineNode* pUncle = NULL; + while(pCurNode->m_pParent->color==RED)//pCurNode->color==RED && pParent->color == RED + { + if ( pCurNode->m_pParent == pCurNode->m_pParent->m_pParent->m_pLeft) + { + pUncle = pCurNode->m_pParent->m_pParent->m_pRight; + if (pUncle->color == RED) + { + pCurNode->m_pParent->color = BLACK; + pUncle->color = BLACK; + pCurNode->m_pParent->m_pParent->color = RED; + pCurNode = pCurNode->m_pParent->m_pParent; + } + else + { + if (pCurNode==pCurNode->m_pParent->m_pRight) + { + pCurNode = pCurNode->m_pParent; + LeftRotation(pCurNode); + } + pCurNode->m_pParent->color = BLACK; + pCurNode->m_pParent->m_pParent->color = RED; + RightRotation(pCurNode->m_pParent->m_pParent); + } + } + else + { + pUncle = pCurNode->m_pParent->m_pParent->m_pLeft; + if (pUncle->color==RED) + { + pCurNode->m_pParent->color = BLACK; + pUncle->color = BLACK; + pCurNode->m_pParent->m_pParent->color = RED; + pCurNode = pCurNode->m_pParent->m_pParent; + } + else + { + if (pCurNode==pCurNode->m_pParent->m_pLeft) + { + pCurNode = pCurNode->m_pParent; + RightRotation(pCurNode); + } + pCurNode->m_pParent->color = BLACK; + pCurNode->m_pParent->m_pParent->color = RED; + LeftRotation(pCurNode->m_pParent->m_pParent); + } + } + } + m_pRoot->color = BLACK; +} + +void StatusLine::LeftRotation(StatusLineNode* pCurNode) +{ + StatusLineNode* pParent = pCurNode->m_pParent; + StatusLineNode* pRight = pCurNode->m_pRight; // up this node + StatusLineNode* pRightLeft = pRight->m_pLeft; + _ASSERT(pRight!=&m_nullNode); + + if (pParent == &m_nullNode) + { + m_pRoot = pRight; + m_nullNode.m_pLeft = m_pRoot; + } + else + { + pCurNode == pParent->m_pLeft? pParent->m_pLeft = pRight: pParent->m_pRight = pRight; + } + + if (pRightLeft!=&m_nullNode) + { + pRightLeft->m_pParent = pCurNode; + } + else + { +#if (_DEBUG_LEVEL==2) + cout<<"Meet "<m_pLeft = pCurNode; + pRight->m_pParent = pParent; + + pCurNode->m_pRight = pRightLeft; + pCurNode->m_pParent = pRight; +} + +void StatusLine::RightRotation(StatusLineNode* pCurNode) +{ + StatusLineNode* pParent = pCurNode->m_pParent; + StatusLineNode* pLeft = pCurNode->m_pLeft; + StatusLineNode* pLeftRight = pLeft->m_pRight; + + _ASSERT(pLeft!=&m_nullNode); + + if (pParent == &m_nullNode) + { + m_pRoot = pLeft; + m_nullNode.m_pLeft = m_pRoot; + } + else + { + pCurNode == pParent->m_pLeft? pParent->m_pLeft = pLeft: pParent->m_pRight = pLeft; + } + + if (pLeftRight!=&m_nullNode) + { + pLeftRight->m_pParent = pCurNode; + } + else + { +#if (_DEBUG_LEVEL==2) + cout<<"Meet "<m_pRight = pCurNode; + pLeft->m_pParent = pParent; + + pCurNode->m_pLeft = pLeftRight; + pCurNode->m_pParent = pLeft; +} + +void StatusLine::Transplant(StatusLineNode* pU,StatusLineNode* pV) +{ + if (pU->m_pParent == &m_nullNode) + { + m_pRoot = pV; + } + else if ( pU == pU->m_pParent->m_pLeft) + { + pU->m_pParent->m_pLeft = pV; + } + else + { + pU->m_pParent->m_pRight = pV; + } + pV->m_pParent = pU->m_pParent; +} + + +bool StatusLine::EraseNode(DoubleEdge* pEdge) +{ + if (m_pRoot==&m_nullNode)//m_pRoot==NULL + { + _ASSERT(numSegs == 0); + return false; + } + //1 find this node + StatusLineNode* pCurNode = m_pRoot; + +#if (_DEBUG_LEVEL==2) + cout<<"EraseNode: "<m_edgeId.MajorIndex<<" "<m_edgeId.MinorIndex<m_pData) ; + if ( 0 == CompRes ) + { + break; + } + else if ( CompRes == -1 ) + { + if (pCurNode->m_pLeft!=&m_nullNode) + { + pCurNode = pCurNode->m_pLeft; + } + else + return false; + } + else if ( CompRes == 1 ) + { + if (pCurNode->m_pRight != &m_nullNode) + { + pCurNode = pCurNode->m_pRight; + } + else + return false; + } + } while (true); + + StatusLineNode* pY = pCurNode; + StatusLineNode* pX ; + COLOR ycolor = pCurNode->color; + + if (pCurNode->m_pLeft == &m_nullNode) + { + pX = pCurNode->m_pRight; + Transplant(pCurNode,pCurNode->m_pRight); + } + else if (pCurNode->m_pRight == &m_nullNode) + { + pX = pCurNode->m_pLeft; + Transplant(pCurNode,pCurNode->m_pLeft); + } + else + { + pY = Minimum(pCurNode->m_pRight); + ycolor = pY->color; + pX = pY->m_pRight; + if (pY->m_pParent == pCurNode) //pY is the right child of pCurNode (pY always have no left child) + { + pX->m_pParent = pY; + } + else + { + Transplant(pY,pY->m_pRight); + pY->m_pRight = pCurNode->m_pRight; + pY->m_pRight->m_pParent = pY; + } + Transplant(pCurNode,pY); + pY->m_pLeft = pCurNode->m_pLeft; + pY->m_pLeft->m_pParent = pY; + pY->color = pCurNode->color; + + } + delete pCurNode; + if (ycolor==BLACK) + { + FixDeleteNode(pX); + } + + --numSegs; + + return true; +} + +void StatusLine::FixDeleteNode(StatusLineNode* pCurNode) +{ + + StatusLineNode* pUncle = NULL ; + //pCurNode is not root and color is black + while( pCurNode!=m_pRoot && pCurNode->color==BLACK) + { + if (pCurNode==pCurNode->m_pParent->m_pLeft) + { + pUncle = pCurNode->m_pParent->m_pRight; + if (pUncle->color==RED) + { + pUncle->color = BLACK; + pCurNode->m_pParent->color = RED; + LeftRotation(pCurNode->m_pParent); + pUncle = pCurNode->m_pParent->m_pRight; + } + if (pUncle->m_pLeft->color == BLACK && pUncle->m_pRight->color == BLACK) + { + pUncle->color = RED; + pCurNode = pCurNode->m_pParent; + } + else + { + if (pUncle->m_pRight->color == BLACK) + { + //此时要知道 pUncle->m_pLeft->color == RED,所以换色右旋 + pUncle->m_pLeft->color = BLACK; + pUncle->color = RED; + RightRotation(pUncle); + pUncle = pCurNode->m_pParent->m_pRight; //pUncle = pCurNode->m_pParent->m_pRight; + } + pUncle->color = pCurNode->m_pParent->color; + pCurNode->m_pParent->color = BLACK; + pUncle->m_pRight->color = BLACK; + LeftRotation(pCurNode->m_pParent); + pCurNode = m_pRoot; + } + } + else + { + pUncle = pCurNode->m_pParent->m_pLeft; + if (pUncle->color==RED) + { + pUncle->color = BLACK; + pCurNode->m_pParent->color = RED; + RightRotation(pCurNode->m_pParent); + pUncle = pCurNode->m_pParent->m_pLeft; + } + + if (pUncle->m_pLeft->color==BLACK && pUncle->m_pRight->color==BLACK) + { + pUncle->color = RED; + pCurNode = pCurNode->m_pParent; + } + else + { + if (pUncle->m_pLeft->color == BLACK) + { + pUncle->color = RED; + pUncle->m_pRight->color = BLACK; + LeftRotation(pUncle); + pUncle = pCurNode->m_pParent->m_pLeft; //pUncle = pCurNode->m_pParent->m_pLeft; + } + pUncle->color = pCurNode->m_pParent->color; + pCurNode->m_pParent->color = BLACK; + pUncle->m_pLeft->color = BLACK; + RightRotation(pCurNode->m_pParent); + pCurNode = m_pRoot; + } + } + } + pCurNode->color = BLACK; + //m_pRoot = m_nullNode.m_pLeft; +} + +StatusLine::StatusLineNode* StatusLine::Minimum(StatusLineNode* pCurNode) +{ + while (pCurNode->m_pLeft!=&m_nullNode) + { + pCurNode = pCurNode->m_pLeft; + } + return pCurNode; +} + +StatusLine::iterator StatusLine::Find(DoubleEdge* pEdge) +{ + if (m_pRoot==&m_nullNode) + { + return iterator(this,NULL); + } + StatusLineNode* pCurNode = m_pRoot; + + do + { + int CompRes = CompareDoubleEdge(pEdge,pCurNode->m_pData); + if (CompRes == 0) + { + return iterator(this,pCurNode); + } + else if (CompRes==-1) + { + if (pCurNode->m_pLeft!=&m_nullNode) + { + pCurNode = pCurNode->m_pLeft; + } + else + break; + } + else if (CompRes==1) + { + if (pCurNode->m_pRight!=&m_nullNode) + { + pCurNode = pCurNode->m_pRight; + } + else + break; + } + } while (true); + + return iterator(this,NULL); +} + +StatusLine::StatusLineNode* StatusLine::GetMinNode() +{ + if (m_pRoot==NULL) + { + return NULL; + } + StatusLineNode* pCurNode = m_pRoot; + + while (pCurNode->m_pLeft!=&m_nullNode) + { + pCurNode = pCurNode->m_pLeft; + } + return pCurNode; +} + +StatusLine::StatusLineNode* StatusLine::GetMaxNode() +{ + if (m_pRoot== &m_nullNode) + { + return NULL; + } + StatusLineNode* pCurNode = m_pRoot; + + while (pCurNode->m_pRight!=&m_nullNode) + { + pCurNode = pCurNode->m_pRight; + } + return pCurNode; +} + +StatusLine::StatusLineNode* StatusLine::GetPrev(StatusLineNode* pCurNode) +{ + if (pCurNode==NULL) + { + return NULL; + } + if (pCurNode->m_pLeft!=&m_nullNode) + { + StatusLineNode* pTmp = pCurNode->m_pLeft; + while (pTmp->m_pRight!=&m_nullNode) + { + pTmp = pTmp->m_pRight; + } + return pTmp; + } + else + { + StatusLineNode* pParent = pCurNode->m_pParent; + +NEXT: + if (pParent==&m_nullNode) + { + return NULL; + } + else + { + if (pCurNode == pParent->m_pRight) + { + return pParent; + } + else + { + pCurNode = pParent; + pParent = pParent->m_pParent; + goto NEXT; + } + } + } +} + +StatusLine::StatusLineNode* StatusLine::GetNext(StatusLineNode* pCurNode) +{ + if (pCurNode->m_pRight!=&m_nullNode) + { + StatusLineNode* pTmp = pCurNode->m_pRight; + while(pTmp->m_pLeft!=&m_nullNode) + { + pTmp = pTmp->m_pLeft; + } + return pTmp; + } + else + { + StatusLineNode* pParent = pCurNode->m_pParent; + +NEXT: + if (pParent==&m_nullNode) + { + return NULL; + } + else + { + if (pCurNode == pParent->m_pLeft) + { + return pParent; + } + else + { + pCurNode = pParent; + pParent = pParent->m_pParent; + goto NEXT; + } + } + + } +} + +StatusLine::iterator StatusLine::begin() +{ + iterator ItBegin(this,GetMinNode()); + return ItBegin; +} + +StatusLine::iterator StatusLine::end() +{ + iterator endIt(this,NULL); + return endIt; +} + +bool StatusLine::erase(iterator Iter) +{ + return EraseNode(Iter.m_pCurNode->m_pData); +} + +bool StatusLine::EraseAllNode() +{ + if (m_pRoot==&m_nullNode) + { + return true; + } + if (m_pRoot->m_pLeft!=&m_nullNode) + { + EraseSubTree(m_pRoot->m_pLeft); + } + if (m_pRoot->m_pRight!=&m_nullNode) + { + EraseSubTree(m_pRoot->m_pRight); + } + delete m_pRoot; + return true; +} + +bool StatusLine::EraseSubTree(StatusLineNode* pNode) +{ + if (pNode->m_pLeft!=&m_nullNode) + { + EraseSubTree(pNode->m_pLeft); + } + if (pNode->m_pRight!=&m_nullNode) + { + EraseSubTree(pNode->m_pRight); + } + delete pNode; + return true; +} + +DoubleEdge* StatusLine::FindDirectLeft(Point_2 ptPoint) +{ + StatusLineNode* pParent = &m_nullNode; + StatusLineNode* pCurNode = GetMaxNode(); + + if (pCurNode==NULL) + { + return NULL;// + } + + double curY = ptPoint.y; + double IntersectionX ; + + while (pCurNode!=NULL) + { + Point_2 ptStart = pCurNode->m_pData->m_ptStart; + Point_2 ptEnd = pCurNode->m_pData->m_pNext->m_ptStart; + //bug may come from here + if (DOUBLE_EQU(ptStart.y,ptEnd.y))//abs(ptStart.y-ptEnd.y)<1.e-9 + { + IntersectionX = max(ptStart.x,ptEnd.x); + } + else + { + IntersectionX = (curY-ptStart.y)*(ptEnd.x-ptStart.x)/(ptEnd.y-ptStart.y) + ptStart.x;// + } + if (IntersectionX+1.e-9m_pData; + } + else + { + pCurNode = GetPrev(pCurNode); + } + } + + return NULL; +} + +Triangulation::Triangulation(void) +{ +} + +Triangulation::~Triangulation(void) +{ + int n = (int)m_OutTriangle.size(); + for (int i=0;iClearMajorIdCount(); + //GeoGetDoubleEdgeFactory()->ClearMinorIdCount(); +} + +Surface* Triangulation::MakeYMonotone(int nSegmentNo_) +{ + m_InputSurface.MakeSurface(m_ptStart,vecInput,vecBulge); + + m_polyEdgeNum = (int)vecInput.size(); + + //Insert all edges into set + DoubleEdge* pStartEdge = m_InputSurface.m_ptEdge; + DoubleEdge* pCurEdge = pStartEdge; + + do + { + m_setEdge.insert(DoubleEdgeRep(pCurEdge)); + pCurEdge = pCurEdge->m_pNext; + } while (pCurEdge!=pStartEdge); + + // m_polyEdgeNum = DoubleEdge::s_IdCount; + + int ret = 0; + int cnt = 0; + while (m_setEdge.size()>0) + { + ++cnt; + set::iterator Iter = m_setEdge.begin(); + DoubleEdgeRep& CurEdge = (*Iter); + + DoubleEdge* pCurEdge = CurEdge.m_pEdge; + m_setEdge.erase(CurEdge); + + PointType pType = pCurEdge->m_eType; + + m_StatusLine.SetCurPosition(pCurEdge->m_ptStart); + switch(pType) + { + case PT_BEGIN: + { + ret = ProcessBeginPoint(pCurEdge); + } + break; + case PT_END: + { + ret = ProcessEndPoint(pCurEdge); + } + break; + case PT_REGULARLEFT: + case PT_REGULARRIGHT: + { + ret = ProcessRegularPoint(pCurEdge); + } + break; + case PT_MERGE: + { + ret = ProcessMergePoint(pCurEdge); + } + break; + case PT_SPLIT: + { + ret = ProcessSplitPoint(pCurEdge); + } + break; + } + +//#ifdef _DEBUG + if (ret==0) + { + cout<=1) + cout<<"Polygone :"<OutPutEdge(cout); + vecSurface[i]->OutPutEdgeForDebug(OutDebugFile); +#endif + Surface* curPoly = vecSurface[i]; + + DoubleEdge* pStartEdge = curPoly->m_ptEdge; + DoubleEdge* pCurEdge = pStartEdge; + + do + { + if (pCurEdge->m_edgeId.MajorIndex == nSegmentNo_) // to do + { + curPoly->m_ptEdge = pCurEdge; + return curPoly; + } + pCurEdge = pCurEdge->m_pNext; + } while (pCurEdge!=pStartEdge); + } +#if (_DEBUG_LEVEL==2) + OutDebugFile.close(); +#endif + return NULL; +} + +Surface* Triangulation::DoTriangle(int& nSegmentNo_) +{ + ReleaseOutTriangle(); + + GeoGetDoubleEdgeFactory()->ClearMajorIdCount(); + GeoGetDoubleEdgeFactory()->ClearMinorIdCount(); + GeoGetDoubleEdgeFactory()->SetTriangulation(this); + MakeYMonotone(nSegmentNo_); + + ReleaseOutTriangle(); + + //三角形剖分,将所有三角形输入到OutTriangle中 + for (int i=0;iDoTriangulate(m_OutTriangle); + } + + if (nSegmentNo_!=-1) + { + cout<<"Triangles :"<=1) + m_OutTriangle[i]->OutPutEdge(cout); +#endif + Surface* curTriangle = m_OutTriangle[i]; + DoubleEdge* Edge1 = curTriangle->m_ptEdge; + DoubleEdge* Edge2 = Edge1->m_pNext; + DoubleEdge* Edge3 = Edge2->m_pNext; + if (Edge1->m_edgeId.MajorIndex == nSegmentNo_ || Edge2->m_edgeId.MajorIndex==nSegmentNo_ ||Edge3->m_edgeId.MajorIndex==nSegmentNo_ ) + { + return curTriangle; + } + } + } + else //寻找合适的线段,来插入引刀线。 + { + for(int i=0;iArea(); + DoubleEdge* Edge1 = curTriangle->m_ptEdge; + DoubleEdge* Edge2 = Edge1->m_pNext; + DoubleEdge* Edge3 = Edge2->m_pNext; + if (Edge1->m_edgeId.MajorIndex < m_polyEdgeNum || Edge2->m_edgeId.MajorIndex < m_polyEdgeNum ||Edge3->m_edgeId.MajorIndex < m_polyEdgeNum) + { + mp_AreaToID[Area] = i; + } + } + map::iterator Iter = mp_AreaToID.begin(), + IterEnd = mp_AreaToID.end(); + --IterEnd; + Surface* curTriangle = NULL; + map mpLenToId; + do + { + mpLenToId.clear(); + curTriangle = m_OutTriangle[(*IterEnd).second]; + DoubleEdge* Edge1 = curTriangle->m_ptEdge; + DoubleEdge* Edge2 = Edge1->m_pNext; + DoubleEdge* Edge3 = Edge2->m_pNext; + //double nLen = m_IODistance + m_InIntraLen + m_OutIntraLen; + //double nPowerLen = nLen*nLen; + double nEdgePowerLen1; + double nEdgePowerLen2; + double nEdgePowerLen3; + + if(Edge1->m_edgeId.MajorIndex < m_polyEdgeNum) + { + nEdgePowerLen1 = PowerDistance(Edge1->m_ptStart ,Edge2->m_ptStart); + nSegmentNo_ = Edge1->m_edgeId.MajorIndex; + + //if(nEdgePowerLen>=nPowerLen) + //{ + mpLenToId[nEdgePowerLen1] = nSegmentNo_; + //nSegmentNo_ = Edge1->m_nId; + //nEdgeLen = sqrt(nEdgePowerLen1); + //Ratio = (nEdgeLen - m_IODistance)/2 / nEdgeLen; + + //return curTriangle; + //} + } + if(Edge2->m_edgeId.MajorIndex < m_polyEdgeNum) + { + nEdgePowerLen2 = PowerDistance(Edge2->m_ptStart ,Edge3->m_ptStart); + nSegmentNo_ = Edge2->m_edgeId.MajorIndex; + + mpLenToId[nEdgePowerLen2] = nSegmentNo_; + //if(nEdgePowerLen>=nPowerLen) + //{ + //nSegmentNo_ = Edge2->m_nId; + //nEdgeLen = sqrt(nEdgePowerLen2); + //Ratio = (nEdgeLen - m_IODistance)/2 / nEdgeLen; + //return curTriangle; + //} + } + + if(Edge3->m_edgeId.MajorIndex < m_polyEdgeNum) + { + nEdgePowerLen3 = PowerDistance(Edge3->m_ptStart ,Edge1->m_ptStart); + nSegmentNo_ = Edge3->m_edgeId.MajorIndex; + mpLenToId[nEdgePowerLen3] = nSegmentNo_; + //if(nEdgePowerLen>=nPowerLen) + //{ + //nSegmentNo_ = Edge3->m_nId; + //nEdgeLen = sqrt(nEdgePowerLen3); + //Ratio = (nEdgeLen - m_IODistance)/2 / nEdgeLen; + //return curTriangle; + //} + } + if (Iter==IterEnd || mpLenToId.size()>=1) + { + break; + } + }while(1); + + //IterEnd = mp_AreaToID.end(); + //--IterEnd; + //return curTriangle=m_OutTriangle[nSegmentNo_]; + map::iterator EdgeIter = mpLenToId.end(); + --EdgeIter; + nSegmentNo_ = (*EdgeIter).second; + return curTriangle; + + } + + return NULL; +} + +Surface* Triangulation::DoYMonotone(int& nSegmentNo_ , LLInformation* pLLInformation_, DestEdgeInfo& destEdgeInfo_) +{ + ReleaseOutTriangle(); + + GeoGetDoubleEdgeFactory()->ClearMajorIdCount(); + GeoGetDoubleEdgeFactory()->ClearMinorIdCount(); + GeoGetDoubleEdgeFactory()->SetTriangulation(this); + + MakeYMonotone(nSegmentNo_); + + vector vecOutYMonotone ;//= vecSurface; + + if (vecSurface.size()==0) + { + GeoGetDoubleEdgeFactory()->ClearMajorIdCount(); + GeoGetDoubleEdgeFactory()->ClearMinorIdCount(); + GeoGetDoubleEdgeFactory()->ReleaseEdges(); + m_InputSurface.m_nEdgeCount = 0; + m_InputSurface.ReleaseEdges(); + m_InputSurface.MakeSurface(m_ptStart,vecInput,vecBulge); + vecOutYMonotone.push_back(&m_InputSurface); + //return NULL; + } + else{ + vecOutYMonotone = vecSurface; + } + + + + if (nSegmentNo_!=-1) + { + cout<<"YMonotone :"<FindEdgeById(nSegmentNo_); + + if (pObjEdge!=NULL) + { + destEdgeInfo_.m_pDestEdge = pObjEdge; + return curYMonotone; + } + } + destEdgeInfo_.m_pDestEdge = NULL; + } + else //寻找合适的线段,来插入引刀线。 + { + map, set > > mpAreaSurfaceToLengthEdges; + map mpPEdgeToEdgeInfo; + for(int i=0;iOutPutEdgeForDebug(Ofile); + Ofile.close(); +#endif + double Area = curYMonotone->Area(); + DoubleEdge* pCurEdge = curYMonotone->m_ptEdge; + + do + { + if (pCurEdge->m_edgeId.MajorIndex < m_polyEdgeNum ) // to do + { + if (pCurEdge->m_edgeId.MinorIndex==-1) //当前段为直线 + { + double powlen = PowerDistance(pCurEdge->m_ptStart,pCurEdge->m_pNext->m_ptStart); + mpAreaSurfaceToLengthEdges[make_pair(Area,curYMonotone)].insert(make_pair(powlen,pCurEdge) ); //Area 面积,curYMonotone pair 对应的区域和 边 + pCurEdge = pCurEdge->m_pNext; + } + else + { + int ArcMajorIndex = pCurEdge->m_edgeId.MajorIndex; + int ArcMinorIndex = pCurEdge->m_edgeId.MinorIndex; + ArcInfo& arcInfo = m_mpIdxToArcInfo[ArcMajorIndex]; + double arclen = arcInfo.nLength; + int ArcSegNum = arcInfo.nArcSegNum; + int nTotalSeg = 1; + + //int tmpCnt = 1; + DoubleEdge* pCenterEdge = NULL; + DoubleEdge* pPreStart = pCurEdge; + DoubleEdge* pAfterEnd = pCurEdge; + //1 统计多少个 + do + { + pPreStart=pPreStart->m_pPre; + if (pPreStart->m_edgeId.MajorIndex == ArcMajorIndex) + { + ++nTotalSeg; + } + else + { + break; + } + } while (1); + do + { + pAfterEnd=pAfterEnd->m_pNext; + if (pAfterEnd==curYMonotone->m_ptEdge) + { + goto NEXTYMONOTONE; + } + if (pAfterEnd->m_edgeId.MajorIndex == ArcMajorIndex) + { + ++nTotalSeg; + } + else + { + break; + } + } while (1); + double curArcLen = arclen*((double)nTotalSeg/(double)ArcSegNum); + double powCurArcLen = curArcLen*curArcLen; + int nHalf = nTotalSeg/2; + + pCenterEdge = pPreStart->m_pNext; + + for (int i=0;i<=nHalf;i++) + { + pCenterEdge = pCenterEdge->m_pNext; + } + + //在处理圆弧的时候,我们将圆弧打散之后中间的线段保存,作为目标线段 + mpAreaSurfaceToLengthEdges[make_pair(Area,curYMonotone)].insert(make_pair(powCurArcLen,pCenterEdge) ); //Area 面积,curYMonotone pair 对应的区域和 边 + + DestEdgeInfo& _destEdgeInfo = mpPEdgeToEdgeInfo[pCenterEdge]; + _destEdgeInfo.m_nLength = curArcLen; + _destEdgeInfo.m_pDestEdge = pCenterEdge; + _destEdgeInfo.m_pArcStart = pPreStart->m_pNext; + _destEdgeInfo.m_pArcEnd = pAfterEnd->m_pPre; + + ASSERT(_destEdgeInfo.m_pArcStart->m_edgeId.MajorIndex == _destEdgeInfo.m_pArcEnd->m_edgeId.MajorIndex); + + + pCurEdge = pAfterEnd; + } + } + else + { + pCurEdge = pCurEdge->m_pNext; + } + + } while (pCurEdge!=curYMonotone->m_ptEdge); +NEXTYMONOTONE: ; + } + + if (mpAreaSurfaceToLengthEdges.size()==0) + { + return NULL; + } + + map, set > >::iterator Iter = mpAreaSurfaceToLengthEdges.begin(), + IterEnd = mpAreaSurfaceToLengthEdges.end(); + + do //YMonotone面积 从最大面积到最小 + { + --IterEnd; + const pair& SurfaceEdgePair = (*IterEnd).first; + set >& setLengthEdge = (*IterEnd).second; + if (setLengthEdge.size()>1) + { + set >::iterator setLengthIterEnd = setLengthEdge.end(); + --setLengthIterEnd; + pair pr = (*setLengthIterEnd); + nSegmentNo_ = pr.second->m_edgeId.MajorIndex; // to do + destEdgeInfo_.m_pDestEdge = pr.second; + if ((pr.first)*0.9 < pLLInformation_->nIODistance*pLLInformation_->nIODistance) + { + if (IterEnd==Iter) + { + break; + } + continue; + } + if (pr.second->m_edgeId.MinorIndex!=-1) + { + destEdgeInfo_ = mpPEdgeToEdgeInfo[destEdgeInfo_.m_pDestEdge]; + } + return SurfaceEdgePair.second;//返回目标线段。圆弧情况下,是圆弧打散后中心的那个小线段 + } + if (IterEnd==Iter) + { + break; + } + }while(true); + } + return NULL; +} + +Surface* Triangulation::DoMakeSurface() +{ + m_InputSurface.MakeSurface(m_ptStart,vecInput,vecBulge); + return &m_InputSurface; +} + +Surface* Triangulation::DoTriangleMax(int& nSegmentNo_) +{ + ReleaseOutTriangle(); + + GeoGetDoubleEdgeFactory()->ClearMajorIdCount(); + GeoGetDoubleEdgeFactory()->ClearMinorIdCount(); + GeoGetDoubleEdgeFactory()->SetTriangulation(this); + MakeYMonotone(nSegmentNo_); + + ReleaseOutTriangle(); + + //三角形剖分,将所有三角形输入到OutTriangle中 + for (int i=0;iDoTriangulate(m_OutTriangle); + } + + + for(int i=0;iArea(); + DoubleEdge* Edge1 = curTriangle->m_ptEdge; + DoubleEdge* Edge2 = Edge1->m_pNext; + DoubleEdge* Edge3 = Edge2->m_pNext; + if (Edge1->m_edgeId.MajorIndex < m_polyEdgeNum || Edge2->m_edgeId.MajorIndex < m_polyEdgeNum ||Edge3->m_edgeId.MajorIndex < m_polyEdgeNum) + { + mp_AreaToID[Area] = i; + } + } + map::iterator Iter = mp_AreaToID.begin(), + IterEnd = mp_AreaToID.end(); + --IterEnd; + do + { + Surface* curTriangle = m_OutTriangle[(*IterEnd).second]; + DoubleEdge* Edge1 = curTriangle->m_ptEdge; + DoubleEdge* Edge2 = Edge1->m_pNext; + DoubleEdge* Edge3 = Edge2->m_pNext; + + if(Edge1->m_edgeId.MajorIndex < m_polyEdgeNum) + { + nSegmentNo_ = Edge1->m_edgeId.MajorIndex; + return curTriangle; + } + if(Edge2->m_edgeId.MajorIndex < m_polyEdgeNum) + { + nSegmentNo_ = Edge2->m_edgeId.MajorIndex; + return curTriangle; + } + + if(Edge3->m_edgeId.MajorIndex < m_polyEdgeNum) + { + nSegmentNo_ = Edge3->m_edgeId.MajorIndex; + return curTriangle; + } + --IterEnd; + }while(IterEnd != Iter); + + //如果来到这里,说明没有好的位置。 + IterEnd = mp_AreaToID.end(); + --IterEnd; + nSegmentNo_ = 0; + + + return NULL; +} + +bool Triangulation::ProcessBeginPoint(DoubleEdge* pCurEdge) +{ + CheckPointer(pCurEdge); + pCurEdge->UpdateHelper(pCurEdge); + m_StatusLine.InsertNode(pCurEdge); + return true; +} + +bool Triangulation::ProcessEndPoint(DoubleEdge* pCurEdge) +{ + CheckPointer(pCurEdge); + CheckPointer(pCurEdge->m_pPre); + + DoubleEdge* pPre = pCurEdge->m_pPre; + CheckPointer(pPre->m_ptHelper); + if(pPre->m_ptHelper->m_eType == PT_MERGE) + { + ConnectDiagonalEndPoint(pPre->m_ptHelper, pCurEdge);// + } + else + { + Surface* pNewSurface = new Surface(pCurEdge,true); + CheckPointer(pNewSurface); + pNewSurface->CheckSurface(); + vecSurface.push_back(pNewSurface); + } + m_StatusLine.EraseNode(pPre); + return true; +} + +bool Triangulation::ProcessRegularPoint(DoubleEdge* pCurEdge) +{ + CheckPointer(pCurEdge); + if (pCurEdge->m_eType==PT_REGULARLEFT) + { + CheckPointer(pCurEdge->m_pPre); + CheckPointer(pCurEdge->m_pNext); + DoubleEdge* pPreRegular = pCurEdge->m_pPre; + DoubleEdge* pNext = pCurEdge->m_pNext; + CheckPointer(pPreRegular->m_ptHelper); + if (pPreRegular->m_ptHelper->m_eType==PT_MERGE) + { + ConnectDiagonalLeftRegulerToMerge(pCurEdge,pPreRegular->m_ptHelper); + } + m_StatusLine.EraseNode(pPreRegular); + + CheckPointer(pNext->m_pPre); + DoubleEdge* pNewCurEdge = pNext->m_pPre; +#if (_DEBUG_LEVEL==2) + if (pNewCurEdge!=pCurEdge) + { + cout<<"ProcessRegularPoint LEFT pNewCurEdge!"<m_ptHelper = pCurEdge; + //m_StatusLine.InsertNode(pCurEdge); + pNewCurEdge->UpdateHelper(pNewCurEdge); + m_StatusLine.InsertNode(pNewCurEdge); + } + else + { + CheckPointer(pCurEdge->m_pPre); + DoubleEdge* pPreRegular = pCurEdge->m_pPre; + DoubleEdge* pDirectLeft = m_StatusLine.FindDirectLeft(pCurEdge->m_ptStart); + CheckPointer(pDirectLeft); + //same bug + DoubleEdge* pPre = pCurEdge->m_pPre; + CheckPointer(pDirectLeft->m_ptHelper); + if (pDirectLeft->m_ptHelper->m_eType==PT_MERGE) + { + ConnectDiagonalRightRegulerToMerge(pCurEdge,pDirectLeft->m_ptHelper); + } + DoubleEdge* pNewCurEdge = pPre->m_pNext; + CheckPointer(pNewCurEdge); + //pDirectLeft->UpdateHelper(pCurEdge); + pDirectLeft->UpdateHelper(pNewCurEdge); + } + + return true; +} + +bool Triangulation::ProcessMergePoint(DoubleEdge* pCurEdge) +{ + CheckPointer(pCurEdge); + DoubleEdge* pDirectLeft = m_StatusLine.FindDirectLeft(pCurEdge->m_ptStart); + CheckPointer(pDirectLeft); + CheckPointer(pCurEdge->m_pPre); + DoubleEdge* pPre = pCurEdge->m_pPre; + CheckPointer(pDirectLeft->m_ptHelper); + if (pDirectLeft->m_ptHelper->m_eType == PT_MERGE) + { + ConnectDiagonalMergeToLeftMerge(pCurEdge,pDirectLeft->m_ptHelper); + } + + CheckPointer(pPre->m_pNext); + //update the helper of the direct left edge + DoubleEdge* pNewCurEdge = pPre->m_pNext; + //pDirectLeft->UpdateHelper(pCurEdge); // + pDirectLeft->UpdateHelper(pNewCurEdge); // + + // + if (pNewCurEdge!=pCurEdge) + { + cout<<"ProcessMergePoint new CurEdge"<m_ptHelper); + //DoubleEdge* pPre = pCurEdge->m_pPre; + if (pPre->m_ptHelper->m_eType == PT_MERGE) + { + ConnectDiagonalMergeToRightMerge(pCurEdge,pPre->m_ptHelper); + } + //删除preEdge + m_StatusLine.EraseNode(pPre); + return true; +} + +bool Triangulation::ProcessSplitPoint(DoubleEdge* pCurEdge) +{ + CheckPointer(pCurEdge); + + DoubleEdge* pDirectLeft = m_StatusLine.FindDirectLeft(pCurEdge->m_ptStart); + + CheckPointer(pDirectLeft); + + CheckPointer(pCurEdge->m_pPre); + DoubleEdge* pPre = pCurEdge->m_pPre; + + CheckPointer(pDirectLeft->m_ptHelper); + ConnectDiagonalSplit(pCurEdge,pDirectLeft->m_ptHelper); + + CheckPointer(pPre->m_pNext); + DoubleEdge* pNewCurEdge = pPre->m_pNext; + + //pDirectLeft->UpdateHelper(pCurEdge); + //This bug is so tricky!!! ,上面的更新操作,会产生严重错误,文献中的描述只是一带而过,实现中应该很小心 + pDirectLeft->UpdateHelper(pNewCurEdge); + pCurEdge->UpdateHelper(pCurEdge); + m_StatusLine.InsertNode(pCurEdge); + + return true; +} + +//连接endPoint 和 mergePoint,生成2个Surface +bool Triangulation::ConnectDiagonalEndPoint(DoubleEdge* pEdgeMerge,DoubleEdge* pEdgeEnd) +{ + DoubleEdge* pPreMerge = pEdgeMerge->m_pPre; + DoubleEdge* pPreEnd = pEdgeEnd->m_pPre; + + DoubleEdge* pFromMerge = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeMerge->m_ptStart); + DoubleEdge* pFromEnd = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeEnd->m_ptStart); + + ConnectThreeEdge(pPreMerge,pFromMerge,pEdgeEnd); + ConnectThreeEdge(pPreEnd,pFromEnd,pEdgeMerge); + + Surface* pNewSurface1 = new Surface(pFromMerge,true); + Surface* pNewSurface2 = new Surface(pFromEnd,true); + + CheckPointer(pNewSurface1); + CheckPointer(pNewSurface2); + + pNewSurface1->CheckSurface(); + pNewSurface2->CheckSurface(); + + vecSurface.push_back(pNewSurface1); + vecSurface.push_back(pNewSurface2); + return true; +} + +//Merge 连接 左边Merge,有一个面被分割出去 +bool Triangulation::ConnectDiagonalMergeToLeftMerge(DoubleEdge* pEdgeMerge,DoubleEdge* pEdgeLeftMerge) +{ + DoubleEdge* pMergeToLeftMerge = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeMerge->m_ptStart); + DoubleEdge* pLeftMergeToMerge = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeLeftMerge->m_ptStart); + + DoubleEdge* pPreMerge = pEdgeMerge->m_pPre; + DoubleEdge* pPreLeftMerge = pEdgeLeftMerge->m_pPre; + + ConnectThreeEdge(pPreLeftMerge,pLeftMergeToMerge,pEdgeMerge); + ConnectThreeEdge(pPreMerge,pMergeToLeftMerge,pEdgeLeftMerge); + + Surface* pNewSurface = new Surface(pLeftMergeToMerge,true); //the Surface which can be split out + CheckPointer(pNewSurface); + pNewSurface->CheckSurface(); + vecSurface.push_back(pNewSurface); + + return true; +} + +//Merge 连接 右边Merge,有一个面被分割出去 +bool Triangulation::ConnectDiagonalMergeToRightMerge(DoubleEdge* pEdgeMerge,DoubleEdge* pEdgeRightMerge) +{ + DoubleEdge* pMergeToRightMerge = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeMerge->m_ptStart); + DoubleEdge* pRightMergeToMerge = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeRightMerge->m_ptStart); + + DoubleEdge* pPreMerge = pEdgeMerge->m_pPre; + DoubleEdge* pPreRightMerge = pEdgeRightMerge->m_pPre; + + ConnectThreeEdge(pPreRightMerge,pRightMergeToMerge,pEdgeMerge); + ConnectThreeEdge(pPreMerge,pMergeToRightMerge,pEdgeRightMerge); + + Surface* pNewSurface = new Surface(pMergeToRightMerge,true); //the Surface which can be split out + CheckPointer(pNewSurface); + pNewSurface->CheckSurface(); + vecSurface.push_back(pNewSurface); + return true; +} + +//split 连向 其它点,每一次split虽然有新的Surface生成,但是暂时不会加入到vecSurface中,因为还不能确定是否是 y 单调的 +bool Triangulation::ConnectDiagonalSplit(DoubleEdge* pEdgeSplit,DoubleEdge* pEdgeOther) +{ + DoubleEdge* pOtherToSplit = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeOther->m_ptStart); + DoubleEdge* pSplitToOther = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeSplit->m_ptStart); + + DoubleEdge* pSplitPre = pEdgeSplit->m_pPre; + DoubleEdge* pOtherPre = pEdgeOther->m_pPre; + + ConnectThreeEdge(pOtherPre,pOtherToSplit,pEdgeSplit); + ConnectThreeEdge(pSplitPre,pSplitToOther,pEdgeOther); + //pEdgeSplit = pSplitToOther; + return true; +} + +bool Triangulation::ConnectDiagonalLeftRegulerToMerge(DoubleEdge* pEdgeRegular,DoubleEdge* pEdgeMerge) +{ + DoubleEdge* pRegularToMerge = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeRegular->m_ptStart); + DoubleEdge* pMergeToRegular = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeMerge->m_ptStart); + + + DoubleEdge* pPreRegular = pEdgeRegular->m_pPre; + DoubleEdge* pPreMerge = pEdgeMerge->m_pPre; + + ConnectThreeEdge(pPreRegular,pRegularToMerge,pEdgeMerge); + ConnectThreeEdge(pPreMerge,pMergeToRegular,pEdgeRegular); + + Surface* pNewSurface = new Surface(pRegularToMerge,true); + CheckPointer(pNewSurface); + pNewSurface->CheckSurface(); + vecSurface.push_back(pNewSurface); + return true; +} + +bool Triangulation::ConnectDiagonalRightRegulerToMerge(DoubleEdge* pEdgeRegular,DoubleEdge* pEdgeMerge) +{ + DoubleEdge* pRegularToMerge = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeRegular->m_ptStart); + DoubleEdge* pMergeToRegular = GeoGetDoubleEdgeFactory()->ConstructLineEdge(pEdgeMerge->m_ptStart); + + DoubleEdge* pPreRegular = pEdgeRegular->m_pPre; + DoubleEdge* pPreMerge = pEdgeMerge->m_pPre; + + ConnectThreeEdge(pPreRegular,pRegularToMerge,pEdgeMerge); + ConnectThreeEdge(pPreMerge,pMergeToRegular,pEdgeRegular); + + Surface* pNewSurface = new Surface(pMergeToRegular,true); + CheckPointer(pNewSurface); + pNewSurface->CheckSurface(); + vecSurface.push_back(pNewSurface); + return true; +} + +void leadingline::ConnectThreeEdge(DoubleEdge* pFirst,DoubleEdge* pSecond,DoubleEdge* pThird) +{ + pFirst->m_pNext = pSecond; + pSecond->m_pPre = pFirst; + + pSecond->m_pNext = pThird; + pThird->m_pPre = pSecond; +} + + +//utility +void leadingline::DoRotationCCW(const Point_2& ptOrigin,const Point_2& ptStart,IN OUT Point_2& ptDest,double nAngle) +{ + double nCos = cos(nAngle); + double nSin = sin(nAngle); + + double Vx = ptStart.x - ptOrigin.x; + double Vy = ptStart.y - ptOrigin.y; + + double Dx = Vx*nCos - Vy*nSin; + double Dy = Vy*nCos + Vx*nSin; + + ptDest.x = ptOrigin.x + Dx; + ptDest.y = ptOrigin.y + Dy; +} + +void leadingline::DoRotationCW(Point_2 ptOrigin,Point_2 ptStart,Point_2& ptDest,double nAngle) +{ + //double nNewAngle = 2*c_nPI - nAngle; + //DoRotationCCW(ptOrigin, ptStart, ptDest,nNewAngle); + double nCos = cos(nAngle); + double nSin = sin(nAngle); + + double Vx = ptStart.x - ptOrigin.x; + double Vy = ptStart.y - ptOrigin.y; + + double Dx = Vx*nCos + Vy*nSin; + double Dy = Vy*nCos - Vx*nSin; + + ptDest.x = ptOrigin.x + Dx; + ptDest.y = ptOrigin.y + Dy; +} + +//向指定方向前进nLength距离 +void leadingline::GoFront(Point_2 ptCurPos,double nCos,double nSin,double nLength,Point_2& ptOut) +{ + ptOut.x = ptCurPos.x + nCos*nLength; + ptOut.y = ptCurPos.y + nSin*nLength; +} + +//判断ptPoint是否在三角形pTriangle中 +bool leadingline::IsInTriangle(Surface* pTriangle,Point_2 ptPoint) +{ + DoubleEdge* pEdge = pTriangle->m_ptEdge; + for (int i=0;i<3;i++) + { + Point_2 ptStart = pEdge->m_ptStart; + Point_2 ptEnd = pEdge->m_pNext->m_ptStart; + if (!IsLeftOf(ptPoint,ptStart,ptEnd)) + { + return false; + } + pEdge = pEdge->m_pNext; + } + return true; +} + +bool leadingline::IsLeftOf(Point_2 ptPoint,Point_2 ptStart,Point_2 ptEnd) +{ + double dx1 = ptEnd.x - ptStart.x; + double dy1 = ptEnd.y - ptStart.y; + double dx2 = ptPoint.x - ptStart.x; + double dy2 = ptPoint.y - ptStart.y; + double b = dx1*dy2 - dx2*dy1; + if (b>0) + { + return true; + } + return false; +} + +double leadingline::PowerDistance(Point_2 ptStart,Point_2 ptEnd) +{ + double dx = ptStart.x - ptEnd.x; + double dy = ptStart.y - ptEnd.y; + return dx*dx+dy*dy; +} + +double leadingline::PointToSegmentDistance(const Point_2& ptSegStart,const Point_2& ptSegEnd,const Point_2& ptPoint) +{ + double area = 0; + double BotLen = sqrt(PowerDistance(ptSegStart,ptSegEnd)); + vector vec; + vec.push_back(ptSegStart),vec.push_back(ptSegEnd),vec.push_back(ptPoint),vec.push_back(ptSegStart); + for (int i=0;i= c_nPI * 2.0) + { + _nRagularizeRadian -= c_nPI * 2.0; + } + + ASSERT(_nRagularizeRadian >= 0.0 && _nRagularizeRadian < c_nPI * 2.0); + return _nRagularizeRadian; +} + +bool leadingline::IsPointInArc(IN const DPOINT2& ptPoint_, + IN const DPOINT2& ptCenter_, + IN const double& nRadius_, + IN const double& nStartAngle_, + IN const double& nCentralAngle_, + IN const bool& bIsNormalDir_) +{ + ASSERT(IsValidDouble(ptPoint_.x)); + ASSERT(IsValidDouble(ptPoint_.y)); + ASSERT(IsValidDouble(ptCenter_.x)); + ASSERT(IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + ASSERT(DOUBLE_GREAT_ZERO(nCentralAngle_) && + DOUBLE_LE(nCentralAngle_, 2 * c_nPI)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle_) && + DOUBLE_LE(nStartAngle_, 2 * c_nPI)); + + double _nFactor = bIsNormalDir_ ? 1 : -1; + + // 点到圆心等于半径 --- 吴阳明 2010 08 21 + DPOINT2 _vecPtToCenter = ptPoint_ - ptCenter_; + double _nDis = _vecPtToCenter.GetLength(); + if (!DOUBLE_EQU(_nDis, nRadius_)) + return false; + + // 求圆弧起始角到ptPoint之间的圆心角 --- 吴阳明 2010 08 21 + double _nEndAngleTemp = D2GetNormalAngle(_vecPtToCenter); + double _nCentralAngleTemp = (_nEndAngleTemp - nStartAngle_) * _nFactor; + _nCentralAngleTemp = RegularizeRadian(_nCentralAngleTemp); + + // 比较圆心角大小来判断是否在圆弧上 --- 吴阳明 2010 08 21 + return DOUBLE_LE(_nCentralAngleTemp, nCentralAngle_); +} + +double leadingline::D2GetNormalAngle(IN const DPOINT2& ptX_) +{ + //获取坐标点到原点的距离 --- 吴阳明 2010-1-20 + double _nDistance = sqrt(pow(ptX_.x, 2) + pow(ptX_.y, 2)); + + //如距离小于零,点为原点,即在X轴上,所成角度为零 --- 吴阳明 2010-1-20 + if (DOUBLE_LE_ZERO(_nDistance)) + return 0.0; + + //求向量与X轴正向所成的余弦值 --- 吴阳明 2010-1-20 + ASSERT(_nDistance > 0.0); + double _nTemp = ptX_.x / _nDistance; + //将_nTemp限制在-1和1之间 --- 吴阳明 2010-1-20 + __CUT(_nTemp, -1., 1.); + //计算反余弦,求出角度 --- 吴阳明 2010-1-20 + double _nAngle = acos(_nTemp); + //当ptX_.y为正值,(ptX_.x,ptX_.y)点在第一或第二象限--- 吴阳明 2010-1-20 + if (DOUBLE_GE_ZERO(ptX_.y)) + return _nAngle; + //当ptX_.y为负值,(ptX_.x,ptX_.y)点在第三或第四象限--- 吴阳明 2010-1-20 + return 2.0 * c_nPI - _nAngle; +} + +double leadingline::D2GetPointToLineDistance(IN DPOINT2 ptPoint_, + IN DPOINT2 ptLineStart_, + IN DPOINT2 ptLineEnd_) +{ + DPOINT2 _vecLine(ptLineEnd_ - ptLineStart_); + ASSERT(DOUBLE_GREAT_ZERO(_vecLine.GetLength())); + + // 直线标准方程的系数 + double _a, _b, _c; + _a = ptLineEnd_.y - ptLineStart_.y; + _b = ptLineStart_.x - ptLineEnd_.x; + _c = (ptLineEnd_.x - ptLineStart_.x) * ptLineStart_.y - + (ptLineEnd_.y - ptLineStart_.y) * ptLineStart_.x; + + return (fabs(_a * ptPoint_.x + _b * ptPoint_.y + _c)) / _vecLine.GetLength(); +} + +double leadingline::D2GetProjectionDistance(IN const VectorD2D& vectorA_,IN const VectorD2D& vectorB_) +{ + double _nLength = vectorB_.GetLength(); + if (DOUBLE_NOT_ZERO(_nLength)) + return (vectorA_.x * vectorB_.x + vectorA_.y * vectorB_.y) / _nLength; + return 0; +} + +double D2GetProjectionDistance(IN const double& nPtAx_, IN const double& nPtAy_, IN const double& nPtBx_, IN const double& nPtBy_) +{ + VectorD2D _vectorA(nPtAx_, nPtAy_); + VectorD2D _vectorB(nPtBx_, nPtBy_); + return D2GetProjectionDistance(_vectorA, _vectorB); +} + +namespace +{ + VectorD2D NormalizeVector(const VectorD2D& vecValue_) + { + double _nLength = vecValue_.GetLength(); + ASSERT(DOUBLE_GREAT_ZERO(_nLength)); + return VectorD2D(vecValue_.x / _nLength, vecValue_.y / _nLength); + } +} + +int leadingline::Intersect_BeelineWithBeeline(IN const DPOINT2& pt1_, + IN double nAngle1_, + IN const DPOINT2& pt2_, + IN double nAngle2_, + OUT DPOINT2* pptIntersect_ /* = NULL */) +{ + ASSERT(IsValidDouble(pt1_.x)); + ASSERT(IsValidDouble(pt1_.y)); + ASSERT(IsValidDouble(pt2_.x)); + ASSERT(IsValidDouble(pt2_.y)); + + // 另外一点取x = pt1.x + 1 --- 吴阳明 2010 09 07 + __point2 _pt11(pt1_.x, pt1_.y); + __point2 _pt12(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + + __point2 _pt21(pt2_.x, pt2_.y); + __point2 _pt22(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + + if (DOUBLE_EQU(nAngle1_, c_nPI / 2) || DOUBLE_EQU(nAngle1_, 3 * c_nPI / 2)) + { + _pt12 .Set(pt1_.x, pt1_.y + 1); + } + else + { + _pt12.Set(pt1_.x + 1, tan(nAngle1_) + pt1_.y); + } + + if (DOUBLE_EQU(nAngle2_, c_nPI / 2) || DOUBLE_EQU(nAngle2_, 3 * c_nPI / 2)) + { + _pt22.Set(pt2_.x, pt2_.y + 1); + } + else + { + _pt22.Set(pt2_.x + 1, tan(nAngle2_) + pt2_.y); + } + + // 自坐标原点到两条直线的端点的向量 ---wanghong 2010 09 07 + VectorD2D _vec1x(_pt11), _vec1y(_pt12); + VectorD2D _vec2x(_pt21), _vec2y(_pt22); + // 两条直线的向量 ---wanghong 2010 09 07 + VectorD2D _vecA(_vec1y - _vec1x), _vecB(_vec2y - _vec2x); + // 第二条直线的垂直向量 ---wanghong 2010 09 07 + VectorD2D _vecBPlumb(-_vecB.y, _vecB.x); + + if (DOUBLE_EQU_ZERO(NormalizeVector(_vecA) * NormalizeVector(_vecBPlumb))) + { + // 平行或重合 ---wanghong 2010 09 07 + return 0; + } + + double _n = (_vec2x * _vecBPlumb - _vec1x * _vecBPlumb) / (_vecA * _vecBPlumb); + if (pptIntersect_ != NULL) + { + pptIntersect_->x = _vec1x.x + _n * _vecA.x; + pptIntersect_->y = _vec1x.y + _n * _vecA.y; + } + + return 1; +} + +int leadingline::Intersect_LineWithLine(IN const DPOINT2& ptStart1_, + IN const DPOINT2& ptEnd1_, + IN const DPOINT2& ptStart2_, + IN const DPOINT2& ptEnd2_, + OUT DPOINT2* pptIntersect_ /* = NULL */) +{ + DPOINT2 _vecLine1(ptEnd1_ - ptStart1_); + DPOINT2 _vecLine2(ptEnd2_ - ptStart2_); + + ASSERT(DOUBLE_GE_ZERO(_vecLine1.GetLength())); + ASSERT(DOUBLE_GE_ZERO(_vecLine2.GetLength())); + + double _nAngle1 = D2GetNormalAngle(_vecLine1); + double _nAngle2 = D2GetNormalAngle(_vecLine2); + + DPOINT2 _ptIntersect(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + int _nNum = Intersect_BeelineWithBeeline(ptStart1_, _nAngle1, + ptStart2_, _nAngle2, &_ptIntersect); + + if (_nNum == 0 || !IsPointInLine(_ptIntersect, ptStart1_, ptEnd1_) || + !IsPointInLine(_ptIntersect, ptStart2_, ptEnd2_)) + { + return 0; + } + + if (pptIntersect_) + *pptIntersect_ = _ptIntersect; + + return 1; +} + +int leadingline::Intersect_BeelineWithCircle(IN const DPOINT2& ptBeeline_, + IN double nBeelineAngle_, + IN const DPOINT2& ptCenter_, + IN double nRadius_, + OUT DPOINT2* pptIntersect1_ /* = NULL */, + OUT DPOINT2* pptIntersect2_ /* = NULL */) +{ + ASSERT(IsValidDouble(ptBeeline_.x)); + ASSERT(IsValidDouble(ptBeeline_.y)); + ASSERT(IsValidDouble(ptCenter_.x)); + ASSERT(IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + + double x1, y1, x2, y2; // 直线12 + double x3, y3; // 圆心到直线12的投影坐标; + double _nCenterToLineDis; // 圆心到直线12的距离 + double _nPrjToIntersectDis; // 投影点到交点的距离 + double _nLineLength; // 指定线段的长度 + double dvx1c, dvy1c; // 连接点1和圆心的直线的方向矢量 + double prjc; // 连接点1和圆心的直线在12上的投影长度 + + // 为直线两端点赋值 + x1 = ptBeeline_.x; + y1 = ptBeeline_.y; + x2 = c_nINVALID_DOUBLE; + y2 = c_nINVALID_DOUBLE; + + if (DOUBLE_EQU(nBeelineAngle_, c_nPI / 2) || + DOUBLE_EQU(nBeelineAngle_, 3 * c_nPI / 2)) + { + x2 = ptBeeline_.x; + y2 = ptBeeline_.y + 1; + } + else + { + x2 = ptBeeline_.x + 1; + y2 = ptBeeline_.y + tan(nBeelineAngle_); + } + + DPOINT2 _ptBeelineEnd(DPOINT2(x2, y2)); + _nLineLength = (_ptBeelineEnd - ptBeeline_).GetLength(); + DPOINT2 _vecLine(_ptBeelineEnd - ptBeeline_); + + if (DOUBLE_EQU_ZERO(nRadius_)) + return -1; + + // 当圆心到直线的距离大于半径时,直线与圆弧没有交点 + _nCenterToLineDis = D2GetPointToLineDistance(ptCenter_, ptBeeline_, _ptBeelineEnd); + if (DOUBLE_GREAT(_nCenterToLineDis, nRadius_)) + return 0; + + dvx1c = ptCenter_.x - x1; + dvy1c = ptCenter_.y - y1; + prjc = D2GetProjectionDistance(dvx1c, dvy1c, _vecLine.x, _vecLine.y); + + _vecLine.Unify(); + x3 = x1 + prjc * _vecLine.x; + y3 = y1 + prjc * _vecLine.y; + + double nTemp = nRadius_ * nRadius_ - _nCenterToLineDis * _nCenterToLineDis; + if (nTemp < 0) + nTemp = 0; + _nPrjToIntersectDis = sqrt(nTemp); + + DPOINT2 _ptIntersect1(x3 - _nPrjToIntersectDis * _vecLine.x, y3 - _nPrjToIntersectDis * _vecLine.y); + DPOINT2 _ptIntersect2(x3 + _nPrjToIntersectDis * _vecLine.x, y3 + _nPrjToIntersectDis * _vecLine.y); + + // 相切情况 --- 吴阳明 2010 09 07 + if (pptIntersect1_ != NULL && DOUBLE_EQU_ZERO((_ptIntersect1 - _ptIntersect2).GetLength())) + { + *pptIntersect1_ = _ptIntersect1; + return 1; + } + + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersect1; + + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersect2; + + return 2; +} + +int leadingline::Intersect_LineWithArc(IN const DPOINT2& ptStart_, + IN const DPOINT2& ptEnd_, + IN const DPOINT2& ptCenter_, + IN double nRadius_, + IN double nStartAngle_, + IN double nSweptAngle_, + OUT DPOINT2* pptIntersect1_/* = NULL*/, + OUT DPOINT2* pptIntersect2_/* = NULL*/) +{ + ASSERT(IsValidDouble(ptStart_.x) && IsValidDouble(ptStart_.y)); + ASSERT(IsValidDouble(ptEnd_.x) && IsValidDouble(ptEnd_.y)); + ASSERT(IsValidDouble(ptCenter_.x) && IsValidDouble(ptCenter_.y)); + ASSERT(DOUBLE_GREAT_ZERO(nRadius_)); + ASSERT(DOUBLE_GE_ZERO(nStartAngle_) && DOUBLE_LESS(nStartAngle_, 2 * c_nPI)); + ASSERT(DOUBLE_GREAT_ZERO(fabs(nSweptAngle_)) && DOUBLE_LE(fabs(nSweptAngle_), 2 * c_nPI)); + + DPOINT2 _ptIntersec1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersec2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + // 通过线段对应的直线与圆弧对应的圆求交,获得“可能是交点”的点集 --- wanghong 2010 09 08 + int _nImageIntersect = Intersect_BeelineWithCircle(ptStart_, D2GetNormalAngle(ptEnd_ - ptStart_), + ptCenter_, nRadius_, &_ptIntersec1, &_ptIntersec2); + if (_nImageIntersect < 1) + return _nImageIntersect; + + bool _bPt1Exist = IsPointInLine(_ptIntersec1, ptStart_, ptEnd_) && + IsPointInArc(_ptIntersec1, ptCenter_, nRadius_, nStartAngle_, fabs(nSweptAngle_), DOUBLE_GREAT_ZERO(nSweptAngle_)); + bool _bPt2Exist = false; + if (_nImageIntersect == 2) + { // 避免相切时重复计算 --- wanghong 2010 09 08 + _bPt2Exist = IsPointInLine(_ptIntersec2, ptStart_, ptEnd_) && + IsPointInArc(_ptIntersec2, ptCenter_, nRadius_, nStartAngle_, fabs(nSweptAngle_), DOUBLE_GREAT_ZERO(nSweptAngle_)); + } + // 存在两个交点 --- wanghong 2010 09 08 + if (_bPt1Exist && _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersec1; + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersec2; + return 2; + } + // 存在一个交点 --- wanghong 2010 09 08 + if (_bPt1Exist || _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _bPt1Exist ? _ptIntersec1 : _ptIntersec2; + return 1; + } + + return 0; +} +} + +int leadingline::Intersect_ArcWithArc(IN const DPOINT2& ptCenter1_, IN const DPOINT2& ptCenter2_, + IN double nRadius1_, IN double nRadius2_, + IN double nStartAngle1_, IN double nStartAngle2_, + IN double nSweptAngle1_, IN double nSweptAngle2_, + OUT DPOINT2* pptIntersect1_, OUT DPOINT2* pptIntersect2_) +{ + DPOINT2 _ptIntersec1(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + DPOINT2 _ptIntersec2(c_nINVALID_DOUBLE, c_nINVALID_DOUBLE); + int _nImageIntersect = 0; + DPOINT2 _vecCenter1ToCenter2(ptCenter2_.x - ptCenter1_.x, ptCenter2_.y - ptCenter1_.y); + double _nAngleCenter1ToCenter2 = D2GetNormalAngle(_vecCenter1ToCenter2); + double _nCenterDistance = sqrt(_vecCenter1ToCenter2.x * _vecCenter1ToCenter2.x + _vecCenter1ToCenter2.y * _vecCenter1ToCenter2.y); + double _nRadiusSum = nRadius1_ + nRadius2_; + double _nRadiusDif = abs(nRadius1_ - nRadius2_); + + if(_nCenterDistance - _nRadiusSum > 1e-3 || _nCenterDistance - _nRadiusDif < -(1e-3)) + { + return 0; + } + + // 圆心距等于半径和或差,两圆相切 + if((_nCenterDistance - _nRadiusSum >= -(1e-3) && _nCenterDistance - _nRadiusSum <= 1e-3) + || (_nCenterDistance - _nRadiusDif >= -(1e-3) && _nCenterDistance - _nRadiusDif <= 1e-3)) + { + _nImageIntersect = 1; + if(_nCenterDistance - _nRadiusSum >= -(1e-3) && _nCenterDistance - _nRadiusSum <= 1e-3) + { + _ptIntersec1.x = ptCenter1_.x + nRadius1_ * _vecCenter1ToCenter2.x / _nCenterDistance; + _ptIntersec1.y = ptCenter1_.y + nRadius1_ * _vecCenter1ToCenter2.y / _nCenterDistance; + } + if(_nCenterDistance - _nRadiusDif >= -(1e-3) && _nCenterDistance - _nRadiusDif <= 1e-3) + { + if(nRadius1_> nRadius2_) + { + _ptIntersec1.x = ptCenter1_.x + nRadius1_ * _vecCenter1ToCenter2.x / _nCenterDistance; + _ptIntersec1.y = ptCenter1_.y + nRadius1_ * _vecCenter1ToCenter2.y / _nCenterDistance; + } + else + { + _ptIntersec1.x = ptCenter2_.x - nRadius2_ * _vecCenter1ToCenter2.x / _nCenterDistance; + _ptIntersec1.y = ptCenter1_.y - nRadius2_ * _vecCenter1ToCenter2.y / _nCenterDistance; + } + } + } + if(_nCenterDistance - _nRadiusSum < -(1e-3) && _nCenterDistance - _nRadiusDif > 1e-3) + { + _nImageIntersect = 2; + double _nIntersectAngle = acos((nRadius1_ * nRadius1_ + _nCenterDistance * _nCenterDistance - nRadius2_ * nRadius2_) / (2 * nRadius1_ * _nCenterDistance)); + _ptIntersec1.x = ptCenter1_.x + nRadius1_ * cos(_nAngleCenter1ToCenter2 + _nIntersectAngle); + _ptIntersec1.y = ptCenter1_.y + nRadius1_ * sin(_nAngleCenter1ToCenter2 + _nIntersectAngle); + _ptIntersec2.x = ptCenter1_.x + nRadius1_ * cos(_nAngleCenter1ToCenter2 - _nIntersectAngle); + _ptIntersec2.y = ptCenter1_.y + nRadius1_ * sin(_nAngleCenter1ToCenter2 - _nIntersectAngle); + } + + + + // 判断两圆的交点是否在弧上 + bool _bPt1Exist = IsPointInArc(_ptIntersec1, ptCenter1_, nRadius1_, nStartAngle1_, fabs(nSweptAngle1_), DOUBLE_GREAT_ZERO(nSweptAngle1_)) + && IsPointInArc(_ptIntersec1, ptCenter2_, nRadius2_, nStartAngle2_, fabs(nSweptAngle2_), DOUBLE_GREAT_ZERO(nSweptAngle2_)); + bool _bPt2Exist = false; + if(_nImageIntersect == 2) + { + _bPt2Exist = IsPointInArc(_ptIntersec2, ptCenter1_, nRadius1_, nStartAngle1_, fabs(nSweptAngle1_), DOUBLE_GREAT_ZERO(nSweptAngle1_)) + && IsPointInArc(_ptIntersec2, ptCenter2_, nRadius2_, nStartAngle2_, fabs(nSweptAngle2_), DOUBLE_GREAT_ZERO(nSweptAngle2_)); + } + + if (_bPt1Exist && _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _ptIntersec1; + if (pptIntersect2_ != NULL) + *pptIntersect2_ = _ptIntersec2; + return 2; + } + + if (_bPt1Exist || _bPt2Exist) + { + if (pptIntersect1_ != NULL) + *pptIntersect1_ = _bPt1Exist ? _ptIntersec1 : _ptIntersec2; + return 1; + } + + else + { + return 0; + } +} \ No newline at end of file diff --git a/src/TubeToCadTranslator.cpp b/src/TubeToCadTranslator.cpp new file mode 100644 index 0000000..07e533c --- /dev/null +++ b/src/TubeToCadTranslator.cpp @@ -0,0 +1,2684 @@ +// ************************************************************************** // +// TubeToCadTranslator.cpp : implementation of CTubeToCadTranslator class. +// Copyright(c) 2017 WeiHong Company. All rights reserved. +// +// Abstract: +// 本文件实现将管材坐标转换为CAD对象。 +// *********************************************** ---- 杜全 2017-02-28 ***** // +#include "stdafx.h" + +using namespace translators; + +////////////////////////////////////////////////////////////////////////// +// class CWires3DTranslator +CWires3DTranslator::CWires3DTranslator() + : m_pTubeToCadTranslator(NULL) +{ +} + +void CWires3DTranslator::Initialize(CTubeToCadTranslator* pTubeToCadTranslator_) +{ + ASSERT(pTubeToCadTranslator_ != NULL); + m_pTubeToCadTranslator = pTubeToCadTranslator_; +} + +Standard_Boolean CWires3DTranslator::Translate(LISTWIRES3DONPLANE& listWires3DOnPlane_) +{ + ASSERT(listWires3DOnPlane_.empty()); + + // 调整管材横截面的外边界 + if (!AdjustOuterBoundary()) + return false; + + LISTEDGES3DCITER _iterBegin = m_pTubeToCadTranslator->m_OuterBoundary.listEdges.begin(); + LISTEDGES3DCITER _iterEnd = m_pTubeToCadTranslator->m_OuterBoundary.listEdges.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + ASSERT((EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType) || (EdgeInfo::EDGE_OVAL == _iterBegin->nEdgeType)); + if (EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType) + { + TransWiresOnPlane(_iterBegin, listWires3DOnPlane_); + } + else if (DIST_EQU(_iterBegin->nLongRadius, _iterBegin->nShortRadius)) + { + // 先获取圆柱面相连平面的边/线,再获取圆柱面上的边/线 + Wire3DOnPlaneInfo _WireOnSurface; + LISTEDGES3DCITER _iterNext = _iterBegin; + if (++_iterNext != _iterEnd) + { + TransWiresOnPlane(_iterNext, listWires3DOnPlane_); + GetWiresOnOvalSurface(*_iterBegin, _WireOnSurface); + listWires3DOnPlane_.insert(--listWires3DOnPlane_.end(), _WireOnSurface); + ++_iterBegin; + } + else + { + GetWiresOnOvalSurface(*_iterBegin, _WireOnSurface); + listWires3DOnPlane_.push_back(_WireOnSurface); + } + } + else + { + ASSERT(!DIST_EQU(_iterBegin->nLongRadius, _iterBegin->nShortRadius)); + Wire3DOnPlaneInfo _WireOnSurface; + GetWiresOnOvalSurface(*_iterBegin, _WireOnSurface); + listWires3DOnPlane_.push_back(_WireOnSurface); + } + } + + if (listWires3DOnPlane_.empty()) + return false; + + ASSERT((listWires3DOnPlane_.size() == 1) || (listWires3DOnPlane_.size() == 4) || (listWires3DOnPlane_.size() == 8)); + DeleteRepeatEdges(listWires3DOnPlane_); + + return true; +} + +Standard_Boolean CWires3DTranslator::AdjustOuterBoundary() +{ + ASSERT(m_pTubeToCadTranslator->m_OuterBoundary.bClosed); + + switch (m_pTubeToCadTranslator->m_TubeParam.nTubeType) + { + case TubeInfo::rectangular: + { + // 方管:调整方向 + LISTEDGES3D& _listEdges = m_pTubeToCadTranslator->m_OuterBoundary.listEdges; + LISTEDGES3DCITER _iterBegin = _listEdges.begin(); + if (_iterBegin->nEdgeType != EdgeInfo::EDGE_LINE) + ++_iterBegin; + + LISTEDGES3DCITER _iterNext = _iterBegin; + if ((++_iterNext)->nEdgeType != EdgeInfo::EDGE_LINE) + ++_iterNext; + + ASSERT((EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType) && (EdgeInfo::EDGE_LINE == _iterNext->nEdgeType)); + ASSERT(IsEqualVectorNoDir(_iterBegin->ptDir ^ _iterNext->ptDir, m_pTubeToCadTranslator->m_ptAxleWireDir)); + if (!(_iterBegin->ptDir ^ _iterNext->ptDir).IsEqual(m_pTubeToCadTranslator->m_ptAxleWireDir, g_nDistPrecision)) + { + _listEdges.reverse(); + LISTEDGES3D::iterator _iterBegin = _listEdges.begin(); + LISTEDGES3D::iterator _iterEnd = _listEdges.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + _iterBegin->Reverse(); + } + + // 方管:调整最长的边为第一个边 + Standard_Integer _nSize = static_cast(_listEdges.size()); + Standard_Integer _nIndex = 0; + while (_nIndex++ < _nSize) + { + const Edge3DInfo& _edge = _listEdges.front(); + if ((EdgeInfo::EDGE_LINE == _edge.nEdgeType) + && DIST_EQU((_edge.ptEnd - _edge.ptStart).Modulus(), m_pTubeToCadTranslator->m_TubeParam.nRectWidth + - 2.0 * m_pTubeToCadTranslator->m_TubeParam.nRectRadius)) + break; + + _listEdges.push_back(_edge); + _listEdges.pop_front(); + } + + ASSERT(_nIndex < _nSize); + return (_nIndex < _nSize); + } + break; + + case TubeInfo::circular: + { + // 圆管:将外边框起点调整到轴上 + AdjustCircularOuterBoundary(); + } + case TubeInfo::oval: + { + // 圆管/椭圆管:调整方向 + ASSERT(m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 1); + Edge3DInfo& _edge = m_pTubeToCadTranslator->m_OuterBoundary.listEdges.front(); + ASSERT(IsEqualVectorNoDir(_edge.ptXDir ^ _edge.ptYDir, m_pTubeToCadTranslator->m_ptAxleWireDir)); + if ((_edge.ptXDir ^ _edge.ptYDir).IsEqual(m_pTubeToCadTranslator->m_ptAxleWireDir, g_nDistPrecision) + != (_edge.nLastParam > _edge.nFirstParam)) + { + _edge.Reverse(); + } + } + break; + + case TubeInfo::waist: + { + // 腰管:调整方向 + LISTEDGES3D::iterator _iterBegin = m_pTubeToCadTranslator->m_OuterBoundary.listEdges.begin(); + LISTEDGES3D::iterator _iterTemp = _iterBegin; + if (EdgeInfo::EDGE_LINE == _iterTemp->nEdgeType) + ++_iterTemp; + + ASSERT(EdgeInfo::EDGE_OVAL == _iterTemp->nEdgeType); + ASSERT(IsEqualVectorNoDir(_iterTemp->ptXDir ^ _iterTemp->ptYDir, m_pTubeToCadTranslator->m_ptAxleWireDir)); + if ((_iterTemp->ptXDir ^ _iterTemp->ptYDir).IsEqual(m_pTubeToCadTranslator->m_ptAxleWireDir, g_nDistPrecision) + != (_iterTemp->nLastParam > _iterTemp->nFirstParam)) + { + m_pTubeToCadTranslator->m_OuterBoundary.listEdges.reverse(); + LISTEDGES3D::iterator _iterEnd = m_pTubeToCadTranslator->m_OuterBoundary.listEdges.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + _iterBegin->Reverse(); + } + } + + // 腰管:调整直线边为第一个边 + Standard_Integer _nSize = static_cast(m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size()); + ASSERT(_nSize == 4); + Standard_Integer _nIndex = 0; + while (_nIndex++ < _nSize) + { + const Edge3DInfo& _edge = m_pTubeToCadTranslator->m_OuterBoundary.listEdges.front(); + if ((EdgeInfo::EDGE_LINE == _edge.nEdgeType) + && DIST_EQU((_edge.ptEnd - _edge.ptStart).Modulus(), m_pTubeToCadTranslator->m_TubeParam.nWaistWidth)) + break; + + m_pTubeToCadTranslator->m_OuterBoundary.listEdges.push_back(_edge); + m_pTubeToCadTranslator->m_OuterBoundary.listEdges.pop_front(); + } + + ASSERT(_nIndex < _nSize); + return (_nIndex < _nSize); + } + break; + + default: + ASSERT(false); + return false; + } + + return true; +} + +void CWires3DTranslator::AdjustCircularOuterBoundary() +{ + ASSERT(TubeInfo::circular == m_pTubeToCadTranslator->m_TubeParam.nTubeType); + ASSERT(m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 1); + + Edge3DInfo& _edge = m_pTubeToCadTranslator->m_OuterBoundary.listEdges.front(); + if ((_edge.nEdgeType != EdgeInfo::EDGE_OVAL) || !ANGLE_EQU((_edge.nLastParam - _edge.nFirstParam), 2.0 * g_nPIE)) + return; + + // 修正参数范围 + Standard_Real _nParamDir = (_edge.nLastParam > _edge.nFirstParam) ? 1.0 : -1.0; + _edge.nFirstParam = 0.; + _edge.nLastParam = _nParamDir * 2.0 * g_nPIE; + + // 修正方向 + gp_XYZ _ptNormalVector = _edge.ptXDir ^ _edge.ptYDir; + ASSERT(IsEqualVectorNoDir(_ptNormalVector, m_pTubeToCadTranslator->m_ptAxleWireDir)); + ASSERT(DIGIT_EQU(max(max(fabs(_ptNormalVector.X()), fabs(_ptNormalVector.Y())), fabs(_ptNormalVector.Z())), 1.0)); + + gp_XYZ _ptNewXDir; + Standard_Real _nMaxAxle = max(max(fabs(_edge.ptXDir.X()), fabs(_edge.ptXDir.Y())), fabs(_edge.ptXDir.Z())); + if (DIGIT_EQU(_nMaxAxle, fabs(_edge.ptXDir.X()))) + { + _ptNewXDir.SetX(_copysign(1.0, _edge.ptXDir.X())); + } + else if (DIGIT_EQU(_nMaxAxle, fabs(_edge.ptXDir.Y()))) + { + _ptNewXDir.SetY(_copysign(1.0, _edge.ptXDir.Y())); + } + else + { + ASSERT(DIGIT_EQU(_nMaxAxle, fabs(_edge.ptXDir.Z()))); + _ptNewXDir.SetZ(_copysign(1.0, _edge.ptXDir.Z())); + } + + _edge.ptXDir = _ptNewXDir; + _edge.ptYDir = _ptNormalVector ^ _edge.ptXDir; +} + +void CWires3DTranslator::TransWiresOnPlane(const LISTEDGES3DCITER& curIter_, LISTWIRES3DONPLANE& listWiresOnPlane_) +{ + ASSERT(EdgeInfo::EDGE_LINE == curIter_->nEdgeType); + gp_XYZ _ptAimPoint = (curIter_->StartPoint() + curIter_->EndPoint()) * 0.5; + gp_XYZ _ptNormalVector = curIter_->ptDir ^ m_pTubeToCadTranslator->m_ptAxleWireDir; + + Wire3DOnPlaneInfo _WireOnPlane; + _WireOnPlane.ptNormalVector = _ptNormalVector; + + LISTWIRES3D::iterator _iterWireBegin = m_pTubeToCadTranslator->m_listDiceyWires.begin(); + LISTWIRES3D::iterator _iterWireEnd = m_pTubeToCadTranslator->m_listDiceyWires.end(); + while (_iterWireBegin != _iterWireEnd) + { + Wire3DInfo _wire; + LISTEDGES3D::iterator _iterEdgeBegin = _iterWireBegin->listEdges.begin(); + LISTEDGES3D::iterator _iterEdgeEnd = _iterWireBegin->listEdges.end(); + while (_iterEdgeBegin != _iterEdgeEnd) + { + if (!JudgeEdgeOnPlane(_ptAimPoint, _ptNormalVector, *_iterEdgeBegin)) + { + ++_iterEdgeBegin; + continue; + } + + // 该边与前面的边非首尾相连 + if (!_wire.listEdges.empty() && !_wire.listEdges.back().EndPoint().IsEqual(_iterEdgeBegin->StartPoint(), g_nDistPrecision)) + { + CheckRepeatWire(_wire, _iterWireBegin->bExclude); + _WireOnPlane.listWires.push_back(_wire); + _wire.listEdges.clear(); + } + + _wire.listEdges.push_back(*_iterEdgeBegin); + LISTEDGES3D::iterator _iterTemp = _iterEdgeBegin++; + _iterWireBegin->listEdges.erase(_iterTemp); + } + + if (!_wire.listEdges.empty()) + { + CheckRepeatWire(_wire, _iterWireBegin->bExclude); + _WireOnPlane.listWires.push_back(_wire); + } + + if (!_iterWireBegin->listEdges.empty()) + { + ++_iterWireBegin; + continue; + } + + LISTWIRES3D::iterator _iterTemp = _iterWireBegin++; + m_pTubeToCadTranslator->m_listDiceyWires.erase(_iterTemp); + } + + listWiresOnPlane_.push_back(_WireOnPlane); +} + +void CWires3DTranslator::GetWiresOnOvalSurface(const Edge3DInfo& OvalEdge_, Wire3DOnPlaneInfo& WireOnSurface_) +{ + ASSERT(EdgeInfo::EDGE_OVAL == OvalEdge_.nEdgeType); + + LISTWIRES3D::iterator _iterWireBegin = m_pTubeToCadTranslator->m_listDiceyWires.begin(); + LISTWIRES3D::iterator _iterWireEnd = m_pTubeToCadTranslator->m_listDiceyWires.end(); + while (_iterWireBegin != _iterWireEnd) + { + Wire3DInfo _wire; + LISTEDGES3D::iterator _iterEdgeBegin = _iterWireBegin->listEdges.begin(); + LISTEDGES3D::iterator _iterEdgeEnd = _iterWireBegin->listEdges.end(); + while (_iterEdgeBegin != _iterEdgeEnd) + { + if (!JudgeEdgeOnOvalSurface(OvalEdge_, *_iterEdgeBegin)) + { + ++_iterEdgeBegin; + continue; + } + + // 该边与前面的边非首尾相连 + if (!_wire.listEdges.empty() && !_wire.listEdges.back().EndPoint().IsEqual(_iterEdgeBegin->StartPoint(), g_nDistPrecision)) + { + CheckRepeatWire(_wire, _iterWireBegin->bExclude); + WireOnSurface_.listWires.push_back(_wire); + _wire.listEdges.clear(); + } + + _wire.listEdges.push_back(*_iterEdgeBegin); + LISTEDGES3D::iterator _iterTemp = _iterEdgeBegin++; + _iterWireBegin->listEdges.erase(_iterTemp); + } + + if (!_wire.listEdges.empty()) + { + CheckRepeatWire(_wire, _iterWireBegin->bExclude); + WireOnSurface_.listWires.push_back(_wire); + } + + if (!_iterWireBegin->listEdges.empty()) + { + ++_iterWireBegin; + continue; + } + + LISTWIRES3D::iterator _iterTemp = _iterWireBegin++; + m_pTubeToCadTranslator->m_listDiceyWires.erase(_iterTemp); + } +} + +Standard_Boolean CWires3DTranslator::JudgeEdgeOnPlane(const gp_XYZ& ptAimPoint_, const gp_XYZ& ptNormalVector_, const Edge3DInfo& edge_) const +{ + if (EdgeInfo::EDGE_LINE == edge_.nEdgeType) + { + return (JudgePointOnPlane(ptAimPoint_, ptNormalVector_, edge_.StartPoint()) + && JudgePointOnPlane(ptAimPoint_, ptNormalVector_, edge_.EndPoint())); + } + + ASSERT(EdgeInfo::EDGE_OVAL == edge_.nEdgeType); + return (JudgePointOnPlane(ptAimPoint_, ptNormalVector_, edge_.ptCenter) + && IsEqualVectorNoDir(edge_.ptXDir ^ edge_.ptYDir, ptNormalVector_)); +} + +Standard_Boolean CWires3DTranslator::JudgeEdgeOnOvalSurface(const Edge3DInfo& OvalEdge_, const Edge3DInfo& edge_) const +{ + ASSERT(EdgeInfo::EDGE_OVAL == OvalEdge_.nEdgeType); + + if (EdgeInfo::EDGE_LINE == edge_.nEdgeType) + { + gp_XYZ _ptMiddlePoint = 0.5 * (edge_.ptStart + edge_.ptEnd); + return (JudgePointOnOvalSurface(OvalEdge_, edge_.ptStart) + && JudgePointOnOvalSurface(OvalEdge_, _ptMiddlePoint) + && JudgePointOnOvalSurface(OvalEdge_, edge_.ptEnd)); + } + + // 取椭圆/圆弧上的5个点进行判断 + ASSERT(EdgeInfo::EDGE_OVAL == edge_.nEdgeType); + for (Standard_Integer i = 0; i < 5; ++i) + { + Standard_Real _nAlpha = static_cast(i) / 4.0; + Standard_Real _nParam = edge_.nFirstParam * (1.0 - _nAlpha) + edge_.nLastParam * _nAlpha; + gp_XYZ _ptPoint = edge_.ptCenter + edge_.nLongRadius * cos(_nParam) * edge_.ptXDir + edge_.nShortRadius * sin(_nParam) * edge_.ptYDir; + if (!JudgePointOnOvalSurface(OvalEdge_, _ptPoint)) + return false; + } + + return true; +} + +Standard_Boolean CWires3DTranslator::JudgePointOnOvalSurface(const Edge3DInfo& OvalEdge_, const gp_XYZ& ptPoint_) const +{ + ASSERT(EdgeInfo::EDGE_OVAL == OvalEdge_.nEdgeType); + + Standard_Real _nHeight = (ptPoint_ - OvalEdge_.ptCenter) * m_pTubeToCadTranslator->m_ptAxleWireDir; + gp_XYZ _ptProjection = ptPoint_ - _nHeight * m_pTubeToCadTranslator->m_ptAxleWireDir; + + // 圆管 + if (DIST_EQU(OvalEdge_.nLongRadius, OvalEdge_.nShortRadius)) + return fabs((_ptProjection - OvalEdge_.ptCenter).Modulus() - OvalEdge_.nLongRadius) < 2.0 * g_nEdgeDeflection; + + // 椭圆管:计算椭圆的两焦点,根据椭圆定义(到两焦点距离和为定值),判断投影点是否在椭圆上 + gp_XYZ _ptLeftFocus, _ptRightFocus; + GetOvalFocus(OvalEdge_, _ptLeftFocus, _ptRightFocus); + Standard_Real _nError = (_ptProjection - _ptLeftFocus).Modulus() + (_ptProjection - _ptRightFocus).Modulus() - 2.0 * OvalEdge_.nLongRadius; + + return (fabs(_nError) < 2.0 * g_nEdgeDeflection); +} + +void CWires3DTranslator::CheckRepeatWire(Wire3DInfo& wire_, Standard_Boolean bExclude_) const +{ + wire_.bExclude = bExclude_; + + // 如果是单个直线边,则认为可能是重复边 + if ((wire_.listEdges.size() == 1) && (EdgeInfo::EDGE_LINE == wire_.listEdges.front().nEdgeType)) + wire_.bExclude = true; +} + +void CWires3DTranslator::DeleteRepeatEdges(LISTWIRES3DONPLANE& listWires3DOnPlane_) const +{ + LISTWIRES3DONPLANE::iterator _iterPlaneBegin = listWires3DOnPlane_.begin(); + LISTWIRES3DONPLANE::iterator _iterPlaneEnd = listWires3DOnPlane_.end(); + for (; _iterPlaneBegin != _iterPlaneEnd; ++_iterPlaneBegin) + { + LISTWIRES3D::iterator _iterWireBegin = _iterPlaneBegin->listWires.begin(); + LISTWIRES3D::iterator _iterWireEnd = _iterPlaneBegin->listWires.end(); + while (_iterWireBegin != _iterWireEnd) + { + if (!_iterWireBegin->bExclude || !JudgeRepeatEdges(*_iterWireBegin, _iterPlaneBegin->listWires)) + { + ++_iterWireBegin; + continue; + } + + LISTWIRES3D::iterator _iterTemp = _iterWireBegin++; + _iterPlaneBegin->listWires.erase(_iterTemp); + } + } +} + +Standard_Boolean CWires3DTranslator::JudgeRepeatEdges(Wire3DInfo& wire_, LISTWIRES3D& listWires_) const +{ + ASSERT(wire_.bExclude); + + LISTWIRES3D::iterator _iterWireBegin = listWires_.begin(); + LISTWIRES3D::iterator _iterWireEnd = listWires_.end(); + for (; _iterWireBegin != _iterWireEnd; ++_iterWireBegin) + { + if (_iterWireBegin->bExclude) + continue; + + LISTEDGES3DCITER _iterEdgeBegin = wire_.listEdges.begin(); + LISTEDGES3DCITER _iterEdgeEnd = wire_.listEdges.end(); + for (; _iterEdgeBegin != _iterEdgeEnd; ++_iterEdgeBegin) + { + if (!JudgeRepeatEdges(*_iterEdgeBegin, _iterWireBegin->listEdges)) + break; + } + + if (_iterEdgeBegin == _iterEdgeEnd) + { + wire_.bExclude = false; + return true; + } + } + + wire_.bExclude = false; + return false; +} + +Standard_Boolean CWires3DTranslator::JudgeRepeatEdges(const Edge3DInfo& edge_, const LISTEDGES3D& listEdges_) const +{ + // 如果是直线,计算起点、中点及终点是否满足误差要求 + if (EdgeInfo::EDGE_LINE == edge_.nEdgeType) + { + gp_XYZ _ptMiddle = 0.5 * (edge_.ptStart + edge_.ptEnd); + if (!JudgePointOnEdges(edge_.ptStart, listEdges_) + || !JudgePointOnEdges(_ptMiddle, listEdges_) + || !JudgePointOnEdges(edge_.ptEnd, listEdges_)) + return false; + } + else + { + ASSERT(EdgeInfo::EDGE_OVAL == edge_.nEdgeType); + Standard_Real _nAimCentralAngle = fabs(edge_.nLastParam - edge_.nFirstParam); + Standard_Real _nAimMiddleAngle = 0.5 * (edge_.nFirstParam + edge_.nLastParam); + gp_XYZ _ptAimMiddlePoint = edge_.ptCenter + edge_.nLongRadius * cos(_nAimMiddleAngle) * edge_.ptXDir + + edge_.nShortRadius * sin(_nAimMiddleAngle) * edge_.ptYDir; + gp_XYZ _ptAimStartPoint = edge_.StartPoint(); + gp_XYZ _ptAimEndPoint = edge_.EndPoint(); + + LISTEDGES3DCITER _iterBegin = listEdges_.begin(); + LISTEDGES3DCITER _iterEnd = listEdges_.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + if ((_iterBegin->nEdgeType != EdgeInfo::EDGE_OVAL) + || !edge_.ptCenter.IsEqual(_iterBegin->ptCenter, g_nDistPrecision) + || !DIST_EQU(edge_.nLongRadius, _iterBegin->nLongRadius) + || !DIST_EQU(edge_.nShortRadius, _iterBegin->nShortRadius) + || !IsEqualVectorNoDir(edge_.ptXDir ^ edge_.ptYDir, _iterBegin->ptXDir ^ _iterBegin->ptYDir)) + continue; + + if (!DIST_EQU(edge_.nLongRadius, edge_.nShortRadius) && !IsEqualVectorNoDir(edge_.ptXDir, _iterBegin->ptXDir)) + continue; + + Standard_Real _nCentralAngle = fabs(_iterBegin->nLastParam - _iterBegin->nFirstParam); + if (!ANGLE_EQU(_nAimCentralAngle, _nCentralAngle) && (_nAimCentralAngle > _nCentralAngle)) + continue; + + if (!JudgePointOnArc(_ptAimStartPoint, *_iterBegin) + || !JudgePointOnArc(_ptAimMiddlePoint, *_iterBegin) + || !JudgePointOnArc(_ptAimEndPoint, *_iterBegin)) + continue; + + break; + } + + if (_iterBegin == _iterEnd) + return false; + } + + return true; +} + +Standard_Boolean CWires3DTranslator::JudgePointOnEdges(const gp_XYZ& ptPoint_, const LISTEDGES3D& listEdges_) const +{ + LISTEDGES3DCITER _iterBegin = listEdges_.begin(); + LISTEDGES3DCITER _iterEnd = listEdges_.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + if (EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType) + { + if (ptPoint_.IsEqual(_iterBegin->ptStart, g_nDistPrecision) || ptPoint_.IsEqual(_iterBegin->ptEnd, g_nDistPrecision)) + return true; + + // 计算点到线段的最小距离 + Standard_Real _nMinDistance = 0.; + gp_XYZ _ptStartDiff = ptPoint_ - _iterBegin->ptStart; + gp_XYZ _ptEndDiff = ptPoint_ - _iterBegin->ptEnd; + if (_ptStartDiff * _iterBegin->ptDir < -1.0 * g_nCosinPrecision) + _nMinDistance = _ptStartDiff.Modulus(); + else if (_ptEndDiff * _iterBegin->ptDir.Reversed() < -1.0 * g_nCosinPrecision) + _nMinDistance = _ptEndDiff.Modulus(); + else + _nMinDistance = (_ptStartDiff ^ _iterBegin->ptDir).Modulus(); + + if (_nMinDistance < 2.0 * g_nEdgeDeflection) + return true; + } + else + { + ASSERT(EdgeInfo::EDGE_OVAL == _iterBegin->nEdgeType); + if (JudgePointOnArc(ptPoint_, *_iterBegin)) + return true; + } + } + + return false; +} + +Standard_Boolean CWires3DTranslator::JudgePointOnArc(const gp_XYZ& ptPoint_, const Edge3DInfo& edge_) const +{ + ASSERT(EdgeInfo::EDGE_OVAL == edge_.nEdgeType); + + // 先判断点是否在圆/椭圆上 + if (!COSIN_EQU((ptPoint_ - edge_.ptCenter) * (edge_.ptXDir ^ edge_.ptYDir), 0.)) + return false; + + if (DIST_EQU(edge_.nLongRadius, edge_.nShortRadius)) + { + Standard_Real _nDistError = (ptPoint_ - edge_.ptCenter).Modulus() - edge_.nLongRadius; + if (fabs(_nDistError) > 2.0 * g_nDistPrecision) + return false; + } + else + { + gp_XYZ _ptLeftFocus, _ptRightFocus; + GetOvalFocus(edge_, _ptLeftFocus, _ptRightFocus); + Standard_Real _nDistError = (ptPoint_ - _ptLeftFocus).Modulus() + (ptPoint_ - _ptRightFocus).Modulus() - 2.0 * edge_.nLongRadius; + if (fabs(_nDistError) > 2.0 * g_nDistPrecision) + return false; + } + + // 再判断点是否在圆/椭圆弧上 + if (ANGLE_EQU(fabs(edge_.nLastParam - edge_.nFirstParam), 2.0 * g_nPIE)) + return true; + + Standard_Real _nAngle = GetElipsAngle(edge_.ptXDir, edge_.ptYDir, edge_.ptCenter, ptPoint_); + Standard_Real _nMinAngle = min(edge_.nFirstParam, edge_.nLastParam); + while (!ANGLE_EQU(_nAngle, _nMinAngle) && (_nAngle < _nMinAngle)) + _nAngle += 2.0 * g_nPIE; + while (!ANGLE_EQU(_nAngle, _nMinAngle) && (ANGLE_EQU(_nAngle - 2.0 * g_nPIE, _nMinAngle) || (_nAngle - 2.0 * g_nPIE > _nMinAngle))) + _nAngle -= 2.0 * g_nPIE; + + if (ANGLE_EQU(_nAngle, edge_.nFirstParam) + || ANGLE_EQU(_nAngle, edge_.nLastParam) + || ((_nAngle - edge_.nFirstParam) * (_nAngle - edge_.nLastParam) < 0.)) + return true; + + return false; +} + +////////////////////////////////////////////////////////////////////////// +// class CWires2DTranslator +CWires2DTranslator::CWires2DTranslator() + : m_nCurXBorder(0.) + , m_nCurXOffset(0.) + , m_pTubeToCadTranslator(NULL) +{ +} + +void CWires2DTranslator::Initialize(CTubeToCadTranslator* pTubeToCadTranslator_) +{ + ASSERT(pTubeToCadTranslator_ != NULL); + m_pTubeToCadTranslator = pTubeToCadTranslator_; + m_nCurXBorder = 0.; + m_nCurXOffset = 0.; +} + +Standard_Boolean CWires2DTranslator::Translate(const LISTWIRES3DONPLANE& listWires3DOnPlane_, LISTWIRES2DONSURFACE& listWires2DOnSurface_) +{ + ASSERT(listWires3DOnPlane_.size() == m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size()); + if (listWires3DOnPlane_.size() != m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size()) + return false; + + LISTDOUBLE _listXBorder; + LISTDOUBLE _listXOffset; + if (!GetExpandXBorder(_listXBorder) || !GetExpandXOffset(_listXOffset)) + return false; + + LISTEDGES3DCITER _iterBaseEdge = m_pTubeToCadTranslator->m_OuterBoundary.listEdges.begin(); + LISTDOUBLE::const_iterator _iterXBorder = _listXBorder.begin(); + LISTDOUBLE::const_iterator _iterXOffset = _listXOffset.begin(); + + LISTWIRES3DONPLANECITER _iterPlaneBegin = listWires3DOnPlane_.begin(); + LISTWIRES3DONPLANECITER _iterPlaneEnd = listWires3DOnPlane_.end(); + for (; _iterPlaneBegin != _iterPlaneEnd; ++_iterPlaneBegin, ++_iterBaseEdge, ++_iterXBorder, ++_iterXOffset) + { + // 当前面的X轴展开坐标的边界及偏置 + m_nCurXBorder = *_iterXBorder; + m_nCurXOffset = *_iterXOffset; + + Wire2DOnSurfaceInfo _wires2DOnSurface; + if (EdgeInfo::EDGE_LINE == _iterBaseEdge->nEdgeType) + { + Trans3DWiresTo2DWiresOnPlane(*_iterBaseEdge, _iterPlaneBegin->listWires, _wires2DOnSurface.listWires); + } + else + { + ASSERT(EdgeInfo::EDGE_OVAL == _iterBaseEdge->nEdgeType); + Trans3DWiresTo2DWiresOnOvalSurface(*_iterBaseEdge, _iterPlaneBegin->listWires, _wires2DOnSurface.listWires); + } + + listWires2DOnSurface_.push_back(_wires2DOnSurface); + } + + ASSERT(listWires2DOnSurface_.size() == m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size()); + + return true; +} + +Standard_Boolean CWires2DTranslator::GetExpandXBorder(LISTDOUBLE& listXBorder_) const +{ + ASSERT(listXBorder_.empty()); + + TubeInfo& _TubeParam = m_pTubeToCadTranslator->m_TubeParam; + if ((TubeInfo::circular == _TubeParam.nTubeType) || (TubeInfo::oval == _TubeParam.nTubeType)) + { + listXBorder_.push_back(0.); + return true; + } + else if (TubeInfo::rectangular == _TubeParam.nTubeType) + { + if (m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 4) + { + // 直角矩形 + for (Standard_Integer i = 0; i < 2; ++i) + { + listXBorder_.push_back(0.5 * _TubeParam.nRectWidth); + listXBorder_.push_back(0.5 * _TubeParam.nRectHeight); + } + } + else + { + // 圆角矩形 + ASSERT(m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 8); + for (Standard_Integer i = 0; i < 2; ++i) + { + listXBorder_.push_back(0.5 * _TubeParam.nRectWidth - _TubeParam.nRectRadius); + listXBorder_.push_back(0.); + listXBorder_.push_back(0.5 * _TubeParam.nRectHeight - _TubeParam.nRectRadius); + listXBorder_.push_back(0.); + } + } + + return (listXBorder_.size() == m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size()); + } + else if (TubeInfo::waist == _TubeParam.nTubeType) + { + // 腰形 + ASSERT(m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 4); + for (Standard_Integer i = 0; i < 2; ++i) + { + listXBorder_.push_back(0.5 * _TubeParam.nWaistWidth); + listXBorder_.push_back(0.); + } + + return (listXBorder_.size() == m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size()); + } + + ASSERT(false); + return false; +} + +Standard_Boolean CWires2DTranslator::GetExpandXOffset(LISTDOUBLE& listXOffset_) const +{ + ASSERT(listXOffset_.empty()); + + TubeInfo& _TubeParam = m_pTubeToCadTranslator->m_TubeParam; + if ((TubeInfo::circular == _TubeParam.nTubeType) || (TubeInfo::oval == _TubeParam.nTubeType)) + { + listXOffset_.push_back(0.); + return true; + } + else if (TubeInfo::rectangular == _TubeParam.nTubeType) + { + if (m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 4) + { + // 直角矩形 + Standard_Real _nStep = 0.5 * (_TubeParam.nRectWidth + _TubeParam.nRectHeight); + for (Standard_Integer i = 0; i < 4; ++i) + listXOffset_.push_back(_nStep * i); + } + else + { + // 圆角矩形 + ASSERT(m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 8); + Standard_Real _nStep = _TubeParam.nRectWidth + _TubeParam.nRectHeight; + for (Standard_Integer i = 0; i < 2; ++i) + { + listXOffset_.push_back(_nStep * i); + listXOffset_.push_back(_nStep * i + 0.5 * _TubeParam.nRectWidth - _TubeParam.nRectRadius); + listXOffset_.push_back(_nStep * i + 0.5 * _TubeParam.nRectWidth + 0.5 * _TubeParam.nRectHeight); + listXOffset_.push_back(_nStep * i + 0.5 * _TubeParam.nRectWidth + _TubeParam.nRectHeight - _TubeParam.nRectRadius); + } + } + + return (listXOffset_.size() == m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size()); + } + else if (TubeInfo::waist == _TubeParam.nTubeType) + { + // 腰形 + ASSERT(m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 4); + Standard_Real _nStep = _TubeParam.nWaistWidth + 0.5 * g_nPIE * _TubeParam.nWaistHeight; + for (Standard_Integer i = 0; i < 2; ++i) + { + listXOffset_.push_back(_nStep * i); + listXOffset_.push_back(_nStep * i + 0.5 * _TubeParam.nWaistWidth); + } + + return (listXOffset_.size() == m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size()); + } + + ASSERT(false); + return false; +} + +void CWires2DTranslator::Trans3DWiresTo2DWiresOnPlane(const Edge3DInfo& baseEdge_, const LISTWIRES3D& listWires3D_, LISTWIRES2D& listWires2D_) +{ + ASSERT(EdgeInfo::EDGE_LINE == baseEdge_.nEdgeType); + + LISTWIRES3DCITER _iterWireBegin = listWires3D_.begin(); + LISTWIRES3DCITER _iterWireEnd = listWires3D_.end(); + for (; _iterWireBegin != _iterWireEnd; ++_iterWireBegin) + { + Wire2DInfo _wire2D; + LISTEDGES3DCITER _iterEdge3DBegin = _iterWireBegin->listEdges.begin(); + LISTEDGES3DCITER _iterEdge3DEnd = _iterWireBegin->listEdges.end(); + for (; _iterEdge3DBegin != _iterEdge3DEnd; ++_iterEdge3DBegin) + { + Trans3DEdgeTo2DEdgeOnPlane(baseEdge_, *_iterEdge3DBegin, _wire2D); + } + + // 检查刚添加的线是否在边界上 + LISTEDGES2D::iterator _iterEdge2DBegin = _wire2D.listEdges.begin(); + LISTEDGES2D::iterator _iterEdge2DEnd = _wire2D.listEdges.end(); + for (; _iterEdge2DBegin != _iterEdge2DEnd; ++_iterEdge2DBegin) + { + if (DIST_EQU(fabs(_iterEdge2DBegin->StartPoint().X() - m_nCurXOffset), m_nCurXBorder)) + { + _wire2D.bOnBorder = true; + break; + } + } + + if (!_wire2D.bOnBorder && DIST_EQU(fabs(_wire2D.listEdges.back().EndPoint().X() - m_nCurXOffset), m_nCurXBorder)) + _wire2D.bOnBorder = true; + + listWires2D_.push_back(_wire2D); + } +} + +void CWires2DTranslator::Trans3DEdgeTo2DEdgeOnPlane(const Edge3DInfo& baseEdge_, const Edge3DInfo& edge3D_, Wire2DInfo& wire2D_) +{ + ASSERT(EdgeInfo::EDGE_LINE == baseEdge_.nEdgeType); + gp_XYZ _ptStandardPoint = (baseEdge_.StartPoint() + baseEdge_.EndPoint()) * 0.5; + + Edge2DInfo _edge2D; + _edge2D.nEdgeType = edge3D_.nEdgeType; + if (EdgeInfo::EDGE_LINE == edge3D_.nEdgeType) + { + _edge2D.ptStart = GetProjectionOnPlane(baseEdge_, _ptStandardPoint, edge3D_.ptStart); + _edge2D.ptEnd = GetProjectionOnPlane(baseEdge_, _ptStandardPoint, edge3D_.ptEnd); + wire2D_.listEdges.push_back(_edge2D); + return; + } + + ASSERT(EdgeInfo::EDGE_OVAL == edge3D_.nEdgeType); + _edge2D.ptCenter = GetProjectionOnPlane(baseEdge_, _ptStandardPoint, edge3D_.ptCenter); + _edge2D.nLongRadius = edge3D_.nLongRadius; + _edge2D.nShortRadius = edge3D_.nShortRadius; + + gp_XYZ _ptNormalVector = baseEdge_.ptDir ^ m_pTubeToCadTranslator->m_ptAxleWireDir; + Standard_Real _nRotateAngle = gp_Dir(baseEdge_.ptDir).Angle(gp_Dir(edge3D_.ptXDir)); + gp_XYZ _ptTestNormalVector = baseEdge_.ptDir ^ edge3D_.ptXDir; + if (!DIST_EQU(_ptTestNormalVector.Modulus(), 0.) && !_ptNormalVector.IsEqual(_ptTestNormalVector.Normalized(), g_nDistPrecision)) + _nRotateAngle = 2.0 * g_nPIE - _nRotateAngle; + _edge2D.nDipAngle = _nRotateAngle; + + Standard_Real _nRatio = _ptNormalVector.IsEqual(edge3D_.ptXDir ^ edge3D_.ptYDir, g_nDistPrecision) ? 1.0 : -1.0; + _edge2D.nFirstParam = edge3D_.nFirstParam * _nRatio; + _edge2D.nLastParam = edge3D_.nLastParam * _nRatio; + + wire2D_.listEdges.push_back(_edge2D); +} + +gp_XY CWires2DTranslator::GetProjectionOnPlane(const Edge3DInfo& baseEdge_, const gp_XYZ& ptStandardPoint_, const gp_XYZ& ptAimPoint_) +{ + ASSERT(EdgeInfo::EDGE_LINE == baseEdge_.nEdgeType); + + Standard_Real _nRelativeY = (ptAimPoint_ - ptStandardPoint_) * m_pTubeToCadTranslator->m_ptAxleWireDir; + gp_XYZ _ptProjectionDiff = (ptAimPoint_ - _nRelativeY * m_pTubeToCadTranslator->m_ptAxleWireDir) - ptStandardPoint_; + ASSERT(DIST_EQU(_ptProjectionDiff.Modulus(), 0.) || IsEqualVectorNoDir(_ptProjectionDiff.Normalized(), baseEdge_.ptDir)); + Standard_Real _nRelativeX = _ptProjectionDiff * baseEdge_.ptDir; + + return gp_XY(_nRelativeX + m_nCurXOffset, _nRelativeY); +} + +void CWires2DTranslator::Trans3DWiresTo2DWiresOnOvalSurface(const Edge3DInfo& baseEdge_, const LISTWIRES3D& listWires3D_, LISTWIRES2D& listWires2D_) +{ + ASSERT(EdgeInfo::EDGE_OVAL == baseEdge_.nEdgeType); + + LISTWIRES3DCITER _iterWireBegin = listWires3D_.begin(); + LISTWIRES3DCITER _iterWireEnd = listWires3D_.end(); + for (; _iterWireBegin != _iterWireEnd; ++_iterWireBegin) + { + Wire2DInfo _wire2D; + LISTEDGES3DCITER _iterEdgeBegin = _iterWireBegin->listEdges.begin(); + LISTEDGES3DCITER _iterEdgeEnd = _iterWireBegin->listEdges.end(); + for (; _iterEdgeBegin != _iterEdgeEnd; ++_iterEdgeBegin) + { + if ((EdgeInfo::EDGE_LINE == _iterEdgeBegin->nEdgeType) + || IsEqualVectorNoDir(_iterEdgeBegin->ptXDir ^ _iterEdgeBegin->ptYDir, m_pTubeToCadTranslator->m_ptAxleWireDir)) + { + Trans3DEdgeTo2DEdgeOnOvalSurface(baseEdge_, *_iterEdgeBegin, _wire2D); + continue; + } + + // 将椭圆/圆弧按照精度离散 + LISTEDGES3D _listEdges3D; + SplitArcEdgeToLineEdges(*_iterEdgeBegin, _listEdges3D); + + LISTEDGES3DCITER _iterTempBegin = _listEdges3D.begin(); + LISTEDGES3DCITER _iterTempEnd = _listEdges3D.end(); + for (; _iterTempBegin != _iterTempEnd; ++_iterTempBegin) + { + ASSERT(EdgeInfo::EDGE_LINE == _iterTempBegin->nEdgeType); + Trans3DEdgeTo2DEdgeOnOvalSurface(baseEdge_, *_iterTempBegin, _wire2D); + } + } + + _wire2D.bOnBorder = true; + ScatterWireByJoin(_wire2D, listWires2D_); + } +} + +void CWires2DTranslator::Trans3DEdgeTo2DEdgeOnOvalSurface(const Edge3DInfo& baseEdge_, const Edge3DInfo& edge3D_, Wire2DInfo& wire2D_) +{ + ASSERT(EdgeInfo::EDGE_OVAL == baseEdge_.nEdgeType); + ASSERT((EdgeInfo::EDGE_LINE == edge3D_.nEdgeType) + || IsEqualVectorNoDir(edge3D_.ptXDir ^ edge3D_.ptYDir, m_pTubeToCadTranslator->m_ptAxleWireDir)); + + gp_XYZ _ptStandardPoint = baseEdge_.ptCenter; + + Edge2DInfo _edge2D; + _edge2D.nEdgeType = EdgeInfo::EDGE_LINE; + _edge2D.ptStart = GetProjectionOnOvalSurface(baseEdge_, _ptStandardPoint, edge3D_.StartPoint()); + _edge2D.ptEnd = GetProjectionOnOvalSurface(baseEdge_, _ptStandardPoint, edge3D_.EndPoint()); + + const TubeInfo& _TubeParam = m_pTubeToCadTranslator->m_TubeParam; + if ((_TubeParam.nTubeType != TubeInfo::circular) && (_TubeParam.nTubeType != TubeInfo::oval)) + { + wire2D_.listEdges.push_back(_edge2D); + return; + } + + // 椭圆/圆管 + Standard_Real _nPerimeter = 0.; + if (TubeInfo::circular == _TubeParam.nTubeType) + { + ASSERT(DIST_EQU(_TubeParam.nCircleRadius, baseEdge_.nLongRadius) && DIST_EQU(baseEdge_.nLongRadius, baseEdge_.nShortRadius)); + _nPerimeter = baseEdge_.nLongRadius * 2.0 * g_nPIE; + } + else + { + ASSERT(TubeInfo::oval == _TubeParam.nTubeType); + ASSERT(DIST_EQU(_TubeParam.nOvalLongRadius, baseEdge_.nLongRadius) && DIST_EQU(_TubeParam.nOvalShortRadius, baseEdge_.nShortRadius)); + _nPerimeter = _TubeParam.nOvalPerimeter; + } + + if (IsEqualVectorNoDir(edge3D_.ptXDir ^ edge3D_.ptYDir, m_pTubeToCadTranslator->m_ptAxleWireDir) + && ANGLE_EQU(fabs(edge3D_.nLastParam - edge3D_.nFirstParam), 2.0 * g_nPIE)) + { + ASSERT(edge3D_.StartPoint().IsEqual(edge3D_.EndPoint(), g_nDistPrecision)); + _edge2D.ptStart.SetX(0.); + _edge2D.ptEnd.SetX(_nPerimeter); + wire2D_.listEdges.push_back(_edge2D); + return; + } + + // 检查边是否跨越边界 + if (EdgeInfo::EDGE_LINE == edge3D_.nEdgeType) + JudgeLineAcrossBorder(baseEdge_, edge3D_, _edge2D, wire2D_); + else + { + ASSERT(EdgeInfo::EDGE_OVAL == edge3D_.nEdgeType); + JudgeArcAcrossBorder(baseEdge_, edge3D_, _edge2D, wire2D_); + } +} + +gp_XY CWires2DTranslator::GetProjectionOnOvalSurface(const Edge3DInfo& baseEdge_, const gp_XYZ& ptStandardPoint_, const gp_XYZ& ptAimPoint_) +{ + ASSERT(EdgeInfo::EDGE_OVAL == baseEdge_.nEdgeType); + + Standard_Real _nRelativeY = (ptAimPoint_ - ptStandardPoint_) * m_pTubeToCadTranslator->m_ptAxleWireDir; + gp_XYZ _ptProjectionDiff = (ptAimPoint_ - _nRelativeY * m_pTubeToCadTranslator->m_ptAxleWireDir) - ptStandardPoint_; + ASSERT(COSIN_EQU(_ptProjectionDiff * m_pTubeToCadTranslator->m_ptAxleWireDir, 0.)); + + gp_XYZ _ptStartDiff = baseEdge_.StartPoint() - ptStandardPoint_; + Standard_Real _nAngle = gp_Dir(_ptProjectionDiff).Angle(gp_Dir(_ptStartDiff)); + Standard_Real _nRelativeX = 0.; + switch (m_pTubeToCadTranslator->m_TubeParam.nTubeType) + { + case TubeInfo::rectangular: + { + ASSERT((fabs(_nAngle) > -g_nEdgeDeflection) && (_nAngle < g_nPIE * 0.5 + g_nEdgeDeflection)); + __CUT(_nAngle, 0., g_nPIE * 0.5); + _nRelativeX = 2.0 * baseEdge_.nLongRadius * _nAngle / (g_nPIE * 0.5); + } + break; + + case TubeInfo::circular: + case TubeInfo::oval: + { + if (DIGIT_EQU(_nAngle, 0.)) + _nAngle = 0.; + else if (DIGIT_EQU(_nAngle, g_nPIE)) + _nAngle = g_nPIE; + else + { + // 计算起点沿弧方向旋转45°后的坐标值 + Standard_Real _nRotateAngle = 0.25 * g_nPIE * _copysign(1.0, baseEdge_.nLastParam - baseEdge_.nFirstParam); + gp_XYZ _ptMiniDeltaStart = baseEdge_.ptCenter + baseEdge_.nLongRadius * cos(baseEdge_.nFirstParam + _nRotateAngle) * baseEdge_.ptXDir + + baseEdge_.nShortRadius * sin(baseEdge_.nFirstParam + _nRotateAngle) * baseEdge_.ptYDir; + gp_XYZ _ptNormalVector = (_ptStartDiff ^ (_ptMiniDeltaStart - ptStandardPoint_)).Normalized(); + gp_XYZ _ptAimNormalVector = _ptStartDiff ^ _ptProjectionDiff; + if (!DIST_EQU(_ptAimNormalVector.Modulus(), 0.) && !_ptNormalVector.IsEqual(_ptAimNormalVector.Normalized(), g_nDistPrecision)) + { + ASSERT(_ptNormalVector.IsEqual(_ptAimNormalVector.Normalized().Reversed(), g_nDistPrecision)); + _nAngle = 2.0 * g_nPIE - _nAngle; + } + } + + _nRelativeX = GetOvalArcLength(baseEdge_, _nAngle); + } + break; + + case TubeInfo::waist: + { + ASSERT((fabs(_nAngle) > -g_nEdgeDeflection) && (_nAngle < g_nPIE + g_nEdgeDeflection)); + __CUT(_nAngle, 0., g_nPIE); + _nRelativeX = GetOvalArcLength(baseEdge_, _nAngle); + } + break; + + default: + ASSERT(false); + return gp_XY(0., 0.); + } + + return gp_XY(_nRelativeX + m_nCurXOffset, _nRelativeY); +} + +Standard_Real CWires2DTranslator::GetOvalArcLength(const Edge3DInfo& baseEdge_, Standard_Real nCentralAngle_) +{ + ASSERT(EdgeInfo::EDGE_OVAL == baseEdge_.nEdgeType); + + const TubeInfo& _TubeParam = m_pTubeToCadTranslator->m_TubeParam; + if (TubeInfo::circular == _TubeParam.nTubeType) + { + ASSERT(DIST_EQU(_TubeParam.nCircleRadius, baseEdge_.nLongRadius) && DIST_EQU(baseEdge_.nLongRadius, baseEdge_.nShortRadius)); + return baseEdge_.nLongRadius * nCentralAngle_; + } + + if (TubeInfo::waist == _TubeParam.nTubeType) + { + ASSERT(DIST_EQU(_TubeParam.nWaistHeight * 0.5, baseEdge_.nLongRadius) && DIST_EQU(baseEdge_.nLongRadius, baseEdge_.nShortRadius)); + return baseEdge_.nLongRadius * nCentralAngle_; + } + + // 数值积分计算椭圆弧长度 + ASSERT(TubeInfo::oval == _TubeParam.nTubeType); + ASSERT(DIST_EQU(_TubeParam.nOvalLongRadius, baseEdge_.nLongRadius) && DIST_EQU(_TubeParam.nOvalShortRadius, baseEdge_.nShortRadius)); + Standard_Real _nStartRadian = 0.; + Standard_Real _nEndRadian = 0.; + if (baseEdge_.nLastParam > baseEdge_.nFirstParam) + { + _nStartRadian = baseEdge_.nFirstParam; + _nEndRadian = baseEdge_.nFirstParam + nCentralAngle_; + } + else + { + _nStartRadian = baseEdge_.nFirstParam - nCentralAngle_; + _nEndRadian = baseEdge_.nFirstParam; + } + + ASSERT(_nStartRadian <= _nEndRadian); + if (ANGLE_EQU(_nStartRadian, _nEndRadian)) + return 0.; + if (ANGLE_EQU(_nEndRadian - _nStartRadian, 2.0 * g_nPIE)) + return _TubeParam.nOvalPerimeter; + + // 更新椭圆的离心率 + m_nEccentricity = sqrt(pow(_TubeParam.nOvalLongRadius, 2) - pow(_TubeParam.nOvalShortRadius, 2)) / _TubeParam.nOvalLongRadius; + + // 数值积分计算椭圆弧长度 + int _nLevel = 4; + double _nLength1 = CotesFormula(_nStartRadian, _nEndRadian, _nLevel); + double _nLength2 = CotesFormula(_nStartRadian, _nEndRadian, _nLevel * 2); + while (true) + { + // 曲线积分误差为曲线长度的千分之一 + if (fabs(_nLength1 - _nLength2) < min(1.e-6, _nLength2 * 0.001)) + return min(_nLength2, _TubeParam.nOvalPerimeter); + + _nLevel *= 2; + _nLength1 = _nLength2; + _nLength2 = CotesFormula(_nStartRadian, _nEndRadian, _nLevel * 2); + } +} + +Standard_Real CWires2DTranslator::CotesFormula(Standard_Real nLower_, Standard_Real nUpper_, Standard_Integer nLevel_) const +{ + // nLevel_阶复合柯特斯公式:S = L*∫_{ψ}^{φ}sqrt(1-k^2*(sinθ)^2)dθ + // 其中ψ为积分下限,φ为积分上限,L为长轴半径,k为离心率 + double _nStep = (nUpper_ - nLower_) / nLevel_; + ASSERT(!DIGIT_EQU(_nStep, 0.)); + + double _nLength = 0.; + for (int i = 0; i < nLevel_; ++i) + { + double _nBaseRadian = nLower_ + i * _nStep; + _nLength += 32.0 * GetIntegralTerm(_nBaseRadian + 0.25 * _nStep); + _nLength += 12.0 * GetIntegralTerm(_nBaseRadian + 0.5 * _nStep); + _nLength += 32.0 * GetIntegralTerm(_nBaseRadian + 0.75 * _nStep); + if (i > 0) + _nLength += 14.0 * GetIntegralTerm(_nBaseRadian); + } + + _nLength += 7.0 * GetIntegralTerm(nLower_); + _nLength += 7.0 * GetIntegralTerm(nUpper_); + + _nLength = _nLength * _nStep / 90.0; + return _nLength * m_pTubeToCadTranslator->m_TubeParam.nOvalLongRadius; +} + +Standard_Real CWires2DTranslator::GetIntegralTerm(Standard_Real nRadian_) const +{ + // 积分项:sqrt(1-k^2*(sinθ)^2) + return sqrt(1.0 - pow(m_nEccentricity * sin(nRadian_), 2)); +} + +void CWires2DTranslator::JudgeLineAcrossBorder(const Edge3DInfo& baseEdge_, const Edge3DInfo& edge3D_, const Edge2DInfo& edge2D_, Wire2DInfo& wire2D_) +{ + ASSERT((EdgeInfo::EDGE_OVAL == baseEdge_.nEdgeType) && (EdgeInfo::EDGE_LINE == edge3D_.nEdgeType)); + + Standard_Real _nMinXPos = min(edge2D_.ptStart.X(), edge2D_.ptEnd.X()); + Standard_Real _nMaxXPos = max(edge2D_.ptStart.X(), edge2D_.ptEnd.X()); + if (DIST_EQU(_nMinXPos, _nMaxXPos)) + { + wire2D_.listEdges.push_back(edge2D_); + return; + } + + //从首尾按照比率取点并转换,然后检查转换后的坐标 + const static Standard_Real _s_nRatio = 0.01; + gp_XYZ _ptFrontPoint3D = (1.0 - _s_nRatio) * edge3D_.ptStart + _s_nRatio * edge3D_.ptEnd; + gp_XYZ _ptBackPoint3D = _s_nRatio * edge3D_.ptStart + (1.0 - _s_nRatio) * edge3D_.ptEnd; + gp_XY _ptFrontPoint2D = GetProjectionOnOvalSurface(baseEdge_, baseEdge_.ptCenter, _ptFrontPoint3D); + gp_XY _ptBackPoint2D = GetProjectionOnOvalSurface(baseEdge_, baseEdge_.ptCenter, _ptBackPoint3D); + + if ((min(_ptFrontPoint2D.X(), _ptBackPoint2D.X()) >= _nMinXPos) && (max(_ptFrontPoint2D.X(), _ptBackPoint2D.X()) <= _nMaxXPos)) + { + wire2D_.listEdges.push_back(edge2D_); + return; + } + + // 椭圆/圆周长 + Standard_Real _nPerimeter = (TubeInfo::oval == m_pTubeToCadTranslator->m_TubeParam.nTubeType) + ? m_pTubeToCadTranslator->m_TubeParam.nOvalPerimeter + : 2.0 * g_nPIE * m_pTubeToCadTranslator->m_TubeParam.nCircleRadius; + ASSERT(fabs(edge2D_.ptStart.X() - edge2D_.ptEnd.X()) > 0.5 * _nPerimeter); + if (edge2D_.ptStart.X() > edge2D_.ptEnd.X()) + { + Standard_Real _nRatio = (_nPerimeter - edge2D_.ptStart.X()) / (_nPerimeter + edge2D_.ptEnd.X() - edge2D_.ptStart.X()); + Standard_Real _nNewYPos = (1.0 - _nRatio) * edge2D_.ptStart.Y() + _nRatio * edge2D_.ptEnd.Y(); + Edge2DInfo _edge2D = edge2D_; + _edge2D.ptEnd.SetX(_nPerimeter); + _edge2D.ptEnd.SetY(_nNewYPos); + if (!DIST_EQU((_edge2D.ptEnd - _edge2D.ptStart).Modulus(), 0.)) + wire2D_.listEdges.push_back(_edge2D); + + _edge2D.ptStart = _edge2D.ptEnd; + if (DIST_EQU((_edge2D.ptStart - edge2D_.ptEnd).Modulus(), 0.)) + return; + + _edge2D.ptStart.SetX(0.); + _edge2D.ptEnd = edge2D_.ptEnd; + if (!DIST_EQU((_edge2D.ptEnd - _edge2D.ptStart).Modulus(), 0.)) + wire2D_.listEdges.push_back(_edge2D); + } + else + { + Standard_Real _nRatio = edge2D_.ptStart.X() / (edge2D_.ptStart.X() - edge2D_.ptEnd.X() + _nPerimeter + edge2D_.ptEnd.X()); + Standard_Real _nNewYPos = (1.0 - _nRatio) * edge2D_.ptStart.Y() + _nRatio * edge2D_.ptEnd.Y(); + Edge2DInfo _edge2D = edge2D_; + _edge2D.ptEnd.SetX(0.); + _edge2D.ptEnd.SetY(_nNewYPos); + if (!DIST_EQU((_edge2D.ptEnd - _edge2D.ptStart).Modulus(), 0.)) + wire2D_.listEdges.push_back(_edge2D); + + _edge2D.ptStart = _edge2D.ptEnd; + if (DIST_EQU((_edge2D.ptStart - edge2D_.ptEnd).Modulus(), 0.)) + return; + + _edge2D.ptStart.SetX(_nPerimeter); + _edge2D.ptEnd = edge2D_.ptEnd; + if (!DIST_EQU((_edge2D.ptEnd - _edge2D.ptStart).Modulus(), 0.)) + wire2D_.listEdges.push_back(_edge2D); + } +} + +void CWires2DTranslator::JudgeArcAcrossBorder(const Edge3DInfo& baseEdge_, const Edge3DInfo& edge3D_, const Edge2DInfo& edge2D_, Wire2DInfo& wire2D_) +{ + ASSERT((EdgeInfo::EDGE_OVAL == baseEdge_.nEdgeType) && (EdgeInfo::EDGE_OVAL == edge3D_.nEdgeType)); + + // 椭圆/圆周长和弧长 + Standard_Real _nPerimeter = 0.; + Standard_Real _nOvalArcLength = 0.; + if (TubeInfo::circular == m_pTubeToCadTranslator->m_TubeParam.nTubeType) + { + _nPerimeter = 2.0 * g_nPIE * baseEdge_.nLongRadius; + _nOvalArcLength = fabs(edge3D_.nLastParam - edge3D_.nFirstParam) * baseEdge_.nLongRadius; + } + else + { + ASSERT(TubeInfo::oval == m_pTubeToCadTranslator->m_TubeParam.nTubeType); + _nPerimeter = m_pTubeToCadTranslator->m_TubeParam.nOvalPerimeter; + _nOvalArcLength = GetOvalArcLength(baseEdge_, fabs(edge3D_.nLastParam - edge3D_.nFirstParam)); + } + + Standard_Boolean _bSameDir = (baseEdge_.ptXDir ^ baseEdge_.ptYDir).IsEqual(edge3D_.ptXDir ^ edge3D_.ptYDir, g_nDistPrecision) + == ((baseEdge_.nLastParam - baseEdge_.nFirstParam) * (edge3D_.nLastParam - edge3D_.nFirstParam) > 0.); + if (_bSameDir) + { + Standard_Real _nRealEndX = edge2D_.ptStart.X() + _nOvalArcLength; + if (DIST_EQU(_nRealEndX, _nPerimeter) || (_nRealEndX > _nPerimeter)) + { + Edge2DInfo _edge2D = edge2D_; + _edge2D.ptEnd.SetX(_nPerimeter); + if (!DIST_EQU(_edge2D.ptStart.X(), _edge2D.ptEnd.X())) + wire2D_.listEdges.push_back(_edge2D); + + _edge2D.ptStart = _edge2D.ptEnd; + if (DIST_EQU(_edge2D.ptStart.X(), edge2D_.ptEnd.X())) + return; + + _edge2D.ptStart.SetX(0.); + _edge2D.ptEnd = edge2D_.ptEnd; + if (!DIST_EQU(_edge2D.ptStart.X(), _edge2D.ptEnd.X())) + wire2D_.listEdges.push_back(_edge2D); + + return; + } + } + else + { + Standard_Real _nRealEndX = edge2D_.ptStart.X() - _nOvalArcLength; + if (DIST_EQU(_nRealEndX, 0.) || (_nRealEndX < 0.)) + { + Edge2DInfo _edge2D = edge2D_; + _edge2D.ptEnd.SetX(0.); + if (!DIST_EQU(_edge2D.ptStart.X(), _edge2D.ptEnd.X())) + wire2D_.listEdges.push_back(_edge2D); + + _edge2D.ptStart = _edge2D.ptEnd; + if (DIST_EQU(_edge2D.ptStart.X(), edge2D_.ptEnd.X())) + return; + + _edge2D.ptStart.SetX(_nPerimeter); + _edge2D.ptEnd = edge2D_.ptEnd; + if (!DIST_EQU(_edge2D.ptStart.X(), _edge2D.ptEnd.X())) + wire2D_.listEdges.push_back(_edge2D); + + return; + } + } + + wire2D_.listEdges.push_back(edge2D_); +} + +void CWires2DTranslator::ScatterWireByJoin(const Wire2DInfo& wire2D_, LISTWIRES2D& listWires2D_) +{ + const TubeInfo::TubeType& _nTubeType = m_pTubeToCadTranslator->m_TubeParam.nTubeType; + if ((_nTubeType != TubeInfo::circular) && (_nTubeType != TubeInfo::oval)) + { + listWires2D_.push_back(wire2D_); + return; + } + + Wire2DInfo _wire2D; + _wire2D.bOnBorder = wire2D_.bOnBorder; + + LISTEDGES2D::const_iterator _iterEnd = wire2D_.listEdges.end(); + LISTEDGES2D::const_iterator _iterCur = wire2D_.listEdges.begin(); + LISTEDGES2D::const_iterator _iterNext = ++wire2D_.listEdges.begin(); + LISTEDGES2D::const_iterator _iterFlag = _iterCur; + while (_iterCur != _iterEnd && _iterNext != _iterEnd) + { + if (!_iterCur->EndPoint().IsEqual(_iterNext->StartPoint(), g_nDistPrecision)) + { + _wire2D.listEdges.assign(_iterFlag, _iterNext); + listWires2D_.push_back(_wire2D); + _wire2D.listEdges.clear(); + _iterFlag = _iterNext; + } + + ++_iterCur; + ++_iterNext; + } + + if (_iterFlag == wire2D_.listEdges.begin()) + listWires2D_.push_back(wire2D_); + else + { + _wire2D.listEdges.assign(_iterFlag, _iterNext); + listWires2D_.push_back(_wire2D); + } +} + +////////////////////////////////////////////////////////////////////////// +// class CCad2DTranslator +CCad2DTranslator::CCad2DTranslator() + : m_nPerimeter(0.) + , m_pTubeToCadTranslator(NULL) +{ +} + +void CCad2DTranslator::Initialize(CTubeToCadTranslator* pTubeToCadTranslator_) +{ + ASSERT(pTubeToCadTranslator_ != NULL); + m_pTubeToCadTranslator = pTubeToCadTranslator_; + + m_listEdgesOnArris.clear(); + m_listArrisBoundary.clear(); + m_nPerimeter = 0.; +} + +Standard_Boolean CCad2DTranslator::Translate(LISTWIRES2DONSURFACE& listWiresOnSurface_) +{ + // 去除管材棱处的边界线 + if (!RemoveArrisBoundary(listWiresOnSurface_)) + return false; + + // 获取首尾相连的线 + LISTWIRES2DONSURFACE _listWiresOnSurface; + GetConjoint2DWires(listWiresOnSurface_, _listWiresOnSurface); + + // 将管材边界棱上的线合并到扩展面 + LISTWIRES2DONSURFACE::iterator _iterSurfaceBegin = _listWiresOnSurface.begin(); + LISTWIRES2DONSURFACE::iterator _iterSurfaceEnd = _listWiresOnSurface.end(); + for (; _iterSurfaceBegin != _iterSurfaceEnd; ++_iterSurfaceBegin) + { + LISTWIRES2D::iterator _iterWireBegin = _iterSurfaceBegin->listWires.begin(); + LISTWIRES2D::iterator _iterWireEnd = _iterSurfaceBegin->listWires.end(); + while (_iterWireBegin != _iterWireEnd) + { + if (_iterWireBegin->bOnBorder + && CheckIsOnlyLeftBoundary(*_iterWireBegin) + && CombineWireOnArris(*_iterWireBegin, m_nPerimeter, _listWiresOnSurface.back().listWires)) + { + LISTWIRES2D::iterator _iterTemp = _iterWireBegin++; + _iterSurfaceBegin->listWires.erase(_iterTemp); + } + else + ++_iterWireBegin; + } + + _iterWireBegin = _iterSurfaceBegin->listWires.begin(); + _iterWireEnd = _iterSurfaceBegin->listWires.end(); + while (_iterWireBegin != _iterWireEnd) + { + if (_iterWireBegin->bOnBorder + && CheckIsOnlyRightBoundary(*_iterWireBegin) + && CombineWireOnArris(*_iterWireBegin, -m_nPerimeter, _listWiresOnSurface.front().listWires)) + { + LISTWIRES2D::iterator _iterTemp = _iterWireBegin++; + _iterSurfaceBegin->listWires.erase(_iterTemp); + } + else + ++_iterWireBegin; + } + } + + // 将二维展开面的线转化为二维空间的CAD对象 + _iterSurfaceBegin = _listWiresOnSurface.begin(); + _iterSurfaceEnd = _listWiresOnSurface.end(); + for (; _iterSurfaceBegin != _iterSurfaceEnd; ++_iterSurfaceBegin) + { + LISTWIRES2D::iterator _iterWireBegin = _iterSurfaceBegin->listWires.begin(); + LISTWIRES2D::iterator _iterWireEnd = _iterSurfaceBegin->listWires.end(); + while (_iterWireBegin != _iterWireEnd) + { + if (!_iterWireBegin->bOnBorder) + { + // 平面内 + Trans2DWireTo2DCad(_iterWireBegin->listEdges); + LISTWIRES2D::iterator _iterTemp = _iterWireBegin++; + _iterSurfaceBegin->listWires.erase(_iterTemp); + continue; + } + + LISTWIRES2DONSURFACE::iterator _iterSurfaceTemp = _iterSurfaceBegin; + ++_iterSurfaceTemp; + if (_iterSurfaceTemp == _iterSurfaceEnd) + { + Trans2DWireTo2DCad(_iterWireBegin->listEdges); + LISTWIRES2D::iterator _iterTemp = _iterWireBegin++; + _iterSurfaceBegin->listWires.erase(_iterTemp); + continue; + } + + if (!CombineWireOnArris(*_iterWireBegin, 0., _iterSurfaceTemp->listWires)) + Trans2DWireTo2DCad(_iterWireBegin->listEdges); + + LISTWIRES2D::iterator _iterTemp = _iterWireBegin++; + _iterSurfaceBegin->listWires.erase(_iterTemp); + } + } + + return true; +} + +Standard_Boolean CCad2DTranslator::RemoveArrisBoundary(LISTWIRES2DONSURFACE& listWiresOnSurface_) +{ + // 获取管材棱处的X轴边界值 + ASSERT(m_listArrisBoundary.empty()); + + const TubeInfo& _TubeParam = m_pTubeToCadTranslator->m_TubeParam; + switch (_TubeParam.nTubeType) + { + case TubeInfo::circular: + case TubeInfo::oval: + { + m_nPerimeter = (TubeInfo::circular == _TubeParam.nTubeType) ? 2.0 * g_nPIE * _TubeParam.nCircleRadius : _TubeParam.nOvalPerimeter; + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0., true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.25 * m_nPerimeter, false)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.5 * m_nPerimeter, false)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.75 * m_nPerimeter, false)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(m_nPerimeter, true)); + } + break; + + case TubeInfo::rectangular: + { + m_nPerimeter = 2.0 * (_TubeParam.nRectWidth + _TubeParam.nRectHeight); + if (m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 4) + { + // 直角矩形 + m_listArrisBoundary.push_back(ArrisBoundaryInfo(-0.5 * _TubeParam.nRectWidth, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.5 * _TubeParam.nRectWidth, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.5 * _TubeParam.nRectWidth + _TubeParam.nRectHeight, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(1.5 * _TubeParam.nRectWidth + _TubeParam.nRectHeight, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(1.5 * _TubeParam.nRectWidth + 2.0 * _TubeParam.nRectHeight, true)); + } + else + { + // 圆角矩形 + ASSERT(m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 8); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(-0.5 * _TubeParam.nRectWidth + _TubeParam.nRectRadius, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.5 * _TubeParam.nRectWidth - _TubeParam.nRectRadius, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.5 * _TubeParam.nRectWidth + _TubeParam.nRectRadius, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.5 * _TubeParam.nRectWidth + _TubeParam.nRectHeight - _TubeParam.nRectRadius, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.5 * _TubeParam.nRectWidth + _TubeParam.nRectHeight + _TubeParam.nRectRadius, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(1.5 * _TubeParam.nRectWidth + _TubeParam.nRectHeight - _TubeParam.nRectRadius, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(1.5 * _TubeParam.nRectWidth + _TubeParam.nRectHeight + _TubeParam.nRectRadius, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(1.5 * _TubeParam.nRectWidth + 2.0 * _TubeParam.nRectHeight - _TubeParam.nRectRadius, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(1.5 * _TubeParam.nRectWidth + 2.0 * _TubeParam.nRectHeight + _TubeParam.nRectRadius, true)); + } + } + break; + + case TubeInfo::waist: + { + //腰形管 + m_nPerimeter = 2.0 * _TubeParam.nWaistWidth + g_nPIE * _TubeParam.nWaistHeight; + ASSERT(m_pTubeToCadTranslator->m_OuterBoundary.listEdges.size() == 4); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(-0.5 * _TubeParam.nWaistWidth, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.5 * _TubeParam.nWaistWidth, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.5 * _TubeParam.nWaistWidth + 0.25 * g_nPIE * _TubeParam.nWaistHeight, false)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(0.5 * _TubeParam.nWaistWidth + 0.5 * g_nPIE * _TubeParam.nWaistHeight, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(1.5 * _TubeParam.nWaistWidth + 0.5 * g_nPIE * _TubeParam.nWaistHeight, true)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(1.5 * _TubeParam.nWaistWidth + 0.75 * g_nPIE * _TubeParam.nWaistHeight, false)); + m_listArrisBoundary.push_back(ArrisBoundaryInfo(1.5 * _TubeParam.nWaistWidth + g_nPIE * _TubeParam.nWaistHeight, true)); + } + break; + + default: + ASSERT(false); + return false; + } + + // 去除管材棱处的边界线 + LISTWIRES2DONSURFACE::iterator _iterSurfaceBegin = listWiresOnSurface_.begin(); + LISTWIRES2DONSURFACE::iterator _iterSurfaceEnd = listWiresOnSurface_.end(); + for (; _iterSurfaceBegin != _iterSurfaceEnd; ++_iterSurfaceBegin) + { + RemoveArrisBoundary(_iterSurfaceBegin->listWires); + } + + return true; +} + +void CCad2DTranslator::RemoveArrisBoundary(LISTWIRES2D& listWires2D_) +{ + LISTWIRES2D::iterator _iterWireBegin = listWires2D_.begin(); + LISTWIRES2D::iterator _iterWireEnd = listWires2D_.end(); + while (_iterWireBegin != _iterWireEnd) + { + if (!_iterWireBegin->bOnBorder) + { + ++_iterWireBegin; + continue; + } + + LISTEDGES2D::iterator _iterEdgeBegin = _iterWireBegin->listEdges.begin(); + LISTEDGES2D::iterator _iterEdgeEnd = _iterWireBegin->listEdges.end(); + LISTEDGES2D::iterator _iterEdgeFlag = _iterEdgeBegin; + while (_iterEdgeBegin != _iterEdgeEnd) + { + if (_iterEdgeBegin->nEdgeType != EdgeInfo::EDGE_LINE) + { + ++_iterEdgeBegin; + continue; + } + + gp_XY _ptCrossProduct = (_iterEdgeBegin->ptEnd - _iterEdgeBegin->ptStart); + if (!DIST_EQU(_ptCrossProduct.X(), 0.)) + { + ++_iterEdgeBegin; + continue; + } + + if (!JudgeOnAllArrisBoundary(_iterEdgeBegin->ptEnd.X())) + { + ++_iterEdgeBegin; + continue; + } + + // 收集在棱上的边,有些可能是不能删除的,需要在后面补上 + m_listEdgesOnArris.push_back(*_iterEdgeBegin); + + // 拆分 + Wire2DInfo _wire2D; + _wire2D.listEdges = LISTEDGES2D(_iterEdgeFlag, _iterEdgeBegin++); + _wire2D.bOnBorder = _iterWireBegin->bOnBorder; + if (!_wire2D.listEdges.empty()) + listWires2D_.push_front(_wire2D); + _iterEdgeFlag = _iterEdgeBegin; + } + + if (_iterEdgeFlag == _iterWireBegin->listEdges.begin()) + { + ++_iterWireBegin; + continue; + } + + if (_iterEdgeFlag != _iterWireBegin->listEdges.end()) + { + Wire2DInfo _wire2D; + _wire2D.listEdges = LISTEDGES2D(_iterEdgeFlag, _iterWireBegin->listEdges.end()); + _wire2D.bOnBorder = _iterWireBegin->bOnBorder; + listWires2D_.push_front(_wire2D); + } + + LISTWIRES2D::iterator _iterWireTemp = _iterWireBegin++; + listWires2D_.erase(_iterWireTemp); + } +} + +Standard_Boolean CCad2DTranslator::JudgeOnRealArrisBoundary(Standard_Real nAimXPos_) const +{ + LISTARRISBOUNDARY::const_iterator _iterBegin = m_listArrisBoundary.begin(); + LISTARRISBOUNDARY::const_iterator _iterEnd = m_listArrisBoundary.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + if (_iterBegin->bRealArris && DIST_EQU(nAimXPos_, _iterBegin->nArrisXPos)) + return true; + } + + return false; +} + +Standard_Boolean CCad2DTranslator::JudgeOnAllArrisBoundary(Standard_Real nAimXPos_) const +{ + // 圆管/椭圆管/腰形管会在轴线上构造出虚拟棱,用于删除多余的边 + LISTARRISBOUNDARY::const_iterator _iterBegin = m_listArrisBoundary.begin(); + LISTARRISBOUNDARY::const_iterator _iterEnd = m_listArrisBoundary.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + if (DIST_EQU(nAimXPos_, _iterBegin->nArrisXPos)) + return true; + } + + return false; +} + +void CCad2DTranslator::GetConjoint2DWires(LISTWIRES2DONSURFACE& listWiresOnSurfaceIn_, LISTWIRES2DONSURFACE& listWiresOnSurfaceOut_) const +{ + LISTWIRES2DONSURFACE::iterator _iterBegin = listWiresOnSurfaceIn_.begin(); + LISTWIRES2DONSURFACE::iterator _iterEnd = listWiresOnSurfaceIn_.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + Wire2DOnSurfaceInfo _wires2DOnSurface; + GetConjoint2DWires(_iterBegin->listWires, _wires2DOnSurface.listWires); + listWiresOnSurfaceOut_.push_back(_wires2DOnSurface); + } +} + +void CCad2DTranslator::GetConjoint2DWires(LISTWIRES2D& listWires2DIn_, LISTWIRES2D& listWires2DOut_) const +{ + while (!listWires2DIn_.empty()) + { + Wire2DInfo _wire2D; + _wire2D.listEdges = listWires2DIn_.front().listEdges; + listWires2DIn_.pop_front(); + + LISTWIRES2D::iterator _iterWireBegin = listWires2DIn_.begin(); + LISTWIRES2D::iterator _iterWireEnd = listWires2DIn_.end(); + while (_iterWireBegin != _iterWireEnd) + { + if (!Combine2DWires(_iterWireBegin->listEdges, _wire2D.listEdges)) + { + ++_iterWireBegin; + continue; + } + + LISTWIRES2D::iterator _iterTemp = _iterWireBegin++; + listWires2DIn_.erase(_iterTemp); + } + + gp_XY& _ptStartPoint = _wire2D.listEdges.front().StartPoint(); + gp_XY& _ptEndPoint = _wire2D.listEdges.back().EndPoint(); + if (JudgeOnRealArrisBoundary(_ptStartPoint.X()) || JudgeOnRealArrisBoundary(_ptEndPoint.X())) + _wire2D.bOnBorder = true; + + // 合并多段线 + Merge2DEdges(_wire2D.listEdges); + + // 如果是整圆/椭圆,则修改参数值,保证同一几何图形表达方式一致 + if ((_wire2D.listEdges.size() == 1) && (_wire2D.listEdges.back().nEdgeType == EdgeInfo::EDGE_OVAL)) + { + Edge2DInfo& _edge2D = _wire2D.listEdges.back(); + if (ANGLE_EQU(fabs(_edge2D.nLastParam - _edge2D.nFirstParam), 2.0 * g_nPIE)) + { + _edge2D.nFirstParam = 0.; + _edge2D.nLastParam = 2.0 * g_nPIE; + + if (DIST_EQU(_edge2D.nLongRadius, _edge2D.nShortRadius)) + _edge2D.nDipAngle = 0.; + else if (_edge2D.nDipAngle > g_nPIE) + _edge2D.nDipAngle -= g_nPIE; + } + } + + // 将多义线转换为整圆 + CArcSplineHelper _arcSplineHelper; + Edge2DInfo _transEdge; + if (_arcSplineHelper.TransPolylineToCircle(_wire2D.listEdges, _transEdge)) + { + _wire2D.listEdges.clear(); + _wire2D.listEdges.push_back(_transEdge); + } + + if (!CheckWireExist(_wire2D, listWires2DOut_)) + listWires2DOut_.push_back(_wire2D); + } +} + +Standard_Boolean CCad2DTranslator::Combine2DWires(LISTEDGES2D& listEdgesSrc_, LISTEDGES2D& listEdgesDest_) const +{ + ASSERT(!listEdgesSrc_.empty() && !listEdgesDest_.empty()); + + gp_XY _ptSrcStart = listEdgesSrc_.front().StartPoint(); + gp_XY _ptSrcEnd = listEdgesSrc_.back().EndPoint(); + gp_XY _ptDestStart = listEdgesDest_.front().StartPoint(); + gp_XY _ptDestEnd = listEdgesDest_.back().EndPoint(); + + // 调整线的方向:Src的终点 与 Dest的起点 对接 + if (_ptSrcEnd.IsEqual(_ptDestEnd, g_nDistPrecision)) + ReverseEdges(listEdgesDest_); + else if (_ptSrcStart.IsEqual(_ptDestStart, g_nDistPrecision)) + ReverseEdges(listEdgesSrc_); + else if (_ptSrcStart.IsEqual(_ptDestEnd, g_nDistPrecision)) + { + ReverseEdges(listEdgesSrc_); + ReverseEdges(listEdgesDest_); + } + else if (!_ptSrcEnd.IsEqual(_ptDestStart, g_nDistPrecision)) + return JudgeInclude2DWires(listEdgesSrc_, listEdgesDest_); + + // 删除重复边 + DeleteRepeatEdges(listEdgesSrc_, listEdgesDest_); + Combine2DEdges(listEdgesSrc_, listEdgesDest_); + + return listEdgesSrc_.empty(); +} + +void CCad2DTranslator::ReverseEdges(LISTEDGES2D& listEdges_) const +{ + LISTEDGES2D _listEdges; + LISTEDGES2D::const_reverse_iterator _iterRBegin = listEdges_.rbegin(); + LISTEDGES2D::const_reverse_iterator _iterREnd = listEdges_.rend(); + for (; _iterRBegin != _iterREnd; ++_iterRBegin) + { + _listEdges.push_back(*_iterRBegin); + _listEdges.back().Reverse(); + } + + listEdges_ = _listEdges; +} + +void CCad2DTranslator::DeleteRepeatEdges(LISTEDGES2D& listCurEdges_, LISTEDGES2D& listNextEdges_) const +{ + ASSERT(listCurEdges_.back().EndPoint().IsEqual(listNextEdges_.front().StartPoint(), g_nDistPrecision)); + + // 从listCurEdges_的末尾开始检查是否有重复边 + LISTEDGES2D::iterator _iterRBegin = --listCurEdges_.end(); + LISTEDGES2D::iterator _iterREnd = listCurEdges_.begin(); + while (true) + { + Standard_Boolean _bBreak = false; + LISTEDGES2D::iterator _iterBegin = listNextEdges_.begin(); + LISTEDGES2D::iterator _iterEnd = listNextEdges_.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + if (!JudgeInclude2DEdge(*_iterBegin, *_iterRBegin)) + continue; + + if (_iterRBegin == _iterREnd) + { + listCurEdges_.erase(_iterRBegin); + _bBreak = true; + } + else + { + LISTEDGES2D::iterator _iterBak = _iterRBegin--; + listCurEdges_.erase(_iterBak); + } + + break; + } + + if (_bBreak || (_iterBegin == _iterEnd)) + break; + } + + // 从listNextEdges_的开头开始检查是否有重复边 + LISTEDGES2D::iterator _iterBegin = listNextEdges_.begin(); + LISTEDGES2D::iterator _iterEnd = listNextEdges_.end(); + while (_iterBegin != _iterEnd) + { + LISTEDGES2D::reverse_iterator _iterRBegin = listCurEdges_.rbegin(); + LISTEDGES2D::reverse_iterator _iterREnd = listCurEdges_.rend(); + for (; _iterRBegin != _iterREnd; ++_iterRBegin) + { + if (JudgeInclude2DEdge(*_iterRBegin, *_iterBegin)) + { + LISTEDGES2D::iterator _iterBak = _iterBegin++; + listNextEdges_.erase(_iterBak); + break; + } + } + + if (_iterRBegin == _iterREnd) + break; + } +} + +void CCad2DTranslator::Combine2DEdges(LISTEDGES2D& listEdgesSrc_, LISTEDGES2D& listEdgesDest_) const +{ + ASSERT(!listEdgesSrc_.empty() || !listEdgesDest_.empty()); + if (listEdgesSrc_.empty()) + return; + + if (listEdgesDest_.empty()) + { + listEdgesDest_ = listEdgesSrc_; + listEdgesSrc_.clear(); + return; + } + + gp_XY _ptSrcStart = listEdgesSrc_.front().StartPoint(); + gp_XY _ptSrcEnd = listEdgesSrc_.back().EndPoint(); + gp_XY _ptDestStart = listEdgesDest_.front().StartPoint(); + gp_XY _ptDestEnd = listEdgesDest_.back().EndPoint(); + if (_ptDestEnd.IsEqual(_ptSrcStart, g_nDistPrecision)) + { + listEdgesDest_.splice(listEdgesDest_.end(), listEdgesSrc_); + ASSERT(listEdgesSrc_.empty()); + } + else if (_ptDestEnd.IsEqual(_ptSrcEnd, g_nDistPrecision)) + { + LISTEDGES2D::const_reverse_iterator _iterRBegin = listEdgesSrc_.rbegin(); + LISTEDGES2D::const_reverse_iterator _iterREnd = listEdgesSrc_.rend(); + for (; _iterRBegin != _iterREnd; ++_iterRBegin) + { + listEdgesDest_.push_back(*_iterRBegin); + listEdgesDest_.back().Reverse(); + } + + listEdgesSrc_.clear(); + } + else if (_ptDestStart.IsEqual(_ptSrcStart, g_nDistPrecision)) + { + LISTEDGES2D::const_iterator _iterBegin = listEdgesSrc_.begin(); + LISTEDGES2D::const_iterator _iterEnd = listEdgesSrc_.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + listEdgesDest_.push_front(*_iterBegin); + listEdgesDest_.front().Reverse(); + } + + listEdgesSrc_.clear(); + } + else if (_ptDestStart.IsEqual(_ptSrcEnd, g_nDistPrecision)) + { + listEdgesDest_.splice(listEdgesDest_.begin(), listEdgesSrc_); + ASSERT(listEdgesSrc_.empty()); + } +} + +Standard_Boolean CCad2DTranslator::JudgeInclude2DEdge(const Edge2DInfo& standardEdge_, const Edge2DInfo& checkEdge_) const +{ + if ((standardEdge_.nEdgeType != checkEdge_.nEdgeType) || (EdgeInfo::EDGE_NONE == standardEdge_.nEdgeType)) + return false; + + // 两直线 + if (EdgeInfo::EDGE_LINE == standardEdge_.nEdgeType) + { + Standard_Real _nCrossProduct = (standardEdge_.ptEnd - standardEdge_.ptStart) ^ (checkEdge_.ptEnd - checkEdge_.ptStart); + if (!COSIN_EQU(_nCrossProduct, 0.)) + return false; + + // 线段长度 + Standard_Real _nStdEdgeLength = (standardEdge_.ptEnd - standardEdge_.ptStart).Modulus(); + Standard_Real _nCheckEdgeLength = (checkEdge_.ptEnd - checkEdge_.ptStart).Modulus(); + if (!DIST_EQU(_nStdEdgeLength, _nCheckEdgeLength) && (_nCheckEdgeLength > _nStdEdgeLength)) + return false; + + Standard_Real _nScalarProduct = (standardEdge_.ptEnd - standardEdge_.ptStart) * (checkEdge_.ptEnd - checkEdge_.ptStart); + if ((_nScalarProduct > 0.) + && (standardEdge_.ptStart.IsEqual(checkEdge_.ptStart, g_nDistPrecision) + || standardEdge_.ptEnd.IsEqual(checkEdge_.ptEnd, g_nDistPrecision))) + return true; + + if ((_nScalarProduct < 0.) + && (standardEdge_.ptStart.IsEqual(checkEdge_.ptEnd, g_nDistPrecision) + || standardEdge_.ptEnd.IsEqual(checkEdge_.ptStart, g_nDistPrecision))) + return true; + + return false; + } + + // 两椭圆/圆弧 + ASSERT(EdgeInfo::EDGE_OVAL == standardEdge_.nEdgeType); + if (!standardEdge_.ptCenter.IsEqual(checkEdge_.ptCenter, g_nDistPrecision)) + return false; + if (!DIST_EQU(standardEdge_.nLongRadius, checkEdge_.nLongRadius)) + return false; + if (!DIST_EQU(standardEdge_.nShortRadius, checkEdge_.nShortRadius)) + return false; + if (!DIST_EQU(standardEdge_.nLongRadius, checkEdge_.nShortRadius) + && !ANGLE_EQU(standardEdge_.nDipAngle, checkEdge_.nDipAngle) + && !ANGLE_EQU(fabs(standardEdge_.nDipAngle - checkEdge_.nDipAngle), g_nPIE)) + return false; + + // 圆心角 + Standard_Real _nStdCentralAngle = fabs(standardEdge_.nLastParam - standardEdge_.nFirstParam); + Standard_Real _nCheckCentralAngle = fabs(checkEdge_.nLastParam - checkEdge_.nFirstParam); + if (!ANGLE_EQU(_nStdCentralAngle, _nCheckCentralAngle) && (_nStdCentralAngle < _nCheckCentralAngle)) + return false; + + // 方向 + Standard_Boolean _bSameDir = (standardEdge_.nLastParam - standardEdge_.nFirstParam) * (checkEdge_.nLastParam - checkEdge_.nFirstParam) > 0.; + + if (_bSameDir + && (standardEdge_.StartPoint().IsEqual(checkEdge_.StartPoint(), g_nDistPrecision) + || standardEdge_.EndPoint().IsEqual(checkEdge_.EndPoint(), g_nDistPrecision))) + return true; + + if (!_bSameDir + && (standardEdge_.StartPoint().IsEqual(checkEdge_.EndPoint(), g_nDistPrecision) + || standardEdge_.EndPoint().IsEqual(checkEdge_.StartPoint(), g_nDistPrecision))) + return true; + + return false; +} + +Standard_Boolean CCad2DTranslator::JudgeInclude2DWires(LISTEDGES2D& listEdgesSrc_, LISTEDGES2D& listEdgesDest_) const +{ + if (listEdgesSrc_.size() > listEdgesDest_.size()) + { + if (JudgeInclude2DWires(listEdgesDest_, listEdgesSrc_)) + { + listEdgesDest_ = listEdgesSrc_; + return true; + } + + return false; + } + + LISTEDGES2D::iterator _iterSrcBegin = listEdgesSrc_.begin(); + LISTEDGES2D::iterator _iterSrcEnd = listEdgesSrc_.end(); + for (; _iterSrcBegin != _iterSrcEnd; ++_iterSrcBegin) + { + LISTEDGES2D::iterator _iterDestBegin = listEdgesDest_.begin(); + LISTEDGES2D::iterator _iterDestEnd = listEdgesDest_.end(); + for (; _iterDestBegin != _iterDestEnd; ++_iterDestBegin) + { + if (JudgeInclude2DEdge(*_iterDestBegin, *_iterSrcBegin)) + break; + } + + if (_iterDestBegin == _iterDestEnd) + return false; + } + + return true; +} + +Standard_Boolean CCad2DTranslator::CheckWireExist(const Wire2DInfo& wire2D_, const LISTWIRES2D& listWires_) const +{ + ASSERT(!wire2D_.listEdges.empty()); + + LISTEDGES2D::const_iterator _iterBegin = wire2D_.listEdges.begin(); + LISTEDGES2D::const_iterator _iterEnd = wire2D_.listEdges.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + if (!CheckEdgeExist(*_iterBegin, listWires_)) + return false; + } + + return true; +} + +Standard_Boolean CCad2DTranslator::CheckEdgeExist(const Edge2DInfo& edge2D_, const LISTWIRES2D& listWires_) const +{ + LISTWIRES2D::const_iterator _iterWireBegin = listWires_.begin(); + LISTWIRES2D::const_iterator _iterWireEnd = listWires_.end(); + for (; _iterWireBegin != _iterWireEnd; ++_iterWireBegin) + { + LISTEDGES2D::const_iterator _iterEdgeBegin = _iterWireBegin->listEdges.begin(); + LISTEDGES2D::const_iterator _iterEdgeEnd = _iterWireBegin->listEdges.end(); + for (; _iterEdgeBegin != _iterEdgeEnd; ++_iterEdgeBegin) + { + if (JudgeSame2DEdge(edge2D_, *_iterEdgeBegin)) + return true; + } + } + + return false; +} + +Standard_Boolean CCad2DTranslator::JudgeSame2DEdge(const Edge2DInfo& leftEdge_, const Edge2DInfo& rightEdge_) const +{ + if ((leftEdge_.nEdgeType != rightEdge_.nEdgeType) || (EdgeInfo::EDGE_NONE == leftEdge_.nEdgeType)) + return false; + + // 两直线相等 + if (EdgeInfo::EDGE_LINE == leftEdge_.nEdgeType) + { + if (leftEdge_.ptStart.IsEqual(rightEdge_.ptStart, g_nDistPrecision) && leftEdge_.ptEnd.IsEqual(rightEdge_.ptEnd, g_nDistPrecision)) + return true; + else if (leftEdge_.ptStart.IsEqual(rightEdge_.ptEnd, g_nDistPrecision) && leftEdge_.ptEnd.IsEqual(rightEdge_.ptStart, g_nDistPrecision)) + return true; + + return false; + } + + // 两椭圆弧相等 + ASSERT(EdgeInfo::EDGE_OVAL == leftEdge_.nEdgeType); + if (!leftEdge_.ptCenter.IsEqual(rightEdge_.ptCenter, g_nDistPrecision)) + return false; + if (!DIST_EQU(leftEdge_.nLongRadius, rightEdge_.nLongRadius)) + return false; + if (!DIST_EQU(leftEdge_.nShortRadius, rightEdge_.nShortRadius)) + return false; + if (!ANGLE_EQU(fabs(leftEdge_.nLastParam - leftEdge_.nFirstParam), fabs(rightEdge_.nLastParam - rightEdge_.nFirstParam))) + return false; + if (!DIST_EQU(leftEdge_.nLongRadius, leftEdge_.nShortRadius) && !ANGLE_EQU(leftEdge_.nDipAngle, rightEdge_.nDipAngle) + && !ANGLE_EQU(fabs(leftEdge_.nDipAngle - rightEdge_.nDipAngle), g_nPIE)) + return false; + + gp_XY _ptLeftStart = leftEdge_.StartPoint(); + gp_XY _ptLeftEnd = leftEdge_.EndPoint(); + gp_XY _ptRightStart = rightEdge_.StartPoint(); + gp_XY _ptRightEnd = rightEdge_.EndPoint(); + if (_ptLeftStart.IsEqual(_ptRightStart, g_nDistPrecision) && _ptLeftEnd.IsEqual(_ptRightEnd, g_nDistPrecision) + && ANGLE_EQU(leftEdge_.nLastParam - leftEdge_.nFirstParam, rightEdge_.nLastParam - rightEdge_.nFirstParam)) + return true; + else if (_ptLeftStart.IsEqual(_ptRightEnd, g_nDistPrecision) && _ptLeftEnd.IsEqual(_ptRightStart, g_nDistPrecision) + && ANGLE_EQU(leftEdge_.nLastParam - leftEdge_.nFirstParam, rightEdge_.nFirstParam - rightEdge_.nLastParam)) + return true; + + return false; +} + +Standard_Boolean CCad2DTranslator::CheckIsOnlyLeftBoundary(const Wire2DInfo& wire2D_) const +{ + ASSERT(!m_listArrisBoundary.empty()); + ASSERT(m_listArrisBoundary.front().bRealArris && m_listArrisBoundary.back().bRealArris); + + Standard_Real _nStartX = wire2D_.listEdges.front().StartPoint().X(); + Standard_Real _nEndX = wire2D_.listEdges.back().EndPoint().X(); + if (!DIST_EQU(_nStartX, m_listArrisBoundary.front().nArrisXPos) && !DIST_EQU(_nEndX, m_listArrisBoundary.front().nArrisXPos)) + return false; + + Standard_Real _nNextBoundary = 0.; + const TubeInfo::TubeType& _nTubeType = m_pTubeToCadTranslator->m_TubeParam.nTubeType; + if ((TubeInfo::circular == _nTubeType) || (TubeInfo::oval == _nTubeType)) + _nNextBoundary = m_listArrisBoundary.back().nArrisXPos; + else + { + LISTARRISBOUNDARY::const_iterator _iterBegin = ++m_listArrisBoundary.begin(); + LISTARRISBOUNDARY::const_iterator _iterEnd = m_listArrisBoundary.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + if (_iterBegin->bRealArris) + { + _nNextBoundary = _iterBegin->nArrisXPos; + break; + } + } + + ASSERT(_iterBegin != _iterEnd); + } + + if (DIST_EQU(_nStartX, _nNextBoundary) || DIST_EQU(_nEndX, _nNextBoundary)) + return false; + if ((_nStartX > _nNextBoundary) || (_nEndX > _nNextBoundary)) + return false; + + return true; +} + +Standard_Boolean CCad2DTranslator::CheckIsOnlyRightBoundary(const Wire2DInfo& wire2D_) const +{ + ASSERT(!m_listArrisBoundary.empty()); + ASSERT(m_listArrisBoundary.front().bRealArris && m_listArrisBoundary.back().bRealArris); + + Standard_Real _nStartX = wire2D_.listEdges.front().StartPoint().X(); + Standard_Real _nEndX = wire2D_.listEdges.back().EndPoint().X(); + if (!DIST_EQU(_nStartX, m_listArrisBoundary.back().nArrisXPos) && !DIST_EQU(_nEndX, m_listArrisBoundary.back().nArrisXPos)) + return false; + + Standard_Real _nLastBoundary = 0.; + const TubeInfo::TubeType& _nTubeType = m_pTubeToCadTranslator->m_TubeParam.nTubeType; + if ((TubeInfo::circular == _nTubeType) || (TubeInfo::oval == _nTubeType)) + _nLastBoundary = m_listArrisBoundary.front().nArrisXPos; + else + { + LISTARRISBOUNDARY::const_reverse_iterator _iterRBegin = ++m_listArrisBoundary.rbegin(); + LISTARRISBOUNDARY::const_reverse_iterator _iterREnd = m_listArrisBoundary.rend(); + for (; _iterRBegin != _iterREnd; ++_iterRBegin) + { + if (_iterRBegin->bRealArris) + { + _nLastBoundary = _iterRBegin->nArrisXPos; + break; + } + } + + ASSERT(_iterRBegin != _iterREnd); + } + + if (DIST_EQU(_nStartX, _nLastBoundary) || DIST_EQU(_nEndX, _nLastBoundary)) + return false; + if ((_nStartX < _nLastBoundary) || (_nEndX < _nLastBoundary)) + return false; + + return true; +} + +Standard_Boolean CCad2DTranslator::CombineWireOnArris(const Wire2DInfo& wire2D_, Standard_Real nXOffset_, LISTWIRES2D& listWires_) +{ + // 将在棱上的线加上偏置后,如果可以和目标区域的线合并,则合并到目标区域 + gp_XY _ptStartPoint = wire2D_.listEdges.front().StartPoint() + gp_XY(nXOffset_, 0.); + gp_XY _ptEndPoint = wire2D_.listEdges.back().EndPoint() + gp_XY(nXOffset_, 0.); + + LISTWIRES2D::iterator _iterWireEnd = listWires_.end(); + LISTWIRES2D::iterator _iterWireCur = listWires_.begin(); + while (_iterWireCur != _iterWireEnd) + { + if (_iterWireCur->listEdges.front().StartPoint().IsEqual(_ptStartPoint, g_nDistPrecision)) + { + LISTEDGES2D::const_iterator _iterEdgeBegin = wire2D_.listEdges.begin(); + LISTEDGES2D::const_iterator _iterEdgeEnd = wire2D_.listEdges.end(); + for (; _iterEdgeBegin != _iterEdgeEnd; ++_iterEdgeBegin) + { + _iterWireCur->listEdges.push_front(*_iterEdgeBegin); + _iterWireCur->listEdges.front().Reverse(); + AddXOffsetForEdge(_iterWireCur->listEdges.front(), nXOffset_); + } + } + else if (_iterWireCur->listEdges.front().StartPoint().IsEqual(_ptEndPoint, g_nDistPrecision)) + { + LISTEDGES2D::const_reverse_iterator _iterEdgeRBegin = wire2D_.listEdges.rbegin(); + LISTEDGES2D::const_reverse_iterator _iterEdgeREnd = wire2D_.listEdges.rend(); + for (; _iterEdgeRBegin != _iterEdgeREnd; ++_iterEdgeRBegin) + { + _iterWireCur->listEdges.push_front(*_iterEdgeRBegin); + AddXOffsetForEdge(_iterWireCur->listEdges.front(), nXOffset_); + } + } + else if (_iterWireCur->listEdges.back().EndPoint().IsEqual(_ptStartPoint, g_nDistPrecision)) + { + LISTEDGES2D::const_iterator _iterEdgeBegin = wire2D_.listEdges.begin(); + LISTEDGES2D::const_iterator _iterEdgeEnd = wire2D_.listEdges.end(); + for (; _iterEdgeBegin != _iterEdgeEnd; ++_iterEdgeBegin) + { + _iterWireCur->listEdges.push_back(*_iterEdgeBegin); + AddXOffsetForEdge(_iterWireCur->listEdges.back(), nXOffset_); + } + } + else if (_iterWireCur->listEdges.back().EndPoint().IsEqual(_ptEndPoint, g_nDistPrecision)) + { + LISTEDGES2D::const_reverse_iterator _iterEdgeRBegin = wire2D_.listEdges.rbegin(); + LISTEDGES2D::const_reverse_iterator _iterEdgeREnd = wire2D_.listEdges.rend(); + for (; _iterEdgeRBegin != _iterEdgeREnd; ++_iterEdgeRBegin) + { + _iterWireCur->listEdges.push_back(*_iterEdgeRBegin); + _iterWireCur->listEdges.back().Reverse(); + AddXOffsetForEdge(_iterWireCur->listEdges.back(), nXOffset_); + } + } + else + { + ++_iterWireCur; + continue; + } + + break; + } + + if (_iterWireCur == _iterWireEnd) + return false; + + // 对已经在该区域被合并的线,寻找该区域中是否还存在可以合并的线 + _ptStartPoint = _iterWireCur->listEdges.front().StartPoint(); + _ptEndPoint = _iterWireCur->listEdges.back().EndPoint(); + LISTWIRES2D::iterator _iterWireTemp = listWires_.begin(); + while (_iterWireTemp != _iterWireEnd) + { + if (_iterWireTemp == _iterWireCur) + { + ++_iterWireTemp; + continue; + } + + if (_iterWireTemp->listEdges.front().StartPoint().IsEqual(_ptStartPoint, g_nDistPrecision)) + { + LISTEDGES2D::iterator _iterEdgeBegin = _iterWireTemp->listEdges.begin(); + LISTEDGES2D::iterator _iterEdgeEnd = _iterWireTemp->listEdges.end(); + for (; _iterEdgeBegin != _iterEdgeEnd; ++_iterEdgeBegin) + { + _iterWireCur->listEdges.push_front(*_iterEdgeBegin); + _iterWireCur->listEdges.front().Reverse(); + } + } + else if (_iterWireTemp->listEdges.front().StartPoint().IsEqual(_ptEndPoint, g_nDistPrecision)) + { + _iterWireCur->listEdges.splice(_iterWireCur->listEdges.end(), _iterWireTemp->listEdges); + } + else if (_iterWireTemp->listEdges.back().EndPoint().IsEqual(_ptStartPoint, g_nDistPrecision)) + { + _iterWireCur->listEdges.splice(_iterWireCur->listEdges.begin(), _iterWireTemp->listEdges); + } + else if (_iterWireTemp->listEdges.back().EndPoint().IsEqual(_ptEndPoint, g_nDistPrecision)) + { + LISTEDGES2D::reverse_iterator _iterEdgeRBegin = _iterWireTemp->listEdges.rbegin(); + LISTEDGES2D::reverse_iterator _iterEdgeREnd = _iterWireTemp->listEdges.rend(); + for (; _iterEdgeRBegin != _iterEdgeREnd; ++_iterEdgeRBegin) + { + _iterWireCur->listEdges.push_back(*_iterEdgeRBegin); + _iterWireCur->listEdges.back().Reverse(); + } + } + else + { + ++_iterWireTemp; + continue; + } + + listWires_.erase(_iterWireTemp); + break; + } + + return true; +} + +void CCad2DTranslator::AddXOffsetForEdge(Edge2DInfo& edge2D_, Standard_Real nXOffset_) +{ + if (EdgeInfo::EDGE_LINE == edge2D_.nEdgeType) + { + edge2D_.ptStart.SetX(edge2D_.ptStart.X() + nXOffset_); + edge2D_.ptEnd.SetX(edge2D_.ptEnd.X() + nXOffset_); + } + else + { + ASSERT(EdgeInfo::EDGE_OVAL == edge2D_.nEdgeType); + edge2D_.ptCenter.SetX(edge2D_.ptCenter.X() + nXOffset_); + } +} + +void CCad2DTranslator::Trans2DWireTo2DCad(LISTEDGES2D& listEdges_) +{ + ASSERT(m_pTubeToCadTranslator != NULL); + + ReplenishMissEdge(listEdges_); + MoveWireToExtendedPlane(listEdges_); + m_pTubeToCadTranslator->Trans2DWireTo2DCad(listEdges_); +} + +void CCad2DTranslator::ReplenishMissEdge(LISTEDGES2D& listEdges_) +{ + // 只对开口图形生效 + gp_XY _ptStartPoint = listEdges_.front().StartPoint(); + gp_XY _ptEndPoint = listEdges_.back().EndPoint(); + if (_ptStartPoint.IsEqual(_ptEndPoint, g_nDistPrecision)) + return; + + if ((listEdges_.size() == 1) && (EdgeInfo::EDGE_LINE == listEdges_.back().nEdgeType)) + return; + + // 构造使图形闭合的边 + Edge2DInfo _edge2D; + _edge2D.nEdgeType = EdgeInfo::EDGE_LINE; + _edge2D.ptStart = _ptEndPoint; + _edge2D.ptEnd = _ptStartPoint; + + // 判断起点和终点是否都在线段上 + LISTEDGES2D::const_iterator _iterBegin = m_listEdgesOnArris.begin(); + LISTEDGES2D::const_iterator _iterEnd = m_listEdgesOnArris.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + ASSERT(EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType); + + gp_XY _ptStartTemp = _iterBegin->StartPoint(); + gp_XY _ptEndTemp = _iterBegin->EndPoint(); + if (JudgePointOnSegment(_ptStartTemp, _ptEndTemp, _ptStartPoint) && JudgePointOnSegment(_ptStartTemp, _ptEndTemp, _ptEndPoint)) + { + listEdges_.push_back(_edge2D); + return; + } + + _ptStartTemp.SetX(_ptStartTemp.X() + m_nPerimeter); + _ptEndTemp.SetX(_ptEndTemp.X() + m_nPerimeter); + if (JudgePointOnSegment(_ptStartTemp, _ptEndTemp, _ptStartPoint) && JudgePointOnSegment(_ptStartTemp, _ptEndTemp, _ptEndPoint)) + { + listEdges_.push_back(_edge2D); + return; + } + } +} + +Standard_Boolean CCad2DTranslator::JudgePointOnSegment(const gp_XY& ptStart_, const gp_XY& ptEnd_, const gp_XY& ptPoint_) +{ + if (ptPoint_.IsEqual(ptStart_, g_nDistPrecision) || ptPoint_.IsEqual(ptEnd_, g_nDistPrecision)) + return true; + + gp_XY _ptStartVector = (ptPoint_ - ptStart_).Normalized(); + gp_XY _ptEndVector = (ptPoint_ - ptEnd_).Normalized(); + + return _ptStartVector.IsEqual(_ptEndVector.Reversed(), g_nDistPrecision); +} + +void CCad2DTranslator::MoveWireToExtendedPlane(LISTEDGES2D& listEdges_) +{ + // 只对椭圆/圆管生效 + const TubeInfo::TubeType& _nTubeType = m_pTubeToCadTranslator->m_TubeParam.nTubeType; + if ((_nTubeType != TubeInfo::circular) && (_nTubeType != TubeInfo::oval)) + return; + + Standard_Boolean _bOnBoundary = false; + LISTEDGES2D::iterator _iterBegin = listEdges_.begin(); + LISTEDGES2D::iterator _iterEnd = listEdges_.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + Standard_Real _nStartX = _iterBegin->StartPoint().X(); + if (!DIST_EQU(_nStartX, m_nPerimeter) && (_nStartX > m_nPerimeter)) + { + _bOnBoundary = true; + break; + } + + Standard_Real _nEndX = _iterBegin->EndPoint().X(); + if (!DIST_EQU(_nEndX, m_nPerimeter) && (_nEndX > m_nPerimeter)) + { + _bOnBoundary = true; + break; + } + } + + if (!_bOnBoundary) + return; + + for (_iterBegin = listEdges_.begin(); _iterBegin != _iterEnd; ++_iterBegin) + { + AddXOffsetForEdge(*_iterBegin, -1.0 * m_nPerimeter); + } +} + +////////////////////////////////////////////////////////////////////////// +// class CTubeToCadTranslator +CTubeToCadTranslator::CTubeToCadTranslator() + : m_plistCadObjects(NULL) + , m_pFirstCadObject(NULL) + , m_nMinYPos(DBL_MAX) + , m_nMaxYPos(-1.0 * DBL_MAX) +{ +} + +void CTubeToCadTranslator::SetAxleWireDir(const gp_XYZ& ptAxleWireDir_) +{ + m_ptAxleWireDir = ptAxleWireDir_; + ASSERT(DIST_EQU(m_ptAxleWireDir.Modulus(), 1.0)); + + m_listDiceyWires.clear(); + m_OuterBoundary = Wire3DInfo(); + m_TubeParam = TubeInfo(); + + m_Wires3DTranslator.Initialize(this); + m_Wires2DTranslator.Initialize(this); + m_Cad2DTranslator.Initialize(this); + + m_plistCadObjects = NULL; + m_pFirstCadObject = NULL; + + m_nMinYPos = DBL_MAX; + m_nMaxYPos = -1.0 * DBL_MAX; +} + +Standard_Boolean CTubeToCadTranslator::Translate(nce::CadObjectList* plistCadObjects_) +{ + ASSERT(plistCadObjects_ != NULL); + if (!plistCadObjects_) + return false; + + LISTWIRES3DONPLANE _listWires3DOnPlane; + if (!m_Wires3DTranslator.Translate(_listWires3DOnPlane)) + return false; + + LISTWIRES2DONSURFACE _listWires2DOnSurface; + if (!m_Wires2DTranslator.Translate(_listWires3DOnPlane, _listWires2DOnSurface)) + return false; + + m_plistCadObjects = plistCadObjects_; + if (!m_Cad2DTranslator.Translate(_listWires2DOnSurface) || (NULL == m_pFirstCadObject)) + return false; + + return true; +} + +void CTubeToCadTranslator::Trans2DWireTo2DCad(LISTEDGES2D& listEdges_) +{ + ASSERT(!listEdges_.empty()); + if (listEdges_.size() == 0) + return; + + // 转换前先进行合并 + Merge2DEdges(listEdges_); + + // 获取Y轴的边界 + GetYBoundary(listEdges_); + + if (listEdges_.size() == 1) + { + TransPreprocess2DWireTo2DCad(listEdges_); + return; + } + + // 如果多段线中包含椭圆弧,则将多段线进行分割,防止椭圆弧被当做圆弧进行转换 + LISTEDGES2D _listEdges; + LISTEDGES2D::const_iterator _iterBegin = listEdges_.begin(); + LISTEDGES2D::const_iterator _iterEnd = listEdges_.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + if ((_iterBegin->nEdgeType != EdgeInfo::EDGE_OVAL) || DIST_EQU(_iterBegin->nLongRadius, _iterBegin->nShortRadius)) + { + _listEdges.push_back(*_iterBegin); + continue; + } + + // 将椭圆弧前面的多段线进行转换 + TransPreprocess2DWireTo2DCad(_listEdges); + _listEdges.clear(); + + // 转换当前椭圆弧 + _listEdges.push_back(*_iterBegin); + TransPreprocess2DWireTo2DCad(_listEdges); + _listEdges.clear(); + } + + TransPreprocess2DWireTo2DCad(_listEdges); +} + +void CTubeToCadTranslator::TransPreprocess2DWireTo2DCad(LISTEDGES2D& listEdges_) +{ + if (listEdges_.empty()) + return; + + // 如果一条线绕方管转一圈,则将起点修正到平面上 + while (true) + { + if (m_TubeParam.nTubeType != TubeInfo::rectangular) + break; + + // 这里只修正与X轴平行的直线的情况 + if ((listEdges_.front().nEdgeType != EdgeInfo::EDGE_LINE) || (listEdges_.back().nEdgeType != EdgeInfo::EDGE_LINE)) + break; + + Edge2DInfo& _frontEdge = listEdges_.front(); + Edge2DInfo& _backEdge = listEdges_.back(); + if (!DIST_EQU(_frontEdge.ptStart.Y(), _frontEdge.ptEnd.Y()) + || !DIST_EQU(_backEdge.ptStart.Y(), _backEdge.ptEnd.Y()) + || !DIST_EQU(_frontEdge.ptStart.Y(), _backEdge.ptEnd.Y())) + break; + + const static Standard_Real _s_nMinThickness = 0.01; + Standard_Real _nXOffset = max(m_TubeParam.nRectRadius, max(m_TubeParam.nRectThickness, _s_nMinThickness)); + Standard_Real _nXMinBorder = -0.5 * m_TubeParam.nRectWidth; + Standard_Real _nXMaxBorder = _nXMinBorder + 2.0 * (m_TubeParam.nRectWidth + m_TubeParam.nRectHeight); + if ((!DIST_EQU(_frontEdge.ptStart.X(), _nXMinBorder) || !DIST_EQU(_backEdge.ptEnd.X(), _nXMaxBorder)) + && (!DIST_EQU(_frontEdge.ptStart.X(), _nXMaxBorder) || !DIST_EQU(_backEdge.ptEnd.X(), _nXMinBorder))) + break; + if (((_frontEdge.ptEnd - _frontEdge.ptStart).Modulus() < _nXOffset) || ((_backEdge.ptEnd - _backEdge.ptStart).Modulus() < _nXOffset)) + break; + + // 修正起始段起点和终止段终点 + _frontEdge.ptStart.SetX(_frontEdge.ptStart.X() + _nXOffset); + _backEdge.ptEnd.SetX(_backEdge.ptEnd.X() + _nXOffset); + + if (DIST_EQU((_frontEdge.ptEnd - _frontEdge.ptStart).Modulus(), 0.)) + listEdges_.pop_front(); + if (!listEdges_.empty() && DIST_EQU((_backEdge.ptEnd - _backEdge.ptStart).Modulus(), 0.)) + listEdges_.pop_back(); + + break; + } + + if (listEdges_.empty()) + return; + + // 多义线 + if (listEdges_.size() > 1) + { + if (CheckIsRectangle(listEdges_)) + Trans2DWireToRectangle(listEdges_); + else + Trans2DWireToPolyline(listEdges_); + + return; + } + + ASSERT(listEdges_.size() == 1); + const Edge2DInfo& _edge2D = listEdges_.back(); + if (EdgeInfo::EDGE_LINE == _edge2D.nEdgeType) + { + // 直线 + Trans2DWireToLine(_edge2D); + return; + } + + ASSERT(EdgeInfo::EDGE_OVAL == _edge2D.nEdgeType); + Standard_Boolean _bEqualRadius = DIST_EQU(_edge2D.nLongRadius, _edge2D.nShortRadius); + Standard_Boolean _bRound = ANGLE_EQU(fabs(_edge2D.nLastParam - _edge2D.nFirstParam), 2.0 * g_nPIE); + if (_bEqualRadius && _bRound) + { + // 整圆 + Trans2DWireToCircle(_edge2D); + } + else if (_bEqualRadius && !_bRound) + { + // 圆弧 + Trans2DWireToArc(_edge2D); + } + else if (!_bEqualRadius && _bRound) + { + // 整椭圆 + Trans2DWireToEllipse(_edge2D); + } + else + { + // 椭圆弧 + Trans2DWireToEllipseArc(_edge2D); + } +} + +void CTubeToCadTranslator::Trans2DWireToLine(const Edge2DInfo& edge2D_) +{ + ASSERT(EdgeInfo::EDGE_LINE == edge2D_.nEdgeType); + + nce::CCadLine* _pCadLine = nce::access::NewCadLine(); + _pCadLine->SetStartPoint(DPOINT2(edge2D_.ptStart.X(), edge2D_.ptStart.Y())); + _pCadLine->SetEndPoint(DPOINT2(edge2D_.ptEnd.X(), edge2D_.ptEnd.Y())); + + nce::access::CadObjectList_push_back(m_plistCadObjects, _pCadLine); + StoreFirstCadObject(_pCadLine); +} + +void CTubeToCadTranslator::Trans2DWireToArc(const Edge2DInfo& edge2D_) +{ + ASSERT(EdgeInfo::EDGE_OVAL == edge2D_.nEdgeType); + ASSERT(DIST_EQU(edge2D_.nLongRadius, edge2D_.nShortRadius)); + ASSERT(!ANGLE_EQU(fabs(edge2D_.nLastParam - edge2D_.nFirstParam), 2.0 * g_nPIE)); + + nce::CCadArc* _pCadArc = nce::access::NewCadArc(); + _pCadArc->SetCenterPoint(DPOINT2(edge2D_.ptCenter.X(), edge2D_.ptCenter.Y())); + _pCadArc->SetRadius(edge2D_.nLongRadius); + + Standard_Real _nStartAngle = NormalizeAngle(min(edge2D_.nFirstParam, edge2D_.nLastParam) + edge2D_.nDipAngle); + Standard_Real _nCentralAngle = fabs(edge2D_.nLastParam - edge2D_.nFirstParam); + _pCadArc->SetStartAngle(_nStartAngle); + _pCadArc->SetCentralAngle(_nCentralAngle); + + nce::access::CadObjectList_push_back(m_plistCadObjects, _pCadArc); + StoreFirstCadObject(_pCadArc); +} + +void CTubeToCadTranslator::Trans2DWireToCircle(const Edge2DInfo& edge2D_) +{ + ASSERT(EdgeInfo::EDGE_OVAL == edge2D_.nEdgeType); + ASSERT(DIST_EQU(edge2D_.nLongRadius, edge2D_.nShortRadius)); + ASSERT(ANGLE_EQU(fabs(edge2D_.nLastParam - edge2D_.nFirstParam), 2.0 * g_nPIE)); + + nce::CCadCircle* _pCadCircle = nce::access::NewCadCircle(); + _pCadCircle->SetCenterPoint(DPOINT2(edge2D_.ptCenter.X(), edge2D_.ptCenter.Y())); + _pCadCircle->SetRadius(edge2D_.nLongRadius); + + nce::access::CadObjectList_push_back(m_plistCadObjects, _pCadCircle); + StoreFirstCadObject(_pCadCircle); +} + +void CTubeToCadTranslator::Trans2DWireToEllipse(const Edge2DInfo& edge2D_) +{ + ASSERT(EdgeInfo::EDGE_OVAL == edge2D_.nEdgeType); + ASSERT(!DIST_EQU(edge2D_.nLongRadius, edge2D_.nShortRadius)); + ASSERT(ANGLE_EQU(fabs(edge2D_.nLastParam - edge2D_.nFirstParam), 2.0 * g_nPIE)); + + nce::CCadEllipse* _pCadEllipse = nce::access::NewCadEllipse(); + _pCadEllipse->SetCenterPoint(DPOINT2(edge2D_.ptCenter.X(), edge2D_.ptCenter.Y())); + _pCadEllipse->SetLongRadius(edge2D_.nLongRadius); + _pCadEllipse->SetShortRadius(edge2D_.nShortRadius); + _pCadEllipse->SetAngle(edge2D_.nDipAngle); + + nce::access::CadObjectList_push_back(m_plistCadObjects, _pCadEllipse); + StoreFirstCadObject(_pCadEllipse); +} + +void CTubeToCadTranslator::Trans2DWireToEllipseArc(const Edge2DInfo& edge2D_) +{ + ASSERT(EdgeInfo::EDGE_OVAL == edge2D_.nEdgeType); + ASSERT(!DIST_EQU(edge2D_.nLongRadius, edge2D_.nShortRadius)); + ASSERT(!ANGLE_EQU(fabs(edge2D_.nLastParam - edge2D_.nFirstParam), 2.0 * g_nPIE)); + + nce::CCadEllipseArc* _pCadEllipseArc = nce::access::NewCadEllipseArc(); + _pCadEllipseArc->SetCenterPoint(DPOINT2(edge2D_.ptCenter.X(), edge2D_.ptCenter.Y())); + _pCadEllipseArc->SetLongRadius(edge2D_.nLongRadius); + _pCadEllipseArc->SetShortRadius(edge2D_.nShortRadius); + _pCadEllipseArc->SetAngle(edge2D_.nDipAngle); + + Standard_Real _nStartAngle = NormalizeAngle(min(edge2D_.nFirstParam, edge2D_.nLastParam)); + Standard_Real _nCentralAngle = fabs(edge2D_.nLastParam - edge2D_.nFirstParam); + _pCadEllipseArc->SetStartAngle(_nStartAngle); + _pCadEllipseArc->SetCentralAngle(_nCentralAngle); + + nce::access::CadObjectList_push_back(m_plistCadObjects, _pCadEllipseArc); + StoreFirstCadObject(_pCadEllipseArc); +} + +void CTubeToCadTranslator::Trans2DWireToRectangle(const LISTEDGES2D& listEdges_) +{ + ASSERT(listEdges_.size() == 4); + ASSERT(listEdges_.front().StartPoint().IsEqual(listEdges_.back().EndPoint(), g_nDistPrecision)); + + LISTEDGES2D::const_iterator _iterBegin = listEdges_.begin(); + ASSERT(EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType); + DPOINT2 _ptPoint1(_iterBegin->ptStart.X(), _iterBegin->ptStart.Y()); + + ++_iterBegin; + ASSERT(EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType); + DPOINT2 _ptPoint2(_iterBegin->ptStart.X(), _iterBegin->ptStart.Y()); + + ++_iterBegin; + ASSERT(EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType); + DPOINT2 _ptPoint3(_iterBegin->ptStart.X(), _iterBegin->ptStart.Y()); + + ++_iterBegin; + ASSERT(EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType); + DPOINT2 _ptPoint4(_iterBegin->ptStart.X(), _iterBegin->ptStart.Y()); + ASSERT(++_iterBegin == listEdges_.end()); + + nce::CCadRectangle* _pCadRectangle = nce::access::NewCadRectangle(); + _pCadRectangle->SetVertexes(_ptPoint1, _ptPoint2, _ptPoint3, _ptPoint4); + + nce::access::CadObjectList_push_back(m_plistCadObjects, _pCadRectangle); + StoreFirstCadObject(_pCadRectangle); +} + +void CTubeToCadTranslator::Trans2DWireToPolyline(const LISTEDGES2D& listEdges_) +{ + ASSERT(listEdges_.size() > 1); + + nce::CCadPolyline* _pCadPolyline = nce::access::NewCadPolyline(); + gp_XY _ptStartPoint = listEdges_.front().StartPoint(); + _pCadPolyline->SetStartPoint(DPOINT2(_ptStartPoint.X(), _ptStartPoint.Y())); + + LISTEDGES2D::const_iterator _iterBegin = listEdges_.begin(); + LISTEDGES2D::const_iterator _iterEnd = listEdges_.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + ASSERT(DIST_EQU(_pCadPolyline->GetEndPoint().x, _iterBegin->StartPoint().X())); + ASSERT(DIST_EQU(_pCadPolyline->GetEndPoint().y, _iterBegin->StartPoint().Y())); + gp_XY _ptTempEnd = _iterBegin->EndPoint(); + if (EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType) + { + _pCadPolyline->AddLine(DPOINT2(_ptTempEnd.X(), _ptTempEnd.Y())); + } + else if (DIGIT_EQU(fabs(_iterBegin->nLastParam - _iterBegin->nFirstParam), 2.0 * g_nPIE)) + { + // 将整圆拆分成两个半圆 + ASSERT(EdgeInfo::EDGE_OVAL == _iterBegin->nEdgeType); + ASSERT(DIST_EQU(_iterBegin->nLongRadius, _iterBegin->nShortRadius)); + gp_XY _ptTempMiddle = 2.0 * _iterBegin->ptCenter - _ptTempEnd; + Standard_Real _nBulge = (_iterBegin->nLastParam > _iterBegin->nFirstParam) ? 1.0 : -1.0; + _pCadPolyline->AddArc(DPOINT2(_ptTempMiddle.X(), _ptTempMiddle.Y()), _nBulge); + _pCadPolyline->AddArc(DPOINT2(_ptTempEnd.X(), _ptTempEnd.Y()), _nBulge); + } + else + { + ASSERT(EdgeInfo::EDGE_OVAL == _iterBegin->nEdgeType); + ASSERT(DIST_EQU(_iterBegin->nLongRadius, _iterBegin->nShortRadius)); + Standard_Real _nBulge = tan(0.25 * (_iterBegin->nLastParam - _iterBegin->nFirstParam)); + _pCadPolyline->AddArc(DPOINT2(_ptTempEnd.X(), _ptTempEnd.Y()), _nBulge); + } + } + + gp_XY _ptEndPoint = listEdges_.back().EndPoint(); + if (_ptStartPoint.IsEqual(_ptEndPoint, g_nDistPrecision)) + _pCadPolyline->SetClosed(true); + + nce::access::CadObjectList_push_back(m_plistCadObjects, _pCadPolyline); + StoreFirstCadObject(_pCadPolyline); +} + +void CTubeToCadTranslator::StoreFirstCadObject(nce::CCadObject* pCadObject_) +{ + if (NULL == m_pFirstCadObject) + { + m_pFirstCadObject = pCadObject_; + ASSERT(m_pFirstCadObject != NULL); + } +} + +Standard_Boolean CTubeToCadTranslator::CheckIsRectangle(const LISTEDGES2D& listEdges_) const +{ + // 闭合图形 + if (!listEdges_.front().StartPoint().IsEqual(listEdges_.back().EndPoint(), g_nDistPrecision)) + return false; + + // 四条边(起点在顶点处) + if (listEdges_.size() != 4) + return false; + + LISTEDGES2D::const_iterator _iterBegin = listEdges_.begin(); + LISTEDGES2D::const_iterator _iterEnd = listEdges_.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + if (_iterBegin->nEdgeType != EdgeInfo::EDGE_LINE) + return false; + } + + _iterBegin = listEdges_.begin(); + _iterEnd = listEdges_.end(); + gp_XY _ptPoint1 = _iterBegin->ptStart; + gp_XY _ptPoint2 = (++_iterBegin)->ptStart; + gp_XY _ptPoint3 = (++_iterBegin)->ptStart; + gp_XY _ptPoint4 = (++_iterBegin)->ptStart; + ASSERT(++_iterBegin == _iterEnd); + + // 判断四个点是否组成矩形 + if (!(_ptPoint1 - _ptPoint2).IsEqual(_ptPoint4 - _ptPoint3, g_nDistPrecision)) + return false; + if (!(_ptPoint1 - _ptPoint4).IsEqual(_ptPoint2 - _ptPoint3, g_nDistPrecision)) + return false; + if (DIST_EQU((_ptPoint1 - _ptPoint2).Modulus(), 0.) || DIST_EQU((_ptPoint1 - _ptPoint4).Modulus(), 0.)) + return false; + if (!DIST_EQU((_ptPoint1 - _ptPoint3).Modulus(), (_ptPoint2 - _ptPoint4).Modulus())) + return false; + + return true; +} + +Standard_Real CTubeToCadTranslator::NormalizeAngle(Standard_Real nAngle_) const +{ + if (nAngle_ < 0.) + return (nAngle_ + 2.0 * g_nPIE); + + if (nAngle_ >= 2.0 * g_nPIE) + return (nAngle_ - 2.0 * g_nPIE); + + return nAngle_; +} + +void CTubeToCadTranslator::GetYBoundary(const LISTEDGES2D& listEdges_) +{ + LISTEDGES2D::const_iterator _iterBegin = listEdges_.begin(); + LISTEDGES2D::const_iterator _iterEnd = listEdges_.end(); + for (; _iterBegin != _iterEnd; ++_iterBegin) + { + // 直线 + if (EdgeInfo::EDGE_LINE == _iterBegin->nEdgeType) + { + GetYBoundary(_iterBegin->ptStart.Y()); + GetYBoundary(_iterBegin->ptEnd.Y()); + continue; + } + + // 椭圆:管材面上一般都是闭合图形,这里拿整椭圆计算 + gp_XY _ptPole; + ASSERT(EdgeInfo::EDGE_OVAL == _iterBegin->nEdgeType); + ASSERT(ANGLE_EQU(fabs(_iterBegin->nDipAngle), 2.0 * g_nPIE) || (fabs(_iterBegin->nDipAngle) < 2.0 * g_nPIE)); + if (ANGLE_EQU(fabs(_iterBegin->nDipAngle), 0.5 * g_nPIE) || ANGLE_EQU(fabs(_iterBegin->nDipAngle), 1.5 * g_nPIE)) + _ptPole.SetX(_iterBegin->nLongRadius); + else + { + // 旋转前外切矩形与椭圆的一个切点 + Standard_Real _nSlope = tan(-1.0 * _iterBegin->nDipAngle); + Standard_Real _nDenominator = sqrt(pow(_iterBegin->nLongRadius * _nSlope, 2) + pow(_iterBegin->nShortRadius, 2)); + _ptPole.SetX(pow(_iterBegin->nLongRadius, 2) * _nSlope / _nDenominator); + _ptPole.SetY(-1.0 * pow(_iterBegin->nShortRadius, 2) / _nDenominator); + } + + Standard_Real _nRotateY = _ptPole.X() * sin(_iterBegin->nDipAngle) + _ptPole.Y() * cos(_iterBegin->nDipAngle); + GetYBoundary(_iterBegin->ptCenter.Y() + _nRotateY); + GetYBoundary(_iterBegin->ptCenter.Y() - _nRotateY); + } +} + +void CTubeToCadTranslator::GetYBoundary(Standard_Real nAimYPos_) +{ + if (nAimYPos_ < m_nMinYPos) + m_nMinYPos = nAimYPos_; + if (nAimYPos_ > m_nMaxYPos) + m_nMaxYPos = nAimYPos_; +} \ No newline at end of file diff --git a/src/dibapi.cpp b/src/dibapi.cpp new file mode 100644 index 0000000..0f16856 --- /dev/null +++ b/src/dibapi.cpp @@ -0,0 +1,4039 @@ +//********************************************************************** +// +// AIBAPI.CPP +// +// Source file for Device-Independent Bitmap (DIB) API. +// +//********************************************************************** + +#define STRICT // enable strict type checking + +#include "stdafx.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////// +// Local use only function prototypes +//////////////////////////////////////////////////////////////////////////////////// +BOOL CopyColorTable(LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource, HPALETTE hPalSrc); +void DecreaseContrast(BYTE *pByte, const int Level, const float Grad); +void IncreaseContrast(BYTE *pByte, const int Low, const int High, const float Grad); +double Value(double n1, double n2, double hue); +HGLOBAL DitherImage(LPBYTE lpImageData, WORD Width, WORD Height); +//////////////////////////////////////////////////////////////////////////////////// + +/************************************************************************* + * + * CreateDIB() + * + * Parameters: + * + * DWORD dwWidth - Width for new bitmap, in pixels + * DWORD dwHeight - Height for new bitmap + * WORD wBitCount - Bit Count for new DIB (1, 4, 8, or 24) + * + * Return Value: + * + * HDIB - Handle to new DIB + * + * Description: + * + * This function allocates memory for and initializes a new DIB by + * filling in the BITMAPINFOHEADER, allocating memory for the color + * table, and allocating memory for the bitmap bits. As with all + * HDIBs, the header, colortable and bits are all in one contiguous + * memory block. This function is similar to the CreateBitmap() + * Windows API. + * + * The colortable and bitmap bits are left uninitialized (zeroed) in the + * returned HDIB. + * + * + ************************************************************************/ +HDIB CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount) +{ + BITMAPINFOHEADER bi; // bitmap header + LPBITMAPINFOHEADER lpbi; // pointer to BITMAPINFOHEADER + DWORD dwLen; // size of memory block + HDIB hDIB; + DWORD dwBytesPerLine; // Number of bytes per scanline + + + // Make sure bits per pixel is valid + + if (wBitCount <= 1) + wBitCount = 1; + else if (wBitCount <= 4) + wBitCount = 4; + else if (wBitCount <= 8) + wBitCount = 8; + else if (wBitCount <= 24) + wBitCount = 24; + else + wBitCount = 4; // set default value to 4 if parameter is bogus + + // initialize BITMAPINFOHEADER + + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = dwWidth; // fill in width from parameter + bi.biHeight = dwHeight; // fill in height from parameter + bi.biPlanes = 1; // must be 1 + bi.biBitCount = wBitCount; // from parameter + bi.biCompression = BI_RGB; + bi.biSizeImage = 0; // 0's here mean "default" + bi.biXPelsPerMeter = 0; + bi.biYPelsPerMeter = 0; + bi.biClrUsed = 0; + bi.biClrImportant = 0; + + // calculate size of memory block required to store the DIB. This + // block should be big enough to hold the BITMAPINFOHEADER, the color + // table, and the bits + + dwBytesPerLine = WIDTHBYTES(wBitCount * dwWidth); + dwLen = bi.biSize + PaletteSize((LPBYTE)&bi) + (dwBytesPerLine * dwHeight); + + // alloc memory block to store our bitmap + + hDIB = GlobalAlloc(GHND, dwLen); + + // major bummer if we couldn't get memory block + + if (!hDIB) + return NULL; + + // lock memory and get pointer to it + + lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); + + // use our bitmap info structure to fill in first part of + // our DIB with the BITMAPINFOHEADER + + *lpbi = bi; + + // Since we don't know what the colortable and bits should contain, + // just leave these blank. Unlock the DIB and return the HDIB. + + GlobalUnlock(hDIB); + + //return handle to the DIB + + return hDIB; +} + +/************************************************************************* + * + * CreateDefaultDIB() + * + * Parameters: + * + * DWORD dwWidth - Width for new bitmap, in pixels + * DWORD dwHeight - Height for new bitmap + * + * Return Value: + * + * HDIB - Handle to new DIB + * + * Description: + * + * This function allocates memory for and initializes a new DIB by + * filling in the BITMAPINFOHEADER, allocating memory for the color + * table, and allocating memory for the bitmap bits. As with all + * HDIBs, the header, colortable and bits are all in one contiguous + * memory block. This function is similar to the CreateBitmap() + * Windows API. + * + * The colortable is initialized with system palette, but bitmap bits + * are left uninitialized (zeroed) in the returned HDIB. + * + * + ************************************************************************/ +HDIB CreateDefaultDIB(DWORD dwWidth, DWORD dwHeight) +{ + // Get DC + HDC hDC = GetDC(NULL); + if (!hDC) + return NULL; + + // DC bts/pixel + int nDeviceBitsPixel = GetDeviceCaps(hDC, BITSPIXEL); + + // create DIB according to DC + HDIB hDIB = CreateDIB(dwWidth, dwHeight, nDeviceBitsPixel); + + // DIB buffer + LPBITMAPINFO lpbmi = (LPBITMAPINFO)GlobalLock(hDIB); + LPBYTE lpDIBBits = FindDIBBits((LPBYTE)lpbmi); + DWORD dwBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + + // set DIB color to White + for (DWORD l=0; l 8) + { + GlobalUnlock(hDIB); + ReleaseDC(NULL, hDC); + return hDIB; + } + + // if there is palette, set system palette to DIB + + // colors in system palette + int nColors = PalEntriesOnDevice(hDC); // Number of palette entries + + // Copy the current system palette into our logical palette + PALETTEENTRY pe[256]; + GetSystemPaletteEntries(hDC, 0, nColors, pe); + + // set color table + for (int i=0; ibmiColors[i].rgbRed = pe[i].peRed; + lpbmi->bmiColors[i].rgbGreen = pe[i].peGreen; + lpbmi->bmiColors[i].rgbBlue = pe[i].peBlue; + lpbmi->bmiColors[i].rgbReserved = 0; + } + + // clean up + GlobalUnlock(hDIB); + ReleaseDC(NULL, hDC); + + return hDIB; +} +/************************************************************************* + * + * DestroyDIB () + * + * Purpose: Frees memory associated with a DIB + * + * Returns: none + * + *************************************************************************/ +void DestroyDIB(HDIB hDib) +{ + GlobalFree(hDib); +} + +/************************************************************************* +* +* SaveDIB() +* +* Saves the specified DIB into the specified CFile. The CFile +* is opened and closed by the caller. +* +* Parameters: +* +* HDIB hDib - Handle to the dib to save +* +* CFile& file - open CFile used to save DIB +* +* Return value: TRUE if successful, else FALSE or CFileException +* +*************************************************************************/ +BOOL SaveDIB(HDIB hDib, CFile& file) +{ + BITMAPFILEHEADER bmfHdr; // Header for Bitmap file + LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure + UINT nDIBSize; + + if (hDib == NULL) + return FALSE; + + + /* + * Get a pointer to the DIB memory, the first of which contains + * a BITMAPINFO structure + */ + + lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); + if (lpBI == NULL) + return FALSE; + + if (!IS_WIN30_DIB(lpBI)) + { + ::GlobalUnlock((HGLOBAL) hDib); + return FALSE; // It's an other-style DIB (save not supported) + } + + + /* + * Fill in the fields of the file header + */ + + + + /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */ + + bmfHdr.bfType = DIB_HEADER_MARKER; // "BM" + + // Calculating the size of the DIB is a bit tricky (if we want to + // do it right). The easiest way to do this is to call GlobalSize() + // on our global handle, but since the size of our global memory may have + // been padded a few bytes, we may end up writing out a few too + // many bytes to the file (which may cause problems with some apps). + // + // So, instead let's calculate the size manually (if we can) + // + // First, find size of header plus size of color table. Since the + // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains + // the size of the structure, let's use this. + + nDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPBYTE)lpBI); // Partial Calculation + + // Now calculate the size of the image + + if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) + { + // It's an RLE bitmap, we can't calculate size, so trust the + // biSizeImage field + + nDIBSize += lpBI->biSizeImage; + } + else + { + DWORD dwBmBitsSize; // Size of Bitmap Bits only + + // It's not RLE, so size is Width (DWORD aligned) * Height + + dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; + + nDIBSize += dwBmBitsSize; + + // Now, since we have calculated the correct size, why don't we + // fill in the biSizeImage field (this will fix any .BMP files which + // have this field incorrect). + + lpBI->biSizeImage = dwBmBitsSize; + } + + + // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) + + bmfHdr.bfSize = nDIBSize + sizeof(BITMAPFILEHEADER); + bmfHdr.bfReserved1 = 0; + bmfHdr.bfReserved2 = 0; + + + /* + * Now, calculate the offset the actual bitmap bits will be in + * the file -- It's the Bitmap file header plus the DIB header, + * plus the size of the color table. + */ + + bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + + PaletteSize((LPBYTE)lpBI); + TRY + { + // Write the file header + file.Write((LPBYTE)&bmfHdr, sizeof(BITMAPFILEHEADER)); + // + // Write the DIB header and the bits + // + file.Write(lpBI, nDIBSize); + } + CATCH (CFileException, e) + { + ::GlobalUnlock((HGLOBAL) hDib); + THROW_LAST(); + } + END_CATCH + + ::GlobalUnlock((HGLOBAL) hDib); + return TRUE; +} + + +/************************************************************************* + +Function: ReadDIBFile (CFile&) + +Purpose: Reads in the specified DIB file into a global chunk of +memory. + +Returns: A handle to a dib (hDIB) if successful. +NULL if an error occurs. + +Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything +from the end of the BITMAPFILEHEADER structure on is +returned in the global memory handle. + +*************************************************************************/ +HDIB ReadDIBFile(CFile& file) +{ + BITMAPFILEHEADER bmfHeader; + UINT nBitsSize; + HDIB hDIB; + LPBYTE pDIB; + + /* + * get length of DIB in bytes for use when reading + */ + + + nBitsSize = (UINT)file.GetLength(); + + + /* + * Go read the DIB file header and check if it's valid. + */ + + if (file.Read((LPBYTE)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) + { + return NULL; + } + if (bmfHeader.bfType != DIB_HEADER_MARKER) + { + return NULL; + } + + /* + * Allocate memory for DIB + */ + + hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD)nBitsSize); + if (hDIB == 0) + { + return NULL; + } + pDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB); + + + /* + * Go read the bits. + */ + + if (file.Read(pDIB, nBitsSize - sizeof(BITMAPFILEHEADER)) != + nBitsSize - sizeof(BITMAPFILEHEADER) ) + { + ::GlobalUnlock((HGLOBAL) hDIB); + ::GlobalFree((HGLOBAL) hDIB); + return NULL; + } + ::GlobalUnlock((HGLOBAL) hDIB); + return hDIB; +} + + +/************************************************************************* + * + * FindDIBBits() + * + * Parameter: + * + * LPBYTE lpDIB - pointer to packed-DIB memory block + * + * Return Value: + * + * LPBYTE - pointer to the DIB bits + * + * Description: + * + * This function calculates the address of the DIB's bits and returns a + * pointer to the DIB bits. + * + ************************************************************************/ +LPBYTE FindDIBBits(LPBYTE lpDIB) +{ + return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB)); +} + +LPBYTE FindDIBBits (HDIB hDIB) +{ + LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); + LPBYTE lpDIBBits = FindDIBBits(lpDIB); + GlobalUnlock(hDIB); + return lpDIBBits; +} + +/************************************************************************* + * + * DIBWidth() + * + * Parameter: + * + * LPBYTE lpDIB - pointer to packed-DIB memory block + * + * Return Value: + * + * DWORD - width of the DIB + * + * Description: + * + * This function gets the width of the DIB from the BITMAPINFOHEADER + * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER + * width field if it is an OS/2-style DIB. + * + ************************************************************************/ +DWORD DIBWidth(LPBYTE lpDIB) +{ + LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB + LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB + + // point to the header (whether Win 3.0 and OS/2) + + lpbmi = (LPBITMAPINFOHEADER)lpDIB; + lpbmc = (LPBITMAPCOREHEADER)lpDIB; + + // return the DIB width if it is a Win 3.0 DIB + + if (lpbmi->biSize == sizeof(BITMAPINFOHEADER)) + return lpbmi->biWidth; + else // it is an OS/2 DIB, so return its width + return (DWORD)lpbmc->bcWidth; +} + +DWORD DIBWidth(HDIB hDIB) +{ + LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); + DWORD dw = DIBWidth(lpDIB); + GlobalUnlock(hDIB); + return dw; +} + +/************************************************************************* + * + * DIBHeight() + * + * Parameter: + * + * LPBYTE lpDIB - pointer to packed-DIB memory block + * + * Return Value: + * + * DWORD - height of the DIB + * + * Description: + * + * This function gets the height of the DIB from the BITMAPINFOHEADER + * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER + * height field if it is an OS/2-style DIB. + * + ************************************************************************/ +DWORD DIBHeight(LPBYTE lpDIB) +{ + LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB + LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB + + // point to the header (whether OS/2 or Win 3.0 + + lpbmi = (LPBITMAPINFOHEADER)lpDIB; + lpbmc = (LPBITMAPCOREHEADER)lpDIB; + + // return the DIB height if it is a Win 3.0 DIB + if (lpbmi->biSize == sizeof(BITMAPINFOHEADER)) + return lpbmi->biHeight; + else // it is an OS/2 DIB, so return its height + return (DWORD)lpbmc->bcHeight; +} + +DWORD DIBHeight(HDIB hDIB) +{ + LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); + DWORD dw = DIBHeight(lpDIB); + GlobalUnlock(hDIB); + return dw; +} + +/************************************************************************* + * + * PaletteSize() + * + * Parameter: + * + * LPBYTE lpDIB - pointer to packed-DIB memory block + * + * Return Value: + * + * WORD - size of the color palette of the DIB + * + * Description: + * + * This function gets the size required to store the DIB's palette by + * multiplying the number of colors by the size of an RGBQUAD (for a + * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an OS/2- + * style DIB). + * + ************************************************************************/ +WORD PaletteSize(LPBYTE lpDIB) +{ + // calculate the size required by the palette + if (IS_WIN30_DIB (lpDIB)) + return (DIBNumColors(lpDIB) * sizeof(RGBQUAD)); + else + return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE)); +} + +WORD PaletteSize(HDIB hDIB) +{ + LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); + WORD wSize = PaletteSize(lpDIB); + GlobalUnlock(hDIB); + return wSize; +} + +/************************************************************************* + * + * DIBNumColors() + * + * Parameter: + * + * LPBYTE lpDIB - pointer to packed-DIB memory block + * + * Return Value: + * + * WORD - number of colors in the color table + * + * Description: + * + * This function calculates the number of colors in the DIB's color table + * by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style + * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256, + * if 24, no colors in color table. + * + ************************************************************************/ +WORD DIBNumColors(LPBYTE lpDIB) +{ + WORD wBitCount; // DIB bit count + + // If this is a Windows-style DIB, the number of colors in the + // color table can be less than the number of bits per pixel + // allows for (i.e. lpbi->biClrUsed can be set to some value). + // If this is the case, return the appropriate value. + + + if (IS_WIN30_DIB(lpDIB)) + { + DWORD dwClrUsed; + + dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed; + if (dwClrUsed) + + return (WORD)dwClrUsed; + } + + // Calculate the number of colors in the color table based on + // the number of bits per pixel for the DIB. + + if (IS_WIN30_DIB(lpDIB)) + wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount; + else + wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount; + + // return number of colors based on bits per pixel + + switch (wBitCount) + { + case 1: + return 2; + + case 4: + return 16; + + case 8: + return 256; + + default: + return 0; + } +} + +WORD DIBNumColors(HDIB hDIB) +{ + LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); + WORD wSize = DIBNumColors(lpDIB); + GlobalUnlock(hDIB); + return wSize; +} + +WORD DIBBitCount(LPBYTE lpDIB) +{ + if (IS_WIN30_DIB(lpDIB)) + return ((LPBITMAPINFOHEADER)lpDIB)->biBitCount; + else + return ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount; +} + +WORD DIBBitCount(HDIB hDIB) +{ + LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); + WORD wSize = DIBBitCount(lpDIB); + GlobalUnlock(hDIB); + return wSize; +} + +/**************************************************************************** +* +* FUNCTION: BytesPerLine +* +* PURPOSE: Calculates the number of bytes in one scan line. +* +* PARAMS: LPBYTE lpDIB - pointer to the BITMAPINFOHEADER + that begins the CF_DIB block +* +* RETURNS: DWORD - number of bytes in one scan line (DWORD aligned) +* +\****************************************************************************/ +DWORD BytesPerLine(LPBYTE lpDIB) +{ + return WIDTHBYTES(((LPBITMAPINFOHEADER)lpDIB)->biWidth * ((LPBITMAPINFOHEADER)lpDIB)->biPlanes * ((LPBITMAPINFOHEADER)lpDIB)->biBitCount); +} + +DWORD BytesPerLine(HDIB hDIB) +{ + LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); + DWORD dw = BytesPerLine(lpDIB); + GlobalUnlock(hDIB); + return dw; +} + +/**************************************************************************** +* +* FUNCTION: DIBBlockSize +* +* PURPOSE: Calculates the number of bytes in one scan line. +* +* PARAMS: LPBYTE lpDIB - pointer to the BITMAPINFOHEADER + that begins the CF_DIB block +* +* RETURNS: DWORD - DIB block size +* +\****************************************************************************/ +DWORD DIBBlockSize(LPBYTE lpDIB) +{ + if (((LPBITMAPINFOHEADER)lpDIB)->biSizeImage == 0) + ((LPBITMAPINFOHEADER)lpDIB)->biSizeImage = BytesPerLine(lpDIB) * ((LPBITMAPINFOHEADER)lpDIB)->biHeight; + return ((LPBITMAPINFOHEADER)lpDIB)->biSize + PaletteSize(lpDIB) + ((LPBITMAPINFOHEADER)lpDIB)->biSizeImage; +} + +DWORD DIBBlockSize(HDIB hDIB) +{ + LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); + DWORD dw = DIBBlockSize(lpDIB); + GlobalUnlock(hDIB); + return dw; +} + +/************************************************************************* + * + * CreateDIBPalette() + * + * Parameter: + * + * LPBYTE lpbi - specifies the DIB + * + * Return Value: + * + * HPALETTE - specifies the palette + * + * Description: + * + * This function creates a palette from a DIB by allocating memory for the + * logical palette, reading and storing the colors from the DIB's color table + * into the logical palette, creating a palette from this logical palette, + * and then returning the palette's handle. This allows the DIB to be + * displayed using the best possible colors (important for DIBs with 256 or + * more colors). + * + ************************************************************************/ +HPALETTE CreateDIBPalette(LPBYTE lpbi) +{ + LPLOGPALETTE lpPal; // pointer to a logical palette + HANDLE hLogPal; // handle to a logical palette + HPALETTE hPal = NULL; // handle to a palette + int i, wNumColors; // loop index, number of colors in color table + LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0) + LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (OS/2) + BOOL bWinStyleDIB; // Win3.0 DIB? + + // if handle to DIB is invalid, return NULL + + if (! lpbi) + return NULL; + + // get pointer to BITMAPINFO (Win 3.0) + + lpbmi = (LPBITMAPINFO)lpbi; + + // get pointer to BITMAPCOREINFO (OS/2 1.x) + + lpbmc = (LPBITMAPCOREINFO)lpbi; + + // get the number of colors in the DIB + + wNumColors = DIBNumColors(lpbi); + + // is this a Win 3.0 DIB? + + bWinStyleDIB = IS_WIN30_DIB(lpbi); + if (wNumColors) + { + // allocate memory block for logical palette + + hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + + sizeof(PALETTEENTRY) * wNumColors); + + // if not enough memory, clean up and return NULL + + if (!hLogPal) + return NULL; + + // lock memory block and get pointer to it + + lpPal = (LPLOGPALETTE)GlobalLock(hLogPal); + + // set version and number of palette entries + + lpPal->palVersion = PALVERSION; + lpPal->palNumEntries = wNumColors; + + // store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB) + // into palette + + for (i = 0; i < wNumColors; i++) + { + if (bWinStyleDIB) + { + lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; + lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; + lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; + lpPal->palPalEntry[i].peFlags = 0; + } + else + { + lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; + lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; + lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue; + lpPal->palPalEntry[i].peFlags = 0; + } + } + + // create the palette and get handle to it + + hPal = CreatePalette(lpPal); + + // cleanup + + GlobalUnlock(hLogPal); + GlobalFree(hLogPal); + } + + // return handle to DIB's palette + return hPal; +} + +/************************************************************************* + * + * CreateDIBPalette() + * + * Parameter: + * + * HDIB hDIB - specifies the DIB + * + * Return Value: + * + * HPALETTE - specifies the palette + * + * Description: + * + * This function creates a palette from a DIB by allocating memory for the + * logical palette, reading and storing the colors from the DIB's color table + * into the logical palette, creating a palette from this logical palette, + * and then returning the palette's handle. This allows the DIB to be + * displayed using the best possible colors (important for DIBs with 256 or + * more colors). + * + ************************************************************************/ +HPALETTE CreateDIBPalette(HDIB hDIB) +{ + HPALETTE hPal = NULL; // handle to a palette + LPBYTE lpbi; // pointer to packed-DIB + + // if handle to DIB is invalid, return NULL + + if (!hDIB) + return NULL; + + // lock DIB memory block and get a pointer to it + + lpbi = (LPBYTE)GlobalLock(hDIB); + + hPal = CreateDIBPalette(lpbi); + + // Unlock hDIB + GlobalUnlock(hDIB); + + // return handle to DIB's palette + return hPal; +} + +/************************************************************************* + * + * DIBToBitmap() + * + * Parameters: + * + * HDIB hDIB - specifies the DIB to convert + * + * HPALETTE hPal - specifies the palette to use with the bitmap + * + * Return Value: + * + * HBITMAP - identifies the device-dependent bitmap + * + * Description: + * + * This function creates a bitmap from a DIB using the specified palette. + * If no palette is specified, default is used. + * + * NOTE: + * + * The bitmap returned from this funciton is always a bitmap compatible + * with the screen (e.g. same bits/pixel and color planes) rather than + * a bitmap with the same attributes as the DIB. This behavior is by + * design, and occurs because this function calls CreateDIBitmap to + * do its work, and CreateDIBitmap always creates a bitmap compatible + * with the hDC parameter passed in (because it in turn calls + * CreateCompatibleBitmap). + * + * So for instance, if your DIB is a monochrome DIB and you call this + * function, you will not get back a monochrome HBITMAP -- you will + * get an HBITMAP compatible with the screen DC, but with only 2 + * colors used in the bitmap. + * + * If your application requires a monochrome HBITMAP returned for a + * monochrome DIB, use the function SetDIBits(). + * + * Also, the DIBpassed in to the function is not destroyed on exit. This + * must be done later, once it is no longer needed. + * + ************************************************************************/ +HBITMAP DIBToBitmap(HDIB hDIB, HPALETTE hPal) +{ + LPBYTE lpDIBHdr, lpDIBBits; // pointer to DIB header, pointer to DIB bits + HBITMAP hBitmap; // handle to device-dependent bitmap + HDC hDC; // handle to DC + HPALETTE hOldPal = NULL; // handle to a palette + + // if invalid handle, return NULL + + if (!hDIB) + return NULL; + + // lock memory block and get a pointer to it + + lpDIBHdr = (LPBYTE)GlobalLock(hDIB); + + // get a pointer to the DIB bits + + lpDIBBits = FindDIBBits(lpDIBHdr); + + // get a DC + + hDC = GetDC(NULL); + if (!hDC) + { + // clean up and return NULL + GlobalUnlock(hDIB); + return NULL; + } + + // select and realize palette + + if (hPal) + { + hOldPal = SelectPalette(hDC, hPal, FALSE); + RealizePalette(hDC); + } + + // create bitmap from DIB info and bits + hBitmap = CreateDIBitmap(hDC, + (LPBITMAPINFOHEADER)lpDIBHdr, + CBM_INIT, + lpDIBBits, + (LPBITMAPINFO)lpDIBHdr, + DIB_RGB_COLORS); + + // restore previous palette + if (hOldPal) + SelectPalette(hDC, hOldPal, FALSE); + + // clean up + ReleaseDC(NULL, hDC); + GlobalUnlock(hDIB); + + // return handle to the bitmap + return hBitmap; +} + +/************************************************************************* + * + * ChangeBitmapFormat() + * + * Parameter: + * + * HBITMAP - handle to a bitmap + * + * WORD - desired bits per pixel + * + * DWORD - desired compression format + * + * HPALETTE - handle to palette + * + * Return Value: + * + * HDIB - handle to the new DIB if successful, else NULL + * + * Description: + * + * This function will convert a bitmap to the specified bits per pixel + * and compression format. The bitmap and it's palette will remain + * after calling this function. + * + ************************************************************************/ +HDIB ChangeBitmapFormat (HBITMAP hbm, WORD biBits, DWORD biCompression, HPALETTE hpal) +{ + BITMAP bm; + BITMAPINFOHEADER bi; + LPBITMAPINFOHEADER lpbi; + DWORD dwLen; + HANDLE hdib; + HANDLE h; + HDC hdc; + + if (!hbm) + return NULL; + + if (hpal == NULL) + hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE); + + GetObject(hbm,sizeof(bm),(LPBYTE)&bm); + + if (biBits == 0) + { + biBits = bm.bmPlanes * bm.bmBitsPixel; + + // make sure bits per pixel is valid + if (biBits <= 1) + biBits = 1; + else if (biBits <= 4) + biBits = 4; + else if (biBits <= 8) + biBits = 8; + else // if greater than 8-bit, force to 24-bit + biBits = 24; + } + + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = bm.bmWidth; + bi.biHeight = bm.bmHeight; + bi.biPlanes = 1; + bi.biBitCount = biBits; + bi.biCompression = biCompression; + bi.biSizeImage = 0; + bi.biXPelsPerMeter = 0; + bi.biYPelsPerMeter = 0; + bi.biClrUsed = 0; + bi.biClrImportant = 0; + + dwLen = bi.biSize + PaletteSize((LPBYTE)&bi); + + hdc = GetDC(NULL); + HPALETTE hpalT = SelectPalette(hdc,hpal,FALSE); + RealizePalette(hdc); + + hdib = GlobalAlloc(GHND,dwLen); + + if (!hdib) + { + SelectPalette(hdc,hpalT,FALSE); + ReleaseDC(NULL,hdc); + return NULL; + } + + lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib); + + *lpbi = bi; + + /* call GetDIBits with a NULL lpBits param, so it will calculate the + * biSizeImage field for us + */ + GetDIBits(hdc, hbm, 0L, (DWORD)bi.biHeight, + (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS); + + bi = *lpbi; + GlobalUnlock(hdib); + + /* If the driver did not fill in the biSizeImage field, make one up */ + if (bi.biSizeImage == 0) + { + bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight; + + if (biCompression != BI_RGB) + bi.biSizeImage = (bi.biSizeImage * 3) / 2; + } + + /* realloc the buffer big enough to hold all the bits */ + dwLen = bi.biSize + PaletteSize((LPBYTE)&bi) + bi.biSizeImage; + if ((h = GlobalReAlloc(hdib,dwLen,0)) != NULL) + hdib = h; + else + { + GlobalFree(hdib); + hdib = NULL; + + SelectPalette(hdc,hpalT,FALSE); + ReleaseDC(NULL,hdc); + return hdib; + } + + /* call GetDIBits with a NON-NULL lpBits param, and actualy get the + * bits this time + */ + lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib); + + if (! GetDIBits(hdc, + hbm, + 0L, + (DWORD)bi.biHeight, + (LPBYTE)lpbi + (WORD)lpbi->biSize + PaletteSize((LPBYTE)lpbi), + (LPBITMAPINFO)lpbi, + (DWORD)DIB_RGB_COLORS)) + { + GlobalUnlock(hdib); + hdib = NULL; + SelectPalette(hdc,hpalT,FALSE); + ReleaseDC(NULL,hdc); + return NULL; + } + bi = *lpbi; + + GlobalUnlock(hdib); + SelectPalette(hdc,hpalT,FALSE); + ReleaseDC(NULL,hdc); + return hdib; +} + + +/************************************************************************* + * + * ChangeDIBFormat() + * + * Parameter: + * + * HDIB - handle to packed-DIB in memory + * + * WORD - desired bits per pixel + * + * DWORD - desired compression format + * + * Return Value: + * + * HDIB - handle to the new DIB if successful, else NULL + * + * Description: + * + * This function will convert the bits per pixel and/or the compression + * format of the specified DIB. Note: If the conversion was unsuccessful, + * we return NULL. The original DIB is left alone. Don't use code like the + * following: + * + * hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4); + * + * The conversion will fail, but hMyDIB will now be NULL and the original + * DIB will now hang around in memory. We could have returned the old + * DIB, but we wanted to allow the programmer to check whether this + * conversion succeeded or failed. + * + ************************************************************************/ +HDIB ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression) +{ + HBITMAP hBitmap; // Handle to bitmap + HDIB hNewDIB = NULL; // Handle to new DIB + HPALETTE hPal; // Handle to palette + + // Check for a valid DIB handle + + if (!hDIB) + return NULL; + + // Save the old DIB's palette + + hPal = CreateDIBPalette(hDIB); + if (hPal == NULL) + hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE); + + // Convert old DIB to a bitmap + + hBitmap = DIBToBitmap(hDIB, hPal); + if (!hBitmap) + { + DeleteObject(hPal); + return NULL; + } + + // Change bitmap format + + hNewDIB = ChangeBitmapFormat(hBitmap, wBitCount, dwCompression, hPal); + + // Clean up and return + + DeleteObject(hBitmap); + DeleteObject(hPal); + + return hNewDIB; +} + + +/**************************************************************************** +* +* FUNCTION: ConvertDIBFormat +* +* PURPOSE: Creates a new DIB of the requested format, copies the source +* image to the new DIB. +* +* PARAMS: LPBITMAPINFO lpSrcDIB - the source CF_DIB +* UINT nWidth - width for new DIB +* UINT nHeight - height for new DIB +* UINT nbpp - bpp for new DIB +* BOOL bStretch - TRUE to stretch source to dest +* FALSE to take upper left of image +* HPALETTE hPalSrc - Palette used to set new DIB +* DWORD dwSize - return the size of new DIB pointer +* +* RETURNS: HDIB - Handle of CF_DIB memory block with new image +* NULL on failure +* +\****************************************************************************/ +HDIB ConvertDIBFormat(LPBYTE lpDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch, HPALETTE hPalSrc) +{ + LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)lpDIB; + LPBITMAPINFO lpbmi = NULL; + LPBYTE lpSourceBits, lpTargetBits, lpResult; + HDC hDC = NULL, hSourceDC, hTargetDC; + HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; + DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum; + HDIB hDib; + + // Allocate and fill out a BITMAPINFO struct for the new DIB + if (nbpp <= 8) + dwColorNum = 1 << nbpp; + else + dwColorNum = 0; + dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) ); + lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); + lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); + lpbmi->bmiHeader.biWidth = nWidth; + lpbmi->bmiHeader.biHeight = nHeight; + lpbmi->bmiHeader.biPlanes = 1; + lpbmi->bmiHeader.biBitCount = nbpp; + lpbmi->bmiHeader.biCompression = BI_RGB; + lpbmi->bmiHeader.biSizeImage = 0; + lpbmi->bmiHeader.biXPelsPerMeter = 0; + lpbmi->bmiHeader.biYPelsPerMeter = 0; + lpbmi->bmiHeader.biClrUsed = 0; + lpbmi->bmiHeader.biClrImportant = 0; + // Fill in the color table + if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) ) + { + free( lpbmi ); + return NULL; + } + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); + hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); + hSourceDC = CreateCompatibleDC( hDC ); + hTargetDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); + dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize ); + lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; + + // Select DIBSections into DCs + hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); + hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); + + // Set the color tables for the DIBSections + if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) + SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); + if( lpbmi->bmiHeader.biBitCount <= 8 ) + SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); + + // If we are asking for a straight copy, do it + if( (lpSrcDIB->bmiHeader.biWidth==lpbmi->bmiHeader.biWidth) && (lpSrcDIB->bmiHeader.biHeight==lpbmi->bmiHeader.biHeight) ) + { + BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); + } + else + { + // else, should we stretch it? + if( bStretch ) + { + SetStretchBltMode( hTargetDC, COLORONCOLOR ); + StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY ); + } + else + { + // or just take the upper left corner of the source + BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); + } + } + + // Clean up and delete the DCs + SelectObject( hSourceDC, hOldSourceBitmap ); + SelectObject( hTargetDC, hOldTargetBitmap ); + DeleteDC( hSourceDC ); + DeleteDC( hTargetDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + // Allocate enough memory for the new CF_DIB, and copy bits + hDib = GlobalAlloc(GHND, dwTargetHeaderSize + dwTargetBitsSize ); + lpResult = (LPBYTE)GlobalLock(hDib); + memcpy( lpResult, lpbmi, dwTargetHeaderSize ); + memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize ); + + // final cleanup + DeleteObject( hTargetBitmap ); + DeleteObject( hSourceBitmap ); + free( lpbmi ); + GlobalUnlock(hDib); + + return hDib; +} +/* End ConvertDIBFormat() 1***************************************************/ + +/**************************************************************************** +* +* FUNCTION: ConvertDIBFormat +* +* PURPOSE: Creates a new DIB of the requested format, copies the source +* image to the new DIB. +* +* PARAMS: HDIB hDIB - the source CF_DIB +* UINT nWidth - width for new DIB +* UINT nHeight - height for new DIB +* UINT nbpp - bpp for new DIB +* BOOL bStretch - TRUE to stretch source to dest +* FALSE to take upper left of image +* HPALETTE hPalSrc - Palette used to set new DIB +* +* RETURNS: HDIB - new CF_DIB handle +* +\****************************************************************************/ +HDIB ConvertDIBFormat(HDIB hDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch, HPALETTE hPalSrc) +{ + LPBITMAPINFO lpbmi = NULL; + LPBYTE lpSourceBits, lpTargetBits, lpResult; + HDC hDC = NULL, hSourceDC, hTargetDC; + HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; + DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum; + HDIB hNewDIB; + DWORD dwSize; + + // Get DIB pointer + if (! hDIB) + return NULL; + LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB); + if (! lpSrcDIB) + return NULL; + + // Allocate and fill out a BITMAPINFO struct for the new DIB + if (nbpp <= 8) + dwColorNum = 1 << nbpp; + else + dwColorNum = 0; + dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) ); + lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); + lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); + lpbmi->bmiHeader.biWidth = nWidth; + lpbmi->bmiHeader.biHeight = nHeight; + lpbmi->bmiHeader.biPlanes = 1; + lpbmi->bmiHeader.biBitCount = nbpp; + lpbmi->bmiHeader.biCompression = BI_RGB; + lpbmi->bmiHeader.biSizeImage = 0; + lpbmi->bmiHeader.biXPelsPerMeter = 0; + lpbmi->bmiHeader.biYPelsPerMeter = 0; + lpbmi->bmiHeader.biClrUsed = 0; + lpbmi->bmiHeader.biClrImportant = 0; + // Fill in the color table + if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) ) + { + free( lpbmi ); + return NULL; + } + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); + hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); + hSourceDC = CreateCompatibleDC( hDC ); + hTargetDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); + dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize ); + lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; + + // Select DIBSections into DCs + hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); + hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); + + // Set the color tables for the DIBSections + if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) + SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); + if( lpbmi->bmiHeader.biBitCount <= 8 ) + SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); + + // If we are asking for a straight copy, do it + if( (lpSrcDIB->bmiHeader.biWidth==lpbmi->bmiHeader.biWidth) && (lpSrcDIB->bmiHeader.biHeight==lpbmi->bmiHeader.biHeight) ) + { + BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); + } + else + { + // else, should we stretch it? + if( bStretch ) + { + SetStretchBltMode( hTargetDC, COLORONCOLOR ); + StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY ); + } + else + { + // or just take the upper left corner of the source + BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); + } + } + + // Clean up and delete the DCs + SelectObject( hSourceDC, hOldSourceBitmap ); + SelectObject( hTargetDC, hOldTargetBitmap ); + DeleteDC( hSourceDC ); + DeleteDC( hTargetDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + // Allocate enough memory for the new CF_DIB, and copy bits + dwSize = dwTargetHeaderSize + dwTargetBitsSize; + hNewDIB = GlobalAlloc(GHND, dwSize); + lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); + memcpy( lpResult, lpbmi, dwTargetHeaderSize ); + memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize ); + + // final cleanup + DeleteObject( hTargetBitmap ); + DeleteObject( hSourceBitmap ); + free( lpbmi ); + GlobalUnlock(hDIB); + GlobalUnlock(hNewDIB); + + return hNewDIB; +} +/* End ConvertDIBFormat() 2***************************************************/ + +/**************************************************************************** +* +* FUNCTION: ConvertDIBFormat +* +* PURPOSE: Creates a new DIB of the requested format, copies the source +* image to the new DIB. +* +* PARAMS: LPBYTE lpDIB - the source CF_DIB +* UINT nbpp - bpp for new DIB +* HPALETTE hPalSrc - Palette used to set new DIB +* +* RETURNS: HDIB - new CF_DIB handle +* +\****************************************************************************/ +HDIB ConvertDIBFormat(LPBYTE lpDIB, UINT nbpp, HPALETTE hPalSrc) +{ + LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)lpDIB; + LPBITMAPINFO lpbmi = NULL; + LPBYTE lpSourceBits, lpTargetBits, lpResult; + HDC hDC = NULL, hSourceDC, hTargetDC; + HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; + DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum; + HDIB hNewDIB; + DWORD dwSize; + int nWidth, nHeight; + + nWidth = lpSrcDIB->bmiHeader.biWidth; + nHeight = lpSrcDIB->bmiHeader.biHeight; + + // Allocate and fill out a BITMAPINFO struct for the new DIB + if (nbpp <= 8) + dwColorNum = 1 << nbpp; + else + dwColorNum = 0; + dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) ); + lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); + lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); + lpbmi->bmiHeader.biWidth = nWidth; + lpbmi->bmiHeader.biHeight = nHeight; + lpbmi->bmiHeader.biPlanes = 1; + lpbmi->bmiHeader.biBitCount = nbpp; + lpbmi->bmiHeader.biCompression = BI_RGB; + lpbmi->bmiHeader.biSizeImage = 0; + lpbmi->bmiHeader.biXPelsPerMeter = 0; + lpbmi->bmiHeader.biYPelsPerMeter = 0; + lpbmi->bmiHeader.biClrUsed = 0; + lpbmi->bmiHeader.biClrImportant = 0; + // Fill in the color table + if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) ) + { + free( lpbmi ); + return NULL; + } + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); + hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); + hSourceDC = CreateCompatibleDC( hDC ); + hTargetDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); + dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize ); + lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; + + // Select DIBSections into DCs + hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); + hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); + + // Set the color tables for the DIBSections + if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) + SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); + if( lpbmi->bmiHeader.biBitCount <= 8 ) + SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); + + // We are asking for a straight copy, do it + BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); + + // Clean up and delete the DCs + SelectObject( hSourceDC, hOldSourceBitmap ); + SelectObject( hTargetDC, hOldTargetBitmap ); + DeleteDC( hSourceDC ); + DeleteDC( hTargetDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + // Allocate enough memory for the new CF_DIB, and copy bits + dwSize = dwTargetHeaderSize + dwTargetBitsSize; + hNewDIB = GlobalAlloc(GHND, dwSize); + lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); + memcpy( lpResult, lpbmi, dwTargetHeaderSize ); + memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize ); + + // final cleanup + DeleteObject( hTargetBitmap ); + DeleteObject( hSourceBitmap ); + free( lpbmi ); + GlobalUnlock(hNewDIB); + + return hNewDIB; +} +/* End ConvertDIBFormat() 3***************************************************/ + +/**************************************************************************** +* +* FUNCTION: ConvertDIBFormat +* +* PURPOSE: Creates a new DIB of the requested format, copies the source +* image to the new DIB. +* +* PARAMS: HDIB hDIB - the source CF_DIB +* UINT nbpp - bpp for new DIB +* HPALETTE hPalSrc - Palette used to set new DIB +* +* RETURNS: HDIB - new CF_DIB handle +* +\****************************************************************************/ +HDIB ConvertDIBFormat(HDIB hDIB, UINT nbpp, HPALETTE hPalSrc) +{ + LPBITMAPINFO lpbmi = NULL; + LPBYTE lpSourceBits, lpTargetBits, lpResult; + HDC hDC = NULL, hSourceDC, hTargetDC; + HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; + DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize, dwColorNum; + HANDLE hNewDIB; + DWORD dwSize; + int nWidth, nHeight; + + // Get DIB pointer + if (! hDIB) + return NULL; + LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB); + if (! lpSrcDIB) + return NULL; + nWidth = lpSrcDIB->bmiHeader.biWidth; + nHeight = lpSrcDIB->bmiHeader.biHeight; + + // Allocate and fill out a BITMAPINFO struct for the new DIB + if (nbpp <= 8) + dwColorNum = 1 << nbpp; + else + dwColorNum = 0; + dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( dwColorNum * sizeof( RGBQUAD ) ); + lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); + lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); + lpbmi->bmiHeader.biWidth = nWidth; + lpbmi->bmiHeader.biHeight = nHeight; + lpbmi->bmiHeader.biPlanes = 1; + lpbmi->bmiHeader.biBitCount = nbpp; + lpbmi->bmiHeader.biCompression = BI_RGB; + lpbmi->bmiHeader.biSizeImage = 0; + lpbmi->bmiHeader.biXPelsPerMeter = 0; + lpbmi->bmiHeader.biYPelsPerMeter = 0; + lpbmi->bmiHeader.biClrUsed = 0; + lpbmi->bmiHeader.biClrImportant = 0; + // Fill in the color table + if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB, hPalSrc ) ) + { + free( lpbmi ); + return NULL; + } + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); + hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); + hSourceDC = CreateCompatibleDC( hDC ); + hTargetDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); + dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize ); + lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; + + // Select DIBSections into DCs + hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); + hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); + + // Set the color tables for the DIBSections + if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) + SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); + if( lpbmi->bmiHeader.biBitCount <= 8 ) + SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); + + // We are asking for a straight copy, do it + BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY ); + + // Clean up and delete the DCs + SelectObject( hSourceDC, hOldSourceBitmap ); + SelectObject( hTargetDC, hOldTargetBitmap ); + DeleteDC( hSourceDC ); + DeleteDC( hTargetDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + // Allocate enough memory for the new CF_DIB, and copy bits + dwSize = dwTargetHeaderSize + dwTargetBitsSize; + hNewDIB = GlobalAlloc(GHND, dwSize); + lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); + memcpy( lpResult, lpbmi, dwTargetHeaderSize ); + memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize ); + + // final cleanup + DeleteObject( hTargetBitmap ); + DeleteObject( hSourceBitmap ); + free( lpbmi ); + GlobalUnlock(hDIB); + GlobalUnlock(hNewDIB); + + return hNewDIB; +} +/* End ConvertDIBFormat() 4***************************************************/ + +/**************************************************************************** +* +* FUNCTION: CopyColorTable +* +* PURPOSE: Copies the color table from one CF_DIB to another. +* +* PARAMS: LPBITMAPINFO lpTarget - pointer to target DIB +* LPBITMAPINFO lpSource - pointer to source DIB +* +* RETURNS: BOOL - TRUE for success, FALSE for failure +* +\****************************************************************************/ +BOOL CopyColorTable( LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource, HPALETTE hPalSrc ) +{ + // What we do depends on the target's color depth + switch( lpTarget->bmiHeader.biBitCount ) + { + // 8bpp - need 256 entry color table + case 8: + if (hPalSrc) + { // Palette is provided, use it + PALETTEENTRY pe[256]; + UINT i; + + GetPaletteEntries( hPalSrc, 0, 256, pe ); + for(i=0;i<256;i++) + { + lpTarget->bmiColors[i].rgbRed = pe[i].peRed; + lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; + lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; + lpTarget->bmiColors[i].rgbReserved = 0; + } + } + else + { // no palette povided + if( lpSource->bmiHeader.biBitCount == 8 ) + { // Source is 8bpp too, copy color table + memcpy( lpTarget->bmiColors, lpSource->bmiColors, 256*sizeof(RGBQUAD) ); + } + else + { // Source is != 8bpp, use Octree algorithm to create palette + HPALETTE hPal; + HDC hDC = GetDC( NULL ); + PALETTEENTRY pe[256]; + UINT i; + + hPal = CreateOctreePalette((LPBYTE)lpSource, 236, 8); + if (! hPal) // use halftone palette + hPal = CreateHalftonePalette( hDC ); + ReleaseDC( NULL, hDC ); + + GetPaletteEntries( hPal, 0, 256, pe ); + DeleteObject( hPal ); + for(i=0;i<256;i++) + { + lpTarget->bmiColors[i].rgbRed = pe[i].peRed; + lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; + lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; + lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags; + } + } + } + break; // end 8bpp + + // 4bpp - need 16 entry color table + case 4: + if (hPalSrc) + { // Palette is provided, use it + PALETTEENTRY pe[16]; + UINT i; + + GetPaletteEntries( hPalSrc, 0, 16, pe ); + for(i=0;i<16;i++) + { + lpTarget->bmiColors[i].rgbRed = pe[i].peRed; + lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; + lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; + lpTarget->bmiColors[i].rgbReserved = 0; + } + } + else + { // No palette is provided + if( lpSource->bmiHeader.biBitCount == 4 ) + { // Source is 4bpp too, copy color table + memcpy( lpTarget->bmiColors, lpSource->bmiColors, 16*sizeof(RGBQUAD) ); + } + else + { // Source is != 4bpp, use system palette + HPALETTE hPal; + PALETTEENTRY pe[256]; + UINT i; + + hPal = (HPALETTE)GetStockObject( DEFAULT_PALETTE ); + GetPaletteEntries( hPal, 0, 16, pe ); + for(i=0;i<16;i++) + { + lpTarget->bmiColors[i].rgbRed = pe[i].peRed; + lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen; + lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue; + lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags; + } + } + } + break; // end 4bpp + + // 1bpp - need 2 entry mono color table + case 1: + lpTarget->bmiColors[0].rgbRed = 0; + lpTarget->bmiColors[0].rgbGreen = 0; + lpTarget->bmiColors[0].rgbBlue = 0; + lpTarget->bmiColors[0].rgbReserved = 0; + lpTarget->bmiColors[1].rgbRed = 255; + lpTarget->bmiColors[1].rgbGreen = 255; + lpTarget->bmiColors[1].rgbBlue = 255; + lpTarget->bmiColors[1].rgbReserved = 0; + break; // end 1bpp + + // no color table for the > 8bpp modes + case 32: + case 24: + case 16: + default: + break; + } + return TRUE; +} +/* End CopyColorTable() *****************************************************/ + +/**************************************************************************** +* +* FUNCTION: DIBToDIBSection +* +* PURPOSE: Create DIBSECTION from DIB +* +* PARAMS: LPBYTE lpDIB - pointer to DIB data buffer +* +* RETURNS: HBITMAP - handle of DIBSECTION, or NULL for failure +* +\****************************************************************************/ +HBITMAP DIBToDIBSection(LPBYTE lpDIB) +{ + LPBYTE lpSourceBits; + HDC hDC = NULL, hSourceDC; + HBITMAP hSourceBitmap, hOldSourceBitmap; + DWORD dwSourceBitsSize; + + LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)lpDIB; + if (! lpSrcDIB) + return NULL; + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); + hSourceDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); + memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize ); + + // Select DIBSections into DCs + hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); + + // Set the color tables for the DIBSections + if( lpSrcDIB->bmiHeader.biBitCount <= 8 ) + SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors ); + + // Clean up and delete the DCs + SelectObject( hSourceDC, hOldSourceBitmap ); + DeleteDC( hSourceDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + return hSourceBitmap; +} + +// Create DIBSECTION from DIB +HBITMAP DIBToDIBSection(HDIB hDIB) +{ + HBITMAP hSourceBitmap; + + // Get DIB pointer + if (! hDIB) + return NULL; + LPBYTE lpSrcDIB = (LPBYTE)GlobalLock(hDIB); + if (! lpSrcDIB) + return NULL; + + hSourceBitmap = DIBToDIBSection(lpSrcDIB); + + // final cleanup + GlobalUnlock(hDIB); + + return hSourceBitmap; +} + +/**************************************************************************** +* +* FUNCTION: DIBSectionToDIB +* +* PURPOSE: Create DIB from DIBSECTION +* +* PARAMS: HBITMAP - handle of DIBSECTION, or NULL for failure +* +* RETURNS: HBITMAP hBitmap - DIB handle +* +\****************************************************************************/ +HDIB DIBSectionToDIB(HBITMAP hBitmap) +{ + HDC hDC = NULL, hSourceDC; + HBITMAP hOldSourceBitmap; + HANDLE hNewDIB; + LPBITMAPINFO lpbmi = NULL; + DWORD dwSize; + DIBSECTION ds; + DWORD dwColorNum; + + // get DIB info + GetObject(hBitmap, sizeof(DIBSECTION), &ds); + dwColorNum = ds.dsBmih.biClrUsed; + if (dwColorNum == 0 && ds.dsBmih.biBitCount <= 8) + dwColorNum = 1 << ds.dsBmih.biBitCount; + + // Allocate and fill out a BITMAPINFO struct for the new DIB + dwSize = sizeof(BITMAPINFOHEADER) + (dwColorNum * sizeof(RGBQUAD)) + ds.dsBmih.biSizeImage; + hNewDIB = GlobalAlloc(GHND, dwSize); + if (! hNewDIB) + return NULL; + lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB); + if (! lpbmi) + return NULL; + lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); + lpbmi->bmiHeader.biWidth = ds.dsBm.bmWidth; + lpbmi->bmiHeader.biHeight = ds.dsBm.bmHeight; + lpbmi->bmiHeader.biPlanes = 1; + lpbmi->bmiHeader.biBitCount = ds.dsBmih.biBitCount; + lpbmi->bmiHeader.biCompression = ds.dsBmih.biCompression; + lpbmi->bmiHeader.biSizeImage = ds.dsBmih.biSizeImage; + lpbmi->bmiHeader.biXPelsPerMeter = ds.dsBmih.biXPelsPerMeter; + lpbmi->bmiHeader.biYPelsPerMeter = ds.dsBmih.biYPelsPerMeter; + lpbmi->bmiHeader.biClrUsed = ds.dsBmih.biClrUsed; + lpbmi->bmiHeader.biClrImportant = ds.dsBmih.biClrImportant; + + // get DC for operation + hDC = GetDC( NULL ); + + // get DIB bits + if (! GetDIBits(hDC, + hBitmap, + 0L, + (DWORD)ds.dsBm.bmHeight, + (LPBYTE)lpbmi + (WORD)lpbmi->bmiHeader.biSize + (dwColorNum*sizeof(RGBQUAD)), + (LPBITMAPINFO)lpbmi, + (DWORD)DIB_RGB_COLORS)) + { + GlobalUnlock(hNewDIB); + ReleaseDC(NULL,hDC); + return NULL; + } + + // memory DC + hSourceDC = CreateCompatibleDC( hDC ); + // Select DIBSections into DCs + hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hBitmap ); + + // Fill in the color table from DIBSection + if( lpbmi->bmiHeader.biBitCount <= 8 ) + GetDIBColorTable( hSourceDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); + + // Clean up and delete the DCs + SelectObject( hSourceDC, hOldSourceBitmap ); + DeleteDC( hSourceDC ); + ReleaseDC( NULL, hDC ); + GlobalUnlock(hNewDIB); + + return hNewDIB; +} + + +/************************************************************************* + * + * CopyScreenToBitmap() + * + * Parameter: + * + * LPRECT lpRect - specifies the window + * + * Return Value: + * + * HDIB - identifies the device-dependent bitmap + * + * Description: + * + * This function copies the specified part of the screen to a device- + * dependent bitmap. + * + * + ************************************************************************/ +HBITMAP CopyScreenToBitmap(LPRECT lpRect) +{ + HDC hScrDC, hMemDC; // screen DC and memory DC + HBITMAP hBitmap, hOldBitmap; // handles to deice-dependent bitmaps + int nX, nY, nX2, nY2; // coordinates of rectangle to grab + int nWidth, nHeight; // DIB width and height + int xScrn, yScrn; // screen resolution + + // check for an empty rectangle + + if (IsRectEmpty(lpRect)) + return NULL; + + // create a DC for the screen and create + // a memory DC compatible to screen DC + + hScrDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL); + hMemDC = CreateCompatibleDC(hScrDC); + + // get points of rectangle to grab + + nX = lpRect->left; + nY = lpRect->top; + nX2 = lpRect->right; + nY2 = lpRect->bottom; + + // get screen resolution + + xScrn = GetDeviceCaps(hScrDC, HORZRES); + yScrn = GetDeviceCaps(hScrDC, VERTRES); + + //make sure bitmap rectangle is visible + + if (nX < 0) + nX = 0; + if (nY < 0) + nY = 0; + if (nX2 > xScrn) + nX2 = xScrn; + if (nY2 > yScrn) + nY2 = yScrn; + + nWidth = nX2 - nX; + nHeight = nY2 - nY; + + // create a bitmap compatible with the screen DC + hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); + + // select new bitmap into memory DC + hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); + + // bitblt screen DC to memory DC + BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); + + // select old bitmap back into memory DC and get handle to + // bitmap of the screen + + hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap); + + // clean up + + DeleteDC(hScrDC); + DeleteDC(hMemDC); + + // return handle to the bitmap + + return hBitmap; +} + +/************************************************************************* + * + * CopyWindowToBitmap() + * + * Parameters: + * + * HWND hWnd - specifies the window + * + * WORD fPrintArea - specifies the window area to copy into the device- + * dependent bitmap + * + * Return Value: + * + * HDIB - identifies the device-dependent bitmap + * + * Description: + * + * This function copies the specified part(s) of the window to a device- + * dependent bitmap. + * + * + ************************************************************************/ +HBITMAP CopyWindowToBitmap(HWND hWnd, WORD fPrintArea) +{ + HBITMAP hBitmap = NULL; // handle to device-dependent bitmap + + // check for a valid window handle + + if (!hWnd) + return NULL; + + switch (fPrintArea) + { + case PW_WINDOW: // copy entire window + { + RECT rectWnd; + + // get the window rectangle + + GetWindowRect(hWnd, &rectWnd); + + // get the bitmap of that window by calling + // CopyScreenToBitmap and passing it the window rect + + hBitmap = CopyScreenToBitmap(&rectWnd); + break; + } + + + case PW_CLIENT: // copy client area + { + RECT rectClient; + POINT pt1, pt2; + + // get client dimensions + + GetClientRect(hWnd, &rectClient); + + // convert client coords to screen coords + + pt1.x = rectClient.left; + pt1.y = rectClient.top; + pt2.x = rectClient.right; + pt2.y = rectClient.bottom; + ClientToScreen(hWnd, &pt1); + ClientToScreen(hWnd, &pt2); + rectClient.left = pt1.x; + rectClient.top = pt1.y; + rectClient.right = pt2.x; + rectClient.bottom = pt2.y; + + // get the bitmap of the client area by calling + // CopyScreenToBitmap and passing it the client rect + + hBitmap = CopyScreenToBitmap(&rectClient); + break; + } + + default: // invalid print area + return NULL; + } + + // return handle to the bitmap + + return hBitmap; +} + + +/************************************************************************* + * + * CopyClientRectToBitmap() + * + * Parameters: + * + * HWND hWnd - specifies the window + * + * LPRECT lpRect - specifies the client area rect to copy into the device- + * independent bitmap + * + * Return Value: + * + * HDIB - identifies the device-independent bitmap + * + * Description: + * + * This function copies the specified part(s) of the window client to a + * device-independent bitmap. + * + ************************************************************************/ +HBITMAP CopyClientRectToBitmap(HWND hWnd, LPRECT lpRect) +{ + HBITMAP hBitmap = NULL; // handle to DIB + + // check for a valid window handle + + if (!hWnd) + return NULL; + + POINT pt1, pt2; + + // convert client coords to screen coords + + pt1.x = lpRect->left; + pt1.y = lpRect->top; + pt2.x = lpRect->right; + pt2.y = lpRect->bottom; + ClientToScreen(hWnd, &pt1); + ClientToScreen(hWnd, &pt2); + lpRect->left = pt1.x; + lpRect->top = pt1.y; + lpRect->right = pt2.x; + lpRect->bottom = pt2.y; + + // get the DIB of the client area by calling + // CopyScreenToDIB and passing it the client rect + + hBitmap = CopyScreenToBitmap(lpRect); + + // restore lpRect + + pt1.x = lpRect->left; + pt1.y = lpRect->top; + pt2.x = lpRect->right; + pt2.y = lpRect->bottom; + ScreenToClient(hWnd, &pt1); + ScreenToClient(hWnd, &pt2); + lpRect->left = pt1.x; + lpRect->top = pt1.y; + lpRect->right = pt2.x; + lpRect->bottom = pt2.y; + + // return the handle to the DIB + + return hBitmap; +} + +/************************************************************************* +* +* PaintDIB() +* +* Parameters: +* +* HDC hDC - DC to do output to +* +* LPRECT lpDCRect - rectangle on DC to do output to +* +* HDIB hDIB - handle to global memory with a DIB spec +* in it followed by the DIB bits +* +* LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect +* +* CPalette* pPal - pointer to CPalette containing DIB's palette +* +* Return Value: +* +* BOOL - TRUE if DIB was drawn, FALSE otherwise +* +* Description: +* Painting routine for a DIB. Calls StretchDIBits() or +* SetDIBitsToDevice() to paint the DIB. The DIB is +* output to the specified DC, at the coordinates given +* in lpDCRect. The area of the DIB to be output is +* given by lpDIBRect. +* +************************************************************************/ + + +BOOL PaintDIB(HDC hDC, + LPRECT lpDCRect, + HDIB hDIB, + LPRECT lpDIBRect, + CPalette* pPal, + BOOL bStretch) +{ + LPBYTE lpDIBHdr; // Pointer to BITMAPINFOHEADER + LPBYTE lpDIBBits; // Pointer to DIB bits + BOOL bSuccess=FALSE; // Success/fail flag + HPALETTE hPal=NULL; // Our DIB's palette + HPALETTE hOldPal=NULL; // Previous palette + + + /* Check for valid DIB handle */ + + if (hDIB == NULL) + return FALSE; + + + /* Lock down the DIB, and get a pointer to the beginning of the bit + * buffer + */ + + lpDIBHdr = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB); + lpDIBBits = ::FindDIBBits(lpDIBHdr); + + // Get the DIB's palette, then select it into DC + if (pPal != NULL) + { + hPal = (HPALETTE) pPal->m_hObject; + + // Select as background since we have + // already realized in forground if needed + hOldPal = ::SelectPalette(hDC, hPal, TRUE); + } + + + /* Make sure to use the stretching mode best for color pictures */ + + ::SetStretchBltMode(hDC, COLORONCOLOR); + + + /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */ + + bool _bSameDim = (RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) && (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)); + if (bStretch && !_bSameDim) + { + bSuccess = ::StretchDIBits(hDC, // hDC + lpDCRect->left, // DestX + lpDCRect->top, // DestY + RECTWIDTH(lpDCRect), // nDestWidth + RECTHEIGHT(lpDCRect), // nDestHeight + lpDIBRect->left, // SrcX + lpDIBRect->top, // SrcY + RECTWIDTH(lpDIBRect), // wSrcWidth + RECTHEIGHT(lpDIBRect), // wSrcHeight + lpDIBBits, // lpBits + (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo + DIB_RGB_COLORS, // wUsage + SRCCOPY); // dwROP + } + else + { + bSuccess = ::SetDIBitsToDevice(hDC, // hDC + lpDCRect->left, // DestX + lpDCRect->top, // DestY + RECTWIDTH(lpDCRect), // nDestWidth + RECTHEIGHT(lpDCRect), // nDestHeight + lpDIBRect->left, // SrcX + (int)DIBHeight(lpDIBHdr) - lpDIBRect->top - RECTHEIGHT(lpDIBRect), // SrcY + 0, // nStartScan + (WORD)DIBHeight(lpDIBHdr), // nNumScans + lpDIBBits, // lpBits + (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo + DIB_RGB_COLORS); // wUsage + } + + ::GlobalUnlock((HGLOBAL) hDIB); + + + /* Reselect old palette */ + + if (hOldPal != NULL) + { + ::SelectPalette(hDC, hOldPal, TRUE); + } + + return bSuccess; +} + +/************************************************************************* + * + * PaintBitmap() + * + * Parameters: + * + * HDC hDC - DC to do output to + * + * LPRECT lpDCRect - rectangle on DC to do output to + * + * HBITMAP hDDB - handle to device-dependent bitmap (DDB) + * + * LPRECT lpDDBRect - rectangle of DDB to output into lpDCRect + * + * HPALETTE hPalette - handle to the palette to use with hDDB + * + * Return Value: + * + * BOOL - TRUE if bitmap was drawn, FLASE otherwise + * + * Description: + * + * Painting routine for a DDB. Calls BitBlt() or + * StretchBlt() to paint the DDB. The DDB is + * output to the specified DC, at the coordinates given + * in lpDCRect. The area of the DDB to be output is + * given by lpDDBRect. The specified palette is used. + * + * NOTE: This function always selects the palette as background. Before + * calling this function, be sure your palette is selected to desired + * priority (foreground or background). + * + ************************************************************************/ +BOOL PaintBitmap(HDC hDC, LPRECT lpDCRect, HBITMAP hDDB, LPRECT lpDDBRect, + HPALETTE hPal, DWORD dwRop) +{ + HDC hMemDC; // Handle to memory DC + HBITMAP hOldBitmap; // Handle to previous bitmap + HPALETTE hOldPal1 = NULL; // Handle to previous palette + HPALETTE hOldPal2 = NULL; // Handle to previous palette + BOOL bSuccess = FALSE; // Success/fail flag + + // Create a memory DC + + hMemDC = CreateCompatibleDC (hDC); + + // If this failed, return FALSE + + if (!hMemDC) + return FALSE; + + // If we have a palette, select and realize it + + if (hPal) + { + hOldPal1 = SelectPalette(hMemDC, hPal, TRUE); + hOldPal2 = SelectPalette(hDC, hPal, TRUE); + RealizePalette(hDC); + } + + // Select bitmap into the memory DC + + hOldBitmap = (HBITMAP)SelectObject (hMemDC, hDDB); + + // Make sure to use the stretching mode best for color pictures + + SetStretchBltMode (hDC, COLORONCOLOR); + + // Determine whether to call StretchBlt() or BitBlt() + if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDDBRect)) && + (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDDBRect))) + bSuccess = BitBlt(hDC, lpDCRect->left, lpDCRect->top, + lpDCRect->right - lpDCRect->left, + lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left, + lpDDBRect->top, dwRop); + else + bSuccess = StretchBlt(hDC, lpDCRect->left, lpDCRect->top, + lpDCRect->right - lpDCRect->left, + lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left, + lpDDBRect->top, lpDDBRect->right - lpDDBRect->left, + lpDDBRect->bottom - lpDDBRect->top, dwRop); + + // Clean up + + SelectObject(hMemDC, hOldBitmap); + + if (hOldPal1) + SelectPalette (hMemDC, hOldPal1, FALSE); + + if (hOldPal2) + SelectPalette (hDC, hOldPal2, FALSE); + + DeleteDC (hMemDC); + + // Return with success/fail flag + + return bSuccess; +} + +/************************************************************************* + * + * DisplayPalette () + * + * Parameter: + * + * HDC hDC - handle of device context to display palette + * LPRECT lpRect - rect range to show palette + * HPALETTE hPal - handle of palette to display + * + * Return Value: + * + * BOOL - TRUE, if success, else FALSE + * + * Description: + * + * This function displays palette on the specified rectangle in a device context + * + ************************************************************************/ +BOOL DisplayPalette(HDC hDC, LPRECT lpRect, HPALETTE hPal) +{ + if (! hPal) + return FALSE; + + int nEntries; + PALETTEENTRY pe[256]; + nEntries = GetPaletteEntries(hPal, 0, 256, pe); + int nSqr = (int)sqrt((double)nEntries); + + int nWidth = (lpRect->right-lpRect->left)/nSqr; + int nHeight = (lpRect->bottom-lpRect->top)/nSqr; + lpRect->right = lpRect->left + nWidth*nSqr; + lpRect->bottom = lpRect->top + nHeight*nSqr; + + HPALETTE hOldPal = (HPALETTE)SelectPalette(hDC, hPal, FALSE); + RealizePalette(hDC); + + HBRUSH hBrush, hOldBrush; + int x, y; + for (int i=0; ileft + x*nWidth, + lpRect->top + y*nHeight, + lpRect->left + (x+1)*nWidth, + lpRect->top + (y+1) *nHeight); + SelectObject(hDC, hOldBrush); + DeleteObject(hBrush); + } + + SelectPalette(hDC, hOldPal, FALSE); + + return TRUE; +} + +/************************************************************************* + * + * CopyPalette () + * + * Parameter: + * + * HPALETTE hPalSrc - source palette handle + * + * Return Value: + * + * HPALETTE - destination palette handle + * + * Description: + * + * This function copys the source palette to a new palette handle + * + ************************************************************************/ +HPALETTE CopyPalette(HPALETTE hPalSrc) +{ + PLOGPALETTE plogPal; + int iNumEntries=0; + HPALETTE hPal; + HANDLE h; + + iNumEntries = GetPaletteEntries(hPalSrc, 0, iNumEntries, NULL); + if (iNumEntries == 0) + return (HPALETTE) NULL; + + h = GlobalAlloc(GHND, sizeof(DWORD) + sizeof(PALETTEENTRY)*iNumEntries); + if (! h) + return (HPALETTE) NULL; + plogPal = (PLOGPALETTE)GlobalLock(h); + if (! plogPal) + return (HPALETTE) NULL; + + plogPal->palVersion = 0x300; + plogPal->palNumEntries = (WORD) iNumEntries; + GetPaletteEntries(hPalSrc, 0, iNumEntries, plogPal->palPalEntry); + hPal = CreatePalette(plogPal); + + GlobalUnlock(h); + GlobalFree(h); + + return hPal; +} + +/************************************************************************* + * + * PalEntriesOnDevice() + * + * Parameter: + * + * HDC hDC - device context + * + * Return Value: + * + * int - number of palette entries on device + * + * Description: + * + * This function gets the number of palette entries on the specified device + * + ************************************************************************/ +int PalEntriesOnDevice(HDC hDC) +{ + int nColors; // number of colors + + // Find out the number of colors on this device. + + nColors = (1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES))); + + assert(nColors); + return nColors; +} + + +/************************************************************************* + * + * GetSystemPalette() + * + * Parameters: + * + * None + * + * Return Value: + * + * HPALETTE - handle to a copy of the current system palette + * + * Description: + * + * This function returns a handle to a palette which represents the system + * palette. The system RGB values are copied into our logical palette using + * the GetSystemPaletteEntries function. + * + ************************************************************************/ +HPALETTE GetSystemPalette(void) +{ + HDC hDC; // handle to a DC + static HPALETTE hPal = NULL; // handle to a palette + HANDLE hLogPal; // handle to a logical palette + LPLOGPALETTE lpLogPal; // pointer to a logical palette + int nColors; // number of colors + + // Find out how many palette entries we want. + + hDC = GetDC(NULL); + + if (!hDC) + return NULL; + + nColors = PalEntriesOnDevice(hDC); // Number of palette entries + + // Allocate room for the palette and lock it. + + hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors * + sizeof(PALETTEENTRY)); + + // if we didn't get a logical palette, return NULL + + if (!hLogPal) + return NULL; + + // get a pointer to the logical palette + + lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal); + + // set some important fields + + lpLogPal->palVersion = PALVERSION; + lpLogPal->palNumEntries = nColors; + + // Copy the current system palette into our logical palette + + GetSystemPaletteEntries(hDC, 0, nColors, + (LPPALETTEENTRY)(lpLogPal->palPalEntry)); + + // Go ahead and create the palette. Once it's created, + // we no longer need the LOGPALETTE, so free it. + + hPal = CreatePalette(lpLogPal); + + // clean up + + GlobalUnlock(hLogPal); + GlobalFree(hLogPal); + ReleaseDC(NULL, hDC); + + return hPal; +} + +/************************************************************************* + * + * CreateIdentifyPalette () + * + * Parameter: + * + * HPALETTE hPalSrc - source palette handle + * + * Return Value: + * + * HPALETTE - destination identify palette handle + * + * Description: + * + * This function creates an identify palette from the source palette handle + * + ************************************************************************/ +HPALETTE CreateIdentifyPalette(HPALETTE hPalSrc) +{ + BOOL bResult = FALSE; + int i, iSysColors, iPalEntries; + HPALETTE hPalette, hpalOld; + + if (! hPalSrc) + return NULL; + + // create a new palette equal to input + hPalette = CopyPalette(hPalSrc); + + // Get a screen DC to work with + HDC hdcScreen = GetDC(NULL); + ASSERT(hdcScreen); + + // Make sure we are on a palettized device + if (!(GetDeviceCaps(hdcScreen, RASTERCAPS) & RC_PALETTE)) + { + TRACE("Not a palettized device"); + goto abort; + } + + // Get the number of system colors and the number of palette entries + // Note that on a palletized device the number of colors is the + // number of guaranteed colors. I.e. the number of reserved system colors + iSysColors = GetDeviceCaps(hdcScreen, NUMCOLORS); + iPalEntries = GetDeviceCaps(hdcScreen, SIZEPALETTE); + + // if there are more than 256 colors we are wasting our time + if (iSysColors > 256) goto abort; + + // Now we force the palette manager to reset its tables so that + // the next palette to be realized will get its colors in the order they are + // in the logical palette. This is done by changing the number of + // reserved colors. + SetSystemPaletteUse(hdcScreen, SYSPAL_NOSTATIC); + SetSystemPaletteUse(hdcScreen, SYSPAL_STATIC); + + // Select our palette into the screen DC and realize it so that + // its colors will be entered into the free slots in the physical palette + hpalOld = ::SelectPalette(hdcScreen, + hPalette, // our hpal + FALSE); + ::RealizePalette(hdcScreen); + // Now replace the old palette (but don't realize it) + ::SelectPalette(hdcScreen, hpalOld, FALSE); + + // The physical palette now has our colors set in place and its own + // reserved colors at either end. We can grab the lot now + PALETTEENTRY pe[256]; + GetSystemPaletteEntries(hdcScreen, + 0, + iPalEntries, + pe); + + // Set the PC_NOCOLLAPSE flag for each of our colors so that GDI + // won't merge them together. Be careful not to set PC_NOCOLLAPSE for the + // sys color entries or we'll get multpile copies of these colors in + // the palette when we realize it. + for (i = 0; i < iSysColors/2; i++) { + pe[i].peFlags = 0; + } + for (; i < iPalEntries-iSysColors/2; i++) { + pe[i].peFlags = PC_NOCOLLAPSE; + } + for (; i < iPalEntries; i++) { + pe[i].peFlags = 0; + } + + // Resize the palette in case it was smaller + ResizePalette(hPalette, iPalEntries); + + // Update the palette entries with what is now in the physical palette + SetPaletteEntries(hPalette, 0, iPalEntries, pe); + bResult = TRUE; + +abort: + ::ReleaseDC(NULL, hdcScreen); + return bResult ? hPalette : NULL; +} + +/************************************************************************* + * + * MapDIBColorsToPalette () + * + * Parameter: + * + * HDIB hDIB - DIB handle + * HPALETTE hPalette - given palette handle + * + * Return Value: + * + * HPALETTE - destination identify palette handle + * + * Description: + * + * This function Map the colors in a DIB to a given palette. + * + ************************************************************************/ +BOOL MapDIBColorsToPalette(HDIB hDIB, HPALETTE hPalette) +{ + if (! hDIB) + return FALSE; + if (! hPalette) + return FALSE; + + LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); + if (! lpbi) + return FALSE; + LPRGBQUAD pctThis = (LPRGBQUAD)((LPBYTE)lpbi + lpbi->biSize); + + // build an index translation table to map this DIBs colors + // to those of the reference DIB + BYTE imap[256]; + for (int i = 0; i < 256; i++) + { + imap[i] = (BYTE)GetNearestPaletteIndex(hPalette, + RGB(pctThis->rgbRed, + pctThis->rgbGreen, + pctThis->rgbBlue)); + pctThis++; + } + // now map the DIB bits + LPBYTE pBits = (LPBYTE)lpbi + lpbi->biSize + PaletteSize((LPBYTE)lpbi); + int iSize = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) * lpbi->biHeight; + while (iSize--) + { + *pBits = imap[*pBits]; + pBits++; + } + // Now reset the DIB color table so that its RGB values match + // those in the palette + PALETTEENTRY pe[256]; + GetPaletteEntries(hPalette, 0, 256, pe); + pctThis = (LPRGBQUAD)((LPBYTE)lpbi + lpbi->biSize); + for (int i = 0; i < 256; i++) + { + pctThis->rgbRed = pe[i].peRed; + pctThis->rgbGreen = pe[i].peGreen; + pctThis->rgbBlue = pe[i].peBlue; + pctThis++; + } + + GlobalUnlock(hDIB); + return TRUE; +} + +/************************************************************************* + * + * DrawTransparentBitmap () + * + * Parameters: + * + * HDC hDC - DC to do output to + * + * HBITMAP hBitmap - handle of bitmap to draw transparently + * + * LONG xStart, yStart - start position to draw * + * + * COLORREF cTransparentColor - transparent color * + * Return Value: + * + * Description: none + * Draw bitmap transparently + * + ************************************************************************/ +void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, + LONG xStart, LONG yStart, + COLORREF cTransparentColor) +{ + BITMAP bm; + COLORREF cColor; + HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave; + HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld; + HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave; + POINT ptSize; + + hdcTemp = CreateCompatibleDC(hdc); + SelectObject(hdcTemp, hBitmap); // Select the bitmap + + GetObject(hBitmap, sizeof(BITMAP), (LPBYTE)&bm); + ptSize.x = bm.bmWidth; // Get width of bitmap + ptSize.y = bm.bmHeight; // Get height of bitmap + DPtoLP(hdcTemp, &ptSize, 1); // Convert from device + // to logical points + + // Create some DCs to hold temporary data. + hdcBack = CreateCompatibleDC(hdc); + hdcObject = CreateCompatibleDC(hdc); + hdcMem = CreateCompatibleDC(hdc); + hdcSave = CreateCompatibleDC(hdc); + + // Create a bitmap for each DC. DCs are required for a number of + // GDI functions. + + // Monochrome DC + bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL); + + // Monochrome DC + bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL); + + bmAndMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y); + bmSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y); + + // Each DC must select a bitmap object to store pixel data. + bmBackOld = (HBITMAP)SelectObject(hdcBack, bmAndBack); + bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject); + bmMemOld = (HBITMAP)SelectObject(hdcMem, bmAndMem); + bmSaveOld = (HBITMAP)SelectObject(hdcSave, bmSave); + + // Set proper mapping mode. + SetMapMode(hdcTemp, GetMapMode(hdc)); + + // Save the bitmap sent here, because it will be overwritten. + BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY); + + // Set the background color of the source DC to the color. + // contained in the parts of the bitmap that should be transparent + cColor = SetBkColor(hdcTemp, cTransparentColor); + + // Create the object mask for the bitmap by performing a BitBlt + // from the source bitmap to a monochrome bitmap. + BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, + SRCCOPY); + + // Set the background color of the source DC back to the original + // color. + SetBkColor(hdcTemp, cColor); + + // Create the inverse of the object mask. + BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, + NOTSRCCOPY); + + // Copy the background of the main DC to the destination. + BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart, + SRCCOPY); + + // Mask out the places where the bitmap will be placed. + BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND); + + // Mask out the transparent colored pixels on the bitmap. + BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND); + + // XOR the bitmap with the background on the destination DC. + BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT); + + // Copy the destination to the screen. + BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, + SRCCOPY); + + // Place the original bitmap back into the bitmap sent here. + BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY); + + // Delete the memory bitmaps. + DeleteObject(SelectObject(hdcBack, bmBackOld)); + DeleteObject(SelectObject(hdcObject, bmObjectOld)); + DeleteObject(SelectObject(hdcMem, bmMemOld)); + DeleteObject(SelectObject(hdcSave, bmSaveOld)); + + // Delete the memory DCs. + DeleteDC(hdcMem); + DeleteDC(hdcBack); + DeleteDC(hdcObject); + DeleteDC(hdcSave); + DeleteDC(hdcTemp); +} + +/************************************************************************* + * + * Fade() + * + * Parameters: + * + * int nDeltaR - change value of Red + * int nDeltaG - change value of Green + * int nDeltaB - change value of Blue + * BYTE rm - maxinum value of Red + * BYTE gm - maxinum value of Green + * BYTE bm - maxinum value of Blue + * BYTE *r - pointer of value of Red after change + * BYTE *g - pointer of value of Green after change + * BYTE *b - pointer of value of Blue after change + * + * Return Value: + * + * BOOL - TRUE if success, FALSE is failue + * + * Description: + * + * This function change the value of R, G, b + * + ************************************************************************/ +BOOL Fade(int nDeltaR, int nDeltaG, int nDeltaB, + BYTE rm, BYTE gm, BYTE bm, + BYTE *r, BYTE *g, BYTE *b) +{ + int R = *r + nDeltaR; + int G = *g + nDeltaG; + int B = *b + nDeltaB; + + if (nDeltaR < 0) + *r = (BYTE)BOUND(R, rm, 255); + else + *r = (BYTE)BOUND(R, 0, rm); + if (nDeltaG < 0) + *g = (BYTE)BOUND(G, gm, 255); + else + *g = (BYTE)BOUND(G, 0, gm); + if (nDeltaB < 0) + *b = (BYTE)BOUND(B, bm, 255); + else + *b = (BYTE)BOUND(B, 0, bm); + + if (*r==rm && *g==gm && *b==bm) + return TRUE; + else + return FALSE; +} + + +/************************************************************************* + * + * Delay() + * + * Parameters: + * + * DWORD dwDelayTime - ms to delay + * + * Return Value: none + * + * Description: + * + * This function Delay specified ms before perform next instruction + * + ************************************************************************/ +void Delay(DWORD dwDelayTime) +{ + /* DWORD dwTimeBegin, dwTimeEnd; + dwTimeBegin = timeGetTime(); + do + { + dwTimeEnd = timeGetTime(); + } while (dwTimeEnd - dwTimeBegin < dwDelayTime);*/ +} + +/************************************************************************* + * + * CopyHandle() + * + * Parameters: + * + * HANDLE h - source handle + * + * Return Value: + * + * HANDLE - duplicated handle + * + * Description: + * + * Copy memory handle to another + ************************************************************************/ +HANDLE CopyHandle(HANDLE h) +{ + if (h == NULL) + return NULL; + + DWORD dwLen = (DWORD)::GlobalSize((HGLOBAL)h); + HANDLE hCopy = (HANDLE)::GlobalAlloc(GHND, dwLen); + if (hCopy == NULL) + return NULL; + + void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); + void* lp = ::GlobalLock((HGLOBAL) h); + ::CopyMemory(lpCopy, lp, dwLen); + ::GlobalUnlock(hCopy); + ::GlobalUnlock(h); + + return hCopy; +} + +/************************************************************************* + * + * CropBitmap() + * + * Parameters: + * + * HBITMAP hBitmap - handle of DDB to be cropped + * LPRECT lpRect - specified rectangle to crop + * + * Return Value: + * + * HDIB - Handle to new bitmap + * + * Description: + * + * This function crop the specified rectangle in DDB, and return + * the cropped DDB in a new DIB handle, let the source DDB unchanged + * + ************************************************************************/ +HBITMAP CropBitmap(HBITMAP hBitmap, LPRECT lpRect) +{ + WaitCursorBegin(); + + // Get Curent DC + HDC hDC = GetDC(NULL); + // create bitmap + HBITMAP hNewBmp = CreateCompatibleBitmap(hDC, RECTWIDTH(lpRect), RECTHEIGHT(lpRect)); + if (hNewBmp == NULL) + { + ReleaseDC(NULL, hDC); + WaitCursorEnd(); + return NULL; + } + // Create memory DC + HDC hMemDC = CreateCompatibleDC(hDC); + if (hMemDC == NULL) + { + ReleaseDC(NULL, hDC); + DeleteObject(hNewBmp); + WaitCursorEnd(); + return NULL; + } + HDC hSrcMemDC = CreateCompatibleDC(hDC); + if (hSrcMemDC == NULL) + { + DeleteDC(hMemDC); + ReleaseDC(NULL, hDC); + DeleteObject(hNewBmp); + WaitCursorEnd(); + return NULL; + } + + // Select new bitmap in memory DC + HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hNewBmp); + // select old bitmap in SrcMemDC + HBITMAP hSrcOldBitmap = (HBITMAP)SelectObject(hSrcMemDC, hBitmap); + + // bitblt old bitmap in new bitmap + if (! BitBlt(hMemDC, + 0, + 0, + RECTWIDTH(lpRect), + RECTHEIGHT(lpRect), + hSrcMemDC, + lpRect->left, + lpRect->top, + SRCCOPY)) + { + SelectObject(hMemDC, hOldBitmap); + SelectObject(hSrcMemDC, hSrcOldBitmap); + DeleteDC(hMemDC); + DeleteDC(hSrcMemDC); + ReleaseDC(NULL, hDC); + DeleteObject(hNewBmp); + WaitCursorEnd(); + return NULL; + } + + // restore + SelectObject(hMemDC, hOldBitmap); + SelectObject(hSrcMemDC, hSrcOldBitmap); + DeleteDC(hMemDC); + DeleteDC(hSrcMemDC); + ReleaseDC(NULL, hDC); + WaitCursorEnd(); + + // return + return hNewBmp; +} + +/************************************************************************* + * + * CropDIB() + * + * Parameters: + * + * HDIB hDIB - handle of DIB to be cropped + * LPRECT lpRect - specified rectangle to crop + * + * Return Value: + * + * HDIB - Handle to new DIB + * + * Description: + * + * This function crop the specified rectangle in DIB, and return + * the cropped DIB in a new DIB handle, let the source DIB unchanged + * + ************************************************************************/ +HDIB CropDIB(HDIB hDIB, LPRECT lpRect) +{ + LPBITMAPINFO lpbmi = NULL; + LPBYTE lpSourceBits, lpTargetBits, lpResult; + HDC hDC = NULL, hSourceDC, hTargetDC; + HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; + DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize; + int nWidth, nHeight; + HDIB hNewDIB; + DWORD dwSize; + + WaitCursorBegin(); + + // Get DIB pointer + if (! hDIB) + { + WaitCursorEnd(); + return NULL; + } + LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB); + if (! lpSrcDIB) + { + WaitCursorEnd(); + return NULL; + } + + // Allocate and fill out a BITMAPINFO struct for the new DIB + dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + PaletteSize(lpSrcDIB); + lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); + memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize); + nWidth = RECTWIDTH(lpRect); + nHeight = RECTHEIGHT(lpRect); + lpbmi->bmiHeader.biWidth = nWidth; + lpbmi->bmiHeader.biHeight = nHeight; + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); + hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); + hSourceDC = CreateCompatibleDC( hDC ); + hTargetDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); + dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize ); + lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; + + // Select DIBSections into DCs + hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); + hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); + + // put old bitmap in new bitmap + BitBlt(hTargetDC, 0, 0, nWidth, nHeight, hSourceDC, lpRect->left, lpRect->top, SRCCOPY); + + // Clean up and delete the DCs + SelectObject( hSourceDC, hOldSourceBitmap ); + SelectObject( hTargetDC, hOldTargetBitmap ); + DeleteDC( hSourceDC ); + DeleteDC( hTargetDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + // Allocate enough memory for the new CF_DIB, and copy bits + dwSize = dwTargetHeaderSize + dwTargetBitsSize; + hNewDIB = GlobalAlloc(GHND, dwSize); + lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); + memcpy( lpResult, lpbmi, dwTargetHeaderSize ); + memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize ); + + // final cleanup + DeleteObject( hTargetBitmap ); + DeleteObject( hSourceBitmap ); + free( lpbmi ); + GlobalUnlock(hDIB); + GlobalUnlock(hNewDIB); + WaitCursorEnd(); + + return hNewDIB; +} + +/************************************************************************* + * + * CutDIB() + * + * Parameters: + * + * HDIB hDIB - handle of DIB to be cut + * LPRECT lpRect - specified rectangle to cut off + * + * Return Value: + * + * HDIB - Handle to new DIB + * + * Description: + * + * This function cut off the specified rectangle in DIB, and return + * the cut DIB in a new DIB handle, let the source DIB unchanged + * + ************************************************************************/ +HDIB CutDIB(HDIB hDIB, LPRECT lpRect) +{ + LPBITMAPINFO lpbmi = NULL; + LPBYTE lpTargetBits; + HDC hDC = NULL, hTargetDC; + HBITMAP hTargetBitmap, hOldTargetBitmap; + DWORD dwTargetBitsSize; + HDIB hNewDIB; + + WaitCursorBegin(); + + // Get new DIB handle + if (! hDIB) + { + WaitCursorEnd(); + return NULL; + } + hNewDIB = CopyHandle(hDIB); + if (! hNewDIB) + { + WaitCursorEnd(); + return NULL; + } + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB); + hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); + hTargetDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + memcpy( lpTargetBits, FindDIBBits((LPBYTE)lpbmi), dwTargetBitsSize ); + + // Select DIBSections into DCs + hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); + + // clear rectangle specified + HBRUSH hBrush = CreateSolidBrush(RGB(255,255,255)); + HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255,255,255)); + HBRUSH hOldBrush = (HBRUSH)SelectObject(hTargetDC, hBrush); + HPEN hOldPen = (HPEN)SelectObject(hTargetDC, hPen); + Rectangle(hTargetDC, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + SelectObject(hTargetDC, hOldBrush); + SelectObject(hTargetDC, hOldPen); + + // Clean up and delete the DCs + SelectObject( hTargetDC, hOldTargetBitmap ); + DeleteDC( hTargetDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + // copy bits + memcpy( FindDIBBits( (LPBYTE)lpbmi ), lpTargetBits, dwTargetBitsSize ); + + // final cleanup + DeleteObject( hTargetBitmap ); + GlobalUnlock(hNewDIB); + WaitCursorEnd(); + + return hNewDIB; +} + +/************************************************************************* + * + * MergeDIB() + * + * Parameters: + * + * HDIB hDIB1 - handle of DIB to be merged to + * HDIB hDIB2 - handle of DIB to be merged from + * POINT ptTopLeft - start merge position in hDIB1 + * + * Return Value: + * + * HDIB - Handle to new DIB + * + * Description: + * + * This function merge the second DIB to the first DIB, and return + * the merged DIB in a new DIB handle, let the source DIBs unchanged + * + ************************************************************************/ +HDIB MergeDIB(HDIB hDIB1, HDIB hDIB2, POINT ptTopLeft) +{ + LPBITMAPINFO lpbmi = NULL; + LPBYTE lpSourceBits, lpTargetBits; + HDC hDC = NULL, hSourceDC, hTargetDC; + HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; + DWORD dwTargetBitsSize, dwSourceBitsSize; + HDIB hNewDIB; + int nWidth, nHeight; + + WaitCursorBegin(); + + // Get DIB pointer + if (! hDIB1 || ! hDIB2) + { + WaitCursorEnd(); + return NULL; + } + + // new DIB + hNewDIB = CopyHandle(hDIB1); + if (! hNewDIB) + { + WaitCursorEnd(); + return NULL; + } + // New DIB buffer + lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB); + if (! lpbmi) + { + WaitCursorBegin(); + return NULL; + } + // DIB2 buffer + LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB2); + + if (! lpSrcDIB) + { + GlobalUnlock(hNewDIB); + DestroyDIB(hNewDIB); + WaitCursorBegin(); + return NULL; + } + nWidth = DIBWidth(lpSrcDIB); + nHeight = DIBHeight(lpSrcDIB); + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); + hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); + hSourceDC = CreateCompatibleDC( hDC ); + hTargetDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); + dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize ); + memcpy( lpTargetBits, FindDIBBits((LPBYTE)lpbmi), dwTargetBitsSize ); + + // Select DIBSections into DCs + hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); + hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); + + // Merge + BitBlt(hTargetDC, ptTopLeft.x, ptTopLeft.y, nWidth, nHeight, hSourceDC, 0, 0, SRCCOPY); + + // Clean up and delete the DCs + SelectObject( hSourceDC, hOldSourceBitmap ); + SelectObject( hTargetDC, hOldTargetBitmap ); + DeleteDC( hSourceDC ); + DeleteDC( hTargetDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + // and copy bits + memcpy( FindDIBBits((LPBYTE)lpbmi), lpTargetBits, dwTargetBitsSize ); + + // final cleanup + DeleteObject( hTargetBitmap ); + DeleteObject( hSourceBitmap ); + GlobalUnlock(hDIB2); + GlobalUnlock(hNewDIB); + WaitCursorEnd(); + + return hNewDIB; +} + +/************************************************************************* + * + * TransparentMergeDIB() + * + * Parameters: + * + * HDIB hDIB1 - handle of DIB to be merged to + * HDIB hDIB2 - handle of DIB to be merged from + * POINT ptTopLeft - start merge position in hDIB1 + * COLORREF crTransparent - transparent color + * + * Return Value: + * + * HDIB - Handle to new DIB + * + * Description: + * + * This function merge the second DIB to the first DIB with transparent of specified + * color, and return the merged DIB in a new DIB handle, let the source DIBs unchanged + * + ************************************************************************/ +HDIB TransparentMergeDIB(HDIB hDIB1, HDIB hDIB2, POINT ptTopLeft, COLORREF crTransparent) +{ + LPBITMAPINFO lpbmi = NULL; + LPBYTE lpTargetBits; + HDC hDC = NULL, hTargetDC; + HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap; + DWORD dwTargetBitsSize; + HDIB hNewDIB; + int nWidth, nHeight; + + // Get DIB pointer + if (! hDIB1 || ! hDIB2) + return NULL; + + // new DIB + hNewDIB = CopyHandle(hDIB1); + if (! hNewDIB) + return NULL; + + // New DIB buffer + lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB); + if (! lpbmi) + return NULL; + + // DIB2 + hSourceBitmap = DIBToBitmap(hDIB2, NULL); + if (! hSourceBitmap) + { + GlobalUnlock(hNewDIB); + DestroyDIB(hNewDIB); + return NULL; + } + BITMAP bm; + GetObject(hSourceBitmap, sizeof(BITMAP), &bm); + nWidth = bm.bmWidth; + nHeight = bm.bmHeight; + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); + hTargetDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + memcpy( lpTargetBits, FindDIBBits((LPBYTE)lpbmi), dwTargetBitsSize ); + + // Select DIBSections into DCs + hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); + // Set the color tables for the DIBSections + if( lpbmi->bmiHeader.biBitCount <= 8 ) + SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors ); + + // Merge + DrawTransparentBitmap(hTargetDC, hSourceBitmap, ptTopLeft.x, ptTopLeft.y, crTransparent); + + // Clean up and delete the DCs + SelectObject( hTargetDC, hOldTargetBitmap ); + DeleteDC( hTargetDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + // and copy bits + memcpy( FindDIBBits((LPBYTE)lpbmi), lpTargetBits, dwTargetBitsSize ); + + // final cleanup + DeleteObject( hTargetBitmap ); + DeleteObject( hSourceBitmap ); + GlobalUnlock(hDIB2); + GlobalUnlock(hNewDIB); + + return hNewDIB; +} + +/************************************************************************* + * + * ChangeDIBSize() + * + * Parameters: + * + * HDIB hDIB - handle of DIB to zoom + * int nWidth, int nHeight - new size of DIB + * + * Return Value: + * + * HDIB - Handle to new DIB + * + * Description: + * + * This function zoom a DIB to specified size, and return + * the zoomed DIB in a new DIB handle, let the source DIB unchanged + * + ************************************************************************/ +HDIB ChangeDIBSize(HDIB hDIB, int nWidth, int nHeight) +{ + LPBITMAPINFO lpbmi = NULL; + LPBYTE lpSourceBits, lpTargetBits, lpResult; + HDC hDC = NULL, hSourceDC, hTargetDC; + HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; + DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize; + HDIB hNewDIB; + DWORD dwSize; + + WaitCursorBegin(); + + // Get DIB pointer + if (! hDIB) + { + WaitCursorEnd(); + return NULL; + } + LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB); + if (! lpSrcDIB) + { + WaitCursorEnd(); + return NULL; + } + + // Allocate and fill out a BITMAPINFO struct for the new DIB + dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + PaletteSize(lpSrcDIB); + lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); + memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize); + lpbmi->bmiHeader.biWidth = nWidth; + lpbmi->bmiHeader.biHeight = nHeight; + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); + hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); + hSourceDC = CreateCompatibleDC( hDC ); + hTargetDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); + dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize ); + lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; + + // Select DIBSections into DCs + hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); + hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); + + // put old bitmap in new bitmap + SetStretchBltMode( hTargetDC, COLORONCOLOR ); + StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY ); + + // Clean up and delete the DCs + SelectObject( hSourceDC, hOldSourceBitmap ); + SelectObject( hTargetDC, hOldTargetBitmap ); + DeleteDC( hSourceDC ); + DeleteDC( hTargetDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + // Allocate enough memory for the new CF_DIB, and copy bits + dwSize = dwTargetHeaderSize + dwTargetBitsSize; + hNewDIB = GlobalAlloc(GHND, dwSize); + lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); + memcpy( lpResult, lpbmi, dwTargetHeaderSize ); + memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize ); + + // final cleanup + DeleteObject( hTargetBitmap ); + DeleteObject( hSourceBitmap ); + free( lpbmi ); + GlobalUnlock(hDIB); + GlobalUnlock(hNewDIB); + WaitCursorEnd(); + + return hNewDIB; +} + +/************************************************************************* + * + * ChangeDIBCanvasSize() + * + * Parameters: + * + * HDIB hDIB - handle of DIB to change + * int nWidth, int nHeight - new size of DIB + * int nPosition - position of source DIB in new DIB + * + * Return Value: + * + * HDIB - Handle to new DIB + * + * Description: + * + * This function change the canvas of DIB, and put source DIB in the + * specified position of new DIB (canvas), and return the changed DIB + * in a new DIB handle, let the source DIB unchanged + * + ************************************************************************/ +HDIB ChangeDIBCanvasSize(HDIB hDIB, int nWidth, int nHeight, int nPosition) +{ + LPBITMAPINFO lpbmi = NULL; + LPBYTE lpSourceBits, lpTargetBits, lpResult; + HDC hDC = NULL, hSourceDC, hTargetDC; + HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; + DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize; + HDIB hNewDIB; + DWORD dwSize; + + WaitCursorBegin(); + + // Get DIB pointer + if (! hDIB) + { + WaitCursorEnd(); + return NULL; + } + LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB); + if (! lpSrcDIB) + { + WaitCursorEnd(); + return NULL; + } + + // Allocate and fill out a BITMAPINFO struct for the new DIB + dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + PaletteSize(lpSrcDIB); + lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); + memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize); + lpbmi->bmiHeader.biWidth = nWidth; + lpbmi->bmiHeader.biHeight = nHeight; + + // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em + hDC = GetDC( NULL ); + hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); + hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); + hSourceDC = CreateCompatibleDC( hDC ); + hTargetDC = CreateCompatibleDC( hDC ); + + // Flip the bits on the source DIBSection to match the source DIB + dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader)); + dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader)); + memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize ); + lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; + + // Select DIBSections into DCs + hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); + hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); + + // old bitmap position in new bitmap + int x = 0; + int y = 0; + int nOldWidth = lpSrcDIB->bmiHeader.biWidth; + int nOldHeight = lpSrcDIB->bmiHeader.biHeight; + switch (nPosition) + { + case LEFT_UP: + x = 0; + y = 0; + break; + case CENTER_UP: + x = (nWidth-nOldWidth)/2; + y = 0; + break; + case RIGHT_UP: + x = nWidth-nOldWidth; + y = 0; + break; + case LEFT_CENTER: + x = 0; + y = (nHeight-nOldHeight)/2; + break; + case CENTER_CENTER: + x = (nWidth-nOldWidth)/2; + y = (nHeight-nOldHeight)/2; + break; + case CENTER_RIGHT: + x = nWidth-nOldWidth; + y = (nHeight-nOldHeight)/2; + break; + case LEFT_DOWN: + x = 0; + y = nHeight-nOldHeight; + break; + case CENTER_DOWN: + x = (nWidth-nOldWidth)/2; + y = nHeight-nOldHeight; + break; + case RIGHT_DOWN: + x = nWidth-nOldWidth; + y = nHeight-nOldHeight; + break; + } + + // first clear the new bitmap with whitwness + HBRUSH hBrush = CreateSolidBrush(RGB(255,255,255)); + HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255,255,255)); + HBRUSH hOldBrush = (HBRUSH)SelectObject(hTargetDC, hBrush); + HPEN hOldPen = (HPEN)SelectObject(hTargetDC, hPen); + Rectangle(hTargetDC, 0, 0, nWidth, nHeight); + SelectObject(hTargetDC, hOldBrush); + SelectObject(hTargetDC, hOldPen); + // put old bitmap in new bitmap + BitBlt(hTargetDC, x, y, nOldWidth, nOldHeight, hSourceDC, 0, 0, SRCCOPY); + + // Clean up and delete the DCs + SelectObject( hSourceDC, hOldSourceBitmap ); + SelectObject( hTargetDC, hOldTargetBitmap ); + DeleteDC( hSourceDC ); + DeleteDC( hTargetDC ); + ReleaseDC( NULL, hDC ); + + // Flush the GDI batch, so we can play with the bits + GdiFlush(); + + // Allocate enough memory for the new CF_DIB, and copy bits + dwSize = dwTargetHeaderSize + dwTargetBitsSize; + hNewDIB = GlobalAlloc(GHND, dwSize); + lpResult = (LPBYTE)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); + memcpy( lpResult, lpbmi, dwTargetHeaderSize ); + memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize ); + + // final cleanup + DeleteObject( hTargetBitmap ); + DeleteObject( hSourceBitmap ); + free( lpbmi ); + GlobalUnlock(hDIB); + GlobalUnlock(hNewDIB); + WaitCursorEnd(); + + return hNewDIB; +} + +/************************************************************************* + * + * ColorQuantizeDIB() + * + * Parameters: + * + * HDIB hDIB - handle to global memory with a DIB spec + * in it followed by the DIB bits + * + * UINT nColorBits - reduced DIB color bits + * + * UINT nMaxColors - reduced DIB color number + * + * + * Return Value: + * + * HDIB - destination DIB handle + * + * Description: + * Perform DIB color quatization + * + ************************************************************************/ +HDIB ColorQuantizeDIB(HDIB hDIB, UINT nColorBits, UINT nMaxColors) +{ + HPALETTE hPal = NULL; + + WaitCursorBegin(); + + // color quantization palette + LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); + + hPal = CreateOctreePalette(lpDIB, nMaxColors, nColorBits); + + GlobalUnlock(hDIB); + + // convert DIB to new format + HDIB hNewDIB = ConvertDIBFormat(hDIB, nColorBits, hPal); + + WaitCursorEnd(); + + return hNewDIB; +} + +/************************************************************************* + * + * ConvertToGrayscale() + * + * Parameters: + * + * HDIB hDIB - handle to global memory with a DIB spec + * in it followed by the DIB bits + * + * int nMethod - method used to convert color to grayscale + * + * double fRedWeight - weight of Red + * + * double fGreenWeight - weight of Green + * + * double fBlueWeight - weight of Blue + * + * Return Value: + * + * HPALETTE - handle of result grayscale palette + * + * Description: + * Change DIB color table from color to grayscale + * + ************************************************************************/ +HPALETTE ConvertToGrayscale(HDIB hDib, int nMethod, + double fRedWeight, double fGreenWeight, double fBlueWeight) +{ + if (hDib == NULL) + return NULL; + + BITMAPINFO* lpbi = (BITMAPINFO *)GlobalLock(hDib); + if (! lpbi) + return NULL; + + WaitCursorBegin(); + + // get color number + WORD wNumColors = DIBNumColors((LPBYTE)lpbi); + if (wNumColors == 0) // There is no palette + { + GlobalUnlock(hDib); + // reduce colors to 256 + HDIB hNewDib = ColorQuantizeDIB(hDib, 8, 256); + LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib); + if (! lpDIB) + { + WaitCursorEnd(); + return NULL; + } + DWORD dwSize = DIBBlockSize(lpDIB); + hDib = GlobalReAlloc(hDib, dwSize, 0); + lpbi = (BITMAPINFO *)GlobalLock(hDib); + CopyMemory((LPBYTE)lpbi, (LPBYTE)lpDIB, dwSize); + GlobalUnlock(hNewDib); + GlobalFree(hNewDib); + } + + wNumColors = DIBNumColors((LPBYTE)lpbi); + BYTE GrayValue = 0; + WORD i; + switch (nMethod) + { + case MAXIMUM_GRAY: + for (i=0; ibmiColors[i].rgbRed, + lpbi->bmiColors[i].rgbGreen), + lpbi->bmiColors[i].rgbBlue); + lpbi->bmiColors[i].rgbRed = + lpbi->bmiColors[i].rgbGreen = + lpbi->bmiColors[i].rgbBlue = GrayValue; + } + break; + case MEAN_GRAY: + for (i=0; ibmiColors[i].rgbRed + + lpbi->bmiColors[i].rgbGreen + + lpbi->bmiColors[i].rgbBlue)/3); + lpbi->bmiColors[i].rgbRed = + lpbi->bmiColors[i].rgbGreen = + lpbi->bmiColors[i].rgbBlue = GrayValue; + } + break; + case WEIGHT_GRAY: + for (i=0; ibmiColors[i].rgbRed*fRedWeight + + lpbi->bmiColors[i].rgbGreen*fGreenWeight + + lpbi->bmiColors[i].rgbBlue*fBlueWeight)); + lpbi->bmiColors[i].rgbRed = + lpbi->bmiColors[i].rgbGreen = + lpbi->bmiColors[i].rgbBlue = GrayValue; + } + break; + } + GlobalUnlock(hDib); + WaitCursorEnd(); + + return CreateDIBPalette(hDib); +} + +/************************************************************************ +* +* 最小误差法取阈值 +* +************************************************************************/ +static int MaxMin(double *tab,int flag) +{ + double max,min; + int i,p,q; + + max=min=tab[128]; + p=q=128; + for (i=0;i<256;i++) { + if (tab[i]>max) { + max=tab[i]; + p=i; + } + if (tab[i]255) ? 255 : Red; \ + Green = (Green<0) ? 0 : Green; \ + Green = (Green>255) ? 255 : Green;\ + Blue = (Blue<0) ? 0 : Blue; \ + Blue = (Blue>255) ? 255 : Blue; \ + *(Addr) = (BYTE)Blue; \ + *(Addr+1) = (BYTE)Green; \ + *(Addr+2) = (BYTE)Red; + +// This is the palette with which all true color images will be +// displayed when hardware support is unavailable. +typedef struct +{ + BYTE Red; + BYTE Green; + BYTE Blue; +} RGBCOLOR; + +// Define temporary vars as global, try to speedup... +int TRed, TGreen, TBlue; +int RedError, GreenError, BlueError; +BYTE PaletteIndex; +int BlueOffset; +LPBYTE PixelAddr; +LPBYTE RPixelAddr; +LPBYTE DPixelAddr; + +///////////////////// local used only !!! ///////////////////////////// diff --git a/src/gpc.cpp b/src/gpc.cpp new file mode 100644 index 0000000..678dc0d --- /dev/null +++ b/src/gpc.cpp @@ -0,0 +1,2472 @@ +/* +=========================================================================== + +Project: Generic Polygon Clipper + + A new algorithm for calculating the difference, intersection, + exclusive-or or union of arbitrary polygon sets. + +File: gpc.c +Author: Alan Murta (email: gpc@cs.man.ac.uk) +Version: 2.32 +Date: 17th December 2004 + +Copyright: (C) Advanced Interfaces Group, + University of Manchester. + + This software is free for non-commercial use. It may be copied, + modified, and redistributed provided that this copyright notice + is preserved on all copies. The intellectual property rights of + the algorithms used reside with the University of Manchester + Advanced Interfaces Group. + + You may not use this software, in whole or in part, in support + of any commercial product without the express consent of the + author. + + There is no warranty or other guarantee of fitness of this + software for any purpose. It is provided solely "as is". + +=========================================================================== +*/ + + +/* +=========================================================================== + Includes +=========================================================================== +*/ +#include "stdafx.h" +#include "gpc.h" +#include +#include +#include + + +/* +=========================================================================== + Constants +=========================================================================== +*/ + +#ifndef TRUE +#define FALSE 0 +#define TRUE 1 +#endif + +#define LEFT 0 +#define RIGHT 1 + +#define ABOVE 0 +#define BELOW 1 + +#define CLIP 0 +#define SUBJ 1 + +#define INVERT_TRISTRIPS FALSE + + +/* +=========================================================================== + Macros +=========================================================================== +*/ + +#define EQ(a, b) (fabs((a) - (b)) <= GPC_EPSILON) + +#define PREV_INDEX(i, n) ((i - 1 + n) % n) +#define NEXT_INDEX(i, n) ((i + 1 ) % n) + +#define OPTIMAL(v, i, n) ((v[PREV_INDEX(i, n)].y != v[i].y) || \ + (v[NEXT_INDEX(i, n)].y != v[i].y)) + +#define FWD_MIN(v, i, n) ((v[PREV_INDEX(i, n)].vertex.y >= v[i].vertex.y) \ + && (v[NEXT_INDEX(i, n)].vertex.y > v[i].vertex.y)) + +#define NOT_FMAX(v, i, n) (v[NEXT_INDEX(i, n)].vertex.y > v[i].vertex.y) + +#define REV_MIN(v, i, n) ((v[PREV_INDEX(i, n)].vertex.y > v[i].vertex.y) \ + && (v[NEXT_INDEX(i, n)].vertex.y >= v[i].vertex.y)) + +#define NOT_RMAX(v, i, n) (v[PREV_INDEX(i, n)].vertex.y > v[i].vertex.y) + +#define VERTEX(e,p,s,x,y) {add_vertex(&((e)->outp[(p)]->v[(s)]), x, y); \ + (e)->outp[(p)]->active++;} + +#define P_EDGE(d,e,p,i,j) {(d)= (e); \ + do {(d)= (d)->prev;} while (!(d)->outp[(p)]); \ + (i)= (d)->bot.x + (d)->dx * ((j)-(d)->bot.y);} + +#define N_EDGE(d,e,p,i,j) {(d)= (e); \ + do {(d)= (d)->next;} while (!(d)->outp[(p)]); \ + (i)= (d)->bot.x + (d)->dx * ((j)-(d)->bot.y);} + +#define MALLOC(p, b, s, t) {if ((b) > 0) { \ + p= (t*)malloc(b); if (!(p)) { \ + fprintf(stderr, "gpc malloc failure: %s\n", s); \ + exit(0);}} else p= NULL;} + +#define FREE(p) {if (p) {free(p); (p)= NULL;}} + + +/* +=========================================================================== + Private Data Types +=========================================================================== +*/ + +typedef enum /* Edge intersection classes */ +{ + NUL, /* Empty non-intersection */ + EMX, /* External maximum */ + ELI, /* External left intermediate */ + TED, /* Top edge */ + ERI, /* External right intermediate */ + RED, /* Right edge */ + IMM, /* Internal maximum and minimum */ + IMN, /* Internal minimum */ + EMN, /* External minimum */ + EMM, /* External maximum and minimum */ + LED, /* Left edge */ + ILI, /* Internal left intermediate */ + BED, /* Bottom edge */ + IRI, /* Internal right intermediate */ + IMX, /* Internal maximum */ + FUL /* Full non-intersection */ +} vertex_type; + +typedef enum /* Horizontal edge states */ +{ + NH, /* No horizontal edge */ + BH, /* Bottom horizontal edge */ + TH /* Top horizontal edge */ +} h_state; + +typedef enum /* Edge bundle state */ +{ + UNBUNDLED, /* Isolated edge not within a bundle */ + BUNDLE_HEAD, /* Bundle head node */ + BUNDLE_TAIL /* Passive bundle tail node */ +} bundle_state; + +typedef struct v_shape /* Internal vertex list datatype */ +{ + double x; /* X coordinate component */ + double y; /* Y coordinate component */ + struct v_shape *next; /* Pointer to next vertex in list */ +} vertex_node; + +typedef struct p_shape /* Internal contour / tristrip type */ +{ + int active; /* Active flag / vertex count */ + int hole; /* Hole / external contour flag */ + vertex_node *v[2]; /* Left and right vertex list ptrs */ + struct p_shape *next; /* Pointer to next polygon contour */ + struct p_shape *proxy; /* Pointer to actual structure used */ +} polygon_node; + +typedef struct edge_shape +{ + gpc_vertex vertex; /* Piggy-backed contour vertex data */ + gpc_vertex bot; /* Edge lower (x, y) coordinate */ + gpc_vertex top; /* Edge upper (x, y) coordinate */ + double xb; /* Scanbeam bottom x coordinate */ + double xt; /* Scanbeam top x coordinate */ + double dx; /* Change in x for a unit y increase */ + int type; /* Clip / subject edge flag */ + int bundle[2][2]; /* Bundle edge flags */ + int bside[2]; /* Bundle left / right indicators */ + bundle_state bstate[2]; /* Edge bundle state */ + polygon_node *outp[2]; /* Output polygon / tristrip pointer */ + struct edge_shape *prev; /* Previous edge in the AET */ + struct edge_shape *next; /* Next edge in the AET */ + struct edge_shape *pred; /* Edge connected at the lower end */ + struct edge_shape *succ; /* Edge connected at the upper end */ + struct edge_shape *next_bound; /* Pointer to next bound in LMT */ +} edge_node; + +typedef struct lmt_shape /* Local minima table */ +{ + double y; /* Y coordinate at local minimum */ + edge_node *first_bound; /* Pointer to bound list */ + struct lmt_shape *next; /* Pointer to next local minimum */ +} lmt_node; + +typedef struct sbt_t_shape /* Scanbeam tree */ +{ + double y; /* Scanbeam node y value */ + struct sbt_t_shape *less; /* Pointer to nodes with lower y */ + struct sbt_t_shape *more; /* Pointer to nodes with higher y */ +} sb_tree; + +typedef struct it_shape /* Intersection table */ +{ + edge_node *ie[2]; /* Intersecting edge (bundle) pair */ + gpc_vertex point; /* Point of intersection */ + struct it_shape *next; /* The next intersection table node */ +} it_node; + +typedef struct st_shape /* Sorted edge table */ +{ + edge_node *edge; /* Pointer to AET edge */ + double xb; /* Scanbeam bottom x coordinate */ + double xt; /* Scanbeam top x coordinate */ + double dx; /* Change in x for a unit y increase */ + struct st_shape *prev; /* Previous edge in sorted list */ +} st_node; + +typedef struct bbox_shape /* Contour axis-aligned bounding box */ +{ + double xmin; /* Minimum x coordinate */ + double ymin; /* Minimum y coordinate */ + double xmax; /* Maximum x coordinate */ + double ymax; /* Maximum y coordinate */ +} bbox; + + +/* +=========================================================================== + Global Data +=========================================================================== +*/ + +/* Horizontal edge state transitions within scanbeam boundary */ +const h_state next_h_state[3][6]= +{ + /* ABOVE BELOW CROSS */ + /* L R L R L R */ + /* NH */ {BH, TH, TH, BH, NH, NH}, + /* BH */ {NH, NH, NH, NH, TH, TH}, + /* TH */ {NH, NH, NH, NH, BH, BH} +}; + + +/* +=========================================================================== + Private Functions +=========================================================================== +*/ + +static void reset_it(it_node **it) +{ + it_node *itn; + + while (*it) + { + itn= (*it)->next; + FREE(*it); + *it= itn; + } +} + + +static void reset_lmt(lmt_node **lmt) +{ + lmt_node *lmtn; + + while (*lmt) + { + lmtn= (*lmt)->next; + FREE(*lmt); + *lmt= lmtn; + } +} + + +static void insert_bound(edge_node **b, edge_node *e) +{ + edge_node *existing_bound; + + if (!*b) + { + /* Link node e to the tail of the list */ + *b= e; + } + else + { + /* Do primary sort on the x field */ + if (e[0].bot.x < (*b)[0].bot.x) + { + /* Insert a new node mid-list */ + existing_bound= *b; + *b= e; + (*b)->next_bound= existing_bound; + } + else + { + if (e[0].bot.x == (*b)[0].bot.x) + { + /* Do secondary sort on the dx field */ + if (e[0].dx < (*b)[0].dx) + { + /* Insert a new node mid-list */ + existing_bound= *b; + *b= e; + (*b)->next_bound= existing_bound; + } + else + { + /* Head further down the list */ + insert_bound(&((*b)->next_bound), e); + } + } + else + { + /* Head further down the list */ + insert_bound(&((*b)->next_bound), e); + } + } + } +} + + +static edge_node **bound_list(lmt_node **lmt, double y) +{ + lmt_node *existing_node; + + if (!*lmt) + { + /* Add node onto the tail end of the LMT */ + MALLOC(*lmt, sizeof(lmt_node), "LMT insertion", lmt_node); + (*lmt)->y= y; + (*lmt)->first_bound= NULL; + (*lmt)->next= NULL; + return &((*lmt)->first_bound); + } + else + if (y < (*lmt)->y) + { + /* Insert a new LMT node before the current node */ + existing_node= *lmt; + MALLOC(*lmt, sizeof(lmt_node), "LMT insertion", lmt_node); + (*lmt)->y= y; + (*lmt)->first_bound= NULL; + (*lmt)->next= existing_node; + return &((*lmt)->first_bound); + } + else + if (y > (*lmt)->y) + /* Head further up the LMT */ + return bound_list(&((*lmt)->next), y); + else + /* Use this existing LMT node */ + return &((*lmt)->first_bound); +} + + +static void add_to_sbtree(int *entries, sb_tree **sbtree, double y) +{ + if (!*sbtree) + { + /* Add a new tree node here */ + MALLOC(*sbtree, sizeof(sb_tree), "scanbeam tree insertion", sb_tree); + (*sbtree)->y= y; + (*sbtree)->less= NULL; + (*sbtree)->more= NULL; + (*entries)++; + } + else + { + if ((*sbtree)->y > y) + { + /* Head into the 'less' sub-tree */ + add_to_sbtree(entries, &((*sbtree)->less), y); + } + else + { + if ((*sbtree)->y < y) + { + /* Head into the 'more' sub-tree */ + add_to_sbtree(entries, &((*sbtree)->more), y); + } + } + } +} + + +static void build_sbt(int *entries, double *sbt, sb_tree *sbtree) +{ + if (sbtree->less) + build_sbt(entries, sbt, sbtree->less); + sbt[*entries]= sbtree->y; + (*entries)++; + if (sbtree->more) + build_sbt(entries, sbt, sbtree->more); +} + + +static void free_sbtree(sb_tree **sbtree) +{ + if (*sbtree) + { + free_sbtree(&((*sbtree)->less)); + free_sbtree(&((*sbtree)->more)); + FREE(*sbtree); + } +} + + +static int count_optimal_vertices(gpc_vertex_list c) +{ + int result= 0, i; + + /* Ignore non-contributing contours */ + if (c.num_vertices > 0) + { + for (i= 0; i < c.num_vertices; i++) + /* Ignore superfluous vertices embedded in horizontal edges */ + if (OPTIMAL(c.vertex, i, c.num_vertices)) + result++; + } + return result; +} + + +static edge_node *build_lmt(lmt_node **lmt, sb_tree **sbtree, + int *sbt_entries, gpc_polygon *p, int type, + gpc_op op) +{ + int c, i, min, max, num_edges, v, num_vertices; + int total_vertices= 0, e_index=0; + edge_node *e, *edge_table; + + for (c= 0; c < p->num_contours; c++) + total_vertices+= count_optimal_vertices(p->contour[c]); + + /* Create the entire input polygon edge table in one go */ + MALLOC(edge_table, total_vertices * sizeof(edge_node), + "edge table creation", edge_node); + + for (c= 0; c < p->num_contours; c++) + { + if (p->contour[c].num_vertices < 0) + { + /* Ignore the non-contributing contour and repair the vertex count */ + p->contour[c].num_vertices= -p->contour[c].num_vertices; + } + else + { + /* Perform contour optimisation */ + num_vertices= 0; + for (i= 0; i < p->contour[c].num_vertices; i++) + if (OPTIMAL(p->contour[c].vertex, i, p->contour[c].num_vertices)) + { + edge_table[num_vertices].vertex.x= p->contour[c].vertex[i].x; + edge_table[num_vertices].vertex.y= p->contour[c].vertex[i].y; + + /* Record vertex in the scanbeam table */ + add_to_sbtree(sbt_entries, sbtree, + edge_table[num_vertices].vertex.y); + + num_vertices++; + } + + /* Do the contour forward pass */ + for (min= 0; min < num_vertices; min++) + { + /* If a forward local minimum... */ + if (FWD_MIN(edge_table, min, num_vertices)) + { + /* Search for the next local maximum... */ + num_edges= 1; + max= NEXT_INDEX(min, num_vertices); + while (NOT_FMAX(edge_table, max, num_vertices)) + { + num_edges++; + max= NEXT_INDEX(max, num_vertices); + } + + /* Build the next edge list */ + e= &edge_table[e_index]; + e_index+= num_edges; + v= min; + e[0].bstate[BELOW]= UNBUNDLED; + e[0].bundle[BELOW][CLIP]= FALSE; + e[0].bundle[BELOW][SUBJ]= FALSE; + for (i= 0; i < num_edges; i++) + { + e[i].xb= edge_table[v].vertex.x; + e[i].bot.x= edge_table[v].vertex.x; + e[i].bot.y= edge_table[v].vertex.y; + + v= NEXT_INDEX(v, num_vertices); + + e[i].top.x= edge_table[v].vertex.x; + e[i].top.y= edge_table[v].vertex.y; + e[i].dx= (edge_table[v].vertex.x - e[i].bot.x) / + (e[i].top.y - e[i].bot.y); + e[i].type= type; + e[i].outp[ABOVE]= NULL; + e[i].outp[BELOW]= NULL; + e[i].next= NULL; + e[i].prev= NULL; + e[i].succ= ((num_edges > 1) && (i < (num_edges - 1))) ? + &(e[i + 1]) : NULL; + e[i].pred= ((num_edges > 1) && (i > 0)) ? &(e[i - 1]) : NULL; + e[i].next_bound= NULL; + e[i].bside[CLIP]= (op == GPC_DIFF) ? RIGHT : LEFT; + e[i].bside[SUBJ]= LEFT; + } + insert_bound(bound_list(lmt, edge_table[min].vertex.y), e); + } + } + + /* Do the contour reverse pass */ + for (min= 0; min < num_vertices; min++) + { + /* If a reverse local minimum... */ + if (REV_MIN(edge_table, min, num_vertices)) + { + /* Search for the previous local maximum... */ + num_edges= 1; + max= PREV_INDEX(min, num_vertices); + while (NOT_RMAX(edge_table, max, num_vertices)) + { + num_edges++; + max= PREV_INDEX(max, num_vertices); + } + + /* Build the previous edge list */ + e= &edge_table[e_index]; + e_index+= num_edges; + v= min; + e[0].bstate[BELOW]= UNBUNDLED; + e[0].bundle[BELOW][CLIP]= FALSE; + e[0].bundle[BELOW][SUBJ]= FALSE; + for (i= 0; i < num_edges; i++) + { + e[i].xb= edge_table[v].vertex.x; + e[i].bot.x= edge_table[v].vertex.x; + e[i].bot.y= edge_table[v].vertex.y; + + v= PREV_INDEX(v, num_vertices); + + e[i].top.x= edge_table[v].vertex.x; + e[i].top.y= edge_table[v].vertex.y; + e[i].dx= (edge_table[v].vertex.x - e[i].bot.x) / + (e[i].top.y - e[i].bot.y); + e[i].type= type; + e[i].outp[ABOVE]= NULL; + e[i].outp[BELOW]= NULL; + e[i].next= NULL; + e[i].prev= NULL; + e[i].succ= ((num_edges > 1) && (i < (num_edges - 1))) ? + &(e[i + 1]) : NULL; + e[i].pred= ((num_edges > 1) && (i > 0)) ? &(e[i - 1]) : NULL; + e[i].next_bound= NULL; + e[i].bside[CLIP]= (op == GPC_DIFF) ? RIGHT : LEFT; + e[i].bside[SUBJ]= LEFT; + } + insert_bound(bound_list(lmt, edge_table[min].vertex.y), e); + } + } + } + } + return edge_table; +} + + +static void add_edge_to_aet(edge_node **aet, edge_node *edge, edge_node *prev) +{ + if (!*aet) + { + /* Append edge onto the tail end of the AET */ + *aet= edge; + edge->prev= prev; + edge->next= NULL; + } + else + { + /* Do primary sort on the xb field */ + if (edge->xb < (*aet)->xb) + { + /* Insert edge here (before the AET edge) */ + edge->prev= prev; + edge->next= *aet; + (*aet)->prev= edge; + *aet= edge; + } + else + { + if (edge->xb == (*aet)->xb) + { + /* Do secondary sort on the dx field */ + if (edge->dx < (*aet)->dx) + { + /* Insert edge here (before the AET edge) */ + edge->prev= prev; + edge->next= *aet; + (*aet)->prev= edge; + *aet= edge; + } + else + { + /* Head further into the AET */ + add_edge_to_aet(&((*aet)->next), edge, *aet); + } + } + else + { + /* Head further into the AET */ + add_edge_to_aet(&((*aet)->next), edge, *aet); + } + } + } +} + + +static void add_intersection(it_node **it, edge_node *edge0, edge_node *edge1, + double x, double y) +{ + it_node *existing_node; + + if (!*it) + { + /* Append a new node to the tail of the list */ + MALLOC(*it, sizeof(it_node), "IT insertion", it_node); + (*it)->ie[0]= edge0; + (*it)->ie[1]= edge1; + (*it)->point.x= x; + (*it)->point.y= y; + (*it)->next= NULL; + } + else + { + if ((*it)->point.y > y) + { + /* Insert a new node mid-list */ + existing_node= *it; + MALLOC(*it, sizeof(it_node), "IT insertion", it_node); + (*it)->ie[0]= edge0; + (*it)->ie[1]= edge1; + (*it)->point.x= x; + (*it)->point.y= y; + (*it)->next= existing_node; + } + else + /* Head further down the list */ + add_intersection(&((*it)->next), edge0, edge1, x, y); + } +} + + +static void add_st_edge(st_node **st, it_node **it, edge_node *edge, + double dy) +{ + st_node *existing_node; + double den, r, x, y; + + if (!*st) + { + /* Append edge onto the tail end of the ST */ + MALLOC(*st, sizeof(st_node), "ST insertion", st_node); + (*st)->edge= edge; + (*st)->xb= edge->xb; + (*st)->xt= edge->xt; + (*st)->dx= edge->dx; + (*st)->prev= NULL; + } + else + { + den= ((*st)->xt - (*st)->xb) - (edge->xt - edge->xb); + + /* If new edge and ST edge don't cross */ + if ((edge->xt >= (*st)->xt) || (edge->dx == (*st)->dx) || + (fabs(den) <= DBL_EPSILON)) + { + /* No intersection - insert edge here (before the ST edge) */ + existing_node= *st; + MALLOC(*st, sizeof(st_node), "ST insertion", st_node); + (*st)->edge= edge; + (*st)->xb= edge->xb; + (*st)->xt= edge->xt; + (*st)->dx= edge->dx; + (*st)->prev= existing_node; + } + else + { + /* Compute intersection between new edge and ST edge */ + r= (edge->xb - (*st)->xb) / den; + x= (*st)->xb + r * ((*st)->xt - (*st)->xb); + y= r * dy; + + /* Insert the edge pointers and the intersection point in the IT */ + add_intersection(it, (*st)->edge, edge, x, y); + + /* Head further into the ST */ + add_st_edge(&((*st)->prev), it, edge, dy); + } + } +} + + +static void build_intersection_table(it_node **it, edge_node *aet, double dy) +{ + st_node *st, *stp; + edge_node *edge; + + /* Build intersection table for the current scanbeam */ + reset_it(it); + st= NULL; + + /* Process each AET edge */ + for (edge= aet; edge; edge= edge->next) + { + if ((edge->bstate[ABOVE] == BUNDLE_HEAD) || + edge->bundle[ABOVE][CLIP] || edge->bundle[ABOVE][SUBJ]) + add_st_edge(&st, it, edge, dy); + } + + /* Free the sorted edge table */ + while (st) + { + stp= st->prev; + FREE(st); + st= stp; + } +} + +static int count_contours(polygon_node *polygon) +{ + int nc, nv; + vertex_node *v, *nextv; + + for (nc= 0; polygon; polygon= polygon->next) + if (polygon->active) + { + /* Count the vertices in the current contour */ + nv= 0; + for (v= polygon->proxy->v[LEFT]; v; v= v->next) + nv++; + + /* Record valid vertex counts in the active field */ + if (nv > 2) + { + polygon->active= nv; + nc++; + } + else + { + /* Invalid contour: just free the heap */ + for (v= polygon->proxy->v[LEFT]; v; v= nextv) + { + nextv= v->next; + FREE(v); + } + polygon->active= 0; + } + } + return nc; +} + + +static void add_left(polygon_node *p, double x, double y) +{ + vertex_node *nv; + + /* Create a new vertex node and set its fields */ + MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node); + nv->x= x; + nv->y= y; + + /* Add vertex nv to the left end of the polygon's vertex list */ + nv->next= p->proxy->v[LEFT]; + + /* Update proxy->[LEFT] to point to nv */ + p->proxy->v[LEFT]= nv; +} + + +static void merge_left(polygon_node *p, polygon_node *q, polygon_node *list) +{ + polygon_node *target; + + /* Label contour as a hole */ + q->proxy->hole= TRUE; + + if (p->proxy != q->proxy) + { + /* Assign p's vertex list to the left end of q's list */ + p->proxy->v[RIGHT]->next= q->proxy->v[LEFT]; + q->proxy->v[LEFT]= p->proxy->v[LEFT]; + + /* Redirect any p->proxy references to q->proxy */ + + for (target= p->proxy; list; list= list->next) + { + if (list->proxy == target) + { + list->active= FALSE; + list->proxy= q->proxy; + } + } + } +} + + +static void add_right(polygon_node *p, double x, double y) +{ + vertex_node *nv; + + /* Create a new vertex node and set its fields */ + MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node); + nv->x= x; + nv->y= y; + nv->next= NULL; + + /* Add vertex nv to the right end of the polygon's vertex list */ + p->proxy->v[RIGHT]->next= nv; + + /* Update proxy->v[RIGHT] to point to nv */ + p->proxy->v[RIGHT]= nv; +} + + +static void merge_right(polygon_node *p, polygon_node *q, polygon_node *list) +{ + polygon_node *target; + + /* Label contour as external */ + q->proxy->hole= FALSE; + + if (p->proxy != q->proxy) + { + /* Assign p's vertex list to the right end of q's list */ + q->proxy->v[RIGHT]->next= p->proxy->v[LEFT]; + q->proxy->v[RIGHT]= p->proxy->v[RIGHT]; + + /* Redirect any p->proxy references to q->proxy */ + for (target= p->proxy; list; list= list->next) + { + if (list->proxy == target) + { + list->active= FALSE; + list->proxy= q->proxy; + } + } + } +} + + +static void add_local_min(polygon_node **p, edge_node *edge, + double x, double y) +{ + polygon_node *existing_min; + vertex_node *nv; + + existing_min= *p; + + MALLOC(*p, sizeof(polygon_node), "polygon node creation", polygon_node); + + /* Create a new vertex node and set its fields */ + MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node); + nv->x= x; + nv->y= y; + nv->next= NULL; + + /* Initialise proxy to point to p itself */ + (*p)->proxy= (*p); + (*p)->active= TRUE; + (*p)->next= existing_min; + + /* Make v[LEFT] and v[RIGHT] point to new vertex nv */ + (*p)->v[LEFT]= nv; + (*p)->v[RIGHT]= nv; + + /* Assign polygon p to the edge */ + edge->outp[ABOVE]= *p; +} + + +static int count_tristrips(polygon_node *tn) +{ + int total; + + for (total= 0; tn; tn= tn->next) + if (tn->active > 2) + total++; + return total; +} + + +static void add_vertex(vertex_node **t, double x, double y) +{ + if (!(*t)) + { + MALLOC(*t, sizeof(vertex_node), "tristrip vertex creation", vertex_node); + (*t)->x= x; + (*t)->y= y; + (*t)->next= NULL; + } + else + /* Head further down the list */ + add_vertex(&((*t)->next), x, y); +} + + +static void new_tristrip(polygon_node **tn, edge_node *edge, + double x, double y) +{ + if (!(*tn)) + { + MALLOC(*tn, sizeof(polygon_node), "tristrip node creation", polygon_node); + (*tn)->next= NULL; + (*tn)->v[LEFT]= NULL; + (*tn)->v[RIGHT]= NULL; + (*tn)->active= 1; + add_vertex(&((*tn)->v[LEFT]), x, y); + edge->outp[ABOVE]= *tn; + } + else + /* Head further down the list */ + new_tristrip(&((*tn)->next), edge, x, y); +} + + +static bbox *create_contour_bboxes(gpc_polygon *p) +{ + bbox *box; + int c, v; + + MALLOC(box, p->num_contours * sizeof(bbox), "Bounding box creation", bbox); + + /* Construct contour bounding boxes */ + for (c= 0; c < p->num_contours; c++) + { + /* Initialise bounding box extent */ + box[c].xmin= DBL_MAX; + box[c].ymin= DBL_MAX; + box[c].xmax= -DBL_MAX; + box[c].ymax= -DBL_MAX; + + for (v= 0; v < p->contour[c].num_vertices; v++) + { + /* Adjust bounding box */ + if (p->contour[c].vertex[v].x < box[c].xmin) + box[c].xmin= p->contour[c].vertex[v].x; + if (p->contour[c].vertex[v].y < box[c].ymin) + box[c].ymin= p->contour[c].vertex[v].y; + if (p->contour[c].vertex[v].x > box[c].xmax) + box[c].xmax= p->contour[c].vertex[v].x; + if (p->contour[c].vertex[v].y > box[c].ymax) + box[c].ymax= p->contour[c].vertex[v].y; + } + } + return box; +} + + +static void minimax_test(gpc_polygon *subj, gpc_polygon *clip, gpc_op op) +{ + bbox *s_bbox, *c_bbox; + int s, c, *o_table, overlap; + + s_bbox= create_contour_bboxes(subj); + c_bbox= create_contour_bboxes(clip); + + MALLOC(o_table, subj->num_contours * clip->num_contours * sizeof(int), + "overlap table creation", int); + + /* Check all subject contour bounding boxes against clip boxes */ + for (s= 0; s < subj->num_contours; s++) + for (c= 0; c < clip->num_contours; c++) + o_table[c * subj->num_contours + s]= + (!((s_bbox[s].xmax < c_bbox[c].xmin) || + (s_bbox[s].xmin > c_bbox[c].xmax))) && + (!((s_bbox[s].ymax < c_bbox[c].ymin) || + (s_bbox[s].ymin > c_bbox[c].ymax))); + + /* For each clip contour, search for any subject contour overlaps */ + for (c= 0; c < clip->num_contours; c++) + { + overlap= 0; + for (s= 0; (!overlap) && (s < subj->num_contours); s++) + overlap= o_table[c * subj->num_contours + s]; + + if (!overlap) + /* Flag non contributing status by negating vertex count */ + clip->contour[c].num_vertices = -clip->contour[c].num_vertices; + } + + if (op == GPC_INT) + { + /* For each subject contour, search for any clip contour overlaps */ + for (s= 0; s < subj->num_contours; s++) + { + overlap= 0; + for (c= 0; (!overlap) && (c < clip->num_contours); c++) + overlap= o_table[c * subj->num_contours + s]; + + if (!overlap) + /* Flag non contributing status by negating vertex count */ + subj->contour[s].num_vertices = -subj->contour[s].num_vertices; + } + } + + FREE(s_bbox); + FREE(c_bbox); + FREE(o_table); +} + + +/* +=========================================================================== + Public Functions +=========================================================================== +*/ + +void gpc_free_polygon(gpc_polygon *p) +{ + int c; + + for (c= 0; c < p->num_contours; c++) + FREE(p->contour[c].vertex); + FREE(p->hole); + FREE(p->contour); + p->num_contours= 0; +} + + +void gpc_read_polygon(FILE *fp, int read_hole_flags, gpc_polygon *p) +{ + int c, v; + + fscanf_s(fp, "%d", &(p->num_contours)); + MALLOC(p->hole, p->num_contours * sizeof(int), + "hole flag array creation", int); + MALLOC(p->contour, p->num_contours + * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list); + for (c= 0; c < p->num_contours; c++) + { + fscanf_s(fp, "%d", &(p->contour[c].num_vertices)); + + if (read_hole_flags) + fscanf_s(fp, "%d", &(p->hole[c])); + else + p->hole[c]= FALSE; /* Assume all contours to be external */ + + MALLOC(p->contour[c].vertex, p->contour[c].num_vertices + * sizeof(gpc_vertex), "vertex creation", gpc_vertex); + for (v= 0; v < p->contour[c].num_vertices; v++) + fscanf_s(fp, "%lf %lf", &(p->contour[c].vertex[v].x), + &(p->contour[c].vertex[v].y)); + } +} + + +void gpc_write_polygon(FILE *fp, int write_hole_flags, gpc_polygon *p) +{ + int c, v; + + fprintf(fp, "%d\n", p->num_contours); + for (c= 0; c < p->num_contours; c++) + { + fprintf(fp, "%d\n", p->contour[c].num_vertices); + + if (write_hole_flags) + fprintf(fp, "%d\n", p->hole[c]); + + for (v= 0; v < p->contour[c].num_vertices; v++) + fprintf(fp, "% .*lf % .*lf\n", + DBL_DIG, p->contour[c].vertex[v].x, + DBL_DIG, p->contour[c].vertex[v].y); + } +} + + +void gpc_add_contour(gpc_polygon *p, gpc_vertex_list *new_contour, int hole) +{ + int *extended_hole, c, v; + gpc_vertex_list *extended_contour; + + /* Create an extended hole array */ + MALLOC(extended_hole, (p->num_contours + 1) + * sizeof(int), "contour hole addition", int); + + /* Create an extended contour array */ + MALLOC(extended_contour, (p->num_contours + 1) + * sizeof(gpc_vertex_list), "contour addition", gpc_vertex_list); + + /* Copy the old contour and hole data into the extended arrays */ + for (c= 0; c < p->num_contours; c++) + { + extended_hole[c]= p->hole[c]; + extended_contour[c]= p->contour[c]; + } + + /* Copy the new contour and hole onto the end of the extended arrays */ + c= p->num_contours; + extended_hole[c]= hole; + extended_contour[c].num_vertices= new_contour->num_vertices; + MALLOC(extended_contour[c].vertex, new_contour->num_vertices + * sizeof(gpc_vertex), "contour addition", gpc_vertex); + for (v= 0; v < new_contour->num_vertices; v++) + extended_contour[c].vertex[v]= new_contour->vertex[v]; + + /* Dispose of the old contour */ + FREE(p->contour); + FREE(p->hole); + + /* Update the polygon information */ + p->num_contours++; + p->hole= extended_hole; + p->contour= extended_contour; +} + + +void gpc_polygon_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip, + gpc_polygon *result) +{ + sb_tree *sbtree= NULL; + it_node *it= NULL, *intersect; + edge_node *edge, *prev_edge, *next_edge, *succ_edge, *e0, *e1; + edge_node *aet= NULL, *c_heap= NULL, *s_heap= NULL; + lmt_node *lmt= NULL, *local_min; + polygon_node *out_poly= NULL, *p, *q, *poly, *npoly, *cf= NULL; + vertex_node *vtx, *nv; + h_state horiz[2]; + int in[2], exists[2], parity[2]= {LEFT, LEFT}; + int c, v, contributing, search, scanbeam= 0, sbt_entries= 0; + int vclass, bl, br, tl, tr; + double *sbt= NULL, xb, px, yb, yt, dy, ix, iy; + + /* Test for trivial NULL result cases */ + if (((subj->num_contours == 0) && (clip->num_contours == 0)) + || ((subj->num_contours == 0) && ((op == GPC_INT) || (op == GPC_DIFF))) + || ((clip->num_contours == 0) && (op == GPC_INT))) + { + result->num_contours= 0; + result->hole= NULL; + result->contour= NULL; + return; + } + + /* Identify potentialy contributing contours */ + if (((op == GPC_INT) || (op == GPC_DIFF)) + && (subj->num_contours > 0) && (clip->num_contours > 0)) + minimax_test(subj, clip, op); + + /* Build LMT */ + if (subj->num_contours > 0) + s_heap= build_lmt(&lmt, &sbtree, &sbt_entries, subj, SUBJ, op); + if (clip->num_contours > 0) + c_heap= build_lmt(&lmt, &sbtree, &sbt_entries, clip, CLIP, op); + + /* Return a NULL result if no contours contribute */ + if (lmt == NULL) + { + result->num_contours= 0; + result->hole= NULL; + result->contour= NULL; + reset_lmt(&lmt); + FREE(s_heap); + FREE(c_heap); + return; + } + + /* Build scanbeam table from scanbeam tree */ + MALLOC(sbt, sbt_entries * sizeof(double), "sbt creation", double); + build_sbt(&scanbeam, sbt, sbtree); + scanbeam= 0; + free_sbtree(&sbtree); + + /* Allow pointer re-use without causing memory leak */ + if (subj == result) + gpc_free_polygon(subj); + if (clip == result) + gpc_free_polygon(clip); + + /* Invert clip polygon for difference operation */ + if (op == GPC_DIFF) + parity[CLIP]= RIGHT; + + local_min= lmt; + + /* Process each scanbeam */ + while (scanbeam < sbt_entries) + { + /* Set yb and yt to the bottom and top of the scanbeam */ + yb= sbt[scanbeam++]; + if (scanbeam < sbt_entries) + { + yt= sbt[scanbeam]; + dy= yt - yb; + } + + /* === SCANBEAM BOUNDARY PROCESSING ================================ */ + + /* If LMT node corresponding to yb exists */ + if (local_min) + { + if (local_min->y == yb) + { + /* Add edges starting at this local minimum to the AET */ + for (edge= local_min->first_bound; edge; edge= edge->next_bound) + add_edge_to_aet(&aet, edge, NULL); + + local_min= local_min->next; + } + } + + /* Set dummy previous x value */ + px= -DBL_MAX; + + /* Create bundles within AET */ + e0= aet; + e1= aet; + + /* Set up bundle fields of first edge */ + aet->bundle[ABOVE][ aet->type]= (aet->top.y != yb); + aet->bundle[ABOVE][!aet->type]= FALSE; + aet->bstate[ABOVE]= UNBUNDLED; + + for (next_edge= aet->next; next_edge; next_edge= next_edge->next) + { + /* Set up bundle fields of next edge */ + next_edge->bundle[ABOVE][ next_edge->type]= (next_edge->top.y != yb); + next_edge->bundle[ABOVE][!next_edge->type]= FALSE; + next_edge->bstate[ABOVE]= UNBUNDLED; + + /* Bundle edges above the scanbeam boundary if they coincide */ + if (next_edge->bundle[ABOVE][next_edge->type]) + { + if (EQ(e0->xb, next_edge->xb) && EQ(e0->dx, next_edge->dx) + && (e0->top.y != yb)) + { + next_edge->bundle[ABOVE][ next_edge->type]^= + e0->bundle[ABOVE][ next_edge->type]; + next_edge->bundle[ABOVE][!next_edge->type]= + e0->bundle[ABOVE][!next_edge->type]; + next_edge->bstate[ABOVE]= BUNDLE_HEAD; + e0->bundle[ABOVE][CLIP]= FALSE; + e0->bundle[ABOVE][SUBJ]= FALSE; + e0->bstate[ABOVE]= BUNDLE_TAIL; + } + e0= next_edge; + } + } + + horiz[CLIP]= NH; + horiz[SUBJ]= NH; + + /* Process each edge at this scanbeam boundary */ + for (edge= aet; edge; edge= edge->next) + { + exists[CLIP]= edge->bundle[ABOVE][CLIP] + + (edge->bundle[BELOW][CLIP] << 1); + exists[SUBJ]= edge->bundle[ABOVE][SUBJ] + + (edge->bundle[BELOW][SUBJ] << 1); + + if (exists[CLIP] || exists[SUBJ]) + { + /* Set bundle side */ + edge->bside[CLIP]= parity[CLIP]; + edge->bside[SUBJ]= parity[SUBJ]; + + /* Determine contributing status and quadrant occupancies */ + switch (op) + { + case GPC_DIFF: + case GPC_INT: + contributing= (exists[CLIP] && (parity[SUBJ] || horiz[SUBJ])) + || (exists[SUBJ] && (parity[CLIP] || horiz[CLIP])) + || (exists[CLIP] && exists[SUBJ] + && (parity[CLIP] == parity[SUBJ])); + br= (parity[CLIP]) + && (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + && (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + && (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + && (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + case GPC_XOR: + contributing= exists[CLIP] || exists[SUBJ]; + br= (parity[CLIP]) + ^ (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + ^ (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + case GPC_UNION: + contributing= (exists[CLIP] && (!parity[SUBJ] || horiz[SUBJ])) + || (exists[SUBJ] && (!parity[CLIP] || horiz[CLIP])) + || (exists[CLIP] && exists[SUBJ] + && (parity[CLIP] == parity[SUBJ])); + br= (parity[CLIP]) + || (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + || (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + || (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + || (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + } + + /* Update parity */ + parity[CLIP]^= edge->bundle[ABOVE][CLIP]; + parity[SUBJ]^= edge->bundle[ABOVE][SUBJ]; + + /* Update horizontal state */ + if (exists[CLIP]) + horiz[CLIP]= + next_h_state[horiz[CLIP]] + [((exists[CLIP] - 1) << 1) + parity[CLIP]]; + if (exists[SUBJ]) + horiz[SUBJ]= + next_h_state[horiz[SUBJ]] + [((exists[SUBJ] - 1) << 1) + parity[SUBJ]]; + + vclass= tr + (tl << 1) + (br << 2) + (bl << 3); + + if (contributing) + { + xb= edge->xb; + + switch (vclass) + { + case EMN: + case IMN: + add_local_min(&out_poly, edge, xb, yb); + px= xb; + cf= edge->outp[ABOVE]; + break; + case ERI: + if (xb != px) + { + add_right(cf, xb, yb); + px= xb; + } + edge->outp[ABOVE]= cf; + cf= NULL; + break; + case ELI: + add_left(edge->outp[BELOW], xb, yb); + px= xb; + cf= edge->outp[BELOW]; + break; + case EMX: + if (xb != px) + { + add_left(cf, xb, yb); + px= xb; + } + merge_right(cf, edge->outp[BELOW], out_poly); + cf= NULL; + break; + case ILI: + if (xb != px) + { + add_left(cf, xb, yb); + px= xb; + } + edge->outp[ABOVE]= cf; + cf= NULL; + break; + case IRI: + add_right(edge->outp[BELOW], xb, yb); + px= xb; + cf= edge->outp[BELOW]; + edge->outp[BELOW]= NULL; + break; + case IMX: + if (xb != px) + { + add_right(cf, xb, yb); + px= xb; + } + merge_left(cf, edge->outp[BELOW], out_poly); + cf= NULL; + edge->outp[BELOW]= NULL; + break; + case IMM: + if (xb != px) + { + add_right(cf, xb, yb); + px= xb; + } + merge_left(cf, edge->outp[BELOW], out_poly); + edge->outp[BELOW]= NULL; + add_local_min(&out_poly, edge, xb, yb); + cf= edge->outp[ABOVE]; + break; + case EMM: + if (xb != px) + { + add_left(cf, xb, yb); + px= xb; + } + merge_right(cf, edge->outp[BELOW], out_poly); + edge->outp[BELOW]= NULL; + add_local_min(&out_poly, edge, xb, yb); + cf= edge->outp[ABOVE]; + break; + case LED: + if (edge->bot.y == yb) + add_left(edge->outp[BELOW], xb, yb); + edge->outp[ABOVE]= edge->outp[BELOW]; + px= xb; + break; + case RED: + if (edge->bot.y == yb) + add_right(edge->outp[BELOW], xb, yb); + edge->outp[ABOVE]= edge->outp[BELOW]; + px= xb; + break; + default: + break; + } /* End of switch */ + } /* End of contributing conditional */ + } /* End of edge exists conditional */ + } /* End of AET loop */ + + /* Delete terminating edges from the AET, otherwise compute xt */ + for (edge= aet; edge; edge= edge->next) + { + if (edge->top.y == yb) + { + prev_edge= edge->prev; + next_edge= edge->next; + if (prev_edge) + prev_edge->next= next_edge; + else + aet= next_edge; + if (next_edge) + next_edge->prev= prev_edge; + + /* Copy bundle head state to the adjacent tail edge if required */ + if ((edge->bstate[BELOW] == BUNDLE_HEAD) && prev_edge) + { + if (prev_edge->bstate[BELOW] == BUNDLE_TAIL) + { + prev_edge->outp[BELOW]= edge->outp[BELOW]; + prev_edge->bstate[BELOW]= UNBUNDLED; + if (prev_edge->prev) + if (prev_edge->prev->bstate[BELOW] == BUNDLE_TAIL) + prev_edge->bstate[BELOW]= BUNDLE_HEAD; + } + } + } + else + { + if (edge->top.y == yt) + edge->xt= edge->top.x; + else + edge->xt= edge->bot.x + edge->dx * (yt - edge->bot.y); + } + } + + if (scanbeam < sbt_entries) + { + /* === SCANBEAM INTERIOR PROCESSING ============================== */ + + build_intersection_table(&it, aet, dy); + + /* Process each node in the intersection table */ + for (intersect= it; intersect; intersect= intersect->next) + { + e0= intersect->ie[0]; + e1= intersect->ie[1]; + + /* Only generate output for contributing intersections */ + if ((e0->bundle[ABOVE][CLIP] || e0->bundle[ABOVE][SUBJ]) + && (e1->bundle[ABOVE][CLIP] || e1->bundle[ABOVE][SUBJ])) + { + p= e0->outp[ABOVE]; + q= e1->outp[ABOVE]; + ix= intersect->point.x; + iy= intersect->point.y + yb; + + in[CLIP]= ( e0->bundle[ABOVE][CLIP] && !e0->bside[CLIP]) + || ( e1->bundle[ABOVE][CLIP] && e1->bside[CLIP]) + || (!e0->bundle[ABOVE][CLIP] && !e1->bundle[ABOVE][CLIP] + && e0->bside[CLIP] && e1->bside[CLIP]); + in[SUBJ]= ( e0->bundle[ABOVE][SUBJ] && !e0->bside[SUBJ]) + || ( e1->bundle[ABOVE][SUBJ] && e1->bside[SUBJ]) + || (!e0->bundle[ABOVE][SUBJ] && !e1->bundle[ABOVE][SUBJ] + && e0->bside[SUBJ] && e1->bside[SUBJ]); + + /* Determine quadrant occupancies */ + switch (op) + { + case GPC_DIFF: + case GPC_INT: + tr= (in[CLIP]) + && (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + case GPC_XOR: + tr= (in[CLIP]) + ^ (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + case GPC_UNION: + tr= (in[CLIP]) + || (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + } + + vclass= tr + (tl << 1) + (br << 2) + (bl << 3); + + switch (vclass) + { + case EMN: + add_local_min(&out_poly, e0, ix, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + break; + case ERI: + if (p) + { + add_right(p, ix, iy); + e1->outp[ABOVE]= p; + e0->outp[ABOVE]= NULL; + } + break; + case ELI: + if (q) + { + add_left(q, ix, iy); + e0->outp[ABOVE]= q; + e1->outp[ABOVE]= NULL; + } + break; + case EMX: + if (p && q) + { + add_left(p, ix, iy); + merge_right(p, q, out_poly); + e0->outp[ABOVE]= NULL; + e1->outp[ABOVE]= NULL; + } + break; + case IMN: + add_local_min(&out_poly, e0, ix, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + break; + case ILI: + if (p) + { + add_left(p, ix, iy); + e1->outp[ABOVE]= p; + e0->outp[ABOVE]= NULL; + } + break; + case IRI: + if (q) + { + add_right(q, ix, iy); + e0->outp[ABOVE]= q; + e1->outp[ABOVE]= NULL; + } + break; + case IMX: + if (p && q) + { + add_right(p, ix, iy); + merge_left(p, q, out_poly); + e0->outp[ABOVE]= NULL; + e1->outp[ABOVE]= NULL; + } + break; + case IMM: + if (p && q) + { + add_right(p, ix, iy); + merge_left(p, q, out_poly); + add_local_min(&out_poly, e0, ix, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + } + break; + case EMM: + if (p && q) + { + add_left(p, ix, iy); + merge_right(p, q, out_poly); + add_local_min(&out_poly, e0, ix, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + } + break; + default: + break; + } /* End of switch */ + } /* End of contributing intersection conditional */ + + /* Swap bundle sides in response to edge crossing */ + if (e0->bundle[ABOVE][CLIP]) + e1->bside[CLIP]= !e1->bside[CLIP]; + if (e1->bundle[ABOVE][CLIP]) + e0->bside[CLIP]= !e0->bside[CLIP]; + if (e0->bundle[ABOVE][SUBJ]) + e1->bside[SUBJ]= !e1->bside[SUBJ]; + if (e1->bundle[ABOVE][SUBJ]) + e0->bside[SUBJ]= !e0->bside[SUBJ]; + + /* Swap e0 and e1 bundles in the AET */ + prev_edge= e0->prev; + next_edge= e1->next; + if (next_edge) + next_edge->prev= e0; + + if (e0->bstate[ABOVE] == BUNDLE_HEAD) + { + search= TRUE; + while (search) + { + prev_edge= prev_edge->prev; + if (prev_edge) + { + if (prev_edge->bstate[ABOVE] != BUNDLE_TAIL) + search= FALSE; + } + else + search= FALSE; + } + } + if (!prev_edge) + { + aet->prev= e1; + e1->next= aet; + aet= e0->next; + } + else + { + prev_edge->next->prev= e1; + e1->next= prev_edge->next; + prev_edge->next= e0->next; + } + e0->next->prev= prev_edge; + e1->next->prev= e1; + e0->next= next_edge; + } /* End of IT loop*/ + + /* Prepare for next scanbeam */ + for (edge= aet; edge; edge= next_edge) + { + next_edge= edge->next; + succ_edge= edge->succ; + + if ((edge->top.y == yt) && succ_edge) + { + /* Replace AET edge by its successor */ + succ_edge->outp[BELOW]= edge->outp[ABOVE]; + succ_edge->bstate[BELOW]= edge->bstate[ABOVE]; + succ_edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP]; + succ_edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ]; + prev_edge= edge->prev; + if (prev_edge) + prev_edge->next= succ_edge; + else + aet= succ_edge; + if (next_edge) + next_edge->prev= succ_edge; + succ_edge->prev= prev_edge; + succ_edge->next= next_edge; + } + else + { + /* Update this edge */ + edge->outp[BELOW]= edge->outp[ABOVE]; + edge->bstate[BELOW]= edge->bstate[ABOVE]; + edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP]; + edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ]; + edge->xb= edge->xt; + } + edge->outp[ABOVE]= NULL; + } + } + } /* === END OF SCANBEAM PROCESSING ================================== */ + + /* Generate result polygon from out_poly */ + result->contour= NULL; + result->hole= NULL; + result->num_contours= count_contours(out_poly); + if (result->num_contours > 0) + { + MALLOC(result->hole, result->num_contours + * sizeof(int), "hole flag table creation", int); + MALLOC(result->contour, result->num_contours + * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list); + + c= 0; + for (poly= out_poly; poly; poly= npoly) + { + npoly= poly->next; + if (poly->active) + { + result->hole[c]= poly->proxy->hole; + result->contour[c].num_vertices= poly->active; + MALLOC(result->contour[c].vertex, + result->contour[c].num_vertices * sizeof(gpc_vertex), + "vertex creation", gpc_vertex); + + v= result->contour[c].num_vertices - 1; + for (vtx= poly->proxy->v[LEFT]; vtx; vtx= nv) + { + nv= vtx->next; + result->contour[c].vertex[v].x= vtx->x; + result->contour[c].vertex[v].y= vtx->y; + FREE(vtx); + v--; + } + c++; + } + FREE(poly); + } + } + else + { + for (poly= out_poly; poly; poly= npoly) + { + npoly= poly->next; + FREE(poly); + } + } + + /* Tidy up */ + reset_it(&it); + reset_lmt(&lmt); + FREE(c_heap); + FREE(s_heap); + FREE(sbt); +} + + +void gpc_free_tristrip(gpc_tristrip *t) +{ + int s; + + for (s= 0; s < t->num_strips; s++) + FREE(t->strip[s].vertex); + FREE(t->strip); + t->num_strips= 0; +} + + +void gpc_polygon_to_tristrip(gpc_polygon *s, gpc_tristrip *t) +{ + gpc_polygon c; + + c.num_contours= 0; + c.hole= NULL; + c.contour= NULL; + gpc_tristrip_clip(GPC_DIFF, s, &c, t); +} + + +void gpc_tristrip_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip, + gpc_tristrip *result) +{ + sb_tree *sbtree= NULL; + it_node *it= NULL, *intersect; + edge_node *edge, *prev_edge, *next_edge, *succ_edge, *e0, *e1; + edge_node *aet= NULL, *c_heap= NULL, *s_heap= NULL, *cf; + lmt_node *lmt= NULL, *local_min; + polygon_node *tlist= NULL, *tn, *tnn, *p, *q; + vertex_node *lt, *ltn, *rt, *rtn; + h_state horiz[2]; + vertex_type cft; + int in[2], exists[2], parity[2]= {LEFT, LEFT}; + int s, v, contributing, search, scanbeam= 0, sbt_entries= 0; + int vclass, bl, br, tl, tr; + double *sbt= NULL, xb, px, nx, yb, yt, dy, ix, iy; + + /* Test for trivial NULL result cases */ + if (((subj->num_contours == 0) && (clip->num_contours == 0)) + || ((subj->num_contours == 0) && ((op == GPC_INT) || (op == GPC_DIFF))) + || ((clip->num_contours == 0) && (op == GPC_INT))) + { + result->num_strips= 0; + result->strip= NULL; + return; + } + + /* Identify potentialy contributing contours */ + if (((op == GPC_INT) || (op == GPC_DIFF)) + && (subj->num_contours > 0) && (clip->num_contours > 0)) + minimax_test(subj, clip, op); + + /* Build LMT */ + if (subj->num_contours > 0) + s_heap= build_lmt(&lmt, &sbtree, &sbt_entries, subj, SUBJ, op); + if (clip->num_contours > 0) + c_heap= build_lmt(&lmt, &sbtree, &sbt_entries, clip, CLIP, op); + + /* Return a NULL result if no contours contribute */ + if (lmt == NULL) + { + result->num_strips= 0; + result->strip= NULL; + reset_lmt(&lmt); + FREE(s_heap); + FREE(c_heap); + return; + } + + /* Build scanbeam table from scanbeam tree */ + MALLOC(sbt, sbt_entries * sizeof(double), "sbt creation", double); + build_sbt(&scanbeam, sbt, sbtree); + scanbeam= 0; + free_sbtree(&sbtree); + + /* Invert clip polygon for difference operation */ + if (op == GPC_DIFF) + parity[CLIP]= RIGHT; + + local_min= lmt; + + /* Process each scanbeam */ + while (scanbeam < sbt_entries) + { + /* Set yb and yt to the bottom and top of the scanbeam */ + yb= sbt[scanbeam++]; + if (scanbeam < sbt_entries) + { + yt= sbt[scanbeam]; + dy= yt - yb; + } + + /* === SCANBEAM BOUNDARY PROCESSING ================================ */ + + /* If LMT node corresponding to yb exists */ + if (local_min) + { + if (local_min->y == yb) + { + /* Add edges starting at this local minimum to the AET */ + for (edge= local_min->first_bound; edge; edge= edge->next_bound) + add_edge_to_aet(&aet, edge, NULL); + + local_min= local_min->next; + } + } + + /* Set dummy previous x value */ + px= -DBL_MAX; + + /* Create bundles within AET */ + e0= aet; + e1= aet; + + /* Set up bundle fields of first edge */ + aet->bundle[ABOVE][ aet->type]= (aet->top.y != yb); + aet->bundle[ABOVE][!aet->type]= FALSE; + aet->bstate[ABOVE]= UNBUNDLED; + + for (next_edge= aet->next; next_edge; next_edge= next_edge->next) + { + /* Set up bundle fields of next edge */ + next_edge->bundle[ABOVE][ next_edge->type]= (next_edge->top.y != yb); + next_edge->bundle[ABOVE][!next_edge->type]= FALSE; + next_edge->bstate[ABOVE]= UNBUNDLED; + + /* Bundle edges above the scanbeam boundary if they coincide */ + if (next_edge->bundle[ABOVE][next_edge->type]) + { + if (EQ(e0->xb, next_edge->xb) && EQ(e0->dx, next_edge->dx) + && (e0->top.y != yb)) + { + next_edge->bundle[ABOVE][ next_edge->type]^= + e0->bundle[ABOVE][ next_edge->type]; + next_edge->bundle[ABOVE][!next_edge->type]= + e0->bundle[ABOVE][!next_edge->type]; + next_edge->bstate[ABOVE]= BUNDLE_HEAD; + e0->bundle[ABOVE][CLIP]= FALSE; + e0->bundle[ABOVE][SUBJ]= FALSE; + e0->bstate[ABOVE]= BUNDLE_TAIL; + } + e0= next_edge; + } + } + + horiz[CLIP]= NH; + horiz[SUBJ]= NH; + + /* Process each edge at this scanbeam boundary */ + for (edge= aet; edge; edge= edge->next) + { + exists[CLIP]= edge->bundle[ABOVE][CLIP] + + (edge->bundle[BELOW][CLIP] << 1); + exists[SUBJ]= edge->bundle[ABOVE][SUBJ] + + (edge->bundle[BELOW][SUBJ] << 1); + + if (exists[CLIP] || exists[SUBJ]) + { + /* Set bundle side */ + edge->bside[CLIP]= parity[CLIP]; + edge->bside[SUBJ]= parity[SUBJ]; + + /* Determine contributing status and quadrant occupancies */ + switch (op) + { + case GPC_DIFF: + case GPC_INT: + contributing= (exists[CLIP] && (parity[SUBJ] || horiz[SUBJ])) + || (exists[SUBJ] && (parity[CLIP] || horiz[CLIP])) + || (exists[CLIP] && exists[SUBJ] + && (parity[CLIP] == parity[SUBJ])); + br= (parity[CLIP]) + && (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + && (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + && (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + && (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + case GPC_XOR: + contributing= exists[CLIP] || exists[SUBJ]; + br= (parity[CLIP]) + ^ (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + ^ (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + case GPC_UNION: + contributing= (exists[CLIP] && (!parity[SUBJ] || horiz[SUBJ])) + || (exists[SUBJ] && (!parity[CLIP] || horiz[CLIP])) + || (exists[CLIP] && exists[SUBJ] + && (parity[CLIP] == parity[SUBJ])); + br= (parity[CLIP]) + || (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + || (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + || (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + || (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + } + + /* Update parity */ + parity[CLIP]^= edge->bundle[ABOVE][CLIP]; + parity[SUBJ]^= edge->bundle[ABOVE][SUBJ]; + + /* Update horizontal state */ + if (exists[CLIP]) + horiz[CLIP]= + next_h_state[horiz[CLIP]] + [((exists[CLIP] - 1) << 1) + parity[CLIP]]; + if (exists[SUBJ]) + horiz[SUBJ]= + next_h_state[horiz[SUBJ]] + [((exists[SUBJ] - 1) << 1) + parity[SUBJ]]; + + vclass= tr + (tl << 1) + (br << 2) + (bl << 3); + + if (contributing) + { + xb= edge->xb; + + switch (vclass) + { + case EMN: + new_tristrip(&tlist, edge, xb, yb); + cf= edge; + break; + case ERI: + edge->outp[ABOVE]= cf->outp[ABOVE]; + if (xb != cf->xb) + VERTEX(edge, ABOVE, RIGHT, xb, yb); + cf= NULL; + break; + case ELI: + VERTEX(edge, BELOW, LEFT, xb, yb); + edge->outp[ABOVE]= NULL; + cf= edge; + break; + case EMX: + if (xb != cf->xb) + VERTEX(edge, BELOW, RIGHT, xb, yb); + edge->outp[ABOVE]= NULL; + cf= NULL; + break; + case IMN: + if (cft == LED) + { + if (cf->bot.y != yb) + VERTEX(cf, BELOW, LEFT, cf->xb, yb); + new_tristrip(&tlist, cf, cf->xb, yb); + } + edge->outp[ABOVE]= cf->outp[ABOVE]; + VERTEX(edge, ABOVE, RIGHT, xb, yb); + break; + case ILI: + new_tristrip(&tlist, edge, xb, yb); + cf= edge; + cft= ILI; + break; + case IRI: + if (cft == LED) + { + if (cf->bot.y != yb) + VERTEX(cf, BELOW, LEFT, cf->xb, yb); + new_tristrip(&tlist, cf, cf->xb, yb); + } + VERTEX(edge, BELOW, RIGHT, xb, yb); + edge->outp[ABOVE]= NULL; + break; + case IMX: + VERTEX(edge, BELOW, LEFT, xb, yb); + edge->outp[ABOVE]= NULL; + cft= IMX; + break; + case IMM: + VERTEX(edge, BELOW, LEFT, xb, yb); + edge->outp[ABOVE]= cf->outp[ABOVE]; + if (xb != cf->xb) + VERTEX(cf, ABOVE, RIGHT, xb, yb); + cf= edge; + break; + case EMM: + VERTEX(edge, BELOW, RIGHT, xb, yb); + edge->outp[ABOVE]= NULL; + new_tristrip(&tlist, edge, xb, yb); + cf= edge; + break; + case LED: + if (edge->bot.y == yb) + VERTEX(edge, BELOW, LEFT, xb, yb); + edge->outp[ABOVE]= edge->outp[BELOW]; + cf= edge; + cft= LED; + break; + case RED: + edge->outp[ABOVE]= cf->outp[ABOVE]; + if (cft == LED) + { + if (cf->bot.y == yb) + { + VERTEX(edge, BELOW, RIGHT, xb, yb); + } + else + { + if (edge->bot.y == yb) + { + VERTEX(cf, BELOW, LEFT, cf->xb, yb); + VERTEX(edge, BELOW, RIGHT, xb, yb); + } + } + } + else + { + VERTEX(edge, BELOW, RIGHT, xb, yb); + VERTEX(edge, ABOVE, RIGHT, xb, yb); + } + cf= NULL; + break; + default: + break; + } /* End of switch */ + } /* End of contributing conditional */ + } /* End of edge exists conditional */ + } /* End of AET loop */ + + /* Delete terminating edges from the AET, otherwise compute xt */ + for (edge= aet; edge; edge= edge->next) + { + if (edge->top.y == yb) + { + prev_edge= edge->prev; + next_edge= edge->next; + if (prev_edge) + prev_edge->next= next_edge; + else + aet= next_edge; + if (next_edge) + next_edge->prev= prev_edge; + + /* Copy bundle head state to the adjacent tail edge if required */ + if ((edge->bstate[BELOW] == BUNDLE_HEAD) && prev_edge) + { + if (prev_edge->bstate[BELOW] == BUNDLE_TAIL) + { + prev_edge->outp[BELOW]= edge->outp[BELOW]; + prev_edge->bstate[BELOW]= UNBUNDLED; + if (prev_edge->prev) + if (prev_edge->prev->bstate[BELOW] == BUNDLE_TAIL) + prev_edge->bstate[BELOW]= BUNDLE_HEAD; + } + } + } + else + { + if (edge->top.y == yt) + edge->xt= edge->top.x; + else + edge->xt= edge->bot.x + edge->dx * (yt - edge->bot.y); + } + } + + if (scanbeam < sbt_entries) + { + /* === SCANBEAM INTERIOR PROCESSING ============================== */ + + build_intersection_table(&it, aet, dy); + + /* Process each node in the intersection table */ + for (intersect= it; intersect; intersect= intersect->next) + { + e0= intersect->ie[0]; + e1= intersect->ie[1]; + + /* Only generate output for contributing intersections */ + if ((e0->bundle[ABOVE][CLIP] || e0->bundle[ABOVE][SUBJ]) + && (e1->bundle[ABOVE][CLIP] || e1->bundle[ABOVE][SUBJ])) + { + p= e0->outp[ABOVE]; + q= e1->outp[ABOVE]; + ix= intersect->point.x; + iy= intersect->point.y + yb; + + in[CLIP]= ( e0->bundle[ABOVE][CLIP] && !e0->bside[CLIP]) + || ( e1->bundle[ABOVE][CLIP] && e1->bside[CLIP]) + || (!e0->bundle[ABOVE][CLIP] && !e1->bundle[ABOVE][CLIP] + && e0->bside[CLIP] && e1->bside[CLIP]); + in[SUBJ]= ( e0->bundle[ABOVE][SUBJ] && !e0->bside[SUBJ]) + || ( e1->bundle[ABOVE][SUBJ] && e1->bside[SUBJ]) + || (!e0->bundle[ABOVE][SUBJ] && !e1->bundle[ABOVE][SUBJ] + && e0->bside[SUBJ] && e1->bside[SUBJ]); + + /* Determine quadrant occupancies */ + switch (op) + { + case GPC_DIFF: + case GPC_INT: + tr= (in[CLIP]) + && (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + case GPC_XOR: + tr= (in[CLIP]) + ^ (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + case GPC_UNION: + tr= (in[CLIP]) + || (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + } + + vclass= tr + (tl << 1) + (br << 2) + (bl << 3); + + switch (vclass) + { + case EMN: + new_tristrip(&tlist, e1, ix, iy); + e0->outp[ABOVE]= e1->outp[ABOVE]; + break; + case ERI: + if (p) + { + P_EDGE(prev_edge, e0, ABOVE, px, iy); + VERTEX(prev_edge, ABOVE, LEFT, px, iy); + VERTEX(e0, ABOVE, RIGHT, ix, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + e0->outp[ABOVE]= NULL; + } + break; + case ELI: + if (q) + { + N_EDGE(next_edge, e1, ABOVE, nx, iy); + VERTEX(e1, ABOVE, LEFT, ix, iy); + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + e0->outp[ABOVE]= e1->outp[ABOVE]; + e1->outp[ABOVE]= NULL; + } + break; + case EMX: + if (p && q) + { + VERTEX(e0, ABOVE, LEFT, ix, iy); + e0->outp[ABOVE]= NULL; + e1->outp[ABOVE]= NULL; + } + break; + case IMN: + P_EDGE(prev_edge, e0, ABOVE, px, iy); + VERTEX(prev_edge, ABOVE, LEFT, px, iy); + N_EDGE(next_edge, e1, ABOVE, nx, iy); + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + new_tristrip(&tlist, prev_edge, px, iy); + e1->outp[ABOVE]= prev_edge->outp[ABOVE]; + VERTEX(e1, ABOVE, RIGHT, ix, iy); + new_tristrip(&tlist, e0, ix, iy); + next_edge->outp[ABOVE]= e0->outp[ABOVE]; + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + break; + case ILI: + if (p) + { + VERTEX(e0, ABOVE, LEFT, ix, iy); + N_EDGE(next_edge, e1, ABOVE, nx, iy); + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + e0->outp[ABOVE]= NULL; + } + break; + case IRI: + if (q) + { + VERTEX(e1, ABOVE, RIGHT, ix, iy); + P_EDGE(prev_edge, e0, ABOVE, px, iy); + VERTEX(prev_edge, ABOVE, LEFT, px, iy); + e0->outp[ABOVE]= e1->outp[ABOVE]; + e1->outp[ABOVE]= NULL; + } + break; + case IMX: + if (p && q) + { + VERTEX(e0, ABOVE, RIGHT, ix, iy); + VERTEX(e1, ABOVE, LEFT, ix, iy); + e0->outp[ABOVE]= NULL; + e1->outp[ABOVE]= NULL; + P_EDGE(prev_edge, e0, ABOVE, px, iy); + VERTEX(prev_edge, ABOVE, LEFT, px, iy); + new_tristrip(&tlist, prev_edge, px, iy); + N_EDGE(next_edge, e1, ABOVE, nx, iy); + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + next_edge->outp[ABOVE]= prev_edge->outp[ABOVE]; + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + } + break; + case IMM: + if (p && q) + { + VERTEX(e0, ABOVE, RIGHT, ix, iy); + VERTEX(e1, ABOVE, LEFT, ix, iy); + P_EDGE(prev_edge, e0, ABOVE, px, iy); + VERTEX(prev_edge, ABOVE, LEFT, px, iy); + new_tristrip(&tlist, prev_edge, px, iy); + N_EDGE(next_edge, e1, ABOVE, nx, iy); + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + e1->outp[ABOVE]= prev_edge->outp[ABOVE]; + VERTEX(e1, ABOVE, RIGHT, ix, iy); + new_tristrip(&tlist, e0, ix, iy); + next_edge->outp[ABOVE]= e0->outp[ABOVE]; + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + } + break; + case EMM: + if (p && q) + { + VERTEX(e0, ABOVE, LEFT, ix, iy); + new_tristrip(&tlist, e1, ix, iy); + e0->outp[ABOVE]= e1->outp[ABOVE]; + } + break; + default: + break; + } /* End of switch */ + } /* End of contributing intersection conditional */ + + /* Swap bundle sides in response to edge crossing */ + if (e0->bundle[ABOVE][CLIP]) + e1->bside[CLIP]= !e1->bside[CLIP]; + if (e1->bundle[ABOVE][CLIP]) + e0->bside[CLIP]= !e0->bside[CLIP]; + if (e0->bundle[ABOVE][SUBJ]) + e1->bside[SUBJ]= !e1->bside[SUBJ]; + if (e1->bundle[ABOVE][SUBJ]) + e0->bside[SUBJ]= !e0->bside[SUBJ]; + + /* Swap e0 and e1 bundles in the AET */ + prev_edge= e0->prev; + next_edge= e1->next; + if (e1->next) + e1->next->prev= e0; + + if (e0->bstate[ABOVE] == BUNDLE_HEAD) + { + search= TRUE; + while (search) + { + prev_edge= prev_edge->prev; + if (prev_edge) + { + if (prev_edge->bundle[ABOVE][CLIP] + || prev_edge->bundle[ABOVE][SUBJ] + || (prev_edge->bstate[ABOVE] == BUNDLE_HEAD)) + search= FALSE; + } + else + search= FALSE; + } + } + if (!prev_edge) + { + e1->next= aet; + aet= e0->next; + } + else + { + e1->next= prev_edge->next; + prev_edge->next= e0->next; + } + e0->next->prev= prev_edge; + e1->next->prev= e1; + e0->next= next_edge; + } /* End of IT loop*/ + + /* Prepare for next scanbeam */ + for (edge= aet; edge; edge= next_edge) + { + next_edge= edge->next; + succ_edge= edge->succ; + + if ((edge->top.y == yt) && succ_edge) + { + /* Replace AET edge by its successor */ + succ_edge->outp[BELOW]= edge->outp[ABOVE]; + succ_edge->bstate[BELOW]= edge->bstate[ABOVE]; + succ_edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP]; + succ_edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ]; + prev_edge= edge->prev; + if (prev_edge) + prev_edge->next= succ_edge; + else + aet= succ_edge; + if (next_edge) + next_edge->prev= succ_edge; + succ_edge->prev= prev_edge; + succ_edge->next= next_edge; + } + else + { + /* Update this edge */ + edge->outp[BELOW]= edge->outp[ABOVE]; + edge->bstate[BELOW]= edge->bstate[ABOVE]; + edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP]; + edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ]; + edge->xb= edge->xt; + } + edge->outp[ABOVE]= NULL; + } + } + } /* === END OF SCANBEAM PROCESSING ================================== */ + + /* Generate result tristrip from tlist */ + result->strip= NULL; + result->num_strips= count_tristrips(tlist); + if (result->num_strips > 0) + { + MALLOC(result->strip, result->num_strips * sizeof(gpc_vertex_list), + "tristrip list creation", gpc_vertex_list); + + s= 0; + for (tn= tlist; tn; tn= tnn) + { + tnn= tn->next; + + if (tn->active > 2) + { + /* Valid tristrip: copy the vertices and free the heap */ + result->strip[s].num_vertices= tn->active; + MALLOC(result->strip[s].vertex, tn->active * sizeof(gpc_vertex), + "tristrip creation", gpc_vertex); + v= 0; + if (INVERT_TRISTRIPS) + { + lt= tn->v[RIGHT]; + rt= tn->v[LEFT]; + } + else + { + lt= tn->v[LEFT]; + rt= tn->v[RIGHT]; + } + while (lt || rt) + { + if (lt) + { + ltn= lt->next; + result->strip[s].vertex[v].x= lt->x; + result->strip[s].vertex[v].y= lt->y; + v++; + FREE(lt); + lt= ltn; + } + if (rt) + { + rtn= rt->next; + result->strip[s].vertex[v].x= rt->x; + result->strip[s].vertex[v].y= rt->y; + v++; + FREE(rt); + rt= rtn; + } + } + s++; + } + else + { + /* Invalid tristrip: just free the heap */ + for (lt= tn->v[LEFT]; lt; lt= ltn) + { + ltn= lt->next; + FREE(lt); + } + for (rt= tn->v[RIGHT]; rt; rt=rtn) + { + rtn= rt->next; + FREE(rt); + } + } + FREE(tn); + } + } + + /* Tidy up */ + reset_it(&it); + reset_lmt(&lmt); + FREE(c_heap); + FREE(s_heap); + FREE(sbt); +} + +/* +=========================================================================== + End of file: gpc.c +=========================================================================== +*/ diff --git a/src/minilzo.cpp b/src/minilzo.cpp new file mode 100644 index 0000000..ba68ccd --- /dev/null +++ b/src/minilzo.cpp @@ -0,0 +1,3828 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#include "StdAfx.h" + +#define __LZO_IN_MINILZO +#define LZO_BUILD + +#if defined(LZO_CFG_FREESTANDING) +# undef MINILZO_HAVE_CONFIG_H +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif +#include +#include +#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if defined(__IBMCPP__) && !defined(__IBMC__) +# define __IBMC__ __IBMCPP__ +#endif +#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) +# define __INTEL_COMPILER __ICL +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if defined(__INTEL_COMPILER) && defined(__linux__) +# pragma warning(disable: 193) +#endif +#if defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif 0 && defined(__C251__) +# pragma warning disable = 322 +#endif +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if (_MSC_VER >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if 0 +#define LZO_0xffffL 0xfffful +#define LZO_0xffffffffL 0xfffffffful +#else +#define LZO_0xffffL 65535ul +#define LZO_0xffffffffL 4294967295ul +#endif +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +#else +# define LZO_EXTERN_C extern +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if defined(LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif defined(LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif (defined(__mips__) && defined(__psp__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) || defined(__MACOS__) +# define LZO_OS_POSIX_MACOSX 1 +# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +#elif defined(__INTEL_COMPILER) +# define LZO_CC_INTELC 1 +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__INTEL_COMPILER) +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__POCC__) +#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__) +# define LZO_CC_LLVM 1 +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__BORLANDC__) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__DECC) +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__IBMC__) +# define LZO_CC_IBMC 1 +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__IBMC__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(_MSC_VER) +# define LZO_CC_MSC 1 +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(_MSC_VER) "." LZO_CPP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(_MSC_VER) +# endif +#elif defined(__MWERKS__) +# define LZO_CC_MWERKS 1 +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CC "Sun C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if (__ZTC__ == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_CPP_MACRO_EXPAND(__ZTC__) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if defined(LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_ARCH_IA16 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#endif +#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM) +# error "this should not happen" +#endif +#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "this should not happen" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if !defined(__LZO_MM_OVERRIDE) +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown memory model" +#endif +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "this should not happen" +# elif (LZO_CC_ZORTECHC) +# else +# error "this should not happen" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS51 __MODEL__" +#endif +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#else +# error "unknown memory model" +#endif +#endif +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#endif +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#endif +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#endif +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#endif +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#endif +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#endif +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +#if !defined(LZO_SIZEOF_INT) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_WIN32 && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && defined(LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if (LZO_ARCH_I086) +# define __LZO_WORDSIZE 2 +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "LZO_MM" +# endif +#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) +# define __LZO_WORDSIZE 1 +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 4 +# else +# define __LZO_WORDSIZE 2 +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_M16C) +# define __LZO_WORDSIZE 2 +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_OS_OS400) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_OS_OS400) +# define __LZO_WORDSIZE LZO_SIZEOF_LONG +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#else +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_WORDSIZE) +# if defined(__LZO_WORDSIZE) +# define LZO_WORDSIZE __LZO_WORDSIZE +# else +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +# endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#else +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "LZO_MM" +# endif +#else +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#endif +#if !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN) && !defined(LZO_ABI_NEUTRAL_ENDIAN) +#if (LZO_ARCH_AMD64 || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_M68K || LZO_ARCH_S390) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN) +# error "this should not happen" +#endif +#if defined(LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif defined(LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif defined(LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if !defined(__LZO_LIBC_OVERRIDE) +#if defined(LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif defined(LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif defined(LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif defined(LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif defined(LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uclibc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#else +# define __lzo_gnuc_extension__ +#endif +#if (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define lzo_alignof(e) __alignof(e) +#endif +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define __lzo_inline inline +#endif +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#endif +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#endif +#if (defined(__lzo_forceinline) || defined(__lzo_noinline)) && !defined(__lzo_inline) +# error "this should not happen" +#endif +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && (LZO_OS_POSIX)) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#endif +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#if defined(__lzo_destructor) && !defined(__lzo_constructor) +# error "this should not happen" +#endif +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#else +# define __lzo_likely(e) (e) +# define __lzo_unlikely(e) (e) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# elif (LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if (0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +# endif +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# define LZO_OPT_UNALIGNED64 1 +#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) +#elif (LZO_ARCH_ARM) +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_CRIS) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_I386) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(LZO_ABI_BIG_ENDIAN) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_S390) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# if (LZO_SIZEOF_SIZE_T == 8) +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#if !defined(LZO_CFG_NO_INLINE_ASM) +#if defined(LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if !defined(LZO_CFG_NO_UNALIGNED) +#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if defined(LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(LZO_CFG_NO_INLINE_ASM) +#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +#elif (LZO_CC_INTELC) +# define __LZO_ASM_CLOBBER "memory" +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +#endif +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER + +#endif + +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2020) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H +#endif + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H + +#if !defined(__LZO_IN_MINILZO) +#if defined(LZO_CFG_FREESTANDING) +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +# define ACC_LIBC_FREESTANDING 1 +# define ACC_OS_FREESTANDING 1 +#endif +#if defined(LZO_CFG_NO_UNALIGNED) +# define ACC_CFG_NO_UNALIGNED 1 +#endif +#if defined(LZO_HAVE_CONFIG_H) +# define ACC_CONFIG_NO_HEADER 1 +#endif +#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) +# error "include this file first" +#endif +#include "lzo/lzoconf.h" +#endif + +#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED) +# error "version mismatch" +#endif + +#if (LZO_CC_BORLANDC && LZO_ARCH_I086) +# pragma option -h +#endif + +#if (LZO_CC_MSC && (_MSC_VER >= 1000)) +# pragma warning(disable: 4127 4701) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1300)) +# pragma warning(disable: 4820) +# pragma warning(disable: 4514 4710 4711) +#endif + +#if defined(__LZO_MMODEL_HUGE) && (!LZO_HAVE_MM_HUGE_PTR) +# error "this should not happen - check defines for __huge" +#endif + +#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING) +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define ACC_WANT_ACC_INCD_H 1 +# define ACC_WANT_ACC_INCE_H 1 +# define ACC_WANT_ACC_INCI_H 1 +#elif 1 +# include +#else +# define ACC_WANT_ACC_INCD_H 1 +#endif + +#if (LZO_ARCH_I086) +# define ACC_MM_AHSHIFT LZO_MM_AHSHIFT +# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0]) +# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1]) +# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o))) +#endif + +#if !defined(lzo_uintptr_t) +# if defined(__LZO_MMODEL_HUGE) +# define lzo_uintptr_t unsigned long +# elif 1 && defined(LZO_OS_OS400) && (LZO_SIZEOF_VOID_P == 16) +# define __LZO_UINTPTR_T_IS_POINTER 1 + typedef char* lzo_uintptr_t; +# define lzo_uintptr_t lzo_uintptr_t +# elif (LZO_SIZEOF_SIZE_T == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t size_t +# elif (LZO_SIZEOF_LONG == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned long +# elif (LZO_SIZEOF_INT == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned int +# elif (LZO_SIZEOF_LONG_LONG == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned long long +# else +# define lzo_uintptr_t size_t +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + +#if 1 && !defined(LZO_CFG_FREESTANDING) +#if 1 && !defined(HAVE_STRING_H) +#define HAVE_STRING_H 1 +#endif +#if 1 && !defined(HAVE_MEMCMP) +#define HAVE_MEMCMP 1 +#endif +#if 1 && !defined(HAVE_MEMCPY) +#define HAVE_MEMCPY 1 +#endif +#if 1 && !defined(HAVE_MEMMOVE) +#define HAVE_MEMMOVE 1 +#endif +#if 1 && !defined(HAVE_MEMSET) +#define HAVE_MEMSET 1 +#endif +#endif + +#if 1 && defined(HAVE_STRING_H) +#include +#endif + +#if defined(LZO_CFG_FREESTANDING) +# undef HAVE_MEMCMP +# undef HAVE_MEMCPY +# undef HAVE_MEMMOVE +# undef HAVE_MEMSET +#endif + +#if !defined(HAVE_MEMCMP) +# undef memcmp +# define memcmp(a,b,c) lzo_memcmp(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memcmp(a,b,c) memcmp(a,b,c) +#endif +#if !defined(HAVE_MEMCPY) +# undef memcpy +# define memcpy(a,b,c) lzo_memcpy(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memcpy(a,b,c) memcpy(a,b,c) +#endif +#if !defined(HAVE_MEMMOVE) +# undef memmove +# define memmove(a,b,c) lzo_memmove(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memmove(a,b,c) memmove(a,b,c) +#endif +#if !defined(HAVE_MEMSET) +# undef memset +# define memset(a,b,c) lzo_memset(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memset(a,b,c) memset(a,b,c) +#endif + +#undef NDEBUG +#if defined(LZO_CFG_FREESTANDING) +# undef LZO_DEBUG +# define NDEBUG 1 +# undef assert +# define assert(e) ((void)0) +#else +# if !defined(LZO_DEBUG) +# define NDEBUG 1 +# endif +# include +#endif + +#if 0 && defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(__lzo_inline) +# define __lzo_inline +#endif +#if !defined(__lzo_forceinline) +# define __lzo_forceinline +#endif +#if !defined(__lzo_noinline) +# define __lzo_noinline +#endif + +#if 1 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#if !defined(DMUL) +#if 0 + +# define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b))) +#else +# define DMUL(a,b) ((lzo_xint) ((a) * (b))) +#endif +#endif + +#if 1 && !defined(LZO_CFG_NO_UNALIGNED) +#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if (LZO_SIZEOF_SHORT == 2) +# define LZO_UNALIGNED_OK_2 +# endif +# if (LZO_SIZEOF_INT == 4) +# define LZO_UNALIGNED_OK_4 +# endif +#endif +#endif + +#if defined(LZO_UNALIGNED_OK_2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(short) == 2) +#endif +#if defined(LZO_UNALIGNED_OK_4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) +#elif defined(LZO_ALIGNED_OK_4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) +#endif + +#define MEMCPY8_DS(dest,src,len) \ + lzo_memcpy(dest,src,len); dest += len; src += len + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; while (--len > 0) + +__LZO_EXTERN_C int __lzo_init_done; +__LZO_EXTERN_C const char __lzo_copyright[]; +LZO_EXTERN(const lzo_bytep) lzo_copyright(void); + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(lzo_uintptr_t) +# if defined(__LZO_MMODEL_HUGE) +# define lzo_uintptr_t unsigned long +# else +# define lzo_uintptr_t acc_uintptr_t +# ifdef __ACC_INTPTR_T_IS_POINTER +# define __LZO_UINTPTR_T_IS_POINTER 1 +# endif +# endif +#endif + +#if (LZO_ARCH_I086) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((ACC_PTR_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0) +#else +#define PTR(a) ((lzo_uintptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) (PTR(a) - PTR(b)) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_uintptr_t a_lzo_uintptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#define LZO_DETERMINISTIC + +#define LZO_DICT_USE_PTR +#if 0 && (LZO_ARCH_I086) +# undef LZO_DICT_USE_PTR +#endif + +#if defined(LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#endif + +#if !defined(MINILZO_CFG_SKIP_LZO_PTR) + +LZO_PUBLIC(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_uintptr_t p; + +#if (LZO_ARCH_I086) + p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr)); +#else + p = (lzo_uintptr_t) PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ +#if defined(__LZO_UINTPTR_T_IS_POINTER) + size_t n = (size_t) ptr; + n = (((n + size - 1) / size) * size) - n; +#else + lzo_uintptr_t p, n; + p = __lzo_ptr_linear(ptr); + n = (((p + size - 1) / size) * size) - p; +#endif + + assert(size > 0); + assert((long)n >= 0); + assert(n <= s); + return (unsigned)n; +} + +#endif + +/* If you use the LZO library in a product, you *must* keep this + * copyright string in the executable of your product. + */ + +const char __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\r\n\n" + "LZO data compression library.\n" + "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com $\n\n" + "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" + "$Built: " __DATE__ " " __TIME__ " $\n" + "$Info: " LZO_INFO_STRING " $\n"; +#endif + +LZO_PUBLIC(const lzo_bytep) +lzo_copyright(void) +{ +#if (LZO_OS_DOS16 && LZO_CC_TURBOC) + return (lzo_voidp) __lzo_copyright; +#else + return (const lzo_bytep) __lzo_copyright; +#endif +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + unsigned k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +#undef LZO_DO1 +#undef LZO_DO2 +#undef LZO_DO4 +#undef LZO_DO8 +#undef LZO_DO16 + +#if !defined(MINILZO_CFG_SKIP_LZO_STRING) +#undef lzo_memcmp +#undef lzo_memcpy +#undef lzo_memmove +#undef lzo_memset +#if !defined(__LZO_MMODEL_HUGE) +# undef LZO_HAVE_MM_HUGE_PTR +#endif +#define lzo_hsize_t lzo_uint +#define lzo_hvoid_p lzo_voidp +#define lzo_hbyte_p lzo_bytep +#define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f +#define lzo_hmemcmp lzo_memcmp +#define lzo_hmemcpy lzo_memcpy +#define lzo_hmemmove lzo_memmove +#define lzo_hmemset lzo_memset +#define __LZOLIB_HMEMCPY_CH_INCLUDED 1 +#if !defined(LZOLIB_PUBLIC) +# define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) +#endif +LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCMP) + const lzo_hbyte_p p1 = (const lzo_hbyte_p) s1; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) s2; + if __lzo_likely(len > 0) do + { + int d = *p1 - *p2; + if (d != 0) + return d; + p1++; p2++; + } while __lzo_likely(--len > 0); + return 0; +#else + return memcmp(s1, s2, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCPY) + lzo_hbyte_p p1 = (lzo_hbyte_p) dest; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + if (len <= 0 || p1 == p2) + return dest; + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + return dest; +#else + return memcpy(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMMOVE) + lzo_hbyte_p p1 = (lzo_hbyte_p) dest; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + if (len <= 0 || p1 == p2) + return dest; + if (p1 < p2) + { + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while __lzo_likely(--len > 0); + } + return dest; +#else + return memmove(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMSET) + lzo_hbyte_p p = (lzo_hbyte_p) s; + if __lzo_likely(len > 0) do + *p++ = (unsigned char) c; + while __lzo_likely(--len > 0); + return s; +#else + return memset(s, c, len); +#endif +} +#undef LZOLIB_PUBLIC +#endif + +#if !defined(__LZO_IN_MINILZO) + +#define ACC_WANT_ACC_CHK_CH 1 +#undef ACCCHK_ASSERT + + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) + + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32) + ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) + ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4) + +#if !defined(__LZO_UINTPTR_T_IS_POINTER) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) +#endif + ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) + ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32)) + ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint)) + ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint)) + +#endif +#undef ACCCHK_ASSERT + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + union { unsigned char c[2*sizeof(lzo_xint)]; lzo_xint l[2]; } u; + +#if !defined(LZO_CFG_NO_CONFIG_CHECK) +#if defined(LZO_ABI_BIG_ENDIAN) + u.l[0] = u.l[1] = 0; u.c[sizeof(lzo_xint) - 1] = 128; + r &= (u.l[0] == 128); +#endif +#if defined(LZO_ABI_LITTLE_ENDIAN) + u.l[0] = u.l[1] = 0; u.c[0] = 128; + r &= (u.l[0] == 128); +#endif +#if defined(LZO_UNALIGNED_OK_2) + u.l[0] = u.l[1] = 0; + r &= ((* (const lzo_ushortp) (const lzo_voidp) &u.c[1]) == 0); +#endif +#if defined(LZO_UNALIGNED_OK_4) + u.l[0] = u.l[1] = 0; + r &= ((* (const lzo_uint32p) (const lzo_voidp) &u.c[1]) == 0); +#endif +#endif + + LZO_UNUSED(u); + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +int __lzo_init_done = 0; + +LZO_PUBLIC(int) +__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + +#if defined(__LZO_IN_MINILZO) +#elif (LZO_CC_MSC && ((_MSC_VER) < 700)) +#else +#define ACC_WANT_ACC_CHK_CH 1 +#undef ACCCHK_ASSERT +#define ACCCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif +#undef ACCCHK_ASSERT + + __lzo_init_done = 1; + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) + +#if 0 +BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, + WORD wHeapSize, LPSTR lpszCmdLine ) +#else +int __far __pascal LibMain ( int a, short b, short c, long d ) +#endif +{ + LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); + return 1; +} + +#endif + +#endif + +#define do_compress _lzo1x_1_do_compress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) + +#define LZO_NEED_DICT_H +#define D_BITS 14 +#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X +#endif + +#if !defined(__LZO_IN_MINILZO) +#include "lzo/lzo1x.h" +#endif + +#define LZO_EOF_CODE +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 8 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 8 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#undef DM +#undef DX + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_xint)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_xint)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) +{ + lzo_xint df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if defined(LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if defined(LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR(( \ + m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ + PTR_LT(m_pos,in) || \ + (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) <= 0 || \ + m_off > max_offset ))) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (pd(ip, in) <= m_off || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if defined(LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define DO_COMPRESS lzo1x_1_compress + +static __lzo_noinline lzo_uint +do_compress ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + register const lzo_bytep ip; + lzo_bytep op; + const lzo_bytep const in_end = in + in_len; + const lzo_bytep const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_bytep ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) + { + register const lzo_bytep m_pos; + lzo_uint m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if 1 && defined(LZO_UNALIGNED_OK_2) + if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) +#endif + { + } + else + { + if __lzo_likely(m_pos[2] == ip[2]) + { +#if 0 + if (m_off <= M2_MAX_OFFSET) + goto match; + if (lit <= 3) + goto match; + if (lit == 3) + { + assert(op - 2 > out); op[-2] |= LZO_BYTE(3); + *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; + goto code_match; + } + if (m_pos[3] == ip[3]) +#endif + goto match; + } + else + { +#if 0 +#if 0 + if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) +#else + if (m_off <= M1_MAX_OFFSET && lit == 3) +#endif + { + register lzo_uint t; + + t = lit; + assert(op - 2 > out); op[-2] |= LZO_BYTE(t); + do *op++ = *ii++; while (--t > 0); + assert(ii == ip); + m_off -= 1; + *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); + ip += 2; + goto match_done; + } +#endif + } + } + +literal: + UPDATE_I(dict,0,dindex,ip,in); + ++ip; + if __lzo_unlikely(ip >= ip_end) + break; + continue; + +match: + UPDATE_I(dict,0,dindex,ip,in); + if (pd(ip,ii) > 0) + { + register lzo_uint t = pd(ip,ii); + + if (t <= 3) + { + assert(op - 2 > out); + op[-2] |= LZO_BYTE(t); + } + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + assert(ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || + m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ +#ifdef LZO1Y + || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ + || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ +#endif + ) + { + --ip; + m_len = pd(ip, ii); + assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } + else +#if defined(LZO1X) + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + goto m3_m4_offset; + } +#elif defined(LZO1Y) + goto m4_match; +#endif + } + else + { + { + const lzo_bytep end = in_end; + const lzo_bytep m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = pd(ip, ii); + } + assert(m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= 33) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } + else + { +#if defined(LZO1Y) +m4_match: +#endif + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) + { + m_len -= 255; + *op++ = 0; + } + assert(m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + +m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + +#if 0 +match_done: +#endif + ii = ip; + if __lzo_unlikely(ip >= ip_end) + break; + } + + *out_len = pd(op, out); + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + lzo_bytep op = out; + lzo_uint t; + + if __lzo_unlikely(in_len <= M2_MAX_LEN + 5) + t = in_len; + else + { + t = do_compress(in,in_len,op,out_len,wrkmem); + op += *out_len; + } + + if (t > 0) + { + const lzo_bytep ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = pd(op, out); + return LZO_E_OK; +} + +#endif + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_bytep op; + register const lzo_bytep ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + register const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + do { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } while (TEST_IP && TEST_OP); + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +#define LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_bytep op; + register const lzo_bytep ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + register const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + do { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } while (TEST_IP && TEST_OP); + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +/***** End of minilzo.c *****/ +