OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
MeshGenerator.cpp
Go to the documentation of this file.
5#include "Physics/Physics.h"
6#include "Utilities/Util.h"
7
8#include <fstream>
9#include <iostream>
10#include <vector>
11
12extern Inform* gmsg;
13
14namespace {
15 void appendMesh(MeshData& target, const MeshData& source) {
16 const unsigned int offset = target.vertices_m.size();
17 target.vertices_m.insert(
18 target.vertices_m.end(), source.vertices_m.begin(), source.vertices_m.end());
19 for (const auto& triangle : source.triangles_m) {
20 target.triangles_m.push_back(
22 triangle(0) + offset, triangle(1) + offset, triangle(2) + offset));
23 }
24 target.decorations_m.insert(
25 target.decorations_m.end(), source.decorations_m.begin(),
26 source.decorations_m.end());
27 }
28
29 void translateMesh(MeshData& mesh, const double dx, const double dy, const double dz = 0.0) {
30 const Vector_t<double, 3> shift(dx, dy, dz);
31 for (auto& vertex : mesh.vertices_m) {
32 vertex += shift;
33 }
34 for (auto& decoration : mesh.decorations_m) {
35 decoration.first += shift;
36 decoration.second += shift;
37 }
38 }
39
40} // namespace
41
43 : elements_m(), hasDriftReference_m(false), driftMinor_m(0.0), driftMajor_m(0.0) {}
44
45bool MeshGenerator::getTransverseSupport(const ElementBase& element, double& minor, double& major) {
46 if (element.getType() == ElementType::SOLENOID) {
47 const auto* solenoid = dynamic_cast<const Solenoid*>(&element);
48 double horizontalRadius = 0.0;
49 double verticalRadius = 0.0;
50 if (solenoid == nullptr
51 || !solenoid->getSupportEnvelope(horizontalRadius, verticalRadius)) {
52 return false;
53 }
54 minor = verticalRadius;
55 major = horizontalRadius;
56 return true;
57 }
58
59 if (element.getType() == ElementType::DRIFT) {
60 return false;
61 }
62
63 const auto apert = element.getAperture();
64 if (apert.second.size() < 3) {
65 return false;
66 }
67
68 switch (apert.first) {
73 minor = apert.second[0];
74 major = apert.second[1];
75 return true;
76 default:
77 return false;
78 }
79}
80
81void MeshGenerator::setDriftReference(const double minor, const double major) {
82 hasDriftReference_m = minor > 0.0 && major > 0.0;
83 driftMinor_m = minor;
84 driftMajor_m = major;
85}
86
87void MeshGenerator::add(const ElementBase& element) {
88 double start = 0.0;
89
90 MeshData mesh;
91 if (element.getType() == ElementType::SBEND || element.getType() == ElementType::RBEND) {
92 // const Bend2D* dipole = static_cast<const Bend2D*>(&element);
93 // mesh = dipole->getSurfaceMesh();
94 mesh.type_m = DIPOLE;
95 } else if (element.getType() == ElementType::RBEND3D) {
96 // const RBend3D* dipole = static_cast<const RBend3D*>(&element);
97 // mesh = dipole->getSurfaceMesh();
98 mesh.type_m = DIPOLE;
99 } else if (element.getType() == ElementType::SOLENOID) {
100 double end = 0.0;
101 element.getElementDimensions(start, end);
102 mesh = getCylinder(end - start, driftMinor_m, driftMajor_m, 1.0);
103 {
104 double minor = 0.0;
105 double major = 0.0;
106 if (getTransverseSupport(element, minor, major)) {
107 mesh = getSolenoid(end - start, minor, major);
108 }
109 }
110 mesh.type_m = SOLENOID;
111 } else if (element.getType() == ElementType::DRIFT) {
112 if (!hasDriftReference_m) {
113 return;
114 }
115 double end = 0.0;
116 element.getElementDimensions(start, end);
117 mesh = getTube(
118 end - start, 0.7 * driftMinor_m, 0.7 * driftMajor_m, driftMinor_m, driftMajor_m);
119 mesh.type_m = DRIFT;
120 } else {
121 double end, length;
122 if (element.getType() == ElementType::RFCAVITY
123 || element.getType() == ElementType::TRAVELINGWAVE) {
124 start = 0.0;
125 end = element.getElementLength();
126 } else {
127 element.getElementDimensions(start, end);
128 }
129 length = end - start;
130 auto apert = element.getAperture();
131
132 switch (apert.first) {
135 mesh = getBox(length, apert.second[0], apert.second[1], apert.second[2]);
136 break;
139 if (element.getType() == ElementType::MULTIPOLE
140 && static_cast<const Multipole*>(&element)->getMaxNormalComponentIndex() == 2) {
141 mesh = getQuadrupole(length, apert.second[0], apert.second[1], apert.second[2]);
142 } else if (element.getType() == ElementType::RFCAVITY) {
143 mesh = getRFCavity(length, apert.second[0], apert.second[1]);
144 } else if (element.getType() == ElementType::TRAVELINGWAVE) {
145 mesh = getTravelingWave(length, apert.second[0], apert.second[1]);
146 } else {
147 mesh = getCylinder(length, apert.second[0], apert.second[1], apert.second[2]);
148 }
149 break;
150 default:
151 return;
152 }
153
154 switch (element.getType()) {
156 switch (static_cast<const Multipole*>(&element)->getMaxNormalComponentIndex()) {
157 case 1:
158 mesh.type_m = DIPOLE;
159 break;
160 case 2:
161 mesh.type_m = QUADRUPOLE;
162 break;
163 case 3:
164 mesh.type_m = SEXTUPOLE;
165 break;
166 case 4:
167 mesh.type_m = OCTUPOLE;
168 break;
169 default:
170 break;
171 }
172 break;
174 mesh.type_m = RFCAVITY;
175 break;
177 mesh.type_m = TRAVELINGWAVE;
178 break;
180 mesh.type_m = SOLENOID;
181 break;
182 default:
183 mesh.type_m = OTHER;
184 }
185 }
186
187 const CoordinateSystemTrafo trafo =
190 for (unsigned int i = 0; i < mesh.vertices_m.size(); ++i) {
191 mesh.vertices_m[i] = trafo.transformTo(mesh.vertices_m[i]) + start * z;
192 }
193
194 for (unsigned int i = 0; i < mesh.decorations_m.size(); ++i) {
195 mesh.decorations_m[i].first = trafo.transformTo(mesh.decorations_m[i].first) + start * z;
196 mesh.decorations_m[i].second = trafo.transformTo(mesh.decorations_m[i].second) + start * z;
197 }
198
199 elements_m.push_back(mesh);
200}
201
202#include <zlib.h>
203#include <sstream>
204
205void MeshGenerator::write(const std::string& fname) {
206 std::string filename = Util::combineFilePath(
208 fname + "_ElementPositions.py"});
209 std::ofstream out(filename);
210 const char* buffer;
211 const std::string indent(" ");
212
213 out << std::fixed << std::setprecision(6);
214
215 out << "import os, sys, argparse, math, base64, zlib, struct\n\n";
216 out << "if sys.version_info < (3,0):\n";
217 out << " range = xrange\n\n";
218
219 std::stringstream vertices_ascii;
220 std::ostringstream vertices_compressed;
221 out << "vertices = []\n";
222 out << "numVertices = [";
223 for (auto& element : elements_m) {
224 auto& vertices = element.vertices_m;
225 out << vertices.size() << ", ";
226 for (unsigned int i = 0; i < vertices.size(); ++i) {
227 buffer = reinterpret_cast<const char*>(&(vertices[i](0)));
228 vertices_ascii.write(buffer, 3 * sizeof(double));
229 }
230 }
231 out.seekp(-2, std::ios_base::end);
232 out << "]\n";
233
234 {
235 std::string data = vertices_ascii.str();
236 uLongf compressed_size = compressBound(data.size());
237 std::vector<Bytef> compressed_data(compressed_size);
238 int result = compress(
239 compressed_data.data(), &compressed_size,
240 reinterpret_cast<const Bytef*>(data.data()), data.size());
241 if (result == Z_OK) {
242 vertices_compressed.write(
243 reinterpret_cast<const char*>(compressed_data.data()), compressed_size);
244 }
245 }
246
247 std::string vertices_base64 = Util::base64_encode(vertices_compressed.str());
248 out << "vertices_base64 = \"" << vertices_base64 << "\"\n";
249 out << "triangles = [";
250 for (auto& element : elements_m) {
251 out << "[ ";
252 auto& triangles = element.triangles_m;
253 for (unsigned int i = 0; i < triangles.size(); ++i) {
254 out << triangles[i](0) << ", " << triangles[i](1) << ", " << triangles[i](2) << ", ";
255 }
256 out.seekp(-2, std::ios_base::end);
257 out << "], ";
258 }
259 out.seekp(-2, std::ios_base::end);
260 out << "]\n";
261
262 out << "decoration = [";
263 for (auto& element : elements_m) {
264 out << "[ ";
265 for (auto& decoration : element.decorations_m) {
266 out << (decoration.first)(0) << ", " << (decoration.first)(1) << ", "
267 << (decoration.first)(2) << ", " << (decoration.second)(0) << ", "
268 << (decoration.second)(1) << ", " << (decoration.second)(2) << ", ";
269 }
270 if (!element.decorations_m.empty()) out.seekp(-2, std::ios_base::end);
271 out << "], ";
272 }
273 if (!elements_m.empty()) out.seekp(-2, std::ios_base::end);
274 out << "]\n\n";
275
276 out << "color = [";
277 for (auto& element : elements_m) {
278 out << element.type_m << ", ";
279 }
280 out.seekp(-2, std::ios_base::end);
281 out << "]\n\n";
282
283 std::stringstream index_ascii;
284 std::ostringstream index_compressed;
285 index_ascii
286 << "<!DOCTYPE html>\n"
287 << "<html>\n"
288 << " <head>\n"
289 << " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n"
290 << "\n"
291 << " <title>Babylon.js sample code</title>\n"
292 << " <!-- Babylon.js -->\n"
293 << " <script src=\"https://cdn.babylonjs.com/cannon.js\"></script>\n"
294 << " <script src=\"https://cdn.babylonjs.com/babylon.js\"></script>\n"
295 << " <style>\n"
296 << " html, body {\n"
297 << " overflow: hidden;\n"
298 << " width: 100%;\n"
299 << " height: 100%;\n"
300 << " margin: 0;\n"
301 << " padding: 0;\n"
302 << " }\n"
303 << "\n"
304 << " #renderCanvas {\n"
305 << " width: 100%;\n"
306 << " height: 100%;\n"
307 << " touch-action: none;\n"
308 << " }\n"
309 << " </style>\n"
310 << " </head>\n"
311 << "<body>\n"
312 << " <canvas id=\"renderCanvas\"></canvas>\n"
313 << " <script>\n"
314 << " var canvas = document.getElementById(\"renderCanvas\");\n"
315 << " var engine = new BABYLON.Engine(canvas, true);\n"
316 << "\n"
317 << " var createScene = function () {\n"
318 << " var scene = new BABYLON.Scene(engine);\n"
319 << "\n"
320 << " //Adding a light\n"
321 << " var light = new BABYLON.HemisphericLight(\"Hemi\", new "
322 "BABYLON.Vector3(0, 1, 0), scene);\n"
323 << " light.intensity = 0.8;\n"
324 << " light.diffuse = new BABYLON.Color3(1.0, 1.0, 1.0);\n"
325 << " light.groundColor = new BABYLON.Color3(0.7, 0.7, 0.7);\n"
326 << " light.specular = new BABYLON.Color3(0.1, 0.1, 0.1);\n"
327 << "\n"
328 << " //Adding an Arc Rotate Camera\n"
329 << " var camera = new BABYLON.ArcRotateCamera(\"Camera\", 0.0, Math.PI, "
330 "50, "
331 "BABYLON.Vector3.Zero(), scene);\n"
332 << " camera.attachControl(canvas, false);\n"
333 << " camera.wheelPrecision = 20;\n"
334 << "\n"
335 << " var mymesh = ##DATA##;\n"
336 << " // The first parameter can be used to specify which mesh to import. "
337 "Here "
338 "we import all meshes\n"
339 << " BABYLON.SceneLoader.ImportMesh(\"\", \"\", mymesh, scene, function "
340 "(newMeshes) {\n"
341 << " // Set the target of the camera to the first imported mesh\n"
342 << " camera.target = newMeshes[0];\n"
343 << "\n"
344 << " var material1 = new BABYLON.StandardMaterial(\"texture1\", "
345 "scene);\n"
346 << " //material1.wireframe = true;\n"
347 << " newMeshes[0].material = material1;\n"
348 << " newMeshes[0].material.emissiveColor = new BABYLON.Color3(0.2, 0.2, "
349 "0.2);\n"
350 << " });\n"
351 << "\n"
352 << " return scene;\n"
353 << " }\n"
354 << "\n"
355 << "\n"
356 << " var scene = createScene();\n"
357 << "\n"
358 << " engine.runRenderLoop(function () {\n"
359 << " scene.render();\n"
360 << " });\n"
361 << "\n"
362 << " // Resize\n"
363 << " window.addEventListener(\"resize\", function () {\n"
364 << " engine.resize();\n"
365 << " });\n"
366 << " </script>\n"
367 << "</body>\n"
368 << "</html>";
369 {
370 std::string data = index_ascii.str();
371 uLongf compressed_size = compressBound(data.size());
372 std::vector<Bytef> compressed_data(compressed_size);
373 int result = compress(
374 compressed_data.data(), &compressed_size,
375 reinterpret_cast<const Bytef*>(data.data()), data.size());
376 if (result == Z_OK) {
377 index_compressed.write(
378 reinterpret_cast<const char*>(compressed_data.data()), compressed_size);
379 }
380 }
381
382 out << "index_base64 = '" << Util::base64_encode(index_compressed.str()) << "'\n\n";
383
384 out << "def decodeVertices():\n";
385 out << indent << "vertices_binary = zlib.decompress(base64.b64decode(vertices_base64))\n";
386 out << indent << "k = 0\n";
387 out << indent << "for i in range(len(numVertices)):\n";
388 out << indent << indent << "current = []\n";
389 out << indent << indent << "for j in range(numVertices[i] * 3):\n";
390 out << indent << indent << indent
391 << "current.append(float(struct.unpack('=d', vertices_binary[k:k+8])[0]))\n";
392 out << indent << indent << indent << "k += 8\n";
393 out << indent << indent << "vertices.append(current)\n\n";
394
395 out << "def showVTK():\n";
396 out << indent << "try:\n";
397 out << indent << indent << "import numpy as np\n";
398 out << indent << indent << "import pyvista as pv\n";
399 out << indent << "except ModuleNotFoundError:\n";
400 out << indent << indent << "sys.stderr.write(\"PyVista is not installed.\\n\")\n";
401 out << indent << indent
402 << "sys.stderr.write(\"Install it in the local virtual environment with:\\n\")\n";
403 out << indent << indent
404 << "sys.stderr.write(\" source /Users/adelmann/git/opalx/.venv-h6/bin/activate\\n\")\n";
405 out << indent << indent << "sys.stderr.write(\" python -m pip install pyvista\\n\")\n";
406 out << indent << indent << "return 1\n\n";
407
408 out << indent << "vtk_file = \"" << fname << "_ElementPositions.vtk\"\n";
409 out << indent << "script_file = os.path.abspath(__file__)\n";
410 out << indent << "needs_export = not os.path.exists(vtk_file)\n";
411 out << indent << "if not needs_export:\n";
412 out << indent << indent
413 << "needs_export = os.path.getmtime(script_file) > os.path.getmtime(vtk_file)\n";
414 out << indent << "if needs_export:\n";
415 out << indent << indent << "exportVTK()\n\n";
416
417 out << indent << "mesh = pv.read(vtk_file)\n";
418 out << indent << "plotter = pv.Plotter()\n";
419 out << indent << "add_mesh_kwargs = {}\n";
420 out << indent << "active_scalars_name = mesh.active_scalars_name\n";
421 out << indent << "if active_scalars_name is not None:\n";
422 out << indent << indent << "active_scalars = mesh.active_scalars\n";
423 out << indent << indent
424 << "if getattr(active_scalars, 'ndim', 0) == 2 and active_scalars.shape[1] in (3, 4):\n";
425 out << indent << indent << indent << "add_mesh_kwargs['scalars'] = active_scalars_name\n";
426 out << indent << indent << indent << "add_mesh_kwargs['rgb'] = True\n";
427 out << indent << indent << indent << "add_mesh_kwargs['preference'] = 'cell'\n";
428 out << indent << indent << indent << "unique_colors = active_scalars[:, :3].astype(float)\n";
429 out << indent << indent << indent << "if np.nanmax(unique_colors) > 1.0:\n";
430 out << indent << indent << indent << indent << "unique_colors /= 255.0\n";
431 out << indent << indent << indent << "unique_colors = np.unique(unique_colors, axis=0)\n";
432 out << indent << indent << indent << "legend = [\n";
433 out << indent << indent << indent << indent << "('Other', (0.5, 0.5, 0.5)),\n";
434 out << indent << indent << indent << indent << "('Dipole', (1.0, 0.847, 0.0)),\n";
435 out << indent << indent << indent << indent << "('Quadrupole', (1.0, 0.0, 0.0)),\n";
436 out << indent << indent << indent << indent << "('Sextupole', (0.537, 0.745, 0.525)),\n";
437 out << indent << indent << indent << indent << "('Octupole', (0.5, 0.5, 0.0)),\n";
438 out << indent << indent << indent << indent << "('Solenoid', (1.0, 138.0 / 255.0, 0.0)),\n";
439 out << indent << indent << indent << indent << "('RFCavity', (1.0, 1.0, 0.0)),\n";
440 out << indent << indent << indent << indent << "('TravelingWave', (0.0, 0.6, 0.0)),\n";
441 out << indent << indent << indent << indent << "('Drift', (0.0, 0.0, 1.0)),\n";
442 out << indent << indent << indent << "]\n";
443 out << indent << indent << indent << "present = []\n";
444 out << indent << indent << indent << "for label, color in legend:\n";
445 out << indent << indent << indent << indent << "color_arr = np.asarray(color, dtype=float)\n";
446 out << indent << indent << indent << indent
447 << "if np.any(np.all(np.isclose(unique_colors, color_arr, atol=5e-3), axis=1)):\n";
448 out << indent << indent << indent << indent << indent << "present.append((label, color))\n";
449 out << indent << indent << indent << "if present:\n";
450 out << indent << indent << indent << indent
451 << "plotter.add_legend(present, bcolor=(1.0, 1.0, 1.0), face='circle', border=True, "
452 "size=(0.2, 0.24))\n";
453 out << indent << "plotter.add_mesh(mesh, **add_mesh_kwargs)\n";
454 out << indent << "plotter.add_axes()\n";
455 out << indent << "plotter.show_grid()\n";
456 out << indent << "plotter.show()\n";
457 out << indent << "return 0\n\n";
458
459 out << "def dot(a, b):\n";
460 out << indent << "return sum(a[i]*b[i] for i in range(len(a)))\n\n";
461
462 out << "def normalize(a):\n";
463 out << indent << "length = math.sqrt(dot(a, a))\n";
464 out << indent << "for i in range(3):\n";
465 out << indent << indent << "a[i]/=length\n";
466 out << indent << "return a\n\n";
467
468 out << "def distance(a, b):\n";
469 out << indent << "c = [0] * 2\n";
470 out << indent << "for i in range(len(a)):\n";
471 out << indent << indent << "c[i] = a[i] - b[i]\n";
472 out << indent << "return math.sqrt(dot(c, c))\n\n";
473
474 out << "def cross(a, b):\n";
475 out << indent << "c = [0, 0, 0]\n";
476 out << indent << "c[0] = a[1]*b[2] - a[2]*b[1]\n";
477 out << indent << "c[1] = a[2]*b[0] - a[0]*b[2]\n";
478 out << indent << "c[2] = a[0]*b[1] - a[1]*b[0]\n";
479 out << indent << "return c\n\n";
480
481 out << "class Quaternion:\n";
482 out << indent << "def __init__(self, values):\n";
483 out << indent << indent << "self.R = values\n\n";
484
485 out << indent << "def __str__(self):\n";
486 out << indent << indent << "return str(self.R)\n\n";
487
488 out << indent << "def __mul__(self, other):\n";
489 out << indent << indent << "imagThis = self.imag()\n";
490 out << indent << indent << "imagOther = other.imag()\n";
491 out << indent << indent << "cro = cross(imagThis, imagOther)\n\n";
492
493 out << indent << indent << "ret = ([self.R[0] * other.R[0] - dot(imagThis, imagOther)] +\n";
494 out << indent << indent << indent
495 << " [self.R[0] * imagOther[0] + other.R[0] * imagThis[0] + cro[0],\n";
496 out << indent << indent << indent << indent
497 << "self.R[0] * imagOther[1] + other.R[0] * imagThis[1] + cro[1],\n";
498 out << indent << indent << indent << indent
499 << "self.R[0] * imagOther[2] + other.R[0] * imagThis[2] + cro[2]])\n\n";
500
501 out << indent << indent << "return Quaternion(ret)\n\n";
502
503 out << indent << "def imag(self):\n";
504 out << indent << indent << "return self.R[1:]\n\n";
505
506 out << indent << "def conjugate(self):\n";
507 out << indent << indent << "ret = [0] * 4\n";
508 out << indent << indent << "ret[0] = self.R[0]\n";
509 out << indent << indent << "ret[1] = -self.R[1]\n";
510 out << indent << indent << "ret[2] = -self.R[2]\n";
511 out << indent << indent << "ret[3] = -self.R[3]\n\n";
512
513 out << indent << indent << "return Quaternion(ret)\n\n";
514
515 out << indent << "def inverse(self):\n";
516 out << indent << indent << "return self.conjugate()\n\n";
517
518 out << indent << "def rotate(self, vec3D):\n";
519 out << indent << indent << "quat = Quaternion([0.0] + vec3D)\n";
520 out << indent << indent << "conj = self.conjugate()\n\n";
521
522 out << indent << indent << "ret = self * (quat * conj)\n";
523 out << indent << indent << "return ret.R[1:]\n\n";
524
525 out << "def getQuaternion(u, ref):\n";
526 out << indent << "u = normalize(u)\n";
527 out << indent << "ref = normalize(ref)\n";
528 out << indent << "axis = cross(u, ref)\n";
529 out << indent << "normAxis = math.sqrt(dot(axis, axis))\n\n";
530
531 out << indent << "if normAxis < 1e-12:\n";
532 out << indent << indent << "if math.fabs(dot(u, ref) - 1.0) < 1e-12:\n";
533 out << indent << indent << indent << "return Quaternion([1.0, 0.0, 0.0, 0.0])\n\n";
534
535 out << indent << indent << "return Quaternion([0.0, 1.0, 0.0, 0.0])\n\n";
536
537 out << indent << "axis = normalize(axis)\n";
538 out << indent << "cosAngle = math.sqrt(0.5 * (1 + dot(u, ref)))\n";
539 out << indent << "sinAngle = math.sqrt(1 - cosAngle * cosAngle)\n\n";
540
541 out << indent
542 << "return Quaternion([cosAngle, sinAngle * axis[0], sinAngle * axis[1], sinAngle * "
543 "axis[2]])\n\n";
544
545 out << "def exportVTK():\n";
546 out << indent << "vertices_str = \"\"\n";
547 out << indent << "triangles_str = \"\"\n";
548 out << indent << "color_str = \"\"\n";
549 out << indent << "cellTypes_str = \"\"\n";
550 out << indent << "startIdx = 0\n";
551 out << indent << "vertexCounter = 0\n";
552 out << indent << "cellCounter = 0\n";
553 out << indent << "lookup_table = []\n";
554 out << indent << "lookup_table.append([0.5, 0.5, 0.5, 0.5])\n";
555 out << indent << "lookup_table.append([1.0, 0.847, 0.0, 1.0])\n";
556 out << indent << "lookup_table.append([1.0, 0.0, 0.0, 1.0])\n";
557 out << indent << "lookup_table.append([0.537, 0.745, 0.525, 1.0])\n";
558 out << indent << "lookup_table.append([0.5, 0.5, 0.0, 1.0])\n";
559 out << indent << "lookup_table.append([1.0, 0.5411764706, 0.0, 1.0])\n";
560 out << indent << "lookup_table.append([1.0, 1.0, 0.0, 1.0])\n";
561 out << indent << "lookup_table.append([0.0, 0.6, 0.0, 1.0])\n";
562 out << indent << "lookup_table.append([0.0, 0.0, 1.0, 1.0])\n\n";
563
564 out << indent << "decodeVertices()\n\n";
565
566 out << indent << "for i in range(len(vertices)):\n";
567 out << indent << indent << "for j in range(0, len(vertices[i]), 3):\n";
568 out << indent << indent << indent
569 << "vertices_str += (\"%f %f %f\\n\" %(vertices[i][j], vertices[i][j+1], "
570 "vertices[i][j+2]))\n";
571 out << indent << indent << indent << "vertexCounter += 1\n\n";
572
573 out << indent << indent << "for j in range(0, len(triangles[i]), 3):\n";
574 out << indent << indent << indent
575 << "triangles_str += (\"3 %d %d %d\\n\" % (triangles[i][j] + startIdx, triangles[i][j+1] + "
576 "startIdx, triangles[i][j+2] + startIdx))\n";
577 out << indent << indent << indent << "cellTypes_str += \"5\\n\"\n";
578 out << indent << indent << indent << "tmp_color = lookup_table[color[i]]\n";
579 out << indent << indent << indent
580 << "color_str += (\"%f %f %f %f\\n\" % (tmp_color[0], tmp_color[1], tmp_color[2], "
581 "tmp_color[3]))\n";
582 out << indent << indent << indent << "cellCounter += 1\n";
583
584 out << indent << indent << "startIdx = vertexCounter\n\n";
585
586 out << indent << "fh = open('" << fname << "_ElementPositions.vtk','w')\n";
587 out << indent << "fh.write(\"# vtk DataFile Version 2.0\\n\")\n";
588 out << indent << "fh.write(\"test\\nASCII\\n\\n\")\n";
589 out << indent << "fh.write(\"DATASET UNSTRUCTURED_GRID\\n\")\n";
590 out << indent << "fh.write(\"POINTS \" + str(vertexCounter) + \" float\\n\")\n";
591 out << indent << "fh.write(vertices_str)\n";
592 out << indent
593 << "fh.write(\"CELLS \" + str(cellCounter) + \" \" + str(cellCounter * 4) + \"\\n\")\n";
594 out << indent << "fh.write(triangles_str)\n";
595 out << indent << "fh.write(\"CELL_TYPES \" + str(cellCounter) + \"\\n\")\n";
596 out << indent << "fh.write(cellTypes_str)\n";
597 out << indent << "fh.write(\"CELL_DATA \" + str(cellCounter) + \"\\n\")\n";
598 out << indent << "fh.write(\"COLOR_SCALARS type 4\\n\")\n";
599 out << indent << "fh.write(color_str + \"\\n\")\n";
600 out << indent << "fh.close()\n\n";
601
602 out << "def getNormal(tri_vertices):\n";
603 out << indent << "vec1 = [tri_vertices[1][0] - tri_vertices[0][0],\n";
604 out << indent << " tri_vertices[1][1] - tri_vertices[0][1],\n";
605 out << indent << " tri_vertices[1][2] - tri_vertices[0][2]]\n";
606 out << indent << "vec2 = [tri_vertices[2][0] - tri_vertices[0][0],\n";
607 out << indent << " tri_vertices[2][1] - tri_vertices[0][1],\n";
608 out << indent << " tri_vertices[2][2] - tri_vertices[0][2]]\n";
609 out << indent << "return normalize(cross(vec1,vec2))\n\n";
610
611 out << "def exportWeb(bgcolor):\n";
612 // out << indent << "if not os.path.exists('scenes'):\n";
613 // out << indent << indent << "os.makedirs('scenes')\n";
614 // out << indent << "fh = open('scenes/" << fname << "_ElementPositions.babylon','w')\n";
615 // out << indent << "indent = \"\";\n\n";
616
617 out << indent << "lookup_table = []\n";
618 out << indent << "lookup_table.append([0.5, 0.5, 0.5])\n";
619 out << indent << "lookup_table.append([1.0, 0.847, 0.0])\n";
620 out << indent << "lookup_table.append([1.0, 0.0, 0.0])\n";
621 out << indent << "lookup_table.append([0.537, 0.745, 0.525])\n";
622 out << indent << "lookup_table.append([0.5, 0.5, 0.0])\n";
623 out << indent << "lookup_table.append([1.0, 0.5411764706, 0.0])\n";
624 out << indent << "lookup_table.append([1.0, 1.0, 0.0])\n";
625 out << indent << "lookup_table.append([0.0, 0.6, 0.0])\n";
626 out << indent << "lookup_table.append([0.0, 0.0, 1.0])\n\n";
627
628 out << indent << "decodeVertices()\n\n";
629
630 out << indent << "mesh = \"'data:\"\n";
631 out << indent << "mesh += \"{\"\n";
632 out << indent << "mesh += \"\\\"autoClear\\\":true,\"\n";
633 out << indent << "mesh += \"\\\"clearColor\\\":[0.0000,0.0000,0.0000],\"\n";
634 out << indent << "mesh += \"\\\"ambientColor\\\":[0.0000,0.0000,0.0000],\"\n";
635 out << indent << "mesh += \"\\\"gravity\\\":[0.0000,-9.8100,0.0000],\"\n";
636 out << indent << "mesh += \"\\\"cameras\\\":[\"\n";
637 out << indent << "mesh += \"{\"\n";
638 out << indent << "mesh += \"\\\"name\\\":\\\"Camera\\\",\"\n";
639 out << indent << "mesh += \"\\\"id\\\":\\\"Camera\\\",\"\n";
640 out << indent << "mesh += \"\\\"position\\\":[21.7936,2.2312,-85.7292],\"\n";
641 out << indent << "mesh += \"\\\"rotation\\\":[0.0432,-0.1766,-0.0668],\"\n";
642 out << indent << "mesh += \"\\\"fov\\\":0.8578,\"\n";
643 out << indent << "mesh += \"\\\"minZ\\\":10.0000,\"\n";
644 out << indent << "mesh += \"\\\"maxZ\\\":10000.0000,\"\n";
645 out << indent << "mesh += \"\\\"speed\\\":1.0000,\"\n";
646 out << indent << "mesh += \"\\\"inertia\\\":0.9000,\"\n";
647 out << indent << "mesh += \"\\\"checkCollisions\\\":false,\"\n";
648 out << indent << "mesh += \"\\\"applyGravity\\\":false,\"\n";
649 out << indent << "mesh += \"\\\"ellipsoid\\\":[0.2000,0.9000,0.2000]\"\n";
650 out << indent << "mesh += \"}],\"\n";
651 out << indent << "mesh += \"\\\"activeCamera\\\":\\\"Camera\\\",\"\n";
652 out << indent << "mesh += \"\\\"lights\\\":[\"\n";
653 out << indent << "mesh += \"{\"\n";
654 out << indent << "mesh += \"\\\"name\\\":\\\"Lamp\\\",\"\n";
655 out << indent << "mesh += \"\\\"id\\\":\\\"Lamp\\\",\"\n";
656 out << indent << "mesh += \"\\\"type\\\":0.0000,\"\n";
657 out << indent << "mesh += \"\\\"position\\\":[4.0762,34.9321,-63.5788],\"\n";
658 out << indent << "mesh += \"\\\"intensity\\\":1.0000,\"\n";
659 out << indent << "mesh += \"\\\"diffuse\\\":[1.0000,1.0000,1.0000],\"\n";
660 out << indent << "mesh += \"\\\"specular\\\":[1.0000,1.0000,1.0000]\"\n";
661 out << indent << "mesh += \"}],\"\n";
662 out << indent << "mesh += \"\\\"materials\\\":[],\"\n";
663 out << indent << "mesh += \"\\\"meshes\\\":[\"\n\n";
664
665 out << indent << "for i in range(len(triangles)):\n";
666 out << indent << indent << "vertex_list = []\n";
667 out << indent << indent << "indices_list = []\n";
668 out << indent << indent << "normals_list = []\n";
669 out << indent << indent << "color_list = []\n";
670 out << indent << indent << "for j in range(0, len(triangles[i]), 3):\n";
671 out << indent << indent << indent << "tri_vertices = []\n";
672 out << indent << indent << indent << "idcs = triangles[i][j:j + 3]\n";
673 out << indent << indent << indent
674 << "tri_vertices.append(vertices[i][3 * idcs[0]:3 * (idcs[0] + 1)])\n";
675 out << indent << indent << indent
676 << "tri_vertices.append(vertices[i][3 * idcs[1]:3 * (idcs[1] + 1)])\n";
677 out << indent << indent << indent
678 << "tri_vertices.append(vertices[i][3 * idcs[2]:3 * (idcs[2] + 1)])\n";
679 out << indent << indent << indent
680 << "indices_list.append(','.join(str(n) for n in range(len(vertex_list),len(vertex_list) + "
681 "3)))\n";
682 out << indent << indent << indent << "# left hand order!\n";
683 out << indent << indent << indent
684 << "vertex_list.append(','.join(\"%.5f\" % (round(n,5) + 0.0) for n in tri_vertices[0]))\n";
685 out << indent << indent << indent
686 << "vertex_list.append(','.join(\"%.5f\" % (round(n,5) + 0.0) for n in tri_vertices[2]))\n";
687 out << indent << indent << indent
688 << "vertex_list.append(','.join(\"%.5f\" % (round(n,5) + 0.0) for n in tri_vertices[1]))\n";
689 out << indent << indent << indent << "normal = getNormal(tri_vertices)\n";
690 out << indent << indent << indent
691 << "normals_list.append(','.join(\"%.5f\" % (round(n,5) + 0.0) for n in normal * 3))\n";
692 out << indent << indent << indent
693 << "color_list.append(','.join([str(n) for n in lookup_table[color[i]]] * 3))\n";
694 out << indent << indent << "mesh += \"{\"\n";
695 out << indent << indent << "mesh += \"\\\"name\\\":\\\"element_\" + str(i) + \"\\\",\"\n";
696 out << indent << indent << "mesh += \"\\\"id\\\":\\\"element_\" + str(i) + \"\\\",\"\n";
697 out << indent << indent << "mesh += \"\\\"position\\\":[0.0,0.0,0.0],\"\n";
698 out << indent << indent << "mesh += \"\\\"rotation\\\":[0.0,0.0,0.0],\"\n";
699 out << indent << indent << "mesh += \"\\\"scaling\\\":[1.0,1.0,1.0],\"\n";
700 out << indent << indent << "mesh += \"\\\"isVisible\\\":true,\"\n";
701 out << indent << indent << "mesh += \"\\\"isEnabled\\\":true,\"\n";
702 out << indent << indent << "mesh += \"\\\"useFlatShading\\\":false,\"\n";
703 out << indent << indent << "mesh += \"\\\"checkCollisions\\\":false,\"\n";
704 out << indent << indent << "mesh += \"\\\"billboardMode\\\":0,\"\n";
705 out << indent << indent << "mesh += \"\\\"receiveShadows\\\":false,\"\n";
706 out << indent << indent << "mesh += \"\\\"positions\\\":[\" + ','.join(vertex_list) + \"],\"\n";
707 out << indent << indent << "mesh += \"\\\"normals\\\":[\" + ','.join(normals_list) + \"],\"\n";
708 out << indent << indent << "mesh += \"\\\"indices\\\":[\" + ','.join(indices_list) + \"],\"\n";
709 out << indent << indent << "mesh += \"\\\"colors\\\":[\" + ','.join(color_list) + \"],\"\n";
710 out << indent << indent << "mesh += \"\\\"subMeshes\\\":[\"\n";
711 out << indent << indent << "mesh += \"{\"\n";
712 out << indent << indent << "mesh += \"\\\"materialIndex\\\":0,\"\n";
713 out << indent << indent << "mesh += \" \\\"verticesStart\\\":0,\"\n";
714 out << indent << indent
715 << "mesh += \" \\\"verticesCount\\\":\" + str(len(triangles[i])) + \",\"\n";
716 out << indent << indent << "mesh += \" \\\"indexStart\\\":0,\"\n";
717 out << indent << indent << "mesh += \" \\\"indexCount\\\":\" + str(len(triangles[i])) + \"\"\n";
718 out << indent << indent << "mesh += \"}]\"\n";
719 out << indent << indent << "mesh += \"}\"\n";
720 out << indent << indent << "mesh += \",\"\n\n";
721
722 out << indent << indent << "del normals_list[:]\n";
723 out << indent << indent << "del vertex_list[:]\n";
724 out << indent << indent << "del color_list[:]\n";
725 out << indent << indent << "del indices_list[:]\n\n";
726
727 out << indent << "mesh = mesh[:-1] + \"]\"\n";
728 out << indent << "mesh += \"}'\"\n";
729
730 out << indent << "index_compressed = base64.b64decode(index_base64)\n";
731 out << indent << "index = zlib.decompress(index_compressed).decode('utf-8')\n";
732 out << indent << "if (len(bgcolor) == 3):\n";
733 out << indent << indent << "mesh += \";\\n \"\n";
734 out << indent << indent
735 << "mesh += \"scene.clearColor = new BABYLON.Color3(%f, %f, %f)\" % (bgcolor[0], "
736 "bgcolor[1], bgcolor[2])\n\n";
737 out << indent << "index = index.replace('##DATA##', mesh)\n";
738 out << indent << "fh = open('" << fname << "_ElementPositions.html','w')\n";
739 out << indent << "fh.write(index)\n";
740 out << indent << "fh.close()\n\n";
741
742 out << "def computeMinAngle(idx, curAngle, positions, connections, check):\n";
743 out << indent
744 << "matrix = [[-math.cos(curAngle), -math.sin(curAngle)], [math.sin(curAngle), "
745 "-math.cos(curAngle)]]\n\n";
746
747 out << indent << "minAngle = 2 * math.pi\n";
748 out << indent << "nextIdx = -1\n\n";
749
750 out << indent << "for j in connections[idx]:\n";
751 out << indent << indent << "direction = [positions[j][0] - positions[idx][0],\n";
752 out << indent << indent << indent << " positions[j][1] - positions[idx][1]]\n";
753 out << indent << indent
754 << "direction = [dot(matrix[0],direction), dot(matrix[1],direction)]\n\n";
755
756 out << indent << indent
757 << "if math.fabs(dot([1.0, 0.0], direction) / distance(positions[j], positions[idx]) - "
758 "1.0) < 1e-6: continue\n\n";
759
760 out << indent << indent
761 << "angle = math.fmod(math.atan2(direction[1],direction[0]) + 2 * math.pi, 2 * "
762 "math.pi)\n\n";
763
764 out << indent << indent << "if angle < minAngle:\n";
765 out << indent << indent << indent << "nextIdx = j\n";
766 out << indent << indent << indent << "minAngle = angle\n";
767 out << indent << indent << "if angle == minAngle and check:\n";
768 out << indent << indent << indent << "dire = [positions[j][0] - positions[idx][0],\n";
769 out << indent << indent << indent << " positions[j][1] - positions[idx][1]]\n";
770 out << indent << indent << indent << "minA0 = math.atan2(dire[1], dire[0])\n";
771 out << indent << indent << indent
772 << "minA1 = computeMinAngle(nextIdx, minA0, positions, connections, False)\n";
773 out << indent << indent << indent
774 << "minA2 = computeMinAngle(j, minA0, positions, connections, False)\n";
775 out << indent << indent << indent << "if minA2[1] < minA2[1]:\n";
776 out << indent << indent << indent << indent << "nextIdx = j\n\n";
777
778 out << indent << "if nextIdx == -1:\n";
779 out << indent << indent << "nextIdx = connections[idx][0]\n\n";
780
781 out << indent << "return (nextIdx, minAngle)\n\n";
782
783 out << "def squashVertices(positionDict, connections):\n";
784 out << indent << "removedItems = []\n";
785 out << indent << "indices = [int(k) for k in positionDict.keys()]\n";
786 out << indent << "idxChanges = indices\n";
787 out << indent << "for i in indices:\n";
788 out << indent << indent << "if i in removedItems:\n";
789 out << indent << indent << indent << "continue\n";
790 out << indent << indent << "for j in indices:\n";
791 out << indent << indent << indent << "if j in removedItems or j == i:\n";
792 out << indent << indent << indent << indent << "continue\n\n";
793
794 out << indent << indent << indent << "if distance(positionDict[i], positionDict[j]) < 1e-6:\n";
795 out << indent << indent << indent << indent << "connections[j] = list(set(connections[j]))\n";
796 out << indent << indent << indent << indent << "if i in connections[j]:\n";
797 out << indent << indent << indent << indent << indent << "connections[j].remove(i)\n";
798 out << indent << indent << indent << indent << "if j in connections[i]:\n";
799 out << indent << indent << indent << indent << indent << "connections[i].remove(j)\n\n";
800
801 out << indent << indent << indent << indent << "connections[i].extend(connections[j])\n";
802 out << indent << indent << indent << indent << "connections[i] = list(set(connections[i]))\n";
803 out << indent << indent << indent << indent << "connections[i].sort()\n\n";
804
805 out << indent << indent << indent << indent << "for k in connections.keys():\n";
806 out << indent << indent << indent << indent << indent << "if k == i: continue\n";
807 out << indent << indent << indent << indent << indent << "if j in connections[k]:\n";
808 out << indent << indent << indent << indent << indent << indent
809 << "idx = connections[k].index(j)\n";
810 out << indent << indent << indent << indent << indent << indent
811 << "connections[k][idx] = i\n\n";
812
813 out << indent << indent << indent << indent << "idxChanges[j] = i\n";
814 out << indent << indent << indent << indent << "removedItems.append(j)\n\n";
815
816 out << indent << "for i in removedItems:\n";
817 out << indent << indent << "del positionDict[i]\n";
818 out << indent << indent << "del connections[i]\n\n";
819
820 out << indent << "for i in connections.keys():\n";
821 out << indent << indent << "connections[i] = list(set(connections[i]))\n";
822 out << indent << indent << "connections[i].sort()\n\n";
823
824 out << indent << "return idxChanges\n\n";
825
826 out << "def computeLineEquations(positions, connections):\n";
827 out << indent << "cons = set()\n";
828 out << indent << "for i in connections.keys():\n";
829 out << indent << indent << "for j in connections[i]:\n";
830 out << indent << indent << indent << "cons.add((min(i, j), max(i, j)))\n\n";
831
832 out << indent << "lineEquations = {}\n";
833 out << indent << "for item in cons:\n";
834 out << indent << indent << "a = (positions[item[1]][1] - positions[item[0]][1])\n";
835 out << indent << indent << "b = -(positions[item[1]][0] - positions[item[0]][0])\n\n";
836
837 out << indent << indent << "xm = 0.5 * (positions[item[0]][0] + positions[item[1]][0])\n";
838 out << indent << indent << "ym = 0.5 * (positions[item[0]][1] + positions[item[1]][1])\n";
839 out << indent << indent << "c = -(a * xm + b * ym)\n\n";
840
841 out << indent << indent << "lineEquations[item] = (a, b, c)\n\n";
842
843 out << indent << "return lineEquations\n\n";
844
845 out << "def checkPossibleSegmentIntersection(segment, positions, lineEquations, minAngle, "
846 "lastIntersection):\n";
847 out << indent << "item1 = (min(segment), max(segment))\n\n";
848
849 out << indent << "(a1, b1, c1) = (0,0,0)\n";
850 out << indent << "A = [0]*2\n";
851 out << indent << "B = A\n\n";
852
853 out << indent << "if segment[0] == None:\n";
854 out << indent << indent << "A = lastIntersection\n";
855 out << indent << indent << "B = positions[segment[1]]\n\n";
856
857 out << indent << indent << "a1 = B[1] - A[1]\n";
858 out << indent << indent << "b1 = -(B[0] - A[0])\n";
859 out << indent << indent << "xm = 0.5 * (A[0] + B[0])\n";
860 out << indent << indent << "ym = 0.5 * (A[1] + B[1])\n";
861 out << indent << indent << "c1 = -(a1 * xm + b1 * ym)\n\n";
862
863 out << indent << "else:\n";
864 out << indent << indent << "A = positions[segment[0]]\n";
865 out << indent << indent << "B = positions[segment[1]]\n\n";
866
867 out << indent << indent << "(a1, b1, c1) = lineEquations[item1]\n\n";
868
869 out << indent << indent << "if segment[1] < segment[0]:\n";
870 out << indent << indent << indent << "(a1, b1, c1) = (-a1, -b1, -c1)\n\n";
871
872 out << indent << "curAngle = math.atan2(a1, -b1)\n";
873 out << indent
874 << "matrix = [[-math.cos(curAngle), -math.sin(curAngle)], [math.sin(curAngle), "
875 "-math.cos(curAngle)]]\n\n";
876
877 out << indent << "origMinAngle = minAngle\n\n";
878
879 out << indent << "segment1 = [B[0] - A[0], B[1] - A[1], 0.0]\n\n";
880
881 out << indent << "intersectingSegments = []\n";
882 out << indent << "distanceAB = distance(A, B)\n";
883 out << indent << "for item2 in lineEquations.keys():\n";
884 out << indent << indent << "item = item2\n";
885 out << indent << indent << "C = positions[item[0]]\n";
886 out << indent << indent << "D = positions[item[1]]\n\n";
887
888 out << indent << indent << "if segment[0] == None:\n";
889 out << indent << indent << indent << "if (segment[1] == item[0] or\n";
890 out << indent << indent << indent << indent << "segment[1] == item[1]): continue\n";
891 out << indent << indent << "else:\n";
892 out << indent << indent << indent << "if (item1[0] == item[0] or\n";
893 out << indent << indent << indent << indent << "item1[1] == item[0] or\n";
894 out << indent << indent << indent << indent << "item1[0] == item[1] or\n";
895 out << indent << indent << indent << indent << "item1[1] == item[1]): continue\n\n";
896
897 out << indent << indent << "nodes = set([item1[0],item1[1],item[0],item[1]])\n";
898 out << indent << indent << "if len(nodes) < 4: continue # share same vertex\n\n";
899
900 out << indent << indent << "(a2, b2, c2) = lineEquations[item]\n\n";
901
902 out << indent << indent << "segment2 = [C[0] - A[0], C[1] - A[1], 0.0]\n";
903 out << indent << indent << "segment3 = [D[0] - A[0], D[1] - A[1], 0.0]\n\n";
904
905 out << indent << indent << "# check that C and D aren't on the same side of AB\n";
906 out << indent << indent
907 << "if cross(segment1, segment2)[2] * cross(segment1, segment3)[2] > 0.0: continue\n\n";
908
909 out << indent << indent
910 << "if cross(segment1, segment2)[2] < 0.0 or cross(segment1, segment3)[2] > 0.0:\n";
911 out << indent << indent << indent << "(C, D, a2, b2, c2) = (D, C, -a2, -b2, -c2)\n";
912 out << indent << indent << indent << "item = (item[1], item[0])\n\n";
913
914 out << indent << indent << "denominator = a1 * b2 - b1 * a2\n";
915 out << indent << indent << "if math.fabs(denominator) < 1e-9: continue\n\n";
916
917 out << indent << indent << "px = (b1 * c2 - b2 * c1) / denominator\n";
918 out << indent << indent << "py = (a2 * c1 - a1 * c2) / denominator\n\n";
919
920 out << indent << indent << "distanceCD = distance(C, D)\n\n";
921
922 out << indent << indent << "distanceAP = distance(A, [px, py])\n";
923 out << indent << indent << "distanceBP = distance(B, [px, py])\n";
924 out << indent << indent << "distanceCP = distance(C, [px, py])\n";
925 out << indent << indent << "distanceDP = distance(D, [px, py])\n\n";
926
927 out << indent << indent << "# check intersection is between AB and CD\n";
928 out << indent << indent
929 << "check1 = (distanceAP - 1e-6 < distanceAB and distanceBP - 1e-6 < distanceAB)\n";
930 out << indent << indent
931 << "check2 = (distanceCP - 1e-6 < distanceCD and distanceDP - 1e-6 < distanceCD)\n";
932 out << indent << indent << "if not check1 or not check2: continue\n\n";
933
934 out << indent << indent
935 << "if math.fabs(dot(segment1, [D[0] - C[0], D[1] - C[1], 0.0]) / (distanceAB * "
936 "distanceCD) + 1.0) < 1e-9: continue\n\n";
937
938 out << indent << indent << "if ((distanceAP < 1e-6) or\n";
939 out << indent << indent << indent << "(distanceBP < 1e-6 and distanceCP < 1e-6) or\n";
940 out << indent << indent << indent << "(distanceDP < 1e-6)):\n";
941 out << indent << indent << indent << "continue\n\n";
942
943 out << indent << indent << "direction = [D[0] - C[0], D[1] - C[1]]\n";
944 out << indent << indent
945 << "direction = [dot(matrix[0], direction), dot(matrix[1], direction)]\n";
946 out << indent << indent
947 << "angle = math.fmod(math.atan2(direction[1], direction[0]) + 2 * math.pi, 2 * "
948 "math.pi)\n\n";
949
950 out << indent << indent << "newSegment = ([px, py], item[1], distanceAP, angle)\n\n";
951
952 out << indent << indent << "if distanceCP < 1e-6 and angle > origMinAngle: continue\n";
953 out << indent << indent << "if distanceBP > 1e-6 and angle > math.pi: continue\n\n";
954
955 out << indent << indent << "if len(intersectingSegments) == 0:\n";
956 out << indent << indent << indent << "intersectingSegments.append(newSegment)\n";
957 out << indent << indent << indent << "minAngle = angle\n";
958 out << indent << indent << "else:\n";
959 out << indent << indent << indent << "if intersectingSegments[0][2] - 1e-9 > distanceAP:\n";
960 out << indent << indent << indent << indent << "intersectingSegments[0] = newSegment\n";
961 out << indent << indent << indent << indent << "minAngle = angle\n";
962 out << indent << indent << indent
963 << "elif intersectingSegments[0][2] + 1e-9 > distanceAP and angle < minAngle:\n";
964 out << indent << indent << indent << indent << "intersectingSegments[0] = newSegment\n";
965 out << indent << indent << indent << indent << "minAngle = angle\n\n";
966
967 out << indent << "return intersectingSegments\n\n";
968
969 out << "def projectToPlane(normal):\n";
970 out << indent << "fh = open('" << fname << "_ElementPositions.gpl','w')\n";
971 // out << indent << "fg = open('test2.dat', 'w')\n";
972 out << indent << "normal = normalize(normal)\n";
973 out << indent << "ori = getQuaternion(normal, [0, 0, 1])\n\n";
974
975 out << indent << "left2Right = [0, 0, 1]\n";
976 out << indent << "if math.fabs(math.fabs(dot(normal, left2Right)) - 1) < 1e-9:\n";
977 out << indent << indent << "left2Right = [1, 0, 0]\n";
978 out << indent << "rotL2R = ori.rotate(left2Right)\n";
979 out << indent << "deviation = math.atan2(rotL2R[1], rotL2R[0])\n";
980 out << indent
981 << "rotBack = Quaternion([math.cos(0.5 * deviation), 0, 0, -math.sin(0.5 * deviation)])\n";
982 out << indent << "ori = rotBack * ori\n\n";
983
984 out << indent << "decodeVertices()\n\n";
985
986 out << indent << "for i in range(len(vertices)):\n";
987 out << indent << indent << "positions = {}\n";
988 out << indent << indent << "connections = {}\n";
989 out << indent << indent << "for j in range(0, len(vertices[i]), 3):\n";
990 out << indent << indent << indent << "nextPos3D = ori.rotate(vertices[i][j:j+3])\n";
991 out << indent << indent << indent << "nextPos2D = nextPos3D[0:2]\n";
992 out << indent << indent << indent << "positions[j/3] = nextPos2D\n\n";
993
994 out << indent << indent << "if len(positions) == 0:\n";
995 out << indent << indent << indent << "continue\n\n";
996
997 out << indent << indent << "idx = 0\n";
998 out << indent << indent << "maxX = positions[0][0]\n";
999 out << indent << indent << "for j in positions.keys():\n";
1000 out << indent << indent << indent << "if positions[j][0] > maxX:\n";
1001 out << indent << indent << indent << indent << "maxX = positions[j][0]\n";
1002 out << indent << indent << indent << indent << "idx = j\n";
1003 out << indent << indent << indent
1004 << "if positions[j][0] == maxX and positions[j][1] > positions[idx][1]:\n";
1005 out << indent << indent << indent << indent << "idx = j\n\n";
1006
1007 out << indent << indent << "for j in range(0, len(triangles[i]), 3):\n";
1008 out << indent << indent << indent << "for k in range(0, 3):\n";
1009 out << indent << indent << indent << indent << "vertIdx = triangles[i][j + k]\n";
1010 out << indent << indent << indent << indent << "if not vertIdx in connections:\n";
1011 out << indent << indent << indent << indent << indent << "connections[vertIdx] = []\n";
1012 out << indent << indent << indent << indent << "for l in range(1, 3):\n";
1013 out << indent << indent << indent << indent << indent
1014 << "connections[vertIdx].append(triangles[i][j + ((k + l) % 3)])\n\n";
1015
1016 out << indent << indent << "numConnections = 0\n";
1017 out << indent << indent << "for j in connections.keys():\n";
1018 out << indent << indent << indent << "connections[j] = list(set(connections[j]))\n";
1019 out << indent << indent << indent << "numConnections += len(connections[j])\n\n";
1020 out << indent << indent << "numConnections /= 2\n";
1021
1022 out << indent << indent << "idChanges = squashVertices(positions, connections)\n\n";
1023
1024 out << indent << indent << "lineEquations = computeLineEquations(positions, connections)\n\n";
1025
1026 // out << indent << indent << "for j in positions.keys():\n";
1027 // out << indent << indent << indent << "for k in connections[j]:\n";
1028 // out << indent << indent << indent << indent << "if j < k:\n";
1029 // out << indent << indent << indent << indent << indent << "fg.write(\"%.8f %.8f \\n%.8f
1030 // %.8f\\n# %d %d\\n\\n\" %(positions[j][0], positions[j][1], positions[k][0],
1031 // positions[k][1], j, k))\n"; out << indent << indent << indent << "fg.write(\"\\n\")\n\n";
1032
1033 out << indent << indent << "idx = idChanges[int(idx)]\n";
1034 out << indent << indent
1035 << "fh.write(\"%.6f %.6f\\n\" % (positions[idx][0], positions[idx][1]))\n\n";
1036
1037 out << indent << indent << "curAngle = math.pi\n";
1038 out << indent << indent << "origin = idx\n";
1039 out << indent << indent << "count = 0\n";
1040 out << indent << indent << "passed = []\n";
1041 out << indent << indent
1042 << "while (count == 0 or distance(positions[origin], positions[idx]) > 1e-9) and not count "
1043 "> numConnections:\n";
1044 out << indent << indent << indent
1045 << "nextGen = computeMinAngle(idx, curAngle, positions, connections, False)\n";
1046 out << indent << indent << indent << "nextIdx = nextGen[0]\n";
1047 out << indent << indent << indent
1048 << "direction = [positions[nextIdx][0] - positions[idx][0],\n";
1049 out << indent << indent << indent << indent
1050 << " positions[nextIdx][1] - positions[idx][1]]\n";
1051 out << indent << indent << indent << "curAngle = math.atan2(direction[1], direction[0])\n\n";
1052
1053 out << indent << indent << indent
1054 << "intersections = checkPossibleSegmentIntersection((idx, nextIdx), positions, "
1055 "lineEquations, nextGen[1], [])\n";
1056 out << indent << indent << indent << "if len(intersections) > 0:\n";
1057 out << indent << indent << indent << indent
1058 << "while len(intersections) > 0 and not count > numConnections:\n";
1059 out << indent << indent << indent << indent << indent
1060 << "fh.write(\"%.6f %.6f\\n\" %(intersections[0][0][0], intersections[0][0][1]))\n";
1061 out << indent << indent << indent << indent << indent << "count += 1\n";
1062 out << indent << "\n";
1063 out << indent << indent << indent << indent << indent << "idx = intersections[0][1]\n";
1064 out << indent << indent << indent << indent << indent
1065 << "direction = [positions[idx][0] - intersections[0][0][0],\n";
1066 out << indent << indent << indent << indent << indent
1067 << " positions[idx][1] - intersections[0][0][1]]\n";
1068 out << indent << indent << indent << indent << indent
1069 << "curAngle = math.atan2(direction[1], direction[0])\n";
1070 out << indent << indent << indent << indent << indent
1071 << "nextGen = computeMinAngle(idx, curAngle, positions, connections, False)\n";
1072 out << indent << "\n";
1073 out << indent << indent << indent << indent << indent
1074 << "intersections = checkPossibleSegmentIntersection((None, idx), positions, "
1075 "lineEquations, nextGen[1], intersections[0][0])\n";
1076 out << indent << indent << indent << "else:\n";
1077 out << indent << indent << indent << indent << "idx = nextIdx\n";
1078 out << indent << "\n";
1079 out << indent << indent << indent
1080 << "fh.write(\"%.6f %.6f\\n\" % (positions[idx][0], positions[idx][1]))\n";
1081 out << indent << "\n";
1082 out << indent << indent << indent << "if idx in passed:\n";
1083 out << indent << indent << indent << indent
1084 << "direction1 = [positions[idx][0] - positions[passed[-1]][0],\n";
1085 out << indent << indent << indent << indent << indent
1086 << " positions[idx][1] - positions[passed[-1]][1]]\n";
1087 out << indent << indent << indent << indent
1088 << "direction2 = [positions[origin][0] - positions[passed[-1]][0],\n";
1089 out << indent << indent << indent << indent << indent
1090 << " positions[origin][1] - positions[passed[-1]][1]]\n";
1091 out << indent << indent << indent << indent
1092 << "dist1 = distance(positions[idx], positions[passed[-1]])\n";
1093 out << indent << indent << indent << indent
1094 << "dist2 = distance(positions[origin], positions[passed[-1]])\n";
1095 out << indent << indent << indent << indent
1096 << "if dist1 * dist2 > 0.0 and math.fabs(math.fabs(dot(direction1, direction2) / (dist1 * "
1097 "dist2)) - 1.0) > 1e-9:\n";
1098 out << indent << indent << indent << indent << indent
1099 << "sys.stderr.write(\"error: projection cycling on element id: %d, vertex id: %d\\n\" "
1100 "%(i, idx))\n";
1101 out << indent << indent << indent << indent << "break\n\n";
1102
1103 out << indent << indent << indent << "passed.append(idx)\n";
1104 out << indent << indent << indent << "count += 1\n";
1105 out << indent << indent << "fh.write(\"\\n\")\n\n";
1106
1107 out << indent << indent << "if count > numConnections:\n";
1108 out << indent << indent << indent
1109 << "sys.stderr.write(\"error: projection cycling on element id: %d\\n\" % i)\n\n";
1110
1111 out << indent << indent << "for j in range(0, len(decoration[i]), 6):\n";
1112 out << indent << indent << indent << "for k in range(j, j + 6, 3):\n";
1113 out << indent << indent << indent << indent << "nextPos3D = ori.rotate(decoration[i][k:k+3])\n";
1114 out << indent << indent << indent << indent
1115 << "fh.write(\"%.6f %.6f\\n\" % (nextPos3D[0], nextPos3D[1]))\n";
1116 out << indent << indent << indent << "fh.write(\"\\n\")\n\n";
1117
1118 out << indent << "fh.close()\n\n";
1119
1120 out << "if __name__ == \"__main__\":\n";
1121 out << indent << "parser = argparse.ArgumentParser()\n";
1122 out << indent << "parser.add_argument('--export-vtk', action='store_true')\n";
1123 out << indent << "parser.add_argument('--export-web', action='store_true')\n";
1124 out << indent << "parser.add_argument('--show', action='store_true')\n";
1125 out << indent << "parser.add_argument('--background', nargs=3, type=float)\n";
1126 out << indent << "parser.add_argument('--project-to-plane', action='store_true')\n";
1127 out << indent << "parser.add_argument('--normal', nargs=3, type=float)\n";
1128 out << indent << "args = parser.parse_args()\n\n";
1129
1130 out << indent << "if (args.export_vtk):\n";
1131 out << indent << indent << "exportVTK()\n";
1132 out << indent << indent << "sys.exit()\n\n";
1133
1134 out << indent << "if (args.export_web):\n";
1135 out << indent << indent << "bgcolor = []\n";
1136 out << indent << indent << "if (args.background):\n";
1137 out << indent << indent << indent << "validBackground = True\n";
1138 out << indent << indent << indent << "for comp in bgcolor:\n";
1139 out << indent << indent << indent << indent << "if comp < 0.0 or comp > 1.0:\n";
1140 out << indent << indent << indent << indent << indent << "validBackground = False\n";
1141 out << indent << indent << indent << indent << indent << "break\n";
1142 out << indent << indent << indent << "if (validBackground):\n";
1143 out << indent << indent << indent << indent << "bgcolor = args.background\n";
1144 out << indent << indent << "exportWeb(bgcolor)\n";
1145 out << indent << indent << "sys.exit()\n\n";
1146
1147 out << indent << "if (args.show):\n";
1148 out << indent << indent << "sys.exit(showVTK())\n\n";
1149
1150 out << indent << "if (args.project_to_plane):\n";
1151 out << indent << indent << "normal = [0.0, 1.0, 0.0]\n";
1152 out << indent << indent << "if (args.normal):\n";
1153 out << indent << indent << indent << "normal = args.normal\n";
1154 out << indent << indent << "projectToPlane(normal)\n";
1155 out << indent << indent << "sys.exit()\n\n";
1156
1157 out << indent << "parser.print_help()\n";
1158}
1159
1161 double length, double minor, double major, double formFactor,
1162 const unsigned int numSegments) {
1163 double angle = 0;
1164 double dAngle = Physics::two_pi / numSegments;
1165
1166 MeshData mesh;
1167 mesh.vertices_m.push_back(Vector_t<double, 3>(0.0));
1168 for (unsigned int i = 0; i < numSegments; ++i, angle += dAngle) {
1169 Vector_t<double, 3> node(major * cos(angle), minor * sin(angle), 0);
1170 mesh.vertices_m.push_back(node);
1171
1172 unsigned int next = (i + 1) % numSegments;
1173 Vector_t<unsigned int, 3> baseTriangle(0u, next + 1, i + 1);
1174 mesh.triangles_m.push_back(baseTriangle);
1175
1176 Vector_t<unsigned int, 3> sideTriangle1(i + 1, next + 1, i + numSegments + 2);
1177 mesh.triangles_m.push_back(sideTriangle1);
1178
1179 Vector_t<unsigned int, 3> sideTriangle2(
1180 next + 1, next + numSegments + 2, i + numSegments + 2);
1181 mesh.triangles_m.push_back(sideTriangle2);
1182 }
1183
1184 mesh.vertices_m.push_back(Vector_t<double, 3>(0.0, 0.0, length));
1185 for (unsigned int i = 0; i < numSegments; ++i, angle += dAngle) {
1187 formFactor * major * cos(angle), formFactor * minor * sin(angle), length);
1188 mesh.vertices_m.push_back(node);
1189
1190 unsigned int next = (i + 1) % numSegments;
1191 Vector_t<unsigned int, 3> topTriangle(
1192 numSegments + 1, i + numSegments + 2, next + numSegments + 2);
1193 mesh.triangles_m.push_back(topTriangle);
1194 }
1195
1196 mesh.decorations_m.push_back(
1197 std::make_pair(Vector_t<double, 3>(0.0), Vector_t<double, 3>(0, 0, length)));
1198
1199 return mesh;
1200}
1201
1203 double length, double innerMinor, double innerMajor, double outerMinor, double outerMajor,
1204 const unsigned int numSegments) {
1205 double angle = 0.0;
1206 double dAngle = Physics::two_pi / numSegments;
1207
1208 MeshData mesh;
1209 for (unsigned int i = 0; i < numSegments; ++i, angle += dAngle) {
1210 mesh.vertices_m.push_back(
1211 Vector_t<double, 3>(outerMajor * cos(angle), outerMinor * sin(angle), 0.0));
1212 }
1213 for (unsigned int i = 0; i < numSegments; ++i, angle += dAngle) {
1214 mesh.vertices_m.push_back(
1215 Vector_t<double, 3>(innerMajor * cos(angle), innerMinor * sin(angle), 0.0));
1216 }
1217 for (unsigned int i = 0; i < numSegments; ++i, angle += dAngle) {
1218 mesh.vertices_m.push_back(
1219 Vector_t<double, 3>(outerMajor * cos(angle), outerMinor * sin(angle), length));
1220 }
1221 for (unsigned int i = 0; i < numSegments; ++i, angle += dAngle) {
1222 mesh.vertices_m.push_back(
1223 Vector_t<double, 3>(innerMajor * cos(angle), innerMinor * sin(angle), length));
1224 }
1225
1226 for (unsigned int i = 0; i < numSegments; ++i) {
1227 const unsigned int next = (i + 1) % numSegments;
1228 const unsigned int bottomOuter = i;
1229 const unsigned int bottomOuterNext = next;
1230 const unsigned int bottomInner = numSegments + i;
1231 const unsigned int bottomInnerNext = numSegments + next;
1232 const unsigned int topOuter = 2 * numSegments + i;
1233 const unsigned int topOuterNext = 2 * numSegments + next;
1234 const unsigned int topInner = 3 * numSegments + i;
1235 const unsigned int topInnerNext = 3 * numSegments + next;
1236
1237 mesh.triangles_m.push_back(
1238 Vector_t<unsigned int, 3>(bottomOuter, bottomOuterNext, topOuter));
1239 mesh.triangles_m.push_back(
1240 Vector_t<unsigned int, 3>(bottomOuterNext, topOuterNext, topOuter));
1241
1242 mesh.triangles_m.push_back(
1243 Vector_t<unsigned int, 3>(bottomInner, topInner, bottomInnerNext));
1244 mesh.triangles_m.push_back(
1245 Vector_t<unsigned int, 3>(bottomInnerNext, topInner, topInnerNext));
1246 }
1247
1248 return mesh;
1249}
1250
1252 double length, double minor, double major, double formFactor) {
1253 MeshData mesh;
1254
1255 const double poleHalfWidthX = 0.45 * major;
1256 const double poleHalfHeightX = 0.75 * minor;
1257 const double poleHalfWidthY = 0.75 * major;
1258 const double poleHalfHeightY = 0.45 * minor;
1259 const double xOffset = major + poleHalfWidthX;
1260 const double yOffset = minor + poleHalfHeightY;
1261
1262 MeshData rightPole = getBox(length, poleHalfWidthX, poleHalfHeightX, formFactor);
1263 translateMesh(rightPole, xOffset, 0.0);
1264 appendMesh(mesh, rightPole);
1265
1266 MeshData leftPole = getBox(length, poleHalfWidthX, poleHalfHeightX, formFactor);
1267 translateMesh(leftPole, -xOffset, 0.0);
1268 appendMesh(mesh, leftPole);
1269
1270 MeshData topPole = getBox(length, poleHalfWidthY, poleHalfHeightY, formFactor);
1271 translateMesh(topPole, 0.0, yOffset);
1272 appendMesh(mesh, topPole);
1273
1274 MeshData bottomPole = getBox(length, poleHalfWidthY, poleHalfHeightY, formFactor);
1275 translateMesh(bottomPole, 0.0, -yOffset);
1276 appendMesh(mesh, bottomPole);
1277
1278 return mesh;
1279}
1280
1281MeshData MeshGenerator::getSolenoid(double length, double minor, double major) {
1282 const double boreMinor = 0.45 * minor;
1283 const double boreMajor = 0.45 * major;
1284 const double collarLength = std::min(0.18 * length, 0.8 * std::min(minor, major));
1285
1286 if (collarLength <= 1e-12 || 2.0 * collarLength >= length) {
1287 return getTube(length, boreMinor, boreMajor, minor, major);
1288 }
1289
1290 MeshData mesh;
1291
1292 MeshData entranceCollar =
1293 getTube(collarLength, boreMinor, boreMajor, 1.18 * minor, 1.18 * major);
1294 appendMesh(mesh, entranceCollar);
1295
1296 MeshData body = getTube(length - 2.0 * collarLength, boreMinor, boreMajor, minor, major);
1297 translateMesh(body, 0.0, 0.0, collarLength);
1298 appendMesh(mesh, body);
1299
1300 MeshData exitCollar = getTube(collarLength, boreMinor, boreMajor, 1.18 * minor, 1.18 * major);
1301 translateMesh(exitCollar, 0.0, 0.0, length - collarLength);
1302 appendMesh(mesh, exitCollar);
1303
1304 return mesh;
1305}
1306
1307MeshData MeshGenerator::getRFCavity(double length, double minor, double major) {
1308 const double boreMinor = 0.42 * minor;
1309 const double boreMajor = 0.42 * major;
1310 const std::vector<double> profile = {0.78, 1.15, 0.82, 1.25, 0.82, 1.15, 0.78};
1311
1312 MeshData mesh;
1313 const auto appendTubeSegment = [&](const double zStart, const double segmentLength,
1314 const double scale) {
1315 if (segmentLength <= 1e-12) {
1316 return;
1317 }
1318 MeshData segment =
1319 getTube(segmentLength, boreMinor, boreMajor, scale * minor, scale * major);
1320 translateMesh(segment, 0.0, 0.0, zStart);
1321 appendMesh(mesh, segment);
1322 };
1323 const double segmentLength = length / static_cast<double>(profile.size());
1324 double z = 0.0;
1325 for (double scale : profile) {
1326 appendTubeSegment(z, segmentLength, scale);
1327 z += segmentLength;
1328 }
1329 return mesh;
1330}
1331
1332MeshData MeshGenerator::getTravelingWave(double length, double minor, double major) {
1333 const double boreMinor = 0.48 * minor;
1334 const double boreMajor = 0.48 * major;
1335 const std::vector<double> profile = {0.92, 1.05, 0.92, 1.05, 0.92, 1.05, 0.92, 1.05};
1336
1337 MeshData mesh;
1338 const auto appendTubeSegment = [&](const double zStart, const double segmentLength,
1339 const double scale) {
1340 if (segmentLength <= 1e-12) {
1341 return;
1342 }
1343 MeshData segment =
1344 getTube(segmentLength, boreMinor, boreMajor, scale * minor, scale * major);
1345 translateMesh(segment, 0.0, 0.0, zStart);
1346 appendMesh(mesh, segment);
1347 };
1348 const double segmentLength = length / static_cast<double>(profile.size());
1349 double z = 0.0;
1350 for (double scale : profile) {
1351 appendTubeSegment(z, segmentLength, scale);
1352 z += segmentLength;
1353 }
1354 return mesh;
1355}
1356
1357MeshData MeshGenerator::getBox(double length, double width, double height, double formFactor) {
1358 MeshData mesh;
1359 mesh.vertices_m.push_back(Vector_t<double, 3>(width, height, 0.0));
1360 mesh.vertices_m.push_back(Vector_t<double, 3>(-width, height, 0.0));
1361 mesh.vertices_m.push_back(Vector_t<double, 3>(-width, -height, 0.0));
1362 mesh.vertices_m.push_back(Vector_t<double, 3>(width, -height, 0.0));
1363
1364 mesh.vertices_m.push_back(Vector_t<double, 3>(formFactor * width, formFactor * height, length));
1365 mesh.vertices_m.push_back(
1366 Vector_t<double, 3>(-formFactor * width, formFactor * height, length));
1367 mesh.vertices_m.push_back(
1368 Vector_t<double, 3>(-formFactor * width, -formFactor * height, length));
1369 mesh.vertices_m.push_back(
1370 Vector_t<double, 3>(formFactor * width, -formFactor * height, length));
1371
1372 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(0, 2, 1));
1373 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(0, 3, 2));
1374
1375 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(0, 1, 4));
1376 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(4, 1, 5));
1377 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(1, 2, 5));
1378 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(5, 2, 6));
1379 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(2, 3, 6));
1380 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(6, 3, 7));
1381 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(3, 0, 7));
1382 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(7, 0, 4));
1383
1384 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(4, 5, 6));
1385 mesh.triangles_m.push_back(Vector_t<unsigned int, 3>(4, 6, 7));
1386
1387 mesh.decorations_m.push_back(
1388 std::make_pair(Vector_t<double, 3>(0.0), Vector_t<double, 3>(0, 0, length)));
1389
1390 return mesh;
1391}
ippl::Vector< T, Dim > Vector_t
Inform * gmsg
Definition changes.cpp:7
std::vector< Vector_t< double, 3 > > vertices_m
std::vector< std::pair< Vector_t< double, 3 >, Vector_t< double, 3 > > > decorations_m
std::vector< Vector_t< unsigned int, 3 > > triangles_m
Rigid spatial transform between a parent frame and a local frame.
ippl::Vector< double, 3 > rotateTo(const ippl::Vector< double, 3 > &r) const
Rotate a vector from the parent frame into the local frame.
ippl::Vector< double, 3 > transformTo(const ippl::Vector< double, 3 > &r) const
Map a point from the parent frame to the local frame.
CoordinateSystemTrafo inverted() const
Return the inverse transform.
virtual double getElementLength() const
Get design length.
std::pair< ApertureType, std::vector< double > > getAperture() const
virtual ElementType getType() const =0
Get element type std::string.
PlacedElement getPlacedElement() const
Return a placed-element view assembled from the current bridge objects.
virtual void getElementDimensions(double &begin, double &end) const
Return the nominal body extent of the element.
static MeshData getSolenoid(double length, double minor, double major)
Build a solenoid body as a hollow tube with short end collars.
static MeshData getTube(double length, double innerMinor, double innerMajor, double outerMinor, double outerMajor, const unsigned int numSegments=36)
Build a hollow tube aligned with the local z-axis.
static MeshData getTravelingWave(double length, double minor, double major)
Build a traveling-wave structure with repeated shallow corrugations.
static MeshData getRFCavity(double length, double minor, double major)
Build a standing-wave cavity body from a sequence of bulged cells.
void add(const ElementBase &element)
static MeshData getBox(double length, double width, double height, double formFactor)
std::vector< MeshData > elements_m
void setDriftReference(double minor, double major)
Set the drift support radius used when meshing drift spaces.
static MeshData getQuadrupole(double length, double minor, double major, double formFactor)
Build a quadrupole-like body from four longitudinal pole blocks.
void write(const std::string &fname)
static MeshData getCylinder(double length, double minor, double major, double formFactor, const unsigned int numSegments=36)
static bool getTransverseSupport(const ElementBase &element, double &minor, double &major)
Extract a transverse support size suitable for placement/export meshes.
Interface for general multipole.
Definition Multipole.h:30
size_t getMaxNormalComponentIndex() const
Definition Multipole.h:219
static OpalData * getInstance()
Definition OpalData.cpp:193
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Definition OpalData.cpp:567
CoordinateSystemTrafo getNominalBodyTransform() const
Abstract class for a solenoid magnet.
Definition Solenoid.h:33
constexpr double two_pi
The value of.
Definition Physics.h:40
std::string combineFilePath(std::initializer_list< std::string > ilist)
Definition Util.cpp:193
std::string base64_encode(const std::string &string_to_encode)
Definition Util.cpp:359