В этой небольшой статье, я покажу, как создавать любые утилиты для Unigraphics NX с помощью библиотеки NXOpen и языка программирования Java. В моем примере утилита будет строить 2D сетку на все свободных телах и гранях (это может быть полезно для задачи оптимизации).
Необходимую информацию по библиотеке NXOpen можно найти на официальном сайте.
В корневой папки NX лежат необходимые нам библиотеки по умолчанию, а так же примеры:
- C:\Program Files\Siemens\NX 12.0\NXBIN с расширением jar
- C:\Program Files\Siemens\NX 12.0\UGOPEN с расширением jar
- C:\Program Files\Siemens\NX 12.0\UGOPEN\SampleNXOpenApplications\Java.
Для упрощения написания кода можно за основу использовать журнал записи своих действий в текстовый файл. По умолчанию Unigraphics NX записывает на языке Visual Basic, но в настройках можно поменять на Java или на любой другой из списка доступных:
Вот пример записи журнала в текстовый файл:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
// NX 12.0.1.7 // Journal created by Aleksandr on Sun Nov 3 19:49:32 2019 RTZ 2 (зима) // import nxopen.*; public class journalTT { public static void main(String [] args) throws NXException, java.rmi.RemoteException { nxopen.Session theSession = (nxopen.Session)nxopen.SessionFactory.get("Session"); nxopen.cae.FemPart workFemPart = ((nxopen.cae.FemPart)theSession.parts().baseWork()); nxopen.cae.FemPart displayFemPart = ((nxopen.cae.FemPart)theSession.parts().baseDisplay()); // ---------------------------------------------- // Меню: Вставить->Сетка->2D сетка... // ---------------------------------------------- int markId1; markId1 = theSession.setUndoMark(nxopen.Session.MarkVisibility.VISIBLE, "Начало"); nxopen.cae.FEModel fEModel1 = ((nxopen.cae.FEModel)workFemPart.findObject("FEModel")); nxopen.cae.MeshManager meshManager1 = ((nxopen.cae.MeshManager)fEModel1.find("MeshManager")); nxopen.cae.Mesh2d nullNXOpen_CAE_Mesh2d = null; nxopen.cae.Mesh2dBuilder mesh2dBuilder1; mesh2dBuilder1 = meshManager1.createMesh2dBuilder(nullNXOpen_CAE_Mesh2d); nxopen.cae.MeshCollector nullNXOpen_CAE_MeshCollector = null; mesh2dBuilder1.elementType().destinationCollector().setElementContainer(nullNXOpen_CAE_MeshCollector); mesh2dBuilder1.elementType().setElementTypeName("CQUAD4"); nxopen.Unit unit1 = ((nxopen.Unit)workFemPart.unitCollection().findObject("MilliMeter")); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("quad mesh overall edge size", "10", unit1); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("target minimum element edge length", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("surface curvature threshold", "5.05", unit1); nxopen.Unit nullNXOpen_Unit = null; mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("small feature value", "1", nullNXOpen_Unit); theSession.setUndoMarkName(markId1, "Диалоговое окно 2D сетка"); nxopen.DisplayableObject [] objects1 = new nxopen.DisplayableObject[1]; nxopen.cae.CAEBody cAEBody1 = ((nxopen.cae.CAEBody)workFemPart.findObject("CAE_Body(14)")); nxopen.cae.CAEFace cAEFace1 = ((nxopen.cae.CAEFace)cAEBody1.findObject("CAE_Face(14)")); objects1[0] = cAEFace1; boolean added1; added1 = mesh2dBuilder1.selectionList().add(objects1); nxopen.DisplayableObject [] objects2 = new nxopen.DisplayableObject[1]; nxopen.cae.CAEBody cAEBody2 = ((nxopen.cae.CAEBody)workFemPart.findObject("CAE_Body(3)")); nxopen.cae.CAEFace cAEFace2 = ((nxopen.cae.CAEFace)cAEBody2.findObject("CAE_Face(3)")); objects2[0] = cAEFace2; boolean added2; added2 = mesh2dBuilder1.selectionList().add(objects2); nxopen.DisplayableObject [] objects3 = new nxopen.DisplayableObject[1]; nxopen.cae.CAEBody cAEBody3 = ((nxopen.cae.CAEBody)workFemPart.findObject("CAE_Body(2)")); nxopen.cae.CAEFace cAEFace3 = ((nxopen.cae.CAEFace)cAEBody3.findObject("CAE_Face(2)")); objects3[0] = cAEFace3; boolean added3; added3 = mesh2dBuilder1.selectionList().add(objects3); nxopen.DisplayableObject [] objects4 = new nxopen.DisplayableObject[1]; nxopen.cae.CAEBody cAEBody4 = ((nxopen.cae.CAEBody)workFemPart.findObject("CAE_Body(1)")); nxopen.cae.CAEFace cAEFace4 = ((nxopen.cae.CAEFace)cAEBody4.findObject("CAE_Face(1)")); objects4[0] = cAEFace4; boolean added4; added4 = mesh2dBuilder1.selectionList().add(objects4); int markId2; markId2 = theSession.setUndoMark(nxopen.Session.MarkVisibility.INVISIBLE, "2D сетка"); theSession.deleteUndoMark(markId2, null); int markId3; markId3 = theSession.setUndoMark(nxopen.Session.MarkVisibility.INVISIBLE, "2D сетка"); mesh2dBuilder1.setAutoResetOption(false); mesh2dBuilder1.elementType().setElementDimension(nxopen.cae.ElementTypeBuilder.ElementType.SHELL); mesh2dBuilder1.elementType().setElementTypeName("CQUAD4"); nxopen.cae.DestinationCollectorBuilder destinationCollectorBuilder1; destinationCollectorBuilder1 = mesh2dBuilder1.elementType().destinationCollector(); destinationCollectorBuilder1.setElementContainer(nullNXOpen_CAE_MeshCollector); destinationCollectorBuilder1.setAutomaticMode(true); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("meshing method", 0); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("quad mesh overall edge size", "10", unit1); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("block decomposition option bool", false); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("mapped mesh option bool", false); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("fillet num elements", 3); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("num elements on cylinder circumference", 6); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("element size on cylinder height", "1", unit1); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("quad only option", 0); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("mesh individual faces option bool", false); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("midnodes", 0); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("geometry tolerance option bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("geometry tolerance", "0", unit1); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("target maximum element edge length bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("maximum element edge length", "1", unit1); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("target minimum element edge length", false); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("split poor quads bool", false); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("move nodes off geometry bool", false); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("max quad warp option bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("max quad warp", "5", nullNXOpen_Unit); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("max jacobian", "5", nullNXOpen_Unit); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("target element skew bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("element skew", "30", nullNXOpen_Unit); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("max included angle quad option bool", false); nxopen.Unit unit2 = ((nxopen.Unit)workFemPart.unitCollection().findObject("Degrees")); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("max included angle quad", "150", unit2); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("min included angle quad option bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("min included angle quad", "30", unit2); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("max included angle tria option bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("max included angle tria", "150", unit2); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("min included angle tria option bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("min included angle tria", "30", unit2); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("mesh transition bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("mesh size variation", "50", nullNXOpen_Unit); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("surface curvature threshold", "5.05", unit1); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("alternate feature abstraction bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("minimum feature element size", "0.001", unit1); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("small feature tolerance", "10", nullNXOpen_Unit); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("small feature value", "1", nullNXOpen_Unit); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("suppress hole option bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("hole diameter tolerance", "0", unit1); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("hole suppresion point type", 0); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("merge edge toggle bool", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("edge angle", "15", unit2); mesh2dBuilder1.propertyTable().setBooleanPropertyValue("quad mesh edge match toggle", false); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("quad mesh edge match tolerance", "0.02", unit1); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("quad mesh smoothness tolerance", "0.01", unit1); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("quad mesh surface match tolerance", "0.001", unit1); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("quad mesh transitional rows", 3); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("min face angle", "20", unit2); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("mesh time stamp", 0); mesh2dBuilder1.propertyTable().setBaseScalarWithDataPropertyValue("quad mesh node coincidence tolerance", "0.0001", unit1); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("mesh edit allowed", 0); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("transition edge seeding", 0); mesh2dBuilder1.propertyTable().setIntegerPropertyValue("cylinder curved end num elements", 6); int id1; id1 = theSession.newestVisibleUndoMark(); int nErrs1; nErrs1 = theSession.updateManager().doUpdate(id1); nxopen.cae.Mesh [] meshes1 ; meshes1 = mesh2dBuilder1.commitMesh(); theSession.deleteUndoMark(markId3, null); theSession.setUndoMarkName(id1, "2D сетка"); mesh2dBuilder1.destroy(); // ---------------------------------------------- // Меню: Инструменты->Повторить команду->3 Остановка записи журнала // ---------------------------------------------- // ---------------------------------------------- // Меню: Инструменты->Журнал->Остановка записи // ---------------------------------------------- } public static final int getUnloadOption() { return nxopen.BaseSession.LibraryUnloadOption.IMMEDIATELY; } } } |
Сейчас он строит сетку только на тех поверхностях, которые указаны в коде, а если их меньше или больше будет, а также отличатся будут их названия, то nx выдаст ошибку при запуске нашего кода. Поэтому нам нужно доработать код добавив в него исключения try/catch и придумать способ, чтобы мы не привязывались к количеству полигональных граней.
Я сделал это так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
try { for (int i = 1; i < 20; i++) { obj="object"+i; cAEB="cAEBody"+i; cAEF="cAEFace"+i; adde="added"+i; //Object objects = new Object(); nxopen.DisplayableObject [] obj = new nxopen.DisplayableObject[1]; nxopen.cae.CAEBody cAEB = ((nxopen.cae.CAEBody)workFemPart.findObject(("CAE_Body"+"("+i+")"))); nxopen.cae.CAEFace cAEF = ((nxopen.cae.CAEFace)cAEB.findObject("CAE_Face"+"("+i+")")); obj[0] = cAEF; boolean adde; adde = mesh2dBuilder1.selectionList().add(obj); } } catch (Exception ex) { |
Вот конечный результат исполненный в программе: