diff --git a/Bin/Config/Common/ModelParaDefinesNM_cn.dat b/Bin/Config/Common/ModelParaDefinesNM_cn.dat
index 6a0acc0..a975784 100644
--- a/Bin/Config/Common/ModelParaDefinesNM_cn.dat
+++ b/Bin/Config/Common/ModelParaDefinesNM_cn.dat
@@ -1 +1 @@
-77u/PD94bWwgcup_mpadmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSoqKioqKioqKiwzyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCjwhLS0gICAg5pys5paH5qGj55qE55uu55qE5piv5bu656uLV1RBSeaVsOWAvOinoyhOTSnmqKHlnZfnmoTlj4LmlbDlrprkuYkgICAgICAgICAgICAgICAgLS0+DQo8IS0tICAgIOS7heWMheWQq1BFQknmsYLop6PlmajmiYDpnIDnmoTlgqjlsYLlkozkupXlj4LmlbAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLS0+CjwhLS0gICAgRGF0ZTogMjAyNjA2MTUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCg0KPCEtLQ0KICAgIOWPguaVsOiMg+WbtO+8mlBFQknmsYLop6PlmajmiYDpnIDnmoTlgqjlsYLlj4LmlbDlkozkupXlj4LmlbAKICAgIOWvueW6lCBIWF9OV1RNX01PREVMX0lOUFVUIOe7k+aehOS9k+Wtl+autQogICAg6YCa6L+HIF9wYXJhSGVscGVyLT5sb2FkUGFyYURlZmluZXMoKSDliqDovb3vvIxzS2V5IOagh+ivhuS4uiBzX05tX1NlcmllDQotLT4NCg0KPFJvb3Q+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSLlgqjlsYLlj4LmlbAiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJoIiAgIEFsaWFzPSLlgqjlsYLljprluqYiICAgICAgIFVuaXQ9Im0iICAgICBEZWZhdWx0PSIxMCIgICAgTWF4PSIxMDAwMCIgIE1pbj0iMWUtMDUiICBEaWdpdD0iNiIgIERlc2M9InJlc2Vydm9pciB0aGlja25lc3MiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlBpIiAgQWxpYXM9IuWIneWni+WOi+WKmyIgICAgICAgVW5pdD0iTVBhIiAgIERlZmF1bHQ9IjQwIiAgICBNYXg9IjUwMCIgICAgTWluPSIwLjEiICAgIERpZ2l0PSI2IiAgRGVzYz0iaW5pdGlhbCBmb3JtYXRpb24gcHJlc3N1cmUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IksiICAgQWxpYXM9Iua4l+mAj+eOhyIgICAgICAgICBVbml0PSJtRCIgICAgRGVmYXVsdD0iMSIgICAgIE1heD0iMTAwMDAiICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJwZXJtZWFiaWxpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9InBoaSIgQWxpYXM9IuWtlOmameW6piIgICAgICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC4xIiAgIE1heD0iMSIgICAgICBNaW49IjFlLTA1IiAgRGlnaXQ9IjYiICBEZXNjPSJwb3Jvc2l0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQ3RpIiBBbGlhcz0i57u85ZCI5Y6L57yp57O75pWwIiAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwLjAwMSIgTWF4PSIxMCIgICAgIE1pbj0iMWUtMzAiICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InRvdGFsIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQ2YiICBBbGlhcz0i5bKp55+z5Y6L57yp57O75pWwIiAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwLjAwMDEiIE1heD0iMTAiICAgIE1pbj0iMWUtMzAiICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InJvY2sgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTb2kiIEFsaWFzPSLliJ3lp4vlkKvmsrnppbHlkozluqYiIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjgiICAgTWF4PSIxIiAgICAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9ImluaXRpYWwgb2lsIHNhdHVyYXRpb24iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlN3aSIgQWxpYXM9IuWIneWni+WQq+awtOmlseWSjOW6piIgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjAuMiIgICBNYXg9IjEiICAgICAgTWluPSIwIiAgICAgIERpZ2l0PSI2IiAgRGVzYz0iaW5pdGlhbCB3YXRlciBzYXR1cmF0aW9uIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IuS6leWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfWCIgICAgQWxpYXM9IljlnZDmoIciICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAiICAgICBNYXg9IjEwMDAwIiAgTWluPSItMTAwMDAiIERpZ2l0PSI2IiAgRGVzYz0id2VsbCBYIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfWSIgICAgQWxpYXM9IlnlnZDmoIciICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAiICAgICBNYXg9IjEwMDAwIiAgTWluPSItMTAwMDAiIERpZ2l0PSI2IiAgRGVzYz0id2VsbCBZIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfUnciICAgQWxpYXM9IuS6leetkuWNiuW+hCIgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMC4xIiAgIE1heD0iMTAiICAgICBNaW49IjAuMDAxIiAgRGlnaXQ9IjYiICBEZXNjPSJ3ZWxsYm9yZSByYWRpdXMiIC8+CiAgICA8UGFyYUl0ZW0gTmFtZT0iV19Ta2luIiBBbGlhcz0i6KGo55qu57O75pWwIiAgICBVbml0PSIiICAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwIiAgIE1pbj0iLTEwMCIgICBEaWdpdD0iNiIgIERlc2M9InNraW4gZmFjdG9yIiAvPgogICAgPFBhcmFJdGVtIE5hbWU9IldfQyIgICAgQWxpYXM9IuS6leetkuWCqOmbhuezu+aVsCIgVW5pdD0ibTMvTVBhIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAiICAgTWluPSIwIiAgICAgIERpZ2l0PSI2IiAgRGVzYz0id2VsbGJvcmUgc3RvcmFnZSBjb2VmZmljaWVudCIgLz4KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1dlbGxMZW5ndGgiICAgICAgICAgQWxpYXM9IuawtOW5s+autemVv+W6piIgICBVbml0PSJtIiAgICBEZWZhdWx0PSIyMDAiICBNYXg9IjEwMDAwIiBNaW49IjFlLTA1IiBEaWdpdD0iNiIgRGVzYz0iaG9yaXpvbnRhbCB3ZWxsIGxlbmd0aCIgLz4KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0RyYWluQW5nbGUiICAgICAgICAgQWxpYXM9IuaOkuawtOinkuW6piIgICAgIFVuaXQ9Im8iICAgIERlZmF1bHQ9IjAiICAgIE1heD0iMzYwIiAgIE1pbj0iLTM2MCIgIERpZ2l0PSI2IiBEZXNjPSJob3Jpem9udGFsIHdlbGwgZHJhaW4gYW5nbGUiIC8+CiAgICA8UGFyYUl0ZW0gTmFtZT0iV19OdW1iZXJPZkZyYWN0dXJlcyIgIEFsaWFzPSLoo4LnvJ3mlbDph48iICAgICBVbml0PSIiICAgICBEZWZhdWx0PSIxNSIgICBNYXg9IjEwMDAiICBNaW49IjIiICAgICBEaWdpdD0iMCIgRGVzYz0ibnVtYmVyIG9mIGZyYWN0dXJlcyIgLz4KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlSGFsZkxlbmd0aCIgQWxpYXM9Iuijgue8neWNiumVvyIgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjUwIiAgIE1heD0iMTAwMDAiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBoYWxmLWxlbmd0aCIgLz4KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlQW5nbGUiICAgICAgQWxpYXM9Iuijgue8neinkuW6piIgICAgIFVuaXQ9Im8iICAgIERlZmF1bHQ9IjkwIiAgIE1heD0iMzYwIiAgIE1pbj0iLTM2MCIgIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBhbmdsZSIgLz4KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0RmYyIgICAgICAgICAgICAgICAgQWxpYXM9Iuijgue8neWvvOa1geiDveWKmyIgVW5pdD0ibWQubSIgRGVmYXVsdD0iMTAwMCIgTWF4PSIxZSszMCIgTWluPSIwIiAgICAgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGNvbmR1Y3Rpdml0eSIgLz4KICA8L1BhcmFHcm91cD4KDQo8L1Jvb3Q+DQo=
\ No newline at end of file
+PD94bWwgdmVycup_mpac2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSoqKioqKioqKioqKiwzyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCjwhLS0gICAg5pys5paH5qGj55qE55uu55qE5piv5bu656uLV1RBSeaVsOWAvOinoyhOTSnmqKHlnZfnmoTlj4LmlbDlrprkuYkgICAgICAgICAgICAgICAgLS0+DQo8IS0tICAgIOS7heWMheWQq1BFQknmsYLop6PlmajmiYDpnIDnmoTlgqjlsYLjgIHkupXlkozlh6DkvZXlr7nosaHlj4LmlbAgICAgICAgICAgICAgICAgICAtLT4NCjwhLS0gICAgRGF0ZTogMjAyNjA2MTUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCg0KPCEtLQ0KICAgIOWPguaVsOiMg+WbtO+8mlBFQknmsYLop6PlmajmiYDpnIDnmoTlgqjlsYLjgIHkupXlkozlh6DkvZXlr7nosaHlj4LmlbANCiAgICDlr7nlupQgSFhfTldUTV9NT0RFTF9JTlBVVCDnu5PmnoTkvZPlrZfmrrUNCiAgICDpgJrov4cgX3BhcmFIZWxwZXItPmxvYWRQYXJhRGVmaW5lcygpIOWKoOi9ve+8jHNLZXkg5qCH6K+G5Li6IHNfTm1fU2VyaWUNCi0tPg0KDQo8Um9vdD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IuWCqOWxguWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9ImgiICAgQWxpYXM9IuWCqOWxguWOmuW6piIgICAgICAgVW5pdD0ibSIgICAgIERlZmF1bHQ9IjEwIiAgICBNYXg9IjEwMDAwIiAgTWluPSIxZS0wNSIgIERpZ2l0PSI2IiAgRGVzYz0icmVzZXJ2b2lyIHRoaWNrbmVzcyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iUGkiICBBbGlhcz0i5Yid5aeL5Y6L5YqbIiAgICAgICBVbml0PSJNUGEiICAgRGVmYXVsdD0iNDAiICAgIE1heD0iNTAwIiAgICBNaW49IjAuMSIgICAgRGlnaXQ9IjYiICBEZXNjPSJpbml0aWFsIGZvcm1hdGlvbiBwcmVzc3VyZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iSyIgICBBbGlhcz0i5riX6YCP546HIiAgICAgICAgIFVuaXQ9Im1EIiAgICBEZWZhdWx0PSIxIiAgICAgTWF4PSIxMDAwMCIgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9InBlcm1lYWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0icGhpIiBBbGlhcz0i5a2U6ZqZ5bqmIiAgICAgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjEiICAgTWF4PSIxIiAgICAgIE1pbj0iMWUtMDUiICBEaWdpdD0iNiIgIERlc2M9InBvcm9zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJDdGkiIEFsaWFzPSLnu7zlkIjljovnvKnns7vmlbAiICAgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAuMDAxIiBNYXg9IjEwIiAgICAgTWluPSIxZS0zMCIgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0idG90YWwgY29tcHJlc3NpYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJDZiIgIEFsaWFzPSLlsqnnn7PljovnvKnns7vmlbAiICAgVW5pdD0iMS9NUGEiIERlZmF1bHQ9IjAuMDAwMSIgTWF4PSIxMCIgICAgTWluPSIxZS0zMCIgIERpZ2l0PSIxMCIgU2NpZW50aWZpYz0iMSIgRGVzYz0icm9jayBjb21wcmVzc2liaWxpdHkiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlNvaSIgQWxpYXM9IuWIneWni+WQq+ayuemlseWSjOW6piIgVW5pdD0iIiAgICAgIERlZmF1bHQ9IjAuOCIgICBNYXg9IjEiICAgICAgTWluPSIwIiAgICAgIERpZ2l0PSI2IiAgRGVzYz0iaW5pdGlhbCBvaWwgc2F0dXJhdGlvbiIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU3dpIiBBbGlhcz0i5Yid5aeL5ZCr5rC06aWx5ZKM5bqmIiBVbml0PSIiICAgICAgRGVmYXVsdD0iMC4yIiAgIE1heD0iMSIgICAgICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJpbml0aWFsIHdhdGVyIHNhdHVyYXRpb24iIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i5LqV5Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19YIiAgICBBbGlhcz0iWOWdkOaghyIgICAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgICAgIE1heD0iMTAwMDAiICBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiICBEZXNjPSJ3ZWxsIFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19ZIiAgICBBbGlhcz0iWeWdkOaghyIgICAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgICAgIE1heD0iMTAwMDAiICBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiICBEZXNjPSJ3ZWxsIFkgY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19SdyIgICBBbGlhcz0i5LqV562S5Y2K5b6EIiAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwLjEiICAgTWF4PSIxMCIgICAgIE1pbj0iMC4wMDEiICBEaWdpdD0iNiIgIERlc2M9IndlbGxib3JlIHJhZGl1cyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19Ta2luIiBBbGlhcz0i6KGo55qu57O75pWwIiAgICBVbml0PSIiICAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwIiAgIE1pbj0iLTEwMCIgICBEaWdpdD0iNiIgIERlc2M9InNraW4gZmFjdG9yIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0MiICAgIEFsaWFzPSLkupXnrZLlgqjpm4bns7vmlbAiIFVuaXQ9Im0zL01QYSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwIiAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9IndlbGxib3JlIHN0b3JhZ2UgY29lZmZpY2llbnQiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfV2VsbExlbmd0aCIgICAgICAgICBBbGlhcz0i5rC05bmz5q616ZW/5bqmIiAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjIwMCIgIE1heD0iMTAwMDAiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSJob3Jpem9udGFsIHdlbGwgbGVuZ3RoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0RyYWluQW5nbGUiICAgICAgICAgQWxpYXM9IuaOkuawtOinkuW6piIgICAgIFVuaXQ9Im8iICAgIERlZmF1bHQ9IjAiICAgIE1heD0iMzYwIiAgIE1pbj0iLTM2MCIgIERpZ2l0PSI2IiBEZXNjPSJob3Jpem9udGFsIHdlbGwgZHJhaW4gYW5nbGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfTnVtYmVyT2ZGcmFjdHVyZXMiICBBbGlhcz0i6KOC57yd5pWw6YePIiAgICAgVW5pdD0iIiAgICAgRGVmYXVsdD0iMTUiICAgTWF4PSIxMDAwIiAgTWluPSIyIiAgICAgRGlnaXQ9IjAiIERlc2M9Im51bWJlciBvZiBmcmFjdHVyZXMiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRnJhY3R1cmVIYWxmTGVuZ3RoIiBBbGlhcz0i6KOC57yd5Y2K6ZW/IiAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iNTAiICAgTWF4PSIxMDAwMCIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGhhbGYtbGVuZ3RoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlQW5nbGUiICAgICAgQWxpYXM9Iuijgue8neinkuW6piIgICAgIFVuaXQ9Im8iICAgIERlZmF1bHQ9IjkwIiAgIE1heD0iMzYwIiAgIE1pbj0iLTM2MCIgIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBhbmdsZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19EZmMiICAgICAgICAgICAgICAgIEFsaWFzPSLoo4LnvJ3lr7zmtYHog73lipsiIFVuaXQ9Im1kLm0iIERlZmF1bHQ9IjEwMDAiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBjb25kdWN0aXZpdHkiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i54us56uL6KOC57yd5Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9YMCIgQWxpYXM9Iui1t+eCuVgwIiAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgc3RhcnQgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX1kwIiBBbGlhcz0i6LW354K5WTAiICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBzdGFydCBZIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZfWDEiIEFsaWFzPSLnu4jngrlYMSIgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGVuZCBYIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZfWTEiIEFsaWFzPSLnu4jngrlZMSIgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGVuZCBZIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZfRkMiIEFsaWFzPSLlr7zmtYHog73lipsiIFVuaXQ9Im1kLm0iIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgY29uZHVjdGl2aXR5IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IuaWreWxguWPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZUX1gwIiBBbGlhcz0i6LW354K5WDAiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgc3RhcnQgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGVF9ZMCIgQWxpYXM9Iui1t+eCuVkwIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZhdWx0IHN0YXJ0IFkgY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfWDEiIEFsaWFzPSLnu4jngrlYMSIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmYXVsdCBlbmQgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGVF9ZMSIgQWxpYXM9Iue7iOeCuVkxIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZhdWx0IGVuZCBZIGNvb3JkaW5hdGUiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0i55+p5b2i6L6555WM5Y+C5pWwIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlJfWE1pbiIgQWxpYXM9IuW3pui+ueeVjFgiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icmVjdGFuZ2xlIGJvdW5kYXJ5IG1pbmltdW0gWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlJfWU1pbiIgQWxpYXM9IuS4i+i+ueeVjFkiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icmVjdGFuZ2xlIGJvdW5kYXJ5IG1pbmltdW0gWSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlJfWE1heCIgQWxpYXM9IuWPs+i+ueeVjFgiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icmVjdGFuZ2xlIGJvdW5kYXJ5IG1heGltdW0gWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlJfWU1heCIgQWxpYXM9IuS4iui+ueeVjFkiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icmVjdGFuZ2xlIGJvdW5kYXJ5IG1heGltdW0gWSIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSLlnIblvaLovrnnlYzlj4LmlbAiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCQ19DZW50ZXJYIiBBbGlhcz0i5ZyG5b+DWCIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJjaXJjbGUgYm91bmRhcnkgY2VudGVyIFgiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkJDX0NlbnRlclkiIEFsaWFzPSLlnIblv4NZIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImNpcmNsZSBib3VuZGFyeSBjZW50ZXIgWSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQkNfUmFkaXVzIiAgQWxpYXM9IuWNiuW+hCIgIFVuaXQ9Im0iIERlZmF1bHQ9IjEiIE1heD0iMTAwMDAiIE1pbj0iMWUtMDUiICBEaWdpdD0iNiIgRGVzYz0iY2lyY2xlIGJvdW5kYXJ5IHJhZGl1cyIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSLlpJrovrnlvaLovrnnlYzngrnlj4LmlbAiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCUF9YIiBBbGlhcz0iWOWdkOaghyIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJwb2x5Z29uIGJvdW5kYXJ5IHZlcnRleCBYIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCUF9ZIiBBbGlhcz0iWeWdkOaghyIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJwb2x5Z29uIGJvdW5kYXJ5IHZlcnRleCBZIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IuWMuuWfn+WPguaVsCI+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJfTGVha2FnZSIgQWxpYXM9IuazhOmcsuezu+aVsCIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiIERpZ2l0PSI2IiBEZXNjPSJyZWdpb24gbGVha2FnZSBjb2VmZmljaWVudCIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSLmoIforrDljLrln5/lj4LmlbAiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSTV9Db21XIiAgICAgICBBbGlhcz0i5YKo6IO95q+UIiBVbml0PSIiIERlZmF1bHQ9IjEiIE1heD0iMSIgICAgTWluPSIwIiAgICAgRGlnaXQ9IjYiIERlc2M9InN0b3JhZ2UgcmF0aW8iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJNX0NvbUtyIiAgICAgIEFsaWFzPSLmtYHluqbmr5QiIFVuaXQ9IiIgRGVmYXVsdD0iMSIgTWF4PSIxMDAwIiBNaW49IjAuMDAxIiBEaWdpdD0iNiIgRGVzYz0ibW9iaWxpdHkgcmF0aW8iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJNX05ldFRvR3Jvc3MiIEFsaWFzPSLlh4Dmr5vmr5QiIFVuaXQ9IiIgRGVmYXVsdD0iMSIgTWF4PSIxIiAgICBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0ibmV0LXRvLWdyb3NzIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KPC9Sb290Pg0K
\ No newline at end of file
diff --git a/Bin/Config/Common/ModelParaDefinesNM_en.dat b/Bin/Config/Common/ModelParaDefinesNM_en.dat
index abfe56f..ac661fa 100644
--- a/Bin/Config/Common/ModelParaDefinesNM_en.dat
+++ b/Bin/Config/Common/ModelParaDefinesNM_en.dat
@@ -1 +1 @@
-77u/PD94bWwgcup_mpadmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSoqKioqKioqKiwzyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCjwhLS0gICAgVGhpcyBmaWxlIGRlZmluZXMgcGFyYW1ldGVycyBmb3IgdGhlIFdUQUkgTnVtZXJpY2FsIChOTSkgICAgLS0+DQo8IS0tICAgIG1vZHVsZS4gT25seSBwYXJhbWV0ZXJzIHJlcXVpcmVkIGJ5IHRoZSBQRUJJIHNvbHZlciBhcmUgICAgICAtLT4KPCEtLSAgICBpbmNsdWRlZC4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLS0+CjwhLS0gICAgRGF0ZTogMjAyNjA2MTUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCg0KPCEtLQ0KICAgIFBhcmFtZXRlciBzY29wZTogcmVzZXJ2b2lyIGFuZCB3ZWxsIHBhcmFtZXRlcnMgcmVxdWlyZWQgYnkgdGhlIFBFQkkgc29sdmVyCiAgICBDb3JyZXNwb25kcyB0byBIWF9OV1RNX01PREVMX0lOUFVUIHN0cnVjdCBmaWVsZHMKICAgIExvYWRlZCB2aWEgX3BhcmFIZWxwZXItPmxvYWRQYXJhRGVmaW5lcygpLCBzS2V5ID0gc19ObV9TZXJpZQ0KLS0+DQoNCjxSb290Pg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iUmVzZXJ2b2lyIFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJoIiAgIEFsaWFzPSJSZXNlcnZvaXIgVGhpY2tuZXNzIiAgICAgICAgIFVuaXQ9Im0iICAgICBEZWZhdWx0PSIxMCIgICAgTWF4PSIxMDAwMCIgIE1pbj0iMWUtMDUiICBEaWdpdD0iMyIgIERlc2M9InJlc2Vydm9pciB0aGlja25lc3MiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlBpIiAgQWxpYXM9IkluaXRpYWwgUHJlc3N1cmUiICAgICAgICAgICAgVW5pdD0iTVBhIiAgIERlZmF1bHQ9IjQwIiAgICBNYXg9IjUwMCIgICAgTWluPSIwLjEiICAgIERpZ2l0PSI1IiAgRGVzYz0iaW5pdGlhbCBmb3JtYXRpb24gcHJlc3N1cmUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IksiICAgQWxpYXM9IlBlcm1lYWJpbGl0eSIgICAgICAgICAgICAgICAgVW5pdD0ibUQiICAgIERlZmF1bHQ9IjEiICAgICBNYXg9IjEwMDAwIiAgTWluPSIwIiAgICAgIERpZ2l0PSI2IiAgRGVzYz0icGVybWVhYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJwaGkiIEFsaWFzPSJQb3Jvc2l0eSIgICAgICAgICAgICAgICAgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjEiICAgTWF4PSIxIiAgICAgIE1pbj0iMWUtMDUiICBEaWdpdD0iNCIgIERlc2M9InBvcm9zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJDdGkiIEFsaWFzPSJUb3RhbCBDb21wcmVzc2liaWxpdHkiICAgICAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwLjAwMSIgTWF4PSIxMCIgICAgIE1pbj0iMWUtMzAiICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InRvdGFsIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQ2YiICBBbGlhcz0iUm9jayBDb21wcmVzc2liaWxpdHkiICAgICAgICBVbml0PSIxL01QYSIgRGVmYXVsdD0iMC4wMDAxIiBNYXg9IjEwIiAgICBNaW49IjFlLTMwIiAgRGlnaXQ9IjEwIiBTY2llbnRpZmljPSIxIiBEZXNjPSJyb2NrIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU29pIiBBbGlhcz0iSW5pdGlhbCBPaWwgU2F0dXJhdGlvbiIgICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC44IiAgIE1heD0iMSIgICAgICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJpbml0aWFsIG9pbCBzYXR1cmF0aW9uIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTd2kiIEFsaWFzPSJJbml0aWFsIFdhdGVyIFNhdHVyYXRpb24iICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjIiICAgTWF4PSIxIiAgICAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9ImluaXRpYWwgd2F0ZXIgc2F0dXJhdGlvbiIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSJXZWxsIFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1giICAgIEFsaWFzPSJYIENvb3JkaW5hdGUiICAgICAgICAgICAgVW5pdD0ibSIgICAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwMCIgIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgIERlc2M9IndlbGwgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1kiICAgIEFsaWFzPSJZIENvb3JkaW5hdGUiICAgICAgICAgICAgVW5pdD0ibSIgICAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwMCIgIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgIERlc2M9IndlbGwgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1J3IiAgIEFsaWFzPSJXZWxsYm9yZSBSYWRpdXMiICAgICAgICAgVW5pdD0ibSIgICAgICBEZWZhdWx0PSIwLjEiICAgTWF4PSIxMCIgICAgIE1pbj0iMC4wMDEiICBEaWdpdD0iNiIgIERlc2M9IndlbGxib3JlIHJhZGl1cyIgLz4KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1NraW4iIEFsaWFzPSJTa2luIEZhY3RvciIgICAgICAgICAgICAgVW5pdD0iIiAgICAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwIiAgIE1pbj0iLTEwMCIgICBEaWdpdD0iNiIgIERlc2M9InNraW4gZmFjdG9yIiAvPgogICAgPFBhcmFJdGVtIE5hbWU9IldfQyIgICAgQWxpYXM9IldlbGxib3JlIFN0b3JhZ2UgQ29lZmYiICBVbml0PSJtMy9NUGEiIERlZmF1bHQ9IjAiICAgICBNYXg9IjEwMDAiICAgTWluPSIwIiAgICAgIERpZ2l0PSI2IiAgRGVzYz0id2VsbGJvcmUgc3RvcmFnZSBjb2VmZmljaWVudCIgLz4KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1dlbGxMZW5ndGgiICAgICAgICAgQWxpYXM9Ikhvcml6b250YWwgV2VsbCBMZW5ndGgiIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjIwMCIgIE1heD0iMTAwMDAiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSJob3Jpem9udGFsIHdlbGwgbGVuZ3RoIiAvPgogICAgPFBhcmFJdGVtIE5hbWU9IldfRHJhaW5BbmdsZSIgICAgICAgICBBbGlhcz0iRHJhaW4gQW5nbGUiICAgICAgICAgICAgVW5pdD0ibyIgICAgRGVmYXVsdD0iMCIgICAgTWF4PSIzNjAiICAgTWluPSItMzYwIiAgRGlnaXQ9IjYiIERlc2M9Imhvcml6b250YWwgd2VsbCBkcmFpbiBhbmdsZSIgLz4KICAgIDxQYXJhSXRlbSBOYW1lPSJXX051bWJlck9mRnJhY3R1cmVzIiAgQWxpYXM9Ik51bWJlciBvZiBGcmFjdHVyZXMiICAgIFVuaXQ9IiIgICAgIERlZmF1bHQ9IjE1IiAgIE1heD0iMTAwMCIgIE1pbj0iMiIgICAgIERpZ2l0PSIwIiBEZXNjPSJudW1iZXIgb2YgZnJhY3R1cmVzIiAvPgogICAgPFBhcmFJdGVtIE5hbWU9IldfRnJhY3R1cmVIYWxmTGVuZ3RoIiBBbGlhcz0iRnJhY3R1cmUgSGFsZi1MZW5ndGgiICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iNTAiICAgTWF4PSIxMDAwMCIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGhhbGYtbGVuZ3RoIiAvPgogICAgPFBhcmFJdGVtIE5hbWU9IldfRnJhY3R1cmVBbmdsZSIgICAgICBBbGlhcz0iRnJhY3R1cmUgQW5nbGUiICAgICAgICAgVW5pdD0ibyIgICAgRGVmYXVsdD0iOTAiICAgTWF4PSIzNjAiICAgTWluPSItMzYwIiAgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGFuZ2xlIiAvPgogICAgPFBhcmFJdGVtIE5hbWU9IldfRGZjIiAgICAgICAgICAgICAgICBBbGlhcz0iRnJhY3R1cmUgQ29uZHVjdGl2aXR5IiAgVW5pdD0ibWQubSIgRGVmYXVsdD0iMTAwMCIgTWF4PSIxZSszMCIgTWluPSIwIiAgICAgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGNvbmR1Y3Rpdml0eSIgLz4KICA8L1BhcmFHcm91cD4KDQo8L1Jvb3Q+DQo=
\ No newline at end of file
+PD94bWwgdmVycup_mpac2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPCEtLSoqKioqKioqKioqKiwzyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiotLT4NCjwhLS0gICAgVGhpcyBmaWxlIGRlZmluZXMgcGFyYW1ldGVycyBmb3IgdGhlIFdUQUkgTnVtZXJpY2FsIChOTSkgICAgLS0+DQo8IS0tICAgIG1vZHVsZS4gT25seSByZXNlcnZvaXIsIHdlbGwsIGFuZCBnZW9tZXRyeSBwYXJhbWV0ZXJzICAgICAgICAtLT4NCjwhLS0gICAgcmVxdWlyZWQgYnkgdGhlIFBFQkkgc29sdmVyIGFyZSBpbmNsdWRlZC4gICAgICAgICAgICAgICAgICAgIC0tPg0KPCEtLSAgICBEYXRlOiAyMDI2MDYxNSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLS0+DQo8IS0tKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi0tPg0KDQo8IS0tDQogICAgUGFyYW1ldGVyIHNjb3BlOiByZXNlcnZvaXIsIHdlbGwsIGFuZCBnZW9tZXRyeSBwYXJhbWV0ZXJzIHJlcXVpcmVkIGJ5IHRoZSBQRUJJIHNvbHZlcg0KICAgIENvcnJlc3BvbmRzIHRvIEhYX05XVE1fTU9ERUxfSU5QVVQgc3RydWN0IGZpZWxkcw0KICAgIExvYWRlZCB2aWEgX3BhcmFIZWxwZXItPmxvYWRQYXJhRGVmaW5lcygpLCBzS2V5ID0gc19ObV9TZXJpZQ0KLS0+DQoNCjxSb290Pg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iUmVzZXJ2b2lyIFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJoIiAgIEFsaWFzPSJSZXNlcnZvaXIgVGhpY2tuZXNzIiAgICAgICAgIFVuaXQ9Im0iICAgICBEZWZhdWx0PSIxMCIgICAgTWF4PSIxMDAwMCIgIE1pbj0iMWUtMDUiICBEaWdpdD0iMyIgIERlc2M9InJlc2Vydm9pciB0aGlja25lc3MiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlBpIiAgQWxpYXM9IkluaXRpYWwgUHJlc3N1cmUiICAgICAgICAgICAgVW5pdD0iTVBhIiAgIERlZmF1bHQ9IjQwIiAgICBNYXg9IjUwMCIgICAgTWluPSIwLjEiICAgIERpZ2l0PSI1IiAgRGVzYz0iaW5pdGlhbCBmb3JtYXRpb24gcHJlc3N1cmUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IksiICAgQWxpYXM9IlBlcm1lYWJpbGl0eSIgICAgICAgICAgICAgICAgVW5pdD0ibUQiICAgIERlZmF1bHQ9IjEiICAgICBNYXg9IjEwMDAwIiAgTWluPSIwIiAgICAgIERpZ2l0PSI2IiAgRGVzYz0icGVybWVhYmlsaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJwaGkiIEFsaWFzPSJQb3Jvc2l0eSIgICAgICAgICAgICAgICAgICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjEiICAgTWF4PSIxIiAgICAgIE1pbj0iMWUtMDUiICBEaWdpdD0iNCIgIERlc2M9InBvcm9zaXR5IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJDdGkiIEFsaWFzPSJUb3RhbCBDb21wcmVzc2liaWxpdHkiICAgICAgIFVuaXQ9IjEvTVBhIiBEZWZhdWx0PSIwLjAwMSIgTWF4PSIxMCIgICAgIE1pbj0iMWUtMzAiICBEaWdpdD0iMTAiIFNjaWVudGlmaWM9IjEiIERlc2M9InRvdGFsIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQ2YiICBBbGlhcz0iUm9jayBDb21wcmVzc2liaWxpdHkiICAgICAgICBVbml0PSIxL01QYSIgRGVmYXVsdD0iMC4wMDAxIiBNYXg9IjEwIiAgICBNaW49IjFlLTMwIiAgRGlnaXQ9IjEwIiBTY2llbnRpZmljPSIxIiBEZXNjPSJyb2NrIGNvbXByZXNzaWJpbGl0eSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iU29pIiBBbGlhcz0iSW5pdGlhbCBPaWwgU2F0dXJhdGlvbiIgICAgICBVbml0PSIiICAgICAgRGVmYXVsdD0iMC44IiAgIE1heD0iMSIgICAgICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJpbml0aWFsIG9pbCBzYXR1cmF0aW9uIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJTd2kiIEFsaWFzPSJJbml0aWFsIFdhdGVyIFNhdHVyYXRpb24iICAgIFVuaXQ9IiIgICAgICBEZWZhdWx0PSIwLjIiICAgTWF4PSIxIiAgICAgIE1pbj0iMCIgICAgICBEaWdpdD0iNiIgIERlc2M9ImluaXRpYWwgd2F0ZXIgc2F0dXJhdGlvbiIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSJXZWxsIFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1giICAgIEFsaWFzPSJYIENvb3JkaW5hdGUiICAgICAgICAgICAgVW5pdD0ibSIgICAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwMCIgIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgIERlc2M9IndlbGwgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1kiICAgIEFsaWFzPSJZIENvb3JkaW5hdGUiICAgICAgICAgICAgVW5pdD0ibSIgICAgICBEZWZhdWx0PSIwIiAgICAgTWF4PSIxMDAwMCIgIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgIERlc2M9IndlbGwgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1J3IiAgIEFsaWFzPSJXZWxsYm9yZSBSYWRpdXMiICAgICAgICAgVW5pdD0ibSIgICAgICBEZWZhdWx0PSIwLjEiICAgTWF4PSIxMCIgICAgIE1pbj0iMC4wMDEiICBEaWdpdD0iNiIgIERlc2M9IndlbGxib3JlIHJhZGl1cyIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19Ta2luIiBBbGlhcz0iU2tpbiBGYWN0b3IiICAgICAgICAgICAgIFVuaXQ9IiIgICAgICAgRGVmYXVsdD0iMCIgICAgIE1heD0iMTAwMCIgICBNaW49Ii0xMDAiICAgRGlnaXQ9IjYiICBEZXNjPSJza2luIGZhY3RvciIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19DIiAgICBBbGlhcz0iV2VsbGJvcmUgU3RvcmFnZSBDb2VmZiIgIFVuaXQ9Im0zL01QYSIgRGVmYXVsdD0iMCIgICAgIE1heD0iMTAwMCIgICBNaW49IjAiICAgICAgRGlnaXQ9IjYiICBEZXNjPSJ3ZWxsYm9yZSBzdG9yYWdlIGNvZWZmaWNpZW50IiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX1dlbGxMZW5ndGgiICAgICAgICAgQWxpYXM9Ikhvcml6b250YWwgV2VsbCBMZW5ndGgiIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjIwMCIgIE1heD0iMTAwMDAiIE1pbj0iMWUtMDUiIERpZ2l0PSI2IiBEZXNjPSJob3Jpem9udGFsIHdlbGwgbGVuZ3RoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0RyYWluQW5nbGUiICAgICAgICAgQWxpYXM9IkRyYWluIEFuZ2xlIiAgICAgICAgICAgIFVuaXQ9Im8iICAgIERlZmF1bHQ9IjAiICAgIE1heD0iMzYwIiAgIE1pbj0iLTM2MCIgIERpZ2l0PSI2IiBEZXNjPSJob3Jpem9udGFsIHdlbGwgZHJhaW4gYW5nbGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfTnVtYmVyT2ZGcmFjdHVyZXMiICBBbGlhcz0iTnVtYmVyIG9mIEZyYWN0dXJlcyIgICAgVW5pdD0iIiAgICAgRGVmYXVsdD0iMTUiICAgTWF4PSIxMDAwIiAgTWluPSIyIiAgICAgRGlnaXQ9IjAiIERlc2M9Im51bWJlciBvZiBmcmFjdHVyZXMiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IldfRnJhY3R1cmVIYWxmTGVuZ3RoIiBBbGlhcz0iRnJhY3R1cmUgSGFsZi1MZW5ndGgiICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iNTAiICAgTWF4PSIxMDAwMCIgTWluPSIxZS0wNSIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGhhbGYtbGVuZ3RoIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJXX0ZyYWN0dXJlQW5nbGUiICAgICAgQWxpYXM9IkZyYWN0dXJlIEFuZ2xlIiAgICAgICAgIFVuaXQ9Im8iICAgIERlZmF1bHQ9IjkwIiAgIE1heD0iMzYwIiAgIE1pbj0iLTM2MCIgIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBhbmdsZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iV19EZmMiICAgICAgICAgICAgICAgIEFsaWFzPSJGcmFjdHVyZSBDb25kdWN0aXZpdHkiICBVbml0PSJtZC5tIiBEZWZhdWx0PSIxMDAwIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgY29uZHVjdGl2aXR5IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IkluZGVwZW5kZW50IEZyYWN0dXJlIFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX1gwIiBBbGlhcz0iU3RhcnQgWDAiICAgICAgICAgICAgICBVbml0PSJtIiAgICBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIHN0YXJ0IFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9ZMCIgQWxpYXM9IlN0YXJ0IFkwIiAgICAgICAgICAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBzdGFydCBZIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZfWDEiIEFsaWFzPSJFbmQgWDEiICAgICAgICAgICAgICAgIFVuaXQ9Im0iICAgIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZnJhY3R1cmUgZW5kIFggY29vcmRpbmF0ZSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRl9ZMSIgQWxpYXM9IkVuZCBZMSIgICAgICAgICAgICAgICAgVW5pdD0ibSIgICAgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmcmFjdHVyZSBlbmQgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGX0ZDIiBBbGlhcz0iRnJhY3R1cmUgQ29uZHVjdGl2aXR5IiBVbml0PSJtZC5tIiBEZWZhdWx0PSIxIiBNYXg9IjFlKzMwIiBNaW49IjAiICAgICAgRGlnaXQ9IjYiIERlc2M9ImZyYWN0dXJlIGNvbmR1Y3Rpdml0eSIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSJGYXVsdCBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iRlRfWDAiIEFsaWFzPSJTdGFydCBYMCIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmYXVsdCBzdGFydCBYIGNvb3JkaW5hdGUiIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IkZUX1kwIiBBbGlhcz0iU3RhcnQgWTAiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iZmF1bHQgc3RhcnQgWSBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGVF9YMSIgQWxpYXM9IkVuZCBYMSIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmYXVsdCBlbmQgWCBjb29yZGluYXRlIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJGVF9ZMSIgQWxpYXM9IkVuZCBZMSIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJmYXVsdCBlbmQgWSBjb29yZGluYXRlIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IlJlY3RhbmdsZSBCb3VuZGFyeSBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlJfWE1pbiIgQWxpYXM9IkxlZnQgQm91bmRhcnkgWCIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJyZWN0YW5nbGUgYm91bmRhcnkgbWluaW11bSBYIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCUl9ZTWluIiBBbGlhcz0iQm90dG9tIEJvdW5kYXJ5IFkiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icmVjdGFuZ2xlIGJvdW5kYXJ5IG1pbmltdW0gWSIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlJfWE1heCIgQWxpYXM9IlJpZ2h0IEJvdW5kYXJ5IFgiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0icmVjdGFuZ2xlIGJvdW5kYXJ5IG1heGltdW0gWCIgLz4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlJfWU1heCIgQWxpYXM9IlRvcCBCb3VuZGFyeSBZIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InJlY3RhbmdsZSBib3VuZGFyeSBtYXhpbXVtIFkiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iQ2lyY2xlIEJvdW5kYXJ5IFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCQ19DZW50ZXJYIiBBbGlhcz0iQ2VudGVyIFgiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iY2lyY2xlIGJvdW5kYXJ5IGNlbnRlciBYIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCQ19DZW50ZXJZIiBBbGlhcz0iQ2VudGVyIFkiIFVuaXQ9Im0iIERlZmF1bHQ9IjAiIE1heD0iMTAwMDAiIE1pbj0iLTEwMDAwIiBEaWdpdD0iNiIgRGVzYz0iY2lyY2xlIGJvdW5kYXJ5IGNlbnRlciBZIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCQ19SYWRpdXMiICBBbGlhcz0iUmFkaXVzIiAgIFVuaXQ9Im0iIERlZmF1bHQ9IjEiIE1heD0iMTAwMDAiIE1pbj0iMWUtMDUiICBEaWdpdD0iNiIgRGVzYz0iY2lyY2xlIGJvdW5kYXJ5IHJhZGl1cyIgLz4NCiAgPC9QYXJhR3JvdXA+DQoNCiAgPFBhcmFHcm91cCBOYW1lPSIiIEFsaWFzPSJQb2x5Z29uIEJvdW5kYXJ5IFZlcnRleCBQYXJhbWV0ZXJzIj4NCiAgICA8UGFyYUl0ZW0gTmFtZT0iQlBfWCIgQWxpYXM9IlggQ29vcmRpbmF0ZSIgVW5pdD0ibSIgRGVmYXVsdD0iMCIgTWF4PSIxMDAwMCIgTWluPSItMTAwMDAiIERpZ2l0PSI2IiBEZXNjPSJwb2x5Z29uIGJvdW5kYXJ5IHZlcnRleCBYIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJCUF9ZIiBBbGlhcz0iWSBDb29yZGluYXRlIiBVbml0PSJtIiBEZWZhdWx0PSIwIiBNYXg9IjEwMDAwIiBNaW49Ii0xMDAwMCIgRGlnaXQ9IjYiIERlc2M9InBvbHlnb24gYm91bmRhcnkgdmVydGV4IFkiIC8+DQogIDwvUGFyYUdyb3VwPg0KDQogIDxQYXJhR3JvdXAgTmFtZT0iIiBBbGlhcz0iUmVnaW9uIFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSX0xlYWthZ2UiIEFsaWFzPSJMZWFrYWdlIENvZWZmaWNpZW50IiBVbml0PSIiIERlZmF1bHQ9IjEiIE1heD0iMWUrMzAiIE1pbj0iMCIgRGlnaXQ9IjYiIERlc2M9InJlZ2lvbiBsZWFrYWdlIGNvZWZmaWNpZW50IiAvPg0KICA8L1BhcmFHcm91cD4NCg0KICA8UGFyYUdyb3VwIE5hbWU9IiIgQWxpYXM9IlJlZ2lvbiBNYXJrIFBhcmFtZXRlcnMiPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSTV9Db21XIiAgICAgICBBbGlhcz0iU3RvcmFnZSBSYXRpbyIgVW5pdD0iIiBEZWZhdWx0PSIxIiBNYXg9IjEiICAgIE1pbj0iMCIgICAgIERpZ2l0PSI2IiBEZXNjPSJzdG9yYWdlIHJhdGlvIiAvPg0KICAgIDxQYXJhSXRlbSBOYW1lPSJSTV9Db21LciIgICAgICBBbGlhcz0iTW9iaWxpdHkgUmF0aW8iIFVuaXQ9IiIgRGVmYXVsdD0iMSIgTWF4PSIxMDAwIiBNaW49IjAuMDAxIiBEaWdpdD0iNiIgRGVzYz0ibW9iaWxpdHkgcmF0aW8iIC8+DQogICAgPFBhcmFJdGVtIE5hbWU9IlJNX05ldFRvR3Jvc3MiIEFsaWFzPSJOZXQtdG8tR3Jvc3MiIFVuaXQ9IiIgRGVmYXVsdD0iMSIgTWF4PSIxIiAgICBNaW49IjAiICAgICBEaWdpdD0iNiIgRGVzYz0ibmV0LXRvLWdyb3NzIiAvPg0KICA8L1BhcmFHcm91cD4NCg0KPC9Sb290Pg0K
\ No newline at end of file
diff --git a/Bin/XmlFiles/ModelParaDefinesNM_cn.xml b/Bin/XmlFiles/ModelParaDefinesNM_cn.xml
index dd96fcf..8b1445b 100644
--- a/Bin/XmlFiles/ModelParaDefinesNM_cn.xml
+++ b/Bin/XmlFiles/ModelParaDefinesNM_cn.xml
@@ -1,13 +1,13 @@
-
+
-
+
@@ -39,4 +39,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Bin/XmlFiles/ModelParaDefinesNM_en.xml b/Bin/XmlFiles/ModelParaDefinesNM_en.xml
index 9bfea9a..10dc60e 100644
--- a/Bin/XmlFiles/ModelParaDefinesNM_en.xml
+++ b/Bin/XmlFiles/ModelParaDefinesNM_en.xml
@@ -1,14 +1,14 @@
-
+
-
-
+
+
@@ -40,4 +40,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Include/nmNum/nmData/nmDataAnalyzeManager.h b/Include/nmNum/nmData/nmDataAnalyzeManager.h
index 76192df..fc40196 100644
--- a/Include/nmNum/nmData/nmDataAnalyzeManager.h
+++ b/Include/nmNum/nmData/nmDataAnalyzeManager.h
@@ -1,4 +1,4 @@
-#ifndef NMDATAANALYZEMANAGER_H
+#ifndef NMDATAANALYZEMANAGER_H
#define NMDATAANALYZEMANAGER_H
#include
@@ -353,6 +353,10 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin
// 获取当前查看井
nmDataWellBase* getCurWellData();
void notifyDataChanged();
+ /// @brief 对象新增或删除后刷新参数面板,并通知网格更新
+ void notifyGeometryListChanged();
+ /// @brief 仅刷新参数面板中的对象名称,避免改名触发网格重建
+ void notifyParameterObjectNameChanged();
/**
* @brief 设置显示设置信息。
@@ -551,6 +555,8 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin
/// @note wellCode + "_W_XX" 作为注册名,使双向绑定链路适用于井参数
/// @note 增量同步:自动清理已删除井的注册,注册新增井的参数
void syncWellAttrs();
+ /// @brief 按“对象编码 + XML 参数名”注册几何对象参数
+ void syncGeometryAttrs();
signals:
void dataChanged();
@@ -558,6 +564,8 @@ class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin
void sigWellAdded(QString wellCode, QString wellName, QStringList baseParas);
/// @brief 井删除信号(removeWell 发出)
void sigWellRemoved(QString wellCode, QString wellName);
+ /// @brief 参数面板中的对象列表或对象名称发生变化
+ void sigGeometryListChanged();
private:
// 存储井的数据
diff --git a/Include/nmNum/nmData/nmDataFault.h b/Include/nmNum/nmData/nmDataFault.h
index a2176fd..b09bceb 100644
--- a/Include/nmNum/nmData/nmDataFault.h
+++ b/Include/nmNum/nmData/nmDataFault.h
@@ -41,10 +41,35 @@ public:
QVector getFaultPoints() const;
void setFaultPoints(const QVector& vecPts);
+ nmDataAttribute& getStartX();
+ nmDataAttribute& getStartY();
+ nmDataAttribute& getEndX();
+ nmDataAttribute& getEndY();
+
bool getPlotVisible() const;
void setPlotVisible(const bool newState);
+ // 批量赋值后手动通知关联视图刷新。
+ void notifyDataChanged();
+
+signals:
+ // 参数面板修改数据后,通知 Binder 刷新图元和左侧属性面板。
+ void sigFaultDataChanged();
+
+private slots:
+ void onEndPointAttributeChanged();
private:
+ void connectAttributeSignals();
+ void syncEndPointAttributes();
+
+ // m_vecPts 首尾点的面板绑定属性,不单独参与序列化。
+ nmDataAttribute m_startX;
+ nmDataAttribute m_startY;
+ nmDataAttribute m_endX;
+ nmDataAttribute m_endY;
+ // 防止“点集 -> 属性 -> 点集”递归同步。
+ bool m_bSyncingEndPoints;
+
QString m_sFaultName; // 断层名称
QVector m_vecPts; // 断层位置信息
nmDataAttribute m_faultFlowModel; // 断层流动模型
diff --git a/Include/nmNum/nmData/nmDataFracture.h b/Include/nmNum/nmData/nmDataFracture.h
index ed40e16..d251f99 100644
--- a/Include/nmNum/nmData/nmDataFracture.h
+++ b/Include/nmNum/nmData/nmDataFracture.h
@@ -32,6 +32,11 @@ public:
QVector getFracturePoints() const;
void setFracturePoints(const QVector& vecPts);
+ nmDataAttribute& getStartX();
+ nmDataAttribute& getStartY();
+ nmDataAttribute& getEndX();
+ nmDataAttribute& getEndY();
+
// Getter and Setter for m_fractureFlowModel
nmDataAttribute& getFractureFlowModel();
void setFractureFlowModel(const nmDataAttribute& fractureFlowModel);
@@ -49,8 +54,28 @@ public:
bool getPlotVisible() const;
void setPlotVisible(const bool newState);
+ // 批量赋值后手动通知关联视图刷新。
+ void notifyDataChanged();
+
+signals:
+ // 参数面板修改数据后,通知 Binder 刷新图元和左侧属性面板。
+ void sigFractureDataChanged();
+
+private slots:
+ void onEndPointAttributeChanged();
private:
+ void connectAttributeSignals();
+ void syncEndPointAttributes();
+
+ // m_vecPts 首尾点的面板绑定属性,不单独参与序列化。
+ nmDataAttribute m_startX;
+ nmDataAttribute m_startY;
+ nmDataAttribute m_endX;
+ nmDataAttribute m_endY;
+ // 防止“点集 -> 属性 -> 点集”递归同步。
+ bool m_bSyncingEndPoints;
+
QString m_sFractureName; // 裂缝名称
QVector m_vecPts; // 裂缝位置信息
nmDataAttribute m_fractureFlowModel; // 裂缝流动类型
diff --git a/Include/nmNum/nmData/nmDataOutline.h b/Include/nmNum/nmData/nmDataOutline.h
index 718d664..bf90316 100644
--- a/Include/nmNum/nmData/nmDataOutline.h
+++ b/Include/nmNum/nmData/nmDataOutline.h
@@ -6,6 +6,7 @@
#include
#include "nmDefines.h"
+#include "nmDataAttribute.h"
#include "nmDataBase.h"
@@ -29,6 +30,18 @@ class NM_DATA_EXPORT nmDataOutline : public nmDataBase {
QVector getOutlinePoints();
void setOutlinePoints(const QVector& vecPts);
+ int getOutlinePointCount() const;
+ nmDataAttribute* getPointXAttribute(int nIndex) const;
+ nmDataAttribute* getPointYAttribute(int nIndex) const;
+
+ nmDataAttribute& getLeftAttribute();
+ nmDataAttribute& getRightAttribute();
+ nmDataAttribute& getTopAttribute();
+ nmDataAttribute& getBottomAttribute();
+ nmDataAttribute& getCenterXAttribute();
+ nmDataAttribute& getCenterYAttribute();
+ nmDataAttribute& getRadiusAttribute();
+
QVector getFlowTypeList() const;
void setFlowTypeList(const QVector& vecFlowTypeList);
@@ -56,7 +69,36 @@ class NM_DATA_EXPORT nmDataOutline : public nmDataBase {
bool hasVisualProps() const;
void setVisualPropsValid(bool bValid);
+ signals:
+ // 参数面板修改数据后,通知 Binder 刷新图元。
+ void sigOutlineDataChanged();
+
+ private slots:
+ void onGeometryAttributeChanged();
+
private:
+ void initGeometryAttributes();
+ void clearPointAttributes();
+ void syncGeometryAttributes();
+ void syncPointAttributes();
+ void syncRectAttributes();
+ void syncRoundAttributes();
+ void updateRectPointsFromAttributes();
+ void updateRoundPointsFromAttributes();
+
+ // m_vecPts 及固定几何量的面板绑定属性,不单独参与序列化。
+ QVector m_vPointXAttributes;
+ QVector m_vPointYAttributes;
+ nmDataAttribute m_left;
+ nmDataAttribute m_right;
+ nmDataAttribute m_top;
+ nmDataAttribute m_bottom;
+ nmDataAttribute m_centerX;
+ nmDataAttribute m_centerY;
+ nmDataAttribute m_radius;
+ // 防止“点集 -> 属性 -> 点集”递归同步。
+ bool m_bSyncingGeometryAttributes;
+
QString m_sName;// 边界名称
QVector m_vecPts; // 边界点的数据;
QVector m_vFlowTypeList; //边界压力类型
diff --git a/Include/nmNum/nmData/nmDataRegion.h b/Include/nmNum/nmData/nmDataRegion.h
index 69144d7..6b345ef 100644
--- a/Include/nmNum/nmData/nmDataRegion.h
+++ b/Include/nmNum/nmData/nmDataRegion.h
@@ -51,8 +51,16 @@ public:
void setPenWidth(double dWidth);
QColor getBackgrdColor() const;
void setBackgrdColor(const QColor& clr);
+ // 批量赋值后手动通知关联视图刷新。
+ void notifyDataChanged();
+
+signals:
+ // 参数面板修改数据后,通知 Binder 刷新图元和左侧属性面板。
+ void sigRegionDataChanged();
private:
+ void connectAttributeSignals();
+
QString m_sRegionName; // 复合区名称
QVector m_vecPts; // 复合区位置信息
nmDataAttribute m_regionFlowModel; // 复合区流动类型
diff --git a/Include/nmNum/nmData/nmDataRegionMark.h b/Include/nmNum/nmData/nmDataRegionMark.h
index cd8464a..9dbbe34 100644
--- a/Include/nmNum/nmData/nmDataRegionMark.h
+++ b/Include/nmNum/nmData/nmDataRegionMark.h
@@ -49,8 +49,16 @@ public:
bool getPlotVisible() const;
void setPlotVisible(const bool newState);
+ // 批量赋值后手动通知关联视图刷新。
+ void notifyDataChanged();
+
+signals:
+ // 参数面板修改数据后,通知 Binder 刷新图元和左侧属性面板。
+ void sigRegionMarkDataChanged();
private:
+ void connectAttributeSignals();
+
QString m_sRegionMarkName;
bool m_bSelectRegion;
QPointF m_ptPos; // 当前区域标记所在的位置
diff --git a/Include/nmNum/nmPlot/nmPlotGraphicBinder.h b/Include/nmNum/nmPlot/nmPlotGraphicBinder.h
index 5a1fb10..b97f58e 100644
--- a/Include/nmNum/nmPlot/nmPlotGraphicBinder.h
+++ b/Include/nmNum/nmPlot/nmPlotGraphicBinder.h
@@ -56,6 +56,8 @@ public:
// 调用:用户画完裂缝后
void createCrackForGraphic(nmObjLineCrack* pGraphic);
+ // DFN 批量生成时传 false,不将裂缝加入独立裂缝参数面板。
+ void createCrackForGraphic(nmObjLineCrack* pGraphic, bool bNotifyGeometryList);
// 调用:从文件加载,绑定已有裂缝数据到已有图元
void bindCrackToGraphic(nmObjLineCrack* pGraphic, nmDataFracture* pData);
@@ -209,6 +211,7 @@ private slots:
void onGraphicLeakageChanged(double leakage);
void onGraphicPointsChanged();
void onGraphicVisibleChanged(bool bVisible);
+ void onFaultDataChanged();
// 裂缝图元信号 → 数据同步
void onGraphicCrackFlowModelChanged(int model);
@@ -216,11 +219,13 @@ private slots:
void onGraphicCrackDwChanged(double dw);
void onGraphicCrackPointsChanged();
void onGraphicCrackVisibleChanged(bool bVisible);
+ void onFractureDataChanged();
// 边界图元信号 → 数据同步
void onGraphicOutlinePointsChanged();
void onGraphicOutlineFlowTypeChanged();
void onGraphicOutlineVisibleChanged(bool bVisible);
+ void onOutlineDataChanged();
// 区域标记图元信号 → 数据同步
void onGraphicRegionMarkReservoirTypeChanged(int type);
@@ -228,11 +233,13 @@ private slots:
void onGraphicRegionMarkComWChanged(double comW);
void onGraphicRegionMarkNetToGrossChanged(double netToGross);
void onGraphicRegionMarkVisibleChanged(bool bVisible);
+ void onRegionMarkDataChanged();
// 复合区图元信号 → 数据同步
void onGraphicRegionFlowModelChanged(int model);
void onGraphicRegionLeakageChanged(double leakage);
void onGraphicRegionVisibleChanged(bool bVisible);
+ void onRegionDataChanged();
// 井图元信号 → 数据同步
void onGraphicWellVisibleChanged(bool bVisible);
@@ -249,10 +256,10 @@ private:
// 图元 ←→ 数据 双向信号连接(图元 emit → Binder slot → 数据 setter)
void _connectFault(nmObjLineFault* pGraphic, nmDataFault* pData);
- // 断开指定图元与本 Binder 的四条信号连接
+ // 断开指定图元与本 Binder 的信号连接
void _disconnectFault(nmObjLineFault* pGraphic);
- // 从数据对象读取值,写入图元本地副本(加载时用)
+ // 从数据对象读取值,写入图元本地副本(加载及参数变更时用)
void _pushFaultDataToGraphic(nmObjLineFault* pGraphic, nmDataFault* pData);
// 裂缝图元 → 数据 的映射表
@@ -264,10 +271,10 @@ private:
// 裂缝图元 ←→ 数据 双向信号连接
void _connectCrack(nmObjLineCrack* pGraphic, nmDataFracture* pData);
- // 断开指定裂缝图元与本 Binder 的五条信号连接
+ // 断开指定裂缝图元与本 Binder 的信号连接
void _disconnectCrack(nmObjLineCrack* pGraphic);
- // 从裂缝数据对象读取值,写入图元本地副本(加载时用)
+ // 从裂缝数据对象读取值,写入图元本地副本(加载及参数变更时用)
void _pushCrackDataToGraphic(nmObjLineCrack* pGraphic, nmDataFracture* pData);
// 边界图元 → 数据 的映射表(三种边界类型共用)
@@ -276,13 +283,13 @@ private:
// 已建立信号连接的边界图元集合
QSet m_setBoundOutlineGraphics;
- // 边界图元 ←→ 数据 信号连接(三条信号)
+ // 边界图元 ←→ 数据 信号连接
void _connectOutline(nmObjBase* pGraphic, nmDataOutline* pData);
// 断开指定边界图元与本 Binder 的信号连接
void _disconnectOutline(nmObjBase* pGraphic);
- // 从边界数据对象读取值,写入图元本地副本(加载时用)
+ // 从边界数据对象读取值,写入图元本地副本(加载及参数变更时用)
void _pushOutlineDataToGraphic(nmObjBase* pGraphic, nmDataOutline* pData);
// 测量线图元 → 数据 的映射表
@@ -302,7 +309,7 @@ private:
// 断开指定区域标记图元与本 Binder 的信号连接
void _disconnectRegionMark(nmObjRegionMark* pGraphic);
- // 从区域标记数据对象读取值,写入图元本地副本(加载时用)
+ // 从区域标记数据对象读取值,写入图元本地副本(加载及参数变更时用)
void _pushRegionMarkDataToGraphic(nmObjRegionMark* pGraphic, nmDataRegionMark* pData);
// ==================== 复合区图元 ====================
@@ -319,7 +326,7 @@ private:
// 断开指定复合区图元与本 Binder 的信号连接
void _disconnectRegion(nmObjRegion* pGraphic);
- // 从复合区数据对象读取值,写入图元本地副本(加载时用)
+ // 从复合区数据对象读取值,写入图元本地副本(加载及参数变更时用)
void _pushRegionDataToGraphic(nmObjRegion* pGraphic, nmDataRegion* pData);
// ==================== 井图元 ====================
diff --git a/Include/nmNum/nmSubWxs/nmWxParaPropertyPebi.h b/Include/nmNum/nmSubWxs/nmWxParaPropertyPebi.h
index 75877fe..b4118c9 100644
--- a/Include/nmNum/nmSubWxs/nmWxParaPropertyPebi.h
+++ b/Include/nmNum/nmSubWxs/nmWxParaPropertyPebi.h
@@ -1,4 +1,4 @@
-#pragma once
+#pragma once
#include "iDlgBase.h"
#include "nmSubWxs_global.h"
@@ -28,13 +28,13 @@ public:
/// @note 参数列表必须是在系统中配置的参数,listParas已经包括了显示顺序
/// 但对于层级,由系统配置来决定
virtual void refreshUIs(QStringList& listParas, bool bReserveOlds = true,
- QMap mapWellNames = QMap());
+ QMap mapObjectNames = QMap());
/// @brief 从数据管理器重建完整参数面板
- /// @note XML 中井参数只定义一份,运行时按 wellCode 创建多个对象分组。
+ /// @note XML 中参数只定义一份,运行时沿用多井机制按对象编码创建分组。
void rebuildAllParas();
- /// @brief 设置数据管理器引用(用于面板重建时获取井列表)
+ /// @brief 设置数据管理器引用(用于面板重建时获取井和几何对象列表)
void setDataManager(nmDataAnalyzeManager* mgr) { m_pDataManager = mgr; }
// 允许备份/恢复原有的参数内容
@@ -75,6 +75,8 @@ public slots:
void slotWellAdded(QString wellCode, QString wellName, QStringList paras);
/// @brief 井删除时按当前井列表刷新面板
void slotWellRemoved(QString wellCode, QString wellName);
+ /// @brief 几何对象新增、删除或改名后重建参数面板
+ void slotGeometryListChanged();
protected:
@@ -92,7 +94,7 @@ protected:
// Help
QTextEdit* m_pHelpBox;
- // 数据管理器引用(用于全量重建面板时获取井列表)
+ // 数据管理器引用(用于全量重建面板时获取井和几何对象列表)
nmDataAnalyzeManager* m_pDataManager;
signals:
diff --git a/Src/nmNum/nmData/nmDataAnalyzeManager.cpp b/Src/nmNum/nmData/nmDataAnalyzeManager.cpp
index 9c484e1..2611e0b 100644
--- a/Src/nmNum/nmData/nmDataAnalyzeManager.cpp
+++ b/Src/nmNum/nmData/nmDataAnalyzeManager.cpp
@@ -1,4 +1,4 @@
-#include "nmDataAnalyzeManager.h"
+#include "nmDataAnalyzeManager.h"
#include "nmAttrRegistry.h"
@@ -130,6 +130,68 @@ static bool isWellParaAttrName(const QString& name)
return false;
}
+// 参数名必须与 XML 定义和参数面板拼接的基础编号完全一致。
+struct GeometryParaDesc {
+ const char* sName;
+ nmDataAttribute* (*getFractureAttr)(nmDataFracture&);
+ nmDataAttribute* (*getFaultAttr)(nmDataFault&);
+ nmDataAttribute* (*getRegionAttr)(nmDataRegion&);
+ nmDataAttribute* (*getRegionMarkAttr)(nmDataRegionMark&);
+};
+
+static nmDataAttribute* getFractureStartX(nmDataFracture& data) { return &data.getStartX(); }
+static nmDataAttribute* getFractureStartY(nmDataFracture& data) { return &data.getStartY(); }
+static nmDataAttribute* getFractureEndX(nmDataFracture& data) { return &data.getEndX(); }
+static nmDataAttribute* getFractureEndY(nmDataFracture& data) { return &data.getEndY(); }
+static nmDataAttribute* getFractureFc(nmDataFracture& data) { return &data.getFractureDfc(); }
+static nmDataAttribute* getFaultStartX(nmDataFault& data) { return &data.getStartX(); }
+static nmDataAttribute* getFaultStartY(nmDataFault& data) { return &data.getStartY(); }
+static nmDataAttribute* getFaultEndX(nmDataFault& data) { return &data.getEndX(); }
+static nmDataAttribute* getFaultEndY(nmDataFault& data) { return &data.getEndY(); }
+static nmDataAttribute* getRegionLeakage(nmDataRegion& data) { return &data.getRegionLeakage(); }
+static nmDataAttribute* getRegionMarkComW(nmDataRegionMark& data) { return &data.getComW(); }
+static nmDataAttribute* getRegionMarkComKr(nmDataRegionMark& data) { return &data.getComKr(); }
+static nmDataAttribute* getRegionMarkNetToGross(nmDataRegionMark& data) { return &data.getNetToGross(); }
+
+static const GeometryParaDesc GEOMETRY_PARA_DESCS[] = {
+ {"F_X0", &getFractureStartX, NULL, NULL, NULL},
+ {"F_Y0", &getFractureStartY, NULL, NULL, NULL},
+ {"F_X1", &getFractureEndX, NULL, NULL, NULL},
+ {"F_Y1", &getFractureEndY, NULL, NULL, NULL},
+ {"F_FC", &getFractureFc, NULL, NULL, NULL},
+ {"FT_X0", NULL, &getFaultStartX, NULL, NULL},
+ {"FT_Y0", NULL, &getFaultStartY, NULL, NULL},
+ {"FT_X1", NULL, &getFaultEndX, NULL, NULL},
+ {"FT_Y1", NULL, &getFaultEndY, NULL, NULL},
+ {"R_Leakage", NULL, NULL, &getRegionLeakage, NULL},
+ {"RM_ComW", NULL, NULL, NULL, &getRegionMarkComW},
+ {"RM_ComKr", NULL, NULL, NULL, &getRegionMarkComKr},
+ {"RM_NetToGross", NULL, NULL, NULL, &getRegionMarkNetToGross},
+};
+static const int GEOMETRY_PARA_DESC_COUNT = sizeof(GEOMETRY_PARA_DESCS) / sizeof(GEOMETRY_PARA_DESCS[0]);
+
+static const char* OUTLINE_PARA_NAMES[] = {
+ "BR_XMin", "BR_YMin", "BR_XMax", "BR_YMax",
+ "BC_CenterX", "BC_CenterY", "BC_Radius",
+ "BP_X", "BP_Y"
+};
+static const int OUTLINE_PARA_NAME_COUNT = sizeof(OUTLINE_PARA_NAMES) / sizeof(OUTLINE_PARA_NAMES[0]);
+
+static bool isGeometryParaAttrName(const QString& name)
+{
+ for (int i = 0; i < GEOMETRY_PARA_DESC_COUNT; ++i) {
+ if (name.endsWith(QString("_") + GEOMETRY_PARA_DESCS[i].sName)) {
+ return true;
+ }
+ }
+ for (int i = 0; i < OUTLINE_PARA_NAME_COUNT; ++i) {
+ if (name.endsWith(QString("_") + OUTLINE_PARA_NAMES[i])) {
+ return true;
+ }
+ }
+ return false;
+}
+
namespace {
// 清空指定目录下的所有旧文件和子目录,但保留目录本身
bool clearDirectoryContents(const QString& dirPath)
@@ -1536,6 +1598,158 @@ void nmDataAnalyzeManager::syncWellAttrs()
}
}
+void nmDataAnalyzeManager::syncGeometryAttrs()
+{
+ if (m_pAttrRegistry == NULL) return;
+
+ // 沿用井参数注册方式,以“对象编码 + XML 参数名”建立双向绑定。
+ QSet activeAttrNames;
+ int fractureIndex = 0;
+ foreach (nmDataFracture* pFracture, m_vFractureData)
+ {
+ // DFN 裂缝由专用功能批量管理,不作为独立裂缝显示在参数面板中。
+ if (pFracture == nullptr || pFracture->getFractureType().getValue().toString() == "DFN") {
+ continue;
+ }
+
+ QString code = QString("FRAC%1").arg(++fractureIndex, 4, 10, QChar('0'));
+ for (int i = 0; i < GEOMETRY_PARA_DESC_COUNT; ++i)
+ {
+ if (GEOMETRY_PARA_DESCS[i].getFractureAttr == NULL) continue;
+ nmDataAttribute* pAttr = GEOMETRY_PARA_DESCS[i].getFractureAttr(*pFracture);
+ if (pAttr != NULL)
+ {
+ QString name = code + "_" + GEOMETRY_PARA_DESCS[i].sName;
+ activeAttrNames.insert(name);
+ m_pAttrRegistry->regAttr(name, pAttr);
+ }
+ }
+ }
+
+ for (int faultIndex = 0; faultIndex < m_vFaultData.size(); ++faultIndex)
+ {
+ nmDataFault* pFault = m_vFaultData[faultIndex];
+ if (pFault == nullptr) continue;
+
+ QString code = QString("FAULT%1").arg(faultIndex + 1, 4, 10, QChar('0'));
+ for (int i = 0; i < GEOMETRY_PARA_DESC_COUNT; ++i)
+ {
+ if (GEOMETRY_PARA_DESCS[i].getFaultAttr == NULL) continue;
+ nmDataAttribute* pAttr = GEOMETRY_PARA_DESCS[i].getFaultAttr(*pFault);
+ if (pAttr != NULL)
+ {
+ QString name = code + "_" + GEOMETRY_PARA_DESCS[i].sName;
+ activeAttrNames.insert(name);
+ m_pAttrRegistry->regAttr(name, pAttr);
+ }
+ }
+ }
+
+ for (int regionIndex = 0; regionIndex < m_vRegionData.size(); ++regionIndex)
+ {
+ nmDataRegion* pRegion = m_vRegionData[regionIndex];
+ if (pRegion == nullptr) continue;
+
+ QString code = QString("REGION%1").arg(regionIndex + 1, 4, 10, QChar('0'));
+ for (int i = 0; i < GEOMETRY_PARA_DESC_COUNT; ++i)
+ {
+ if (GEOMETRY_PARA_DESCS[i].getRegionAttr == NULL) continue;
+ nmDataAttribute* pAttr = GEOMETRY_PARA_DESCS[i].getRegionAttr(*pRegion);
+ if (pAttr != NULL)
+ {
+ QString name = code + "_" + GEOMETRY_PARA_DESCS[i].sName;
+ activeAttrNames.insert(name);
+ m_pAttrRegistry->regAttr(name, pAttr);
+ }
+ }
+ }
+
+ for (int markIndex = 0; markIndex < m_vRegionMarkData.size(); ++markIndex)
+ {
+ nmDataRegionMark* pMark = m_vRegionMarkData[markIndex];
+ if (pMark == nullptr) continue;
+
+ QString code = QString("RMARK%1").arg(markIndex + 1, 4, 10, QChar('0'));
+ for (int i = 0; i < GEOMETRY_PARA_DESC_COUNT; ++i)
+ {
+ if (GEOMETRY_PARA_DESCS[i].getRegionMarkAttr == NULL) continue;
+ nmDataAttribute* pAttr = GEOMETRY_PARA_DESCS[i].getRegionMarkAttr(*pMark);
+ if (pAttr != NULL)
+ {
+ QString name = code + "_" + GEOMETRY_PARA_DESCS[i].sName;
+ activeAttrNames.insert(name);
+ m_pAttrRegistry->regAttr(name, pAttr);
+ }
+ }
+ }
+
+ if (m_outlineData != nullptr)
+ {
+ if (m_outlineData->getOutlineType() == NM_Rect_Outline_Type)
+ {
+ const QString code = "BOUNDARY";
+ const QStringList names = QStringList() << "BR_XMin" << "BR_YMin" << "BR_XMax" << "BR_YMax";
+ nmDataAttribute* attrs[] = {
+ &m_outlineData->getLeftAttribute(),
+ &m_outlineData->getBottomAttribute(),
+ &m_outlineData->getRightAttribute(),
+ &m_outlineData->getTopAttribute()
+ };
+ for (int i = 0; i < names.count(); ++i) {
+ const QString name = code + "_" + names[i];
+ activeAttrNames.insert(name);
+ m_pAttrRegistry->regAttr(name, attrs[i]);
+ }
+ }
+ else if (m_outlineData->getOutlineType() == NM_Round_Outline_Type)
+ {
+ const QString code = "BOUNDARY";
+ const QStringList names = QStringList() << "BC_CenterX" << "BC_CenterY" << "BC_Radius";
+ nmDataAttribute* attrs[] = {
+ &m_outlineData->getCenterXAttribute(),
+ &m_outlineData->getCenterYAttribute(),
+ &m_outlineData->getRadiusAttribute()
+ };
+ for (int i = 0; i < names.count(); ++i) {
+ const QString name = code + "_" + names[i];
+ activeAttrNames.insert(name);
+ m_pAttrRegistry->regAttr(name, attrs[i]);
+ }
+ }
+ else if (m_outlineData->getOutlineType() == NM_Polygon_Outline_Type)
+ {
+ // 多边形顶点数量动态变化,每个 Point 使用独立对象编码注册 X/Y。
+ for (int pointIndex = 0; pointIndex < m_outlineData->getOutlinePointCount(); ++pointIndex)
+ {
+ const QString code = QString("BVERT%1").arg(pointIndex + 1, 4, 10, QChar('0'));
+ nmDataAttribute* pX = m_outlineData->getPointXAttribute(pointIndex);
+ nmDataAttribute* pY = m_outlineData->getPointYAttribute(pointIndex);
+ if (pX != nullptr)
+ {
+ const QString name = code + "_BP_X";
+ activeAttrNames.insert(name);
+ m_pAttrRegistry->regAttr(name, pX);
+ }
+ if (pY != nullptr)
+ {
+ const QString name = code + "_BP_Y";
+ activeAttrNames.insert(name);
+ m_pAttrRegistry->regAttr(name, pY);
+ }
+ }
+ }
+ }
+
+ // 精确清理已删除对象、已删除顶点和旧边界类型留下的注册项。
+ foreach (const QString& name, m_pAttrRegistry->registeredNames())
+ {
+ if (isGeometryParaAttrName(name) && !activeAttrNames.contains(name))
+ {
+ m_pAttrRegistry->unregAttr(name);
+ }
+ }
+}
+
nmDataReservoir nmDataAnalyzeManager::getReservoirDataCopy() const
{
if(m_reservoirData) {
@@ -1959,6 +2173,7 @@ bool nmDataAnalyzeManager::removeRegionMarkData(nmDataRegionMark * pData)
if(m_vRegionMarkData[i] == pData) {
delete m_vRegionMarkData[i]; // 释放内存
m_vRegionMarkData.remove(i);
+ notifyGeometryListChanged();
return true; // 移除成功,返回 true
}
}
@@ -1992,8 +2207,14 @@ void nmDataAnalyzeManager::updateRegionMarkData(const QVector&
if(m_vRegionMarkData[i]) {
// 只更新内容,不改变指针
*m_vRegionMarkData[i] = newData[i]; // 调用赋值运算符
+ m_vRegionMarkData[i]->notifyDataChanged();
}
}
+
+ // 批量赋值不触发属性信号,完成后统一刷新参数面板。
+ if (m_pAttrRegistry) {
+ m_pAttrRegistry->refreshAll();
+ }
}
nmDataOutline *nmDataAnalyzeManager::createOutline()
@@ -2017,6 +2238,7 @@ bool nmDataAnalyzeManager::removeOutlineData()
if(m_outlineData) {
delete m_outlineData; // 删除边界数据对象
m_outlineData = nullptr;
+ notifyGeometryListChanged();
return true; // 移除成功,返回 true
}
@@ -2060,6 +2282,7 @@ bool nmDataAnalyzeManager::removeRegionData(nmDataRegion * pData)
if(m_vRegionData[i] == pData) {
delete m_vRegionData[i]; // 释放内存
m_vRegionData.remove(i);
+ notifyGeometryListChanged();
return true; // 移除成功,返回 true
}
}
@@ -2093,8 +2316,14 @@ void nmDataAnalyzeManager::updateRegionData(const QVector& newData
if(m_vRegionData[i]) {
// 只更新内容,不改变指针
*m_vRegionData[i] = newData[i]; // 调用赋值运算符
+ m_vRegionData[i]->notifyDataChanged();
}
}
+
+ // 批量赋值不触发属性信号,完成后统一刷新参数面板。
+ if (m_pAttrRegistry) {
+ m_pAttrRegistry->refreshAll();
+ }
}
nmDataFracture *nmDataAnalyzeManager::createFracture()
@@ -2129,9 +2358,15 @@ bool nmDataAnalyzeManager::removeFractureData(nmDataFracture * pData)
// 遍历 m_vFractureData 数组,找到并移除对应的对象
for(int i = 0; i < m_vFractureData.size(); ++i) {
if(m_vFractureData[i] == pData) {
+ const bool bNotifyGeometryList =
+ m_vFractureData[i]->getFractureType().getValue().toString() != "DFN";
delete m_vFractureData[i]; // 释放内存
m_vFractureData.remove(i);
- emit dataChanged();
+ if (bNotifyGeometryList) {
+ notifyGeometryListChanged();
+ } else {
+ notifyDataChanged();
+ }
return true; // 移除成功,返回 true
}
}
@@ -2165,8 +2400,14 @@ void nmDataAnalyzeManager::updateFractureData(const QVector& new
if(m_vFractureData[i]) {
// 只更新内容,不改变指针
*m_vFractureData[i] = newData[i]; // 调用赋值运算符
+ m_vFractureData[i]->notifyDataChanged();
}
}
+
+ // 批量赋值不触发属性信号,完成后统一刷新参数面板。
+ if (m_pAttrRegistry) {
+ m_pAttrRegistry->refreshAll();
+ }
}
@@ -2190,7 +2431,7 @@ bool nmDataAnalyzeManager::removeFaultData(nmDataFault * pData)
if(m_vFaultData[i] == pData) {
delete m_vFaultData[i]; // 释放内存
m_vFaultData.remove(i);
- emit dataChanged();
+ notifyGeometryListChanged();
return true; // 移除成功,返回 true
}
}
@@ -2224,8 +2465,14 @@ void nmDataAnalyzeManager::updateFaultData(const QVector& newData)
if(m_vFaultData[i]) {
// 只更新内容,不改变指针
*m_vFaultData[i] = newData[i]; // 调用赋值运算符
+ m_vFaultData[i]->notifyDataChanged();
}
}
+
+ // 批量赋值不触发属性信号,完成后统一刷新参数面板。
+ if (m_pAttrRegistry) {
+ m_pAttrRegistry->refreshAll();
+ }
}
nmGuiPlot* nmDataAnalyzeManager::getPlot() const
@@ -2775,6 +3022,17 @@ void nmDataAnalyzeManager::notifyDataChanged()
emit dataChanged();
}
+void nmDataAnalyzeManager::notifyGeometryListChanged()
+{
+ emit sigGeometryListChanged();
+ emit dataChanged();
+}
+
+void nmDataAnalyzeManager::notifyParameterObjectNameChanged()
+{
+ emit sigGeometryListChanged();
+}
+
void nmDataAnalyzeManager::setDisplaySettings(const QVector& displaySettings)
{
m_vecDisplaySettings = displaySettings;
diff --git a/Src/nmNum/nmData/nmDataFault.cpp b/Src/nmNum/nmData/nmDataFault.cpp
index d82b920..0985269 100644
--- a/Src/nmNum/nmData/nmDataFault.cpp
+++ b/Src/nmNum/nmData/nmDataFault.cpp
@@ -1,21 +1,36 @@
#include "nmDataFault.h"
-nmDataFault::nmDataFault(){
+nmDataFault::nmDataFault()
+ : m_bSyncingEndPoints(false) {
+ QStringList lengthUnits;
+ lengthUnits << "m" << "cm" << "mm" << "in" << "0.1 in" << "ft" << "mile" << "km";
+ m_startX = nmDataAttribute("Fault start X", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_startY = nmDataAttribute("Fault start Y", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_endX = nmDataAttribute("Fault end X", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_endY = nmDataAttribute("Fault end Y", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
m_faultFlowModel = nmDataAttribute("Fault flow model", "Leaky","", UNIT_TYPE_DIMENSIONLESS, QStringList() << "Leaky" << "Composite limit", QStringList());
m_faultLeakage = nmDataAttribute("Fault leakage", 1.0,"",UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList());
// 图元可见性,默认为true
m_bPlotVisible = true;
+
+ this->connectAttributeSignals();
}
-nmDataFault::nmDataFault(const nmDataFault& other){
+nmDataFault::nmDataFault(const nmDataFault& other)
+ : m_bSyncingEndPoints(false) {
*this = other;
+ this->connectAttributeSignals();
}
nmDataFault& nmDataFault::operator=(const nmDataFault& other) {
if (this != &other) {
m_sFaultName = other.m_sFaultName;
m_vecPts = other.m_vecPts;
+ m_startX = other.m_startX;
+ m_startY = other.m_startY;
+ m_endX = other.m_endX;
+ m_endY = other.m_endY;
m_faultFlowModel = other.m_faultFlowModel;
m_faultLeakage = other.m_faultLeakage;
@@ -94,6 +109,8 @@ void nmDataFault::FromJsonValue(const rapidjson::Value& jsonValue)
if (jsonValue.HasMember("PlotVisible") && jsonValue["PlotVisible"].IsBool()) {
m_bPlotVisible = jsonValue["PlotVisible"].GetBool();
}
+
+ syncEndPointAttributes();
}
/// Getter and Setter for m_faultName
@@ -116,6 +133,27 @@ QVector nmDataFault::getFaultPoints() const
void nmDataFault::setFaultPoints(const QVector& vecPts)
{
m_vecPts = vecPts;
+ syncEndPointAttributes();
+}
+
+nmDataAttribute& nmDataFault::getStartX()
+{
+ return m_startX;
+}
+
+nmDataAttribute& nmDataFault::getStartY()
+{
+ return m_startY;
+}
+
+nmDataAttribute& nmDataFault::getEndX()
+{
+ return m_endX;
+}
+
+nmDataAttribute& nmDataFault::getEndY()
+{
+ return m_endY;
}
// Getter and Setter for m_faultFlowModel
@@ -145,5 +183,55 @@ bool nmDataFault::getPlotVisible() const{
}
void nmDataFault::setPlotVisible(const bool newState) {
- m_bPlotVisible = newState;
+ m_bPlotVisible = newState;
+}
+
+// 批量赋值不会触发属性信号,通过对象级信号统一刷新关联视图。
+void nmDataFault::notifyDataChanged()
+{
+ emit sigFaultDataChanged();
+}
+
+// 端点属性负责坐标回写,其余属性直接转发为断层数据变化信号。
+void nmDataFault::connectAttributeSignals()
+{
+ connect(&m_startX, SIGNAL(sigValueChanged()), this, SLOT(onEndPointAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_startY, SIGNAL(sigValueChanged()), this, SLOT(onEndPointAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_endX, SIGNAL(sigValueChanged()), this, SLOT(onEndPointAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_endY, SIGNAL(sigValueChanged()), this, SLOT(onEndPointAttributeChanged()), Qt::UniqueConnection);
+
+ connect(&m_faultFlowModel, SIGNAL(sigValueChanged()), this, SIGNAL(sigFaultDataChanged()), Qt::UniqueConnection);
+ connect(&m_faultLeakage, SIGNAL(sigValueChanged()), this, SIGNAL(sigFaultDataChanged()), Qt::UniqueConnection);
+}
+
+// 图元或文件数据变化后,将点集首尾坐标同步到面板绑定属性。
+void nmDataFault::syncEndPointAttributes()
+{
+ if (m_vecPts.size() < 2) {
+ return;
+ }
+
+ m_bSyncingEndPoints = true;
+ const QPointF& start = m_vecPts.first();
+ const QPointF& end = m_vecPts.last();
+ if (m_startX.getValue().toDouble() != start.x()) m_startX.setValue(start.x());
+ if (m_startY.getValue().toDouble() != start.y()) m_startY.setValue(start.y());
+ if (m_endX.getValue().toDouble() != end.x()) m_endX.setValue(end.x());
+ if (m_endY.getValue().toDouble() != end.y()) m_endY.setValue(end.y());
+ m_bSyncingEndPoints = false;
+}
+
+// 参数面板修改端点坐标后,回写真实点集并通知 Binder 更新图元。
+void nmDataFault::onEndPointAttributeChanged()
+{
+ if (m_bSyncingEndPoints || m_vecPts.size() < 2) {
+ return;
+ }
+
+ m_vecPts.first().setX(m_startX.getValue().toDouble());
+ m_vecPts.first().setY(m_startY.getValue().toDouble());
+ m_vecPts.last().setX(m_endX.getValue().toDouble());
+ m_vecPts.last().setY(m_endY.getValue().toDouble());
+
+ emit sigFaultDataChanged();
}
diff --git a/Src/nmNum/nmData/nmDataFracture.cpp b/Src/nmNum/nmData/nmDataFracture.cpp
index 23c9cb5..d9c83d8 100644
--- a/Src/nmNum/nmData/nmDataFracture.cpp
+++ b/Src/nmNum/nmData/nmDataFracture.cpp
@@ -8,7 +8,14 @@
#include // 确保 QVariantMap 被包含
#include // 确保 QVariantList 被包含
-nmDataFracture::nmDataFracture() {
+nmDataFracture::nmDataFracture()
+ : m_bSyncingEndPoints(false) {
+ QStringList lengthUnits;
+ lengthUnits << "m" << "cm" << "mm" << "in" << "0.1 in" << "ft" << "mile" << "km";
+ m_startX = nmDataAttribute("Fracture start X", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_startY = nmDataAttribute("Fracture start Y", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_endX = nmDataAttribute("Fracture end X", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_endY = nmDataAttribute("Fracture end Y", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
m_fractureFlowModel = nmDataAttribute("Fracture flow model", "Finite Conductivity","",UNIT_TYPE_DIMENSIONLESS, QStringList() << "Infinite Conductivity" << "Finite Conductivity", QStringList());
m_fractureDfc = nmDataAttribute("Fracture dFc", 1, "md.m", UNIT_TYPE_CONDUCTIVITY, QStringList(), QStringList() << "md.ft" << "md.m" << "m^3");
m_fractureDw = nmDataAttribute("Fracture dW", 1, "", UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList());
@@ -17,16 +24,24 @@ nmDataFracture::nmDataFracture() {
// 图元可见性,默认为true
m_bPlotVisible = true;
+
+ this->connectAttributeSignals();
}
-nmDataFracture::nmDataFracture(const nmDataFracture& other) {
+nmDataFracture::nmDataFracture(const nmDataFracture& other)
+ : m_bSyncingEndPoints(false) {
*this = other;
+ this->connectAttributeSignals();
}
nmDataFracture& nmDataFracture::operator=(const nmDataFracture& other) {
if (this != &other) {
m_sFractureName = other.m_sFractureName;
m_vecPts = other.m_vecPts;
+ m_startX = other.m_startX;
+ m_startY = other.m_startY;
+ m_endX = other.m_endX;
+ m_endY = other.m_endY;
m_fractureFlowModel = other.m_fractureFlowModel;
m_fractureDfc = other.m_fractureDfc;
m_fractureDw = other.m_fractureDw;
@@ -116,6 +131,8 @@ void nmDataFracture::FromJsonValue(const rapidjson::Value& jsonValue)
if (jsonValue.HasMember("PlotVisible") && jsonValue["PlotVisible"].IsBool()) {
m_bPlotVisible = jsonValue["PlotVisible"].GetBool(); // 使用m_bPlotVisible
}
+
+ syncEndPointAttributes();
}
// Getter and Setter for m_sFractureName
@@ -138,6 +155,27 @@ QVector nmDataFracture::getFracturePoints() const
void nmDataFracture::setFracturePoints(const QVector& vecPts)
{
m_vecPts = vecPts;
+ syncEndPointAttributes();
+}
+
+nmDataAttribute& nmDataFracture::getStartX()
+{
+ return m_startX;
+}
+
+nmDataAttribute& nmDataFracture::getStartY()
+{
+ return m_startY;
+}
+
+nmDataAttribute& nmDataFracture::getEndX()
+{
+ return m_endX;
+}
+
+nmDataAttribute& nmDataFracture::getEndY()
+{
+ return m_endY;
}
// Getter and Setter for m_fractureFlowModel
@@ -191,3 +229,54 @@ void nmDataFracture::setPlotVisible(const bool newState) {
m_bPlotVisible = newState;
}
+// 批量赋值不会触发属性信号,通过对象级信号统一刷新关联视图。
+void nmDataFracture::notifyDataChanged()
+{
+ emit sigFractureDataChanged();
+}
+
+// 端点属性负责坐标回写,其余属性直接转发为裂缝数据变化信号。
+void nmDataFracture::connectAttributeSignals()
+{
+ connect(&m_startX, SIGNAL(sigValueChanged()), this, SLOT(onEndPointAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_startY, SIGNAL(sigValueChanged()), this, SLOT(onEndPointAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_endX, SIGNAL(sigValueChanged()), this, SLOT(onEndPointAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_endY, SIGNAL(sigValueChanged()), this, SLOT(onEndPointAttributeChanged()), Qt::UniqueConnection);
+
+ connect(&m_fractureFlowModel, SIGNAL(sigValueChanged()), this, SIGNAL(sigFractureDataChanged()), Qt::UniqueConnection);
+ connect(&m_fractureDfc, SIGNAL(sigValueChanged()), this, SIGNAL(sigFractureDataChanged()), Qt::UniqueConnection);
+ connect(&m_fractureDw, SIGNAL(sigValueChanged()), this, SIGNAL(sigFractureDataChanged()), Qt::UniqueConnection);
+}
+
+// 图元或文件数据变化后,将点集首尾坐标同步到面板绑定属性。
+void nmDataFracture::syncEndPointAttributes()
+{
+ if (m_vecPts.size() < 2) {
+ return;
+ }
+
+ m_bSyncingEndPoints = true;
+ const QPointF& start = m_vecPts.first();
+ const QPointF& end = m_vecPts.last();
+ if (m_startX.getValue().toDouble() != start.x()) m_startX.setValue(start.x());
+ if (m_startY.getValue().toDouble() != start.y()) m_startY.setValue(start.y());
+ if (m_endX.getValue().toDouble() != end.x()) m_endX.setValue(end.x());
+ if (m_endY.getValue().toDouble() != end.y()) m_endY.setValue(end.y());
+ m_bSyncingEndPoints = false;
+}
+
+// 参数面板修改端点坐标后,回写真实点集并通知 Binder 更新图元。
+void nmDataFracture::onEndPointAttributeChanged()
+{
+ if (m_bSyncingEndPoints || m_vecPts.size() < 2) {
+ return;
+ }
+
+ m_vecPts.first().setX(m_startX.getValue().toDouble());
+ m_vecPts.first().setY(m_startY.getValue().toDouble());
+ m_vecPts.last().setX(m_endX.getValue().toDouble());
+ m_vecPts.last().setY(m_endY.getValue().toDouble());
+
+ emit sigFractureDataChanged();
+}
+
diff --git a/Src/nmNum/nmData/nmDataOutline.cpp b/Src/nmNum/nmData/nmDataOutline.cpp
index f6cfbed..4e70e9f 100644
--- a/Src/nmNum/nmData/nmDataOutline.cpp
+++ b/Src/nmNum/nmData/nmDataOutline.cpp
@@ -1,9 +1,12 @@
#include "nmDataOutline.h"
#include "nmDataJsonTools.h"
+#include
+
// Constructor
nmDataOutline::nmDataOutline()
- : m_sName()
+ : m_bSyncingGeometryAttributes(false)
+ , m_sName()
, m_vecPts()
, m_vFlowTypeList()
, m_eOutlineType(NM_Rect_Outline_Type)
@@ -15,9 +18,12 @@ nmDataOutline::nmDataOutline()
, m_nBackgrdAlpha(0)
, m_bHasVisualProps(false)
{
+ initGeometryAttributes();
}
-nmDataOutline::nmDataOutline(const nmDataOutline& other) {
+nmDataOutline::nmDataOutline(const nmDataOutline& other)
+ : m_bSyncingGeometryAttributes(false) {
+ initGeometryAttributes();
*this = other;
}
@@ -36,12 +42,15 @@ nmDataOutline& nmDataOutline::operator=(const nmDataOutline& other) {
m_clrBackgrd = other.m_clrBackgrd;
m_nBackgrdAlpha = other.m_nBackgrdAlpha;
m_bHasVisualProps = other.m_bHasVisualProps;
+
+ syncGeometryAttributes();
}
return *this;
}
// Destructor
nmDataOutline::~nmDataOutline() {
+ clearPointAttributes();
}
// 序列化 nmDataOutline 为 RapidJSON Value
@@ -170,6 +179,8 @@ void nmDataOutline::FromJsonValue(const rapidjson::Value& jsonValue)
bHasVisual = true;
}
m_bHasVisualProps = bHasVisual;
+
+ syncGeometryAttributes();
}
// Getter and Setter for m_sName
@@ -188,6 +199,55 @@ QVector nmDataOutline::getOutlinePoints() {
void nmDataOutline::setOutlinePoints(const QVector& vecPts) {
m_vecPts = vecPts;
+ syncPointAttributes();
+
+ if (m_eOutlineType == NM_Rect_Outline_Type) {
+ syncRectAttributes();
+ } else if (m_eOutlineType == NM_Round_Outline_Type) {
+ syncRoundAttributes();
+ }
+}
+
+int nmDataOutline::getOutlinePointCount() const {
+ return m_vecPts.count();
+}
+
+nmDataAttribute* nmDataOutline::getPointXAttribute(int nIndex) const {
+ if (nIndex < 0 || nIndex >= m_vPointXAttributes.count()) return nullptr;
+ return m_vPointXAttributes[nIndex];
+}
+
+nmDataAttribute* nmDataOutline::getPointYAttribute(int nIndex) const {
+ if (nIndex < 0 || nIndex >= m_vPointYAttributes.count()) return nullptr;
+ return m_vPointYAttributes[nIndex];
+}
+
+nmDataAttribute& nmDataOutline::getLeftAttribute() {
+ return m_left;
+}
+
+nmDataAttribute& nmDataOutline::getRightAttribute() {
+ return m_right;
+}
+
+nmDataAttribute& nmDataOutline::getTopAttribute() {
+ return m_top;
+}
+
+nmDataAttribute& nmDataOutline::getBottomAttribute() {
+ return m_bottom;
+}
+
+nmDataAttribute& nmDataOutline::getCenterXAttribute() {
+ return m_centerX;
+}
+
+nmDataAttribute& nmDataOutline::getCenterYAttribute() {
+ return m_centerY;
+}
+
+nmDataAttribute& nmDataOutline::getRadiusAttribute() {
+ return m_radius;
}
QVector nmDataOutline::getFlowTypeList() const {
@@ -208,6 +268,7 @@ NM_Data_Outline_Type nmDataOutline::getOutlineType() const
void nmDataOutline::setOutlineType(NM_Data_Outline_Type eOutlineType)
{
m_eOutlineType = eOutlineType;
+ syncGeometryAttributes();
}
// Getter for m_ptCenter
@@ -220,6 +281,7 @@ QPointF nmDataOutline::getCenter() const
void nmDataOutline::setCenter(const QPointF& ptCenter)
{
m_ptCenter = ptCenter;
+ syncRoundAttributes();
}
// Getter for m_dRadius
@@ -232,6 +294,7 @@ double nmDataOutline::getRadius() const
void nmDataOutline::setRadius(double dRadius)
{
m_dRadius = dRadius;
+ syncRoundAttributes();
}
bool nmDataOutline::getPlotVisible() const{
@@ -268,3 +331,180 @@ bool nmDataOutline::hasVisualProps() const {
void nmDataOutline::setVisualPropsValid(bool bValid) {
m_bHasVisualProps = bValid;
}
+
+// 固定几何属性作为参数面板适配层,实际持久化数据仍保存在原有字段中。
+void nmDataOutline::initGeometryAttributes()
+{
+ QStringList lengthUnits;
+ lengthUnits << "m" << "cm" << "mm" << "in" << "0.1 in" << "ft" << "mile" << "km";
+
+ m_left = nmDataAttribute("Boundary left X", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_right = nmDataAttribute("Boundary right X", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_top = nmDataAttribute("Boundary top Y", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_bottom = nmDataAttribute("Boundary bottom Y", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_centerX = nmDataAttribute("Boundary center X", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_centerY = nmDataAttribute("Boundary center Y", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+ m_radius = nmDataAttribute("Boundary radius", 0.0, "m", UNIT_TYPE_LENGTH, QStringList(), lengthUnits);
+
+ connect(&m_left, SIGNAL(sigValueChanged()), this, SLOT(onGeometryAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_right, SIGNAL(sigValueChanged()), this, SLOT(onGeometryAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_top, SIGNAL(sigValueChanged()), this, SLOT(onGeometryAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_bottom, SIGNAL(sigValueChanged()), this, SLOT(onGeometryAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_centerX, SIGNAL(sigValueChanged()), this, SLOT(onGeometryAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_centerY, SIGNAL(sigValueChanged()), this, SLOT(onGeometryAttributeChanged()), Qt::UniqueConnection);
+ connect(&m_radius, SIGNAL(sigValueChanged()), this, SLOT(onGeometryAttributeChanged()), Qt::UniqueConnection);
+}
+
+void nmDataOutline::clearPointAttributes()
+{
+ qDeleteAll(m_vPointXAttributes);
+ qDeleteAll(m_vPointYAttributes);
+ m_vPointXAttributes.clear();
+ m_vPointYAttributes.clear();
+}
+
+// 根据边界类型,将原有几何数据同步到对应的面板绑定属性。
+void nmDataOutline::syncGeometryAttributes()
+{
+ syncPointAttributes();
+ if (m_eOutlineType == NM_Rect_Outline_Type) {
+ syncRectAttributes();
+ } else if (m_eOutlineType == NM_Round_Outline_Type) {
+ syncRoundAttributes();
+ }
+}
+
+void nmDataOutline::syncPointAttributes()
+{
+ // 矩形和圆形使用固定几何属性,只有多边形需要逐点属性。
+ if (m_eOutlineType != NM_Polygon_Outline_Type) {
+ if (!m_vPointXAttributes.isEmpty() || !m_vPointYAttributes.isEmpty()) {
+ clearPointAttributes();
+ }
+ return;
+ }
+
+ if (m_vPointXAttributes.count() != m_vecPts.count() ||
+ m_vPointYAttributes.count() != m_vecPts.count()) {
+ clearPointAttributes();
+
+ QStringList lengthUnits;
+ lengthUnits << "m" << "cm" << "mm" << "in" << "0.1 in" << "ft" << "mile" << "km";
+ for (int i = 0; i < m_vecPts.count(); ++i) {
+ nmDataAttribute* pX = new nmDataAttribute(QString("Boundary point %1 X").arg(i + 1),
+ m_vecPts[i].x(), "m", UNIT_TYPE_LENGTH,
+ QStringList(), lengthUnits);
+ nmDataAttribute* pY = new nmDataAttribute(QString("Boundary point %1 Y").arg(i + 1),
+ m_vecPts[i].y(), "m", UNIT_TYPE_LENGTH,
+ QStringList(), lengthUnits);
+ pX->setParent(this);
+ pY->setParent(this);
+ connect(pX, SIGNAL(sigValueChanged()), this, SLOT(onGeometryAttributeChanged()), Qt::UniqueConnection);
+ connect(pY, SIGNAL(sigValueChanged()), this, SLOT(onGeometryAttributeChanged()), Qt::UniqueConnection);
+ m_vPointXAttributes.append(pX);
+ m_vPointYAttributes.append(pY);
+ }
+ }
+
+ m_bSyncingGeometryAttributes = true;
+ for (int i = 0; i < m_vecPts.count(); ++i) {
+ if (m_vPointXAttributes[i]->getValue().toDouble() != m_vecPts[i].x()) {
+ m_vPointXAttributes[i]->setValue(m_vecPts[i].x());
+ }
+ if (m_vPointYAttributes[i]->getValue().toDouble() != m_vecPts[i].y()) {
+ m_vPointYAttributes[i]->setValue(m_vecPts[i].y());
+ }
+ }
+ m_bSyncingGeometryAttributes = false;
+}
+
+void nmDataOutline::syncRectAttributes()
+{
+ if (m_vecPts.isEmpty()) return;
+
+ double left = m_vecPts.first().x();
+ double right = left;
+ double top = m_vecPts.first().y();
+ double bottom = top;
+ foreach (const QPointF& pt, m_vecPts) {
+ left = qMin(left, pt.x());
+ right = qMax(right, pt.x());
+ top = qMax(top, pt.y());
+ bottom = qMin(bottom, pt.y());
+ }
+
+ m_bSyncingGeometryAttributes = true;
+ if (m_left.getValue().toDouble() != left) m_left.setValue(left);
+ if (m_right.getValue().toDouble() != right) m_right.setValue(right);
+ if (m_top.getValue().toDouble() != top) m_top.setValue(top);
+ if (m_bottom.getValue().toDouble() != bottom) m_bottom.setValue(bottom);
+ m_bSyncingGeometryAttributes = false;
+}
+
+void nmDataOutline::syncRoundAttributes()
+{
+ m_bSyncingGeometryAttributes = true;
+ if (m_centerX.getValue().toDouble() != m_ptCenter.x()) m_centerX.setValue(m_ptCenter.x());
+ if (m_centerY.getValue().toDouble() != m_ptCenter.y()) m_centerY.setValue(m_ptCenter.y());
+ if (m_radius.getValue().toDouble() != m_dRadius) m_radius.setValue(m_dRadius);
+ m_bSyncingGeometryAttributes = false;
+}
+
+void nmDataOutline::updateRectPointsFromAttributes()
+{
+ const double left = m_left.getValue().toDouble();
+ const double right = m_right.getValue().toDouble();
+ const double top = m_top.getValue().toDouble();
+ const double bottom = m_bottom.getValue().toDouble();
+
+ m_vecPts.clear();
+ m_vecPts << QPointF(left, top)
+ << QPointF(right, top)
+ << QPointF(right, bottom)
+ << QPointF(left, bottom);
+ syncPointAttributes();
+}
+
+void nmDataOutline::updateRoundPointsFromAttributes()
+{
+ const QPointF center(m_centerX.getValue().toDouble(), m_centerY.getValue().toDouble());
+ const double radius = m_radius.getValue().toDouble();
+ m_ptCenter = center;
+ m_dRadius = radius;
+
+ m_vecPts.clear();
+ m_vecPts << center
+ << QPointF(radius, radius)
+ << QPointF(center.x(), center.y() - radius)
+ << QPointF(center.x() + radius, center.y())
+ << QPointF(center.x(), center.y() + radius)
+ << QPointF(center.x() - radius, center.y());
+ syncPointAttributes();
+}
+
+// 参数面板修改几何属性后,回写边界数据并通知 Binder 更新图元。
+void nmDataOutline::onGeometryAttributeChanged()
+{
+ if (m_bSyncingGeometryAttributes) return;
+
+ QObject* pSender = sender();
+ if (pSender == &m_left || pSender == &m_right ||
+ pSender == &m_top || pSender == &m_bottom) {
+ updateRectPointsFromAttributes();
+ } else if (pSender == &m_centerX || pSender == &m_centerY || pSender == &m_radius) {
+ updateRoundPointsFromAttributes();
+ } else {
+ for (int i = 0; i < m_vecPts.count(); ++i) {
+ if (pSender == m_vPointXAttributes.value(i, nullptr)) {
+ m_vecPts[i].setX(m_vPointXAttributes[i]->getValue().toDouble());
+ break;
+ }
+ if (pSender == m_vPointYAttributes.value(i, nullptr)) {
+ m_vecPts[i].setY(m_vPointYAttributes[i]->getValue().toDouble());
+ break;
+ }
+ }
+ }
+
+ emit sigOutlineDataChanged();
+}
diff --git a/Src/nmNum/nmData/nmDataRegion.cpp b/Src/nmNum/nmData/nmDataRegion.cpp
index 10e1133..d626bdb 100644
--- a/Src/nmNum/nmData/nmDataRegion.cpp
+++ b/Src/nmNum/nmData/nmDataRegion.cpp
@@ -12,10 +12,13 @@ nmDataRegion::nmDataRegion(){
// 视觉属性默认值(与 nmObjRegion::init 保持一致)
m_dPenWidth = 0.3;
m_clrBackgrd = QColor(0, 0, 0, 0);
+
+ this->connectAttributeSignals();
}
nmDataRegion::nmDataRegion(const nmDataRegion& other){
*this = other; // 使用赋值运算符实现
+ this->connectAttributeSignals();
}
nmDataRegion& nmDataRegion::operator=(const nmDataRegion& other) {
@@ -212,3 +215,16 @@ QColor nmDataRegion::getBackgrdColor() const {
void nmDataRegion::setBackgrdColor(const QColor& clr) {
m_clrBackgrd = clr;
}
+
+// 批量赋值不会触发属性信号,通过对象级信号统一刷新关联视图。
+void nmDataRegion::notifyDataChanged()
+{
+ emit sigRegionDataChanged();
+}
+
+// 将已有属性的变化汇总为区域数据变化信号,供 Binder 统一处理。
+void nmDataRegion::connectAttributeSignals()
+{
+ connect(&m_regionFlowModel, SIGNAL(sigValueChanged()), this, SIGNAL(sigRegionDataChanged()), Qt::UniqueConnection);
+ connect(&m_regionLeakage, SIGNAL(sigValueChanged()), this, SIGNAL(sigRegionDataChanged()), Qt::UniqueConnection);
+}
diff --git a/Src/nmNum/nmData/nmDataRegionMark.cpp b/Src/nmNum/nmData/nmDataRegionMark.cpp
index 36771e8..f491999 100644
--- a/Src/nmNum/nmData/nmDataRegionMark.cpp
+++ b/Src/nmNum/nmData/nmDataRegionMark.cpp
@@ -19,10 +19,12 @@ nmDataRegionMark::nmDataRegionMark()
m_netToGross = nmDataAttribute("NetToGross", 1.0, "", UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList());
// 图元可见性,默认为true
+ this->connectAttributeSignals();
}
nmDataRegionMark::nmDataRegionMark(const nmDataRegionMark& other) {
*this = other; // 使用赋值运算符实现
+ this->connectAttributeSignals();
}
nmDataRegionMark& nmDataRegionMark::operator=(const nmDataRegionMark& other) {
@@ -189,3 +191,18 @@ bool nmDataRegionMark::getPlotVisible() const{
void nmDataRegionMark::setPlotVisible(const bool newState) {
m_bPlotVisible = newState;
}
+
+// 批量赋值不会触发属性信号,通过对象级信号统一刷新关联视图。
+void nmDataRegionMark::notifyDataChanged()
+{
+ emit sigRegionMarkDataChanged();
+}
+
+// 将已有属性的变化汇总为标记区域数据变化信号,供 Binder 统一处理。
+void nmDataRegionMark::connectAttributeSignals()
+{
+ connect(&m_reservoirType, SIGNAL(sigValueChanged()), this, SIGNAL(sigRegionMarkDataChanged()), Qt::UniqueConnection);
+ connect(&m_comKr, SIGNAL(sigValueChanged()), this, SIGNAL(sigRegionMarkDataChanged()), Qt::UniqueConnection);
+ connect(&m_comW, SIGNAL(sigValueChanged()), this, SIGNAL(sigRegionMarkDataChanged()), Qt::UniqueConnection);
+ connect(&m_netToGross, SIGNAL(sigValueChanged()), this, SIGNAL(sigRegionMarkDataChanged()), Qt::UniqueConnection);
+}
diff --git a/Src/nmNum/nmGUI/nmGridRowUtils.cpp b/Src/nmNum/nmGUI/nmGridRowUtils.cpp
index e55b12d..319b960 100644
--- a/Src/nmNum/nmGUI/nmGridRowUtils.cpp
+++ b/Src/nmNum/nmGUI/nmGridRowUtils.cpp
@@ -1,4 +1,4 @@
-#include "nmGridRowUtils.h"
+#include "nmGridRowUtils.h"
#include "iGridRowGroup.h"
#include "iParameter.h"
#include "iSysParaHelper.h"
@@ -64,7 +64,7 @@ bool nmGridRowUtils::buildRowUtils(QStringList listParas,
bool bDnMode,
QWidget* pWxDlg)
{
- // 分离储层参数和井参数
+ // 分离储层参数和带对象编码前缀的参数。
QStringList listRes;
QMap mapWellParas;
splitWellParas(listParas, listRes, mapWellParas);
@@ -74,12 +74,12 @@ bool nmGridRowUtils::buildRowUtils(QStringList listParas,
{
return false;
}
- // 构建井分组
+ // 沿用多井机制构建对象分组。
if (!mapWellParas.isEmpty())
{
buildWellGroups(mapWellParas, bDnMode);
- // 井分组追加完成后,重新备份、绑定、计算布局
+ // 对象分组追加完成后,重新备份、绑定、计算布局。
bkAllItems();
bindItems();
@@ -263,7 +263,7 @@ void nmGridRowUtils::bindItems()
}
// ================================================================
-// 多井分组实现
+// 多对象分组实现(沿用多井接口)
// ================================================================
void nmGridRowUtils::splitWellParas(QStringList listParas,
@@ -302,10 +302,33 @@ void nmGridRowUtils::buildWellGroups(QMap& mapWellParas,
{
bool bProperOrder = true;
- // 按wellCode排序遍历
+ // 沿用多井分组机制,按对象编码排序遍历。
QList listCodes = mapWellParas.keys();
qSort(listCodes);
+ // 多边形边界先建立外层分组,各顶点作为其子分组。
+ nmWellGridRowGroup* pPolygonGroup = nullptr;
+ foreach (const QString& sCode, listCodes)
+ {
+ if (sCode.startsWith("BVERT"))
+ {
+ pPolygonGroup = new nmWellGridRowGroup(nullptr);
+ Q_ASSERT(nullptr != pPolygonGroup);
+ pPolygonGroup->setParaSrcTag(m_sParaSrcTag);
+ pPolygonGroup->setTagInner(m_mapWellNames.value("BOUNDARY", tr("PolygonOutline")));
+ connectSignalsOf(pPolygonGroup);
+
+ pPolygonGroup->setDlgBase(this);
+ pPolygonGroup->initEditor();
+ pPolygonGroup->configEditor();
+ pPolygonGroup->setSplitPos(m_dSplitPos);
+ pPolygonGroup->initOtherEditors();
+
+ m_vecGridItems.append(pPolygonGroup);
+ break;
+ }
+ }
+
foreach (QString sCode, listCodes)
{
QStringList listParas = mapWellParas[sCode];
@@ -314,7 +337,7 @@ void nmGridRowUtils::buildWellGroups(QMap& mapWellParas,
continue;
}
- // 井前缀,如 "W001_"
+ // 对象编码前缀,如 "W001_"、"FRAC0001_"。
QString sPrefix = sCode + "_";
// 显示名称
@@ -325,12 +348,17 @@ void nmGridRowUtils::buildWellGroups(QMap& mapWellParas,
sWellName = m_mapWellNames[sCode];
}
- // 参考多对象 UI 的 Layer 分组:用父节点的 tagLayer 标记对象作用域。
- nmWellGridRowGroup* pGroup = new nmWellGridRowGroup(nullptr);
+ // 用父节点的 tagLayer 标记对象作用域。
+ iGridRowItem* pParent = sCode.startsWith("BVERT") ? pPolygonGroup : nullptr;
+ nmWellGridRowGroup* pGroup = new nmWellGridRowGroup(pParent);
Q_ASSERT(nullptr != pGroup);
+ if (pParent != nullptr)
+ {
+ pParent->appendChild(pGroup);
+ }
pGroup->setParaSrcTag(m_sParaSrcTag);
pGroup->setTagInner(sWellName); // Group 标题
- pGroup->setTagLayer(sPrefix); // 井前缀标识
+ pGroup->setTagLayer(sPrefix); // 对象编码前缀
connectSignalsOf(pGroup);
pGroup->setDlgBase(this);
@@ -339,10 +367,28 @@ void nmGridRowUtils::buildWellGroups(QMap& mapWellParas,
pGroup->setSplitPos(m_dSplitPos);
pGroup->initOtherEditors();
- m_vecGridItems.append(pGroup);
+ if (pParent == nullptr)
+ {
+ m_vecGridItems.append(pGroup);
+ }
- // 在该分组下构建参数项
- _buildRowUtils(listParas, pGroup, bDnMode, bProperOrder);
+ // 多边形顶点直接显示 X/Y,避免每个 Point 下重复一层参数组。
+ if (pParent != nullptr)
+ {
+ foreach (const QString& sPara, listParas)
+ {
+ iParameter* p = _paraHelper->getPara(sPara, m_sParaSrcTag);
+ if (p != nullptr)
+ {
+ createAndAddItem(pGroup, p, sPara);
+ }
+ }
+ }
+ else
+ {
+ // 在该分组下构建参数项
+ _buildRowUtils(listParas, pGroup, bDnMode, bProperOrder);
+ }
}
}
diff --git a/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp b/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp
index b1c47bb..9824adb 100644
--- a/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp
+++ b/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp
@@ -1,4 +1,4 @@
-#include "nmPlotGraphicBinder.h"
+#include "nmPlotGraphicBinder.h"
#include "nmObjLineFault.h"
#include "nmDataFault.h"
@@ -30,10 +30,30 @@
#include "Defines.h"
#include "iDataTypes.h"
#include "zxSysUtils.h"
+#include "IxPtyPano.h"
+#include "IxPtyItem.h"
#include
#include
+namespace {
+
+// 参数面板回写图元后,同步当前选中对象的左侧属性项。
+void refreshPropertyValue(nmObjBase* pGraphic, const QString& key, const QVariant& value)
+{
+ if (pGraphic == nullptr || !pGraphic->isSelected()) return;
+
+ IxPtyPano* pPano = pGraphic->getPtyPano();
+ if (pPano == nullptr) return;
+
+ IxPtyItem* pItem = pPano->findPropertyItem(key);
+ if (pItem != nullptr && pItem->getValue() != value) {
+ pItem->setValue(value, pGraphic);
+ }
+}
+
+}
+
nmPlotGraphicBinder::WellRenderData::WellRenderData()
: valid(false)
, wellType(Vertical_Well)
@@ -73,7 +93,7 @@ void nmPlotGraphicBinder::createFaultForGraphic(nmObjLineFault* pGraphic)
// 建立信号连接
_connectFault(pGraphic, pData);
- m_pDataMgr->notifyDataChanged();
+ m_pDataMgr->notifyGeometryListChanged();
}
// 从文件加载:绑定已有数据到已有图元
@@ -84,6 +104,7 @@ void nmPlotGraphicBinder::bindFaultToGraphic(nmObjLineFault* pGraphic, nmDataFau
}
// 将数据值推到图元
+ pGraphic->setName(pData->getFaultName());
_pushFaultDataToGraphic(pGraphic, pData);
// 建立信号连接
@@ -122,6 +143,9 @@ void nmPlotGraphicBinder::syncFaultName(nmObjLineFault* pGraphic)
nmDataFault* pData = m_mapFaultData.value(pGraphic, nullptr);
if (pData && pData->getFaultName() != pGraphic->getName()) {
pData->setFaultName(pGraphic->getName());
+ if (m_pDataMgr) {
+ m_pDataMgr->notifyParameterObjectNameChanged();
+ }
}
}
@@ -149,16 +173,22 @@ void nmPlotGraphicBinder::updateDataMgr(nmDataAnalyzeManager* pDataMgr)
void nmPlotGraphicBinder::_pushFaultDataToGraphic(nmObjLineFault* pGraphic, nmDataFault* pData)
{
// 阻断信号,防止推送中触发反向同步
- pGraphic->blockSignals(true);
+ bool bOldSignalsBlocked = pGraphic->blockSignals(true);
- pGraphic->setName(pData->getFaultName());
+ pGraphic->setAllValues(pData->getFaultPoints());
int flowModel = (pData->getFaultFlowModel().getValue() == tr("Leaky")) ? 0 : 1;
pGraphic->setFaultFlowModel(flowModel);
pGraphic->setFaultLeakage(pData->getFaultLeakage().getValue().toDouble());
- pGraphic->blockSignals(false);
+ pGraphic->blockSignals(bOldSignalsBlocked);
+
+ refreshPropertyValue(pGraphic, "ObjLineFaultStartPos.StartPointX", pData->getStartX().getValue());
+ refreshPropertyValue(pGraphic, "ObjLineFaultStartPos.StartPointY", pData->getStartY().getValue());
+ refreshPropertyValue(pGraphic, "ObjLineFaultEndPos.EndPointX", pData->getEndX().getValue());
+ refreshPropertyValue(pGraphic, "ObjLineFaultEndPos.EndPointY", pData->getEndY().getValue());
+ pGraphic->update();
}
// 建立图元与数据的双向信号连接
@@ -175,6 +205,8 @@ void nmPlotGraphicBinder::_connectFault(nmObjLineFault* pGraphic, nmDataFault* p
QObject::connect(pGraphic, SIGNAL(sigObjVisibleChanged(bool)),
this, SLOT(onGraphicVisibleChanged(bool)));
+ QObject::connect(pData, SIGNAL(sigFaultDataChanged()),
+ this, SLOT(onFaultDataChanged()), Qt::UniqueConnection);
m_mapFaultData[pGraphic] = pData;
@@ -198,6 +230,12 @@ void nmPlotGraphicBinder::_disconnectFault(nmObjLineFault* pGraphic)
QObject::disconnect(pGraphic, SIGNAL(sigObjVisibleChanged(bool)),
this, SLOT(onGraphicVisibleChanged(bool)));
+ nmDataFault* pData = m_mapFaultData.value(pGraphic, nullptr);
+ if (pData != nullptr) {
+ QObject::disconnect(pData, SIGNAL(sigFaultDataChanged()),
+ this, SLOT(onFaultDataChanged()));
+ }
+
m_setBoundGraphics.remove(pGraphic);
}
@@ -241,7 +279,6 @@ void nmPlotGraphicBinder::onGraphicPointsChanged()
if (!pData) return;
pData->setFaultPoints(pGraphic->getAllValues());
- pData->setFaultName(pGraphic->getName());
if (m_pDataMgr) {
m_pDataMgr->notifyDataChanged();
@@ -260,6 +297,18 @@ void nmPlotGraphicBinder::onGraphicVisibleChanged(bool bVisible)
pData->setPlotVisible(bVisible);
}
+// 数据参数变更 -> 同步到图元和左侧属性面板
+void nmPlotGraphicBinder::onFaultDataChanged()
+{
+ nmDataFault* pData = qobject_cast(sender());
+ if (!pData) return;
+
+ nmObjLineFault* pGraphic = m_mapFaultData.key(pData, nullptr);
+ if (pGraphic) {
+ _pushFaultDataToGraphic(pGraphic, pData);
+ }
+}
+
// 数据变更(预留)
void nmPlotGraphicBinder::onDataChanged()
{
@@ -269,6 +318,11 @@ void nmPlotGraphicBinder::onDataChanged()
// 用户画完裂缝后:创建数据对象并建立绑定
void nmPlotGraphicBinder::createCrackForGraphic(nmObjLineCrack* pGraphic)
+{
+ createCrackForGraphic(pGraphic, true);
+}
+
+void nmPlotGraphicBinder::createCrackForGraphic(nmObjLineCrack* pGraphic, bool bNotifyGeometryList)
{
if (!pGraphic || !m_pDataMgr) {
return;
@@ -293,7 +347,11 @@ void nmPlotGraphicBinder::createCrackForGraphic(nmObjLineCrack* pGraphic)
// 建立信号连接
_connectCrack(pGraphic, pData);
- m_pDataMgr->notifyDataChanged();
+ if (bNotifyGeometryList) {
+ m_pDataMgr->notifyGeometryListChanged();
+ } else {
+ m_pDataMgr->notifyDataChanged();
+ }
}
// 从文件加载:绑定已有裂缝数据到已有图元
@@ -304,6 +362,7 @@ void nmPlotGraphicBinder::bindCrackToGraphic(nmObjLineCrack* pGraphic, nmDataFra
}
// 将数据值推到图元
+ pGraphic->setName(pData->getFractureName());
_pushCrackDataToGraphic(pGraphic, pData);
// 建立信号连接
@@ -342,6 +401,10 @@ void nmPlotGraphicBinder::syncCrackName(nmObjLineCrack* pGraphic)
nmDataFracture* pData = m_mapCrackData.value(pGraphic, nullptr);
if (pData && pData->getFractureName() != pGraphic->getName()) {
pData->setFractureName(pGraphic->getName());
+ // DFN 裂缝不在参数面板中显示,改名时无需重建面板。
+ if (m_pDataMgr && pData->getFractureType().getValue().toString() != "DFN") {
+ m_pDataMgr->notifyParameterObjectNameChanged();
+ }
}
}
@@ -349,9 +412,9 @@ void nmPlotGraphicBinder::syncCrackName(nmObjLineCrack* pGraphic)
void nmPlotGraphicBinder::_pushCrackDataToGraphic(nmObjLineCrack* pGraphic, nmDataFracture* pData)
{
// 阻断信号,防止推送中触发反向同步
- pGraphic->blockSignals(true);
+ bool bOldSignalsBlocked = pGraphic->blockSignals(true);
- pGraphic->setName(pData->getFractureName());
+ pGraphic->setAllValues(pData->getFracturePoints());
int flowModel = (pData->getFractureFlowModel().getValue() == tr("Infinite Conductivity")) ? 0 : 1;
pGraphic->setCrackFlowModel(flowModel);
@@ -359,7 +422,14 @@ void nmPlotGraphicBinder::_pushCrackDataToGraphic(nmObjLineCrack* pGraphic, nmDa
pGraphic->setCrackDfc(pData->getFractureDfc().getValue().toDouble());
pGraphic->setCrackDw(pData->getFractureDw().getValue().toDouble());
- pGraphic->blockSignals(false);
+ pGraphic->blockSignals(bOldSignalsBlocked);
+
+ refreshPropertyValue(pGraphic, "ObjLineCrackStartPos.StartPointX", pData->getStartX().getValue());
+ refreshPropertyValue(pGraphic, "ObjLineCrackStartPos.StartPointY", pData->getStartY().getValue());
+ refreshPropertyValue(pGraphic, "ObjLineCrackEndPos.EndPointX", pData->getEndX().getValue());
+ refreshPropertyValue(pGraphic, "ObjLineCrackEndPos.EndPointY", pData->getEndY().getValue());
+ refreshPropertyValue(pGraphic, "ObjLineFracture.dFc", pData->getFractureDfc().getValue());
+ pGraphic->update();
}
// 建立裂缝图元与数据的双向信号连接
@@ -379,6 +449,8 @@ void nmPlotGraphicBinder::_connectCrack(nmObjLineCrack* pGraphic, nmDataFracture
QObject::connect(pGraphic, SIGNAL(sigObjVisibleChanged(bool)),
this, SLOT(onGraphicCrackVisibleChanged(bool)));
+ QObject::connect(pData, SIGNAL(sigFractureDataChanged()),
+ this, SLOT(onFractureDataChanged()), Qt::UniqueConnection);
m_mapCrackData[pGraphic] = pData;
@@ -405,6 +477,12 @@ void nmPlotGraphicBinder::_disconnectCrack(nmObjLineCrack* pGraphic)
QObject::disconnect(pGraphic, SIGNAL(sigObjVisibleChanged(bool)),
this, SLOT(onGraphicCrackVisibleChanged(bool)));
+ nmDataFracture* pData = m_mapCrackData.value(pGraphic, nullptr);
+ if (pData != nullptr) {
+ QObject::disconnect(pData, SIGNAL(sigFractureDataChanged()),
+ this, SLOT(onFractureDataChanged()));
+ }
+
m_setBoundCrackGraphics.remove(pGraphic);
}
@@ -431,9 +509,9 @@ void nmPlotGraphicBinder::onGraphicCrackDfcChanged(double dfc)
nmDataFracture* pData = m_mapCrackData.value(pGraphic, nullptr);
if (!pData) return;
- nmDataAttribute attr = pData->getFractureDfc();
- attr.setValue(dfc);
- pData->setFractureDfc(attr);
+ if (pData->getFractureDfc().getValue().toDouble() != dfc) {
+ pData->getFractureDfc().setValue(dfc);
+ }
}
// 裂缝储能比变更
@@ -460,7 +538,6 @@ void nmPlotGraphicBinder::onGraphicCrackPointsChanged()
if (!pData) return;
pData->setFracturePoints(pGraphic->getAllValues());
- pData->setFractureName(pGraphic->getName());
if (m_pDataMgr) {
m_pDataMgr->notifyDataChanged();
@@ -479,6 +556,18 @@ void nmPlotGraphicBinder::onGraphicCrackVisibleChanged(bool bVisible)
pData->setPlotVisible(bVisible);
}
+// 数据参数变更 -> 同步到图元和左侧属性面板
+void nmPlotGraphicBinder::onFractureDataChanged()
+{
+ nmDataFracture* pData = qobject_cast(sender());
+ if (!pData) return;
+
+ nmObjLineCrack* pGraphic = m_mapCrackData.key(pData, nullptr);
+ if (pGraphic) {
+ _pushCrackDataToGraphic(pGraphic, pData);
+ }
+}
+
// ==================== 边界图元绑定 ====================
// 圆形边界:用户画完后创建数据并绑定
@@ -508,7 +597,7 @@ void nmPlotGraphicBinder::createOutlineForGraphic(nmObjRoundOutline* pGraphic)
pData->setBackgrdAlpha(roundClr.alpha());
pData->setVisualPropsValid(true);
- double qradius = pGraphic->getAllValues()[2].y() - pGraphic->getAllValues()[0].y();
+ double qradius = qAbs(pGraphic->getAllValues()[2].y() - pGraphic->getAllValues()[0].y());
pData->setRadius(qradius);
pData->setCenter(pGraphic->getAllValues()[0]);
@@ -517,7 +606,7 @@ void nmPlotGraphicBinder::createOutlineForGraphic(nmObjRoundOutline* pGraphic)
_connectOutline(pGraphic, pData);
if (m_pDataMgr) {
- m_pDataMgr->notifyDataChanged();
+ m_pDataMgr->notifyGeometryListChanged();
}
}
@@ -551,7 +640,7 @@ void nmPlotGraphicBinder::createOutlineForGraphic(nmObjRectOutline* pGraphic)
_connectOutline(pGraphic, pData);
if (m_pDataMgr) {
- m_pDataMgr->notifyDataChanged();
+ m_pDataMgr->notifyGeometryListChanged();
}
}
@@ -585,7 +674,7 @@ void nmPlotGraphicBinder::createOutlineForGraphic(nmObjPolygonOutline* pGraphic)
_connectOutline(pGraphic, pData);
if (m_pDataMgr) {
- m_pDataMgr->notifyDataChanged();
+ m_pDataMgr->notifyGeometryListChanged();
}
}
@@ -597,6 +686,7 @@ void nmPlotGraphicBinder::bindOutlineToGraphic(nmObjBase* pGraphic, nmDataOutlin
m_mapOutlineData[pGraphic] = pData;
m_setBoundOutlineGraphics.insert(pGraphic);
+ pGraphic->setName(pData->getName());
_pushOutlineDataToGraphic(pGraphic, pData);
_connectOutline(pGraphic, pData);
}
@@ -606,12 +696,13 @@ void nmPlotGraphicBinder::removeOutlineBinding(nmObjBase* pGraphic)
{
if (!pGraphic) return;
+ nmDataOutline* pData = m_mapOutlineData.value(pGraphic, nullptr);
+
_disconnectOutline(pGraphic);
m_mapOutlineData.remove(pGraphic);
- if (m_pDataMgr) {
+ if (m_pDataMgr && pData != nullptr && m_pDataMgr->getOutlineData() == pData) {
m_pDataMgr->removeOutlineData();
- m_pDataMgr->notifyDataChanged();
}
}
@@ -628,6 +719,9 @@ void nmPlotGraphicBinder::syncOutlineName(nmObjBase* pGraphic)
nmDataOutline* pData = m_mapOutlineData.value(pGraphic, nullptr);
if (pData && pData->getName() != pGraphic->getName()) {
pData->setName(pGraphic->getName());
+ if (m_pDataMgr) {
+ m_pDataMgr->notifyParameterObjectNameChanged();
+ }
}
}
@@ -669,17 +763,20 @@ void nmPlotGraphicBinder::syncOutlineVisual(nmObjBase* pGraphic)
pData->setVisualPropsValid(true);
}
-// 建立边界图元与数据的信号连接(三条信号)
+// 建立边界图元与数据的信号连接
void nmPlotGraphicBinder::_connectOutline(nmObjBase* pGraphic, nmDataOutline* pData)
{
QObject::connect(pGraphic, SIGNAL(sigOutlinePointsChanged()),
- this, SLOT(onGraphicOutlinePointsChanged()));
+ this, SLOT(onGraphicOutlinePointsChanged()), Qt::UniqueConnection);
QObject::connect(pGraphic, SIGNAL(sigOutlineFlowTypeChanged()),
- this, SLOT(onGraphicOutlineFlowTypeChanged()));
+ this, SLOT(onGraphicOutlineFlowTypeChanged()), Qt::UniqueConnection);
QObject::connect(pGraphic, SIGNAL(sigObjVisibleChanged(bool)),
- this, SLOT(onGraphicOutlineVisibleChanged(bool)));
+ this, SLOT(onGraphicOutlineVisibleChanged(bool)), Qt::UniqueConnection);
+
+ QObject::connect(pData, SIGNAL(sigOutlineDataChanged()),
+ this, SLOT(onOutlineDataChanged()), Qt::UniqueConnection);
m_setBoundOutlineGraphics.insert(pGraphic);
@@ -705,15 +802,29 @@ void nmPlotGraphicBinder::_disconnectOutline(nmObjBase* pGraphic)
QObject::disconnect(pGraphic, SIGNAL(sigObjVisibleChanged(bool)),
this, SLOT(onGraphicOutlineVisibleChanged(bool)));
+ nmDataOutline* pData = m_mapOutlineData.value(pGraphic, nullptr);
+ if (pData != nullptr) {
+ QObject::disconnect(pData, SIGNAL(sigOutlineDataChanged()),
+ this, SLOT(onOutlineDataChanged()));
+ }
+
+ if (nmObjRoundOutline* pRound = dynamic_cast(pGraphic)) {
+ pRound->setGraphicBinder(nullptr);
+ } else if (nmObjRectOutline* pRect = dynamic_cast(pGraphic)) {
+ pRect->setGraphicBinder(nullptr);
+ } else if (nmObjPolygonOutline* pPolygon = dynamic_cast(pGraphic)) {
+ pPolygon->setGraphicBinder(nullptr);
+ }
+
m_setBoundOutlineGraphics.remove(pGraphic);
}
-// 从边界数据对象读取值,写入图元本地副本(加载时用)
+// 从边界数据对象读取值,写入图元本地副本(加载及参数变更时用)
void nmPlotGraphicBinder::_pushOutlineDataToGraphic(nmObjBase* pGraphic, nmDataOutline* pData)
{
- pGraphic->blockSignals(true);
+ bool bOldSignalsBlocked = pGraphic->blockSignals(true);
- pGraphic->setName(pData->getName());
+ pGraphic->setAllValues(pData->getOutlinePoints());
QVector flowTypes = pData->getFlowTypeList();
@@ -749,7 +860,8 @@ void nmPlotGraphicBinder::_pushOutlineDataToGraphic(nmObjBase* pGraphic, nmDataO
}
}
- pGraphic->blockSignals(false);
+ pGraphic->blockSignals(bOldSignalsBlocked);
+ pGraphic->update();
}
// ==================== 边界图元信号 → 数据同步 ====================
@@ -763,20 +875,38 @@ void nmPlotGraphicBinder::onGraphicOutlinePointsChanged()
nmDataOutline* pData = m_mapOutlineData.value(pGraphic, nullptr);
if (!pData) return;
- pData->setOutlinePoints(pGraphic->getAllValues());
+ const int nOldPointCount = pData->getOutlinePointCount();
+ const QVector points = pGraphic->getAllValues();
+ pData->setOutlinePoints(points);
// 圆形边界额外同步 radius 和 center
if (nmObjRoundOutline* pRound = dynamic_cast(pGraphic)) {
QVector pts = pRound->getAllValues();
if (pts.count() >= 3) {
- double radius = pts[2].y() - pts[0].y();
+ double radius = qAbs(pts[2].y() - pts[0].y());
pData->setRadius(radius);
pData->setCenter(pts[0]);
}
}
if (m_pDataMgr) {
- m_pDataMgr->notifyDataChanged();
+ if (nOldPointCount != points.count()) {
+ m_pDataMgr->notifyGeometryListChanged();
+ } else {
+ m_pDataMgr->notifyDataChanged();
+ }
+ }
+}
+
+// 数据参数变更 -> 同步到图元
+void nmPlotGraphicBinder::onOutlineDataChanged()
+{
+ nmDataOutline* pData = qobject_cast(sender());
+ if (!pData) return;
+
+ nmObjBase* pGraphic = m_mapOutlineData.key(pData, nullptr);
+ if (pGraphic) {
+ _pushOutlineDataToGraphic(pGraphic, pData);
}
}
@@ -938,7 +1068,7 @@ void nmPlotGraphicBinder::createRegionMarkForGraphic(nmObjRegionMark* pGraphic)
// 建立信号连接
_connectRegionMark(pGraphic, pData);
- m_pDataMgr->notifyDataChanged();
+ m_pDataMgr->notifyGeometryListChanged();
}
// 从文件加载:绑定已有区域标记数据到已有图元
@@ -980,7 +1110,12 @@ void nmPlotGraphicBinder::syncRegionMarkData(nmObjRegionMark* pGraphic)
nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr);
if (!pData) return;
- pData->setRegionMarkName(pGraphic->getName());
+ if (pData->getRegionMarkName() != pGraphic->getName()) {
+ pData->setRegionMarkName(pGraphic->getName());
+ if (m_pDataMgr) {
+ m_pDataMgr->notifyParameterObjectNameChanged();
+ }
+ }
pData->setBackgroundColor(pGraphic->getBackgrdColor());
pData->setSelectRegion(pGraphic->getSelectRegion());
@@ -1026,9 +1161,9 @@ void nmPlotGraphicBinder::onGraphicRegionMarkComKrChanged(double comKr)
nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr);
if (!pData) return;
- nmDataAttribute attr = pData->getComKr();
- attr.setValue(comKr);
- pData->setComKr(attr);
+ if (pData->getComKr().getValue().toDouble() != comKr) {
+ pData->getComKr().setValue(comKr);
+ }
if (m_pDataMgr) {
m_pDataMgr->notifyDataChanged();
@@ -1043,9 +1178,9 @@ void nmPlotGraphicBinder::onGraphicRegionMarkComWChanged(double comW)
nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr);
if (!pData) return;
- nmDataAttribute attr = pData->getComW();
- attr.setValue(comW);
- pData->setComW(attr);
+ if (pData->getComW().getValue().toDouble() != comW) {
+ pData->getComW().setValue(comW);
+ }
if (m_pDataMgr) {
m_pDataMgr->notifyDataChanged();
@@ -1060,9 +1195,9 @@ void nmPlotGraphicBinder::onGraphicRegionMarkNetToGrossChanged(double netToGross
nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr);
if (!pData) return;
- nmDataAttribute attr = pData->getNetToGross();
- attr.setValue(netToGross);
- pData->setNetToGross(attr);
+ if (pData->getNetToGross().getValue().toDouble() != netToGross) {
+ pData->getNetToGross().setValue(netToGross);
+ }
if (m_pDataMgr) {
m_pDataMgr->notifyDataChanged();
@@ -1106,6 +1241,8 @@ void nmPlotGraphicBinder::_connectRegionMark(nmObjRegionMark* pGraphic, nmDataRe
this, SLOT(onGraphicRegionMarkNetToGrossChanged(double)));
connect(pGraphic, SIGNAL(sigObjVisibleChanged(bool)),
this, SLOT(onGraphicRegionMarkVisibleChanged(bool)));
+ connect(pData, SIGNAL(sigRegionMarkDataChanged()),
+ this, SLOT(onRegionMarkDataChanged()), Qt::UniqueConnection);
m_setBoundRegionMarkGraphics.insert(pGraphic);
}
@@ -1130,13 +1267,19 @@ void nmPlotGraphicBinder::_disconnectRegionMark(nmObjRegionMark* pGraphic)
disconnect(pGraphic, SIGNAL(sigObjVisibleChanged(bool)),
this, SLOT(onGraphicRegionMarkVisibleChanged(bool)));
+ nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr);
+ if (pData != nullptr) {
+ disconnect(pData, SIGNAL(sigRegionMarkDataChanged()),
+ this, SLOT(onRegionMarkDataChanged()));
+ }
+
m_setBoundRegionMarkGraphics.remove(pGraphic);
}
-// 从数据对象读取值,写入图元本地副本(加载时用)
+// 从数据对象读取值,写入图元本地副本(加载及参数变更时用)
void nmPlotGraphicBinder::_pushRegionMarkDataToGraphic(nmObjRegionMark* pGraphic, nmDataRegionMark* pData)
{
- pGraphic->blockSignals(true);
+ bool bOldSignalsBlocked = pGraphic->blockSignals(true);
// 储层类型:字符串 → int
if (pData->getReservoirType().getValue() == "Homogeneous") {
@@ -1154,7 +1297,24 @@ void nmPlotGraphicBinder::_pushRegionMarkDataToGraphic(nmObjRegionMark* pGraphic
pts << pData->getPtPos();
pGraphic->setAllValues(pts);
- pGraphic->blockSignals(false);
+ pGraphic->blockSignals(bOldSignalsBlocked);
+
+ refreshPropertyValue(pGraphic, "ObjRegionMark.dComW", pData->getComW().getValue());
+ refreshPropertyValue(pGraphic, "ObjRegionMark.dComKr", pData->getComKr().getValue());
+ refreshPropertyValue(pGraphic, "ObjRegionMark.NetToGross", pData->getNetToGross().getValue());
+ pGraphic->update();
+}
+
+// 数据参数变更 -> 同步到图元和左侧属性面板
+void nmPlotGraphicBinder::onRegionMarkDataChanged()
+{
+ nmDataRegionMark* pData = qobject_cast(sender());
+ if (!pData) return;
+
+ nmObjRegionMark* pGraphic = m_mapRegionMarkData.key(pData, nullptr);
+ if (pGraphic) {
+ _pushRegionMarkDataToGraphic(pGraphic, pData);
+ }
}
// ==================== 复合区图元 ====================
@@ -1197,7 +1357,7 @@ void nmPlotGraphicBinder::createRegionForGraphic(nmObjRegion* pGraphic)
// 建立信号连接
_connectRegion(pGraphic, pData);
- m_pDataMgr->notifyDataChanged();
+ m_pDataMgr->notifyGeometryListChanged();
}
// 从文件加载:绑定已有数据到已有图元
@@ -1240,7 +1400,12 @@ void nmPlotGraphicBinder::syncRegionData(nmObjRegion* pGraphic)
if (!pData) return;
// 兜底同步:名称、位置
- pData->setRegionName(pGraphic->getName());
+ if (pData->getRegoinName() != pGraphic->getName()) {
+ pData->setRegionName(pGraphic->getName());
+ if (m_pDataMgr) {
+ m_pDataMgr->notifyParameterObjectNameChanged();
+ }
+ }
pData->setVecPts(pGraphic->getAllValues());
// 视觉属性兜底同步:画笔宽度、填充背景色
@@ -1304,9 +1469,9 @@ void nmPlotGraphicBinder::onGraphicRegionLeakageChanged(double leakage)
nmDataRegion* pData = m_mapRegionData.value(pGraphic, nullptr);
if (!pData) return;
- nmDataAttribute attr = pData->getRegionLeakage();
- attr.setValue(leakage);
- pData->setRegionLeakage(attr);
+ if (pData->getRegionLeakage().getValue().toDouble() != leakage) {
+ pData->getRegionLeakage().setValue(leakage);
+ }
}
void nmPlotGraphicBinder::onGraphicRegionVisibleChanged(bool bVisible)
@@ -1332,6 +1497,8 @@ void nmPlotGraphicBinder::_connectRegion(nmObjRegion* pGraphic, nmDataRegion* pD
this, SLOT(onGraphicRegionLeakageChanged(double)));
connect(pGraphic, SIGNAL(sigObjVisibleChanged(bool)),
this, SLOT(onGraphicRegionVisibleChanged(bool)));
+ connect(pData, SIGNAL(sigRegionDataChanged()),
+ this, SLOT(onRegionDataChanged()), Qt::UniqueConnection);
m_setBoundRegionGraphics.insert(pGraphic);
}
@@ -1349,15 +1516,21 @@ void nmPlotGraphicBinder::_disconnectRegion(nmObjRegion* pGraphic)
disconnect(pGraphic, SIGNAL(sigObjVisibleChanged(bool)),
this, SLOT(onGraphicRegionVisibleChanged(bool)));
+ nmDataRegion* pData = m_mapRegionData.value(pGraphic, nullptr);
+ if (pData != nullptr) {
+ disconnect(pData, SIGNAL(sigRegionDataChanged()),
+ this, SLOT(onRegionDataChanged()));
+ }
+
m_setBoundRegionGraphics.remove(pGraphic);
}
-// 从数据对象读取值,写入图元本地副本(加载时用)
+// 从数据对象读取值,写入图元本地副本(加载及参数变更时用)
void nmPlotGraphicBinder::_pushRegionDataToGraphic(nmObjRegion* pGraphic, nmDataRegion* pData)
{
if (!pGraphic || !pData) return;
- pGraphic->blockSignals(true);
+ bool bOldSignalsBlocked = pGraphic->blockSignals(true);
// 流动模型:字符串 → int
if (pData->getRegionFlowModel().getValue() == "Leaky") {
@@ -1374,7 +1547,22 @@ void nmPlotGraphicBinder::_pushRegionDataToGraphic(nmObjRegion* pGraphic, nmData
pGraphic->setPen(pen);
pGraphic->setBackgrdColor(pData->getBackgrdColor());
- pGraphic->blockSignals(false);
+ pGraphic->blockSignals(bOldSignalsBlocked);
+
+ refreshPropertyValue(pGraphic, "ObjRegion.Leakage", pData->getRegionLeakage().getValue());
+ pGraphic->update();
+}
+
+// 数据参数变更 -> 同步到图元和左侧属性面板
+void nmPlotGraphicBinder::onRegionDataChanged()
+{
+ nmDataRegion* pData = qobject_cast(sender());
+ if (!pData) return;
+
+ nmObjRegion* pGraphic = m_mapRegionData.key(pData, nullptr);
+ if (pGraphic) {
+ _pushRegionDataToGraphic(pGraphic, pData);
+ }
}
// ==================== 井图元 ====================
@@ -1441,15 +1629,20 @@ void nmPlotGraphicBinder::syncWellData(nmObjPointWell* pGraphic)
// 同步名称(用户在属性面板改名后,同步到数据中心和框架数据)
QString sName = pGraphic->getName();
+ bool bNameChanged = false;
if (!sName.isEmpty()) {
if (pData->getWellName() != sName) {
pData->setWellName(sName);
+ bNameChanged = true;
}
if (pWellData && pWellData->getName() != sName) {
pWellData->setName(sName);
pWellData->save();
}
}
+ if (bNameChanged && m_pDataMgr) {
+ m_pDataMgr->notifyParameterObjectNameChanged();
+ }
if (pWellData) {
// 数值井数据是分析侧的数据源,这里回写到框架井数据,保证保存工程树时一致。
diff --git a/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp b/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp
index ca66e6c..d21b127 100644
--- a/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp
+++ b/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp
@@ -1,4 +1,4 @@
-#include "zxLogInstance.h"
+#include "zxLogInstance.h"
#include "iRibbonXmlCmd.h"
#include
#include
@@ -374,6 +374,10 @@ void nmSubWndUtils::connectWellListSignals(nmDataAnalyzeManager* pDataManager,
QObject::connect(pDataManager, SIGNAL(sigWellRemoved(QString,QString)),
pParaWx, SLOT(slotWellRemoved(QString,QString)),
Qt::UniqueConnection);
+ // 参数对象新增、删除或改名后重建面板;队列连接避免在图元绘制过程中直接刷新。
+ QObject::connect(pDataManager, SIGNAL(sigGeometryListChanged()),
+ pParaWx, SLOT(slotGeometryListChanged()),
+ static_cast(Qt::QueuedConnection | Qt::UniqueConnection));
}
bool nmSubWndUtils::fillNmDockWxs(iSubWnd* pSubWnd)
diff --git a/Src/nmNum/nmSubWxs/nmWxDFNGenerateDlg.cpp b/Src/nmNum/nmSubWxs/nmWxDFNGenerateDlg.cpp
index 0d137d1..bbbba56 100644
--- a/Src/nmNum/nmSubWxs/nmWxDFNGenerateDlg.cpp
+++ b/Src/nmNum/nmSubWxs/nmWxDFNGenerateDlg.cpp
@@ -484,7 +484,8 @@ void nmWxDFNGenerateDlg::generateFractures()
// 通过 Binder 创建裂缝数据并建立信号连接
nmPlotGraphicBinder* pBinder = plot->graphicBinder();
if (pBinder) {
- pBinder->createCrackForGraphic(crack);
+ // DFN 不进入独立裂缝参数面板,批量生成时也不重复刷新对象列表。
+ pBinder->createCrackForGraphic(crack, false);
}
// 设置属性为 DFN
nmDataFracture* pData = pBinder ? pBinder->getCrackDataFor(crack) : nullptr;
diff --git a/Src/nmNum/nmSubWxs/nmWxParaPropertyPebi.cpp b/Src/nmNum/nmSubWxs/nmWxParaPropertyPebi.cpp
index 8497381..0f30cb0 100644
--- a/Src/nmNum/nmSubWxs/nmWxParaPropertyPebi.cpp
+++ b/Src/nmNum/nmSubWxs/nmWxParaPropertyPebi.cpp
@@ -1,4 +1,4 @@
-
+
#include "zxLogInstance.h"
#include "ZxResolutionHelper.h"
#include "zxSysUtils.h"
@@ -12,6 +12,11 @@
#include "nmGridRowUtils.h"
#include "nmDataAnalyzeManager.h"
#include "nmDataWellBase.h"
+#include "nmDataFracture.h"
+#include "nmDataFault.h"
+#include "nmDataRegion.h"
+#include "nmDataRegionMark.h"
+#include "nmDataOutline.h"
#include "nmAttrRegistry.h"
#include
@@ -57,6 +62,57 @@ QStringList wellParasOf(const QString& wellCode, bool hasPerforation, NM_WELL_MO
return paras;
}
+// XML 只定义基础参数名,运行时拼接对象编码以区分多个同类对象。
+QStringList fractureParasOf(const QString& fractureCode)
+{
+ return QStringList() << fractureCode + "_F_X0"
+ << fractureCode + "_F_Y0"
+ << fractureCode + "_F_X1"
+ << fractureCode + "_F_Y1"
+ << fractureCode + "_F_FC";
+}
+
+QStringList faultParasOf(const QString& faultCode)
+{
+ return QStringList() << faultCode + "_FT_X0"
+ << faultCode + "_FT_Y0"
+ << faultCode + "_FT_X1"
+ << faultCode + "_FT_Y1";
+}
+
+QStringList regionParasOf(const QString& regionCode)
+{
+ return QStringList() << regionCode + "_R_Leakage";
+}
+
+QStringList regionMarkParasOf(const QString& regionMarkCode)
+{
+ return QStringList() << regionMarkCode + "_RM_ComW"
+ << regionMarkCode + "_RM_ComKr"
+ << regionMarkCode + "_RM_NetToGross";
+}
+
+QStringList rectBoundaryParasOf(const QString& boundaryCode)
+{
+ return QStringList() << boundaryCode + "_BR_XMin"
+ << boundaryCode + "_BR_YMin"
+ << boundaryCode + "_BR_XMax"
+ << boundaryCode + "_BR_YMax";
+}
+
+QStringList roundBoundaryParasOf(const QString& boundaryCode)
+{
+ return QStringList() << boundaryCode + "_BC_CenterX"
+ << boundaryCode + "_BC_CenterY"
+ << boundaryCode + "_BC_Radius";
+}
+
+QStringList polygonPointParasOf(const QString& pointCode)
+{
+ return QStringList() << pointCode + "_BP_X"
+ << pointCode + "_BP_Y";
+}
+
}
nmWxParaPropertyPebi::nmWxParaPropertyPebi(QWidget* parent) :
@@ -133,7 +189,7 @@ void nmWxParaPropertyPebi::initUI_HelpBox()
}
void nmWxParaPropertyPebi::refreshUIs(QStringList& listParas, bool bReserveOlds /*= true*/,
- QMap mapWellNames /*= QMap()*/)
+ QMap mapObjectNames /*= QMap()*/)
{
if (nullptr == m_pMainLayout)
{
@@ -163,7 +219,7 @@ void nmWxParaPropertyPebi::refreshUIs(QStringList& listParas, bool bReserveOlds
connect(m_pGridItemUtils, SIGNAL(sigHelpMsg(QString&)),
this, SLOT(slotHelpMsg(QString&)));
m_pMainLayout->addWidget(m_pGridItemUtils);
- m_pGridItemUtils->setWellNames(mapWellNames);
+ m_pGridItemUtils->setWellNames(mapObjectNames);
m_pGridItemUtils->buildRowUtils(listParas, false, this);
// 恢复原有的参数内容
@@ -198,7 +254,7 @@ void nmWxParaPropertyPebi::restoreOldParas(QMap& map)
QString sPara = iter.key();
iParameter* p = _paraHelper->getPara(sPara, s_Nm_Serie);
- // 带前缀的井参数(如 "W001_W_X")在 XML 中查不到,需剥掉 wellCode 前缀
+ // 带对象编码前缀的参数在 XML 中查不到,需先剥掉运行时前缀。
if (nullptr == p)
{
QString sBase = m_pGridItemUtils->stripWellPrefix(sPara);
@@ -249,9 +305,10 @@ void nmWxParaPropertyPebi::rebuildAllParas()
return;
m_pDataManager->syncWellAttrs();
+ m_pDataManager->syncGeometryAttrs();
QStringList listParas = reservoirParas();
- QMap mapWellNames;
+ QMap mapObjectNames;
QSet addedWellCodes;
const QVector wells = m_pDataManager->getWellDataList();
foreach (nmDataWellBase* pWell, wells)
@@ -264,13 +321,105 @@ void nmWxParaPropertyPebi::rebuildAllParas()
continue;
addedWellCodes.insert(sCode);
- mapWellNames[sCode] = pWell->getWellName();
+ mapObjectNames[sCode] = pWell->getWellName();
listParas << wellParasOf(sCode,
pWell->getPerforationCount() > 0,
pWell->getWellType());
}
- refreshUIs(listParas, false, mapWellNames);
+ int fractureIndex = 0;
+ const QVector fractures = m_pDataManager->getFractureDataList();
+ foreach (nmDataFracture* pFracture, fractures)
+ {
+ // DFN 裂缝由专用功能批量管理,不作为独立裂缝显示。
+ if (pFracture == nullptr || pFracture->getFractureType().getValue().toString() == "DFN")
+ {
+ continue;
+ }
+
+ const QString sCode = QString("FRAC%1").arg(++fractureIndex, 4, 10, QChar('0'));
+ mapObjectNames[sCode] = pFracture->getFractureName();
+ listParas << fractureParasOf(sCode);
+ }
+
+ const QVector faults = m_pDataManager->getFaultDataList();
+ for (int i = 0; i < faults.size(); ++i)
+ {
+ nmDataFault* pFault = faults[i];
+ if (pFault == nullptr)
+ continue;
+
+ const QString sCode = QString("FAULT%1").arg(i + 1, 4, 10, QChar('0'));
+ mapObjectNames[sCode] = pFault->getFaultName();
+ listParas << faultParasOf(sCode);
+ }
+
+ const QVector regions = m_pDataManager->getRegionDataList();
+ for (int i = 0; i < regions.size(); ++i)
+ {
+ nmDataRegion* pRegion = regions[i];
+ if (pRegion == nullptr)
+ continue;
+
+ const QString sCode = QString("REGION%1").arg(i + 1, 4, 10, QChar('0'));
+ mapObjectNames[sCode] = pRegion->getRegoinName();
+ listParas << regionParasOf(sCode);
+ }
+
+ const QVector regionMarks = m_pDataManager->getRegionMarkDataList();
+ for (int i = 0; i < regionMarks.size(); ++i)
+ {
+ nmDataRegionMark* pRegionMark = regionMarks[i];
+ if (pRegionMark == nullptr)
+ continue;
+
+ const QString sCode = QString("RMARK%1").arg(i + 1, 4, 10, QChar('0'));
+ mapObjectNames[sCode] = pRegionMark->getRegionMarkName();
+ listParas << regionMarkParasOf(sCode);
+ }
+
+ nmDataOutline* pOutline = m_pDataManager->getOutlineData();
+ if (pOutline != nullptr)
+ {
+ QString sOutlineName = pOutline->getName();
+ if (pOutline->getOutlineType() == NM_Rect_Outline_Type)
+ {
+ if (sOutlineName.isEmpty())
+ {
+ sOutlineName = tr("RectangleOutline");
+ }
+ const QString sCode = "BOUNDARY";
+ mapObjectNames[sCode] = sOutlineName;
+ listParas << rectBoundaryParasOf(sCode);
+ }
+ else if (pOutline->getOutlineType() == NM_Round_Outline_Type)
+ {
+ if (sOutlineName.isEmpty())
+ {
+ sOutlineName = tr("CircleOutline");
+ }
+ const QString sCode = "BOUNDARY";
+ mapObjectNames[sCode] = sOutlineName;
+ listParas << roundBoundaryParasOf(sCode);
+ }
+ else if (pOutline->getOutlineType() == NM_Polygon_Outline_Type)
+ {
+ if (sOutlineName.isEmpty())
+ {
+ sOutlineName = tr("PolygonOutline");
+ }
+ const QString sBoundaryCode = "BOUNDARY";
+ mapObjectNames[sBoundaryCode] = sOutlineName;
+ for (int i = 0; i < pOutline->getOutlinePointCount(); ++i)
+ {
+ const QString sPointCode = QString("BVERT%1").arg(i + 1, 4, 10, QChar('0'));
+ mapObjectNames[sPointCode] = QString("%1 %2").arg(tr("Point")).arg(i + 1);
+ listParas << polygonPointParasOf(sPointCode);
+ }
+ }
+ }
+
+ refreshUIs(listParas, false, mapObjectNames);
nmAttrRegistry* pReg = m_pDataManager->getAttrRegistry();
if (pReg)
@@ -390,3 +539,9 @@ void nmWxParaPropertyPebi::slotWellRemoved(QString wellCode, QString wellName)
Q_UNUSED(wellName);
rebuildAllParas();
}
+
+// 参数对象新增、删除或改名后,按当前数据完整重建对象分组。
+void nmWxParaPropertyPebi::slotGeometryListChanged()
+{
+ rebuildAllParas();
+}