Removed tight connections between data structures, auxiliary tools and algorithms in order to create extensible solution, easy for maintenance and improvements;
Code is separated on several functional units responsible for specific operation for the sake of simplification of debugging and readability;
Introduced new data structures enabling possibility to manipulate discrete model of particular entity (edge, wire, face) in order to perform computations locally instead of processing an entire model.
The workflow of updated component can be divided on six parts:
* Creation of model data structure: source TopoDS_Shape passed to algorithm is analyzed and exploded on faces and edges. For each topological entity corresponding reflection is created in data model. Note that underlying algorithms use data model as input and access it via common interface which allows user to create custom data model with necessary dependencies between particular entities;
* Discretize edges 3D & 2D curves: 3D curve as well as associated set of 2D curves of each model edge is discretized in order to create coherent skeleton used as a base in faces meshing process. In case if some edge of source shape already contains polygonal data which suites specified parameters, it is extracted from shape and stored to the model as is. Each edge is processed separately, adjacency is not taken into account;
* Heal discrete model: source TopoDS_Shape can contain problems, such as open-wire or self-intersections, introduced during design, exchange or modification of model. In addition, some problems like self-intersections can be introduced by roughly discretized edges. This stage is responsible for analysis of discrete model in order to detect and repair faced problems or refuse model’s part for further processing in case if problem cannot be solved;
* Preprocess discrete model: defines actions specific for implemented approach to be performed before meshing of faces. By default, iterates over model faces and checks consistency of existing triangulations. Cleans topological faces and its adjacent edges from polygonal data in case of inconsistency or marks face of discrete model as not required for computation;
* Discretize faces: represents core part performing mesh generation for particular face based on 2D discrete data related to processing face. Caches polygonal data associated with face’s edges in data model for further processing and stores generated mesh to TopoDS_Face;
* Postprocess discrete model: defines actions specific for implemented approach to be performed after meshing of faces. By default, stores polygonal data obtained on previous stage to TopoDS_Edge objects of source model.
Component is now spread over IMeshData, IMeshTools, BRepMeshData and BRepMesh units.
<!break>
1. Extend "tricheck" DRAW-command in order to find degenerated triangles.
2. Class BRepMesh_FastDiscret::Parameters has been declared as deprecated.
3. NURBS range splitter: do not split intervals without necessity. Intervals are split only in case if it is impossible to compute normals directly on intervals.
4. Default value of IMeshTools_Parameters::MinSize has been changed. New value is equal to 0.1*Deflection.
5. Correction of test scripts:
1) perf mesh bug27119: requested deflection is increased from 1e-6 to 1e-5 to keep reasonable performance (but still reproducing original issue)
2) bugs mesh bug26692_1, 2: make snapshot of triangulation instead of wireframe (irrelevant)
Correction in upgrade guide.
n BRepLib
n BRepMAT2d
n BRepMesh
+n BRepMeshData
n BRepOffset
n BRepOffsetAPI
n BRepPrim
n HLRAppli
n Hatch
n HatchGen
+n IMeshData
+n IMeshTools
n IntCurve
n IntCurveSurface
n IntCurvesFace
Previously Document format version after restoring by DocumentRetrievalDriver was propagated using static methods of corresponding units (like MDataStd or MNaming) to static variables of these units and after that became accessible to Drivers of these units.
Now Document format version is available to drivers via RelocationTable. The Relocation table now keeps HeaderData of the document and a format version can be extracted in next way: theRelocTable.GetHeaderData()->StorageVersion().
Obsolete methods: *static void SetDocumentVersion (const Standard_Integer DocVersion)* and *static Standard_Integer DocumentVersion()* of *BinMDataStd*, *BinMNaming*, *XmlMDataStd* and *XmlMNaming* are removed.
+
+@subsection upgrade_740_changed_api_of_brepmesh BRepMesh - revision of the data model
+
+The entire structure of *BRepMesh* component has been revised and separated into several logically connected classes.
+
+In new version, deflection is controlled more accurately, this may be necessary to tune parameters of call of the BRepMesh algorithm on the application side to obtain the same quality of presentation and/or performance as before.
+
+*BRepMesh_FastDiscret* and *BRepMesh_FastDiscretFace* classes have been removed.
+
+The following changes have been introduced in the API of *BRepMesh_IncrementalMesh*, component entry point:
+* Due to revised logic, *adaptiveMin* parameter of the constructor has been removed as meaningless;
+* *BRepMesh_FastDiscret::Parameters* has been moved to a separate structure called *IMeshTools_Parameters*; the signatures of related methods have been changed correspondingly.
+
+* Interface of *BRepMesh_Delaun* class has been changed.
+
+Example of usage:
+Case 1 (explicit parameters):
+~~~~
+#include <IMeshData_Status.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <BRepMesh_IncrementalMesh.hxx>
+
+Standard_Boolean meshing_explicit_parameters()
+{
+ BRepMesh_IncrementalMesh aMesher (aShape, 0.1, Standard_False, 0.5, Standard_True);
+ const Standard_Integer aStatus = aMesher.GetStatusFlags();
+ return !aStatus;
+}
+
+Standard_Boolean meshing_new()
+{
+ IMeshTools_Parameters aMeshParams;
+ aMeshParams.Deflection = 0.1;
+ aMeshParams.Angle = 0.5;
+ aMeshParams.Relative = Standard_False;
+ aMeshParams.InParallel = Standard_True;
+ aMeshParams.MinSize = Precision::Confusion();
+ aMeshParams.InternalVerticesMode = Standard_True;
+ aMeshParams.ControlSurfaceDeflection = Standard_True;
+
+ BRepMesh_IncrementalMesh aMesher (aShape, aMeshParams);
+ const Standard_Integer aStatus = aMesher.GetStatusFlags();
+ return !aStatus;
+}
+~~~~
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" stroke-dasharray="none" shape-rendering="auto" font-family="'Dialog'" width="503" text-rendering="auto" fill-opacity="1" contentScriptType="text/ecmascript" color-interpolation="auto" color-rendering="auto" preserveAspectRatio="xMidYMid meet" font-size="12" viewBox="0 0 503 507" fill="black" stroke="black" image-rendering="auto" stroke-miterlimit="10" zoomAndPan="magnify" version="1.0" stroke-linecap="square" stroke-linejoin="miter" contentStyleType="text/css" font-style="normal" height="507" stroke-width="1" stroke-dashoffset="0" font-weight="normal" stroke-opacity="1">
+<!--Generated by the Batik Graphics2D SVG Generator-->
+<defs id="genericDefs"/>
+<g>
+<defs id="defs1">
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath1">
+<path d="M9 38 L494 38 L494 498 L9 498 L9 38 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath2">
+<path d="M9 38 L492 38 L492 496 L9 496 L9 38 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath3">
+<path d="M185 43 L316 43 L316 61 L185 61 L185 43 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath4">
+<path d="M185 43 L319 43 L319 61 L185 61 L185 43 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath5">
+<path d="M25 134 L206 134 L206 206 L25 206 L25 134 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath6">
+<path d="M25 134 L204 134 L204 204 L25 204 L25 134 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath7">
+<path d="M40 139 L191 139 L191 154 L40 154 L40 139 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath8">
+<path d="M153 122 L175 122 L175 144 L153 144 L153 122 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath9">
+<path d="M97 105 L232 105 L232 123 L97 123 L97 105 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath10">
+<path d="M97 105 L234 105 L234 123 L97 123 L97 105 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath11">
+<path d="M285 134 L470 134 L470 206 L285 206 L285 134 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath12">
+<path d="M285 134 L468 134 L468 204 L285 204 L285 134 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath13">
+<path d="M292 139 L463 139 L463 154 L292 154 L292 139 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath14">
+<path d="M309 122 L331 122 L331 144 L309 144 L309 122 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath15">
+<path d="M253 105 L388 105 L388 123 L253 123 L253 105 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath16">
+<path d="M253 105 L390 105 L390 123 L253 123 L253 105 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath17">
+<path d="M27 242 L208 242 L208 314 L27 314 L27 242 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath18">
+<path d="M27 242 L206 242 L206 312 L27 312 L27 242 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath19">
+<path d="M63 247 L171 247 L171 262 L63 262 L63 247 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath20">
+<path d="M286 242 L470 242 L470 314 L286 314 L286 242 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath21">
+<path d="M286 242 L468 242 L468 312 L286 312 L286 242 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath22">
+<path d="M307 247 L448 247 L448 262 L307 262 L307 247 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath23">
+<path d="M28 350 L204 350 L204 422 L28 422 L28 350 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath24">
+<path d="M28 350 L202 350 L202 420 L28 420 L28 350 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath25">
+<path d="M74 355 L158 355 L158 370 L74 370 L74 355 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath26">
+<path d="M286 350 L470 350 L470 422 L286 422 L286 350 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath27">
+<path d="M286 350 L468 350 L468 420 L286 420 L286 350 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath28">
+<path d="M304 355 L451 355 L451 370 L304 370 L304 355 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath29">
+<path d="M45 74 L77 74 L77 106 L45 106 L45 74 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath30">
+<path d="M76 74 L158 74 L158 89 L76 89 L76 74 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath31">
+<path d="M357 458 L389 458 L389 490 L357 490 L357 458 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath32">
+<path d="M388 458 L421 458 L421 473 L388 473 L388 458 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath33">
+<path d="M129 26 L151 26 L151 48 L129 48 L129 26 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath34">
+<path d="M14 9 L267 9 L267 27 L14 27 L14 9 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath35">
+<path d="M14 9 L269 9 L269 27 L14 27 L14 9 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath36">
+<path d="M469 473 L487 473 L487 491 L469 491 L469 473 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath37">
+<path d="M-1 -1 L504 -1 L504 508 L-1 508 L-1 -1 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath38">
+<path d="M279 272 L289 272 L289 281 L279 281 L279 272 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath39">
+<path d="M102 343 L111 343 L111 353 L102 353 L102 343 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath40">
+<path d="M302 119 L312 119 L312 128 L302 128 L302 119 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath41">
+<path d="M110 235 L119 235 L119 245 L110 245 L110 235 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath42">
+<path d="M279 380 L289 380 L289 389 L279 389 L279 380 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath43">
+<path d="M369 451 L378 451 L378 461 L369 461 L369 451 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath44">
+<path d="M56 127 L65 127 L65 137 L56 137 L56 127 Z"/>
+</clipPath>
+</defs>
+<g fill="rgb(131,122,133)" font-family="'Segoe UI'" stroke-linejoin="round" stroke="rgb(131,122,133)" stroke-width="0" stroke-miterlimit="0">
+<rect x="11" y="40" clip-path="url(#clipPath1)" width="481" rx="12.5" opacity="0.2549" ry="12.5" height="456" stroke="none"/>
+<rect x="12" y="41" clip-path="url(#clipPath1)" width="481" rx="12.5" opacity="0.2549" ry="12.5" height="456" stroke="none"/>
+<rect x="10" y="39" clip-path="url(#clipPath2)" fill="white" width="481" rx="12.5" ry="12.5" height="456" stroke="none"/>
+</g>
+<g fill="rgb(114,73,110)" stroke-width="1.1" font-family="'Segoe UI'" stroke-linecap="butt" stroke="rgb(114,73,110)">
+<rect x="10" y="39" clip-path="url(#clipPath2)" fill="none" width="480" rx="12.5" ry="12.5" height="455"/>
+<image x="186" y="44" clip-path="url(#clipPath3)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABP0lEQVR42mNgGPKA EV3g+LWn/4ObljE8XV7CIB3ZAxbDxl5bF8VgqSXNyIhN876uJDD/P9SG/0i2/YfK OJfNBxuCYsCPn3/+//n3D85/8f4LUC1UCeN/OBtk7f///xmUpQQZGN3K1/zH5rf1 DX4Mrz99Z6hYfgFFfH6mFdAARoaX778yWObPYmABCU7Ic0dRVDBpJ1hR7vTDDH2Z jkDboDYDnR7avoNhbZUnAwszE1iMiejQRQOszMzgAGXCFz9///xluPP8EwMbKxMY 33nxCSwGAiwsTODYYIE5GVM/I8NKoFNDmrcw/EcK2E1NAVAXMGG6FBQLyBH79z/u iASxOdmYUb1w/u5LBsW4fnAAggxiYWICBhaIZkRjMzKoxPcznLj+DNUAUMoCJQ6F 2D4GVqBqEK0Q04+F3Q9PiQOfmQBRlXo/vG/acgAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="205" y="57" clip-path="url(#clipPath4)" fill="black" stroke="none" xml:space="preserve">BRepMesh Workflow</text>
+</g>
+<g stroke-linecap="butt" font-size="11" fill="rgb(131,122,133)" font-family="'Segoe UI'" stroke="rgb(131,122,133)" font-weight="bold" stroke-width="1.1">
+<rect x="27" y="136" clip-path="url(#clipPath5)" width="177" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="28" y="137" clip-path="url(#clipPath5)" width="177" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="26" y="135" clip-path="url(#clipPath6)" fill="white" width="177" rx="12.5" ry="12.5" height="68" stroke="none"/>
+<rect x="26" y="135" clip-path="url(#clipPath6)" fill="none" width="176" rx="12.5" ry="12.5" height="67" stroke="rgb(224,133,3)"/>
+<text x="41" y="152" clip-path="url(#clipPath7)" fill="black" stroke="none" xml:space="preserve">Create Model Data Structure</text>
+</g>
+<g fill="rgb(69,69,69)" stroke-width="1.1" font-family="'Segoe UI'" stroke-linecap="butt" stroke="rgb(69,69,69)">
+<rect x="154" y="123" clip-path="url(#clipPath8)" width="20" height="20" stroke="none"/>
+<rect x="154" y="123" clip-path="url(#clipPath8)" fill="none" width="19" height="19" stroke="rgb(136,136,136)" stroke-width="0.1"/>
+</g>
+<g stroke-linecap="butt" font-size="11" fill="rgb(136,136,136)" font-family="'Segoe UI'" stroke="rgb(136,136,136)" stroke-width="0.1">
+<image x="98" y="106" clip-path="url(#clipPath9)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAkUlEQVR42mNgGAX0 B/O3XP+PzGcEERZVa/9bqonDBY/feslwoi2YEZsBel6t/wuzghgSfTTB8kwgQl9e mCHWTh2OQXxc4NK2asb+aevgLmEBEe++/GS4++IjXBGID7MNl0EwQ8AGvPn8g+HG 0w9wSRAfZhshb4ANuP70PcOHrz/hCp5/+IbTC+hhQHEsjAIGBgCVuEWDRzoaKgAA AABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="117" y="119" clip-path="url(#clipPath10)" fill="black" stroke="none" xml:space="preserve">IMeshData_Model : [1]</text>
+<rect x="287" y="136" clip-path="url(#clipPath11)" fill="rgb(131,122,133)" width="181" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="288" y="137" clip-path="url(#clipPath11)" fill="rgb(131,122,133)" width="181" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="286" y="135" clip-path="url(#clipPath12)" fill="white" width="181" rx="12.5" ry="12.5" height="68" stroke="none"/>
+</g>
+<g stroke-linecap="butt" font-size="11" fill="rgb(224,133,3)" font-family="'Segoe UI'" stroke="rgb(224,133,3)" font-weight="bold" stroke-width="1.1">
+<rect x="286" y="135" clip-path="url(#clipPath12)" fill="none" width="180" rx="12.5" ry="12.5" height="67"/>
+<text x="293" y="152" clip-path="url(#clipPath13)" fill="black" stroke="none" xml:space="preserve">Discretize Edges 3D & 2D Curves</text>
+</g>
+<g fill="rgb(209,209,209)" stroke-width="1.1" font-family="'Segoe UI'" stroke-linecap="butt" stroke="rgb(209,209,209)">
+<rect x="310" y="123" clip-path="url(#clipPath14)" width="20" height="20" stroke="none"/>
+<rect x="310" y="123" clip-path="url(#clipPath14)" fill="none" width="19" height="19" stroke="rgb(136,136,136)" stroke-width="0.1"/>
+</g>
+<g stroke-linecap="butt" font-size="11" fill="rgb(136,136,136)" font-family="'Segoe UI'" stroke="rgb(136,136,136)" stroke-width="0.1">
+<image x="254" y="106" clip-path="url(#clipPath15)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAnklEQVR42mNgGAW0 A/O3XP9PjDpGXBJ6Xq3/C7OCGBJ9NOFqLKrW/rdUE4erOX7rJQMzLgNe3t7XeP+D VENH/9SGjcumNoLEvGOyGpKcNBn05UXA+MnbLwwsMNtwGdQ/bR3YOyCXvPvyk+Hu i49wORAfbMClbdWMxHjjzecfDDeefoDLg/gspITB9afvGT58/QlX8/zDN8pjYRQw MAAAk/9KnUC0a2QAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="273" y="119" clip-path="url(#clipPath16)" fill="black" stroke="none" xml:space="preserve">IMeshData_Model : [1]</text>
+<rect x="29" y="244" clip-path="url(#clipPath17)" fill="rgb(131,122,133)" width="177" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="30" y="245" clip-path="url(#clipPath17)" fill="rgb(131,122,133)" width="177" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="28" y="243" clip-path="url(#clipPath18)" fill="white" width="177" rx="12.5" ry="12.5" height="68" stroke="none"/>
+</g>
+<g stroke-linecap="butt" font-size="11" fill="rgb(224,133,3)" font-family="'Segoe UI'" stroke="rgb(224,133,3)" font-weight="bold" stroke-width="1.1">
+<rect x="28" y="243" clip-path="url(#clipPath18)" fill="none" width="176" rx="12.5" ry="12.5" height="67"/>
+<text x="64" y="260" clip-path="url(#clipPath19)" fill="black" stroke="none" xml:space="preserve">Heal Discrete Model</text>
+<rect x="288" y="244" clip-path="url(#clipPath20)" fill="rgb(131,122,133)" width="180" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="289" y="245" clip-path="url(#clipPath20)" fill="rgb(131,122,133)" width="180" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="287" y="243" clip-path="url(#clipPath21)" fill="white" width="180" rx="12.5" ry="12.5" height="68" stroke="none"/>
+<rect x="287" y="243" clip-path="url(#clipPath21)" fill="none" width="179" rx="12.5" ry="12.5" height="67"/>
+<text x="308" y="260" clip-path="url(#clipPath22)" fill="black" stroke="none" xml:space="preserve">Preprocess Discrete Model</text>
+<rect x="30" y="352" clip-path="url(#clipPath23)" fill="rgb(131,122,133)" width="172" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="31" y="353" clip-path="url(#clipPath23)" fill="rgb(131,122,133)" width="172" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="29" y="351" clip-path="url(#clipPath24)" fill="white" width="172" rx="12.5" ry="12.5" height="68" stroke="none"/>
+<rect x="29" y="351" clip-path="url(#clipPath24)" fill="none" width="171" rx="12.5" ry="12.5" height="67"/>
+<text x="75" y="368" clip-path="url(#clipPath25)" fill="black" stroke="none" xml:space="preserve">Discretize Faces</text>
+<rect x="288" y="352" clip-path="url(#clipPath26)" fill="rgb(131,122,133)" width="180" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="289" y="353" clip-path="url(#clipPath26)" fill="rgb(131,122,133)" width="180" rx="12.5" opacity="0.2549" ry="12.5" height="68" stroke="none"/>
+<rect x="287" y="351" clip-path="url(#clipPath27)" fill="white" width="180" rx="12.5" ry="12.5" height="68" stroke="none"/>
+<rect x="287" y="351" clip-path="url(#clipPath27)" fill="none" width="179" rx="12.5" ry="12.5" height="67"/>
+<text x="305" y="368" clip-path="url(#clipPath28)" fill="black" stroke="none" xml:space="preserve">Postprocess Discrete Model</text>
+</g>
+<g stroke-width="1.1" font-family="'Segoe UI'" stroke-linecap="butt">
+<image x="46" y="75" clip-path="url(#clipPath29)" width="30" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHsAAAB7CAYAAABUx/9/AAAgAElEQVR42u2dWXdb 15Xnz9nn3AETQZCEKGqyBttJpDjLiVPp6qRrha5a/ZhH+zlP9ZAvYelL5KHf8hr1 W9eqp15ZSg/lWk5cSdoRE8u2TFkTKZAEMd/hDL33ufcCIEXJkk1JlAMsXwMigAtg /+5/732mfbi1lh31G+ccGMu/5+UrQHfvXL8IrdYa9F5fgajdgLi/AWq5BiuDCiSN NqSjEqQDLtgSYzoKoJ608H0LTFUGUJxXDiqGsR3W8ZtGhLFhW4x5Fau90sj47Ya5 XxkYudkzQfW4CRttU7tx3zSbF83VS2sm+y7vmfwbMrSjOep2lC8H4MvArl+FVYJ7 L4P7u8pALkYrMu6BSEtM1ubKMu0nUkNJpB3ha6GlFFyYgQTmJaInS2D0EEpDzoxO AYRnOnzIQJSMgMTAgGsQymhtNesIJcAk1VGivRNlNUiZ4j1QrLai1ysDden6ReXg r14x1xA+u3TZcD7+5kcWvDyykAkw3lavXZEEuNPfkHHzokxHkUS43pwWPvP9wHIW yqQfmJR7RlaCkR0FQjHfCuExrj3GEo9HXEhhBTMctEQsEDCN5w4UujWwRkepZgIh +5yughSUTkdylBheic0wjqXtpxZkzHwW4efGUYklYlRK8fuoV/sbqn5vRTnwq+8p /OIsA3/0oPOj4sYnkK8AueibjbYkBc8x5vdkxyvZqt+zvZIMgtAkusSNKHOAMjBT Mh4v8YSXjVQlsCywBkIQ1lP4WFgmDR54doH254R38pnM4EcSEg2cKY2H5Cw2mqcc TGTwMSg5sr4dQmpHhsHIGjO0gC7CFyMVx1GN10Yj3k9qqp528coixZ9vN5Rz9c7N Hx3oLxz2QZC3E98n5Q7SXuBDOQSWVjTIcpBCFRVYVdzWAPCxFlWkVQWMxJbzsjW2 ZC2EarS1oEfdeZ0Oa8wY31jlMWuktVoiLFS4BvTfqHPQnKMf4KCAy5QBJMIr90Rp bleWlnY4NxEHPkIjDQ1GeGC8z4TuG2P60vIe07wfe6YvjMLnvUFihlHFq8VdoZNF P0mOGvQXBnsa8uo1JlvoogcYh6vxQgDyi7IwjVKskxpCnPO5X0uNmkfD19ER11HV c5zpOaX1XNLfPJEOt1Z0NJi3Oilj0A24ADy9RIb4EZijcfKr+HHunvGpb0Gyxu+A DLJ7jQ/pscKHxoIQMRf+UISVXa+8dN+vLt+TQnQtwwN01xrRwQus44HcTWzSQ2N2 A+H3NLRHRp0Z9oOduDKoqGZrTV1bZepFQ3/usA9S8mZ7ENZ0MxDesMyCsCJSNaet X8fXLaDTbaAS8R7m0Ubzab91OhlsnlZRt6mTeA5jLIrSw6cxRFOYBpEBBoIME8hj 0Hthu8NOQ8fD6Bw8HjpF55Ayq+heG+EHXRnOtfzK8m2v2ryNn7GLT+yip9jBoNDG 8+8InnS0J7ssjgY6LQ97ohUvNyrRi1a6uHz58nMEjeguo/WbLfGWkt6nwoRi2CyH LKlzny8Ah2OayxMA5gxa+6wFfhaRnVVJ71uD1o3/PHzw8d8nvY3XUX2LIINQhjWO hmd0iKCaHX4F78t4X2bglZjAg+5BhvkR4N+y++LfgP8W08+5f5fcvXvslfPzhPgT eKiT0WLcvXcu3r3zuop7KzIoh1KGFQN2DriuYXZQUVYGeNn5zLN4JgE6Pc7XS124 gNfz/fM3GXv3Ervy9irmocx+o5Q9UTODVXZN3tn+yC/vzof4VMVg/OWpbqDjXTRc LBqtltFdL3GjjvV31r+T9h6c1Wk0nxs7g4OJeKZidNVCZvekYFI1ZWFO0bmKCU/e JJq+Gwu7cOfublrpJvs7qdupnVy7yu9R5TphRsXMpBHD3J0ukl2vdmy9unD2L5i5 P0D3vgVCboLV28babeuJNlCcZ2wwnN+NTi2+kVxjq+ja2XNT+TNXdqHmd1DNvLUW mNt3y1HKqiVeasRMNlmSnMTM+Qz+1HNo2vP4my8MHtz4cX9j7ScmGZxE9YVeqZ6r t8ZkUMnUm6tW5PAnFwC6dFFcBOLhg08d47/D1GM5dS+z8ED3eG6Qfn4f5I/JE2Te AGGFatg+Pty59S28OBe98gJdbhV8At2CDU1qfQUB+NgaiPsJh1ttWGjfZKuX1uza c1L5M1P23gTsp3L97HpIyZfmO+jqvHmwaRNV3QTrHbdMraCiTwxbN94kJaP1PHLD Ts3OsMEY5ARaFo+dcjmMOzQYn8iX75Hxk93s2N42V372bye8fXE9O9JM6aRyPEjl OhkyfJCS0svN1/+IF989zuR9w9MNVHfLcK9lbLor7EKXkriz62eja6u/feYJ3DNR tgNNhlm7Kik2MzClkulUjfUwLqfLmuvT+KKz+MoLCPzCqPXxT/r3P/ovCLyJCsZw iUoO8jjsYm8eb3P1Asg9Si2Ac3c/Odh0TjY++NTx8PN7zjEVErIwAfnniFz1uQcR Mv9umYch1ePzApPIxWjns2/hBVEXVYxSjJUsZz426z1p8SUGmxqY1NsSY8tKWhfL r//aXMEPRy72yMN2oC9fhnd+iW4bExT8TZXYQD2Vqont1hNop7Nc8/P4wvNp/8Gb vTt/eFvHg1MyrCPTOhPhPsiFAceAiwwbchjTYA+ku+/Y820ff+TnPRA+8Cnw+eGg y8wLFaEFJKTD9rG4/cV5dPdC+FWEzLB5iakbV5Bgiz+xPmoD2JKSZvVq4dbfZocN /FBhF/GZ2s03LpwLwOtVw65ujGSy7Gl52gh2Dv3TeUxqvt2/+6d/jNp3vovx15el +UlGPVZy4OKlMx6pd6yqx8F9JgHpMfCnVT+dB0ygg8iahEjTj9t3XlGD7RVZbqRW SPphHighEkhYKWI2WbD27vy8/d4Hd+36z1ftYcfxQ4Odgb4Cb91b8e/XFgPebc35 fW8xDeVxaeCM5eYCquF8vLv5Vv/uH1bxDfP4oxEyuexaBtkv7YU8rWI+HY+fJdyn gc/Gij9Q7SJz9QVwOkw6rEU76xdAllHoGNnwIkCR89SXXPQMS6MHtr3UNK6J9rN/ MYcJ/FBgZ6AZgr7h++0GZs/RHEvlInj8JDapXrHMXLDCXhjcu/7TqH3re6hiOVEz Zdc5ZLEPMjsI8pEaWvgS6LnihdiT2eNrRdy9ewrDV8OrHxvRgBTGPODUg2vBVANr g868cXH8Z28hcHYowL82bAf6HUrE/q/H7rNyVO3OqVQ0uaycQGhntdEXWDq82P3i g/+qk+iEV25wp+aw5iBnnRmTmPxyQH5C6GPge9We9w9wNeosJLt3zgSVpci6eO9x NAom97FVXseILWFPsA8NJW5X3r1kvy7wrwV7rOgcdFxmdW3CpsfFKcw4zzFtXksH 2292b//+nzg2kL3yvMuyXVvZK081qSgmi0e465fp9ijoPMs59rT3pVO80Wk42v78 PNpFCRlgSqO5tIIp7RmD/8k2MyeakT4MhX9l2JMYfcPHf5Zjg6BZBUGz08qyc/gD X427Gz8YbP75xyKsSa+Ug3YdIuG4g2J81b/UkL8MOuxrHu4FTxzi3S/OcFmymL+k GhtpqHOrWKCNl2p0fuZEDxX+NWP4V4I9nYw50B0EXao0pUpPM2nO42+5EG/f+tFg 65MfeiH1dOZuO+/y5K5JMnHZ3xzIj4E+rXIuJm32ooMIpR917pzEv0ivWo8Yts/A GKNLoTL9AnjtawF/atjToCkZixifwyux6SmGoOE8dXkOH3zykxEmYqhmoA4S6uYs esMmI1P7XfY3+TZROWN8PApXxPQJfM7j3v3jVqvQqyz2yU4iNVpzrpgJVKlf01nS 9tWAw9N3mFyBVfZTNywZzXVr2sCSB/wkk/asZfr8cOPjf4h273zXKzW4U3RQ25Nt 8+nY/I1U8+NVPu3Gi352sg/ZiexFdiP7kR3JnmRXsi/ZmexNdif7Ewc+6Sc+XNhF FyiNQa+vr4cBtpniAVuwKjmhmHjFGHY+2vr8R1H33kX8wkyWsFnlV7PhRZEp2iUp e9z23+KtcOuQ2cM1N4NsOBbtRXYj+5EdyZ5kV7Iv2ZnsTXYn+xMH4vE0wJ9iwiF6 jHevyjXG/JIvS6JXbfDArKB/PmVVei7q3fv+sL3+pms/7wHtu+YGGycqf8ugp4Ej KIu8uMk6Xw4YkCF7Mi+Iw9oJBb6f0OBKKa5qPQdqbcAU8qBXqkNV9riJ1WhLEUbl cqLqJhRN/JYntVZn037rjeHmX/9OBnU3meBh0DNFP1bhZJ98MGWscJqUgfYku5J9 yc5kb7I72Z84EA/i4vgcRoKWxemsv5tGr2hQY2SSZeoCBWYuqHR4sXfnw7exeeV5 RTJGXZ97QPMZ6McCn2Tq2WPI4zt1qVuIdm+f8GvH25KmMxuWjLROQJWS8qisXl1r 6fWf/8o+ycAJPIn7dnH67HqomrpipVoIrTyOzcDT1ppX+vf++A/gl/3xkKQbqfJm oL8S8ELhnrMj2ZPsSvYlO5O9ye5kf+JAPIiLi99PkJjDl3eFvuviNE08iLd5nSYd aGtOMW7O9DfX/t5q3ShGrGjMmVPzCooYPQP9lRRO3an5HDkHHO1LdiZ7k93J/sSB eBAX4kOcvsydw5c2sy79wk3UpxkmFoaLHOwJTB5ORbv3vhv1HlzI+rirk3Y0iFnW fRhZOjXN3ATIIobXGNmb7E72dxyQB3EhPsTpy5pj8rHZ9/WrcOf4R35DiArw+jwT 5phJ9Ulm01eGDz7+Oy+s8WwMulTMzsi6Pmegv3aW7kwH1tlV2JKb/uTplJPd/Urz vlFej3uiAwaGSrSi1vaGYhsXjZs39TTKLlRN2R7NAlWiXhPcLiJ+bGrBSn/j+n/C q84fTzZwii56xmau+zAUnrlzkU2gdB0v5TxUBj7ZnzgQD+JCfIhTlp0/Wt3waFVf BFqGw1inYrmY1zZd5taeSLutb6lR+1QxR9vF6em+bs5noA8B+HgVixsW9bP47ebE VxnZnzgQD+JCfIiT4/WYZA0ep2oK/obP1Vg6aoLlxw2zK/3WX97CD+QOdD5HLJv0 B19pNufs9ljkuYBE3gYfA+fEgXgQF+JDnIjX49QNB6ma2tTuKjEbVa7svPFYk+FJ Rxsffx9DQq2Ytw155p3NLJm572fnziGb6TJO2CoUmmsZDxQh8iFOxIu4uT6RA9QN B6m61WSyWl8IrPBrAsSCMeKYselKtHvn21nmXc7c9/Tskpn7fvbu3AHPlyMhB+JB XIgPcSJexI34HaRuOKgDZVB5RcJOpww0fGmTJj5xbNS6+QaXvlfM/iyW38zc93N0 55DPWHXuvMyIB3EhPsSJeBE34ndQRwvsV/VNF6tVQGuwhDYNawFhq+Woe/9CFqdL xXzoWfb9QrLz6T70CiMuxIc4ES/iRvxuHhC7Yb+qO8Fp6ZV5mKRqDrO8RW55c9i6 eQk/KBD5asjxBATGZ6p+nupmOXA3Dh66+E1cHB/kRLyIG/EjjvvVPYFNsfpSE+qx 9lkUVnxr60boJQ1mKe7cfW2yQmN6HfRM1S9E3fnig8KdEx/iRLyIG/EjjsSzqC41 hu2kTqWmrrdkLxoFVPGAca+BZ12It299G18RFqs0HOhiVIbNkrLnq+1itks+6SFf W058HCfkRdyIH3EknsS1cOUwbm611mCO3fGFGrhUzwBrGK0Xk+7m2WJhXdF5Ml7/ POP83AW+Z7lR3tlCfIgT8SJuxI84Ek/iWrhy1wNLC/FoAmHcgxrz/GWhzKsG4JKO hj9s3/q3n/mVJvfKC0xSdx1l4pCre+bCn/PN5rUCjOsrp0IAKu6zdLjDkkHLNl75 8f8QYfn3YMx1LeFTliabQc30PjxxP0HGZky9czuWJZv4GkQ5tbzOjG6M2rdeEyLg k8mCMl8TzWagX2jsZuOm2HjSInIiXsSN+BFH4klciwslc+Po16Oqkn0ohyxOa8BR 4VbU40HrFOQT+vn0zNCnm5Q6ux068ul1ZHlFCOREvIib44cciSdxzfrLXczO+sEX wiUpYigFQlY42LoatY8zldTGNUwKVY/VPFP1iwvchcph0u5GTsSLuBE/4kg8iavr L0fONJGQUSXBiIeeDUWgtKlqY+fifuu0m3VSdKCMJ7TPErMjlaiNe9Z8N7uFuBE/ 4kg8iSvxJc6uyRUfr0JoIx9Mgo1pUwVu6QpZnqzHkm7h3Xiq0ex2NDpZ3IJBsafA j+OG/BxH5ElciS9xlpSax+yi1OB7EdUAZbpqta2qdDBPk9UnsXrWpj6SyPd0tPgs HbXnuWFVLniVirmFiedVNvryFHIGtvpTNggjOVRxyI0qG2Wr8XB7GZM3n0+rms2y 8COZlbs5a2I8SELciB9xJJ7ElfgSZ+jduwFpia4D62kLZQO8ovpbJ/aUopoNYR5t ZY+HQLOubOJHHIkncSW+xNkVaq9KKYUOAhA6FNyW0rjfyEpeiPEslFm8PsJxezyb JVssSPyIo+OJXIkvcXbJWdxLZZokgbGixAyUrIorRYW/yXj1rMl1VJtge8a78SB+ xJF4ElfiS5wh2virTLWWwqYBaBswwQOjk3K2okPsG92a3Y5sM6yoxozciB9xJJ7E lfgSZ7ncqIAZeF4SMtS/CW0yqjFmJOdiMrfsoCKvs9vRAG2LhI2PS5YQP50MahyC kIXCC43nlZFztksObZ6iEbaQnhq0G1lhdjFbq/USZeYTV54V5yGOxJO4El/iDEbV uUlSkXDrgdG+SnpzbKrY3Cwxe3kStXHxXuRHHIkncSW+xBl0rUvF1qQwwtMGn1Aq zKoXFf3gfAb8ZcjIpyc2ID/iSDyJK/ElzkAbnFktwYIWAoAKc3mM71X27PYyUJ9S Nh3IkXgSV+JLnN1Odjb0uUXWxm2LpL1xMdhZpH75GmI5O+JIPIkr8SXObpzTKgGY obm9Vaw1cnrLhdnt5VJ3wY04ur1ykCvxpadBJYHbttBaiepOydnLSUX+mbZfOm0X LSfkSDyJK/ElzvumnGBzy5jZNJRvws1xFHv+tA+sprTdzCz1Dbg5jnrvn6QfGxBl w7myHFtfDISabIbCGGN2ZriX4man7iwNeyriSVyJr+PsPLzU2CwTtCGddXtTuh2B 8t1uZreXiPeEG3EknsSV+Dpl00bhPEpQ1drtNAtcpNZtYjbT9Uuo62w3KtpKGDkS T+JKfIkz0I7wdBFwg39FbaP8U1eDJd+/qqBuZ9iPKGQ7pmxzbu5AjsSTuBJf4gyi N4ftb1AaME8HnmIQj6zV4+0Ji+0KZ7ej7r6zw60WQX7EkXgSV+JLnAFkx4Lvad/y FNEnMqx2MG3fo+yZql8CdU8rG/kRR+JJXImv4+yVRsbTAuM4S5lWqSw32m5zUbet sMlPNIveRzpa2wJ4sW2kYsSReBJX4kucYbM9MJFNUxFR9xlEwgv6nENq843DWeHO 7Yz3kczKCiE60JkLJ37E0fFErsSXOEN4/NvKE0Jp7sUYy2NuWMSFP6Ltg9kY+Izy UY/ZGSfttn0mfsSReBJX4kucIdjom6DmKe37MXA+shxhS2+QuXI1ceXTu8/Obkep sTXlwjNmjh9yJJ7ElfgSZwgbbdNXCtUdx9b6Q8Ng6JVqO8ZtCK6dW2CzRO1IJ2Ys z8CJF3Fz/JAj8SSuxJc4Q+3E68ZDp237mLXZNOLaDGXl+D3aE9rtDV3sDG9nQftI 4s6z8Om9vIkfcSSexJX4Emdg137LKlGolAwiC3oIkveDSmOTcZZkwBXNesi74dgs Mz9CGXiGwTg+zoUjL+JG/Igj8SSuxJc4w7XmRdM6XlW+n6TWyKGxto/XykB61bbR CcuA65myj7KyiY8LuwkjbsTPcUSexJX4Emdgl9YMBe+Ih4nhcsQM9I3lPVmqbxqV uBgwVvcsbh+9eJ2r2uVYyMtxQ36OI/IkrsSXOLtF2hS8QxulQsmR1NAXwLvB3PHb RkV4xeTAp/vKZ7yPQPvajpk4PsQJeRE34uc4Ik/iSnyzxfjsPfNhu6F2oi2VilEc C4XNLt2RQX1TiFLXqDhP1NRUf/ksbh+JJte4uUWqjhnxIm7EjzgST+JKfIlzNlMF JR72paqaIV4aXg/baB3GdcevLd7RaeTcgwv+RWbOZpNZXizu3MsWsVrR/m4RI17E zfFDjsSTuBJfel9RzIzVTwcq9mqx6Omhx70OA9EOF87dwCvG0lUzjt12lpUfiSw8 V3UWq2M6LPEibsSPOBJP4pq9lzOwdIlcfs/Ubtw3FZS8DswowQBvuN3hMnggg+qW SUfZCfcPkMxuLygxy9rVxMNxQT7EiXgRN+JHHIkncSW+xBkK6pSad9mpRMvKELXe BSPbYGEnqC1/rh3sLFkrOllmidoLTsycC8+SMuJDnIgXcSN+xJF4EtfCe2eLBOjd 6Nebl5qqFpZin7EBs+kuF2bbnz9zg3M2Mi52x1m7O0/U7Gwo7DlremqCQuG+kQvx cZyQF3EjfsSReBJXmwGbLkH9nmleb5lOIBIWRoMUwl2u2bYA1grmT32ik6E78XRH y0TdM+DPJ1bv7UAhHsSF+BAn4kXciB9xJJ7EtTjL1Lxxzq7iVVCPb6t0aCMJSZ8b s2M5tMqL59YwQMQOeKFu14U662R5rrGaTcFGDsSDuBAf4kS8iBvxI45XXRY+WdEz hl0kauexTdYPZAwU5AW0gZsWvmwzqC9/lql7lKl7nKzN1P1cVe0y8MRxcKpGLsSH ODleyI34EcciMTtA2RN1L/pJYlR9aCXfBWa2MChsVpZe/xMmBEnhzu1UU2zW7n72 7erxeLVOx+6beBAX4kOciBdxI377Vf0Q7L3q3snUbeSOUzewjXD+zF913Mfsb5hn 55PYPRsoeUbO29q9sdpl30NGHIgHcXGqJk5O1TsHqvoAZR+sbs3DTcblRql54Y8c RCcDXrjzdDJ1aebOn5H7zovJ68TZnexPHIgHcSE+X6ZquonLly/v+QPtrn7l7VV2 //xNVi51oSIVS5QvAYwH2pREUIFR+85ZEJJDXndrumLxrBLis+hAyeN0MmAq7rF0 1LG1lUvvS1n62Eq4qa24G/hRqwvx4C/duZj98hfa2ssPxdZHLM/lrr+crhKd+KOS 1btgk5YFds+rLt7wK43bOuqxLDuPxjNa2GxGyyG778kMFOe+0d5kd7I/cSAexIX4 ECfixR6h6gOVvV/dtaUtVuknPEG/AQLlzCCQ5UYa7dx6Fb+OHO+ZPd6mcVZO63Cz 7zTPvFHVUZfZNIprp3/wGxDep2jqdWP1/UAPd3qLo8H1rWbyKFU/RtkTdZ9afCOR ujkw1ttlyj4AYHeZCG5Vli9+oOOeHcdvlTfHaDprMYVppvCvBDob1cqbWWoSp8ne ZHeyv+OAPIgL8SFOj1P1I5U9re711V/ZequF8fm8BTOgfdsFZ0IKr4IXXlRPh+3F rCKumFS2zzeNmSn8q4Gm5Ts0/9t1nKSZ61ajXer//qTUOPsB2vczfM0X3JgNzpfa sfko+t2xW0mWgV9+ZDv4sSU1LH0ynuA6u5hES94o4HHH8LQFxt5jYG+Xj33n30H4 2yru4lU3yNvfST6NabZ06OlB28xurj2dd4fGlJR1qXD8Ntmb7E72Jw7Eg7gQnwz0 4zs8nqB+Su7OPyo5d86V3Ym42sD08DY+9UX11Pf+N36pxAFP+m4Qvehhm60Ve0rQ U5m3dh0nfQea7Et2JnuT3cn+xMG5b+TyZe77iWFnHS2XzbXVVZU02hH4pV4tgC0j 2D3M2G5xWf60evK7/wddjVYuQ+/nAyYpy5YQmVkMfxLXbXPXPe4hQ9BkT7Qr2Zfs TPYmu5P9iQPxIC7EZ38HylPF7IfjN3PZ+ZKSJqlaK3oYmz2OeYQF6ZcV7TwTde6e 5NmmFeNqe5zxWQz/UtA2B531edMufJR5p1HHVJa//UFQO/4HZvhNALjFIthMamKH 9cPBn6JSyn55ST8uTj+lG59y51ffURcZS0aJGo28flupeJN59gtMHNdL86f/o7R0 4Q+YSFgVddwXHg+a0Pw1Nw15pvCDQaf7QHcoIbNkT7Ir2ZfsTPYmu5P9iQPxeBrh PJGyx+q+wvnau5fYm/NvmnZ/YKoBCjvV1hOB4SZFT9OIrFJh0n+wXGxnMN5/alzx /m9d4fuy7nGMHmXJWAaahfXTfy43z/+7MOqmkN7nxsb3gzLfGoqge/bs2ehfj/1e s2tv2ydx308Ne+LO38bm2Dl7YVhmQWfeKK9jUiUsMGm5YFZWFvsI3I97D47x7OYc CN9TIjOvi/o3VUXRFjlQPnCULa+108kYue4hKnr+9Efl5df+DTjDJpa4lRp1V8pR qzxY7AbVQfx+7c/pk8bprwx7T+/az/7FLCtpxZawrBIoZbQGAxnwcHEghMQYfn+F M5vXvM1VXRTAzaH/baj84OoIxWRBnfScotNR11Sbr31YWjj3AQgErfi6Yvq29OQD b9f2dDMaZTvmPr49fWiwM+BsDPwEqxnhKWsiKs3DlWC+1iy1slwfSr+URrt3TuCP g+mK9wX8yTXwTa2VaqdYF25bjyf1F0OV5LbxXtVWLr7vz5/4D3ztTcGCz5VN74BN t/yq6rIaG05Af7UJBF8J9kPAezUj2/gFSOE6Nb70U2sRfFCORDg3jHfvnMIfKMab WhQbzNC9ZWNlf3OgT0PeWwJjPCM0GWSgo11Sd1I98b3f+tXmnzgTn3pCrqc6uUeK 9nuHA/prwd4L/C1U+IdGbCl06ZFCqaeW08RmQOCVKJxb3ok7G8fwB5b2F2eZ8vBT f3tZoe+HPFkoP5kNmvdzY3wmRWPyulN/5Yf/U5Tmr2PE+4xJc4sJe1dAf4tcN1sh 0P+MoFe/FuivDXsCnI1deqm/pE1ppHUCiRBUZU8heD8J509v6nRQSvutBTQAn9Rp 2XvPp7aVenmg74PM7J5Rq2KGiaEhyriXgY461q8d+6R28ge/4cL7RIDBdrS8hR7g nhfoHUrGJjH664M+FNj7Xfqraxf1Rr2L4cq+CzcAAAglSURBVLuSygRSBXEKVsSc W+WXj+2IMIyi3bvHrUpk0c58qCiu3b/D1FGF/ijIk/5tq4rJgVnXp4vP6Siurnzn /dL8+Q842Jvcwk3N9W1QpfuJH2xjA6y3dO/k6P03KOt+71BAHxrsaeDrP/+VffOP HdM5c06z3b4qa5aMhE48BG4BYu5Xe2H95IN0tFtLBztzaBHu6rbs6XDZB33ave/h zV8o4OzOjisMjiGTmvMJ/OjN3OySrFnVwZbK3J250z/8DYTz12n0Cgxfj7m6U4nF ZqxZWzfn+2durMXXVm+pwwR9qLAnwLEd/vNV+0+f1/UWSG1LRoFKEtpWDFvbsaTS W543CuaWN2Uw10t7Dxbxqg+ymS56PEOjqO1VGJKP6T8K/LOCbw/gbKe+H8VkNW4z 26nJ+zqHTEkYvrxbPX7pfeooAel9ipa5ybj9wgAmYtq0bOh3mAkH3+sn8b/+qKWz dvTlQ522e6iwpzte1q7/2rSurtlTtZ4qjxrYJOsl2gCqm0dMiBE2QyIZVrtB/fRd axOedFsLRseiqPIwXaVpTw1Vx/vhqU/8WewquAcumyrxnGXXLC9F5WbZqmQydSjO XTa2nTFOp+HCyevVE9+/5pUqH+MbbnIQ69aaOzQeXbLJdsksYsbdG1Jf99qv31Hs 7afrGXthsMfAKdNa+7Up4viDcxtKjGSiuUhAsiFgmmIsGwEXQz9c2AoWTt41SSzS 4dYcGk04pbhh0qmVo3a64uLkIuAHJHoPXQRPxNbu6wjJ4TI7ufimitW4/my3MgOv Xeeu+0Xyhf8eJn5l+ZPa6Td/G5SP/T8OcNMwvY6J2BdM8LvKsC3OTbvfTPoLn5+L XHz+5S80u8LZswDtbGGfcfVCRA7s8hV45/pFWGPMn8PjgWhV5kS9NuLJvODhorDR sjHiGL78GLrE5dHWJ2/EnfsXGIMQ/BIDGeZH4LYMps1Fsx1l883m3KZzRVfs9Agb f3gw53FuOlfvZAzeTObE55Wa7Rj29NroKM+2R/SeKKivfFZaeu0jzuUm/uEBgH5A 0321jbZL1t/t6k7vmG4OuowlNKDhpv4ecnx+bso+KI6vocpb7/53TSrv6Q0lK0Ei eC9mQ2+EV/pAguhbWj3KWN8vNzdKC+fWUfmpjjuhGnVCjIXc5iNopqjRptV4rpZT 3tj9F2CmvIGdxNiHjymQ7jxqSr05UJ0lXMb1eg2ziRrUjHLuumvxwmsHc6fX6ie/ /7/88tKf8UL7HC/EdQlwC7/GHRaZTen3ty0POqo9Gix0zkW/+9HvkzVSsxvQuPzM l9U8c2UfpHKGKn+r0Zbbie9XYxVg/K6yIKxwZee1Ng184aIQdgkVu4CGWrRxf3nY vvV6Otw+icCrIAKncl4ovZi/7o5ppefj6ntGXfgBQbkYpDCT6dB53daiRGRR5cBm VQ4cfC78vldevFtuvHKDB9VN/OhtfN+O1nwLT7ItBLRp8j6LowED6NMaLJru62qc PCc1T9/kc2204A/jnDyJNR9evmLQtaubjXaC0ONqPN/nstPDxtlu4qtt0P4m46aB rBrcKy/Uli9+ZgWvp/2tk3H3wRmMi8fMoFVHiwsQPt55mVsv3PvYxcNkX1F+AOy8 uWendk/IXLUeL14s4jM+0OBVOrK8+CCYO/aFV126y7Xt4MWxi6fdweujzazXVjzp +Knscp/3bFof9ks7DvJ32hV19ewtw/7bPxt2lWLze891kdxzVfZelRMB/GxU+uo1 Jnuvr0ChdK/MQxaFlVgnNSb8qocWSy2vc7B1rlkdhKhpa2rATS3ubp5MetsrOu03 jErLCCXEU8MY9hg6nxp84XlsniRi44I0Y3duDF5EETaThsKrtv3a4n1sLt41FnqC Q89o3bOCdazhHY/bTkp1aKgNKfyeW98+tFGhZCp1cW2VqWyt9LNLwI4s7IOgUxKH Sped4LSsx9rvRaNAqEFZxFDSNVFmcVoLhKwoZWuW2xoiraLVKgIPY02ZAV4kxpbS YbuB8XTexEO8KNIA6UlUqce0ERiTJZUXwY81bqcjARq9QYoeQAnuxRCUeyKo7XpU nB04ptk2witniJF8gF90YIztcyoKKDHh0GpAVYmoWA3VMKHSFlTxgBbC0/poWmBX JF8vEvKRgf0o6K1LTWhdb8kOu+PPy5qH7VG/D+WQwBtPlwRnIb6pwg2UDT7mwEuY yZcwA8a/28AY7gNYD9XqW8ulBURni+Uqlny6S7vxojHcUHjBNh6IBN+X4vswE+Qx ni/C842ssSOwLLJghviOgcbHkIoRAabyUyPuJ7uql9bZqYRKW1DFg6ME+cjBPgg6 Y++xd65fzdR+O5ZRVcmFcElGPPRCG/ke6imugG+1CKSJA6WlJ3wIVJoGEoM4bRQu rZKGS0kbhNO+lEypybw7Kd3mdbQbDlilFJeK9tRQGKSl52EUMbEUKlUQxFzoOBiY JEU/QyUiqXIgFZSjOmNUfipT8TsI9Qo7apCPLOwnAR+1GxAfr0Jzoy8HYSTTEhfh VuynnpaK1UVJKpkKLWlHeNoo3O0PTttGK+E2mS3O73YqlDrf10y5XZBo8xTaU2Ok 8CSso71UqGgpSKiMM1X3paKvVAuUSkS+DIBfWDb+9Nl7Zrgsg3+PXWVoWMzi2Yn7 jJpvp1prkGBip9v3oTdaADVXg5UBQFLB/41K6LKbXFe6bqPwetTKIS9MPkDt4MEY bXBG+1657ZAwuYbKwDTaDXO/4hvZ7Zmgfcd4jRUT3L5pPmUXTVEx8EOXVbvehDyz PtqzZv8/fdFJcNYPglIAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="30" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="77" font-size="11" y="87" clip-path="url(#clipPath30)" stroke="none" xml:space="preserve">TopoDS_Shape</text>
+<image x="358" y="459" clip-path="url(#clipPath31)" width="30" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHsAAAB7CAYAAABUx/9/AAAgAElEQVR42u29C5Bc 13mY+d9zn/3unpmeNwbAACBeBCmRMimJlAhK1sOyFTmbULErVWt51xU7rtRubbac zabKS2Cd3XJtbalS67WddTaRXZtKHMOVRApNSbYoQeJLfFMEMHgPBhhgXj0z/e77 Ovfc/f9z+/Y0hoOZHvAFiWjooqFhT3ef/zv/85z7HyUMQ7jTH4qiMID29zx2nNHT E2cOsVJpitXvGWFOucDcxgLjQxk20kwxr5Bgvl1mfkJR844pX8/TAeNuk61/b81M Ca2hCvp3xXKFboeBnigIo2yL+VRTaIt1YaaHhVUoi8yFeVEsHhInDk+J6Ls8Kdrf EFCO4o6X450K+22AEe7RLrjNVFPrX/E0P59gKcXSHb2mJdS0xkNQNQGGb9sa0xWV M6GFlqGYXGXCDZnQvQ5w5huCmYpwtUAojhdqgnHhE+wE5ww8TYHADhrc8rO8GTq+ XrHFSr/BU80Uj+GfRPhA8H8KwGt3LORjxxDwiQjw3AirNhY0t3hI821HyyZAV9Oq AWCYphdYPOXphpI0w4CbuqKYAoRhphM6A6ZrEOoKF6pQQTXTwMIgoXQ+ywxCji9O cjUI9VSgguILU/hB4Pt6yDwhQtdQky5nnms2A1/0G042rbopAV7TTvj4ffjexgLP zY3wzNHjbfDHhKLcmdC1OxHyEwh5em5EiwG7dVMv7G4ZwYpIJBTN8tQgkfHMZKh6 ySCpJXQVEoyFSYSbEIpu6qqwFEWYqhLqoDJNEaqmqIqKH8AEWTMhmMKYYKARDREG +IeFHALBgzD0Nc1wRcAcPfRdoYEthNryk6qth9y2PKPlqEErEWh2wIRT2F207XLS M4oFPwY/+cQJfuIOhP6Bm/E1yMfZ0ZOgkZle8QwjG6iG6ddNxpIWSirlp6ykqShp RQnSaqhlVFWgnmppTYg0U9GSKyKJzwnUTqvVWO1zG6t5t9XI8NA3Qx7oAQ/wpVwL Ao7PAWMMlV3VOGMaVzWVK5rqa4rumsl03Uz3VZLpvtUAQkcEwg5D1sLnJr64AYI3 goA1AoXXw1BtuGHY0JtOCwfRFKLluHrGramB1294njTzR4FHJv6Dh/6BwV4PuYQa nIXrRl3bozOtmkx7RspNhiktDLOgKTldgayqsxwqS07TWRZVNcNAZGvLs2P1ytKI 3aznXc9O+p5ngsLw7TV8UvGDGH0WyI+TqqZ0fQv8fBw/MZByoGeBiFHJ8R+hbhiu aSRaiVSmkskPzmcHdtwQwGo8DOrcFzX8jSoa96ofQg14WOWKUjNbSrNheE3Bc60M v+zXYNwrlqb4nQD9fYfdDZki6il0vAS5UiiaBdCTfsPOQELJqoGR0ywlD6pe0MKg T2V6XtOCgl1dHK+vzO9o1ivFZqOeBbTOiqYDYzr+U5eAFaa1IbOu5wi00sU6Gvoa cAk7fhY8Ah/4IIQPIffx54FIpTO1VCZfyvSPzCZyQ9c5V8uB8CtcUVch8MvcCSuB 6lXBDmt6OlEvg9/Kl0suQT8E4J3oBHPvP/T3FTYKmsWQpwtlLYPmejnXZ2ZtO+2H CJmbOdUI+1Wm9qGR7Td0MYCQ+wK3PLqyML2vUlocdX0vwTQLLbiBcA1g6s2QFQW1 mUWAsykL+vNJSFk6pBI6JBMGJE0dTFMD1+XQcn1o2R40bR+ajg8rlRbUmk4EXBD4 4GboeIWBh5acLgdM3bDzxaG5/uHJi6pZmEPoq57PlgMWrAQiWA08ZQU0t6oriXot kWgMVFfdOpr3yXKBx9BR/OJnCvaaNgM7Cie16yunjGQlb+F/SplBkEPpS8hGqBTR Ag+ahlbEOGmoPHfxYGVlfqLVbOWYToDpMhGw0QaMcFUN0kkL7t0zCHvH+2FiJAu7 RguwcyQHhYzVNuFr1/pHKLV67SrXHbg6X4WZuTJcm6/BpesrcPryEjRaOAkCHsGX 4Am4K6EL34FkKlnN949cK4zuO6so+qLr8RJ6giVPCUsSuutWXVWt4kc2W/mKM95/ xDsJR9G0w/um5e857G5tJpNtOWWL7eAJq5rLeKrbpxpWv66ZgwD+sKHrgxgUjy5d O31kZXF2VwCarhLkDugIsmVacGTfMHzs4Ag8eGgU7p0sgo5JFmORf46f2xPtpueN HrEMup+FEJ1n3+dweroEr03Nwatn5+HUxQVwXCeC3tZyAh7gpQL3+4d2zAxO3HtK KNqc5/tLAPqCz92lwHNWjMBcdXLVupjVbMcqON2m/b3W8vcM9k0BGDymzczMWGk0 2anSalak9LzhoxZrypCiw3BStYaEsHcsXjv9kXJpbiJUdI0ZSXTXiQ5kFTWawP7C J/fCZ39uF5pkE1RVlWBjuOs1eDPAvYDvvgg6XUEQoOl34ZlXZuDbL1ySEyCQGh5B D3wbhNdCwfq8UBy9NjRx75uMJWZbgbMY+rAQ8nDR08MSa/qVZrGv1kDTvmvXLuck /PA9D+DUY8eOvTegSWhTJ7QHOUZP1zA/zqvppM37AlUdMpRwB+LcZVjapKWre5Zn Tz965fyrjzi2269aOaYlsqBbWVCNNOyeGIK//6WPwu/+xqfhV75wBA7tGYJEwkJN 1uWlaZFGbwY+vjabFLd6bfye9P7xZZoGHNhVhC89sg9+6VP7oJBLw3LNh5qNAiXr gxeaI9aqVwqlGxfuYeDl8/3DAaaGFqLE4Yc6Z7qS9APFSmC+MWPDENfC+clpgDN/ IY7jByOX8I7XbAlaFkYis61aTjKdMDJ+yPvIJ4OujuqKMmYY2qhTmTs4e/mtBzxP pFQzhXAjbVZQiw9NDsOvffl+ePzB3dJEbwRzvfbejib3qukbaX23tpOp/8FrV+DP /stPYGp6AaN3V2p5gFoeuE0wDNbcsee+16386FnP43N+GN4AP5gjn64r2mrD9uqB Y7XWzPox8W5r+Luq2ZF/VmTePDWYTGjpMGWFQUHxUZtZsENX1d0IeVJT/ANz51/6 zNy1S/eCmjT0ZB400mQzDQ8c2gX/7Nc/Df/drz4M9+wsopAMqb10xcBvpanvkTva 0BLEEy++NE2FybE++Mpj+zFYHIbFigdLVU9mC+SGOA+MlfkrO/3mykh+YNhXVV1T hNCZCFTu4Xurfuilw/Cq6iofebMqZr52NDz++FFkDuEdBzsOxB6cGzHmM/1mMdnK WC29HyENaxab0Ax1j2WZk075xoOXTz131PFEXksQ5BxeaZgYG4Ljv/k4/KO/9xDs xqg6hryVX/4AikEbuoBuU79jOAe/9Og+OLh7EM5erULDEZg5RCmi3WpkVm9c2JNJ pdVkrk8IBgbGLgoLFcXwBEb1TTGXKoo9rSTMf/kp8W4Cf1dgR6ABQV8wjHLB0hNO lge5fktTxnTd2olzeI+JsBevvPnY7My5+5iR0SLQWUikM/Df/PLPwe/91lHYv2uw 44u7teaDBrwV+PWTIJ6gO0fy8LfQp6sYtkxdrSAxTaaL6AHUlaWZceB2IT8wip5e 0Zii40BDxeZJkWRuaFbzQvrxLz+IwOFdAf6OYUvQT1Ag9rwO85B00koWU6giJtHj OOjduqHsUUP74JWfPPu5SqU6qicLSqTNGfjkA5Pw9X/8Bfjcw3tl0LVek9f75zt4 vX3DAI8uA+ONBw+MwM8/tBtmS02YW3Gi+gDTlHplpa9RujbRNzjsKJquiBAtPrlp pgkbfKEu83AUXhMUuB3/6uHwnQJ/R7A7oAtlDWA0aWbquRCSRWQ2joPcbaE2u/XF By6/9fzjfqilpG82s2AlM/Df/+on4Z/82iNQ7MveFFW/m4DjXDm6FJkgbHytve6d fu5G5p2ufCYBn394EtI4qV+/uIzUVDTrKniea63euDiZyeZEIoVxLP6SkPVbTZg5 VwQwKkYTpeDdAH7bsDs+mlIrgKQJLOd4WjGlsR2aqey2GNvbrFz/2JXzr31c0TOa nshJ0GMjg/D1//EL8IVP7sMUxtww8LodgUdgI6ABwqMKRSCi0ncQUNQMwFF0AUXP XVdUGRWybh4QePwj5AxQOhNhu9/nVsEcjfPevYPwsUOj8Oq5EjSlL2f4eaCuLl4Z T6WSSiKZ80IGoONXs30tsFSK9V0E7gTv1IffFuzuYIxAuwC5EEEnVW2HarLJpK7v qSxd+sS1S6cfUM0ck6DRbH/qgb3wf/3OF2HvjuJN2ny7kGPABJfACqTlcRSNj5fD 5XMLn21fgONyWf9u2h7+jH7ugeMF4OFrHC7AxX9zfBOfngWlVZI8RPMlhr898LeC Ptyfhi9+YhKuzNXh+nIrqueHCisvXh0zTdXIZgdbAXl4wYTNOfdUP0DTKUbrGfFO gG8bdjdoCsbQA2UNNN2k0QSaArHla6c/fWPm4r0YhCkUiKkYbf+9z98Px3/rcchm khL0em2+HcCklT7Oe4+HYEuQLlSbrqxvr9ZdWKk6sFxzoLTahAW8llZbsFBuyeel qg0rFfzv+FzB11dbPtTwdxu2jxPBlxOFB2QJCHUbNP4RtwF+I9OeMHXpx2tNH6au VSLg+Hdl6fowAz+V6RuuC6q+hEoQcpP7HuOJRiaIgrbbA65t0zzJggmVP93yG5aT VTMmswZUJjDqNnYZCpsszZ56dH72ykE9UQCqhFEV7Lf+7kPw3/7yA5106nYh02oW l2aXI2CqWaNWej6CDqCOgBpND+p4NfDfNq1qITjSXJoMfkDa64PjuNBqNjDFSQOm gmAaGP2rGEhpCgZTKiQTOoLQIG3pkEkZkMYrg/9OWCpY9Fp8jaG1c2smv5j8d6/A 11uy38G4pS+XgH/5ly/L5VeaUCQ/ml/F0SOhZ2Ey7nuCaUw4Rk1Y5SYcHX1MnDx2 nCvKsW2VVrVtgUYn9sRXT7BXUjNWsWimhJvq00MxqqvaTg1BV0oXH5q/Nn0oAp0D PZGGf/prn4b/6rOHJOjb0ebIn0aQuUeQuQRZb/hQR5MstRKhVqptTS6X4eLFy1Cp VKDZaqI5dxGwg9B9NNFeWxUUaZzpbx2/F2YPCN4CE+GnkinI5/Owb98eGCgUoD9n QT5nQg4nQT5jQSaB8NPRhDBksYe1hbh96DTx6f//xt9+EPqyCfj9P/tRZ3OFlKNu udniPmGqWuAHPPAgxXnRFfMzM+KJ5qHWCQRNXHoFvg3NRjF99YRGJdAdhpbwGulC 2hAjqm6Om1q4u1WZ/ejs9NRHZP4sa9tp+L1/+Fn4wif2dTR6O765GzJpsoOgSWvJ TK9WPTS/TSiVbVhFM319fhnOnz8HczeuQ71eb69zdy2DsgzQhiUzqUYbGTrlT9qo EGCSg9qP1iFs2RCWaiCmr8Irr7wCmUwGRsfGYf/+AzA+MoBALCgWEjCQS6E2GpBL mVL7LSOyVr1CX6/l9CCFSCV1+N0/eqYdJYRA8txtWG4yP8bD0PTSvuvzRjrYYTE+ 1QSOPOi1/F312Z2iCebSqA8pESYLmiaGqWCC49zj1EsfvXLulU9QMKbJqDsD/+Rr n4a/9diB2wQN0jf6FGy5AVQaLiyh+ZpdbMDlGxU4d60ML795AX7w7I/h2eefhzNn zkClZkPAEqCn+kFP9knLQvm8it+FKnRUitWo9i6vRHTRqlrnZyn83vS6lPz+9Hr0 ALCysgLnzp6G01NTMDO7gJMNXUegSr/u+e2IHn24Km1wSDuipE/fapjdcoih7x7N Qx41/IVT89HOGny71aWZkUy2zzGtVAt1Ez9ReA5PeKFq8/FMnW+n6LIl7MhPR/Vu YCJhZlhO8fkQlUCpMsYC59ClU88+ruhpnaJuFaPu3/w7D8N//Yv3bxu0XFSglAkh 2xgVN1CLlyotuFFqweXrVTg3W4GXXj8PTz31V3D6zBTUWxzT0TQYEnChU19X9ZuX R6MND3qXprcvqlurWscKMNWMXkuXbsn3oElAVxCq0jWcP3cGps6ew2TIBK6YcjJi HIfQA2AdzQiJt0ziNxvzRsAP7OyXW6lev1CKnI0QrLJ4ZbQ4PFEGTXXxfT3wAs9K aJ5aTvK9U6Vg5mt/Fh5//HHYaqVsS9jHjx9TniiW1KnBklymFEFQNFU2rlPkrbO9 M6ef/XlfqGndysv06onP3ScXMeIcejugyXBztNtNTJdW0f/OLjVgZr4K52dW4JXT 0/Dtb39XarFgSTDSRQlYTjACgoCZHu9iiYFiIKVEplu55dIn/hzY2nYmFhU7WGcy RPBjS0BWgIK+SxfOwqVLV8BHa8IFkymfj6kfI9gY8Kmo4ZGWbx/4/fsGoVxz4ezV crtOwNVW5cbgwNjuJYKNBsT1IPBEBry51LL43I0xPjX1F2Ir7d4UdpxmKaWiaYaZ RJLxPg3CUYxJdlsa27M0c+rT5XJlLF61+sT9k/DPf/szHdC9BmNRwSOU+8LqqM2L 6Iun5ytwATX5jbOz8PR3n4HXX38d/BCj4VQEWZpaFLzS0VoEpGjroLY3GnZ2ld7i ar8m+h1YmwSdCRBtf6KJFGs9Q/C2Y8N5NPEzs2h29TRw1H5O0Tn+rorvQ+Dl94HN zfr6ZVq6Hj48CqcuL8ON5ab8udNqJBS/lczlBldRMQi4wzhzQyfrlkQgSl/9y2Cr dOyWsDvmG9MszWxZerNWoI0HqqnuomVKpzr3wOzMuft1yqXRNw4P9sMf/E+/ALlM qrOQ0Sto0mobAzCKrOdwcJdvVGHqSgn+y9PPwHM/ehZaXoimugtyW4slgC7Ab4d6 W7XBmybBevByyZJFy5bxdql6rQpn3noDFkplSOUGpA+PFkSUKFpnb9/ZulUuTtdD h0fgr1+akYUhimJq5YVCOpNx9VS+xhVwfV/YZtDwrFHD22sdCmaObm7ObwmbzDeg +dbUadP07UyoJgdMVR3TVWWPzoJ7pk89/xmmpzUKhMxEBv7P/+ELcv05Lpj0BJrM NoYcVNWq1j002zXU5iqcujAP//E/fRNuLJRQYQYQcn+UsxNkLYKsKOoGgN+TZY6b wZNnlpUwrbNWTcDJ5JeWFuDSxUuQLgyjz1aBbkEx5XdFQdOEVJVNv+V64BTl70cf /t0fX4lKuEIotdLscHFschFC5qDlaHFdcUS46i05C3z1yu4ANjHnG8KOtZrq3moj kwQnUUioxgh+812WwfbMX3j1aMv1+7R2GfQ3/+7D8Euf2v+2XHpL0OifGwh6BXPk q2i2z86swqtnrsBT3/oWtHxF+mUNc3bpk6VAN4L8vq5v3aTtMXSlA92AVqsF56ZO gZHpw/9mSHMu6/8aarnKpB9XoHeTPtSXlM+vnVuU/p+Kp7xZzuSHdiz6wGzNZ7bb 1B3NNb0oOqfq2sbard0qp6b7rV5JNY0sQMpKqvlQCYcwnx716iv3rKwujuvJAQnh Y4d3wq9/+aNvK4Fu7aOF9M+lig3XFutwEYOR5155C1584XlQzBwYBJnuxKM9XfF+ cAU+AMC3gg5rWh77ZhkU6uDbZfj2U09BZfURhHMfeBiPcIymaFUtg7m5JifJ5sDj XJ3kSvJ95cwcvPLWZbl3neTfX1++x0j3l101rCKfWtMR9opneE+cOcRPwMZFlrdp dqzVSqlkmsXJRNIJ+pgajmlMQ60GjL6ff1wwy6SAzExm4Otovgf7sz0HZBI057IG TaAj/7wM3/nes/Dqa6+BhibbILNNoPU1bb5zQN8aOkXyjC7UdKrPzVw+j3FIC9L5 fmnGTUMFXYvKrFEc0PN6BKZkffDNH11C+dGNC4HSKt/oL47tmQu40goFt1WhtpR8 zinVT2Gw9sNgI+1mG2k15dRZyBpZeyEtdDWv6GrRsGB45fq5+23Xz8Spzq9+8T7Y OzGwPdD4V0umVq7U6HNXV+E/ffNpWbQwMkPSP0cabbU1mn1AJnu7pj3SbPre9P1p HDQeGheNj8ZJ46Vx0/i5iJZdt1oxi8uqJGeSt6whoPyJA/EgLsSHOBEv4iZrIhu4 bfZ2rT7O6CY7uvfKD40M/lafoemDqsJHF65dOkALG5TyDBfz8Btf+cjb1qM3y6Np gI6MutFHL2BqhQL4m2eehauzN9A/I+iO6Tbxm7V9M9zZu1S6ocvvS5pNeTkBx/HQ uGh8NE4aL42bxk9y4O3dqVuZc5IvyZnkTXKPKn5pkDyQC/EhTsSLuBE/mTJ314bf rtmhbF9BXQ1UaCXp3itFF0VdEcOlmbP3C0XX6YOYlpCFk0w62Ym8eymYeDjAKqZX N1bqcGmuAs+9fArOTJ1FgQyiYKJByJxZ+WkDfTNw+v40DhoPjYvGR+Ok8dK4afwk B5KH6KwDbK7lJGeSN8md5E/vTTyIC/EhTvJeOeRG/Ijjeu1m67WabrhLu31mysmk NKYWTIUVNSaGlhev7ZYw9ATcs2sIPvfwnm366SjFWlxtoZ+uw5tnr8GLLz4HeqpP 1rCpRq20Qd+Z/nmbfpwmLEXpOC4aH42TxkvjpvGTHEgeJJftmHOSO8mftat5xIX4 RJzUAnEjfsRxvXaz9VpdNXdoepLTTXdZlYk+1WDF0vXzh4NQNeJ6869/+f6b8ule iibkp0qUYi2gn55ehO999zvAzHxkurs0+qcb9NuBr2l4QY6Xxk3jJzmU2v5bbOG/ u7U7is7vj2ID5EFciA9xIl7EjfgRx/XavQabfPXhIsu5gQGOnVJ1LafqbEBjysDS 3JU9UdXKgsnxfvjsQ5M3FU421Wr8Q9t+aEfG3HIDLs2W4a/+6ilA/9IF2vgZAr0R cKMDnMZN4yc5kDxILiQfAWJL7Y6Bk/yJQ7RYkwTiQ5yIF3EjfsSReMbdpTqwpapT q6kzJc1wbJMZakZVvIKhs77qwvQBzJSsqDRowq99+SM33THZi/m20VzRtqCr8zV4 5ofPQrnWjIolZkrWtoH9rIG+GbgMNmXQlpLjpvGTHEgeJBd7m+ac5E8c4jo98SFO xIu4ET/iSDyJa2zKWSfdKk0x6oAgeDNpMA1Dbq2gKtBfXrq+K5pBFoxgJPj5j0/e 5Ku3jr4FlBsezK2gVl8rwYXz53HAfVEeTaVP9tMajG0zaGtH6TRuGj/JgeRBciH5 kJx6jc5J/sSBeMS3NBMn4kXciB9xJJ7ENTbl6vHjx2URpd8Y0VrcShi6lgczHDVU dZcm+N7Z6VMfUa2cQpsAnvj8ffDJ+3f2tNBBiwE8CKHecuA65pcXrpXh2999BupN LjcY0CxfM98/q6C7gHetrtEj8F2olJdhYmIXZJMGZFO63OMma+g9imO1asOb5xdk gwCnsZIYGpm8IRRW4YpfBRHWG6DZwWjaj0uoEXUKzGZdLRF6hp9SkxooOU2H/PL8 xX1IWYkX/7/06L6efHVHqx1P7vKcX2nCpZkFmJ293l7QSMhIFWTBBD4cD2m8mBw3 jZ/kQPIguZB8SE4kr820e73vJh7RYgwtDpkK8SJuxI84Ek/iCu1ATZpxUvVimmvU hkq3WUYLAfM1LVdZnhuPfLUBh/cOwe7RQqeAsmXtGx1J08UIvNyC2aU6vPDC85iG pGUxgPzXT28u/c5zcOm/UQ4kD5ILyYfkRPIiuW0VmceFFuJBXOLlVuJF3IgfcSSe xDUy5dJnH5ctIpvWgAYaSzBVxShCzXnO6kir1crEPUy++Il9N6Vam2l1VEARUMXZ uoAR57lL12BhYVGukFF+yOIy6IcGdDfw9vIoaTfKg+Qi5YNyInmR3DYrtHTLn3gQ l3hTBfEibsQv4sgSxJX4Emf0108C9QKl/p9cDRKqLjKqyjK1pRsTkXmgZUsdPvfx 3T2uajH5RV1fwErNxkE04ccvPNfZPkRmRy75fNg4d5vz9iYIkgfJheRDciJ5kdzi nbW9lFEjLnq0oxZ5ETfiRxyJp+zrinyJs+wPSuU1PesYDCxLDUKErWSatdVBpa3V e3fSNtpkj8uXQm7gr7dcWK46cPHqPJTL1chsxYsb8GHU6u5grWvRBOVC8iE5kbxI bh4XPZVQiQdxIT4y2EVexI34EUfiSVyJL3GWjWCpbXOzEZiGGqaoBaymqOlGo56P 9nZp8ODB0Z6qZVERJcqt6y3alNCE85hiyMWNOCj7MGv1Ou2W5VQqe6J8SE4kL5Kb zLl7WvqMTDnxifbI6UDciB9xJJ7ElfgS57a/djRNMIMDS2pKmGpVFkdEKDQyDbQY /9DhsZ6j8MiEc6jil6bN/HNzN6IqmWbE9zPB3Ufsv9WoExTKh+RE8iK5kfzENqJy 4hN1djCAuBE/4ih5IlfiS5xZ5K+bujBV09CZhTMkWavMjUinj7OFqjUP7B/qfQcK VcycQG6FXVyuQL3elKs00kq0d1reBR7l3Uq8gRHlQ3IieZHcSH5bVdS6TTnxkVXN 9g5Y4kcciSdxJb7EWXbgd/CVzHVNFooEXimnXi3EG+mpBRT1HOt5AyFtN3KiOyLP nTsXbdSnnaCyn6hyl/NNebcS+W7a745yInmR3Eh+XGxtymMmxIc4xcyIH3GUPJEr 8SXO8qiFhBpo+IFmoEJCZarluXYqvnticrywYcfAjUw4SBMeQqMZ3Qp7fXa2s9AB HRN+l3YXbSmXeKGE5EVyI/mRHGELU96t3cQpvsuF+BFH4klciS9xlsEZr+bQ8oe6 GqIZVxTL9txE3Nl3YjjfkwmPbsKjm959aLR8KGOwsVpeade/tS4TfvdxkzFncWRu SnmR3Eh+JEe+RQrWDZs4QXtrlOSHHIkncSW+xJl5hTIzNa4JBZ+EMH27lg2FUKMu vyrsGsn1vJRJd1zSvU8Nm8P05SvU5Q+iIE9dWwG6+7hZuUFp33IkuyJKuZH8SI7y DtYelz4lpzYz4kcciSdxJb7Emfl2gnkq09CY6KHCDLu5WpCN2dt9uifasLd+MOm0 vYBjgMFhpVJeu+9KuZtubQZcyrodXJHcSH4kx4hzb/d8R5xY+0LtRo7Ek7gSX+LM RF9OceiUnCCU97U4dj0TrS+rsmvf2ECmtz1m7cUP3xeyX0mr0ezaZvRhLqL0Qpt1 tjGR3Eh+JMd4UaSXAgtxIl4yNkJ+EUemE4MXA1gAACAASURBVFfiS5xZwa4xwwk0 zcKMjYEWBIEZ3/WYS1vyXqXNArMuvZbLmi4P5H3LLTvu96V2Uo27wDdOwTqmHOVF ciP5kRxJnqwHraYHcSJeSruxPnEknsSV+BJnxh2TCYNuMAWVhaEmAl+PNTFpGdvq lMBl01bahhTIftzRxgR2xzet+8CRd/adq1JuJD+SI+9Bq29KwSyjYymII/EkrsSX OMuJE2j4Azr7Cj8tDLgW/zIdt9A7KPLZ0T3K1NjGa8OGzib/u49NaLUjaVXKjeRH ciR59uKzY+AxL7qII/EkrsRXEqJjCxNkgjW65QyBB0KL78CgHh89g47iMwi4kPda +55/8y6Uu7w3icjbBRaUF8mN5BfE9XEGPQOPeEW7YYgj8SSuxJc4y3ehYws1/GnI mMIF1+I0KdU247084u2wQRD1QuG+H83Wu5R79t4kL5KbL8142NmG3btmG510jjgS T+JKfN82ZeQtnSLo/Mwyt3egX9SrTAGn2WrPVLjD79O6o/Kvjryk/MjOiu31lr+J F3LUNgiiOw/ZY4mpnU+gFpDbecjtSmiCrFSyfVYWtA/PCu/y3PQR3iQvKT9qUczY tt7lJl7krjeCTSfNcoWHihChxjQefTjIG+V7PVaCte85pg6AOuZ7mmFEh6HdBd0j 7ujEQJIbyY/kyBj0DJw4ES9oH0xHHIkncSW+khGdHW2T9eAhzaWAqSqPtZHaQfZo wOX/ZMKGf1EPEV3T5SFoEE+Wu8xvqdRtWlJeJDdNdlpqa6Lo/LXlI+IVWQniSDyJ K/ElzvL9EC8aeARNd3nTi9q9t6mLb+8HxghZuTH1aFZSa0jaz9w58vDuYxOtXDsS kuQm5adHlbBeQXfzkn3TkSPxJK7EN9JsyxXMo967GO0rCmeq7kddGuiXvc4v92LG NbkJjuEX1WR7rOgQU3FXq3ty2dGhryQ3U552xNrtOFhPoCPYXvvNBG2K8IkncSW+ knM5kRWepXLuBNTVmauq6kYfLKDacOSOifgNt9BrDCRD0Bl1+VEhlUhGsGVhIPbd d6m/3VOHkXzasiK5kfxIjiRP0QNoGVzziFcoIksqOSJP4kp8iTNjq9XQ8sNAUxV5 nGwika3Jyg36D2oreaNU3xJ057gjedMZ9Q7RIJVJyeML1/z2XdCbR+LR4a4kN5If yVHrOitlK+DEiXgRN+IXcRQ+cSW+xJnpCVsYdCI8CB89uGum+it0fnTY9rVXF6o9 +m00HRoDSzcwudegkMvKw0nlYaV3TfnWJhzlRPIiuZH8SI4samjekxmPOIn2hb4f ORJP4kp8iTMzygXhco2cucsU5hiJdE1RWBCbFepP1n0m5a0LpvRH4IykPVEa7N13 DyjyRFqvbcrDu8A3jMTD9pHNnpQXyY3kR3IkebJNSqXdXCSnNjPiRxyJJ3ElvsSZ zaeaQstV6QZ+14fADRjYCdO040iajheOT9HZSrPJ7FimDvm0CX25JBT6++TJs9Kc i7s594Yem+SC8iE5kbxIbiQ/kqPGttbs+JhI4hRH9MSPOBJP4kp8iTPTFuvCDihA a/iMh07oc9cwE80IEIfL11dvgn0r6CyqAGAkqchDyQsZE3aM70QjYkeHjIdt7b4L vEutI19N8iE5kbxIbiQ/kiNs4q/XH/9MnOKzvSU/5Eg8iSvxJc7MTA+LtGp6wjRd oQS2CFnTSuXKMewLV5eh0XJ7SsHoa9FspDM16Byr/fvvkedK01HDIC3FXVN+M+tQ yiU+f5vkRXIj+cngrMeUi/gQpxg28SOOkidyJb7EmVmFsqjaGK25gesLs+WHvJXp H5nDQA5nHAff9+GN8ws9mXKahLRjgg5PyaV1GC7mIJNJR8BvMuXhXQPeNuGRVjtS TiQvkhvJT9M2b3nZrdXEhzgRL+JG/Igj8SSuxJc4s8yFeZFyLB6apqOpYQtCpZnO D81jTs+j4IrDS6dvyGODtwrU4jSBigKFdAL6cwkYGx+DwGvKw8TXTPndR8eEc0/K h+RE8iK5mbq2acrVzYG4EJ+wHQwTN+JHHIkncSW+xJmdLB4S5Lwdx/Ndm9uBHzQC ETZSqVxFaiPOltfOznVgb1lJw8ugPBtnZyGbgAMH9uNgGjh7W9LEyEXau4ot5RBK rW5J+ZCcSF4kN5JfL8sfMWziE6VumKcjN+JHHIkncSW+xJnB4SdEqpniKcXyQBMt UJU6F2E9nR9YFNyVud/l2WVYLjd7NOVMnnuVSZowkLNg78QIDAz0A3cb0jfJGdg+ B+/Da8KjqJnkQXIh+Ug5obxIbvG5Yb2YcOJCfIgT8SJuxI84Ek/iSnyJM/XJArLn zdDxdaGhZrN6KMJaun/sWhi40jSQL/ibl67IWbQ1cNE25Qz6caaOFNPw0Mc/iUlA PTLnH3btbms1yYHkQXIh+ZCcSF4kN7ZFyhWDJh7EhfhIl4u8JDfkRxyJJ3ElvsQZ 3/VJMVku8JSzzAPbdkUQNN1QqZrpwnwikarF2v2dFy/dZMo39dvSlDPIYRoxPJCG Q/t2wsjwEHCnHqViol1V+9ARD+W4afwkB5IHyYXkQ3IieZHcGEBPKRfxIC6xVhMv 4kb8iCPxJK7ElzjLdzyBf0oNjQtBp1WJeugH1cALqn3FketR6uTB2elFmMZcLtbu LQssGvptU4NiLglj/Sn45COPQOjVpX8KuRvVgj9UNfM4qArk+KUcUB4kF5IPyYnk RXLbqpASazXxIC7EhzgRL+JG/Igj8SSuxLcdT2HyfviwyO0wuatnXF0ELaECvhjK hdG9F9A0hJF2+/D0cxd7jsplNc3SMG/UYXQwBXsmhmDnzl3g21UI4mDtw1Qzl/M6 rpa1pBxIHiQXkg/JieSlbSMKJx4ydSPlQU7Ei7gRP+JIPIkr8ZUt8OU5jseeFFEK tkxNsG3w/HoYKKuqai1lsoUVMjnkD779wiVwXa/n8ml0mqwB/ZkEjA9mcBZ/HBRu t835hylY6wrKcNw0fpIDyYPkQvIhObFtlEeJA/EgLsSHOBEv4kb8iCPxJK7Elzi3 p5ACFJrXYNxjWqrFGdQgEGXui3Lf0Ph0gG9GtdvFlQp854XL7V5dmwPvaDf6oP48 mvLBNOwZH4CDBw+C3ypjFFpvz8ifdXPe1kZyfzheGjeNn+RA8iC5kHxITlttVohB k/yJA/EgLsSHOBEvyQ35EUfiSVzj3b2s/SYCDk+J4uEi96yEy1vQDIRfCRRYzg7t voARoh35bhf+9Kk35Ym1MezNgUcVNdpiM4iR5s6RLHzm6CMwUMjggNH/Y9pBMxPE zyrwtnzkqpYrx0vjpvGTHEgegzIC37piFstadqNC+RMH6V6RC/EhTsSLuBE/4kg8 iWt8Cm9XC+onRfFMSVRN1QPLaXLPqXkuX+UCSoOjk5fIz9AbX51bhe+9NC1nV69L nzRrsxhpjg6g7x7Pw5e+9CUw1CDScJmOeV3+O/yZAR37aRofjZPGS+Om8ZMcSB4k F8tgPS9lktxJ/sRBSK1uAfEhTpIXciN+xJF4EtfughfEpvwEzoKcO8v9VuigTtZE KFbwe5YGRvef0RThkbmgQsA3vvUm+D7vqaoWabcGSQw+ioU07BzOwYHJQfj8538B o9Ea8BaaIq+1tjL2MwE8bG9KCNr5dEuOk8ZL46bxkxxIHiSXqMtzb9Uykvu/+dYb kgPxIC59yIc4ES/iRvyII/HsvkGjc9QTHQtEZzk+OjkNM4mAKaarMaHQcQG0lJ4K Q7e/Xl0eoBvGK60AdowUYN+Ovp76rcQ3hdB4aE80HT/MNF0egXzl8tmoRVR8e298 Kt5Pbf/xNdCyHEqg7TJq9TI8+qnH4BMf3QcHJvrQV2cgk9Axr1blIa29mG9a7Hj6 +QvwH793SroE7lShOLLjYjI98hM75DN+4N1oGe5KQ9Hr99ay7tQf/XYQhsc20uw1 7e43jniQGG5grF4TnrKMKr1UHD/4lhpyX2ohmo8/+POXoFpv9Zh3r9XM6XDxsWIG 9ozl4RMPHoYjh+8Fr1GSB591a/hPpw9fy6VjjaZx0fhonDReGjeNn+TQaw08zqtJ 3iR3ab7xvYlHcfzQW8SHOBEv4kb81mv1TZrdrd37M/+KJROmAppHm8hRBTVLNZUE upZMdXVxiDoEOJjQ+QGDh+8d7akhXnSOJTV7iY4p1FQ6YBx9eb4IS8vLsLw419Um gnXO81J+ajR8LRgjH02lUN4GvWdyJ/zi5z8DB3f2wS4Mymh1i+7LiqJvZcvoWwZl ngd/+BevwI9/Mi0jeu5UYGxi7xk92/+Wa4czPjjXbeYtD7S8unn5FX/mT5/k3Vq9 gWa307CjwEvNq7yGs4T5SiVUghJakPn+sYNvJhJmlUwI+Yv/8Nen4OLV5ZtSsS2j 83Y61ocDnhjJwP7dBfjlX/wi3Hf/ERTMEvjNlXZa5nRtVryTtTzeHdreNCgXN+py HDQeGheNj8ZJ46Vxr6VZvUXfJF+SM8lbpsEof+JAPIiLi3yIE2k1cSN+GynI245n jLX76OFSOCNqzNAy+MWEGobcxJdbuWyOleandylMQ7XTYHquDl/85CRqqtrTuSFK u2EMpRp0VKGhRevffQNDwMwUzE6fl4X97gPOY6d/52l5e3KHa6tYQRs0YDD26GOP wWce/ZjU6J0IerCQgnTSaMuqtyVMAm07DvzP//czcGO+hBMJg1q3Gu458HMvcpY4 73NvhoE667JEqWZXmh/xx5z1vnoTze723Z6H5sh2WkFFCcJFD5Q5I1O80D8wPBs4 0SrWG+dm4V9/8w0ZPPS2KraWf9PASQC7R7NweLIPHv/4EfjFX/oyaOCAV0ctp0jd bUbFF3EnaXmXNkvIrvye9H3pe9P3p3HQeGhcNL4O6G3sQImib1/Kl+QsV8lQ7gMo f+JAPIgL8SFOxGsjX31Lze7W7nmMzDMDy5BqeEpgWaomgFpwmLmBIX917tLeQNB9 /Rq8dXkVjuwbkoFHL9F5rJ/U64GafpiGLg8llTcXJBIwNLoTZq9NQ6O20rkvMPL5 a7+sdPqqKe8zZIhKvKIdbfN2scSuoEaXoJBLwt/+ylfgI/vH4R6MuieGMjCAP0ua Kmh0Z2YP2twdfb/41jX43//1D+W6N8cUWg09d/d9j36fB8qlwA9mXCWcZ051td5v N88sFz24hVZvotltIeIsGe8/4mlBscmafsX1xZLr8htBwK7u3P+xl4VXD+VA3RY8 +S9/AAvLtZ79d/zhcQ5OvoyCl0Po2x48NAp//1e+Cgf274WguYgWcSHy5ThY8lkY hG6g6eF7B3idJtPnB3KJshb5Zvx+9D3p+9L3pu9P46Dx0Lg6ufQ2QJMcSZ4kV5Iv yZnkTXIn+RMH4kFciA9xgk20+paa3a3dM0f/LMyVSorPJsOkEeA7CTVQdc1KpkMl dHP1cqlfdvnB6Pz8tQp8vn3iQLfv3sqHy8NKWFRWpY4/Scw/k6jlY+M7YGTHJJTL K7C6fF36cuisg4dyWN170Tu6r6y3IdsBe/M/pRbLuywCuvUx0mS/FYFuraJGL8P4 6Iisin3q4ftg/0QBJmV1LAPZlAmGTnk0bBp1bwSa/PTv/Iu/gYszOJHwszhajsGx iYvZoT0vO4JdDjm/xhR1oeFny6445bwyeNWLFjyOiW3DjoBDJ1i7PpgAo+JQyyaG lCnE0LL9I06rcmPcdVpJKowsrDpQqrnw6P3jNx34vTVwwkT3FCsyaKOALWnp6OM0 yGVSMLFrFwwUx2CldAOqqwty+22UiwftXS+x5oXQngEbo1a24hsTXrvZDtrbc6PS JO0soarfKnhosgf6MvDzn/08HH30QTg0OQh7d+Rgx1AWBvIJ/O66vF9LVaCnLUbd 5VBKs/63bzwHP3jpggz4KM1Kp6yVsXs+/gPfCy+7Hr/KbTEnXGWlUUw27mvk2gWU zZfMNoVNj+PHFWXqq4fhvpf3hmHCBjVbg9A1FMWQ3XH0fN+oU567MImfpFL0fGEW Zzx+5IMHht+2Q3Ir4HTCPMlbRwkZZmTesylDnnvVX8jAzt17IJcbgKWFa9ColNqr ZmTS/fbtwUHnXuf4ijRzzRR39mu3o+j4FtewfUOc9MWCt3d/OHL5MBJ4NdLkxor8 To99+nH47NFPwn33jMA+1GQy2UN9SchnLLRKqjyfi+oJWzUg2gj0H554Bf782z/B gCz6XDWwvd1Hjj4TALvIhZgOHHFdSzZKrJWs9V3JOU8/9GoAJx8P1x+Ovm3YkTl/ HGa+9qfhEH8+dGw6/sFH5QZF4Eh0VWX5fL+/PD89IUMuHORbl1Ygk7Rwtg9sS8Oj SF1pp2ZKZNZNHTIpXZrEXNqEoYE+uOeeg1AcHgbuueDUV6GFgVxAeTnBpy3LBD+Q N6VCfLODvJ2p/RyXMkO5N96P9tnRChKP1obljk+nCzD6Zeo6tWN8FD71qUfgc0c/ BfcfoACsgJF2DgPTtFyTJm02JWi81K3dx0ag//13TsMfn3hJ7mQhV4F+Oth7+BPP MiN1xgnE5cDjsz54i45nVCFTb7145O/4cOzxzsrWO4K9BhxkdD7ANeGlUclDXbCA gWCCaakczyYTsLp4dSw62ZPBy1OLMEplUeqDva66thVweea41HQmTTvdr5zQqdRq ouZE1/BgH+zdsxsOHDgEOyZ24WtDsBtlaFYXoxRFlnVbkWZ6dgSRR+vy0fZdu22W mzLSlRsiyQ+jb6TKF130eXsndyPgT8GnH/k4PPzAQbh33yjsHc/B7rEc+mWCbMnS p+wlo0Z17l66iXX7aEqxCPRTz56H3//Gjzqg0WWIyf0ffVkrjL3h+3waPPUqSme+ rkMZGlbzJ07Chz86HGzmp7sf2+h9hSM4EfJDT5yAN8z+ZlhtsLoe6BkR6ihAPVnY oU1M+ubV6dMfjYf7v/4/P4BGy4Nf+cIRMKihDqz5r176q8l8XP4DI9lktM2J9mkV EMJIvy8PT6EzNcqoYfcfGIPVuger5TpcungRytUaNFstsFs2OK4tm8n5Ph224kPs 2DWN/CqCwtTPMi1IJHOQSiblbbN79+2DPnQdfRlD3pJTyKJlQXeSSRqyk2ACvwd9 n3iTRrQzp8cwcAPQf/7dU/D1/+/5qBRq18hPhzsn730T5fq66zsz+NJrOB0Xk75a 9pP9zY9Cwztz4gn+tiBlM4K990yJD1Q/xo7CYxrMzFhVNchpzBpEoY3pIdtjmsre yvWzj964dvFeLZGXh4TTQaO//pUH4bef+DkJvNcD1jdaDIgb2Ed9UkGeLE+Hp9CZ GnTUQqPpQaVhQ6uFP8PAwUYhui4dPRXIFpGchxhPBOA0G2Cl0qAzVboL0kpDwzzf ZJDA75jAwCqJwWE+jaYZtZbuvaJbcihwpMULjcE6yL23sFofdRPoP0If/Y1vvtbO pasy8h6b2Hc6P37wOdcNL/mKuIyT9AYXzlIuUKuwa5dzEn7IkUVP5vs2NDva0UKA Th47xh80RjyrXKg3LYcJDY25KpCjpvSPHqJminB99vLhSIVC+Df/+VVYrdnwT7/2 CArN6gDfnpaztS+Mmq7hZ1iagdDJvAvo46Y8asFx07IxuxdEpxAFPJRNX31aD26f ZCsbzOBnyh4wBgNdnqKD/5ZxAgKlvjCmKm+bpbspqeqlxXAZtDcaxJrce+uqeNJ2 p1e//6fPw3/+/pmO6SaNHp/Yc6Zv9NDzOIbLLsfIO4B5n4vllJOt1wtl77XbAL1t ze7yqfIQ7gfnRsg2J30jkdGb+iAqx46UBbswLN/bXL72sauXT39UNbOMjiGks6se uncX/N4/fByDrKwE3uuB61tpuzxqXJ5pCJ2DVASPwSrRKQc8aP/OzW5CTiBqrU8H qylhtEChsc4dqRDdidwFmG37e67fFUqgF5dr8Lt//AN4+fRMe226Ln30zj33vpEa mHg1CMWlpgMz+LVn/ZS/pHt2Hd+q9drofDufhm23oOopQLtV/k1H9Y7WM0JF9TFV V3i+Rmk4fgk1SGULzXQqJVaXro6GQjByK3RW9HdfmoH9O/tkmtLJsbtAbwe60l4C ZXGe3k53cA7JHJc2SiQouEPTS89J05DmmFK6pPT/hixjUsQvm9aQOTei5VddLlYo MvCLjzne7oRcfw91bLZfOXMd/tH/8TRcuDKHQWFkuoXfCCgYS/fvfMXxlcu2J676 PLhuGY3lMOC1dwr6tmFvBJwyVK/hB0wTXNF16rYq9FR/s5DPOdWlmTEe+LQNBVoO h+/++IoEdO+e4i0hb1ewMfi1SF5p7wAJo5+x9vmVXVf0s7VjrWmixL+rdI67Vm5L k7s1Ol7QoO2/3/jW6/B7/+ok1KrVTsGE8ug9hx56Ts+Mv+677rTHlCu+37rh2c4y WFB9N0C/I9g3A38Qgb8mtDJ1azE5YyEquOIrOEzdzNr9wxMrrfLCoNOqJWQBEr/x a+cW4Y0LS3AAtZzy580gvpNHt5tQus4r74Z5u25kK8ixNhPoi1dL8M/+8PvwzZOn wUdtjkugqYS1Onnfp7/HzPwZP/CmXYAZnBzznqeUjDpqdIZA/wMEffQdgX7HsNeA QwQcXhOJRibwjCb3heEbgYrfmXOMed3BsT2LirATtdX5PpSCQhWs+eUGfPNHl6S2 H97d3ylEbCT4O/k0gvWQu7W5jtnBH//lq3D8T34AszeWOvl84FbD4bGJixP7P/59 nysXbRFMg6/ONEU4H4b2crKZqgVFx45AwzsG/a7Avhn4U2KIa+Eq13lfYPqgCj+k EpWKDh3HnusbXk1nM061NDvMfVeLZn8Ab10swbd/PA2DhSTsGMxsCvhOgn4ryLFv /t7Ll+Ef/4u/hudfu4zaXG9vJ6oCC11398EHXywM7X3Z8cLLHMJp4fNZKpjovrpS Al430003Mt1H3xXQ7xrs9T78I29WxcLEbsx0Gpxx7oWe6/mK6ilMdXUzUy+O7Fry W+VMs1bKUrtUyiCaLReeefkqvPDWDcimdBgfTPdkoj8owBsVR2LI339lGo79yQ/h 3z39Jvrmylr+jGlVodB/fffhR78vzbaAyy2PXw2c5nUfwkWqjNVT+cbEhSn3xSMN /5366PcM9hpwqqMfDT97JRcsO1oQqoJ7Cc8zPHBCP/SCMHSYptuF/onFXF+h0SrP 97t2w5QrTAi9VG7C916ZgZOvXpMR846hdFQj2mB9fP3/fy/gr4e7fidJDJly5u+8 cAn+lz8+CX/+1z+BxaWVdkpVk6AtXanvPvixF/uGD/yYA7vkunw6cPg1EXjXm5a/ HFKtu2E172t47tMPlYIojz72rnb4fVdhdy+cTE39hSgdngrHM3WeLBd4ICo+M1Mu 0nbwZbbHmKNpyVpxdHJOVXxWX53rC7jHov5rAaxWW/CD167C089flltoB3IJ2flv o7tQtrpn/FYTYqvX38pMd2vxzI1V+Hff+Qn88//3WQy+pmB5ZbWrQIKBNG/ykR2T U+P3PPxDoabO2iFMyx0mPLzOVHUhsKuriVZ/jRY1qNY9RSXQk4+H4XvQyvldh90B fhylisDJrO+dOhQs7U7zoMo8M2h43FccDXybh8xGwbVSfUNLQzv23AC/Zdi15Sz3 HDVepao3bdkN6MQzZ+Gl03PgYtAz0p+UGwLialQ3jPWANitwbPbfRNcBanFUHUfW 5VoTvvWjc/D1f/si/MF/+DG8duYaVKuVCDKtd9volwPbLw6OTO8+8shJMzv0Ewc1 2Q9gRvHda64dzjPulWjjQaPY36BlyhePnPZpSxGlp+F71LP7tipot1Nte+LMITYF YGTx4mopxdVcxkqqeSUURUVXizoLhw1VGwyVcHjl2tSRlfmZSR4qBtMRrG5FB7iq pjxvWjcMODQ5BB87OCJPhb9v36AsbcYl2JvTra1X2jbS4G7gdAjqWxeXZKOaV8/O w9T0Ivie114eddu7V6LVNE0Jvf6RXdP9E4dOKaGy4AV8yRfKQugHpVBhJdocqAXV Om0lqgF4h/CSmwTfZf/8gcDuLKBQCQ2hHz35mHb9yCkjWclb+J9SCSXMCD3Mq5o+ YCpmP9ODIguVQY1BsTx/4VClNLez0WrkmWoq8ixuzZSnyUdHPuvyDEvTNDB1K8Ke cdqym8crB7vwebAv1V4f3xj62/PiEJZWmzAzX5HtIakfKHUOPHOlJAsich97vFbO 4zVw6vHmhulkupIvjl4tjNwzRTfZCSVcEr5ackN3JeD+Mu3rtkOFSp7NVr7ijJ86 4p08SjXuJ8V7qc3vO+z1Wg6o5Q8WytqKZxhpt8+EzEI6ERoZ4GZOY2qBgTegmUYf U5UBk6l9GK0OLy9e3ldZmRtzHSclodOhrlqk6dG50Zo8cFSRJbGo5m7hJBjIJ2V7 SNrmJJcmqeOvoYHjRQfEUvd9ai7Ssj1YrrRQi9vnotAGBxF1+I0gR62nwnaPGYJs WlYz3z96Y2Boz0XVSi1gfrkqgnCZu96qAGOZi6AMmlu1Fa8O9eFGw1x1abvva9Tj 5H3S5tte9XrnkS0IRaEYIRSvHTsu0LTz6cKCl/EMdznX18jaC/XAscoC9OUQlJyq hAWu+gVVNWf7d957cWjiSMFpro7WVq/vaFbLg43mSi4MFTU6zVfvnGcZn9fNHQaN 2tqtRG8/rP3mnaPxERcScryrJd4yTF2DlTBIp7LVVG5kKds3Pmul+ua4EpZ9X1Qc x8fITCkHIV6+ipGZU9Mtp0l31QxUV916ZsE7iJBP7Loq4E/+gYATpM1Pvq/nabyv mn1r0w5aqXhIK6aa2jJqup7kFjh2ihlqxmBaOtS8nAYqghU5XVNzqsoydCHSTL0y N1ZfnR+xm7WC5zpJz3WtUG6Pis4Bhfi5fa/ZGvQ25G7Y7WMuZBtn/NswTccwrVYi lS1n+kbmM/nRG4i/HgRCXj6GnPjeVQ74zI2qJ3hDeEEdrETTb2nOAGpyqZnixdJU dEvO+2iy7yjYG0GnIG66bd6zgWqkZZawSQAAAoZJREFUFEsXvJkEzUz4KTOp226G JdQUhuoZCLSMqou0pqjomMOUCiypMgXjgCDhOLWC0yjnnWY9g1ppChHo6Df1QASa 4L5G7UXwYwXm+xzNAsd4wWdM9dE6uFYqU7fShYplZcuYrNiBCJ0ARAttUpOHQTPw WQNUXg8URu2cm37CrOtNt4VhuE2tLajvWE0NPDLX1JIqDr4+SMh3DOxbQS8dLrLS mZKWhetGXcvoiULaYBXHAo0luBokaJOSoYYpjpANnVksVBOB8BOqxiwQzFQhNEMd 8CWK3HdAhycJ2qMgaDkMP5C2gbMwZJg6y5axmF0FSsgVHzzUaxeYcAMuHJXpNnX3 9XyB6aJoeYHSxPjc0QLVpiY1Im85drnhZXjdpx4m1NqCOh7cSZDvONgbQQd4Eo6e PK7V7xlh1VlXK6aHtablaKTxqEGGrgamJpghTNVkrmtqVlpXAsV0FN+kE+GZGuoq RW1hSOdSqtF5o15n94EijPjwOmq/zwOMxkSg+HTUghXqbqiGLvXrpjbO1N2XM+H5 gepSi0jSYGoAW2oscGo/RV2JTh59kgMchzsN8h0L+5bgUdufwJ+RmXfKBeYOp1lx oSHh5xKK6miaZvOakazmVF/jmqEyjU6ENxiZbpUZdGy028L3S3R9gg3MTApPnmsW CE+onA5P8ehMDa7xVq4aJLSsZ3HOqY2zhDuc5uZCQ1CLSGmm6W3uQC3+qYP9Nuiy PHc80kyEf7Q0xUjr6f+S5vOhDBtppphXKDPfTjDBc0ohU5MHhXOvxKCvT/4qd5uY rqciKKuroBlFee5VuZ5FP14N5SE55YLs1kwd+GXjOHxI7aVWU/KeKoC15jR3NuT4 8f8D/BVoxjuzuWYAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="30" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="389" font-size="11" y="471" clip-path="url(#clipPath32)" stroke="none" xml:space="preserve">Mesh</text>
+<rect x="130" y="27" clip-path="url(#clipPath33)" fill="rgb(209,209,209)" width="20" height="20" stroke="none"/>
+<rect x="130" y="27" clip-path="url(#clipPath33)" fill="none" width="19" height="19" stroke="rgb(136,136,136)"/>
+<image stroke="rgb(136,136,136)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(136,136,136)" clip-path="url(#clipPath34)" preserveAspectRatio="none" height="16" x="15" y="10" font-size="11" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA50lEQVR42mNgGGjA iC7w4evP/xtO32d48OozTk0KYrwMAaaKDALc7IyM6JodGjYyOGhLgRXgAgeuPmNY cOAGw4EGfwYWZImG1acZCrz1GBIcNBgnEHD6gatP/zesPgPxwoV7L/9/+PqDoWD+ EYYJiTZgBQ668oyE/O/QsOE/2AWTt5xl0FKUZoh11GE4++ADw84zt4gORLAB3Jzs DPrKUnDBi3efk2bA1+8/gZqewQVfvP9MtAFMICLXx5jBWEGAYfH+K2C6KsSMvHRQ sODIfwMFEXAsMBARCwsO3GSgOB1QnBIZhj4AAGcNZeNL2Ad0AAAAAElFTkSuQmCC" xlink:actuate="onLoad"/>
+<text x="34" font-size="11" y="23" clip-path="url(#clipPath35)" stroke="none" xml:space="preserve">Meshing Parameters : IMeshTools_Parameters</text>
+<image x="470" y="474" clip-path="url(#clipPath36)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABGElEQVR42mP8//8/ AyWAiYFCQLEBLLgk9i0K+f/kygE4X0bHgcEpbg0j0QaANMfW7IDzF7d4kOaCd6// MPy+O4WB4R+Ixwjmk2SAnqMLQ1/nejhfwdaCNANA/nWKY2DwL1j1f+OEMEaSAtEt fcF/kNMZofHknr4InFhAxK6ZcYwEDfj25RvDkaVZGLbaRE7DSHWMyClx8fqD/9cc fAnnh9iLM8QG2jPWbZvw//yj83BxQzlDhiavAkYMF4A0d5a4wPnlPXuABjAwgDR3 uzPDxUt3nsfuhQ9v3zLsu34bkj7/gfjvweJbDp5gsBbXhavbcvAyA0MGFgNC3A0Z Fs86Aefra8uC6TzXCIbKVSvg4tGebtjDYEAyEwAqcGWs48tc2QAAAABJRU5ErkJg gg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="205" x2="287" y1="276" y2="276" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath38)" fill="none" x1="280" x2="287" y1="279" y2="276" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath38)" fill="none" x1="287" x2="280" y1="276" y2="273" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="373" x2="373" y1="311" y2="331" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="373" x2="106" y1="331" y2="331" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="106" x2="106" y1="331" y2="351" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath39)" fill="none" x1="103" x2="106" y1="344" y2="351" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath39)" fill="none" x1="106" x2="109" y1="351" y2="344" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="174" x2="310" y1="123" y2="123" stroke="rgb(69,69,69)"/>
+<line clip-path="url(#clipPath40)" fill="none" x1="303" x2="310" y1="126" y2="123" stroke="rgb(69,69,69)"/>
+<line clip-path="url(#clipPath40)" fill="none" x1="310" x2="303" y1="123" y2="120" stroke="rgb(69,69,69)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="370" x2="370" y1="203" y2="219" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="370" x2="114" y1="219" y2="219" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="114" x2="114" y1="219" y2="243" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath41)" fill="none" x1="111" x2="114" y1="236" y2="243" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath41)" fill="none" x1="114" x2="117" y1="243" y2="236" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="201" x2="287" y1="384" y2="384" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath42)" fill="none" x1="280" x2="287" y1="387" y2="384" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath42)" fill="none" x1="287" x2="280" y1="384" y2="381" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="373" x2="373" y1="419" y2="459" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath43)" fill="none" x1="370" x2="373" y1="452" y2="459" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath43)" fill="none" x1="373" x2="376" y1="459" y2="452" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="60" x2="60" y1="104" y2="135" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath44)" fill="none" x1="57" x2="60" y1="128" y2="135" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath44)" fill="none" x1="60" x2="63" y1="135" y2="128" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="60" x2="60" y1="104" y2="135" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath44)" fill="none" x1="57" x2="60" y1="128" y2="135" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath44)" fill="none" x1="60" x2="63" y1="135" y2="128" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="174" x2="310" y1="123" y2="123" stroke="rgb(69,69,69)"/>
+<line clip-path="url(#clipPath40)" fill="none" x1="303" x2="310" y1="126" y2="123" stroke="rgb(69,69,69)"/>
+<line clip-path="url(#clipPath40)" fill="none" x1="310" x2="303" y1="123" y2="120" stroke="rgb(69,69,69)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="373" x2="373" y1="419" y2="459" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath43)" fill="none" x1="370" x2="373" y1="452" y2="459" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath43)" fill="none" x1="373" x2="376" y1="459" y2="452" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="370" x2="370" y1="203" y2="219" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="370" x2="114" y1="219" y2="219" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="114" x2="114" y1="219" y2="243" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath41)" fill="none" x1="111" x2="114" y1="236" y2="243" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath41)" fill="none" x1="114" x2="117" y1="243" y2="236" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="205" x2="287" y1="276" y2="276" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath38)" fill="none" x1="280" x2="287" y1="279" y2="276" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath38)" fill="none" x1="287" x2="280" y1="276" y2="273" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="373" x2="373" y1="311" y2="331" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="373" x2="106" y1="331" y2="331" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="106" x2="106" y1="331" y2="351" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath39)" fill="none" x1="103" x2="106" y1="344" y2="351" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath39)" fill="none" x1="106" x2="109" y1="351" y2="344" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath37)" fill="none" x1="201" x2="287" y1="384" y2="384" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath42)" fill="none" x1="280" x2="287" y1="387" y2="384" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath42)" fill="none" x1="287" x2="280" y1="384" y2="381" stroke="rgb(136,136,136)"/>
+</g>
+</g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" stroke-dasharray="none" shape-rendering="auto" font-family="'Dialog'" width="1032" text-rendering="auto" fill-opacity="1" contentScriptType="text/ecmascript" color-interpolation="auto" color-rendering="auto" preserveAspectRatio="xMidYMid meet" font-size="12" viewBox="0 0 1032 595" fill="black" stroke="black" image-rendering="auto" stroke-miterlimit="10" zoomAndPan="magnify" version="1.0" stroke-linecap="square" stroke-linejoin="miter" contentStyleType="text/css" font-style="normal" height="595" stroke-width="1" stroke-dashoffset="0" font-weight="normal" stroke-opacity="1">
+<!--Generated by the Batik Graphics2D SVG Generator-->
+<defs id="genericDefs"/>
+<g>
+<defs id="defs1">
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath1">
+<path d="M131 9 L316 9 L316 206 L131 206 L131 9 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath2">
+<path d="M131 9 L314 9 L314 204 L131 204 L131 9 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath3">
+<path d="M146 14 L299 14 L299 32 L146 32 L146 14 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath4">
+<path d="M146 14 L302 14 L302 32 L146 32 L146 14 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath5">
+<path d="M136 37 L256 37 L256 55 L136 55 L136 37 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath6">
+<path d="M136 37 L258 37 L258 55 L136 55 L136 37 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath7">
+<path d="M136 53 L233 53 L233 71 L136 71 L136 53 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath8">
+<path d="M136 53 L235 53 L235 71 L136 71 L136 53 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath9">
+<path d="M136 69 L243 69 L243 87 L136 87 L136 69 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath10">
+<path d="M136 69 L245 69 L245 87 L136 87 L136 69 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath11">
+<path d="M136 85 L264 85 L264 103 L136 103 L136 85 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath12">
+<path d="M136 85 L266 85 L266 103 L136 103 L136 85 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath13">
+<path d="M136 101 L271 101 L271 119 L136 119 L136 101 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath14">
+<path d="M136 101 L273 101 L273 119 L136 119 L136 101 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath15">
+<path d="M136 117 L276 117 L276 145 L136 145 L136 117 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath16">
+<path d="M136 117 L278 117 L278 145 L136 145 L136 117 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath17">
+<path d="M136 143 L296 143 L296 171 L136 171 L136 143 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath18">
+<path d="M136 143 L298 143 L298 171 L136 171 L136 143 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath19">
+<path d="M136 169 L286 169 L286 187 L136 187 L136 169 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath20">
+<path d="M136 169 L288 169 L288 187 L136 187 L136 169 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath21">
+<path d="M132 35 L313 35 L313 203 L132 203 L132 35 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath22">
+<path d="M455 44 L745 44 L745 565 L455 565 L455 44 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath23">
+<path d="M455 44 L743 44 L743 563 L455 563 L455 44 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath24">
+<path d="M532 49 L666 49 L666 67 L532 67 L532 49 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath25">
+<path d="M532 49 L669 49 L669 67 L532 67 L532 49 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath26">
+<path d="M460 72 L694 72 L694 90 L460 90 L460 72 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath27">
+<path d="M460 72 L696 72 L696 90 L460 90 L460 72 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath28">
+<path d="M460 88 L552 88 L552 106 L460 106 L460 88 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath29">
+<path d="M460 88 L554 88 L554 106 L460 106 L460 88 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath30">
+<path d="M460 104 L722 104 L722 122 L460 122 L460 104 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath31">
+<path d="M460 104 L724 104 L724 122 L460 122 L460 104 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath32">
+<path d="M460 120 L700 120 L700 138 L460 138 L460 120 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath33">
+<path d="M460 120 L702 120 L702 138 L460 138 L460 120 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath34">
+<path d="M460 136 L705 136 L705 154 L460 154 L460 136 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath35">
+<path d="M460 136 L707 136 L707 154 L460 154 L460 136 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath36">
+<path d="M460 152 L704 152 L704 170 L460 170 L460 152 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath37">
+<path d="M460 152 L706 152 L706 170 L460 170 L460 152 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath38">
+<path d="M460 168 L697 168 L697 186 L460 186 L460 168 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath39">
+<path d="M460 168 L699 168 L699 186 L460 186 L460 168 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath40">
+<path d="M460 184 L710 184 L710 202 L460 202 L460 184 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath41">
+<path d="M460 184 L712 184 L712 202 L460 202 L460 184 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath42">
+<path d="M460 200 L561 200 L561 218 L460 218 L460 200 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath43">
+<path d="M460 200 L563 200 L563 218 L460 218 L460 200 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath44">
+<path d="M460 216 L583 216 L583 234 L460 234 L460 216 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath45">
+<path d="M460 216 L585 216 L585 234 L460 234 L460 216 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath46">
+<path d="M460 232 L547 232 L547 250 L460 250 L460 232 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath47">
+<path d="M460 232 L549 232 L549 250 L460 250 L460 232 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath48">
+<path d="M460 248 L538 248 L538 266 L460 266 L460 248 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath49">
+<path d="M460 248 L540 248 L540 266 L460 266 L460 248 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath50">
+<path d="M460 264 L567 264 L567 282 L460 282 L460 264 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath51">
+<path d="M460 264 L569 264 L569 282 L460 282 L460 264 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath52">
+<path d="M460 280 L543 280 L543 298 L460 298 L460 280 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath53">
+<path d="M460 280 L545 280 L545 298 L460 298 L460 280 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath54">
+<path d="M460 296 L574 296 L574 314 L460 314 L460 296 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath55">
+<path d="M460 296 L576 296 L576 314 L460 314 L460 296 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath56">
+<path d="M460 312 L564 312 L564 330 L460 330 L460 312 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath57">
+<path d="M460 312 L566 312 L566 330 L460 330 L460 312 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath58">
+<path d="M460 328 L580 328 L580 346 L460 346 L460 328 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath59">
+<path d="M460 328 L582 328 L582 346 L460 346 L460 328 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath60">
+<path d="M460 344 L573 344 L573 362 L460 362 L460 344 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath61">
+<path d="M460 344 L575 344 L575 362 L460 362 L460 344 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath62">
+<path d="M460 360 L575 360 L575 378 L460 378 L460 360 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath63">
+<path d="M460 360 L577 360 L577 378 L460 378 L460 360 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath64">
+<path d="M460 376 L564 376 L564 394 L460 394 L460 376 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath65">
+<path d="M460 376 L566 376 L566 394 L460 394 L460 376 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath66">
+<path d="M460 392 L566 392 L566 410 L460 410 L460 392 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath67">
+<path d="M460 392 L568 392 L568 410 L460 410 L460 392 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath68">
+<path d="M460 408 L569 408 L569 426 L460 426 L460 408 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath69">
+<path d="M460 408 L571 408 L571 426 L460 426 L460 408 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath70">
+<path d="M460 424 L571 424 L571 442 L460 442 L460 424 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath71">
+<path d="M460 424 L573 424 L573 442 L460 442 L460 424 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath72">
+<path d="M460 440 L568 440 L568 458 L460 458 L460 440 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath73">
+<path d="M460 440 L570 440 L570 458 L460 458 L460 440 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath74">
+<path d="M460 456 L570 456 L570 474 L460 474 L460 456 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath75">
+<path d="M460 456 L572 456 L572 474 L460 474 L460 456 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath76">
+<path d="M460 472 L561 472 L561 490 L460 490 L460 472 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath77">
+<path d="M460 472 L563 472 L563 490 L460 490 L460 472 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath78">
+<path d="M460 488 L563 488 L563 506 L460 506 L460 488 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath79">
+<path d="M460 488 L565 488 L565 506 L460 506 L460 488 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath80">
+<path d="M460 504 L574 504 L574 522 L460 522 L460 504 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath81">
+<path d="M460 504 L576 504 L576 522 L460 522 L460 504 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath82">
+<path d="M460 520 L576 520 L576 538 L460 538 L460 520 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath83">
+<path d="M460 520 L578 520 L578 538 L460 538 L460 520 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath84">
+<path d="M460 536 L516 536 L516 554 L460 554 L460 536 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath85">
+<path d="M460 536 L518 536 L518 554 L460 554 L460 536 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath86">
+<path d="M456 70 L742 70 L742 562 L456 562 L456 70 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath87">
+<path d="M131 225 L316 225 L316 315 L131 315 L131 225 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath88">
+<path d="M131 225 L314 225 L314 313 L131 313 L131 225 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath89">
+<path d="M140 230 L304 230 L304 248 L140 248 L140 230 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath90">
+<path d="M140 230 L307 230 L307 248 L140 248 L140 230 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath91">
+<path d="M136 253 L292 253 L292 281 L136 281 L136 253 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath92">
+<path d="M136 253 L294 253 L294 281 L136 281 L136 253 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath93">
+<path d="M132 251 L313 251 L313 312 L132 312 L132 251 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath94">
+<path d="M131 333 L316 333 L316 423 L131 423 L131 333 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath95">
+<path d="M131 333 L314 333 L314 421 L131 421 L131 333 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath96">
+<path d="M148 338 L297 338 L297 356 L148 356 L148 338 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath97">
+<path d="M148 338 L300 338 L300 356 L148 356 L148 338 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath98">
+<path d="M136 361 L308 361 L308 389 L136 389 L136 361 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath99">
+<path d="M136 361 L310 361 L310 389 L136 389 L136 361 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath100">
+<path d="M132 359 L313 359 L313 420 L132 420 L132 359 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath101">
+<path d="M131 441 L316 441 L316 586 L131 586 L131 441 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath102">
+<path d="M131 441 L314 441 L314 584 L131 584 L131 441 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath103">
+<path d="M162 446 L283 446 L283 464 L162 464 L162 446 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath104">
+<path d="M162 446 L286 446 L286 464 L162 464 L162 446 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath105">
+<path d="M136 469 L222 469 L222 487 L136 487 L136 469 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath106">
+<path d="M136 469 L224 469 L224 487 L136 487 L136 469 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath107">
+<path d="M136 485 L206 485 L206 503 L136 503 L136 485 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath108">
+<path d="M136 485 L208 485 L208 503 L136 503 L136 485 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath109">
+<path d="M136 501 L207 501 L207 519 L136 519 L136 501 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath110">
+<path d="M136 501 L209 501 L209 519 L136 519 L136 501 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath111">
+<path d="M136 517 L204 517 L204 535 L136 535 L136 517 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath112">
+<path d="M136 517 L206 517 L206 535 L136 535 L136 517 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath113">
+<path d="M136 533 L209 533 L209 551 L136 551 L136 533 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath114">
+<path d="M136 533 L211 533 L211 551 L136 551 L136 533 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath115">
+<path d="M136 549 L210 549 L210 567 L136 567 L136 549 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath116">
+<path d="M136 549 L212 549 L212 567 L136 567 L136 549 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath117">
+<path d="M136 565 L207 565 L207 583 L136 583 L136 565 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath118">
+<path d="M136 565 L209 565 L209 583 L136 583 L136 565 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath119">
+<path d="M132 467 L313 467 L313 583 L132 583 L132 467 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath120">
+<path d="M851 105 L1023 105 L1023 207 L851 207 L851 105 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath121">
+<path d="M851 105 L1021 105 L1021 205 L851 205 L851 105 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath122">
+<path d="M856 110 L1015 110 L1015 128 L856 128 L856 110 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath123">
+<path d="M856 110 L1018 110 L1018 128 L856 128 L856 110 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath124">
+<path d="M856 133 L939 133 L939 151 L856 151 L856 133 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath125">
+<path d="M856 133 L941 133 L941 151 L856 151 L856 133 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath126">
+<path d="M856 149 L941 149 L941 167 L856 167 L856 149 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath127">
+<path d="M856 149 L943 149 L943 167 L856 167 L856 149 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath128">
+<path d="M856 165 L923 165 L923 183 L856 183 L856 165 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath129">
+<path d="M856 165 L925 165 L925 183 L856 183 L856 165 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath130">
+<path d="M852 131 L1020 131 L1020 204 L852 204 L852 131 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath131">
+<path d="M-1 -1 L1033 -1 L1033 596 L-1 596 L-1 -1 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath132">
+<path d="M58 177 L113 177 L113 192 L58 192 L58 177 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath133">
+<path d="M124 128 L134 128 L134 137 L124 137 L124 128 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath134">
+<path d="M22 211 L77 211 L77 226 L22 226 L22 211 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath135">
+<path d="M124 86 L134 86 L134 95 L124 95 L124 86 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath136">
+<path d="M22 436 L77 436 L77 451 L22 451 L22 436 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath137">
+<path d="M124 510 L134 510 L134 519 L124 519 L124 510 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath138">
+<path d="M363 129 L401 129 L401 144 L363 144 L363 129 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath139">
+<path d="M406 105 L460 105 L460 120 L406 120 L406 105 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath140">
+<path d="M311 105 L384 105 L384 120 L311 120 L311 105 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath141">
+<path d="M443 121 L458 121 L458 130 L443 130 L443 121 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath142">
+<path d="M312 121 L322 121 L322 130 L312 130 L312 121 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath143">
+<path d="M366 271 L404 271 L404 286 L366 286 L366 271 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath144">
+<path d="M409 251 L463 251 L463 266 L409 266 L409 251 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath145">
+<path d="M309 251 L362 251 L362 266 L309 266 L309 251 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath146">
+<path d="M443 264 L458 264 L458 273 L443 273 L443 264 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath147">
+<path d="M312 264 L322 264 L322 273 L312 273 L312 264 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath148">
+<path d="M366 504 L404 504 L404 519 L366 519 L366 504 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath149">
+<path d="M409 484 L463 484 L463 499 L409 499 L409 484 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath150">
+<path d="M311 484 L359 484 L359 499 L311 499 L311 484 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath151">
+<path d="M443 497 L458 497 L458 506 L443 506 L443 497 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath152">
+<path d="M312 497 L322 497 L322 506 L312 506 L312 497 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath153">
+<path d="M366 379 L404 379 L404 394 L366 394 L366 379 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath154">
+<path d="M409 359 L463 359 L463 374 L409 374 L409 359 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath155">
+<path d="M317 359 L356 359 L356 374 L317 374 L317 359 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath156">
+<path d="M443 372 L458 372 L458 381 L443 381 L443 372 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath157">
+<path d="M312 372 L322 372 L322 381 L312 381 L312 372 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath158">
+<path d="M771 163 L826 163 L826 178 L771 178 L771 163 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath159">
+<path d="M741 156 L751 156 L751 165 L741 165 L741 156 Z"/>
+</clipPath>
+</defs>
+<g fill="rgb(131,122,133)" font-family="'Segoe UI'" stroke-linejoin="round" stroke="rgb(131,122,133)" font-weight="bold" stroke-width="0" stroke-miterlimit="0">
+<rect x="133" y="11" clip-path="url(#clipPath1)" width="181" rx="2.5" opacity="0.2549" ry="2.5" height="193" stroke="none"/>
+<rect x="134" y="12" clip-path="url(#clipPath1)" width="181" rx="2.5" opacity="0.2549" ry="2.5" height="193" stroke="none"/>
+<rect x="132" y="10" clip-path="url(#clipPath2)" fill="white" width="181" rx="2.5" ry="2.5" height="193" stroke="none"/>
+</g>
+<g stroke-linecap="butt" fill="rgb(77,137,20)" font-family="'Segoe UI'" stroke="rgb(77,137,20)" font-weight="bold" stroke-width="1.1">
+<rect x="132" y="10" clip-path="url(#clipPath2)" fill="none" width="180" rx="2.5" ry="2.5" height="192"/>
+<image x="147" y="15" clip-path="url(#clipPath3)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABSUlEQVR42mNgGGjA CCIKFhz5/+DJJyj3PxAyQiQYkdggmf8IjYoyvAwTEmwYWUCc+48/MUxMswNrBhnC CNUB4QEN+c8INhtoHlSMgSF31kGwGrAB//7+Y+BgYwZrOXHjMYOFuhyDk2cB3La9 O/rB9EmQnIYsxIh/EOcwwRSxMDOBNdc1r2FgYYE44dDuiWDs7FHIwAaUB8mB1IDU wgCcxcrMCFZweHUpkM0EFWOCs0GaQHJgC5gZMQ0ACTbVhjDYhnbDFbCwMCHYQBok B1LDiuQCFljwgmzwNFFhYAAqgDnR1C4bTJ8/Mg1MgzSD1ICM/AcNAxaI/n8MzExM 4LDxMVMFK7h0bAYkBiAxCxbzNVODR8X//0gGgIB/w0ZopCFIWFQiJxpIygCyoXEN N2BphRdJKTCmcztqIJILwC5QURKGm0gsAOkZHAAAeQpotyJG88kAAAAASUVORK5C YII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="166" y="28" clip-path="url(#clipPath4)" fill="black" stroke="none" xml:space="preserve">IMeshTools_Parameters</text>
+</g>
+<g stroke-width="1.1" font-size="11" font-family="'Segoe UI'" stroke-linecap="butt">
+<image x="137" y="38" clip-path="url(#clipPath5)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="51" clip-path="url(#clipPath6)" stroke="none">Deflection : Real [1]</text>
+<image x="137" y="54" clip-path="url(#clipPath7)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="67" clip-path="url(#clipPath8)" stroke="none">Angle : Real [1]</text>
+<image x="137" y="70" clip-path="url(#clipPath9)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="83" clip-path="url(#clipPath10)" stroke="none">MinSize : Real [1]</text>
+<image x="137" y="86" clip-path="url(#clipPath11)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="99" clip-path="url(#clipPath12)" stroke="none">Relative : Boolean [1]</text>
+<image x="137" y="102" clip-path="url(#clipPath13)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="115" clip-path="url(#clipPath14)" stroke="none">InParallel : Boolean [1]</text>
+<image x="137" y="123" clip-path="url(#clipPath15)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="130" clip-path="url(#clipPath16)" stroke="none">InternalVerticesMode : </text>
+<text xml:space="preserve" x="156" y="143" clip-path="url(#clipPath16)" stroke="none">Boolean [1]</text>
+<image x="137" y="149" clip-path="url(#clipPath17)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="156" clip-path="url(#clipPath18)" stroke="none">ControlSurfaceDeflection : </text>
+<text xml:space="preserve" x="156" y="169" clip-path="url(#clipPath18)" stroke="none">Boolean [1]</text>
+<image x="137" y="170" clip-path="url(#clipPath19)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="183" clip-path="url(#clipPath20)" stroke="none">CleanModel : Boolean [1]</text>
+</g>
+<g stroke-linecap="butt" fill="rgb(77,137,20)" font-family="'Segoe UI'" stroke="rgb(77,137,20)" font-weight="bold" stroke-width="1.1">
+<line clip-path="url(#clipPath21)" fill="none" x1="133" x2="312" y1="36" y2="36"/>
+<rect x="457" y="46" clip-path="url(#clipPath22)" fill="rgb(131,122,133)" width="286" rx="2.5" opacity="0.2549" ry="2.5" height="517" stroke="none"/>
+<rect x="458" y="47" clip-path="url(#clipPath22)" fill="rgb(131,122,133)" width="286" rx="2.5" opacity="0.2549" ry="2.5" height="517" stroke="none"/>
+<rect x="456" y="45" clip-path="url(#clipPath23)" fill="white" width="286" rx="2.5" ry="2.5" height="517" stroke="none"/>
+<rect x="456" y="45" clip-path="url(#clipPath23)" fill="none" width="285" rx="2.5" ry="2.5" height="516" stroke="rgb(173,127,168)"/>
+<image stroke="rgb(173,127,168)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(173,127,168)" clip-path="url(#clipPath24)" preserveAspectRatio="none" height="16" x="533" y="50" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX 0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO RK5CYII=" xlink:actuate="onLoad"/>
+<text x="552" y="63" clip-path="url(#clipPath25)" fill="black" stroke="none" xml:space="preserve">IMeshTools_Context</text>
+</g>
+<g stroke-width="1.1" font-size="11" font-family="'Segoe UI'" stroke-linecap="butt">
+<image x="461" y="73" clip-path="url(#clipPath26)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="86" clip-path="url(#clipPath27)" stroke="none">myParameters : IMeshTools_Parameters [1]</text>
+<image x="461" y="89" clip-path="url(#clipPath28)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="102" clip-path="url(#clipPath29)" stroke="none">myModel : [1]</text>
+<image x="461" y="105" clip-path="url(#clipPath30)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="118" clip-path="url(#clipPath31)" stroke="none">myModelBuilder : IMeshTools_ModelBuilder [1]</text>
+<image x="461" y="121" clip-path="url(#clipPath32)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="134" clip-path="url(#clipPath33)" stroke="none">myEdgeDiscret : IMeshTools_ModelAlgo [1]</text>
+<image x="461" y="137" clip-path="url(#clipPath34)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="150" clip-path="url(#clipPath35)" stroke="none">myModelHealer : IMeshTools_ModelAlgo [1]</text>
+<image x="461" y="153" clip-path="url(#clipPath36)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="166" clip-path="url(#clipPath37)" stroke="none">myPreProcessor : IMeshTools_ModelAlgo [1]</text>
+<image x="461" y="169" clip-path="url(#clipPath38)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="182" clip-path="url(#clipPath39)" stroke="none">myFaceDiscret : IMeshTools_ModelAlgo [1]</text>
+<image x="461" y="185" clip-path="url(#clipPath40)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3 obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5 A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg==" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="198" clip-path="url(#clipPath41)" stroke="none">myPostProcessor : IMeshTools_ModelAlgo [1]</text>
+<image x="461" y="201" clip-path="url(#clipPath42)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="214" clip-path="url(#clipPath43)" stroke="none">GetParameters()</text>
+<image x="461" y="217" clip-path="url(#clipPath44)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="230" clip-path="url(#clipPath45)" stroke="none">ChangeParameters()</text>
+<image x="461" y="233" clip-path="url(#clipPath46)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="246" clip-path="url(#clipPath47)" stroke="none">BuildModel()</text>
+<image x="461" y="249" clip-path="url(#clipPath48)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="262" clip-path="url(#clipPath49)" stroke="none">GetModel()</text>
+<image x="461" y="265" clip-path="url(#clipPath50)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="278" clip-path="url(#clipPath51)" stroke="none">DiscretizeEdges()</text>
+<image x="461" y="281" clip-path="url(#clipPath52)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="294" clip-path="url(#clipPath53)" stroke="none">HealModel()</text>
+<image x="461" y="297" clip-path="url(#clipPath54)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="310" clip-path="url(#clipPath55)" stroke="none">PreProcessModel()</text>
+<image x="461" y="313" clip-path="url(#clipPath56)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="326" clip-path="url(#clipPath57)" stroke="none">DiscretizeFaces()</text>
+<image x="461" y="329" clip-path="url(#clipPath58)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="342" clip-path="url(#clipPath59)" stroke="none">PostProcessModel()</text>
+<image x="461" y="345" clip-path="url(#clipPath60)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="358" clip-path="url(#clipPath61)" stroke="none">SetModelBuilder()</text>
+<image x="461" y="361" clip-path="url(#clipPath62)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="374" clip-path="url(#clipPath63)" stroke="none">GetModelBuilder()</text>
+<image x="461" y="377" clip-path="url(#clipPath64)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="390" clip-path="url(#clipPath65)" stroke="none">SetEdgeDiscret()</text>
+<image x="461" y="393" clip-path="url(#clipPath66)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="406" clip-path="url(#clipPath67)" stroke="none">GetEdgeDiscret()</text>
+<image x="461" y="409" clip-path="url(#clipPath68)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="422" clip-path="url(#clipPath69)" stroke="none">SetModelHealer()</text>
+<image x="461" y="425" clip-path="url(#clipPath70)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="438" clip-path="url(#clipPath71)" stroke="none">GetModelHealer()</text>
+<image x="461" y="441" clip-path="url(#clipPath72)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="454" clip-path="url(#clipPath73)" stroke="none">SetPreProcessor()</text>
+<image x="461" y="457" clip-path="url(#clipPath74)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="470" clip-path="url(#clipPath75)" stroke="none">GetPreProcessor()</text>
+<image x="461" y="473" clip-path="url(#clipPath76)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="486" clip-path="url(#clipPath77)" stroke="none">SetFaceDiscret()</text>
+<image x="461" y="489" clip-path="url(#clipPath78)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="502" clip-path="url(#clipPath79)" stroke="none">GetFaceDiscret()</text>
+<image x="461" y="505" clip-path="url(#clipPath80)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="518" clip-path="url(#clipPath81)" stroke="none">SetPostProcessor()</text>
+<image x="461" y="521" clip-path="url(#clipPath82)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="534" clip-path="url(#clipPath83)" stroke="none">GetPostProcessor()</text>
+<image x="461" y="537" clip-path="url(#clipPath84)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="480" y="550" clip-path="url(#clipPath85)" stroke="none">Clean()</text>
+</g>
+<g stroke-linecap="butt" fill="rgb(173,127,168)" font-family="'Segoe UI'" stroke="rgb(173,127,168)" font-weight="bold" stroke-width="1.1">
+<line clip-path="url(#clipPath86)" fill="none" x1="457" x2="741" y1="71" y2="71"/>
+<rect x="133" y="227" clip-path="url(#clipPath87)" fill="rgb(131,122,133)" width="181" rx="2.5" opacity="0.2549" ry="2.5" height="86" stroke="none"/>
+<rect x="134" y="228" clip-path="url(#clipPath87)" fill="rgb(131,122,133)" width="181" rx="2.5" opacity="0.2549" ry="2.5" height="86" stroke="none"/>
+<rect x="132" y="226" clip-path="url(#clipPath88)" fill="white" width="181" rx="2.5" ry="2.5" height="86" stroke="none"/>
+<rect x="132" y="226" clip-path="url(#clipPath88)" fill="none" width="180" rx="2.5" ry="2.5" height="85"/>
+<image x="141" y="231" clip-path="url(#clipPath89)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX 0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO RK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="160" y="244" clip-path="url(#clipPath90)" fill="black" stroke="none" xml:space="preserve">IMeshTools_ModelBuilder</text>
+</g>
+<g stroke-width="1.1" font-size="11" font-family="'Segoe UI'" stroke-linecap="butt">
+<image x="137" y="259" clip-path="url(#clipPath91)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="266" clip-path="url(#clipPath92)" stroke="none">Perform(TopoDS_Shape : , </text>
+<text xml:space="preserve" x="156" y="279" clip-path="url(#clipPath92)" stroke="none">IMeshTools_Parameter : )</text>
+</g>
+<g stroke-linecap="butt" fill="rgb(173,127,168)" font-family="'Segoe UI'" stroke="rgb(173,127,168)" font-weight="bold" stroke-width="1.1">
+<line clip-path="url(#clipPath93)" fill="none" x1="133" x2="312" y1="252" y2="252"/>
+<rect x="133" y="335" clip-path="url(#clipPath94)" fill="rgb(131,122,133)" width="181" rx="2.5" opacity="0.2549" ry="2.5" height="86" stroke="none"/>
+<rect x="134" y="336" clip-path="url(#clipPath94)" fill="rgb(131,122,133)" width="181" rx="2.5" opacity="0.2549" ry="2.5" height="86" stroke="none"/>
+<rect x="132" y="334" clip-path="url(#clipPath95)" fill="white" width="181" rx="2.5" ry="2.5" height="86" stroke="none"/>
+<rect x="132" y="334" clip-path="url(#clipPath95)" fill="none" width="180" rx="2.5" ry="2.5" height="85"/>
+<image x="149" y="339" clip-path="url(#clipPath96)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX 0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO RK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="168" y="352" clip-path="url(#clipPath97)" fill="black" stroke="none" xml:space="preserve">IMeshTools_ModelAlgo</text>
+</g>
+<g stroke-width="1.1" font-size="11" font-family="'Segoe UI'" stroke-linecap="butt">
+<image x="137" y="367" clip-path="url(#clipPath98)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="374" clip-path="url(#clipPath99)" stroke="none">Perform(IMeshData_Model : , </text>
+<text xml:space="preserve" x="156" y="387" clip-path="url(#clipPath99)" stroke="none">IMeshTools_Parameters : )</text>
+</g>
+<g stroke-linecap="butt" fill="rgb(173,127,168)" font-family="'Segoe UI'" stroke="rgb(173,127,168)" font-weight="bold" stroke-width="1.1">
+<line clip-path="url(#clipPath100)" fill="none" x1="133" x2="312" y1="360" y2="360"/>
+<rect x="133" y="443" clip-path="url(#clipPath101)" fill="rgb(131,122,133)" width="181" rx="2.5" opacity="0.2549" ry="2.5" height="141" stroke="none"/>
+<rect x="134" y="444" clip-path="url(#clipPath101)" fill="rgb(131,122,133)" width="181" rx="2.5" opacity="0.2549" ry="2.5" height="141" stroke="none"/>
+<rect x="132" y="442" clip-path="url(#clipPath102)" fill="white" width="181" rx="2.5" ry="2.5" height="141" stroke="none"/>
+<rect x="132" y="442" clip-path="url(#clipPath102)" fill="none" width="180" rx="2.5" ry="2.5" height="140"/>
+<image x="163" y="447" clip-path="url(#clipPath103)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX 0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO RK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="182" y="460" clip-path="url(#clipPath104)" fill="black" stroke="none" xml:space="preserve">IMeshData_Model</text>
+</g>
+<g stroke-width="1.1" font-size="11" font-family="'Segoe UI'" stroke-linecap="butt">
+<image x="137" y="470" clip-path="url(#clipPath105)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="483" clip-path="url(#clipPath106)" stroke="none">GetMaxSize()</text>
+<image x="137" y="486" clip-path="url(#clipPath107)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="499" clip-path="url(#clipPath108)" stroke="none">FacesNb()</text>
+<image x="137" y="502" clip-path="url(#clipPath109)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="515" clip-path="url(#clipPath110)" stroke="none">AddFace()</text>
+<image x="137" y="518" clip-path="url(#clipPath111)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="531" clip-path="url(#clipPath112)" stroke="none">GetFace()</text>
+<image x="137" y="534" clip-path="url(#clipPath113)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="547" clip-path="url(#clipPath114)" stroke="none">EdgesNb()</text>
+<image x="137" y="550" clip-path="url(#clipPath115)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="563" clip-path="url(#clipPath116)" stroke="none">AddEdge()</text>
+<image x="137" y="566" clip-path="url(#clipPath117)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="156" y="579" clip-path="url(#clipPath118)" stroke="none">GetEdge()</text>
+</g>
+<g stroke-linecap="butt" fill="rgb(173,127,168)" font-family="'Segoe UI'" stroke="rgb(173,127,168)" font-weight="bold" stroke-width="1.1">
+<line clip-path="url(#clipPath119)" fill="none" x1="133" x2="312" y1="468" y2="468"/>
+<rect x="853" y="107" clip-path="url(#clipPath120)" fill="rgb(131,122,133)" width="168" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="854" y="108" clip-path="url(#clipPath120)" fill="rgb(131,122,133)" width="168" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="852" y="106" clip-path="url(#clipPath121)" fill="white" width="168" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="852" y="106" clip-path="url(#clipPath121)" fill="none" width="167" rx="2.5" ry="2.5" height="97"/>
+<image x="857" y="111" clip-path="url(#clipPath122)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX 0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO RK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="876" y="124" clip-path="url(#clipPath123)" fill="black" stroke="none" xml:space="preserve">IMeshTools_MeshBuilder</text>
+</g>
+<g stroke-width="1.1" font-size="11" font-family="'Segoe UI'" stroke-linecap="butt">
+<image x="857" y="134" clip-path="url(#clipPath124)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="876" y="147" clip-path="url(#clipPath125)" stroke="none">SetContext()</text>
+<image x="857" y="150" clip-path="url(#clipPath126)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="876" y="163" clip-path="url(#clipPath127)" stroke="none">GetContext()</text>
+<image x="857" y="166" clip-path="url(#clipPath128)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="876" y="179" clip-path="url(#clipPath129)" stroke="none">Perform()</text>
+</g>
+<g stroke-linecap="butt" fill="rgb(173,127,168)" font-family="'Segoe UI'" stroke="rgb(173,127,168)" font-weight="bold" stroke-width="1.1">
+<line clip-path="url(#clipPath130)" fill="none" x1="853" x2="1019" y1="132" y2="132"/>
+</g>
+<g stroke-linecap="butt" font-size="11" fill="rgb(136,136,136)" font-family="'Segoe UI'" stroke-dasharray="5,5" stroke="rgb(136,136,136)" stroke-width="1.1">
+<line clip-path="url(#clipPath131)" fill="none" x1="132" x2="84" y1="268" y2="268"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="84" x2="84" y1="268" y2="132"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="84" x2="132" y1="132" y2="132"/>
+<text x="59" y="190" clip-path="url(#clipPath132)" fill="black" stroke="none" xml:space="preserve"><<use>></text>
+<line clip-path="url(#clipPath133)" fill="none" x1="125" x2="132" y1="135" y2="132" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath133)" fill="none" x1="132" x2="125" y1="132" y2="129" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="132" x2="48" y1="370" y2="370"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="48" x2="48" y1="370" y2="90"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="48" x2="132" y1="90" y2="90"/>
+<text x="23" y="224" clip-path="url(#clipPath134)" fill="black" stroke="none" xml:space="preserve"><<use>></text>
+<line clip-path="url(#clipPath135)" fill="none" x1="125" x2="132" y1="93" y2="90" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath135)" fill="none" x1="132" x2="125" y1="90" y2="87" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="132" x2="48" y1="390" y2="390"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="48" x2="48" y1="390" y2="514"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="48" x2="132" y1="514" y2="514"/>
+<text x="23" y="449" clip-path="url(#clipPath136)" fill="black" stroke="none" xml:space="preserve"><<use>></text>
+<line clip-path="url(#clipPath137)" fill="none" x1="125" x2="132" y1="517" y2="514" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath137)" fill="none" x1="132" x2="125" y1="514" y2="511" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="456" x2="313" y1="125" y2="125" stroke-dasharray="none"/>
+<text x="364" y="142" clip-path="url(#clipPath138)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">caches</text>
+<text x="407" y="118" clip-path="url(#clipPath139)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">context[1]</text>
+<text x="312" y="118" clip-path="url(#clipPath140)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">parameters[1]</text>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath141)" points=" 456 125 450 128 444 125 450 122" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath141)" points=" 456 125 450 128 444 125 450 122"/>
+<line clip-path="url(#clipPath142)" fill="none" x1="320" x2="313" y1="122" y2="125" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath142)" fill="none" x1="313" x2="320" y1="125" y2="128" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="456" x2="313" y1="268" y2="268" stroke-dasharray="none"/>
+<text x="367" y="284" clip-path="url(#clipPath143)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">caches</text>
+<text x="410" y="264" clip-path="url(#clipPath144)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">context[1]</text>
+<text x="310" y="264" clip-path="url(#clipPath145)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">builder[1]</text>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath146)" points=" 456 268 450 271 444 268 450 265" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath146)" points=" 456 268 450 271 444 268 450 265"/>
+<line clip-path="url(#clipPath147)" fill="none" x1="320" x2="313" y1="265" y2="268" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath147)" fill="none" x1="313" x2="320" y1="268" y2="271" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="456" x2="313" y1="501" y2="501" stroke-dasharray="none"/>
+<text x="367" y="517" clip-path="url(#clipPath148)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">caches</text>
+<text x="410" y="497" clip-path="url(#clipPath149)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">context[1]</text>
+<text x="312" y="497" clip-path="url(#clipPath150)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">model[1]</text>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath151)" points=" 456 501 450 504 444 501 450 498" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath151)" points=" 456 501 450 504 444 501 450 498"/>
+<line clip-path="url(#clipPath152)" fill="none" x1="320" x2="313" y1="498" y2="501" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath152)" fill="none" x1="313" x2="320" y1="501" y2="504" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="456" x2="313" y1="376" y2="376" stroke-dasharray="none"/>
+<text x="367" y="392" clip-path="url(#clipPath153)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">caches</text>
+<text x="410" y="372" clip-path="url(#clipPath154)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">context[1]</text>
+<text x="318" y="372" clip-path="url(#clipPath155)" fill="black" stroke-dasharray="none" stroke="none" xml:space="preserve">algo[5]</text>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath156)" points=" 456 376 450 379 444 376 450 373" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath156)" points=" 456 376 450 379 444 376 450 373"/>
+<line clip-path="url(#clipPath157)" fill="none" x1="320" x2="313" y1="373" y2="376" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath157)" fill="none" x1="313" x2="320" y1="376" y2="379" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="852" x2="742" y1="160" y2="160"/>
+<text x="772" y="176" clip-path="url(#clipPath158)" fill="black" stroke="none" xml:space="preserve"><<use>></text>
+<line clip-path="url(#clipPath159)" fill="none" x1="749" x2="742" y1="157" y2="160" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath159)" fill="none" x1="742" x2="749" y1="160" y2="163" stroke-dasharray="none"/>
+</g>
+</g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ shape-rendering="auto"
+ width="889.54999"
+ text-rendering="auto"
+ contentScriptType="text/ecmascript"
+ color-interpolation="auto"
+ color-rendering="auto"
+ preserveAspectRatio="xMidYMid meet"
+ font-size="12"
+ viewBox="0 0 889.54999 913.09998"
+ image-rendering="auto"
+ stroke-miterlimit="10"
+ zoomAndPan="magnify"
+ version="1.0"
+ contentStyleType="text/css"
+ font-style="normal"
+ height="913.09998"
+ font-weight="normal"
+ id="svg2"
+ inkscape:version="0.48.0 r9654"
+ sodipodi:docname="modeling_algos_mesh_003.svg"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;font-family:Dialog">
+ <metadata
+ id="metadata1250">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1028"
+ id="namedview1248"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="0.68480471"
+ inkscape:cx="164.85375"
+ inkscape:cy="906.86367"
+ inkscape:window-x="1912"
+ inkscape:window-y="13"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g1054" />
+ <!--Generated by the Batik Graphics2D SVG Generator-->
+ <defs
+ id="genericDefs" />
+ <g
+ id="g5"
+ transform="translate(-9.45,-141.45)">
+ <defs
+ id="defs1">
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath1">
+ <path
+ d="m 214,141 149,0 0,102 -149,0 0,-102 z"
+ id="path9"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath2">
+ <path
+ d="m 214,141 147,0 0,100 -147,0 0,-100 z"
+ id="path12"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3">
+ <path
+ d="m 227,146 120,0 0,18 -120,0 0,-18 z"
+ id="path15"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath4">
+ <path
+ d="m 227,146 123,0 0,18 -123,0 0,-18 z"
+ id="path18"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath5">
+ <path
+ d="m 219,169 113,0 0,28 -113,0 0,-28 z"
+ id="path21"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath6">
+ <path
+ d="m 219,169 115,0 0,28 -115,0 0,-28 z"
+ id="path24"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath7">
+ <path
+ d="m 219,195 75,0 0,18 -75,0 0,-18 z"
+ id="path27"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath8">
+ <path
+ d="m 219,195 77,0 0,18 -77,0 0,-18 z"
+ id="path30"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath9">
+ <path
+ d="m 219,211 77,0 0,18 -77,0 0,-18 z"
+ id="path33"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath10">
+ <path
+ d="m 219,211 79,0 0,18 -79,0 0,-18 z"
+ id="path36"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath11">
+ <path
+ d="m 215,167 145,0 0,73 -145,0 0,-73 z"
+ id="path39"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath12">
+ <path
+ d="m 9,297 186,0 0,149 -186,0 0,-149 z"
+ id="path42"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath13">
+ <path
+ d="m 9,297 184,0 0,147 -184,0 0,-147 z"
+ id="path45"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath14">
+ <path
+ d="m 40,302 121,0 0,18 -121,0 0,-18 z"
+ id="path48"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath15">
+ <path
+ d="m 40,302 124,0 0,18 -124,0 0,-18 z"
+ id="path51"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath16">
+ <path
+ d="m 14,325 86,0 0,18 -86,0 0,-18 z"
+ id="path54"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath17">
+ <path
+ d="m 14,325 88,0 0,18 -88,0 0,-18 z"
+ id="path57"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath18">
+ <path
+ d="m 14,341 70,0 0,18 -70,0 0,-18 z"
+ id="path60"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath19">
+ <path
+ d="m 14,341 72,0 0,18 -72,0 0,-18 z"
+ id="path63"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath20">
+ <path
+ d="m 14,357 71,0 0,18 -71,0 0,-18 z"
+ id="path66"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath21">
+ <path
+ d="m 14,357 73,0 0,18 -73,0 0,-18 z"
+ id="path69"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath22">
+ <path
+ d="m 14,373 68,0 0,18 -68,0 0,-18 z"
+ id="path72"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath23">
+ <path
+ d="m 14,373 70,0 0,18 -70,0 0,-18 z"
+ id="path75"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath24">
+ <path
+ d="m 14,389 73,0 0,18 -73,0 0,-18 z"
+ id="path78"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath25">
+ <path
+ d="m 14,389 75,0 0,18 -75,0 0,-18 z"
+ id="path81"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath26">
+ <path
+ d="m 14,405 74,0 0,18 -74,0 0,-18 z"
+ id="path84"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath27">
+ <path
+ d="m 14,405 76,0 0,18 -76,0 0,-18 z"
+ id="path87"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath28">
+ <path
+ d="m 14,421 71,0 0,18 -71,0 0,-18 z"
+ id="path90"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath29">
+ <path
+ d="m 14,421 73,0 0,18 -73,0 0,-18 z"
+ id="path93"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath30">
+ <path
+ d="m 10,323 182,0 0,120 -182,0 0,-120 z"
+ id="path96"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath31">
+ <path
+ d="m 370,357 197,0 0,126 -197,0 0,-126 z"
+ id="path99"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath32">
+ <path
+ d="m 370,357 195,0 0,124 -195,0 0,-124 z"
+ id="path102"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath33">
+ <path
+ d="m 376,362 182,0 0,18 -182,0 0,-18 z"
+ id="path105"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath34">
+ <path
+ d="m 376,362 185,0 0,18 -185,0 0,-18 z"
+ id="path108"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath35">
+ <path
+ d="m 375,385 96,0 0,18 -96,0 0,-18 z"
+ id="path111"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath36">
+ <path
+ d="m 375,385 98,0 0,18 -98,0 0,-18 z"
+ id="path114"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath37">
+ <path
+ d="m 375,401 98,0 0,18 -98,0 0,-18 z"
+ id="path117"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath38">
+ <path
+ d="m 375,401 100,0 0,18 -100,0 0,-18 z"
+ id="path120"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath39">
+ <path
+ d="m 371,383 193,0 0,97 -193,0 0,-97 z"
+ id="path123"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath40">
+ <path
+ d="m 238,513 161,0 0,293 -161,0 0,-293 z"
+ id="path126"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath41">
+ <path
+ d="m 238,513 159,0 0,291 -159,0 0,-291 z"
+ id="path129"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath42">
+ <path
+ d="m 261,518 113,0 0,18 -113,0 0,-18 z"
+ id="path132"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath43">
+ <path
+ d="m 261,518 116,0 0,18 -116,0 0,-18 z"
+ id="path135"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath44">
+ <path
+ d="m 243,541 71,0 0,18 -71,0 0,-18 z"
+ id="path138"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath45">
+ <path
+ d="m 243,541 73,0 0,18 -73,0 0,-18 z"
+ id="path141"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath46">
+ <path
+ d="m 243,557 72,0 0,18 -72,0 0,-18 z"
+ id="path144"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath47">
+ <path
+ d="m 243,557 74,0 0,18 -74,0 0,-18 z"
+ id="path147"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath48">
+ <path
+ d="m 243,573 74,0 0,18 -74,0 0,-18 z"
+ id="path150"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath49">
+ <path
+ d="m 243,573 76,0 0,18 -76,0 0,-18 z"
+ id="path153"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath50">
+ <path
+ d="m 243,589 82,0 0,18 -82,0 0,-18 z"
+ id="path156"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath51">
+ <path
+ d="m 243,589 84,0 0,18 -84,0 0,-18 z"
+ id="path159"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath52">
+ <path
+ d="m 243,605 83,0 0,18 -83,0 0,-18 z"
+ id="path162"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath53">
+ <path
+ d="m 243,605 85,0 0,18 -85,0 0,-18 z"
+ id="path165"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath54">
+ <path
+ d="m 243,621 80,0 0,18 -80,0 0,-18 z"
+ id="path168"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath55">
+ <path
+ d="m 243,621 82,0 0,18 -82,0 0,-18 z"
+ id="path171"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath56">
+ <path
+ d="m 243,637 53,0 0,18 -53,0 0,-18 z"
+ id="path174"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath57">
+ <path
+ d="m 243,637 55,0 0,18 -55,0 0,-18 z"
+ id="path177"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath58">
+ <path
+ d="m 243,653 57,0 0,18 -57,0 0,-18 z"
+ id="path180"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath59">
+ <path
+ d="m 243,653 59,0 0,18 -59,0 0,-18 z"
+ id="path183"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath60">
+ <path
+ d="m 243,669 139,0 0,18 -139,0 0,-18 z"
+ id="path186"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath61">
+ <path
+ d="m 243,669 141,0 0,18 -141,0 0,-18 z"
+ id="path189"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath62">
+ <path
+ d="m 243,685 137,0 0,18 -137,0 0,-18 z"
+ id="path192"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath63">
+ <path
+ d="m 243,685 139,0 0,18 -139,0 0,-18 z"
+ id="path195"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath64">
+ <path
+ d="m 243,701 101,0 0,18 -101,0 0,-18 z"
+ id="path198"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath65">
+ <path
+ d="m 243,701 103,0 0,18 -103,0 0,-18 z"
+ id="path201"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath66">
+ <path
+ d="m 243,717 103,0 0,18 -103,0 0,-18 z"
+ id="path204"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath67">
+ <path
+ d="m 243,717 105,0 0,18 -105,0 0,-18 z"
+ id="path207"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath68">
+ <path
+ d="m 243,733 103,0 0,18 -103,0 0,-18 z"
+ id="path210"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath69">
+ <path
+ d="m 243,733 105,0 0,18 -105,0 0,-18 z"
+ id="path213"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath70">
+ <path
+ d="m 243,749 105,0 0,18 -105,0 0,-18 z"
+ id="path216"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath71">
+ <path
+ d="m 243,749 108,0 0,18 -108,0 0,-18 z"
+ id="path219"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath72">
+ <path
+ d="m 243,765 110,0 0,18 -110,0 0,-18 z"
+ id="path222"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath73">
+ <path
+ d="m 243,765 112,0 0,18 -112,0 0,-18 z"
+ id="path225"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath74">
+ <path
+ d="m 243,781 112,0 0,18 -112,0 0,-18 z"
+ id="path228"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath75">
+ <path
+ d="m 243,781 114,0 0,18 -114,0 0,-18 z"
+ id="path231"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath76">
+ <path
+ d="m 239,539 157,0 0,264 -157,0 0,-264 z"
+ id="path234"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath77">
+ <path
+ d="m 514,513 149,0 0,125 -149,0 0,-125 z"
+ id="path237"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath78">
+ <path
+ d="m 514,513 147,0 0,123 -147,0 0,-123 z"
+ id="path240"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath79">
+ <path
+ d="m 531,518 113,0 0,18 -113,0 0,-18 z"
+ id="path243"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath80">
+ <path
+ d="m 531,518 116,0 0,18 -116,0 0,-18 z"
+ id="path246"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath81">
+ <path
+ d="m 519,541 69,0 0,18 -69,0 0,-18 z"
+ id="path249"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath82">
+ <path
+ d="m 519,541 71,0 0,18 -71,0 0,-18 z"
+ id="path252"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath83">
+ <path
+ d="m 519,557 73,0 0,18 -73,0 0,-18 z"
+ id="path255"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath84">
+ <path
+ d="m 519,557 75,0 0,18 -75,0 0,-18 z"
+ id="path258"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath85">
+ <path
+ d="m 519,573 74,0 0,18 -74,0 0,-18 z"
+ id="path261"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath86">
+ <path
+ d="m 519,573 76,0 0,18 -76,0 0,-18 z"
+ id="path264"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath87">
+ <path
+ d="m 519,589 71,0 0,18 -71,0 0,-18 z"
+ id="path267"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath88">
+ <path
+ d="m 519,589 73,0 0,18 -73,0 0,-18 z"
+ id="path270"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath89">
+ <path
+ d="m 519,605 131,0 0,18 -131,0 0,-18 z"
+ id="path273"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath90">
+ <path
+ d="m 519,605 133,0 0,18 -133,0 0,-18 z"
+ id="path276"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath91">
+ <path
+ d="m 515,539 145,0 0,96 -145,0 0,-96 z"
+ id="path279"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath92">
+ <path
+ d="m 778,513 122,0 0,137 -122,0 0,-137 z"
+ id="path282"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath93">
+ <path
+ d="m 778,513 120,0 0,135 -120,0 0,-135 z"
+ id="path285"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath94">
+ <path
+ d="m 782,518 111,0 0,18 -111,0 0,-18 z"
+ id="path288"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath95">
+ <path
+ d="m 782,518 114,0 0,18 -114,0 0,-18 z"
+ id="path291"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath96">
+ <path
+ d="m 783,541 68,0 0,18 -68,0 0,-18 z"
+ id="path294"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath97">
+ <path
+ d="m 783,541 70,0 0,18 -70,0 0,-18 z"
+ id="path297"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath98">
+ <path
+ d="m 783,557 71,0 0,18 -71,0 0,-18 z"
+ id="path300"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath99">
+ <path
+ d="m 783,557 73,0 0,18 -73,0 0,-18 z"
+ id="path303"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath100">
+ <path
+ d="m 783,573 72,0 0,18 -72,0 0,-18 z"
+ id="path306"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath101">
+ <path
+ d="m 783,573 74,0 0,18 -74,0 0,-18 z"
+ id="path309"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath102">
+ <path
+ d="m 783,589 69,0 0,18 -69,0 0,-18 z"
+ id="path312"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath103">
+ <path
+ d="m 783,589 71,0 0,18 -71,0 0,-18 z"
+ id="path315"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath104">
+ <path
+ d="m 783,605 83,0 0,18 -83,0 0,-18 z"
+ id="path318"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath105">
+ <path
+ d="m 783,605 85,0 0,18 -85,0 0,-18 z"
+ id="path321"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath106">
+ <path
+ d="m 783,621 61,0 0,18 -61,0 0,-18 z"
+ id="path324"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath107">
+ <path
+ d="m 783,621 63,0 0,18 -63,0 0,-18 z"
+ id="path327"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath108">
+ <path
+ d="m 779,539 118,0 0,108 -118,0 0,-108 z"
+ id="path330"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath109">
+ <path
+ d="m 622,357 173,0 0,126 -173,0 0,-126 z"
+ id="path333"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath110">
+ <path
+ d="m 622,357 171,0 0,124 -171,0 0,-124 z"
+ id="path336"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath111">
+ <path
+ d="m 628,362 159,0 0,18 -159,0 0,-18 z"
+ id="path339"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath112">
+ <path
+ d="m 628,362 162,0 0,18 -162,0 0,-18 z"
+ id="path342"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath113">
+ <path
+ d="m 627,385 64,0 0,18 -64,0 0,-18 z"
+ id="path345"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath114">
+ <path
+ d="m 627,385 66,0 0,18 -66,0 0,-18 z"
+ id="path348"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath115">
+ <path
+ d="m 627,401 51,0 0,18 -51,0 0,-18 z"
+ id="path351"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath116">
+ <path
+ d="m 627,401 53,0 0,18 -53,0 0,-18 z"
+ id="path354"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath117">
+ <path
+ d="m 627,417 75,0 0,18 -75,0 0,-18 z"
+ id="path357"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath118">
+ <path
+ d="m 627,417 77,0 0,18 -77,0 0,-18 z"
+ id="path360"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath119">
+ <path
+ d="m 627,433 89,0 0,18 -89,0 0,-18 z"
+ id="path363"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath120">
+ <path
+ d="m 627,433 91,0 0,18 -91,0 0,-18 z"
+ id="path366"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath121">
+ <path
+ d="m 627,449 104,0 0,18 -104,0 0,-18 z"
+ id="path369"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath122">
+ <path
+ d="m 627,449 106,0 0,18 -106,0 0,-18 z"
+ id="path372"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath123">
+ <path
+ d="m 623,383 169,0 0,97 -169,0 0,-97 z"
+ id="path375"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath124">
+ <path
+ d="m 9,549 186,0 0,102 -186,0 0,-102 z"
+ id="path378"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath125">
+ <path
+ d="m 9,549 184,0 0,100 -184,0 0,-100 z"
+ id="path381"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath126">
+ <path
+ d="m 16,554 169,0 0,18 -169,0 0,-18 z"
+ id="path384"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath127">
+ <path
+ d="m 16,554 172,0 0,18 -172,0 0,-18 z"
+ id="path387"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath128">
+ <path
+ d="m 14,577 96,0 0,18 -96,0 0,-18 z"
+ id="path390"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath129">
+ <path
+ d="m 14,577 98,0 0,18 -98,0 0,-18 z"
+ id="path393"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath130">
+ <path
+ d="m 14,593 98,0 0,18 -98,0 0,-18 z"
+ id="path396"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath131">
+ <path
+ d="m 14,593 100,0 0,18 -100,0 0,-18 z"
+ id="path399"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath132">
+ <path
+ d="m 14,609 53,0 0,18 -53,0 0,-18 z"
+ id="path402"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath133">
+ <path
+ d="m 14,609 55,0 0,18 -55,0 0,-18 z"
+ id="path405"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath134">
+ <path
+ d="m 10,575 182,0 0,73 -182,0 0,-73 z"
+ id="path408"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath135">
+ <path
+ d="m 154,825 149,0 0,185 -149,0 0,-185 z"
+ id="path411"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath136">
+ <path
+ d="m 154,825 147,0 0,183 -147,0 0,-183 z"
+ id="path414"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath137">
+ <path
+ d="m 168,830 119,0 0,18 -119,0 0,-18 z"
+ id="path417"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath138">
+ <path
+ d="m 168,830 122,0 0,18 -122,0 0,-18 z"
+ id="path420"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath139">
+ <path
+ d="m 159,853 83,0 0,18 -83,0 0,-18 z"
+ id="path423"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath140">
+ <path
+ d="m 159,853 85,0 0,18 -85,0 0,-18 z"
+ id="path426"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath141">
+ <path
+ d="m 159,869 75,0 0,18 -75,0 0,-18 z"
+ id="path429"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath142">
+ <path
+ d="m 159,869 77,0 0,18 -77,0 0,-18 z"
+ id="path432"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath143">
+ <path
+ d="m 159,885 72,0 0,18 -72,0 0,-18 z"
+ id="path435"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath144">
+ <path
+ d="m 159,885 74,0 0,18 -74,0 0,-18 z"
+ id="path438"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath145">
+ <path
+ d="m 159,901 94,0 0,18 -94,0 0,-18 z"
+ id="path441"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath146">
+ <path
+ d="m 159,901 96,0 0,18 -96,0 0,-18 z"
+ id="path444"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath147">
+ <path
+ d="m 155,851 145,0 0,156 -145,0 0,-156 z"
+ id="path447"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath148">
+ <path
+ d="m 334,825 149,0 0,185 -149,0 0,-185 z"
+ id="path450"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath149">
+ <path
+ d="m 334,825 147,0 0,183 -147,0 0,-183 z"
+ id="path453"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath150">
+ <path
+ d="m 344,830 126,0 0,18 -126,0 0,-18 z"
+ id="path456"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath151">
+ <path
+ d="m 344,830 129,0 0,18 -129,0 0,-18 z"
+ id="path459"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath152">
+ <path
+ d="m 339,853 83,0 0,18 -83,0 0,-18 z"
+ id="path462"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath153">
+ <path
+ d="m 339,853 85,0 0,18 -85,0 0,-18 z"
+ id="path465"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath154">
+ <path
+ d="m 339,869 75,0 0,18 -75,0 0,-18 z"
+ id="path468"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath155">
+ <path
+ d="m 339,869 77,0 0,18 -77,0 0,-18 z"
+ id="path471"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath156">
+ <path
+ d="m 339,885 72,0 0,18 -72,0 0,-18 z"
+ id="path474"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath157">
+ <path
+ d="m 339,885 74,0 0,18 -74,0 0,-18 z"
+ id="path477"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath158">
+ <path
+ d="m 339,901 94,0 0,18 -94,0 0,-18 z"
+ id="path480"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath159">
+ <path
+ d="m 339,901 96,0 0,18 -96,0 0,-18 z"
+ id="path483"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath160">
+ <path
+ d="m 339,917 73,0 0,18 -73,0 0,-18 z"
+ id="path486"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath161">
+ <path
+ d="m 339,917 75,0 0,18 -75,0 0,-18 z"
+ id="path489"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath162">
+ <path
+ d="m 339,933 78,0 0,18 -78,0 0,-18 z"
+ id="path492"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath163">
+ <path
+ d="m 339,933 80,0 0,18 -80,0 0,-18 z"
+ id="path495"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath164">
+ <path
+ d="m 339,949 75,0 0,18 -75,0 0,-18 z"
+ id="path498"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath165">
+ <path
+ d="m 339,949 77,0 0,18 -77,0 0,-18 z"
+ id="path501"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath166">
+ <path
+ d="m 339,965 105,0 0,18 -105,0 0,-18 z"
+ id="path504"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath167">
+ <path
+ d="m 339,965 107,0 0,18 -107,0 0,-18 z"
+ id="path507"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath168">
+ <path
+ d="m 339,981 68,0 0,18 -68,0 0,-18 z"
+ id="path510"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath169">
+ <path
+ d="m 339,981 70,0 0,18 -70,0 0,-18 z"
+ id="path513"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath170">
+ <path
+ d="m 335,851 145,0 0,156 -145,0 0,-156 z"
+ id="path516"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath171">
+ <path
+ d="M 9,9 169,9 169,61 9,61 9,9 z"
+ id="path519"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath172">
+ <path
+ d="M 9,9 167,9 167,59 9,59 9,9 z"
+ id="path522"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath173">
+ <path
+ d="m 36,14 104,0 0,18 -104,0 0,-18 z"
+ id="path525"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath174">
+ <path
+ d="m 36,14 107,0 0,18 -107,0 0,-18 z"
+ id="path528"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath175">
+ <path
+ d="m 10,35 156,0 0,23 -156,0 0,-23 z"
+ id="path531"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath176">
+ <path
+ d="m -1,-1 923,0 0,1080 -923,0 0,-1080 z"
+ id="path534"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath177">
+ <path
+ d="m 283,239 11,0 0,11 -11,0 0,-11 z"
+ id="path537"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath178">
+ <path
+ d="m 463,479 11,0 0,11 -11,0 0,-11 z"
+ id="path540"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath179">
+ <path
+ d="m 702,479 11,0 0,11 -11,0 0,-11 z"
+ id="path543"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath180">
+ <path
+ d="m 99,647 11,0 0,11 -11,0 0,-11 z"
+ id="path546"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath181">
+ <path
+ d="m 190,765 23,0 0,15 -23,0 0,-15 z"
+ id="path549"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath182">
+ <path
+ d="m 190,717 42,0 0,15 -42,0 0,-15 z"
+ id="path552"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath183">
+ <path
+ d="m 190,813 43,0 0,15 -43,0 0,-15 z"
+ id="path555"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath184">
+ <path
+ d="m 175,818 9,0 0,10 -9,0 0,-10 z"
+ id="path558"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath185">
+ <path
+ d="m 430,765 23,0 0,15 -23,0 0,-15 z"
+ id="path561"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath186">
+ <path
+ d="m 406,717 42,0 0,15 -42,0 0,-15 z"
+ id="path564"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath187">
+ <path
+ d="m 394,813 49,0 0,15 -49,0 0,-15 z"
+ id="path567"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath188">
+ <path
+ d="m 449,818 9,0 0,10 -9,0 0,-10 z"
+ id="path570"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath189">
+ <path
+ d="m 778,861 57,0 0,15 -57,0 0,-15 z"
+ id="path573"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath190">
+ <path
+ d="m 478,885 50,0 0,15 -50,0 0,-15 z"
+ id="path576"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath191">
+ <path
+ d="m 850,651 37,0 0,15 -37,0 0,-15 z"
+ id="path579"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath192">
+ <path
+ d="m 834,646 9,0 0,10 -9,0 0,-10 z"
+ id="path582"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath193">
+ <path
+ d="m 704,582 23,0 0,15 -23,0 0,-15 z"
+ id="path585"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath194">
+ <path
+ d="m 742,567 37,0 0,15 -37,0 0,-15 z"
+ id="path588"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath195">
+ <path
+ d="m 663,566 49,0 0,15 -49,0 0,-15 z"
+ id="path591"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath196">
+ <path
+ d="m 659,578 10,0 0,9 -10,0 0,-9 z"
+ id="path594"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath197">
+ <path
+ d="m 444,583 23,0 0,15 -23,0 0,-15 z"
+ id="path597"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath198">
+ <path
+ d="m 478,565 38,0 0,15 -38,0 0,-15 z"
+ id="path600"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath199">
+ <path
+ d="m 393,564 53,0 0,15 -53,0 0,-15 z"
+ id="path603"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath200">
+ <path
+ d="m 395,578 10,0 0,9 -10,0 0,-9 z"
+ id="path606"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath201">
+ <path
+ d="m 265,465 23,0 0,15 -23,0 0,-15 z"
+ id="path609"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath202">
+ <path
+ d="m 190,369 48,0 0,15 -48,0 0,-15 z"
+ id="path612"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath203">
+ <path
+ d="m 249,502 41,0 0,15 -41,0 0,-15 z"
+ id="path615"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath204">
+ <path
+ d="m 287,506 9,0 0,10 -9,0 0,-10 z"
+ id="path618"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath205">
+ <path
+ d="m 683,317 23,0 0,15 -23,0 0,-15 z"
+ id="path621"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath206">
+ <path
+ d="m 190,321 48,0 0,15 -48,0 0,-15 z"
+ id="path624"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath207">
+ <path
+ d="m 865,497 36,0 0,15 -36,0 0,-15 z"
+ id="path627"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath208">
+ <path
+ d="m 859,506 9,0 0,10 -9,0 0,-10 z"
+ id="path630"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ </defs>
+ <g
+ font-weight="bold"
+ stroke-miterlimit="0"
+ id="g632"
+ style="font-weight:bold;fill:#837a85;stroke:#837a85;stroke-width:0;stroke-linejoin:round;stroke-miterlimit:0;font-family:Segoe UI">
+ <rect
+ x="216"
+ y="143"
+ clip-path="url(#clipPath1)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="98"
+ id="rect634"
+ style="opacity:0.25489999;stroke:none" />
+ <rect
+ x="217"
+ y="144"
+ clip-path="url(#clipPath1)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="98"
+ id="rect636"
+ style="opacity:0.25489999;stroke:none" />
+ <rect
+ x="215"
+ y="142"
+ clip-path="url(#clipPath2)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="98"
+ id="rect638"
+ style="fill:#ffffff;stroke:none" />
+ </g>
+ <g
+ font-weight="bold"
+ id="g640"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <rect
+ x="215"
+ y="142"
+ clip-path="url(#clipPath2)"
+ width="144"
+ rx="2.5"
+ ry="2.5"
+ height="97"
+ id="rect642"
+ style="fill:none" />
+ <image
+ x="228"
+ y="147"
+ clip-path="url(#clipPath3)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC
+BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu
+rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF
+x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG
+g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL
+Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX
+0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO
+RK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image644" />
+ <text
+ x="247"
+ y="160"
+ clip-path="url(#clipPath4)"
+ xml:space="preserve"
+ id="text646"
+ style="fill:#000000;stroke:none">IMeshData_Shape</text>
+ </g>
+ <g
+ font-size="11"
+ id="g648"
+ style="font-size:11px;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <image
+ x="220"
+ y="175"
+ clip-path="url(#clipPath5)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVR42mNgGAWM
+ICJr1qH/pGqclmYH1ssCIn7/+ccwI8OeaM0ZMw/C2WADfgIN+At0Q8rUfRDR/zC3
+obGBYE62E8Ov339RDfjx6w/DHyjdne2G0+aSqbsZ/gAN/I5kABOI+P4TaMA/EA2R
+EGSBYlYELcfBwLCq2JWBk5mBYWWRK8N/IIC74BvQ5l9A7rfff8AG/P4PcTmIYIR5
+A6iRrckLbvOvum0IL3z/9Res6fuPPwyRTetRnH20LRCFn2OgwzDlwhVI8AABxACg
+zaBAXNkQyMCIFmgggGwzuhjYAFCoupWvRDgXKZVcmRAOtxnZFSAAcgnYgKsTIxhx
+Bv2E8P8wxSBgJ63McOjpXdRoJARgAYYtEBmJTX2gAMNmAAC8fn+eU+XlTAAAAABJRU5ErkJggg=="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image650" />
+ <text
+ xml:space="preserve"
+ x="239"
+ y="182"
+ clip-path="url(#clipPath6)"
+ id="text652"
+ style="stroke:none">myShape : </text>
+ <text
+ xml:space="preserve"
+ x="239"
+ y="195"
+ clip-path="url(#clipPath6)"
+ id="text654"
+ style="stroke:none">TopoDS_Shape [1]</text>
+ <image
+ x="220"
+ y="196"
+ clip-path="url(#clipPath7)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image656" />
+ <text
+ xml:space="preserve"
+ x="239"
+ y="209"
+ clip-path="url(#clipPath8)"
+ id="text658"
+ style="stroke:none">SetShape()</text>
+ <image
+ x="220"
+ y="212"
+ clip-path="url(#clipPath9)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image660" />
+ <text
+ xml:space="preserve"
+ x="239"
+ y="225"
+ clip-path="url(#clipPath10)"
+ id="text662"
+ style="stroke:none">GetShape()</text>
+ </g>
+ <g
+ font-weight="bold"
+ id="g664"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath11)"
+ x1="216"
+ x2="359"
+ y1="168"
+ y2="168"
+ id="line666"
+ style="fill:none" />
+ <rect
+ x="11"
+ y="299"
+ clip-path="url(#clipPath12)"
+ width="182"
+ rx="2.5"
+ ry="2.5"
+ height="145"
+ id="rect668"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="12"
+ y="300"
+ clip-path="url(#clipPath12)"
+ width="182"
+ rx="2.5"
+ ry="2.5"
+ height="145"
+ id="rect670"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="10"
+ y="298"
+ clip-path="url(#clipPath13)"
+ width="182"
+ rx="2.5"
+ ry="2.5"
+ height="145"
+ id="rect672"
+ style="fill:#ffffff;stroke:none" />
+ <rect
+ x="10"
+ y="298"
+ clip-path="url(#clipPath13)"
+ width="181"
+ rx="2.5"
+ ry="2.5"
+ height="144"
+ id="rect674"
+ style="fill:none" />
+ <image
+ x="41"
+ y="303"
+ clip-path="url(#clipPath14)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC
+BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu
+rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF
+x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG
+g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL
+Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX
+0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO
+RK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image676" />
+ <text
+ x="60"
+ y="316"
+ clip-path="url(#clipPath15)"
+ xml:space="preserve"
+ id="text678"
+ style="fill:#000000;stroke:none">IMeshData_Model</text>
+ </g>
+ <g
+ font-size="11"
+ id="g680"
+ style="font-size:11px;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <image
+ x="15"
+ y="326"
+ clip-path="url(#clipPath16)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image682" />
+ <text
+ xml:space="preserve"
+ x="34"
+ y="339"
+ clip-path="url(#clipPath17)"
+ id="text684"
+ style="stroke:none">GetMaxSize()</text>
+ <image
+ x="15"
+ y="342"
+ clip-path="url(#clipPath18)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image686" />
+ <text
+ xml:space="preserve"
+ x="34"
+ y="355"
+ clip-path="url(#clipPath19)"
+ id="text688"
+ style="stroke:none">FacesNb()</text>
+ <image
+ x="15"
+ y="358"
+ clip-path="url(#clipPath20)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image690" />
+ <text
+ xml:space="preserve"
+ x="34"
+ y="371"
+ clip-path="url(#clipPath21)"
+ id="text692"
+ style="stroke:none">AddFace()</text>
+ <image
+ x="15"
+ y="374"
+ clip-path="url(#clipPath22)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image694" />
+ <text
+ xml:space="preserve"
+ x="34"
+ y="387"
+ clip-path="url(#clipPath23)"
+ id="text696"
+ style="stroke:none">GetFace()</text>
+ <image
+ x="15"
+ y="390"
+ clip-path="url(#clipPath24)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image698" />
+ <text
+ xml:space="preserve"
+ x="34"
+ y="403"
+ clip-path="url(#clipPath25)"
+ id="text700"
+ style="stroke:none">EdgesNb()</text>
+ <image
+ x="15"
+ y="406"
+ clip-path="url(#clipPath26)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image702" />
+ <text
+ xml:space="preserve"
+ x="34"
+ y="419"
+ clip-path="url(#clipPath27)"
+ id="text704"
+ style="stroke:none">AddEdge()</text>
+ <image
+ x="15"
+ y="422"
+ clip-path="url(#clipPath28)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image706" />
+ <text
+ xml:space="preserve"
+ x="34"
+ y="435"
+ clip-path="url(#clipPath29)"
+ id="text708"
+ style="stroke:none">GetEdge()</text>
+ </g>
+ <g
+ font-weight="bold"
+ id="g710"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath30)"
+ x1="11"
+ x2="191"
+ y1="324"
+ y2="324"
+ id="line712"
+ style="fill:none" />
+ <rect
+ x="372"
+ y="359"
+ clip-path="url(#clipPath31)"
+ width="193"
+ rx="2.5"
+ ry="2.5"
+ height="122"
+ id="rect714"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="373"
+ y="360"
+ clip-path="url(#clipPath31)"
+ width="193"
+ rx="2.5"
+ ry="2.5"
+ height="122"
+ id="rect716"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="371"
+ y="358"
+ clip-path="url(#clipPath32)"
+ width="193"
+ rx="2.5"
+ ry="2.5"
+ height="122"
+ id="rect718"
+ style="fill:#ffffff;stroke:none" />
+ <rect
+ x="371"
+ y="358"
+ clip-path="url(#clipPath32)"
+ width="192"
+ rx="2.5"
+ ry="2.5"
+ height="121"
+ id="rect720"
+ style="fill:none" />
+ <image
+ x="377"
+ y="363"
+ clip-path="url(#clipPath33)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC
+BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu
+rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF
+x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG
+g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL
+Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX
+0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO
+RK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image722" />
+ <text
+ x="396"
+ y="376"
+ clip-path="url(#clipPath34)"
+ xml:space="preserve"
+ id="text724"
+ style="fill:#000000;stroke:none">IMeshData_TessellatedShape</text>
+ </g>
+ <g
+ font-size="11"
+ id="g726"
+ style="font-size:11px;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <image
+ x="376"
+ y="386"
+ clip-path="url(#clipPath35)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image728" />
+ <text
+ xml:space="preserve"
+ x="395"
+ y="399"
+ clip-path="url(#clipPath36)"
+ id="text730"
+ style="stroke:none">SetDeflection()</text>
+ <image
+ x="376"
+ y="402"
+ clip-path="url(#clipPath37)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image732" />
+ <text
+ xml:space="preserve"
+ x="395"
+ y="415"
+ clip-path="url(#clipPath38)"
+ id="text734"
+ style="stroke:none">GetDeflection()</text>
+ </g>
+ <g
+ font-weight="bold"
+ id="g736"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath39)"
+ x1="372"
+ x2="563"
+ y1="384"
+ y2="384"
+ id="line738"
+ style="fill:none" />
+ <rect
+ x="240"
+ y="515"
+ clip-path="url(#clipPath40)"
+ width="157"
+ rx="2.5"
+ ry="2.5"
+ height="289"
+ id="rect740"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="241"
+ y="516"
+ clip-path="url(#clipPath40)"
+ width="157"
+ rx="2.5"
+ ry="2.5"
+ height="289"
+ id="rect742"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="239"
+ y="514"
+ clip-path="url(#clipPath41)"
+ width="157"
+ rx="2.5"
+ ry="2.5"
+ height="289"
+ id="rect744"
+ style="fill:#ffffff;stroke:none" />
+ <rect
+ x="239"
+ y="514"
+ clip-path="url(#clipPath41)"
+ width="156"
+ rx="2.5"
+ ry="2.5"
+ height="288"
+ id="rect746"
+ style="fill:none" />
+ <image
+ x="262"
+ y="519"
+ clip-path="url(#clipPath42)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC
+BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu
+rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF
+x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG
+g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL
+Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX
+0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO
+RK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image748" />
+ <text
+ x="281"
+ y="532"
+ clip-path="url(#clipPath43)"
+ xml:space="preserve"
+ id="text750"
+ style="fill:#000000;stroke:none">IMeshData_Edge</text>
+ </g>
+ <g
+ font-size="11"
+ id="g752"
+ style="font-size:11px;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <image
+ x="244"
+ y="542"
+ clip-path="url(#clipPath44)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image754" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="555"
+ clip-path="url(#clipPath45)"
+ id="text756"
+ style="stroke:none">GetEdge()</text>
+ <image
+ x="244"
+ y="558"
+ clip-path="url(#clipPath46)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image758" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="571"
+ clip-path="url(#clipPath47)"
+ id="text760"
+ style="stroke:none">SetCurve()</text>
+ <image
+ x="244"
+ y="574"
+ clip-path="url(#clipPath48)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image762" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="587"
+ clip-path="url(#clipPath49)"
+ id="text764"
+ style="stroke:none">GetCurve()</text>
+ <image
+ x="244"
+ y="590"
+ clip-path="url(#clipPath50)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image766" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="603"
+ clip-path="url(#clipPath51)"
+ id="text768"
+ style="stroke:none">PCurvesNb()</text>
+ <image
+ x="244"
+ y="606"
+ clip-path="url(#clipPath52)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image770" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="619"
+ clip-path="url(#clipPath53)"
+ id="text772"
+ style="stroke:none">AddPCurve()</text>
+ <image
+ x="244"
+ y="622"
+ clip-path="url(#clipPath54)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image774" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="635"
+ clip-path="url(#clipPath55)"
+ id="text776"
+ style="stroke:none">GetPCurve()</text>
+ <image
+ x="244"
+ y="638"
+ clip-path="url(#clipPath56)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image778" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="651"
+ clip-path="url(#clipPath57)"
+ id="text780"
+ style="stroke:none">Clear()</text>
+ <image
+ x="244"
+ y="654"
+ clip-path="url(#clipPath58)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image782" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="667"
+ clip-path="url(#clipPath59)"
+ id="text784"
+ style="stroke:none">IsFree()</text>
+ <image
+ x="244"
+ y="670"
+ clip-path="url(#clipPath60)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image786" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="683"
+ clip-path="url(#clipPath61)"
+ id="text788"
+ style="stroke:none">GetAngularDeflection()</text>
+ <image
+ x="244"
+ y="686"
+ clip-path="url(#clipPath62)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image790" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="699"
+ clip-path="url(#clipPath63)"
+ id="text792"
+ style="stroke:none">SetAngularDeflection()</text>
+ <image
+ x="244"
+ y="702"
+ clip-path="url(#clipPath64)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image794" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="715"
+ clip-path="url(#clipPath65)"
+ id="text796"
+ style="stroke:none">SetSameParam()</text>
+ <image
+ x="244"
+ y="718"
+ clip-path="url(#clipPath66)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image798" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="731"
+ clip-path="url(#clipPath67)"
+ id="text800"
+ style="stroke:none">GetSameParam()</text>
+ <image
+ x="244"
+ y="734"
+ clip-path="url(#clipPath68)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image802" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="747"
+ clip-path="url(#clipPath69)"
+ id="text804"
+ style="stroke:none">SetSameRange()</text>
+ <image
+ x="244"
+ y="750"
+ clip-path="url(#clipPath70)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image806" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="763"
+ clip-path="url(#clipPath71)"
+ id="text808"
+ style="stroke:none">GetSameRange()</text>
+ <image
+ x="244"
+ y="766"
+ clip-path="url(#clipPath72)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image810" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="779"
+ clip-path="url(#clipPath73)"
+ id="text812"
+ style="stroke:none">SetDegenerated()</text>
+ <image
+ x="244"
+ y="782"
+ clip-path="url(#clipPath74)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image814" />
+ <text
+ xml:space="preserve"
+ x="263"
+ y="795"
+ clip-path="url(#clipPath75)"
+ id="text816"
+ style="stroke:none">GetDegenerated()</text>
+ </g>
+ <g
+ font-weight="bold"
+ id="g818"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath76)"
+ x1="240"
+ x2="395"
+ y1="540"
+ y2="540"
+ id="line820"
+ style="fill:none" />
+ <rect
+ x="516"
+ y="515"
+ clip-path="url(#clipPath77)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="121"
+ id="rect822"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="517"
+ y="516"
+ clip-path="url(#clipPath77)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="121"
+ id="rect824"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="515"
+ y="514"
+ clip-path="url(#clipPath78)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="121"
+ id="rect826"
+ style="fill:#ffffff;stroke:none" />
+ <rect
+ x="515"
+ y="514"
+ clip-path="url(#clipPath78)"
+ width="144"
+ rx="2.5"
+ ry="2.5"
+ height="120"
+ id="rect828"
+ style="fill:none" />
+ <image
+ x="532"
+ y="519"
+ clip-path="url(#clipPath79)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC
+BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu
+rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF
+x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG
+g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL
+Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX
+0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO
+RK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image830" />
+ <text
+ x="551"
+ y="532"
+ clip-path="url(#clipPath80)"
+ xml:space="preserve"
+ id="text832"
+ style="fill:#000000;stroke:none">IMeshData_Wire</text>
+ </g>
+ <g
+ font-size="11"
+ id="g834"
+ style="font-size:11px;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <image
+ x="520"
+ y="542"
+ clip-path="url(#clipPath81)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image836" />
+ <text
+ xml:space="preserve"
+ x="539"
+ y="555"
+ clip-path="url(#clipPath82)"
+ id="text838"
+ style="stroke:none">GetWire()</text>
+ <image
+ x="520"
+ y="558"
+ clip-path="url(#clipPath83)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image840" />
+ <text
+ xml:space="preserve"
+ x="539"
+ y="571"
+ clip-path="url(#clipPath84)"
+ id="text842"
+ style="stroke:none">EdgesNb()</text>
+ <image
+ x="520"
+ y="574"
+ clip-path="url(#clipPath85)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image844" />
+ <text
+ xml:space="preserve"
+ x="539"
+ y="587"
+ clip-path="url(#clipPath86)"
+ id="text846"
+ style="stroke:none">AddEdge()</text>
+ <image
+ x="520"
+ y="590"
+ clip-path="url(#clipPath87)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image848" />
+ <text
+ xml:space="preserve"
+ x="539"
+ y="603"
+ clip-path="url(#clipPath88)"
+ id="text850"
+ style="stroke:none">GetEdge()</text>
+ <image
+ x="520"
+ y="606"
+ clip-path="url(#clipPath89)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image852" />
+ <text
+ xml:space="preserve"
+ x="539"
+ y="619"
+ clip-path="url(#clipPath90)"
+ id="text854"
+ style="stroke:none">GetEdgeOrientation()</text>
+ </g>
+ <g
+ font-weight="bold"
+ id="g856"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath91)"
+ x1="516"
+ x2="659"
+ y1="540"
+ y2="540"
+ id="line858"
+ style="fill:none" />
+ <rect
+ x="780"
+ y="515"
+ clip-path="url(#clipPath92)"
+ width="118"
+ rx="2.5"
+ ry="2.5"
+ height="133"
+ id="rect860"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="781"
+ y="516"
+ clip-path="url(#clipPath92)"
+ width="118"
+ rx="2.5"
+ ry="2.5"
+ height="133"
+ id="rect862"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="779"
+ y="514"
+ clip-path="url(#clipPath93)"
+ width="118"
+ rx="2.5"
+ ry="2.5"
+ height="133"
+ id="rect864"
+ style="fill:#ffffff;stroke:none" />
+ <rect
+ x="779"
+ y="514"
+ clip-path="url(#clipPath93)"
+ width="117"
+ rx="2.5"
+ ry="2.5"
+ height="132"
+ id="rect866"
+ style="fill:none" />
+ <image
+ x="783"
+ y="519"
+ clip-path="url(#clipPath94)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC
+BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu
+rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF
+x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG
+g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL
+Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX
+0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO
+RK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image868" />
+ <text
+ x="802"
+ y="532"
+ clip-path="url(#clipPath95)"
+ xml:space="preserve"
+ id="text870"
+ style="fill:#000000;stroke:none">IMeshData_Face</text>
+ </g>
+ <g
+ font-size="11"
+ id="g872"
+ style="font-size:11px;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <image
+ x="784"
+ y="542"
+ clip-path="url(#clipPath96)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image874" />
+ <text
+ xml:space="preserve"
+ x="803"
+ y="555"
+ clip-path="url(#clipPath97)"
+ id="text876"
+ style="stroke:none">GetFace()</text>
+ <image
+ x="784"
+ y="558"
+ clip-path="url(#clipPath98)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image878" />
+ <text
+ xml:space="preserve"
+ x="803"
+ y="571"
+ clip-path="url(#clipPath99)"
+ id="text880"
+ style="stroke:none">WiresNb()</text>
+ <image
+ x="784"
+ y="574"
+ clip-path="url(#clipPath100)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image882" />
+ <text
+ xml:space="preserve"
+ x="803"
+ y="587"
+ clip-path="url(#clipPath101)"
+ id="text884"
+ style="stroke:none">AddWire()</text>
+ <image
+ x="784"
+ y="590"
+ clip-path="url(#clipPath102)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image886" />
+ <text
+ xml:space="preserve"
+ x="803"
+ y="603"
+ clip-path="url(#clipPath103)"
+ id="text888"
+ style="stroke:none">GetWire()</text>
+ <image
+ x="784"
+ y="606"
+ clip-path="url(#clipPath104)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image890" />
+ <text
+ xml:space="preserve"
+ x="803"
+ y="619"
+ clip-path="url(#clipPath105)"
+ id="text892"
+ style="stroke:none">GetSurface()</text>
+ <image
+ x="784"
+ y="622"
+ clip-path="url(#clipPath106)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image894" />
+ <text
+ xml:space="preserve"
+ x="803"
+ y="635"
+ clip-path="url(#clipPath107)"
+ id="text896"
+ style="stroke:none">IsValid()</text>
+ </g>
+ <g
+ font-weight="bold"
+ id="g898"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath108)"
+ x1="780"
+ x2="896"
+ y1="540"
+ y2="540"
+ id="line900"
+ style="fill:none" />
+ <rect
+ x="624"
+ y="359"
+ clip-path="url(#clipPath109)"
+ width="169"
+ rx="2.5"
+ ry="2.5"
+ height="122"
+ id="rect902"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="625"
+ y="360"
+ clip-path="url(#clipPath109)"
+ width="169"
+ rx="2.5"
+ ry="2.5"
+ height="122"
+ id="rect904"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="623"
+ y="358"
+ clip-path="url(#clipPath110)"
+ width="169"
+ rx="2.5"
+ ry="2.5"
+ height="122"
+ id="rect906"
+ style="fill:#ffffff;stroke:none" />
+ <rect
+ x="623"
+ y="358"
+ clip-path="url(#clipPath110)"
+ width="168"
+ rx="2.5"
+ ry="2.5"
+ height="121"
+ id="rect908"
+ style="fill:none" />
+ <image
+ x="629"
+ y="363"
+ clip-path="url(#clipPath111)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC
+BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu
+rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF
+x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG
+g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL
+Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX
+0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO
+RK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image910" />
+ <text
+ x="648"
+ y="376"
+ clip-path="url(#clipPath112)"
+ xml:space="preserve"
+ id="text912"
+ style="fill:#000000;stroke:none">IMeshData_StatusOwner</text>
+ </g>
+ <g
+ font-size="11"
+ id="g914"
+ style="font-size:11px;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <image
+ x="628"
+ y="386"
+ clip-path="url(#clipPath113)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image916" />
+ <text
+ xml:space="preserve"
+ x="647"
+ y="399"
+ clip-path="url(#clipPath114)"
+ id="text918"
+ style="stroke:none">IsEqual()</text>
+ <image
+ x="628"
+ y="402"
+ clip-path="url(#clipPath115)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image920" />
+ <text
+ xml:space="preserve"
+ x="647"
+ y="415"
+ clip-path="url(#clipPath116)"
+ id="text922"
+ style="stroke:none">IsSet()</text>
+ <image
+ x="628"
+ y="418"
+ clip-path="url(#clipPath117)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image924" />
+ <text
+ xml:space="preserve"
+ x="647"
+ y="431"
+ clip-path="url(#clipPath118)"
+ id="text926"
+ style="stroke:none">SetStatus()</text>
+ <image
+ x="628"
+ y="434"
+ clip-path="url(#clipPath119)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image928" />
+ <text
+ xml:space="preserve"
+ x="647"
+ y="447"
+ clip-path="url(#clipPath120)"
+ id="text930"
+ style="stroke:none">UnsetStatus()</text>
+ <image
+ x="628"
+ y="450"
+ clip-path="url(#clipPath121)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image932" />
+ <text
+ xml:space="preserve"
+ x="647"
+ y="463"
+ clip-path="url(#clipPath122)"
+ id="text934"
+ style="stroke:none">GetStatusMask()</text>
+ </g>
+ <g
+ font-weight="bold"
+ id="g936"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath123)"
+ x1="624"
+ x2="791"
+ y1="384"
+ y2="384"
+ id="line938"
+ style="fill:none" />
+ <rect
+ x="11"
+ y="551"
+ clip-path="url(#clipPath124)"
+ width="182"
+ rx="2.5"
+ ry="2.5"
+ height="98"
+ id="rect940"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="12"
+ y="552"
+ clip-path="url(#clipPath124)"
+ width="182"
+ rx="2.5"
+ ry="2.5"
+ height="98"
+ id="rect942"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="10"
+ y="550"
+ clip-path="url(#clipPath125)"
+ width="182"
+ rx="2.5"
+ ry="2.5"
+ height="98"
+ id="rect944"
+ style="fill:#ffffff;stroke:none" />
+ <rect
+ x="10"
+ y="550"
+ clip-path="url(#clipPath125)"
+ width="181"
+ rx="2.5"
+ ry="2.5"
+ height="97"
+ id="rect946"
+ style="fill:none" />
+ <image
+ x="17"
+ y="555"
+ clip-path="url(#clipPath126)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC
+BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu
+rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF
+x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG
+g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL
+Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX
+0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO
+RK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image948" />
+ <text
+ x="36"
+ y="568"
+ clip-path="url(#clipPath127)"
+ xml:space="preserve"
+ id="text950"
+ style="fill:#000000;stroke:none">IMeshData_ParametersList</text>
+ </g>
+ <g
+ font-size="11"
+ id="g952"
+ style="font-size:11px;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <image
+ x="15"
+ y="578"
+ clip-path="url(#clipPath128)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image954" />
+ <text
+ xml:space="preserve"
+ x="34"
+ y="591"
+ clip-path="url(#clipPath129)"
+ id="text956"
+ style="stroke:none">GetParameter()</text>
+ <image
+ x="15"
+ y="594"
+ clip-path="url(#clipPath130)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image958" />
+ <text
+ xml:space="preserve"
+ x="34"
+ y="607"
+ clip-path="url(#clipPath131)"
+ id="text960"
+ style="stroke:none">ParametersNb()</text>
+ <image
+ x="15"
+ y="610"
+ clip-path="url(#clipPath132)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image962" />
+ <text
+ xml:space="preserve"
+ x="34"
+ y="623"
+ clip-path="url(#clipPath133)"
+ id="text964"
+ style="stroke:none">Clear()</text>
+ </g>
+ <g
+ font-weight="bold"
+ id="g966"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath134)"
+ x1="11"
+ x2="191"
+ y1="576"
+ y2="576"
+ id="line968"
+ style="fill:none" />
+ <rect
+ x="156"
+ y="827"
+ clip-path="url(#clipPath135)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="181"
+ id="rect970"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="157"
+ y="828"
+ clip-path="url(#clipPath135)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="181"
+ id="rect972"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="155"
+ y="826"
+ clip-path="url(#clipPath136)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="181"
+ id="rect974"
+ style="fill:#ffffff;stroke:none" />
+ <rect
+ x="155"
+ y="826"
+ clip-path="url(#clipPath136)"
+ width="144"
+ rx="2.5"
+ ry="2.5"
+ height="180"
+ id="rect976"
+ style="fill:none" />
+ <image
+ x="169"
+ y="831"
+ clip-path="url(#clipPath137)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC
+BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu
+rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF
+x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG
+g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL
+Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX
+0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO
+RK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image978" />
+ <text
+ x="188"
+ y="844"
+ clip-path="url(#clipPath138)"
+ xml:space="preserve"
+ id="text980"
+ style="fill:#000000;stroke:none">IMeshData_Curve</text>
+ </g>
+ <g
+ font-size="11"
+ id="g982"
+ style="font-size:11px;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <image
+ x="160"
+ y="854"
+ clip-path="url(#clipPath139)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image984" />
+ <text
+ xml:space="preserve"
+ x="179"
+ y="867"
+ clip-path="url(#clipPath140)"
+ id="text986"
+ style="stroke:none">InsertPoint()</text>
+ <image
+ x="160"
+ y="870"
+ clip-path="url(#clipPath141)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image988" />
+ <text
+ xml:space="preserve"
+ x="179"
+ y="883"
+ clip-path="url(#clipPath142)"
+ id="text990"
+ style="stroke:none">AddPoint()</text>
+ <image
+ x="160"
+ y="886"
+ clip-path="url(#clipPath143)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image992" />
+ <text
+ xml:space="preserve"
+ x="179"
+ y="899"
+ clip-path="url(#clipPath144)"
+ id="text994"
+ style="stroke:none">GetPoint()</text>
+ <image
+ x="160"
+ y="902"
+ clip-path="url(#clipPath145)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image996" />
+ <text
+ xml:space="preserve"
+ x="179"
+ y="915"
+ clip-path="url(#clipPath146)"
+ id="text998"
+ style="stroke:none">RemovePoint()</text>
+ </g>
+ <g
+ font-weight="bold"
+ id="g1000"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath147)"
+ x1="156"
+ x2="299"
+ y1="852"
+ y2="852"
+ id="line1002"
+ style="fill:none" />
+ <rect
+ x="336"
+ y="827"
+ clip-path="url(#clipPath148)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="181"
+ id="rect1004"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="337"
+ y="828"
+ clip-path="url(#clipPath148)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="181"
+ id="rect1006"
+ style="opacity:0.25489999;fill:#837a85;stroke:none" />
+ <rect
+ x="335"
+ y="826"
+ clip-path="url(#clipPath149)"
+ width="145"
+ rx="2.5"
+ ry="2.5"
+ height="181"
+ id="rect1008"
+ style="fill:#ffffff;stroke:none" />
+ <rect
+ x="335"
+ y="826"
+ clip-path="url(#clipPath149)"
+ width="144"
+ rx="2.5"
+ ry="2.5"
+ height="180"
+ id="rect1010"
+ style="fill:none" />
+ <image
+ x="345"
+ y="831"
+ clip-path="url(#clipPath150)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC
+BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu
+rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF
+x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG
+g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL
+Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX
+0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO
+RK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image1012" />
+ <text
+ x="364"
+ y="844"
+ clip-path="url(#clipPath151)"
+ xml:space="preserve"
+ id="text1014"
+ style="fill:#000000;stroke:none">IMeshData_PCurve</text>
+ </g>
+ <g
+ font-size="11"
+ id="g1016"
+ style="font-size:11px;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <image
+ x="340"
+ y="854"
+ clip-path="url(#clipPath152)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image1018" />
+ <text
+ xml:space="preserve"
+ x="359"
+ y="867"
+ clip-path="url(#clipPath153)"
+ id="text1020"
+ style="stroke:none">InsertPoint()</text>
+ <image
+ x="340"
+ y="870"
+ clip-path="url(#clipPath154)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image1022" />
+ <text
+ xml:space="preserve"
+ x="359"
+ y="883"
+ clip-path="url(#clipPath155)"
+ id="text1024"
+ style="stroke:none">AddPoint()</text>
+ <image
+ x="340"
+ y="886"
+ clip-path="url(#clipPath156)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image1026" />
+ <text
+ xml:space="preserve"
+ x="359"
+ y="899"
+ clip-path="url(#clipPath157)"
+ id="text1028"
+ style="stroke:none">GetPoint()</text>
+ <image
+ x="340"
+ y="902"
+ clip-path="url(#clipPath158)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image1030" />
+ <text
+ xml:space="preserve"
+ x="359"
+ y="915"
+ clip-path="url(#clipPath159)"
+ id="text1032"
+ style="stroke:none">RemovePoint()</text>
+ <image
+ x="340"
+ y="918"
+ clip-path="url(#clipPath160)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image1034" />
+ <text
+ xml:space="preserve"
+ x="359"
+ y="931"
+ clip-path="url(#clipPath161)"
+ id="text1036"
+ style="stroke:none">GetIndex()</text>
+ <image
+ x="340"
+ y="934"
+ clip-path="url(#clipPath162)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image1038" />
+ <text
+ xml:space="preserve"
+ x="359"
+ y="947"
+ clip-path="url(#clipPath163)"
+ id="text1040"
+ style="stroke:none">IsForward()</text>
+ <image
+ x="340"
+ y="950"
+ clip-path="url(#clipPath164)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image1042" />
+ <text
+ xml:space="preserve"
+ x="359"
+ y="963"
+ clip-path="url(#clipPath165)"
+ id="text1044"
+ style="stroke:none">IsInternal()</text>
+ <image
+ x="340"
+ y="966"
+ clip-path="url(#clipPath166)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image1046" />
+ <text
+ xml:space="preserve"
+ x="359"
+ y="979"
+ clip-path="url(#clipPath167)"
+ id="text1048"
+ style="stroke:none">GetOrientation()</text>
+ <image
+ x="340"
+ y="982"
+ clip-path="url(#clipPath168)"
+ width="16"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT
+URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp
+B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/
+u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0
+rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri
+aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx
+OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM
+/kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4
+lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI
+/FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA
+zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms
+ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG
+Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII="
+ xlink:type="simple"
+ xlink:actuate="onLoad"
+ height="16"
+ preserveAspectRatio="none"
+ xlink:show="embed"
+ id="image1050" />
+ <text
+ xml:space="preserve"
+ x="359"
+ y="995"
+ clip-path="url(#clipPath169)"
+ id="text1052"
+ style="stroke:none">GetFace()</text>
+ </g>
+ <g
+ font-weight="bold"
+ id="g1054"
+ style="font-weight:bold;fill:#ad7fa8;stroke:#ad7fa8;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath170)"
+ x1="336"
+ x2="479"
+ y1="852"
+ y2="852"
+ id="line1056"
+ style="fill:none" />
+ </g>
+ <g
+ font-size="11"
+ id="g1072"
+ style="font-size:11px;fill:#888888;stroke:#888888;stroke-width:1.10000002;stroke-linecap:butt;font-family:Segoe UI">
+ <line
+ clip-path="url(#clipPath176)"
+ x1="83"
+ x2="83"
+ y1="298"
+ y2="258"
+ id="line1074"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="83"
+ x2="288"
+ y1="258"
+ y2="258"
+ id="line1076"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="288"
+ x2="288"
+ y1="258"
+ y2="240"
+ id="line1078"
+ style="fill:none" />
+ <polygon
+ clip-path="url(#clipPath177)"
+ points="288,240 292,248 284,248 "
+ id="polygon1080"
+ style="fill:#ffffff;stroke:none" />
+ <polygon
+ clip-path="url(#clipPath177)"
+ points="288,240 292,248 284,248 "
+ id="polygon1082"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="466"
+ x2="466"
+ y1="358"
+ y2="258"
+ id="line1084"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="466"
+ x2="288"
+ y1="258"
+ y2="258"
+ id="line1086"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="288"
+ x2="288"
+ y1="258"
+ y2="240"
+ id="line1088"
+ style="fill:none" />
+ <polygon
+ clip-path="url(#clipPath177)"
+ points="288,240 292,248 284,248 "
+ id="polygon1090"
+ style="fill:#ffffff;stroke:none" />
+ <polygon
+ clip-path="url(#clipPath177)"
+ points="288,240 292,248 284,248 "
+ id="polygon1092"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="323"
+ x2="323"
+ y1="514"
+ y2="502"
+ id="line1094"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="323"
+ x2="468"
+ y1="502"
+ y2="502"
+ id="line1096"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="468"
+ x2="468"
+ y1="502"
+ y2="480"
+ id="line1098"
+ style="fill:none" />
+ <polygon
+ clip-path="url(#clipPath178)"
+ points="468,480 472,488 464,488 "
+ id="polygon1100"
+ style="fill:#ffffff;stroke:none" />
+ <polygon
+ clip-path="url(#clipPath178)"
+ points="468,480 472,488 464,488 "
+ id="polygon1102"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="583"
+ x2="583"
+ y1="514"
+ y2="502"
+ id="line1104"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="583"
+ x2="468"
+ y1="502"
+ y2="502"
+ id="line1106"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="468"
+ x2="468"
+ y1="502"
+ y2="480"
+ id="line1108"
+ style="fill:none" />
+ <polygon
+ clip-path="url(#clipPath178)"
+ points="468,480 472,488 464,488 "
+ id="polygon1110"
+ style="fill:#ffffff;stroke:none" />
+ <polygon
+ clip-path="url(#clipPath178)"
+ points="468,480 472,488 464,488 "
+ id="polygon1112"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="822"
+ x2="822"
+ y1="514"
+ y2="502"
+ id="line1114"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="822"
+ x2="468"
+ y1="502"
+ y2="502"
+ id="line1116"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="468"
+ x2="468"
+ y1="502"
+ y2="480"
+ id="line1118"
+ style="fill:none" />
+ <polygon
+ clip-path="url(#clipPath178)"
+ points="468,480 472,488 464,488 "
+ id="polygon1120"
+ style="fill:#ffffff;stroke:none" />
+ <polygon
+ clip-path="url(#clipPath178)"
+ points="468,480 472,488 464,488 "
+ id="polygon1122"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="323"
+ x2="323"
+ y1="514"
+ y2="502"
+ id="line1124"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="323"
+ x2="707"
+ y1="502"
+ y2="502"
+ id="line1126"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="707"
+ x2="707"
+ y1="502"
+ y2="480"
+ id="line1128"
+ style="fill:none" />
+ <polygon
+ clip-path="url(#clipPath179)"
+ points="707,480 711,488 703,488 "
+ id="polygon1130"
+ style="fill:#ffffff;stroke:none" />
+ <polygon
+ clip-path="url(#clipPath179)"
+ points="707,480 711,488 703,488 "
+ id="polygon1132"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="409"
+ x2="409"
+ y1="1007"
+ y2="1054"
+ id="line1134"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="409"
+ x2="104"
+ y1="1054"
+ y2="1054"
+ id="line1136"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="104"
+ x2="104"
+ y1="1054"
+ y2="648"
+ id="line1138"
+ style="fill:none" />
+ <polygon
+ clip-path="url(#clipPath180)"
+ points="104,648 108,656 100,656 "
+ id="polygon1140"
+ style="fill:#ffffff;stroke:none" />
+ <polygon
+ clip-path="url(#clipPath180)"
+ points="104,648 108,656 100,656 "
+ id="polygon1142"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="239"
+ x2="179"
+ y1="714"
+ y2="714"
+ id="line1144"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="179"
+ x2="179"
+ y1="714"
+ y2="826"
+ id="line1146"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <text
+ x="191"
+ y="778"
+ clip-path="url(#clipPath181)"
+ xml:space="preserve"
+ id="text1148"
+ style="fill:#000000;stroke:none">has</text>
+ <text
+ x="191"
+ y="730"
+ clip-path="url(#clipPath182)"
+ xml:space="preserve"
+ id="text1150"
+ style="fill:#000000;stroke:none">edge[1]</text>
+ <text
+ x="191"
+ y="826"
+ clip-path="url(#clipPath183)"
+ xml:space="preserve"
+ id="text1152"
+ style="fill:#000000;stroke:none">curve[1]</text>
+ <line
+ clip-path="url(#clipPath184)"
+ x1="176"
+ x2="179"
+ y1="819"
+ y2="826"
+ id="line1154"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath184)"
+ x1="179"
+ x2="182"
+ y1="826"
+ y2="819"
+ id="line1156"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="396"
+ x2="453"
+ y1="718"
+ y2="718"
+ id="line1158"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="453"
+ x2="453"
+ y1="718"
+ y2="826"
+ id="line1160"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <text
+ x="431"
+ y="778"
+ clip-path="url(#clipPath185)"
+ xml:space="preserve"
+ id="text1162"
+ style="fill:#000000;stroke:none">has</text>
+ <text
+ x="407"
+ y="730"
+ clip-path="url(#clipPath186)"
+ xml:space="preserve"
+ id="text1164"
+ style="fill:#000000;stroke:none">edge[1]</text>
+ <text
+ x="395"
+ y="826"
+ clip-path="url(#clipPath187)"
+ xml:space="preserve"
+ id="text1166"
+ style="fill:#000000;stroke:none">pcurve[*]</text>
+ <line
+ clip-path="url(#clipPath188)"
+ x1="450"
+ x2="453"
+ y1="819"
+ y2="826"
+ id="line1168"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath188)"
+ x1="453"
+ x2="456"
+ y1="826"
+ y2="819"
+ id="line1170"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="480"
+ x2="838"
+ y1="886"
+ y2="886"
+ id="line1172"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="838"
+ x2="838"
+ y1="886"
+ y2="647"
+ id="line1174"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <text
+ x="779"
+ y="874"
+ clip-path="url(#clipPath189)"
+ xml:space="preserve"
+ id="text1176"
+ style="fill:#000000;stroke:none">references</text>
+ <text
+ x="479"
+ y="898"
+ clip-path="url(#clipPath190)"
+ xml:space="preserve"
+ id="text1178"
+ style="fill:#000000;stroke:none">pcurve[1]</text>
+ <text
+ x="851"
+ y="664"
+ clip-path="url(#clipPath191)"
+ xml:space="preserve"
+ id="text1180"
+ style="fill:#000000;stroke:none">face[1]</text>
+ <line
+ clip-path="url(#clipPath192)"
+ x1="841"
+ x2="838"
+ y1="654"
+ y2="647"
+ id="line1182"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath192)"
+ x1="838"
+ x2="835"
+ y1="647"
+ y2="654"
+ id="line1184"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="779"
+ x2="660"
+ y1="582"
+ y2="582"
+ id="line1186"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <text
+ x="705"
+ y="595"
+ clip-path="url(#clipPath193)"
+ xml:space="preserve"
+ id="text1188"
+ style="fill:#000000;stroke:none">has</text>
+ <text
+ x="743"
+ y="580"
+ clip-path="url(#clipPath194)"
+ xml:space="preserve"
+ id="text1190"
+ style="fill:#000000;stroke:none">face[1]</text>
+ <text
+ x="664"
+ y="579"
+ clip-path="url(#clipPath195)"
+ xml:space="preserve"
+ id="text1192"
+ style="fill:#000000;stroke:none">wire[1..*]</text>
+ <line
+ clip-path="url(#clipPath196)"
+ x1="667"
+ x2="660"
+ y1="579"
+ y2="582"
+ id="line1194"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath196)"
+ x1="660"
+ x2="667"
+ y1="582"
+ y2="585"
+ id="line1196"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="515"
+ x2="396"
+ y1="582"
+ y2="582"
+ id="line1198"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <text
+ x="445"
+ y="596"
+ clip-path="url(#clipPath197)"
+ xml:space="preserve"
+ id="text1200"
+ style="fill:#000000;stroke:none">has</text>
+ <text
+ x="479"
+ y="578"
+ clip-path="url(#clipPath198)"
+ xml:space="preserve"
+ id="text1202"
+ style="fill:#000000;stroke:none">wire[1]</text>
+ <text
+ x="394"
+ y="577"
+ clip-path="url(#clipPath199)"
+ xml:space="preserve"
+ id="text1204"
+ style="fill:#000000;stroke:none">edge[1..*]</text>
+ <line
+ clip-path="url(#clipPath200)"
+ x1="403"
+ x2="396"
+ y1="579"
+ y2="582"
+ id="line1206"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath200)"
+ x1="396"
+ x2="403"
+ y1="582"
+ y2="585"
+ id="line1208"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="192"
+ x2="291"
+ y1="382"
+ y2="382"
+ id="line1210"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="291"
+ x2="291"
+ y1="382"
+ y2="514"
+ id="line1212"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <text
+ x="266"
+ y="478"
+ clip-path="url(#clipPath201)"
+ xml:space="preserve"
+ id="text1214"
+ style="fill:#000000;stroke:none">has</text>
+ <text
+ x="191"
+ y="382"
+ clip-path="url(#clipPath202)"
+ xml:space="preserve"
+ id="text1216"
+ style="fill:#000000;stroke:none">model[1]</text>
+ <text
+ x="250"
+ y="515"
+ clip-path="url(#clipPath203)"
+ xml:space="preserve"
+ id="text1218"
+ style="fill:#000000;stroke:none">edge[*]</text>
+ <line
+ clip-path="url(#clipPath204)"
+ x1="288"
+ x2="291"
+ y1="507"
+ y2="514"
+ id="line1220"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath204)"
+ x1="291"
+ x2="294"
+ y1="514"
+ y2="507"
+ id="line1222"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="192"
+ x2="863"
+ y1="334"
+ y2="334"
+ id="line1224"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="863"
+ x2="863"
+ y1="334"
+ y2="514"
+ id="line1226"
+ style="fill:none;stroke-dasharray:5, 5" />
+ <text
+ x="684"
+ y="330"
+ clip-path="url(#clipPath205)"
+ xml:space="preserve"
+ id="text1228"
+ style="fill:#000000;stroke:none">has</text>
+ <text
+ x="191"
+ y="334"
+ clip-path="url(#clipPath206)"
+ xml:space="preserve"
+ id="text1230"
+ style="fill:#000000;stroke:none">model[1]</text>
+ <text
+ x="866"
+ y="510"
+ clip-path="url(#clipPath207)"
+ xml:space="preserve"
+ id="text1232"
+ style="fill:#000000;stroke:none">face[*]</text>
+ <line
+ clip-path="url(#clipPath208)"
+ x1="860"
+ x2="863"
+ y1="507"
+ y2="514"
+ id="line1234"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath208)"
+ x1="863"
+ x2="866"
+ y1="514"
+ y2="507"
+ id="line1236"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="228"
+ x2="228"
+ y1="1007"
+ y2="1054"
+ id="line1238"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="228"
+ x2="104"
+ y1="1054"
+ y2="1054"
+ id="line1240"
+ style="fill:none" />
+ <line
+ clip-path="url(#clipPath176)"
+ x1="104"
+ x2="104"
+ y1="1054"
+ y2="648"
+ id="line1242"
+ style="fill:none" />
+ <polygon
+ clip-path="url(#clipPath180)"
+ points="104,648 108,656 100,656 "
+ id="polygon1244"
+ style="fill:#ffffff;stroke:none" />
+ <polygon
+ clip-path="url(#clipPath180)"
+ points="104,648 108,656 100,656 "
+ id="polygon1246"
+ style="fill:none" />
+ </g>
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" stroke-dasharray="none" shape-rendering="auto" font-family="'Dialog'" width="1514" text-rendering="auto" fill-opacity="1" contentScriptType="text/ecmascript" color-interpolation="auto" color-rendering="auto" preserveAspectRatio="xMidYMid meet" font-size="12" viewBox="0 0 1514 1571" fill="black" stroke="black" image-rendering="auto" stroke-miterlimit="10" zoomAndPan="magnify" version="1.0" stroke-linecap="square" stroke-linejoin="miter" contentStyleType="text/css" font-style="normal" height="1571" stroke-width="1" stroke-dashoffset="0" font-weight="normal" stroke-opacity="1">
+<!--Generated by the Batik Graphics2D SVG Generator-->
+<defs id="genericDefs"/>
+<g>
+<defs id="defs1">
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath1">
+<path d="M1296 189 L1505 189 L1505 291 L1296 291 L1296 189 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath2">
+<path d="M1296 189 L1503 189 L1503 289 L1296 289 L1296 189 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath3">
+<path d="M1307 194 L1492 194 L1492 212 L1307 212 L1307 194 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath4">
+<path d="M1307 194 L1495 194 L1495 212 L1307 212 L1307 194 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath5">
+<path d="M1301 217 L1497 217 L1497 245 L1301 245 L1301 217 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath6">
+<path d="M1301 217 L1499 217 L1499 245 L1301 245 L1301 217 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath7">
+<path d="M1297 215 L1502 215 L1502 288 L1297 288 L1297 215 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath8">
+<path d="M1296 345 L1505 345 L1505 434 L1296 434 L1296 345 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath9">
+<path d="M1296 345 L1503 345 L1503 432 L1296 432 L1296 345 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath10">
+<path d="M1308 350 L1490 350 L1490 368 L1308 368 L1308 350 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath11">
+<path d="M1308 350 L1493 350 L1493 368 L1308 368 L1308 350 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath12">
+<path d="M1297 371 L1502 371 L1502 431 L1297 431 L1297 371 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath13">
+<path d="M12 165 L1168 165 L1168 1562 L12 1562 L12 165 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath14">
+<path d="M12 165 L1166 165 L1166 1560 L12 1560 L12 165 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath15">
+<path d="M13 170 L135 170 L135 188 L13 188 L13 170 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath16">
+<path d="M13 170 L137 170 L137 188 L13 188 L13 170 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath17">
+<path d="M291 189 L523 189 L523 291 L291 291 L291 189 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath18">
+<path d="M291 189 L521 189 L521 289 L291 289 L291 189 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath19">
+<path d="M334 194 L478 194 L478 212 L334 212 L334 194 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath20">
+<path d="M334 194 L481 194 L481 212 L334 212 L334 194 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath21">
+<path d="M296 217 L458 217 L458 245 L296 245 L296 217 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath22">
+<path d="M296 217 L460 217 L460 245 L296 245 L296 217 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath23">
+<path d="M292 215 L520 215 L520 288 L292 288 L292 215 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath24">
+<path d="M446 465 L739 465 L739 567 L446 567 L446 465 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath25">
+<path d="M446 465 L737 465 L737 565 L446 565 L446 465 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath26">
+<path d="M482 470 L700 470 L700 488 L482 488 L482 470 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath27">
+<path d="M482 470 L703 470 L703 488 L482 488 L482 470 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath28">
+<path d="M447 491 L736 491 L736 564 L447 564 L447 491 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath29">
+<path d="M444 777 L737 777 L737 879 L444 879 L444 777 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath30">
+<path d="M444 777 L735 777 L735 877 L444 877 L444 777 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath31">
+<path d="M452 782 L727 782 L727 814 L452 814 L452 782 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath32">
+<path d="M452 782 L730 782 L730 814 L452 814 L452 782 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath33">
+<path d="M445 817 L734 817 L734 876 L445 876 L445 817 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath34">
+<path d="M792 777 L1097 777 L1097 879 L792 879 L792 777 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath35">
+<path d="M792 777 L1095 777 L1095 877 L792 877 L792 777 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath36">
+<path d="M796 782 L1091 782 L1091 814 L796 814 L796 782 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath37">
+<path d="M796 782 L1094 782 L1094 814 L796 814 L796 782 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath38">
+<path d="M793 817 L1094 817 L1094 876 L793 876 L793 817 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath39">
+<path d="M74 465 L367 465 L367 567 L74 567 L74 465 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath40">
+<path d="M74 465 L365 465 L365 565 L74 565 L74 465 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath41">
+<path d="M118 470 L320 470 L320 488 L118 488 L118 470 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath42">
+<path d="M118 470 L323 470 L323 488 L118 488 L118 470 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath43">
+<path d="M75 491 L364 491 L364 564 L75 564 L75 491 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath44">
+<path d="M72 777 L365 777 L365 879 L72 879 L72 777 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath45">
+<path d="M72 777 L363 777 L363 877 L72 877 L72 777 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath46">
+<path d="M75 782 L360 782 L360 814 L75 814 L75 782 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath47">
+<path d="M75 782 L363 782 L363 814 L75 814 L75 782 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath48">
+<path d="M73 817 L362 817 L362 876 L73 876 L73 817 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath49">
+<path d="M36 944 L1145 944 L1145 1538 L36 1538 L36 944 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath50">
+<path d="M36 944 L1143 944 L1143 1536 L36 1536 L36 944 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath51">
+<path d="M37 949 L135 949 L135 967 L37 967 L37 949 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath52">
+<path d="M37 949 L137 949 L137 967 L37 967 L37 949 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath53">
+<path d="M492 980 L713 980 L713 1082 L492 1082 L492 980 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath54">
+<path d="M492 980 L711 980 L711 1080 L492 1080 L492 980 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath55">
+<path d="M499 985 L704 985 L704 1003 L499 1003 L499 985 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath56">
+<path d="M499 985 L707 985 L707 1003 L499 1003 L499 985 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath57">
+<path d="M493 1006 L710 1006 L710 1079 L493 1079 L493 1006 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath58">
+<path d="M60 1124 L281 1124 L281 1226 L60 1226 L60 1124 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath59">
+<path d="M60 1124 L279 1124 L279 1224 L60 1224 L60 1124 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath60">
+<path d="M74 1129 L265 1129 L265 1147 L74 1147 L74 1129 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath61">
+<path d="M74 1129 L268 1129 L268 1147 L74 1147 L74 1129 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath62">
+<path d="M61 1150 L278 1150 L278 1223 L61 1223 L61 1150 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath63">
+<path d="M300 1124 L521 1124 L521 1226 L300 1226 L300 1124 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath64">
+<path d="M300 1124 L519 1124 L519 1224 L300 1224 L300 1124 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath65">
+<path d="M305 1129 L513 1129 L513 1147 L305 1147 L305 1129 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath66">
+<path d="M305 1129 L516 1129 L516 1147 L305 1147 L305 1129 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath67">
+<path d="M301 1150 L518 1150 L518 1223 L301 1223 L301 1150 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath68">
+<path d="M535 1124 L756 1124 L756 1226 L535 1226 L535 1124 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath69">
+<path d="M535 1124 L754 1124 L754 1224 L535 1224 L535 1124 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath70">
+<path d="M543 1129 L746 1129 L746 1147 L543 1147 L543 1129 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath71">
+<path d="M543 1129 L749 1129 L749 1147 L543 1147 L543 1129 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath72">
+<path d="M536 1150 L753 1150 L753 1223 L536 1223 L536 1150 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath73">
+<path d="M775 1124 L995 1124 L995 1226 L775 1226 L775 1124 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath74">
+<path d="M775 1124 L993 1124 L993 1224 L775 1224 L775 1124 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath75">
+<path d="M776 1129 L991 1129 L991 1147 L776 1147 L776 1129 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath76">
+<path d="M776 1129 L994 1129 L994 1147 L776 1147 L776 1129 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath77">
+<path d="M776 1150 L992 1150 L992 1223 L776 1223 L776 1150 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath78">
+<path d="M649 1280 L869 1280 L869 1382 L649 1382 L649 1280 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath79">
+<path d="M649 1280 L867 1280 L867 1380 L649 1380 L649 1280 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath80">
+<path d="M661 1285 L855 1285 L855 1303 L661 1303 L661 1285 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath81">
+<path d="M661 1285 L858 1285 L858 1303 L661 1303 L661 1285 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath82">
+<path d="M650 1306 L866 1306 L866 1379 L650 1379 L650 1306 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath83">
+<path d="M900 1280 L1119 1280 L1119 1382 L900 1382 L900 1280 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath84">
+<path d="M900 1280 L1117 1280 L1117 1380 L900 1380 L900 1280 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath85">
+<path d="M906 1285 L1110 1285 L1110 1303 L906 1303 L906 1285 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath86">
+<path d="M906 1285 L1113 1285 L1113 1303 L906 1303 L906 1285 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath87">
+<path d="M901 1306 L1116 1306 L1116 1379 L901 1379 L901 1306 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath88">
+<path d="M852 1413 L1119 1413 L1119 1515 L852 1515 L852 1413 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath89">
+<path d="M852 1413 L1117 1413 L1117 1513 L852 1513 L852 1413 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath90">
+<path d="M856 1418 L1112 1418 L1112 1436 L856 1436 L856 1418 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath91">
+<path d="M856 1418 L1115 1418 L1115 1436 L856 1436 L856 1418 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath92">
+<path d="M853 1439 L1116 1439 L1116 1512 L853 1512 L853 1439 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath93">
+<path d="M290 321 L523 321 L523 423 L290 423 L290 321 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath94">
+<path d="M290 321 L521 321 L521 421 L290 421 L290 321 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath95">
+<path d="M322 326 L489 326 L489 344 L322 344 L322 326 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath96">
+<path d="M322 326 L492 326 L492 344 L322 344 L322 326 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath97">
+<path d="M291 347 L520 347 L520 420 L291 420 L291 347 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath98">
+<path d="M822 321 L1067 321 L1067 423 L822 423 L822 321 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath99">
+<path d="M822 321 L1065 321 L1065 421 L822 421 L822 321 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath100">
+<path d="M834 326 L1053 326 L1053 344 L834 344 L834 326 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath101">
+<path d="M834 326 L1056 326 L1056 344 L834 344 L834 326 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath102">
+<path d="M823 347 L1064 347 L1064 420 L823 420 L823 347 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath103">
+<path d="M276 621 L538 621 L538 723 L276 723 L276 621 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath104">
+<path d="M276 621 L536 621 L536 721 L276 721 L276 621 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath105">
+<path d="M294 626 L518 626 L518 658 L294 658 L294 626 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath106">
+<path d="M294 626 L521 626 L521 658 L294 658 L294 626 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath107">
+<path d="M294 626 L520 626 L520 658 L294 658 L294 626 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath108">
+<path d="M277 661 L535 661 L535 720 L277 720 L277 661 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath109">
+<path d="M792 9 L986 9 L986 111 L792 111 L792 9 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath110">
+<path d="M792 9 L984 9 L984 109 L792 109 L792 9 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath111">
+<path d="M812 14 L963 14 L963 32 L812 32 L812 14 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath112">
+<path d="M812 14 L966 14 L966 32 L812 32 L812 14 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath113">
+<path d="M793 35 L983 35 L983 108 L793 108 L793 35 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath114">
+<path d="M-1 -1 L1515 -1 L1515 1572 L-1 1572 L-1 -1 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath115">
+<path d="M22 597 L365 597 L365 615 L22 615 L22 597 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath116">
+<path d="M22 597 L367 597 L367 615 L22 615 L22 597 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath117">
+<path d="M366 616 L377 616 L377 624 L366 624 L366 616 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath118">
+<path d="M828 908 L1001 908 L1001 926 L828 926 L828 908 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath119">
+<path d="M828 908 L1003 908 L1003 926 L828 926 L828 908 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath120">
+<path d="M904 875 L915 875 L915 883 L904 883 L904 875 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath121">
+<path d="M597 1078 L608 1078 L608 1089 L597 1089 L597 1078 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath122">
+<path d="M400 419 L411 419 L411 430 L400 430 L400 419 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath123">
+<path d="M880 1222 L891 1222 L891 1233 L880 1233 L880 1222 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath124">
+<path d="M127 902 L300 902 L300 920 L127 920 L127 902 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath125">
+<path d="M127 902 L302 902 L302 920 L127 920 L127 902 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath126">
+<path d="M252 875 L263 875 L263 883 L252 883 L252 875 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath127">
+<path d="M434 597 L794 597 L794 615 L434 615 L434 597 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath128">
+<path d="M434 597 L796 597 L796 615 L434 615 L434 597 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath129">
+<path d="M446 616 L457 616 L457 624 L446 624 L446 616 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath130">
+<path d="M1004 1378 L1015 1378 L1015 1389 L1004 1389 L1004 1378 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath131">
+<path d="M733 823 L743 823 L743 832 L733 832 L733 823 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath132">
+<path d="M402 719 L413 719 L413 730 L402 730 L402 719 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath133">
+<path d="M408 896 L581 896 L581 914 L408 914 L408 896 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath134">
+<path d="M408 896 L583 896 L583 914 L408 914 L408 896 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath135">
+<path d="M586 875 L595 875 L595 885 L586 885 L586 875 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath136">
+<path d="M666 359 L721 359 L721 374 L666 374 L666 359 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath137">
+<path d="M815 372 L825 372 L825 381 L815 381 L815 372 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath138">
+<path d="M401 287 L412 287 L412 298 L401 298 L401 287 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath139">
+<path d="M1394 287 L1405 287 L1405 298 L1394 298 L1394 287 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath140">
+<path d="M1164 394 L1174 394 L1174 403 L1164 403 L1164 394 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath141">
+<path d="M579 123 L634 123 L634 138 L579 138 L579 123 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath142">
+<path d="M408 185 L418 185 L418 194 L408 194 L408 185 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath143">
+<path d="M1140 129 L1195 129 L1195 144 L1140 144 L1140 129 Z"/>
+</clipPath>
+<clipPath clipPathUnits="userSpaceOnUse" id="clipPath144">
+<path d="M1385 185 L1395 185 L1395 194 L1385 194 L1385 185 Z"/>
+</clipPath>
+</defs>
+<g fill="rgb(131,122,133)" font-family="'Segoe UI'" stroke-linejoin="round" stroke="rgb(131,122,133)" font-weight="bold" stroke-width="0" stroke-miterlimit="0">
+<rect x="1298" y="191" clip-path="url(#clipPath1)" width="205" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="1299" y="192" clip-path="url(#clipPath1)" width="205" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="1297" y="190" clip-path="url(#clipPath2)" fill="white" width="205" rx="2.5" ry="2.5" height="98" stroke="none"/>
+</g>
+<g stroke-linecap="butt" fill="rgb(173,127,168)" font-family="'Segoe UI'" stroke="rgb(173,127,168)" font-weight="bold" stroke-width="1.1">
+<rect x="1297" y="190" clip-path="url(#clipPath2)" fill="none" width="204" rx="2.5" ry="2.5" height="97"/>
+<image x="1308" y="195" clip-path="url(#clipPath3)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX 0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO RK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="1327" y="208" clip-path="url(#clipPath4)" fill="black" stroke="none" xml:space="preserve">IMeshTools_MeshAlgoFactory</text>
+</g>
+<g stroke-width="1.1" font-size="11" font-family="'Segoe UI'" stroke-linecap="butt">
+<image x="1302" y="223" clip-path="url(#clipPath5)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="1321" y="230" clip-path="url(#clipPath6)" stroke="none">GetAlgo(GeomAbs_SurfaceType : , </text>
+<text xml:space="preserve" x="1321" y="243" clip-path="url(#clipPath6)" stroke="none">IMeshTools_Parameters : )</text>
+</g>
+<g stroke-linecap="butt" fill="rgb(173,127,168)" font-family="'Segoe UI'" stroke="rgb(173,127,168)" font-weight="bold" stroke-width="1.1">
+<line clip-path="url(#clipPath7)" fill="none" x1="1298" x2="1501" y1="216" y2="216"/>
+<rect x="1298" y="347" clip-path="url(#clipPath8)" fill="rgb(131,122,133)" width="205" rx="2.5" opacity="0.2549" ry="2.5" height="85" stroke="none"/>
+<rect x="1299" y="348" clip-path="url(#clipPath8)" fill="rgb(131,122,133)" width="205" rx="2.5" opacity="0.2549" ry="2.5" height="85" stroke="none"/>
+<rect x="1297" y="346" clip-path="url(#clipPath9)" fill="white" width="205" rx="2.5" ry="2.5" height="85" stroke="none"/>
+<rect x="1297" y="346" clip-path="url(#clipPath9)" fill="none" width="204" rx="2.5" ry="2.5" height="84" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath10)" preserveAspectRatio="none" height="16" x="1309" y="351" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="1328" y="364" clip-path="url(#clipPath11)" fill="black" stroke="none" xml:space="preserve">BRepMesh_MeshAlgoFactory</text>
+<line clip-path="url(#clipPath12)" fill="none" x1="1298" x2="1501" y1="372" y2="372" stroke="rgb(39,76,114)"/>
+<rect x="14" y="167" clip-path="url(#clipPath13)" fill="rgb(131,122,133)" width="1152" rx="2.5" opacity="0.2549" ry="2.5" height="1393" stroke="none"/>
+<rect x="15" y="168" clip-path="url(#clipPath13)" fill="rgb(131,122,133)" width="1152" rx="2.5" opacity="0.2549" ry="2.5" height="1393" stroke="none"/>
+<rect x="13" y="166" clip-path="url(#clipPath14)" fill="white" width="1152" rx="2.5" ry="2.5" height="1393" stroke="none"/>
+<rect x="13" y="166" clip-path="url(#clipPath14)" fill="none" width="1151" rx="2.5" ry="2.5" height="1392" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath15)" preserveAspectRatio="none" height="16" x="14" y="171" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAWUlEQVR42mNgGPKA EUQoZCz4j0vBgxkJjPgMYIEx7k+Px5BUzFxIuQvwAZDr4C7YUBdAkuaApg2oXgAB MV5+kl3BRGksoLiAnZlCA5gZKTWAiQIDYKE6AgEAAu0P6M4KKrgAAAAASUVORK5C YII=" xlink:actuate="onLoad"/>
+<text x="33" y="184" clip-path="url(#clipPath16)" fill="black" stroke="none" xml:space="preserve">Triangulation Algo</text>
+<rect x="293" y="191" clip-path="url(#clipPath17)" fill="rgb(131,122,133)" width="228" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="294" y="192" clip-path="url(#clipPath17)" fill="rgb(131,122,133)" width="228" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="292" y="190" clip-path="url(#clipPath18)" fill="white" width="228" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="292" y="190" clip-path="url(#clipPath18)" fill="none" width="227" rx="2.5" ry="2.5" height="97"/>
+<image x="335" y="195" clip-path="url(#clipPath19)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmMHsEzceMVhoyDFYVK6EazjRHg4Xh2iAOIcJ2VQWZiawooKF x8HsM12RYHEQDeKDxEHyIDYMoBnACFZ0oTcKzAZhmDgIg8QhhjNiN4AVaPKEeEsG g+JlYDYr1CYYGyQOkmfF6gJgELMCTfYyUYEqYmTQLlgClgLRID5IHCQPYv+DhgEL Qv8/BmYmiNN8zVTB9N2pcSghDxOHqEczAAT8GjaB08F/NBIGECkEyGZkxDRgaYUX 0ekgpnM7ZiCSA1iwmUq2AUvKPQfQCypKwiR5AaSeKgAABcZdRqE6GaQAAAAASUVO RK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="354" y="208" clip-path="url(#clipPath20)" fill="black" stroke="none" xml:space="preserve">IMeshTools_MeshAlgo</text>
+</g>
+<g stroke-width="1.1" font-size="11" font-family="'Segoe UI'" stroke-linecap="butt">
+<image x="297" y="223" clip-path="url(#clipPath21)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACM0lEQVR42sVTX0hT URz+7p3OCIqkaMLq0R6CCIRMaCMyr9ushkT17Fq9RNk/iJBk5z5s+BAhBQYh6Hyp B5W0NufcbCuNFcToIQrxz5g0IsVE5u52d+89HScMYw56CPo9nHN+/L7z8fGd7wD/ u3TlBgIJ0nmlmljb3GQ2OiCWw/FbmyYxQGG+SzfOE+HXePfkNgLhwc3hiZvUSsK0 rAKLK0gnwq8w+fA6vF950v/gCnZWVaGxoQ4jC3oy+agdnU/7IVzuIvNRb1ERV5Ri aqejXTcASsFxKjRaCbaggtfYtAIKVIbWcO5+DzD1mCtRQJMfxBczHGk1NSCfB3yx OGYWF/ElkcLBmhrICnCxswd0y+UigcUVonPqHuK+5kClTofI5zhjVNDr/4RjtUbM /kjhQLUBx48cRWhpB2l2uslcZNPYgonjzDDP1TZsqFxeyUHTFPSNxRH1nMez8Rh4 lcP31RwUlcLjdCAYfPnnK9iEs+joHUBiOYOVjASOee04U4dTHUNw2uqh8TqsrctI /FpnuD4IFjtKTCwUM9JxoRW8wnjlFGOn0BiE0xug6vTwDg5Bm+7mtg+S+Ra1t7RA zgGSKiNHdyPNVbJ9FyRNRUZWcfhQLb7l9xEkY2JJkMwnGzHq92E1l8XImA8/M2ms ScCSlMWwP4h0VsJwwI/TTbbtg5R8+1ysv3SPTE9FCk+VpPvJXqMRHyOsf9/NLagG Igh2hFwC91efxOp6Q2G6Q5vF0vj+0/oNRdDxkTDUjqQAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text xml:space="preserve" x="316" y="230" clip-path="url(#clipPath22)" stroke="none">Perform(IMeshData_Face : , </text>
+<text xml:space="preserve" x="316" y="243" clip-path="url(#clipPath22)" stroke="none">IMeshTools_Parameters : )</text>
+</g>
+<g stroke-linecap="butt" fill="rgb(173,127,168)" font-family="'Segoe UI'" stroke="rgb(173,127,168)" font-weight="bold" stroke-width="1.1">
+<line clip-path="url(#clipPath23)" fill="none" x1="293" x2="519" y1="216" y2="216"/>
+<rect x="448" y="467" clip-path="url(#clipPath24)" fill="rgb(131,122,133)" width="289" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="449" y="468" clip-path="url(#clipPath24)" fill="rgb(131,122,133)" width="289" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="447" y="466" clip-path="url(#clipPath25)" fill="white" width="289" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="447" y="466" clip-path="url(#clipPath25)" fill="none" width="288" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath26)" preserveAspectRatio="none" height="16" x="483" y="471" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="502" y="484" clip-path="url(#clipPath27)" fill="black" stroke="none" xml:space="preserve">BRepMesh_DelaunayBaseMeshAlgo</text>
+<line clip-path="url(#clipPath28)" fill="none" x1="448" x2="735" y1="492" y2="492" stroke="rgb(39,76,114)"/>
+<rect x="446" y="779" clip-path="url(#clipPath29)" fill="rgb(131,122,133)" width="289" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="447" y="780" clip-path="url(#clipPath29)" fill="rgb(131,122,133)" width="289" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="445" y="778" clip-path="url(#clipPath30)" fill="white" width="289" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="445" y="778" clip-path="url(#clipPath30)" fill="none" width="288" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath31)" preserveAspectRatio="none" height="16" x="453" y="790" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="472" y="796" clip-path="url(#clipPath32)" fill="black" stroke="none" xml:space="preserve">BRepMesh_DelaunayNodeInsertionMeshAlgo </text>
+<text x="472" y="811" clip-path="url(#clipPath32)" fill="black" stroke="none" xml:space="preserve"><RangeSplitter></text>
+<line clip-path="url(#clipPath33)" fill="none" x1="446" x2="733" y1="818" y2="818" stroke="rgb(39,76,114)"/>
+<rect x="794" y="779" clip-path="url(#clipPath34)" fill="rgb(131,122,133)" width="301" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="795" y="780" clip-path="url(#clipPath34)" fill="rgb(131,122,133)" width="301" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="793" y="778" clip-path="url(#clipPath35)" fill="white" width="301" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="793" y="778" clip-path="url(#clipPath35)" fill="none" width="300" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath36)" preserveAspectRatio="none" height="16" x="797" y="790" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="816" y="796" clip-path="url(#clipPath37)" fill="black" stroke="none" xml:space="preserve">BRepMesh_DelaunayDeflectionControlMeshAlgo </text>
+<text x="816" y="811" clip-path="url(#clipPath37)" fill="black" stroke="none" xml:space="preserve"><RangeSplitter></text>
+<line clip-path="url(#clipPath38)" fill="none" x1="794" x2="1093" y1="818" y2="818" stroke="rgb(39,76,114)"/>
+<rect x="76" y="467" clip-path="url(#clipPath39)" fill="rgb(131,122,133)" width="289" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="77" y="468" clip-path="url(#clipPath39)" fill="rgb(131,122,133)" width="289" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="75" y="466" clip-path="url(#clipPath40)" fill="white" width="289" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="75" y="466" clip-path="url(#clipPath40)" fill="none" width="288" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath41)" preserveAspectRatio="none" height="16" x="119" y="471" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="138" y="484" clip-path="url(#clipPath42)" fill="black" stroke="none" xml:space="preserve">BRepMesh_SweepLineMeshAlgo</text>
+<line clip-path="url(#clipPath43)" fill="none" x1="76" x2="363" y1="492" y2="492" stroke="rgb(39,76,114)"/>
+<rect x="74" y="779" clip-path="url(#clipPath44)" fill="rgb(131,122,133)" width="289" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="75" y="780" clip-path="url(#clipPath44)" fill="rgb(131,122,133)" width="289" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="73" y="778" clip-path="url(#clipPath45)" fill="white" width="289" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="73" y="778" clip-path="url(#clipPath45)" fill="none" width="288" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath46)" preserveAspectRatio="none" height="16" x="76" y="790" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="95" y="796" clip-path="url(#clipPath47)" fill="black" stroke="none" xml:space="preserve">BRepMesh_SweepLineNodeInsertionMeshAlgo </text>
+<text x="95" y="811" clip-path="url(#clipPath47)" fill="black" stroke="none" xml:space="preserve"><RangeSplitter></text>
+<line clip-path="url(#clipPath48)" fill="none" x1="74" x2="361" y1="818" y2="818" stroke="rgb(39,76,114)"/>
+<rect x="38" y="946" clip-path="url(#clipPath49)" fill="rgb(131,122,133)" width="1105" rx="2.5" opacity="0.2549" ry="2.5" height="590" stroke="none"/>
+<rect x="39" y="947" clip-path="url(#clipPath49)" fill="rgb(131,122,133)" width="1105" rx="2.5" opacity="0.2549" ry="2.5" height="590" stroke="none"/>
+<rect x="37" y="945" clip-path="url(#clipPath50)" fill="white" width="1105" rx="2.5" ry="2.5" height="590" stroke="none"/>
+<rect x="37" y="945" clip-path="url(#clipPath50)" fill="none" width="1104" rx="2.5" ry="2.5" height="589" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath51)" preserveAspectRatio="none" height="16" x="38" y="950" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAWUlEQVR42mNgGPKA EUQoZCz4j0vBgxkJjPgMYIEx7k+Px5BUzFxIuQvwAZDr4C7YUBdAkuaApg2oXgAB MV5+kl3BRGksoLiAnZlCA5gZKTWAiQIDYKE6AgEAAu0P6M4KKrgAAAAASUVORK5C YII=" xlink:actuate="onLoad"/>
+<text x="57" y="963" clip-path="url(#clipPath52)" fill="black" stroke="none" xml:space="preserve">RangeSplitter</text>
+<rect x="494" y="982" clip-path="url(#clipPath53)" fill="rgb(131,122,133)" width="217" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="495" y="983" clip-path="url(#clipPath53)" fill="rgb(131,122,133)" width="217" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="493" y="981" clip-path="url(#clipPath54)" fill="white" width="217" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="493" y="981" clip-path="url(#clipPath54)" fill="none" width="216" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath55)" preserveAspectRatio="none" height="16" x="500" y="986" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="519" y="999" clip-path="url(#clipPath56)" fill="black" stroke="none" xml:space="preserve">BRepMesh_DefaultRangeSplitter</text>
+<line clip-path="url(#clipPath57)" fill="none" x1="494" x2="709" y1="1007" y2="1007" stroke="rgb(39,76,114)"/>
+<rect x="62" y="1126" clip-path="url(#clipPath58)" fill="rgb(131,122,133)" width="217" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="63" y="1127" clip-path="url(#clipPath58)" fill="rgb(131,122,133)" width="217" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="61" y="1125" clip-path="url(#clipPath59)" fill="white" width="217" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="61" y="1125" clip-path="url(#clipPath59)" fill="none" width="216" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath60)" preserveAspectRatio="none" height="16" x="75" y="1130" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="94" y="1143" clip-path="url(#clipPath61)" fill="black" stroke="none" xml:space="preserve">BRepMesh_ConeRangeSplitter</text>
+<line clip-path="url(#clipPath62)" fill="none" x1="62" x2="277" y1="1151" y2="1151" stroke="rgb(39,76,114)"/>
+<rect x="302" y="1126" clip-path="url(#clipPath63)" fill="rgb(131,122,133)" width="217" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="303" y="1127" clip-path="url(#clipPath63)" fill="rgb(131,122,133)" width="217" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="301" y="1125" clip-path="url(#clipPath64)" fill="white" width="217" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="301" y="1125" clip-path="url(#clipPath64)" fill="none" width="216" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath65)" preserveAspectRatio="none" height="16" x="306" y="1130" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="325" y="1143" clip-path="url(#clipPath66)" fill="black" stroke="none" xml:space="preserve">BRepMesh_CylinderRangeSplitter</text>
+<line clip-path="url(#clipPath67)" fill="none" x1="302" x2="517" y1="1151" y2="1151" stroke="rgb(39,76,114)"/>
+<rect x="537" y="1126" clip-path="url(#clipPath68)" fill="rgb(131,122,133)" width="217" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="538" y="1127" clip-path="url(#clipPath68)" fill="rgb(131,122,133)" width="217" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="536" y="1125" clip-path="url(#clipPath69)" fill="white" width="217" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="536" y="1125" clip-path="url(#clipPath69)" fill="none" width="216" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath70)" preserveAspectRatio="none" height="16" x="544" y="1130" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="563" y="1143" clip-path="url(#clipPath71)" fill="black" stroke="none" xml:space="preserve">BRepMesh_SphereRangeSplitter</text>
+<line clip-path="url(#clipPath72)" fill="none" x1="537" x2="752" y1="1151" y2="1151" stroke="rgb(39,76,114)"/>
+<rect x="777" y="1126" clip-path="url(#clipPath73)" fill="rgb(131,122,133)" width="216" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="778" y="1127" clip-path="url(#clipPath73)" fill="rgb(131,122,133)" width="216" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="776" y="1125" clip-path="url(#clipPath74)" fill="white" width="216" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="776" y="1125" clip-path="url(#clipPath74)" fill="none" width="215" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath75)" preserveAspectRatio="none" height="16" x="777" y="1130" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="796" y="1143" clip-path="url(#clipPath76)" fill="black" stroke="none" xml:space="preserve">BRepMesh_UVParamRangeSplitter</text>
+<line clip-path="url(#clipPath77)" fill="none" x1="777" x2="991" y1="1151" y2="1151" stroke="rgb(39,76,114)"/>
+<rect x="651" y="1282" clip-path="url(#clipPath78)" fill="rgb(131,122,133)" width="216" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="652" y="1283" clip-path="url(#clipPath78)" fill="rgb(131,122,133)" width="216" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="650" y="1281" clip-path="url(#clipPath79)" fill="white" width="216" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="650" y="1281" clip-path="url(#clipPath79)" fill="none" width="215" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath80)" preserveAspectRatio="none" height="16" x="662" y="1286" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="681" y="1299" clip-path="url(#clipPath81)" fill="black" stroke="none" xml:space="preserve">BRepMesh_TorusRangeSplitter</text>
+<line clip-path="url(#clipPath82)" fill="none" x1="651" x2="865" y1="1307" y2="1307" stroke="rgb(39,76,114)"/>
+<rect x="902" y="1282" clip-path="url(#clipPath83)" fill="rgb(131,122,133)" width="215" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="903" y="1283" clip-path="url(#clipPath83)" fill="rgb(131,122,133)" width="215" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="901" y="1281" clip-path="url(#clipPath84)" fill="white" width="215" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="901" y="1281" clip-path="url(#clipPath84)" fill="none" width="214" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath85)" preserveAspectRatio="none" height="16" x="907" y="1286" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="926" y="1299" clip-path="url(#clipPath86)" fill="black" stroke="none" xml:space="preserve">BRepMesh_NURBSRangeSplitter</text>
+<line clip-path="url(#clipPath87)" fill="none" x1="902" x2="1115" y1="1307" y2="1307" stroke="rgb(39,76,114)"/>
+<rect x="854" y="1415" clip-path="url(#clipPath88)" fill="rgb(131,122,133)" width="263" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="855" y="1416" clip-path="url(#clipPath88)" fill="rgb(131,122,133)" width="263" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="853" y="1414" clip-path="url(#clipPath89)" fill="white" width="263" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="853" y="1414" clip-path="url(#clipPath89)" fill="none" width="262" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath90)" preserveAspectRatio="none" height="16" x="857" y="1419" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="876" y="1432" clip-path="url(#clipPath91)" fill="black" stroke="none" xml:space="preserve">BRepMesh_BoundaryParamsRangeSplitter</text>
+<line clip-path="url(#clipPath92)" fill="none" x1="854" x2="1115" y1="1440" y2="1440" stroke="rgb(39,76,114)"/>
+<line clip-path="url(#clipPath49)" fill="none" x1="38" x2="134" y1="971" y2="971" stroke="rgb(39,76,114)"/>
+<line clip-path="url(#clipPath49)" fill="none" x1="134" x2="134" y1="971" y2="971" stroke="rgb(39,76,114)"/>
+<line clip-path="url(#clipPath49)" fill="none" x1="134" x2="139" y1="971" y2="966" stroke="rgb(39,76,114)"/>
+<line clip-path="url(#clipPath49)" fill="none" x1="139" x2="139" y1="966" y2="966" stroke="rgb(39,76,114)"/>
+<line clip-path="url(#clipPath49)" fill="none" x1="139" x2="139" y1="966" y2="945" stroke="rgb(39,76,114)"/>
+<rect x="292" y="323" clip-path="url(#clipPath93)" fill="rgb(131,122,133)" width="229" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="293" y="324" clip-path="url(#clipPath93)" fill="rgb(131,122,133)" width="229" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="291" y="322" clip-path="url(#clipPath94)" fill="white" width="229" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="291" y="322" clip-path="url(#clipPath94)" fill="none" width="228" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath95)" preserveAspectRatio="none" height="16" x="323" y="327" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="342" y="340" clip-path="url(#clipPath96)" fill="black" stroke="none" xml:space="preserve">BRepMesh_BaseMeshAlgo</text>
+<line clip-path="url(#clipPath97)" fill="none" x1="292" x2="519" y1="348" y2="348" stroke="rgb(39,76,114)"/>
+<rect x="824" y="323" clip-path="url(#clipPath98)" fill="rgb(131,122,133)" width="241" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="825" y="324" clip-path="url(#clipPath98)" fill="rgb(131,122,133)" width="241" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="823" y="322" clip-path="url(#clipPath99)" fill="white" width="241" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="823" y="322" clip-path="url(#clipPath99)" fill="none" width="240" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath100)" preserveAspectRatio="none" height="16" x="835" y="327" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="854" y="340" clip-path="url(#clipPath101)" fill="black" stroke="none" xml:space="preserve">BRepMesh_DataStructureOfDelaun</text>
+<line clip-path="url(#clipPath102)" fill="none" x1="824" x2="1063" y1="348" y2="348" stroke="rgb(39,76,114)"/>
+<rect x="278" y="623" clip-path="url(#clipPath103)" fill="rgb(131,122,133)" width="258" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="279" y="624" clip-path="url(#clipPath103)" fill="rgb(131,122,133)" width="258" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="277" y="622" clip-path="url(#clipPath104)" fill="white" width="258" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="277" y="622" clip-path="url(#clipPath104)" fill="none" width="257" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath105)" preserveAspectRatio="none" height="16" x="295" y="634" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="314" y="640" clip-path="url(#clipPath106)" fill="black" stroke="none" xml:space="preserve">BRepMesh_NodeInsertionMeshAlgo </text>
+<text x="314" y="655" clip-path="url(#clipPath107)" fill="black" stroke="none" xml:space="preserve"><RangeSplitter, BaseClass></text>
+<line clip-path="url(#clipPath108)" fill="none" x1="278" x2="534" y1="662" y2="662" stroke="rgb(39,76,114)"/>
+<line clip-path="url(#clipPath13)" fill="none" x1="14" x2="134" y1="192" y2="192" stroke="rgb(39,76,114)"/>
+<line clip-path="url(#clipPath13)" fill="none" x1="134" x2="134" y1="192" y2="192" stroke="rgb(39,76,114)"/>
+<line clip-path="url(#clipPath13)" fill="none" x1="134" x2="139" y1="192" y2="187" stroke="rgb(39,76,114)"/>
+<line clip-path="url(#clipPath13)" fill="none" x1="139" x2="139" y1="187" y2="187" stroke="rgb(39,76,114)"/>
+<line clip-path="url(#clipPath13)" fill="none" x1="139" x2="139" y1="187" y2="166" stroke="rgb(39,76,114)"/>
+<rect x="794" y="11" clip-path="url(#clipPath109)" fill="rgb(131,122,133)" width="190" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="795" y="12" clip-path="url(#clipPath109)" fill="rgb(131,122,133)" width="190" rx="2.5" opacity="0.2549" ry="2.5" height="98" stroke="none"/>
+<rect x="793" y="10" clip-path="url(#clipPath110)" fill="white" width="190" rx="2.5" ry="2.5" height="98" stroke="none"/>
+<rect x="793" y="10" clip-path="url(#clipPath110)" fill="none" width="189" rx="2.5" ry="2.5" height="97" stroke="rgb(39,76,114)"/>
+<image stroke="rgb(39,76,114)" width="16" xlink:show="embed" xlink:type="simple" fill="rgb(39,76,114)" clip-path="url(#clipPath111)" preserveAspectRatio="none" height="16" x="813" y="15" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAr0lEQVR42mNkgIKC BUf+P3jyCchiBOL/QMgIYTFCREDg/38GOFCU4WWYkGDDyAITuP/4E8OkNDsGYkHu rINgGm7Av7//GNjZmIk2gOHff1QDwBxmJgZSAZoBjJQZwEqRC4BBzEqCC/6hh8H/ //8YmJmIN+D/fyyB6NewCZwO/qORMIBIIUA2IyOmAUsrvIh2QUzndjBNeqjhiwWY qWQbsKTccwC9oKIkTJIXQOqpAgBzFjJ6SnHW0gAAAABJRU5ErkJggg==" xlink:actuate="onLoad"/>
+<text x="832" y="28" clip-path="url(#clipPath112)" fill="black" stroke="none" xml:space="preserve">BRepMesh_FaceDiscret</text>
+<line clip-path="url(#clipPath113)" fill="none" x1="794" x2="982" y1="36" y2="36" stroke="rgb(39,76,114)"/>
+</g>
+<g stroke-linecap="butt" font-size="11" fill="rgb(69,69,69)" font-family="'Segoe UI'" stroke-dasharray="5,5" stroke="rgb(69,69,69)" stroke-width="1.1">
+<line clip-path="url(#clipPath114)" fill="none" x1="219" x2="375" y1="564" y2="622"/>
+<image x="23" y="598" clip-path="url(#clipPath115)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVR42mNkIALo ebX+R+Zf2lbNCGMzEWMASENTbQhWOaIM2HD85v+65jUMCbF2DGSDvuWH/2PzDkGb CWlgoouzSQLEOBunF2jmbJCL8LoKl7NB4shRB6Nh4mAv4HI2TBzZFbAkDBJHNgTD 2eguQncBjI1iCD5vYaPxasYWBsi2E6WZWAAAvauBMFaKJxwAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="42" y="611" clip-path="url(#clipPath116)" fill="black" stroke="none" xml:space="preserve">RangeSplitter->T, BaseClass->BRepMesh_SweepLineMeshAlgo</text>
+<line clip-path="url(#clipPath117)" fill="none" x1="367" x2="375" y1="622" y2="622" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath117)" fill="none" x1="375" x2="369" y1="622" y2="617" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="661" x2="913" y1="981" y2="876"/>
+<image x="829" y="909" clip-path="url(#clipPath118)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVR42mNkIALo ebX+R+Zf2lbNCGMzEWMASENTbQhWOaIM2HD85v+65jUMCbF2DGSDvuWH/2PzDkGb CWlgoouzSQLEOBunF2jmbJCL8LoKl7NB4shRB6Nh4mAv4HI2TBzZFbAkDBJHNgTD 2eguQncBjI1iCD5vYaPxasYWBsi2E6WZWAAAvauBMFaKJxwAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="848" y="922" clip-path="url(#clipPath119)" fill="black" stroke="none" xml:space="preserve">RangeSplitter->RangeSplitter</text>
+<line clip-path="url(#clipPath120)" fill="none" x1="908" x2="913" y1="881" y2="876" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath120)" fill="none" x1="913" x2="905" y1="876" y2="876" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="672" x2="672" y1="1125" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="672" x2="602" y1="1097" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="602" y1="1097" y2="1079" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="602" y1="466" y2="438" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="405" y1="438" y2="438" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="405" x2="405" y1="438" y2="420" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath122)" points=" 405 420 409 428 401 428" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath122)" points=" 405 420 409 428 401 428" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="757" x2="757" y1="1281" y2="1241" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="757" x2="885" y1="1241" y2="1241" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="885" x2="885" y1="1241" y2="1223" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath123)" points=" 885 1223 889 1231 881 1231" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath123)" points=" 885 1223 889 1231 881 1231" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="538" x2="253" y1="981" y2="876"/>
+<image x="128" y="903" clip-path="url(#clipPath124)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVR42mNkIALo ebX+R+Zf2lbNCGMzEWMASENTbQhWOaIM2HD85v+65jUMCbF2DGSDvuWH/2PzDkGb CWlgoouzSQLEOBunF2jmbJCL8LoKl7NB4shRB6Nh4mAv4HI2TBzZFbAkDBJHNgTD 2eguQncBjI1iCD5vYaPxasYWBsi2E6WZWAAAvauBMFaKJxwAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="147" y="916" clip-path="url(#clipPath125)" fill="black" stroke="none" xml:space="preserve">RangeSplitter->RangeSplitter</text>
+<line clip-path="url(#clipPath126)" fill="none" x1="261" x2="253" y1="876" y2="876" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath126)" fill="none" x1="253" x2="259" y1="876" y2="881" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="214" x2="214" y1="466" y2="438" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="214" x2="405" y1="438" y2="438" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="405" x2="405" y1="438" y2="420" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath122)" points=" 405 420 409 428 401 428" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath122)" points=" 405 420 409 428 401 428" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="600" x2="447" y1="564" y2="622"/>
+<image x="435" y="598" clip-path="url(#clipPath127)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVR42mNkIALo ebX+R+Zf2lbNCGMzEWMASENTbQhWOaIM2HD85v+65jUMCbF2DGSDvuWH/2PzDkGb CWlgoouzSQLEOBunF2jmbJCL8LoKl7NB4shRB6Nh4mAv4HI2TBzZFbAkDBJHNgTD 2eguQncBjI1iCD5vYaPxasYWBsi2E6WZWAAAvauBMFaKJxwAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="454" y="611" clip-path="url(#clipPath128)" fill="black" stroke="none" xml:space="preserve">RangeSplitter->T, BaseClass->BRepMesh_DelaunayBaseMeshAlgo</text>
+<line clip-path="url(#clipPath129)" fill="none" x1="452" x2="447" y1="617" y2="622" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath129)" fill="none" x1="447" x2="455" y1="622" y2="622" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1009" x2="1009" y1="1414" y2="1397" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1009" x2="1009" y1="1397" y2="1397" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1009" x2="1009" y1="1397" y2="1379" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath130)" points=" 1009 1379 1013 1387 1005 1387" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath130)" points=" 1009 1379 1013 1387 1005 1387" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="428" x2="428" y1="1125" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="428" x2="602" y1="1097" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="602" y1="1097" y2="1079" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1013" x2="1013" y1="1281" y2="1241" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1013" x2="885" y1="1241" y2="1241" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="885" x2="885" y1="1241" y2="1223" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath123)" points=" 885 1223 889 1231 881 1231" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath123)" points=" 885 1223 889 1231 881 1231" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="793" x2="734" y1="827" y2="827" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="741" x2="734" y1="824" y2="827" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="734" x2="741" y1="827" y2="830" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="218" x2="218" y1="778" y2="738" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="218" x2="407" y1="738" y2="738" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="407" x2="407" y1="738" y2="720" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath132)" points=" 407 720 411 728 403 728" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath132)" points=" 407 720 411 728 403 728" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="590" x2="590" y1="981" y2="876"/>
+<image x="409" y="897" clip-path="url(#clipPath133)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVR42mNkIALo ebX+R+Zf2lbNCGMzEWMASENTbQhWOaIM2HD85v+65jUMCbF2DGSDvuWH/2PzDkGb CWlgoouzSQLEOBunF2jmbJCL8LoKl7NB4shRB6Nh4mAv4HI2TBzZFbAkDBJHNgTD 2eguQncBjI1iCD5vYaPxasYWBsi2E6WZWAAAvauBMFaKJxwAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="428" y="910" clip-path="url(#clipPath134)" fill="black" stroke="none" xml:space="preserve">RangeSplitter->RangeSplitter</text>
+<line clip-path="url(#clipPath135)" fill="none" x1="593" x2="590" y1="883" y2="876" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath135)" fill="none" x1="590" x2="587" y1="876" y2="883" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="520" x2="823" y1="376" y2="376" stroke="rgb(136,136,136)"/>
+<text x="667" y="372" clip-path="url(#clipPath136)" fill="black" stroke="none" xml:space="preserve"><<use>></text>
+<line clip-path="url(#clipPath137)" fill="none" x1="816" x2="823" y1="379" y2="376" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath137)" fill="none" x1="823" x2="816" y1="376" y2="373" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="176" x2="176" y1="1125" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="176" x2="602" y1="1097" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="602" y1="1097" y2="1079" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="896" x2="896" y1="1125" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="896" x2="602" y1="1097" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="602" y1="1097" y2="1079" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="601" x2="601" y1="778" y2="738" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="601" x2="407" y1="738" y2="738" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="407" x2="407" y1="738" y2="720" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath132)" points=" 407 720 411 728 403 728" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath132)" points=" 407 720 411 728 403 728" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="406" x2="406" y1="322" y2="288" stroke="rgb(136,136,136)"/>
+<polygon fill="white" clip-path="url(#clipPath138)" points=" 406 288 410 296 402 296" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath138)" points=" 406 288 410 296 402 296" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1399" x2="1399" y1="346" y2="288" stroke="rgb(136,136,136)"/>
+<polygon fill="white" clip-path="url(#clipPath139)" points=" 1399 288 1403 296 1395 296" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath139)" points=" 1399 288 1403 296 1395 296" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="793" x2="734" y1="827" y2="827" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="741" x2="734" y1="824" y2="827" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath131)" fill="none" x1="734" x2="741" y1="827" y2="830" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1297" x2="1165" y1="398" y2="398" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath140)" fill="none" x1="1172" x2="1165" y1="395" y2="398" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath140)" fill="none" x1="1165" x2="1172" y1="398" y2="401" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="176" x2="176" y1="1125" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="176" x2="602" y1="1097" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="602" y1="1097" y2="1079" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="428" x2="428" y1="1125" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="428" x2="602" y1="1097" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="602" y1="1097" y2="1079" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="672" x2="672" y1="1125" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="672" x2="602" y1="1097" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="602" y1="1097" y2="1079" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="896" x2="896" y1="1125" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="896" x2="602" y1="1097" y2="1097" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="602" y1="1097" y2="1079" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath121)" points=" 602 1079 606 1087 598 1087" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="757" x2="757" y1="1281" y2="1241" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="757" x2="885" y1="1241" y2="1241" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="885" x2="885" y1="1241" y2="1223" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath123)" points=" 885 1223 889 1231 881 1231" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath123)" points=" 885 1223 889 1231 881 1231" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1013" x2="1013" y1="1281" y2="1241" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1013" x2="885" y1="1241" y2="1241" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="885" x2="885" y1="1241" y2="1223" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath123)" points=" 885 1223 889 1231 881 1231" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath123)" points=" 885 1223 889 1231 881 1231" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="538" x2="253" y1="981" y2="876"/>
+<image x="128" y="903" clip-path="url(#clipPath124)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVR42mNkIALo ebX+R+Zf2lbNCGMzEWMASENTbQhWOaIM2HD85v+65jUMCbF2DGSDvuWH/2PzDkGb CWlgoouzSQLEOBunF2jmbJCL8LoKl7NB4shRB6Nh4mAv4HI2TBzZFbAkDBJHNgTD 2eguQncBjI1iCD5vYaPxasYWBsi2E6WZWAAAvauBMFaKJxwAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="147" y="916" clip-path="url(#clipPath125)" fill="black" stroke="none" xml:space="preserve">RangeSplitter->RangeSplitter</text>
+<line clip-path="url(#clipPath126)" fill="none" x1="261" x2="253" y1="876" y2="876" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath126)" fill="none" x1="253" x2="259" y1="876" y2="881" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="590" x2="590" y1="981" y2="876"/>
+<image x="409" y="897" clip-path="url(#clipPath133)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVR42mNkIALo ebX+R+Zf2lbNCGMzEWMASENTbQhWOaIM2HD85v+65jUMCbF2DGSDvuWH/2PzDkGb CWlgoouzSQLEOBunF2jmbJCL8LoKl7NB4shRB6Nh4mAv4HI2TBzZFbAkDBJHNgTD 2eguQncBjI1iCD5vYaPxasYWBsi2E6WZWAAAvauBMFaKJxwAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="428" y="910" clip-path="url(#clipPath134)" fill="black" stroke="none" xml:space="preserve">RangeSplitter->RangeSplitter</text>
+<line clip-path="url(#clipPath135)" fill="none" x1="593" x2="590" y1="883" y2="876" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath135)" fill="none" x1="590" x2="587" y1="876" y2="883" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="661" x2="913" y1="981" y2="876"/>
+<image x="829" y="909" clip-path="url(#clipPath118)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVR42mNkIALo ebX+R+Zf2lbNCGMzEWMASENTbQhWOaIM2HD85v+65jUMCbF2DGSDvuWH/2PzDkGb CWlgoouzSQLEOBunF2jmbJCL8LoKl7NB4shRB6Nh4mAv4HI2TBzZFbAkDBJHNgTD 2eguQncBjI1iCD5vYaPxasYWBsi2E6WZWAAAvauBMFaKJxwAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="848" y="922" clip-path="url(#clipPath119)" fill="black" stroke="none" xml:space="preserve">RangeSplitter->RangeSplitter</text>
+<line clip-path="url(#clipPath120)" fill="none" x1="908" x2="913" y1="881" y2="876" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath120)" fill="none" x1="913" x2="905" y1="876" y2="876" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="828" x2="409" y1="108" y2="190" stroke="rgb(136,136,136)"/>
+<text x="580" y="136" clip-path="url(#clipPath141)" fill="black" stroke="none" xml:space="preserve"><<use>></text>
+<line clip-path="url(#clipPath142)" fill="none" x1="415" x2="409" y1="186" y2="190" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath142)" fill="none" x1="409" x2="416" y1="190" y2="192" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="966" x2="1393" y1="108" y2="190" stroke="rgb(136,136,136)"/>
+<text x="1141" y="142" clip-path="url(#clipPath143)" fill="black" stroke="none" xml:space="preserve"><<use>></text>
+<line clip-path="url(#clipPath144)" fill="none" x1="1386" x2="1393" y1="192" y2="190" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath144)" fill="none" x1="1393" x2="1387" y1="190" y2="186" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="406" x2="406" y1="322" y2="288" stroke="rgb(136,136,136)"/>
+<polygon fill="white" clip-path="url(#clipPath138)" points=" 406 288 410 296 402 296" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath138)" points=" 406 288 410 296 402 296" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="214" x2="214" y1="466" y2="438" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="214" x2="405" y1="438" y2="438" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="405" x2="405" y1="438" y2="420" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath122)" points=" 405 420 409 428 401 428" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath122)" points=" 405 420 409 428 401 428" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="520" x2="823" y1="376" y2="376" stroke="rgb(136,136,136)"/>
+<text x="667" y="372" clip-path="url(#clipPath136)" fill="black" stroke="none" xml:space="preserve"><<use>></text>
+<line clip-path="url(#clipPath137)" fill="none" x1="816" x2="823" y1="379" y2="376" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath137)" fill="none" x1="823" x2="816" y1="376" y2="373" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="602" y1="466" y2="438" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="602" x2="405" y1="438" y2="438" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="405" x2="405" y1="438" y2="420" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath122)" points=" 405 420 409 428 401 428" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath122)" points=" 405 420 409 428 401 428" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="600" x2="447" y1="564" y2="622"/>
+<image x="435" y="598" clip-path="url(#clipPath127)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVR42mNkIALo ebX+R+Zf2lbNCGMzEWMASENTbQhWOaIM2HD85v+65jUMCbF2DGSDvuWH/2PzDkGb CWlgoouzSQLEOBunF2jmbJCL8LoKl7NB4shRB6Nh4mAv4HI2TBzZFbAkDBJHNgTD 2eguQncBjI1iCD5vYaPxasYWBsi2E6WZWAAAvauBMFaKJxwAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="454" y="611" clip-path="url(#clipPath128)" fill="black" stroke="none" xml:space="preserve">RangeSplitter->T, BaseClass->BRepMesh_DelaunayBaseMeshAlgo</text>
+<line clip-path="url(#clipPath129)" fill="none" x1="452" x2="447" y1="617" y2="622" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath129)" fill="none" x1="447" x2="455" y1="622" y2="622" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="219" x2="375" y1="564" y2="622"/>
+<image x="23" y="598" clip-path="url(#clipPath115)" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVR42mNkIALo ebX+R+Zf2lbNCGMzEWMASENTbQhWOaIM2HD85v+65jUMCbF2DGSDvuWH/2PzDkGb CWlgoouzSQLEOBunF2jmbJCL8LoKl7NB4shRB6Nh4mAv4HI2TBzZFbAkDBJHNgTD 2eguQncBjI1iCD5vYaPxasYWBsi2E6WZWAAAvauBMFaKJxwAAAAASUVORK5CYII=" xlink:type="simple" xlink:actuate="onLoad" height="16" preserveAspectRatio="none" xlink:show="embed"/>
+<text x="42" y="611" clip-path="url(#clipPath116)" fill="black" stroke="none" xml:space="preserve">RangeSplitter->T, BaseClass->BRepMesh_SweepLineMeshAlgo</text>
+<line clip-path="url(#clipPath117)" fill="none" x1="367" x2="375" y1="622" y2="622" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath117)" fill="none" x1="375" x2="369" y1="622" y2="617" stroke-dasharray="none"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="218" x2="218" y1="778" y2="738" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="218" x2="407" y1="738" y2="738" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="407" x2="407" y1="738" y2="720" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath132)" points=" 407 720 411 728 403 728" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath132)" points=" 407 720 411 728 403 728" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="601" x2="601" y1="778" y2="738" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="601" x2="407" y1="738" y2="738" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="407" x2="407" y1="738" y2="720" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath132)" points=" 407 720 411 728 403 728" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath132)" points=" 407 720 411 728 403 728" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1009" x2="1009" y1="1414" y2="1397" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1009" x2="1009" y1="1397" y2="1397" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<line clip-path="url(#clipPath114)" fill="none" x1="1009" x2="1009" y1="1397" y2="1379" stroke-dasharray="none" stroke="rgb(136,136,136)"/>
+<polygon fill="white" stroke-dasharray="none" clip-path="url(#clipPath130)" points=" 1009 1379 1013 1387 1005 1387" stroke="none"/>
+<polygon fill="none" stroke-dasharray="none" clip-path="url(#clipPath130)" points=" 1009 1379 1013 1387 1005 1387" stroke="rgb(136,136,136)"/>
+</g>
+</g>
+</svg>
The algorithm of shape triangulation is provided by the functionality of *BRepMesh_IncrementalMesh* class, which adds a triangulation of the shape to its topological data structure. This triangulation is used to visualize the shape in shaded mode.
~~~~~
-const Standard_Real aRadius = 10.0;
-const Standard_Real aHeight = 25.0;
-BRepPrimAPI_MakeCylinder aCylinder(aRadius, aHeight);
-TopoDS_Shape aShape = aCylinder.Shape();
-
-const Standard_Real aLinearDeflection = 0.01;
-const Standard_Real anAngularDeflection = 0.5;
+#include <IMeshData_Status.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <BRepMesh_IncrementalMesh.hxx>
-BRepMesh_IncrementalMesh aMesh(aShape, aLinearDeflection, Standard_False, anAngularDeflection);
+Standard_Boolean meshing_explicit_parameters()
+{
+ const Standard_Real aRadius = 10.0;
+ const Standard_Real aHeight = 25.0;
+ BRepPrimAPI_MakeCylinder aCylinder(aRadius, aHeight);
+ TopoDS_Shape aShape = aCylinder.Shape();
+
+ const Standard_Real aLinearDeflection = 0.01;
+ const Standard_Real anAngularDeflection = 0.5;
+ BRepMesh_IncrementalMesh aMesher (aShape, aLinearDeflection, Standard_False, anAngularDeflection, Standard_True);
+ const Standard_Integer aStatus = aMesher.GetStatusFlags();
+ return !aStatus;
+}
+
+Standard_Boolean meshing_imeshtools_parameters()
+{
+ const Standard_Real aRadius = 10.0;
+ const Standard_Real aHeight = 25.0;
+ BRepPrimAPI_MakeCylinder aCylinder(aRadius, aHeight);
+ TopoDS_Shape aShape = aCylinder.Shape();
+
+ IMeshTools_Parameters aMeshParams;
+ aMeshParams.Deflection = 0.01;
+ aMeshParams.Angle = 0.5;
+ aMeshParams.Relative = Standard_False;
+ aMeshParams.InParallel = Standard_True;
+ aMeshParams.MinSize = Precision::Confusion();
+ aMeshParams.InternalVerticesMode = Standard_True;
+ aMeshParams.ControlSurfaceDeflection = Standard_True;
+
+ BRepMesh_IncrementalMesh aMesher (aShape, aMeshParams);
+ const Standard_Integer aStatus = aMesher.GetStatusFlags();
+ return !aStatus;
+}
~~~~~
The default meshing algorithm *BRepMesh_IncrementalMesh* has two major options to define triangulation -- linear and angular deflections.
You can obtain information on the shape by first exploring it. To access triangulation of a face in the shape later, use *BRepTool::Triangulation*. To access a polygon, which is the approximation of an edge of the face, use *BRepTool::PolygonOnTriangulation*.
+@subsection occt_modalg_11_3 BRepMesh Architecture
+@subsubsection occt_modalg_11_3_1 Goals
+
+The main goals of the chosen architecture are:
+ * Remove tight connections between data structures, auxiliary tools and algorithms in order to create an extensible solution, easy for maintenance and improvements;
+ * Separate the code among several functional units responsible for specific operation for the sake of simplification of debugging and readability;
+ * Introduce new data structures enabling the possibility to manipulate a discrete model of a particular entity (edge, wire, face) in order to perform computations locally instead of processing an entire model;
+ * Implement a new triangulation algorithm replacing existing functionality that contains too complicated solutions that need to be moved to the upper level. In addition, provide the possibility to change algorithm depending on surface type (initially to speed up meshing of planes).
+
+@subsubsection occt_modalg_11_3_2 General workflow
+@figure{/user_guides/modeling_algos/images/modeling_algos_mesh_001.svg,"General workflow of BRepMesh component",500}
+
+Generally, the workflow of the component can be divided on six parts:
+ * **Creation of model data structure**: source *TopoDS_Shape* passed to algorithm is analyzed and exploded on faces and edges. The reflection corresponding to each topological entity is created in the data model. Note that underlying algorithms use the data model as input and access it via a common interface which allows creating a custom data model with necessary dependencies between particular entities (see the paragraph "Data model interface");
+ * **Discretize edges 3D & 2D curves**: 3D curve as well as an associated set of 2D curves of each model edge is discretized in order to create a coherent skeleton used as a base in face meshing process. If an edge of the source shape already contains polygonal data which suits the specified parameters, it is extracted from the shape and stored in the model as is. Each edge is processed separately, adjacency is not taken into account;
+ * **Heal discrete model**: the source *TopoDS_Shape* can contain problems, such as open wires or self-intersections, introduced during design, exchange or modification of model. In addition, some problems like self-intersections can be introduced by roughly discretized edges. This stage is responsible for analysis of a discrete model in order to detect and repair problems or to refuse further processing of a model part in case if a problem cannot be solved;
+ * **Preprocess discrete model**: defines actions specific to the implemented approach to be performed before meshing of faces. By default, this operation iterates over model faces, checks the consistency of existing triangulations and cleans topological faces and adjacent edges from polygonal data in case of inconsistency or marks a face of the discrete model as not required for the computation;
+ * **Discretize faces**: represents the core part performing mesh generation for a particular face based on 2D discrete data. This operation caches polygonal data associated with face edges in the data model for further processing and stores the generated mesh to *TopoDS_Face*;
+ * **Postprocess discrete model**: defines actions specific for the implemented approach to be performed after meshing of faces. By default, this operation stores polygonal data obtained at the previous stage to *TopoDS_Edge* objects of the source model.
+
+@subsubsection occt_modalg_11_3_3 Common interfaces
+The component structure contains two units: <i>IMeshData</i> (see Data model interface) and <i>IMeshTools</i>, defining common interfaces for the data model and algorithmic tools correspondingly. Class *IMeshTools_Context* represents a connector between these units. The context class caches the data model as well as the tools corresponding to each of six stages of the workflow mentioned above and provides methods to call the corresponding tool safely (designed similarly to *IntTools_Context* in order to keep consistency with OCCT core tools). All stages, except for the first one use data model as input and perform a specific action on the entire structure. Thus, API class *IMeshTools_ModelAlgo* is defined in order to unify the interface of tools manipulating the data model. Each tool supposed to process the data model should inherit this interface enabling the possibility to cache it in context. In contrast to others, the model builder interface is defined by another class *IMeshTools_ModelBuilder* due to a different meaning of the stage. The entry point starting the entire workflow is represented by *IMeshTools_MeshBuilder*.
+
+The default implementation of *IMeshTools_Context* is given in *BRepMesh_Context* class initializing the context by instances of default algorithmic tools.
+
+The factory interface *IMeshTools_MeshAlgoFactory* gives the possibility to change the triangulation algorithm for a specific surface. The factory returns an instance of the triangulation algorithm via *IMeshTools_MeshAlgo* interface depending on the type of surface passed as parameter. It is supposed to be used at the face discretization stage.
+
+The default implementation of AlgoFactory is given in *BRepMesh_MeshAlgoFactory* returning algorithms of different complexity chosen according to the passed surface type. In its turn, it is used as the initializer of *BRepMesh_FaceDiscret* algorithm representing the starter of face discretization stage.
+
+@figure{/user_guides/modeling_algos/images/modeling_algos_mesh_002.svg,"Interface describing entry point to meshing workflow",500}
+
+Remaining interfaces describe auxiliary tools:
+ * *IMeshTools_CurveTessellator*: provides a common interface to the algorithms responsible for creation of discrete polygons on 3D and 2D curves as well as tools for extraction of existing polygons from *TopoDS_Edge* allowing to obtain discrete points and the corresponding parameters on curve regardless of the implementation details (see examples of usage of derived classes *BRepMesh_CurveTessellator*, *BRepMesh_EdgeTessellationExtractor* in *BRepMesh_EdgeDiscret*);
+ * *IMeshTools_ShapeExplorer*: the last two interfaces represent visitor design pattern and are intended to separate iteration over elements of topological shape (edges and faces) from the operations performed on a particular element;
+ * *IMeshTools_ShapeVisitor*: provides a common interface for operations on edges and faces of the target topological shape. It can be used in couple with *IMeshTools_ShapeExplorer*. The default implementation available in *BRepMesh_ShapeVisitor* performs initialization of the data model. The advantage of such approach is that the implementation of *IMeshTools_ShapeVisitor* can be changed according to the specific data model whereas the shape explorer implementation remains the same.
+
+@subsubsection occt_modalg_11_3_4 Create model data structure
+The data structures intended to keep discrete and temporary data required by underlying algorithms are created at the first stage of the meshing procedure. Generally, the model represents dependencies between entities of the source topological shape suitable for the target task.
+
+#### Data model interface
+Unit <i>IMeshData</i> provides common interfaces specifying the data model API used on different stages of the entire workflow. Dependencies and references of the designed interfaces are given in the figure below. A specific interface implementation depends on the target application which allows the developer to implement different models and use custom low-level data structures, e.g. different collections, either <i>NCollection</i> or STL. *IMeshData_Shape* is used as the base class for all data structures and tools keeping the topological shape in order to avoid possible copy-paste.
+
+The default implementation of interfaces is given in <i>BRepMeshData</i> unit. The main aim of the default data model is to provide features performing discretization of edges in a parallel mode. Thus, curve, pcurve and other classes are based on STL containers and smart-pointers as far as <i>NCollection</i> does not provide thread-safety for some cases (e.g. *NCollection_Sequence*). In addition, it closely reflects topology of the source shape, i.e. the number of edges in the data model is equal to the number of edges in the source model; each edge contains a set of pcurves associated with its adjacent faces which allows creation of discrete polygons for all pcurves or the 3D curve of a particular edge in a separate thread.
+
+**Advantages**:
+In case of necessity, the data model (probably with algorithms for its processing) can be easily substituted by another implementation supporting another kind of dependencies between elements.
+
+An additional example of a different data model is the case when it is not required to create a mesh with discrete polygons synchronized between adjacent faces, i.e. in case of necessity to speed up creation of a rough per-face tessellation used for visualization or quick computation only (the approach used in *XDEDRAW_Props*).
+
+@figure{/user_guides/modeling_algos/images/modeling_algos_mesh_003.svg,"Common API of data model",500}
+
+#### Collecting data model
+At this stage the data model is filled by entities according to the topological structure of the source shape. A default implementation of the data model is given in <i>BRepMeshData</i> unit and represents the model as two sets: a set of edges and a set of faces. Each face consists of one or several wires, the first of which always represents the outer wire, while others are internal. In its turn, each wire depicts the ordered sequence of oriented edges. Each edge is characterized by a single 3D curve and zero (in case of free edge) or more 2D curves associated with faces adjacent to this edge. Both 3D and 2D curves represent a set of pairs point-parameter defined in 3D and 2D space of the reference face correspondingly. An additional difference between a curve and a pcurve is that the latter has a reference to the face it is defined for.
+
+Model filler algorithm is represented by *BRepMesh_ShapeVisitor* class creating the model as a reflection to topological shape with help of *BRepMesh_ShapeExplorer* performing iteration over edges and faces of the target shape. Note that the algorithm operates on a common interface of the data model and creates a structure without any knowledge about the implementation details and underlying data structures. The entry point to collecting functionality is *BRepMesh_ModelBuilder* class.
+
+@subsubsection occt_modalg_11_3_5 Discretize edges 3D & 2D curves
+At this stage only the edges of the data model are considered. Each edge is processed separately (with the possibility to run processing in multiple threads). The edge is checked for existing polygonal data. In case if at least one representation exists and suits the meshing parameters, it is recuperated and used as reference data for tessellation of the whole set of pcurves as well as 3D curve assigned to the edge (see *BRepMesh_EdgeTessellationExtractor*). Otherwise, a new tessellation algorithm is created and used to generate the initial polygon (see *BRepMesh_CurveTessellator*) and the edge is marked as outdated. In addition, the model edge is updated by deflection as well as recomputed same range, same parameter and degeneracy parameters. See *BRepMesh_EdgeDiscret* for implementation details.
+
+<i>IMeshData</i> unit defines interface *IMeshData_ParametersListArrayAdaptor*, which is intended to adapt arbitrary data structures to the *NCollection_Array1* container API. This solution is made to use both *NCollection_Array1* and *IMeshData_Curve* as the source for *BRepMesh_EdgeParameterProvider* tool intended to generate a consistent parametrization taking into account the same parameter property.
+
+@subsubsection occt_modalg_11_3_6 Heal discrete model
+In general, this stage represents a set of operations performed on the entire discrete model in order to resolve inconsistencies due to the problems caused by design, translation or rough discretization. A different sequence of operations can be performed depending on the target triangulation algorithm, e.g. there are different approaches to process self-intersections – either to amplify edges discretization by decreasing the target precision or to split links at the intersection points. At this stage the whole set of edges is considered in aggregate and their adjacency is taken into account. A default implementation of the model healer is given in *BRepMesh_ModelHealer* which performs the following actions:
+ * Iterates over model faces and checks their wires for consistency, i.e. whether the wires are closed and do not contain self-intersections. The data structures are designed free of collisions, thus it is possible to run processing in a parallel mode;
+ * Forcibly connects the ends of adjacent edges in the parametric space, closing gaps between possible disconnected parts. The aim of this operation is to create a correct discrete model defined relatively to the parametric space of the target face taking into account connectivity and tolerances of 3D space only. This means that no specific computations are made to determine U and V tolerance;
+ * Registers intersections on edges forming the face shape. Two solutions are possible in order to resolve self-intersection:
+ * Decrease deflection of a particular edge and update its discrete model. After that the workflow "intersection check – amplification" is repeated up to 5 times. As the result, target edges contain a finer tessellation and meshing continues or the face is marked by *IMeshData_SelfIntersectingWire* status and refused from further processing;
+ * Split target edges by intersection point and synchronize the updated polygon with curve and remaining pcurves associated to each edge. This operation presents a more robust solution comparing to the amplification procedure with a guaranteed result, but it is more difficult for implementation from the point of view of synchronization functionality.
+
+@subsubsection occt_modalg_11_3_7 Preprocess discrete model
+This stage implements actions to be performed before meshing of faces. Depending on target goals it can be changed or omitted. By default, *BRepMesh_ModelPreProcessor* implements the functionality checking topological faces for consistency of existing triangulation, i.e.: consistency with the target deflection parameter; indices of nodes referenced by triangles do not exceed the number of nodes stored in a triangulation. If the face fails some checks, it is cleaned from triangulation and its adjacent edges are cleaned from existing polygons. This does not affect a discrete model and does not require any recomputation as the model keeps tessellations for the whole set of edges despite consistency of their polygons.
+
+@subsubsection occt_modalg_11_3_8 Discretize faces
+Discretization of faces is the general part of meshing algorithm. At this stage edges tessellation data obtained and processed on previous steps is used to form contours of target faces and passed as input to the triangulation algorithm. Default implementation is provided by *BRepMesh_FaceDiscret* class which represents a starter for triangulation algorithm. It iterates over faces available in the data model, creates an instance of the triangulation algorithm according to the type of surface associated with each face via *IMeshTools_MeshAlgoFactory* and executes it. Each face is processed separately, thus it is possible to process faces in a parallel mode. The class diagram of face discretization is given in the figure below.
+
+@figure{/user_guides/modeling_algos/images/modeling_algos_mesh_004.svg,"Class diagram of face discrete stage",300}
+
+In general, face meshing algorithms have the following structure:
+ * *BRepMesh_BaseMeshAlgo* implements *IMeshTools_MeshAlgo* interface and the base functionality for inherited algorithms. The main goal of this class is to initialize an instance of *BRepMesh_DataStructureOfDelaun* as well as auxiliary data structures suitable for nested algorithms using face model data passed as input parameter. Despite implementation of triangulation algorithm this structure is currently supposed as common for OCCT. However, the user is free to implement a custom algorithm and supporting data structure accessible via *IMeshTools_MeshAlgo* interface, e.g. to connect a 3-rd party meshing tool that does not support *TopoDS_Shape* out of box. For this, such structure provides the possibility to distribute connectors to various algorithms in the form of plugins;
+ * *BRepMesh_DelaunayBaseMeshAlgo* and *BRepMesh_SweepLineMeshAlgo* classes implement core meshing functionality operating directly on an instance of *BRepMesh_DataStructureOfDelaun*. The algorithms represent mesh generation tools adding new points from the data structure to the final mesh;
+ * *BRepMesh_NodeInsertionMeshAlgo* class represents a wrapper intended to extend the algorithm inherited from *BRepMesh_BaseMeshAlgo* to enable the functionality generating surface nodes and inserting them into the structure. On this level, an instance of the classification tool is created and can be used to accept-reject internal nodes. In addition, computations necessary for scaling UV coordinates of points relatively to the range specified for the corresponding direction are performed. As far as both triangulation algorithms work on static data provided by the structure, new nodes are added at the initialization stage. Surface nodes are generated by an auxiliary tool called range splitter and passed as template parameter (see Range splitter);
+ * Classes *BRepMesh_DelaunayNodeInsertionMeshAlgo* and *BRepMesh_SweepLineNodeInsertionMeshAlgo* implement algorithm-specific functionality related to addition of internal nodes supplementing functionality provided by *BRepMesh_NodeInsertionMeshAlgo*;
+ * *BRepMesh_DelaunayDeflectionControlMeshAlgo* extends functionality of *BRepMesh_DelaunayNodeInsertionMeshAlgo* by additional procedure controlling deflection of generated triangles.
+
+#### Range splitter
+Range splitter tools provide functionality to generate internal surface nodes defined within the range computed using discrete model data. The base functionality is provided by *BRepMesh_DefaultRangeSplitter* which can be used without modifications in case of planar surface. The default splitter does not generate any internal node.
+
+*BRepMesh_ConeRangeSplitter*, *BRepMesh_CylinderRangeSplitter* and *BRepMesh_SphereRangeSplitter* are specializations of the default splitter intended for quick generation of internal nodes for the corresponding type of analytical surface.
+
+*BRepMesh_UVParamRangeSplitter* implements base functionality taking discretization points of face border into account for node generation. Its successors BRepMesh_TorusRangeSplitter and *BRepMesh_NURBSRangeSplitter* extend the base functionality for toroidal and NURBS surfaces correspondingly.
+
+@subsubsection occt_modalg_11_3_9 Postprocess discrete model
+This stage implements actions to be performed after meshing of faces. Depending on target goals it can be changed or omitted. By default, *BRepMesh_ModelPostProcessor* commits polygonal data stored in the data model to *TopoDS_Edge*.
+
@section occt_modalg_defeaturing 3D Model Defeaturing
Handle(BRepMesh_DataStructureOfDelaun) aMeshStructure = new BRepMesh_DataStructureOfDelaun(anAllocator);
Standard_Integer aPtsLower = myPoints.Lower();
Standard_Integer aPtsUpper = myPoints.Upper();
- BRepMesh::Array1OfInteger anIndexes (0, myPoints.Length() - 1);
+ IMeshData::VectorOfInteger anIndexes (myPoints.Length(), anAllocator);
for (Standard_Integer aPtIdx = aPtsLower; aPtIdx <= aPtsUpper; ++aPtIdx)
{
gp_XY aP ((Standard_Real)myPoints.Value (aPtIdx).x(),
(Standard_Real)myPoints.Value (aPtIdx).y());
BRepMesh_Vertex aVertex (aP, aPtIdx, BRepMesh_Frontier);
- anIndexes.ChangeValue (aPtIdx - aPtsLower) = aMeshStructure->AddNode (aVertex);
+ anIndexes.Append (aMeshStructure->AddNode (aVertex));
}
Standard_Real aPtSum = 0;
}
BRepMesh_Delaun aTriangulation (aMeshStructure, anIndexes);
- const BRepMesh::MapOfInteger& aTriangles = aMeshStructure->ElementsOfDomain();
+ const IMeshData::MapOfInteger& aTriangles = aMeshStructure->ElementsOfDomain();
if (aTriangles.Extent() < 1)
return Standard_False;
}
Standard_Integer aVertexIndex = 1;
- BRepMesh::MapOfInteger::Iterator aTriangleIt (aTriangles);
+ IMeshData::IteratorOfMapOfInteger aTriangleIt (aTriangles);
for (; aTriangleIt.More(); aTriangleIt.Next())
{
const Standard_Integer aTriangleId = aTriangleIt.Key();
+++ /dev/null
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef _BRepMesh_HeaderFile
-#define _BRepMesh_HeaderFile
-
-#include <gp_Pnt.hxx>
-#include <gp_XYZ.hxx>
-#include <gp_XY.hxx>
-#include <Bnd_B2d.hxx>
-#include <Bnd_Box2d.hxx>
-#include <Standard.hxx>
-#include <NCollection_List.hxx>
-#include <NCollection_Map.hxx>
-#include <NCollection_Vector.hxx>
-#include <NCollection_Handle.hxx>
-#include <NCollection_DataMap.hxx>
-#include <NCollection_IndexedMap.hxx>
-#include <NCollection_IndexedDataMap.hxx>
-#include <NCollection_Array1.hxx>
-#include <NCollection_Sequence.hxx>
-#include <NCollection_CellFilter.hxx>
-#include <NCollection_IncAllocator.hxx>
-#include <NCollection_EBTree.hxx>
-#include <NCollection_UBTreeFiller.hxx>
-#include <BRepMesh_Edge.hxx>
-#include <BRepMesh_Triangle.hxx>
-#include <BRepMesh_PairOfPolygon.hxx>
-#include <BRepMesh_PairOfIndex.hxx>
-#include <BRepMesh_Circle.hxx>
-#include <TopTools_ShapeMapHasher.hxx>
-#include <TopoDS_Face.hxx>
-#include <TopoDS_Shape.hxx>
-
-#include <vector>
-
-class BRepMesh_Vertex;
-class TopoDS_Edge;
-class TopoDS_Vertex;
-class BRepMesh_FaceAttribute;
-class BRepMesh_VertexInspector;
-class BRepMesh_CircleInspector;
-class BRepMesh_Classifier;
-class Poly_Triangulation;
-class BRepMesh_VertexTool;
-
-namespace BRepMesh
-{
- //! Default size for memory block allocated by IncAllocator.
- /**
- * The idea here is that blocks of the given size are returned to the system
- * rather than retained in the malloc heap, at least on WIN32 and WIN64 platforms.
- */
-#ifdef _WIN64
- const size_t MEMORY_BLOCK_SIZE_HUGE = 1024 * 1024;
-#else
- const size_t MEMORY_BLOCK_SIZE_HUGE = 512 * 1024;
-#endif
-
- //! Structure keeping parameters of segment.
- struct Segment
- {
- gp_XY StartPnt;
- gp_XY EndPnt;
- };
-
- //! Sequences
- typedef NCollection_Sequence<Bnd_B2d> SequenceOfBndB2d;
- typedef NCollection_Sequence<Standard_Integer> SequenceOfInteger;
- typedef NCollection_Sequence<Standard_Real> SequenceOfReal;
-
- //! Vectors
- typedef NCollection_Vector<BRepMesh_Vertex> VectorOfVertex;
- typedef NCollection_Vector<Standard_Integer> VectorOfInteger;
- typedef NCollection_Vector<BRepMesh_Circle> VectorOfCircle;
-
- //! Trees
- typedef NCollection_EBTree<Standard_Integer, Bnd_Box2d> BndBox2dTree;
- typedef NCollection_UBTreeFiller<Standard_Integer, Bnd_Box2d> BndBox2dTreeFiller;
-
- //! Arrays
- typedef NCollection_Array1<BRepMesh_Vertex> Array1OfVertexOfDelaun;
- typedef NCollection_Array1<Standard_Integer> Array1OfInteger;
- typedef NCollection_Array1<Standard_Real> Array1OfReal;
- typedef NCollection_Array1<Segment> Array1OfSegments;
-
- //! Lists
- typedef NCollection_List<gp_XY> ListOfXY;
- typedef NCollection_List<BRepMesh_Vertex> ListOfVertex;
- typedef NCollection_List<Standard_Integer> ListOfInteger;
-
- //! Maps
- typedef NCollection_Map<Standard_Real> MapOfReal;
- typedef NCollection_Map<Standard_Integer> MapOfInteger;
- typedef NCollection_DataMap<Handle(Poly_Triangulation), Standard_Boolean> DMapOfTriangulationBool;
- typedef NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> MapOfShape;
-
- typedef NCollection_DataMap<Standard_Integer, Standard_Integer> MapOfIntegerInteger;
- typedef NCollection_DataMap<TopoDS_Vertex, Standard_Integer, TopTools_ShapeMapHasher> DMapOfVertexInteger;
- typedef NCollection_DataMap<TopoDS_Face, Handle(BRepMesh_FaceAttribute), TopTools_ShapeMapHasher> DMapOfFaceAttribute;
- typedef NCollection_DataMap<TopoDS_Shape, BRepMesh_PairOfPolygon, TopTools_ShapeMapHasher> DMapOfShapePairOfPolygon;
- typedef NCollection_DataMap<Standard_Integer, gp_Pnt> DMapOfIntegerPnt;
- typedef NCollection_DataMap<Standard_Integer, ListOfXY> DMapOfIntegerListOfXY;
- typedef NCollection_DataMap<Standard_Integer, ListOfInteger> DMapOfIntegerListOfInteger;
- typedef NCollection_DataMap<TopoDS_Edge, DMapOfTriangulationBool, TopTools_ShapeMapHasher> DMapOfEdgeListOfTriangulationBool;
-
- typedef NCollection_IndexedMap<Standard_Integer> IMapOfInteger;
- typedef NCollection_IndexedMap<Standard_Real> IMapOfReal;
- typedef NCollection_IndexedMap<BRepMesh_Triangle> IMapOfElement;
- typedef NCollection_IndexedDataMap<BRepMesh_Edge, BRepMesh_PairOfIndex> IDMapOfLink;
-
- //! CellFilters
- typedef NCollection_CellFilter<BRepMesh_CircleInspector> CircleCellFilter;
- typedef NCollection_CellFilter<BRepMesh_VertexInspector> VertexCellFilter;
-
- //! Handles
- typedef NCollection_Handle<VectorOfVertex> HVectorOfVertex;
- typedef NCollection_Handle<MapOfInteger> HMapOfInteger;
- typedef NCollection_Handle<IMapOfInteger> HIMapOfInteger;
- typedef NCollection_Handle<DMapOfShapePairOfPolygon> HDMapOfShapePairOfPolygon;
- typedef NCollection_Handle<DMapOfIntegerPnt> HDMapOfIntegerPnt;
- typedef NCollection_Handle<BRepMesh_Classifier> HClassifier;
- typedef NCollection_Handle<BndBox2dTree> HBndBox2dTree;
- typedef NCollection_Handle<Array1OfSegments> HArray1OfSegments;
- typedef NCollection_Handle<DMapOfVertexInteger> HDMapOfVertexInteger;
- typedef NCollection_Handle<DMapOfIntegerListOfXY> HDMapOfIntegerListOfXY;
- typedef NCollection_Handle<BRepMesh_VertexTool> HVertexTool;
- typedef NCollection_Handle<SequenceOfBndB2d> HSequenceOfBndB2d;
- typedef NCollection_Handle<SequenceOfInteger> HSequenceOfInteger;
-
- //! Other data structures
- typedef std::pair<HArray1OfSegments, HBndBox2dTree> SegmentsTree;
- typedef NCollection_Array1<SegmentsTree> Array1OfSegmentsTree;
-
-} // namespace BRepMesh
-
-#endif
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_BaseMeshAlgo.hxx>
+#include <BRepMesh_DataStructureOfDelaun.hxx>
+#include <IMeshData_Face.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_PCurve.hxx>
+#include <IMeshData_Curve.hxx>
+#include <BRepMesh_Delaun.hxx>
+#include <BRepMesh_ShapeTool.hxx>
+#include <Standard_ErrorHandler.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_BaseMeshAlgo::BRepMesh_BaseMeshAlgo()
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_BaseMeshAlgo::~BRepMesh_BaseMeshAlgo()
+{
+}
+
+//=======================================================================
+// Function: Perform
+// Purpose :
+//=======================================================================
+void BRepMesh_BaseMeshAlgo::Perform(
+ const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters)
+{
+ try
+ {
+ OCC_CATCH_SIGNALS
+
+ myDFace = theDFace;
+ myParameters = theParameters;
+ myAllocator = new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
+ myStructure = new BRepMesh_DataStructureOfDelaun(myAllocator);
+ myNodesMap = new VectorOfPnt(256, myAllocator);
+ myUsedNodes = new DMapOfIntegerInteger(1, myAllocator);
+
+ if (initDataStructure())
+ {
+ generateMesh();
+ commitSurfaceTriangulation();
+ }
+ }
+ catch (Standard_Failure& /*theExeption*/)
+ {
+ }
+
+ myDFace.Nullify(); // Do not hold link to face.
+ myStructure.Nullify();
+ myNodesMap .Nullify();
+ myUsedNodes.Nullify();
+ myAllocator.Nullify();
+}
+
+//=======================================================================
+//function : initDataStructure
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_BaseMeshAlgo::initDataStructure()
+{
+ for (Standard_Integer aWireIt = 0; aWireIt < myDFace->WiresNb(); ++aWireIt)
+ {
+ const IMeshData::IWireHandle& aDWire = myDFace->GetWire(aWireIt);
+ if (aDWire->IsSet(IMeshData_SelfIntersectingWire))
+ {
+ // TODO: here we can add points of self-intersecting wire as fixed points
+ // in order to keep consistency of nodes with adjacent faces.
+ continue;
+ }
+
+ for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt)
+ {
+ const IMeshData::IEdgeHandle aDEdge = aDWire->GetEdge(aEdgeIt);
+ const IMeshData::ICurveHandle& aCurve = aDEdge->GetCurve();
+ const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(
+ myDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt));
+
+ const TopAbs_Orientation aOri = fixSeamEdgeOrientation(aDEdge, aPCurve);
+
+ Standard_Integer aPrevNodeIndex = -1;
+ const Standard_Integer aLastPoint = aPCurve->ParametersNb() - 1;
+ for (Standard_Integer aPointIt = 0; aPointIt <= aLastPoint; ++aPointIt)
+ {
+ const Standard_Integer aNodeIndex = registerNode(
+ aCurve ->GetPoint(aPointIt),
+ aPCurve->GetPoint(aPointIt),
+ BRepMesh_Frontier, Standard_False/*aPointIt > 0 && aPointIt < aLastPoint*/);
+
+ aPCurve->GetIndex(aPointIt) = aNodeIndex;
+ myUsedNodes->Bind(aNodeIndex, aNodeIndex);
+
+ if (aPrevNodeIndex != -1 && aPrevNodeIndex != aNodeIndex)
+ {
+ const Standard_Integer aLinksNb = myStructure->NbLinks();
+ const Standard_Integer aLinkIndex = addLinkToMesh(aPrevNodeIndex, aNodeIndex, aOri);
+ if (aWireIt != 0 && aLinkIndex <= aLinksNb)
+ {
+ // Prevent holes around wire of zero area.
+ BRepMesh_Edge& aLink = const_cast<BRepMesh_Edge&>(myStructure->GetLink(aLinkIndex));
+ aLink.SetMovability(BRepMesh_Fixed);
+ }
+ }
+
+ aPrevNodeIndex = aNodeIndex;
+ }
+ }
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+// Function: registerNode
+// Purpose :
+//=======================================================================
+Standard_Integer BRepMesh_BaseMeshAlgo::registerNode(
+ const gp_Pnt& thePoint,
+ const gp_Pnt2d& thePoint2d,
+ const BRepMesh_DegreeOfFreedom theMovability,
+ const Standard_Boolean isForceAdd)
+{
+ const Standard_Integer aNodeIndex = addNodeToStructure(
+ thePoint2d, myNodesMap->Size(), theMovability, isForceAdd);
+
+ if (aNodeIndex > myNodesMap->Size())
+ {
+ myNodesMap->Append(thePoint);
+ }
+
+ return aNodeIndex;
+}
+
+//=======================================================================
+// Function: addNode
+// Purpose :
+//=======================================================================
+Standard_Integer BRepMesh_BaseMeshAlgo::addNodeToStructure(
+ const gp_Pnt2d& thePoint,
+ const Standard_Integer theLocation3d,
+ const BRepMesh_DegreeOfFreedom theMovability,
+ const Standard_Boolean isForceAdd)
+{
+ BRepMesh_Vertex aNode(thePoint.XY(), theLocation3d, theMovability);
+ return myStructure->AddNode(aNode, isForceAdd);
+}
+
+//=======================================================================
+//function : addLinkToMesh
+//purpose :
+//=======================================================================
+Standard_Integer BRepMesh_BaseMeshAlgo::addLinkToMesh(
+ const Standard_Integer theFirstNodeId,
+ const Standard_Integer theLastNodeId,
+ const TopAbs_Orientation theOrientation)
+{
+ Standard_Integer aLinkIndex;
+ if (theOrientation == TopAbs_REVERSED)
+ aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theLastNodeId, theFirstNodeId, BRepMesh_Frontier));
+ else if (theOrientation == TopAbs_INTERNAL)
+ aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Fixed));
+ else
+ aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Frontier));
+
+ return Abs(aLinkIndex);
+}
+
+//=======================================================================
+//function : fixSeamEdgeOrientation
+//purpose :
+//=======================================================================
+TopAbs_Orientation BRepMesh_BaseMeshAlgo::fixSeamEdgeOrientation(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const IMeshData::IPCurveHandle& thePCurve) const
+{
+ for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt)
+ {
+ const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt);
+ if (aPCurve->GetFace() == myDFace && thePCurve != aPCurve)
+ {
+ // Simple check that another pcurve of seam edge does not coincide with reference one.
+ const gp_Pnt2d& aPnt1_1 = thePCurve->GetPoint(0);
+ const gp_Pnt2d& aPnt2_1 = thePCurve->GetPoint(thePCurve->ParametersNb() - 1);
+
+ const gp_Pnt2d& aPnt1_2 = aPCurve->GetPoint(0);
+ const gp_Pnt2d& aPnt2_2 = aPCurve->GetPoint(aPCurve->ParametersNb() - 1);
+
+ const Standard_Real aSqDist1 = Min(aPnt1_1.SquareDistance(aPnt1_2), aPnt1_1.SquareDistance(aPnt2_2));
+ const Standard_Real aSqDist2 = Min(aPnt2_1.SquareDistance(aPnt1_2), aPnt2_1.SquareDistance(aPnt2_2));
+ if (aSqDist1 < Precision::SquareConfusion() &&
+ aSqDist2 < Precision::SquareConfusion())
+ {
+ return TopAbs_INTERNAL;
+ }
+ }
+ }
+
+ return thePCurve->GetOrientation();
+}
+
+//=======================================================================
+//function : commitSurfaceTriangulation
+//purpose :
+//=======================================================================
+void BRepMesh_BaseMeshAlgo::commitSurfaceTriangulation()
+{
+ Handle(Poly_Triangulation) aTriangulation = collectTriangles();
+ if (aTriangulation.IsNull())
+ {
+ myDFace->SetStatus(IMeshData_Failure);
+ return;
+ }
+
+ collectNodes(aTriangulation);
+
+ aTriangulation->Deflection(myDFace->GetDeflection());
+ BRepMesh_ShapeTool::AddInFace(myDFace->GetFace(), aTriangulation);
+}
+
+//=======================================================================
+//function : collectTriangles
+//purpose :
+//=======================================================================
+Handle(Poly_Triangulation) BRepMesh_BaseMeshAlgo::collectTriangles()
+{
+ const IMeshData::MapOfInteger& aTriangles = myStructure->ElementsOfDomain();
+ if (aTriangles.IsEmpty())
+ {
+ return Handle(Poly_Triangulation)();
+ }
+
+ Poly_Array1OfTriangle aPolyTrianges(1, aTriangles.Extent());
+ IMeshData::IteratorOfMapOfInteger aTriIt(aTriangles);
+ for (Standard_Integer aTriangeId = 1; aTriIt.More(); aTriIt.Next(), ++aTriangeId)
+ {
+ const BRepMesh_Triangle& aCurElem = myStructure->GetElement(aTriIt.Key());
+
+ Standard_Integer aNode[3];
+ myStructure->ElementNodes(aCurElem, aNode);
+
+ for (Standard_Integer i = 0; i < 3; ++i)
+ {
+ if (!myUsedNodes->IsBound(aNode[i]))
+ {
+ myUsedNodes->Bind(aNode[i], myUsedNodes->Size() + 1);
+ }
+
+ aNode[i] = myUsedNodes->Find(aNode[i]);
+ }
+
+ aPolyTrianges(aTriangeId).Set(aNode[0], aNode[1], aNode[2]);
+ }
+
+ Handle(Poly_Triangulation) aTriangulation = new Poly_Triangulation(
+ myUsedNodes->Extent(), aTriangles.Extent(), Standard_True);
+
+ aTriangulation->ChangeTriangles() = aPolyTrianges;
+ return aTriangulation;
+}
+
+//=======================================================================
+//function : collectNodes
+//purpose :
+//=======================================================================
+void BRepMesh_BaseMeshAlgo::collectNodes(
+ const Handle(Poly_Triangulation)& theTriangulation)
+{
+ // Store mesh nodes
+ TColgp_Array1OfPnt& aNodes = theTriangulation->ChangeNodes();
+ TColgp_Array1OfPnt2d& aNodes2d = theTriangulation->ChangeUVNodes();
+
+ for (Standard_Integer i = 1; i <= myNodesMap->Size(); ++i)
+ {
+ if (myUsedNodes->IsBound(i))
+ {
+ const BRepMesh_Vertex& aVertex = myStructure->GetNode(i);
+
+ const Standard_Integer aNodeIndex = myUsedNodes->Find(i);
+ aNodes(aNodeIndex) = myNodesMap->Value(aVertex.Location3d());
+ aNodes2d(aNodeIndex) = getNodePoint2d(aVertex);
+ }
+ }
+}
+
+//=======================================================================
+// Function: getNodePoint2d
+// Purpose :
+//=======================================================================
+gp_Pnt2d BRepMesh_BaseMeshAlgo::getNodePoint2d(
+ const BRepMesh_Vertex& theVertex) const
+{
+ return theVertex.Coord();
+}
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_BaseMeshAlgo_HeaderFile
+#define _BRepMesh_BaseMeshAlgo_HeaderFile
+
+#include <IMeshTools_MeshAlgo.hxx>
+#include <NCollection_Shared.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <BRepMesh_DegreeOfFreedom.hxx>
+#include <Poly_Triangulation.hxx>
+
+class BRepMesh_DataStructureOfDelaun;
+class BRepMesh_Delaun;
+
+//! Class provides base fuctionality for algorithms building face triangulation.
+//! Performs initialization of BRepMesh_DataStructureOfDelaun and nodes map structures.
+class BRepMesh_BaseMeshAlgo : public IMeshTools_MeshAlgo
+{
+public:
+
+ typedef NCollection_Shared<NCollection_Vector<gp_Pnt> > VectorOfPnt;
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_BaseMeshAlgo();
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_BaseMeshAlgo();
+
+ //! Performs processing of the given face.
+ Standard_EXPORT virtual void Perform(
+ const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_BaseMeshAlgo, IMeshTools_MeshAlgo)
+
+protected:
+
+ //! Gets discrete face.
+ inline const IMeshData::IFaceHandle& getDFace() const
+ {
+ return myDFace;
+ }
+
+ //! Gets meshing parameters.
+ inline const IMeshTools_Parameters& getParameters() const
+ {
+ return myParameters;
+ }
+
+ //! Gets common allocator.
+ inline const Handle(NCollection_IncAllocator)& getAllocator() const
+ {
+ return myAllocator;
+ }
+
+ //! Gets mesh structure.
+ inline const Handle(BRepMesh_DataStructureOfDelaun)& getStructure() const
+ {
+ return myStructure;
+ }
+
+ //! Gets 3d nodes map.
+ inline const Handle(VectorOfPnt)& getNodesMap() const
+ {
+ return myNodesMap;
+ }
+
+protected:
+
+ //! Registers the given point in vertex map and adds 2d point to mesh data structure.
+ //! Returns index of node in the structure.
+ Standard_EXPORT virtual Standard_Integer registerNode(
+ const gp_Pnt& thePoint,
+ const gp_Pnt2d& thePoint2d,
+ const BRepMesh_DegreeOfFreedom theMovability,
+ const Standard_Boolean isForceAdd);
+
+ //! Adds the given 2d point to mesh data structure.
+ //! Returns index of node in the structure.
+ Standard_EXPORT virtual Standard_Integer addNodeToStructure(
+ const gp_Pnt2d& thePoint,
+ const Standard_Integer theLocation3d,
+ const BRepMesh_DegreeOfFreedom theMovability,
+ const Standard_Boolean isForceAdd);
+
+ //! Returns 2d point associated to the given vertex.
+ Standard_EXPORT virtual gp_Pnt2d getNodePoint2d(const BRepMesh_Vertex& theVertex) const;
+
+ //! Performs initialization of data structure using existing model data.
+ Standard_EXPORT virtual Standard_Boolean initDataStructure();
+
+ //! Generates mesh for the contour stored in data structure.
+ Standard_EXPORT virtual void generateMesh() = 0;
+
+private:
+
+ //! If the given edge has another pcurve for current face coinsiding with specified one,
+ //! returns TopAbs_INTERNAL flag. Elsewhere returns orientation of specified pcurve.
+ TopAbs_Orientation fixSeamEdgeOrientation(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const IMeshData::IPCurveHandle& thePCurve) const;
+
+ //! Adds new link to the mesh data structure.
+ //! Movability of the link and order of nodes depend on orientation parameter.
+ Standard_Integer addLinkToMesh(
+ const Standard_Integer theFirstNodeId,
+ const Standard_Integer theLastNodeId,
+ const TopAbs_Orientation theOrientation);
+
+ //! Commits generated triangulation to TopoDS face.
+ void commitSurfaceTriangulation();
+
+ //! Collects triangles to output data.
+ Handle(Poly_Triangulation) collectTriangles();
+
+ //! Collects nodes to output data.
+ void collectNodes(const Handle(Poly_Triangulation)& theTriangulation);
+
+private:
+ typedef NCollection_Shared<NCollection_DataMap<Standard_Integer, Standard_Integer> > DMapOfIntegerInteger;
+
+ IMeshData::IFaceHandle myDFace;
+ IMeshTools_Parameters myParameters;
+ Handle(NCollection_IncAllocator) myAllocator;
+ Handle(BRepMesh_DataStructureOfDelaun) myStructure;
+ Handle(VectorOfPnt) myNodesMap;
+ Handle(DMapOfIntegerInteger) myUsedNodes;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_BoundaryParamsRangeSplitter_HeaderFile
+#define _BRepMesh_BoundaryParamsRangeSplitter_HeaderFile
+
+#include <BRepMesh_NURBSRangeSplitter.hxx>
+
+//! Auxiliary class extending UV range splitter in order to generate
+//! internal nodes for NURBS surface.
+class BRepMesh_BoundaryParamsRangeSplitter : public BRepMesh_NURBSRangeSplitter
+{
+public:
+
+ //! Constructor.
+ BRepMesh_BoundaryParamsRangeSplitter()
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_BoundaryParamsRangeSplitter()
+ {
+ }
+
+ //! Registers border point.
+ virtual void AddPoint(const gp_Pnt2d& thePoint) Standard_OVERRIDE
+ {
+ BRepMesh_NURBSRangeSplitter::AddPoint(thePoint);
+ GetParametersU().Add(thePoint.X());
+ GetParametersV().Add(thePoint.Y());
+ }
+
+protected:
+
+};
+
+#endif
#ifndef BRepMesh_CircleInspector_Header
#define BRepMesh_CircleInspector_Header
-#include <BRepMesh.hxx>
+#include <IMeshData_Types.hxx>
#include <BRepMesh_Circle.hxx>
#include <Precision.hxx>
#include <gp_XY.hxx>
const Standard_Real theTolerance,
const Standard_Integer theReservedSize,
const Handle(NCollection_IncAllocator)& theAllocator)
- : myTolerance(theTolerance*theTolerance),
+ : mySqTolerance(theTolerance*theTolerance),
myResIndices(theAllocator),
- myCircles(theReservedSize)
+ myCircles(theReservedSize, theAllocator)
{
}
}
//! Resutns vector of registered circles.
- inline const BRepMesh::VectorOfCircle& Circles() const
+ inline const IMeshData::VectorOfCircle& Circles() const
{
return myCircles;
}
}
//! Returns list of circles shot by the reference point.
- inline BRepMesh::ListOfInteger& GetShotCircles()
+ inline IMeshData::ListOfInteger& GetShotCircles()
{
return myResIndices;
}
//! Performs inspection of a circle with the given index.
//! @param theTargetIndex index of a circle to be checked.
//! @return status of the check.
- Standard_EXPORT NCollection_CellFilter_Action Inspect(
- const Standard_Integer theTargetIndex);
+ inline NCollection_CellFilter_Action Inspect(
+ const Standard_Integer theTargetIndex)
+ {
+ BRepMesh_Circle& aCircle = myCircles(theTargetIndex);
+ const Standard_Real& aRadius = aCircle.Radius();
+ if (aRadius < 0.)
+ return CellFilter_Purge;
+
+ gp_XY& aLoc = const_cast<gp_XY&>(aCircle.Location());
+
+ const Standard_Real aDX = myPoint.ChangeCoord(1) - aLoc.ChangeCoord(1);
+ const Standard_Real aDY = myPoint.ChangeCoord(2) - aLoc.ChangeCoord(2);
+
+ //This check is wrong. It is better to use
+ //
+ // const Standard_Real aR = aRadius + aToler;
+ // if ((aDX * aDX + aDY * aDY) <= aR * aR)
+ // {
+ // ...
+ // }
+
+ //where aToler = sqrt(mySqTolerance). Taking into account the fact
+ //that the input parameter of the class (see constructor) is linear
+ //(not quadratic) tolerance there is no point in square root computation.
+ //Simply, we do not need to compute square of the input tolerance and to
+ //assign it to mySqTolerance. The input linear tolerance is needed to be used.
+
+ //However, this change leads to hangs the test case "perf mesh bug27119".
+ //So, this correction is better to be implemented in the future.
+
+ if ((aDX * aDX + aDY * aDY) - (aRadius * aRadius) <= mySqTolerance)
+ myResIndices.Append(theTargetIndex);
+
+ return CellFilter_Keep;
+ }
//! Checks indices for equlity.
static Standard_Boolean IsEqual(
}
private:
- Standard_Real myTolerance;
- BRepMesh::ListOfInteger myResIndices;
- BRepMesh::VectorOfCircle myCircles;
- gp_XY myPoint;
+ Standard_Real mySqTolerance;
+ IMeshData::ListOfInteger myResIndices;
+ IMeshData::VectorOfCircle myCircles;
+ gp_XY myPoint;
};
#endif
#include <BRepMesh_Circle.hxx>
#include <BRepMesh_CircleInspector.hxx>
-//=======================================================================
-//function : Inspect
-//purpose :
-//=======================================================================
-NCollection_CellFilter_Action BRepMesh_CircleInspector::Inspect(
- const Standard_Integer theTargetIndex)
-{
- const BRepMesh_Circle& aCircle = myCircles(theTargetIndex);
- Standard_Real aRadius = aCircle.Radius();
- if(aRadius < 0.)
- return CellFilter_Purge;
-
- const gp_XY& aLoc = aCircle.Location();
-
- if ((myPoint - aLoc).SquareModulus() - (aRadius * aRadius) <= myTolerance)
- myResIndices.Append(theTargetIndex);
-
- return CellFilter_Keep;
-}
-
-
//=======================================================================
//function : BRepMesh_CircleTool
//purpose :
//=======================================================================
BRepMesh_CircleTool::BRepMesh_CircleTool(
const Handle(NCollection_IncAllocator)& theAllocator)
-: myTolerance (Precision::PConfusion() * Precision::PConfusion()),
+: myTolerance (Precision::PConfusion()),
myAllocator (theAllocator),
myCellFilter(10.0, theAllocator),
mySelector (myTolerance, 64, theAllocator)
BRepMesh_CircleTool::BRepMesh_CircleTool(
const Standard_Integer theReservedSize,
const Handle(NCollection_IncAllocator)& theAllocator)
-: myTolerance (Precision::PConfusion() * Precision::PConfusion()),
+: myTolerance (Precision::PConfusion()),
myAllocator (theAllocator),
myCellFilter(10.0, theAllocator),
mySelector (myTolerance, Max(theReservedSize, 64), theAllocator)
static const Standard_Real aPrecision = Precision::PConfusion();
static const Standard_Real aSqPrecision = aPrecision * aPrecision;
- if ((thePoint1 - thePoint3).SquareModulus() < aSqPrecision)
- return Standard_False;
-
- gp_XY aLink1(thePoint2 - thePoint1);
+ gp_XY aLink1(const_cast<gp_XY&>(thePoint3).ChangeCoord(1) - const_cast<gp_XY&>(thePoint2).ChangeCoord(1),
+ const_cast<gp_XY&>(thePoint2).ChangeCoord(2) - const_cast<gp_XY&>(thePoint3).ChangeCoord(2));
if (aLink1.SquareModulus() < aSqPrecision)
return Standard_False;
- gp_XY aLink2(thePoint3 - thePoint2);
+ gp_XY aLink2(const_cast<gp_XY&>(thePoint1).ChangeCoord(1) - const_cast<gp_XY&>(thePoint3).ChangeCoord(1),
+ const_cast<gp_XY&>(thePoint3).ChangeCoord(2) - const_cast<gp_XY&>(thePoint1).ChangeCoord(2));
if (aLink2.SquareModulus() < aSqPrecision)
return Standard_False;
- gp_XY aMidPnt1 = (thePoint1 + thePoint2) / 2.;
- gp_XY aNorm1 = gp_XY(aLink1.Y(), -aLink1.X());
- aNorm1.Add(aMidPnt1);
-
- if (aLink2.SquareModulus() < aSqPrecision)
+ gp_XY aLink3(const_cast<gp_XY&>(thePoint2).ChangeCoord(1) - const_cast<gp_XY&>(thePoint1).ChangeCoord(1),
+ const_cast<gp_XY&>(thePoint1).ChangeCoord(2) - const_cast<gp_XY&>(thePoint2).ChangeCoord(2));
+ if (aLink3.SquareModulus() < aSqPrecision)
return Standard_False;
- gp_XY aMidPnt2 = (thePoint2 + thePoint3) / 2.;
- gp_XY aNorm2 = gp_XY(aLink2.Y(), -aLink2.X());
- aNorm2.Add(aMidPnt2);
+ const Standard_Real aD = 2 * (const_cast<gp_XY&>(thePoint1).ChangeCoord(1) * aLink1.Y() +
+ const_cast<gp_XY&>(thePoint2).ChangeCoord(1) * aLink2.Y() +
+ const_cast<gp_XY&>(thePoint3).ChangeCoord(1) * aLink3.Y());
- gp_XY aIntPnt;
- Standard_Real aParam[2];
- BRepMesh_GeomTool::IntFlag aIntFlag =
- BRepMesh_GeomTool::IntLinLin(aMidPnt1, aNorm1,
- aMidPnt2, aNorm2, aIntPnt, aParam);
-
- if (aIntFlag != BRepMesh_GeomTool::Cross)
+ if (Abs(aD) < gp::Resolution())
return Standard_False;
- theLocation = aIntPnt;
+ const Standard_Real aInvD = 1. / aD;
+ const Standard_Real aSqMod1 = thePoint1.SquareModulus();
+ const Standard_Real aSqMod2 = thePoint2.SquareModulus();
+ const Standard_Real aSqMod3 = thePoint3.SquareModulus();
+ theLocation.ChangeCoord(1) = (aSqMod1 * aLink1.Y() +
+ aSqMod2 * aLink2.Y() +
+ aSqMod3 * aLink3.Y()) * aInvD;
+
+ theLocation.ChangeCoord(2) = (aSqMod1 * aLink1.X() +
+ aSqMod2 * aLink2.X() +
+ aSqMod3 * aLink3.X()) * aInvD;
- theRadius = Sqrt(Max(Max((thePoint1 - aIntPnt).SquareModulus(),
- (thePoint2 - aIntPnt).SquareModulus()),
- (thePoint3 - aIntPnt).SquareModulus())) + 2 * RealEpsilon();
+ theRadius = Sqrt(Max(Max((thePoint1 - theLocation).SquareModulus(),
+ (thePoint2 - theLocation).SquareModulus()),
+ (thePoint3 - theLocation).SquareModulus())) + 2 * RealEpsilon();
return Standard_True;
}
//function : Select
//purpose :
//=======================================================================
-BRepMesh::ListOfInteger& BRepMesh_CircleTool::Select(const gp_XY& thePoint)
+IMeshData::ListOfInteger& BRepMesh_CircleTool::Select(const gp_XY& thePoint)
{
mySelector.SetPoint(thePoint);
myCellFilter.Inspect(thePoint, mySelector);
#include <gp_XYZ.hxx>
#include <Standard_Integer.hxx>
#include <Standard_Boolean.hxx>
-#include <BRepMesh.hxx>
+#include <IMeshData_Types.hxx>
#include <NCollection_Array1.hxx>
class gp_Circ2d;
//! @param theReservedSize size to be reserved for vector of circles.
inline void Init(const Standard_Integer /*theReservedSize*/)
{
- myTolerance = Precision::PConfusion() * Precision::PConfusion();
+ myTolerance = Precision::PConfusion();
}
//! Sets new size for cell filter.
//! Select the circles shot by the given point.
//! @param thePoint bullet point.
- Standard_EXPORT BRepMesh::ListOfInteger& Select(const gp_XY& thePoint);
+ Standard_EXPORT IMeshData::ListOfInteger& Select(const gp_XY& thePoint);
private:
Standard_Real myTolerance;
Handle(NCollection_IncAllocator) myAllocator;
- BRepMesh::CircleCellFilter myCellFilter;
+ IMeshData::CircleCellFilter myCellFilter;
BRepMesh_CircleInspector mySelector;
gp_XY myFaceMax;
gp_XY myFaceMin;
-// Created on: 1997-06-26
-// Created by: Laurent PAINNOT
-// Copyright (c) 1997-1999 Matra Datavision
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
//
// This file is part of Open CASCADE Technology software library.
//
{
}
+//=======================================================================
+//function : Destructor
+//purpose :
+//=======================================================================
+BRepMesh_Classifier::~BRepMesh_Classifier()
+{
+}
+
//=======================================================================
//function : Perform
//purpose :
Standard_Boolean isOut = Standard_False;
Standard_Integer aNb = myTabClass.Length();
- for (Standard_Integer i = 1; i <= aNb; i++)
+ for (Standard_Integer i = 0; i < aNb; i++)
{
- Standard_Integer aCur = ((CSLib_Class2d*)myTabClass(i))->SiDans(thePoint);
+ const Standard_Integer aCur = myTabClass(i)->SiDans(thePoint);
if (aCur == 0)
{
// Point is ON, but mark it as OUT
isOut = Standard_True;
}
else
+ {
isOut = myTabOrient(i) ? (aCur == -1) : (aCur == 1);
+ }
if (isOut)
+ {
return TopAbs_OUT;
+ }
}
return TopAbs_IN;
//purpose :
//=======================================================================
void BRepMesh_Classifier::RegisterWire(
- const NCollection_Sequence<gp_Pnt2d>& theWire,
- const Standard_Real theTolUV,
- const Standard_Real theUmin,
- const Standard_Real theUmax,
- const Standard_Real theVmin,
- const Standard_Real theVmax)
+ const NCollection_Sequence<const gp_Pnt2d*>& theWire,
+ const std::pair<Standard_Real, Standard_Real>& theTolUV,
+ const std::pair<Standard_Real, Standard_Real>& theRangeU,
+ const std::pair<Standard_Real, Standard_Real>& theRangeV)
{
const Standard_Integer aNbPnts = theWire.Length();
if (aNbPnts < 2)
+ {
return;
+ }
// Accumulate angle
TColgp_Array1OfPnt2d aPClass(1, aNbPnts);
Standard_Real anAngle = 0.0;
- gp_Pnt2d p1 = theWire(1), p2 = theWire(2), p3;
- aPClass(1) = p1;
- aPClass(2) = p2;
+ const gp_Pnt2d *p1 = theWire(1), *p2 = theWire(2), *p3;
+ aPClass(1) = *p1;
+ aPClass(2) = *p2;
const Standard_Real aAngTol = Precision::Angular();
const Standard_Real aSqConfusion =
Standard_Integer ii = i + 2;
if (ii > aNbPnts)
{
- p3 = aPClass(ii - aNbPnts);
+ p3 = &aPClass(ii - aNbPnts);
}
else
{
p3 = theWire.Value(ii);
- aPClass(ii) = p3;
+ aPClass(ii) = *p3;
}
- gp_Vec2d A(p1,p2), B(p2,p3);
+ const gp_Vec2d A(*p1,*p2), B(*p2,*p3);
if (A.SquareMagnitude() > aSqConfusion &&
B.SquareMagnitude() > aSqConfusion)
{
if (Abs(anAngle) < aAngTol)
anAngle = 0.0;
- myTabClass.Append( (void *)new CSLib_Class2d(aPClass,
- theTolUV, theTolUV, theUmin, theVmin, theUmax, theVmax) );
- myTabOrient.Append( !(anAngle < 0.0) );
-}
-
-//=======================================================================
-//function : Destroy
-//purpose :
-//=======================================================================
-void BRepMesh_Classifier::Destroy()
-{
- Standard_Integer aNb = myTabClass.Length();
- for (Standard_Integer i = 1; i <= aNb; i++)
- {
- if (myTabClass(i))
- {
- delete ((CSLib_Class2d*)myTabClass(i));
- myTabClass(i) = NULL;
- }
- }
+ myTabClass.Append(new CSLib_Class2d(
+ aPClass, theTolUV.first, theTolUV.second,
+ theRangeU.first, theRangeV.first,
+ theRangeU.second, theRangeV.second));
- myTabClass.Clear();
- myTabOrient.Clear();
+ myTabOrient.Append( !(anAngle < 0.0) );
}
-// Created on: 2014-06-03
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
-// Copyright (c) 1997-1999 Matra Datavision
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
#define _BRepMesh_Classifier_HeaderFile
#include <Standard.hxx>
-#include <Standard_DefineAlloc.hxx>
#include <Standard_Macro.hxx>
-#include <BRepTopAdaptor_SeqOfPtr.hxx>
-#include <TColStd_SequenceOfBoolean.hxx>
#include <TopAbs_State.hxx>
-#include <NCollection_Sequence.hxx>
-#include <gp_Pnt2d.hxx>
+#include <IMeshData_Types.hxx>
+#include <NCollection_Handle.hxx>
-//! Auxilary class contains information about correctness of discretized
-//! face and used for classification of points regarding face internals.
-class BRepMesh_Classifier
+#include <memory>
+
+class gp_Pnt2d;
+class CSLib_Class2d;
+
+//! Auxilary class intended for classification of points
+//! regarding internals of discrete face.
+class BRepMesh_Classifier : public Standard_Transient
{
public:
- DEFINE_STANDARD_ALLOC
-
//! Constructor.
Standard_EXPORT BRepMesh_Classifier();
//! Destructor.
- virtual ~BRepMesh_Classifier()
- {
- Destroy();
- }
-
- //! Method is called on destruction.
- //! Clears internal data structures.
- Standard_EXPORT void Destroy();
+ Standard_EXPORT virtual ~BRepMesh_Classifier();
//! Performs classification of the given point regarding to face internals.
//! @param thePoint Point in parametric space to be classified.
- //! @return
+ //! @return TopAbs_IN if point lies within face boundaries and TopAbs_OUT elsewhere.
Standard_EXPORT TopAbs_State Perform(const gp_Pnt2d& thePoint) const;
//! Registers wire specified by sequence of points for
//! @param theVmin Lower V boundary of the face in parametric space.
//! @param theVmax Upper V boundary of the face in parametric space.
Standard_EXPORT void RegisterWire(
- const NCollection_Sequence<gp_Pnt2d>& theWire,
- const Standard_Real theTolUV,
- const Standard_Real theUmin,
- const Standard_Real theUmax,
- const Standard_Real theVmin,
- const Standard_Real theVmax);
+ const NCollection_Sequence<const gp_Pnt2d*>& theWire,
+ const std::pair<Standard_Real, Standard_Real>& theTolUV,
+ const std::pair<Standard_Real, Standard_Real>& theRangeU,
+ const std::pair<Standard_Real, Standard_Real>& theRangeV);
+
+ DEFINE_STANDARD_RTTI_INLINE (BRepMesh_Classifier, Standard_Transient)
private:
- BRepTopAdaptor_SeqOfPtr myTabClass;
- TColStd_SequenceOfBoolean myTabOrient;
+ NCollection_Vector<NCollection_Handle<CSLib_Class2d> > myTabClass;
+ IMeshData::VectorOfBoolean myTabOrient;
};
#endif
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_ConeRangeSplitter.hxx>
+#include <GCPnts_TangentialDeflection.hxx>
+
+//=======================================================================
+// Function: GenerateSurfaceNodes
+// Purpose :
+//=======================================================================
+Handle(IMeshData::ListOfPnt2d) BRepMesh_ConeRangeSplitter::GenerateSurfaceNodes(
+ const IMeshTools_Parameters& theParameters) const
+{
+ const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
+ const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
+
+ gp_Cone aCone = GetDFace()->GetSurface()->Cone();
+ Standard_Real aRefR = aCone.RefRadius();
+ Standard_Real aSAng = aCone.SemiAngle();
+ Standard_Real aRadius = Max(Abs(aRefR + aRangeV.first * Sin(aSAng)),
+ Abs(aRefR + aRangeV.second * Sin(aSAng)));
+
+ Standard_Real Dv, Du = GCPnts_TangentialDeflection::ArcAngularStep(
+ aRadius, GetDFace()->GetDeflection(),
+ theParameters.Angle, theParameters.MinSize);
+
+ const Standard_Real aDiffU = aRangeU.second - aRangeU.first;
+ const Standard_Real aDiffV = aRangeV.second - aRangeV.first;
+ Standard_Integer nbU = (Standard_Integer) (aDiffU / Du);
+ Standard_Integer nbV = (Standard_Integer) (nbU * (aDiffV) / (aDiffU * aRadius));
+ Du = aDiffU / (nbU + 1);
+ Dv = aDiffV / (nbV + 1);
+
+ const Handle(NCollection_IncAllocator) aTmpAlloc =
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
+ Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc);
+
+ const Standard_Real aPasMaxV = aRangeV.second - Dv*0.5;
+ const Standard_Real aPasMaxU = aRangeU.second - Du*0.5;
+ for (Standard_Real aPasV = aRangeV.first + Dv; aPasV < aPasMaxV; aPasV += Dv)
+ {
+ for (Standard_Real aPasU = aRangeU.first + Du; aPasU < aPasMaxU; aPasU += Du)
+ {
+ aNodes->Append(gp_Pnt2d(aPasU, aPasV));
+ }
+ }
+
+ return aNodes;
+}
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_ConeRangeSplitter_HeaderFile
+#define _BRepMesh_ConeRangeSplitter_HeaderFile
+
+#include <BRepMesh_DefaultRangeSplitter.hxx>
+#include <IMeshTools_Parameters.hxx>
+
+//! Auxiliary class extending default range splitter in
+//! order to generate internal nodes for conical surface.
+class BRepMesh_ConeRangeSplitter : public BRepMesh_DefaultRangeSplitter
+{
+public:
+
+ //! Constructor.
+ BRepMesh_ConeRangeSplitter()
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_ConeRangeSplitter()
+ {
+ }
+
+ //! Returns list of nodes generated using surface data and specified parameters.
+ Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes(
+ const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE;
+};
+
+#endif
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_Context.hxx>
+#include <BRepMesh_ModelBuilder.hxx>
+#include <BRepMesh_EdgeDiscret.hxx>
+#include <BRepMesh_ModelHealer.hxx>
+#include <BRepMesh_FaceDiscret.hxx>
+#include <BRepMesh_ModelPreProcessor.hxx>
+#include <BRepMesh_ModelPostProcessor.hxx>
+#include <BRepMesh_MeshAlgoFactory.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_Context::BRepMesh_Context ()
+{
+ SetModelBuilder (new BRepMesh_ModelBuilder);
+ SetEdgeDiscret (new BRepMesh_EdgeDiscret);
+ SetModelHealer (new BRepMesh_ModelHealer);
+ SetPreProcessor (new BRepMesh_ModelPreProcessor);
+ SetFaceDiscret (new BRepMesh_FaceDiscret(new BRepMesh_MeshAlgoFactory));
+ SetPostProcessor(new BRepMesh_ModelPostProcessor);
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_Context::~BRepMesh_Context ()
+{
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_Context_HeaderFile
+#define _BRepMesh_Context_HeaderFile
+
+#include <IMeshTools_Context.hxx>
+
+//! Class implemeting default context of BRepMesh algorithm.
+//! Initializes context by default algorithms.
+class BRepMesh_Context : public IMeshTools_Context
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_Context ();
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_Context ();
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_Context, IMeshTools_Context)
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_CurveTessellator.hxx>
+#include <gp_Pnt.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS_Edge.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_PCurve.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <TopExp_Explorer.hxx>
+#include <Geom_Plane.hxx>
+#include <TopExp.hxx>
+#include <Adaptor3d_HCurveOnSurface.hxx>
+#include <Adaptor2d_HCurve2d.hxx>
+#include <Standard_Failure.hxx>
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+BRepMesh_CurveTessellator::BRepMesh_CurveTessellator(
+ const IMeshData::IEdgeHandle& theEdge,
+ const IMeshTools_Parameters& theParameters)
+ : myDEdge(theEdge),
+ myParameters(theParameters),
+ myEdge(theEdge->GetEdge()),
+ myCurve(myEdge)
+{
+ init();
+}
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+BRepMesh_CurveTessellator::BRepMesh_CurveTessellator (
+ const IMeshData::IEdgeHandle& theEdge,
+ const TopAbs_Orientation theOrientation,
+ const IMeshData::IFaceHandle& theFace,
+ const IMeshTools_Parameters& theParameters)
+ : myDEdge(theEdge),
+ myParameters(theParameters),
+ myEdge(TopoDS::Edge(theEdge->GetEdge().Oriented(theOrientation))),
+ myCurve(myEdge, theFace->GetFace())
+{
+ init();
+}
+
+//=======================================================================
+//function : init
+//purpose :
+//=======================================================================
+void BRepMesh_CurveTessellator::init()
+{
+ if (myParameters.MinSize <= 0.0)
+ {
+ Standard_Failure::Raise ("The structure \"myParameters\" is not initialized");
+ }
+
+ TopExp::Vertices(myEdge, myFirstVertex, myLastVertex);
+
+ Standard_Real aPreciseAngDef = 0.5 * myDEdge->GetAngularDeflection();
+ Standard_Real aPreciseLinDef = 0.5 * myDEdge->GetDeflection();
+ if (myEdge.Orientation() == TopAbs_INTERNAL)
+ {
+ aPreciseLinDef *= 0.5;
+ }
+
+ mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
+ mySquareMinSize = Max(mySquareEdgeDef, myParameters.MinSize * myParameters.MinSize);
+
+ myEdgeSqTol = BRep_Tool::Tolerance(myEdge);
+ myEdgeSqTol *= myEdgeSqTol;
+
+ const Standard_Integer aMinPntNb = (myCurve.GetType() == GeomAbs_Circle) ? 4 : 2; //OCC287
+
+ myDiscretTool.Initialize(myCurve,
+ myCurve.FirstParameter(), myCurve.LastParameter(),
+ aPreciseAngDef, aPreciseLinDef, aMinPntNb,
+ Precision::PConfusion(), myParameters.MinSize);
+
+ if (myCurve.IsCurveOnSurface())
+ {
+ const Adaptor3d_CurveOnSurface& aCurve = myCurve.CurveOnSurface();
+ const Handle(Adaptor3d_HSurface)& aSurface = aCurve.GetSurface();
+
+ const Standard_Real aTol = Precision::Confusion();
+ const Standard_Real aDu = aSurface->UResolution(aTol);
+ const Standard_Real aDv = aSurface->VResolution(aTol);
+
+ myFaceRangeU[0] = aSurface->FirstUParameter() - aDu;
+ myFaceRangeU[1] = aSurface->LastUParameter() + aDu;
+
+ myFaceRangeV[0] = aSurface->FirstVParameter() - aDv;
+ myFaceRangeV[1] = aSurface->LastVParameter() + aDv;
+ }
+
+ addInternalVertices();
+ splitByDeflection2d();
+}
+
+//=======================================================================
+//function : Destructor
+//purpose :
+//=======================================================================
+BRepMesh_CurveTessellator::~BRepMesh_CurveTessellator ()
+{
+}
+
+//=======================================================================
+//function : NbPoints
+//purpose :
+//=======================================================================
+Standard_Integer BRepMesh_CurveTessellator::PointsNb () const
+{
+ return myDiscretTool.NbPoints ();
+}
+
+//=======================================================================
+//function : splitByDeflection2d
+//purpose :
+//=======================================================================
+void BRepMesh_CurveTessellator::splitByDeflection2d ()
+{
+ const Standard_Integer aNodesNb = myDiscretTool.NbPoints ();
+ if (!myDEdge->IsFree () &&
+ myDEdge->GetSameParam () &&
+ myDEdge->GetSameRange () &&
+ aNodesNb > 1)
+ {
+ for (Standard_Integer aPCurveIt = 0; aPCurveIt < myDEdge->PCurvesNb (); ++aPCurveIt)
+ {
+ TopLoc_Location aLoc;
+ const IMeshData::IPCurveHandle& aPCurve = myDEdge->GetPCurve(aPCurveIt);
+ const TopoDS_Face& aFace = aPCurve->GetFace ()->GetFace ();
+ const Handle (Geom_Surface)& aSurface = BRep_Tool::Surface (aFace, aLoc);
+ if (aSurface->IsInstance(STANDARD_TYPE(Geom_Plane)))
+ {
+ continue;
+ }
+
+ const TopoDS_Edge aCurrEdge = TopoDS::Edge(myEdge.Oriented(aPCurve->GetOrientation()));
+
+ Standard_Real aF, aL;
+ Handle (Geom2d_Curve) aCurve2d = BRep_Tool::CurveOnSurface (aCurrEdge, aFace, aF, aL);
+ TColStd_Array1OfReal aParamArray (1, aNodesNb);
+ for (Standard_Integer i = 1; i <= aNodesNb; ++i)
+ aParamArray.SetValue (i, myDiscretTool.Parameter (i));
+
+ for (Standard_Integer i = 1; i < aNodesNb; ++i)
+ splitSegment (aSurface, aCurve2d, aParamArray (i), aParamArray (i + 1), 1);
+ }
+ }
+}
+
+//=======================================================================
+//function : addInternalVertices
+//purpose :
+//=======================================================================
+void BRepMesh_CurveTessellator::addInternalVertices ()
+{
+ // PTv, chl/922/G9, Take into account internal vertices
+ // it is necessary for internal edges, which do not split other edges, by their vertex
+ TopExp_Explorer aVertexIt (myEdge, TopAbs_VERTEX);
+ for (; aVertexIt.More (); aVertexIt.Next ())
+ {
+ const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVertexIt.Current ());
+ if (aVertex.Orientation() != TopAbs_INTERNAL)
+ {
+ continue;
+ }
+
+ myDiscretTool.AddPoint (BRep_Tool::Pnt (aVertex),
+ BRep_Tool::Parameter (aVertex, myEdge), Standard_True);
+ }
+}
+
+//=======================================================================
+//function : isInToleranceOfVertex
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_CurveTessellator::isInToleranceOfVertex (
+ const gp_Pnt& thePoint,
+ const TopoDS_Vertex& theVertex) const
+{
+ const gp_Pnt aPoint = BRep_Tool::Pnt(theVertex);
+ const Standard_Real aTolerance = BRep_Tool::Tolerance(theVertex);
+
+ return (thePoint.SquareDistance (aPoint) < aTolerance * aTolerance);
+}
+
+//=======================================================================
+//function : Value
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_CurveTessellator::Value (
+ const Standard_Integer theIndex,
+ gp_Pnt& thePoint,
+ Standard_Real& theParameter) const
+{
+ thePoint = myDiscretTool.Value (theIndex);
+ theParameter = myDiscretTool.Parameter (theIndex);
+
+ /*if (!isInToleranceOfVertex(thePoint, myFirstVertex) &&
+ !isInToleranceOfVertex(thePoint, myLastVertex))
+ {*/
+ if (!myCurve.IsCurveOnSurface())
+ {
+ return Standard_True;
+ }
+
+ // If point coordinates are out of surface range,
+ // it is necessary to re-project point.
+ const Adaptor3d_CurveOnSurface& aCurve = myCurve.CurveOnSurface();
+ const Handle(Adaptor3d_HSurface)& aSurface = aCurve.GetSurface();
+ if (aSurface->GetType() != GeomAbs_BSplineSurface &&
+ aSurface->GetType() != GeomAbs_BezierSurface &&
+ aSurface->GetType() != GeomAbs_OtherSurface)
+ {
+ return Standard_True;
+ }
+
+ // Let skip periodic case.
+ if (aSurface->IsUPeriodic() || aSurface->IsVPeriodic())
+ {
+ return Standard_True;
+ }
+
+ gp_Pnt2d aUV;
+ aCurve.GetCurve()->D0(theParameter, aUV);
+ // Point lies within the surface range - nothing to do.
+ if (aUV.X() > myFaceRangeU[0] && aUV.X() < myFaceRangeU[1] &&
+ aUV.Y() > myFaceRangeV[0] && aUV.Y() < myFaceRangeV[1])
+ {
+ return Standard_True;
+ }
+
+ gp_Pnt aPntOnSurf;
+ aSurface->D0(aUV.X(), aUV.Y(), aPntOnSurf);
+
+ return (thePoint.SquareDistance(aPntOnSurf) < myEdgeSqTol);
+ /*}
+
+ return Standard_False;*/
+}
+
+//=======================================================================
+//function : splitSegment
+//purpose :
+//=======================================================================
+void BRepMesh_CurveTessellator::splitSegment (
+ const Handle (Geom_Surface)& theSurf,
+ const Handle (Geom2d_Curve)& theCurve2d,
+ const Standard_Real theFirst,
+ const Standard_Real theLast,
+ const Standard_Integer theNbIter)
+{
+ // limit iteration depth
+ if (theNbIter > 10)
+ {
+ return;
+ }
+
+ gp_Pnt2d uvf, uvl, uvm;
+ gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf;
+ Standard_Real midpar;
+
+ if (Abs(theLast - theFirst) < 2 * Precision::PConfusion())
+ {
+ return;
+ }
+
+ if ((theCurve2d->FirstParameter() - theFirst > Precision::PConfusion()) ||
+ (theLast - theCurve2d->LastParameter() > Precision::PConfusion()))
+ {
+ // E.g. test bugs moddata_3 bug30133
+ return;
+ }
+
+ theCurve2d->D0 (theFirst, uvf);
+ theCurve2d->D0 (theLast, uvl);
+
+ P3dF = theSurf->Value (uvf.X (), uvf.Y ());
+ P3dL = theSurf->Value (uvl.X (), uvl.Y ());
+
+ if (P3dF.SquareDistance(P3dL) < mySquareMinSize)
+ {
+ return;
+ }
+
+ uvm = gp_Pnt2d ((uvf.XY () + uvl.XY ())*0.5);
+ midP3dFromSurf = theSurf->Value (uvm.X (), uvm.Y ());
+
+ gp_XYZ Vec1 = midP3dFromSurf.XYZ () - P3dF.XYZ ();
+ if (Vec1.SquareModulus() < mySquareMinSize)
+ {
+ return;
+ }
+
+ gp_XYZ aVec = P3dL.XYZ () - P3dF.XYZ ();
+ aVec.Normalize ();
+
+ Standard_Real aModulus = Vec1.Dot (aVec);
+ gp_XYZ aProj = aVec * aModulus;
+ gp_XYZ aDist = Vec1 - aProj;
+
+ if (aDist.SquareModulus() < mySquareEdgeDef)
+ {
+ return;
+ }
+
+ midpar = (theFirst + theLast) * 0.5;
+ myCurve.D0 (midpar, midP3d);
+ myDiscretTool.AddPoint (midP3d, midpar, Standard_False);
+
+ splitSegment (theSurf, theCurve2d, theFirst, midpar, theNbIter + 1);
+ splitSegment (theSurf, theCurve2d, midpar, theLast, theNbIter + 1);
+}
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_EdgeTessellator_HeaderFile
+#define _BRepMesh_EdgeTessellator_HeaderFile
+
+#include <IMeshTools_CurveTessellator.hxx>
+#include <GCPnts_TangentialDeflection.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <IMeshData_Types.hxx>
+
+class TopoDS_Face;
+class Geom_Surface;
+class Geom2d_Curve;
+struct IMeshTools_Parameters;
+
+//! Auxiliary class performing tessellation of passed edge according to specified parameters.
+class BRepMesh_CurveTessellator : public IMeshTools_CurveTessellator
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_CurveTessellator(
+ const IMeshData::IEdgeHandle& theEdge,
+ const IMeshTools_Parameters& theParameters);
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_CurveTessellator (
+ const IMeshData::IEdgeHandle& theEdge,
+ const TopAbs_Orientation theOrientation,
+ const IMeshData::IFaceHandle& theFace,
+ const IMeshTools_Parameters& theParameters);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_CurveTessellator ();
+
+ //! Returns number of tessellation points.
+ Standard_EXPORT virtual Standard_Integer PointsNb () const Standard_OVERRIDE;
+
+ //! Returns parameters of solution with the given index.
+ //! @param theIndex index of tessellation point.
+ //! @param theParameter parameters on PCurve corresponded to the solution.
+ //! @param thePoint tessellation point.
+ //! @return True in case of valid result, false elewhere.
+ Standard_EXPORT virtual Standard_Boolean Value (
+ const Standard_Integer theIndex,
+ gp_Pnt& thePoint,
+ Standard_Real& theParameter) const Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_CurveTessellator, IMeshTools_CurveTessellator)
+
+private:
+
+ //! Performs initialization of this tool.
+ void init();
+
+ //! Adds internal vertices to discrete polygon.
+ void addInternalVertices ();
+
+ //Check deflection in 2d space for improvement of edge tesselation.
+ void splitByDeflection2d ();
+
+ void splitSegment (
+ const Handle (Geom_Surface)& theSurf,
+ const Handle (Geom2d_Curve)& theCurve2d,
+ const Standard_Real theFirst,
+ const Standard_Real theLast,
+ const Standard_Integer theNbIter);
+
+ //! Checks whether the given point lies within tolerance of the vertex.
+ Standard_Boolean isInToleranceOfVertex (
+ const gp_Pnt& thePoint,
+ const TopoDS_Vertex& theVertex) const;
+
+private:
+
+ BRepMesh_CurveTessellator (const BRepMesh_CurveTessellator& theOther);
+
+ void operator=(const BRepMesh_CurveTessellator& theOther);
+
+private:
+
+ const IMeshData::IEdgeHandle& myDEdge;
+ const IMeshTools_Parameters& myParameters;
+ TopoDS_Edge myEdge;
+ BRepAdaptor_Curve myCurve;
+ GCPnts_TangentialDeflection myDiscretTool;
+ TopoDS_Vertex myFirstVertex;
+ TopoDS_Vertex myLastVertex;
+ Standard_Real mySquareEdgeDef;
+ Standard_Real mySquareMinSize;
+ Standard_Real myEdgeSqTol;
+ Standard_Real myFaceRangeU[2];
+ Standard_Real myFaceRangeV[2];
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_CylinderRangeSplitter.hxx>
+#include <GCPnts_TangentialDeflection.hxx>
+
+//=======================================================================
+// Function: Reset
+// Purpose :
+//=======================================================================
+void BRepMesh_CylinderRangeSplitter::Reset(const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters)
+{
+ BRepMesh_DefaultRangeSplitter::Reset(theDFace, theParameters);
+
+ const Standard_Real aRadius = GetDFace()->GetSurface()->Cylinder().Radius();
+ myDu = GCPnts_TangentialDeflection::ArcAngularStep(
+ aRadius, GetDFace()->GetDeflection(),
+ theParameters.Angle, theParameters.MinSize);
+}
+
+//=======================================================================
+// Function: GenerateSurfaceNodes
+// Purpose :
+//=======================================================================
+Handle(IMeshData::ListOfPnt2d) BRepMesh_CylinderRangeSplitter::GenerateSurfaceNodes(
+ const IMeshTools_Parameters& /*theParameters*/) const
+{
+ const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
+ const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
+
+ const Standard_Real aRadius = GetDFace()->GetSurface()->Cylinder().Radius();
+
+ Standard_Integer nbU = 0;
+ Standard_Integer nbV = 0;
+ const Standard_Real su = aRangeU.second - aRangeU.first;
+ const Standard_Real sv = aRangeV.second - aRangeV.first;
+ const Standard_Real aArcLen = su * aRadius;
+ if (aArcLen > GetDFace()->GetDeflection())
+ {
+ // Calculate parameters for iteration in U direction
+ nbU = (Standard_Integer) (su / myDu);
+
+ /*
+ // Calculate parameters for iteration in V direction
+ const Standard_Real aDv = nbU*sv / aArcLen;
+ // Protection against overflow during casting to int in case
+ // of long cylinder with small radius.
+ nbV = aDv > static_cast<Standard_Real> (IntegerLast()) ?
+ 0 : (Standard_Integer) (aDv);
+ nbV = Min(nbV, 100 * nbU);
+ */
+ }
+
+ const Standard_Real Du = su / (nbU + 1);
+ const Standard_Real Dv = sv / (nbV + 1);
+
+ const Handle(NCollection_IncAllocator) aTmpAlloc =
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
+ Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc);
+
+ const Standard_Real aPasMaxV = aRangeV.second - Dv*0.5;
+ const Standard_Real aPasMaxU = aRangeU.second - Du*0.5;
+ for (Standard_Real aPasV = aRangeV.first + Dv; aPasV < aPasMaxV; aPasV += Dv)
+ {
+ for (Standard_Real aPasU = aRangeU.first + Du; aPasU < aPasMaxU; aPasU += Du)
+ {
+ aNodes->Append(gp_Pnt2d(aPasU, aPasV));
+ }
+ }
+
+ return aNodes;
+}
+
+//=======================================================================
+// Function: computeDelta
+// Purpose :
+//=======================================================================
+void BRepMesh_CylinderRangeSplitter::computeDelta(
+ const Standard_Real /*theLengthU*/,
+ const Standard_Real theLengthV)
+{
+ const std::pair<double, double>& aRangeV = GetRangeV();
+ myDelta.first = myDu / Max(theLengthV, aRangeV.second - aRangeV.first);
+ myDelta.second = 1.;
+}
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_CylinderRangeSplitter_HeaderFile
+#define _BRepMesh_CylinderRangeSplitter_HeaderFile
+
+#include <BRepMesh_DefaultRangeSplitter.hxx>
+#include <IMeshTools_Parameters.hxx>
+
+//! Auxiliary class extending default range splitter in
+//! order to generate internal nodes for cylindrical surface.
+class BRepMesh_CylinderRangeSplitter : public BRepMesh_DefaultRangeSplitter
+{
+public:
+
+ //! Constructor.
+ BRepMesh_CylinderRangeSplitter()
+ : myDu(1.)
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_CylinderRangeSplitter()
+ {
+ }
+
+ //! Resets this splitter. Must be called before first use.
+ Standard_EXPORT virtual void Reset(const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
+
+ //! Returns list of nodes generated using surface data and specified parameters.
+ Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes(
+ const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE;
+
+protected:
+
+ //! Computes parametric delta taking length along U and V into account.
+ Standard_EXPORT virtual void computeDelta(
+ const Standard_Real theLengthU,
+ const Standard_Real theLengthV) Standard_OVERRIDE;
+
+private:
+
+ Standard_Real myDu;
+};
+
+#endif
// commercial license or contractual agreement.
#include <BRepMesh_DataStructureOfDelaun.hxx>
-#include <BRepMesh_PairOfIndex.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <BRepMesh_Edge.hxx>
#include <TopoDS_Compound.hxx>
#include <BRep_Builder.hxx>
#include <BRepTools.hxx>
#include <Standard_ErrorHandler.hxx>
-
-IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_DataStructureOfDelaun,Standard_Transient)
-
//=======================================================================
//function : BRepMesh_DataStructureOfDelaun
//purpose :
myNodeLinks (theReservedNodeSize * 3, myAllocator),
myLinks (theReservedNodeSize * 3, myAllocator),
myDelLinks (myAllocator),
- myElements (theReservedNodeSize * 2, myAllocator),
- myElementsOfDomain(theReservedNodeSize * 2, myAllocator),
- myLinksOfDomain (theReservedNodeSize * 2, myAllocator)
+ myElements (theReservedNodeSize * 2, myAllocator)
{
}
{
const Standard_Integer aNodeId = myNodes->Add(theNode, isForceAdd);
if (!myNodeLinks.IsBound(aNodeId))
- myNodeLinks.Bind(aNodeId, BRepMesh::ListOfInteger(myAllocator));
+ myNodeLinks.Bind(aNodeId, IMeshData::ListOfInteger(myAllocator));
return aNodeId;
}
const Standard_Integer aNodeId = (i == 0) ?
theLink.FirstNode() : theLink.LastNode();
- BRepMesh::ListOfInteger& aLinkList = linksConnectedTo(aNodeId);
- BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList);
+ IMeshData::ListOfInteger& aLinkList = linksConnectedTo(aNodeId);
+ IMeshData::ListOfInteger::Iterator aLinkIt(aLinkList);
for(; aLinkIt.More(); aLinkIt.Next())
{
if (aLinkIt.Value() == theIndex)
Standard_Integer BRepMesh_DataStructureOfDelaun::AddElement(
const BRepMesh_Triangle& theElement)
{
- Standard_Integer aElementIndex = IndexOf(theElement);
- if (aElementIndex > 0)
- return aElementIndex;
-
- aElementIndex = myElements.Add(theElement);
+ myElements.Append(theElement);
+ Standard_Integer aElementIndex = myElements.Size();
myElementsOfDomain.Add(aElementIndex);
- Standard_Integer e[3];
- Standard_Boolean o[3];
- theElement.Edges(e, o);
+ const Standard_Integer (&e)[3] = theElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
myLinks(e[i]).Append(aElementIndex);
if (theElement.Movability() != BRepMesh_Free)
return;
- Standard_Integer e[3];
- Standard_Boolean o[3];
- theElement.Edges(e, o);
-
+ const Standard_Integer(&e)[3] = theElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
removeElementIndex(theIndex, myLinks(e[i]));
}
const BRepMesh_Triangle& aElement = GetElement(theIndex);
if (aElement.Movability() == BRepMesh_Deleted)
{
- myElements.Substitute(theIndex, theNewElement);
+ myElements(theIndex) = theNewElement;
return Standard_True;
}
- if (IndexOf(theNewElement) != 0)
- return Standard_False;
-
cleanElement(theIndex, aElement);
// Warning: here new element and old element should have different Hash code
- myElements.Substitute(theIndex, theNewElement);
+ myElements(theIndex) = theNewElement;
- Standard_Integer e[3];
- Standard_Boolean o[3];
- theNewElement.Edges(e, o);
+ const Standard_Integer(&e)[3] = theNewElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
myLinks(e[i]).Append(theIndex);
const BRepMesh_Triangle& theElement,
Standard_Integer (&theNodes)[3])
{
- Standard_Integer e[3];
- Standard_Boolean o[3];
- theElement.Edges(e, o);
+ const Standard_Integer(&e)[3] = theElement.myEdges;
+ const Standard_Boolean(&o)[3] = theElement.myOrientations;
const BRepMesh_Edge& aLink1 = GetLink(e[0]);
if (o[0])
//=======================================================================
void BRepMesh_DataStructureOfDelaun::ClearDomain()
{
- BRepMesh::MapOfInteger aFreeEdges;
- BRepMesh::MapOfInteger::Iterator aElementIt(myElementsOfDomain);
+ IMeshData::MapOfInteger aFreeEdges;
+ IMeshData::IteratorOfMapOfInteger aElementIt(myElementsOfDomain);
for (; aElementIt.More(); aElementIt.Next())
{
const Standard_Integer aElementId = aElementIt.Key();
BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(aElementId);
- Standard_Integer e[3];
- Standard_Boolean o[3];
- aElement.Edges(e, o);
+ const Standard_Integer(&e)[3] = aElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
aFreeEdges.Add(e[i]);
}
myElementsOfDomain.Clear();
- BRepMesh::MapOfInteger::Iterator aEdgeIt(aFreeEdges);
+ IMeshData::IteratorOfMapOfInteger aEdgeIt(aFreeEdges);
for (; aEdgeIt.More(); aEdgeIt.Next())
RemoveLink(aEdgeIt.Key());
}
--aLastLiveItem;
const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
- BRepMesh::ListOfInteger::Iterator aLinkIt;
+ IMeshData::ListOfInteger::Iterator aLinkIt;
// update link references
for (Standard_Integer i = 0; i < 2; ++i)
{
// update elements references
for(Standard_Integer j = 1, jn = aPair.Extent(); j <= jn; ++j)
{
- const BRepMesh_Triangle& aElement = GetElement(aPair.Index(j));
-
Standard_Integer e[3];
Standard_Boolean o[3];
+ const BRepMesh_Triangle& aElement = GetElement(aPair.Index(j));
aElement.Edges(e, o);
for (Standard_Integer i = 0; i < 3; ++i)
{
}
}
- myElements.Substitute(aLinkIt.Value(),
- BRepMesh_Triangle(e, o, aElement.Movability()));
+ myElements(aLinkIt.Value()) = BRepMesh_Triangle(e, o, aElement.Movability());
}
}
}
//=======================================================================
void BRepMesh_DataStructureOfDelaun::clearDeletedNodes()
{
- BRepMesh::ListOfInteger& aDelNodes =
- (BRepMesh::ListOfInteger&)myNodes->GetListOfDelNodes();
+ IMeshData::ListOfInteger& aDelNodes =
+ (IMeshData::ListOfInteger&)myNodes->GetListOfDelNodes();
Standard_Integer aLastLiveItem = NbNodes();
while (!aDelNodes.IsEmpty())
continue;
BRepMesh_Vertex aNode = GetNode(aLastLiveItem);
- BRepMesh::ListOfInteger& aLinkList = linksConnectedTo(aLastLiveItem);
+ IMeshData::ListOfInteger& aLinkList = linksConnectedTo(aLastLiveItem);
myNodes->RemoveLast();
--aLastLiveItem;
myNodeLinks.ChangeFind(aDelItem) = aLinkList;
const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
- BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList);
+ IMeshData::ListOfInteger::Iterator aLinkIt(aLinkList);
for (; aLinkIt.More(); aLinkIt.Next())
{
const Standard_Integer aLinkId = aLinkIt.Value();
theStream << "\n Deleted links : " << myDelLinks.Extent() << endl;
theStream << "\n\n Map of elements : \n";
- myElements.Statistics(theStream);
+ theStream << "\n Elements : " << myElements.Size() << endl;
}
//=======================================================================
return "Error: file name or mesh data is null";
}
- Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
+ Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
*(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr;
if (aMeshData.IsNull())
}
else
{
- BRepMesh::MapOfInteger::Iterator aLinksIt(aMeshData->LinksOfDomain());
+ IMeshData::IteratorOfMapOfInteger aLinksIt(aMeshData->LinksOfDomain());
for (; aLinksIt.More(); aLinksIt.Next())
{
- const BRepMesh_Edge& aLink = aMeshData->GetLink(aLinksIt.Value());
+ const BRepMesh_Edge& aLink = aMeshData->GetLink(aLinksIt.Key());
gp_Pnt aPnt[2];
for (Standard_Integer i = 0; i < 2; ++i)
{
return theFileNameStr;
}
+
+void BRepMesh_DataStructureOfDelaun::Dump(Standard_CString theFileNameStr)
+{
+ Handle(BRepMesh_DataStructureOfDelaun) aMeshData (this);
+ BRepMesh_Dump((void*)&aMeshData, theFileNameStr);
+}
#ifndef _BRepMesh_DataStructureOfDelaun_HeaderFile
#define _BRepMesh_DataStructureOfDelaun_HeaderFile
-#include <Standard.hxx>
-#include <Standard_Type.hxx>
-#include <BRepMesh_VertexTool.hxx>
#include <Standard_Transient.hxx>
#include <BRepMesh_Triangle.hxx>
#include <BRepMesh_PairOfIndex.hxx>
#include <Standard_OStream.hxx>
-#include <BRepMesh.hxx>
+#include <IMeshData_Types.hxx>
+#include <BRepMesh_VertexTool.hxx>
class BRepMesh_Vertex;
-class BRepMesh_VertexTool;
class BRepMesh_Edge;
//! Describes the data structure necessary for the mesh algorithms in
if (isForce || myNodes->FindKey(theIndex).Movability() == BRepMesh_Free)
{
if (LinksConnectedTo(theIndex).Extent()==0)
- myNodes->Delete(theIndex);
+ myNodes->DeleteVertex(theIndex);
}
}
//! Get list of links attached to the node with the given index.
//! @param theIndex index of node whose links should be retrieved.
//! @return list of links attached to the node.
- inline const BRepMesh::ListOfInteger& LinksConnectedTo(
+ inline const IMeshData::ListOfInteger& LinksConnectedTo(
const Standard_Integer theIndex) const
{
return linksConnectedTo(theIndex);
}
//! Returns map of indices of links registered in mesh.
- inline const BRepMesh::MapOfInteger& LinksOfDomain() const
+ inline const IMeshData::MapOfInteger& LinksOfDomain() const
{
return myLinksOfDomain;
}
//! Returns number of links.
inline Standard_Integer NbElements() const
{
- return myElements.Extent();
+ return myElements.Size();
}
//! Adds element to the mesh if it is not already in the mesh.
//! @return index of the element in the structure.
Standard_EXPORT Standard_Integer AddElement(const BRepMesh_Triangle& theElement);
- //! Finds the index of the given element.
- //! @param theElement element to find.
- //! @return index of the given element of zero if element is not in the mesh.
- Standard_Integer IndexOf(const BRepMesh_Triangle& theElement) const
- {
- return myElements.FindIndex(theElement);
- }
-
//! Get element by the index.
//! @param theIndex index of an element.
//! @return element with the given index.
const BRepMesh_Triangle& GetElement(const Standard_Integer theIndex)
{
- return myElements.FindKey(theIndex);
+ return myElements.ChangeValue(theIndex - 1);
}
//! Returns map of indices of elements registered in mesh.
- inline const BRepMesh::MapOfInteger& ElementsOfDomain() const
+ inline const IMeshData::MapOfInteger& ElementsOfDomain() const
{
return myElementsOfDomain;
}
const BRepMesh_Triangle& theElement,
Standard_Integer (&theNodes)[3]);
+ Standard_EXPORT void Dump(Standard_CString theFileNameStr);
+
public: //! @name Auxilary API
}
//! Gives the data structure for initialization of cell size and tolerance.
- inline BRepMesh::HVertexTool& Data()
+ inline const Handle(BRepMesh_VertexTool)& Data()
{
return myNodes;
}
clearDeletedNodes();
}
- DEFINE_STANDARD_RTTIEXT(BRepMesh_DataStructureOfDelaun,Standard_Transient)
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_DataStructureOfDelaun, Standard_Transient)
private:
//! Get list of links attached to the node with the given index.
//! @param theIndex index of node whose links should be retrieved.
//! @return list of links attached to the node.
- inline BRepMesh::ListOfInteger& linksConnectedTo(
+ inline IMeshData::ListOfInteger& linksConnectedTo(
const Standard_Integer theIndex) const
{
- return (BRepMesh::ListOfInteger&)myNodeLinks.Find(theIndex);
+ return (IMeshData::ListOfInteger&)myNodeLinks.Find(theIndex);
}
//! Substitutes deleted links by the last one from corresponding map
private:
Handle(NCollection_IncAllocator) myAllocator;
- BRepMesh::HVertexTool myNodes;
- BRepMesh::DMapOfIntegerListOfInteger myNodeLinks;
- BRepMesh::IDMapOfLink myLinks;
- BRepMesh::ListOfInteger myDelLinks;
- BRepMesh::IMapOfElement myElements;
- BRepMesh::MapOfInteger myElementsOfDomain;
- BRepMesh::MapOfInteger myLinksOfDomain;
+ Handle(BRepMesh_VertexTool) myNodes;
+ IMeshData::DMapOfIntegerListOfInteger myNodeLinks;
+ IMeshData::IDMapOfLink myLinks;
+ IMeshData::ListOfInteger myDelLinks;
+ IMeshData::VectorOfElements myElements;
+ IMeshData::MapOfInteger myElementsOfDomain;
+ IMeshData::MapOfInteger myLinksOfDomain;
};
-DEFINE_STANDARD_HANDLE(BRepMesh_DataStructureOfDelaun,Standard_Transient)
-
#endif
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_DefaultRangeSplitter.hxx>
+
+#include <GCPnts_AbscissaPoint.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <GeomAbs_IsoType.hxx>
+
+//=======================================================================
+// Function: Reset
+// Purpose :
+//=======================================================================
+void BRepMesh_DefaultRangeSplitter::Reset(const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& /*theParameters*/)
+{
+ myDFace = theDFace;
+ myRangeU.first = myRangeV.first = 1.e100;
+ myRangeU.second = myRangeV.second = -1.e100;
+ myDelta.first = myDelta.second = 1.;
+ myTolerance.first = myTolerance.second = Precision::Confusion();
+}
+
+//=======================================================================
+// Function: AddPoint
+// Purpose :
+//=======================================================================
+void BRepMesh_DefaultRangeSplitter::AddPoint(const gp_Pnt2d& thePoint)
+{
+ myRangeU.first = Min(thePoint.X(), myRangeU.first);
+ myRangeU.second = Max(thePoint.X(), myRangeU.second);
+ myRangeV.first = Min(thePoint.Y(), myRangeV.first);
+ myRangeV.second = Max(thePoint.Y(), myRangeV.second);
+}
+
+//=======================================================================
+// Function: AdjustRange
+// Purpose :
+//=======================================================================
+void BRepMesh_DefaultRangeSplitter::AdjustRange()
+{
+ const Handle(BRepAdaptor_HSurface)& aSurface = GetSurface();
+ updateRange(aSurface->FirstUParameter(), aSurface->LastUParameter(),
+ aSurface->IsUPeriodic(), myRangeU.first, myRangeU.second);
+
+ if (myRangeU.second < myRangeU.first)
+ {
+ myIsValid = Standard_False;
+ return;
+ }
+
+ updateRange(aSurface->FirstVParameter(), aSurface->LastVParameter(),
+ aSurface->IsVPeriodic(), myRangeV.first, myRangeV.second);
+
+ if (myRangeV.second < myRangeV.first)
+ {
+ myIsValid = Standard_False;
+ return;
+ }
+
+ const Standard_Real aLengthU = computeLengthU();
+ const Standard_Real aLengthV = computeLengthV();
+ myIsValid = aLengthU > Precision::PConfusion () && aLengthV > Precision::PConfusion ();
+
+ if (myIsValid)
+ {
+ computeTolerance(aLengthU, aLengthV);
+ computeDelta (aLengthU, aLengthV);
+ }
+}
+
+//=======================================================================
+// Function: IsValid
+// Purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_DefaultRangeSplitter::IsValid()
+{
+ return myIsValid;
+}
+
+//=======================================================================
+// Function: Scale
+// Purpose :
+//=======================================================================
+gp_Pnt2d BRepMesh_DefaultRangeSplitter::Scale(const gp_Pnt2d& thePoint,
+ const Standard_Boolean isToFaceBasis) const
+{
+ return isToFaceBasis ?
+ gp_Pnt2d ((thePoint.X () - myRangeU.first) / myDelta.first,
+ (thePoint.Y () - myRangeV.first) / myDelta.second) :
+ gp_Pnt2d (thePoint.X () * myDelta.first + myRangeU.first,
+ thePoint.Y () * myDelta.second + myRangeV.first);
+}
+
+//=======================================================================
+// Function: GenerateSurfaceNodes
+// Purpose :
+//=======================================================================
+Handle(IMeshData::ListOfPnt2d) BRepMesh_DefaultRangeSplitter::GenerateSurfaceNodes(
+ const IMeshTools_Parameters& /*theParameters*/) const
+{
+ return Handle(IMeshData::ListOfPnt2d)();
+}
+
+//=======================================================================
+// Function: computeTolerance
+// Purpose :
+//=======================================================================
+void BRepMesh_DefaultRangeSplitter::computeTolerance(
+ const Standard_Real /*theLenU*/,
+ const Standard_Real /*theLenV*/)
+{
+ const Standard_Real aDiffU = myRangeU.second - myRangeU.first;
+ const Standard_Real aDiffV = myRangeV.second - myRangeV.first;
+
+ const Standard_Real aDeflectionUV = 1.e-05;
+ myTolerance.first = Max(aDeflectionUV, Precision::Confusion() * aDiffU);
+ myTolerance.second = Max(aDeflectionUV, Precision::Confusion() * aDiffV);
+}
+
+//=======================================================================
+// Function: computeDelta
+// Purpose :
+//=======================================================================
+void BRepMesh_DefaultRangeSplitter::computeDelta(
+ const Standard_Real theLengthU,
+ const Standard_Real theLengthV)
+{
+ const Standard_Real aDiffU = myRangeU.second - myRangeU.first;
+ const Standard_Real aDiffV = myRangeV.second - myRangeV.first;
+
+ myDelta.first = aDiffU / (theLengthU < myTolerance.first ? 1. : theLengthU);
+ myDelta.second = aDiffV / (theLengthV < myTolerance.second ? 1. : theLengthV);
+}
+
+//=======================================================================
+// Function: computeLengthU
+// Purpose :
+//=======================================================================
+Standard_Real BRepMesh_DefaultRangeSplitter::computeLengthU()
+{
+ Standard_Real longu = 0.0;
+ gp_Pnt P11, P12, P21, P22, P31, P32;
+
+ Standard_Real du = 0.05 * (myRangeU.second - myRangeU.first);
+ Standard_Real dfvave = 0.5 * (myRangeV.second + myRangeV.first);
+ Standard_Real dfucur;
+ Standard_Integer i1;
+
+ const Handle(BRepAdaptor_HSurface)& gFace = GetSurface();
+ gFace->D0(myRangeU.first, myRangeV.first, P11);
+ gFace->D0(myRangeU.first, dfvave, P21);
+ gFace->D0(myRangeU.first, myRangeV.second, P31);
+ for (i1 = 1, dfucur = myRangeU.first + du; i1 <= 20; i1++, dfucur += du)
+ {
+ gFace->D0(dfucur, myRangeV.first, P12);
+ gFace->D0(dfucur, dfvave, P22);
+ gFace->D0(dfucur, myRangeV.second, P32);
+ longu += (P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32));
+ P11 = P12;
+ P21 = P22;
+ P31 = P32;
+ }
+
+ return longu / 3.;
+}
+
+//=======================================================================
+// Function: computeLengthV
+// Purpose :
+//=======================================================================
+Standard_Real BRepMesh_DefaultRangeSplitter::computeLengthV()
+{
+ Standard_Real longv = 0.0;
+ gp_Pnt P11, P12, P21, P22, P31, P32;
+
+ Standard_Real dv = 0.05 * (myRangeV.second - myRangeV.first);
+ Standard_Real dfuave = 0.5 * (myRangeU.second + myRangeU.first);
+ Standard_Real dfvcur;
+ Standard_Integer i1;
+
+ const Handle(BRepAdaptor_HSurface)& gFace = GetSurface();
+ gFace->D0(myRangeU.first, myRangeV.first, P11);
+ gFace->D0(dfuave, myRangeV.first, P21);
+ gFace->D0(myRangeU.second, myRangeV.first, P31);
+ for (i1 = 1, dfvcur = myRangeV.first + dv; i1 <= 20; i1++, dfvcur += dv)
+ {
+ gFace->D0(myRangeU.first, dfvcur, P12);
+ gFace->D0(dfuave, dfvcur, P22);
+ gFace->D0(myRangeU.second, dfvcur, P32);
+ longv += (P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32));
+ P11 = P12;
+ P21 = P22;
+ P31 = P32;
+ }
+
+ return longv / 3.;
+}
+
+//=======================================================================
+// Function: updateRange
+// Purpose :
+//=======================================================================
+void BRepMesh_DefaultRangeSplitter::updateRange(
+ const Standard_Real theGeomFirst,
+ const Standard_Real theGeomLast,
+ const Standard_Boolean isPeriodic,
+ Standard_Real& theDiscreteFirst,
+ Standard_Real& theDiscreteLast)
+{
+ if (theDiscreteFirst < theGeomFirst ||
+ theDiscreteLast > theGeomLast)
+ {
+ if (isPeriodic)
+ {
+ if ((theDiscreteLast - theDiscreteFirst) > (theGeomLast - theGeomFirst))
+ {
+ theDiscreteLast = theDiscreteFirst + (theGeomLast - theGeomFirst);
+ }
+ }
+ else
+ {
+ if ((theDiscreteFirst < theGeomLast) && (theDiscreteLast > theGeomFirst))
+ {
+ //Protection against the faces whose pcurve is out of the surface's domain
+ //(see issue #23675 and test cases "bugs iges buc60820*")
+
+ if (theGeomFirst > theDiscreteFirst)
+ {
+ theDiscreteFirst = theGeomFirst;
+ }
+
+ if (theGeomLast < theDiscreteLast)
+ {
+ theDiscreteLast = theGeomLast;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_DefaultRangeSplitter_HeaderFile
+#define _BRepMesh_DefaultRangeSplitter_HeaderFile
+
+#include <Standard_Type.hxx>
+#include <gp_Pnt2d.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+#include <IMeshData_Types.hxx>
+#include <IMeshData_Face.hxx>
+
+struct IMeshTools_Parameters;
+
+//! Default tool to define range of discrete face model and
+//! obtain grid points distributed within this range.
+class BRepMesh_DefaultRangeSplitter
+{
+public:
+
+ //! Constructor.
+ BRepMesh_DefaultRangeSplitter()
+ : myIsValid (Standard_True)
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_DefaultRangeSplitter()
+ {
+ }
+
+ //! Resets this splitter. Must be called before first use.
+ Standard_EXPORT virtual void Reset(const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters);
+
+ //! Registers border point.
+ Standard_EXPORT virtual void AddPoint(const gp_Pnt2d& thePoint);
+
+ //! Updates discrete range of surface according to its geometric range.
+ Standard_EXPORT virtual void AdjustRange();
+
+ //! Returns True if computed range is valid.
+ Standard_EXPORT virtual Standard_Boolean IsValid();
+
+ //! Scales the given point from real parametric space
+ //! to face basis and otherwise.
+ //! @param thePoint point to be scaled.
+ //! @param isToFaceBasis if TRUE converts point to face basis,
+ //! otherwise performs reverse conversion.
+ //! @return scaled point.
+ Standard_EXPORT gp_Pnt2d Scale(const gp_Pnt2d& thePoint,
+ const Standard_Boolean isToFaceBasis) const;
+
+ //! Returns list of nodes generated using surface data and specified parameters.
+ //! By default returns null ptr.
+ Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes(
+ const IMeshTools_Parameters& theParameters) const;
+
+ //! Returns point in 3d space corresponded to the given
+ //! point defined in parameteric space of surface.
+ inline gp_Pnt Point(const gp_Pnt2d& thePoint2d) const
+ {
+ return GetSurface()->Value(thePoint2d.X(), thePoint2d.Y());
+ }
+
+protected:
+
+ //! Computes parametric tolerance taking length along U and V into account.
+ virtual void computeTolerance(
+ const Standard_Real theLenU,
+ const Standard_Real theLenV);
+
+ //! Computes parametric delta taking length along U and V and value of tolerance into account.
+ virtual void computeDelta(
+ const Standard_Real theLengthU,
+ const Standard_Real theLengthV);
+
+public:
+ //! Returns face model.
+ inline const IMeshData::IFaceHandle& GetDFace() const
+ {
+ return myDFace;
+ }
+
+ //! Returns surface.
+ inline const Handle(BRepAdaptor_HSurface)& GetSurface() const
+ {
+ return myDFace->GetSurface();
+ }
+
+ //! Returns U range.
+ inline const std::pair<Standard_Real, Standard_Real>& GetRangeU() const
+ {
+ return myRangeU;
+ }
+
+ //! Returns V range.
+ inline const std::pair<Standard_Real, Standard_Real>& GetRangeV() const
+ {
+ return myRangeV;
+ }
+
+ //! Returns delta.
+ inline const std::pair<Standard_Real, Standard_Real>& GetDelta () const
+ {
+ return myDelta;
+ }
+
+ inline const std::pair<Standard_Real, Standard_Real>& GetToleranceUV() const
+ {
+ return myTolerance;
+ }
+
+private:
+
+ //! Computes length along U direction.
+ Standard_Real computeLengthU();
+
+ //! Computes length along V direction.
+ Standard_Real computeLengthV();
+
+ //! Updates discrete range of surface according to its geometric range.
+ void updateRange(const Standard_Real theGeomFirst,
+ const Standard_Real theGeomLast,
+ const Standard_Boolean isPeriodic,
+ Standard_Real& theDiscreteFirst,
+ Standard_Real& theDiscreteLast);
+
+protected:
+ IMeshData::IFaceHandle myDFace;
+ std::pair<Standard_Real, Standard_Real> myRangeU;
+ std::pair<Standard_Real, Standard_Real> myRangeV;
+ std::pair<Standard_Real, Standard_Real> myDelta;
+ std::pair<Standard_Real, Standard_Real> myTolerance;
+ Standard_Boolean myIsValid;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_Deflection.hxx>
+#include <BRepMesh_ShapeTool.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Face.hxx>
+#include <BRep_Tool.hxx>
+#include <Bnd_Box.hxx>
+#include <BRepBndLib.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopExp.hxx>
+
+//=======================================================================
+//function : RelativeEdgeDeflection
+//purpose :
+//=======================================================================
+Standard_Real BRepMesh_Deflection::RelativeEdgeDeflection(
+ const TopoDS_Edge& theEdge,
+ const Standard_Real theDeflection,
+ const Standard_Real theMaxShapeSize,
+ Standard_Real& theAdjustmentCoefficient)
+{
+ theAdjustmentCoefficient = 1.;
+ Standard_Real aEdgeDeflection = theDeflection;
+ if (theEdge.IsNull())
+ {
+ return aEdgeDeflection;
+ }
+
+ Bnd_Box aBox;
+ BRepBndLib::Add (theEdge, aBox, Standard_False);
+ BRepMesh_ShapeTool::BoxMaxDimension (aBox, aEdgeDeflection);
+
+ // Adjust resulting value in relation to the total size
+ theAdjustmentCoefficient = theMaxShapeSize / (2 * aEdgeDeflection);
+ if (theAdjustmentCoefficient < 0.5)
+ {
+ theAdjustmentCoefficient = 0.5;
+ }
+ else if (theAdjustmentCoefficient > 2.)
+ {
+ theAdjustmentCoefficient = 2.;
+ }
+
+ return (theAdjustmentCoefficient * aEdgeDeflection * theDeflection);
+}
+
+//=======================================================================
+// Function: ComputeDeflection (edge)
+// Purpose :
+//=======================================================================
+void BRepMesh_Deflection::ComputeDeflection (
+ const IMeshData::IEdgeHandle& theDEdge,
+ const Standard_Real theMaxShapeSize,
+ const IMeshTools_Parameters& theParameters)
+{
+ Standard_Real aLinDeflection;
+ Standard_Real aAngDeflection;
+ if (theParameters.Relative)
+ {
+ Standard_Real aScale;
+ aLinDeflection = RelativeEdgeDeflection (theDEdge->GetEdge (),
+ theParameters.Deflection, theMaxShapeSize, aScale);
+
+ // Is it OK?
+ aAngDeflection = theParameters.Angle * aScale;
+ }
+ else
+ {
+ aLinDeflection = theParameters.Deflection;
+ aAngDeflection = theParameters.Angle;
+ }
+
+ const TopoDS_Edge& anEdge = theDEdge->GetEdge();
+
+ TopoDS_Vertex aFirstVertex, aLastVertex;
+ TopExp::Vertices(anEdge, aFirstVertex, aLastVertex);
+
+ Handle(Geom_Curve) aCurve;
+ Standard_Real aFirstParam, aLastParam;
+ if (BRepMesh_ShapeTool::Range(anEdge, aCurve, aFirstParam, aLastParam))
+ {
+ const Standard_Real aDistF = aFirstVertex.IsNull() ? -1.0 :
+ BRep_Tool::Pnt(aFirstVertex).Distance(aCurve->Value(aFirstParam));
+ const Standard_Real aDistL = aLastVertex.IsNull() ? -1.0 :
+ BRep_Tool::Pnt(aLastVertex).Distance(aCurve->Value(aLastParam));
+
+ const Standard_Real aVertexAdjustDistance = Max(aDistF, aDistL);
+
+ aLinDeflection = Max(aVertexAdjustDistance, aLinDeflection);
+ }
+
+ theDEdge->SetDeflection (aLinDeflection);
+ theDEdge->SetAngularDeflection (aAngDeflection);
+}
+
+//=======================================================================
+// Function: ComputeDeflection (wire)
+// Purpose :
+//=======================================================================
+void BRepMesh_Deflection::ComputeDeflection (
+ const IMeshData::IWireHandle& theDWire,
+ const IMeshTools_Parameters& theParameters)
+{
+ Standard_Real aWireDeflection = 0.;
+ if (theDWire->EdgesNb () > 0)
+ {
+ for (Standard_Integer aEdgeIt = 0; aEdgeIt < theDWire->EdgesNb(); ++aEdgeIt)
+ {
+ aWireDeflection += theDWire->GetEdge(aEdgeIt)->GetDeflection();
+ }
+
+ aWireDeflection /= theDWire->EdgesNb ();
+ }
+ else
+ {
+ aWireDeflection = theParameters.Deflection;
+ }
+
+ theDWire->SetDeflection (aWireDeflection);
+}
+
+//=======================================================================
+// Function: ComputeDeflection (face)
+// Purpose :
+//=======================================================================
+void BRepMesh_Deflection::ComputeDeflection (
+ const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters)
+{
+ Standard_Real aFaceDeflection = 0.;
+ if (theDFace->WiresNb () > 0)
+ {
+ for (Standard_Integer aWireIt = 0; aWireIt < theDFace->WiresNb(); ++aWireIt)
+ {
+ aFaceDeflection += theDFace->GetWire(aWireIt)->GetDeflection();
+ }
+
+ aFaceDeflection /= theDFace->WiresNb ();
+ }
+ else
+ {
+ aFaceDeflection = theParameters.Deflection;
+ }
+
+ theDFace->SetDeflection (Max(2.* BRepMesh_ShapeTool::MaxFaceTolerance(
+ theDFace->GetFace()), aFaceDeflection));
+}
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_Deflection_HeaderFile
+#define _BRepMesh_Deflection_HeaderFile
+
+#include <Standard_Type.hxx>
+#include <Standard_Handle.hxx>
+#include <Standard_Transient.hxx>
+#include <IMeshData_Types.hxx>
+
+class Bnd_Box;
+class TopoDS_Face;
+class TopoDS_Edge;
+struct IMeshTools_Parameters;
+
+//! Auxiliary tool encompassing methods to compute deflection of shapes.
+class BRepMesh_Deflection : public Standard_Transient
+{
+public:
+
+ //! Returns relative deflection for edge with respect to shape size.
+ //! @param theEdge edge for which relative deflection should be computed.
+ //! @param theDeflection absolute deflection.
+ //! @param theMaxShapeSize maximum size of a shape.
+ //! @param theAdjustmentCoefficient coefficient of adjustment between maximum
+ //! size of shape and calculated relative deflection.
+ //! @return relative deflection for the edge.
+ Standard_EXPORT static Standard_Real RelativeEdgeDeflection (
+ const TopoDS_Edge& theEdge,
+ const Standard_Real theDeflection,
+ const Standard_Real theMaxShapeSize,
+ Standard_Real& theAdjustmentCoefficient);
+
+ //! Computes and updates deflection of the given discrete edge.
+ Standard_EXPORT static void ComputeDeflection (
+ const IMeshData::IEdgeHandle& theDEdge,
+ const Standard_Real theMaxShapeSize,
+ const IMeshTools_Parameters& theParameters);
+
+ //! Computes and updates deflection of the given discrete wire.
+ Standard_EXPORT static void ComputeDeflection (
+ const IMeshData::IWireHandle& theDWire,
+ const IMeshTools_Parameters& theParameters);
+
+ //! Computes and updates deflection of the given discrete face.
+ Standard_EXPORT static void ComputeDeflection (
+ const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters);
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_Deflection, Standard_Transient)
+};
+
+#endif
\ No newline at end of file
//function : BRepMesh_Delaun
//purpose : Creates the triangulation with an empty Mesh data structure
//=======================================================================
-BRepMesh_Delaun::BRepMesh_Delaun(BRepMesh::Array1OfVertexOfDelaun& theVertices)
+BRepMesh_Delaun::BRepMesh_Delaun(IMeshData::Array1OfVertexOfDelaun& theVertices)
: myCircles (theVertices.Length(), new NCollection_IncAllocator(
- BRepMesh::MEMORY_BLOCK_SIZE_HUGE))
+ IMeshData::MEMORY_BLOCK_SIZE_HUGE))
{
if ( theVertices.Length() > 2 )
{
myMeshData = new BRepMesh_DataStructureOfDelaun(
- new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE),
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE),
theVertices.Length() );
Init( theVertices );
}
//purpose : Creates the triangulation with and existent Mesh data structure
//=======================================================================
BRepMesh_Delaun::BRepMesh_Delaun(
- const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh,
- BRepMesh::Array1OfVertexOfDelaun& theVertices)
+ const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
+ IMeshData::Array1OfVertexOfDelaun& theVertices)
: myMeshData( theOldMesh ),
myCircles ( theVertices.Length(), theOldMesh->Allocator() )
{
//purpose : Creates the triangulation with and existent Mesh data structure
//=======================================================================
BRepMesh_Delaun::BRepMesh_Delaun(
- const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh,
- BRepMesh::Array1OfInteger& theVertexIndices)
+ const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
+ IMeshData::VectorOfInteger& theVertexIndices)
: myMeshData( theOldMesh ),
myCircles ( theVertexIndices.Length(), theOldMesh->Allocator() )
{
- perform( theVertexIndices );
+ perform(theVertexIndices);
}
//=======================================================================
//purpose : Creates the triangulation with and existent Mesh data structure
//=======================================================================
BRepMesh_Delaun::BRepMesh_Delaun (const Handle (BRepMesh_DataStructureOfDelaun)& theOldMesh,
- BRepMesh::Array1OfInteger& theVertexIndices,
+ IMeshData::VectorOfInteger& theVertexIndices,
const Standard_Integer theCellsCountU,
const Standard_Integer theCellsCountV)
- : myMeshData (theOldMesh),
+: myMeshData (theOldMesh),
myCircles (theVertexIndices.Length (), theOldMesh->Allocator ())
{
perform (theVertexIndices, theCellsCountU, theCellsCountV);
//function : Init
//purpose : Initializes the triangulation with an Array of Vertex
//=======================================================================
-void BRepMesh_Delaun::Init(BRepMesh::Array1OfVertexOfDelaun& theVertices)
+void BRepMesh_Delaun::Init(IMeshData::Array1OfVertexOfDelaun& theVertices)
{
Standard_Integer aLowerIdx = theVertices.Lower();
Standard_Integer anUpperIdx = theVertices.Upper();
- BRepMesh::Array1OfInteger aVertexIndexes( aLowerIdx, anUpperIdx );
+ IMeshData::VectorOfInteger aVertexIndexes(theVertices.Size());
Standard_Integer anIndex = aLowerIdx;
for ( ; anIndex <= anUpperIdx; ++anIndex )
{
- aVertexIndexes( anIndex ) = myMeshData->AddNode( theVertices( anIndex ) );
+ aVertexIndexes.Append(myMeshData->AddNode( theVertices( anIndex ) ));
}
perform( aVertexIndexes );
//function : perform
//purpose : Create super mesh and run triangulation procedure
//=======================================================================
-void BRepMesh_Delaun::perform (BRepMesh::Array1OfInteger& theVertexIndices,
- const Standard_Integer theCellsCountU /* = -1 */,
- const Standard_Integer theCellsCountV /* = -1 */)
+void BRepMesh_Delaun::perform(IMeshData::VectorOfInteger& theVertexIndices,
+ const Standard_Integer theCellsCountU /* = -1 */,
+ const Standard_Integer theCellsCountV /* = -1 */)
{
if (theVertexIndices.Length () <= 2)
{
//function : superMesh
//purpose : Build the super mesh
//=======================================================================
-void BRepMesh_Delaun::superMesh (const Bnd_Box2d& theBox,
- const Standard_Integer theCellsCountU,
- const Standard_Integer theCellsCountV)
+void BRepMesh_Delaun::superMesh(const Bnd_Box2d& theBox,
+ const Standard_Integer theCellsCountU,
+ const Standard_Integer theCellsCountV)
{
Standard_Real aMinX, aMinY, aMaxX, aMaxY;
- theBox.Get( aMinX, aMinY, aMaxX, aMaxY );
+ theBox.Get ( aMinX, aMinY, aMaxX, aMaxY );
Standard_Real aDeltaX = aMaxX - aMinX;
Standard_Real aDeltaY = aMaxY - aMinY;
Standard_Real aDeltaMin = Min( aDeltaX, aDeltaY );
Standard_Real aDeltaMax = Max( aDeltaX, aDeltaY );
Standard_Real aDelta = aDeltaX + aDeltaY;
-
+
myCircles.SetMinMaxSize( gp_XY( aMinX, aMinY ), gp_XY( aMaxX, aMaxY ) );
myCircles.SetCellSize( aDeltaX / theCellsCountU, aDeltaY / theCellsCountV);
mySupVert[0] = myMeshData->AddNode(
BRepMesh_Vertex( ( aMinX + aMaxX ) / 2, aMaxY + aDeltaMax, BRepMesh_Free ) );
-
+
mySupVert[1] = myMeshData->AddNode(
BRepMesh_Vertex( aMinX - aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
-
+
mySupVert[2] = myMeshData->AddNode(
BRepMesh_Vertex( aMaxX + aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
{
Standard_Integer aFirstNode = aNodeId;
Standard_Integer aLastNode = (aNodeId + 1) % 3;
- Standard_Integer aLinkIndex = myMeshData->AddLink( BRepMesh_Edge(
+ Standard_Integer aLinkIndex = myMeshData->AddLink( BRepMesh_Edge(
mySupVert[aFirstNode], mySupVert[aLastNode], BRepMesh_Free ) );
e[aNodeId] = Abs(aLinkIndex);
o[aNodeId] = (aLinkIndex > 0);
}
-
+
mySupTrian = BRepMesh_Triangle(e, o, BRepMesh_Free);
}
// edges into the map.
// When an edge is suppressed more than one time it is destroyed.
//=======================================================================
-void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex,
- BRepMesh::MapOfIntegerInteger& theLoopEdges )
+void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex,
+ IMeshData::MapOfIntegerInteger& theLoopEdges )
{
myCircles.Delete( theIndex );
- Standard_Integer e[3];
- Standard_Boolean o[3];
- GetTriangle( theIndex ).Edges( e, o );
-
+ const BRepMesh_Triangle& aElement = GetTriangle(theIndex);
+ const Standard_Integer(&e)[3] = aElement.myEdges;
+ const Standard_Boolean(&o)[3] = aElement.myOrientations;
+
myMeshData->RemoveElement( theIndex );
for ( Standard_Integer i = 0; i < 3; ++i )
//purpose : Computes the triangulation and add the vertices edges and
// triangles to the Mesh data structure
//=======================================================================
-void BRepMesh_Delaun::compute(BRepMesh::Array1OfInteger& theVertexIndexes)
+void BRepMesh_Delaun::compute(IMeshData::VectorOfInteger& theVertexIndexes)
{
// Insertion of edges of super triangles in the list of free edges:
- BRepMesh::MapOfIntegerInteger aLoopEdges(10, myMeshData->Allocator());
- Standard_Integer e[3];
- Standard_Boolean o[3];
- mySupTrian.Edges( e, o );
+ IMeshData::MapOfIntegerInteger aLoopEdges(10, myMeshData->Allocator());
+ const Standard_Integer(&e)[3] = mySupTrian.myEdges;
aLoopEdges.Bind( e[0], Standard_True );
aLoopEdges.Bind( e[1], Standard_True );
aSelector.NeighboursOfNode( mySupVert[aSupVertId] );
aLoopEdges.Clear();
- BRepMesh::MapOfInteger::Iterator aFreeTriangles( aSelector.Elements() );
+ IMeshData::IteratorOfMapOfInteger aFreeTriangles( aSelector.Elements() );
for ( ; aFreeTriangles.More(); aFreeTriangles.Next() )
deleteTriangle( aFreeTriangles.Key(), aLoopEdges );
// All edges that remain free are removed from aLoopEdges;
// only the boundary edges of the triangulation remain there
- BRepMesh::MapOfIntegerInteger::Iterator aFreeEdges( aLoopEdges );
+ IMeshData::MapOfIntegerInteger::Iterator aFreeEdges( aLoopEdges );
for ( ; aFreeEdges.More(); aFreeEdges.Next() )
{
if ( myMeshData->ElementsConnectedTo( aFreeEdges.Key() ).IsEmpty() )
//function : createTriangles
//purpose : Creates the triangles beetween the node and the polyline.
//=======================================================================
-void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIndex,
- BRepMesh::MapOfIntegerInteger& thePoly)
+void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIndex,
+ IMeshData::MapOfIntegerInteger& thePoly)
{
- BRepMesh::ListOfInteger aLoopEdges, anExternalEdges;
+ IMeshData::ListOfInteger aLoopEdges, anExternalEdges;
const gp_XY& aVertexCoord = myMeshData->GetNode( theVertexIndex ).Coord();
- BRepMesh::MapOfIntegerInteger::Iterator anEdges( thePoly );
+ IMeshData::MapOfIntegerInteger::Iterator anEdges( thePoly );
for ( ; anEdges.More(); anEdges.Next() )
{
Standard_Integer anEdgeId = anEdges.Key();
const BRepMesh_Edge& anEdge = GetEdge( anEdgeId );
- const Standard_Boolean isPositive = thePoly (anEdgeId) != 0;
+ Standard_Boolean isPositive = thePoly( anEdgeId ) != 0;
Standard_Integer aNodes[3];
if ( isPositive )
//purpose : Creation of triangles from the new nodes
//=======================================================================
void BRepMesh_Delaun::createTrianglesOnNewVertices(
- BRepMesh::Array1OfInteger& theVertexIndexes)
+ IMeshData::VectorOfInteger& theVertexIndexes)
{
Handle(NCollection_IncAllocator) aAllocator =
- new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
Standard_Real aTolU, aTolV;
myMeshData->Data()->GetTolerance(aTolU, aTolV);
for( ; anIndex <= anUpper; ++anIndex )
{
aAllocator->Reset(Standard_False);
- BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
+ IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
Standard_Integer aVertexIdx = theVertexIndexes( anIndex );
const BRepMesh_Vertex& aVertex = GetVertex( aVertexIdx );
// Iterator in the list of indexes of circles containing the node
- BRepMesh::ListOfInteger& aCirclesList = myCircles.Select( aVertex.Coord() );
+ IMeshData::ListOfInteger& aCirclesList = myCircles.Select( aVertex.Coord() );
Standard_Integer onEgdeId = 0, aTriangleId = 0;
- BRepMesh::ListOfInteger::Iterator aCircleIt( aCirclesList );
+ IMeshData::ListOfInteger::Iterator aCircleIt( aCirclesList );
for ( ; aCircleIt.More(); aCircleIt.Next() )
{
// To add a node in the mesh it is necessary to check conditions:
while ( isModify && !aCirclesList.IsEmpty() )
{
isModify = Standard_False;
- BRepMesh::ListOfInteger::Iterator aCircleIt1( aCirclesList );
+ IMeshData::ListOfInteger::Iterator aCircleIt1( aCirclesList );
for ( ; aCircleIt1.More(); aCircleIt1.Next() )
{
- Standard_Integer e[3];
- Standard_Boolean o[3];
- GetTriangle( aCircleIt1.Value() ).Edges( e, o );
+ const BRepMesh_Triangle& aElement = GetTriangle(aCircleIt1.Value());
+ const Standard_Integer(&e)[3] = aElement.myEdges;
if ( aLoopEdges.IsBound( e[0] ) ||
aLoopEdges.IsBound( e[1] ) ||
//=======================================================================
void BRepMesh_Delaun::insertInternalEdges()
{
- BRepMesh::HMapOfInteger anInternalEdges = InternalEdges();
+ Handle(IMeshData::MapOfInteger) anInternalEdges = InternalEdges();;
// Destruction of triancles intersecting internal edges
// and their replacement by makeshift triangles
- Standard_Integer e[3];
- Standard_Boolean o[3];
- BRepMesh::MapOfInteger::Iterator anInernalEdgesIt( *anInternalEdges );
+ IMeshData::IteratorOfMapOfInteger anInernalEdgesIt( *anInternalEdges );
for ( ; anInernalEdgesIt.More(); anInernalEdgesIt.Next() )
{
const Standard_Integer aLinkIndex = anInernalEdgesIt.Key();
Standard_Boolean isGo[2] = { Standard_True, Standard_True };
for (Standard_Integer aTriangleIt = 1; aTriangleIt <= aPair.Extent(); ++aTriangleIt)
{
- GetTriangle(aPair.Index(aTriangleIt)).Edges(e, o);
+ const BRepMesh_Triangle& aElement = GetTriangle(aPair.Index(aTriangleIt));
+ const Standard_Integer(&e)[3] = aElement.myEdges;
+ const Standard_Boolean(&o)[3] = aElement.myOrientations;
+
for (Standard_Integer i = 0; i < 3; ++i)
{
if (e[i] == aLinkIndex)
if ( aTriId < 0 || aTriId == thePrevElementId )
continue;
- Standard_Integer anEdges[3];
- Standard_Boolean anEdgesOri[3];
- GetTriangle( aTriId ).Edges( anEdges, anEdgesOri );
+ const BRepMesh_Triangle& aElement = GetTriangle(aTriId);
+ const Standard_Integer(&anEdges)[3] = aElement.myEdges;
for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
{
void BRepMesh_Delaun::cleanupMesh()
{
Handle(NCollection_IncAllocator) aAllocator =
- new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
for(;;)
{
aAllocator->Reset(Standard_False);
- BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
- BRepMesh::MapOfInteger aDelTriangles(10, aAllocator);
+ IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
+ IMeshData::MapOfInteger aDelTriangles;
- BRepMesh::HMapOfInteger aFreeEdges = FreeEdges();
- BRepMesh::MapOfInteger::Iterator aFreeEdgesIt( *aFreeEdges );
+ Handle(IMeshData::MapOfInteger) aFreeEdges = FreeEdges();
+ IMeshData::IteratorOfMapOfInteger aFreeEdgesIt( *aFreeEdges );
for ( ; aFreeEdgesIt.More(); aFreeEdgesIt.Next() )
{
const Standard_Integer& aFreeEdgeId = aFreeEdgesIt.Key();
Standard_Integer aTriId = aPair.FirstIndex();
// Check that the connected triangle is not surrounded by another triangles
- Standard_Integer anEdges[3];
- Standard_Boolean anEdgesOri[3];
- GetTriangle( aTriId ).Edges( anEdges, anEdgesOri );
+ const BRepMesh_Triangle& aElement = GetTriangle(aTriId);
+ const Standard_Integer(&anEdges)[3] = aElement.myEdges;
Standard_Boolean isCanNotBeRemoved = Standard_True;
for ( Standard_Integer aCurEdgeIdx = 0; aCurEdgeIdx < 3; ++aCurEdgeIdx )
// Destruction of triangles :
Standard_Integer aDeletedTrianglesNb = 0;
- BRepMesh::MapOfInteger::Iterator aDelTrianglesIt( aDelTriangles );
+ IMeshData::IteratorOfMapOfInteger aDelTrianglesIt( aDelTriangles );
for ( ; aDelTrianglesIt.More(); aDelTrianglesIt.Next() )
{
deleteTriangle( aDelTrianglesIt.Key(), aLoopEdges );
}
// Destruction of remaining hanging edges
- BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
+ IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
{
if ( myMeshData->ElementsConnectedTo( aLoopEdgesIt.Key() ).IsEmpty() )
//=======================================================================
void BRepMesh_Delaun::frontierAdjust()
{
- BRepMesh::HMapOfInteger aFrontier = Frontier();
+ Handle(IMeshData::MapOfInteger) aFrontier = Frontier();
Handle(NCollection_IncAllocator) aAllocator =
- new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
- BRepMesh::VectorOfInteger aFailedFrontiers(256, aAllocator);
- BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
- BRepMesh::HMapOfInteger aIntFrontierEdges =
- new BRepMesh::MapOfInteger(10, aAllocator);
+ IMeshData::VectorOfInteger aFailedFrontiers(256, aAllocator);
+ IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
+ Handle(IMeshData::MapOfInteger) aIntFrontierEdges = new IMeshData::MapOfInteger;
for ( Standard_Integer aPass = 1; aPass <= 2; ++aPass )
{
// 2 pass): find external triangles on boundary edges appeared
// during triangles replacement.
- BRepMesh::MapOfInteger::Iterator aFrontierIt( *aFrontier );
+ IMeshData::IteratorOfMapOfInteger aFrontierIt( *aFrontier );
for ( ; aFrontierIt.More(); aFrontierIt.Next() )
{
Standard_Integer aFrontierId = aFrontierIt.Key();
if( aPriorElemId < 0 )
continue;
- Standard_Integer e[3];
- Standard_Boolean o[3];
- GetTriangle( aPriorElemId ).Edges( e, o );
+ const BRepMesh_Triangle& aElement = GetTriangle(aPriorElemId);
+ const Standard_Integer(&e)[3] = aElement.myEdges;
+ const Standard_Boolean(&o)[3] = aElement.myOrientations;
Standard_Boolean isTriangleFound = Standard_False;
for ( Standard_Integer n = 0; n < 3; ++n )
}
// destrucrion of remaining hanging edges :
- BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
+ IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
{
Standard_Integer aLoopEdgeId = aLoopEdgesIt.Key();
// situation when frontier edge has a triangle at a right side, but its free
// links cross another frontieres and meshLeftPolygonOf itself can't collect
// a closed polygon.
- BRepMesh::VectorOfInteger::Iterator aFailedFrontiersIt( aFailedFrontiers );
+ IMeshData::VectorOfInteger::Iterator aFailedFrontiersIt( aFailedFrontiers );
for ( ; aFailedFrontiersIt.More(); aFailedFrontiersIt.Next() )
{
Standard_Integer aFrontierId = aFailedFrontiersIt.Value();
//purpose : Add boundig box for edge defined by start & end point to
// the given vector of bounding boxes for triangulation edges
//=======================================================================
-void BRepMesh_Delaun::fillBndBox(BRepMesh::SequenceOfBndB2d& theBoxes,
- const BRepMesh_Vertex& theV1,
- const BRepMesh_Vertex& theV2)
+void BRepMesh_Delaun::fillBndBox(IMeshData::SequenceOfBndB2d& theBoxes,
+ const BRepMesh_Vertex& theV1,
+ const BRepMesh_Vertex& theV2)
{
Bnd_B2d aBox;
UpdateBndBox(theV1.Coord(), theV2.Coord(), aBox);
//purpose : Collect the polygon at the left of the given edge (material side)
//=======================================================================
Standard_Boolean BRepMesh_Delaun::meshLeftPolygonOf(
- const Standard_Integer theStartEdgeId,
- const Standard_Boolean isForward,
- BRepMesh::HMapOfInteger theSkipped )
+ const Standard_Integer theStartEdgeId,
+ const Standard_Boolean isForward,
+ Handle(IMeshData::MapOfInteger) theSkipped)
{
if ( !theSkipped.IsNull() && theSkipped->Contains( theStartEdgeId ) )
return Standard_True;
const BRepMesh_Edge& aRefEdge = GetEdge( theStartEdgeId );
- BRepMesh::SequenceOfInteger aPolygon;
+ IMeshData::SequenceOfInteger aPolygon;
Standard_Integer aStartNode, aPivotNode;
if ( isForward )
{
// Auxilary structures.
// Bounding boxes of polygon links to be used for preliminary
// analysis of intersections
- BRepMesh::SequenceOfBndB2d aBoxes;
+ IMeshData::SequenceOfBndB2d aBoxes;
fillBndBox( aBoxes, aStartEdgeVertexS, aPivotVertex );
// Hanging ends
- BRepMesh::MapOfInteger aDeadLinks;
+ IMeshData::MapOfInteger aDeadLinks;
// Links are temporarily excluded from consideration
- BRepMesh::MapOfInteger aLeprousLinks;
+ IMeshData::MapOfInteger aLeprousLinks;
aLeprousLinks.Add( theStartEdgeId );
Standard_Boolean isSkipLeprous = Standard_True;
// consideration next time until a hanging end is occured.
//=======================================================================
Standard_Integer BRepMesh_Delaun::findNextPolygonLink(
- const Standard_Integer& theFirstNode,
- const Standard_Integer& thePivotNode,
- const BRepMesh_Vertex& thePivotVertex,
- const gp_Vec2d& theRefLinkDir,
- const BRepMesh::SequenceOfBndB2d& theBoxes,
- const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::HMapOfInteger theSkipped,
- const Standard_Boolean& isSkipLeprous,
- BRepMesh::MapOfInteger& theLeprousLinks,
- BRepMesh::MapOfInteger& theDeadLinks,
- Standard_Integer& theNextPivotNode,
- gp_Vec2d& theNextLinkDir,
- Bnd_B2d& theNextLinkBndBox )
+ const Standard_Integer& theFirstNode,
+ const Standard_Integer& thePivotNode,
+ const BRepMesh_Vertex& thePivotVertex,
+ const gp_Vec2d& theRefLinkDir,
+ const IMeshData::SequenceOfBndB2d& theBoxes,
+ const IMeshData::SequenceOfInteger& thePolygon,
+ const Handle(IMeshData::MapOfInteger) theSkipped,
+ const Standard_Boolean& isSkipLeprous,
+ IMeshData::MapOfInteger& theLeprousLinks,
+ IMeshData::MapOfInteger& theDeadLinks,
+ Standard_Integer& theNextPivotNode,
+ gp_Vec2d& theNextLinkDir,
+ Bnd_B2d& theNextLinkBndBox )
{
// Find the next link having the greatest angle
// respect to a direction of a reference one
Standard_Real aMaxAngle = RealFirst();
Standard_Integer aNextLinkId = 0;
- BRepMesh::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) );
+ IMeshData::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) );
for ( ; aLinkIt.More(); aLinkIt.Next() )
{
const Standard_Integer& aNeighbourLinkInfo = aLinkIt.Value();
// <theLinkBndBox> parameter.
//=======================================================================
Standard_Boolean BRepMesh_Delaun::checkIntersection(
- const BRepMesh_Edge& theLink,
- const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
- const Standard_Boolean isConsiderEndPointTouch,
- const Standard_Boolean isConsiderPointOnEdge,
- const Standard_Boolean isSkipLastEdge,
- Bnd_B2d& theLinkBndBox ) const
+ const BRepMesh_Edge& theLink,
+ const IMeshData::SequenceOfInteger& thePolygon,
+ const IMeshData::SequenceOfBndB2d& thePolyBoxes,
+ const Standard_Boolean isConsiderEndPointTouch,
+ const Standard_Boolean isConsiderPointOnEdge,
+ const Standard_Boolean isSkipLastEdge,
+ Bnd_B2d& theLinkBndBox ) const
{
UpdateBndBox(GetVertex(theLink.FirstNode()).Coord(),
GetVertex(theLink.LastNode()).Coord(), theLinkBndBox);
continue;
gp_Pnt2d anIntPnt;
- BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( theLink, aPolyLink,
+ BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( theLink, aPolyLink,
isConsiderEndPointTouch, isConsiderPointOnEdge, anIntPnt );
if ( aIntFlag != BRepMesh_GeomTool::NoIntersection )
//function : addTriangle
//purpose : Add a triangle based on the given oriented edges into mesh
//=======================================================================
-void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3],
- const Standard_Boolean (&theEdgesOri)[3],
- const Standard_Integer (&theNodesId)[3])
+inline void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3],
+ const Standard_Boolean (&theEdgesOri)[3],
+ const Standard_Integer (&theNodesId)[3] )
{
- for (Standard_Integer i = 0; i < 3; ++i)
- {
- const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo(theEdgesId[i]);
- if (aPair.Extent() == 2)
- // it is forbidden to have more than two triangles connected to the same link
- return;
- }
Standard_Integer aNewTriangleId =
myMeshData->AddElement(BRepMesh_Triangle(theEdgesId,
theEdgesOri, BRepMesh_Free));
//function : cleanupPolygon
//purpose : Remove internal triangles from the given polygon
//=======================================================================
-void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::SequenceOfBndB2d& thePolyBoxes )
+void BRepMesh_Delaun::cleanupPolygon(const IMeshData::SequenceOfInteger& thePolygon,
+ const IMeshData::SequenceOfBndB2d& thePolyBoxes )
{
Standard_Integer aPolyLen = thePolygon.Length();
if ( aPolyLen < 3 )
return;
Handle(NCollection_IncAllocator) aAllocator =
- new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
- BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
- BRepMesh::MapOfInteger anIgnoredEdges(10, aAllocator);
- BRepMesh::MapOfInteger aPolyVerticesFindMap(10, aAllocator);
- BRepMesh::VectorOfInteger aPolyVertices(256, aAllocator);
+ IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
+ IMeshData::MapOfInteger anIgnoredEdges;
+ IMeshData::MapOfInteger aPolyVerticesFindMap;
+ IMeshData::VectorOfInteger aPolyVertices(256, aAllocator);
// Collect boundary vertices of the polygon
for ( Standard_Integer aPolyIt = 1; aPolyIt <= aPolyLen; ++aPolyIt )
{
if ( anElemId < 0 )
continue;
- Standard_Integer anEdges[3];
- Standard_Boolean anEdgesOri[3];
- GetTriangle( anElemId ).Edges(anEdges, anEdgesOri);
+ const BRepMesh_Triangle& aElement = GetTriangle(anElemId);
+ const Standard_Integer(&anEdges)[3] = aElement.myEdges;
+ const Standard_Boolean(&anEdgesOri)[3] = aElement.myOrientations;
Standard_Integer isTriangleFound = Standard_False;
for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
if ( aPolyVertices.First() != aPolyVertices.Last() )
aPolyVertices.Append( aPolyVertices.First() );
- BRepMesh::MapOfInteger aSurvivedLinks( anIgnoredEdges );
+ IMeshData::MapOfInteger aSurvivedLinks( anIgnoredEdges );
Standard_Integer aPolyVertIt = 0;
Standard_Integer anUniqueVerticesNum = aPolyVertices.Length() - 1;
thePolyBoxes, aSurvivedLinks, aLoopEdges );
}
- BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
+ IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
{
const Standard_Integer& aLoopEdgeId = aLoopEdgesIt.Key();
// inside the polygon or crossed it.
//=======================================================================
void BRepMesh_Delaun::killTrianglesAroundVertex(
- const Standard_Integer theZombieNodeId,
- const BRepMesh::VectorOfInteger& thePolyVertices,
- const BRepMesh::MapOfInteger& thePolyVerticesFindMap,
- const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
- BRepMesh::MapOfInteger& theSurvivedLinks,
- BRepMesh::MapOfIntegerInteger& theLoopEdges )
+ const Standard_Integer theZombieNodeId,
+ const IMeshData::VectorOfInteger& thePolyVertices,
+ const IMeshData::MapOfInteger& thePolyVerticesFindMap,
+ const IMeshData::SequenceOfInteger& thePolygon,
+ const IMeshData::SequenceOfBndB2d& thePolyBoxes,
+ IMeshData::MapOfInteger& theSurvivedLinks,
+ IMeshData::MapOfIntegerInteger& theLoopEdges )
{
- BRepMesh::ListOfInteger::Iterator aNeighborsIt =
+ IMeshData::ListOfInteger::Iterator aNeighborsIt =
myMeshData->LinksConnectedTo( theZombieNodeId );
// Try to infect neighbor nodes
- BRepMesh::VectorOfInteger aVictimNodes;
+ IMeshData::VectorOfInteger aVictimNodes;
for ( ; aNeighborsIt.More(); aNeighborsIt.Next() )
{
const Standard_Integer& aNeighborLinkId = aNeighborsIt.Value();
}
// Go and do your job!
- BRepMesh::VectorOfInteger::Iterator aVictimIt( aVictimNodes );
+ IMeshData::VectorOfInteger::Iterator aVictimIt( aVictimNodes );
for ( ; aVictimIt.More(); aVictimIt.Next() )
{
killTrianglesAroundVertex( aVictimIt.Value(), thePolyVertices,
//purpose : Checks is the given vertex lies inside the polygon
//=======================================================================
Standard_Boolean BRepMesh_Delaun::isVertexInsidePolygon(
- const Standard_Integer& theVertexId,
- const BRepMesh::VectorOfInteger& thePolygonVertices ) const
+ const Standard_Integer& theVertexId,
+ const IMeshData::VectorOfInteger& thePolygonVertices ) const
{
Standard_Integer aPolyLen = thePolygonVertices.Length();
if ( aPolyLen < 3 )
// boundary intersection. Does nothing elsewhere.
//=======================================================================
void BRepMesh_Delaun::killTrianglesOnIntersectingLinks(
- const Standard_Integer& theLinkToCheckId,
- const BRepMesh_Edge& theLinkToCheck,
- const Standard_Integer& theEndPoint,
- const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
- BRepMesh::MapOfInteger& theSurvivedLinks,
- BRepMesh::MapOfIntegerInteger& theLoopEdges )
+ const Standard_Integer& theLinkToCheckId,
+ const BRepMesh_Edge& theLinkToCheck,
+ const Standard_Integer& theEndPoint,
+ const IMeshData::SequenceOfInteger& thePolygon,
+ const IMeshData::SequenceOfBndB2d& thePolyBoxes,
+ IMeshData::MapOfInteger& theSurvivedLinks,
+ IMeshData::MapOfIntegerInteger& theLoopEdges )
{
if ( theSurvivedLinks.Contains( theLinkToCheckId ) )
return;
killLinkTriangles( theLinkToCheckId, theLoopEdges );
- BRepMesh::ListOfInteger::Iterator aNeighborsIt(
+ IMeshData::ListOfInteger::Iterator aNeighborsIt(
myMeshData->LinksConnectedTo(theEndPoint));
for ( ; aNeighborsIt.More(); aNeighborsIt.Next() )
//purpose : Kill triangles bound to the given link.
//=======================================================================
void BRepMesh_Delaun::killLinkTriangles(
- const Standard_Integer& theLinkId,
- BRepMesh::MapOfIntegerInteger& theLoopEdges )
+ const Standard_Integer& theLinkId,
+ IMeshData::MapOfIntegerInteger& theLoopEdges )
{
const BRepMesh_PairOfIndex& aPair =
myMeshData->ElementsConnectedTo( theLinkId );
//purpose : Processes loop within the given polygon formed by range of
// its links specified by start and end link indices.
//=======================================================================
-void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom,
- const Standard_Integer theLinkTo,
- const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::SequenceOfBndB2d& thePolyBoxes)
+void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom,
+ const Standard_Integer theLinkTo,
+ const IMeshData::SequenceOfInteger& thePolygon,
+ const IMeshData::SequenceOfBndB2d& thePolyBoxes)
{
Standard_Integer aNbOfLinksInLoop = theLinkTo - theLinkFrom - 1;
if ( aNbOfLinksInLoop < 3 )
return;
- BRepMesh::SequenceOfInteger aPolygon;
- BRepMesh::SequenceOfBndB2d aPolyBoxes;
+ IMeshData::SequenceOfInteger aPolygon;
+ IMeshData::SequenceOfBndB2d aPolyBoxes;
for ( ; aNbOfLinksInLoop > 0; --aNbOfLinksInLoop )
{
Standard_Integer aLoopLinkIndex = theLinkFrom + aNbOfLinksInLoop;
Standard_Integer BRepMesh_Delaun::createAndReplacePolygonLink(
const Standard_Integer *theNodes,
const gp_Pnt2d *thePnts,
- const Standard_Integer theRootIndex,
- const ReplaceFlag theReplaceFlag,
- BRepMesh::SequenceOfInteger& thePolygon,
- BRepMesh::SequenceOfBndB2d& thePolyBoxes )
+ const Standard_Integer theRootIndex,
+ const ReplaceFlag theReplaceFlag,
+ IMeshData::SequenceOfInteger& thePolygon,
+ IMeshData::SequenceOfBndB2d& thePolyBoxes )
{
Standard_Integer aNewEdgeId =
myMeshData->AddLink( BRepMesh_Edge(
//function : meshPolygon
//purpose :
//=======================================================================
-void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon,
- BRepMesh::SequenceOfBndB2d& thePolyBoxes,
- BRepMesh::HMapOfInteger theSkipped )
+void BRepMesh_Delaun::meshPolygon(IMeshData::SequenceOfInteger& thePolygon,
+ IMeshData::SequenceOfBndB2d& thePolyBoxes,
+ Handle(IMeshData::MapOfInteger) theSkipped)
{
// Check is the source polygon elementary
if ( meshElementaryPolygon( thePolygon ) )
};
gp_Pnt2d anIntPnt;
- BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( *aCurEdge, *aNextEdge,
+ BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( *aCurEdge, *aNextEdge,
Standard_False, Standard_True, anIntPnt );
if ( aIntFlag == BRepMesh_GeomTool::NoIntersection )
}
}
- BRepMesh::SequenceOfInteger* aPolygon1 = &thePolygon;
- BRepMesh::SequenceOfBndB2d* aPolyBoxes1 = &thePolyBoxes;
+ IMeshData::SequenceOfInteger* aPolygon1 = &thePolygon;
+ IMeshData::SequenceOfBndB2d* aPolyBoxes1 = &thePolyBoxes;
- BRepMesh::HSequenceOfInteger aPolygon2 = new BRepMesh::SequenceOfInteger;
- BRepMesh::HSequenceOfBndB2d aPolyBoxes2 = new BRepMesh::SequenceOfBndB2d;
+ Handle(IMeshData::SequenceOfInteger) aPolygon2 = new IMeshData::SequenceOfInteger;
+ Handle(IMeshData::SequenceOfBndB2d) aPolyBoxes2 = new IMeshData::SequenceOfBndB2d;
- NCollection_Sequence<BRepMesh::HSequenceOfInteger> aPolyStack;
- NCollection_Sequence<BRepMesh::HSequenceOfBndB2d> aPolyBoxStack;
+ NCollection_Sequence<Handle(IMeshData::SequenceOfInteger)> aPolyStack;
+ NCollection_Sequence<Handle(IMeshData::SequenceOfBndB2d)> aPolyBoxStack;
for (;;)
{
decomposeSimplePolygon(*aPolygon1, *aPolyBoxes1, *aPolygon2, *aPolyBoxes2);
aPolyStack.Append(aPolygon2);
aPolyBoxStack.Append(aPolyBoxes2);
- aPolygon2 = new BRepMesh::SequenceOfInteger;
- aPolyBoxes2 = new BRepMesh::SequenceOfBndB2d;
+ aPolygon2 = new IMeshData::SequenceOfInteger;
+ aPolyBoxes2 = new IMeshData::SequenceOfBndB2d;
}
if (aPolygon1->IsEmpty())
//purpose : Triangulation of closed polygon containing only three edges.
//=======================================================================
inline Standard_Boolean BRepMesh_Delaun::meshElementaryPolygon(
- const BRepMesh::SequenceOfInteger& thePolygon)
+ const IMeshData::SequenceOfInteger& thePolygon)
{
Standard_Integer aPolyLen = thePolygon.Length();
if ( aPolyLen < 3 )
//purpose :
//=======================================================================
void BRepMesh_Delaun::decomposeSimplePolygon(
- BRepMesh::SequenceOfInteger& thePolygon,
- BRepMesh::SequenceOfBndB2d& thePolyBoxes,
- BRepMesh::SequenceOfInteger& thePolygonCut,
- BRepMesh::SequenceOfBndB2d& thePolyBoxesCut)
+ IMeshData::SequenceOfInteger& thePolygon,
+ IMeshData::SequenceOfBndB2d& thePolyBoxes,
+ IMeshData::SequenceOfInteger& thePolygonCut,
+ IMeshData::SequenceOfBndB2d& thePolyBoxesCut)
{
// Check is the given polygon elementary
if ( meshElementaryPolygon( thePolygon ) )
// intersection is possible...
gp_Pnt2d anIntPnt;
- BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( aCheckLink, aPolyLink,
+ BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( aCheckLink, aPolyLink,
Standard_False, Standard_False, anIntPnt );
if( aIntFlag != BRepMesh_GeomTool::NoIntersection )
BRepMesh_SelectorOfDataStructureOfDelaun aSelector( myMeshData );
aSelector.NeighboursOf( theVertex );
- BRepMesh::MapOfIntegerInteger aLoopEdges;//( 10, myMeshData->Allocator() );
+ IMeshData::MapOfIntegerInteger aLoopEdges;//( 10, myMeshData->Allocator() );
// Loop on triangles to be destroyed :
- BRepMesh::MapOfInteger::Iterator aTriangleIt( aSelector.Elements() );
+ IMeshData::IteratorOfMapOfInteger aTriangleIt( aSelector.Elements() );
for ( ; aTriangleIt.More(); aTriangleIt.Next() )
deleteTriangle( aTriangleIt.Key(), aLoopEdges );
- BRepMesh::SequenceOfBndB2d aBoxes;
- BRepMesh::SequenceOfInteger aPolygon;
+ IMeshData::SequenceOfBndB2d aBoxes;
+ IMeshData::SequenceOfInteger aPolygon;
Standard_Integer aLoopEdgesCount = aLoopEdges.Extent();
- BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
+ IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
if ( aLoopEdgesIt.More() )
{
Standard_Integer aPivotNode = anEdge.LastNode();
Standard_Integer anEdgeId = aLoopEdgesIt.Key();
- Standard_Boolean isPositive = (aLoopEdges (anEdgeId) != 0);
+ Standard_Boolean isPositive = aLoopEdges( anEdgeId ) != 0;
if ( !isPositive )
{
Standard_Integer aTmp;
aLastNode = aFirstNode;
while ( aPivotNode != aLastNode )
{
- BRepMesh::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( aPivotNode ) );
+ IMeshData::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( aPivotNode ) );
for ( ; aLinkIt.More(); aLinkIt.Next() )
{
if ( aLinkIt.Value() != anEdgeId &&
//function : AddVertices
//purpose : Adds some vertices in the triangulation.
//=======================================================================
-void BRepMesh_Delaun::AddVertices(BRepMesh::Array1OfVertexOfDelaun& theVertices)
+void BRepMesh_Delaun::AddVertices(IMeshData::VectorOfInteger& theVertices)
{
- std::make_heap(theVertices.begin(), theVertices.end(), ComparatorOfVertexOfDelaun());
- std::sort_heap(theVertices.begin(), theVertices.end(), ComparatorOfVertexOfDelaun());
-
- Standard_Integer aLower = theVertices.Lower();
- Standard_Integer anUpper = theVertices.Upper();
-
- BRepMesh::Array1OfInteger aVertexIndexes( aLower, anUpper );
- for ( Standard_Integer i = aLower; i <= anUpper; ++i )
- aVertexIndexes(i) = myMeshData->AddNode( theVertices(i) );
+ ComparatorOfIndexedVertexOfDelaun aCmp(myMeshData);
+ std::make_heap(theVertices.begin(), theVertices.end(), aCmp);
+ std::sort_heap(theVertices.begin(), theVertices.end(), aCmp);
- createTrianglesOnNewVertices( aVertexIndexes );
+ createTrianglesOnNewVertices(theVertices);
}
//=======================================================================
//function : getEdgesByType
//purpose : Gives the list of edges with type defined by input parameter
//=======================================================================
-BRepMesh::HMapOfInteger BRepMesh_Delaun::getEdgesByType(
+Handle(IMeshData::MapOfInteger) BRepMesh_Delaun::getEdgesByType(
const BRepMesh_DegreeOfFreedom theEdgeType ) const
{
Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
- BRepMesh::HMapOfInteger aResult = new BRepMesh::MapOfInteger(1, anAlloc);
- BRepMesh::MapOfInteger::Iterator anEdgeIt( myMeshData->LinksOfDomain() );
+ Handle(IMeshData::MapOfInteger) aResult = new IMeshData::MapOfInteger;
+ IMeshData::IteratorOfMapOfInteger anEdgeIt( myMeshData->LinksOfDomain() );
for ( ; anEdgeIt.More(); anEdgeIt.Next() )
{
{
theEdgeOn = 0;
- Standard_Integer e[3];
- Standard_Boolean o[3];
Standard_Integer p[3];
const BRepMesh_Triangle& aElement = GetTriangle( theTriangleId );
- aElement.Edges(e, o);
+ const Standard_Integer(&e)[3] = aElement.myEdges;
const BRepMesh_Edge* anEdges[3] = { &GetEdge( e[0] ),
&GetEdge( e[1] ),
//function : intSegSeg
//purpose : Checks intersection between the two segments.
//=============================================================================
-BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg(
+BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg(
const BRepMesh_Edge& theEdg1,
const BRepMesh_Edge& theEdg2,
const Standard_Boolean isConsiderEndPointTouch,
//purpose : Returns area of the loop of the given polygon defined by indices
// of its start and end links.
//=============================================================================
-Standard_Real BRepMesh_Delaun::polyArea(const BRepMesh::SequenceOfInteger& thePolygon,
- const Standard_Integer theStartIndex,
- const Standard_Integer theEndIndex) const
+Standard_Real BRepMesh_Delaun::polyArea(const IMeshData::SequenceOfInteger& thePolygon,
+ const Standard_Integer theStartIndex,
+ const Standard_Integer theEndIndex) const
{
Standard_Real aArea = 0.0;
Standard_Integer aPolyLen = thePolygon.Length();
return "Error: file name or polygon data is null";
}
- BRepMesh::SequenceOfInteger& aPolygon = *(BRepMesh::SequenceOfInteger*)thePolygon;
+ IMeshData::SequenceOfInteger& aPolygon = *(IMeshData::SequenceOfInteger*)thePolygon;
- Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
+ Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
*(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr;
if (aMeshData.IsNull())
{
OCC_CATCH_SIGNALS
- BRepMesh::SequenceOfInteger::Iterator aLinksIt(aPolygon);
+ IMeshData::SequenceOfInteger::Iterator aLinksIt(aPolygon);
for (; aLinksIt.More(); aLinksIt.Next())
{
const BRepMesh_Edge& aLink = aMeshData->GetLink(Abs(aLinksIt.Value()));
#include <BRepMesh_CircleTool.hxx>
#include <BRepMesh_Triangle.hxx>
#include <BRepMesh_Edge.hxx>
-#include <BRepMesh.hxx>
+#include <IMeshData_Types.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_GeomTool.hxx>
#include <TColStd_Array1OfInteger.hxx>
DEFINE_STANDARD_ALLOC
//! Creates the triangulation with an empty Mesh data structure.
- Standard_EXPORT BRepMesh_Delaun (BRepMesh::Array1OfVertexOfDelaun& theVertices);
+ Standard_EXPORT BRepMesh_Delaun (IMeshData::Array1OfVertexOfDelaun& theVertices);
//! Creates the triangulation with an existent Mesh data structure.
Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
- BRepMesh::Array1OfVertexOfDelaun& theVertices);
+ IMeshData::Array1OfVertexOfDelaun& theVertices);
//! Creates the triangulation with an existant Mesh data structure.
Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
- BRepMesh::Array1OfInteger& theVertexIndices);
+ IMeshData::VectorOfInteger& theVertexIndices);
//! Creates the triangulation with an existant Mesh data structure.
Standard_EXPORT BRepMesh_Delaun (const Handle (BRepMesh_DataStructureOfDelaun)& theOldMesh,
- BRepMesh::Array1OfInteger& theVertexIndices,
+ IMeshData::VectorOfInteger& theVertexIndices,
const Standard_Integer theCellsCountU,
const Standard_Integer theCellsCountV);
//! Initializes the triangulation with an array of vertices.
- Standard_EXPORT void Init (BRepMesh::Array1OfVertexOfDelaun& theVertices);
+ Standard_EXPORT void Init (IMeshData::Array1OfVertexOfDelaun& theVertices);
//! Removes a vertex from the triangulation.
Standard_EXPORT void RemoveVertex (const BRepMesh_Vertex& theVertex);
//! Adds some vertices into the triangulation.
- Standard_EXPORT void AddVertices (BRepMesh::Array1OfVertexOfDelaun& theVertices);
+ Standard_EXPORT void AddVertices (IMeshData::VectorOfInteger& theVerticesIndices);
//! Modify mesh to use the edge.
//! @return True if done
}
//! Gives the list of frontier edges.
- inline BRepMesh::HMapOfInteger Frontier() const
+ inline Handle(IMeshData::MapOfInteger) Frontier() const
{
return getEdgesByType (BRepMesh_Frontier);
}
//! Gives the list of internal edges.
- inline BRepMesh::HMapOfInteger InternalEdges() const
+ inline Handle(IMeshData::MapOfInteger) InternalEdges() const
{
return getEdgesByType (BRepMesh_Fixed);
}
//! Gives the list of free edges used only one time
- inline BRepMesh::HMapOfInteger FreeEdges() const
+ inline Handle(IMeshData::MapOfInteger) FreeEdges() const
{
return getEdgesByType (BRepMesh_Free);
}
InsertBefore
};
- typedef NCollection_DataMap<Standard_Integer, BRepMesh::MapOfInteger> DataMapOfMap;
+ typedef NCollection_DataMap<Standard_Integer, IMeshData::MapOfInteger> DataMapOfMap;
//! Add boundig box for edge defined by start & end point to
//! the given vector of bounding boxes for triangulation edges.
- void fillBndBox (BRepMesh::SequenceOfBndB2d& theBoxes,
+ void fillBndBox (IMeshData::SequenceOfBndB2d& theBoxes,
const BRepMesh_Vertex& theV1,
const BRepMesh_Vertex& theV2);
//! Gives the list of edges with type defined by the input parameter.
//! If the given type is BRepMesh_Free returns list of edges
//! that have number of connected elements less or equal 1.
- BRepMesh::HMapOfInteger getEdgesByType (const BRepMesh_DegreeOfFreedom theEdgeType) const;
+ Handle(IMeshData::MapOfInteger) getEdgesByType (const BRepMesh_DegreeOfFreedom theEdgeType) const;
//! Run triangulation procedure.
- void perform (BRepMesh::Array1OfInteger& theVertexIndices,
- const Standard_Integer theCellsCountU = -1,
- const Standard_Integer theCellsCountV = -1);
+ void perform (IMeshData::VectorOfInteger& theVertexIndices,
+ const Standard_Integer theCellsCountU = -1,
+ const Standard_Integer theCellsCountV = -1);
//! Build the super mesh.
void superMesh (const Bnd_Box2d& theBox,
//! Computes the triangulation and adds the vertices,
//! edges and triangles to the Mesh data structure.
- void compute (BRepMesh::Array1OfInteger& theVertexIndices);
+ void compute (IMeshData::VectorOfInteger& theVertexIndices);
//! Adjust the mesh on the frontier.
void frontierAdjust();
//! Find left polygon of the given edge and call meshPolygon.
Standard_Boolean meshLeftPolygonOf(
- const Standard_Integer theEdgeIndex,
- const Standard_Boolean isForward,
- BRepMesh::HMapOfInteger theSkipped = NULL);
+ const Standard_Integer theEdgeIndex,
+ const Standard_Boolean isForward,
+ Handle(IMeshData::MapOfInteger) theSkipped = NULL);
//! Find next link starting from the given node and has maximum
//! angle respect the given reference link.
//! Each time the next link is found other neighbor links at the pivot
//! node are marked as leprous and will be excluded from consideration
//! next time until a hanging end is occured.
- Standard_Integer findNextPolygonLink (const Standard_Integer& theFirstNode,
- const Standard_Integer& thePivotNode,
- const BRepMesh_Vertex& thePivotVertex,
- const gp_Vec2d& theRefLinkDir,
- const BRepMesh::SequenceOfBndB2d& theBoxes,
- const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::HMapOfInteger theSkipped,
- const Standard_Boolean& isSkipLeprous,
- BRepMesh::MapOfInteger& theLeprousLinks,
- BRepMesh::MapOfInteger& theDeadLinks,
- Standard_Integer& theNextPivotNode,
- gp_Vec2d& theNextLinkDir,
- Bnd_B2d& theNextLinkBndBox);
+ Standard_Integer findNextPolygonLink (const Standard_Integer& theFirstNode,
+ const Standard_Integer& thePivotNode,
+ const BRepMesh_Vertex& thePivotVertex,
+ const gp_Vec2d& theRefLinkDir,
+ const IMeshData::SequenceOfBndB2d& theBoxes,
+ const IMeshData::SequenceOfInteger& thePolygon,
+ const Handle(IMeshData::MapOfInteger) theSkipped,
+ const Standard_Boolean& isSkipLeprous,
+ IMeshData::MapOfInteger& theLeprousLinks,
+ IMeshData::MapOfInteger& theDeadLinks,
+ Standard_Integer& theNextPivotNode,
+ gp_Vec2d& theNextLinkDir,
+ Bnd_B2d& theNextLinkBndBox);
//! Check is the given link intersects the polygon boundaries.
//! Returns bounding box for the given link trough the theLinkBndBox parameter.
- Standard_Boolean checkIntersection (const BRepMesh_Edge& theLink,
- const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
- const Standard_Boolean isConsiderEndPointTouch,
- const Standard_Boolean isConsiderPointOnEdge,
- const Standard_Boolean isSkipLastEdge,
- Bnd_B2d& theLinkBndBox) const;
+ Standard_Boolean checkIntersection (const BRepMesh_Edge& theLink,
+ const IMeshData::SequenceOfInteger& thePolygon,
+ const IMeshData::SequenceOfBndB2d& thePolyBoxes,
+ const Standard_Boolean isConsiderEndPointTouch,
+ const Standard_Boolean isConsiderPointOnEdge,
+ const Standard_Boolean isSkipLastEdge,
+ Bnd_B2d& theLinkBndBox) const;
//! Triangulatiion of a closed polygon described by the list
//! of indexes of its edges in the structure.
//! (negative index means reversed edge)
- void meshPolygon (BRepMesh::SequenceOfInteger& thePolygon,
- BRepMesh::SequenceOfBndB2d& thePolyBoxes,
- BRepMesh::HMapOfInteger theSkipped = NULL);
+ void meshPolygon (IMeshData::SequenceOfInteger& thePolygon,
+ IMeshData::SequenceOfBndB2d& thePolyBoxes,
+ Handle(IMeshData::MapOfInteger) theSkipped = NULL);
//! Decomposes the given closed simple polygon (polygon without glued edges
//! and loops) on two simpler ones by adding new link at the most thin part
//! @param thePolygonCut product of decomposition of source polygon (second part of decomposition).
//! @param thePolyBoxesCut bounding boxes corresponded to resulting polygon's links.
void decomposeSimplePolygon (
- BRepMesh::SequenceOfInteger& thePolygon,
- BRepMesh::SequenceOfBndB2d& thePolyBoxes,
- BRepMesh::SequenceOfInteger& thePolygonCut,
- BRepMesh::SequenceOfBndB2d& thePolyBoxesCut);
+ IMeshData::SequenceOfInteger& thePolygon,
+ IMeshData::SequenceOfBndB2d& thePolyBoxes,
+ IMeshData::SequenceOfInteger& thePolygonCut,
+ IMeshData::SequenceOfBndB2d& thePolyBoxesCut);
//! Triangulation of closed polygon containing only three edges.
- inline Standard_Boolean meshElementaryPolygon (const BRepMesh::SequenceOfInteger& thePolygon);
+ inline Standard_Boolean meshElementaryPolygon (const IMeshData::SequenceOfInteger& thePolygon);
//! Creates the triangles beetween the given node and the given polyline.
void createTriangles (const Standard_Integer theVertexIndex,
- BRepMesh::MapOfIntegerInteger& thePoly);
+ IMeshData::MapOfIntegerInteger& thePoly);
//! Add a triangle based on the given oriented edges into mesh
- void addTriangle (const Standard_Integer (&theEdgesId)[3],
- const Standard_Boolean (&theEdgesOri)[3],
- const Standard_Integer (&theNodesId)[3]);
+ inline void addTriangle (const Standard_Integer (&theEdgesId)[3],
+ const Standard_Boolean (&theEdgesOri)[3],
+ const Standard_Integer (&theNodesId)[3]);
//! Deletes the triangle with the given index and adds the free edges into the map.
//! When an edge is suppressed more than one time it is destroyed.
void deleteTriangle (const Standard_Integer theIndex,
- BRepMesh::MapOfIntegerInteger& theLoopEdges);
+ IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Returns start and end nodes of the given edge in respect to its orientation.
void getOrientedNodes (const BRepMesh_Edge& theEdge,
//! Processes loop within the given polygon formed by range of its
//! links specified by start and end link indices.
- void processLoop (const Standard_Integer theLinkFrom,
- const Standard_Integer theLinkTo,
- const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::SequenceOfBndB2d& thePolyBoxes);
+ void processLoop (const Standard_Integer theLinkFrom,
+ const Standard_Integer theLinkTo,
+ const IMeshData::SequenceOfInteger& thePolygon,
+ const IMeshData::SequenceOfBndB2d& thePolyBoxes);
//! Creates new link based on the given nodes and updates the given polygon.
- Standard_Integer createAndReplacePolygonLink (const Standard_Integer theNodes[],
- const gp_Pnt2d thePnts [],
- const Standard_Integer theRootIndex,
- const ReplaceFlag theReplaceFlag,
- BRepMesh::SequenceOfInteger& thePolygon,
- BRepMesh::SequenceOfBndB2d& thePolyBoxes);
+ Standard_Integer createAndReplacePolygonLink (const Standard_Integer theNodes[],
+ const gp_Pnt2d thePnts [],
+ const Standard_Integer theRootIndex,
+ const ReplaceFlag theReplaceFlag,
+ IMeshData::SequenceOfInteger& thePolygon,
+ IMeshData::SequenceOfBndB2d& thePolyBoxes);
//! Creates the triangles on new nodes.
- void createTrianglesOnNewVertices (BRepMesh::Array1OfInteger& theVertexIndices);
+ void createTrianglesOnNewVertices (IMeshData::VectorOfInteger& theVertexIndices);
//! Cleanup mesh from the free triangles.
void cleanupMesh();
const Standard_Integer thePrevElementId);
//! Remove internal triangles from the given polygon.
- void cleanupPolygon (const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::SequenceOfBndB2d& thePolyBoxes);
+ void cleanupPolygon (const IMeshData::SequenceOfInteger& thePolygon,
+ const IMeshData::SequenceOfBndB2d& thePolyBoxes);
//! Checks is the given vertex lies inside the polygon.
- Standard_Boolean isVertexInsidePolygon (const Standard_Integer& theVertexId,
- const BRepMesh::VectorOfInteger& thePolygonVertices) const;
+ Standard_Boolean isVertexInsidePolygon (const Standard_Integer& theVertexId,
+ const IMeshData::VectorOfInteger& thePolygonVertices) const;
//! Remove all triangles and edges that are placed inside the polygon or crossed it.
- void killTrianglesAroundVertex (const Standard_Integer theZombieNodeId,
- const BRepMesh::VectorOfInteger& thePolyVertices,
- const BRepMesh::MapOfInteger& thePolyVerticesFindMap,
- const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
- BRepMesh::MapOfInteger& theSurvivedLinks,
- BRepMesh::MapOfIntegerInteger& theLoopEdges);
+ void killTrianglesAroundVertex (const Standard_Integer theZombieNodeId,
+ const IMeshData::VectorOfInteger& thePolyVertices,
+ const IMeshData::MapOfInteger& thePolyVerticesFindMap,
+ const IMeshData::SequenceOfInteger& thePolygon,
+ const IMeshData::SequenceOfBndB2d& thePolyBoxes,
+ IMeshData::MapOfInteger& theSurvivedLinks,
+ IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Checks is the given link crosses the polygon boundary.
//! If yes, kills its triangles and checks neighbor links on boundary intersection. Does nothing elsewhere.
- void killTrianglesOnIntersectingLinks (const Standard_Integer& theLinkToCheckId,
- const BRepMesh_Edge& theLinkToCheck,
- const Standard_Integer& theEndPoint,
- const BRepMesh::SequenceOfInteger& thePolygon,
- const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
- BRepMesh::MapOfInteger& theSurvivedLinks,
- BRepMesh::MapOfIntegerInteger& theLoopEdges);
+ void killTrianglesOnIntersectingLinks (const Standard_Integer& theLinkToCheckId,
+ const BRepMesh_Edge& theLinkToCheck,
+ const Standard_Integer& theEndPoint,
+ const IMeshData::SequenceOfInteger& thePolygon,
+ const IMeshData::SequenceOfBndB2d& thePolyBoxes,
+ IMeshData::MapOfInteger& theSurvivedLinks,
+ IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Kill triangles bound to the given link.
- void killLinkTriangles (const Standard_Integer& theLinkId,
- BRepMesh::MapOfIntegerInteger& theLoopEdges);
+ void killLinkTriangles (const Standard_Integer& theLinkId,
+ IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Calculates distances between the given point and edges of triangle.
Standard_Real calculateDist (const gp_XY theVEdges[3],
gp_Pnt2d& theIntPnt) const;
//! Returns area of the loop of the given polygon defined by indices of its start and end links.
- Standard_Real polyArea (const BRepMesh::SequenceOfInteger& thePolygon,
- const Standard_Integer theStartIndex,
- const Standard_Integer theEndIndex) const;
+ Standard_Real polyArea (const IMeshData::SequenceOfInteger& thePolygon,
+ const Standard_Integer theStartIndex,
+ const Standard_Integer theEndIndex) const;
//! Performs insertion of internal edges into mesh.
void insertInternalEdges();
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_DelaunayBaseMeshAlgo.hxx>
+#include <BRepMesh_MeshTool.hxx>
+#include <BRepMesh_Delaun.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_DelaunayBaseMeshAlgo::BRepMesh_DelaunayBaseMeshAlgo()
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_DelaunayBaseMeshAlgo::~BRepMesh_DelaunayBaseMeshAlgo()
+{
+}
+
+//=======================================================================
+//function : generateMesh
+//purpose :
+//=======================================================================
+void BRepMesh_DelaunayBaseMeshAlgo::generateMesh()
+{
+ const Handle(BRepMesh_DataStructureOfDelaun)& aStructure = getStructure();
+ const Handle(VectorOfPnt)& aNodesMap = getNodesMap();
+
+ IMeshData::VectorOfInteger aVerticesOrder(aNodesMap->Size(), getAllocator());
+ for (Standard_Integer i = 1; i <= aNodesMap->Size(); ++i)
+ {
+ aVerticesOrder.Append(i);
+ }
+
+ std::pair<Standard_Integer, Standard_Integer> aCellsCount = getCellsCount (aVerticesOrder.Size ());
+ BRepMesh_Delaun aMesher(aStructure, aVerticesOrder, aCellsCount.first, aCellsCount.second);
+ BRepMesh_MeshTool aCleaner(aStructure);
+ aCleaner.EraseFreeLinks();
+
+ postProcessMesh(aMesher);
+}
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_DelaunayBaseMeshAlgo_HeaderFile
+#define _BRepMesh_DelaunayBaseMeshAlgo_HeaderFile
+
+#include <BRepMesh_BaseMeshAlgo.hxx>
+#include <NCollection_Shared.hxx>
+#include <IMeshTools_Parameters.hxx>
+
+class BRepMesh_DataStructureOfDelaun;
+class BRepMesh_Delaun;
+
+//! Class provides base fuctionality to build face triangulation using Dealunay approach.
+//! Performs generation of mesh using raw data from model.
+class BRepMesh_DelaunayBaseMeshAlgo : public BRepMesh_BaseMeshAlgo
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_DelaunayBaseMeshAlgo();
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_DelaunayBaseMeshAlgo();
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_DelaunayBaseMeshAlgo, BRepMesh_BaseMeshAlgo)
+
+protected:
+
+ //! Returns size of cell to be used by acceleration circles grid structure.
+ virtual std::pair<Standard_Integer, Standard_Integer> getCellsCount (const Standard_Integer /*theVerticesNb*/)
+ {
+ return std::pair<Standard_Integer, Standard_Integer> (-1, -1);
+ }
+
+ //! Generates mesh for the contour stored in data structure.
+ Standard_EXPORT virtual void generateMesh() Standard_OVERRIDE;
+
+ //! Perfroms processing of generated mesh.
+ //! By default does nothing.
+ virtual void postProcessMesh(BRepMesh_Delaun& /*theMesher*/)
+ {
+ }
+};
+
+#endif
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMeshTools_DelaunayDeflectionControlMeshAlgo_HeaderFile
+#define _BRepMeshTools_DelaunayDeflectionControlMeshAlgo_HeaderFile
+
+#include <BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx>
+#include <BRepMesh_GeomTool.hxx>
+
+//! Extends node insertion Delaunay meshing algo in order to control
+//! deflection of generated trianges. Splits triangles failing the check.
+template<class RangeSplitter>
+class BRepMesh_DelaunayDeflectionControlMeshAlgo : public BRepMesh_DelaunayNodeInsertionMeshAlgo<RangeSplitter>
+{
+private:
+ // Typedef for OCCT RTTI
+ typedef BRepMesh_DelaunayNodeInsertionMeshAlgo<RangeSplitter> DelaunayInsertionBaseClass;
+
+public:
+
+ //! Constructor.
+ BRepMesh_DelaunayDeflectionControlMeshAlgo()
+ : myMaxSqDeflection(-1.),
+ myIsAllDegenerated(Standard_False)
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_DelaunayDeflectionControlMeshAlgo()
+ {
+ }
+
+protected:
+
+ //! Perfroms processing of generated mesh. Generates surface nodes and inserts them into structure.
+ virtual void postProcessMesh(BRepMesh_Delaun& theMesher) Standard_OVERRIDE
+ {
+ // Insert surface nodes.
+ DelaunayInsertionBaseClass::postProcessMesh(theMesher);
+
+ if (this->getParameters().ControlSurfaceDeflection &&
+ this->getStructure()->ElementsOfDomain().Extent() > 0)
+ {
+ optimizeMesh(theMesher);
+ }
+ }
+
+ //! Checks deviation of a mesh from geometrical surface.
+ //! Inserts additional nodes in case of huge deviation.
+ virtual void optimizeMesh(BRepMesh_Delaun& theMesher)
+ {
+ Handle(NCollection_IncAllocator) aTmpAlloc =
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
+
+ myCouplesMap = new IMeshData::MapOfOrientedEdges(3 * this->getStructure()->ElementsOfDomain().Extent(), aTmpAlloc);
+ myControlNodes = new IMeshData::ListOfPnt2d(aTmpAlloc);
+ myCircles = &theMesher.Circles();
+
+ const Standard_Integer aIterationsNb = 11;
+ Standard_Boolean isInserted = Standard_True;
+ for (Standard_Integer aPass = 1; aPass <= aIterationsNb && isInserted && !myIsAllDegenerated; ++aPass)
+ {
+ // Reset stop condition
+ myMaxSqDeflection = -1.;
+ myIsAllDegenerated = Standard_True;
+ myControlNodes->Clear();
+
+ if (this->getStructure()->ElementsOfDomain().Extent() < 1)
+ {
+ break;
+ }
+
+ // Iterate on current triangles
+ IMeshData::IteratorOfMapOfInteger aTriangleIt(this->getStructure()->ElementsOfDomain());
+ for (; aTriangleIt.More(); aTriangleIt.Next())
+ {
+ const BRepMesh_Triangle& aTriangle = this->getStructure()->GetElement(aTriangleIt.Key());
+ splitTriangleGeometry(aTriangle);
+ }
+
+ isInserted = this->insertNodes(myControlNodes, theMesher);
+ }
+
+ myCouplesMap.Nullify();
+ myControlNodes.Nullify();
+
+ if (!(myMaxSqDeflection < 0.))
+ {
+ this->getDFace()->SetDeflection(Sqrt(myMaxSqDeflection));
+ }
+ }
+
+private:
+ //! Contains geometrical data related to node of triangle.
+ struct TriangleNodeInfo
+ {
+ gp_XY Point2d;
+ gp_XYZ Point;
+ Standard_Boolean isFrontierLink;
+ };
+
+ //! Functor computing deflection of a point from surface.
+ class NormalDeviation
+ {
+ public:
+ NormalDeviation(
+ const gp_Pnt& theRefPnt,
+ const gp_Vec& theNormal)
+ : myRefPnt(theRefPnt),
+ myNormal(theNormal)
+ {
+ }
+
+ Standard_Real SquareDeviation(const gp_Pnt& thePoint) const
+ {
+ const Standard_Real aDeflection = Abs(myNormal.Dot(gp_Vec(myRefPnt, thePoint)));
+ return aDeflection * aDeflection;
+ }
+
+ private:
+
+ NormalDeviation (const NormalDeviation& theOther);
+
+ void operator= (const NormalDeviation& theOther);
+
+ private:
+
+ const gp_Pnt& myRefPnt;
+ const gp_Vec& myNormal;
+ };
+
+ //! Functor computing deflection of a point on triangle link from surface.
+ class LineDeviation
+ {
+ public:
+
+ LineDeviation(
+ const gp_Pnt& thePnt1,
+ const gp_Pnt& thePnt2)
+ : myPnt1(thePnt1),
+ myPnt2(thePnt2)
+ {
+ }
+
+ Standard_Real SquareDeviation(const gp_Pnt& thePoint) const
+ {
+ return BRepMesh_GeomTool::SquareDeflectionOfSegment(myPnt1, myPnt2, thePoint);
+ }
+
+ private:
+
+ LineDeviation (const LineDeviation& theOther);
+
+ void operator= (const LineDeviation& theOther);
+
+ private:
+ const gp_Pnt& myPnt1;
+ const gp_Pnt& myPnt2;
+ };
+
+ //! Returns nodes info of the given triangle.
+ inline void getTriangleInfo(
+ const BRepMesh_Triangle& theTriangle,
+ const Standard_Integer (&theNodesIndices)[3],
+ TriangleNodeInfo (&theInfo)[3]) const
+ {
+ const Standard_Integer(&e)[3] = theTriangle.myEdges;
+ for (Standard_Integer i = 0; i < 3; ++i)
+ {
+ const BRepMesh_Vertex& aVertex = this->getStructure()->GetNode(theNodesIndices[i]);
+ theInfo[i].Point2d = this->getRangeSplitter().Scale(aVertex.Coord(), Standard_False).XY();
+ theInfo[i].Point = this->getNodesMap()->Value(aVertex.Location3d()).XYZ();
+ theInfo[i].isFrontierLink = (this->getStructure()->GetLink(e[i]).Movability() == BRepMesh_Frontier);
+ }
+ }
+
+ // Check geometry of the given triangle. If triangle does not suit specified deflection, inserts new point.
+ void splitTriangleGeometry(const BRepMesh_Triangle& theTriangle)
+ {
+ if (theTriangle.Movability() != BRepMesh_Deleted)
+ {
+ Standard_Integer aNodexIndices[3];
+ this->getStructure()->ElementNodes(theTriangle, aNodexIndices);
+
+ TriangleNodeInfo aNodesInfo[3];
+ getTriangleInfo(theTriangle, aNodexIndices, aNodesInfo);
+
+ gp_Vec aNormal;
+ gp_Vec aLinkVec[3];
+ if (computeTriangleGeometry(aNodesInfo, aLinkVec, aNormal))
+ {
+ myIsAllDegenerated = Standard_False;
+
+ const gp_XY aCenter2d = (aNodesInfo[0].Point2d +
+ aNodesInfo[1].Point2d +
+ aNodesInfo[2].Point2d) / 3.;
+
+ usePoint(aCenter2d, NormalDeviation(aNodesInfo[0].Point, aNormal));
+ splitLinks(aNodesInfo, aNodexIndices);
+ }
+ }
+ }
+
+ //! Updates array of links vectors.
+ //! @return False on degenerative triangle.
+ inline Standard_Boolean computeTriangleGeometry(
+ const TriangleNodeInfo(&theNodesInfo)[3],
+ gp_Vec (&theLinks)[3],
+ gp_Vec &theNormal)
+ {
+ if (checkTriangleForDegenerativityAndGetLinks(theNodesInfo, theLinks))
+ {
+ if (checkTriangleArea2d(theNodesInfo))
+ {
+ if (computeNormal(theLinks[0], theLinks[1], theNormal))
+ {
+ return Standard_True;
+ }
+ }
+ }
+
+ return Standard_False;
+ }
+
+ //! Updates array of links vectors.
+ //! @return False on degenerative triangle.
+ inline Standard_Boolean checkTriangleForDegenerativityAndGetLinks(
+ const TriangleNodeInfo (&theNodesInfo)[3],
+ gp_Vec (&theLinks)[3])
+ {
+ const Standard_Real MinimalSqLength3d = 1.e-12;
+ for (Standard_Integer i = 0; i < 3; ++i)
+ {
+ theLinks[i] = theNodesInfo[(i + 1) % 3].Point - theNodesInfo[i].Point;
+ if (theLinks[i].SquareMagnitude() < MinimalSqLength3d)
+ {
+ return Standard_False;
+ }
+ }
+
+ return Standard_True;
+ }
+
+ //! Checks area of triangle in parametric space for degenerativity.
+ //! @return False on degenerative triangle.
+ inline Standard_Boolean checkTriangleArea2d(
+ const TriangleNodeInfo (&theNodesInfo)[3])
+ {
+ const gp_Vec2d aLink2d1(theNodesInfo[0].Point2d, theNodesInfo[1].Point2d);
+ const gp_Vec2d aLink2d2(theNodesInfo[1].Point2d, theNodesInfo[2].Point2d);
+
+ const Standard_Real MinimalArea2d = 1.e-9;
+ return (Abs(aLink2d1 ^ aLink2d2) > MinimalArea2d);
+ }
+
+ //! Computes normal using two link vectors.
+ //! @return True on success, False in case of normal of null magnitude.
+ inline Standard_Boolean computeNormal(const gp_Vec& theLink1,
+ const gp_Vec& theLink2,
+ gp_Vec& theNormal)
+ {
+ const gp_Vec aNormal(theLink1 ^ theLink2);
+ if (aNormal.SquareMagnitude() > gp::Resolution())
+ {
+ theNormal = aNormal.Normalized();
+ return Standard_True;
+ }
+
+ return Standard_False;
+ }
+
+ //! Computes deflection of midpoints of triangles links.
+ //! @return True if point fits specified deflection.
+ inline void splitLinks(
+ const TriangleNodeInfo (&theNodesInfo)[3],
+ const Standard_Integer (&theNodesIndices)[3])
+ {
+ // Check deflection at triangle links
+ for (Standard_Integer i = 0; i < 3; ++i)
+ {
+ if (theNodesInfo[i].isFrontierLink)
+ {
+ continue;
+ }
+
+ const Standard_Integer j = (i + 1) % 3;
+ // Check if this link was already processed
+ Standard_Integer aFirstVertex, aLastVertex;
+ if (theNodesIndices[i] < theNodesIndices[j])
+ {
+ aFirstVertex = theNodesIndices[i];
+ aLastVertex = theNodesIndices[j];
+ }
+ else
+ {
+ aFirstVertex = theNodesIndices[j];
+ aLastVertex = theNodesIndices[i];
+ }
+
+ if (myCouplesMap->Add(BRepMesh_OrientedEdge(aFirstVertex, aLastVertex)))
+ {
+ const gp_XY aMidPnt2d = (theNodesInfo[i].Point2d +
+ theNodesInfo[j].Point2d) / 2.;
+
+ usePoint(aMidPnt2d, LineDeviation(theNodesInfo[i].Point, theNodesInfo[j].Point));
+ }
+ }
+ }
+
+ //! Computes deflection of the given point and caches it for
+ //! insertion in case if it overflows deflection.
+ //! @return True if point has been cached for insertion.
+ template<class DeflectionFunctor>
+ inline void usePoint(
+ const gp_XY& thePnt2d,
+ const DeflectionFunctor& theDeflectionFunctor)
+ {
+ gp_Pnt aPnt;
+ this->getDFace()->GetSurface()->D0(thePnt2d.X(), thePnt2d.Y(), aPnt);
+ if (!checkDeflectionOfPointAndUpdateCache(thePnt2d, aPnt, theDeflectionFunctor.SquareDeviation(aPnt)))
+ {
+ myControlNodes->Append(thePnt2d);
+ }
+ }
+
+ //! Checks the given point for specified linear deflection.
+ //! Updates value of total mesh defleciton.
+ Standard_Boolean checkDeflectionOfPointAndUpdateCache(
+ const gp_XY& thePnt2d,
+ const gp_Pnt& thePnt3d,
+ const Standard_Real theSqDeflection)
+ {
+ if (theSqDeflection > myMaxSqDeflection)
+ {
+ myMaxSqDeflection = theSqDeflection;
+ }
+
+ const Standard_Real aSqDeflection =
+ this->getDFace()->GetDeflection() * this->getDFace()->GetDeflection();
+ if (theSqDeflection < aSqDeflection)
+ {
+ return Standard_True;
+ }
+
+ return rejectByMinSize(thePnt2d, thePnt3d);
+ }
+
+ //! Checks the given node for
+ Standard_Boolean rejectByMinSize(
+ const gp_XY& thePnt2d,
+ const gp_Pnt& thePnt3d)
+ {
+ const Standard_Real aSqMinSize =
+ this->getParameters().MinSize * this->getParameters().MinSize;
+
+ IMeshData::MapOfInteger aUsedNodes;
+ IMeshData::ListOfInteger& aCirclesList =
+ const_cast<BRepMesh_CircleTool&>(*myCircles).Select(
+ this->getRangeSplitter().Scale(thePnt2d, Standard_True).XY());
+
+ IMeshData::ListOfInteger::Iterator aCircleIt(aCirclesList);
+ for (; aCircleIt.More(); aCircleIt.Next())
+ {
+ const BRepMesh_Triangle& aTriangle = this->getStructure()->GetElement(aCircleIt.Value());
+
+ Standard_Integer aNodes[3];
+ this->getStructure()->ElementNodes(aTriangle, aNodes);
+
+ for (Standard_Integer i = 0; i < 3; ++i)
+ {
+ if (!aUsedNodes.Contains(aNodes[i]))
+ {
+ aUsedNodes.Add(aNodes[i]);
+ const BRepMesh_Vertex& aVertex = this->getStructure()->GetNode(aNodes[i]);
+ const gp_Pnt& aPoint = this->getNodesMap()->Value(aVertex.Location3d());
+
+ if (thePnt3d.SquareDistance(aPoint) < aSqMinSize)
+ {
+ return Standard_True;
+ }
+ }
+ }
+ }
+
+ return Standard_False;
+ }
+
+private:
+ Standard_Real myMaxSqDeflection;
+ Standard_Boolean myIsAllDegenerated;
+ Handle(IMeshData::MapOfOrientedEdges) myCouplesMap;
+ Handle(IMeshData::ListOfPnt2d) myControlNodes;
+ const BRepMesh_CircleTool* myCircles;
+};
+
+#endif
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_DelaunayNodeInsertionMeshAlgo_HeaderFile
+#define _BRepMesh_DelaunayNodeInsertionMeshAlgo_HeaderFile
+
+#include <BRepMesh_NodeInsertionMeshAlgo.hxx>
+#include <BRepMesh_GeomTool.hxx>
+
+//! Extends base Delaunay meshing algo in order to enable possibility
+//! of addition of free vertices and internal nodes into the mesh.
+template<class RangeSplitter>
+class BRepMesh_DelaunayNodeInsertionMeshAlgo : public BRepMesh_NodeInsertionMeshAlgo<RangeSplitter, BRepMesh_DelaunayBaseMeshAlgo>
+{
+private:
+ // Typedef for OCCT RTTI
+ typedef BRepMesh_NodeInsertionMeshAlgo<RangeSplitter, BRepMesh_DelaunayBaseMeshAlgo> InsertionBaseClass;
+
+public:
+
+ //! Constructor.
+ BRepMesh_DelaunayNodeInsertionMeshAlgo()
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_DelaunayNodeInsertionMeshAlgo()
+ {
+ }
+
+protected:
+
+ //! Returns size of cell to be used by acceleration circles grid structure.
+ virtual std::pair<Standard_Integer, Standard_Integer> getCellsCount (const Standard_Integer theVerticesNb) Standard_OVERRIDE
+ {
+ return BRepMesh_GeomTool::CellsCount (this->getDFace()->GetSurface(), theVerticesNb,
+ this->getParameters().Deflection, &this->getRangeSplitter());
+ }
+
+ //! Perfroms processing of generated mesh. Generates surface nodes and inserts them into structure.
+ virtual void postProcessMesh(BRepMesh_Delaun& theMesher) Standard_OVERRIDE
+ {
+ InsertionBaseClass::postProcessMesh(theMesher);
+
+ const Handle(IMeshData::ListOfPnt2d) aSurfaceNodes =
+ this->getRangeSplitter().GenerateSurfaceNodes(this->getParameters());
+
+ insertNodes(aSurfaceNodes, theMesher);
+ }
+
+ //! Inserts nodes into mesh.
+ Standard_Boolean insertNodes(
+ const Handle(IMeshData::ListOfPnt2d)& theNodes,
+ BRepMesh_Delaun& theMesher)
+ {
+ if (theNodes.IsNull() || theNodes->IsEmpty())
+ {
+ return Standard_False;
+ }
+
+ IMeshData::VectorOfInteger aVertexIndexes(theNodes->Size(), this->getAllocator());
+ IMeshData::ListOfPnt2d::Iterator aNodesIt(*theNodes);
+ for (Standard_Integer aNodeIt = 1; aNodesIt.More(); aNodesIt.Next(), ++aNodeIt)
+ {
+ const gp_Pnt2d& aPnt2d = aNodesIt.Value();
+ if (this->getClassifier()->Perform(aPnt2d) == TopAbs_IN)
+ {
+ aVertexIndexes.Append(this->registerNode(this->getRangeSplitter().Point(aPnt2d),
+ aPnt2d, BRepMesh_Free, Standard_False));
+ }
+ }
+
+ theMesher.AddVertices(aVertexIndexes);
+ return !aVertexIndexes.IsEmpty();
+ }
+};
+
+#endif
}
//! Compute triangulation for set shape.
- Standard_EXPORT virtual void Perform() = 0;
+ virtual void Perform() = 0;
DEFINE_STANDARD_RTTIEXT(BRepMesh_DiscretRoot,Standard_Transient)
}
//! Alias for IsEqual.
- Standard_Boolean operator ==(const BRepMesh_Edge& Other) const
+ inline Standard_Boolean operator ==(const BRepMesh_Edge& Other) const
{
return IsEqual(Other);
}
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_EdgeDiscret.hxx>
+#include <BRepMesh_Deflection.hxx>
+#include <IMeshData_Model.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_Face.hxx>
+#include <IMeshData_PCurve.hxx>
+#include <TopExp.hxx>
+#include <BRepMesh_ShapeTool.hxx>
+#include <BRepMesh_EdgeTessellationExtractor.hxx>
+#include <IMeshData_ParametersListArrayAdaptor.hxx>
+#include <BRepMesh_CurveTessellator.hxx>
+#include <OSD_Parallel.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_EdgeDiscret::BRepMesh_EdgeDiscret ()
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_EdgeDiscret::~BRepMesh_EdgeDiscret ()
+{
+}
+
+//=======================================================================
+// Function: CreateFreeEdgeTessellator
+// Purpose :
+//=======================================================================
+Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellator(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const IMeshTools_Parameters& theParameters)
+{
+ return new BRepMesh_CurveTessellator(theDEdge, theParameters);
+}
+
+//=======================================================================
+// Function: CreateEdgeTessellator
+// Purpose :
+//=======================================================================
+Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellator(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const TopAbs_Orientation theOrientation,
+ const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters)
+{
+ return theDEdge->GetSameParam() ?
+ new BRepMesh_CurveTessellator(theDEdge, theParameters) :
+ new BRepMesh_CurveTessellator(theDEdge, theOrientation, theDFace, theParameters);
+}
+
+//=======================================================================
+// Function: CreateEdgeTessellationExtractor
+// Purpose :
+//=======================================================================
+Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellationExtractor(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const IMeshData::IFaceHandle& theDFace)
+{
+ return new BRepMesh_EdgeTessellationExtractor(theDEdge, theDFace);
+}
+
+//=======================================================================
+// Function: Perform
+// Purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_EdgeDiscret::Perform (
+ const Handle (IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& theParameters)
+{
+ myModel = theModel;
+ myParameters = theParameters;
+
+ if (myModel.IsNull())
+ {
+ return Standard_False;
+ }
+
+ OSD_Parallel::For (0, myModel->EdgesNb (), *this, !myParameters.InParallel);
+
+ myModel.Nullify(); // Do not hold link to model.
+ return Standard_True;
+}
+
+//=======================================================================
+// Function: process
+// Purpose :
+//=======================================================================
+void BRepMesh_EdgeDiscret::process (const Standard_Integer theEdgeIndex) const
+{
+ const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge (theEdgeIndex);
+ BRepMesh_Deflection::ComputeDeflection (aDEdge, myModel->GetMaxSize (), myParameters);
+
+ Handle (IMeshTools_CurveTessellator) aEdgeTessellator;
+ if (!aDEdge->IsFree ())
+ {
+ // Iterate over pcurves and check deflection on corresponding face.
+ Standard_Real aMinDeflection = RealLast ();
+ Standard_Integer aMinPCurveIndex = -1;
+ for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb (); ++aPCurveIt)
+ {
+ const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve (aPCurveIt);
+ const Standard_Real aTmpDeflection = checkExistingPolygonAndUpdateStatus(aDEdge, aPCurve);
+ if (aTmpDeflection < aMinDeflection)
+ {
+ // Identify pcurve with the smallest deflection in order to
+ // retrieve polygon that represents the most smooth discretization.
+ aMinDeflection = aTmpDeflection;
+ aMinPCurveIndex = aPCurveIt;
+ }
+
+ BRepMesh_ShapeTool::CheckAndUpdateFlags (aDEdge, aPCurve);
+ }
+
+ if (aMinPCurveIndex != -1)
+ {
+ aDEdge->SetDeflection (aMinDeflection);
+ const IMeshData::IFaceHandle aDFace = aDEdge->GetPCurve(aMinPCurveIndex)->GetFace();
+ aEdgeTessellator = CreateEdgeTessellationExtractor(aDEdge, aDFace);
+ }
+ else
+ {
+ const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(0);
+ const IMeshData::IFaceHandle aDFace = aPCurve->GetFace();
+ aEdgeTessellator = BRepMesh_EdgeDiscret::CreateEdgeTessellator(
+ aDEdge, aPCurve->GetOrientation(), aDFace, myParameters);
+ }
+ }
+ else
+ {
+ TopLoc_Location aLoc;
+ const Handle (Poly_Polygon3D)& aPoly3D = BRep_Tool::Polygon3D (aDEdge->GetEdge (), aLoc);
+ if (!aPoly3D.IsNull ())
+ {
+ if (aPoly3D->HasParameters () &&
+ aPoly3D->Deflection () < 1.1 * aDEdge->GetDeflection ())
+ {
+ // Edge already has suitable 3d polygon.
+ aDEdge->SetStatus(IMeshData_Reused);
+ return;
+ }
+ else
+ {
+ aDEdge->SetStatus(IMeshData_Outdated);
+ }
+ }
+
+ aEdgeTessellator = CreateEdgeTessellator(aDEdge, myParameters);
+ }
+
+ Tessellate3d (aDEdge, aEdgeTessellator, Standard_True);
+ if (!aDEdge->IsFree())
+ {
+ Tessellate2d(aDEdge, Standard_True);
+ }
+}
+
+//=======================================================================
+// Function: checkExistingPolygonAndUpdateStatus
+// Purpose :
+//=======================================================================
+Standard_Real BRepMesh_EdgeDiscret::checkExistingPolygonAndUpdateStatus(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const IMeshData::IPCurveHandle& thePCurve) const
+{
+ const TopoDS_Edge& aEdge = theDEdge->GetEdge ();
+ const TopoDS_Face& aFace = thePCurve->GetFace ()->GetFace ();
+
+ TopLoc_Location aLoc;
+ const Handle (Poly_Triangulation)& aFaceTriangulation =
+ BRep_Tool::Triangulation (aFace, aLoc);
+
+ Standard_Real aDeflection = RealLast ();
+ if (aFaceTriangulation.IsNull())
+ {
+ return aDeflection;
+ }
+
+ const Handle (Poly_PolygonOnTriangulation)& aPolygon =
+ BRep_Tool::PolygonOnTriangulation (aEdge, aFaceTriangulation, aLoc);
+
+ if (!aPolygon.IsNull ())
+ {
+ Standard_Boolean isConsistent = aPolygon->HasParameters () &&
+ aPolygon->Deflection () < 1.1 * theDEdge->GetDeflection ();
+
+ if (!isConsistent)
+ {
+ // Nullify edge data and mark discrete pcurve to
+ // notify necessity to mesh the entire face.
+ theDEdge->SetStatus(IMeshData_Outdated);
+ }
+ else
+ {
+ aDeflection = aPolygon->Deflection();
+ }
+ }
+
+ return aDeflection;
+}
+
+//=======================================================================
+// Function: Tessellate3d
+// Purpose :
+//=======================================================================
+void BRepMesh_EdgeDiscret::Tessellate3d(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const Handle (IMeshTools_CurveTessellator)& theTessellator,
+ const Standard_Boolean theUpdateEnds)
+{
+ // Create 3d polygon.
+ const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve();
+
+ const TopoDS_Edge& aEdge = theDEdge->GetEdge();
+ TopoDS_Vertex aFirstVertex, aLastVertex;
+ TopExp::Vertices(aEdge, aFirstVertex, aLastVertex);
+
+ if(aFirstVertex.IsNull() || aLastVertex.IsNull())
+ return;
+
+ if (theUpdateEnds)
+ {
+ gp_Pnt aPoint;
+ Standard_Real aParam;
+ theTessellator->Value(1, aPoint, aParam);
+ aCurve->AddPoint(BRep_Tool::Pnt(aFirstVertex), aParam);
+ }
+
+ if (!theDEdge->GetDegenerated())
+ {
+ for (Standard_Integer i = 2; i < theTessellator->PointsNb(); ++i)
+ {
+ gp_Pnt aPoint;
+ Standard_Real aParam;
+ if (!theTessellator->Value(i, aPoint, aParam))
+ continue;
+
+ if (theUpdateEnds)
+ {
+ aCurve->AddPoint(aPoint, aParam);
+ }
+ else
+ {
+ aCurve->InsertPoint(aCurve->ParametersNb() - 1, aPoint, aParam);
+ }
+ }
+ }
+
+ if (theUpdateEnds)
+ {
+ gp_Pnt aPoint;
+ Standard_Real aParam;
+ theTessellator->Value(theTessellator->PointsNb(), aPoint, aParam);
+ aCurve->AddPoint(BRep_Tool::Pnt(aLastVertex), aParam);
+ }
+}
+
+//=======================================================================
+// Function: Tessellate2d
+// Purpose :
+//=======================================================================
+void BRepMesh_EdgeDiscret::Tessellate2d(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const Standard_Boolean theUpdateEnds)
+{
+ const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve();
+ for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt)
+ {
+ const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt);
+ const IMeshData::IFaceHandle aDFace = aPCurve->GetFace();
+ IMeshData::ICurveArrayAdaptorHandle aCurveArray(new IMeshData::ICurveArrayAdaptor(aCurve));
+ BRepMesh_EdgeParameterProvider<IMeshData::ICurveArrayAdaptorHandle> aProvider(
+ theDEdge, aPCurve->GetOrientation(), aDFace, aCurveArray);
+
+ const Handle(Adaptor2d_HCurve2d)& aGeomPCurve = aProvider.GetPCurve();
+
+ Standard_Integer aParamIdx, aParamNb;
+ if (theUpdateEnds)
+ {
+ aParamIdx = 0;
+ aParamNb = aCurve->ParametersNb();
+ }
+ else
+ {
+ aParamIdx = 1;
+ aParamNb = aCurve->ParametersNb() - 1;
+ }
+
+ for (; aParamIdx < aParamNb; ++aParamIdx)
+ {
+ const Standard_Real aParam = aProvider.Parameter(aParamIdx, aCurve->GetPoint(aParamIdx));
+
+ gp_Pnt2d aPoint2d;
+ aGeomPCurve->D0(aParam, aPoint2d);
+ if (theUpdateEnds)
+ {
+ aPCurve->AddPoint(aPoint2d, aParam);
+ }
+ else
+ {
+ aPCurve->InsertPoint(aPCurve->ParametersNb() - 1, aPoint2d, aParam);
+ }
+ }
+ }
+}
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_EdgeDiscret_HeaderFile
+#define _BRepMesh_EdgeDiscret_HeaderFile
+
+#include <IMeshTools_ModelAlgo.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <IMeshData_Types.hxx>
+
+class IMeshTools_CurveTessellator;
+
+//! Class implements functionality of edge discret tool.
+//! Performs check of the edges for existing Poly_PolygonOnTriangulation.
+//! In case if it fits specified deflection, restores data structure using
+//! it, else clears edges from outdated data.
+class BRepMesh_EdgeDiscret : public IMeshTools_ModelAlgo
+{
+public:
+ //! Constructor.
+ Standard_EXPORT BRepMesh_EdgeDiscret ();
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_EdgeDiscret ();
+
+ //! Creates instance of free edge tessellator.
+ Standard_EXPORT static Handle(IMeshTools_CurveTessellator) CreateEdgeTessellator(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const IMeshTools_Parameters& theParameters);
+
+ //! Creates instance of edge tessellator.
+ Standard_EXPORT static Handle(IMeshTools_CurveTessellator) CreateEdgeTessellator(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const TopAbs_Orientation theOrientation,
+ const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters);
+
+ //! Creates instance of tessellation extractor.
+ Standard_EXPORT static Handle(IMeshTools_CurveTessellator) CreateEdgeTessellationExtractor(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const IMeshData::IFaceHandle& theDFace);
+
+ //! Performs processing of edges of the given model.
+ Standard_EXPORT virtual Standard_Boolean Perform (
+ const Handle (IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
+
+ //! Functor API to discretize the given edge.
+ inline void operator() (const Standard_Integer theEdgeIndex) const {
+ process (theEdgeIndex);
+ }
+
+ //! Updates 3d discrete edge model using the given tessellation tool.
+ Standard_EXPORT static void Tessellate3d(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const Handle(IMeshTools_CurveTessellator)& theTessellator,
+ const Standard_Boolean theUpdateEnds);
+
+ //! Updates 2d discrete edge model using tessellation of 3D curve.
+ Standard_EXPORT static void Tessellate2d(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const Standard_Boolean theUpdateEnds);
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_EdgeDiscret, IMeshTools_ModelAlgo)
+
+private:
+
+ //! Checks existing discretization of the edge and updates data model.
+ void process (const Standard_Integer theEdgeIndex) const;
+
+ //! Checks existing polygon on triangulation does it fit edge deflection or not.
+ //! @return deflection of polygon or RealLast () in case if edge has no polygon
+ //! or it was dropped.
+ Standard_Real checkExistingPolygonAndUpdateStatus(
+ const IMeshData::IEdgeHandle& theDEdge,
+ const IMeshData::IPCurveHandle& thePCurve) const;
+
+private:
+
+ Handle (IMeshData_Model) myModel;
+ IMeshTools_Parameters myParameters;
+};
+
+#endif
\ No newline at end of file
+++ /dev/null
-// Created on: 2014-08-13
-// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <BRepMesh_EdgeParameterProvider.hxx>
-#include <gp_Pnt.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Face.hxx>
-#include <TColStd_HArray1OfReal.hxx>
-#include <BRep_Tool.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <Precision.hxx>
-
-//=======================================================================
-//function : Constructor
-//purpose :
-//=======================================================================
-BRepMesh_EdgeParameterProvider::BRepMesh_EdgeParameterProvider(
- const TopoDS_Edge& theEdge,
- const TopoDS_Face& theFace,
- const Handle(TColStd_HArray1OfReal)& theParameters)
- : myParameters(theParameters),
- myIsSameParam(BRep_Tool::SameParameter(theEdge)),
- myScale(1.),
- myCurveAdaptor(theEdge, theFace)
-{
- if (myIsSameParam)
- return;
-
- // Extract actual parametric values
- Standard_Real aLastParam;
- BRep_Tool::Range(theEdge, theFace, myFirstParam, aLastParam);
-
- myFoundParam = myCurParam = myFirstParam;
-
- // Extract parameters stored in polygon
- myOldFirstParam =
- myParameters->Value(myParameters->Lower());
-
- const Standard_Real aOldLastParam =
- myParameters->Value(myParameters->Upper());
-
- // Calculate scale factor between actual and stored parameters
- if ((myOldFirstParam != myFirstParam || aOldLastParam != aLastParam) &&
- myOldFirstParam != aOldLastParam)
- {
- myScale = (aLastParam - myFirstParam) /
- (aOldLastParam - myOldFirstParam);
- }
-
- myProjector.Initialize(myCurveAdaptor, myCurveAdaptor.FirstParameter(),
- myCurveAdaptor.LastParameter(), Precision::PConfusion());
-}
-
-//=======================================================================
-//function : Parameter
-//purpose :
-//=======================================================================
-Standard_Real BRepMesh_EdgeParameterProvider::Parameter(
- const Standard_Integer theIndex,
- const gp_Pnt& thePoint3d)
-{
- if (myIsSameParam)
- return myParameters->Value(theIndex);
-
- // Use scaled
- Standard_Real aPrevParam = myCurParam;
- myCurParam = myFirstParam + myScale *
- (myParameters->Value(theIndex) - myOldFirstParam);
-
- myFoundParam += (myCurParam - aPrevParam);
-
- myProjector.Perform(thePoint3d, myFoundParam);
- if (myProjector.IsDone())
- myFoundParam = myProjector.Point().Parameter();
-
- return myFoundParam;
-}
#ifndef _BRepMesh_EdgeParameterProvider_HeaderFile
#define _BRepMesh_EdgeParameterProvider_HeaderFile
+#include <IMeshData_Types.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_Face.hxx>
+#include <TopoDS.hxx>
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Extrema_LocateExtPC.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <BRepAdaptor_Curve.hxx>
+#include <Adaptor3d_CurveOnSurface.hxx>
+#include <TColStd_HArray1OfReal.hxx>
+#include <Geom2dAdaptor_HCurve.hxx>
+#include <GeomAdaptor_HSurface.hxx>
class gp_Pnt;
class TopoDS_Edge;
class TopoDS_Face;
-#include <TColStd_HArray1OfReal.hxx>
//! Auxiliary class provides correct parameters
//! on curve regarding SameParameter flag.
-class BRepMesh_EdgeParameterProvider
+template<class ParametersCollection>
+class BRepMesh_EdgeParameterProvider : public Standard_Transient
{
public:
DEFINE_STANDARD_ALLOC
+ //! Constructor. Initializes empty provider.
+ BRepMesh_EdgeParameterProvider()
+ {
+ }
+
//! Constructor.
//! @param theEdge edge which parameters should be processed.
//! @param theFace face the parametric values are defined for.
//! @param theParameters parameters corresponded to discretization points.
BRepMesh_EdgeParameterProvider(
- const TopoDS_Edge& theEdge,
- const TopoDS_Face& theFace,
- const Handle(TColStd_HArray1OfReal)& theParameters);
+ const IMeshData::IEdgeHandle& theEdge,
+ const TopAbs_Orientation theOrientation,
+ const IMeshData::IFaceHandle& theFace,
+ const ParametersCollection& theParameters)
+ {
+ Init(theEdge, theOrientation, theFace, theParameters);
+ }
+
+ //! Initialized provider by the given data.
+ void Init (
+ const IMeshData::IEdgeHandle& theEdge,
+ const TopAbs_Orientation theOrientation,
+ const IMeshData::IFaceHandle& theFace,
+ const ParametersCollection& theParameters)
+ {
+ myParameters = theParameters;
+ myIsSameParam = theEdge->GetSameParam();
+ myScale = 1.;
+
+ // Extract actual parametric values
+ const TopoDS_Edge aEdge = TopoDS::Edge(theEdge->GetEdge().Oriented(theOrientation));
+
+ myCurveAdaptor.Initialize(aEdge, theFace->GetFace());
+ if (myIsSameParam)
+ {
+ return;
+ }
+
+ myFirstParam = myCurveAdaptor.FirstParameter();
+ const Standard_Real aLastParam = myCurveAdaptor.LastParameter();
+
+ myFoundParam = myCurParam = myFirstParam;
+
+ // Extract parameters stored in polygon
+ myOldFirstParam = myParameters->Value(myParameters->Lower());
+ const Standard_Real aOldLastParam = myParameters->Value(myParameters->Upper());
+
+ // Calculate scale factor between actual and stored parameters
+ if ((myOldFirstParam != myFirstParam || aOldLastParam != aLastParam) &&
+ myOldFirstParam != aOldLastParam)
+ {
+ myScale = (aLastParam - myFirstParam) / (aOldLastParam - myOldFirstParam);
+ }
+
+ myProjector.Initialize(myCurveAdaptor, myCurveAdaptor.FirstParameter(),
+ myCurveAdaptor.LastParameter(),Precision::PConfusion());
+ }
//! Returns parameter according to SameParameter flag of the edge.
//! If SameParameter is TRUE returns value from parameters w/o changes,
//! elsewhere scales initial parameter and tries to determine resulting
//! value using projection of the corresponded 3D point on PCurve.
Standard_Real Parameter(const Standard_Integer theIndex,
- const gp_Pnt& thePoint3d);
+ const gp_Pnt& thePoint3d) const
+ {
+ if (myIsSameParam)
+ {
+ return myParameters->Value(theIndex);
+ }
+
+ // Use scaled
+ const Standard_Real aParam = myParameters->Value(theIndex);
+
+ const Standard_Real aPrevParam = myCurParam;
+ myCurParam = myFirstParam + myScale * (aParam - myOldFirstParam);
+
+ const Standard_Real aPrevFoundParam = myFoundParam;
+ myFoundParam += (myCurParam - aPrevParam);
+
+ myProjector.Perform(thePoint3d, myFoundParam);
+ if (myProjector.IsDone())
+ {
+ const Standard_Real aFoundParam = myProjector.Point().Parameter();
+ if ((aPrevFoundParam < myFoundParam && aPrevFoundParam < aFoundParam) ||
+ (aPrevFoundParam > myFoundParam && aPrevFoundParam > aFoundParam))
+ {
+ // Rude protection against case when amplified parameter goes before
+ // previous one due to period or other reason occurred in projector.
+ // Using parameter returned by projector as is can produce self-intersections.
+ myFoundParam = aFoundParam;
+ }
+ }
+
+ return myFoundParam;
+ }
+
+ //! Returns pcurve used to compute parameters.
+ const Handle(Adaptor2d_HCurve2d)& GetPCurve() const
+ {
+ return myCurveAdaptor.CurveOnSurface().GetCurve();
+ }
private:
- Handle(TColStd_HArray1OfReal) myParameters;
+ ParametersCollection myParameters;
Standard_Boolean myIsSameParam;
Standard_Real myFirstParam;
Standard_Real myOldFirstParam;
Standard_Real myScale;
- Standard_Real myCurParam;
- Standard_Real myFoundParam;
+ mutable Standard_Real myCurParam;
+ mutable Standard_Real myFoundParam;
BRepAdaptor_Curve myCurveAdaptor;
- Extrema_LocateExtPC myProjector;
+
+ mutable Extrema_LocateExtPC myProjector;
};
#endif
-// Created on: 2014-08-13
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// commercial license or contractual agreement.
#include <BRepMesh_EdgeTessellationExtractor.hxx>
-#include <Geom2dAdaptor_HCurve.hxx>
-#include <Poly_PolygonOnTriangulation.hxx>
-#include <Poly_Triangulation.hxx>
#include <BRepMesh_ShapeTool.hxx>
+#include <gp_Pnt.hxx>
+#include <BRep_Tool.hxx>
+#include <IMeshData_Face.hxx>
+#include <IMeshData_Edge.hxx>
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor (
+ const IMeshData::IEdgeHandle& theEdge,
+ const IMeshData::IFaceHandle& theFace)
+{
+ Handle (Poly_Triangulation) aTriangulation =
+ BRep_Tool::Triangulation (theFace->GetFace(), myLoc);
+
+ Handle (Poly_PolygonOnTriangulation) aPolygon =
+ BRep_Tool::PolygonOnTriangulation (theEdge->GetEdge(), aTriangulation, myLoc);
-IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellationExtractor,BRepMesh_IEdgeTool)
+ myNodes = &aTriangulation->Nodes ();
+ myIndices = &aPolygon->Nodes ();
+ myProvider.Init (theEdge, TopAbs_FORWARD, theFace, aPolygon->Parameters ());
+}
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
-BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor(
- const TopoDS_Edge& theEdge,
- const Handle(Geom2dAdaptor_HCurve)& thePCurve,
- const TopoDS_Face& theFace,
- const Handle(Poly_Triangulation)& theTriangulation,
- const Handle(Poly_PolygonOnTriangulation)& thePolygon,
- const TopLoc_Location& theLocation)
- : myProvider(theEdge, theFace, thePolygon->Parameters()),
- myPCurve(thePCurve),
- myNodes(theTriangulation->Nodes()),
- myIndices(thePolygon->Nodes()),
- myLoc(theLocation)
+BRepMesh_EdgeTessellationExtractor::~BRepMesh_EdgeTessellationExtractor ()
{
}
+//=======================================================================
+//function : NbPoints
+//purpose :
+//=======================================================================
+Standard_Integer BRepMesh_EdgeTessellationExtractor::PointsNb () const
+{
+ return myIndices->Size ();
+}
+
//=======================================================================
//function : Value
//purpose :
//=======================================================================
-Standard_Boolean BRepMesh_EdgeTessellationExtractor::Value(
+Standard_Boolean BRepMesh_EdgeTessellationExtractor::Value (
const Standard_Integer theIndex,
- Standard_Real& theParameter,
gp_Pnt& thePoint,
- gp_Pnt2d& theUV)
+ Standard_Real& theParameter) const
{
- const gp_Pnt& theRefPnt = myNodes(myIndices(theIndex));
- thePoint = BRepMesh_ShapeTool::UseLocation(theRefPnt, myLoc);
-
- theParameter = myProvider.Parameter(theIndex, thePoint);
- theUV = myPCurve->Value(theParameter);
+ const gp_Pnt& theRefPnt = (*myNodes) ((*myIndices) (theIndex));
+ thePoint = BRepMesh_ShapeTool::UseLocation (theRefPnt, myLoc);
+ theParameter = myProvider.Parameter (theIndex, thePoint);
return Standard_True;
}
-// Created on: 2014-08-13
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
#ifndef _BRepMesh_EdgeTessellationExtractor_HeaderFile
#define _BRepMesh_EdgeTessellationExtractor_HeaderFile
-#include <Standard.hxx>
-#include <Standard_DefineAlloc.hxx>
-#include <BRepMesh_IEdgeTool.hxx>
+#include <IMeshTools_CurveTessellator.hxx>
+#include <IMeshData_Types.hxx>
#include <BRepMesh_EdgeParameterProvider.hxx>
-#include <TopLoc_Location.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfInteger.hxx>
-
-class Poly_Triangulation;
-class Poly_PolygonOnTriangulation;
-class TopoDS_Edge;
-class TopoDS_Face;
-class Geom2dAdaptor_HCurve;
+#include <TopLoc_Location.hxx>
//! Auxiliary class implements functionality retrieving tessellated
//! representation of an edge stored in polygon.
-class BRepMesh_EdgeTessellationExtractor : public BRepMesh_IEdgeTool
+class BRepMesh_EdgeTessellationExtractor : public IMeshTools_CurveTessellator
{
public:
//! Constructor.
- //! Initializes extractor.
- BRepMesh_EdgeTessellationExtractor(
- const TopoDS_Edge& theEdge,
- const Handle(Geom2dAdaptor_HCurve)& thePCurve,
- const TopoDS_Face& theFace,
- const Handle(Poly_Triangulation)& theTriangulation,
- const Handle(Poly_PolygonOnTriangulation)& thePolygon,
- const TopLoc_Location& theLocation);
+ Standard_EXPORT BRepMesh_EdgeTessellationExtractor (
+ const IMeshData::IEdgeHandle& theEdge,
+ const IMeshData::IFaceHandle& theFace);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_EdgeTessellationExtractor ();
- //! Returns number of dicretization points.
- virtual Standard_Integer NbPoints() const Standard_OVERRIDE
- {
- return myIndices.Length();
- }
+ //! Returns number of tessellation points.
+ Standard_EXPORT virtual Standard_Integer PointsNb () const Standard_OVERRIDE;
//! Returns parameters of solution with the given index.
//! @param theIndex index of tessellation point.
//! @param theParameter parameters on PCurve corresponded to the solution.
//! @param thePoint tessellation point.
- //! @param theUV coordinates of tessellation point in parametric space of face.
//! @return True in case of valid result, false elewhere.
- virtual Standard_Boolean Value(
+ Standard_EXPORT virtual Standard_Boolean Value (
const Standard_Integer theIndex,
- Standard_Real& theParameter,
gp_Pnt& thePoint,
- gp_Pnt2d& theUV) Standard_OVERRIDE;
+ Standard_Real& theParameter) const Standard_OVERRIDE;
- DEFINE_STANDARD_RTTIEXT(BRepMesh_EdgeTessellationExtractor,BRepMesh_IEdgeTool)
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_EdgeTessellationExtractor, IMeshTools_CurveTessellator)
private:
- //! Assignment operator.
- void operator =(const BRepMesh_EdgeTessellationExtractor& /*theOther*/)
- {
- }
-
-private:
-
- BRepMesh_EdgeParameterProvider myProvider;
- Handle(Geom2dAdaptor_HCurve) myPCurve;
- const TColgp_Array1OfPnt& myNodes;
- const TColStd_Array1OfInteger& myIndices;
- const TopLoc_Location myLoc;
+ BRepMesh_EdgeParameterProvider<Handle(TColStd_HArray1OfReal)> myProvider;
+ const TColgp_Array1OfPnt* myNodes;
+ const TColStd_Array1OfInteger* myIndices;
+ TopLoc_Location myLoc;
};
-DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellationExtractor, BRepMesh_IEdgeTool)
-
-#endif
+#endif
\ No newline at end of file
+++ /dev/null
-// Created on: 2014-08-13
-// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <BRepMesh_EdgeTessellator.hxx>
-#include <Geom_Surface.hxx>
-#include <Geom_Plane.hxx>
-#include <Geom2d_Curve.hxx>
-#include <Geom2dAdaptor_Curve.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Face.hxx>
-#include <BRepAdaptor_HSurface.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
-#include <TopLoc_Location.hxx>
-#include <BRep_Tool.hxx>
-#include <TColStd_Array1OfReal.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopoDS.hxx>
-#include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <TopTools_ListOfShape.hxx>
-#include <TColStd_Array1OfReal.hxx>
-
-
-IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator,BRepMesh_IEdgeTool)
-
-//=======================================================================
-//function : Constructor
-//purpose :
-//=======================================================================
-BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator(
- const TopoDS_Edge& theEdge,
- const Handle(BRepMesh_FaceAttribute)& theFaceAttribute,
- const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces,
- const Standard_Real theLinDeflection,
- const Standard_Real theAngDeflection,
- const Standard_Real theMinSize)
- : mySurface(theFaceAttribute->Surface())
-{
- Standard_Real aPreciseAngDef = 0.5 * theAngDeflection;
- Standard_Real aPreciseLinDef = 0.5 * theLinDeflection;
- if (theEdge.Orientation() == TopAbs_INTERNAL)
- aPreciseLinDef *= 0.5;
-
- mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
- mySquareMinSize = Max(mySquareEdgeDef, theMinSize * theMinSize);
- myEdgeSqTol = BRep_Tool::Tolerance (theEdge);
- myEdgeSqTol *= myEdgeSqTol;
-
- Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge);
- if (isSameParam)
- myCOnS.Initialize(theEdge);
- else
- myCOnS.Initialize(theEdge, theFaceAttribute->Face());
-
- const GeomAbs_CurveType aCurveType = myCOnS.GetType();
- Standard_Integer aMinPntNb = (aCurveType == GeomAbs_Circle) ? 4 : 2; //OCC287
-
- // Get 2d curve and init geom tool
- Standard_Real aFirstParam, aLastParam;
- Handle(Geom2d_Curve) aCurve2d =
- BRep_Tool::CurveOnSurface(theEdge, theFaceAttribute->Face(), aFirstParam, aLastParam);
- myCurve2d.Load(aCurve2d, aFirstParam, aLastParam);
- myTool = new BRepMesh_GeomTool(myCOnS, aFirstParam, aLastParam,
- aPreciseLinDef, aPreciseAngDef, aMinPntNb, theMinSize);
-
- if (aCurveType == GeomAbs_BSplineCurve)
- {
- // bug24220
- const Standard_Integer aNbInt = myCOnS.NbIntervals(GeomAbs_C1);
- if ( aNbInt > 1 )
- {
- TColStd_Array1OfReal anIntervals( 1, aNbInt + 1 );
- myCOnS.Intervals(anIntervals, GeomAbs_C1);
- for (Standard_Integer aIntIt = 1; aIntIt <= aNbInt; ++aIntIt)
- {
- const Standard_Real& aStartInt = anIntervals.Value( aIntIt );
- const Standard_Real& anEndInt = anIntervals.Value( aIntIt + 1 );
-
- BRepMesh_GeomTool aDetalizator(myCOnS, aStartInt, anEndInt,
- aPreciseLinDef, aPreciseAngDef, aMinPntNb, theMinSize);
-
- Standard_Integer aNbAddNodes = aDetalizator.NbPoints();
- for ( Standard_Integer aNodeIt = 1; aNodeIt <= aNbAddNodes; ++aNodeIt )
- {
- Standard_Real aParam;
- gp_Pnt aPoint3d;
- gp_Pnt2d aPoint2d;
- aDetalizator.Value( aNodeIt, aParam, aPoint3d);
- myCurve2d.D0(aParam, aPoint2d);
-
- myTool->AddPoint( aPoint3d, aParam, Standard_False );
- }
- }
- }
- }
-
- // PTv, chl/922/G9, Take into account internal vertices
- // it is necessary for internal edges, which do not split other edges, by their vertex
- TopExp_Explorer aVertexIt(theEdge, TopAbs_VERTEX);
- for (; aVertexIt.More(); aVertexIt.Next())
- {
- const TopoDS_Vertex& aVertex = TopoDS::Vertex(aVertexIt.Current());
- if (aVertex.Orientation() != TopAbs_INTERNAL)
- continue;
-
- myTool->AddPoint(BRep_Tool::Pnt(aVertex),
- BRep_Tool::Parameter(aVertex, theEdge), Standard_True);
- }
-
- Standard_Integer aNodesNb = myTool->NbPoints();
- //Check deflection in 2d space for improvement of edge tesselation.
- if( isSameParam && aNodesNb > 1)
- {
- const TopTools_ListOfShape& aSharedFaces = theMapOfSharedFaces.FindFromKey(theEdge);
- TopTools_ListIteratorOfListOfShape aFaceIt(aSharedFaces);
- for (; aFaceIt.More(); aFaceIt.Next())
- {
- const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Value());
- BRepAdaptor_Surface aSurf(aFace, Standard_False);
-
- if (aSurf.GetType() == GeomAbs_Plane)
- continue;
-
- Standard_Real aF, aL;
- aCurve2d = BRep_Tool::CurveOnSurface(theEdge, aFace, aF, aL);
- if ( Abs(aF - aFirstParam) > Precision::PConfusion() ||
- Abs(aL - aLastParam ) > Precision::PConfusion() )
- {
- continue;
- }
- Geom2dAdaptor_Curve aGACurve(aCurve2d, aF, aL);
-
- aNodesNb = myTool->NbPoints();
- TColStd_Array1OfReal aParamArray(1, aNodesNb);
- for (Standard_Integer i = 1; i <= aNodesNb; ++i)
- {
- gp_Pnt aTmpPnt;
- Standard_Real aParam;
- myTool->Value(i, aParam, aTmpPnt);
- aParamArray.SetValue(i, aParam);
- }
-
- for (Standard_Integer i = 1; i < aNodesNb; ++i)
- splitSegment(aSurf, aGACurve, aParamArray(i), aParamArray(i + 1), 1);
- }
- }
-
- const Standard_Real aTol = Precision::Confusion();
- const Standard_Real aDu = mySurface->UResolution (aTol);
- const Standard_Real aDv = mySurface->VResolution (aTol);
-
- myFaceRangeU[0] = mySurface->FirstUParameter() - aDu;
- myFaceRangeU[1] = mySurface->LastUParameter() + aDu;
-
- myFaceRangeV[0] = mySurface->FirstVParameter() - aDv;
- myFaceRangeV[1] = mySurface->LastVParameter() + aDv;
-}
-
-//=======================================================================
-//function : Value
-//purpose :
-//=======================================================================
-Standard_Boolean BRepMesh_EdgeTessellator::Value(
- const Standard_Integer theIndex,
- Standard_Real& theParameter,
- gp_Pnt& thePoint,
- gp_Pnt2d& theUV)
-{
- myTool->Value(theIndex, theParameter, thePoint);
- myCurve2d.D0(theParameter, theUV);
-
- // If point coordinates are out of surface range,
- // it is necessary to re-project point.
- if (mySurface->GetType() != GeomAbs_BSplineSurface &&
- mySurface->GetType() != GeomAbs_BezierSurface &&
- mySurface->GetType() != GeomAbs_OtherSurface)
- {
- return Standard_True;
- }
-
- // Let skip periodic case.
- if (mySurface->IsUPeriodic() || mySurface->IsVPeriodic())
- return Standard_True;
-
- // Point lies within the surface range - nothing to do.
- if (theUV.X() > myFaceRangeU[0] && theUV.X() < myFaceRangeU[1] &&
- theUV.Y() > myFaceRangeV[0] && theUV.Y() < myFaceRangeV[1])
- {
- return Standard_True;
- }
-
- gp_Pnt aPntOnSurf;
- mySurface->D0 (theUV.X (), theUV.Y (), aPntOnSurf);
-
- return (thePoint.SquareDistance (aPntOnSurf) < myEdgeSqTol);
-}
-
-//=======================================================================
-//function : splitSegment
-//purpose :
-//=======================================================================
-void BRepMesh_EdgeTessellator::splitSegment(
- const Adaptor3d_Surface& theSurf,
- const Geom2dAdaptor_Curve& theCurve2d,
- const Standard_Real theFirst,
- const Standard_Real theLast,
- const Standard_Integer theNbIter)
-{
- // limit iteration depth
- if(theNbIter > 10)
- return;
-
- gp_Pnt2d uvf, uvl, uvm;
- gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf;
- Standard_Real midpar;
-
- if(Abs(theLast - theFirst) < 2 * Precision::PConfusion())
- return;
-
- theCurve2d.D0(theFirst, uvf);
- theCurve2d.D0(theLast, uvl);
-
- P3dF = theSurf.Value(uvf.X(), uvf.Y());
- P3dL = theSurf.Value(uvl.X(), uvl.Y());
-
- if(P3dF.SquareDistance(P3dL) < mySquareMinSize)
- return;
-
- uvm = gp_Pnt2d((uvf.XY() + uvl.XY())*0.5);
- midP3dFromSurf = theSurf.Value(uvm.X(), uvm.Y());
-
- gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ();
- if(Vec1.SquareModulus() < mySquareMinSize)
- return;
-
- gp_XYZ aVec = P3dL.XYZ() - P3dF.XYZ();
- aVec.Normalize();
-
- Standard_Real aModulus = Vec1.Dot(aVec);
- gp_XYZ aProj = aVec * aModulus;
- gp_XYZ aDist = Vec1 - aProj;
-
- if(aDist.SquareModulus() < mySquareEdgeDef)
- return;
-
- midpar = (theFirst + theLast) * 0.5;
- myCOnS.D0(midpar, midP3d);
- myTool->AddPoint(midP3d, midpar, Standard_False);
-
- splitSegment(theSurf, theCurve2d, theFirst, midpar, theNbIter + 1);
- splitSegment(theSurf, theCurve2d, midpar, theLast, theNbIter + 1);
-}
+++ /dev/null
-// Created on: 2014-08-13
-// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef _BRepMesh_EdgeTessellator_HeaderFile
-#define _BRepMesh_EdgeTessellator_HeaderFile
-
-#include <Standard.hxx>
-#include <Standard_DefineAlloc.hxx>
-#include <BRepMesh.hxx>
-#include <BRepMesh_IEdgeTool.hxx>
-#include <BRepMesh_GeomTool.hxx>
-#include <BRepMesh_FaceAttribute.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <Geom2dAdaptor_Curve.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
-
-class Adaptor3d_Surface;
-class TopoDS_Edge;
-class BRepAdaptor_HSurface;
-
-//! Auxiliary class implements functionality producing tessellated
-//! representation of an edge based on edge geometry.
-class BRepMesh_EdgeTessellator : public BRepMesh_IEdgeTool
-{
-public:
-
- //! Constructor.
- //! Automatically performs tessellation of the edge according to the
- //! given parameters.
- BRepMesh_EdgeTessellator(
- const TopoDS_Edge& theEdge,
- const Handle(BRepMesh_FaceAttribute)& theFaceAttribute,
- const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces,
- const Standard_Real theLinDeflection,
- const Standard_Real theAngDeflection,
- const Standard_Real theMinSize);
-
- //! Returns number of dicretization points.
- virtual Standard_Integer NbPoints() const Standard_OVERRIDE
- {
- return myTool->NbPoints();
- }
-
- //! Returns parameters of solution with the given index.
- //! @param theIndex index of tessellation point.
- //! @param theParameter parameters on PCurve corresponded to the solution.
- //! @param thePoint tessellation point.
- //! @param theUV coordinates of tessellation point in parametric space of face.
- //! @return True in case of valid result, false elewhere.
- virtual Standard_Boolean Value(
- const Standard_Integer theIndex,
- Standard_Real& theParameter,
- gp_Pnt& thePoint,
- gp_Pnt2d& theUV) Standard_OVERRIDE;
-
- DEFINE_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator,BRepMesh_IEdgeTool)
-
-private:
-
- //!
- void splitSegment(const Adaptor3d_Surface& theSurf,
- const Geom2dAdaptor_Curve& theCurve2d,
- const Standard_Real theFirst,
- const Standard_Real theLast,
- const Standard_Integer theNbIter);
-
-private:
- NCollection_Handle<BRepMesh_GeomTool> myTool;
- Handle(BRepAdaptor_HSurface) mySurface;
- BRepAdaptor_Curve myCOnS;
- Geom2dAdaptor_Curve myCurve2d;
- Standard_Real mySquareEdgeDef;
- Standard_Real mySquareMinSize;
- Standard_Real myEdgeSqTol;
- Standard_Real myFaceRangeU[2];
- Standard_Real myFaceRangeV[2];
-};
-
-DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool)
-
-#endif
+++ /dev/null
-// Created by: Ekaterina SMIRNOVA
-// Copyright (c) 2008-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <BRepMesh_FaceAttribute.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <BRepAdaptor_HSurface.hxx>
-#include <BRepMesh_ShapeTool.hxx>
-#include <BRepMesh_Classifier.hxx>
-#include <BRepTools.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TopoDS_Wire.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Iterator.hxx>
-#include <BRep_Tool.hxx>
-
-IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FaceAttribute,Standard_Transient)
-
-//=======================================================================
-//function : Constructor
-//purpose :
-//=======================================================================
-BRepMesh_FaceAttribute::BRepMesh_FaceAttribute()
- : myDefFace (0.),
- myUMin (0.),
- myUMax (0.),
- myVMin (0.),
- myVMax (0.),
- myDeltaX (1.),
- myDeltaY (1.),
- myMinStep (-1.),
- myStatus (BRepMesh_NoError),
- myAdaptiveMin (Standard_False)
-{
- init();
-}
-
-//=======================================================================
-//function : Constructor
-//purpose :
-//=======================================================================
-BRepMesh_FaceAttribute::BRepMesh_FaceAttribute(
- const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices,
- const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints)
- : myDefFace (0.),
- myUMin (0.),
- myUMax (0.),
- myVMin (0.),
- myVMax (0.),
- myDeltaX (1.),
- myDeltaY (1.),
- myMinStep (-1.),
- myStatus (BRepMesh_NoError),
- myAdaptiveMin (Standard_False),
- myBoundaryVertices(theBoundaryVertices),
- myBoundaryPoints (theBoundaryPoints)
-{
-}
-
-//=======================================================================
-//function : Constructor
-//purpose :
-//=======================================================================
-BRepMesh_FaceAttribute::BRepMesh_FaceAttribute(
- const TopoDS_Face& theFace,
- const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices,
- const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints,
- const Standard_Boolean theAdaptiveMin)
- : myDefFace (0.),
- myUMin (0.),
- myUMax (0.),
- myVMin (0.),
- myVMax (0.),
- myDeltaX (1.),
- myDeltaY (1.),
- myMinStep (-1.),
- myStatus (BRepMesh_NoError),
- myAdaptiveMin (theAdaptiveMin),
- myBoundaryVertices(theBoundaryVertices),
- myBoundaryPoints (theBoundaryPoints),
- myFace (theFace)
-{
- init();
-}
-
-//=======================================================================
-//function : Destructor
-//purpose :
-//=======================================================================
-BRepMesh_FaceAttribute::~BRepMesh_FaceAttribute()
-{
-}
-
-//=======================================================================
-//function : SetFace
-//purpose :
-//=======================================================================
-void BRepMesh_FaceAttribute::SetFace (
- const TopoDS_Face& theFace,
- const Standard_Boolean theAdaptiveMin)
-{
- myFace = theFace;
- myAdaptiveMin = theAdaptiveMin;
-
- init ();
-}
-
-//=======================================================================
-//function : init
-//purpose :
-//=======================================================================
-void BRepMesh_FaceAttribute::init()
-{
- myVertexEdgeMap = new BRepMesh::IMapOfInteger;
- myInternalEdges = new BRepMesh::DMapOfShapePairOfPolygon;
- myLocation2D = new BRepMesh::DMapOfIntegerListOfXY;
- myClassifier = new BRepMesh_Classifier;
-
- if (myFace.IsNull())
- return;
-
- BRepTools::Update(myFace);
- myFace.Orientation(TopAbs_FORWARD);
- BRepTools::UVBounds(myFace, myUMin, myUMax, myVMin, myVMax);
-
- if (myAdaptiveMin)
- {
- // compute minimal UV distance
- // between vertices
-
- myMinStep = RealLast();
- for (TopoDS_Iterator aFaceIt(myFace); aFaceIt.More(); aFaceIt.Next())
- {
- for (TopoDS_Iterator aWireIt(aFaceIt.Value()); aWireIt.More(); aWireIt.Next())
- {
- const TopoDS_Edge& anEdge = TopoDS::Edge(aWireIt.Value());
- if (anEdge.IsNull() || BRep_Tool::IsClosed(anEdge))
- continue;
-
- // Get end points on 2d curve
- gp_Pnt2d aFirst2d, aLast2d;
- BRep_Tool::UVPoints(anEdge, myFace, aFirst2d, aLast2d);
- Standard_Real aDist =aFirst2d.Distance(aLast2d);
- if (aDist < myMinStep)
- myMinStep = aDist;
- }
- }
- }
-
- BRepAdaptor_Surface aSurfAdaptor(myFace, Standard_False);
- mySurface = new BRepAdaptor_HSurface(aSurfAdaptor);
-}
-
-//=======================================================================
-//function : Clear
-//purpose :
-//=======================================================================
-void BRepMesh_FaceAttribute::Clear()
-{
- myStructure.Nullify();
- myLocation2D->Clear();
- myInternalEdges->Clear();
- myVertexEdgeMap->Clear();
-}
-
-//=======================================================================
-//function : computeParametricTolerance
-//purpose :
-//=======================================================================
-Standard_Real BRepMesh_FaceAttribute::computeParametricTolerance(
- const Standard_Real theFirstParam,
- const Standard_Real theLastParam) const
-{
- const Standard_Real aDeflectionUV = 1.e-05;
- Standard_Real aPreci = (theLastParam - theFirstParam) * aDeflectionUV;
- if(myAdaptiveMin && myMinStep < aPreci)
- aPreci = myMinStep;
-
- return Max(Precision::PConfusion(), aPreci);
-}
-
-//=======================================================================
-//function : getVertexIndex
-//purpose :
-//=======================================================================
-Standard_Boolean BRepMesh_FaceAttribute::getVertexIndex(
- const TopoDS_Vertex& theVertex,
- Standard_Integer& theVertexIndex) const
-{
- if (!myBoundaryVertices.IsNull() && myBoundaryVertices->IsBound(theVertex))
- theVertexIndex = myBoundaryVertices->Find(theVertex);
- else if (!mySurfaceVertices.IsNull() && mySurfaceVertices->IsBound(theVertex))
- theVertexIndex = mySurfaceVertices->Find(theVertex);
- else
- return Standard_False;
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : AddNode
-//purpose :
-//=======================================================================
-void BRepMesh_FaceAttribute::AddNode(
- const Standard_Integer theIndex,
- const gp_XY& theUV,
- const BRepMesh_DegreeOfFreedom theMovability,
- Standard_Integer& theNodeIndex,
- Standard_Integer& theNodeOnEdgeIndex)
-{
- BRepMesh_Vertex aNode(theUV, theIndex, theMovability);
- theNodeIndex = myStructure->AddNode(aNode);
- theNodeOnEdgeIndex = myVertexEdgeMap->FindIndex(theNodeIndex);
- if (theNodeOnEdgeIndex == 0)
- theNodeOnEdgeIndex = myVertexEdgeMap->Add(theNodeIndex);
-}
-
-//=======================================================================
-//function : Scale
-//purpose :
-//=======================================================================
-gp_XY BRepMesh_FaceAttribute::Scale(const gp_XY& thePoint2d,
- const Standard_Boolean isToFaceBasis)
-{
- return isToFaceBasis ?
- gp_XY((thePoint2d.X() - myUMin) / myDeltaX, (thePoint2d.Y() - myVMin) / myDeltaY) :
- gp_XY(thePoint2d.X() * myDeltaX + myUMin, thePoint2d.Y() * myDeltaY + myVMin);
-}
-
-//=======================================================================
-//function : ToleranceU
-//purpose :
-//=======================================================================
-Standard_Real BRepMesh_FaceAttribute::ToleranceU() const
-{
- return computeParametricTolerance(myUMin, myUMax);
-}
-
-//=======================================================================
-//function : ToleranceV
-//purpose :
-//=======================================================================
-Standard_Real BRepMesh_FaceAttribute::ToleranceV() const
-{
- return computeParametricTolerance(myVMin, myVMax);
-}
+++ /dev/null
-// Copyright (c) 2013 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef _BRepMesh_FaceAttribute_HeaderFile
-#define _BRepMesh_FaceAttribute_HeaderFile
-
-#include <Standard.hxx>
-#include <Standard_Transient.hxx>
-#include <Standard_Type.hxx>
-
-#include <BRepMesh_Status.hxx>
-#include <BRepMesh.hxx>
-#include <BRepMesh_DataStructureOfDelaun.hxx>
-
-class BRepAdaptor_HSurface;
-
-//! Auxiliary class for FastDiscret and FastDiscretFace classes.
-class BRepMesh_FaceAttribute : public Standard_Transient
-{
-public:
-
- //! Constructor. Initializes empty attribute.
- //! @param theBoundaryVertices shared map of shape vertices.
- //! @param theBoundaryPoints shared discretization points of shape boundaries.
- Standard_EXPORT BRepMesh_FaceAttribute(
- const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices,
- const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints);
-
- //! Constructor.
- //! @param theFace face the attribute is created for.
- //! Used for default initialization. Attribute keeps reference
- //! to the source face with forward orientation.
- //! @param theBoundaryVertices shared map of shape vertices.
- //! @param theBoundaryPoints shared discretization points of shape boundaries.
- //! @param theAdaptiveMin switches on adaptive computation of minimal parametric
- //! tolerance (if true).
- Standard_EXPORT BRepMesh_FaceAttribute(
- const TopoDS_Face& theFace,
- const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices,
- const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints,
- const Standard_Boolean theAdaptiveMin);
-
- //! Destructor.
- Standard_EXPORT virtual ~BRepMesh_FaceAttribute();
-
-public: //! @name main geometrical properties.
-
- //! Returns face's surface.
- inline const Handle(BRepAdaptor_HSurface)& Surface() const
- {
- return mySurface;
- }
-
- //! Returns True in case if this attribute has already been intialized.
- inline Standard_Boolean IsInitialized () const
- {
- return !myFace.IsNull ();
- }
-
- //! Initializes this attribute by the given face.
- Standard_EXPORT void SetFace (
- const TopoDS_Face& theFace,
- const Standard_Boolean theAdaptiveMin);
-
- //! Returns forward oriented face to be used for calculations.
- inline const TopoDS_Face& Face() const
- {
- return myFace;
- }
-
- //! Sets boundary vertices map.
- inline void SetBoundaryVertices(const BRepMesh::HDMapOfVertexInteger& theVertices)
- {
- myBoundaryVertices = theVertices;
- }
-
- //! Sets boundary points map.
- inline void SetBoundaryPoints(const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints)
- {
- myBoundaryPoints = theBoundaryPoints;
- }
-
- //! Returns U tolerance of face calculated regarding its parameters.
- Standard_EXPORT Standard_Real ToleranceU() const;
-
- //! Returns V tolerance of face calculated regarding its parameters.
- Standard_EXPORT Standard_Real ToleranceV() const;
-
- //! Gives face deflection parameter.
- inline Standard_Real GetDefFace() const
- {
- return myDefFace;
- }
-
- //! Sets face deflection.
- inline void SetDefFace(const Standard_Real theDefFace)
- {
- myDefFace = theDefFace;
- }
-
- //! Gives minimal value in U domain.
- inline Standard_Real GetUMin() const
- {
- return myUMin;
- }
-
- //! Sets minimal value in U domain.
- inline void SetUMin(const Standard_Real theUMin)
- {
- myUMin = theUMin;
- }
-
- //! Gives minimal value in V domain.
- inline Standard_Real GetVMin() const
- {
- return myVMin;
- }
-
- //! Sets minimal value in V domain.
- inline void SetVMin(const Standard_Real theVMin)
- {
- myVMin = theVMin;
- }
-
- //! Gives maximal value in U domain.
- inline Standard_Real GetUMax() const
- {
- return myUMax;
- }
-
- //! Sets maximal value in U domain.
- inline void SetUMax(const Standard_Real theUMax)
- {
- myUMax = theUMax;
- }
-
- //! Gives maximal value in V domain.
- inline Standard_Real GetVMax() const
- {
- return myVMax;
- }
-
- //! Sets maximal value in V domain.
- inline void SetVMax(const Standard_Real theVMax)
- {
- myVMax = theVMax;
- }
-
- //! Gives value of step in U domain.
- inline Standard_Real GetDeltaX() const
- {
- return myDeltaX;
- }
-
- //! Sets value of step in U domain.
- inline void SetDeltaX(const Standard_Real theDeltaX)
- {
- myDeltaX = theDeltaX;
- }
-
- //! Gives value of step in V domain.
- inline Standard_Real GetDeltaY() const
- {
- return myDeltaY;
- }
-
- //! Sets value of step in V domain.
- inline void SetDeltaY(const Standard_Real theDeltaY)
- {
- myDeltaY = theDeltaY;
- }
-
- //! Sets set of status flags for this face.
- inline Standard_Integer GetStatus() const
- {
- return myStatus;
- }
-
- //! Sets status flag for this face.
- inline void SetStatus(const BRepMesh_Status theStatus)
- {
- myStatus |= theStatus;
- }
-
- //! Returns TRUE in case if computed data is valid.
- inline Standard_Boolean IsValid() const
- {
- return (myStatus == BRepMesh_NoError || myStatus == BRepMesh_ReMesh);
- }
-
-public: //! @name auxiliary structures
-
- //! Clear face attribute.
- Standard_EXPORT void Clear();
-
- //! Gives reference to map of internal edges of face.
- inline BRepMesh::HDMapOfShapePairOfPolygon& ChangeInternalEdges()
- {
- return myInternalEdges;
- }
-
- //! Gives reference to map of 2D points of discretization.
- inline BRepMesh::HDMapOfIntegerListOfXY& ChangeLocation2D()
- {
- return myLocation2D;
- }
-
- //! Gives reference to map of 3D points of discretization.
- inline BRepMesh::HDMapOfIntegerPnt& ChangeSurfacePoints()
- {
- return mySurfacePoints;
- }
-
- //! Gives reference to map of vertices of discretization.
- inline BRepMesh::HDMapOfVertexInteger& ChangeSurfaceVertices()
- {
- return mySurfaceVertices;
- }
-
- //! Gives reference on map of (vertex, edge) pairs of face.
- inline BRepMesh::HIMapOfInteger& ChangeVertexEdgeMap()
- {
- return myVertexEdgeMap;
- }
-
- //! Gives Delaunay data structure.
- inline Handle(BRepMesh_DataStructureOfDelaun)& ChangeStructure()
- {
- return myStructure;
- }
-
- //! Returns classifier.
- inline BRepMesh::HClassifier& ChangeClassifier()
- {
- return myClassifier;
- }
-
- //! Returns mesh nodes calculated for boundaries.
- inline BRepMesh::HVectorOfVertex& ChangeMeshNodes()
- {
- return myMeshNodes;
- }
-
-public: //! @name Point/Vertex/Node manipulators
-
- //! Gives the number of different locations in 3D space.
- inline Standard_Integer LastPointId() const
- {
- return (myBoundaryPoints.IsNull() ? 0 : myBoundaryPoints->Extent()) +
- (mySurfacePoints.IsNull() ? 0 : mySurfacePoints->Extent());
- }
-
- //! Gives the 3D location of the vertex.
- inline const gp_Pnt& GetPoint(const BRepMesh_Vertex& theVertex) const
- {
- return GetPoint(theVertex.Location3d());
- }
-
- //! Gives the 3D location of the vertex.
- inline const gp_Pnt& GetPoint(const Standard_Integer theIndex) const
- {
- if (!mySurfacePoints.IsNull() && theIndex > myBoundaryPoints->Extent())
- return mySurfacePoints->Find(theIndex);
-
- return myBoundaryPoints->Find(theIndex);
- }
-
- //! Returns index of the given vertex if it exists in cache,
- //! elsewhere adds it to cache and returns cached index.
- //! @param theVertexExplorer template parameter intended to transfer
- //! parameters of vertex to method. Explorer class can implement different
- //! approaches of extraction of target parameters.
- //! @param isFillEdgeVertices if TRUE adds vertex to shared map of
- //! edges vertices, elsewhere adds it map of face vertices.
- template<class HVertexExplorer>
- Standard_Integer GetVertexIndex(
- const HVertexExplorer& theVertexExplorer,
- const Standard_Boolean isFillEdgeVertices = Standard_False)
- {
- const TopoDS_Vertex& aVertex = theVertexExplorer->Vertex();
- Standard_Integer aNewVertexIndex = 0;
- if (getVertexIndex(aVertex, aNewVertexIndex))
- return aNewVertexIndex;
-
- if (!theVertexExplorer->IsSameUV() ||
- !getVertexIndex(theVertexExplorer->SameVertex(), aNewVertexIndex))
- {
- aNewVertexIndex = LastPointId() + 1;
-
- BRepMesh::DMapOfIntegerPnt& aPointsMap = isFillEdgeVertices ?
- *myBoundaryPoints : *mySurfacePoints;
-
- aPointsMap.Bind(aNewVertexIndex, theVertexExplorer->Point());
- }
-
- BRepMesh::DMapOfVertexInteger& aVertexMap = isFillEdgeVertices ?
- *myBoundaryVertices : *mySurfaceVertices;
-
- aVertexMap.Bind(aVertex, aNewVertexIndex);
-
- return aNewVertexIndex;
- }
-
- //! Adds node with the given parameters to mesh.
- //! @param theIndex index of 3D point corresponded to the node.
- //! @param theUV node position.
- //! @param theMovability movability of a node.
- //! @param theNodeIndex index of vertex in mesh structure.
- //! @param theNodeOnEdgeIndex ordered index of node on the boundary.
- Standard_EXPORT void AddNode(const Standard_Integer theIndex,
- const gp_XY& theUV,
- const BRepMesh_DegreeOfFreedom theMovability,
- Standard_Integer& theNodeIndex,
- Standard_Integer& theNodeOnEdgeIndex);
-
-public: //! @name Auxiliary methods
-
- //! Scales the given point from real parametric space
- //! to face basis and otherwise.
- //! @param thePoint2d point to be scaled.
- //! @param isToFaceBasis if TRUE converts point to face basis,
- //! otherwise performs reverse conversion.
- //! @return scaled point.
- Standard_EXPORT gp_XY Scale(const gp_XY& thePoint2d,
- const Standard_Boolean isToFaceBasis);
-
- DEFINE_STANDARD_RTTIEXT(BRepMesh_FaceAttribute,Standard_Transient)
-
-private:
-
- //! Default constructor.
- BRepMesh_FaceAttribute();
-
- //! Assignment operator.
- void operator =(const BRepMesh_FaceAttribute& /*theOther*/)
- {
- }
-
- //! Initializes internal data structures.
- void init();
-
- //! Computes parametric tolerance of a face regarding the given limits.
- Standard_Real computeParametricTolerance(
- const Standard_Real theFirstParam,
- const Standard_Real theLastParam) const;
-
- //! Clears internal data structures local to face.
- void clearLocal(
- const Standard_Boolean isClearSurfaceDataOnly = Standard_False);
-
- //! Returns index of the given vertex if it exists in cache.
- //! @param theVertex vertex which index should be retrieved.
- //! @param theVertexIndex index of the given vertex.
- //! @return TRUE if cached value is found, FALSE elsewhere.
- Standard_EXPORT Standard_Boolean getVertexIndex(
- const TopoDS_Vertex& theVertex,
- Standard_Integer& theVertexIndex) const;
-
-private:
-
- Standard_Real myDefFace; //!< Restore face deflection
- Standard_Real myUMin; //!< Describes minimal value in U domain
- Standard_Real myUMax; //!< Describes maximal value in U domain
- Standard_Real myVMin; //!< Describes minimal value in V domain
- Standard_Real myVMax; //!< Describes maximal value in V domain
- Standard_Real myDeltaX;
- Standard_Real myDeltaY;
- Standard_Real myMinStep;
- Standard_Integer myStatus;
- Standard_Boolean myAdaptiveMin;
-
- BRepMesh::HDMapOfVertexInteger myBoundaryVertices;
- BRepMesh::HDMapOfIntegerPnt myBoundaryPoints;
-
- TopoDS_Face myFace;
- Handle(BRepAdaptor_HSurface) mySurface;
- BRepMesh::HClassifier myClassifier;
-
- BRepMesh::HDMapOfShapePairOfPolygon myInternalEdges;
-
- BRepMesh::HDMapOfIntegerListOfXY myLocation2D;
- BRepMesh::HIMapOfInteger myVertexEdgeMap;
-
- // This field is intended to keep calculated mesh nodes to prevent
- // extremely high memory consumption in case if the whole structure is kept.
- BRepMesh::HVectorOfVertex myMeshNodes;
-
- BRepMesh::HDMapOfVertexInteger mySurfaceVertices;
- BRepMesh::HDMapOfIntegerPnt mySurfacePoints;
- Handle(BRepMesh_DataStructureOfDelaun) myStructure;
-};
-
-DEFINE_STANDARD_HANDLE(BRepMesh_FaceAttribute, Standard_Transient)
-
-#endif
--- /dev/null
+// Created on: 2016-07-04
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_FaceChecker.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Edge.hxx>
+#include <OSD_Parallel.hxx>
+#include <BRepMesh_GeomTool.hxx>
+#include <BRepMesh_IncAllocator.hxx>
+
+namespace
+{
+ const Standard_Real MaxTangentAngle = 5. * M_PI / 180.;
+
+ //! Functor to be used to fill segments and bounding box tree in parallel.
+ class SegmentsFiller
+ {
+ public:
+ //! Constructor.
+ SegmentsFiller(const IMeshData::IFaceHandle& theDFace,
+ Handle(BRepMesh_FaceChecker::ArrayOfSegments)& theWiresSegments,
+ Handle(BRepMesh_FaceChecker::ArrayOfBndBoxTree)& theWiresBndBoxTree)
+ : myDFace(theDFace),
+ myWiresSegments(theWiresSegments),
+ myWiresBndBoxTree(theWiresBndBoxTree)
+ {
+ myWiresSegments = new BRepMesh_FaceChecker::ArrayOfSegments (0, myDFace->WiresNb() - 1);
+ myWiresBndBoxTree = new BRepMesh_FaceChecker::ArrayOfBndBoxTree (0, myDFace->WiresNb() - 1);
+ }
+
+ //! Performs initialization of wire with the given index.
+ void operator()(const Standard_Integer theWireIndex) const
+ {
+ const IMeshData::IWireHandle& aDWire = myDFace->GetWire(theWireIndex);
+
+ Handle(NCollection_IncAllocator) aTmpAlloc1 = new NCollection_IncAllocator();
+
+ Handle(BRepMesh_FaceChecker::Segments) aSegments =
+ new BRepMesh_FaceChecker::Segments(aDWire->EdgesNb(), aTmpAlloc1);
+ Handle(IMeshData::BndBox2dTree) aBndBoxTree = new IMeshData::BndBox2dTree(aTmpAlloc1);
+
+ myWiresSegments ->ChangeValue(theWireIndex) = aSegments;
+ myWiresBndBoxTree->ChangeValue(theWireIndex) = aBndBoxTree;
+
+ Handle(NCollection_IncAllocator) aTmpAlloc2 = new NCollection_IncAllocator();
+ IMeshData::BndBox2dTreeFiller aBndBoxTreeFiller(*aBndBoxTree, aTmpAlloc2);
+
+ for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt)
+ {
+ // TODO: check 2d wire for consistency.
+
+ const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge(aEdgeIt);
+ const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(myDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt));
+
+ for (Standard_Integer aPointIt = 1; aPointIt < aPCurve->ParametersNb(); ++aPointIt)
+ {
+ gp_Pnt2d& aPnt1 = aPCurve->GetPoint(aPointIt - 1);
+ gp_Pnt2d& aPnt2 = aPCurve->GetPoint(aPointIt);
+
+ Bnd_Box2d aBox;
+ aBox.Add(aPnt1);
+ aBox.Add(aPnt2);
+ aBox.Enlarge(Precision::Confusion());
+
+ aBndBoxTreeFiller.Add(aSegments->Size(), aBox);
+ aSegments->Append(BRepMesh_FaceChecker::Segment(aDEdge, &aPnt1, &aPnt2));
+ }
+ }
+
+ aBndBoxTreeFiller.Fill();
+ }
+
+ private:
+
+ SegmentsFiller (const SegmentsFiller& theOther);
+
+ void operator=(const SegmentsFiller& theOther);
+
+ private:
+
+ const IMeshData::IFaceHandle& myDFace;
+ Handle(BRepMesh_FaceChecker::ArrayOfSegments)& myWiresSegments;
+ Handle(BRepMesh_FaceChecker::ArrayOfBndBoxTree)& myWiresBndBoxTree;
+ };
+
+ //! Selector.
+ //! Used to identify segments with overlapped bounding boxes.
+ //! Selector.
+ //! Used to identify segments with overlapped bounding boxes.
+ class BndBox2dTreeSelector : public IMeshData::BndBox2dTree::Selector
+ {
+ public:
+ //! Constructor.
+ BndBox2dTreeSelector(const Standard_Real theTolerance)
+ : myMaxLoopSize(M_PI * theTolerance * theTolerance),
+ mySelfSegmentIndex(-1),
+ myIndices(256, new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE))
+ {
+ }
+
+ //! Sets working set of segments.
+ void SetSegments(const Handle(BRepMesh_FaceChecker::Segments)& theSegments)
+ {
+ mySegments = theSegments;
+ }
+
+ //! Resets current selector.
+ void Reset(const BRepMesh_FaceChecker::Segment* theSegment,
+ const Standard_Integer theSelfSegmentIndex)
+ {
+ myIndices.Clear();
+
+ mySelfSegmentIndex = theSelfSegmentIndex;
+ mySegment = theSegment;
+
+ myBox.SetVoid();
+ myBox.Add(*mySegment->Point1);
+ myBox.Add(*mySegment->Point2);
+ myBox.Enlarge(Precision::Confusion());
+ }
+
+ //! Indicates should the given box be rejected or not.
+ virtual Standard_Boolean Reject(const Bnd_Box2d& theBox) const
+ {
+ return myBox.IsOut(theBox);
+ }
+
+ //! Accepts segment with the given index in case if it fits conditions.
+ virtual Standard_Boolean Accept(const Standard_Integer& theSegmentIndex)
+ {
+ const BRepMesh_FaceChecker::Segment& aSegment = mySegments->Value(theSegmentIndex);
+
+ gp_Pnt2d aIntPnt;
+ const BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
+ mySegment->Point1->XY(), mySegment->Point2->XY(),
+ aSegment.Point1->XY(), aSegment.Point2->XY(),
+ Standard_False, Standard_False, aIntPnt);
+
+ if (aIntStatus == BRepMesh_GeomTool::Cross)
+ {
+ const Standard_Real aAngle = gp_Vec2d(mySegment->Point1->XY(), mySegment->Point2->XY()).Angle(
+ gp_Vec2d(aSegment.Point1->XY(), aSegment.Point2->XY()));
+
+ if (Abs(aAngle) < MaxTangentAngle)
+ {
+ return Standard_False;
+ }
+
+ if (mySelfSegmentIndex != -1)
+ {
+ gp_XY aPrevVec;
+ Standard_Real aSumS = 0.;
+ const gp_XY& aRefPnt = aIntPnt.Coord();
+ for (Standard_Integer i = mySelfSegmentIndex; i < theSegmentIndex; ++i)
+ {
+ const BRepMesh_FaceChecker::Segment& aCurrSegment = mySegments->Value(i);
+ gp_XY aCurVec = aCurrSegment.Point2->XY() - aRefPnt;
+
+ if (aCurVec.SquareModulus() < gp::Resolution())
+ continue;
+
+ if (aPrevVec.SquareModulus() > gp::Resolution())
+ aSumS += aPrevVec ^ aCurVec;
+
+ aPrevVec = aCurVec;
+ }
+
+ if (Abs(aSumS / 2.) < myMaxLoopSize)
+ {
+ return Standard_False;
+ }
+ }
+
+ myIndices.Append(theSegmentIndex);
+ return Standard_True;
+ }
+
+ return Standard_False;
+ }
+
+ //! Returns indices of intersecting segments.
+ const IMeshData::VectorOfInteger& Indices() const
+ {
+ return myIndices;
+ }
+
+ private:
+
+ Standard_Real myMaxLoopSize;
+ Standard_Integer mySelfSegmentIndex;
+ Handle(BRepMesh_FaceChecker::Segments) mySegments;
+ const BRepMesh_FaceChecker::Segment* mySegment;
+ Bnd_Box2d myBox;
+ IMeshData::VectorOfInteger myIndices;
+ };
+}
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+BRepMesh_FaceChecker::BRepMesh_FaceChecker(
+ const IMeshData::IFaceHandle& theFace,
+ const IMeshTools_Parameters& theParameters)
+ : myDFace(theFace),
+ myParameters(theParameters)
+{
+}
+
+//=======================================================================
+//function : Destructor
+//purpose :
+//=======================================================================
+BRepMesh_FaceChecker::~BRepMesh_FaceChecker()
+{
+}
+
+//=======================================================================
+//function : Perform
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_FaceChecker::Perform()
+{
+ myIntersectingEdges = new IMeshData::MapOfIEdgePtr;
+ collectSegments();
+
+ OSD_Parallel::For(0, myDFace->WiresNb(), *this, !isParallel());
+ collectResult();
+
+ myWiresBndBoxTree.Nullify();
+ myWiresSegments.Nullify();
+ myWiresIntersectingEdges.Nullify();
+ return myIntersectingEdges->IsEmpty();
+}
+
+//=======================================================================
+//function : collectSegments
+//purpose :
+//=======================================================================
+void BRepMesh_FaceChecker::collectSegments()
+{
+ SegmentsFiller aSegmentsFiller(myDFace, myWiresSegments, myWiresBndBoxTree);
+ OSD_Parallel::For(0, myDFace->WiresNb(), aSegmentsFiller, !isParallel());
+
+ myWiresIntersectingEdges = new ArrayOfMapOfIEdgePtr(0, myDFace->WiresNb() - 1);
+}
+
+//=======================================================================
+//function : perform
+//purpose :
+//=======================================================================
+void BRepMesh_FaceChecker::perform(const Standard_Integer theWireIndex) const
+{
+ const Handle(Segments)& aSegments1 = myWiresSegments->Value(theWireIndex);
+ Handle(IMeshData::MapOfIEdgePtr)& aIntersections = myWiresIntersectingEdges->ChangeValue(theWireIndex);
+
+ // TODO: Tolerance is set to twice value of face deflection in order to fit regressions.
+ BndBox2dTreeSelector aSelector(2 * myDFace->GetDeflection());
+ for (Standard_Integer aWireIt = theWireIndex; aWireIt < myDFace->WiresNb(); ++aWireIt)
+ {
+ const Handle(IMeshData::BndBox2dTree)& aBndBoxTree2 = myWiresBndBoxTree->Value(aWireIt);
+ const Handle(Segments)& aSegments2 = myWiresSegments->Value(aWireIt);
+
+ aSelector.SetSegments(aSegments2);
+ for (Standard_Integer aSegmentIt = 0; aSegmentIt < aSegments1->Size(); ++aSegmentIt)
+ {
+ const BRepMesh_FaceChecker::Segment& aSegment1 = aSegments1->Value(aSegmentIt);
+ aSelector.Reset(&aSegment1, (aWireIt == theWireIndex) ? aSegmentIt : -1);
+ if (aBndBoxTree2->Select(aSelector) != 0)
+ {
+ if (aIntersections.IsNull())
+ {
+ aIntersections = new IMeshData::MapOfIEdgePtr;
+ }
+
+ aIntersections->Add(aSegment1.EdgePtr);
+
+ const IMeshData::VectorOfInteger& aSegments = aSelector.Indices();
+ for (Standard_Integer aSelIt = 0; aSelIt < aSegments.Size(); ++aSelIt)
+ {
+ const BRepMesh_FaceChecker::Segment& aSegment2 = aSegments2->Value(aSegments(aSelIt));
+ aIntersections->Add(aSegment2.EdgePtr);
+ }
+ }
+ }
+ }
+}
+
+//=======================================================================
+//function : collectResult
+//purpose :
+//=======================================================================
+void BRepMesh_FaceChecker::collectResult()
+{
+ for (Standard_Integer aWireIt = 0; aWireIt < myDFace->WiresNb(); ++aWireIt)
+ {
+ const Handle(IMeshData::MapOfIEdgePtr)& aEdges = myWiresIntersectingEdges->Value(aWireIt);
+ if (!aEdges.IsNull())
+ {
+ myIntersectingEdges->Unite(*aEdges);
+ }
+ }
+}
--- /dev/null
+// Created on: 2016-07-04
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_FaceChecker_HeaderFile
+#define _BRepMesh_FaceChecker_HeaderFile
+
+#include <IMeshTools_Parameters.hxx>
+#include <Standard_Transient.hxx>
+#include <IMeshData_Face.hxx>
+#include <Standard_Type.hxx>
+#include <NCollection_Shared.hxx>
+
+//! Auxiliary class checking wires of target face for self-intersections.
+//! Explodes wires of discrete face on sets of segments using tessellation
+//! data stored in model. Each segment is then checked for intersection with
+//! other ones. All collisions are registerd and returned as result of check.
+class BRepMesh_FaceChecker : public Standard_Transient
+{
+public: //! @name mesher API
+
+ //! Identifies segment inside face.
+ struct Segment
+ {
+ IMeshData::IEdgePtr EdgePtr;
+ gp_Pnt2d* Point1; // \ Use explicit pointers to points instead of accessing
+ gp_Pnt2d* Point2; // / using indices.
+
+ Segment()
+ : Point1(NULL)
+ , Point2(NULL)
+ {
+ }
+
+ Segment(const IMeshData::IEdgePtr& theEdgePtr,
+ gp_Pnt2d* thePoint1,
+ gp_Pnt2d* thePoint2)
+ : EdgePtr(theEdgePtr)
+ , Point1(thePoint1)
+ , Point2(thePoint2)
+ {
+ }
+ };
+
+ typedef NCollection_Shared<NCollection_Vector<Segment> > Segments;
+ typedef NCollection_Shared<NCollection_Array1<Handle(Segments)> > ArrayOfSegments;
+ typedef NCollection_Shared<NCollection_Array1<Handle(IMeshData::BndBox2dTree)> > ArrayOfBndBoxTree;
+ typedef NCollection_Shared<NCollection_Array1<Handle(IMeshData::MapOfIEdgePtr)> > ArrayOfMapOfIEdgePtr;
+
+
+ //! Default constructor
+ Standard_EXPORT BRepMesh_FaceChecker(const IMeshData::IFaceHandle& theFace,
+ const IMeshTools_Parameters& theParameters);
+
+ //! Destructor
+ Standard_EXPORT virtual ~BRepMesh_FaceChecker();
+
+ //! Performs check wires of the face for intersections.
+ //! @return True if there is no intersection, False elsewhere.
+ Standard_EXPORT Standard_Boolean Perform();
+
+ //! Returns intersecting edges.
+ const Handle(IMeshData::MapOfIEdgePtr)& GetIntersectingEdges() const
+ {
+ return myIntersectingEdges;
+ }
+
+ //! Checks wire with the given index for intersection with others.
+ inline void operator()(const Standard_Integer theWireIndex) const
+ {
+ perform(theWireIndex);
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_FaceChecker, Standard_Transient)
+
+private:
+
+ //! Returns True in case if check can be performed in parallel mode.
+ inline Standard_Boolean isParallel() const
+ {
+ return (myParameters.InParallel && myDFace->WiresNb() > 1);
+ }
+
+ //! Collects face segments.
+ void collectSegments();
+
+ //! Collects intersecting edges.
+ void collectResult();
+
+ //! Checks wire with the given index for intersection with others.
+ void perform(const Standard_Integer theWireIndex) const;
+
+private:
+
+ BRepMesh_FaceChecker (const BRepMesh_FaceChecker& theOther);
+
+ void operator=(const BRepMesh_FaceChecker& theOther);
+
+private:
+
+ IMeshData::IFaceHandle myDFace;
+ const IMeshTools_Parameters& myParameters;
+
+ Handle(ArrayOfSegments) myWiresSegments;
+ Handle(ArrayOfBndBoxTree) myWiresBndBoxTree;
+ Handle(ArrayOfMapOfIEdgePtr) myWiresIntersectingEdges;
+ Handle(IMeshData::MapOfIEdgePtr) myIntersectingEdges;
+
+};
+
+#endif
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_FaceDiscret.hxx>
+#include <IMeshData_Model.hxx>
+#include <IMeshData_Face.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshTools_MeshAlgo.hxx>
+#include <OSD_Parallel.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_FaceDiscret::BRepMesh_FaceDiscret(
+ const Handle(IMeshTools_MeshAlgoFactory)& theAlgoFactory)
+ : myAlgoFactory(theAlgoFactory)
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_FaceDiscret::~BRepMesh_FaceDiscret()
+{
+}
+
+//=======================================================================
+// Function: Perform
+// Purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_FaceDiscret::Perform(
+ const Handle(IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& theParameters)
+{
+ myModel = theModel;
+ myParameters = theParameters;
+ if (myModel.IsNull())
+ {
+ return Standard_False;
+ }
+
+ OSD_Parallel::For(0, myModel->FacesNb(), *this, !(myParameters.InParallel && myModel->FacesNb() > 1));
+
+ myModel.Nullify(); // Do not hold link to model.
+ return Standard_True;
+}
+
+//=======================================================================
+// Function: process
+// Purpose :
+//=======================================================================
+void BRepMesh_FaceDiscret::process(const Standard_Integer theFaceIndex) const
+{
+ const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
+ if (aDFace->IsSet(IMeshData_Failure) ||
+ aDFace->IsSet(IMeshData_Reused))
+ {
+ return;
+ }
+
+ Handle(IMeshTools_MeshAlgo) aMeshingAlgo =
+ myAlgoFactory->GetAlgo(aDFace->GetSurface()->GetType(), myParameters);
+
+ if (aMeshingAlgo.IsNull())
+ {
+ aDFace->SetStatus(IMeshData_Failure);
+ return;
+ }
+
+ aMeshingAlgo->Perform(aDFace, myParameters);
+}
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_FaceDiscret_HeaderFile
+#define _BRepMesh_FaceDiscret_HeaderFile
+
+#include <IMeshTools_ModelAlgo.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <IMeshData_Types.hxx>
+#include <IMeshTools_MeshAlgoFactory.hxx>
+
+//! Class implements functionality starting triangulation of model's faces.
+//! Each face is processed separately and can be executed in parallel mode.
+//! Uses mesh algo factory passed as initializer to create instace of triangulation
+//! algorithm according to type of surface of target face.
+class BRepMesh_FaceDiscret : public IMeshTools_ModelAlgo
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_FaceDiscret(
+ const Handle(IMeshTools_MeshAlgoFactory)& theAlgoFactory);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_FaceDiscret();
+
+ //! Performs processing of edges of the given model.
+ Standard_EXPORT virtual Standard_Boolean Perform(
+ const Handle(IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
+
+ //! Functor API to discretize the given edge.
+ inline void operator() (const Standard_Integer theFaceIndex) const {
+ process(theFaceIndex);
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_FaceDiscret, IMeshTools_ModelAlgo)
+
+private:
+
+ //! Checks existing discretization of the face and updates data model.
+ void process(const Standard_Integer theFaceIndex) const;
+
+private:
+
+ Handle(IMeshTools_MeshAlgoFactory) myAlgoFactory;
+ Handle(IMeshData_Model) myModel;
+ IMeshTools_Parameters myParameters;
+};
+
+#endif
+++ /dev/null
-// Created on: 1996-02-27
-// Created by: Ekaterina SMIRNOVA
-// Copyright (c) 1996-1999 Matra Datavision
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <BRepMesh_FastDiscret.hxx>
-
-#include <BRepMesh_WireChecker.hxx>
-#include <BRepMesh_FastDiscretFace.hxx>
-#include <BRepMesh_FaceAttribute.hxx>
-#include <BRepMesh_DataStructureOfDelaun.hxx>
-#include <BRepMesh_GeomTool.hxx>
-#include <BRepMesh_PairOfPolygon.hxx>
-#include <BRepMesh_Classifier.hxx>
-#include <BRepMesh_EdgeParameterProvider.hxx>
-#include <BRepMesh_IEdgeTool.hxx>
-#include <BRepMesh_EdgeTessellator.hxx>
-#include <BRepMesh_EdgeTessellationExtractor.hxx>
-
-#include <BRepAdaptor_Curve.hxx>
-#include <BRepAdaptor_Surface.hxx>
-#include <BRepAdaptor_HSurface.hxx>
-
-#include <Bnd_Box.hxx>
-#include <BRepTools.hxx>
-#include <BRepBndLib.hxx>
-#include <BndLib_Add3dCurve.hxx>
-#include <Poly_Triangulation.hxx>
-#include <Poly_PolygonOnTriangulation.hxx>
-
-#include <Precision.hxx>
-#include <Geom2d_Curve.hxx>
-#include <Geom2dAdaptor_HCurve.hxx>
-#include <Geom_Surface.hxx>
-#include <Geom_Plane.hxx>
-#include <GeomAbs_SurfaceType.hxx>
-#include <Extrema_LocateExtPC.hxx>
-
-#include <TColStd_Array1OfInteger.hxx>
-#include <TColStd_Array1OfCharacter.hxx>
-#include <TColStd_HArray1OfReal.hxx>
-#include <TColgp_Array1OfPnt2d.hxx>
-#include <TColGeom2d_SequenceOfCurve.hxx>
-
-#include <TopTools_SequenceOfShape.hxx>
-#include <TopTools_ListIteratorOfListOfShape.hxx>
-
-#include <TopAbs.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopExp.hxx>
-#include <TopExp_Explorer.hxx>
-
-#include <OSD_Parallel.hxx>
-
-#include <Standard_ErrorHandler.hxx>
-#include <Standard_Failure.hxx>
-#include <NCollection_IncAllocator.hxx>
-
-#include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
-#include <BRep_PointRepresentation.hxx>
-
-#include <vector>
-
-IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscret,Standard_Transient)
-
-#define UVDEFLECTION 1.e-05
-
-//=======================================================================
-//function : BRepMesh_FastDiscret
-//purpose :
-//=======================================================================
-BRepMesh_FastDiscret::BRepMesh_FastDiscret( const Bnd_Box& theBox,
- const BRepMesh_FastDiscret::Parameters& theParams)
- :
- myMapdefle(1000, new NCollection_IncAllocator()),
- myBoundaryVertices(new BRepMesh::DMapOfVertexInteger),
- myBoundaryPoints(new BRepMesh::DMapOfIntegerPnt),
- myParameters(theParams),
- myDtotale(0.)
-{
- if ( myParameters.Relative )
- BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale);
-}
-
-//=======================================================================
-//function : InitSharedFaces
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscret::InitSharedFaces(const TopoDS_Shape& theShape)
-{
- TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, mySharedFaces);
-}
-
-//=======================================================================
-//function : Perform(shape)
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape)
-{
- InitSharedFaces(theShape);
-
- std::vector<TopoDS_Face> aFaces;
- TopExp_Explorer anExplorer(theShape, TopAbs_FACE);
- for (; anExplorer.More(); anExplorer.Next())
- {
- const TopoDS_Face& aFace = TopoDS::Face(anExplorer.Current());
- Add(aFace);
- aFaces.push_back(aFace);
- }
-
- OSD_Parallel::ForEach(aFaces.begin(), aFaces.end(), *this, !myParameters.InParallel, (Standard_Integer )aFaces.size());
-}
-
-
-//=======================================================================
-//function : Process
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const
-{
- Handle(BRepMesh_FaceAttribute) anAttribute;
- if (GetFaceAttribute(theFace, anAttribute))
- {
- try
- {
- OCC_CATCH_SIGNALS
-
- BRepMesh_FastDiscretFace aTool(myParameters.Angle, myParameters.MinSize,
- myParameters.InternalVerticesMode, myParameters.ControlSurfaceDeflection);
- aTool.Perform(anAttribute);
- }
- catch (Standard_Failure)
- {
- anAttribute->SetStatus(BRepMesh_Failure);
- }
- }
-}
-
-//=======================================================================
-//function : resetDataStructure
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscret::resetDataStructure()
-{
- Handle(NCollection_IncAllocator) aAllocator;
- if (myAttribute->ChangeStructure().IsNull())
- aAllocator = new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
- else
- aAllocator = myAttribute->ChangeStructure()->Allocator();
-
- myAttribute->Clear();
- aAllocator->Reset(Standard_False);
- Handle(BRepMesh_DataStructureOfDelaun) aStructure =
- new BRepMesh_DataStructureOfDelaun(aAllocator);
-
- const Standard_Real aTolU = myAttribute->ToleranceU();
- const Standard_Real aTolV = myAttribute->ToleranceV();
- const Standard_Real uCellSize = 14.0 * aTolU;
- const Standard_Real vCellSize = 14.0 * aTolV;
-
- aStructure->Data()->SetCellSize ( uCellSize, vCellSize);
- aStructure->Data()->SetTolerance( aTolU , aTolV );
-
- myAttribute->ChangeStructure() = aStructure;
-}
-
-//=======================================================================
-//function : Add(face)
-//purpose :
-//=======================================================================
-Standard_Integer BRepMesh_FastDiscret::Add(const TopoDS_Face& theFace)
-{
- myAttribute.Nullify();
- GetFaceAttribute(theFace, myAttribute, Standard_True);
-
- try
- {
- OCC_CATCH_SIGNALS
-
- // Initialize face attributes
- if (!myAttribute->IsInitialized ())
- myAttribute->SetFace (theFace, myParameters.AdaptiveMin);
-
- BRepMesh::HIMapOfInteger& aVertexEdgeMap = myAttribute->ChangeVertexEdgeMap();
- BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = myAttribute->ChangeInternalEdges();
-
- resetDataStructure();
-
- Standard_Real defedge = myParameters.Deflection;
- Standard_Integer nbEdge = 0;
- Standard_Real savangle = myParameters.Angle;
- Standard_Real cdef;
- Standard_Real maxdef = 2.* BRepMesh_ShapeTool::MaxFaceTolerance(theFace);
-
- Standard_Real defface = 0.;
- if (!myParameters.Relative)
- {
- defedge = Max(UVDEFLECTION, defedge);
- defface = Max(myParameters.Deflection, maxdef);
- }
-
- const TopoDS_Face& aFace = myAttribute->Face();
- for (TopoDS_Iterator aWireIt(aFace); aWireIt.More(); aWireIt.Next())
- {
- for (TopoDS_Iterator aEdgeIt(aWireIt.Value()); aEdgeIt.More(); aEdgeIt.Next(), ++nbEdge)
- {
- const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Value());
- if (aEdge.IsNull())
- continue;
- if (myParameters.Relative)
- {
- if (!myMapdefle.IsBound(aEdge))
- {
- if (myEdges.IsBound(aEdge))
- {
- const BRepMesh_PairOfPolygon& aPair = myEdges.Find(aEdge);
- const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First();
- defedge = aPolygon->Deflection();
- }
- else
- {
- defedge = BRepMesh_ShapeTool::RelativeEdgeDeflection(
- aEdge, myParameters.Deflection, myDtotale, cdef);
-
- myParameters.Angle = savangle * cdef;
- }
- }
- else
- {
- defedge = myMapdefle(aEdge);
- }
-
- defface += defedge;
- defface = Max(maxdef, defface);
-
- if (!myMapdefle.IsBound(aEdge))
- {
- defedge = Max(UVDEFLECTION, defedge);
- myMapdefle.Bind(aEdge, defedge);
- }
- }
- else
- {
- if (!myMapdefle.IsBound(aEdge))
- {
- myMapdefle.Bind(aEdge, defedge);
- }
- }
-
- Standard_Real aFirstParam, aLastParam;
- Handle(Geom2d_Curve) aCurve2d =
- BRep_Tool::CurveOnSurface(aEdge, aFace, aFirstParam, aLastParam);
-
- if (aCurve2d.IsNull())
- continue;
- Handle(Geom2dAdaptor_HCurve) aPCurve =
- new Geom2dAdaptor_HCurve(aCurve2d, aFirstParam, aLastParam);
-
- add(aEdge, aPCurve, defedge);
- myParameters.Angle = savangle;
- }
- }
-
- if ( nbEdge == 0 || aVertexEdgeMap->Extent() < 3 )
- {
- myAttribute->ChangeStructure().Nullify();
- myAttribute->SetStatus(BRepMesh_Failure);
- return myAttribute->GetStatus();
- }
-
- if ( myParameters.Relative )
- {
- defface = defface / nbEdge;
- }
- else
- {
- defface = myParameters.Deflection;
- }
-
- defface = Max(maxdef, defface);
-
- TopLoc_Location aLoc;
- Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc);
- const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
-
- if ( aTriangulation.IsNull() )
- {
- Standard_Real xCur, yCur;
- Standard_Real maxX, minX, maxY, minY;
-
- minX = minY = 1.e100;
- maxX = maxY =-1.e100;
-
- Standard_Integer ipn = 0;
- Standard_Integer i1 = 1;
- for ( i1 = 1; i1 <= aVertexEdgeMap->Extent(); ++i1 )
- {
- const BRepMesh_Vertex& aVertex =
- myAttribute->ChangeStructure()->GetNode(aVertexEdgeMap->FindKey(i1));
-
- ++ipn;
-
- xCur = aVertex.Coord().X();
- yCur = aVertex.Coord().Y();
-
- minX = Min(xCur, minX);
- maxX = Max(xCur, maxX);
- minY = Min(yCur, minY);
- maxY = Max(yCur, maxY);
- }
-
- Standard_Real myumin = minX;
- Standard_Real myumax = maxX;
- Standard_Real myvmin = minY;
- Standard_Real myvmax = maxY;
-
- const Standard_Real umin = gFace->FirstUParameter();
- const Standard_Real umax = gFace->LastUParameter();
- const Standard_Real vmin = gFace->FirstVParameter();
- const Standard_Real vmax = gFace->LastVParameter();
-
- if (myumin < umin || myumax > umax)
- {
- if (gFace->IsUPeriodic())
- {
- if ((myumax - myumin) > (umax - umin))
- myumax = myumin + (umax - umin);
- }
- else
- {
- if (umin > myumin)
- myumin = umin;
-
- if (umax < myumax)
- myumax = umax;
- }
- }
-
- if (myvmin < vmin || myvmax > vmax)
- {
- if (gFace->IsVPeriodic())
- {
- if ((myvmax - myvmin) > (vmax - vmin))
- myvmax = myvmin + (vmax - vmin);
- }
- else
- {
- if ( vmin > myvmin )
- myvmin = vmin;
-
- if (vmax < myvmax)
- myvmax = vmax;
- }
- }
-
- GeomAbs_SurfaceType aSurfType = gFace->GetType();
- // Fast verification of the validity of calculated limits.
- // If wrong, sure a problem of pcurve.
- if (aSurfType == GeomAbs_BezierSurface &&
- (myumin < -0.5 || myumax > 1.5 || myvmin < -0.5 || myvmax > 1.5) )
- {
- myAttribute->ChangeStructure().Nullify();
- myAttribute->SetStatus(BRepMesh_Failure);
- return myAttribute->GetStatus();
- }
-
- //define parameters for correct parametrics
- Standard_Real deltaX = 1.0;
- Standard_Real deltaY = 1.0;
-
- {
- Standard_Real aTolU, aTolV;
- myAttribute->ChangeStructure()->Data()->GetTolerance(aTolU, aTolV);
- const Standard_Real aTol = Sqrt(aTolU * aTolU + aTolV * aTolV);
-
- BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier();
- BRepMesh_WireChecker aDFaceChecker(aFace, aTol, aInternalEdges,
- aVertexEdgeMap, myAttribute->ChangeStructure(),
- myumin, myumax, myvmin, myvmax, myParameters.InParallel );
-
- aDFaceChecker.ReCompute(aClassifier);
- BRepMesh_Status aCheckStatus = aDFaceChecker.Status();
-
- if (aCheckStatus == BRepMesh_SelfIntersectingWire)
- {
- Standard_Integer nbmaill = 0;
- Standard_Real eps = Precision::Confusion();
- while (nbmaill < 5 && aCheckStatus != BRepMesh_ReMesh)
- {
- ++nbmaill;
-
- resetDataStructure();
-
- for (TopoDS_Iterator aWireIt(aFace); aWireIt.More(); aWireIt.Next())
- {
- for (TopoDS_Iterator aEdgeIt(aWireIt.Value()); aEdgeIt.More(); aEdgeIt.Next(), ++nbEdge)
- {
- const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt.Value());
- if (anEdge.IsNull())
- continue;
- if (myEdges.IsBound(anEdge))
- myEdges.UnBind(anEdge);
-
- defedge = Max(myMapdefle(anEdge) / 3.0, eps);
- myMapdefle.Bind(anEdge, defedge);
-
- Standard_Real aFirstParam, aLastParam;
- Handle(Geom2d_Curve) aCurve2d =
- BRep_Tool::CurveOnSurface(anEdge, aFace, aFirstParam, aLastParam);
- if (aCurve2d.IsNull())
- continue;
-
- Handle(Geom2dAdaptor_HCurve) aPCurve =
- new Geom2dAdaptor_HCurve(aCurve2d, aFirstParam, aLastParam);
- add(anEdge, aPCurve, defedge);
- }
- }
-
- aDFaceChecker.ReCompute(aClassifier);
- if (aDFaceChecker.Status() == BRepMesh_NoError)
- aCheckStatus = BRepMesh_ReMesh;
- }
- }
-
- myAttribute->SetStatus(aCheckStatus);
- if (!myAttribute->IsValid())
- {
- myAttribute->ChangeStructure().Nullify();
- return myAttribute->GetStatus();
- }
- }
-
- // try to find the real length:
- // akm (bug OCC16) : We must calculate these measures in non-singular
- // parts of face. Let's try to compute average value of three
- // (umin, (umin+umax)/2, umax), and respectively for v.
- // vvvvv
- Standard_Real longu = 0.0, longv = 0.0; //, last , first;
- gp_Pnt P11, P12, P21, P22, P31, P32;
-
- Standard_Real du = 0.05 * ( myumax - myumin );
- Standard_Real dv = 0.05 * ( myvmax - myvmin );
- Standard_Real dfuave = 0.5 * ( myumin + myumax );
- Standard_Real dfvave = 0.5 * ( myvmin + myvmax );
- Standard_Real dfucur, dfvcur;
-
- // U loop
- gFace->D0(myumin, myvmin, P11);
- gFace->D0(myumin, dfvave, P21);
- gFace->D0(myumin, myvmax, P31);
- for (i1=1, dfucur=myumin+du; i1 <= 20; i1++, dfucur+=du)
- {
- gFace->D0(dfucur, myvmin, P12);
- gFace->D0(dfucur, dfvave, P22);
- gFace->D0(dfucur, myvmax, P32);
- longu += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
- P11 = P12;
- P21 = P22;
- P31 = P32;
- }
-
- // V loop
- gFace->D0(myumin, myvmin, P11);
- gFace->D0(dfuave, myvmin, P21);
- gFace->D0(myumax, myvmin, P31);
- for (i1=1, dfvcur=myvmin+dv; i1 <= 20; i1++, dfvcur+=dv)
- {
- gFace->D0(myumin, dfvcur, P12);
- gFace->D0(dfuave, dfvcur, P22);
- gFace->D0(myumax, dfvcur, P32);
- longv += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
- P11 = P12;
- P21 = P22;
- P31 = P32;
- }
-
- longu /= 3.;
- longv /= 3.;
- // akm (bug OCC16) ^^^^^
-
- if (longu <= 1.e-16 || longv <= 1.e-16)
- {
- //yes, it is seen!!
- myAttribute->ChangeStructure().Nullify();
- myAttribute->SetStatus(BRepMesh_Failure);
- return myAttribute->GetStatus();
- }
-
-
- if (aSurfType == GeomAbs_Torus)
- {
- gp_Torus Tor = gFace->Torus();
- Standard_Real r = Tor.MinorRadius(), R = Tor.MajorRadius();
- Standard_Real Du, Dv;//, pasu, pasv;
-
- Dv = Max(1.0e0 - (defface/r),0.0e0) ;
- Standard_Real oldDv = 2.0 * ACos (Dv);
- oldDv = Min(oldDv, myParameters.Angle);
- Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
- Dv = oldDv;
-
- Standard_Integer nbV = Max((Standard_Integer)((myvmax-myvmin)/Dv), 2);
- Dv = (myvmax-myvmin)/(nbV+1);
-
- Standard_Real ru = R + r;
- if ( ru > 1.e-16 )
- {
- Du = Max(1.0e0 - (defface/ru),0.0e0);
- Du = (2.0 * ACos (Du));
- Du = Min(Du, myParameters.Angle);
- Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
-
- if (aa < gp::Resolution())
- {
- myAttribute->ChangeStructure().Nullify();
- return myAttribute->GetStatus();
- }
-
- Du = Du * Min(oldDv, Du) / aa;
- }
- else
- {
- Du = Dv;
- }
-
- Standard_Integer nbU = Max((Standard_Integer)((myumax-myumin)/Du), 2);
- nbU = Max(nbU, (Standard_Integer)(nbV*(myumax-myumin)*R/((myvmax-myvmin)*r)/5.));
-
- Du = (myumax-myumin)/(nbU+1);
- //-- DeltaX and DeltaY are chosen so that to avoid "jumping"
- //-- of points on the grid
- deltaX = Du;
- deltaY = Dv;
- }
- else if (aSurfType == GeomAbs_Cylinder)
- {
- gp_Cylinder Cyl = gFace->Cylinder();
- Standard_Real R = Cyl.Radius();
-
- // Calculate parameters for iteration in U direction
- Standard_Real Du = 1.0 - (defface/R);
- if (Du < 0.0)
- Du = 0.0;
-
- Du = 2.0 * ACos (Du);
- if (Du > myParameters.Angle)
- Du = myParameters.Angle;
-
- deltaX = Du / longv;
- deltaY = 1.;
- }
- else
- {
- deltaX = (myumax-myumin)/longu;
- deltaY = (myvmax-myvmin)/longv;
- }
-
- // Restore face attribute
- myAttribute->SetDefFace(defface);
- myAttribute->SetUMax(myumax);
- myAttribute->SetVMax(myvmax);
- myAttribute->SetUMin(myumin);
- myAttribute->SetVMin(myvmin);
- myAttribute->SetDeltaX(deltaX);
- myAttribute->SetDeltaY(deltaY);
- }
-
- myAttribute->ChangeMeshNodes() =
- myAttribute->ChangeStructure()->Data()->Vertices();
- }
- catch(Standard_Failure)
- {
- myAttribute->SetStatus(BRepMesh_Failure);
- }
-
- myAttribute->ChangeStructure().Nullify();
- return myAttribute->GetStatus();
-}
-
-//=======================================================================
-//function : getEdgeAttributes
-//purpose :
-//=======================================================================
-Standard_Boolean BRepMesh_FastDiscret::getEdgeAttributes(
- const TopoDS_Edge& theEdge,
- const Handle(Geom2dAdaptor_HCurve)& thePCurve,
- const Standard_Real theDefEdge,
- BRepMesh_FastDiscret::EdgeAttributes& theAttributes) const
-{
- EdgeAttributes& aEAttr = theAttributes;
-
- // Get vertices
- TopExp::Vertices(theEdge, aEAttr.FirstVertex, aEAttr.LastVertex);
- if (aEAttr.FirstVertex.IsNull() || aEAttr.LastVertex.IsNull())
- return Standard_False;
-
- // Get range on 2d curve
- const TopoDS_Face& aFace = myAttribute->Face();
- BRep_Tool::Range(theEdge, aFace, aEAttr.FirstParam, aEAttr.LastParam);
-
- // Get end points on 2d curve
- BRep_Tool::UVPoints(theEdge, aFace, aEAttr.FirstUV, aEAttr.LastUV);
-
- aEAttr.IsSameUV =
- aEAttr.FirstUV.IsEqual(aEAttr.LastUV, Precision::PConfusion());
- if (aEAttr.IsSameUV)
- {
- // 1. is it really sameUV without being degenerated
- gp_Pnt2d uvF, uvL;
- thePCurve->D0(thePCurve->FirstParameter(), uvF);
- thePCurve->D0(thePCurve->LastParameter(), uvL);
-
- if (!aEAttr.FirstUV.IsEqual(uvF, Precision::PConfusion()))
- aEAttr.FirstUV = uvF;
-
- if (!aEAttr.LastUV.IsEqual(uvL, Precision::PConfusion()))
- aEAttr.LastUV = uvL;
-
- aEAttr.IsSameUV =
- aEAttr.FirstUV.IsEqual(aEAttr.LastUV, Precision::PConfusion());
- }
-
- //Control tolerance of vertices
- const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
- gp_Pnt pFirst = gFace->Value(aEAttr.FirstUV.X(), aEAttr.FirstUV.Y());
- gp_Pnt pLast = gFace->Value(aEAttr.LastUV.X(), aEAttr.LastUV.Y());
-
- Standard_Real aSqDist = pFirst.SquareDistance(BRep_Tool::Pnt(aEAttr.FirstVertex));
- aSqDist = Max(aSqDist, pLast.SquareDistance(BRep_Tool::Pnt(aEAttr.LastVertex)));
-
- aEAttr.Deflection = Max(theDefEdge, BRep_Tool::Tolerance(theEdge));
- aEAttr.Deflection = Max(aEAttr.Deflection, sqrt(aSqDist));
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : registerEdgeVertices
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscret::registerEdgeVertices(
- BRepMesh_FastDiscret::EdgeAttributes& theAttributes,
- Standard_Integer& ipf,
- Standard_Integer& ivf,
- Standard_Integer& isvf,
- Standard_Integer& ipl,
- Standard_Integer& ivl,
- Standard_Integer& isvl)
-{
- EdgeAttributes& aEAttr = theAttributes;
- if (aEAttr.FirstVExtractor.IsNull())
- {
- // Use edge geometry to produce tesselation.
- aEAttr.FirstVExtractor =
- new TopoDSVExplorer(aEAttr.FirstVertex, aEAttr.IsSameUV, aEAttr.LastVertex);
- }
-
- if (aEAttr.LastVExtractor.IsNull())
- {
- // Use edge geometry to produce tesselation.
- aEAttr.LastVExtractor =
- new TopoDSVExplorer(aEAttr.LastVertex, aEAttr.IsSameUV, aEAttr.FirstVertex);
- }
-
- // Process first vertex
- ipf = myAttribute->GetVertexIndex(aEAttr.FirstVExtractor, Standard_True);
- Standard_Real aMinDist = 2. * BRep_Tool::Tolerance(aEAttr.FirstVertex);
- gp_XY aTmpUV1 = BRepMesh_ShapeTool::FindUV(ipf, aEAttr.FirstUV, aMinDist, myAttribute);
-
- myAttribute->AddNode(ipf, aTmpUV1, BRepMesh_Frontier, ivf, isvf);
-
- // Process last vertex
- ipl = aEAttr.LastVertex.IsSame(aEAttr.FirstVertex) ? ipf :
- myAttribute->GetVertexIndex(aEAttr.LastVExtractor, Standard_True);
- aMinDist = 2. * BRep_Tool::Tolerance(aEAttr.LastVertex);
- gp_XY aTmpUV2 = BRepMesh_ShapeTool::FindUV(ipl, aEAttr.LastUV, aMinDist, myAttribute);
-
- myAttribute->AddNode(ipl, aTmpUV2, BRepMesh_Frontier, ivl, isvl);
-
- // Update edge deflection
- const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
- gp_Pnt aPntE1 = gFace->Value(aEAttr.FirstUV.X(), aEAttr.FirstUV.Y());
- gp_Pnt aPntFound1 = gFace->Value(aTmpUV1.X(), aTmpUV1.Y());
- Standard_Real aSqDist = aPntE1.SquareDistance(aPntFound1);
- gp_Pnt aPntE2 = gFace->Value(aEAttr.LastUV.X(), aEAttr.LastUV.Y());
- gp_Pnt aPntFound2 = gFace->Value(aTmpUV2.X(), aTmpUV2.Y());
- aSqDist = Max(aSqDist, aPntE2.SquareDistance(aPntFound2));
- aEAttr.Deflection = Max(aEAttr.Deflection, sqrt(aSqDist));
-}
-
-//=======================================================================
-//function : add
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscret::add(
- const TopoDS_Edge& theEdge,
- const Handle(Geom2dAdaptor_HCurve)& thePCurve,
- const Standard_Real theDefEdge)
-{
- const TopAbs_Orientation orEdge = theEdge.Orientation();
- if (orEdge == TopAbs_EXTERNAL)
- return;
-
- EdgeAttributes aEAttr;
- if (!getEdgeAttributes(theEdge, thePCurve, theDefEdge, aEAttr))
- return;
-
- if (!myEdges.IsBound(theEdge))
- {
- update(theEdge, thePCurve, theDefEdge, aEAttr);
- return;
- }
-
- Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;
- registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl);
-
- // If this Edge has been already checked and it is not degenerated,
- // the points of the polygon calculated at the first check are retrieved :
-
- // retrieve the polygone:
- const BRepMesh_PairOfPolygon& aPair = myEdges.Find(theEdge);
- const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First();
- const TColStd_Array1OfInteger& aNodes = aPolygon->Nodes();
- Handle(TColStd_HArray1OfReal) aParams = aPolygon->Parameters();
-
- // creation anew:
- const Standard_Integer aNodesNb = aNodes.Length();
- TColStd_Array1OfInteger aNewNodes (1, aNodesNb);
- TColStd_Array1OfReal aNewParams(1, aNodesNb);
-
- aNewNodes (1) = isvf;
- aNewParams(1) = aEAttr.FirstParam;
-
- aNewNodes (aNodesNb) = isvl;
- aNewParams(aNodesNb) = aEAttr.LastParam;
-
- const TopoDS_Face& aFace = myAttribute->Face();
- if (!BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace))
- {
- BRepMesh_EdgeParameterProvider aProvider(theEdge, aFace, aParams);
- for (Standard_Integer i = 2; i < aNodesNb; ++i)
- {
- const Standard_Integer aPointId = aNodes(i);
- const gp_Pnt& aPnt = myBoundaryPoints->Find(aPointId);
-
- const Standard_Real aParam = aProvider.Parameter(i, aPnt);
- gp_Pnt2d aUV = thePCurve->Value(aParam);
-
- Standard_Integer iv2, isv;
- myAttribute->AddNode(aPointId, aUV.Coord(), BRepMesh_OnCurve, iv2, isv);
-
- aNewNodes (i) = isv;
- aNewParams(i) = aParam;
- }
- }
-
- Handle(Poly_PolygonOnTriangulation) P1 =
- new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
-
- storePolygon(theEdge, P1, aEAttr.Deflection);
-}
-
-//=======================================================================
-//function : update(edge)
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscret::update(
- const TopoDS_Edge& theEdge,
- const Handle(Geom2dAdaptor_HCurve)& theC2d,
- const Standard_Real theDefEdge,
- BRepMesh_FastDiscret::EdgeAttributes& theAttributes)
-{
- EdgeAttributes& aEAttr = theAttributes;
-
- const TopoDS_Face& aFace = myAttribute->Face();
- Handle(BRepMesh_IEdgeTool) aEdgeTool;
- // Try to find existing tessellation.
- for (Standard_Integer i = 1; aEdgeTool.IsNull(); ++i)
- {
- TopLoc_Location aLoc;
- Handle(Poly_Triangulation) aTriangulation;
- Handle(Poly_PolygonOnTriangulation) aPolygon;
- BRep_Tool::PolygonOnTriangulation(theEdge, aPolygon, aTriangulation, aLoc, i);
-
- if (aPolygon.IsNull())
- break;
-
- if (aTriangulation.IsNull() || !aPolygon->HasParameters())
- continue;
-
- if (aPolygon->Deflection() > 1.1 * theDefEdge)
- continue;
-
- const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
- const TColStd_Array1OfInteger& aIndices = aPolygon->Nodes();
- Handle(TColStd_HArray1OfReal) aParams = aPolygon->Parameters();
-
- aEAttr.FirstVExtractor = new PolyVExplorer(aEAttr.FirstVertex,
- aEAttr.IsSameUV, aEAttr.LastVertex, aIndices(1), aNodes, aLoc);
-
- aEAttr.LastVExtractor = new PolyVExplorer(aEAttr.LastVertex,
- aEAttr.IsSameUV, aEAttr.FirstVertex, aIndices(aIndices.Length()), aNodes, aLoc);
-
- aEdgeTool = new BRepMesh_EdgeTessellationExtractor(theEdge, theC2d,
- aFace, aTriangulation, aPolygon, aLoc);
- }
-
- if (aEdgeTool.IsNull())
- {
- aEdgeTool = new BRepMesh_EdgeTessellator(theEdge, myAttribute,
- mySharedFaces, theDefEdge, myParameters.Angle, myParameters.MinSize);
- }
-
- Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;
- registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl);
-
- Handle(Poly_PolygonOnTriangulation) P1, P2;
- if (BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace))
- {
- // two nodes
- Standard_Integer aNewNodesArr[] = {isvf, isvl};
- Standard_Integer aNewNodInStructArr[] = {ipf, ipl};
- Standard_Real aNewParamsArr[] = {aEAttr.FirstParam, aEAttr.LastParam};
- TColStd_Array1OfInteger aNewNodes (aNewNodesArr[0], 1, 2);
- TColStd_Array1OfInteger aNewNodInStruct(aNewNodInStructArr[0], 1, 2);
- TColStd_Array1OfReal aNewParams (aNewParamsArr[0], 1, 2);
-
- P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
- P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
- }
- else
- {
- const Standard_Integer aNodesNb = aEdgeTool->NbPoints();
- // Allocate the memory for arrays aNewNodesVec, aNewNodesInStructVec, aNewParamsVec
- // only once using the buffer aBuf.
- TColStd_Array1OfCharacter aBuf(1, aNodesNb * (2*sizeof(Standard_Integer) + sizeof(Standard_Real)));
- TColStd_Array1OfInteger aNewNodesVec(*reinterpret_cast<const Standard_Integer*>
- (&aBuf(1)), 1, aNodesNb);
- TColStd_Array1OfInteger aNewNodesInStructVec(*reinterpret_cast<const Standard_Integer*>
- (&aBuf(1 + aNodesNb*sizeof(Standard_Integer))), 1, aNodesNb);
- TColStd_Array1OfReal aNewParamsVec(*reinterpret_cast<const Standard_Real*>
- (&aBuf(1 + aNodesNb*2*sizeof(Standard_Integer))), 1, aNodesNb);
-
- Standard_Integer aNodesCount = 1;
- aNewNodesInStructVec(aNodesCount) = ipf;
- aNewNodesVec (aNodesCount) = isvf;
- aNewParamsVec (aNodesCount) = aEAttr.FirstParam;
-
- ++aNodesCount;
- Standard_Integer aPrevNodeId = ivf;
- Standard_Integer aLastPointId = myAttribute->LastPointId();
- for (Standard_Integer i = 2; i < aNodesNb; ++i)
- {
- gp_Pnt aPnt;
- gp_Pnt2d aUV;
- Standard_Real aParam;
- if (!aEdgeTool->Value(i, aParam, aPnt, aUV))
- continue;
-
- // Imitate index of 3d point in order to not to add points to map without necessity.
- Standard_Integer iv2, isv;
- myAttribute->AddNode(aLastPointId + 1, aUV.Coord(), BRepMesh_Frontier, iv2, isv);
- if (aPrevNodeId == iv2)
- continue;
-
- // Ok, now we can add point to the map.
- myBoundaryPoints->Bind (++aLastPointId, aPnt);
-
- aNewNodesInStructVec(aNodesCount) = aLastPointId;
- aNewNodesVec (aNodesCount) = isv;
- aNewParamsVec (aNodesCount) = aParam;
-
- ++aNodesCount;
- aPrevNodeId = iv2;
- }
-
- aNewNodesInStructVec(aNodesCount) = ipl;
- aNewNodesVec (aNodesCount) = isvl;
- aNewParamsVec (aNodesCount) = aEAttr.LastParam;
-
- TColStd_Array1OfInteger aNewNodes (aNewNodesVec.First (), 1, aNodesCount);
- TColStd_Array1OfInteger aNewNodInStruct(aNewNodesInStructVec.First(), 1, aNodesCount);
- TColStd_Array1OfReal aNewParams (aNewParamsVec.First(), 1, aNodesCount);
-
- P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
- P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
- }
-
- storePolygon(theEdge, P1, aEAttr.Deflection);
- storePolygonSharedData(theEdge, P2, aEAttr.Deflection);
-}
-
-//=======================================================================
-//function : storeInternalPolygon
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscret::storePolygon(
- const TopoDS_Edge& theEdge,
- Handle(Poly_PolygonOnTriangulation)& thePolygon,
- const Standard_Real theDeflection)
-{
- thePolygon->Deflection(theDeflection);
- BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = myAttribute->ChangeInternalEdges();
- if (aInternalEdges->IsBound(theEdge))
- {
- BRepMesh_PairOfPolygon& aPair = aInternalEdges->ChangeFind(theEdge);
- if (theEdge.Orientation() == TopAbs_REVERSED)
- aPair.Append(thePolygon);
- else
- aPair.Prepend(thePolygon);
-
- return;
- }
-
- BRepMesh_PairOfPolygon aPair;
- aPair.Append(thePolygon);
- aInternalEdges->Bind(theEdge, aPair);
-}
-
-//=======================================================================
-//function : storePolygonSharedData
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscret::storePolygonSharedData(
- const TopoDS_Edge& theEdge,
- Handle(Poly_PolygonOnTriangulation)& thePolygon,
- const Standard_Real theDeflection)
-{
- thePolygon->Deflection(theDeflection);
- BRepMesh_PairOfPolygon aPair;
- aPair.Append(thePolygon);
- myEdges.Bind(theEdge, aPair);
-}
-
-//=======================================================================
-//function : GetFaceAttribute
-//purpose :
-//=======================================================================
-Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute(
- const TopoDS_Face& theFace,
- Handle(BRepMesh_FaceAttribute)& theAttribute,
- const Standard_Boolean isForceCreate) const
-{
- if (myAttributes.IsBound(theFace))
- {
- theAttribute = myAttributes(theFace);
- return Standard_True;
- }
- else if (isForceCreate)
- {
- theAttribute = new BRepMesh_FaceAttribute(myBoundaryVertices, myBoundaryPoints);
- myAttributes.Bind(theFace, theAttribute);
- }
-
- return Standard_False;
-}
-
-//=======================================================================
-//function : RemoveFaceAttribute
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscret::RemoveFaceAttribute(const TopoDS_Face& theFace)
-{
- if (myAttributes.IsBound(theFace))
- myAttributes.UnBind(theFace);
-}
#ifndef _BRepMesh_FastDiscret_HeaderFile
#define _BRepMesh_FastDiscret_HeaderFile
-#include <Standard.hxx>
-#include <Standard_Type.hxx>
-#include <BRepMesh_FastDiscret.hxx>
-#include <BRepMesh_DataStructureOfDelaun.hxx>
-#include <TColStd_IndexedMapOfInteger.hxx>
-#include <BRepMesh_Status.hxx>
-#include <TopTools_DataMapOfShapeReal.hxx>
-#include <TopTools_ListOfShape.hxx>
-#include <TopTools_MutexForShapeProvider.hxx>
-#include <Standard_Transient.hxx>
-#include <BRepMesh_Delaun.hxx>
-#include <TopAbs_ShapeEnum.hxx>
-#include <BRepMesh_Triangle.hxx>
-#include <BRepMesh_FaceAttribute.hxx>
-#include <BRepMesh.hxx>
-#include <TColgp_Array1OfPnt.hxx>
-#include <BRep_Tool.hxx>
-#include <BRepMesh_ShapeTool.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <IMeshTools_Parameters.hxx>
-class BRepMesh_DataStructureOfDelaun;
-class Bnd_Box;
-class TopoDS_Shape;
-class TopoDS_Face;
-class TopoDS_Edge;
-class Geom2dAdaptor_HCurve;
-class BRepAdaptor_HSurface;
-class BRepMesh_Edge;
-class BRepMesh_Vertex;
-class gp_Pnt;
-class BRepMesh_FaceAttribute;
-
-//! Algorithm to mesh a shape with respect of the <br>
-//! frontier the deflection and by option the shared <br>
-//! components. <br>
-class BRepMesh_FastDiscret : public Standard_Transient
+class Standard_DEPRECATED("The class BRepMesh_FastDiscret is deprecated. Please use IMeshTools package") BRepMesh_FastDiscret
{
public:
-
-
- //! Structure storing meshing parameters
- struct Parameters {
-
- //! Default constructor
- Parameters()
- :
- Angle(0.1),
- Deflection(0.001),
- MinSize(Precision::Confusion()),
- InParallel(Standard_False),
- Relative(Standard_False),
- AdaptiveMin(Standard_False),
- InternalVerticesMode(Standard_True),
- ControlSurfaceDeflection(Standard_True)
- {
- }
-
- //! Angular deflection
- Standard_Real Angle;
-
- //! Deflection
- Standard_Real Deflection;
-
- //! Minimal allowed size of mesh element
- Standard_Real MinSize;
-
- //! Switches on/off multy thread computation
- Standard_Boolean InParallel;
-
- //! Switches on/off relative computation of edge tolerance<br>
- //! If trur, deflection used for the polygonalisation of each edge will be
- //! <defle> * Size of Edge. The deflection used for the faces will be the
- //! maximum deflection of their edges.
- Standard_Boolean Relative;
-
- //! Adaptive parametric tolerance flag. <br>
- //! If this flag is set to true the minimal parametric tolerance
- //! is computed taking minimal parametric distance between vertices
- //! into account
- Standard_Boolean AdaptiveMin;
-
- //! Mode to take or ont to take internal face vertices into account
- //! in triangulation process
- Standard_Boolean InternalVerticesMode;
-
- //! Prameter to check the deviation of triangulation and interior of
- //! the face
- Standard_Boolean ControlSurfaceDeflection;
- };
-
-public:
-
-
- //! Constructor.
- //! Sets the meshing parameters and updates
- //! relative defletion according to bounding box
- //! @param B - bounding box encompasing shape
- //! @param theParams - meshing algo parameters
- Standard_EXPORT BRepMesh_FastDiscret (const Bnd_Box& B,
- const Parameters& theParams);
-
- //! Build triangulation on the whole shape.
- Standard_EXPORT void Perform(const TopoDS_Shape& shape);
-
- //! Record a face for further processing.
- //! @return status flags collected during discretization
- //! of boundaries of the given face.
- Standard_EXPORT Standard_Integer Add(const TopoDS_Face& face);
-
- //! Triangulate a face previously recorded for
- //! processing by call to Add(). Can be executed in
- //! parallel threads.
- Standard_EXPORT void Process(const TopoDS_Face& face) const;
-
- void operator () (const TopoDS_Face& face) const
- {
- Process(face);
- }
-
- //! Returns parameters of meshing
- inline const Parameters& MeshParameters() const
- {
- return myParameters;
- }
-
- //! Returns modificable mesh parameters
- inline Parameters& ChangeMeshParameters()
- {
- return myParameters;
- }
-
-
- Standard_EXPORT void InitSharedFaces(const TopoDS_Shape& theShape);
-
- inline const TopTools_IndexedDataMapOfShapeListOfShape& SharedFaces() const
- {
- return mySharedFaces;
- }
-
- //! Returns attribute descriptor for the given face.
- //! @param theFace face the attribute should be returned for.
- //! @param[out] theAttribute attribute found for the specified face.
- //! @param isForceCreate if True creates new attribute in case if there
- //! is no data for the given face.
- Standard_EXPORT Standard_Boolean GetFaceAttribute (
- const TopoDS_Face& theFace,
- Handle(BRepMesh_FaceAttribute)& theAttribute,
- const Standard_Boolean isForceCreate = Standard_False) const;
-
- //! Remove face attribute as useless to free locate memory.
- Standard_EXPORT void RemoveFaceAttribute( const TopoDS_Face& theFace );
-
- //! Returns number of boundary 3d points.
- inline Standard_Integer NbBoundaryPoints() const
- {
- return myBoundaryPoints->Extent();
- }
-
- DEFINE_STANDARD_RTTIEXT(BRepMesh_FastDiscret,Standard_Transient)
-
-private:
-
- //! Auxiliary class used to extract geometrical parameters of TopoDS_Vertex.
- class TopoDSVExplorer
- {
- public:
- TopoDSVExplorer(
- const TopoDS_Vertex& theVertex,
- const Standard_Boolean isSameUV,
- const TopoDS_Vertex& theSameVertex)
- : myVertex(theVertex),
- myIsSameUV(isSameUV),
- mySameVertex(theSameVertex)
- {
- }
- virtual ~TopoDSVExplorer() {
- }
- const TopoDS_Vertex& Vertex() const
- {
- return myVertex;
- }
-
- Standard_Boolean IsSameUV() const
- {
- return myIsSameUV;
- }
-
- const TopoDS_Vertex& SameVertex() const
- {
- return mySameVertex;
- }
-
- virtual gp_Pnt Point() const
- {
- return BRep_Tool::Pnt(myVertex);
- }
-
- private:
-
- void operator =(const TopoDSVExplorer& /*theOther*/)
- {
- }
-
- private:
- const TopoDS_Vertex& myVertex;
- Standard_Boolean myIsSameUV;
- const TopoDS_Vertex& mySameVertex;
- };
-
-
- //! Auxiliary class used to extract polygonal parameters of TopoDS_Vertex.
- class PolyVExplorer : public TopoDSVExplorer
- {
- public:
- PolyVExplorer(
- const TopoDS_Vertex& theVertex,
- const Standard_Boolean isSameUV,
- const TopoDS_Vertex& theSameVertex,
- const Standard_Integer theVertexIndex,
- const TColgp_Array1OfPnt& thePolygon,
- const TopLoc_Location& theLoc)
- : TopoDSVExplorer(theVertex, isSameUV, theSameVertex),
- myVertexIndex(theVertexIndex),
- myPolygon(thePolygon),
- myLoc(theLoc)
- {
- }
-
- virtual gp_Pnt Point() const
- {
- return BRepMesh_ShapeTool::UseLocation(myPolygon(myVertexIndex), myLoc);
- }
-
- private:
-
- void operator =(const PolyVExplorer& /*theOther*/)
- {
- }
-
- private:
- Standard_Integer myVertexIndex;
- const TColgp_Array1OfPnt& myPolygon;
- const TopLoc_Location myLoc;
- };
-
- //! Structure keeps common parameters of edge
- //! used for tessellation.
- struct EdgeAttributes
- {
- TopoDS_Vertex FirstVertex;
- TopoDS_Vertex LastVertex;
-
- Standard_Real FirstParam;
- Standard_Real LastParam;
-
- gp_Pnt2d FirstUV;
- gp_Pnt2d LastUV;
-
- Standard_Real Deflection;
- Standard_Boolean IsSameUV;
-
- NCollection_Handle<TopoDSVExplorer> FirstVExtractor;
- NCollection_Handle<TopoDSVExplorer> LastVExtractor;
- };
-
- //! Fills structure of by attributes of the given edge.
- //! @return TRUE on success, FALSE elsewhere.
- Standard_Boolean getEdgeAttributes(
- const TopoDS_Edge& theEdge,
- const Handle(Geom2dAdaptor_HCurve)& thePCurve,
- const Standard_Real theDefEdge,
- EdgeAttributes& theAttributes) const;
-
- //! Registers end vertices of the edge in mesh data
- //! structure of currently processed face.
- void registerEdgeVertices(
- EdgeAttributes& theAttributes,
- Standard_Integer& ipf,
- Standard_Integer& ivf,
- Standard_Integer& isvf,
- Standard_Integer& ipl,
- Standard_Integer& ivl,
- Standard_Integer& isvl);
-
- //! Adds tessellated representation of the given edge to
- //! mesh data structure of currently processed face.
- void add(const TopoDS_Edge& theEdge,
- const Handle(Geom2dAdaptor_HCurve)& theCurve2D,
- const Standard_Real theEdgeDeflection);
-
- //! Updates tessellated representation of the given edge.
- //! If edge already has a polygon which deflection satisfies
- //! the given value, retrieves tessellation from polygon.
- //! Computes tessellation using edge's geometry elsewhere.
- void update(
- const TopoDS_Edge& theEdge,
- const Handle(Geom2dAdaptor_HCurve)& theCurve2D,
- const Standard_Real theEdgeDeflection,
- EdgeAttributes& theAttributes);
-
- //! Stores polygonal model of the given edge.
- //! @param theEdge edge which polygonal model is stored.
- //! @param thePolygon polygonal model of the edge.
- //! @param theDeflection deflection with which polygonalization is performed.
- //! This value is stored inside the polygon.
- void storePolygon(
- const TopoDS_Edge& theEdge,
- Handle(Poly_PolygonOnTriangulation)& thePolygon,
- const Standard_Real theDeflection);
-
- //! Caches polygonal model of the given edge to be used in further.
- //! @param theEdge edge which polygonal data is stored.
- //! @param thePolygon shared polygonal data of the edge.
- //! @param theDeflection deflection with which polygonalization is performed.
- //! This value is stored inside the polygon.
- void storePolygonSharedData(
- const TopoDS_Edge& theEdge,
- Handle(Poly_PolygonOnTriangulation)& thePolygon,
- const Standard_Real theDeflection);
-
- //! Resets temporary data structure used to collect unique nodes.
- void resetDataStructure();
-
-private:
-
- TopoDS_Face myFace;
-
- BRepMesh::DMapOfShapePairOfPolygon myEdges;
- mutable BRepMesh::DMapOfFaceAttribute myAttributes;
- TopTools_DataMapOfShapeReal myMapdefle;
-
- // Data shared for whole shape
- BRepMesh::HDMapOfVertexInteger myBoundaryVertices;
- BRepMesh::HDMapOfIntegerPnt myBoundaryPoints;
-
- // Fast access to attributes of current face
- Handle(BRepMesh_FaceAttribute) myAttribute;
- TopTools_IndexedDataMapOfShapeListOfShape mySharedFaces;
-
- Parameters myParameters;
-
- Standard_Real myDtotale;
+ Standard_DEPRECATED("The class BRepMesh_FastDiscret is deprecated. Please use IMeshTools package")
+ typedef IMeshTools_Parameters Parameters;
};
-DEFINE_STANDARD_HANDLE(BRepMesh_FastDiscret, Standard_Transient)
-
#endif
+++ /dev/null
-// Created by: Ekaterina SMIRNOVA
-// Copyright (c) 2008-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <BRepMesh_FastDiscretFace.hxx>
-
-#include <BRepMesh_PairOfPolygon.hxx>
-#include <BRepMesh_ShapeTool.hxx>
-#include <Poly_PolygonOnTriangulation.hxx>
-#include <Poly_Triangulation.hxx>
-
-#include <BRepAdaptor_Surface.hxx>
-#include <BRepAdaptor_HSurface.hxx>
-#include <BRepAdaptor_Curve.hxx>
-#include <Adaptor3d_IsoCurve.hxx>
-#include <Adaptor3d_HCurve.hxx>
-
-#include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
-#include <BRep_PointRepresentation.hxx>
-#include <BRep_TVertex.hxx>
-#include <BRep_Tool.hxx>
-
-#include <GeomLib.hxx>
-#include <Geom_Surface.hxx>
-#include <Geom_BSplineSurface.hxx>
-#include <Geom_BezierSurface.hxx>
-#include <GCPnts_TangentialDeflection.hxx>
-#include <GCPnts_AbscissaPoint.hxx>
-
-#include <Standard_ErrorHandler.hxx>
-#include <Standard_Failure.hxx>
-#include <TColStd_Array1OfReal.hxx>
-#include <TColStd_ListOfInteger.hxx>
-#include <TColStd_SequenceOfReal.hxx>
-#include <TColStd_Array1OfInteger.hxx>
-#include <TColStd_HArray1OfReal.hxx>
-#include <TColgp_Array1OfPnt2d.hxx>
-#include <TopTools_DataMapOfShapeReal.hxx>
-
-#include <TopExp_Explorer.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopExp.hxx>
-
-#include <NCollection_Map.hxx>
-#include <Bnd_Box2d.hxx>
-
-#include <algorithm>
-
-//#define DEBUG_MESH "mesh.tcl"
-#ifdef DEBUG_MESH
-#include <fstream>
-#endif
-
-
-IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace,Standard_Transient)
-
-static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_Integer PLen)
-{
- Standard_Integer i, j, n = 0;
- Standard_Real p, result = 0.;
-
- for(i = 1; i <= PLen; i++)
- {
- // Sort
- for(j = i + 1; j <= PLen; j++)
- {
- if(P(i) > P(j))
- {
- p = P(i);
- P(i) = P(j);
- P(j) = p;
- }
- }
- // Accumulate
- if (i != 1)
- {
- p = Abs(P(i) - P(i-1));
- if(p > 1.e-7)
- {
- result += p;
- n++;
- }
- }
- }
- return (n? (result / (Standard_Real) n) : -1.);
-}
-
-namespace
-{
- Standard_Real deflectionOfSegment (
- const gp_Pnt& theFirstPoint,
- const gp_Pnt& theLastPoint,
- const gp_Pnt& theMidPoint)
- {
- // 23.03.2010 skl for OCC21645 - change precision for comparison
- if (theFirstPoint.SquareDistance (theLastPoint) > Precision::SquareConfusion ())
- {
- gp_Lin aLin (theFirstPoint, gp_Dir (gp_Vec (theFirstPoint, theLastPoint)));
- return aLin.Distance (theMidPoint);
- }
-
- return theFirstPoint.Distance (theMidPoint);
- }
-
- Standard_Boolean IsCompexSurface (const GeomAbs_SurfaceType theType)
- {
- return (
- theType != GeomAbs_Sphere &&
- theType != GeomAbs_Cylinder &&
- theType != GeomAbs_Cone &&
- theType != GeomAbs_Torus);
- }
-
- //! Auxiliary class used to extract geometrical parameters of fixed TopoDS_Vertex.
- class FixedVExplorer
- {
- public:
-
- DEFINE_STANDARD_ALLOC
-
- FixedVExplorer(const TopoDS_Vertex& theVertex)
- : myVertex(theVertex)
- {
- }
-
- const TopoDS_Vertex& Vertex() const
- {
- return myVertex;
- }
-
- Standard_Boolean IsSameUV() const
- {
- return Standard_False;
- }
-
- TopoDS_Vertex SameVertex() const
- {
- return TopoDS_Vertex();
- }
-
- gp_Pnt Point() const
- {
- return BRep_Tool::Pnt(myVertex);
- }
-
- private:
-
- void operator =(const FixedVExplorer& /*theOther*/)
- {
- }
-
- private:
- const TopoDS_Vertex& myVertex;
- };
-
- void ComputeErrFactors (const Standard_Real theDeflection,
- const Handle(Adaptor3d_HSurface)& theFace,
- Standard_Real& theErrFactorU,
- Standard_Real& theErrFactorV)
- {
- theErrFactorU = theDeflection * 10.;
- theErrFactorV = theDeflection * 10.;
-
- switch (theFace->GetType ())
- {
- case GeomAbs_Cylinder:
- case GeomAbs_Cone:
- case GeomAbs_Sphere:
- case GeomAbs_Torus:
- break;
-
- case GeomAbs_SurfaceOfExtrusion:
- case GeomAbs_SurfaceOfRevolution:
- {
- Handle (Adaptor3d_HCurve) aCurve = theFace->BasisCurve ();
- if (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () > 2)
- {
- theErrFactorV /= (aCurve->Degree () * aCurve->NbKnots ());
- }
- break;
- }
- case GeomAbs_BezierSurface:
- {
- if (theFace->UDegree () > 2)
- {
- theErrFactorU /= (theFace->UDegree ());
- }
- if (theFace->VDegree () > 2)
- {
- theErrFactorV /= (theFace->VDegree ());
- }
- break;
- }
- case GeomAbs_BSplineSurface:
- {
- if (theFace->UDegree () > 2)
- {
- theErrFactorU /= (theFace->UDegree () * theFace->NbUKnots ());
- }
- if (theFace->VDegree () > 2)
- {
- theErrFactorV /= (theFace->VDegree () * theFace->NbVKnots ());
- }
- break;
- }
-
- case GeomAbs_Plane:
- default:
- theErrFactorU = theErrFactorV = 1.;
- }
- }
-
- void AdjustCellsCounts (const Handle(Adaptor3d_HSurface)& theFace,
- const Standard_Integer theNbVertices,
- Standard_Integer& theCellsCountU,
- Standard_Integer& theCellsCountV)
- {
- const GeomAbs_SurfaceType aType = theFace->GetType ();
- if (aType == GeomAbs_OtherSurface)
- {
- // fallback to the default behavior
- theCellsCountU = theCellsCountV = -1;
- return;
- }
-
- Standard_Real aSqNbVert = theNbVertices;
- if (aType == GeomAbs_Plane)
- {
- theCellsCountU = theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
- }
- else if (aType == GeomAbs_Cylinder || aType == GeomAbs_Cone)
- {
- theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
- }
- else if (aType == GeomAbs_SurfaceOfExtrusion || aType == GeomAbs_SurfaceOfRevolution)
- {
- Handle (Adaptor3d_HCurve) aCurve = theFace->BasisCurve ();
- if (aCurve->GetType () == GeomAbs_Line ||
- (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () < 2))
- {
- // planar, cylindrical, conical cases
- if (aType == GeomAbs_SurfaceOfExtrusion)
- theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
- else
- theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
- }
- if (aType == GeomAbs_SurfaceOfExtrusion)
- {
- // V is always a line
- theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
- }
- }
- else if (aType == GeomAbs_BezierSurface || aType == GeomAbs_BSplineSurface)
- {
- if (theFace->UDegree () < 2)
- {
- theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
- }
- if (theFace->VDegree () < 2)
- {
- theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
- }
- }
-
- theCellsCountU = Max (theCellsCountU, 2);
- theCellsCountV = Max (theCellsCountV, 2);
- }
-}
-
-
-//=======================================================================
-//function : BRepMesh_FastDiscretFace
-//purpose :
-//=======================================================================
-BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace(
- const Standard_Real theAngle,
- const Standard_Real theMinSize,
- const Standard_Boolean isInternalVerticesMode,
- const Standard_Boolean isControlSurfaceDeflection)
-: myAngle(theAngle),
- myInternalVerticesMode(isInternalVerticesMode),
- myMinSize(theMinSize),
- myIsControlSurfaceDeflection(isControlSurfaceDeflection)
-{
-}
-
-//=======================================================================
-//function : Perform
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::Perform(const Handle(BRepMesh_FaceAttribute)& theAttribute)
-{
- add(theAttribute);
- commitSurfaceTriangulation();
-}
-
-//=======================================================================
-//function : initDataStructure
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::initDataStructure()
-{
- const Standard_Real aTolU = myAttribute->ToleranceU();
- const Standard_Real aTolV = myAttribute->ToleranceV();
- const Standard_Real uCellSize = 14.0 * aTolU;
- const Standard_Real vCellSize = 14.0 * aTolV;
-
- const Standard_Real deltaX = myAttribute->GetDeltaX();
- const Standard_Real deltaY = myAttribute->GetDeltaY();
-
- Handle(NCollection_IncAllocator) aAllocator =
- new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
- myStructure = new BRepMesh_DataStructureOfDelaun(aAllocator);
- myStructure->Data()->SetCellSize ( uCellSize / deltaX, vCellSize / deltaY);
- myStructure->Data()->SetTolerance( aTolU / deltaX, aTolV / deltaY);
-
- myAttribute->ChangeStructure() = myStructure;
- myAttribute->ChangeSurfacePoints() = new BRepMesh::DMapOfIntegerPnt(1, aAllocator);
- myAttribute->ChangeSurfaceVertices()= new BRepMesh::DMapOfVertexInteger(1, aAllocator);
-
- // Check the necessity to fill the map of parameters
- const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
- GeomAbs_SurfaceType thetype = gFace->GetType();
- const Standard_Boolean isBSpline = (thetype == GeomAbs_BezierSurface ||
- thetype == GeomAbs_BSplineSurface);
- const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus || IsCompexSurface (thetype));
-
- Handle(NCollection_BaseAllocator) aBaseAlloc = aAllocator;
- myUParam.Clear (aBaseAlloc);
- myVParam.Clear (aBaseAlloc);
-
- // essai de determination de la longueur vraie:
- // akm (bug OCC16) : We must calculate these measures in non-singular
- // parts of face. Let`s try to compute average value of three
- // (umin, (umin+umax)/2, umax), and respectively for v.
- // vvvvv
- //Standard_Real longu = 0.0, longv = 0.0; //, last , first;
- //gp_Pnt P11, P12, P21, P22, P31, P32;
- BRepMesh::HVectorOfVertex& aBoundaryNodes = myAttribute->ChangeMeshNodes();
- BRepMesh::VectorOfVertex::Iterator aNodesIt(*aBoundaryNodes);
- for (; aNodesIt.More(); aNodesIt.Next())
- {
- BRepMesh_Vertex& aNode = aNodesIt.ChangeValue();
- gp_XY aPnt2d = aNode.Coord();
-
- if (useUVParam)
- {
- myUParam.Add(aPnt2d.X());
- myVParam.Add(aPnt2d.Y());
- }
-
- aNode.ChangeCoord() = myAttribute->Scale(aPnt2d, Standard_True);
- myStructure->AddNode(aNode, Standard_True);
- }
- aBoundaryNodes.Nullify();
-
- if (isBSpline)
- {
- const Standard_Real aRange[2][2] = {
- {myAttribute->GetUMin(), myAttribute->GetUMax()},
- {myAttribute->GetVMin(), myAttribute->GetVMax()}
- };
-
- const GeomAbs_Shape aContinuity = GeomAbs_CN;
- for (Standard_Integer i = 0; i < 2; ++i)
- {
- const Standard_Boolean isU = (i == 0);
- const Standard_Integer aIntervalsNb = isU ?
- gFace->NbUIntervals(aContinuity) :
- gFace->NbVIntervals(aContinuity);
-
- BRepMesh::IMapOfReal& aParams = isU ? myUParam : myVParam;
- if (aIntervalsNb < aParams.Size())
- continue;
-
- TColStd_Array1OfReal aIntervals(1, aIntervalsNb + 1);
- if (isU)
- gFace->UIntervals(aIntervals, aContinuity);
- else
- gFace->VIntervals(aIntervals, aContinuity);
-
- for (Standard_Integer j = 1; j <= aIntervals.Upper(); ++j)
- {
- const Standard_Real aParam = aIntervals(j);
- if (aParam > aRange[i][0] && aParam < aRange[i][1])
- aParams.Add(aParam);
- }
- }
- }
-
- ////////////////////////////////////////////////////////////
- //add internal vertices after self-intersection check
- if ( myInternalVerticesMode )
- {
- TopExp_Explorer anExplorer(myAttribute->Face(), TopAbs_VERTEX, TopAbs_EDGE);
- for ( ; anExplorer.More(); anExplorer.Next() )
- add(TopoDS::Vertex(anExplorer.Current()));
- }
-
- const BRepMesh::HDMapOfShapePairOfPolygon& aEdges = myAttribute->ChangeInternalEdges();
- TopExp_Explorer aWireIt(myAttribute->Face(), TopAbs_WIRE);
- for (; aWireIt.More(); aWireIt.Next())
- {
- TopExp_Explorer aEdgeIt(aWireIt.Current(), TopAbs_EDGE);
- for (; aEdgeIt.More(); aEdgeIt.Next())
- {
- const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
- BRepMesh_PairOfPolygon aPair;
- if (!aEdges->Find(aEdge, aPair))
- continue;
-
- TopAbs_Orientation aOri = aEdge.Orientation();
- const Handle(Poly_PolygonOnTriangulation)& aPolygon =
- aOri == TopAbs_REVERSED ? aPair.Last() : aPair.First();
-
- const TColStd_Array1OfInteger& aIndices = aPolygon->Nodes();
- const Standard_Integer aNodesNb = aPolygon->NbNodes();
-
- Standard_Integer aPrevId = aIndices(1);
- for (Standard_Integer i = 2; i <= aNodesNb; ++i)
- {
- const Standard_Integer aCurId = aIndices(i);
- addLinkToMesh(aPrevId, aCurId, aOri);
- aPrevId = aCurId;
- }
- }
- }
-}
-
-//=======================================================================
-//function : addLinkToMesh
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::addLinkToMesh(
- const Standard_Integer theFirstNodeId,
- const Standard_Integer theLastNodeId,
- const TopAbs_Orientation theOrientation)
-{
- if (theOrientation == TopAbs_FORWARD)
- myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Frontier));
- else if (theOrientation == TopAbs_REVERSED)
- myStructure->AddLink(BRepMesh_Edge(theLastNodeId, theFirstNodeId, BRepMesh_Frontier));
- else if (theOrientation == TopAbs_INTERNAL)
- myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Fixed));
-}
-
-//=======================================================================
-//function : Add
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::add(const Handle(BRepMesh_FaceAttribute)& theAttribute)
-{
- if (!theAttribute->IsValid() || theAttribute->ChangeMeshNodes()->IsEmpty())
- return;
-
- myAttribute = theAttribute;
- initDataStructure();
-
- BRepMesh::HIMapOfInteger& aVertexEdgeMap = myAttribute->ChangeVertexEdgeMap();
- Standard_Integer nbVertices = aVertexEdgeMap->Extent();
- BRepMesh::Array1OfInteger tabvert_corr(1, nbVertices);
- for ( Standard_Integer i = 1; i <= nbVertices; ++i )
- tabvert_corr(i) = i;
-
- Handle (Adaptor3d_HSurface) aSurface (myAttribute->Surface ());
- GeomAbs_SurfaceType aType = aSurface->GetType ();
-
- while (aType == GeomAbs_OffsetSurface)
- {
- aSurface = aSurface->BasisSurface ();
- aType = aSurface->GetType ();
- }
-
- // For better meshing performance we try to estimate the acceleration circles grid structure sizes:
- // For each parametric direction (U, V) we estimate firstly an approximate distance between the future points -
- // this estimation takes into account the required face deflection and the complexity of the face.
- // Particularly, the complexity of the faces based on BSpline curves and surfaces requires much more points.
- // At the same time, for planar faces and linear parts of the arbitrary surfaces usually no intermediate points
- // are necessary.
- // The general idea for each parametric direction:
- // cells_count = 2 ^ log10 ( estimated_points_count )
- // For linear parametric direction we fall back to the initial vertex count:
- // cells_count = 2 ^ log10 ( initial_vertex_count )
-
- Standard_Real anErrFactorU, anErrFactorV;
- ComputeErrFactors(myAttribute->GetDefFace (), aSurface, anErrFactorU, anErrFactorV);
-
- Standard_Integer aCellsCountU, aCellsCountV;
- if (aType == GeomAbs_Torus)
- {
- aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
- (myAttribute->GetUMax() - myAttribute->GetUMin()) / myAttribute->GetDeltaX())));
- aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
- (myAttribute->GetVMax() - myAttribute->GetVMin()) / myAttribute->GetDeltaY())));
- }
- else if (aType == GeomAbs_Cylinder)
- {
- aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
- (myAttribute->GetUMax() - myAttribute->GetUMin()) / myAttribute->GetDeltaX() /
- (myAttribute->GetVMax() - myAttribute->GetVMin()))));
- aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
- (myAttribute->GetVMax() - myAttribute->GetVMin()) / anErrFactorV)));
- }
- else
- {
- aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
- (myAttribute->GetUMax() - myAttribute->GetUMin()) / myAttribute->GetDeltaX() / anErrFactorU)));
- aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
- (myAttribute->GetVMax() - myAttribute->GetVMin()) / myAttribute->GetDeltaY() / anErrFactorV)));
- }
-
- AdjustCellsCounts(aSurface, nbVertices, aCellsCountU, aCellsCountV);
-
- BRepMesh_Delaun trigu(myStructure, tabvert_corr, aCellsCountU, aCellsCountV);
-
- //removed all free edges from triangulation
- const Standard_Integer nbLinks = myStructure->NbLinks();
- for( Standard_Integer i = 1; i <= nbLinks; i++ )
- {
- if( myStructure->ElementsConnectedTo(i).Extent() < 1 )
- {
- BRepMesh_Edge& anEdge = (BRepMesh_Edge&)trigu.GetEdge(i);
- if ( anEdge.Movability() == BRepMesh_Deleted )
- continue;
-
- anEdge.SetMovability(BRepMesh_Free);
- myStructure->RemoveLink(i);
- }
- }
-
- Standard_Boolean rajout =
- (aType == GeomAbs_Sphere || aType == GeomAbs_Torus);
-
- // Check the necessity to fill the map of parameters
- const Standard_Boolean useUVParam = (aType == GeomAbs_Torus ||
- aType == GeomAbs_BezierSurface ||
- aType == GeomAbs_BSplineSurface);
-
- const Standard_Real umax = myAttribute->GetUMax();
- const Standard_Real umin = myAttribute->GetUMin();
- const Standard_Real vmax = myAttribute->GetVMax();
- const Standard_Real vmin = myAttribute->GetVMin();
-
- Standard_Boolean isaline =
- ((umax - umin) < Precision::PConfusion() ||
- (vmax - vmin) < Precision::PConfusion());
-
- Standard_Real aDef = -1;
- if ( !isaline && myStructure->ElementsOfDomain().Extent() > 0 )
- {
- if (!rajout)
- {
- // compute maximal deflection
- aDef = control(trigu, Standard_True);
- rajout = (aDef > myAttribute->GetDefFace() || aDef < 0.);
- }
- if (aType != GeomAbs_Plane)
- {
- if (!rajout && useUVParam)
- {
- rajout = (myVParam.Extent() > 2 &&
- (aSurface->IsUClosed() || aSurface->IsVClosed()));
- }
-
- if (rajout)
- {
- insertInternalVertices(trigu);
-
- //control internal points
- if (myIsControlSurfaceDeflection)
- aDef = control(trigu, Standard_False);
- }
- }
- }
-
- //modify myStructure back
- BRepMesh::HVectorOfVertex& aMeshNodes = myStructure->Data()->ChangeVertices();
- for ( Standard_Integer i = 1; i <= myStructure->NbNodes(); ++i )
- {
- BRepMesh_Vertex& aNode = aMeshNodes->ChangeValue(i - 1);
- aNode.ChangeCoord() = myAttribute->Scale(aNode.Coord(), Standard_False);
-
- const BRepMesh::ListOfInteger& alist = myStructure->LinksConnectedTo(i);
- // Register internal nodes used in triangulation
- if (!alist.IsEmpty() && aVertexEdgeMap->FindIndex(i) == 0)
- aVertexEdgeMap->Add(i);
- }
-
- if (!(aDef < 0.))
- myAttribute->SetDefFace(aDef);
-}
-
-//=======================================================================
-//function : addVerticesToMesh
-//purpose :
-//=======================================================================
-Standard_Boolean BRepMesh_FastDiscretFace::addVerticesToMesh(
- const BRepMesh::ListOfVertex& theVertices,
- BRepMesh_Delaun& theMeshBuilder)
-{
- if (theVertices.IsEmpty())
- return Standard_False;
-
- BRepMesh::Array1OfVertexOfDelaun aArrayOfNewVertices(1, theVertices.Extent());
- BRepMesh::ListOfVertex::Iterator aVertexIt(theVertices);
- for (Standard_Integer aVertexId = 0; aVertexIt.More(); aVertexIt.Next())
- aArrayOfNewVertices(++aVertexId) = aVertexIt.Value();
-
- theMeshBuilder.AddVertices(aArrayOfNewVertices);
- return Standard_True;
-}
-
-//=======================================================================
-//function : filterParameters
-//purpose :
-//=======================================================================
-static void filterParameters(const BRepMesh::IMapOfReal& theParams,
- const Standard_Real theMinDist,
- const Standard_Real theFilterDist,
- BRepMesh::SequenceOfReal& theResult)
-{
- // Sort sequence of parameters
- const Standard_Integer anInitLen = theParams.Extent();
-
- TColStd_Array1OfReal aParamArray(1, anInitLen);
- Standard_Integer j;
- for (j = 1; j <= anInitLen; j++)
- aParamArray(j) = theParams(j);
-
- std::sort (aParamArray.begin(), aParamArray.end());
-
- // mandatory pre-filtering using the first (minimal) filter value
- Standard_Integer aParamLength = 1;
- for (j = 2; j <= anInitLen; j++)
- {
- if ((aParamArray(j)-aParamArray(aParamLength)) > theMinDist)
- {
- if (++aParamLength < j)
- aParamArray(aParamLength) = aParamArray(j);
- }
- }
-
- //perform filtering on series
- Standard_Real aLastAdded, aLastCandidate;
- Standard_Boolean isCandidateDefined = Standard_False;
- aLastAdded = aParamArray(1);
- aLastCandidate = aLastAdded;
- theResult.Append(aLastAdded);
-
- for(j=2; j < aParamLength; j++)
- {
- Standard_Real aVal = aParamArray(j);
- if(aVal-aLastAdded > theFilterDist)
- {
- //adds the parameter
- if(isCandidateDefined) {
- aLastAdded = aLastCandidate;
- isCandidateDefined = Standard_False;
- j--;
- }
- else
- {
- aLastAdded = aVal;
- }
- theResult.Append(aLastAdded);
- continue;
- }
-
- aLastCandidate = aVal;
- isCandidateDefined = Standard_True;
- }
- theResult.Append(aParamArray(aParamLength));
-}
-
-//=======================================================================
-//function : insertInternalVertices
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::insertInternalVertices(BRepMesh_Delaun& theMeshBuilder)
-{
- Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
- BRepMesh::ListOfVertex aNewVertices(anAlloc);
- const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
- switch (gFace->GetType())
- {
- case GeomAbs_Sphere:
- insertInternalVerticesSphere(aNewVertices);
- break;
-
- case GeomAbs_Cylinder:
- insertInternalVerticesCylinder(aNewVertices);
- break;
-
- case GeomAbs_Cone:
- insertInternalVerticesCone(aNewVertices);
- break;
-
- case GeomAbs_Torus:
- insertInternalVerticesTorus(aNewVertices);
- break;
-
- default:
- insertInternalVerticesOther(aNewVertices);
- break;
- }
-
- addVerticesToMesh(aNewVertices, theMeshBuilder);
-}
-
-//=======================================================================
-//function : insertInternalVerticesSphere
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::insertInternalVerticesSphere(
- BRepMesh::ListOfVertex& theNewVertices)
-{
- Standard_Real aRange[] = {
- myAttribute->GetVMin(), myAttribute->GetVMax(),
- myAttribute->GetUMin(), myAttribute->GetUMax()
- };
-
- gp_Sphere aSphere = myAttribute->Surface()->Sphere();
-
- // Calculate parameters for iteration in V direction
- Standard_Real aStep = 0.7 * GCPnts_TangentialDeflection::ArcAngularStep(
- aSphere.Radius(), myAttribute->GetDefFace(), myAngle, myMinSize);
-
- Standard_Real aDd[2] = {aStep, aStep};
- Standard_Real aPasMax[2] = {0., 0.};
- for (Standard_Integer i = 0; i < 2; ++i)
- {
- const Standard_Real aMax = aRange[2 * i + 1];
- const Standard_Real aDiff = aMax - aRange[2 * i + 0];
- aDd[i] = aDiff / ((Standard_Integer)(aDiff / aDd[i]) + 1);
- aPasMax[i] = aMax - Precision::PConfusion();
- }
-
- const Standard_Real aHalfDu = aDd[1] * 0.5;
- Standard_Boolean Shift = Standard_False;
- Standard_Real aPasV = aRange[0] + aDd[0];
- for (; aPasV < aPasMax[0]; aPasV += aDd[0])
- {
- Shift = !Shift;
- const Standard_Real d = (Shift) ? aHalfDu : 0.;
- Standard_Real aPasU = aRange[2] + d;
- for (; aPasU < aPasMax[1]; aPasU += aDd[1])
- {
- tryToInsertAnalyticVertex(gp_Pnt2d(aPasU, aPasV), aSphere, theNewVertices);
- }
- }
-}
-
-//=======================================================================
-//function : insertInternalVerticesCylinder
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::insertInternalVerticesCylinder(
- BRepMesh::ListOfVertex& theNewVertices)
-{
- const Standard_Real umax = myAttribute->GetUMax();
- const Standard_Real umin = myAttribute->GetUMin();
- const Standard_Real vmax = myAttribute->GetVMax();
- const Standard_Real vmin = myAttribute->GetVMin();
-
- gp_Cylinder aCylinder = myAttribute->Surface()->Cylinder();
- const Standard_Real aRadius = aCylinder.Radius();
-
- Standard_Integer nbU = 0;
- Standard_Integer nbV = 0;
- const Standard_Real su = umax - umin;
- const Standard_Real sv = vmax - vmin;
- const Standard_Real aArcLen = su * aRadius;
- if (aArcLen > myAttribute->GetDefFace ())
- {
- // Calculate parameters for iteration in U direction
- const Standard_Real Du = GCPnts_TangentialDeflection::ArcAngularStep (
- aRadius, myAttribute->GetDefFace (), myAngle, myMinSize);
- nbU = (Standard_Integer)(su / Du);
-
- // Calculate parameters for iteration in V direction
- const Standard_Real aDv = nbU*sv / aArcLen;
- // Protection against overflow during casting to int in case
- // of long cylinder with small radius.
- nbV = aDv > static_cast<Standard_Real> (IntegerLast ()) ?
- 0 : (Standard_Integer)(aDv);
- nbV = Min (nbV, 100 * nbU);
- }
-
- const Standard_Real Du = su / (nbU + 1);
- const Standard_Real Dv = sv / (nbV + 1);
-
- Standard_Real pasu, pasv, pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5;
- for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
- {
- for (pasu = umin + Du; pasu < pasumax; pasu += Du)
- {
- tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), aCylinder, theNewVertices);
- }
- }
-}
-
-//=======================================================================
-//function : insertInternalVerticesCone
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::insertInternalVerticesCone(
- BRepMesh::ListOfVertex& theNewVertices)
-{
- const Standard_Real umax = myAttribute->GetUMax();
- const Standard_Real umin = myAttribute->GetUMin();
- const Standard_Real vmax = myAttribute->GetVMax();
- const Standard_Real vmin = myAttribute->GetVMin();
-
- gp_Cone aCone = myAttribute->Surface()->Cone();
- Standard_Real RefR = aCone.RefRadius();
- Standard_Real SAng = aCone.SemiAngle();
- Standard_Real aRadius = Max(Abs(RefR + vmin*Sin(SAng)), Abs(RefR + vmax*Sin(SAng)));
-
- Standard_Real Du = GCPnts_TangentialDeflection::ArcAngularStep(
- aRadius, myAttribute->GetDefFace(), myAngle, myMinSize);
-
- Standard_Real Dv, pasu, pasv;
- Standard_Integer nbU = (Standard_Integer)((umax - umin) / Du);
- Standard_Integer nbV = (Standard_Integer)(nbU*(vmax - vmin) / ((umax - umin)*aRadius));
- Du = (umax - umin) / (nbU + 1);
- Dv = (vmax - vmin) / (nbV + 1);
-
- Standard_Real pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5;
- for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
- {
- for (pasu = umin + Du; pasu < pasumax; pasu += Du)
- {
- tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), aCone, theNewVertices);
- }
- }
-}
-
-//=======================================================================
-//function : insertInternalVerticesTorus
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::insertInternalVerticesTorus(
- BRepMesh::ListOfVertex& theNewVertices)
-{
- const Standard_Real umax = myAttribute->GetUMax();
- const Standard_Real umin = myAttribute->GetUMin();
- const Standard_Real vmax = myAttribute->GetVMax();
- const Standard_Real vmin = myAttribute->GetVMin();
- const Standard_Real deltaX = myAttribute->GetDeltaX();
- const Standard_Real deltaY = myAttribute->GetDeltaY();
- const Standard_Real aDefFace = myAttribute->GetDefFace();
-
- gp_Torus T = myAttribute->Surface()->Torus();
-
- Standard_Boolean insert;
- Standard_Integer i, j, ParamULength, ParamVLength;
- Standard_Real pp, pasu, pasv;
- Standard_Real r = T.MinorRadius(), R = T.MajorRadius();
-
- BRepMesh::SequenceOfReal ParamU, ParamV;
-
- Standard_Real oldDv = GCPnts_TangentialDeflection::ArcAngularStep(
- r, aDefFace, myAngle, myMinSize);
-
- Standard_Real Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
- Dv = oldDv;
-
- Standard_Real Du;
- Standard_Integer nbV = Max((Standard_Integer)((vmax - vmin) / Dv), 2);
- Dv = (vmax - vmin) / (nbV + 1);
- Standard_Real ru = R + r;
- if (ru > 1.e-16)
- {
- Du = GCPnts_TangentialDeflection::ArcAngularStep(
- ru, aDefFace, myAngle, myMinSize);
-
- Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
- if (aa < gp::Resolution())
- return;
- Du *= Min(oldDv, Du) / aa;
- }
- else Du = Dv;
-
- Standard_Integer nbU = Max((Standard_Integer)((umax - umin) / Du), 2);
- nbU = Max(nbU, (int)(nbV*(umax - umin)*R / ((vmax - vmin)*r) / 5.));
- Du = (umax - umin) / (nbU + 1);
-
- if (R < r)
- {
- // As the points of edges are returned.
- // in this case, the points are not representative.
-
- //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid
- for (i = 0; i <= nbU; i++) ParamU.Append(umin + i* Du);
- }//R<r
- else //U if R > r
- {
- //--ofv: U
- // Number of mapped U parameters
- const Standard_Integer LenU = myUParam.Extent();
- // Fill array of U parameters
- TColStd_Array1OfReal Up(1, LenU);
- for (j = 1; j <= LenU; j++) Up(j) = myUParam(j);
-
- // Calculate DU, leave array of parameters
- Standard_Real aDU = FUN_CalcAverageDUV(Up, LenU);
- aDU = Max(aDU, Abs(umax - umin) / (Standard_Real)nbU / 2.);
- Standard_Real dUstd = Abs(umax - umin) / (Standard_Real)LenU;
- if (aDU > dUstd) dUstd = aDU;
- // Add U parameters
- for (j = 1; j <= LenU; j++)
- {
- pp = Up(j);
- insert = Standard_True;
- ParamULength = ParamU.Length();
- for (i = 1; i <= ParamULength && insert; i++)
- {
- insert = (Abs(ParamU.Value(i) - pp) > (0.5*dUstd));
- }
- if (insert) ParamU.Append(pp);
- }
- }
-
- //--ofv: V
- // Number of mapped V parameters
- const Standard_Integer LenV = myVParam.Extent();
- // Fill array of V parameters
- TColStd_Array1OfReal Vp(1, LenV);
- for (j = 1; j <= LenV; j++) Vp(j) = myVParam(j);
- // Calculate DV, sort array of parameters
- Standard_Real aDV = FUN_CalcAverageDUV(Vp, LenV);
- aDV = Max(aDV, Abs(vmax - vmin) / (Standard_Real)nbV / 2.);
-
- Standard_Real dVstd = Abs(vmax - vmin) / (Standard_Real)LenV;
- if (aDV > dVstd) dVstd = aDV;
- // Add V parameters
- for (j = 1; j <= LenV; j++)
- {
- pp = Vp(j);
-
- insert = Standard_True;
- ParamVLength = ParamV.Length();
- for (i = 1; i <= ParamVLength && insert; i++)
- {
- insert = (Abs(ParamV.Value(i) - pp) > (dVstd*2. / 3.));
- }
- if (insert) ParamV.Append(pp);
- }
-
- Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length();
- Standard_Real uminnew = umin + deltaY*0.1;
- Standard_Real vminnew = vmin + deltaX*0.1;
- Standard_Real umaxnew = umax - deltaY*0.1;
- Standard_Real vmaxnew = vmax - deltaX*0.1;
-
- for (i = 1; i <= Lu; i++)
- {
- pasu = ParamU.Value(i);
- if (pasu >= uminnew && pasu < umaxnew)
- {
- for (j = 1; j <= Lv; j++)
- {
- pasv = ParamV.Value(j);
- if (pasv >= vminnew && pasv < vmaxnew)
- {
- tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), T, theNewVertices);
- }
- }
- }
- }
-}
-
-//=======================================================================
-//function : insertInternalVerticesOther
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::insertInternalVerticesOther(
- BRepMesh::ListOfVertex& theNewVertices)
-{
- const Standard_Real aRange[2][2] = {
- { myAttribute->GetUMax(), myAttribute->GetUMin() },
- { myAttribute->GetVMax(), myAttribute->GetVMin() }
- };
-
- const Standard_Real aDelta[2] = {
- myAttribute->GetDeltaX(),
- myAttribute->GetDeltaY()
- };
-
- const Standard_Real aDefFace = myAttribute->GetDefFace();
- const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
-
- Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
- BRepMesh::SequenceOfReal aParams[2] = { BRepMesh::SequenceOfReal(anAlloc),
- BRepMesh::SequenceOfReal(anAlloc) };
- for (Standard_Integer i = 0; i < 2; ++i)
- {
- Standard_Boolean isU = (i == 0);
- Standard_Real aRes = isU ?
- gFace->UResolution(aDefFace) :
- gFace->VResolution(aDefFace);
-
- // Sort and filter sequence of parameters
- Standard_Real aMinDiff = Precision::PConfusion();
- if (aDelta[i] < 1.)
- aMinDiff /= aDelta[i];
-
- aMinDiff = Max(myMinSize, aMinDiff);
-
- Standard_Real aRangeDiff = aRange[i][0] - aRange[i][1];
- Standard_Real aDiffMaxLim = 0.1 * aRangeDiff;
- Standard_Real aDiffMinLim = Max(0.005 * aRangeDiff, 2. * aRes);
- Standard_Real aDiff = Max(myMinSize, Min(aDiffMaxLim, aDiffMinLim));
- filterParameters(isU ? myUParam : myVParam, aMinDiff, aDiff, aParams[i]);
- }
-
- // check intermediate isolines
- Handle (Geom_Surface) aSurface = gFace->ChangeSurface ().Surface ().Surface ();
-
- BRepMesh::MapOfReal aParamsToRemove[2] = { BRepMesh::MapOfReal(1, anAlloc),
- BRepMesh::MapOfReal(1, anAlloc) };
- BRepMesh::MapOfReal aParamsForbiddenToRemove[2] = { BRepMesh::MapOfReal(1, anAlloc),
- BRepMesh::MapOfReal(1, anAlloc) };
-
- // insert additional points where it is needed to conform criteria.
- // precision for normals calculation
- const Standard_Real aNormPrec = Precision::Confusion();
- for (Standard_Integer k = 0; k < 2; ++k)
- {
- const Standard_Integer aOtherIndex = (k + 1) % 2;
- BRepMesh::SequenceOfReal& aParams1 = aParams[k];
- BRepMesh::SequenceOfReal& aParams2 = aParams[aOtherIndex];
- const Standard_Boolean isU = (k == 0);
- for (Standard_Integer i = 2; i < aParams1.Length(); ++i)
- {
- const Standard_Real aParam1 = aParams1(i);
- GeomAdaptor_Curve aIso(isU ?
- aSurface->UIso(aParam1) : aSurface->VIso(aParam1));
-
- Standard_Real aPrevParam2 = aParams2(1);
- gp_Pnt aPrevPnt2;
- gp_Vec aPrevVec2;
- aIso.D1(aPrevParam2, aPrevPnt2, aPrevVec2);
- for (Standard_Integer j = 2; j <= aParams2.Length();)
- {
- Standard_Real aParam2 = aParams2(j);
- gp_Pnt aPnt2;
- gp_Vec aVec2;
- aIso.D1(aParam2, aPnt2, aVec2);
-
- Standard_Real aMidParam = 0.5 * (aPrevParam2 + aParam2);
- gp_Pnt aMidPnt = aIso.Value(aMidParam);
-
- Standard_Real aDist = deflectionOfSegment(aPrevPnt2, aPnt2, aMidPnt);
- if (aDist > aDefFace && aDist > myMinSize)
- {
- // insertion
- aParams2.InsertBefore(j, aMidParam);
- continue;
- }
- //put regular grig for normals
- gp_Pnt2d aStPnt1, aStPnt2;
- if (isU)
- {
- aStPnt1 = gp_Pnt2d(aParam1, aPrevParam2);
- aStPnt2 = gp_Pnt2d(aParam1, aMidParam);
- }
- else
- {
- aStPnt1 = gp_Pnt2d(aPrevParam2, aParam1);
- aStPnt2 = gp_Pnt2d(aMidParam, aParam1);
- }
-
- gp_Dir N1(0, 0, 1), N2(0, 0, 1);
- Standard_Integer aSt1 = GeomLib::NormEstim(aSurface, aStPnt1, aNormPrec, N1);
- Standard_Integer aSt2 = GeomLib::NormEstim(aSurface, aStPnt2, aNormPrec, N2);
-
- const Standard_Real aAngle = N2.Angle(N1);
- if (aSt1 < 1 && aSt2 < 1 && aAngle > myAngle)
- {
- const Standard_Real aLen = GCPnts_AbscissaPoint::Length(
- aIso, aPrevParam2, aMidParam, aDefFace);
-
- if (aLen > myMinSize)
- {
- // insertion
- aParams2.InsertBefore(j, aMidParam);
- continue;
- }
- }
- aPrevParam2 = aParam2;
- aPrevPnt2 = aPnt2;
- aPrevVec2 = aVec2;
-
- ++j;
- }
- }
- }
-#ifdef DEBUG_InsertInternal
- // output numbers of parameters along U and V
- cout << "aParams: " << aParams[0].Length() << " " << aParams[1].Length() << endl;
-#endif
- // try to reduce number of points evaluating of isolines sampling
- for (Standard_Integer k = 0; k < 2; ++k)
- {
- const Standard_Integer aOtherIndex = (k + 1) % 2;
- BRepMesh::SequenceOfReal& aParams1 = aParams[k];
- BRepMesh::SequenceOfReal& aParams2 = aParams[aOtherIndex];
- const Standard_Boolean isU = (k == 0);
- BRepMesh::MapOfReal& aToRemove2 = aParamsToRemove[aOtherIndex];
- BRepMesh::MapOfReal& aForbiddenToRemove1 = aParamsForbiddenToRemove[k];
- BRepMesh::MapOfReal& aForbiddenToRemove2 = aParamsForbiddenToRemove[aOtherIndex];
- for (Standard_Integer i = 2; i < aParams1.Length(); ++i)
- {
- const Standard_Real aParam1 = aParams1(i);
- GeomAdaptor_Curve aIso(isU ?
- aSurface->UIso (aParam1) : aSurface->VIso (aParam1));
-#ifdef DEBUG_InsertInternal
- // write polyline containing initial parameters to the file
- {
- ofstream ff(DEBUG_InsertInternal, std::ios_base::app);
- ff << "polyline " << (k == 0 ? "u" : "v") << i << " ";
- for (Standard_Integer j = 1; j <= aParams2.Length(); j++)
- {
- gp_Pnt aP;
- aIso.D0(aParams2(j), aP);
- ff << aP.X() << " " << aP.Y() << " " << aP.Z() << " ";
- }
- ff << endl;
- }
-#endif
-
- Standard_Real aPrevParam2 = aParams2(1);
- gp_Pnt aPrevPnt2;
- gp_Vec aPrevVec2;
- aIso.D1 (aPrevParam2, aPrevPnt2, aPrevVec2);
- for (Standard_Integer j = 2; j <= aParams2.Length();)
- {
- Standard_Real aParam2 = aParams2(j);
- gp_Pnt aPnt2;
- gp_Vec aVec2;
- aIso.D1 (aParam2, aPnt2, aVec2);
-
- // Here we should leave at least 3 parameters as far as
- // we must have at least one parameter related to surface
- // internals in order to prevent movement of triangle body
- // outside the surface in case of highly curved ones, e.g.
- // BSpline springs.
- if (aParams2.Length() > 3 && j < aParams2.Length())
- {
- // Remove too dense points
- const Standard_Real aNextParam = aParams2(j + 1);
- gp_Pnt aNextPnt;
- gp_Vec aNextVec;
- aIso.D1(aNextParam, aNextPnt, aNextVec);
-
- // Lets check current parameter.
- // If it fits deflection, we can remove it.
- Standard_Real aDist = deflectionOfSegment(aPrevPnt2, aNextPnt, aPnt2);
- if (aDist < aDefFace)
- {
- // Lets check parameters for angular deflection.
- if (aPrevVec2.SquareMagnitude() > gp::Resolution() &&
- aNextVec.SquareMagnitude() > gp::Resolution() &&
- aPrevVec2.Angle(aNextVec) < myAngle)
- {
- // For current Iso line we can remove this parameter.
-#ifdef DEBUG_InsertInternal
- // write point of removed parameter
- {
- ofstream ff(DEBUG_InsertInternal, std::ios_base::app);
- ff << "point " << (k == 0 ? "u" : "v") << i << "r_" << j << " "
- << aPnt2.X() << " " << aPnt2.Y() << " " << aPnt2.Z() << endl;
- }
-#endif
- aToRemove2.Add(aParam2);
- aPrevParam2 = aNextParam;
- aPrevPnt2 = aNextPnt;
- aPrevVec2 = aNextVec;
- j += 2;
- continue;
- }
- else {
- // We have found a place on the surface refusing
- // removement of this parameter.
-#ifdef DEBUG_InsertInternal
- // write point of forbidden to remove parameter
- {
- ofstream ff(DEBUG_InsertInternal, std::ios_base::app);
- ff << "vertex " << (k == 0 ? "u" : "v") << i << "f_" << j << " "
- << aPnt2.X() << " " << aPnt2.Y() << " " << aPnt2.Z() << endl;
- }
-#endif
- aForbiddenToRemove1.Add(aParam1);
- aForbiddenToRemove2.Add(aParam2);
- }
- }
- }
- aPrevParam2 = aParam2;
- aPrevPnt2 = aPnt2;
- aPrevVec2 = aVec2;
- ++j;
- }
- }
- }
- // remove filtered out parameters
- for (Standard_Integer k = 0; k < 2; ++k)
- {
- BRepMesh::SequenceOfReal& aParamsk = aParams[k];
- for (Standard_Integer i = 1; i <= aParamsk.Length();)
- {
- const Standard_Real aParam = aParamsk.Value(i);
- if (aParamsToRemove[k].Contains(aParam) &&
- !aParamsForbiddenToRemove[k].Contains(aParam))
- {
- aParamsk.Remove(i);
- }
- else
- i++;
- }
- }
-#ifdef DEBUG_InsertInternal
- // write polylines containing remaining parameters
- {
- ofstream ff(DEBUG_InsertInternal, std::ios_base::app);
- for (Standard_Integer k = 0; k < 2; ++k)
- {
- for (Standard_Integer i = 1; i <= aParams[k].Length(); i++)
- {
- ff << "polyline " << (k == 0 ? "uo" : "vo") << i << " ";
- for (Standard_Integer j = 1; j <= aParams[1 - k].Length(); j++)
- {
- gp_Pnt aP;
- if (k == 0)
- gFace->D0(aParams[k](i), aParams[1 - k](j), aP);
- else
- gFace->D0(aParams[1 - k](j), aParams[k](i), aP);
- ff << aP.X() << " " << aP.Y() << " " << aP.Z() << " ";
- }
- ff << endl;
- }
- }
- }
-#endif
-
- // insert nodes of the regular grid
- const BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier();
- for (Standard_Integer i = 1; i <= aParams[0].Length(); ++i)
- {
- const Standard_Real aParam1 = aParams[0].Value (i);
- for (Standard_Integer j = 1; j <= aParams[1].Length(); ++j)
- {
- const Standard_Real aParam2 = aParams[1].Value (j);
- gp_Pnt2d aPnt2d(aParam1, aParam2);
-
- // Classify intersection point
- if (aClassifier->Perform(aPnt2d) == TopAbs_IN)
- {
- gp_Pnt aPnt;
- gFace->D0(aPnt2d.X(), aPnt2d.Y(), aPnt);
- insertVertex(aPnt, aPnt2d.Coord(), theNewVertices);
- }
- }
- }
-}
-
-//=======================================================================
-//function : checkDeflectionAndInsert
-//purpose :
-//=======================================================================
-Standard_Boolean BRepMesh_FastDiscretFace::checkDeflectionAndInsert(
- const gp_Pnt& thePnt3d,
- const gp_XY& theUV,
- const Standard_Boolean isDeflectionCheckOnly,
- const Standard_Real theTriangleDeflection,
- const Standard_Real theFaceDeflection,
- const BRepMesh_CircleTool& theCircleTool,
- BRepMesh::ListOfVertex& theVertices,
- Standard_Real& theMaxTriangleDeflection,
- const Handle(NCollection_IncAllocator)& theTempAlloc)
-{
- if (theTriangleDeflection > theMaxTriangleDeflection)
- theMaxTriangleDeflection = theTriangleDeflection;
-
- if (theTriangleDeflection < theFaceDeflection)
- return Standard_True;
-
- if (myMinSize > Precision::Confusion())
- {
- // Iterator in the list of indexes of circles containing the node
- BRepMesh::ListOfInteger& aCirclesList =
- const_cast<BRepMesh_CircleTool&>(theCircleTool).Select(
- myAttribute->Scale(theUV, Standard_True));
-
- BRepMesh::MapOfInteger aUsedNodes(10, theTempAlloc);
- BRepMesh::ListOfInteger::Iterator aCircleIt(aCirclesList);
- for (; aCircleIt.More(); aCircleIt.Next())
- {
- const BRepMesh_Triangle& aTriangle =
- myStructure->GetElement(aCircleIt.Value());
-
- Standard_Integer aNodes[3];
- myStructure->ElementNodes(aTriangle, aNodes);
-
- for (Standard_Integer i = 0; i < 3; ++i)
- {
- const Standard_Integer aNodeId = aNodes[i];
- if (aUsedNodes.Contains(aNodeId))
- continue;
-
- aUsedNodes.Add(aNodeId);
- const BRepMesh_Vertex& aNode = myStructure->GetNode(aNodeId);
- const gp_Pnt& aPoint = myAttribute->GetPoint(aNode);
-
- if (thePnt3d.SquareDistance(aPoint) < myMinSize * myMinSize)
- return Standard_True;
- }
- }
- }
-
- if (isDeflectionCheckOnly)
- return Standard_False;
-
- insertVertex(thePnt3d, theUV, theVertices);
- return Standard_True;
-}
-
-//=======================================================================
-//function : control
-//purpose :
-//=======================================================================
-Standard_Real BRepMesh_FastDiscretFace::control(
- BRepMesh_Delaun& theTrigu,
- const Standard_Boolean theIsFirst)
-{
- Standard_Integer aTrianglesNb = myStructure->ElementsOfDomain().Extent();
- if (aTrianglesNb < 1)
- return -1.0;
-
- //IMPORTANT: Constants used in calculations
- const Standard_Real MinimalArea2d = 1.e-9;
- const Standard_Real MinimalSqLength3d = 1.e-12;
- const Standard_Real aSqDefFace = myAttribute->GetDefFace() * myAttribute->GetDefFace();
-
- const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
-
- Handle(Geom_Surface) aBSpline;
- const GeomAbs_SurfaceType aSurfType = gFace->GetType ();
- if (IsCompexSurface (aSurfType) && aSurfType != GeomAbs_SurfaceOfExtrusion)
- aBSpline = gFace->ChangeSurface ().Surface().Surface();
-
- Handle(NCollection_IncAllocator) anAlloc =
- new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
- NCollection_DataMap<Standard_Integer, gp_Dir> aNorMap(1, anAlloc);
- BRepMesh::MapOfIntegerInteger aStatMap(1, anAlloc);
- NCollection_Map<BRepMesh_Edge> aCouples(3 * aTrianglesNb, anAlloc);
- const BRepMesh_CircleTool& aCircles = theTrigu.Circles();
-
- // Perform refinement passes
- // Define the number of iterations
- Standard_Integer aIterationsNb = 11;
- const Standard_Integer aPassesNb = (theIsFirst ? 1 : aIterationsNb);
- // Initialize stop condition
- Standard_Real aMaxSqDef = -1.;
- Standard_Integer aPass = 1, aInsertedNb = 1;
- Standard_Boolean isAllDegenerated = Standard_False;
- Handle(NCollection_IncAllocator) aTempAlloc =
- new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
- for (; aPass <= aPassesNb && aInsertedNb && !isAllDegenerated; ++aPass)
- {
- aTempAlloc->Reset(Standard_False);
- BRepMesh::ListOfVertex aNewVertices(aTempAlloc);
-
- // Reset stop condition
- aInsertedNb = 0;
- aMaxSqDef = -1.;
- isAllDegenerated = Standard_True;
-
- aTrianglesNb = myStructure->ElementsOfDomain().Extent();
- if (aTrianglesNb < 1)
- break;
-
- // Iterate on current triangles
- const BRepMesh::MapOfInteger& aTriangles = myStructure->ElementsOfDomain();
- BRepMesh::MapOfInteger::Iterator aTriangleIt(aTriangles);
- for (; aTriangleIt.More(); aTriangleIt.Next())
- {
- const Standard_Integer aTriangleId = aTriangleIt.Key();
- const BRepMesh_Triangle& aCurrentTriangle = myStructure->GetElement(aTriangleId);
-
- if (aCurrentTriangle.Movability() == BRepMesh_Deleted)
- continue;
-
- Standard_Integer v[3];
- myStructure->ElementNodes(aCurrentTriangle, v);
-
- Standard_Integer e[3];
- Standard_Boolean o[3];
- aCurrentTriangle.Edges(e, o);
-
- gp_XY xy[3];
- gp_XYZ p[3];
- Standard_Boolean m[3];
- for (Standard_Integer i = 0; i < 3; ++i)
- {
- m[i] = (myStructure->GetLink(e[i]).Movability() == BRepMesh_Frontier);
-
- const BRepMesh_Vertex& aVertex = myStructure->GetNode(v[i]);
- xy[i] = myAttribute->Scale(aVertex.Coord(), Standard_False);
- p [i] = myAttribute->GetPoint(aVertex).Coord();
- }
-
- gp_XYZ aLinkVec[3];
- Standard_Boolean isDegeneratedTri = Standard_False;
- for (Standard_Integer i = 0; i < 3 && !isDegeneratedTri; ++i)
- {
- aLinkVec[i] = p[(i + 1) % 3] - p[i];
- isDegeneratedTri = (aLinkVec[i].SquareModulus() < MinimalSqLength3d);
- }
-
- if (isDegeneratedTri)
- continue;
-
- isAllDegenerated = Standard_False;
-
- // Check triangle area in 2d
- if (Abs((xy[1]-xy[0])^(xy[2]-xy[1])) < MinimalArea2d)
- continue;
-
- // Check triangle normal
- gp_Pnt pDef;
- Standard_Real aSqDef = -1.;
- Standard_Boolean isSkipped = Standard_False;
- gp_XYZ normal(aLinkVec[0] ^ aLinkVec[1]);
- if (normal.SquareModulus () < gp::Resolution())
- continue;
-
- normal.Normalize();
-
- // Check deflection at triangle centroid
- gp_XY aCenter2d = (xy[0] + xy[1] + xy[2]) / 3.0;
- gFace->D0(aCenter2d.X(), aCenter2d.Y(), pDef);
- aSqDef = Abs(normal * (pDef.XYZ() - p[0]));
- aSqDef *= aSqDef;
-
- isSkipped = !checkDeflectionAndInsert(pDef, aCenter2d, theIsFirst,
- aSqDef, aSqDefFace, aCircles, aNewVertices, aMaxSqDef, aTempAlloc);
-
- if (isSkipped)
- break;
-
- // Check deflection at triangle links
- for (Standard_Integer i = 0; i < 3 && !isSkipped; ++i)
- {
- if (m[i]) // is a boundary
- continue;
-
- // Check if this link was already processed
- if (aCouples.Add(myStructure->GetLink(e[i])))
- {
- // Check deflection on edge 1
- Standard_Integer j = (i + 1) % 3;
- gp_XY mi2d = (xy[i] + xy[j]) * 0.5;
- gFace->D0(mi2d.X(), mi2d.Y(), pDef);
- gp_Lin aLin(p[i], gp_Vec(p[i], p[j]));
- aSqDef = aLin.SquareDistance(pDef);
-
- isSkipped = !checkDeflectionAndInsert(pDef, mi2d, theIsFirst,
- aSqDef, aSqDefFace, aCircles, aNewVertices, aMaxSqDef, aTempAlloc);
- }
- }
-
- if (isSkipped)
- break;
-
- //check normal on bsplines
- if (theIsFirst && !aBSpline.IsNull())
- {
- gp_Dir N[3] = { gp::DZ(), gp::DZ(), gp::DZ() };
- Standard_Integer aSt[3];
-
- for (Standard_Integer i = 0; i < 3; ++i)
- {
- if (aNorMap.IsBound(v[i]))
- {
- aSt[i] = aStatMap.Find(v[i]);
- N[i] = aNorMap.Find(v[i]);
- }
- else
- {
- aSt[i] = GeomLib::NormEstim(aBSpline, gp_Pnt2d(xy[i]), Precision::Confusion(), N[i]);
- aStatMap.Bind(v[i], aSt[i]);
- aNorMap.Bind(v[i], N[i]);
- }
- }
-
- Standard_Real aAngle[3];
- for (Standard_Integer i = 0; i < 3; ++i)
- aAngle[i] = N[(i + 1) % 3].Angle(N[i]);
-
- if (aSt[0] < 1 && aSt[1] < 1 && aSt[2] < 1)
- {
- if (aAngle[0] > myAngle || aAngle[1] > myAngle || aAngle[2] > myAngle)
- {
- aMaxSqDef = -1.;
- break;
- }
- }
- }
- }
-
- if (theIsFirst)
- continue;
-
-#ifdef DEBUG_MESH
- // append to the file triangles in the form of polyline commands;
- // so the file can be sourced in draw to analyze triangles on each pass of the algorithm.
- // write triangles
- ofstream ftt(DEBUG_MESH, std::ios_base::app);
- Standard_Integer nbElem = myStructure->NbElements();
- for (Standard_Integer i = 1; i <= nbElem; i++)
- {
- const BRepMesh_Triangle& aTri = myStructure->GetElement(i);
- if (aTri.Movability() == BRepMesh_Deleted)
- continue;
- Standard_Integer n[3];
- myStructure->ElementNodes(aTri, n);
- const BRepMesh_Vertex& aV1 = myStructure->GetNode(n[0]);
- const BRepMesh_Vertex& aV2 = myStructure->GetNode(n[1]);
- const BRepMesh_Vertex& aV3 = myStructure->GetNode(n[2]);
- const gp_Pnt& aP1 = myAttribute->GetPoint(aV1);
- const gp_Pnt& aP2 = myAttribute->GetPoint(aV2);
- const gp_Pnt& aP3 = myAttribute->GetPoint(aV3);
- ftt << "polyline t" << aPass << "_" << i << " "
- << aP1.X() << " " << aP1.Y() << " " << aP1.Z() << " "
- << aP2.X() << " " << aP2.Y() << " " << aP2.Z() << " "
- << aP3.X() << " " << aP3.Y() << " " << aP3.Z() << " "
- << aP1.X() << " " << aP1.Y() << " " << aP1.Z() << endl;
- }
- // write points to insert on the current pass
- BRepMesh::ListOfVertex::Iterator it(aNewVertices);
- for (Standard_Integer i=1; it.More(); it.Next(), i++)
- {
- const BRepMesh_Vertex& aVertex = it.Value();
- const gp_Pnt& aP = myAttribute->GetPoint(aVertex);
- ftt << "vertex vt" << aPass << "_" << i << " "
- << aP.X() << " " << aP.Y() << " " << aP.Z() << endl;
- }
-#endif
-
- if (addVerticesToMesh(aNewVertices, theTrigu))
- ++aInsertedNb;
- }
-
- return (aMaxSqDef < 0) ? aMaxSqDef : Sqrt(aMaxSqDef);
-}
-
-//=======================================================================
-//function : add
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::add(const TopoDS_Vertex& theVertex)
-{
- if (theVertex.Orientation() != TopAbs_INTERNAL)
- return;
-
- try
- {
- OCC_CATCH_SIGNALS
-
- gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, myAttribute->Face());
- // check UV values for internal vertices
- if (myAttribute->ChangeClassifier()->Perform(aPnt2d) != TopAbs_IN)
- return;
-
- NCollection_Handle<FixedVExplorer> aFixedVExplorer = new FixedVExplorer(theVertex);
- Standard_Integer aIndex = myAttribute->GetVertexIndex(aFixedVExplorer);
- gp_XY anUV = BRepMesh_ShapeTool::FindUV(aIndex, aPnt2d,
- BRep_Tool::Tolerance(theVertex), myAttribute);
-
- Standard_Integer aTmpId1, aTmpId2;
- anUV = myAttribute->Scale(anUV, Standard_True);
- myAttribute->AddNode(aIndex, anUV, BRepMesh_Fixed, aTmpId1, aTmpId2);
- }
- catch (Standard_Failure)
- {
- }
-}
-
-//=======================================================================
-//function : insertVertex
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::insertVertex(
- const gp_Pnt& thePnt3d,
- const gp_XY& theUV,
- BRepMesh::ListOfVertex& theVertices)
-{
- Standard_Integer aNbLocat = myAttribute->LastPointId();
- myAttribute->ChangeSurfacePoints()->Bind(++aNbLocat, thePnt3d);
-
- gp_XY aPnt2d = myAttribute->Scale(theUV, Standard_True);
- BRepMesh_Vertex aVertex(aPnt2d, aNbLocat, BRepMesh_Free);
- theVertices.Append(aVertex);
-}
-
-//=======================================================================
-//function : commitSurfaceTriangulation
-//purpose :
-//=======================================================================
-void BRepMesh_FastDiscretFace::commitSurfaceTriangulation()
-{
- if (myAttribute.IsNull() || !myAttribute->IsValid())
- return;
-
- const TopoDS_Face& aFace = myAttribute->Face();
- BRepMesh_ShapeTool::NullifyFace(aFace);
-
- Handle(BRepMesh_DataStructureOfDelaun)& aStructure = myAttribute->ChangeStructure();
- const BRepMesh::MapOfInteger& aTriangles = aStructure->ElementsOfDomain();
-
- if (aTriangles.IsEmpty())
- {
- myAttribute->SetStatus(BRepMesh_Failure);
- return;
- }
-
- BRepMesh::HIMapOfInteger& aVetrexEdgeMap = myAttribute->ChangeVertexEdgeMap();
-
- // Store triangles
- Standard_Integer aVerticesNb = aVetrexEdgeMap->Extent();
- Standard_Integer aTrianglesNb = aTriangles.Extent();
- Handle(Poly_Triangulation) aNewTriangulation =
- new Poly_Triangulation(aVerticesNb, aTrianglesNb, Standard_True);
-
- Poly_Array1OfTriangle& aPolyTrianges = aNewTriangulation->ChangeTriangles();
-
- Standard_Integer aTriangeId = 1;
- BRepMesh::MapOfInteger::Iterator aTriIt(aTriangles);
- for (; aTriIt.More(); aTriIt.Next())
- {
- const BRepMesh_Triangle& aCurElem = aStructure->GetElement(aTriIt.Key());
-
- Standard_Integer aNode[3];
- aStructure->ElementNodes(aCurElem, aNode);
-
- Standard_Integer aNodeId[3];
- for (Standard_Integer i = 0; i < 3; ++i)
- aNodeId[i] = aVetrexEdgeMap->FindIndex(aNode[i]);
-
- aPolyTrianges(aTriangeId++).Set(aNodeId[0], aNodeId[1], aNodeId[2]);
- }
-
- // Store mesh nodes
- TColgp_Array1OfPnt& aNodes = aNewTriangulation->ChangeNodes();
- TColgp_Array1OfPnt2d& aNodes2d = aNewTriangulation->ChangeUVNodes();
-
- for (Standard_Integer i = 1; i <= aVerticesNb; ++i)
- {
- Standard_Integer aVertexId = aVetrexEdgeMap->FindKey(i);
- const BRepMesh_Vertex& aVertex = aStructure->GetNode(aVertexId);
- const gp_Pnt& aPoint = myAttribute->GetPoint(aVertex);
-
- aNodes(i) = aPoint;
- aNodes2d(i) = aVertex.Coord();
- }
-
- aNewTriangulation->Deflection(myAttribute->GetDefFace());
- BRepMesh_ShapeTool::AddInFace(aFace, aNewTriangulation);
-
- // Delete unused data
- myUParam.Clear(0L);
- myVParam.Clear(0L);
- myAttribute->ChangeStructure().Nullify();
- myAttribute->ChangeSurfacePoints().Nullify();
- myAttribute->ChangeSurfaceVertices().Nullify();
-
- myAttribute->ChangeClassifier().Nullify();
- myAttribute->ChangeLocation2D().Nullify();
- myAttribute->ChangeVertexEdgeMap().Nullify();
-}
+++ /dev/null
-// Copyright (c) 2013 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef _BRepMesh_FastDiscretFace_HeaderFile
-#define _BRepMesh_FastDiscretFace_HeaderFile
-
-#include <Standard.hxx>
-#include <Standard_Type.hxx>
-#include <BRepMesh_FastDiscretFace.hxx>
-#include <BRepMesh_DataStructureOfDelaun.hxx>
-#include <BRepMesh.hxx>
-#include <BRepMesh_FaceAttribute.hxx>
-#include <Standard_Transient.hxx>
-#include <TopTools_MutexForShapeProvider.hxx>
-#include <TopTools_DataMapOfShapeReal.hxx>
-#include <BRepMesh_Delaun.hxx>
-#include <BRepMesh_Triangle.hxx>
-#include <BRepMesh_Classifier.hxx>
-#include <ElSLib.hxx>
-
-class BRepMesh_DataStructureOfDelaun;
-class BRepMesh_FaceAttribute;
-class TopoDS_Face;
-class TopoDS_Vertex;
-class BRepAdaptor_HSurface;
-class TopoDS_Edge;
-class Poly_Triangulation;
-class TopLoc_Location;
-class gp_XY;
-class gp_Pnt2d;
-class BRepMesh_Edge;
-class BRepMesh_Vertex;
-class gp_Pnt;
-
-//! Algorithm to mesh a face with respect of the frontier
-//! the deflection and by option the shared components.
-class BRepMesh_FastDiscretFace : public Standard_Transient
-{
-public:
-
- //! Constructor.
- //! @param theAngle deviation angle to be used for surface tessellation.
- //! @param isInternalVerticesMode flag enabling/disabling internal
- //! vertices mode.
- //! @param isControlSurfaceDeflection enables/disables adaptive
- //! reconfiguration of mesh.
- Standard_EXPORT BRepMesh_FastDiscretFace(
- const Standard_Real theAngle,
- const Standard_Real theMinSize,
- const Standard_Boolean isInternalVerticesMode,
- const Standard_Boolean isControlSurfaceDeflection);
-
- Standard_EXPORT void Perform(const Handle(BRepMesh_FaceAttribute)& theAttribute);
-
- DEFINE_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace,Standard_Transient)
-
-private:
-
- void add(const Handle(BRepMesh_FaceAttribute)& theAttribute);
- void add(const TopoDS_Vertex& theVertex);
-
- Standard_Real control(BRepMesh_Delaun& theMeshBuilder,
- const Standard_Boolean theIsFirst);
-
- //! Registers the given nodes in mesh data structure and
- //! performs refinement of existing mesh.
- //! @param theVertices nodes to be inserted.
- //! @param theMeshBuilder initialized tool refining mesh
- //! in respect to inserting nodes.
- //! @return TRUE if vertices were been inserted, FALSE elewhere.
- Standard_Boolean addVerticesToMesh(
- const BRepMesh::ListOfVertex& theVertices,
- BRepMesh_Delaun& theMeshBuilder);
-
- //! Calculates nodes lying on face's surface and inserts them to a mesh.
- //! @param theMeshBuilder initialized tool refining mesh
- //! in respect to inserting nodes.
- void insertInternalVertices(BRepMesh_Delaun& theMeshBuilder);
-
- //! Calculates nodes lying on spherical surface.
- //! @param theNewVertices list of vertices to be extended and added to mesh.
- void insertInternalVerticesSphere(BRepMesh::ListOfVertex& theNewVertices);
-
- //! Calculates nodes lying on cylindrical surface.
- //! @param theNewVertices list of vertices to be extended and added to mesh.
- void insertInternalVerticesCylinder(BRepMesh::ListOfVertex& theNewVertices);
-
- //! Calculates nodes lying on conical surface.
- //! @param theNewVertices list of vertices to be extended and added to mesh.
- void insertInternalVerticesCone(BRepMesh::ListOfVertex& theNewVertices);
-
- //! Calculates nodes lying on toroidal surface.
- //! @param theNewVertices list of vertices to be extended and added to mesh.
- void insertInternalVerticesTorus(BRepMesh::ListOfVertex& theNewVertices);
-
- //! Calculates nodes lying on custom-type surface.
- //! @param theNewVertices list of vertices to be extended and added to mesh.
- void insertInternalVerticesOther(BRepMesh::ListOfVertex& theNewVertices);
-
- //! Template method trying to insert new internal vertex corresponded to
- //! the given 2d point. Calculates 3d position analytically using the given
- //! surface.
- //! @param thePnt2d 2d point to be inserted to the list.
- //! @param theAnalyticSurface analytic surface to calculate 3d point.
- //! @param[out] theVertices list of vertices to be updated.
- template<class AnalyticSurface>
- void tryToInsertAnalyticVertex(const gp_Pnt2d& thePnt2d,
- const AnalyticSurface& theAnalyticSurface,
- BRepMesh::ListOfVertex& theVertices)
- {
- const BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier();
- if (aClassifier->Perform(thePnt2d) != TopAbs_IN)
- return;
-
- gp_Pnt aPnt;
- ElSLib::D0(thePnt2d.X(), thePnt2d.Y(), theAnalyticSurface, aPnt);
- insertVertex(aPnt, thePnt2d.Coord(), theVertices);
- }
-
- //! Creates new vertex with the given parameters.
- //! @param thePnt3d 3d point corresponded to the vertex.
- //! @param theUV UV point corresponded to the vertex.
- //! @param[out] theVertices list of vertices to be updated.
- void insertVertex(const gp_Pnt& thePnt3d,
- const gp_XY& theUV,
- BRepMesh::ListOfVertex& theVertices);
-
- //! Stores mesh into the face (without internal edges).
- void commitSurfaceTriangulation();
-
- //! Performs initialization of data structure using existing data.
- void initDataStructure();
-
- //! Adds new link to the mesh data structure.
- //! Movability of the link and order of nodes depend on orientation parameter.
- void addLinkToMesh(const Standard_Integer theFirstNodeId,
- const Standard_Integer theLastNodeId,
- const TopAbs_Orientation theOrientation);
-
- //! Inserts new node into a mesh in case if smoothed region build
- //! using the given node has better deflection metrics than source state.
- //! @param thePnt3d 3d point corresponded to the vertex.
- //! @param theUV UV point corresponded to the vertex.
- //! @param isDeflectionCheckOnly if TRUE new node will not be added to a mesh
- //! even if deflection parameter is better.
- //! @param theTriangleDeflection deflection of a triangle from real geometry.
- //! @param theFaceDeflection deflection to be achieved.
- //! @param theCircleTool tool used for fast extraction of triangles
- //! touched by the given point.
- //! @param[out] theVertices list of vertices to be updated.
- //! @param[in out] theMaxTriangleDeflection maximal deflection of a mesh.
- //! @return TRUE in case if the given deflection of triangle is fine and
- //! there is no necessity to insert new node or new node was being inserted
- //! successfully, FALSE in case if new configuration is better but
- //! isDeflectionCheckOnly flag is set.
- Standard_Boolean checkDeflectionAndInsert(
- const gp_Pnt& thePnt3d,
- const gp_XY& theUV,
- const Standard_Boolean isDeflectionCheckOnly,
- const Standard_Real theTriangleDeflection,
- const Standard_Real theFaceDeflection,
- const BRepMesh_CircleTool& theCircleTool,
- BRepMesh::ListOfVertex& theVertices,
- Standard_Real& theMaxTriangleDeflection,
- const Handle(NCollection_IncAllocator)& theTempAlloc);
-
-private:
-
- Standard_Real myAngle;
- Standard_Boolean myInternalVerticesMode;
- BRepMesh::IMapOfReal myUParam;
- BRepMesh::IMapOfReal myVParam;
-
- // Fast access to attributes of current face
- Handle(BRepMesh_FaceAttribute) myAttribute;
- Handle(BRepMesh_DataStructureOfDelaun) myStructure;
-
- Standard_Real myMinSize;
- Standard_Boolean myIsControlSurfaceDeflection;
-};
-
-DEFINE_STANDARD_HANDLE (BRepMesh_FastDiscretFace, Standard_Transient)
-
-#endif
#include <BRepMesh_GeomTool.hxx>
+#include <BRepMesh_DefaultRangeSplitter.hxx>
+
#include <TopAbs_Orientation.hxx>
#include <CSLib.hxx>
#include <Precision.hxx>
#include <Adaptor3d_IsoCurve.hxx>
+#include <Adaptor3d_HCurve.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <Geom2d_Curve.hxx>
#include <BRep_Tool.hxx>
+namespace
+{
+ void ComputeErrFactors (const Standard_Real theDeflection,
+ const Handle(Adaptor3d_HSurface)& theFace,
+ Standard_Real& theErrFactorU,
+ Standard_Real& theErrFactorV)
+ {
+ theErrFactorU = theDeflection * 10.;
+ theErrFactorV = theDeflection * 10.;
+
+ switch (theFace->GetType ())
+ {
+ case GeomAbs_Cylinder:
+ case GeomAbs_Cone:
+ case GeomAbs_Sphere:
+ case GeomAbs_Torus:
+ break;
+
+ case GeomAbs_SurfaceOfExtrusion:
+ case GeomAbs_SurfaceOfRevolution:
+ {
+ Handle(Adaptor3d_HCurve) aCurve = theFace->BasisCurve ();
+ if (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () > 2)
+ {
+ theErrFactorV /= (aCurve->Degree () * aCurve->NbKnots ());
+ }
+ break;
+ }
+ case GeomAbs_BezierSurface:
+ {
+ if (theFace->UDegree () > 2)
+ {
+ theErrFactorU /= (theFace->UDegree ());
+ }
+ if (theFace->VDegree () > 2)
+ {
+ theErrFactorV /= (theFace->VDegree ());
+ }
+ break;
+ }
+ case GeomAbs_BSplineSurface:
+ {
+ if (theFace->UDegree () > 2)
+ {
+ theErrFactorU /= (theFace->UDegree () * theFace->NbUKnots ());
+ }
+ if (theFace->VDegree () > 2)
+ {
+ theErrFactorV /= (theFace->VDegree () * theFace->NbVKnots ());
+ }
+ break;
+ }
+
+ case GeomAbs_Plane:
+ default:
+ theErrFactorU = theErrFactorV = 1.;
+ }
+ }
+
+ void AdjustCellsCounts (const Handle(Adaptor3d_HSurface)& theFace,
+ const Standard_Integer theNbVertices,
+ Standard_Integer& theCellsCountU,
+ Standard_Integer& theCellsCountV)
+ {
+ const GeomAbs_SurfaceType aType = theFace->GetType ();
+ if (aType == GeomAbs_OtherSurface)
+ {
+ // fallback to the default behavior
+ theCellsCountU = theCellsCountV = -1;
+ return;
+ }
+
+ Standard_Real aSqNbVert = theNbVertices;
+ if (aType == GeomAbs_Plane)
+ {
+ theCellsCountU = theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ else if (aType == GeomAbs_Cylinder || aType == GeomAbs_Cone)
+ {
+ theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ else if (aType == GeomAbs_SurfaceOfExtrusion || aType == GeomAbs_SurfaceOfRevolution)
+ {
+ Handle (Adaptor3d_HCurve) aCurve = theFace->BasisCurve ();
+ if (aCurve->GetType () == GeomAbs_Line ||
+ (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () < 2))
+ {
+ // planar, cylindrical, conical cases
+ if (aType == GeomAbs_SurfaceOfExtrusion)
+ theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ else
+ theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ if (aType == GeomAbs_SurfaceOfExtrusion)
+ {
+ // V is always a line
+ theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ }
+ else if (aType == GeomAbs_BezierSurface || aType == GeomAbs_BSplineSurface)
+ {
+ if (theFace->UDegree () < 2)
+ {
+ theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ if (theFace->VDegree () < 2)
+ {
+ theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
+ }
+ }
+
+ theCellsCountU = Max (theCellsCountU, 2);
+ theCellsCountV = Max (theCellsCountV, 2);
+ }
+}
+
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_GeomTool::Value(
const Standard_Integer theIndex,
+ const Handle(BRepAdaptor_HSurface)& theSurface,
Standard_Real& theParam,
- gp_Pnt& thePoint) const
+ gp_Pnt& thePoint,
+ gp_Pnt2d& theUV) const
{
if (theIndex < 1 || theIndex > NbPoints())
return Standard_False;
thePoint = myDiscretTool.Value(theIndex);
theParam = myDiscretTool.Parameter(theIndex);
+ const TopoDS_Face& aFace = ((BRepAdaptor_Surface*)&(theSurface->Surface()))->Face();
+
+ Standard_Real aFirst, aLast;
+ Handle(Geom2d_Curve) aCurve =
+ BRep_Tool::CurveOnSurface(*myEdge, aFace, aFirst, aLast);
+
+ aCurve->D0(theParam, theUV);
+
return Standard_True;
}
//function : Value
//purpose :
//=======================================================================
-Standard_Boolean BRepMesh_GeomTool::Value(const Standard_Integer theIndex,
- const Standard_Real theIsoParam,
- Standard_Real& theParam,
- gp_Pnt& thePoint,
- gp_Pnt2d& theUV) const
+Standard_Boolean BRepMesh_GeomTool::Value(
+ const Standard_Integer theIndex,
+ const Standard_Real theIsoParam,
+ Standard_Real& theParam,
+ gp_Pnt& thePoint,
+ gp_Pnt2d& theUV) const
{
if (theIndex < 1 || theIndex > NbPoints())
return Standard_False;
const Standard_Real aEndPrec = 1 - aPrec;
for (Standard_Integer i = 0; i < 2; ++i)
{
- if( aParam[i] < aPrec || aParam[i] > aEndPrec )
+ if(aParam[i] < aPrec || aParam[i] > aEndPrec )
return BRepMesh_GeomTool::NoIntersection;
}
return BRepMesh_GeomTool::Cross;
}
+//=============================================================================
+//function : CellsCount
+//purpose :
+//=============================================================================
+std::pair<Standard_Integer, Standard_Integer> BRepMesh_GeomTool::CellsCount (
+ const Handle (Adaptor3d_HSurface)& theSurface,
+ const Standard_Integer theVerticesNb,
+ const Standard_Real theDeflection,
+ const BRepMesh_DefaultRangeSplitter* theRangeSplitter)
+{
+ if (theRangeSplitter == NULL)
+ return std::pair<Standard_Integer, Standard_Integer>(-1, -1);
+
+ const GeomAbs_SurfaceType aType = theSurface->GetType ();
+
+ Standard_Real anErrFactorU, anErrFactorV;
+ ComputeErrFactors(theDeflection, theSurface, anErrFactorU, anErrFactorV);
+
+ const std::pair<Standard_Real, Standard_Real>& aRangeU = theRangeSplitter->GetRangeU();
+ const std::pair<Standard_Real, Standard_Real>& aRangeV = theRangeSplitter->GetRangeV();
+ const std::pair<Standard_Real, Standard_Real>& aDelta = theRangeSplitter->GetDelta ();
+
+ Standard_Integer aCellsCountU, aCellsCountV;
+ if (aType == GeomAbs_Torus)
+ {
+ aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (aRangeU.second - aRangeU.first) / aDelta.first)));
+ aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (aRangeV.second - aRangeV.first) / aDelta.second)));
+ }
+ else if (aType == GeomAbs_Cylinder)
+ {
+ aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (aRangeU.second - aRangeU.first) / aDelta.first /
+ (aRangeV.second - aRangeV.first))));
+ aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (aRangeV.second - aRangeV.first) / anErrFactorV)));
+ }
+ else
+ {
+ aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (aRangeU.second - aRangeU.first) / aDelta.first / anErrFactorU)));
+ aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
+ (aRangeV.second - aRangeV.first) / aDelta.second / anErrFactorV)));
+ }
+
+ AdjustCellsCounts(theSurface, theVerticesNb, aCellsCountU, aCellsCountV);
+ return std::pair<Standard_Integer, Standard_Integer>(aCellsCountU, aCellsCountV);
+}
+
//=============================================================================
//function : classifyPoint
//purpose :
class gp_Pnt;
class gp_Pnt2d;
class gp_Dir;
+class BRepMesh_DefaultRangeSplitter;
+class Adaptor3d_HSurface;
//! Tool class accumulating common geometrical functions as well as
//! functionality using shape geometry to produce data necessary for
//! @param theLinDeflection linear deflection.
//! @param theAngDeflection angular deflection.
//! @param theMinPointsNb minimum nuber of points to be produced.
- Standard_EXPORT BRepMesh_GeomTool(const BRepAdaptor_Curve& theCurve,
- const Standard_Real theFirstParam,
- const Standard_Real theLastParam,
- const Standard_Real theLinDeflection,
- const Standard_Real theAngDeflection,
- const Standard_Integer theMinPointsNb = 2,
- const Standard_Real theMinSize = Precision::Confusion());
+ Standard_EXPORT BRepMesh_GeomTool(
+ const BRepAdaptor_Curve& theCurve,
+ const Standard_Real theFirstParam,
+ const Standard_Real theLastParam,
+ const Standard_Real theLinDeflection,
+ const Standard_Real theAngDeflection,
+ const Standard_Integer theMinPointsNb = 2,
+ const Standard_Real theMinSize = Precision::Confusion());
//! Constructor.
//! Initiates discretization of geometric curve corresponding
//! @param theLinDeflection linear deflection.
//! @param theAngDeflection angular deflection.
//! @param theMinPointsNb minimum nuber of points to be produced.
- Standard_EXPORT BRepMesh_GeomTool(const Handle(BRepAdaptor_HSurface)& theSurface,
- const GeomAbs_IsoType theIsoType,
- const Standard_Real theParamIso,
- const Standard_Real theFirstParam,
- const Standard_Real theLastParam,
- const Standard_Real theLinDeflection,
- const Standard_Real theAngDeflection,
- const Standard_Integer theMinPointsNb = 2,
- const Standard_Real theMinSize = Precision::Confusion());
+ Standard_EXPORT BRepMesh_GeomTool(
+ const Handle(BRepAdaptor_HSurface)& theSurface,
+ const GeomAbs_IsoType theIsoType,
+ const Standard_Real theParamIso,
+ const Standard_Real theFirstParam,
+ const Standard_Real theLastParam,
+ const Standard_Real theLinDeflection,
+ const Standard_Real theAngDeflection,
+ const Standard_Integer theMinPointsNb = 2,
+ const Standard_Real theMinSize = Precision::Confusion());
//! Adds point to already calculated points (or replaces existing).
//! @param thePoint point to be added.
//! Gets parameters of discretization point with the given index.
//! @param theIndex index of discretization point.
+ //! @param theSurface surface the curve is lying onto.
//! @param theParam[out] parameter of the point on the curve.
//! @param thePoint[out] discretization point.
+ //! @param theUV[out] discretization point in parametric space of the surface.
//! @return TRUE on success, FALSE elsewhere.
Standard_EXPORT Standard_Boolean Value(const Standard_Integer theIndex,
+ const Handle(BRepAdaptor_HSurface)& theSurface,
Standard_Real& theParam,
- gp_Pnt& thePoint) const;
+ gp_Pnt& thePoint,
+ gp_Pnt2d& theUV) const;
public: //! @name static API
const Standard_Boolean isConsiderPointOnSegment,
gp_Pnt2d& theIntPnt);
+ //! Compute deflection of the given segment.
+ static Standard_Real SquareDeflectionOfSegment(
+ const gp_Pnt& theFirstPoint,
+ const gp_Pnt& theLastPoint,
+ const gp_Pnt& theMidPoint)
+ {
+ // 23.03.2010 skl for OCC21645 - change precision for comparison
+ if (theFirstPoint.SquareDistance(theLastPoint) > Precision::SquareConfusion())
+ {
+ gp_Lin aLin(theFirstPoint, gp_Dir(gp_Vec(theFirstPoint, theLastPoint)));
+ return aLin.SquareDistance(theMidPoint);
+ }
+
+ return theFirstPoint.SquareDistance(theMidPoint);
+ }
+
+ // For better meshing performance we try to estimate the acceleration circles grid structure sizes:
+ // For each parametric direction (U, V) we estimate firstly an approximate distance between the future points -
+ // this estimation takes into account the required face deflection and the complexity of the face.
+ // Particularly, the complexity of the faces based on BSpline curves and surfaces requires much more points.
+ // At the same time, for planar faces and linear parts of the arbitrary surfaces usually no intermediate points
+ // are necessary.
+ // The general idea for each parametric direction:
+ // cells_count = 2 ^ log10 ( estimated_points_count )
+ // For linear parametric direction we fall back to the initial vertex count:
+ // cells_count = 2 ^ log10 ( initial_vertex_count )
+ Standard_EXPORT static std::pair<Standard_Integer, Standard_Integer> CellsCount (
+ const Handle (Adaptor3d_HSurface)& theSurface,
+ const Standard_Integer theVerticesNb,
+ const Standard_Real theDeflection,
+ const BRepMesh_DefaultRangeSplitter* theRangeSplitter);
+
private:
//! Classifies the point in case of coincidence of two vectors.
+++ /dev/null
-// Created on: 2014-08-13
-// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <BRepMesh_IEdgeTool.hxx>
-
-
-
-IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IEdgeTool,Standard_Transient)
\ No newline at end of file
+++ /dev/null
-// Created on: 2014-08-13
-// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef _BRepMesh_IEdgeTool_HeaderFile
-#define _BRepMesh_IEdgeTool_HeaderFile
-
-#include <Standard.hxx>
-#include <gp_Pnt.hxx>
-#include <gp_Pnt2d.hxx>
-#include <Standard_Transient.hxx>
-
-//! Interface class providing API for edge tessellation tools.
-class BRepMesh_IEdgeTool : public Standard_Transient
-{
-public:
- //! Returns number of tessellation points.
- virtual Standard_Integer NbPoints() const = 0;
-
- //! Returns parameters of solution with the given index.
- //! @param theIndex index of tessellation point.
- //! @param theParameter parameters on PCurve corresponded to the solution.
- //! @param thePoint tessellation point.
- //! @param theUV coordinates of tessellation point in parametric space of face.
- //! @return True in case of valid result, false elewhere.
- virtual Standard_Boolean Value(
- const Standard_Integer theIndex,
- Standard_Real& theParameter,
- gp_Pnt& thePoint,
- gp_Pnt2d& theUV) = 0;
-
- DEFINE_STANDARD_RTTIEXT(BRepMesh_IEdgeTool,Standard_Transient)
-};
-
-DEFINE_STANDARD_HANDLE(BRepMesh_IEdgeTool, Standard_Transient)
-
-#endif
--- /dev/null
+// Created on: 2016-06-20
+// Created by: Oleg AGASHIN
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_IncAllocator_HeaderFile
+#define _BRepMesh_IncAllocator_HeaderFile
+
+#include <NCollection_IncAllocator.hxx>
+#include <Standard_Mutex.hxx>
+
+//! Extension for NCollection_IncAllocator implementing simple thread safety
+//! by introduction of Mutex. Intended for use in couple with BRepMeshData
+//! entities in order to prevent data races while building data model in
+//! parallel mode. Note that this allocator is supposed for use by collections
+//! which allocate memory by huge blocks at arbitrary moment, thus it should
+//! not introduce significant performance slow down.
+class BRepMesh_IncAllocator : public NCollection_IncAllocator
+{
+public:
+ //! Constructor
+ BRepMesh_IncAllocator(const size_t theBlockSize = DefaultBlockSize)
+ : NCollection_IncAllocator(theBlockSize)
+ {
+ }
+
+ //! Allocate memory with given size. Returns NULL on failure
+ virtual void* Allocate(const size_t size) Standard_OVERRIDE
+ {
+ Standard_Mutex::Sentry aSentry(myMutex);
+ return NCollection_IncAllocator::Allocate(size);
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_IncAllocator, NCollection_IncAllocator)
+
+private:
+ Standard_Mutex myMutex;
+};
+
+#endif
// commercial license or contractual agreement.
#include <BRepMesh_IncrementalMesh.hxx>
-
-#include <OSD_Parallel.hxx>
-#include <Precision.hxx>
-#include <Standard_ErrorHandler.hxx>
-
-#include <BRepMesh_ShapeTool.hxx>
-#include <BRepMesh_Edge.hxx>
+#include <BRepMesh_Context.hxx>
#include <BRepMesh_PluginMacro.hxx>
-
-#include <Bnd_Box.hxx>
-#include <BRep_Builder.hxx>
-#include <BRep_Tool.hxx>
-#include <BRepTools.hxx>
-#include <BRepLib.hxx>
-#include <BRepBndLib.hxx>
-#include <BRepAdaptor_Curve.hxx>
-
-#include <Poly_Triangulation.hxx>
-#include <Poly_Polygon3D.hxx>
-#include <Poly_PolygonOnTriangulation.hxx>
-
-#include <TopoDS.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Face.hxx>
-#include <TopoDS_Shape.hxx>
-#include <TopAbs.hxx>
-#include <TopExp.hxx>
-#include <TopExp_Explorer.hxx>
-
-#include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <TColgp_Array1OfPnt.hxx>
-#include <TColgp_Array1OfPnt2d.hxx>
-#include <TColStd_Array1OfReal.hxx>
-#include <TColStd_MapOfTransient.hxx>
-#include <TopTools_HArray1OfShape.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
-
-#include <GCPnts_TangentialDeflection.hxx>
-
-IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
+#include <IMeshData_Status.hxx>
+#include <IMeshData_Face.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshTools_MeshBuilder.hxx>
namespace
{
static Standard_Boolean IS_IN_PARALLEL = Standard_False;
}
-
//=======================================================================
//function : Default constructor
//purpose :
//=======================================================================
BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh()
-: myMaxShapeSize(0.),
- myModified(Standard_False),
- myStatus(0)
+: myModified(Standard_False),
+ myStatus(IMeshData_NoError)
{
}
const Standard_Real theLinDeflection,
const Standard_Boolean isRelative,
const Standard_Real theAngDeflection,
- const Standard_Boolean isInParallel,
- const Standard_Boolean adaptiveMin)
-: myMaxShapeSize(0.),
- myModified(Standard_False),
- myStatus(0)
+ const Standard_Boolean isInParallel)
+: myModified(Standard_False),
+ myStatus(IMeshData_NoError)
{
myParameters.Deflection = theLinDeflection;
- myParameters.Relative = isRelative;
- myParameters.Angle = theAngDeflection;
+ myParameters.Angle = theAngDeflection;
+ myParameters.Relative = isRelative;
myParameters.InParallel = isInParallel;
- myParameters.AdaptiveMin = adaptiveMin;
myShape = theShape;
Perform();
//function : Constructor
//purpose :
//=======================================================================
-BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape,
- const BRepMesh_FastDiscret::Parameters& theParameters)
+BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(
+ const TopoDS_Shape& theShape,
+ const IMeshTools_Parameters& theParameters)
: myParameters(theParameters)
{
- myShape = theShape;
-
+ myShape = theShape;
Perform();
}
{
}
-//=======================================================================
-//function : clear
-//purpose :
-//=======================================================================
-void BRepMesh_IncrementalMesh::clear()
-{
- // the allocator will be alive while the structures are alive
- Handle(NCollection_BaseAllocator) anAlloc =
- new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
- myEdges.Clear(anAlloc);
- myEdgeDeflection.Clear(anAlloc);
- myFaces.Clear();
- myMesh.Nullify();
-}
-
-//=======================================================================
-//function : init
-//purpose :
-//=======================================================================
-void BRepMesh_IncrementalMesh::init()
-{
- myStatus = 0;
- myModified = Standard_False;
-
- setDone();
- clear();
-
- collectFaces();
-
- Bnd_Box aBox;
- if ( myParameters.Relative )
- {
- BRepBndLib::Add(myShape, aBox, Standard_False);
-
- if (aBox.IsVoid())
- {
- // Nothing to mesh.
- return;
- }
-
- BRepMesh_ShapeTool::BoxMaxDimension(aBox, myMaxShapeSize);
- }
-
- myMesh = new BRepMesh_FastDiscret (aBox, myParameters);
-
- myMesh->InitSharedFaces(myShape);
-}
-
-//=======================================================================
-//function : collectFaces
-//purpose :
-//=======================================================================
-void BRepMesh_IncrementalMesh::collectFaces()
-{
- Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
- TopTools_ListOfShape aFaceList(anAlloc);
- BRepLib::ReverseSortFaces(myShape, aFaceList);
- TColStd_MapOfTransient aTFaceMap(1, anAlloc);
-
- // make array of faces suitable for processing (excluding faces without surface)
- TopLoc_Location aDummyLoc;
- TopTools_ListIteratorOfListOfShape aFaceIter(aFaceList);
- for (; aFaceIter.More(); aFaceIter.Next())
- {
- const TopoDS_Face& aFace = TopoDS::Face(aFaceIter.Value());
- const Handle(TopoDS_TShape)& aTFace = aFace.TShape();
- if (!aTFaceMap.Add (aTFace))
- continue; // already processed
-
- const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aDummyLoc);
- if (aSurf.IsNull())
- continue;
-
- myFaces.Append(aFace);
- }
-}
-
//=======================================================================
//function : Perform
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::Perform()
{
- init();
-
- if (myMesh.IsNull())
- return;
-
- update();
-}
-
-//=======================================================================
-//function : update()
-//purpose :
-//=======================================================================
-void BRepMesh_IncrementalMesh::update()
-{
- // Update edges data
- TopExp_Explorer aExplorer(myShape, TopAbs_EDGE);
- for (; aExplorer.More(); aExplorer.Next())
- {
- const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
- if(!BRep_Tool::IsGeometric(aEdge))
- continue;
-
- update(aEdge);
- }
-
- // Update faces data
- NCollection_Vector<TopoDS_Face>::Iterator aFaceIt(myFaces);
- for (; aFaceIt.More(); aFaceIt.Next())
- update(aFaceIt.Value());
-
- // Mesh faces
- OSD_Parallel::ForEach(myFaces.begin(), myFaces.end(), *myMesh, !myParameters.InParallel, myFaces.Size());
-
- commit();
- clear();
-}
-
-//=======================================================================
-//function : discretizeFreeEdges
-//purpose :
-//=======================================================================
-void BRepMesh_IncrementalMesh::discretizeFreeEdges()
-{
- TopExp_Explorer aExplorer(myShape ,TopAbs_EDGE, TopAbs_FACE);
- for (; aExplorer.More(); aExplorer.Next())
- {
- const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
- if(!BRep_Tool::IsGeometric(aEdge))
- continue;
-
- TopLoc_Location aLoc;
- Standard_Real aEdgeDeflection = edgeDeflection(aEdge);
- Handle(Poly_Polygon3D) aPoly3D = BRep_Tool::Polygon3D(aEdge, aLoc);
- if (!aPoly3D.IsNull() && aPoly3D->Deflection() < 1.1 * aEdgeDeflection)
- continue;
-
- BRepAdaptor_Curve aCurve(aEdge);
- GCPnts_TangentialDeflection aDiscret(aCurve, aCurve.FirstParameter(),
- aCurve.LastParameter(), myParameters.Angle, aEdgeDeflection, 2,
- Precision::PConfusion(), myParameters.MinSize);
-
- Standard_Integer aNodesNb = aDiscret.NbPoints();
- TColgp_Array1OfPnt aNodes (1, aNodesNb);
- TColStd_Array1OfReal aUVNodes(1, aNodesNb);
- for (Standard_Integer i = 1; i <= aNodesNb; ++i)
- {
- aNodes (i) = aDiscret.Value(i);
- aUVNodes(i) = aDiscret.Parameter(i);
- }
-
- aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes);
- aPoly3D->Deflection(myParameters.Deflection);
-
- BRep_Builder aBuilder;
- aBuilder.UpdateEdge(aEdge, aPoly3D);
- }
-}
-
-//=======================================================================
-//function : edgeDeflection
-//purpose :
-//=======================================================================
-Standard_Real BRepMesh_IncrementalMesh::edgeDeflection(
- const TopoDS_Edge& theEdge)
-{
- const Standard_Real* pDef = myEdgeDeflection.Seek(theEdge);
- if (pDef)
- return *pDef;
-
- Standard_Real aEdgeDeflection;
- if ( myParameters.Relative )
- {
- Standard_Real aScale;
- aEdgeDeflection = BRepMesh_ShapeTool::RelativeEdgeDeflection(theEdge,
- myParameters.Deflection, myMaxShapeSize, aScale);
- }
- else
- aEdgeDeflection = myParameters.Deflection;
-
- myEdgeDeflection.Bind(theEdge, aEdgeDeflection);
- return aEdgeDeflection;
-}
-
-//=======================================================================
-//function : faceDeflection
-//purpose :
-//=======================================================================
-Standard_Real BRepMesh_IncrementalMesh::faceDeflection(
- const TopoDS_Face& theFace)
-{
- if ( !myParameters.Relative )
- return myParameters.Deflection;
+ initParameters();
- Standard_Integer aEdgesNb = 0;
- Standard_Real aFaceDeflection = 0.;
+ Handle(BRepMesh_Context) aContext = new BRepMesh_Context;
+ aContext->SetShape(Shape());
+ aContext->ChangeParameters() = myParameters;
+ aContext->ChangeParameters().CleanModel = Standard_False;
- TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
- for (; aEdgeIt.More(); aEdgeIt.Next(), ++aEdgesNb)
- {
- const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
- aFaceDeflection += edgeDeflection(aEdge);
- }
+ IMeshTools_MeshBuilder aIncMesh(aContext);
+ aIncMesh.Perform();
- return (aEdgesNb == 0) ? myParameters.Deflection : (aFaceDeflection / aEdgesNb);
-}
-
-//=======================================================================
-//function : update(edge)
-//purpose :
-//=======================================================================
-void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge)
-{
- if (!myEdges.IsBound(theEdge))
- myEdges.Bind(theEdge, BRepMesh::DMapOfTriangulationBool(3, myEdges.Allocator()));
-
- Standard_Real aEdgeDeflection = edgeDeflection(theEdge);
- // Check that triangulation relies to face of the given shape.
- const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces =
- myMesh->SharedFaces();
-
- const TopTools_ListOfShape& aSharedFaces =
- aMapOfSharedFaces.FindFromKey(theEdge);
-
- TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces);
- for (; aSharedFaceIt.More(); aSharedFaceIt.Next())
+ myStatus = IMeshData_NoError;
+ const Handle(IMeshData_Model)& aModel = aContext->GetModel();
+ for (Standard_Integer aFaceIt = 0; aFaceIt < aModel->FacesNb(); ++aFaceIt)
{
- TopLoc_Location aLoc;
- const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value());
- const Handle(Poly_Triangulation)& aFaceTriangulation =
- BRep_Tool::Triangulation(aFace, aLoc);
-
- if (aFaceTriangulation.IsNull())
- continue;
-
- Standard_Boolean isConsistent = Standard_False;
- const Handle(Poly_PolygonOnTriangulation)& aPolygon =
- BRep_Tool::PolygonOnTriangulation(theEdge, aFaceTriangulation, aLoc);
-
- if (!aPolygon.IsNull())
- {
- isConsistent = aPolygon->Deflection() < 1.1 * aEdgeDeflection &&
- aPolygon->HasParameters();
-
- if (!isConsistent)
- {
- myModified = Standard_True;
- BRepMesh_ShapeTool::NullifyEdge(theEdge, aFaceTriangulation, aLoc);
- }
- }
+ const IMeshData::IFaceHandle& aDFace = aModel->GetFace(aFaceIt);
+ myStatus |= aDFace->GetStatusMask();
- myEdges(theEdge).Bind(aFaceTriangulation, isConsistent);
- }
-}
-
-//=======================================================================
-//function : isToBeMeshed
-//purpose :
-//=======================================================================
-Standard_Boolean BRepMesh_IncrementalMesh::toBeMeshed(
- const TopoDS_Face& theFace,
- const Standard_Boolean isWithCheck)
-{
- TopLoc_Location aLoc;
- const Handle(Poly_Triangulation)& aTriangulation =
- BRep_Tool::Triangulation(theFace, aLoc);
-
- if (aTriangulation.IsNull())
- return Standard_True;
-
- if (isWithCheck)
- {
- Standard_Real aFaceDeflection = faceDeflection(theFace);
- if (aTriangulation->Deflection() < 1.1 * aFaceDeflection)
+ for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
{
- Standard_Boolean isEdgesConsistent = Standard_True;
- TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
- for (; aEdgeIt.More() && isEdgesConsistent; aEdgeIt.Next())
- {
- const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
- if (!myEdges.IsBound(aEdge))
- continue;
-
- BRepMesh::DMapOfTriangulationBool& aTriMap = myEdges(aEdge);
- isEdgesConsistent &= aTriMap.IsBound(aTriangulation) &&
- aTriMap(aTriangulation);
- }
-
- if (isEdgesConsistent)
- {
- // #25080: check that indices of links forming triangles are in range.
- Standard_Boolean isTriangulationConsistent = Standard_True;
- const Standard_Integer aNodesNb = aTriangulation->NbNodes();
- const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();
- Standard_Integer i = aTriangles.Lower();
- for (; i <= aTriangles.Upper() && isTriangulationConsistent; ++i)
- {
- const Poly_Triangle& aTriangle = aTriangles(i);
- Standard_Integer n[3];
- aTriangle.Get(n[0], n[1], n[2]);
- for (Standard_Integer j = 0; j < 3 && isTriangulationConsistent; ++j)
- isTriangulationConsistent = (n[j] >= 1 && n[j] <= aNodesNb);
- }
-
- if (isTriangulationConsistent)
- return Standard_False;
- }
+ const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
+ myStatus |= aDWire->GetStatusMask();
}
}
- // Nullify edges
- TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
- for (; aEdgeIt.More(); aEdgeIt.Next())
- {
- const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
- BRepMesh_ShapeTool::NullifyEdge(aEdge, aTriangulation, aLoc);
- }
-
- BRepMesh_ShapeTool::NullifyFace(theFace);
- return Standard_True;
-}
-
-//=======================================================================
-//function : update(face)
-//purpose :
-//=======================================================================
-void BRepMesh_IncrementalMesh::update(const TopoDS_Face& theFace)
-{
- if (!toBeMeshed(theFace, Standard_True))
- return;
-
- myModified = Standard_True;
- Standard_Integer aStatus = myMesh->Add(theFace);
-
- myStatus |= aStatus;
- if (aStatus != BRepMesh_ReMesh)
- return;
-
- BRepMesh::MapOfShape aUsedFaces;
- aUsedFaces.Add(theFace);
-
- const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces =
- myMesh->SharedFaces();
-
- TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
- for (; aEdgeIt.More(); aEdgeIt.Next())
- {
- const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
- if (aMapOfSharedFaces.FindIndex(aEdge) == 0)
- continue;
-
- const TopTools_ListOfShape& aSharedFaces = aMapOfSharedFaces.FindFromKey(aEdge);
- TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces);
- for (; aSharedFaceIt.More(); aSharedFaceIt.Next())
- {
- const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value());
- if (aUsedFaces.Contains(aFace))
- continue;
-
- aUsedFaces.Add(aFace);
- toBeMeshed(aFace, Standard_False);
-
- myStatus |= myMesh->Add(aFace);
- }
- }
-}
-
-//=======================================================================
-//function : commit
-//purpose :
-//=======================================================================
-void BRepMesh_IncrementalMesh::commit()
-{
- NCollection_Vector<TopoDS_Face>::Iterator aFaceIt(myFaces);
- for (; aFaceIt.More(); aFaceIt.Next())
- commitEdges(aFaceIt.Value());
-
- discretizeFreeEdges();
-}
-
-//=======================================================================
-//function : commitEdges
-//purpose :
-//=======================================================================
-void BRepMesh_IncrementalMesh::commitEdges(const TopoDS_Face& theFace)
-{
- TopoDS_Face aFace = theFace;
- aFace.Orientation(TopAbs_FORWARD);
-
- Handle(BRepMesh_FaceAttribute) aFaceAttribute;
- if (!myMesh->GetFaceAttribute(aFace, aFaceAttribute))
- return;
-
- if (!aFaceAttribute->IsValid())
- {
- myStatus |= aFaceAttribute->GetStatus();
- return;
- }
-
- TopLoc_Location aLoc;
- Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc);
-
- if (aTriangulation.IsNull())
- return;
-
- try
- {
- OCC_CATCH_SIGNALS
-
- // Store discretization of edges
- BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = aFaceAttribute->ChangeInternalEdges();
- BRepMesh::DMapOfShapePairOfPolygon::Iterator aEdgeIt(*aInternalEdges);
- for (; aEdgeIt.More(); aEdgeIt.Next())
- {
- const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Key());
- const BRepMesh_PairOfPolygon& aPolyPair = aEdgeIt.Value();
- const Handle(Poly_PolygonOnTriangulation)& aPolygon1 = aPolyPair.First();
- const Handle(Poly_PolygonOnTriangulation)& aPolygon2 = aPolyPair.Last();
-
- if (aPolygon1 == aPolygon2)
- BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aTriangulation, aLoc);
- else
- BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aPolygon2, aTriangulation, aLoc);
- }
- }
- catch (Standard_Failure)
- {
- myStatus |= BRepMesh_Failure;
- }
+ setDone();
}
//=======================================================================
{
BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh();
anAlgo->ChangeParameters().Deflection = theDeflection;
- anAlgo->ChangeParameters().Angle = theAngle;
+ anAlgo->ChangeParameters().Angle = theAngle;
anAlgo->ChangeParameters().InParallel = IS_IN_PARALLEL;
- anAlgo->SetShape (theShape);
+ anAlgo->SetShape (theShape);
theAlgo = anAlgo;
return 0; // no error
}
#ifndef _BRepMesh_IncrementalMesh_HeaderFile
#define _BRepMesh_IncrementalMesh_HeaderFile
-#include <Standard.hxx>
-#include <Standard_Type.hxx>
-
-#include <BRepMesh_FastDiscret.hxx>
-#include <TopTools_MapOfShape.hxx>
-#include <TopTools_DataMapOfShapeReal.hxx>
#include <BRepMesh_DiscretRoot.hxx>
-#include <BRepMesh.hxx>
-
-#include <vector>
-
-class Poly_Triangulation;
-class TopoDS_Shape;
-class TopoDS_Edge;
-class TopoDS_Face;
+#include <IMeshTools_Parameters.hxx>
//! Builds the mesh of a shape with respect of their
//! correctly triangulated parts
//! used for the faces will be the maximum deflection of their edges.
//! @param theAngDeflection angular deflection.
//! @param isInParallel if TRUE shape will be meshed in parallel.
- Standard_EXPORT BRepMesh_IncrementalMesh(
- const TopoDS_Shape& theShape,
- const Standard_Real theLinDeflection,
- const Standard_Boolean isRelative = Standard_False,
- const Standard_Real theAngDeflection = 0.5,
- const Standard_Boolean isInParallel = Standard_False,
- const Standard_Boolean adaptiveMin = Standard_False);
+ Standard_EXPORT BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape,
+ const Standard_Real theLinDeflection,
+ const Standard_Boolean isRelative = Standard_False,
+ const Standard_Real theAngDeflection = 0.5,
+ const Standard_Boolean isInParallel = Standard_False);
//! Constructor.
//! Automatically calls method Perform.
//! @param theShape shape to be meshed.
//! @param theParameters - parameters of meshing
- Standard_EXPORT BRepMesh_IncrementalMesh (const TopoDS_Shape& theShape,
- const BRepMesh_FastDiscret::Parameters& theParameters);
+ Standard_EXPORT BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape,
+ const IMeshTools_Parameters& theParameters);
//! Performs meshing ot the shape.
Standard_EXPORT virtual void Perform() Standard_OVERRIDE;
public: //! @name accessing to parameters.
//! Returns meshing parameters
- inline const BRepMesh_FastDiscret::Parameters& Parameters() const
+ inline const IMeshTools_Parameters& Parameters() const
{
return myParameters;
}
//! Returns modifiable meshing parameters
- inline BRepMesh_FastDiscret::Parameters& ChangeParameters()
+ inline IMeshTools_Parameters& ChangeParameters()
{
return myParameters;
}
-
+
//! Returns modified flag.
inline Standard_Boolean IsModified() const
{
return myStatus;
}
+private:
+
+ //! Initializes specific parameters
+ inline void initParameters()
+ {
+ if (myParameters.MinSize < Precision::Confusion())
+ {
+ myParameters.MinSize =
+ Max(IMeshTools_Parameters::RelMinSize() * myParameters.Deflection,
+ Precision::Confusion());
+ }
+ }
public: //! @name plugin API
//! Discret() static method (thus applied only to Mesh Factories).
Standard_EXPORT static void SetParallelDefault(const Standard_Boolean isInParallel);
- DEFINE_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_IncrementalMesh, BRepMesh_DiscretRoot)
protected:
- Standard_EXPORT virtual void init() Standard_OVERRIDE;
-
-private:
-
- //! Builds the incremental mesh for the shape.
- void update();
-
- //! Checks triangulation of the given face for consistency
- //! with the chosen tolerance. If some edge of face has no
- //! discrete representation triangulation will be calculated.
- //! @param theFace face to be checked.
- void update(const TopoDS_Face& theFace);
-
- //! Checks discretization of the given edge for consistency
- //! with the chosen tolerance.
- //! @param theEdge edge to be checked.
- void update(const TopoDS_Edge& theEdge);
-
- //! Collects faces suitable for meshing.
- void collectFaces();
-
- //! Discretizes edges that have no associations with faces.
- void discretizeFreeEdges();
-
- //! Returns deflection of the given edge.
- //! @param theEdge edge which tolerance should be taken.
- Standard_Real edgeDeflection(const TopoDS_Edge& theEdge);
-
- //! Returns deflection of the given face.
- //! If relative flag is set, calculates relative deflection of the face
- //! as an average value of relative deflection regarding face's edges.
- //! Returns value of deflection set by user elsewhere.
- Standard_Real faceDeflection(const TopoDS_Face& theFace);
-
- //! Prepares the given face for meshing.
- //! Nullifies triangulation of face and polygons of face's edges.
- //! @param theFace face to be checked.
- //! @param isWithCheck if TRUE, checks parameters of triangulation
- //! existing in face. If its deflection satisfies the given value and
- //! each edge of face has polygon corresponded to this triangulation,
- //! method return FALSE.
- //! @return TRUE in case if the given face should be meshed.
- Standard_Boolean toBeMeshed(const TopoDS_Face& theFace,
- const Standard_Boolean isWithCheck);
-
- //! Stores mesh to the shape.
- void commit();
-
- //! Stores mesh of internal edges to the face.
- void commitEdges(const TopoDS_Face& theFace);
-
- //! Clears internal data structures.
- void clear();
-
-protected:
-
- BRepMesh::DMapOfEdgeListOfTriangulationBool myEdges;
- Handle(BRepMesh_FastDiscret) myMesh;
- TopTools_DataMapOfShapeReal myEdgeDeflection;
- NCollection_Vector<TopoDS_Face> myFaces;
-
- BRepMesh_FastDiscret::Parameters myParameters;
-
- Standard_Real myMaxShapeSize;
- Standard_Boolean myModified;
- Standard_Integer myStatus;
+ IMeshTools_Parameters myParameters;
+ Standard_Boolean myModified;
+ Standard_Integer myStatus;
};
-DEFINE_STANDARD_HANDLE(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
-
#endif
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_MeshAlgoFactory.hxx>
+#include <BRepMesh_DefaultRangeSplitter.hxx>
+#include <BRepMesh_NURBSRangeSplitter.hxx>
+#include <BRepMesh_SphereRangeSplitter.hxx>
+#include <BRepMesh_CylinderRangeSplitter.hxx>
+#include <BRepMesh_ConeRangeSplitter.hxx>
+#include <BRepMesh_TorusRangeSplitter.hxx>
+#include <BRepMesh_DelaunayBaseMeshAlgo.hxx>
+#include <BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx>
+#include <BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx>
+#include <BRepMesh_BoundaryParamsRangeSplitter.hxx>
+
+namespace
+{
+ struct BaseMeshAlgo
+ {
+ typedef BRepMesh_DelaunayBaseMeshAlgo Type;
+ };
+
+ template<class RangeSplitter>
+ struct NodeInsertionMeshAlgo
+ {
+ typedef BRepMesh_DelaunayNodeInsertionMeshAlgo<RangeSplitter> Type;
+ };
+
+ template<class RangeSplitter>
+ struct DeflectionControlMeshAlgo
+ {
+ typedef BRepMesh_DelaunayDeflectionControlMeshAlgo<RangeSplitter> Type;
+ };
+}
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_MeshAlgoFactory::BRepMesh_MeshAlgoFactory()
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_MeshAlgoFactory::~BRepMesh_MeshAlgoFactory()
+{
+}
+
+//=======================================================================
+// Function: GetAlgo
+// Purpose :
+//=======================================================================
+Handle(IMeshTools_MeshAlgo) BRepMesh_MeshAlgoFactory::GetAlgo(
+ const GeomAbs_SurfaceType theSurfaceType,
+ const IMeshTools_Parameters& theParameters) const
+{
+ switch (theSurfaceType)
+ {
+ case GeomAbs_Plane:
+ return theParameters.InternalVerticesMode ?
+ new NodeInsertionMeshAlgo<BRepMesh_DefaultRangeSplitter>::Type :
+ new BaseMeshAlgo::Type;
+ break;
+
+ case GeomAbs_Sphere:
+ return new NodeInsertionMeshAlgo<BRepMesh_SphereRangeSplitter>::Type;
+ break;
+
+ case GeomAbs_Cylinder:
+ return new NodeInsertionMeshAlgo<BRepMesh_CylinderRangeSplitter>::Type;
+ break;
+
+ case GeomAbs_Cone:
+ return new NodeInsertionMeshAlgo<BRepMesh_ConeRangeSplitter>::Type;
+ break;
+
+ case GeomAbs_Torus:
+ return new NodeInsertionMeshAlgo<BRepMesh_TorusRangeSplitter>::Type;
+ break;
+
+ case GeomAbs_SurfaceOfRevolution:
+ return new DeflectionControlMeshAlgo<BRepMesh_BoundaryParamsRangeSplitter>::Type;
+ break;
+
+ default:
+ return new DeflectionControlMeshAlgo<BRepMesh_NURBSRangeSplitter>::Type;
+ }
+}
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_MeshAlgoFactory_HeaderFile
+#define _BRepMesh_MeshAlgoFactory_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+#include <GeomAbs_SurfaceType.hxx>
+#include <IMeshTools_MeshAlgoFactory.hxx>
+
+//! Default implementation of IMeshTools_MeshAlgoFactory providing algorithms
+//! of different compexity depending on type of target surface.
+class BRepMesh_MeshAlgoFactory : public IMeshTools_MeshAlgoFactory
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_MeshAlgoFactory();
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_MeshAlgoFactory();
+
+ //! Creates instance of meshing algorithm for the given type of surface.
+ Standard_EXPORT virtual Handle(IMeshTools_MeshAlgo) GetAlgo(
+ const GeomAbs_SurfaceType theSurfaceType,
+ const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_MeshAlgoFactory, IMeshTools_MeshAlgoFactory)
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-08-22
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_MeshTool.hxx>
+#include <BRepMesh_SelectorOfDataStructureOfDelaun.hxx>
+#include <stack>
+
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepBuilderAPI_MakePolygon.hxx>
+#include <BRep_Builder.hxx>
+#include <TopoDS_Compound.hxx>
+#include <BRepTools.hxx>
+#include <gp_Pln.hxx>
+
+namespace
+{
+ //! Returns index of triangle node opposite to the given link.
+ inline Standard_Integer findApexIndex(
+ const Standard_Integer(&aNodes)[3],
+ const BRepMesh_Edge& theLink)
+ {
+ Standard_Integer i = 0;
+ for (; i < 3; ++i)
+ {
+ if (aNodes[i] != theLink.FirstNode() &&
+ aNodes[i] != theLink.LastNode())
+ {
+ break;
+ }
+ }
+
+ return i;
+ }
+}
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_MeshTool::BRepMesh_MeshTool(
+ const Handle(BRepMesh_DataStructureOfDelaun)& theStructure)
+ : myStructure(theStructure)
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_MeshTool::~BRepMesh_MeshTool()
+{
+}
+
+//=======================================================================
+//function : Legalize
+//purpose :
+//=======================================================================
+void BRepMesh_MeshTool::Legalize(const Standard_Integer theLinkIndex)
+{
+ std::stack<Standard_Integer> aStack;
+ aStack.push(theLinkIndex);
+
+ IMeshData::MapOfInteger aUsedLinks;
+ while (!aStack.empty())
+ {
+ const Standard_Integer aLinkIndex = aStack.top();
+ aStack.pop();
+
+ aUsedLinks.Add(aLinkIndex);
+ const BRepMesh_Edge& aLink = myStructure->GetLink(aLinkIndex);
+ if (aLink.Movability() != BRepMesh_Frontier)
+ {
+ const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aLinkIndex);
+ if (aPair.Extent() == 2)
+ {
+ const BRepMesh_Triangle& aTriangle1 = myStructure->GetElement(aPair.FirstIndex());
+ const BRepMesh_Triangle& aTriangle2 = myStructure->GetElement(aPair.LastIndex());
+
+ Standard_Integer aNodes[2][3];
+ myStructure->ElementNodes(aTriangle1, aNodes[0]);
+ myStructure->ElementNodes(aTriangle2, aNodes[1]);
+
+ const Standard_Integer aApexIndex[2] = {
+ findApexIndex(aNodes[0], aLink),
+ findApexIndex(aNodes[1], aLink)
+ };
+
+ if (checkCircle(aNodes[0], aNodes[1][aApexIndex[1]]) ||
+ checkCircle(aNodes[1], aNodes[0][aApexIndex[0]]))
+ {
+ myStructure->RemoveElement(aPair.FirstIndex());
+ myStructure->RemoveElement(aPair.LastIndex());
+ myStructure->RemoveLink(aLinkIndex);
+
+ addTriangleAndUpdateStack(
+ aNodes[0][(aApexIndex[0])],
+ aNodes[0][(aApexIndex[0] + 1) % 3],
+ aNodes[1][(aApexIndex[1])],
+ aUsedLinks, aStack);
+
+ addTriangleAndUpdateStack(
+ aNodes[1][(aApexIndex[1])],
+ aNodes[1][(aApexIndex[1] + 1) % 3],
+ aNodes[0][(aApexIndex[0])],
+ aUsedLinks, aStack);
+ }
+ }
+ }
+ }
+}
+
+//=======================================================================
+//function : EraseItemsConnectedTo
+//purpose :
+//=======================================================================
+void BRepMesh_MeshTool::EraseItemsConnectedTo(
+ const Standard_Integer theNodeIndex)
+{
+ BRepMesh_SelectorOfDataStructureOfDelaun aSelector(myStructure);
+ aSelector.NeighboursOfNode(theNodeIndex);
+
+ IMeshData::MapOfIntegerInteger aLoopEdges(1, new NCollection_IncAllocator);
+ EraseTriangles(aSelector.Elements(), aLoopEdges);
+ EraseFreeLinks(aLoopEdges);
+ myStructure->RemoveNode(theNodeIndex);
+}
+
+//=======================================================================
+//function : CleanFrontierLinks
+//purpose :
+//=======================================================================
+void BRepMesh_MeshTool::CleanFrontierLinks()
+{
+ Handle(NCollection_IncAllocator) aAlloc = new NCollection_IncAllocator;
+ IMeshData::MapOfInteger aTrianglesToErase;
+ IMeshData::MapOfIntegerInteger aLoopEdges(1, aAlloc);
+
+ Handle(IMeshData::MapOfInteger) aFrontier = GetEdgesByType(BRepMesh_Frontier);
+ IMeshData::IteratorOfMapOfInteger aFrontierIt(*aFrontier);
+ for (; aFrontierIt.More(); aFrontierIt.Next())
+ {
+ Standard_Integer aFrontierId = aFrontierIt.Key();
+ const BRepMesh_Edge& aLink = myStructure->GetLink(aFrontierId);
+
+ Standard_Boolean isTriangleFound = Standard_False;
+ const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aFrontierId);
+ for (Standard_Integer aElemIt = 1; aElemIt <= aPair.Extent() && !isTriangleFound; ++aElemIt)
+ {
+ const Standard_Integer aPriorElemId = aPair.Index(aElemIt);
+ const BRepMesh_Triangle& aElement = myStructure->GetElement(aPriorElemId);
+ const Standard_Integer(&e)[3] = aElement.myEdges;
+ const Standard_Boolean(&o)[3] = aElement.myOrientations;
+
+ for (Standard_Integer n = 0; n < 3 && !isTriangleFound; ++n)
+ {
+ if (aFrontierId == e[n] && !o[n])
+ {
+ // Destruction of external triangles on boundary edges
+ isTriangleFound = Standard_True;
+ aTrianglesToErase.Add(aPriorElemId);
+
+ collectTrianglesOnFreeLinksAroundNodesOf(aLink, e[(n + 1) % 3], aTrianglesToErase);
+ collectTrianglesOnFreeLinksAroundNodesOf(aLink, e[(n + 2) % 3], aTrianglesToErase);
+ }
+ }
+ }
+ }
+
+ EraseTriangles(aTrianglesToErase, aLoopEdges);
+ EraseFreeLinks(aLoopEdges);
+}
+
+//=======================================================================
+//function : EraseTriangles
+//purpose :
+//=======================================================================
+void BRepMesh_MeshTool::EraseTriangles(
+ const IMeshData::MapOfInteger& theTriangles,
+ IMeshData::MapOfIntegerInteger& theLoopEdges)
+{
+ IMeshData::IteratorOfMapOfInteger aFreeTriangles(theTriangles);
+ for (; aFreeTriangles.More(); aFreeTriangles.Next())
+ {
+ EraseTriangle(aFreeTriangles.Key(), theLoopEdges);
+ }
+}
+
+//=======================================================================
+//function : EraseTriangle
+//purpose :
+//=======================================================================
+void BRepMesh_MeshTool::EraseTriangle(
+ const Standard_Integer theTriangleIndex,
+ IMeshData::MapOfIntegerInteger& theLoopEdges)
+{
+ const BRepMesh_Triangle& aElement = myStructure->GetElement(theTriangleIndex);
+ const Standard_Integer(&e)[3] = aElement.myEdges;
+ const Standard_Boolean(&o)[3] = aElement.myOrientations;
+
+ myStructure->RemoveElement(theTriangleIndex);
+
+ for (Standard_Integer i = 0; i < 3; ++i)
+ {
+ if (!theLoopEdges.Bind(e[i], o[i]))
+ {
+ theLoopEdges.UnBind(e[i]);
+ myStructure->RemoveLink(e[i]);
+ }
+ }
+}
+
+//=======================================================================
+//function : EraseFreeLinks
+//purpose :
+//=======================================================================
+void BRepMesh_MeshTool::EraseFreeLinks()
+{
+ for (Standard_Integer i = 1; i <= myStructure->NbLinks(); i++)
+ {
+ if (myStructure->ElementsConnectedTo(i).IsEmpty())
+ {
+ BRepMesh_Edge& anEdge = (BRepMesh_Edge&) myStructure->GetLink(i);
+ if (anEdge.Movability() == BRepMesh_Deleted)
+ {
+ continue;
+ }
+
+ anEdge.SetMovability(BRepMesh_Free);
+ myStructure->RemoveLink(i);
+ }
+ }
+}
+
+//=======================================================================
+//function : collectTrianglesOnFreeLinksAroundNodesOf
+//purpose :
+//=======================================================================
+void BRepMesh_MeshTool::collectTrianglesOnFreeLinksAroundNodesOf(
+ const BRepMesh_Edge& theConstraint,
+ const Standard_Integer theStartLink,
+ IMeshData::MapOfInteger& theTriangles)
+{
+ IMeshData::MapOfInteger aUsedLinks;
+ std::stack<Standard_Integer> aStack;
+ aStack.push(theStartLink);
+ aUsedLinks.Add(theStartLink);
+
+ while (!aStack.empty())
+ {
+ const Standard_Integer aLinkIndex = aStack.top();
+ aStack.pop();
+
+ const BRepMesh_Edge& aLink = myStructure->GetLink(aLinkIndex);
+ if (aLink.Movability() == BRepMesh_Free &&
+ (aLink.FirstNode() == theConstraint.FirstNode() ||
+ aLink.LastNode () == theConstraint.FirstNode() ||
+ aLink.FirstNode() == theConstraint.LastNode () ||
+ aLink.LastNode () == theConstraint.LastNode ()))
+ {
+ const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aLinkIndex);
+ for (Standard_Integer aElemIt = 1; aElemIt <= aPair.Extent(); ++aElemIt)
+ {
+ const Standard_Integer aIndex = aPair.Index(aElemIt);
+ theTriangles.Add(aIndex);
+
+ const BRepMesh_Triangle& aElement = myStructure->GetElement(aIndex);
+ const Standard_Integer(&aEdges)[3] = aElement.myEdges;
+
+ for (Standard_Integer i = 0; i < 3; ++i)
+ {
+ if (aEdges[i] != aLinkIndex && !aUsedLinks.Contains(aEdges[i]))
+ {
+ aUsedLinks.Add(aEdges[i]);
+ aStack .push(aEdges[i]);
+ }
+ }
+ }
+ }
+ }
+}
+
+//=======================================================================
+//function : EraseFreeLinks
+//purpose :
+//=======================================================================
+void BRepMesh_MeshTool::EraseFreeLinks(
+ const IMeshData::MapOfIntegerInteger& theLinks)
+{
+ IMeshData::MapOfIntegerInteger::Iterator aFreeEdges(theLinks);
+ for (; aFreeEdges.More(); aFreeEdges.Next())
+ {
+ if (myStructure->ElementsConnectedTo(aFreeEdges.Key()).IsEmpty())
+ {
+ myStructure->RemoveLink(aFreeEdges.Key());
+ }
+ }
+}
+
+//=======================================================================
+//function : GetEdgesByType
+//purpose :
+//=======================================================================
+Handle(IMeshData::MapOfInteger) BRepMesh_MeshTool::GetEdgesByType(
+ const BRepMesh_DegreeOfFreedom theEdgeType) const
+{
+ Handle(IMeshData::MapOfInteger) aResult = new IMeshData::MapOfInteger;
+ IMeshData::IteratorOfMapOfInteger aEdgeIt(myStructure->LinksOfDomain());
+
+ for (; aEdgeIt.More(); aEdgeIt.Next())
+ {
+ const BRepMesh_Edge& aEdge = myStructure->GetLink(aEdgeIt.Key());
+ if (aEdge.Movability() == theEdgeType)
+ {
+ aResult->Add(aEdgeIt.Key());
+ }
+ }
+
+ return aResult;
+}
+
+//=======================================================================
+//function : DumpStruct
+//purpose :
+//=======================================================================
+void BRepMesh_MeshTool::DumpTriangles(const Standard_CString theFileName,
+ IMeshData::MapOfInteger* theTriangles)
+{
+ BRep_Builder aBuilder;
+ TopoDS_Compound aResult;
+ aBuilder.MakeCompound(aResult);
+
+ const IMeshData::MapOfInteger& aTriangles = myStructure->ElementsOfDomain();
+ for (IMeshData::IteratorOfMapOfInteger aIt(aTriangles); aIt.More(); aIt.Next())
+ {
+ if (theTriangles != NULL && !theTriangles->Contains(aIt.Key()))
+ continue;
+
+ Standard_Integer aNodes[3];
+ const BRepMesh_Triangle& aTri = myStructure->GetElement(aIt.Key());
+ myStructure->ElementNodes(aTri, aNodes);
+
+ const gp_XY& aV1 = myStructure->GetNode(aNodes[0]).Coord();
+ const gp_XY& aV2 = myStructure->GetNode(aNodes[1]).Coord();
+ const gp_XY& aV3 = myStructure->GetNode(aNodes[2]).Coord();
+
+ BRepBuilderAPI_MakePolygon aPoly(gp_Pnt(aV1.X(), aV1.Y(), 0.),
+ gp_Pnt(aV2.X(), aV2.Y(), 0.),
+ gp_Pnt(aV3.X(), aV3.Y(), 0.),
+ Standard_True);
+
+ BRepBuilderAPI_MakeFace aFaceBuilder(gp_Pln(gp::XOY()), aPoly.Wire());
+ aBuilder.Add(aResult, aFaceBuilder.Shape());
+ }
+
+ BRepTools::Write(aResult, theFileName);
+}
--- /dev/null
+// Created on: 2016-08-22
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_MeshTool_HeaderFile
+#define _BRepMesh_MeshTool_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_DefineHandle.hxx>
+#include <BRepMesh_DataStructureOfDelaun.hxx>
+#include <BRepMesh_CircleTool.hxx>
+#include <gp_Lin2d.hxx>
+#include <IMeshData_Types.hxx>
+#include <BRepMesh_Edge.hxx>
+
+#include <stack>
+
+//! Auxiliary tool providing API for manipulation with BRepMesh_DataStructureOfDelaun.
+class BRepMesh_MeshTool : public Standard_Transient
+{
+public:
+
+ //! Helper functor intended to separate points to left and right from the constraint.
+ class NodeClassifier
+ {
+ public:
+
+ NodeClassifier(
+ const BRepMesh_Edge& theConstraint,
+ const Handle(BRepMesh_DataStructureOfDelaun)& theStructure)
+ : myStructure(theStructure)
+ {
+ const BRepMesh_Vertex& aVertex1 = myStructure->GetNode(theConstraint.FirstNode());
+ const BRepMesh_Vertex& aVertex2 = myStructure->GetNode(theConstraint.LastNode());
+
+ myConstraint.SetLocation(aVertex1.Coord());
+ myConstraint.SetDirection(gp_Vec2d(aVertex1.Coord(), aVertex2.Coord()));
+ mySign = myConstraint.Direction().X() > 0;
+ }
+
+ inline Standard_Boolean IsAbove(const Standard_Integer theNodeIndex) const
+ {
+ const BRepMesh_Vertex& aVertex = myStructure->GetNode(theNodeIndex);
+ const gp_Vec2d aNodeVec(myConstraint.Location(), aVertex.Coord());
+ if (aNodeVec.SquareMagnitude() > gp::Resolution())
+ {
+ const Standard_Real aCross = aNodeVec.Crossed(myConstraint.Direction());
+ if (Abs(aCross) > gp::Resolution())
+ {
+ return mySign ?
+ aCross < 0. :
+ aCross > 0.;
+ }
+ }
+
+ return Standard_False;
+ }
+
+ private:
+
+ NodeClassifier (const NodeClassifier& theOther);
+
+ void operator=(const NodeClassifier& theOther);
+
+ private:
+
+ const Handle(BRepMesh_DataStructureOfDelaun)& myStructure;
+ gp_Lin2d myConstraint;
+ Standard_Boolean mySign;
+ };
+
+ //! Constructor.
+ //! Initializes tool by the given data structure.
+ Standard_EXPORT BRepMesh_MeshTool(const Handle(BRepMesh_DataStructureOfDelaun)& theStructure);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_MeshTool();
+
+ //! Returns data structure manipulated by this tool.
+ inline const Handle(BRepMesh_DataStructureOfDelaun)& GetStructure() const
+ {
+ return myStructure;
+ }
+
+ //! Dumps triangles to specified file.
+ void DumpTriangles(const Standard_CString theFileName, IMeshData::MapOfInteger* theTriangles);
+
+ //! Adds new triangle with specified nodes to mesh.
+ //! Legalizes triangle in case if it violates circle criteria.
+ inline void AddAndLegalizeTriangle(
+ const Standard_Integer thePoint1,
+ const Standard_Integer thePoint2,
+ const Standard_Integer thePoint3)
+ {
+ Standard_Integer aEdges[3];
+ AddTriangle(thePoint1, thePoint2, thePoint3, aEdges);
+
+ Legalize(aEdges[0]);
+ Legalize(aEdges[1]);
+ Legalize(aEdges[2]);
+ }
+
+ //! Adds new triangle with specified nodes to mesh.
+ inline void AddTriangle(
+ const Standard_Integer thePoint1,
+ const Standard_Integer thePoint2,
+ const Standard_Integer thePoint3,
+ Standard_Integer (&theEdges)[3])
+ {
+ Standard_Boolean aOri[3];
+ AddLink(thePoint1, thePoint2, theEdges[0], aOri[0]);
+ AddLink(thePoint2, thePoint3, theEdges[1], aOri[1]);
+ AddLink(thePoint3, thePoint1, theEdges[2], aOri[2]);
+
+ myStructure->AddElement(BRepMesh_Triangle(theEdges, aOri, BRepMesh_Free));
+ }
+
+ //! Adds new link to mesh.
+ //! Updates link index and link orientaion parameters.
+ inline void AddLink(const Standard_Integer theFirstNode,
+ const Standard_Integer theLastNode,
+ Standard_Integer& theLinkIndex,
+ Standard_Boolean& theLinkOri)
+ {
+ const Standard_Integer aLinkIt = myStructure->AddLink(
+ BRepMesh_Edge(theFirstNode, theLastNode, BRepMesh_Free));
+
+ theLinkIndex = Abs(aLinkIt);
+ theLinkOri = (aLinkIt > 0);
+ }
+
+ //! Performs legalization of triangles connected to the specified link.
+ Standard_EXPORT void Legalize(const Standard_Integer theLinkIndex);
+
+ //! Erases all elements connected to the specified artificial node.
+ //! In addition, erases the artificial node itself.
+ Standard_EXPORT void EraseItemsConnectedTo(const Standard_Integer theNodeIndex);
+
+ //! Cleans frontier links from triangles to the right.
+ Standard_EXPORT void CleanFrontierLinks();
+
+ //! Erases the given set of triangles.
+ //! Fills map of loop edges forming the countour surrounding the erased triangles.
+ void EraseTriangles(const IMeshData::MapOfInteger& theTriangles,
+ IMeshData::MapOfIntegerInteger& theLoopEdges);
+
+ //! Erases triangle with the given index and adds the free edges into the map.
+ //! When an edge is suppressed more than one time it is destroyed.
+ Standard_EXPORT void EraseTriangle(const Standard_Integer theTriangleIndex,
+ IMeshData::MapOfIntegerInteger& theLoopEdges);
+
+ //! Erases all links that have no elements connected to them.
+ Standard_EXPORT void EraseFreeLinks();
+
+ //! Erases links from the specified map that have no elements connected to them.
+ Standard_EXPORT void EraseFreeLinks(const IMeshData::MapOfIntegerInteger& theLinks);
+
+ //! Gives the list of edges with type defined by input parameter.
+ Standard_EXPORT Handle(IMeshData::MapOfInteger) GetEdgesByType(const BRepMesh_DegreeOfFreedom theEdgeType) const;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_MeshTool, Standard_Transient)
+
+private:
+
+ //! Returns True if the given point lies within circumcircle of the given triangle.
+ inline Standard_Boolean checkCircle(
+ const Standard_Integer(&aNodes)[3],
+ const Standard_Integer thePoint)
+ {
+ const BRepMesh_Vertex& aVertex0 = myStructure->GetNode(aNodes[0]);
+ const BRepMesh_Vertex& aVertex1 = myStructure->GetNode(aNodes[1]);
+ const BRepMesh_Vertex& aVertex2 = myStructure->GetNode(aNodes[2]);
+
+ gp_XY aLocation;
+ Standard_Real aRadius;
+ const Standard_Boolean isOk = BRepMesh_CircleTool::MakeCircle(
+ aVertex0.Coord(), aVertex1.Coord(), aVertex2.Coord(),
+ aLocation, aRadius);
+
+ if (isOk)
+ {
+ const BRepMesh_Vertex& aVertex = myStructure->GetNode(thePoint);
+ const Standard_Real aDist = (aVertex.Coord() - aLocation).SquareModulus() - (aRadius * aRadius);
+ return (aDist < Precision::SquareConfusion());
+ }
+
+ return Standard_False;
+ }
+
+ //! Adds new triangle with the given nodes and updates
+ //! links stack by ones are not in used map.
+ inline void addTriangleAndUpdateStack(
+ const Standard_Integer theNode0,
+ const Standard_Integer theNode1,
+ const Standard_Integer theNode2,
+ const IMeshData::MapOfInteger& theUsedLinks,
+ std::stack<Standard_Integer>& theStack)
+ {
+ Standard_Integer aEdges[3];
+ AddTriangle(theNode0, theNode1, theNode2, aEdges);
+
+ for (Standard_Integer i = 0; i < 3; ++i)
+ {
+ if (!theUsedLinks.Contains(aEdges[i]))
+ {
+ theStack.push(aEdges[i]);
+ }
+ }
+ }
+
+ //! Iteratively erases triangles and their neighbours consisting
+ //! of free links using the given link as starting front.
+ //! Only triangles around the constraint's saddle nodes will be removed.
+ void collectTrianglesOnFreeLinksAroundNodesOf(
+ const BRepMesh_Edge& theConstraint,
+ const Standard_Integer theStartLink,
+ IMeshData::MapOfInteger& theTriangles);
+
+private:
+
+ Handle(BRepMesh_DataStructureOfDelaun) myStructure;
+};
+
+#endif
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_ModelBuilder.hxx>
+#include <BRepMeshData_Model.hxx>
+#include <BRepMesh_ShapeVisitor.hxx>
+#include <BRepMesh_ShapeTool.hxx>
+#include <IMeshTools_ShapeExplorer.hxx>
+#include <Standard_ErrorHandler.hxx>
+
+#include <Bnd_Box.hxx>
+#include <BRepBndLib.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_ModelBuilder::BRepMesh_ModelBuilder ()
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_ModelBuilder::~BRepMesh_ModelBuilder ()
+{
+}
+
+//=======================================================================
+// Function: Perform
+// Purpose :
+//=======================================================================
+Handle (IMeshData_Model) BRepMesh_ModelBuilder::Perform (
+ const TopoDS_Shape& theShape,
+ const IMeshTools_Parameters& theParameters)
+{
+ ClearStatus ();
+
+ Handle (BRepMeshData_Model) aModel;
+ try
+ {
+ OCC_CATCH_SIGNALS
+
+ Bnd_Box aBox;
+ BRepBndLib::Add (theShape, aBox, Standard_False);
+
+ if (!aBox.IsVoid ())
+ {
+ // Build data model for further processing.
+ aModel = new BRepMeshData_Model (theShape);
+
+ if (theParameters.Relative)
+ {
+ Standard_Real aMaxSize;
+ BRepMesh_ShapeTool::BoxMaxDimension (aBox, aMaxSize);
+ aModel->SetMaxSize(aMaxSize);
+ }
+ else
+ {
+ aModel->SetMaxSize(theParameters.Deflection);
+ }
+
+ Handle (IMeshTools_ShapeVisitor) aVisitor =
+ new BRepMesh_ShapeVisitor (aModel);
+
+ IMeshTools_ShapeExplorer aExplorer (theShape);
+ aExplorer.Accept (aVisitor);
+ SetStatus (Message_Done1);
+ }
+ else
+ {
+ SetStatus(Message_Fail1);
+ }
+ }
+ catch (Standard_Failure&)
+ {
+ SetStatus (Message_Fail2);
+ }
+
+ return aModel;
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_ModelBuilder_HeaderFile
+#define _BRepMesh_ModelBuilder_HeaderFile
+
+#include <IMeshTools_ModelBuilder.hxx>
+#include <Standard_Type.hxx>
+#include <TopoDS_Shape.hxx>
+
+//! Class implements interface representing tool for discrete model building.
+//!
+//! The following statuses should be used by default:
+//! Message_Done1 - model has been sucessfully built.
+//! Message_Fail1 - empty shape.
+//! Message_Fail2 - model has not been build due to unexpected reason.
+class BRepMesh_ModelBuilder : public IMeshTools_ModelBuilder
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_ModelBuilder ();
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_ModelBuilder ();
+
+ //! Creates discrete model for the given shape.
+ //! Returns nullptr in case of failure.
+ Standard_EXPORT virtual Handle (IMeshData_Model) Perform (
+ const TopoDS_Shape& theShape,
+ const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelBuilder, IMeshTools_ModelBuilder)
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-06-23
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_ModelHealer.hxx>
+#include <BRepMesh_Deflection.hxx>
+#include <BRepMesh_ShapeTool.hxx>
+#include <BRepMesh_FaceChecker.hxx>
+#include <BRepMesh_EdgeDiscret.hxx>
+#include <IMeshData_Face.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_PCurve.hxx>
+#include <OSD_Parallel.hxx>
+#include <TopExp.hxx>
+#include <TopoDS_Vertex.hxx>
+
+#ifdef DEBUG_HEALER
+#include <BRepBuilderAPI_MakePolygon.hxx>
+#include <BRepTools.hxx>
+#include <BRep_Builder.hxx>
+#include <TopoDS_Compound.hxx>
+#endif
+
+namespace
+{
+ //! Decreases deflection of the given edge and tries to update discretization.
+ class EdgeAmplifier
+ {
+ public:
+ //! Constructor.
+ EdgeAmplifier(const IMeshTools_Parameters& theParameters)
+ : myParameters(theParameters)
+ {
+ }
+
+ //! Main operator.
+ void operator()(const IMeshData::IEdgePtr& theDEdge) const
+ {
+ const IMeshData::IEdgeHandle aDEdge = theDEdge;
+ aDEdge->Clear(Standard_True);
+ aDEdge->SetDeflection(Max(aDEdge->GetDeflection() / 3., Precision::Confusion()));
+
+ const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(0);
+ const IMeshData::IFaceHandle aDFace = aPCurve->GetFace();
+ Handle(IMeshTools_CurveTessellator) aTessellator =
+ BRepMesh_EdgeDiscret::CreateEdgeTessellator(
+ aDEdge, aPCurve->GetOrientation(), aDFace, myParameters);
+
+ BRepMesh_EdgeDiscret::Tessellate3d(aDEdge, aTessellator, Standard_False);
+ BRepMesh_EdgeDiscret::Tessellate2d(aDEdge, Standard_False);
+ }
+
+ private:
+
+ EdgeAmplifier (const EdgeAmplifier& theOther);
+
+ void operator=(const EdgeAmplifier& theOther);
+
+ private:
+ const IMeshTools_Parameters& myParameters;
+ };
+
+ //! Returns True if some of two vertcies is same with reference one.
+ inline Standard_Boolean isSameWithSomeOf(
+ const TopoDS_Vertex& theRefVertex,
+ const TopoDS_Vertex& theVertex1,
+ const TopoDS_Vertex& theVertex2)
+ {
+ return (theRefVertex.IsSame(theVertex1) ||
+ theRefVertex.IsSame(theVertex2));
+ }
+
+ //! Returns True if some of two vertcies is within tolerance of reference one.
+ inline Standard_Boolean isInToleranceWithSomeOf(
+ const gp_Pnt& theRefPoint,
+ const gp_Pnt& thePoint1,
+ const gp_Pnt& thePoint2,
+ const Standard_Real theTol)
+ {
+ const Standard_Real aSqTol = theTol * theTol;
+ return (theRefPoint.SquareDistance(thePoint1) < aSqTol ||
+ theRefPoint.SquareDistance(thePoint2) < aSqTol);
+ }
+}
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_ModelHealer::BRepMesh_ModelHealer()
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_ModelHealer::~BRepMesh_ModelHealer()
+{
+}
+
+//=======================================================================
+// Function: Perform
+// Purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_ModelHealer::Perform(
+ const Handle(IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& theParameters)
+{
+ myModel = theModel;
+ myParameters = theParameters;
+ if (myModel.IsNull())
+ {
+ return Standard_False;
+ }
+
+ // MinSize is made as a constant. It is connected with
+ // the fact that too rude discretisation can lead to
+ // self-intersecting polygon, which cannot be fixed.
+ // As result the face will not be triangulated at all.
+ // E.g. see "Test mesh standard_mesh C7", the face #17.
+ myParameters.MinSize = Precision::Confusion();
+
+ myFaceIntersectingEdges = new IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs;
+ for (Standard_Integer aFaceIt = 0; aFaceIt < myModel->FacesNb(); ++aFaceIt)
+ {
+ myFaceIntersectingEdges->Bind(myModel->GetFace(aFaceIt).get(), Handle(IMeshData::MapOfIEdgePtr)());
+ }
+
+ // TODO: Here we can process edges in order to remove close discrete points.
+ OSD_Parallel::For(0, myModel->FacesNb(), *this, !isParallel());
+ amplifyEdges();
+
+ IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs::Iterator aFaceIt(*myFaceIntersectingEdges);
+ for (; aFaceIt.More(); aFaceIt.Next())
+ {
+ if (!aFaceIt.Value().IsNull())
+ {
+ const IMeshData::IFaceHandle aDFace = aFaceIt.Key();
+ aDFace->SetStatus(IMeshData_SelfIntersectingWire);
+ aDFace->SetStatus(IMeshData_Failure);
+ }
+ }
+
+ myFaceIntersectingEdges.Nullify();
+ myModel.Nullify(); // Do not hold link to model.
+ return Standard_True;
+}
+
+//=======================================================================
+// Function: amplifyEdges
+// Purpose :
+//=======================================================================
+void BRepMesh_ModelHealer::amplifyEdges()
+{
+ Handle(NCollection_IncAllocator) aTmpAlloc =
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
+
+ Standard_Integer aAmpIt = 0;
+ const Standard_Real aIterNb = 5;
+ IMeshData::MapOfIEdgePtr aEdgesToUpdate(1, aTmpAlloc);
+ while (aAmpIt++ < aIterNb && popEdgesToUpdate(aEdgesToUpdate))
+ {
+ // Try to update discretization by decreasing deflection of problematic edges.
+ OSD_Parallel::ForEach(aEdgesToUpdate.cbegin(), aEdgesToUpdate.cend(),
+ EdgeAmplifier(myParameters),
+ !(myParameters.InParallel && aEdgesToUpdate.Size() > 1),
+ aEdgesToUpdate.Size());
+
+ IMeshData::MapOfIFacePtr aFacesToCheck(1, aTmpAlloc);
+ IMeshData::MapOfIEdgePtr::Iterator aEdgeIt(aEdgesToUpdate);
+ for (; aEdgeIt.More(); aEdgeIt.Next())
+ {
+ const IMeshData::IEdgeHandle aDEdge = aEdgeIt.Value();
+ for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb(); ++aPCurveIt)
+ {
+ aFacesToCheck.Add(aDEdge->GetPCurve(aPCurveIt)->GetFace());
+ }
+ }
+
+ OSD_Parallel::ForEach(aFacesToCheck.cbegin(), aFacesToCheck.cend(),
+ *this, !(myParameters.InParallel && aFacesToCheck.Size() > 1),
+ aFacesToCheck.Size());
+
+ aEdgesToUpdate.Clear();
+ aTmpAlloc->Reset(Standard_False);
+ }
+}
+
+//=======================================================================
+// Function: popEdgesToUpdate
+// Purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_ModelHealer::popEdgesToUpdate(
+ IMeshData::MapOfIEdgePtr& theEdgesToUpdate)
+{
+ IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs::Iterator aFaceIt(*myFaceIntersectingEdges);
+ for (; aFaceIt.More(); aFaceIt.Next())
+ {
+ Handle(IMeshData::MapOfIEdgePtr)& aIntersections = aFaceIt.ChangeValue();
+ if (!aIntersections.IsNull())
+ {
+ theEdgesToUpdate.Unite(*aIntersections);
+ aIntersections.Nullify();
+ }
+ }
+
+ return !theEdgesToUpdate.IsEmpty();
+}
+
+//=======================================================================
+// Function: process
+// Purpose :
+//=======================================================================
+void BRepMesh_ModelHealer::process(const IMeshData::IFaceHandle& theDFace) const
+{
+ Handle(IMeshData::MapOfIEdgePtr)& aIntersections = myFaceIntersectingEdges->ChangeFind(theDFace.get());
+ aIntersections.Nullify();
+
+ fixFaceBoundaries(theDFace);
+
+ if (!theDFace->IsSet(IMeshData_Failure))
+ {
+ BRepMesh_FaceChecker aChecker(theDFace, myParameters);
+ if (!aChecker.Perform())
+ {
+#ifdef DEBUG_HEALER
+ std::cout << "Failed : #" << aChecker.GetIntersectingEdges()->Size() << std::endl;
+#endif
+ aIntersections = aChecker.GetIntersectingEdges();
+ }
+ }
+}
+
+//=======================================================================
+// Function: fixFaceBoundaries
+// Purpose :
+//=======================================================================
+void BRepMesh_ModelHealer::fixFaceBoundaries(const IMeshData::IFaceHandle& theDFace) const
+{
+#ifdef DEBUG_HEALER
+ TopoDS_Compound aComp;
+ BRep_Builder aBuilder;
+ aBuilder.MakeCompound(aComp);
+#endif
+
+ for (int aWireIt = 0; aWireIt < theDFace->WiresNb(); ++aWireIt)
+ {
+ const IMeshData::IWireHandle& aDWire = theDFace->GetWire(aWireIt);
+ BRepMesh_Deflection::ComputeDeflection(aDWire, myParameters);
+ for (int aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt)
+ {
+ const int aPrevEdgeIt = (aEdgeIt + aDWire->EdgesNb() - 1) % aDWire->EdgesNb();
+ const int aNextEdgeIt = (aEdgeIt + 1) % aDWire->EdgesNb();
+
+ const IMeshData::IEdgeHandle aPrevEdge = aDWire->GetEdge(aPrevEdgeIt);
+ const IMeshData::IEdgeHandle aCurrEdge = aDWire->GetEdge(aEdgeIt);
+ const IMeshData::IEdgeHandle aNextEdge = aDWire->GetEdge(aNextEdgeIt);
+
+ Standard_Boolean isConnected = !getCommonVertex(aCurrEdge, aNextEdge).IsNull() &&
+ !getCommonVertex(aPrevEdge, aCurrEdge).IsNull();
+
+ if (isConnected)
+ {
+ const IMeshData::IPCurveHandle& aPrevPCurve =
+ aPrevEdge->GetPCurve(theDFace.get(), aDWire->GetEdgeOrientation(aPrevEdgeIt));
+
+ const IMeshData::IPCurveHandle& aCurrPCurve =
+ aCurrEdge->GetPCurve(theDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt));
+
+ const IMeshData::IPCurveHandle& aNextPCurve =
+ aNextEdge->GetPCurve(theDFace.get(), aDWire->GetEdgeOrientation(aNextEdgeIt));
+
+ isConnected = connectClosestPoints(aPrevPCurve, aCurrPCurve, aNextPCurve);
+
+#ifdef DEBUG_HEALER
+ BRepBuilderAPI_MakePolygon aPoly;
+ for (int i = 0; i < aCurrPCurve->ParametersNb(); ++i)
+ {
+ const gp_Pnt2d& aPnt = aCurrPCurve->GetPoint(i);
+ aPoly.Add(gp_Pnt(aPnt.X(), aPnt.Y(), 0.));
+ }
+
+ if (aPoly.IsDone())
+ {
+ aBuilder.Add(aComp, aPoly.Shape());
+ }
+ TCollection_AsciiString aName("face_discr.brep");
+ BRepTools::Write(aComp, aName.ToCString());
+#endif
+ }
+
+ if (!isConnected || aCurrEdge->IsSet(IMeshData_Outdated))
+ {
+ // We have to clean face from triangulation.
+ theDFace->SetStatus(IMeshData_Outdated);
+
+ if (!isConnected)
+ {
+ // Just mark wire as open, but continue fixing other inconsistencies
+ // in hope that this data could be suitable to build mesh somehow.
+ aDWire->SetStatus(IMeshData_OpenWire);
+ }
+ }
+ }
+ }
+
+#ifdef DEBUG_HEALER
+ TCollection_AsciiString aName ("face_discr.brep");
+ TCollection_AsciiString aFaceName("face_geom.brep");
+ BRepTools::Write(aComp, aName.ToCString());
+ BRepTools::Write(theDFace->GetFace(), aFaceName.ToCString());
+#endif
+
+ BRepMesh_Deflection::ComputeDeflection(theDFace, myParameters);
+}
+
+//=======================================================================
+// Function: hasCommonVertex
+// Purpose :
+//=======================================================================
+TopoDS_Vertex BRepMesh_ModelHealer::getCommonVertex(
+ const IMeshData::IEdgeHandle& theEdge1,
+ const IMeshData::IEdgeHandle& theEdge2) const
+{
+ TopoDS_Vertex aVertex1_1, aVertex1_2;
+ TopExp::Vertices(theEdge1->GetEdge(), aVertex1_1, aVertex1_2);
+
+ //Test bugs moddata_2 bug428.
+ // restore [locate_data_file OCC428.brep] rr
+ // explode rr f
+ // explode rr_91 w
+ // explode rr_91_2 e
+ // nbshapes rr_91_2_2
+ // # 0 vertices; 1 edge
+
+ //This shape is invalid and can lead to exception in this code.
+
+ if (aVertex1_1.IsNull() || aVertex1_2.IsNull())
+ return TopoDS_Vertex();
+
+ if (theEdge1->GetEdge().IsSame(theEdge2->GetEdge()))
+ {
+ return aVertex1_1.IsSame(aVertex1_2) ? aVertex1_1 : TopoDS_Vertex();
+ }
+
+ TopoDS_Vertex aVertex2_1, aVertex2_2;
+ TopExp::Vertices(theEdge2->GetEdge(), aVertex2_1, aVertex2_2);
+
+ if (aVertex2_1.IsNull() || aVertex2_2.IsNull())
+ return TopoDS_Vertex();
+
+ if (isSameWithSomeOf(aVertex1_1, aVertex2_1, aVertex2_2))
+ {
+ return aVertex1_1;
+ }
+ else if (isSameWithSomeOf(aVertex1_2, aVertex2_1, aVertex2_2))
+ {
+ return aVertex1_2;
+ }
+
+ const gp_Pnt aPnt1_1 = BRep_Tool::Pnt(aVertex1_1);
+ const gp_Pnt aPnt1_2 = BRep_Tool::Pnt(aVertex1_2);
+ const Standard_Real aTol1_1 = BRep_Tool::Tolerance(aVertex1_1);
+ const Standard_Real aTol1_2 = BRep_Tool::Tolerance(aVertex1_2);
+
+ const gp_Pnt aPnt2_1 = BRep_Tool::Pnt(aVertex2_1);
+ const gp_Pnt aPnt2_2 = BRep_Tool::Pnt(aVertex2_2);
+ const Standard_Real aTol2_1 = BRep_Tool::Tolerance(aVertex2_1);
+ const Standard_Real aTol2_2 = BRep_Tool::Tolerance(aVertex2_2);
+
+ if (isInToleranceWithSomeOf(aPnt1_1, aPnt2_1, aPnt2_2, aTol1_1 + Max(aTol2_1, aTol2_2)))
+ {
+ return aVertex1_1;
+ }
+ else if (isInToleranceWithSomeOf(aPnt1_2, aPnt2_1, aPnt2_2, aTol1_2 + Max(aTol2_1, aTol2_2)))
+ {
+ return aVertex1_2;
+ }
+
+ return TopoDS_Vertex();
+}
+
+//=======================================================================
+// Function: connectClosestPoints
+// Purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_ModelHealer::connectClosestPoints(
+ const IMeshData::IPCurveHandle& thePrevDEdge,
+ const IMeshData::IPCurveHandle& theCurrDEdge,
+ const IMeshData::IPCurveHandle& theNextDEdge) const
+{
+ if (thePrevDEdge->IsInternal() ||
+ theCurrDEdge->IsInternal() ||
+ theNextDEdge->IsInternal())
+ {
+ return Standard_True;
+ }
+
+ gp_Pnt2d& aPrevFirstUV = thePrevDEdge->GetPoint(0);
+ gp_Pnt2d& aPrevLastUV = thePrevDEdge->GetPoint(thePrevDEdge->ParametersNb() - 1);
+
+ if (thePrevDEdge == theCurrDEdge)
+ {
+ // Wire consists of a single edge.
+ aPrevFirstUV = aPrevLastUV;
+ return Standard_True;
+ }
+
+ gp_Pnt2d& aCurrFirstUV = theCurrDEdge->GetPoint(0);
+ gp_Pnt2d& aCurrLastUV = theCurrDEdge->GetPoint(theCurrDEdge->ParametersNb() - 1);
+
+ gp_Pnt2d *aPrevUV = NULL, *aCurrPrevUV = NULL;
+ const Standard_Real aPrevSqDist = closestPoints(aPrevFirstUV, aPrevLastUV,
+ aCurrFirstUV, aCurrLastUV,
+ aPrevUV, aCurrPrevUV);
+
+ gp_Pnt2d *aNextUV = NULL, *aCurrNextUV = NULL;
+ if (thePrevDEdge == theNextDEdge)
+ {
+ // Wire consists of two edges. Connect both ends.
+ aNextUV = (aPrevUV == &aPrevFirstUV) ? &aPrevLastUV : &aPrevFirstUV;
+ aCurrNextUV = (aCurrPrevUV == &aCurrFirstUV) ? &aCurrLastUV : &aCurrFirstUV;
+
+ *aNextUV = *aCurrNextUV;
+ *aPrevUV = *aCurrPrevUV;
+ return Standard_True;
+ }
+
+ gp_Pnt2d& aNextFirstUV = theNextDEdge->GetPoint(0);
+ gp_Pnt2d& aNextLastUV = theNextDEdge->GetPoint(theNextDEdge->ParametersNb() - 1);
+
+ const Standard_Real aNextSqDist = closestPoints(aNextFirstUV, aNextLastUV,
+ aCurrFirstUV, aCurrLastUV,
+ aNextUV, aCurrNextUV);
+
+#ifdef DEBUG_HEALER
+ std::cout << "PrevSqDist = " << aPrevSqDist << std::endl;
+ std::cout << "NextSqDist = " << aNextSqDist << std::endl;
+#endif
+
+ // Connect closest points first. This can help to identify
+ // which ends should be connected in case of gap.
+ if (aPrevSqDist - aNextSqDist > gp::Resolution())
+ {
+ adjustSamePoints(aCurrNextUV, aNextUV, aCurrPrevUV, aPrevUV, aCurrFirstUV, aCurrLastUV, aPrevFirstUV, aPrevLastUV);
+ }
+ else
+ {
+ adjustSamePoints(aCurrPrevUV, aPrevUV, aCurrNextUV, aNextUV, aCurrFirstUV, aCurrLastUV, aNextFirstUV, aNextLastUV);
+ }
+
+ return Standard_True;
+}
--- /dev/null
+// Created on: 2016-06-23
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_ModelHealer_HeaderFile
+#define _BRepMesh_ModelHealer_HeaderFile
+
+#include <IMeshTools_ModelAlgo.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <IMeshData_Types.hxx>
+#include <IMeshData_Model.hxx>
+#include <TopoDS_Vertex.hxx>
+
+//! Class implements functionality of model healer tool.
+//! Iterates over model's faces and checks consistency of their wires,
+//! i.e.whether wires are closed and do not contain self - intersections.
+//! In case if wire contains disconnected parts, ends of adjacent edges
+//! forming the gaps are connected in parametric space forcibly. The notion
+//! of this operation is to create correct discrete model defined relatively
+//! parametric space of target face taking into account connectivity and
+//! tolerances of 3D space only. This means that there are no specific
+//! computations are made for the sake of determination of U and V tolerance.
+//! Registers intersections on edges forming the face\92s shape and tries to
+//! amplify discrete represenation by decreasing of deflection for the target edge.
+//! Checks can be performed in parallel mode.
+class BRepMesh_ModelHealer : public IMeshTools_ModelAlgo
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_ModelHealer();
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_ModelHealer();
+
+ //! Performs processing of edges of the given model.
+ Standard_EXPORT virtual Standard_Boolean Perform(
+ const Handle(IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
+
+ //! Functor API to discretize the given edge.
+ inline void operator() (const Standard_Integer theEdgeIndex) const {
+ process(theEdgeIndex);
+ }
+
+ //! Functor API to discretize the given edge.
+ inline void operator() (const IMeshData::IFaceHandle& theDFace) const {
+ process(theDFace);
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelHealer, IMeshTools_ModelAlgo)
+
+private:
+
+ //! Checks existing discretization of the face and updates data model.
+ inline void process(const Standard_Integer theFaceIndex) const
+ {
+ const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
+ process(aDFace);
+ }
+
+ //! Checks existing discretization of the face and updates data model.
+ void process(const IMeshData::IFaceHandle& theDFace) const;
+
+ //! Amplifies discretization of edges in case if self-intersection problem has been found.
+ void amplifyEdges();
+
+ //! Returns common vertex of two edges or null ptr in case if there is no such vertex.
+ TopoDS_Vertex getCommonVertex(
+ const IMeshData::IEdgeHandle& theEdge1,
+ const IMeshData::IEdgeHandle& theEdge2) const;
+
+ //! Connects pcurves of previous and current edge on the specified face
+ //! according to topological connectivity. Uses next edge in order to
+ //! identify closest point in case of signle vertex shared between both
+ //! ends of edge (degenerative edge)
+ Standard_Boolean connectClosestPoints(
+ const IMeshData::IPCurveHandle& thePrevDEdge,
+ const IMeshData::IPCurveHandle& theCurrDEdge,
+ const IMeshData::IPCurveHandle& theNextDEdge) const;
+
+ //! Chooses the most closest point to reference one from the given pair.
+ //! Returns square distance between reference point and closest one as
+ //! well as pointer to closest point.
+ inline Standard_Real closestPoint(
+ gp_Pnt2d& theRefPnt,
+ gp_Pnt2d& theFristPnt,
+ gp_Pnt2d& theSecondPnt,
+ gp_Pnt2d*& theClosestPnt) const
+ {
+ // Find the most closest end-points.
+ const Standard_Real aSqDist1 = theRefPnt.SquareDistance(theFristPnt);
+ const Standard_Real aSqDist2 = theRefPnt.SquareDistance(theSecondPnt);
+ if (aSqDist1 < aSqDist2)
+ {
+ theClosestPnt = &theFristPnt;
+ return aSqDist1;
+ }
+
+ theClosestPnt = &theSecondPnt;
+ return aSqDist2;
+ }
+
+ //! Chooses the most closest points among the given to reference one from the given pair.
+ //! Returns square distance between reference point and closest one as
+ //! well as pointer to closest point.
+ inline Standard_Real closestPoints(
+ gp_Pnt2d& theFirstPnt1,
+ gp_Pnt2d& theSecondPnt1,
+ gp_Pnt2d& theFirstPnt2,
+ gp_Pnt2d& theSecondPnt2,
+ gp_Pnt2d*& theClosestPnt1,
+ gp_Pnt2d*& theClosestPnt2) const
+ {
+ gp_Pnt2d *aCurrPrevUV1 = NULL, *aCurrPrevUV2 = NULL;
+ const Standard_Real aSqDist1 = closestPoint(theFirstPnt1, theFirstPnt2, theSecondPnt2, aCurrPrevUV1);
+ const Standard_Real aSqDist2 = closestPoint(theSecondPnt1, theFirstPnt2, theSecondPnt2, aCurrPrevUV2);
+ if (aSqDist1 - aSqDist2 < gp::Resolution())
+ {
+ theClosestPnt1 = &theFirstPnt1;
+ theClosestPnt2 = aCurrPrevUV1;
+ return aSqDist1;
+ }
+
+ theClosestPnt1 = &theSecondPnt1;
+ theClosestPnt2 = aCurrPrevUV2;
+ return aSqDist2;
+ }
+
+ //! Adjusts the given pair of points supposed to be the same.
+ //! In addition, adjusts another end-point of an edge in order
+ //! to perform correct matching in case of gap.
+ inline void adjustSamePoints(
+ gp_Pnt2d*& theMajorSamePnt1,
+ gp_Pnt2d*& theMinorSamePnt1,
+ gp_Pnt2d*& theMajorSamePnt2,
+ gp_Pnt2d*& theMinorSamePnt2,
+ gp_Pnt2d& theMajorFirstPnt,
+ gp_Pnt2d& theMajorLastPnt,
+ gp_Pnt2d& theMinorFirstPnt,
+ gp_Pnt2d& theMinorLastPnt) const
+ {
+ if (theMajorSamePnt2 == theMajorSamePnt1)
+ {
+ theMajorSamePnt2 = (theMajorSamePnt2 == &theMajorFirstPnt) ? &theMajorLastPnt : &theMajorFirstPnt;
+ closestPoint(*theMajorSamePnt2, theMinorFirstPnt, theMinorLastPnt, theMinorSamePnt2);
+ }
+
+ *theMajorSamePnt1 = *theMinorSamePnt1;
+ *theMajorSamePnt2 = *theMinorSamePnt2;
+ }
+
+ //! Connects ends of pcurves of face's wires according to topological coherency.
+ void fixFaceBoundaries(const IMeshData::IFaceHandle& theDFace) const;
+
+ //! Returns True if check can be done in parallel.
+ inline Standard_Boolean isParallel() const
+ {
+ return (myParameters.InParallel && myModel->FacesNb() > 1);
+ }
+
+ //! Collects unique edges to be updated from face map. Clears data stored in face map.
+ Standard_Boolean popEdgesToUpdate(IMeshData::MapOfIEdgePtr& theEdgesToUpdate);
+
+private:
+
+ Handle(IMeshData_Model) myModel;
+ IMeshTools_Parameters myParameters;
+ Handle(IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs) myFaceIntersectingEdges;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-07-04
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_ModelPostProcessor.hxx>
+#include <BRepMesh_ShapeTool.hxx>
+#include <IMeshData_Model.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_PCurve.hxx>
+#include <OSD_Parallel.hxx>
+
+namespace
+{
+ //! Commits 3D polygons and polygons on triangulations for corresponding edges.
+ class PolygonCommitter
+ {
+ public:
+ //! Constructor
+ PolygonCommitter(const Handle(IMeshData_Model)& theModel)
+ : myModel(theModel)
+ {
+ }
+
+ //! Main functor.
+ void operator()(const Standard_Integer theEdgeIndex) const
+ {
+ const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge(theEdgeIndex);
+ if (aDEdge->IsFree())
+ {
+ if (!aDEdge->IsSet(IMeshData_Reused))
+ {
+ commitPolygon3D(aDEdge);
+ }
+ }
+ else
+ {
+ commitPolygons(aDEdge);
+ }
+ }
+
+ private:
+
+ //! Commits 3d polygon to topological edge
+ void commitPolygon3D(const IMeshData::IEdgeHandle& theDEdge) const
+ {
+ const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve();
+
+ TColgp_Array1OfPnt aNodes (1, aCurve->ParametersNb());
+ TColStd_Array1OfReal aUVNodes(1, aCurve->ParametersNb());
+ for (Standard_Integer i = 1; i <= aCurve->ParametersNb(); ++i)
+ {
+ aNodes (i) = aCurve->GetPoint (i - 1);
+ aUVNodes(i) = aCurve->GetParameter(i - 1);
+ }
+
+ Handle(Poly_Polygon3D) aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes);
+ aPoly3D->Deflection(theDEdge->GetDeflection());
+
+ BRepMesh_ShapeTool::UpdateEdge(theDEdge->GetEdge(), aPoly3D);
+ }
+
+ //! Commits all polygons on triangulations correspondent to the given edge.
+ void commitPolygons(const IMeshData::IEdgeHandle& theDEdge) const
+ {
+ // Collect pcurves associated with the given edge on the specific surface.
+ IMeshData::IDMapOfIFacePtrsListOfIPCurves aMapOfPCurves;
+ for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt)
+ {
+ const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt);
+ const IMeshData::IFacePtr& aDFacePtr = aPCurve->GetFace();
+ const IMeshData::IFaceHandle aDFace = aDFacePtr;
+ if (aDFace->IsSet(IMeshData_Failure) ||
+ aDFace->IsSet(IMeshData_Reused))
+ {
+ continue;
+ }
+
+ if (!aMapOfPCurves.Contains(aDFacePtr))
+ {
+ aMapOfPCurves.Add(aDFacePtr, IMeshData::ListOfIPCurves());
+ }
+
+ IMeshData::ListOfIPCurves& aPCurves = aMapOfPCurves.ChangeFromKey(aDFacePtr);
+ aPCurves.Append(aPCurve);
+ }
+
+ // Commit polygons related to separate face.
+ const TopoDS_Edge& aEdge = theDEdge->GetEdge();
+ IMeshData::IDMapOfIFacePtrsListOfIPCurves::Iterator aPolygonIt(aMapOfPCurves);
+ for (; aPolygonIt.More(); aPolygonIt.Next())
+ {
+ const TopoDS_Face& aFace = aPolygonIt.Key()->GetFace();
+
+ TopLoc_Location aLoc;
+ const Handle(Poly_Triangulation)& aTriangulation =
+ BRep_Tool::Triangulation(aFace, aLoc);
+
+ if (!aTriangulation.IsNull())
+ {
+ const IMeshData::ListOfIPCurves& aPCurves = aPolygonIt.Value();
+ if (aPCurves.Size() == 2)
+ {
+ BRepMesh_ShapeTool::UpdateEdge(
+ aEdge,
+ collectPolygon(aPCurves.First(), theDEdge->GetDeflection()),
+ collectPolygon(aPCurves.Last (), theDEdge->GetDeflection()),
+ aTriangulation, aLoc);
+ }
+ else
+ {
+ BRepMesh_ShapeTool::UpdateEdge(
+ aEdge,
+ collectPolygon(aPCurves.First(), theDEdge->GetDeflection()),
+ aTriangulation, aLoc);
+ }
+ }
+ }
+ }
+
+ //! Collects polygonal data for the given pcurve
+ Handle(Poly_PolygonOnTriangulation) collectPolygon(
+ const IMeshData::IPCurveHandle& thePCurve,
+ const Standard_Real theDeflection) const
+ {
+ TColStd_Array1OfInteger aNodes (1, thePCurve->ParametersNb());
+ TColStd_Array1OfReal aParams(1, thePCurve->ParametersNb());
+ for (Standard_Integer i = 1; i <= thePCurve->ParametersNb(); ++i)
+ {
+ aNodes (i) = thePCurve->GetIndex (i - 1);
+ aParams(i) = thePCurve->GetParameter(i - 1);
+ }
+
+ Handle(Poly_PolygonOnTriangulation) aPolygon =
+ new Poly_PolygonOnTriangulation(aNodes, aParams);
+
+ aPolygon->Deflection(theDeflection);
+ return aPolygon;
+ }
+
+ private:
+
+ Handle(IMeshData_Model) myModel;
+ };
+}
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_ModelPostProcessor::BRepMesh_ModelPostProcessor()
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_ModelPostProcessor::~BRepMesh_ModelPostProcessor()
+{
+}
+
+//=======================================================================
+// Function: Perform
+// Purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_ModelPostProcessor::Perform(
+ const Handle(IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& /*theParameters*/)
+{
+ if (theModel.IsNull())
+ {
+ return Standard_False;
+ }
+
+ // TODO: Force single threaded solution due to data races on edges sharing the same TShape
+ OSD_Parallel::For(0, theModel->EdgesNb(), PolygonCommitter(theModel), Standard_True/*!theParameters.InParallel*/);
+ return Standard_True;
+}
--- /dev/null
+// Created on: 2016-07-22
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_ModelPostProcessor_HeaderFile
+#define _BRepMesh_ModelPostProcessor_HeaderFile
+
+#include <IMeshTools_ModelAlgo.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <IMeshData_Types.hxx>
+
+//! Class implements functionality of model post-processing tool.
+//! Stores polygons on triangulations to TopoDS_Edge.
+class BRepMesh_ModelPostProcessor : public IMeshTools_ModelAlgo
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_ModelPostProcessor();
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_ModelPostProcessor();
+
+ //! Performs processing of edges of the given model.
+ Standard_EXPORT virtual Standard_Boolean Perform(
+ const Handle(IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelPostProcessor, IMeshTools_ModelAlgo)
+};
+
+#endif
--- /dev/null
+// Created on: 2016-07-04
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_ModelPreProcessor.hxx>
+#include <BRepMesh_ShapeTool.hxx>
+#include <BRep_Tool.hxx>
+#include <IMeshData_Model.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_PCurve.hxx>
+#include <OSD_Parallel.hxx>
+
+namespace
+{
+ //! Checks consistency of triangulation stored in topological face.
+ class TriangulationConsistency
+ {
+ public:
+ //! Constructor
+ TriangulationConsistency(const Handle(IMeshData_Model)& theModel)
+ : myModel (theModel)
+ {
+ }
+
+ //! Main functor.
+ void operator()(const Standard_Integer theFaceIndex) const
+ {
+ const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
+ if (aDFace->IsSet(IMeshData_Outdated))
+ {
+ return;
+ }
+
+ TopLoc_Location aLoc;
+ const Handle(Poly_Triangulation)& aTriangulation =
+ BRep_Tool::Triangulation(aDFace->GetFace(), aLoc);
+
+ if (!aTriangulation.IsNull())
+ {
+ Standard_Boolean isTriangulationConsistent =
+ aTriangulation->Deflection() < 1.1 * aDFace->GetDeflection();
+
+ if (isTriangulationConsistent)
+ {
+ // #25080: check that indices of links forming triangles are in range.
+ const Standard_Integer aNodesNb = aTriangulation->NbNodes();
+ const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();
+
+ Standard_Integer i = aTriangles.Lower();
+ for (; i <= aTriangles.Upper() && isTriangulationConsistent; ++i)
+ {
+ const Poly_Triangle& aTriangle = aTriangles(i);
+
+ Standard_Integer aNode[3];
+ aTriangle.Get(aNode[0], aNode[1], aNode[2]);
+ for (Standard_Integer j = 0; j < 3 && isTriangulationConsistent; ++j)
+ {
+ isTriangulationConsistent = (aNode[j] >= 1 && aNode[j] <= aNodesNb);
+ }
+ }
+ }
+
+ if (isTriangulationConsistent)
+ {
+ aDFace->SetStatus(IMeshData_Reused);
+ aDFace->SetDeflection(aTriangulation->Deflection());
+ }
+ else
+ {
+ aDFace->SetStatus(IMeshData_Outdated);
+ }
+ }
+ }
+
+ private:
+
+ Handle(IMeshData_Model) myModel;
+ };
+}
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_ModelPreProcessor::BRepMesh_ModelPreProcessor()
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_ModelPreProcessor::~BRepMesh_ModelPreProcessor()
+{
+}
+
+//=======================================================================
+// Function: Perform
+// Purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_ModelPreProcessor::Perform(
+ const Handle(IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& theParameters)
+{
+ if (theModel.IsNull())
+ {
+ return Standard_False;
+ }
+
+ OSD_Parallel::For(0, theModel->FacesNb(), TriangulationConsistency(theModel), !theParameters.InParallel);
+
+ // Clean edges and faces from outdated polygons.
+ Handle(NCollection_IncAllocator) aTmpAlloc(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE));
+ NCollection_Map<IMeshData_Face*> aUsedFaces(1, aTmpAlloc);
+ for (Standard_Integer aEdgeIt = 0; aEdgeIt < theModel->EdgesNb(); ++aEdgeIt)
+ {
+ const IMeshData::IEdgeHandle& aDEdge = theModel->GetEdge(aEdgeIt);
+ if (aDEdge->IsFree())
+ {
+ if (aDEdge->IsSet(IMeshData_Outdated))
+ {
+ TopLoc_Location aLoc;
+ BRep_Tool::Polygon3D(aDEdge->GetEdge(), aLoc);
+ BRepMesh_ShapeTool::NullifyEdge(aDEdge->GetEdge(), aLoc);
+ }
+
+ continue;
+ }
+
+ for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb(); ++aPCurveIt)
+ {
+ // Find adjacent outdated face.
+ const IMeshData::IFaceHandle aDFace = aDEdge->GetPCurve(aPCurveIt)->GetFace();
+ if (!aUsedFaces.Contains(aDFace.get()))
+ {
+ aUsedFaces.Add(aDFace.get());
+ if (aDFace->IsSet(IMeshData_Outdated))
+ {
+ TopLoc_Location aLoc;
+ const Handle(Poly_Triangulation)& aTriangulation =
+ BRep_Tool::Triangulation(aDFace->GetFace(), aLoc);
+
+ // Clean all edges of oudated face.
+ for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
+ {
+ const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
+ for (Standard_Integer aWireEdgeIt = 0; aWireEdgeIt < aDWire->EdgesNb(); ++aWireEdgeIt)
+ {
+ const IMeshData::IEdgeHandle aTmpDEdge = aDWire->GetEdge(aWireEdgeIt);
+ BRepMesh_ShapeTool::NullifyEdge(aTmpDEdge->GetEdge(), aTriangulation, aLoc);
+ }
+ }
+
+ BRepMesh_ShapeTool::NullifyFace(aDFace->GetFace());
+ }
+ }
+ }
+ }
+
+ return Standard_True;
+}
+
--- /dev/null
+// Created on: 2016-07-04
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_ModelPreProcessor_HeaderFile
+#define _BRepMesh_ModelPreProcessor_HeaderFile
+
+#include <IMeshTools_ModelAlgo.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <IMeshData_Types.hxx>
+
+//! Class implements functionality of model pre-processing tool.
+//! Nullifies existing polygonal data in case if model elements
+//! have IMeshData_Outdated status.
+class BRepMesh_ModelPreProcessor : public IMeshTools_ModelAlgo
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_ModelPreProcessor();
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_ModelPreProcessor();
+
+ //! Performs processing of edges of the given model.
+ Standard_EXPORT virtual Standard_Boolean Perform(
+ const Handle(IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelPreProcessor, IMeshTools_ModelAlgo)
+};
+
+#endif
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_NURBSRangeSplitter.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_PCurve.hxx>
+#include <GeomAbs_IsoType.hxx>
+#include <BRepMesh_GeomTool.hxx>
+#include <NCollection_Handle.hxx>
+#include <algorithm>
+
+namespace
+{
+ class AnalyticalFilter
+ {
+ public:
+ //! Constructor.
+ AnalyticalFilter(
+ const IMeshData::IFaceHandle& theDFace,
+ const GeomAbs_IsoType theIsoType,
+ const Handle(IMeshData::SequenceOfReal)& theParams,
+ const Handle(IMeshData::SequenceOfReal)& theControlParams,
+ const Handle(IMeshData::MapOfReal)& theParamsForbiddenToRemove,
+ const Handle(IMeshData::MapOfReal)& theControlParamsForbiddenToRemove)
+ : myDFace(theDFace),
+ mySurface(myDFace->GetSurface()->ChangeSurface().Surface().Surface()),
+ myIsoU(theIsoType == GeomAbs_IsoU),
+ myParams(theParams),
+ myControlParams(theControlParams),
+ myParamsForbiddenToRemove(theParamsForbiddenToRemove),
+ myControlParamsForbiddenToRemove(theControlParamsForbiddenToRemove),
+ myAllocator(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)),
+ myControlParamsToRemove(new IMeshData::MapOfReal(1, myAllocator))
+ {
+ }
+
+ //! Returns map of parameters supposed to be removed.
+ const Handle(IMeshData::MapOfReal)& GetControlParametersToRemove(
+ const IMeshTools_Parameters& theParameters)
+ {
+ myParameters = theParameters;
+
+ if (myParameters.MinSize <= Precision::Confusion())
+ {
+ myParameters.MinSize =
+ Max(IMeshTools_Parameters::RelMinSize() * myParameters.Deflection,
+ Precision::Confusion());
+ }
+
+ Standard_Integer aStartIndex, aEndIndex;
+ if (myIsoU)
+ {
+ aStartIndex = 1;
+ aEndIndex = myParams->Length();
+ }
+ else
+ {
+ aStartIndex = 2;
+ aEndIndex = myParams->Length() - 1;
+ }
+
+ for (Standard_Integer i = aStartIndex; i <= aEndIndex; ++i)
+ {
+ myCurrParam = myParams->Value(i);
+ myIso = new GeomAdaptor_Curve(myIsoU ? mySurface->UIso(myCurrParam) : mySurface->VIso(myCurrParam));
+
+ myPrevControlParam = myControlParams->Value(1);
+ myIso->D1(myPrevControlParam, myPrevControlPnt, myPrevControlVec);
+ for (Standard_Integer j = 2; j <= myControlParams->Length();)
+ {
+ j += checkControlPointAndMoveOn(j);
+ }
+ }
+
+ return myControlParamsToRemove;
+ }
+
+ private:
+
+ //! Checks the given control point for deviation.
+ //! Returns number of steps to be used to move point iterator.
+ Standard_Integer checkControlPointAndMoveOn(const Standard_Integer theIndex)
+ {
+ Standard_Integer aMoveSteps = 0;
+ myCurrControlParam = myControlParams->Value(theIndex);
+ myIso->D1(myCurrControlParam, myCurrControlPnt, myCurrControlVec);
+
+ const Standard_Real aMidParam = 0.5 * (myPrevControlParam + myCurrControlParam);
+ const gp_Pnt aMidPnt = myIso->Value(aMidParam);
+
+ const Standard_Real aSqDist = BRepMesh_GeomTool::SquareDeflectionOfSegment(
+ myPrevControlPnt, myCurrControlPnt, aMidPnt);
+
+ const Standard_Real aSqMaxDeflection = myDFace->GetDeflection() * myDFace->GetDeflection();
+ if ((aSqDist > aSqMaxDeflection) &&
+ aSqDist > myParameters.MinSize * myParameters.MinSize)
+ {
+ // insertion
+ myControlParams->InsertBefore(theIndex, aMidParam);
+ }
+ else
+ {
+ // Here we should leave at least 3 parameters as far as
+ // we must have at least one parameter related to surface
+ // internals in order to prevent movement of triangle body
+ // outside the surface in case of highly curved ones, e.g.
+ // BSpline springs.
+ if (aSqDist < aSqMaxDeflection &&
+ myControlParams->Length() > 3 &&
+ theIndex < myControlParams->Length())
+ {
+ // Remove too dense points
+ const Standard_Real aTmpParam = myControlParams->Value(theIndex + 1);
+ if (checkParameterForDeflectionAndUpdateCache(aTmpParam))
+ {
+ ++aMoveSteps;
+ }
+ }
+
+ myPrevControlParam = myCurrControlParam;
+ myPrevControlPnt = myCurrControlPnt;
+ myPrevControlVec = myCurrControlVec;
+
+ ++aMoveSteps;
+ }
+
+ return aMoveSteps;
+ }
+
+ //! Checks whether the given param suits specified deflection. Updates cache.
+ Standard_Boolean checkParameterForDeflectionAndUpdateCache(const Standard_Real theParam)
+ {
+ gp_Pnt aTmpPnt;
+ gp_Vec aTmpVec;
+ myIso->D1(theParam, aTmpPnt, aTmpVec);
+
+ const Standard_Real aTmpMidParam = 0.5 * (myPrevControlParam + theParam);
+ const gp_Pnt aTmpMidPnt = myIso->Value(aTmpMidParam);
+
+ // Lets check next parameter.
+ // If it also fits deflection, we can remove previous parameter.
+ const Standard_Real aSqDist = BRepMesh_GeomTool::SquareDeflectionOfSegment(
+ myPrevControlPnt, aTmpPnt, aTmpMidPnt);
+
+ if (aSqDist < myDFace->GetDeflection() * myDFace->GetDeflection())
+ {
+ // Lets check parameters for angular deflection.
+ if (myPrevControlVec.SquareMagnitude() < gp::Resolution() ||
+ aTmpVec.SquareMagnitude() < gp::Resolution() ||
+ myPrevControlVec.Angle(aTmpVec) < myParameters.Angle)
+ {
+ // For current Iso line we can remove this parameter.
+ myControlParamsToRemove->Add(myCurrControlParam);
+ myCurrControlParam = theParam;
+ myCurrControlPnt = aTmpPnt;
+ myCurrControlVec = aTmpVec;
+ return Standard_True;
+ }
+ else
+ {
+ // We have found a place on the surface refusing
+ // removement of this parameter.
+ myParamsForbiddenToRemove ->Add(myCurrParam);
+ myControlParamsForbiddenToRemove->Add(myCurrControlParam);
+ }
+ }
+
+ return Standard_False;
+ }
+
+ private:
+
+ IMeshData::IFaceHandle myDFace;
+ Handle(Geom_Surface) mySurface;
+ Standard_Boolean myIsoU;
+ Handle(IMeshData::SequenceOfReal) myParams;
+ Handle(IMeshData::SequenceOfReal) myControlParams;
+
+ Handle(IMeshData::MapOfReal) myParamsForbiddenToRemove;
+ Handle(IMeshData::MapOfReal) myControlParamsForbiddenToRemove;
+
+ Handle(NCollection_IncAllocator) myAllocator;
+ Handle(IMeshData::MapOfReal) myControlParamsToRemove;
+
+
+ IMeshTools_Parameters myParameters;
+ NCollection_Handle<GeomAdaptor_Curve> myIso;
+
+ Standard_Real myCurrParam;
+
+ Standard_Real myCurrControlParam;
+ gp_Pnt myCurrControlPnt;
+ gp_Vec myCurrControlVec;
+
+ Standard_Real myPrevControlParam;
+ gp_Pnt myPrevControlPnt;
+ gp_Vec myPrevControlVec;
+ };
+
+ //! Adds param to map if it fits specified range.
+ inline Standard_Boolean addParam(
+ const Standard_Real& theParam,
+ const std::pair<Standard_Real, Standard_Real>& theRange,
+ IMeshData::IMapOfReal& theParams)
+ {
+ if (theParam < theRange.first ||
+ theParam > theRange.second)
+ {
+ return Standard_False;
+ }
+
+ theParams.Add(theParam);
+ return Standard_True;
+ }
+
+ //! Initializes parameters map using CN intervals.
+ inline Standard_Boolean initParamsFromIntervals(
+ const TColStd_Array1OfReal& theIntervals,
+ const std::pair<Standard_Real, Standard_Real>& theRange,
+ const Standard_Boolean isSplitIntervals,
+ IMeshData::IMapOfReal& theParams)
+ {
+ Standard_Boolean isAdded = Standard_False;
+
+ for (Standard_Integer i = theIntervals.Lower(); i <= theIntervals.Upper(); ++i)
+ {
+ const Standard_Real aStartParam = theIntervals.Value(i);
+ if (addParam(aStartParam, theRange, theParams))
+ {
+ isAdded = Standard_True;
+ }
+
+ if (isSplitIntervals && i < theIntervals.Upper())
+ {
+ const Standard_Real aMidParam = (aStartParam + theIntervals.Value(i + 1)) / 2.;
+ if (addParam(aMidParam, theRange, theParams))
+ {
+ isAdded = Standard_True;
+ }
+ }
+ }
+
+ return isAdded;
+ }
+}
+
+//=======================================================================
+// Function: AdjustRange
+// Purpose :
+//=======================================================================
+void BRepMesh_NURBSRangeSplitter::AdjustRange()
+{
+ BRepMesh_DefaultRangeSplitter::AdjustRange();
+ mySurfaceType = GetSurface()->GetType();
+
+ if (mySurfaceType == GeomAbs_BezierSurface)
+ {
+ const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
+ const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
+
+ myIsValid = !(aRangeU.first < -0.5 ||
+ aRangeU.second > 1.5 ||
+ aRangeV.first < -0.5 ||
+ aRangeV.second > 1.5);
+ }
+}
+
+//=======================================================================
+// Function: GenerateSurfaceNodes
+// Purpose :
+//=======================================================================
+Handle(IMeshData::ListOfPnt2d) BRepMesh_NURBSRangeSplitter::GenerateSurfaceNodes(
+ const IMeshTools_Parameters& theParameters) const
+{
+ initParameters();
+
+ const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
+ const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
+ const std::pair<Standard_Real, Standard_Real>& aDelta = GetDelta ();
+
+ const Standard_Real aDefFace = GetDFace()->GetDeflection();
+ const Handle(BRepAdaptor_HSurface)& gFace = GetSurface();
+ Handle(Geom_Surface) aSurface = gFace->ChangeSurface().Surface().Surface();
+
+ const Handle(NCollection_IncAllocator) aTmpAlloc =
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
+
+ const Handle(IMeshData::SequenceOfReal) aParams[2] = {
+ computeGrainAndFilterParameters(GetParametersU(), gFace->UResolution(aDefFace),
+ (aRangeU.second - aRangeU.first), aDelta.first, theParameters, aTmpAlloc),
+
+ computeGrainAndFilterParameters(GetParametersV(), gFace->VResolution(aDefFace),
+ (aRangeV.second - aRangeV.first), aDelta.second, theParameters, aTmpAlloc)
+ };
+
+ // check intermediate isolines
+ Handle(IMeshData::MapOfReal) aFixedParams[2] = {
+ new IMeshData::MapOfReal(1, aTmpAlloc),
+ new IMeshData::MapOfReal(1, aTmpAlloc)
+ };
+
+ const Handle(IMeshData::MapOfReal) aParamsToRemove[2] = {
+ AnalyticalFilter(GetDFace(), GeomAbs_IsoV, aParams[1], aParams[0],
+ aFixedParams[1], aFixedParams[0]).GetControlParametersToRemove(theParameters),
+
+ AnalyticalFilter(GetDFace(), GeomAbs_IsoU, aParams[0], aParams[1],
+ aFixedParams[0], aFixedParams[1]).GetControlParametersToRemove(theParameters),
+ };
+
+ aParamsToRemove[0]->Subtract(*aFixedParams[0]);
+ aParamsToRemove[1]->Subtract(*aFixedParams[1]);
+
+ // insert nodes of the regular grid
+ Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE));
+
+ // insert nodes of the regular grid
+ for (Standard_Integer i = 1; i <= aParams[0]->Length(); ++i)
+ {
+ const Standard_Real aParam1 = aParams[0]->Value(i);
+ if (aParamsToRemove[0]->Contains(aParam1))
+ {
+ continue;
+ }
+
+ for (Standard_Integer j = 1; j <= aParams[1]->Length(); ++j)
+ {
+ const Standard_Real aParam2 = aParams[1]->Value(j);
+ if (aParamsToRemove[1]->Contains(aParam2))
+ {
+ continue;
+ }
+
+ aNodes->Append(gp_Pnt2d(aParam1, aParam2));
+ }
+ }
+
+ return aNodes;
+}
+
+//=======================================================================
+// Function: initParameters
+// Purpose :
+//=======================================================================
+void BRepMesh_NURBSRangeSplitter::initParameters() const
+{
+ const Handle(BRepAdaptor_HSurface)& aSurface = GetSurface();
+
+ const GeomAbs_Shape aContinuity = GeomAbs_CN;
+ const std::pair<Standard_Integer, Standard_Integer> aIntervalsNb(
+ aSurface->NbUIntervals(aContinuity),
+ aSurface->NbVIntervals(aContinuity)
+ );
+
+ TColStd_Array1OfReal aIntervals[2] = {
+ TColStd_Array1OfReal(1, aIntervalsNb.first + 1),
+ TColStd_Array1OfReal(1, aIntervalsNb.second + 1)
+ };
+
+ aSurface->UIntervals(aIntervals[0], aContinuity);
+ aSurface->VIntervals(aIntervals[1], aContinuity);
+
+ Standard_Boolean isSplitIntervals =
+ (aIntervalsNb.first > 1 || aIntervalsNb.second > 1);
+
+ if (!isSplitIntervals &&
+ (aSurface->GetType() == GeomAbs_BezierSurface ||
+ aSurface->GetType() == GeomAbs_BSplineSurface))
+ {
+ isSplitIntervals = (aSurface->NbUPoles() > 2 && aSurface->NbVPoles() > 2);
+ }
+
+ initParamsFromIntervals(aIntervals[0], GetRangeU(), isSplitIntervals,
+ const_cast<IMeshData::IMapOfReal&>(GetParametersU()));
+
+ initParamsFromIntervals(aIntervals[1], GetRangeV(), isSplitIntervals,
+ const_cast<IMeshData::IMapOfReal&>(GetParametersV()));
+}
+
+//=======================================================================
+//function : computeGrainAndFilterParameters
+//purpose :
+//=======================================================================
+Handle(IMeshData::SequenceOfReal) BRepMesh_NURBSRangeSplitter::computeGrainAndFilterParameters(
+ const IMeshData::IMapOfReal& theSourceParams,
+ const Standard_Real theTol2d,
+ const Standard_Real theRangeDiff,
+ const Standard_Real theDelta,
+ const IMeshTools_Parameters& theParameters,
+ const Handle(NCollection_IncAllocator)& theAllocator) const
+{
+ // Sort and filter sequence of parameters
+ Standard_Real aMinDiff = Precision::PConfusion();
+ if (theDelta < 1.)
+ {
+ aMinDiff /= theDelta;
+ }
+
+ const Standard_Real aMinSize =
+ theParameters.MinSize > Precision::Confusion() ? theParameters.MinSize :
+ Max(IMeshTools_Parameters::RelMinSize() * theParameters.Deflection,
+ Precision::Confusion());
+
+ aMinDiff = Max(aMinSize, aMinDiff);
+
+ const Standard_Real aDiffMaxLim = 0.1 * theRangeDiff;
+ const Standard_Real aDiffMinLim = Max(0.005 * theRangeDiff, 2. * theTol2d);
+ const Standard_Real aDiff = Max(aMinSize, Min(aDiffMaxLim, aDiffMinLim));
+ return filterParameters(theSourceParams, aMinDiff, aDiff, theAllocator);
+}
+
+//=======================================================================
+//function : filterParameters
+//purpose :
+//=======================================================================
+Handle(IMeshData::SequenceOfReal) BRepMesh_NURBSRangeSplitter::filterParameters(
+ const IMeshData::IMapOfReal& theParams,
+ const Standard_Real theMinDist,
+ const Standard_Real theFilterDist,
+ const Handle(NCollection_IncAllocator)& theAllocator) const
+{
+ Handle(IMeshData::SequenceOfReal) aResult = new IMeshData::SequenceOfReal(theAllocator);
+
+ // Sort sequence of parameters
+ const Standard_Integer anInitLen = theParams.Extent();
+
+ if (anInitLen < 1)
+ {
+ return aResult;
+ }
+
+ TColStd_Array1OfReal aParamArray(1, anInitLen);
+ Standard_Integer j;
+ for (j = 1; j <= anInitLen; j++)
+ aParamArray(j) = theParams(j);
+
+ std::sort(aParamArray.begin(), aParamArray.end());
+
+ // mandatory pre-filtering using the first (minimal) filter value
+ Standard_Integer aParamLength = 1;
+ for (j = 2; j <= anInitLen; j++)
+ {
+ if ((aParamArray(j) - aParamArray(aParamLength)) > theMinDist)
+ {
+ if (++aParamLength < j)
+ aParamArray(aParamLength) = aParamArray(j);
+ }
+ }
+
+ //perform filtering on series
+ Standard_Real aLastAdded, aLastCandidate;
+ Standard_Boolean isCandidateDefined = Standard_False;
+ aLastAdded = aParamArray(1);
+ aLastCandidate = aLastAdded;
+ aResult->Append(aLastAdded);
+
+ for (j = 2; j < aParamLength; j++)
+ {
+ Standard_Real aVal = aParamArray(j);
+ if (aVal - aLastAdded > theFilterDist)
+ {
+ //adds the parameter
+ if (isCandidateDefined)
+ {
+ aLastAdded = aLastCandidate;
+ isCandidateDefined = Standard_False;
+ j--;
+ }
+ else
+ {
+ aLastAdded = aVal;
+ }
+ aResult->Append(aLastAdded);
+ continue;
+ }
+
+ aLastCandidate = aVal;
+ isCandidateDefined = Standard_True;
+ }
+ aResult->Append(aParamArray(aParamLength));
+
+ return aResult;
+}
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_NURBSRangeSplitter_HeaderFile
+#define _BRepMesh_NURBSRangeSplitter_HeaderFile
+
+#include <BRepMesh_UVParamRangeSplitter.hxx>
+#include <IMeshData_Types.hxx>
+#include <IMeshTools_Parameters.hxx>
+
+//! Auxiliary class extending UV range splitter in order to generate
+//! internal nodes for NURBS surface.
+class BRepMesh_NURBSRangeSplitter : public BRepMesh_UVParamRangeSplitter
+{
+public:
+
+ //! Constructor.
+ BRepMesh_NURBSRangeSplitter()
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_NURBSRangeSplitter()
+ {
+ }
+
+ //! Updates discrete range of surface according to its geometric range.
+ Standard_EXPORT virtual void AdjustRange() Standard_OVERRIDE;
+
+ //! Returns list of nodes generated using surface data and specified parameters.
+ Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes(
+ const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE;
+
+protected:
+
+ //! Initializes U and V parameters lists using CN continuity intervals.
+ Standard_EXPORT virtual void initParameters() const;
+
+private:
+
+ //! Computes parameters of filter and applies it to the source parameters.
+ Handle(IMeshData::SequenceOfReal) computeGrainAndFilterParameters(
+ const IMeshData::IMapOfReal& theSourceParams,
+ const Standard_Real theTol2d,
+ const Standard_Real theRangeDiff,
+ const Standard_Real theDelta,
+ const IMeshTools_Parameters& theParameters,
+ const Handle(NCollection_IncAllocator)& theAllocator) const;
+
+ //! Filters parameters in order to avoid too dence distribution.
+ Handle(IMeshData::SequenceOfReal) filterParameters(
+ const IMeshData::IMapOfReal& theParams,
+ const Standard_Real theMinDist,
+ const Standard_Real theFilterDist,
+ const Handle(NCollection_IncAllocator)& theAllocator) const;
+
+private:
+
+ GeomAbs_SurfaceType mySurfaceType;
+};
+
+#endif
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_NodeInsertionMeshAlgo_HeaderFile
+#define _BRepMesh_NodeInsertionMeshAlgo_HeaderFile
+
+#include <BRepMesh_Classifier.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_PCurve.hxx>
+#include <BRepMesh_Vertex.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <BRep_Tool.hxx>
+#include <Standard_ErrorHandler.hxx>
+#include <BRepMesh_Delaun.hxx>
+
+//! Extends base meshing algo in order to enable possibility
+//! of addition of free vertices into the mesh.
+template<class RangeSplitter, class BaseAlgo>
+class BRepMesh_NodeInsertionMeshAlgo : public BaseAlgo
+{
+public:
+
+ //! Constructor.
+ BRepMesh_NodeInsertionMeshAlgo()
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_NodeInsertionMeshAlgo()
+ {
+ }
+
+ //! Performs processing of the given face.
+ virtual void Perform(
+ const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters) Standard_OVERRIDE
+ {
+ myRangeSplitter.Reset(theDFace, theParameters);
+ myClassifier = new BRepMesh_Classifier;
+ BaseAlgo::Perform(theDFace, theParameters);
+ myClassifier.Nullify();
+ }
+
+protected:
+
+ typedef NCollection_Shared<NCollection_Sequence<const gp_Pnt2d*> > SequenceOfPnt2d;
+
+ //! Performs initialization of data structure using existing model data.
+ virtual Standard_Boolean initDataStructure() Standard_OVERRIDE
+ {
+ Handle(NCollection_IncAllocator) aTmpAlloc = new NCollection_IncAllocator;
+
+ const IMeshData::IFaceHandle& aDFace = this->getDFace();
+ NCollection_Array1<Handle(SequenceOfPnt2d)> aWires(0, aDFace->WiresNb() - 1);
+ for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
+ {
+ const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
+ if (aDWire->IsSet(IMeshData_SelfIntersectingWire) ||
+ (aDWire->IsSet(IMeshData_OpenWire) && aWireIt != 0))
+ {
+ continue;
+ }
+
+ aWires(aWireIt) = collectWirePoints(aDWire, aTmpAlloc);
+ }
+
+ myRangeSplitter.AdjustRange();
+ if (!myRangeSplitter.IsValid())
+ {
+ aDFace->SetStatus(IMeshData_Failure);
+ return Standard_False;
+ }
+
+ const std::pair<Standard_Real, Standard_Real>& aDelta = myRangeSplitter.GetDelta();
+ const std::pair<Standard_Real, Standard_Real>& aTolUV = myRangeSplitter.GetToleranceUV();
+ const Standard_Real uCellSize = 14.0 * aTolUV.first;
+ const Standard_Real vCellSize = 14.0 * aTolUV.second;
+
+ this->getStructure()->Data()->SetCellSize (uCellSize / aDelta.first, vCellSize / aDelta.second);
+ this->getStructure()->Data()->SetTolerance(aTolUV.first / aDelta.first, aTolUV.second / aDelta.second);
+
+ for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
+ {
+ const Handle(SequenceOfPnt2d)& aWire = aWires(aWireIt);
+ if (!aWire.IsNull() && !aWire->IsEmpty())
+ {
+ myClassifier->RegisterWire(*aWire, aTolUV,
+ myRangeSplitter.GetRangeU(),
+ myRangeSplitter.GetRangeV());
+ }
+ }
+
+ if (this->getParameters().InternalVerticesMode)
+ {
+ insertInternalVertices();
+ }
+
+ return BaseAlgo::initDataStructure();
+ }
+
+ //! Adds the given 2d point to mesh data structure.
+ //! Returns index of node in the structure.
+ virtual Standard_Integer addNodeToStructure(
+ const gp_Pnt2d& thePoint,
+ const Standard_Integer theLocation3d,
+ const BRepMesh_DegreeOfFreedom theMovability,
+ const Standard_Boolean isForceAdd) Standard_OVERRIDE
+ {
+ return BaseAlgo::addNodeToStructure(
+ myRangeSplitter.Scale(thePoint, Standard_True),
+ theLocation3d, theMovability, isForceAdd);
+ }
+
+ //! Returns 2d point associated to the given vertex.
+ virtual gp_Pnt2d getNodePoint2d(
+ const BRepMesh_Vertex& theVertex) const Standard_OVERRIDE
+ {
+ return myRangeSplitter.Scale(theVertex.Coord(), Standard_False);
+ }
+
+ //! Returns range splitter.
+ const RangeSplitter& getRangeSplitter() const
+ {
+ return myRangeSplitter;
+ }
+
+ //! Returns classifier.
+ const Handle(BRepMesh_Classifier)& getClassifier() const
+ {
+ return myClassifier;
+ }
+
+private:
+
+ //! Creates collection of points representing discrete wire.
+ Handle(SequenceOfPnt2d) collectWirePoints(
+ const IMeshData::IWireHandle& theDWire,
+ const Handle(NCollection_IncAllocator)& theAllocator)
+ {
+ Handle(SequenceOfPnt2d) aWirePoints = new SequenceOfPnt2d(theAllocator);
+ for (Standard_Integer aEdgeIt = 0; aEdgeIt < theDWire->EdgesNb(); ++aEdgeIt)
+ {
+ const IMeshData::IEdgeHandle aDEdge = theDWire->GetEdge(aEdgeIt);
+ const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(
+ this->getDFace().get(), theDWire->GetEdgeOrientation(aEdgeIt));
+
+ Standard_Integer aPointIt, aEndIndex, aInc;
+ if (aPCurve->IsForward())
+ {
+ // For an infinite cylinder (for example)
+ // aPCurve->ParametersNb() == 0
+
+ aEndIndex = aPCurve->ParametersNb() - 1;
+ aPointIt = Min(0, aEndIndex);
+ aInc = 1;
+ }
+ else
+ {
+ // For an infinite cylinder (for example)
+ // aPCurve->ParametersNb() == 0
+
+ aPointIt = aPCurve->ParametersNb() - 1;
+ aEndIndex = Min(0, aPointIt);
+ aInc = -1;
+ }
+
+ // For an infinite cylinder (for example)
+ // this cycle will not be executed.
+ for (; aPointIt != aEndIndex; aPointIt += aInc)
+ {
+ const gp_Pnt2d& aPnt2d = aPCurve->GetPoint(aPointIt);
+ aWirePoints->Append(&aPnt2d);
+ myRangeSplitter.AddPoint(aPnt2d);
+ }
+ }
+
+ return aWirePoints;
+ }
+
+ //! Iterates over internal vertices of a face and
+ //! creates corresponding nodes in data structure.
+ void insertInternalVertices()
+ {
+ TopExp_Explorer aExplorer(this->getDFace()->GetFace(), TopAbs_VERTEX, TopAbs_EDGE);
+ for (; aExplorer.More(); aExplorer.Next())
+ {
+ const TopoDS_Vertex& aVertex = TopoDS::Vertex(aExplorer.Current());
+ if (aVertex.Orientation() != TopAbs_INTERNAL)
+ {
+ continue;
+ }
+
+ insertInternalVertex(aVertex);
+ }
+ }
+
+ //! Inserts the given vertex into mesh.
+ void insertInternalVertex(const TopoDS_Vertex& theVertex)
+ {
+ try
+ {
+ OCC_CATCH_SIGNALS
+
+ gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, this->getDFace()->GetFace());
+ // check UV values for internal vertices
+ if (myClassifier->Perform(aPnt2d) != TopAbs_IN)
+ return;
+
+ this->registerNode(BRep_Tool::Pnt(theVertex), aPnt2d,
+ BRepMesh_Fixed, Standard_False);
+ }
+ catch (Standard_Failure)
+ {
+ }
+ }
+
+private:
+
+ RangeSplitter myRangeSplitter;
+ Handle(BRepMesh_Classifier) myClassifier;
+};
+
+#endif
//! Constructs a link between two vertices.
BRepMesh_OrientedEdge(
- const Standard_Integer theFirstNode,
- const Standard_Integer theLastNode)
+ const Standard_Integer theFirstNode,
+ const Standard_Integer theLastNode)
: myFirstNode(theFirstNode),
myLastNode(theLastNode)
{
//! Returns hash code for this edge.
//! @param theUpper upper index in the container.
//! @return hash code.
- Standard_Integer HashCode(const Standard_Integer theUpper) const
+ inline Standard_Integer HashCode(const Standard_Integer theUpper) const
{
return ::HashCode(myFirstNode + myLastNode, theUpper);
}
}
//! Alias for IsEqual.
- Standard_Boolean operator ==(const BRepMesh_OrientedEdge& Other) const
+ inline Standard_Boolean operator ==(const BRepMesh_OrientedEdge& Other) const
{
return IsEqual(Other);
}
+++ /dev/null
-// Copyright (c) 2013 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef _BRepMesh_PairOfPolygon_HeaderFile
-#define _BRepMesh_PairOfPolygon_HeaderFile
-
-#include <Standard.hxx>
-#include <Standard_DefineAlloc.hxx>
-#include <Standard_Macro.hxx>
-
-class Poly_PolygonOnTriangulation;
-
-class BRepMesh_PairOfPolygon
-{
-public:
-
- DEFINE_STANDARD_ALLOC
-
- //! Constructor. Creates empty pair with null fileds.
- BRepMesh_PairOfPolygon()
- {
- }
-
- //! Clears pair handles.
- inline void Clear()
- {
- myFirst.Nullify();
- myLast.Nullify();
- }
-
- //! Sets the first element of the pair.
- //! If last element is empty, also assignes the given polygon to it.
- //! @param thePolygon plygon to be set.
- inline void Prepend(const Handle(Poly_PolygonOnTriangulation)& thePolygon)
- {
- myFirst = thePolygon;
-
- if (myLast.IsNull())
- myLast = thePolygon;
- }
-
- //! Sets the last element of the pair.
- //! If first element is empty, also assignes the given polygon to it.
- //! @param thePolygon plygon to be set.
- inline void Append(const Handle(Poly_PolygonOnTriangulation)& thePolygon)
- {
- if (myFirst.IsNull())
- myFirst = thePolygon;
-
- myLast = thePolygon;
- }
-
- //! Returns first polygon on triangulation.
- inline const Handle(Poly_PolygonOnTriangulation)& First() const
- {
- return myFirst;
- }
-
- //! Returns last polygon on triangulation.
- inline const Handle(Poly_PolygonOnTriangulation)& Last() const
- {
- return myLast;
- }
-
-private:
-
- Handle(Poly_PolygonOnTriangulation) myFirst;
- Handle(Poly_PolygonOnTriangulation) myLast;
-};
-
-#endif
#include <BRepMesh_SelectorOfDataStructureOfDelaun.hxx>
#include <BRepMesh_PairOfIndex.hxx>
+#include <BRepMesh_Edge.hxx>
//=======================================================================
//function : Default constructor
//purpose :
//=======================================================================
BRepMesh_SelectorOfDataStructureOfDelaun::BRepMesh_SelectorOfDataStructureOfDelaun()
-: myAllocator(new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE)),
- myNodes (10, myAllocator),
- myLinks (10, myAllocator),
- myElements(10, myAllocator),
- myFrontier(10, myAllocator)
{
}
//=======================================================================
BRepMesh_SelectorOfDataStructureOfDelaun::BRepMesh_SelectorOfDataStructureOfDelaun(
const Handle(BRepMesh_DataStructureOfDelaun)& theMesh)
-: myAllocator(new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE)),
- myMesh (theMesh),
- myNodes (10, myAllocator),
- myLinks (10, myAllocator),
- myElements(10, myAllocator),
- myFrontier(10, myAllocator)
+ : myMesh(theMesh)
{
}
void BRepMesh_SelectorOfDataStructureOfDelaun::NeighboursOfNode(
const Standard_Integer theNodeIndex)
{
- BRepMesh::ListOfInteger::Iterator aLinkIt(
+ IMeshData::ListOfInteger::Iterator aLinkIt(
myMesh->LinksConnectedTo(theNodeIndex));
for (; aLinkIt.More(); aLinkIt.Next())
void BRepMesh_SelectorOfDataStructureOfDelaun::NeighboursByEdgeOf(
const BRepMesh_Triangle& theElement)
{
- Standard_Integer e[3];
- Standard_Boolean o[3];
- theElement.Edges(e, o);
-
+ const Standard_Integer(&e)[3] = theElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
elementsOfLink(e[i]);
}
#ifndef _BRepMesh_SelectorOfDataStructureOfDelaun_HeaderFile
#define _BRepMesh_SelectorOfDataStructureOfDelaun_HeaderFile
-#include <Standard.hxx>
-#include <Standard_DefineAlloc.hxx>
-#include <Standard_Macro.hxx>
+#include <Standard_Transient.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
-#include <BRepMesh.hxx>
-#include <Standard_Integer.hxx>
#include <BRepMesh_Triangle.hxx>
+#include <IMeshData_Types.hxx>
class BRepMesh_Vertex;
class BRepMesh_Edge;
//! Describes a selector and an iterator on a
//! selector of components of a mesh.
-class BRepMesh_SelectorOfDataStructureOfDelaun
+class BRepMesh_SelectorOfDataStructureOfDelaun : public Standard_Transient
{
public:
- DEFINE_STANDARD_ALLOC
-
//! Default constructor.
Standard_EXPORT BRepMesh_SelectorOfDataStructureOfDelaun();
}
//! Returns selected nodes.
- inline const BRepMesh::MapOfInteger& Nodes() const
+ inline const IMeshData::MapOfInteger& Nodes() const
{
return myNodes;
}
//! Returns selected links.
- inline const BRepMesh::MapOfInteger& Links() const
+ inline const IMeshData::MapOfInteger& Links() const
{
return myLinks;
}
//! Returns selected elements.
- inline const BRepMesh::MapOfInteger& Elements() const
+ inline const IMeshData::MapOfInteger& Elements() const
{
return myElements;
}
//! Gives the list of incices of frontier links.
- inline const BRepMesh::MapOfInteger& FrontierLinks() const
+ inline const IMeshData::MapOfInteger& FrontierLinks() const
{
return myFrontier;
}
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_SelectorOfDataStructureOfDelaun, Standard_Transient)
+
private:
//! Collects elements connected to link with the given index.
void elementsOfLink(const Standard_Integer theIndex);
private:
- Handle(NCollection_IncAllocator) myAllocator;
Handle(BRepMesh_DataStructureOfDelaun) myMesh;
- BRepMesh::MapOfInteger myNodes;
- BRepMesh::MapOfInteger myLinks;
- BRepMesh::MapOfInteger myElements;
- BRepMesh::MapOfInteger myFrontier;
+ IMeshData::MapOfInteger myNodes;
+ IMeshData::MapOfInteger myLinks;
+ IMeshData::MapOfInteger myElements;
+ IMeshData::MapOfInteger myFrontier;
};
#endif
-// Copyright (c) 1995-1999 Matra Datavision
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
//
// This file is part of Open CASCADE Technology software library.
//
// commercial license or contractual agreement.
#include <BRepMesh_ShapeTool.hxx>
-
-#include <Bnd_Box.hxx>
-#include <TopoDS_Edge.hxx>
-#include <BRepBndLib.hxx>
-#include <TopoDS.hxx>
-#include <BRep_Tool.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_PCurve.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
-#include <BRepAdaptor_HSurface.hxx>
-#include <TColgp_Array1OfPnt.hxx>
-#include <Poly_Triangulation.hxx>
+#include <BRep_Tool.hxx>
#include <BRep_Builder.hxx>
-#include <TopExp.hxx>
+#include <ShapeAnalysis_Edge.hxx>
#include <BRepAdaptor_Curve.hxx>
+#include <Precision.hxx>
+#include <Bnd_Box.hxx>
-namespace {
+namespace
+{
//! Auxilary struct to take a tolerance of edge.
struct EdgeTolerance
{
}
//=======================================================================
-//function : BoxMaxDimension
+//function : MaxFaceTolerance
//purpose :
//=======================================================================
Standard_Real BRepMesh_ShapeTool::MaxFaceTolerance(const TopoDS_Face& theFace)
Standard_Real aMaxTolerance = BRep_Tool::Tolerance(theFace);
Standard_Real aTolerance = Max(
- MaxTolerance<TopAbs_EDGE, EdgeTolerance >(theFace),
+ MaxTolerance<TopAbs_EDGE, EdgeTolerance >(theFace),
MaxTolerance<TopAbs_VERTEX, VertexTolerance>(theFace));
return Max(aMaxTolerance, aTolerance);
void BRepMesh_ShapeTool::BoxMaxDimension(const Bnd_Box& theBox,
Standard_Real& theMaxDimension)
{
- if(theBox.IsVoid())
+ if (theBox.IsVoid())
return;
Standard_Real aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ;
}
//=======================================================================
-//function : RelativeEdgeDeflection
+//function : CheckAndUpdateFlags
//purpose :
//=======================================================================
-Standard_Real BRepMesh_ShapeTool::RelativeEdgeDeflection(
- const TopoDS_Edge& theEdge,
- const Standard_Real theDeflection,
- const Standard_Real theMaxShapeSize,
- Standard_Real& theAdjustmentCoefficient)
+void BRepMesh_ShapeTool::CheckAndUpdateFlags (
+ const IMeshData::IEdgeHandle& theEdge,
+ const IMeshData::IPCurveHandle& thePCurve)
{
- theAdjustmentCoefficient = 1.;
- Standard_Real aDefEdge = theDeflection;
- if(theEdge.IsNull())
- return aDefEdge;
-
- Bnd_Box aBox;
- BRepBndLib::Add(theEdge, aBox, Standard_False);
- BoxMaxDimension(aBox, aDefEdge);
-
- // Adjust resulting value in relation to the total size
- theAdjustmentCoefficient = theMaxShapeSize / (2 * aDefEdge);
- if (theAdjustmentCoefficient < 0.5)
- theAdjustmentCoefficient = 0.5;
- else if (theAdjustmentCoefficient > 2.)
- theAdjustmentCoefficient = 2.;
-
- return (theAdjustmentCoefficient * aDefEdge * theDeflection);
-}
-
-//=======================================================================
-//function : FindUV
-//purpose :
-//=======================================================================
-gp_XY BRepMesh_ShapeTool::FindUV(
- const Standard_Integer theIndexOfPnt3d,
- const gp_Pnt2d& thePnt2d,
- const Standard_Real theMinDistance,
- const Handle(BRepMesh_FaceAttribute)& theFaceAttribute)
-{
- const gp_XY& aPnt2d = thePnt2d.Coord();
- BRepMesh::HDMapOfIntegerListOfXY& aLocation2D =
- theFaceAttribute->ChangeLocation2D();
-
- if (!aLocation2D->IsBound(theIndexOfPnt3d))
+ if (!theEdge->GetSameParam () &&
+ !theEdge->GetSameRange () &&
+ theEdge->GetDegenerated ())
{
- BRepMesh::ListOfXY aPoints2d;
- aPoints2d.Append(aPnt2d);
- aLocation2D->Bind(theIndexOfPnt3d, aPoints2d);
- return aPnt2d;
+ // Nothing to do worse.
+ return;
}
- BRepMesh::ListOfXY& aPoints2d = aLocation2D->ChangeFind(theIndexOfPnt3d);
+ const TopoDS_Edge& aEdge = theEdge->GetEdge ();
+ const TopoDS_Face& aFace = thePCurve->GetFace ()->GetFace ();
- // Find the most closest 2d point to the given one.
- gp_XY aUV;
- Standard_Real aMinDist = RealLast();
- BRepMesh::ListOfXY::Iterator aPoint2dIt(aPoints2d);
- for (; aPoint2dIt.More(); aPoint2dIt.Next())
+ Handle (Geom_Curve) aCurve;
+ Standard_Real aFirstParam, aLastParam;
+ Range (aEdge, aCurve, aFirstParam, aLastParam);
+ if (aCurve.IsNull())
{
- const gp_XY& aCurPnt2d = aPoint2dIt.Value();
+ theEdge->SetDegenerated(Standard_True);
+ return;
+ }
- Standard_Real aDist = (aPnt2d - aCurPnt2d).Modulus();
- if (aDist < aMinDist)
+ BRepAdaptor_Curve aCurveOnSurf(aEdge, aFace);
+ if (theEdge->GetSameParam () || theEdge->GetSameRange ())
+ {
+ if (theEdge->GetSameRange ())
{
- aUV = aCurPnt2d;
- aMinDist = aDist;
+ const Standard_Real aDiffFirst = aCurveOnSurf.FirstParameter () - aFirstParam;
+ const Standard_Real aDiffLast = aCurveOnSurf.LastParameter () - aLastParam;
+ theEdge->SetSameRange (
+ Abs (aDiffFirst) < Precision::PConfusion () &&
+ Abs (aDiffLast ) < Precision::PConfusion ());
+
+ if (!theEdge->GetSameRange())
+ {
+ theEdge->SetSameParam(Standard_False);
+ }
}
}
- const Standard_Real aTolerance = theMinDistance;
-
- // Get face limits
- Standard_Real aDiffU = theFaceAttribute->GetUMax() - theFaceAttribute->GetUMin();
- Standard_Real aDiffV = theFaceAttribute->GetVMax() - theFaceAttribute->GetVMin();
-
- const Standard_Real Utol2d = .5 * aDiffU;
- const Standard_Real Vtol2d = .5 * aDiffV;
-
- const Handle(BRepAdaptor_HSurface)& aSurface = theFaceAttribute->Surface();
- const gp_Pnt aPnt1 = aSurface->Value(aUV.X(), aUV.Y());
- const gp_Pnt aPnt2 = aSurface->Value(aPnt2d.X(), aPnt2d.Y());
-
- //! If selected point is too far from the given one in parametric space
- //! or their positions in 3d are different, add the given point as unique.
- if (Abs(aUV.X() - aPnt2d.X()) > Utol2d ||
- Abs(aUV.Y() - aPnt2d.Y()) > Vtol2d ||
- !aPnt1.IsEqual(aPnt2, aTolerance))
+ if (!theEdge->GetDegenerated ()/* || theEdge->GetSameParam ()*/)
{
- aUV = aPnt2d;
- aPoints2d.Append(aUV);
- }
+ TopoDS_Vertex aStartVertex, aEndVertex;
+ TopExp::Vertices (aEdge, aStartVertex, aEndVertex);
+ if (aStartVertex.IsNull() || aEndVertex.IsNull())
+ {
+ theEdge->SetDegenerated(Standard_True);
+ return;
+ }
- return aUV;
+ if (aStartVertex.IsSame(aEndVertex))
+ {
+ const Standard_Integer aPointsNb = 20;
+ const Standard_Real aVertexTolerance = BRep_Tool::Tolerance (aStartVertex);
+ const Standard_Real aDu = (aLastParam - aFirstParam) / aPointsNb;
+ //const Standard_Real aEdgeTolerance = BRep_Tool::Tolerance (aEdge);
+ //const Standard_Real aSqEdgeTolerance = aEdgeTolerance * aEdgeTolerance;
+
+ gp_Pnt aPrevPnt;
+ aCurve->D0 (aFirstParam, aPrevPnt);
+
+ Standard_Real aLength = 0.0;
+ for (Standard_Integer i = 1; i <= aPointsNb; ++i)
+ {
+ const Standard_Real aParameter = aFirstParam + i * aDu;
+ // Calculation of the length of the edge in 3D
+ // in order to check degenerativity
+ gp_Pnt aPnt;
+ aCurve->D0 (aParameter, aPnt);
+ aLength += aPrevPnt.Distance (aPnt);
+
+ //if (theEdge->GetSameParam ())
+ //{
+ // // Check that points taken at the 3d and pcurve using
+ // // same parameter are within tolerance of an edge.
+ // gp_Pnt aPntOnSurf;
+ // aCurveOnSurf.D0 (aParameter, aPntOnSurf);
+ // theEdge->SetSameParam (aPnt.SquareDistance (aPntOnSurf) < aSqEdgeTolerance);
+ //}
+
+ if (aLength > aVertexTolerance /*&& !theEdge->GetSameParam()*/)
+ {
+ break;
+ }
+
+ aPrevPnt = aPnt;
+ }
+
+ theEdge->SetDegenerated (aLength < aVertexTolerance);
+ }
+ }
}
//=======================================================================
aTrsf.Invert();
TColgp_Array1OfPnt& aNodes = theTriangulation->ChangeNodes();
- for (Standard_Integer i = aNodes.Lower(); i <= aNodes.Upper(); ++i)
+ for (Standard_Integer i = aNodes.Lower(); i <= aNodes.Upper(); ++i)
aNodes(i).Transform(aTrsf);
}
aBuilder.UpdateFace(theFace, theTriangulation);
}
+
//=======================================================================
//function : NullifyFace
//purpose :
//=======================================================================
-void BRepMesh_ShapeTool::NullifyFace(const TopoDS_Face& theFace)
+void BRepMesh_ShapeTool::NullifyFace (const TopoDS_Face& theFace)
{
BRep_Builder aBuilder;
- aBuilder.UpdateFace(theFace, Handle(Poly_Triangulation)());
+ aBuilder.UpdateFace (theFace, Handle (Poly_Triangulation)());
}
//=======================================================================
//function : NullifyEdge
//purpose :
//=======================================================================
-void BRepMesh_ShapeTool::NullifyEdge(
- const TopoDS_Edge& theEdge,
- const Handle(Poly_Triangulation)& theTriangulation,
- const TopLoc_Location& theLocation)
+void BRepMesh_ShapeTool::NullifyEdge (
+ const TopoDS_Edge& theEdge,
+ const Handle (Poly_Triangulation)& theTriangulation,
+ const TopLoc_Location& theLocation)
{
- UpdateEdge(theEdge, Handle(Poly_PolygonOnTriangulation)(),
+ UpdateEdge (theEdge, Handle (Poly_PolygonOnTriangulation)(),
theTriangulation, theLocation);
}
+//=======================================================================
+//function : NullifyEdge
+//purpose :
+//=======================================================================
+void BRepMesh_ShapeTool::NullifyEdge (
+ const TopoDS_Edge& theEdge,
+ const TopLoc_Location& theLocation)
+{
+ BRep_Builder aBuilder;
+ aBuilder.UpdateEdge (theEdge, Handle (Poly_Polygon3D)(), theLocation);
+}
+
//=======================================================================
//function : UpdateEdge
//purpose :
//=======================================================================
-void BRepMesh_ShapeTool::UpdateEdge(
- const TopoDS_Edge& theEdge,
- const Handle(Poly_PolygonOnTriangulation)& thePolygon,
- const Handle(Poly_Triangulation)& theTriangulation,
- const TopLoc_Location& theLocation)
+void BRepMesh_ShapeTool::UpdateEdge (
+ const TopoDS_Edge& theEdge,
+ const Handle (Poly_PolygonOnTriangulation)& thePolygon,
+ const Handle (Poly_Triangulation)& theTriangulation,
+ const TopLoc_Location& theLocation)
{
BRep_Builder aBuilder;
- aBuilder.UpdateEdge(theEdge, thePolygon, theTriangulation, theLocation);
+ aBuilder.UpdateEdge (theEdge, thePolygon, theTriangulation, theLocation);
}
//=======================================================================
//function : UpdateEdge
//purpose :
//=======================================================================
-void BRepMesh_ShapeTool::UpdateEdge(
- const TopoDS_Edge& theEdge,
- const Handle(Poly_PolygonOnTriangulation)& thePolygon1,
- const Handle(Poly_PolygonOnTriangulation)& thePolygon2,
- const Handle(Poly_Triangulation)& theTriangulation,
- const TopLoc_Location& theLocation)
+void BRepMesh_ShapeTool::UpdateEdge (
+ const TopoDS_Edge& theEdge,
+ const Handle (Poly_PolygonOnTriangulation)& thePolygon1,
+ const Handle (Poly_PolygonOnTriangulation)& thePolygon2,
+ const Handle (Poly_Triangulation)& theTriangulation,
+ const TopLoc_Location& theLocation)
{
BRep_Builder aBuilder;
- aBuilder.UpdateEdge(theEdge, thePolygon1, thePolygon2,
+ aBuilder.UpdateEdge (theEdge, thePolygon1, thePolygon2,
theTriangulation, theLocation);
}
+//=======================================================================
+//function : UpdateEdge
+//purpose :
+//=======================================================================
+void BRepMesh_ShapeTool::UpdateEdge(
+ const TopoDS_Edge& theEdge,
+ const Handle(Poly_Polygon3D)& thePolygon)
+{
+ BRep_Builder aBuilder;
+ aBuilder.UpdateEdge(theEdge, thePolygon);
+}
+
//=======================================================================
//function : UseLocation
//purpose :
//=======================================================================
-gp_Pnt BRepMesh_ShapeTool::UseLocation(const gp_Pnt& thePnt,
- const TopLoc_Location& theLoc)
+gp_Pnt BRepMesh_ShapeTool::UseLocation (
+ const gp_Pnt& thePnt,
+ const TopLoc_Location& theLoc)
{
if (theLoc.IsIdentity())
+ {
return thePnt;
+ }
- return thePnt.Transformed(theLoc.Transformation());
+ return thePnt.Transformed (theLoc.Transformation ());
}
//=======================================================================
-//function : IsDegenerated
+//function : UVPoints
//purpose :
//=======================================================================
-Standard_Boolean BRepMesh_ShapeTool::IsDegenerated(
- const TopoDS_Edge& theEdge,
- const TopoDS_Face& theFace)
+Standard_Boolean BRepMesh_ShapeTool::UVPoints (
+ const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace,
+ gp_Pnt2d& theFirstPoint2d,
+ gp_Pnt2d& theLastPoint2d,
+ const Standard_Boolean isConsiderOrientation)
{
- // Get vertices
- TopoDS_Vertex pBegin, pEnd;
- TopExp::Vertices(theEdge, pBegin, pEnd);
- if (pBegin.IsNull() || pEnd.IsNull())
- return Standard_True;
-
- if (BRep_Tool::Degenerated(theEdge))
- return Standard_True;
- if (!pBegin.IsSame(pEnd))
+ Handle (Geom2d_Curve) aCurve2d;
+ Standard_Real aFirstParam, aLastParam;
+ if (!Range(theEdge, theFace, aCurve2d, aFirstParam, aLastParam, isConsiderOrientation))
+ {
return Standard_False;
+ }
- Standard_Real wFirst, wLast;
- BRep_Tool::Range(theEdge, theFace, wFirst, wLast);
-
- // calculation of the length of the edge in 3D
- Standard_Real longueur = 0.0;
- Standard_Real du = (wLast - wFirst) * 0.05;
- gp_Pnt P1, P2;
- BRepAdaptor_Curve BC(theEdge);
- BC.D0(wFirst, P1);
- Standard_Real tolV = BRep_Tool::Tolerance(pBegin);
- Standard_Real tolV2 = 1.2 * tolV;
-
- for (Standard_Integer l = 1; l <= 20; ++l)
- {
- BC.D0(wFirst + l * du, P2);
- longueur += P1.Distance(P2);
+ aCurve2d->D0 (aFirstParam, theFirstPoint2d);
+ aCurve2d->D0 (aLastParam, theLastPoint2d);
+ return Standard_True;
+}
- if (longueur > tolV2)
- break;
+//=======================================================================
+//function : Range
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_ShapeTool::Range (
+ const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace,
+ Handle (Geom2d_Curve)& thePCurve,
+ Standard_Real& theFirstParam,
+ Standard_Real& theLastParam,
+ const Standard_Boolean isConsiderOrientation)
+{
- P1 = P2;
- }
+ ShapeAnalysis_Edge aEdge;
+ return aEdge.PCurve (theEdge, theFace, thePCurve,
+ theFirstParam, theLastParam,
+ isConsiderOrientation);
+}
- if (longueur < tolV2)
- return Standard_True;
+//=======================================================================
+//function : Range
+//purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_ShapeTool::Range (
+ const TopoDS_Edge& theEdge,
+ Handle (Geom_Curve)& theCurve,
+ Standard_Real& theFirstParam,
+ Standard_Real& theLastParam,
+ const Standard_Boolean isConsiderOrientation)
+{
- return Standard_False;
+ ShapeAnalysis_Edge aEdge;
+ return aEdge.Curve3d (theEdge, theCurve,
+ theFirstParam, theLastParam,
+ isConsiderOrientation);
}
-// Copyright (c) 2013 OPEN CASCADE SAS
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
//
// This file is part of Open CASCADE Technology software library.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-
#ifndef _BRepMesh_ShapeTool_HeaderFile
#define _BRepMesh_ShapeTool_HeaderFile
-#include <Standard.hxx>
-#include <Standard_DefineAlloc.hxx>
-#include <Standard_Macro.hxx>
-#include <BRepAdaptor_HSurface.hxx>
-#include <BRepMesh_FaceAttribute.hxx>
-#include <BRepMesh.hxx>
+#include <Standard_Transient.hxx>
+#include <Standard_Handle.hxx>
+#include <Standard_Type.hxx>
+#include <IMeshData_Types.hxx>
+#include <Poly_Triangulation.hxx>
+#include <Poly_PolygonOnTriangulation.hxx>
-class Poly_Triangulation;
+class Geom_Curve;
+class Geom2d_Curve;
+class Poly_Polygon3D;
class TopoDS_Face;
class TopoDS_Edge;
class Bnd_Box;
-class TopoDS_Vertex;
-class gp_XY;
-class gp_Pnt2d;
-class BRepMesh_ShapeTool
+//! Auxiliary class providing functionality to compute,
+//! retrieve and store data to TopoDS and model shape.
+class BRepMesh_ShapeTool : public Standard_Transient
{
public:
- DEFINE_STANDARD_ALLOC
-
//! Returns maximum tolerance of the given face.
//! Considers tolerances of edges and vertices contained in the given face.
Standard_EXPORT static Standard_Real MaxFaceTolerance(
Standard_EXPORT static void BoxMaxDimension(const Bnd_Box& theBox,
Standard_Real& theMaxDimension);
- //! Returns relative deflection for edge with respect to shape size.
- //! @param theEdge edge for which relative deflection should be computed.
- //! @param theDeflection absolute deflection.
- //! @param theMaxShapeSize maximum size of a shape.
- //! @param theAdjustmentCoefficient coefficient of adjustment between maximum
- //! size of shape and calculated relative deflection.
- //! @return relative deflection for the edge.
- Standard_EXPORT static Standard_Real RelativeEdgeDeflection(
- const TopoDS_Edge& theEdge,
- const Standard_Real theDeflection,
- const Standard_Real theMaxShapeSize,
- Standard_Real& theAdjustmentCoefficient);
-
- //! Checks 2d representations of 3d point with the
- //! given index for equality to avoid duplications.
- //! @param theIndexOfPnt3d index of 3d point with which 2d
- //! representation should be associated.
- //! @param thePnt2d 2d representation of the point with the
- //! given index.
- //! @param theMinDistance minimum distance between vertices
- //! regarding which they could be treated as distinct ones.
- //! @param theFaceAttribute attributes contining data calculated
- //! according to face geomtry and define limits of face in parametric
- //! space. If defined, will be used instead of surface parameter.
- //! @param theLocation2dMap map of 2d representations of 3d points.
- //! @return given 2d point in case if 3d poind does not alredy have
- //! the similar representation, otherwice 2d point corresponding to
- //! existing representation will be returned.
- Standard_EXPORT static gp_XY FindUV(
- const Standard_Integer theIndexOfPnt3d,
- const gp_Pnt2d& thePnt2d,
- const Standard_Real theMinDistance,
- const Handle(BRepMesh_FaceAttribute)& theFaceAttribute);
+ //! Checks same parameter, same range and degenerativity attributes
+ //! using geometrical data of the given edge and updates edge model
+ //! by computed parameters in case of worst case - it can drop flags
+ //! same parameter and same range to False but never to True if it is
+ //! already set to False. In contrary, it can also drop degenerated
+ //! flag to True, but never to False if it is already set to True.
+ Standard_EXPORT static void CheckAndUpdateFlags (
+ const IMeshData::IEdgeHandle& theEdge,
+ const IMeshData::IPCurveHandle& thePCurve);
//! Stores the given triangulation into the given face.
//! @param theFace face to be updated by triangulation.
//! Nullifies triangulation stored in the face.
//! @param theFace face to be updated by null triangulation.
- Standard_EXPORT static void NullifyFace(const TopoDS_Face& theFace);
+ Standard_EXPORT static void NullifyFace (const TopoDS_Face& theFace);
//! Nullifies polygon on triangulation stored in the edge.
//! @param theEdge edge to be updated by null polygon.
//! @param theTriangulation triangulation the given edge is associated to.
//! @param theLocation face location.
- Standard_EXPORT static void NullifyEdge(
- const TopoDS_Edge& theEdge,
- const Handle(Poly_Triangulation)& theTriangulation,
- const TopLoc_Location& theLocation);
+ Standard_EXPORT static void NullifyEdge (
+ const TopoDS_Edge& theEdge,
+ const Handle (Poly_Triangulation)& theTriangulation,
+ const TopLoc_Location& theLocation);
+
+ //! Nullifies 3d polygon stored in the edge.
+ //! @param theEdge edge to be updated by null polygon.
+ //! @param theLocation face location.
+ Standard_EXPORT static void NullifyEdge (
+ const TopoDS_Edge& theEdge,
+ const TopLoc_Location& theLocation);
//! Updates the given edge by the given tessellated representation.
//! @param theEdge edge to be updated.
//! @param thePolygon tessellated representation of the edge to be stored.
//! @param theTriangulation triangulation the given edge is associated to.
//! @param theLocation face location.
+ Standard_EXPORT static void UpdateEdge (
+ const TopoDS_Edge& theEdge,
+ const Handle (Poly_PolygonOnTriangulation)& thePolygon,
+ const Handle (Poly_Triangulation)& theTriangulation,
+ const TopLoc_Location& theLocation);
+
+ //! Updates the given edge by the given tessellated representation.
+ //! @param theEdge edge to be updated.
+ //! @param thePolygon tessellated representation of the edge to be stored.
Standard_EXPORT static void UpdateEdge(
- const TopoDS_Edge& theEdge,
- const Handle(Poly_PolygonOnTriangulation)& thePolygon,
- const Handle(Poly_Triangulation)& theTriangulation,
- const TopLoc_Location& theLocation);
+ const TopoDS_Edge& theEdge,
+ const Handle(Poly_Polygon3D)& thePolygon);
//! Updates the given seam edge by the given tessellated representations.
//! @param theEdge edge to be updated.
//! reversed direction of the seam edge.
//! @param theTriangulation triangulation the given edge is associated to.
//! @param theLocation face location.
- Standard_EXPORT static void UpdateEdge(
- const TopoDS_Edge& theEdge,
- const Handle(Poly_PolygonOnTriangulation)& thePolygon1,
- const Handle(Poly_PolygonOnTriangulation)& thePolygon2,
- const Handle(Poly_Triangulation)& theTriangulation,
- const TopLoc_Location& theLocation);
+ Standard_EXPORT static void UpdateEdge (
+ const TopoDS_Edge& theEdge,
+ const Handle (Poly_PolygonOnTriangulation)& thePolygon1,
+ const Handle (Poly_PolygonOnTriangulation)& thePolygon2,
+ const Handle (Poly_Triangulation)& theTriangulation,
+ const TopLoc_Location& theLocation);
//! Applies location to the given point and return result.
//! @param thePnt point to be transformed.
//! @param theLoc location to be applied.
- Standard_EXPORT static gp_Pnt UseLocation(const gp_Pnt& thePnt,
- const TopLoc_Location& theLoc);
-
- //! Checks is the given edge degenerated.
- //! Checks geometrical parameters in case if IsDegenerated flag is not set.
- //! @param theEdge edge to be checked.
- //! @param theFace face within which parametric space edge will be checked
- //! for geometrical degenerativity.
- Standard_EXPORT static Standard_Boolean IsDegenerated(
- const TopoDS_Edge& theEdge,
- const TopoDS_Face& theFace);
+ Standard_EXPORT static gp_Pnt UseLocation (
+ const gp_Pnt& thePnt,
+ const TopLoc_Location& theLoc);
+
+ //! Gets the strict UV locations of the extremities of the edge using pcurve.
+ Standard_EXPORT static Standard_Boolean UVPoints (
+ const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace,
+ gp_Pnt2d& theFirstPoint2d,
+ gp_Pnt2d& theLastPoint2d,
+ const Standard_Boolean isConsiderOrientation = Standard_False);
+
+ //! Gets the parametric range of the given edge on the given face.
+ Standard_EXPORT static Standard_Boolean Range (
+ const TopoDS_Edge& theEdge,
+ const TopoDS_Face& theFace,
+ Handle (Geom2d_Curve)& thePCurve,
+ Standard_Real& theFirstParam,
+ Standard_Real& theLastParam,
+ const Standard_Boolean isConsiderOrientation = Standard_False);
+
+ //! Gets the 3d range of the given edge.
+ Standard_EXPORT static Standard_Boolean Range (
+ const TopoDS_Edge& theEdge,
+ Handle (Geom_Curve)& theCurve,
+ Standard_Real& theFirstParam,
+ Standard_Real& theLastParam,
+ const Standard_Boolean isConsiderOrientation = Standard_False);
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ShapeTool, Standard_Transient)
};
-#endif
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_ShapeVisitor.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopExp.hxx>
+#include <ShapeAnalysis.hxx>
+#include <TopExp_Explorer.hxx>
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Face.hxx>
+#include <ShapeAnalysis_Wire.hxx>
+#include <ShapeAnalysis_WireOrder.hxx>
+#include <ShapeExtend_WireData.hxx>
+#include <Precision.hxx>
+#include <IMeshData_Status.hxx>
+#include <IMeshTools_Context.hxx>
+#include <BRepTools.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMesh_ShapeVisitor::BRepMesh_ShapeVisitor (const Handle (IMeshData_Model)& theModel)
+: myModel (theModel),
+ myDEdgeMap(1, new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE))
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMesh_ShapeVisitor::~BRepMesh_ShapeVisitor ()
+{
+}
+
+//=======================================================================
+// Function: Visit (edge)
+// Purpose :
+//=======================================================================
+void BRepMesh_ShapeVisitor::Visit(const TopoDS_Edge& theEdge)
+{
+ myModel->AddEdge(theEdge);
+ myDEdgeMap.Bind(theEdge, myModel->EdgesNb() - 1);
+}
+
+//=======================================================================
+// Function: Visit (face)
+// Purpose :
+//=======================================================================
+void BRepMesh_ShapeVisitor::Visit (const TopoDS_Face& theFace)
+{
+ BRepTools::Update(theFace);
+ const IMeshData::IFaceHandle& aDFace = myModel->AddFace (theFace);
+
+ // Outer wire should always be the first in the model.
+ TopoDS_Wire aOuterWire = ShapeAnalysis::OuterWire (theFace);
+ if (!addWire (aOuterWire, aDFace))
+ {
+ aDFace->SetStatus (IMeshData_Failure);
+ return;
+ }
+
+ TopExp_Explorer aWireIt (theFace, TopAbs_WIRE);
+ for (; aWireIt.More (); aWireIt.Next ())
+ {
+ const TopoDS_Wire& aWire = TopoDS::Wire (aWireIt.Current ());
+ if (aWire.IsSame(aOuterWire))
+ {
+ continue;
+ }
+
+ if (!addWire (aWire, aDFace))
+ {
+ // If there is a failure on internal wire, just skip it.
+ // The most significant is an outer wire.
+ aDFace->SetStatus (IMeshData_UnorientedWire);
+ }
+ }
+}
+
+//=======================================================================
+// Function: addWire
+// Purpose :
+//=======================================================================
+Standard_Boolean BRepMesh_ShapeVisitor::addWire (
+ const TopoDS_Wire& theWire,
+ const IMeshData::IFaceHandle& theDFace)
+{
+ if (theWire.IsNull())
+ {
+ return Standard_False;
+ }
+
+ Handle(ShapeExtend_WireData) aWireData = new ShapeExtend_WireData(theWire, Standard_True, Standard_False);
+ ShapeAnalysis_Wire aWireTool (aWireData, theDFace->GetFace (), Precision::Confusion ());
+
+ ShapeAnalysis_WireOrder aOrderTool;
+ aWireTool.CheckOrder (aOrderTool, Standard_True, Standard_False);
+ if (aWireTool.LastCheckStatus(ShapeExtend_FAIL))
+ {
+ return Standard_False;
+ }
+
+ if (aWireTool.LastCheckStatus(ShapeExtend_DONE3))
+ {
+ theDFace->SetStatus(IMeshData_UnorientedWire);
+ }
+
+ const Standard_Integer aEdgesNb = aOrderTool.NbEdges ();
+ if (aEdgesNb != aWireData->NbEdges())
+ {
+ return Standard_False;
+ }
+
+ const IMeshData::IWireHandle& aDWire = theDFace->AddWire (theWire, aEdgesNb);
+ for (Standard_Integer i = 1; i <= aEdgesNb; ++i)
+ {
+ const Standard_Integer aEdgeIndex = aOrderTool.Ordered (i);
+ const TopoDS_Edge& aEdge = aWireData->Edge (aEdgeIndex);
+ if (aEdge.Orientation() != TopAbs_EXTERNAL)
+ {
+ const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge (myDEdgeMap.Find (aEdge));
+
+ aDEdge->AddPCurve (theDFace.get(), aEdge.Orientation());
+ aDWire->AddEdge (aDEdge.get(), aEdge.Orientation());
+ }
+ }
+
+ return Standard_True;
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_ShapeVisitor_HeaderFile
+#define _BRepMesh_ShapeVisitor_HeaderFile
+
+#include <IMeshTools_ShapeVisitor.hxx>
+#include <IMeshData_Model.hxx>
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <IMeshData_Types.hxx>
+
+class TopoDS_Face;
+class TopoDS_Edge;
+class TopoDS_Wire;
+class IMeshTools_Context;
+class IMeshData_Wire;
+
+//! Builds discrete model of a shape by adding faces and free edges.
+//! Computes deflection for corresponded shape and checks whether it
+//! fits existing polygonal representation. If not, cleans shape from
+//! outdated info.
+class BRepMesh_ShapeVisitor : public IMeshTools_ShapeVisitor
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT BRepMesh_ShapeVisitor (const Handle (IMeshData_Model)& theModel);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMesh_ShapeVisitor ();
+
+ //! Handles TopoDS_Face object.
+ Standard_EXPORT virtual void Visit (const TopoDS_Face& theFace) Standard_OVERRIDE;
+
+ //! Handles TopoDS_Edge object.
+ Standard_EXPORT virtual void Visit (const TopoDS_Edge& theEdge) Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ShapeVisitor, IMeshTools_ShapeVisitor)
+
+private:
+
+ //! Adds wire to face discrete model.
+ Standard_Boolean addWire (
+ const TopoDS_Wire& theWire,
+ const IMeshData::IFaceHandle& theDFace);
+
+private:
+
+ Handle (IMeshData_Model) myModel;
+ IMeshData::DMapOfShapeInteger myDEdgeMap;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_SphereRangeSplitter.hxx>
+#include <GCPnts_TangentialDeflection.hxx>
+
+//=======================================================================
+// Function: GenerateSurfaceNodes
+// Purpose :
+//=======================================================================
+Handle(IMeshData::ListOfPnt2d) BRepMesh_SphereRangeSplitter::GenerateSurfaceNodes(
+ const IMeshTools_Parameters& theParameters) const
+{
+ // Calculate parameters for iteration in V direction
+ Standard_Real aStep = 0.7 * GCPnts_TangentialDeflection::ArcAngularStep(
+ GetDFace()->GetSurface()->Sphere().Radius(), GetDFace()->GetDeflection(),
+ theParameters.Angle, theParameters.MinSize);
+
+ const std::pair<Standard_Real, Standard_Real>* aRange[2] = {
+ &GetRangeV(),
+ &GetRangeU()
+ };
+
+ std::pair<Standard_Real, Standard_Real> aStepAndOffset[2];
+ computeStep(*aRange[0], aStep, aStepAndOffset[0]);
+ computeStep(*aRange[1], aStep, aStepAndOffset[1]);
+
+ const Handle(NCollection_IncAllocator) aTmpAlloc =
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
+ Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc);
+
+ const Standard_Real aHalfDu = aStepAndOffset[1].first * 0.5;
+ Standard_Boolean Shift = Standard_False;
+ Standard_Real aPasV = aRange[0]->first + aStepAndOffset[0].first;
+ for (; aPasV < aStepAndOffset[0].second; aPasV += aStepAndOffset[0].first)
+ {
+ Shift = !Shift;
+ const Standard_Real d = (Shift) ? aHalfDu : 0.;
+ Standard_Real aPasU = aRange[1]->first + d;
+ for (; aPasU < aStepAndOffset[1].second; aPasU += aStepAndOffset[1].first)
+ {
+ aNodes->Append(gp_Pnt2d(aPasU, aPasV));
+ }
+ }
+
+ return aNodes;
+}
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_SphereRangeSplitter_HeaderFile
+#define _BRepMesh_SphereRangeSplitter_HeaderFile
+
+#include <BRepMesh_DefaultRangeSplitter.hxx>
+#include <IMeshTools_Parameters.hxx>
+
+//! Auxiliary class extending default range splitter in
+//! order to generate internal nodes for spherical surface.
+class BRepMesh_SphereRangeSplitter : public BRepMesh_DefaultRangeSplitter
+{
+public:
+
+ //! Constructor.
+ BRepMesh_SphereRangeSplitter()
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_SphereRangeSplitter()
+ {
+ }
+
+ //! Returns list of nodes generated using surface data and specified parameters.
+ Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes(
+ const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE;
+
+private:
+
+ //! Computes step for the given range.
+ inline void computeStep(
+ const std::pair<Standard_Real, Standard_Real>& theRange,
+ const Standard_Real theDefaultStep,
+ std::pair<Standard_Real, Standard_Real>& theStepAndOffset) const
+ {
+ const Standard_Real aDiff = theRange.second - theRange.first;
+ theStepAndOffset.first = aDiff / ((Standard_Integer) (aDiff / theDefaultStep) + 1);
+ theStepAndOffset.second = theRange.second - Precision::PConfusion();
+ }
+};
+
+#endif
+++ /dev/null
-// Created on: 2011-05-17
-// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef _BRepMesh_Status_HeaderFile
-#define _BRepMesh_Status_HeaderFile
-
-//! Discribes the wires discretisation.
-enum BRepMesh_Status
-{
- BRepMesh_NoError = 0x0,
- BRepMesh_OpenWire = 0x1,
- BRepMesh_SelfIntersectingWire = 0x2,
- BRepMesh_Failure = 0x4,
- BRepMesh_ReMesh = 0x8
-};
-
-#endif
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMesh_TorusRangeSplitter.hxx>
+#include <GCPnts_TangentialDeflection.hxx>
+
+//=======================================================================
+// Function: GenerateSurfaceNodes
+// Purpose :
+//=======================================================================
+Handle(IMeshData::ListOfPnt2d) BRepMesh_TorusRangeSplitter::GenerateSurfaceNodes(
+ const IMeshTools_Parameters& theParameters) const
+{
+ const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
+ const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
+
+ const Standard_Real aDiffU = aRangeU.second - aRangeU.first;
+ const Standard_Real aDiffV = aRangeV.second - aRangeV.first;
+
+ const gp_Torus aTorus = GetDFace()->GetSurface()->Torus();
+ const Standard_Real r = aTorus.MinorRadius();
+ const Standard_Real R = aTorus.MajorRadius();
+
+ const Standard_Real oldDv = GCPnts_TangentialDeflection::ArcAngularStep(
+ r, GetDFace()->GetDeflection(), theParameters.Angle, theParameters.MinSize);
+
+ Standard_Real Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
+ Dv = oldDv;
+
+ const Standard_Integer nbV = Max((Standard_Integer) (aDiffV / Dv), 2);
+ Dv = aDiffV / (nbV + 1);
+
+ Standard_Real Du;
+ const Standard_Real ru = R + r;
+ if (ru > 1.e-16)
+ {
+ Du = GCPnts_TangentialDeflection::ArcAngularStep(ru,
+ GetDFace()->GetDeflection(), theParameters.Angle, theParameters.MinSize);
+
+ const Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
+ if (aa < gp::Resolution())
+ {
+ return Handle(IMeshData::ListOfPnt2d)();
+ }
+
+ Du *= Min(oldDv, Du) / aa;
+ }
+ else
+ {
+ Du = Dv;
+ }
+
+ Standard_Integer nbU = Max((Standard_Integer) (aDiffU / Du), 2);
+ nbU = Max(nbU, (Standard_Integer) (nbV * aDiffU * R / (aDiffV * r) / 5.));
+ Du = aDiffU / (nbU + 1);
+
+ const Handle(NCollection_IncAllocator) aTmpAlloc =
+ new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
+
+ Handle(IMeshData::SequenceOfReal) aParamU, aParamV;
+ if (R < r)
+ {
+ // As the points of edges are returned.
+ // in this case, the points are not representative.
+
+ //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid
+ aParamU = new IMeshData::SequenceOfReal(aTmpAlloc);
+ for (Standard_Integer i = 0; i <= nbU; i++)
+ {
+ aParamU->Append(aRangeU.first + i * Du);
+ }
+ }//R<r
+ else //U if R > r
+ {
+ aParamU = fillParams(GetParametersU(), GetRangeU(), nbU, 0.5, aTmpAlloc);
+ }
+
+ aParamV = fillParams(GetParametersV(), GetRangeV(), nbV, 2. / 3., aTmpAlloc);
+
+ const std::pair<Standard_Real, Standard_Real> aNewRangeU(aRangeU.first + Du * 0.1,
+ aRangeU.second - Du * 0.1);
+
+ const std::pair<Standard_Real, Standard_Real> aNewRangeV(aRangeV.first + Dv * 0.1,
+ aRangeV.second - Dv * 0.1);
+
+ Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc);
+ for (Standard_Integer i = 1; i <= aParamU->Length(); ++i)
+ {
+ const Standard_Real aPasU = aParamU->Value(i);
+ if (aPasU >= aNewRangeU.first && aPasU < aNewRangeU.second)
+ {
+ for (Standard_Integer j = 1; j <= aParamV->Length(); ++j)
+ {
+ const Standard_Real aPasV = aParamV->Value(j);
+ if (aPasV >= aNewRangeV.first && aPasV < aNewRangeV.second)
+ {
+ aNodes->Append(gp_Pnt2d(aPasU, aPasV));
+ }
+ }
+ }
+ }
+
+ return aNodes;
+}
+
+//=======================================================================
+// Function: AddPoint
+// Purpose :
+//=======================================================================
+void BRepMesh_TorusRangeSplitter::AddPoint(const gp_Pnt2d& thePoint)
+{
+ BRepMesh_DefaultRangeSplitter::AddPoint(thePoint);
+ GetParametersU().Add(thePoint.X());
+ GetParametersV().Add(thePoint.Y());
+}
+
+//=======================================================================
+// Function: fillParams
+// Purpose :
+//=======================================================================
+Handle(IMeshData::SequenceOfReal) BRepMesh_TorusRangeSplitter::fillParams(
+ const IMeshData::IMapOfReal& theParams,
+ const std::pair<Standard_Real, Standard_Real>& theRange,
+ const Standard_Integer theStepsNb,
+ const Standard_Real theScale,
+ const Handle(NCollection_IncAllocator)& theAllocator) const
+{
+ Handle(IMeshData::SequenceOfReal) aParams =
+ new IMeshData::SequenceOfReal(theAllocator);
+
+ const Standard_Integer aLength = theParams.Size();
+ TColStd_Array1OfReal aParamArray(1, aLength);
+
+ for (Standard_Integer j = 1; j <= aLength; ++j)
+ {
+ aParamArray(j) = theParams(j);
+ }
+
+ // Calculate DU, leave array of parameters
+ const Standard_Real aDiff = Abs(theRange.second - theRange.first);
+ Standard_Real aStep = FUN_CalcAverageDUV(aParamArray, aLength);
+ aStep = Max(aStep, aDiff / (Standard_Real) theStepsNb / 2.);
+
+ Standard_Real aStdStep = aDiff / (Standard_Real) aLength;
+ if (aStep > aStdStep)
+ {
+ aStdStep = aStep;
+ }
+ aStdStep *= theScale;
+
+ // Add parameters
+ for (Standard_Integer j = 1; j <= aLength; ++j)
+ {
+ const Standard_Real pp = aParamArray(j);
+
+ Standard_Boolean isToInsert = Standard_True;
+ const Standard_Integer aParamsLength = aParams->Length();
+ for (Standard_Integer i = 1; i <= aParamsLength && isToInsert; ++i)
+ {
+ isToInsert = (Abs(aParams->Value(i) - pp) > aStdStep);
+ }
+
+ if (isToInsert)
+ {
+ aParams->Append(pp);
+ }
+ }
+
+ return aParams;
+}
+
+//=======================================================================
+// Function: FUN_CalcAverageDUV
+// Purpose :
+//=======================================================================
+Standard_Real BRepMesh_TorusRangeSplitter::FUN_CalcAverageDUV(
+ TColStd_Array1OfReal& P, const Standard_Integer PLen) const
+{
+ Standard_Integer i, j, n = 0;
+ Standard_Real p, result = 0.;
+
+ for (i = 1; i <= PLen; i++)
+ {
+ // Sort
+ for (j = i + 1; j <= PLen; j++)
+ {
+ if (P(i) > P(j))
+ {
+ p = P(i);
+ P(i) = P(j);
+ P(j) = p;
+ }
+ }
+ // Accumulate
+ if (i != 1)
+ {
+ p = Abs(P(i) - P(i - 1));
+ if (p > 1.e-7)
+ {
+ result += p;
+ n++;
+ }
+ }
+ }
+ return (n ? (result / (Standard_Real) n) : -1.);
+}
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_TorusRangeSplitter_HeaderFile
+#define _BRepMesh_TorusRangeSplitter_HeaderFile
+
+#include <BRepMesh_UVParamRangeSplitter.hxx>
+#include <IMeshTools_Parameters.hxx>
+
+//! Auxiliary class extending UV range splitter in order to generate
+//! internal nodes for NURBS surface.
+class BRepMesh_TorusRangeSplitter : public BRepMesh_UVParamRangeSplitter
+{
+public:
+
+ //! Constructor.
+ BRepMesh_TorusRangeSplitter()
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_TorusRangeSplitter()
+ {
+ }
+
+ //! Returns list of nodes generated using surface data and specified parameters.
+ Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes(
+ const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE;
+
+ //! Registers border point.
+ Standard_EXPORT virtual void AddPoint(const gp_Pnt2d& thePoint) Standard_OVERRIDE;
+
+private:
+
+ Handle(IMeshData::SequenceOfReal) fillParams(
+ const IMeshData::IMapOfReal& theParams,
+ const std::pair<Standard_Real, Standard_Real>& theRange,
+ const Standard_Integer theStepsNb,
+ const Standard_Real theScale,
+ const Handle(NCollection_IncAllocator)& theAllocator) const;
+
+ Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_Integer PLen) const;
+};
+
+#endif
//! Default constructor.
BRepMesh_Triangle()
- : myEdge1(0),
- myEdge2(0),
- myEdge3(0),
- myOrientation1(Standard_False),
- myOrientation2(Standard_False),
- myOrientation3(Standard_False),
- myMovability (BRepMesh_Free)
+ : myMovability (BRepMesh_Free)
{
+ myEdges[0] = 0;
+ myEdges[1] = 0;
+ myEdges[2] = 0;
+ myOrientations[0] = Standard_False;
+ myOrientations[1] = Standard_False;
+ myOrientations[2] = Standard_False;
}
//! Constructor.
const Standard_Boolean (&theOrientations)[3],
const BRepMesh_DegreeOfFreedom theMovability)
{
- myEdge1 = theEdges[0];
- myEdge2 = theEdges[1];
- myEdge3 = theEdges[2];
- myOrientation1 = theOrientations[0];
- myOrientation2 = theOrientations[1];
- myOrientation3 = theOrientations[2];
+ memcpy(myEdges, theEdges, sizeof(theEdges));
+ memcpy(myOrientations, theOrientations, sizeof(theOrientations));
myMovability = theMovability;
}
inline void Edges(Standard_Integer (&theEdges)[3],
Standard_Boolean (&theOrientations)[3]) const
{
- theEdges[0] = myEdge1;
- theEdges[1] = myEdge2;
- theEdges[2] = myEdge3;
- theOrientations[0] = myOrientation1;
- theOrientations[1] = myOrientation2;
- theOrientations[2] = myOrientation3;
+ memcpy(theEdges, myEdges, sizeof(myEdges));
+ memcpy(theOrientations, myOrientations, sizeof(myOrientations));
}
//! Returns movability of the triangle.
//! Returns hash code for this triangle.
//! @param theUpper upper index in the container.
//! @return hash code.
- Standard_Integer HashCode(const Standard_Integer theUpper) const
+ inline Standard_Integer HashCode(const Standard_Integer theUpper) const
{
- return ::HashCode(myEdge1 + myEdge2 + myEdge3, theUpper);
+ return ::HashCode(myEdges[0] + myEdges[1] + myEdges[2], theUpper);
}
//! Checks for equality with another triangle.
//! @param theOther triangle to be checked against this one.
//! @return TRUE if equal, FALSE if not.
- Standard_Boolean IsEqual(const BRepMesh_Triangle& theOther) const
+ inline Standard_Boolean IsEqual(const BRepMesh_Triangle& theOther) const
{
if (myMovability == BRepMesh_Deleted || theOther.myMovability == BRepMesh_Deleted)
return Standard_False;
- if (myEdge1 == theOther.myEdge1 &&
- myEdge2 == theOther.myEdge2 &&
- myEdge3 == theOther.myEdge3)
+ if (myEdges[0] == theOther.myEdges[0] &&
+ myEdges[1] == theOther.myEdges[1] &&
+ myEdges[2] == theOther.myEdges[2])
{
return Standard_True;
}
- if (myEdge1 == theOther.myEdge2 &&
- myEdge2 == theOther.myEdge3 &&
- myEdge3 == theOther.myEdge1)
+ if (myEdges[0] == theOther.myEdges[1] &&
+ myEdges[1] == theOther.myEdges[2] &&
+ myEdges[2] == theOther.myEdges[0])
{
return Standard_True;
}
- if (myEdge1 == theOther.myEdge3 &&
- myEdge2 == theOther.myEdge1 &&
- myEdge3 == theOther.myEdge2)
+ if (myEdges[0] == theOther.myEdges[2] &&
+ myEdges[1] == theOther.myEdges[0] &&
+ myEdges[2] == theOther.myEdges[1])
{
return Standard_True;
}
}
//! Alias for IsEqual.
- Standard_Boolean operator ==(const BRepMesh_Triangle& theOther) const
+ inline Standard_Boolean operator ==(const BRepMesh_Triangle& theOther) const
{
return IsEqual(theOther);
}
-private:
-
- Standard_Integer myEdge1;
- Standard_Integer myEdge2;
- Standard_Integer myEdge3;
- Standard_Boolean myOrientation1;
- Standard_Boolean myOrientation2;
- Standard_Boolean myOrientation3;
+ Standard_Integer myEdges[3];
+ Standard_Boolean myOrientations[3];
BRepMesh_DegreeOfFreedom myMovability;
};
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMesh_UVParamRangeSplitter_HeaderFile
+#define _BRepMesh_UVParamRangeSplitter_HeaderFile
+
+#include <BRepMesh_DefaultRangeSplitter.hxx>
+#include <IMeshData_Types.hxx>
+
+//! Intended to generate internal mesh nodes using UV parameters of boundary discrete points.
+class BRepMesh_UVParamRangeSplitter : public BRepMesh_DefaultRangeSplitter
+{
+public:
+
+ //! Constructor.
+ BRepMesh_UVParamRangeSplitter()
+ : myAllocator(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)),
+ myUParams(1, myAllocator),
+ myVParams(1, myAllocator)
+ {
+ }
+
+ //! Destructor.
+ virtual ~BRepMesh_UVParamRangeSplitter()
+ {
+ }
+
+ //! Resets this splitter.
+ virtual void Reset(const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters) Standard_OVERRIDE
+ {
+ BRepMesh_DefaultRangeSplitter::Reset(theDFace, theParameters);
+ myUParams.Clear();
+ myVParams.Clear();
+ myAllocator->Reset(Standard_False);
+ }
+
+public:
+ //! Returns U parameters.
+ inline const IMeshData::IMapOfReal& GetParametersU() const
+ {
+ return myUParams;
+ }
+
+ //! Returns U parameters.
+ inline IMeshData::IMapOfReal& GetParametersU()
+ {
+ return myUParams;
+ }
+
+ //! Returns V parameters.
+ inline const IMeshData::IMapOfReal& GetParametersV() const
+ {
+ return myVParams;
+ }
+
+ //! Returns V parameters.
+ inline IMeshData::IMapOfReal& GetParametersV()
+ {
+ return myVParams;
+ }
+
+private:
+ Handle(NCollection_IncAllocator) myAllocator;
+ IMeshData::IMapOfReal myUParams;
+ IMeshData::IMapOfReal myVParams;
+};
+
+#endif
#ifndef _BRepMesh_Vertex_HeaderFile
#define _BRepMesh_Vertex_HeaderFile
-#include <BRepMesh_DegreeOfFreedom.hxx>
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Macro.hxx>
#include <gp_XY.hxx>
+#include <BRepMesh_DegreeOfFreedom.hxx>
#include <Precision.hxx>
//! Light weighted structure representing vertex
//! Returns hash code for this vertex.
//! @param theUpper upper index in the container.
//! @return hash code.
- Standard_Integer HashCode(const Standard_Integer Upper) const
+ inline Standard_Integer HashCode(const Standard_Integer Upper) const
{
return ::HashCode(Floor(1e5 * myUV.X()) * Floor(1e5 * myUV.Y()), Upper);
}
//! Checks for equality with another vertex.
//! @param theOther vertex to be checked against this one.
//! @return TRUE if equal, FALSE if not.
- Standard_Boolean IsEqual(const BRepMesh_Vertex& theOther) const
+ inline Standard_Boolean IsEqual(const BRepMesh_Vertex& theOther) const
{
if (myMovability == BRepMesh_Deleted ||
theOther.myMovability == BRepMesh_Deleted)
}
//! Alias for IsEqual.
- Standard_Boolean operator ==(const BRepMesh_Vertex& Other) const
+ inline Standard_Boolean operator ==(const BRepMesh_Vertex& Other) const
{
return IsEqual(Other);
}
#include <Precision.hxx>
#include <gp_XY.hxx>
#include <gp_XYZ.hxx>
-#include <BRepMesh.hxx>
+#include <IMeshData_Types.hxx>
#include <NCollection_CellFilter.hxx>
#include <BRepMesh_Vertex.hxx>
//! Constructor.
//! @param theAllocator memory allocator to be used by internal collections.
- BRepMesh_VertexInspector (
+ BRepMesh_VertexInspector(
const Handle(NCollection_IncAllocator)& theAllocator)
- : myResIndices(theAllocator),
- myVertices (new BRepMesh::VectorOfVertex),
- myDelNodes (theAllocator)
+ : myIndex(0),
+ myMinSqDist(RealLast()),
+ myVertices(new IMeshData::VectorOfVertex),
+ myDelNodes(theAllocator)
{
- SetTolerance( Precision::Confusion() );
+ SetTolerance(Precision::Confusion());
}
//! Registers the given vertex.
//! Set reference point to be checked.
inline void SetPoint(const gp_XY& thePoint)
{
- myResIndices.Clear();
- myPoint = thePoint;
+ myIndex = 0;
+ myMinSqDist = RealLast();
+ myPoint = thePoint;
}
//! Returns index of point coinciding with regerence one.
inline Standard_Integer GetCoincidentPoint() const
{
- if ( myResIndices.Size() > 0 )
- {
- return myResIndices.First();
- }
- return 0;
+ return myIndex;
}
//! Returns list with indexes of vertices that have movability attribute
//! equal to BRepMesh_Deleted and can be replaced with another node.
- inline const BRepMesh::ListOfInteger& GetListOfDelPoints() const
+ inline const IMeshData::ListOfInteger& GetListOfDelPoints() const
{
return myDelNodes;
}
//! Returns set of mesh vertices.
- inline const BRepMesh::HVectorOfVertex& Vertices() const
+ inline const Handle(IMeshData::VectorOfVertex)& Vertices() const
{
return myVertices;
}
//! Returns set of mesh vertices for modification.
- inline BRepMesh::HVectorOfVertex& ChangeVertices()
+ inline Handle(IMeshData::VectorOfVertex)& ChangeVertices()
{
return myVertices;
}
private:
- Standard_Real myTolerance[2];
- BRepMesh::ListOfInteger myResIndices;
- BRepMesh::HVectorOfVertex myVertices;
- BRepMesh::ListOfInteger myDelNodes;
- gp_XY myPoint;
+ Standard_Integer myIndex;
+ Standard_Real myMinSqDist;
+ Standard_Real myTolerance[2];
+ Handle(IMeshData::VectorOfVertex) myVertices;
+ IMeshData::ListOfInteger myDelNodes;
+ gp_XY myPoint;
};
#endif
// commercial license or contractual agreement.
#include <BRepMesh_VertexTool.hxx>
-#include <gp_XY.hxx>
-#include <gp_XYZ.hxx>
#include <Precision.hxx>
-#include <BRepMesh_Vertex.hxx>
-#include <BRepMesh_VertexInspector.hxx>
//=======================================================================
//function : Inspect
inTol = ((aVec.X() * aVec.X()) < myTolerance[0]) &&
((aVec.Y() * aVec.Y()) < myTolerance[1]);
}
+
if (inTol)
- myResIndices.Append(theTarget);
+ {
+ const Standard_Real aSqDist = aVec.SquareModulus();
+ if (aSqDist < myMinSqDist)
+ {
+ myMinSqDist = aSqDist;
+ myIndex = theTarget;
+ }
+ }
return CellFilter_Keep;
}
//function : Delete
//purpose :
//=======================================================================
-void BRepMesh_VertexTool::Delete(const Standard_Integer theIndex)
+void BRepMesh_VertexTool::DeleteVertex(const Standard_Integer theIndex)
{
BRepMesh_Vertex& aV = mySelector.GetVertex(theIndex);
#define _BRepMesh_VertexTool_HeaderFile
#include <NCollection_Array1.hxx>
-#include <Standard.hxx>
-#include <Standard_DefineAlloc.hxx>
-#include <Standard_Macro.hxx>
+#include <Standard_Transient.hxx>
#include <BRepMesh_VertexInspector.hxx>
-#include <BRepMesh.hxx>
#include <Standard_OStream.hxx>
-#include <gp_XYZ.hxx>
#include <gp_XY.hxx>
+#include <IMeshData_Types.hxx>
class BRepMesh_Vertex;
//! Describes data structure intended to keep mesh nodes
//! defined in UV space and implements functionality
-//! providing their uniqueness regarding thir position.
-class BRepMesh_VertexTool
+//! providing their uniqueness regarding their position.
+class BRepMesh_VertexTool : public Standard_Transient
{
public:
- DEFINE_STANDARD_ALLOC
-
//! Constructor.
//! @param theAllocator memory allocator to be used by internal collections.
Standard_EXPORT BRepMesh_VertexTool(
const Standard_Boolean isForceAdd);
//! Deletes vertex with the given index from the tool.
- Standard_EXPORT void Delete(const Standard_Integer theIndex);
+ Standard_EXPORT void DeleteVertex(const Standard_Integer theIndex);
//! Returns set of mesh vertices.
- inline const BRepMesh::HVectorOfVertex& Vertices() const
+ inline const Handle(IMeshData::VectorOfVertex)& Vertices() const
{
return mySelector.Vertices();
}
//! Returns set of mesh vertices.
- inline BRepMesh::HVectorOfVertex& ChangeVertices()
+ inline Handle(IMeshData::VectorOfVertex)& ChangeVertices()
{
return mySelector.ChangeVertices();
}
//! Remove last node from the structure.
inline void RemoveLast()
{
- Delete(Extent());
+ DeleteVertex(Extent());
}
//! Returns the list with indexes of vertices that have movability attribute
//! equal to BRepMesh_Deleted and can be replaced with another node.
- inline const BRepMesh::ListOfInteger& GetListOfDelNodes() const
+ inline const IMeshData::ListOfInteger& GetListOfDelNodes() const
{
return mySelector.GetListOfDelPoints();
}
//! Prints statistics.
Standard_EXPORT void Statistics(Standard_OStream& theStream) const;
+ DEFINE_STANDARD_RTTI_INLINE(BRepMesh_VertexTool, Standard_Transient)
+
private:
//! Expands the given point according to specified tolerance.
private:
- Handle(NCollection_IncAllocator) myAllocator;
- BRepMesh::VertexCellFilter myCellFilter;
- BRepMesh_VertexInspector mySelector;
- Standard_Real myTolerance[2];
+ Handle(NCollection_IncAllocator) myAllocator;
+ IMeshData::VertexCellFilter myCellFilter;
+ BRepMesh_VertexInspector mySelector;
+ Standard_Real myTolerance[2];
};
#endif
+++ /dev/null
-// Created on: 2014-06-03
-// Created by: Oleg AGASHIN
-// Copyright (c) 1997-1999 Matra Datavision
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <BRepMesh_WireChecker.hxx>
-
-#include <Precision.hxx>
-#include <TColStd_Array1OfInteger.hxx>
-#include <gp_Pnt2d.hxx>
-#include <BRepTools_WireExplorer.hxx>
-#include <TopAbs_Orientation.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Wire.hxx>
-#include <TopoDS_Iterator.hxx>
-#include <Poly_PolygonOnTriangulation.hxx>
-#include <BRepMesh_PairOfPolygon.hxx>
-#include <TColStd_SequenceOfInteger.hxx>
-#include <TColStd_IndexedMapOfInteger.hxx>
-#include <BRepMesh_DataStructureOfDelaun.hxx>
-#include <BRepMesh_Classifier.hxx>
-#include <BRepMesh_WireInterferenceChecker.hxx>
-#include <OSD_Parallel.hxx>
-
-
-//=======================================================================
-//function : Selector::Constructor
-//purpose :
-//=======================================================================
-BRepMesh_WireChecker::BndBox2dTreeSelector::BndBox2dTreeSelector(
- const Standard_Integer theReservedSize)
- : mySkippedIndex(-1),
- myIndices(0, theReservedSize - 1),
- myIndicesNb(0)
-{
-}
-
-//=======================================================================
-//function : Reject
-//purpose :
-//=======================================================================
-Standard_Boolean BRepMesh_WireChecker::BndBox2dTreeSelector::Reject(
- const Bnd_Box2d& theBox2D) const
-{
- return myBox2D.IsOut(theBox2D);
-}
-
-//=======================================================================
-//function : Accept
-//purpose :
-//=======================================================================
-Standard_Boolean BRepMesh_WireChecker::BndBox2dTreeSelector::Accept(
- const Standard_Integer& theIndex)
-{
- if (theIndex <= mySkippedIndex)
- return Standard_False;
-
- myIndices(myIndicesNb++) = theIndex;
- return Standard_True;
-}
-
-//=======================================================================
-//function : Clear
-//purpose :
-//=======================================================================
-void BRepMesh_WireChecker::BndBox2dTreeSelector::Clear()
-{
- mySkippedIndex = -1;
- myIndicesNb = 0;
-}
-
-//=======================================================================
-//function : SetBox
-//purpose :
-//=======================================================================
-void BRepMesh_WireChecker::BndBox2dTreeSelector::SetBox(
- const Bnd_Box2d& theBox2D)
-{
- myBox2D = theBox2D;
-}
-
-//=======================================================================
-//function : Clear
-//purpose :
-//=======================================================================
-void BRepMesh_WireChecker::BndBox2dTreeSelector::SetSkippedIndex(
- const Standard_Integer theIndex)
-{
- mySkippedIndex = theIndex;
-}
-
-//=======================================================================
-//function : Indices
-//purpose :
-//=======================================================================
-const BRepMesh::Array1OfInteger&
- BRepMesh_WireChecker::BndBox2dTreeSelector::Indices() const
-{
- return myIndices;
-}
-
-//=======================================================================
-//function : IndicesNb
-//purpose :
-//=======================================================================
-Standard_Integer BRepMesh_WireChecker::BndBox2dTreeSelector::IndicesNb() const
-{
- return myIndicesNb;
-}
-
-//=======================================================================
-//function : Constructor
-//purpose :
-//=======================================================================
-BRepMesh_WireChecker::BRepMesh_WireChecker(
- const TopoDS_Face& theFace,
- const Standard_Real theTolUV,
- const BRepMesh::HDMapOfShapePairOfPolygon& theEdges,
- const BRepMesh::HIMapOfInteger& theVertexMap,
- const Handle(BRepMesh_DataStructureOfDelaun)& theStructure,
- const Standard_Real theUmin,
- const Standard_Real theUmax,
- const Standard_Real theVmin,
- const Standard_Real theVmax,
- const Standard_Boolean isInParallel)
- : myTolUV(theTolUV),
- myEdges(theEdges),
- myVertexMap(theVertexMap),
- myStructure(theStructure),
- myUmin(theUmin),
- myUmax(theUmax),
- myVmin(theVmin),
- myVmax(theVmax),
- myStatus(BRepMesh_NoError),
- myIsInParallel(isInParallel)
-{
- TopoDS_Face aFace = theFace;
- aFace.Orientation(TopAbs_FORWARD);
-
- for (TopoDS_Iterator aFaceIt(aFace); aFaceIt.More(); aFaceIt.Next())
- {
- if (aFaceIt.Value().IsNull() || aFaceIt.Value().ShapeType() != TopAbs_WIRE) // may be inner vertex
- continue;
- const TopoDS_Wire& aWire = TopoDS::Wire(aFaceIt.Value());
-
- myWiresEdges.Append(ListOfEdges());
- ListOfEdges& aEdges = myWiresEdges.ChangeLast();
-
- // Start traversing the wires
- BRepTools_WireExplorer aWireExplorer(aWire, aFace);
- for (; aWireExplorer.More(); aWireExplorer.Next())
- {
- const TopoDS_Edge& aEdge = aWireExplorer.Current();
- TopAbs_Orientation aOrient = aEdge.Orientation();
- if (aOrient != TopAbs_FORWARD && aOrient != TopAbs_REVERSED)
- continue;
-
- aEdges.Append(aEdge);
- }
-
- if (aEdges.IsEmpty())
- myWiresEdges.Remove(myWiresEdges.Size());
- }
-}
-
-//=======================================================================
-//function : ReCompute
-//purpose :
-//=======================================================================
-void BRepMesh_WireChecker::ReCompute(BRepMesh::HClassifier& theClassifier)
-{
- if (theClassifier.IsNull())
- return;
-
- theClassifier->Destroy();
- myStatus = BRepMesh_NoError;
-
- SeqOfDWires aDWires;
- if (!collectDiscretizedWires(aDWires))
- return;
-
- const Standard_Integer aNbWires = aDWires.Size();
- BRepMesh::Array1OfSegmentsTree aWiresBiPoints(1, aNbWires);
- fillSegmentsTree(aDWires, aWiresBiPoints);
-
- if (myIsInParallel && aNbWires > 1)
- {
- // Check wires in parallel threads.
- Standard_Mutex aWireMutex;
- BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints, &myStatus, &aWireMutex);
- OSD_Parallel::For(1, aNbWires + 1, aIntChecker);
- }
- else
- {
- BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints, &myStatus);
- OSD_Parallel::For(1, aNbWires + 1, aIntChecker, Standard_True);
- }
-
- if (myStatus == BRepMesh_SelfIntersectingWire)
- return;
-
- // Find holes
- SeqOfDWires::Iterator aDWiresIt(aDWires);
- for (; aDWiresIt.More(); aDWiresIt.Next())
- {
- const SeqOfPnt2d& aDWire = aDWiresIt.Value();
- theClassifier->RegisterWire(aDWire, myTolUV, myUmin, myUmax, myVmin, myVmax);
- }
-}
-
-//=======================================================================
-//function : collectDiscretizedWires
-//purpose :
-//=======================================================================
-Standard_Boolean BRepMesh_WireChecker::collectDiscretizedWires(
- SeqOfDWires& theDWires)
-{
- SeqOfWireEdges::Iterator aWireIt(myWiresEdges);
- for(; aWireIt.More(); aWireIt.Next())
- {
- const ListOfEdges& aEdges = aWireIt.Value();
- // For each wire we create a data map, linking vertices (only
- // the ends of edges) with their positions in the sequence of
- // all 2d points from this wire.
- // When we meet some vertex for the second time - the piece
- // of sequence is treated for a HOLE and quits the sequence.
- // Actually, we must unbind the vertices belonging to the
- // loop from the map, but since they can't appear twice on the
- // valid wire, leave them for a little speed up.
-
- SeqOfPnt2d aSeqPnt2d;
- BRepMesh::MapOfIntegerInteger aNodeInSeq;
- Standard_Integer aFirstIndex = 0, aLastIndex = 0;
-
- // Start traversing the wire
- ListOfEdges::Iterator aEdgeIt(aEdges);
- for (; aEdgeIt.More(); aEdgeIt.Next())
- {
- const TopoDS_Edge& aEdge = aEdgeIt.Value();
- TopAbs_Orientation aOrient = aEdge.Orientation();
- if (!myEdges->IsBound(aEdge))
- continue;
-
- // Retrieve polygon
- // Define the direction for adding points to aSeqPnt2d
- Standard_Integer aStartId, aEndId, aIncrement;
- const BRepMesh_PairOfPolygon& aPair = myEdges->Find(aEdge);
- Handle(Poly_PolygonOnTriangulation) aNOD;
- if (aOrient == TopAbs_FORWARD)
- {
- aNOD = aPair.First();
- aStartId = 1;
- aEndId = aNOD->NbNodes();
- aIncrement = 1;
- }
- else
- {
- aNOD = aPair.Last();
- aStartId = aNOD->NbNodes();
- aEndId = 1;
- aIncrement = -1;
- }
-
- const TColStd_Array1OfInteger& aIndices = aNOD->Nodes();
- const Standard_Integer aFirstVertexId = myVertexMap->FindKey(aIndices(aStartId));
- const Standard_Integer aLastVertexId = myVertexMap->FindKey(aIndices(aEndId) );
-
- if (aFirstVertexId == aLastVertexId && (aEndId - aStartId) == aIncrement)
- {
- // case of continuous set of degenerated edges
- aLastIndex = aLastVertexId;
- continue;
- }
-
- if (aFirstIndex != 0)
- {
- if (aFirstVertexId != aLastIndex)
- {
- // there's a gap between edges
- myStatus = BRepMesh_OpenWire;
- return Standard_False;
- }
- }
- else
- aFirstIndex = aFirstVertexId;
-
- aLastIndex = aLastVertexId;
-
- // Record first vertex (to detect loops)
- aNodeInSeq.Bind(aFirstVertexId, (aSeqPnt2d.Length() + 1));
-
- // Add vertices in sequence
- for (Standard_Integer i = aStartId; i != aEndId; i += aIncrement)
- {
- Standard_Integer aIndex = ((i == aStartId) ?
- aFirstVertexId :
- myVertexMap->FindKey(aIndices(i)));
-
- aSeqPnt2d.Append(gp_Pnt2d(myStructure->GetNode(aIndex).Coord()));
- }
-
- // Now, is there a loop?
- if (aNodeInSeq.IsBound(aLastVertexId))
- {
- // Yes, treat it separately as a hole
- // Divide points into main wire and a loop
- const Standard_Integer aIdxWireStart = aNodeInSeq(aLastVertexId);
- if(aIdxWireStart < aSeqPnt2d.Length())
- {
- theDWires.Append(SeqOfPnt2d());
- SeqOfPnt2d& aWire = theDWires.ChangeLast();
- aSeqPnt2d.Split(aIdxWireStart, aWire);
- }
- }
- }
-
- if (aFirstIndex == 0)
- continue;
-
- // Isn't wire open?
- if (aFirstIndex != aLastIndex || aSeqPnt2d.Length() > 1)
- {
- myStatus = BRepMesh_OpenWire;
- return Standard_False;
- }
- }
-
- return Standard_True;
-}
-
-//=======================================================================
-//function : fillSegmentsTree
-//purpose :
-//=======================================================================
-void BRepMesh_WireChecker::fillSegmentsTree(
- const SeqOfDWires& theDWires,
- BRepMesh::Array1OfSegmentsTree& theWiresSegmentsTree)
-{
- const Standard_Integer aNbWires = theDWires.Size();
- for (Standard_Integer aWireIt = 1; aWireIt <= aNbWires; ++aWireIt)
- {
- const SeqOfPnt2d& aWire = theDWires(aWireIt);
- const Standard_Integer aWireLen = aWire.Size();
-
- BRepMesh::HArray1OfSegments aWireSegments =
- new BRepMesh::Array1OfSegments(1, aWireLen);
-
- BRepMesh::HBndBox2dTree aBndBoxTree =
- new BRepMesh::BndBox2dTree;
-
- BRepMesh::BndBox2dTreeFiller aBndBoxTreeFiller(*aBndBoxTree);
-
- Standard_Real x1 = 0., y1 = 0., aXstart = 0., aYstart = 0.;
- for (Standard_Integer aPntIt = 0; aPntIt <= aWireLen; ++aPntIt)
- {
- Standard_Real x2, y2;
- // Obtain last point of the segment
- if (aPntIt == aWireLen)
- {
- x2 = aXstart;
- y2 = aYstart;
- }
- else
- {
- const gp_Pnt2d& aPnt = aWire(aPntIt + 1);
- x2 = aPnt.X();
- y2 = aPnt.Y();
- }
-
- // Build segment (bi-point)
- if (aPntIt == 0)
- {
- aXstart = x2;
- aYstart = y2;
- }
- else
- {
- gp_Pnt2d aStartPnt(x1, y1);
- gp_Pnt2d aEndPnt(x2, y2);
-
- BRepMesh::Segment& aSegment = aWireSegments->ChangeValue(aPntIt);
- aSegment.StartPnt = aStartPnt.XY();
- aSegment.EndPnt = aEndPnt.XY();
-
- Bnd_Box2d aBox;
- aBox.Add(aStartPnt);
- aBox.Add( aEndPnt);
- aBndBoxTreeFiller.Add(aPntIt, aBox);
- }
- x1 = x2;
- y1 = y2;
- }
- aBndBoxTreeFiller.Fill();
-
- BRepMesh::SegmentsTree& aSegmentsTree = theWiresSegmentsTree(aWireIt);
- aSegmentsTree.first = aWireSegments;
- aSegmentsTree.second = aBndBoxTree;
- }
-}
+++ /dev/null
-// Created on: 2014-06-03
-// Created by: Oleg AGASHIN
-// Copyright (c) 1997-1999 Matra Datavision
-// Copyright (c) 1999-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef _BRepMesh_WireChecker_HeaderFile
-#define _BRepMesh_WireChecker_HeaderFile
-
-#include <Standard.hxx>
-#include <TopoDS_Face.hxx>
-#include <BRepMesh_Status.hxx>
-#include <BRepMesh_DataStructureOfDelaun.hxx>
-#include <BRepMesh.hxx>
-#include <TColStd_IndexedMapOfInteger.hxx>
-#include <TopoDS_Edge.hxx>
-#include <Bnd_Box2d.hxx>
-#include <gp_Pnt2d.hxx>
-#include <gp_XY.hxx>
-
-#include <vector>
-
-
-//! Auxilary class intended to check correctness of discretized face.
-//! In particular, checks boundaries of discretized face for self
-//! intersections and gaps.
-class BRepMesh_WireChecker
-{
-public:
-
- //! Selector.
- //! Used to identify segments with overlapped bounding boxes.
- //! Note that instance of selector can be used only once due to
- //! unextentable array of indices.
- class BndBox2dTreeSelector : public BRepMesh::BndBox2dTree::Selector
- {
- public:
- Standard_EXPORT BndBox2dTreeSelector(const Standard_Integer theReservedSize);
- Standard_EXPORT virtual Standard_Boolean Reject(const Bnd_Box2d& theBox2D) const;
- Standard_EXPORT virtual Standard_Boolean Accept(const Standard_Integer& theIndex);
-
- Standard_EXPORT void Clear();
- Standard_EXPORT void SetBox(const Bnd_Box2d& theBox2D);
- Standard_EXPORT void SetSkippedIndex(const Standard_Integer theIndex);
- Standard_EXPORT const BRepMesh::Array1OfInteger& Indices() const;
- Standard_EXPORT Standard_Integer IndicesNb() const;
-
- protected:
- Bnd_Box2d myBox2D;
- Standard_Integer mySkippedIndex;
- BRepMesh::Array1OfInteger myIndices;
- Standard_Integer myIndicesNb;
- };
-
-private:
-
- typedef NCollection_List<TopoDS_Edge> ListOfEdges;
- typedef NCollection_Sequence<ListOfEdges> SeqOfWireEdges;
-
- typedef NCollection_Sequence<gp_Pnt2d> SeqOfPnt2d;
- typedef NCollection_Sequence<SeqOfPnt2d> SeqOfDWires;
-
-public:
-
- //! Constructor.
- //! @param theFace Face to be checked.
- //! @param theTolUV Tolerance to be used for calculations in parametric space.
- //! @param theEdges Map of edges with associated polygon on triangulation.
- //! @param theVertexMap Map of face vertices.
- //! @param theStructure Discretized representation of face in parametric space.
- //! @param theUmin Lower U boundary of the face in parametric space.
- //! @param theUmax Upper U boundary of the face in parametric space.
- //! @param theVmin Lower V boundary of the face in parametric space.
- //! @param theVmax Upper V boundary of the face in parametric space.
- Standard_EXPORT BRepMesh_WireChecker(
- const TopoDS_Face& theFace,
- const Standard_Real theTolUV,
- const BRepMesh::HDMapOfShapePairOfPolygon& theEdges,
- const BRepMesh::HIMapOfInteger& theVertexMap,
- const Handle(BRepMesh_DataStructureOfDelaun)& theStructure,
- const Standard_Real theUmin,
- const Standard_Real theUmax,
- const Standard_Real theVmin,
- const Standard_Real theVmax,
- const Standard_Boolean isInParallel);
-
- //! Recompute data using parameters passed in constructor.
- //! @param[out] theClassifier Classifier to be updated using calculated data.
- Standard_EXPORT void ReCompute(BRepMesh::HClassifier& theClassifier);
-
- //! Returns status of the check.
- inline BRepMesh_Status Status() const
- {
- return myStatus;
- }
-
-private:
-
- //! Collects discrete wires.
- //! @param[out] theDWires sequence of discretized wires to be filled.
- //! @return TRUE on success, FALSE in case of open wire.
- Standard_Boolean collectDiscretizedWires(SeqOfDWires& theDWires);
-
- //! Fills array of BiPoints for corresponding wire.
- //! @param theDWires Sequence of wires to be processed.
- //! @param theWiresSegmentsTree Array of segments with corresponding
- //! bounding boxes trees to be filled.
- void fillSegmentsTree(
- const SeqOfDWires& theDWires,
- BRepMesh::Array1OfSegmentsTree& theWiresSegmentsTree);
-
- //! Assignment operator.
- void operator =(BRepMesh_WireChecker& /*theOther*/)
- {
- }
-
-private:
-
- const Standard_Real myTolUV;
- const BRepMesh::HDMapOfShapePairOfPolygon& myEdges;
- const BRepMesh::HIMapOfInteger& myVertexMap;
- const Handle(BRepMesh_DataStructureOfDelaun)& myStructure;
- const Standard_Real myUmin;
- const Standard_Real myUmax;
- const Standard_Real myVmin;
- const Standard_Real myVmax;
- BRepMesh_Status myStatus;
- SeqOfWireEdges myWiresEdges;
- Standard_Boolean myIsInParallel;
-};
-
-#endif
+++ /dev/null
-// Created on: 2014-06-18
-// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <BRepMesh_WireInterferenceChecker.hxx>
-#include <BRepMesh_GeomTool.hxx>
-#include <Precision.hxx>
-
-// TODO: remove this variable after implementation of LoopChecker2d.
-static const Standard_Real MIN_LOOP_S = 2 * M_PI * 2.E-5;
-
-//=======================================================================
-//function : Constructor
-//purpose :
-//=======================================================================
-BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
- const BRepMesh::Array1OfSegmentsTree& theWires,
- BRepMesh_Status* theStatus,
- Standard_Mutex* theMutex)
-: myWires (theWires),
- myStatus(theStatus),
- myMutex (theMutex)
-{
-}
-
-//=======================================================================
-//function : Checker's body
-//purpose :
-//=======================================================================
-void BRepMesh_WireInterferenceChecker::operator ()(
- const Standard_Integer& theWireId) const
-{
- if (*myStatus == BRepMesh_SelfIntersectingWire)
- return;
-
- const BRepMesh::SegmentsTree& aWireSegTree1 = myWires(theWireId);
- const BRepMesh::HArray1OfSegments& aWireSegments1 = aWireSegTree1.first;
- const BRepMesh::HBndBox2dTree& aWireBoxTree1 = aWireSegTree1.second;
-
- for (Standard_Integer aWireIt = theWireId; aWireIt <= myWires.Upper(); ++aWireIt)
- {
- // Break execution in case if flag was raised by another thread.
- if (*myStatus == BRepMesh_SelfIntersectingWire)
- return;
-
- const Standard_Boolean isSelfIntCheck = (aWireIt == theWireId);
- const BRepMesh::SegmentsTree& aWireSegTree2 =
- isSelfIntCheck ? aWireSegTree1 : myWires(aWireIt);
-
- const BRepMesh::HArray1OfSegments& aWireSegments2 = aWireSegTree2.first;
- const BRepMesh::HBndBox2dTree& aWireBoxTree2 = aWireSegTree2.second;
-
- BRepMesh_WireChecker::BndBox2dTreeSelector aSelector (aWireSegments2->Size());
-
- Standard_Integer aSegmentId1 = aWireSegments1->Lower();
- for (; aSegmentId1 <= aWireSegments1->Upper(); ++aSegmentId1)
- {
- // Break execution in case if flag was raised by another thread
- if (*myStatus == BRepMesh_SelfIntersectingWire)
- return;
-
- aSelector.Clear();
- aSelector.SetBox(aWireBoxTree1->FindNode(aSegmentId1).Bnd());
- if (isSelfIntCheck)
- aSelector.SetSkippedIndex(aSegmentId1);
-
- if (aWireBoxTree2->Select(aSelector) == 0)
- continue;
-
- const BRepMesh::Segment& aSegment1 = aWireSegments1->Value(aSegmentId1);
- const BRepMesh::Array1OfInteger& aSelected = aSelector.Indices();
- const Standard_Integer aSelectedNb = aSelector.IndicesNb();
- for (Standard_Integer aBndIt = 0; aBndIt < aSelectedNb; ++aBndIt)
- {
- // Break execution in case if flag was raised by another thread
- if (*myStatus == BRepMesh_SelfIntersectingWire)
- return;
-
- const Standard_Integer aSegmentId2 = aSelected(aBndIt);
- const BRepMesh::Segment& aSegment2 = aWireSegments2->Value(aSegmentId2);
-
- gp_Pnt2d aIntPnt;
- BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
- aSegment1.StartPnt, aSegment1.EndPnt,
- aSegment2.StartPnt, aSegment2.EndPnt,
- Standard_False, Standard_False,
- aIntPnt);
-
- if (aIntStatus == BRepMesh_GeomTool::Cross)
- {
- // TODO: remove this block after implementation of LoopChecker2d.
- if (isSelfIntCheck)
- {
- gp_XY aPrevVec;
- Standard_Real aSumS = 0.;
- const gp_XY& aRefPnt = aIntPnt.Coord();
- for (Standard_Integer i = aSegmentId1; i < aSegmentId2; ++i)
- {
- const BRepMesh::Segment& aSeg = aWireSegments1->Value(i);
- gp_XY aCurVec = aSeg.EndPnt - aRefPnt;
-
- if (aCurVec.SquareModulus() < gp::Resolution())
- continue;
-
- if (aPrevVec.SquareModulus() > gp::Resolution())
- aSumS += aPrevVec ^ aCurVec;
-
- aPrevVec = aCurVec;
- }
-
- if (Abs(aSumS / 2.) < MIN_LOOP_S)
- continue;
- }
-
- Standard_Mutex::Sentry aSentry(myMutex);
- *myStatus = BRepMesh_SelfIntersectingWire;
-
- return;
- }
- }
- }
- }
-}
+++ /dev/null
-// Created on: 2014-06-18
-// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#ifndef _BRepMesh_WireInterferenceChecker_HeaderFile
-#define _BRepMesh_WireInterferenceChecker_HeaderFile
-
-#include <Standard.hxx>
-#include <Standard_Mutex.hxx>
-#include <BRepMesh_WireChecker.hxx>
-#include <BRepMesh_Status.hxx>
-
-//! Auxilary class implementing functionality for
-//! checking interference between two discretized wires.
-class BRepMesh_WireInterferenceChecker
-{
-public:
-
- //! Enumerates states of segments intersection check.
- enum IntFlag
- {
- NoIntersection,
- Cross,
- EndPointTouch,
- PointOnSegment,
- Glued,
- Same
- };
-
- //! Constructor
- //! @param theWires wires that should be checked.
- //! @param theStatus shared flag to set status of the check.
- //! @param theMutex shared mutex for parallel processing.
- BRepMesh_WireInterferenceChecker(
- const BRepMesh::Array1OfSegmentsTree& theWires,
- BRepMesh_Status* theStatus,
- Standard_Mutex* theMutex = NULL);
-
- //! Checker's body.
- //! @param theWireId Id of discretized wire to be checked.
- void operator ()(const Standard_Integer& theWireId) const;
-
-private:
-
- //! Assignment operator.
- void operator =(const BRepMesh_WireInterferenceChecker& /*theOther*/)
- {
- }
-
-private:
- const BRepMesh::Array1OfSegmentsTree& myWires;
- BRepMesh_Status* myStatus;
- Standard_Mutex* myMutex;
-};
-
-#endif
-BRepMesh.hxx
+BRepMesh_BaseMeshAlgo.cxx
+BRepMesh_BaseMeshAlgo.hxx
+BRepMesh_BoundaryParamsRangeSplitter.hxx
BRepMesh_Circle.hxx
BRepMesh_CircleInspector.hxx
BRepMesh_CircleTool.cxx
BRepMesh_CircleTool.hxx
BRepMesh_Classifier.cxx
BRepMesh_Classifier.hxx
+BRepMesh_ConeRangeSplitter.cxx
+BRepMesh_ConeRangeSplitter.hxx
+BRepMesh_Context.cxx
+BRepMesh_Context.hxx
+BRepMesh_CurveTessellator.cxx
+BRepMesh_CurveTessellator.hxx
+BRepMesh_CylinderRangeSplitter.cxx
+BRepMesh_CylinderRangeSplitter.hxx
BRepMesh_DataStructureOfDelaun.cxx
BRepMesh_DataStructureOfDelaun.hxx
+BRepMesh_DefaultRangeSplitter.cxx
+BRepMesh_DefaultRangeSplitter.hxx
+BRepMesh_Deflection.cxx
+BRepMesh_Deflection.hxx
BRepMesh_DegreeOfFreedom.hxx
BRepMesh_Delaun.cxx
BRepMesh_Delaun.hxx
+BRepMesh_DelaunayBaseMeshAlgo.cxx
+BRepMesh_DelaunayBaseMeshAlgo.hxx
+BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx
+BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx
BRepMesh_DiscretFactory.cxx
BRepMesh_DiscretFactory.hxx
BRepMesh_DiscretRoot.cxx
BRepMesh_DiscretRoot.hxx
BRepMesh_Edge.hxx
-BRepMesh_EdgeParameterProvider.cxx
+BRepMesh_EdgeDiscret.cxx
+BRepMesh_EdgeDiscret.hxx
BRepMesh_EdgeParameterProvider.hxx
BRepMesh_EdgeTessellationExtractor.cxx
BRepMesh_EdgeTessellationExtractor.hxx
-BRepMesh_EdgeTessellator.cxx
-BRepMesh_EdgeTessellator.hxx
-BRepMesh_FaceAttribute.cxx
-BRepMesh_FaceAttribute.hxx
+BRepMesh_FaceChecker.cxx
+BRepMesh_FaceChecker.hxx
+BRepMesh_FaceDiscret.cxx
+BRepMesh_FaceDiscret.hxx
BRepMesh_FactoryError.hxx
-BRepMesh_FastDiscret.cxx
BRepMesh_FastDiscret.hxx
-BRepMesh_FastDiscretFace.cxx
-BRepMesh_FastDiscretFace.hxx
BRepMesh_GeomTool.cxx
BRepMesh_GeomTool.hxx
-BRepMesh_IEdgeTool.cxx
-BRepMesh_IEdgeTool.hxx
+BRepMesh_IncAllocator.hxx
BRepMesh_IncrementalMesh.cxx
BRepMesh_IncrementalMesh.hxx
+BRepMesh_MeshAlgoFactory.cxx
+BRepMesh_MeshAlgoFactory.hxx
+BRepMesh_MeshTool.cxx
+BRepMesh_MeshTool.hxx
+BRepMesh_ModelBuilder.cxx
+BRepMesh_ModelBuilder.hxx
+BRepMesh_ModelHealer.cxx
+BRepMesh_ModelHealer.hxx
+BRepMesh_ModelPostProcessor.cxx
+BRepMesh_ModelPostProcessor.hxx
+BRepMesh_ModelPreProcessor.cxx
+BRepMesh_ModelPreProcessor.hxx
+BRepMesh_NURBSRangeSplitter.cxx
+BRepMesh_NURBSRangeSplitter.hxx
+BRepMesh_NodeInsertionMeshAlgo.hxx
BRepMesh_OrientedEdge.hxx
BRepMesh_PairOfIndex.hxx
-BRepMesh_PairOfPolygon.hxx
BRepMesh_PluginEntryType.hxx
BRepMesh_PluginMacro.hxx
BRepMesh_SelectorOfDataStructureOfDelaun.cxx
BRepMesh_SelectorOfDataStructureOfDelaun.hxx
BRepMesh_ShapeTool.cxx
BRepMesh_ShapeTool.hxx
-BRepMesh_Status.hxx
+BRepMesh_ShapeVisitor.cxx
+BRepMesh_ShapeVisitor.hxx
+BRepMesh_SphereRangeSplitter.cxx
+BRepMesh_SphereRangeSplitter.hxx
+BRepMesh_TorusRangeSplitter.cxx
+BRepMesh_TorusRangeSplitter.hxx
BRepMesh_Triangle.hxx
+BRepMesh_UVParamRangeSplitter.hxx
BRepMesh_Vertex.hxx
BRepMesh_VertexInspector.hxx
BRepMesh_VertexTool.cxx
-BRepMesh_VertexTool.hxx
-BRepMesh_WireChecker.cxx
-BRepMesh_WireChecker.hxx
-BRepMesh_WireInterferenceChecker.cxx
-BRepMesh_WireInterferenceChecker.hxx
+BRepMesh_VertexTool.hxx
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMeshData_Curve.hxx>
+#include <gp_Pnt.hxx>
+#include <BRepMesh_OrientedEdge.hxx>
+#include <BRepMesh_Vertex.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMeshData_Curve::BRepMeshData_Curve (const Handle (NCollection_IncAllocator)& theAllocator)
+: myPoints (NCollection_StdAllocator<gp_Pnt>(theAllocator)),
+ myParameters (NCollection_StdAllocator<Standard_Real>(theAllocator))
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMeshData_Curve::~BRepMeshData_Curve ()
+{
+}
+
+//=======================================================================
+// Function: InsertPoint
+// Purpose :
+//=======================================================================
+void BRepMeshData_Curve::InsertPoint(
+ const Standard_Integer thePosition,
+ const gp_Pnt& thePoint,
+ const Standard_Real theParamOnPCurve)
+{
+ myPoints .insert(myPoints .begin() + thePosition, thePoint);
+ myParameters.insert(myParameters.begin() + thePosition, theParamOnPCurve);
+}
+
+//=======================================================================
+// Function: AddPoint
+// Purpose :
+//=======================================================================
+void BRepMeshData_Curve::AddPoint (
+ const gp_Pnt& thePoint,
+ const Standard_Real theParamOnPCurve)
+{
+ myPoints .push_back(thePoint);
+ myParameters.push_back(theParamOnPCurve);
+}
+
+//=======================================================================
+// Function: GetPoint
+// Purpose :
+//=======================================================================
+gp_Pnt& BRepMeshData_Curve::GetPoint (const Standard_Integer theIndex)
+{
+ return myPoints[theIndex];
+}
+
+//=======================================================================
+// Function: GetParameter
+// Purpose :
+//=======================================================================
+Standard_Real& BRepMeshData_Curve::GetParameter (const Standard_Integer theIndex)
+{
+ return myParameters[theIndex];
+}
+
+//=======================================================================
+// Function: ParameterNb
+// Purpose :
+//=======================================================================
+Standard_Integer BRepMeshData_Curve::ParametersNb() const
+{
+ return static_cast<Standard_Integer>(myParameters.size());
+}
+
+//=======================================================================
+// Function: RemovePoint
+// Purpose :
+//=======================================================================
+void BRepMeshData_Curve::RemovePoint (const Standard_Integer theIndex)
+{
+ myPoints.erase(myPoints.begin() + theIndex);
+ removeParameter (theIndex);
+}
+
+//=======================================================================
+// Function: removeParameter
+// Purpose :
+//=======================================================================
+void BRepMeshData_Curve::removeParameter (const Standard_Integer theIndex)
+{
+ myParameters.erase(myParameters.begin() + theIndex);
+}
+
+//=======================================================================
+// Function: Clear
+// Purpose :
+//=======================================================================
+void BRepMeshData_Curve::Clear(const Standard_Boolean isKeepEndPoints)
+{
+ if (!isKeepEndPoints)
+ {
+ myPoints .clear();
+ myParameters.clear();
+ }
+ else if (ParametersNb() > 2)
+ {
+ myPoints .erase(myPoints .begin() + 1, myPoints .begin() + (myPoints .size() - 1));
+ myParameters.erase(myParameters.begin() + 1, myParameters.begin() + (myParameters.size() - 1));
+ }
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMeshData_Curve_HeaderFile
+#define _BRepMeshData_Curve_HeaderFile
+
+#include <IMeshData_Curve.hxx>
+#include <Standard_Type.hxx>
+#include <NCollection_IncAllocator.hxx>
+#include <IMeshData_Types.hxx>
+
+//! Default implementation of curve data model entity.
+class BRepMeshData_Curve : public IMeshData_Curve
+{
+public:
+
+ DEFINE_INC_ALLOC
+
+ //! Constructor.
+ Standard_EXPORT BRepMeshData_Curve (const Handle (NCollection_IncAllocator)& theAllocator);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMeshData_Curve ();
+
+ //! Inserts new discretization point at the given position.
+ Standard_EXPORT virtual void InsertPoint(
+ const Standard_Integer thePosition,
+ const gp_Pnt& thePoint,
+ const Standard_Real theParamOnPCurve) Standard_OVERRIDE;
+
+ //! Adds new discretization point to pcurve.
+ Standard_EXPORT virtual void AddPoint (
+ const gp_Pnt& thePoint,
+ const Standard_Real theParamOnCurve) Standard_OVERRIDE;
+
+ //! Returns discretization point with the given index.
+ Standard_EXPORT virtual gp_Pnt& GetPoint (const Standard_Integer theIndex) Standard_OVERRIDE;
+
+ //! Removes point with the given index.
+ Standard_EXPORT virtual void RemovePoint (const Standard_Integer theIndex) Standard_OVERRIDE;
+
+ //! Returns parameter with the given index.
+ Standard_EXPORT virtual Standard_Real& GetParameter (const Standard_Integer theIndex) Standard_OVERRIDE;
+
+ //! Returns number of parameters stored in curve.
+ Standard_EXPORT virtual Standard_Integer ParametersNb() const Standard_OVERRIDE;
+
+ //! Clears parameters list.
+ Standard_EXPORT virtual void Clear(const Standard_Boolean isKeepEndPoints) Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Curve, IMeshData_Curve)
+
+protected:
+
+ //! Removes parameter with the given index.
+ Standard_EXPORT virtual void removeParameter (const Standard_Integer theIndex) Standard_OVERRIDE;
+
+private:
+
+ IMeshData::Model::SequenceOfPnt myPoints;
+ IMeshData::Model::SequenceOfReal myParameters;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMeshData_Edge.hxx>
+#include <BRepMeshData_PCurve.hxx>
+#include <BRepMeshData_Curve.hxx>
+#include <BRepMesh_OrientedEdge.hxx>
+#include <BRepMesh_Vertex.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMeshData_Edge::BRepMeshData_Edge (
+ const TopoDS_Edge& theEdge,
+ const Handle (NCollection_IncAllocator)& theAllocator)
+ : IMeshData_Edge (theEdge),
+ myAllocator (theAllocator),
+ myPCurves (256, myAllocator),
+ myPCurvesMap(1, myAllocator)
+{
+ SetCurve (IMeshData::ICurveHandle (new (myAllocator) BRepMeshData_Curve (myAllocator)));
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMeshData_Edge::~BRepMeshData_Edge ()
+{
+}
+
+//=======================================================================
+// Function: AddPCurve
+// Purpose :
+//=======================================================================
+Standard_Integer BRepMeshData_Edge::PCurvesNb () const
+{
+ return myPCurves.Size ();
+}
+
+//=======================================================================
+// Function: AddPCurve
+// Purpose :
+//=======================================================================
+const IMeshData::IPCurveHandle& BRepMeshData_Edge::AddPCurve (
+ const IMeshData::IFacePtr& theDFace,
+ const TopAbs_Orientation theOrientation)
+{
+ const Standard_Integer aPCurveIndex = PCurvesNb ();
+ // Add pcurve to list of pcurves
+ IMeshData::IPCurveHandle aPCurve (new (myAllocator) BRepMeshData_PCurve (theDFace, theOrientation, myAllocator));
+ myPCurves.Append (aPCurve);
+
+ // Map pcurve to faces.
+ if (!myPCurvesMap.IsBound(theDFace))
+ {
+ myPCurvesMap.Bind(theDFace, IMeshData::ListOfInteger(myAllocator));
+ }
+
+ IMeshData::ListOfInteger& aListOfPCurves = myPCurvesMap.ChangeFind(theDFace);
+ aListOfPCurves.Append (aPCurveIndex);
+
+ return GetPCurve (aPCurveIndex);
+}
+
+//=======================================================================
+// Function: GetPCurve
+// Purpose :
+//=======================================================================
+const IMeshData::IPCurveHandle& BRepMeshData_Edge::GetPCurve (
+ const IMeshData::IFacePtr& theDFace,
+ const TopAbs_Orientation theOrientation) const
+{
+ const IMeshData::ListOfInteger& aListOfPCurves = myPCurvesMap.Find (theDFace);
+ const IMeshData::IPCurveHandle& aPCurve1 = myPCurves (aListOfPCurves.First ());
+ return (aPCurve1->GetOrientation () == theOrientation) ?
+ aPCurve1 :
+ myPCurves (aListOfPCurves.Last ());
+}
+
+//=======================================================================
+// Function: GetPCurve
+// Purpose :
+//=======================================================================
+const IMeshData::IPCurveHandle& BRepMeshData_Edge::GetPCurve (
+ const Standard_Integer theIndex) const
+{
+ return myPCurves (theIndex);
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMeshData_Edge_HeaderFile
+#define _BRepMeshData_Edge_HeaderFile
+
+#include <IMeshData_Edge.hxx>
+#include <IMeshData_Curve.hxx>
+#include <NCollection_IncAllocator.hxx>
+#include <IMeshData_Types.hxx>
+
+//! Default implementation of edge data model entity.
+class BRepMeshData_Edge : public IMeshData_Edge
+{
+public:
+
+ DEFINE_INC_ALLOC
+
+ //! Constructor.
+ Standard_EXPORT BRepMeshData_Edge (
+ const TopoDS_Edge& theEdge,
+ const Handle (NCollection_IncAllocator)& theAllocator);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMeshData_Edge ();
+
+ //! Returns number of pcurves assigned to current edge.
+ Standard_EXPORT virtual Standard_Integer PCurvesNb () const Standard_OVERRIDE;
+
+ //! Adds disrete pcurve for the specifed discrete face.
+ Standard_EXPORT virtual const IMeshData::IPCurveHandle& AddPCurve (
+ const IMeshData::IFacePtr& theDFace,
+ const TopAbs_Orientation theOrientation) Standard_OVERRIDE;
+
+ //! Returns pcurve for the specified discrete face.
+ Standard_EXPORT virtual const IMeshData::IPCurveHandle& GetPCurve (
+ const IMeshData::IFacePtr& theDFace,
+ const TopAbs_Orientation theOrientation) const Standard_OVERRIDE;
+
+ //! Returns pcurve with the given index.
+ Standard_EXPORT virtual const IMeshData::IPCurveHandle& GetPCurve (
+ const Standard_Integer theIndex) const Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Edge, IMeshData_Edge)
+
+private:
+
+ Handle (NCollection_IncAllocator) myAllocator;
+ IMeshData::VectorOfIPCurveHandles myPCurves;
+ IMeshData::DMapOfIFacePtrsListOfInteger myPCurvesMap;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMeshData_Face.hxx>
+#include <BRepMeshData_Wire.hxx>
+#include <BRepMesh_OrientedEdge.hxx>
+#include <BRepMesh_Vertex.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMeshData_Face::BRepMeshData_Face (
+ const TopoDS_Face& theFace,
+ const Handle (NCollection_IncAllocator)& theAllocator)
+ : IMeshData_Face (theFace),
+ myAllocator (theAllocator),
+ myDWires (256, myAllocator)
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMeshData_Face::~BRepMeshData_Face ()
+{
+}
+
+//=======================================================================
+// Function: WiresNb
+// Purpose :
+//=======================================================================
+Standard_Integer BRepMeshData_Face::WiresNb () const
+{
+ return myDWires.Size ();
+}
+
+//=======================================================================
+// Function: AddWire
+// Purpose :
+//=======================================================================
+const IMeshData::IWireHandle& BRepMeshData_Face::AddWire (
+ const TopoDS_Wire& theWire,
+ const Standard_Integer theEdgeNb)
+{
+ IMeshData::IWireHandle aWire (new (myAllocator) BRepMeshData_Wire (theWire, theEdgeNb, myAllocator));
+ myDWires.Append (aWire);
+ return GetWire (WiresNb () - 1);
+}
+
+//=======================================================================
+// Function: GetWire
+// Purpose :
+//=======================================================================
+const IMeshData::IWireHandle& BRepMeshData_Face::GetWire (
+ const Standard_Integer theIndex) const
+{
+ return myDWires (theIndex);
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMeshData_Face_HeaderFile
+#define _BRepMeshData_Face_HeaderFile
+
+#include <IMeshData_Types.hxx>
+#include <IMeshData_Face.hxx>
+#include <IMeshData_Wire.hxx>
+
+//! Default implementation of face data model entity.
+class BRepMeshData_Face : public IMeshData_Face
+{
+public:
+
+ DEFINE_INC_ALLOC
+
+ //! Constructor.
+ Standard_EXPORT BRepMeshData_Face (
+ const TopoDS_Face& theFace,
+ const Handle (NCollection_IncAllocator)& theAllocator);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMeshData_Face ();
+
+ //! Gets number of children.
+ Standard_EXPORT virtual Standard_Integer WiresNb () const Standard_OVERRIDE;
+
+ //! Gets wire with the given index.
+ Standard_EXPORT virtual const IMeshData::IWireHandle& GetWire (
+ const Standard_Integer theIndex) const Standard_OVERRIDE;
+
+ //! Adds wire to discrete model of face.
+ Standard_EXPORT virtual const IMeshData::IWireHandle& AddWire (
+ const TopoDS_Wire& theWire,
+ const Standard_Integer theEdgeNb = 0) Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Face, IMeshData_Face)
+
+private:
+
+ Handle (NCollection_IncAllocator) myAllocator;
+ IMeshData::VectorOfIWireHandles myDWires;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMeshData_Model.hxx>
+#include <BRepMeshData_Face.hxx>
+#include <BRepMeshData_Edge.hxx>
+#include <BRepMesh_IncAllocator.hxx>
+#include <BRepMesh_OrientedEdge.hxx>
+#include <BRepMesh_Vertex.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMeshData_Model::BRepMeshData_Model (const TopoDS_Shape& theShape)
+ : IMeshData_Model (theShape),
+ myMaxSize (0.),
+ myAllocator (new BRepMesh_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)),
+ myDFaces (256, myAllocator),
+ myDEdges (256, myAllocator)
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMeshData_Model::~BRepMeshData_Model ()
+{
+}
+
+//=======================================================================
+// Function: FacesNb
+// Purpose :
+//=======================================================================
+Standard_Integer BRepMeshData_Model::FacesNb () const
+{
+ return myDFaces.Size ();
+}
+
+//=======================================================================
+// Function: AddFace
+// Purpose :
+//=======================================================================
+const IMeshData::IFaceHandle& BRepMeshData_Model::AddFace (const TopoDS_Face& theFace)
+{
+ IMeshData::IFaceHandle aFace (new (myAllocator) BRepMeshData_Face (theFace, myAllocator));
+ myDFaces.Append (aFace);
+ return myDFaces (FacesNb () - 1);
+}
+
+//=======================================================================
+// Function: GetFace
+// Purpose :
+//=======================================================================
+const IMeshData::IFaceHandle& BRepMeshData_Model::GetFace (const Standard_Integer theIndex) const
+{
+ return myDFaces (theIndex);
+}
+
+//=======================================================================
+// Function: EdgesNb
+// Purpose :
+//=======================================================================
+Standard_Integer BRepMeshData_Model::EdgesNb () const
+{
+ return myDEdges.Size ();
+}
+
+//=======================================================================
+// Function: AddEdge
+// Purpose :
+//=======================================================================
+const IMeshData::IEdgeHandle& BRepMeshData_Model::AddEdge (const TopoDS_Edge& theEdge)
+{
+ IMeshData::IEdgeHandle aEdge (new (myAllocator) BRepMeshData_Edge (theEdge, myAllocator));
+ myDEdges.Append (aEdge);
+ return myDEdges (EdgesNb () - 1);
+}
+
+//=======================================================================
+// Function: GetEdge
+// Purpose :
+//=======================================================================
+const IMeshData::IEdgeHandle& BRepMeshData_Model::GetEdge (const Standard_Integer theIndex) const
+{
+ return myDEdges (theIndex);
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMeshData_Model_HeaderFile
+#define _BRepMeshData_Model_HeaderFile
+
+#include <IMeshData_Model.hxx>
+#include <IMeshData_Types.hxx>
+#include <NCollection_IncAllocator.hxx>
+#include <IMeshData_Face.hxx>
+#include <IMeshData_Edge.hxx>
+
+//! Default implementation of model entity.
+class BRepMeshData_Model : public IMeshData_Model
+{
+public:
+
+ //! Constructor.
+ //! Initializes empty model.
+ Standard_EXPORT BRepMeshData_Model (const TopoDS_Shape& theShape);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMeshData_Model ();
+
+ //! Returns maximum size of shape's bounding box.
+ Standard_EXPORT virtual Standard_Real GetMaxSize () const Standard_OVERRIDE
+ {
+ return myMaxSize;
+ }
+
+ //! Sets maximum size of shape's bounding box.
+ inline void SetMaxSize (const Standard_Real theValue)
+ {
+ myMaxSize = theValue;
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Model, IMeshData_Model)
+
+public: //! @name discrete faces
+
+ //! Returns number of faces in discrete model.
+ Standard_EXPORT virtual Standard_Integer FacesNb () const Standard_OVERRIDE;
+
+ //! Adds new face to shape model.
+ Standard_EXPORT virtual const IMeshData::IFaceHandle& AddFace (const TopoDS_Face& theFace) Standard_OVERRIDE;
+
+ //! Gets model's face with the given index.
+ Standard_EXPORT virtual const IMeshData::IFaceHandle& GetFace (const Standard_Integer theIndex) const Standard_OVERRIDE;
+
+public: //! @name discrete edges
+
+ //! Returns number of edges in discrete model.
+ Standard_EXPORT virtual Standard_Integer EdgesNb () const Standard_OVERRIDE;
+
+ //! Adds new edge to shape model.
+ Standard_EXPORT virtual const IMeshData::IEdgeHandle& AddEdge (const TopoDS_Edge& theEdge) Standard_OVERRIDE;
+
+ //! Gets model's edge with the given index.
+ Standard_EXPORT virtual const IMeshData::IEdgeHandle& GetEdge (const Standard_Integer theIndex) const Standard_OVERRIDE;
+
+private:
+
+ Standard_Real myMaxSize;
+ Handle (NCollection_IncAllocator) myAllocator;
+ IMeshData::VectorOfIFaceHandles myDFaces;
+ IMeshData::VectorOfIEdgeHandles myDEdges;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMeshData_PCurve.hxx>
+#include <gp_Pnt2d.hxx>
+#include <BRepMesh_OrientedEdge.hxx>
+#include <BRepMesh_Vertex.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMeshData_PCurve::BRepMeshData_PCurve (
+ const IMeshData::IFacePtr& theDFace,
+ const TopAbs_Orientation theOrientation,
+ const Handle (NCollection_IncAllocator)& theAllocator)
+ : IMeshData_PCurve (theDFace, theOrientation),
+ myPoints2d (NCollection_StdAllocator<gp_Pnt2d>(theAllocator)),
+ myParameters (NCollection_StdAllocator<Standard_Real>(theAllocator)),
+ myIndices (NCollection_StdAllocator<Standard_Integer>(theAllocator))
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMeshData_PCurve::~BRepMeshData_PCurve ()
+{
+}
+
+//=======================================================================
+// Function: InsertPoint
+// Purpose :
+//=======================================================================
+void BRepMeshData_PCurve::InsertPoint(
+ const Standard_Integer thePosition,
+ const gp_Pnt2d& thePoint,
+ const Standard_Real theParamOnPCurve)
+{
+ myPoints2d .insert(myPoints2d .begin() + thePosition, thePoint);
+ myParameters.insert(myParameters.begin() + thePosition, theParamOnPCurve);
+ myIndices .insert(myIndices .begin() + thePosition, 0);
+}
+
+//=======================================================================
+// Function: AddPoint
+// Purpose :
+//=======================================================================
+void BRepMeshData_PCurve::AddPoint (
+ const gp_Pnt2d& thePoint,
+ const Standard_Real theParamOnPCurve)
+{
+ myPoints2d .push_back(thePoint);
+ myParameters.push_back(theParamOnPCurve);
+ myIndices .push_back(0);
+}
+
+//=======================================================================
+// Function: GetPoint
+// Purpose :
+//=======================================================================
+gp_Pnt2d& BRepMeshData_PCurve::GetPoint (const Standard_Integer theIndex)
+{
+ return myPoints2d[theIndex];
+}
+
+//=======================================================================
+// Function: GetIndex
+// Purpose :
+//=======================================================================
+Standard_Integer& BRepMeshData_PCurve::GetIndex(const Standard_Integer theIndex)
+{
+ return myIndices[theIndex];
+}
+
+//=======================================================================
+// Function: GetParameter
+// Purpose :
+//=======================================================================
+Standard_Real& BRepMeshData_PCurve::GetParameter (const Standard_Integer theIndex)
+{
+ return myParameters[theIndex];
+}
+
+//=======================================================================
+// Function: ParameterNb
+// Purpose :
+//=======================================================================
+Standard_Integer BRepMeshData_PCurve::ParametersNb() const
+{
+ return static_cast<Standard_Integer>(myParameters.size());
+}
+
+//=======================================================================
+// Function: RemovePoint
+// Purpose :
+//=======================================================================
+void BRepMeshData_PCurve::RemovePoint (const Standard_Integer theIndex)
+{
+ myPoints2d.erase(myPoints2d.begin() + theIndex);
+ myIndices .erase(myIndices .begin() + theIndex);
+ removeParameter (theIndex);
+}
+
+//=======================================================================
+// Function: removeParameter
+// Purpose :
+//=======================================================================
+void BRepMeshData_PCurve::removeParameter (const Standard_Integer theIndex)
+{
+ myParameters.erase(myParameters.begin() + theIndex);
+}
+
+//=======================================================================
+// Function: Clear
+// Purpose :
+//=======================================================================
+void BRepMeshData_PCurve::Clear(const Standard_Boolean isKeepEndPoints)
+{
+ if (!isKeepEndPoints)
+ {
+ myPoints2d .clear();
+ myParameters.clear();
+ myIndices .clear();
+ }
+ else if (ParametersNb() > 2)
+ {
+ myPoints2d .erase(myPoints2d .begin() + 1, myPoints2d .begin() + (myPoints2d .size() - 1));
+ myParameters.erase(myParameters.begin() + 1, myParameters.begin() + (myParameters.size() - 1));
+ myIndices .erase(myIndices .begin() + 1, myIndices .begin() + (myIndices .size() - 1));
+ }
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMeshData_PCurve_HeaderFile
+#define _BRepMeshData_PCurve_HeaderFile
+
+#include <IMeshData_PCurve.hxx>
+#include <Standard_Type.hxx>
+#include <NCollection_IncAllocator.hxx>
+
+//! Default implementation of pcurve data model entity.
+class BRepMeshData_PCurve : public IMeshData_PCurve
+{
+public:
+
+ DEFINE_INC_ALLOC
+
+ //! Constructor.
+ Standard_EXPORT BRepMeshData_PCurve (
+ const IMeshData::IFacePtr& theDFace,
+ const TopAbs_Orientation theOrientation,
+ const Handle (NCollection_IncAllocator)& theAllocator);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMeshData_PCurve ();
+
+ //! Inserts new discretization point at the given position.
+ Standard_EXPORT virtual void InsertPoint(
+ const Standard_Integer thePosition,
+ const gp_Pnt2d& thePoint,
+ const Standard_Real theParamOnPCurve) Standard_OVERRIDE;
+
+ //! Adds new discretization point to pcurve.
+ Standard_EXPORT virtual void AddPoint (
+ const gp_Pnt2d& thePoint,
+ const Standard_Real theParamOnPCurve) Standard_OVERRIDE;
+
+ //! Returns discretization point with the given index.
+ Standard_EXPORT virtual gp_Pnt2d& GetPoint (const Standard_Integer theIndex) Standard_OVERRIDE;
+
+ //! Returns index in mesh corresponded to discretization point with the given index.
+ Standard_EXPORT virtual Standard_Integer& GetIndex(const Standard_Integer theIndex) Standard_OVERRIDE;
+
+ //! Removes point with the given index.
+ Standard_EXPORT virtual void RemovePoint (const Standard_Integer theIndex) Standard_OVERRIDE;
+
+ //! Returns parameter with the given index.
+ Standard_EXPORT virtual Standard_Real& GetParameter (const Standard_Integer theIndex) Standard_OVERRIDE;
+
+ //! Returns number of parameters stored in pcurve.
+ Standard_EXPORT virtual Standard_Integer ParametersNb() const Standard_OVERRIDE;
+
+ //! Clears parameters list.
+ Standard_EXPORT virtual void Clear(const Standard_Boolean isKeepEndPoints) Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_PCurve, IMeshData_PCurve)
+
+protected:
+
+ //! Removes parameter with the given index.
+ Standard_EXPORT virtual void removeParameter (const Standard_Integer theIndex) Standard_OVERRIDE;
+
+private:
+
+ IMeshData::Model::SequenceOfPnt2d myPoints2d;
+ IMeshData::Model::SequenceOfReal myParameters;
+ IMeshData::Model::SequenceOfInteger myIndices;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BRepMeshData_Wire.hxx>
+#include <IMeshData_Edge.hxx>
+#include <BRepMesh_OrientedEdge.hxx>
+#include <BRepMesh_Vertex.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+BRepMeshData_Wire::BRepMeshData_Wire (
+ const TopoDS_Wire& theWire,
+ const Standard_Integer theEdgeNb,
+ const Handle (NCollection_IncAllocator)& theAllocator)
+ : IMeshData_Wire (theWire),
+ myDEdges (theEdgeNb > 0 ? theEdgeNb : 256, theAllocator),
+ myDEdgesOri (theEdgeNb > 0 ? theEdgeNb : 256, theAllocator)
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+BRepMeshData_Wire::~BRepMeshData_Wire ()
+{
+}
+
+//=======================================================================
+// Function: EdgesNb
+// Purpose :
+//=======================================================================
+Standard_Integer BRepMeshData_Wire::EdgesNb () const
+{
+ return myDEdges.Size ();
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+Standard_Integer BRepMeshData_Wire::AddEdge (
+ const IMeshData::IEdgePtr& theDEdge,
+ const TopAbs_Orientation theOrientation)
+{
+ const Standard_Integer aIndex = EdgesNb ();
+
+ myDEdges .Append (theDEdge);
+ myDEdgesOri.Append (theOrientation);
+
+ return aIndex;
+}
+
+//=======================================================================
+// Function: GetEdge
+// Purpose :
+//=======================================================================
+const IMeshData::IEdgePtr& BRepMeshData_Wire::GetEdge (
+ const Standard_Integer theIndex) const
+{
+ return myDEdges (theIndex);
+}
+
+//=======================================================================
+// Function: GetEdgeOrientation
+// Purpose :
+//=======================================================================
+TopAbs_Orientation BRepMeshData_Wire::GetEdgeOrientation (
+ const Standard_Integer theIndex) const
+{
+ return myDEdgesOri (theIndex);
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepMeshData_Wire_HeaderFile
+#define _BRepMeshData_Wire_HeaderFile
+
+#include <IMeshData_Wire.hxx>
+#include <IMeshData_Types.hxx>
+
+//! Default implementation of wire data model entity.
+class BRepMeshData_Wire : public IMeshData_Wire
+{
+public:
+
+ DEFINE_INC_ALLOC
+
+ //! Constructor.
+ Standard_EXPORT BRepMeshData_Wire (
+ const TopoDS_Wire& theWire,
+ const Standard_Integer theEdgeNb,
+ const Handle (NCollection_IncAllocator)& theAllocator);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~BRepMeshData_Wire ();
+
+ //! Gets number of children.
+ Standard_EXPORT virtual Standard_Integer EdgesNb () const Standard_OVERRIDE;
+
+ //! Adds new discrete edge with specified orientation to wire chain.
+ //! @return index of added edge in wire chain.
+ Standard_EXPORT virtual Standard_Integer AddEdge (
+ const IMeshData::IEdgePtr& theDEdge,
+ const TopAbs_Orientation theOrientation) Standard_OVERRIDE;
+
+ //! Gets edge with the given index.
+ Standard_EXPORT virtual const IMeshData::IEdgePtr& GetEdge (
+ const Standard_Integer theIndex) const Standard_OVERRIDE;
+
+ //! Returns True if orientation of discrete edge with the given index is forward.
+ Standard_EXPORT virtual TopAbs_Orientation GetEdgeOrientation (
+ const Standard_Integer theIndex) const Standard_OVERRIDE;
+
+ DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Wire, IMeshData_Wire)
+
+private:
+
+ IMeshData::VectorOfIEdgePtrs myDEdges;
+ IMeshData::VectorOfOrientation myDEdgesOri;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+BRepMeshData_Curve.cxx
+BRepMeshData_Curve.hxx
+BRepMeshData_Edge.cxx
+BRepMeshData_Edge.hxx
+BRepMeshData_Face.cxx
+BRepMeshData_Face.hxx
+BRepMeshData_Model.cxx
+BRepMeshData_Model.hxx
+BRepMeshData_PCurve.cxx
+BRepMeshData_PCurve.hxx
+BRepMeshData_Wire.cxx
+BRepMeshData_Wire.hxx
if (!strcmp(dout.GetType(id),"PERS")) focal = dout.Focal(id);
Standard_Real Ang,Def;
HLRBRep::PolyHLRAngleAndDeflection(myAng,Ang,Def);
- BRepMesh_FastDiscret::Parameters aMeshParams;
- aMeshParams.Relative = Standard_True;
+ IMeshTools_Parameters aMeshParams;
+ aMeshParams.Relative = Standard_True;
aMeshParams.Deflection = Def;
- aMeshParams.Angle = Ang;
+ aMeshParams.Angle = Ang;
+
BRepMesh_IncrementalMesh MESH(myShape, aMeshParams);
Standard_Boolean recompute = Standard_True;
// find if the view must be recomputed
uplevel dval ($x1)*($x2)+($y1)*($y2)
}
+help vecangle {vecangle x1 y1 z1 x2 y2 z2
+ returns angle between two vectors\
+} {Vector and measurement Commands}
+
+proc vecangle {x1 y1 z1 x2 y2 z2} {
+ set d [uplevel dot $x1 $y1 $z1 $x2 $y2 $z2]
+ set c [uplevel cross $x1 $y1 $z1 $x2 $y2 $z2]
+ set cm [uplevel module $c]
+
+ set m1 [uplevel module $x1 $y1 $z1]
+ set m2 [uplevel module $x2 $y2 $z2]
+ set mm [expr $m1*$m2]
+
+ if { $cm < $d } {
+ expr asin($cm/$mm)
+ } else {
+ expr acos($d/$mm)
+ }
+}
+
+help 2dvecangle {2dvecangle x1 y1 x2 y2
+ returns angle between two vectors\
+} {Vector and measurement Commands}
+
+proc 2dvecangle {x1 y1 x2 y2} {
+ set d [uplevel 1 2ddot $x1 $y1 $x2 $y2]
+ set c [uplevel 1 2dcross $x1 $y1 $x2 $y2]
+
+ set m1 [uplevel 1 2dmodule $x1 $y1]
+ set m2 [uplevel 1 2dmodule $x2 $y2]
+ set mm [expr $m1*$m2]
+
+ if { $c < $d } {
+ expr asin($c/$mm)
+ } else {
+ expr acos($d/$mm)
+ }
+}
+
help scale {scale x y z factor
returns vector multiplied by scalar\
} {Vector and measurement Commands}
Standard_Real& U1,
Standard_Real& U2)
{
+ if (Precision::IsInfinite(UFirst) ||
+ Precision::IsInfinite(ULast))
+ {
+ U1 = UFirst;
+ U2 = ULast;
+ return;
+ }
+
Standard_Real period = ULast - UFirst;
+
+ if (period < Epsilon(ULast))
+ {
+ // In order to avoid FLT_Overflow exception
+ // (test bugs moddata_1 bug22757)
+ U1 = UFirst;
+ U2 = ULast;
+ return;
+ }
+
U1 -= Floor((U1-UFirst)/period) * period;
if (ULast - U1 < Preci) U1 -= period;
U2 -= Floor((U2-U1)/period) * period;
const Standard_Real aDiff = lastu - firstu;
// Round up number of points to satisfy curvatureDeflection more precisely
- Standard_Integer NbPoints = (Standard_Integer)Ceiling(aDiff / Du);
+ Standard_Integer NbPoints = (Standard_Integer)Min(Ceiling(aDiff / Du), 1.0e+6);
NbPoints = Max(NbPoints, minNbPnts - 1);
Du = aDiff / NbPoints;
--- /dev/null
+IMeshData_Curve.hxx
+IMeshData_Edge.hxx
+IMeshData_Face.hxx
+IMeshData_Model.hxx
+IMeshData_ParametersList.hxx
+IMeshData_ParametersListArrayAdaptor.hxx
+IMeshData_PCurve.hxx
+IMeshData_Shape.hxx
+IMeshData_Status.hxx
+IMeshData_StatusOwner.hxx
+IMeshData_TessellatedShape.hxx
+IMeshData_Types.hxx
+IMeshData_Wire.hxx
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_Curve_HeaderFile
+#define _IMeshData_Curve_HeaderFile
+
+#include <IMeshData_ParametersList.hxx>
+#include <Standard_Type.hxx>
+
+class gp_Pnt;
+
+//! Interface class representing discrete 3d curve of edge.
+//! Indexation of points starts from zero.
+class IMeshData_Curve : public IMeshData_ParametersList
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_Curve()
+ {
+ }
+
+ //! Inserts new discretization point at the given position.
+ Standard_EXPORT virtual void InsertPoint(
+ const Standard_Integer thePosition,
+ const gp_Pnt& thePoint,
+ const Standard_Real theParamOnPCurve) = 0;
+
+ //! Adds new discretization point to curve.
+ Standard_EXPORT virtual void AddPoint (
+ const gp_Pnt& thePoint,
+ const Standard_Real theParamOnCurve) = 0;
+
+ //! Returns discretization point with the given index.
+ Standard_EXPORT virtual gp_Pnt& GetPoint (const Standard_Integer theIndex) = 0;
+
+ //! Removes point with the given index.
+ Standard_EXPORT virtual void RemovePoint (const Standard_Integer theIndex) = 0;
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshData_Curve, IMeshData_ParametersList)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshData_Curve()
+ {
+ }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_Edge_HeaderFile
+#define _IMeshData_Edge_HeaderFile
+
+#include <IMeshData_TessellatedShape.hxx>
+#include <IMeshData_StatusOwner.hxx>
+#include <Standard_Type.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS.hxx>
+#include <IMeshData_Curve.hxx>
+#include <IMeshData_PCurve.hxx>
+#include <IMeshData_Types.hxx>
+#include <BRep_Tool.hxx>
+
+class IMeshData_Face;
+
+//! Interface class representing discrete model of an edge.
+class IMeshData_Edge : public IMeshData_TessellatedShape, public IMeshData_StatusOwner
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_Edge()
+ {
+ }
+
+ //! Returns TopoDS_Edge attached to model.
+ inline const TopoDS_Edge& GetEdge () const
+ {
+ return TopoDS::Edge (GetShape ());
+ }
+
+ //! Returns number of pcurves assigned to current edge.
+ Standard_EXPORT virtual Standard_Integer PCurvesNb () const = 0;
+
+ //! Adds discrete pcurve for the specifed discrete face.
+ Standard_EXPORT virtual const IMeshData::IPCurveHandle& AddPCurve (
+ const IMeshData::IFacePtr& theDFace,
+ const TopAbs_Orientation theOrientation) = 0;
+
+ //! Returns pcurve for the specified discrete face.
+ Standard_EXPORT virtual const IMeshData::IPCurveHandle& GetPCurve (
+ const IMeshData::IFacePtr& theDFace,
+ const TopAbs_Orientation theOrientation) const = 0;
+
+ //! Returns pcurve with the given index.
+ Standard_EXPORT virtual const IMeshData::IPCurveHandle& GetPCurve (
+ const Standard_Integer theIndex) const = 0;
+
+ //! Clears curve and all pcurves assigned to the edge from discretization.
+ inline void Clear(const Standard_Boolean isKeepEndPoints)
+ {
+ myCurve->Clear(isKeepEndPoints);
+ for (Standard_Integer aPCurveIt = 0; aPCurveIt < PCurvesNb(); ++aPCurveIt)
+ {
+ GetPCurve(aPCurveIt)->Clear(isKeepEndPoints);
+ }
+ }
+
+ //! Returns true in case if the edge is free one, i.e. it does not have pcurves.
+ inline Standard_Boolean IsFree () const
+ {
+ return (PCurvesNb () == 0);
+ }
+
+ //! Sets 3d curve associated with current edge.
+ inline void SetCurve (const IMeshData::ICurveHandle& theCurve)
+ {
+ myCurve = theCurve;
+ }
+
+ //! Returns 3d curve associated with current edge.
+ inline const IMeshData::ICurveHandle& GetCurve () const
+ {
+ return myCurve;
+ }
+
+ //! Gets value of angular deflection for the discrete model.
+ inline Standard_Real GetAngularDeflection () const
+ {
+ return myAngDeflection;
+ }
+
+ //! Sets value of angular deflection for the discrete model.
+ inline void SetAngularDeflection (const Standard_Real theValue)
+ {
+ myAngDeflection = theValue;
+ }
+
+ //! Returns same param flag.
+ //! By default equals to flag stored in topological shape.
+ inline Standard_Boolean GetSameParam () const
+ {
+ return mySameParam;
+ }
+
+ //! Updates same param flag.
+ inline void SetSameParam (const Standard_Boolean theValue)
+ {
+ mySameParam = theValue;
+ }
+
+ //! Returns same range flag.
+ //! By default equals to flag stored in topological shape.
+ inline Standard_Boolean GetSameRange () const
+ {
+ return mySameRange;
+ }
+
+ //! Updates same range flag.
+ inline void SetSameRange (const Standard_Boolean theValue)
+ {
+ mySameRange = theValue;
+ }
+
+ //! Returns degenerative flag.
+ //! By default equals to flag stored in topological shape.
+ inline Standard_Boolean GetDegenerated () const
+ {
+ return myDegenerated;
+ }
+
+ //! Updates degenerative flag.
+ inline void SetDegenerated (const Standard_Boolean theValue)
+ {
+ myDegenerated = theValue;
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshData_Edge, IMeshData_TessellatedShape)
+
+protected:
+
+ //! Constructor.
+ //! Initializes empty model.
+ Standard_EXPORT IMeshData_Edge (const TopoDS_Edge& theEdge)
+ : IMeshData_TessellatedShape(theEdge),
+ mySameParam (BRep_Tool::SameParameter(theEdge)),
+ mySameRange (BRep_Tool::SameRange (theEdge)),
+ myDegenerated(BRep_Tool::Degenerated (theEdge)),
+ myAngDeflection(RealLast())
+ {
+ }
+
+private:
+
+ Standard_Boolean mySameParam;
+ Standard_Boolean mySameRange;
+ Standard_Boolean myDegenerated;
+ Standard_Real myAngDeflection;
+ IMeshData::ICurveHandle myCurve;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_Face_HeaderFile
+#define _IMeshData_Face_HeaderFile
+
+#include <IMeshData_TessellatedShape.hxx>
+#include <IMeshData_StatusOwner.hxx>
+#include <Standard_Type.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS.hxx>
+#include <IMeshData_Status.hxx>
+#include <IMeshData_Types.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+
+class IMeshData_Wire;
+class TopoDS_Wire;
+
+//! Interface class representing discrete model of a face.
+//! Face model contains one or several wires.
+//! First wire is always outer one.
+class IMeshData_Face : public IMeshData_TessellatedShape, public IMeshData_StatusOwner
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_Face()
+ {
+ }
+
+ //! Returns number of wires.
+ Standard_EXPORT virtual Standard_Integer WiresNb () const = 0;
+
+ //! Adds wire to discrete model of face.
+ Standard_EXPORT virtual const IMeshData::IWireHandle& AddWire (
+ const TopoDS_Wire& theWire,
+ const Standard_Integer theEdgeNb = 0) = 0;
+
+ //! Returns discrete edge with the given index.
+ Standard_EXPORT virtual const IMeshData::IWireHandle& GetWire (
+ const Standard_Integer theIndex) const = 0;
+
+ //! Returns face's surface.
+ inline const Handle(BRepAdaptor_HSurface)& GetSurface() const
+ {
+ return mySurface;
+ }
+
+ //! Returns TopoDS_Face attached to model.
+ inline const TopoDS_Face& GetFace () const
+ {
+ return TopoDS::Face (GetShape ());
+ }
+
+ //! Returns whether the face discrete model is valid.
+ inline Standard_Boolean IsValid () const
+ {
+ return (IsEqual(IMeshData_NoError) ||
+ IsEqual(IMeshData_ReMesh) ||
+ IsEqual(IMeshData_UnorientedWire));
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshData_Face, IMeshData_TessellatedShape)
+
+protected:
+
+ //! Constructor.
+ //! Initializes empty model.
+ Standard_EXPORT IMeshData_Face (const TopoDS_Face& theFace)
+ : IMeshData_TessellatedShape(theFace)
+ {
+ BRepAdaptor_Surface aSurfAdaptor(GetFace(), Standard_False);
+ mySurface = new BRepAdaptor_HSurface(aSurfAdaptor);
+ }
+
+private:
+
+ mutable Handle(BRepAdaptor_HSurface) mySurface;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_Model_HeaderFile
+#define _IMeshData_Model_HeaderFile
+
+#include <IMeshData_Shape.hxx>
+#include <Standard_Type.hxx>
+#include <TopoDS_Shape.hxx>
+#include <IMeshData_Types.hxx>
+
+class TopoDS_Face;
+class TopoDS_Edge;
+class IMeshData_Face;
+class IMeshData_Edge;
+
+//! Interface class representing discrete model of a shape.
+class IMeshData_Model : public IMeshData_Shape
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_Model()
+ {
+ }
+
+ //! Returns maximum size of shape model.
+ Standard_EXPORT virtual Standard_Real GetMaxSize () const = 0;
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshData_Model, IMeshData_Shape)
+
+public: //! @name discrete faces
+
+ //! Returns number of faces in discrete model.
+ Standard_EXPORT virtual Standard_Integer FacesNb () const = 0;
+
+ //! Adds new face to shape model.
+ Standard_EXPORT virtual const IMeshData::IFaceHandle& AddFace (const TopoDS_Face& theFace) = 0;
+
+ //! Gets model's face with the given index.
+ Standard_EXPORT virtual const IMeshData::IFaceHandle& GetFace (const Standard_Integer theIndex) const = 0;
+
+public: //! @name discrete edges
+
+ //! Returns number of edges in discrete model.
+ Standard_EXPORT virtual Standard_Integer EdgesNb () const = 0;
+
+ //! Adds new edge to shape model.
+ Standard_EXPORT virtual const IMeshData::IEdgeHandle& AddEdge (const TopoDS_Edge& theEdge) = 0;
+
+ //! Gets model's edge with the given index.
+ Standard_EXPORT virtual const IMeshData::IEdgeHandle& GetEdge (const Standard_Integer theIndex) const = 0;
+
+protected:
+
+ //! Constructor.
+ //! Initializes empty model.
+ Standard_EXPORT IMeshData_Model (const TopoDS_Shape& theShape)
+ : IMeshData_Shape(theShape)
+ {
+ }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_PCurve_HeaderFile
+#define _IMeshData_PCurve_HeaderFile
+
+#include <IMeshData_ParametersList.hxx>
+#include <Standard_Type.hxx>
+#include <IMeshData_Face.hxx>
+
+class gp_Pnt2d;
+
+//! Interface class representing pcurve of edge associated with discrete face.
+//! Indexation of points starts from zero.
+class IMeshData_PCurve : public IMeshData_ParametersList
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_PCurve()
+ {
+ }
+
+ //! Inserts new discretization point at the given position.
+ Standard_EXPORT virtual void InsertPoint(
+ const Standard_Integer thePosition,
+ const gp_Pnt2d& thePoint,
+ const Standard_Real theParamOnPCurve) = 0;
+
+ //! Adds new discretization point to pcurve.
+ Standard_EXPORT virtual void AddPoint (
+ const gp_Pnt2d& thePoint,
+ const Standard_Real theParamOnPCurve) = 0;
+
+ //! Returns discretization point with the given index.
+ Standard_EXPORT virtual gp_Pnt2d& GetPoint (const Standard_Integer theIndex) = 0;
+
+ //! Returns index in mesh corresponded to discretization point with the given index.
+ Standard_EXPORT virtual Standard_Integer& GetIndex(const Standard_Integer theIndex) = 0;
+
+ //! Removes point with the given index.
+ Standard_EXPORT virtual void RemovePoint (const Standard_Integer theIndex) = 0;
+
+ //! Returns forward flag of this pcurve.
+ inline Standard_Boolean IsForward () const
+ {
+ return (myOrientation != TopAbs_REVERSED);
+ }
+
+ //! Returns internal flag of this pcurve.
+ inline Standard_Boolean IsInternal() const
+ {
+ return (myOrientation == TopAbs_INTERNAL);
+ }
+
+ //! Returns orientation of the edge associated with current pcurve.
+ inline TopAbs_Orientation GetOrientation() const
+ {
+ return myOrientation;
+ }
+
+ //! Returns discrete face pcurve is associated to.
+ inline const IMeshData::IFacePtr& GetFace () const
+ {
+ return myDFace;
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshData_PCurve, IMeshData_ParametersList)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshData_PCurve (
+ const IMeshData::IFacePtr& theDFace,
+ const TopAbs_Orientation theOrientation)
+ : myDFace(theDFace),
+ myOrientation(theOrientation)
+ {
+ }
+
+private:
+
+ IMeshData::IFacePtr myDFace;
+ TopAbs_Orientation myOrientation;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_ParametersList_HeaderFile
+#define _IMeshData_ParametersList_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+
+//! Interface class representing list of parameters on curve.
+class IMeshData_ParametersList : public Standard_Transient
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_ParametersList()
+ {
+ }
+
+ //! Returns parameter with the given index.
+ Standard_EXPORT virtual Standard_Real& GetParameter (const Standard_Integer theIndex) = 0;
+
+ //! Returns number of parameters.
+ Standard_EXPORT virtual Standard_Integer ParametersNb() const = 0;
+
+ //! Clears parameters list.
+ Standard_EXPORT virtual void Clear(const Standard_Boolean isKeepEndPoints) = 0;
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshData_ParametersList, Standard_Transient)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshData_ParametersList()
+ {
+ }
+
+ //! Removes parameter with the given index.
+ Standard_EXPORT virtual void removeParameter (const Standard_Integer theIndex) = 0;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_ParametersListArrayAdaptor_HeaderFile
+#define _IMeshData_ParametersListArrayAdaptor_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+#include <IMeshData_ParametersList.hxx>
+
+//! Auxiliary tool representing adaptor interface for child classes of
+//! IMeshData_ParametersList to be used in tools working on NCollection_Array structure.
+template<class ParametersListPtrType>
+class IMeshData_ParametersListArrayAdaptor : public Standard_Transient
+{
+public:
+
+ //! Constructor. Initializes tool by the given parameters.
+ Standard_EXPORT IMeshData_ParametersListArrayAdaptor(
+ const ParametersListPtrType& theParameters)
+ : myParameters (theParameters)
+ {
+ }
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_ParametersListArrayAdaptor()
+ {
+ }
+
+ //! Returns lower index in parameters array.
+ Standard_EXPORT Standard_Integer Lower() const
+ {
+ return 0;
+ }
+
+ //! Returns upper index in parameters array.
+ Standard_EXPORT Standard_Integer Upper() const
+ {
+ return myParameters->ParametersNb() - 1;
+ }
+
+ //! Returns value of the given index.
+ Standard_EXPORT Standard_Real Value(const Standard_Integer theIndex) const
+ {
+ return myParameters->GetParameter(theIndex);
+ }
+
+private:
+
+ IMeshData_ParametersListArrayAdaptor (
+ const IMeshData_ParametersListArrayAdaptor<ParametersListPtrType>& theOther);
+
+ void operator=(const IMeshData_ParametersListArrayAdaptor<ParametersListPtrType>& theOther);
+
+ const ParametersListPtrType myParameters;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_Shape_HeaderFile
+#define _IMeshData_Shape_HeaderFile
+
+#include <Standard_Type.hxx>
+#include <TopoDS_Shape.hxx>
+
+//! Interface class representing model with associated TopoDS_Shape.
+//! Intended for inheritance by structures and algorithms keeping
+//! reference TopoDS_Shape.
+class IMeshData_Shape : public Standard_Transient
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_Shape()
+ {
+ }
+
+ //! Assigns shape to discrete shape.
+ inline void SetShape (const TopoDS_Shape& theShape)
+ {
+ myShape = theShape;
+ }
+
+ //! Returns shape assigned to discrete shape.
+ const TopoDS_Shape& GetShape () const
+ {
+ return myShape;
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshData_Shape, Standard_Transient)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshData_Shape()
+ {
+ }
+
+ //! Constructor.
+ Standard_EXPORT IMeshData_Shape (const TopoDS_Shape& theShape)
+ : myShape(theShape)
+ {
+ }
+
+private:
+
+ TopoDS_Shape myShape;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2011-05-17
+// Created by: Oleg AGASHIN
+// Copyright (c) 2011-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_Status_HeaderFile
+#define _IMeshData_Status_HeaderFile
+
+//! Enumerates statuses used to notify state of discrete model.
+enum IMeshData_Status
+{
+ IMeshData_NoError = 0x0, //!< Mesh generation is successful.
+ IMeshData_OpenWire = 0x1, //!< Notifies open wire problem, which can potentially lead to incorrect results.
+ IMeshData_SelfIntersectingWire = 0x2, //!< Notifies self-intersections on discretized wire, which can potentially lead to incorrect results.
+ IMeshData_Failure = 0x4, //!< Failed to generate mesh for some faces.
+ IMeshData_ReMesh = 0x8, //!< Deflection of some edges has been decreased due to interference of discrete model.
+ IMeshData_UnorientedWire = 0x10, //!< Notifies bad orientation of a wire, which can potentially lead to incorrect results.
+ IMeshData_TooFewPoints = 0x20, //!< Discrete model contains too few boundary points to generate mesh.
+ IMeshData_Outdated = 0x40, //!< Existing triangulation of some faces corresponds to greater deflection than specified by parameter.
+ IMeshData_Reused = 0x80 //!< Existing triangulation of some faces is reused as far as it fits specified deflection.
+};
+
+#endif
--- /dev/null
+// Created on: 2016-06-23
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_StatusOwner_HeaderFile
+#define _IMeshData_StatusOwner_HeaderFile
+
+#include <IMeshData_Status.hxx>
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+
+//! Extension interface class providing status functionality.
+class IMeshData_StatusOwner
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_StatusOwner()
+ {
+ }
+
+ //! Returns true in case if status is strictly equal to the given value.
+ inline Standard_Boolean IsEqual(const IMeshData_Status theValue) const
+ {
+ return (myStatus == theValue);
+ }
+
+ //! Returns true in case if status is set.
+ inline Standard_Boolean IsSet(const IMeshData_Status theValue) const
+ {
+ return (myStatus & theValue) != 0;
+ }
+
+ //! Adds status to status flags of a face.
+ inline void SetStatus(const IMeshData_Status theValue)
+ {
+ myStatus |= theValue;
+ }
+
+ //! Adds status to status flags of a face.
+ inline void UnsetStatus(const IMeshData_Status theValue)
+ {
+ myStatus &= ~theValue;
+ }
+
+ //! Returns complete status mask.
+ inline Standard_Integer GetStatusMask() const
+ {
+ return myStatus;
+ }
+
+protected:
+
+ //! Constructor. Initializes default status.
+ Standard_EXPORT IMeshData_StatusOwner()
+ : myStatus(IMeshData_NoError)
+ {
+ }
+
+private:
+
+ Standard_Integer myStatus;
+};
+
+#endif
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_TessellatedShape_HeaderFile
+#define _IMeshData_TessellatedShape_HeaderFile
+
+#include <IMeshData_Shape.hxx>
+#include <Standard_Type.hxx>
+#include <TopoDS_Shape.hxx>
+
+//! Interface class representing shaped model with deflection.
+class IMeshData_TessellatedShape : public IMeshData_Shape
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_TessellatedShape()
+ {
+ }
+
+ //! Gets deflection value for the discrete model.
+ inline Standard_Real GetDeflection () const
+ {
+ return myDeflection;
+ }
+
+ //! Sets deflection value for the discrete model.
+ inline void SetDeflection (const Standard_Real theValue)
+ {
+ myDeflection = theValue;
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshData_TessellatedShape, IMeshData_Shape)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshData_TessellatedShape ()
+ : myDeflection(RealLast())
+ {
+ }
+
+ //! Constructor.
+ Standard_EXPORT IMeshData_TessellatedShape (const TopoDS_Shape& theShape)
+ : IMeshData_Shape(theShape),
+ myDeflection(RealLast())
+ {
+ }
+
+private:
+
+ Standard_Real myDeflection;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_Types_HeaderFile
+#define _IMeshData_Types_HeaderFile
+
+#include <NCollection_DataMap.hxx>
+#include <NCollection_Vector.hxx>
+#include <NCollection_Sequence.hxx>
+#include <NCollection_List.hxx>
+#include <NCollection_Shared.hxx>
+#include <TopTools_ShapeMapHasher.hxx>
+#include <TopoDS_Shape.hxx>
+#include <NCollection_DefineAlloc.hxx>
+#include <NCollection_StdAllocator.hxx>
+#include <IMeshData_ParametersListArrayAdaptor.hxx>
+#include <TColStd_PackedMapOfInteger.hxx>
+#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
+#include <Precision.hxx>
+#include <NCollection_EBTree.hxx>
+#include <Bnd_Box2d.hxx>
+#include <NCollection_CellFilter.hxx>
+#include <NCollection_IndexedDataMap.hxx>
+#include <NCollection_UBTreeFiller.hxx>
+#include <NCollection_IndexedMap.hxx>
+#include <BRepMesh_OrientedEdge.hxx>
+#include <BRepMesh_Vertex.hxx>
+#include <Bnd_B2d.hxx>
+#include <BRepMesh_Circle.hxx>
+#include <BRepMesh_Triangle.hxx>
+#include <BRepMesh_PairOfIndex.hxx>
+#include <BRepMesh_Edge.hxx>
+
+#include <memory>
+#include <queue>
+#include <list>
+
+class IMeshData_Shape;
+class IMeshData_Face;
+class IMeshData_Wire;
+class IMeshData_Edge;
+class IMeshData_Curve;
+class IMeshData_PCurve;
+class IMeshData_Model;
+class BRepMesh_VertexInspector;
+class BRepMesh_CircleInspector;
+
+#define DEFINE_INC_ALLOC \
+ DEFINE_NCOLLECTION_ALLOC \
+ void operator delete (void* /*theAddress*/) \
+ { \
+ /*it's inc allocator, nothing to do*/ \
+ }
+
+namespace IMeshData
+{
+ //! Default size for memory block allocated by IncAllocator.
+ /**
+ * The idea here is that blocks of the given size are returned to the system
+ * rather than retained in the malloc heap, at least on WIN32 and WIN64 platforms.
+ */
+#ifdef _WIN64
+ const size_t MEMORY_BLOCK_SIZE_HUGE = 1024 * 1024;
+#else
+ const size_t MEMORY_BLOCK_SIZE_HUGE = 512 * 1024;
+#endif
+
+ typedef IMeshData_Edge* IEdgePtr;
+ typedef IMeshData_Face* IFacePtr;
+
+ typedef Handle(IMeshData_Edge) IEdgeHandle;
+ typedef Handle(IMeshData_Wire) IWireHandle;
+ typedef Handle(IMeshData_Face) IFaceHandle;
+ typedef Handle(IMeshData_Curve) ICurveHandle;
+ typedef Handle(IMeshData_PCurve) IPCurveHandle;
+
+ typedef IMeshData_ParametersListArrayAdaptor<ICurveHandle> ICurveArrayAdaptor;
+ typedef Handle(ICurveArrayAdaptor) ICurveArrayAdaptorHandle;
+
+ typedef NCollection_Shared<NCollection_EBTree<Standard_Integer, Bnd_Box2d> > BndBox2dTree;
+ typedef NCollection_UBTreeFiller<Standard_Integer, Bnd_Box2d> BndBox2dTreeFiller;
+
+ // Vectors
+ typedef NCollection_Shared<NCollection_Vector<IFaceHandle> > VectorOfIFaceHandles;
+ typedef NCollection_Shared<NCollection_Vector<IWireHandle> > VectorOfIWireHandles;
+ typedef NCollection_Shared<NCollection_Vector<IEdgeHandle> > VectorOfIEdgeHandles;
+ typedef NCollection_Shared<NCollection_Vector<IPCurveHandle> > VectorOfIPCurveHandles;
+ typedef NCollection_Shared<NCollection_Vector<IEdgePtr> > VectorOfIEdgePtrs;
+ typedef NCollection_Shared<NCollection_Vector<Standard_Boolean> > VectorOfBoolean;
+ typedef NCollection_Shared<NCollection_Vector<Standard_Integer> > VectorOfInteger;
+ typedef NCollection_Shared<NCollection_Vector<TopAbs_Orientation> > VectorOfOrientation;
+ typedef NCollection_Shared<NCollection_Vector<BRepMesh_Triangle> > VectorOfElements;
+ typedef NCollection_Shared<NCollection_Vector<BRepMesh_Circle> > VectorOfCircle;
+
+ typedef NCollection_Shared<NCollection_Array1<BRepMesh_Vertex> > Array1OfVertexOfDelaun;
+ typedef NCollection_Shared<NCollection_Vector<BRepMesh_Vertex> > VectorOfVertex;
+
+ // Sequences
+ typedef NCollection_Shared<NCollection_Sequence<Bnd_B2d> > SequenceOfBndB2d;
+ typedef NCollection_Shared<NCollection_Sequence<Standard_Integer> > SequenceOfInteger;
+ typedef NCollection_Shared<NCollection_Sequence<Standard_Real> > SequenceOfReal;
+
+ namespace Model
+ {
+ typedef std::deque<gp_Pnt, NCollection_StdAllocator<gp_Pnt> > SequenceOfPnt;
+ typedef std::deque<gp_Pnt2d, NCollection_StdAllocator<gp_Pnt2d> > SequenceOfPnt2d;
+ typedef std::deque<Standard_Real, NCollection_StdAllocator<Standard_Real> > SequenceOfReal;
+ typedef std::deque<Standard_Integer, NCollection_StdAllocator<Standard_Integer> > SequenceOfInteger;
+ }
+
+ // Lists
+ typedef NCollection_Shared<NCollection_List<Standard_Integer> > ListOfInteger;
+ typedef NCollection_Shared<NCollection_List<gp_Pnt2d> > ListOfPnt2d;
+ typedef NCollection_Shared<NCollection_List<IPCurveHandle> > ListOfIPCurves;
+
+ typedef NCollection_Shared<TColStd_PackedMapOfInteger> MapOfInteger;
+ typedef TColStd_MapIteratorOfPackedMapOfInteger IteratorOfMapOfInteger;
+
+ typedef NCollection_CellFilter<BRepMesh_CircleInspector> CircleCellFilter;
+ typedef NCollection_CellFilter<BRepMesh_VertexInspector> VertexCellFilter;
+
+ // Data Maps
+ template<typename Type>
+ struct WeakEqual
+ {
+ static Standard_Boolean IsEqual(const Type* theFirst,
+ const Type* theSecond)
+ {
+ return (theFirst == theSecond);
+ }
+
+ static Standard_Integer HashCode(const Type* thePtr, Standard_Integer theUpper)
+ {
+ return ::HashCode(thePtr, theUpper);
+ }
+ };
+
+ typedef NCollection_Shared<NCollection_DataMap<TopoDS_Shape, Standard_Integer, TopTools_ShapeMapHasher> > DMapOfShapeInteger;
+ typedef NCollection_Shared<NCollection_DataMap<IFacePtr, ListOfInteger, WeakEqual<IMeshData_Face> > > DMapOfIFacePtrsListOfInteger;
+ typedef NCollection_Shared<NCollection_Map<IEdgePtr, WeakEqual<IMeshData_Edge> > > MapOfIEdgePtr;
+ typedef NCollection_Shared<NCollection_Map<IFacePtr, WeakEqual<IMeshData_Face> > > MapOfIFacePtr;
+ typedef NCollection_Shared<NCollection_Map<BRepMesh_OrientedEdge> > MapOfOrientedEdges;
+ typedef NCollection_Shared<NCollection_Map<Standard_Real> > MapOfReal;
+ typedef NCollection_Shared<NCollection_IndexedDataMap<IFacePtr, ListOfIPCurves, WeakEqual<IMeshData_Face> > > IDMapOfIFacePtrsListOfIPCurves;
+ typedef NCollection_Shared<NCollection_DataMap<IFacePtr, Handle(MapOfIEdgePtr), WeakEqual<IMeshData_Face> > > DMapOfIFacePtrsMapOfIEdgePtrs;
+ typedef NCollection_Shared<NCollection_IndexedDataMap<BRepMesh_Edge, BRepMesh_PairOfIndex> > IDMapOfLink;
+ typedef NCollection_Shared<NCollection_DataMap<Standard_Integer, ListOfInteger> > DMapOfIntegerListOfInteger;
+ typedef NCollection_Shared<NCollection_DataMap<Standard_Integer, Standard_Integer> > MapOfIntegerInteger;
+ typedef NCollection_Shared<NCollection_IndexedMap<Standard_Real> > IMapOfReal;
+
+ typedef NCollection_Shared<NCollection_Array1<Standard_Integer> > Array1OfInteger;
+}
+
+#endif
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshData_Wire_HeaderFile
+#define _IMeshData_Wire_HeaderFile
+
+#include <IMeshData_TessellatedShape.hxx>
+#include <IMeshData_StatusOwner.hxx>
+#include <Standard_Type.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopoDS.hxx>
+#include <IMeshData_Types.hxx>
+
+class IMeshData_Edge;
+
+//! Interface class representing discrete model of a wire.
+//! Wire should represent an ordered set of edges.
+class IMeshData_Wire : public IMeshData_TessellatedShape, public IMeshData_StatusOwner
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshData_Wire()
+ {
+ }
+
+ //! Returns TopoDS_Face attached to model.
+ inline const TopoDS_Wire& GetWire () const
+ {
+ return TopoDS::Wire (GetShape ());
+ }
+
+ //! Returns number of edges.
+ Standard_EXPORT virtual Standard_Integer EdgesNb () const = 0;
+
+ //! Adds new discrete edge with specified orientation to wire chain.
+ //! @return index of added edge in wire chain.
+ Standard_EXPORT virtual Standard_Integer AddEdge (
+ const IMeshData::IEdgePtr& theDEdge,
+ const TopAbs_Orientation theOrientation) = 0;
+
+ //! Returns discrete edge with the given index.
+ Standard_EXPORT virtual const IMeshData::IEdgePtr& GetEdge (
+ const Standard_Integer theIndex) const = 0;
+
+ //! Returns True if orientation of discrete edge with the given index is forward.
+ Standard_EXPORT virtual TopAbs_Orientation GetEdgeOrientation (
+ const Standard_Integer theIndex) const = 0;
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshData_Wire, IMeshData_TessellatedShape)
+
+protected:
+
+ //! Constructor.
+ //! Initializes empty model.
+ Standard_EXPORT IMeshData_Wire(const TopoDS_Wire& theWire)
+ : IMeshData_TessellatedShape(theWire)
+ {
+ }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+IMeshTools_Context.hxx
+IMeshTools_CurveTessellator.hxx
+IMeshTools_MeshAlgo.hxx
+IMeshTools_MeshAlgoFactory.hxx
+IMeshTools_MeshBuilder.hxx
+IMeshTools_MeshBuilder.cxx
+IMeshTools_ModelAlgo.hxx
+IMeshTools_ModelBuilder.hxx
+IMeshTools_Parameters.hxx
+IMeshTools_ShapeExplorer.hxx
+IMeshTools_ShapeExplorer.cxx
+IMeshTools_ShapeVisitor.hxx
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshTools_Context_HeaderFile
+#define _IMeshTools_Context_HeaderFile
+
+#include <IMeshData_Shape.hxx>
+#include <Standard_Type.hxx>
+#include <IMeshTools_ModelBuilder.hxx>
+#include <IMeshData_Model.hxx>
+#include <IMeshTools_Parameters.hxx>
+#include <IMeshTools_ModelAlgo.hxx>
+
+//! Interface class representing context of BRepMesh algorithm.
+//! Intended to cache discrete model and instances of tools for
+//! its processing.
+class IMeshTools_Context : public IMeshData_Shape
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT IMeshTools_Context()
+ {
+ }
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshTools_Context()
+ {
+ }
+
+ //! Builds model using assined model builder.
+ //! @return True on success, False elsewhere.
+ Standard_EXPORT virtual Standard_Boolean BuildModel ()
+ {
+ if (myModelBuilder.IsNull())
+ {
+ return Standard_False;
+ }
+
+ myModel = myModelBuilder->Perform(GetShape(), myParameters);
+
+ return !myModel.IsNull();
+ }
+
+ //! Performs discretization of model edges using assigned edge discret algorithm.
+ //! @return True on success, False elsewhere.
+ Standard_EXPORT virtual Standard_Boolean DiscretizeEdges()
+ {
+ if (myModel.IsNull() || myEdgeDiscret.IsNull())
+ {
+ return Standard_False;
+ }
+
+ // Discretize edges of a model.
+ return myEdgeDiscret->Perform(myModel, myParameters);
+ }
+
+ //! Performs healing of discrete model built by DiscretizeEdges() method
+ //! using assigned healing algorithm.
+ //! @return True on success, False elsewhere.
+ Standard_EXPORT virtual Standard_Boolean HealModel()
+ {
+ if (myModel.IsNull())
+ {
+ return Standard_False;
+ }
+
+ return myModelHealer.IsNull() ?
+ Standard_True :
+ myModelHealer->Perform(myModel, myParameters);
+ }
+
+ //! Performs pre-processing of discrete model using assigned algorithm.
+ //! Performs auxiliary actions such as cleaning shape from old triangulation.
+ //! @return True on success, False elsewhere.
+ Standard_EXPORT virtual Standard_Boolean PreProcessModel()
+ {
+ if (myModel.IsNull())
+ {
+ return Standard_False;
+ }
+
+ return myPreProcessor.IsNull() ?
+ Standard_True :
+ myPreProcessor->Perform(myModel, myParameters);
+ }
+
+ //! Performs meshing of faces of discrete model using assigned meshing algorithm.
+ //! @return True on success, False elsewhere.
+ Standard_EXPORT virtual Standard_Boolean DiscretizeFaces()
+ {
+ if (myModel.IsNull() || myFaceDiscret.IsNull())
+ {
+ return Standard_False;
+ }
+
+ // Discretize faces of a model.
+ return myFaceDiscret->Perform(myModel, myParameters);
+ }
+
+ //! Performs post-processing of discrete model using assigned algorithm.
+ //! @return True on success, False elsewhere.
+ Standard_EXPORT virtual Standard_Boolean PostProcessModel()
+ {
+ if (myModel.IsNull())
+ {
+ return Standard_False;
+ }
+
+ return myPostProcessor.IsNull() ?
+ Standard_True :
+ myPostProcessor->Perform(myModel, myParameters);
+ }
+
+ //! Cleans temporary context data.
+ Standard_EXPORT virtual void Clean()
+ {
+ if (myParameters.CleanModel)
+ {
+ myModel.Nullify();
+ }
+ }
+
+ //! Gets instance of a tool to be used to build discrete model.
+ inline const Handle (IMeshTools_ModelBuilder)& GetModelBuilder () const
+ {
+ return myModelBuilder;
+ }
+
+ //! Sets instance of a tool to be used to build discrete model.
+ inline void SetModelBuilder (const Handle (IMeshTools_ModelBuilder)& theBuilder)
+ {
+ myModelBuilder = theBuilder;
+ }
+
+ //! Gets instance of a tool to be used to discretize edges of a model.
+ inline const Handle (IMeshTools_ModelAlgo)& GetEdgeDiscret () const
+ {
+ return myEdgeDiscret;
+ }
+
+ //! Sets instance of a tool to be used to discretize edges of a model.
+ inline void SetEdgeDiscret (const Handle (IMeshTools_ModelAlgo)& theEdgeDiscret)
+ {
+ myEdgeDiscret = theEdgeDiscret;
+ }
+
+ //! Gets instance of a tool to be used to heal discrete model.
+ inline const Handle(IMeshTools_ModelAlgo)& GetModelHealer() const
+ {
+ return myModelHealer;
+ }
+
+ //! Sets instance of a tool to be used to heal discrete model.
+ inline void SetModelHealer(const Handle(IMeshTools_ModelAlgo)& theModelHealer)
+ {
+ myModelHealer = theModelHealer;
+ }
+
+ //! Gets instance of pre-processing algorithm.
+ inline const Handle(IMeshTools_ModelAlgo)& GetPreProcessor() const
+ {
+ return myPreProcessor;
+ }
+
+ //! Sets instance of pre-processing algorithm.
+ inline void SetPreProcessor(const Handle(IMeshTools_ModelAlgo)& thePreProcessor)
+ {
+ myPreProcessor = thePreProcessor;
+ }
+
+ //! Gets instance of meshing algorithm.
+ inline const Handle(IMeshTools_ModelAlgo)& GetFaceDiscret() const
+ {
+ return myFaceDiscret;
+ }
+
+ //! Sets instance of meshing algorithm.
+ inline void SetFaceDiscret(const Handle(IMeshTools_ModelAlgo)& theFaceDiscret)
+ {
+ myFaceDiscret = theFaceDiscret;
+ }
+
+ //! Gets instance of post-processing algorithm.
+ inline const Handle(IMeshTools_ModelAlgo)& GetPostProcessor() const
+ {
+ return myPostProcessor;
+ }
+
+ //! Sets instance of post-processing algorithm.
+ inline void SetPostProcessor(const Handle(IMeshTools_ModelAlgo)& thePostProcessor)
+ {
+ myPostProcessor = thePostProcessor;
+ }
+
+ //! Gets parameters to be used for meshing.
+ inline const IMeshTools_Parameters& GetParameters () const
+ {
+ return myParameters;
+ }
+
+ //! Gets reference to parameters to be used for meshing.
+ inline IMeshTools_Parameters& ChangeParameters ()
+ {
+ return myParameters;
+ }
+
+ //! Returns discrete model of a shape.
+ inline const Handle (IMeshData_Model)& GetModel () const
+ {
+ return myModel;
+ }
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshTools_Context, IMeshData_Shape)
+
+private:
+
+ Handle (IMeshTools_ModelBuilder) myModelBuilder;
+ Handle (IMeshData_Model) myModel;
+ Handle (IMeshTools_ModelAlgo) myEdgeDiscret;
+ Handle (IMeshTools_ModelAlgo) myModelHealer;
+ Handle (IMeshTools_ModelAlgo) myPreProcessor;
+ Handle (IMeshTools_ModelAlgo) myFaceDiscret;
+ Handle (IMeshTools_ModelAlgo) myPostProcessor;
+ IMeshTools_Parameters myParameters;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshTools_EdgeTessellator_HeaderFile
+#define _IMeshTools_EdgeTessellator_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+
+class gp_Pnt;
+
+//! Interface class providing API for edge tessellation tools.
+class IMeshTools_CurveTessellator : public Standard_Transient
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshTools_CurveTessellator()
+ {
+ }
+
+ //! Returns number of tessellation points.
+ Standard_EXPORT virtual Standard_Integer PointsNb () const = 0;
+
+ //! Returns parameters of solution with the given index.
+ //! @param theIndex index of tessellation point.
+ //! @param thePoint tessellation point.
+ //! @param theParameter parameters on PCurve corresponded to the solution.
+ //! @return True in case of valid result, false elewhere.
+ Standard_EXPORT virtual Standard_Boolean Value (
+ const Standard_Integer theIndex,
+ gp_Pnt& thePoint,
+ Standard_Real& theParameter) const = 0;
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshTools_CurveTessellator, Standard_Transient)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshTools_CurveTessellator()
+ {
+ }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshTools_MeshAlgo_HeaderFile
+#define _IMeshTools_MeshAlgo_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+#include <IMeshData_Types.hxx>
+
+struct IMeshTools_Parameters;
+
+//! Interface class providing API for algorithms intended to create mesh for discrete face.
+class IMeshTools_MeshAlgo : public Standard_Transient
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshTools_MeshAlgo()
+ {
+ }
+
+ //! Performs processing of the given face.
+ Standard_EXPORT virtual void Perform(
+ const IMeshData::IFaceHandle& theDFace,
+ const IMeshTools_Parameters& theParameters) = 0;
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshTools_MeshAlgo, Standard_Transient)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshTools_MeshAlgo()
+ {
+ }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-07-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshTools_MeshAlgoFactory_HeaderFile
+#define _IMeshTools_MeshAlgoFactory_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+#include <GeomAbs_SurfaceType.hxx>
+#include <IMeshTools_MeshAlgo.hxx>
+
+struct IMeshTools_Parameters;
+
+//! Base interface for factories producing instances of triangulation
+//! algorithms taking into account type of surface of target face.
+class IMeshTools_MeshAlgoFactory : public Standard_Transient
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshTools_MeshAlgoFactory()
+ {
+ }
+
+ //! Creates instance of meshing algorithm for the given type of surface.
+ Standard_EXPORT virtual Handle(IMeshTools_MeshAlgo) GetAlgo(
+ const GeomAbs_SurfaceType theSurfaceType,
+ const IMeshTools_Parameters& theParameters) const = 0;
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshTools_MeshAlgoFactory, Standard_Transient)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshTools_MeshAlgoFactory()
+ {
+ }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <IMeshTools_MeshBuilder.hxx>
+#include <IMeshData_Face.hxx>
+#include <OSD_Parallel.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+IMeshTools_MeshBuilder::IMeshTools_MeshBuilder ()
+{
+}
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+IMeshTools_MeshBuilder::IMeshTools_MeshBuilder (
+ const Handle (IMeshTools_Context)& theContext)
+ : myContext(theContext)
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+IMeshTools_MeshBuilder::~IMeshTools_MeshBuilder ()
+{
+}
+
+//=======================================================================
+// Function: Perform
+// Purpose :
+//=======================================================================
+void IMeshTools_MeshBuilder::Perform ()
+{
+ ClearStatus ();
+
+ const Handle (IMeshTools_Context)& aContext = GetContext ();
+ if (aContext.IsNull ())
+ {
+ SetStatus (Message_Fail1);
+ return;
+ }
+
+ if (aContext->BuildModel ())
+ {
+ if (aContext->DiscretizeEdges ())
+ {
+ if (aContext->HealModel ())
+ {
+ if (aContext->PreProcessModel())
+ {
+ if (aContext->DiscretizeFaces())
+ {
+ if (aContext->PostProcessModel())
+ {
+ SetStatus(Message_Done1);
+ }
+ else
+ {
+ SetStatus(Message_Fail7);
+ }
+ }
+ else
+ {
+ SetStatus(Message_Fail6);
+ }
+ }
+ else
+ {
+ SetStatus(Message_Fail5);
+ }
+ }
+ else
+ {
+ SetStatus(Message_Fail4);
+ }
+ }
+ else
+ {
+ SetStatus (Message_Fail3);
+ }
+ }
+ else
+ {
+ const Handle (IMeshTools_ModelBuilder)& aModelBuilder =
+ aContext->GetModelBuilder ();
+
+ if (aModelBuilder.IsNull ())
+ {
+ SetStatus (Message_Fail1);
+ }
+ else
+ {
+ // Is null shape or another problem?
+ SetStatus (aModelBuilder->GetStatus ().IsSet (Message_Fail1) ?
+ Message_Warn1 : Message_Fail2);
+ }
+ }
+
+ aContext->Clean ();
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshTools_MeshBuilder_HeaderFile
+#define _IMeshTools_MeshBuilder_HeaderFile
+
+#include <Message_Algorithm.hxx>
+#include <IMeshTools_Context.hxx>
+#include <Standard_Type.hxx>
+
+//! Builds mesh for each face of shape without triangulation.
+//! In case if some faces of shape have already been triangulated
+//! checks deflection of existing polygonal model and re-uses it
+//! if deflection satisfies the specified parameter. Otherwise
+//! nullifies existing triangulation and build triangulation anew.
+//!
+//! The following statuses are used:
+//! Message_Done1 - algorithm has finished without errors.
+//! Message_Fail1 - invalid context.
+//! Message_Fail2 - algorithm has faced unexpected error.
+//! Message_Fail3 - fail to discretize edges.
+//! Message_Fail4 - can't heal discrete model.
+//! Message_Fail5 - fail to pre-process model.
+//! Message_Fail6 - fail to discretize faces.
+//! Message_Fail7 - fail to post-process model.
+//! Message_Warn1 - shape contains no objects to mesh.
+class IMeshTools_MeshBuilder : public Message_Algorithm
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT IMeshTools_MeshBuilder();
+
+ //! Constructor.
+ Standard_EXPORT IMeshTools_MeshBuilder (const Handle (IMeshTools_Context)& theContext);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshTools_MeshBuilder();
+
+ //! Sets context for algorithm.
+ inline void SetContext (const Handle (IMeshTools_Context)& theContext)
+ {
+ myContext = theContext;
+ }
+
+ //! Gets context of algorithm.
+ inline const Handle (IMeshTools_Context)& GetContext () const
+ {
+ return myContext;
+ }
+
+ //! Performs meshing ot the shape using current context.
+ Standard_EXPORT virtual void Perform ();
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshTools_MeshBuilder, Message_Algorithm)
+
+private:
+
+ Handle (IMeshTools_Context) myContext;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-19
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshTools_ModelAlgo_HeaderFile
+#define _IMeshTools_ModelAlgo_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+
+class IMeshData_Model;
+struct IMeshTools_Parameters;
+
+//! Interface class providing API for algorithms intended to update or modify discrete model.
+class IMeshTools_ModelAlgo : public Standard_Transient
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshTools_ModelAlgo()
+ {
+ }
+
+ //! Performs processing of edges of the given model.
+ Standard_EXPORT virtual Standard_Boolean Perform (
+ const Handle (IMeshData_Model)& theModel,
+ const IMeshTools_Parameters& theParameters) = 0;
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshTools_ModelAlgo, Standard_Transient)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshTools_ModelAlgo()
+ {
+ }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshTools_ModelBuilder_HeaderFile
+#define _IMeshTools_ModelBuilder_HeaderFile
+
+#include <Message_Algorithm.hxx>
+#include <Standard_Type.hxx>
+#include <TopoDS_Shape.hxx>
+
+class IMeshData_Model;
+struct IMeshTools_Parameters;
+
+//! Interface class represents API for tool building discrete model.
+//!
+//! The following statuses should be used by default:
+//! Message_Done1 - model has been sucessfully built.
+//! Message_Fail1 - empty shape.
+//! Message_Fail2 - model has not been build due to unexpected reason.
+class IMeshTools_ModelBuilder : public Message_Algorithm
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshTools_ModelBuilder()
+ {
+ }
+
+ //! Creates discrete model for the given shape.
+ //! Returns nullptr in case of failure.
+ Standard_EXPORT virtual Handle (IMeshData_Model) Perform (
+ const TopoDS_Shape& theShape,
+ const IMeshTools_Parameters& theParameters) = 0;
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshTools_ModelBuilder, Message_Algorithm)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshTools_ModelBuilder()
+ {
+ }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshTools_Parameters_HeaderFile
+#define _IMeshTools_Parameters_HeaderFile
+
+#include <Precision.hxx>
+
+//! Structure storing meshing parameters
+struct IMeshTools_Parameters {
+
+ //! Default constructor
+ IMeshTools_Parameters ()
+ :
+ Angle(0.5),
+ Deflection(0.001),
+ MinSize (-1.0),
+ InParallel (Standard_False),
+ Relative (Standard_False),
+ InternalVerticesMode (Standard_True),
+ ControlSurfaceDeflection (Standard_True),
+ CleanModel(Standard_True)
+ {
+ }
+
+ //! Returns factor used to compute default value of MinSize
+ //! (minimum mesh edge length) from deflection
+ static Standard_Real RelMinSize()
+ {
+ return 0.1;
+ }
+
+ //! Angular deflection
+ Standard_Real Angle;
+
+ //! Deflection
+ Standard_Real Deflection;
+
+ //! Minimal allowed size of mesh element
+ Standard_Real MinSize;
+
+ //! Switches on/off multi-thread computation
+ Standard_Boolean InParallel;
+
+ //! Switches on/off relative computation of edge tolerance<br>
+ //! If true, deflection used for the polygonalisation of each edge will be
+ //! <defle> * Size of Edge. The deflection used for the faces will be the
+ //! maximum deflection of their edges.
+ Standard_Boolean Relative;
+
+ //! Mode to take or not to take internal face vertices into account
+ //! in triangulation process
+ Standard_Boolean InternalVerticesMode;
+
+ //! Parameter to check the deviation of triangulation and interior of
+ //! the face
+ Standard_Boolean ControlSurfaceDeflection;
+
+ //! Cleans temporary data model when algorithm is finished.
+ Standard_Boolean CleanModel;
+};
+
+#endif
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <IMeshTools_ShapeExplorer.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <BRepLib.hxx>
+#include <BRep_Tool.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <Geom_Surface.hxx>
+
+//=======================================================================
+// Function: Constructor
+// Purpose :
+//=======================================================================
+IMeshTools_ShapeExplorer::IMeshTools_ShapeExplorer (
+ const TopoDS_Shape& theShape)
+ : IMeshData_Shape (theShape)
+{
+}
+
+//=======================================================================
+// Function: Destructor
+// Purpose :
+//=======================================================================
+IMeshTools_ShapeExplorer::~IMeshTools_ShapeExplorer ()
+{
+}
+
+//=======================================================================
+// Function: Accept
+// Purpose :
+//=======================================================================
+void IMeshTools_ShapeExplorer::Accept (
+ const Handle (IMeshTools_ShapeVisitor)& theVisitor)
+{
+ // Explore all edges in shape - either free or related to some face.
+ TopTools_IndexedMapOfShape aEdges;
+ TopExp::MapShapes (GetShape (), TopAbs_EDGE, aEdges);
+
+ TopTools_IndexedMapOfShape::Iterator aEdgeIt (aEdges);
+ for (; aEdgeIt.More (); aEdgeIt.Next ())
+ {
+ const TopoDS_Edge& aEdge = TopoDS::Edge (aEdgeIt.Value ());
+ if (!BRep_Tool::IsGeometric(aEdge))
+ {
+ continue;
+ }
+
+ theVisitor->Visit (aEdge);
+ }
+
+ // Explore faces
+ TopTools_ListOfShape aFaceList;
+ BRepLib::ReverseSortFaces (GetShape (), aFaceList);
+ TopTools_MapOfShape aFaceMap;
+
+ // make array of faces suitable for processing (excluding faces without surface)
+ TopLoc_Location aDummyLoc;
+ const TopLoc_Location aEmptyLoc;
+ TopTools_ListIteratorOfListOfShape aFaceIter (aFaceList);
+ for (; aFaceIter.More (); aFaceIter.Next ())
+ {
+ TopoDS_Shape aFaceNoLoc = aFaceIter.Value ();
+ aFaceNoLoc.Location (aEmptyLoc);
+ if (!aFaceMap.Add(aFaceNoLoc))
+ {
+ continue; // already processed
+ }
+
+ TopoDS_Face aFace = TopoDS::Face (aFaceIter.Value ());
+ const Handle (Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aDummyLoc);
+ if (aSurf.IsNull())
+ {
+ continue;
+ }
+
+ // Store only forward faces in order to prevent inverse issue.
+ theVisitor->Visit (TopoDS::Face (aFace.Oriented (TopAbs_FORWARD)));
+ }
+}
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshTools_ShapeExplorer_HeaderFile
+#define _IMeshTools_ShapeExplorer_HeaderFile
+
+#include <IMeshData_Shape.hxx>
+#include <Standard_Type.hxx>
+#include <IMeshTools_ShapeVisitor.hxx>
+#include <TopoDS_Shape.hxx>
+
+//! Explores TopoDS_Shape for parts to be meshed - faces and free edges.
+class IMeshTools_ShapeExplorer : public IMeshData_Shape
+{
+public:
+
+ //! Constructor.
+ Standard_EXPORT IMeshTools_ShapeExplorer (const TopoDS_Shape& theShape);
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshTools_ShapeExplorer();
+
+ //! Starts exploring of a shape.
+ Standard_EXPORT virtual void Accept (const Handle (IMeshTools_ShapeVisitor)& theVisitor);
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshTools_ShapeExplorer, IMeshData_Shape)
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+// Created on: 2016-04-07
+// Copyright (c) 2016 OPEN CASCADE SAS
+// Created by: Oleg AGASHIN
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _IMeshTools_ShapeVisitor_HeaderFile
+#define _IMeshTools_ShapeVisitor_HeaderFile
+
+#include <Standard_Transient.hxx>
+#include <Standard_Type.hxx>
+
+class TopoDS_Face;
+class TopoDS_Edge;
+
+//! Interface class for shape visitor.
+class IMeshTools_ShapeVisitor : public Standard_Transient
+{
+public:
+
+ //! Destructor.
+ Standard_EXPORT virtual ~IMeshTools_ShapeVisitor()
+ {
+ }
+
+ //! Handles TopoDS_Face object.
+ Standard_EXPORT virtual void Visit (const TopoDS_Face& theFace) = 0;
+
+ //! Handles TopoDS_Edge object.
+ Standard_EXPORT virtual void Visit (const TopoDS_Edge& theEdge) = 0;
+
+ DEFINE_STANDARD_RTTI_INLINE(IMeshTools_ShapeVisitor, Standard_Transient)
+
+protected:
+
+ //! Constructor.
+ Standard_EXPORT IMeshTools_ShapeVisitor()
+ {
+ }
+};
+
+#endif
\ No newline at end of file
#include <Adaptor3d_IsoCurve.hxx>
#include <Bnd_Box.hxx>
#include <BRep_Tool.hxx>
-#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepBndLib.hxx>
#include <BRepMesh_DiscretFactory.hxx>
#include <BRepMesh_DiscretRoot.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_Delaun.hxx>
#include <BRepMesh_Edge.hxx>
-#include <BRepMesh_FastDiscret.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
+#include <IMeshTools_Parameters.hxx>
#include <BRepMesh_Triangle.hxx>
#include <BRepMesh_Vertex.hxx>
#include <BRepTest.hxx>
#include <TopoDS_Wire.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_MapIteratorOfMapOfShape.hxx>
+#include <IMeshData_Status.hxx>
#include <stdio.h>
//epa Memory leaks test
return 0;
}
- Standard_Real aLinDeflection = Max(Draw::Atof(argv[2]), Precision::Confusion());
- Standard_Real aAngDeflection = 0.5;
- Standard_Real aMinSize = Precision::Confusion();
- Standard_Boolean isRelative = Standard_False;
- Standard_Boolean isInParallel = Standard_False;
- Standard_Boolean isIntVertices = Standard_True;
- Standard_Boolean isControlSurDef = Standard_True;
- Standard_Boolean isAdaptiveMin = Standard_False;
+ IMeshTools_Parameters aMeshParams;
if (nbarg > 3)
{
if (aOpt == "")
continue;
else if (aOpt == "-relative")
- isRelative = Standard_True;
+ aMeshParams.Relative = Standard_True;
else if (aOpt == "-parallel")
- isInParallel = Standard_True;
+ aMeshParams.InParallel = Standard_True;
else if (aOpt == "-int_vert_off")
- isIntVertices = Standard_False;
+ aMeshParams.InternalVerticesMode = Standard_False;
else if (aOpt == "-surf_def_off")
- isControlSurDef = Standard_False;
- else if (aOpt == "-adaptive")
- isAdaptiveMin = Standard_True;
+ aMeshParams.ControlSurfaceDeflection = Standard_False;
else if (i < nbarg)
{
Standard_Real aVal = Draw::Atof(argv[i++]);
if (aOpt == "-a")
- aAngDeflection = aVal * M_PI / 180.;
+ {
+ aMeshParams.Angle = aVal * M_PI / 180.;
+ }
else if (aOpt == "-min")
- aMinSize = aVal;
+ aMeshParams.MinSize = aVal;
else
--i;
}
}
di << "Incremental Mesh, multi-threading "
- << (isInParallel ? "ON" : "OFF") << "\n";
-
- BRepMesh_FastDiscret::Parameters aMeshParams;
- aMeshParams.Deflection = aLinDeflection;
- aMeshParams.Angle = aAngDeflection;
- aMeshParams.Relative = isRelative;
- aMeshParams.InParallel = isInParallel;
- aMeshParams.MinSize = aMinSize;
- aMeshParams.InternalVerticesMode = isIntVertices;
- aMeshParams.ControlSurfaceDeflection = isControlSurDef;
- aMeshParams.AdaptiveMin = isAdaptiveMin;
-
+ << (aMeshParams.InParallel ? "ON" : "OFF") << "\n";
+
BRepMesh_IncrementalMesh aMesher (aShape, aMeshParams);
di << "Meshing statuses: ";
- Standard_Integer statusFlags = aMesher.GetStatusFlags();
- if( !statusFlags )
+ const Standard_Integer aStatus = aMesher.GetStatusFlags();
+ if (!aStatus)
{
di << "NoError";
}
else
{
Standard_Integer i;
- for( i = 0; i < 4; i++ )
+ for (i = 0; i < 8; i++)
{
- if( (statusFlags >> i) & (Standard_Integer)1 )
+ Standard_Integer aFlag = aStatus & (1 << i);
+ if (aFlag)
{
- switch(i+1)
+ switch ((IMeshData_Status) aFlag)
{
- case 1:
- di << "OpenWire ";
- break;
- case 2:
- di << "SelfIntersectingWire ";
- break;
- case 3:
- di << "Failure ";
- break;
- case 4:
- di << "ReMesh ";
- break;
+ case IMeshData_OpenWire:
+ di << "OpenWire ";
+ break;
+ case IMeshData_SelfIntersectingWire:
+ di << "SelfIntersectingWire ";
+ break;
+ case IMeshData_Failure:
+ di << "Failure ";
+ break;
+ case IMeshData_ReMesh:
+ di << "ReMesh ";
+ break;
+ case IMeshData_UnorientedWire:
+ di << "UnorientedWire ";
+ break;
+ case IMeshData_TooFewPoints:
+ di << "TooFewPoints ";
+ break;
+ case IMeshData_Outdated:
+ di << "Outdated ";
+ break;
+ case IMeshData_Reused:
+ di << "Reused ";
+ break;
+ case IMeshData_NoError:
+ default:
+ break;
}
}
}
return 0;
}
-//=======================================================================
-//function : fastdiscret
-//purpose :
-//=======================================================================
-
-static Standard_Integer fastdiscret(Draw_Interpretor& di, Standard_Integer nbarg, const char** argv)
-{
- if (nbarg < 3) return 1;
-
- TopoDS_Shape S = DBRep::Get(argv[1]);
- if (S.IsNull()) return 1;
-
- const Standard_Real d = Draw::Atof(argv[2]);
-
- Bnd_Box B;
- BRepBndLib::Add(S,B);
- BRepMesh_FastDiscret::Parameters aParams;
- aParams.Deflection = d;
- aParams.Angle = 0.5;
- BRepMesh_FastDiscret MESH(B,aParams);
-
- //Standard_Integer NbIterations = MESH.NbIterations();
- //if (nbarg > 4) NbIterations = Draw::Atoi(argv[4]);
- //MESH.NbIterations() = NbIterations;
-
- di<<"Starting FastDiscret with :\n";
- di<<" Deflection="<<d<<"\n";
- di<<" Angle="<<0.5<<"\n";
-
- Handle(Poly_Triangulation) T;
- BRep_Builder aBuilder;
- TopExp_Explorer ex;
-
- // Clear existing triangulations
- for (ex.Init(S, TopAbs_FACE); ex.More(); ex.Next())
- aBuilder.UpdateFace(TopoDS::Face(ex.Current()),T);
-
- MESH.Perform(S);
-
- TopoDS_Compound aCompGood, aCompFailed, aCompViolating;
-
- TopLoc_Location L;
- Standard_Integer nbtriangles = 0, nbnodes = 0, nbfailed = 0, nbviolating = 0;
- Standard_Real maxdef = 0.0;
- for (ex.Init(S, TopAbs_FACE); ex.More(); ex.Next())
- {
- T = BRep_Tool::Triangulation(TopoDS::Face(ex.Current()),L);
- if (T.IsNull())
- {
- nbfailed++;
- if (aCompFailed.IsNull())
- aBuilder.MakeCompound(aCompFailed);
- aBuilder.Add(aCompFailed,ex.Current());
- }
- else
- {
- nbtriangles += T->NbTriangles();
- nbnodes += T->NbNodes();
- if (T->Deflection() > maxdef) maxdef = T->Deflection();
- if (T->Deflection() > d)
- {
- nbviolating++;
- if (aCompViolating.IsNull())
- aBuilder.MakeCompound(aCompViolating);
- aBuilder.Add(aCompViolating,ex.Current());
- }
- else
- {
- if (aCompGood.IsNull())
- aBuilder.MakeCompound(aCompGood);
- aBuilder.Add(aCompGood,ex.Current());
- }
- }
- }
-
- if (!aCompGood.IsNull())
- {
- char name[256];
- strcpy(name,argv[1]);
- strcat(name,"_good");
- DBRep::Set(name,aCompGood);
- }
- if (!aCompFailed.IsNull())
- {
- char name[256];
- strcpy(name,argv[1]);
- strcat(name,"_failed");
- DBRep::Set(name,aCompFailed);
- }
- if (!aCompViolating.IsNull())
- {
- char name[256];
- strcpy(name,argv[1]);
- strcat(name,"_violating");
- DBRep::Set(name,aCompViolating);
- }
-
- di<<"FastDiscret completed with :\n";
- di<<" MaxDeflection="<<maxdef<<"\n";
- di<<" NbNodes="<<nbnodes<<"\n";
- di<<" NbTriangles="<<nbtriangles<<"\n";
- di<<" NbFailed="<<nbfailed<<"\n";
- di<<" NbViolating="<<nbviolating<<"\n";
-
- return 0;
-}
-
-
//=======================================================================
//function : triangule
//purpose :
theCommands.Add("incmesh","Builds triangular mesh for the shape, run w/o args for help",__FILE__, incrementalmesh, g);
theCommands.Add("tessellate","Builds triangular mesh for the surface, run w/o args for help",__FILE__, tessellate, g);
theCommands.Add("MemLeakTest","MemLeakTest",__FILE__, MemLeakTest, g);
- theCommands.Add("fastdiscret","fastdiscret shape deflection",__FILE__, fastdiscret, g);
theCommands.Add("mesh","mesh result Shape deflection",__FILE__, triangule, g);
theCommands.Add("addshape","addshape meshname Shape [deflection]",__FILE__, addshape, g);
//theCommands.Add("smooth","smooth meshname",__FILE__, smooth, g);
#include <Poly_Triangulation.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <Poly_Connect.hxx>
+#include <Precision.hxx>
+
+//=======================================================================
+//function : ComputeArea
+//purpose : Computes area of the triangle given by its three points (either 2D or3D)
+//=======================================================================
+static Standard_Real ComputeArea(const gp_XYZ& theP1,
+ const gp_XYZ& theP2,
+ const gp_XYZ& theP3)
+{
+ return 0.5*(theP3 - theP1).Crossed(theP2 - theP1).Modulus();
+}
+
+//=======================================================================
+//function : ComputeArea
+//purpose : Computes area of the triangle given by its three points (either 2D or3D)
+//=======================================================================
+static Standard_Real ComputeArea(const gp_XY& theP1,
+ const gp_XY& theP2,
+ const gp_XY& theP3)
+{
+ return 0.5*Abs((theP3 - theP1).Crossed(theP2 - theP1));
+}
//=======================================================================
//function : Perform
}
// check distances between corresponding points
- Standard_Real aDefle = Max(aT1->Deflection(), aT2->Deflection());
+ Standard_Real aSqDefle = Max(aT1->Deflection(), aT2->Deflection());
+ aSqDefle *= aSqDefle;
const TColgp_Array1OfPnt& aPoints1 = aT1->Nodes();
const TColgp_Array1OfPnt& aPoints2 = aT2->Nodes();
Standard_Integer iF1 = aMapF.FindIndex(aFace1);
Standard_Integer iF2 = aMapF.FindIndex(aFace2);
Standard_Integer i1 = aNodes1.Lower();
Standard_Integer i2 = aNodes2.Lower();
- gp_Trsf aTrsf1 = aFace1.Location().Transformation();
- gp_Trsf aTrsf2 = aFace2.Location().Transformation();
+ const gp_Trsf &aTrsf1 = aFace1.Location().Transformation();
+ const gp_Trsf &aTrsf2 = aFace2.Location().Transformation();
for (; i1 <= aNodes1.Upper(); i1++, i2++) {
- gp_Pnt aP1 = aPoints1(aNodes1(i1)).Transformed(aTrsf1);
- gp_Pnt aP2 = aPoints2(aNodes2(i2)).Transformed(aTrsf2);
- Standard_Real aDist = aP1.Distance(aP2);
- if (aDist > aDefle) {
+ const gp_Pnt aP1 = aPoints1(aNodes1(i1)).Transformed(aTrsf1);
+ const gp_Pnt aP2 = aPoints2(aNodes2(i2)).Transformed(aTrsf2);
+ const Standard_Real aSqDist = aP1.SquareDistance(aP2);
+ if (aSqDist > aSqDefle)
+ {
myErrors.Append(iF1);
myErrors.Append(i1);
myErrors.Append(iF2);
myErrors.Append(i2);
- myErrorsVal.Append(aDist);
+ myErrorsVal.Append(Sqrt(aSqDist));
}
}
}
continue;
}
+ const gp_Trsf &aTrsf = aLoc.Transformation();
+
// remember boundary nodes
TColStd_PackedMapOfInteger aMapBndNodes;
TopExp_Explorer ex(aFace, TopAbs_EDGE);
aUsedNodes.Add (n[1]);
aUsedNodes.Add (n[2]);
+ const gp_Pnt aPts[3] = {aT->Node(n[0]).Transformed(aTrsf),
+ aT->Node(n[1]).Transformed(aTrsf),
+ aT->Node(n[2]).Transformed(aTrsf)};
+
+ Standard_Real anArea = ComputeArea(aPts[0].XYZ(), aPts[1].XYZ(), aPts[2].XYZ());
+ if (anArea < Precision::SquareConfusion())
+ {
+ mySmallTrianglesFaces.Append(iF);
+ mySmallTrianglesTriangles.Append(i);
+ }
+ else if (aT->HasUVNodes())
+ {
+ const gp_XY aPUV[3] = {aT->UVNode(n[0]).XY(),
+ aT->UVNode(n[1]).XY(),
+ aT->UVNode(n[2]).XY()};
+ anArea = ComputeArea(aPUV[0], aPUV[1], aPUV[2]);
+ if (anArea < Precision::SquarePConfusion())
+ {
+ mySmallTrianglesFaces.Append(iF);
+ mySmallTrianglesTriangles.Append(i);
+ }
+ }
+
aConn.Triangles(i, t[0], t[1], t[2]);
for (j = 0; j < 3; j++) {
if (t[j] == 0) {
theNodeNum = myFreeNodeNums(theIndex);
}
+ //! Returns number of triangles with null area
+ Standard_Integer NbSmallTriangles() const
+ {
+ return mySmallTrianglesFaces.Length();
+ }
+
+ //! returns the number of face containing the Index-th detected
+ //! small triangle and number of the problematic triangle in
+ //! this face.
+ void GetSmallTriangle(const Standard_Integer theIndex,
+ Standard_Integer& theFaceNum,
+ Standard_Integer& theNodeNum) const
+ {
+ theFaceNum = mySmallTrianglesFaces(theIndex);
+ theNodeNum = mySmallTrianglesTriangles(theIndex);
+ }
+
private:
TopoDS_Shape myShape;
NCollection_IndexedDataMap<Standard_Integer,Handle(TColStd_HSequenceOfInteger)>
TColStd_SequenceOfInteger myAsyncEdges;
TColStd_SequenceOfInteger myFreeNodeFaces;
TColStd_SequenceOfInteger myFreeNodeNums;
+ TColStd_SequenceOfInteger mySmallTrianglesFaces;
+ TColStd_SequenceOfInteger mySmallTrianglesTriangles;
+
};
#endif
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-#include <BRepMesh_FaceAttribute.hxx>
#include <Draw_Segment3D.hxx>
#include <DrawTrSurf_Polygon3D.hxx>
#include <Draw.hxx>
#include <TCollection_AsciiString.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <Poly_Polygon3D.hxx>
+#include <BRepMesh_Edge.hxx>
+#include <BRepMesh_Vertex.hxx>
+#include <BRepMesh_Triangle.hxx>
+#include <BRepMesh_DataStructureOfDelaun.hxx>
// This file defines global functions not declared in any public header,
// intended for use from debugger prompt (Command Window in Visual Studio)
//function : MeshTest_DrawLinks
//purpose : Draw links from mesh data structure of type BRepMesh_FaceAttribute
//=======================================================================
-Standard_EXPORT const char* MeshTest_DrawLinks(const char* theNameStr, void* theFaceAttr)
+Standard_EXPORT const char* MeshTest_DrawLinks(const char* theNameStr, void* theDataStruct)
{
- if (theNameStr == 0 || theFaceAttr == 0)
+ if (theNameStr == 0 || theDataStruct == 0)
{
return "Error: name or face attribute is null";
}
try {
- const Handle(BRepMesh_FaceAttribute)& aFaceAttr = *(Handle(BRepMesh_FaceAttribute)*)theFaceAttr;
- const Handle(BRepMesh_DataStructureOfDelaun)& aMeshData = aFaceAttr->ChangeStructure();
+ const Handle(BRepMesh_DataStructureOfDelaun)& aMeshData = *(Handle(BRepMesh_DataStructureOfDelaun)*)theDataStruct;
if (aMeshData.IsNull())
return "Null mesh data structure";
Standard_Integer nbLinks = aMeshData->NbLinks();
Standard_Integer n2 = aLink.LastNode();
const BRepMesh_Vertex& aV1 = aMeshData->GetNode(n1);
const BRepMesh_Vertex& aV2 = aMeshData->GetNode(n2);
- const gp_Pnt& aP1 = aFaceAttr->GetPoint(aV1);
- const gp_Pnt& aP2 = aFaceAttr->GetPoint(aV2);
- Handle(Draw_Segment3D) aSeg = new Draw_Segment3D(aP1, aP2, Draw_bleu);
+ Handle(Draw_Segment3D) aSeg = new Draw_Segment3D(gp_Pnt(aV1.Coord().X(), aV1.Coord().Y(), 0),
+ gp_Pnt(aV2.Coord().X(), aV2.Coord().Y(), 0),
+ Draw_bleu);
Draw::Set((aName + "_" + i).ToCString(), aSeg);
}
return theNameStr;
//function : MeshTest_DrawTriangles
//purpose : Draw triangles from mesh data structure of type BRepMesh_FaceAttribute
//=======================================================================
-Standard_EXPORT const char* MeshTest_DrawTriangles(const char* theNameStr, void* theFaceAttr)
+Standard_EXPORT const char* MeshTest_DrawTriangles(const char* theNameStr, void* theDataStruct)
{
- if (theNameStr == 0 || theFaceAttr == 0)
+ if (theNameStr == 0 || theDataStruct == 0)
{
return "Error: name or face attribute is null";
}
try {
- const Handle(BRepMesh_FaceAttribute)& aFaceAttr =
- *(Handle(BRepMesh_FaceAttribute)*)theFaceAttr;
- const Handle(BRepMesh_DataStructureOfDelaun)& aMeshData = aFaceAttr->ChangeStructure();
+ const Handle(BRepMesh_DataStructureOfDelaun)& aMeshData =
+ *(Handle(BRepMesh_DataStructureOfDelaun)*)theDataStruct;
+
if (aMeshData.IsNull())
return "Null mesh data structure";
Standard_Integer nbElem = aMeshData->NbElements();
const BRepMesh_Vertex& aV1 = aMeshData->GetNode(n[0]);
const BRepMesh_Vertex& aV2 = aMeshData->GetNode(n[1]);
const BRepMesh_Vertex& aV3 = aMeshData->GetNode(n[2]);
- gp_Pnt aP[4] = { aFaceAttr->GetPoint(aV1), aFaceAttr->GetPoint(aV2),
- aFaceAttr->GetPoint(aV3), aFaceAttr->GetPoint(aV1) };
+ gp_Pnt aP[4] = { gp_Pnt(aV1.Coord().X(), aV1.Coord().Y(), 0),
+ gp_Pnt(aV2.Coord().X(), aV2.Coord().Y(), 0),
+ gp_Pnt(aV3.Coord().X(), aV3.Coord().Y(), 0),
+ gp_Pnt(aV1.Coord().X(), aV1.Coord().Y(), 0) };
TColgp_Array1OfPnt aPnts(aP[0], 1, 4);
Handle(Poly_Polygon3D) aPoly = new Poly_Polygon3D(aPnts);
Handle(DrawTrSurf_Polygon3D) aDPoly = new DrawTrSurf_Polygon3D(aPoly);
#include <BRepMesh_Triangle.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <TopExp_Explorer.hxx>
-
+#include <BRep_Tool.hxx>
IMPLEMENT_STANDARD_RTTIEXT(MeshTest_DrawableMesh,Draw_Drawable3D)
{
myMesher = new BRepMesh_IncrementalMesh;
myMesher->ChangeParameters().Deflection = myDeflection;
- myMesher->ChangeParameters().Angle = 0.5;
+ myMesher->ChangeParameters().Angle = 0.5;
}
myMesher->SetShape(theShape);
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom2d_BSplineCurve.hxx>
static Standard_Integer mpnames (Draw_Interpretor& , Standard_Integer , const char** );
static Standard_Integer mpsetdefaultname (Draw_Interpretor& , Standard_Integer , const char** );
theCommands.Add("mpparallel" , "mpparallel [toTurnOn] : show / set multi-threading flag for incremental mesh",
__FILE__, mpparallel, g);
theCommands.Add("triarea","shape [eps] (computes triangles and surface area)",__FILE__, triarea, g);
- theCommands.Add("tricheck", "shape (checks triangulation of shape)", __FILE__, tricheck, g);
+ theCommands.Add("tricheck", "shape [-small] (checks triangulation of shape);\n"
+ "\"-small\"-option allows finding triangles with small area", __FILE__, tricheck, g);
}
//=======================================================================
TopoDS_Shape shape = DBRep::Get(a[1]);
if (shape.IsNull()) return 1;
+ const Standard_Boolean isToFindSmallTriangles = (n >= 3) ? (strcmp(a[2], "-small") == 0) : Standard_False;
+
TopTools_IndexedMapOfShape aMapF;
TopExp::MapShapes (shape, TopAbs_FACE, aMapF);
- Standard_CString name = ".";
+ const Standard_CString name = ".";
// execute check
MeshTest_CheckTopology aCheck(shape);
di << "\n";
}
+ const Standard_Integer aNbSmallTriangles = isToFindSmallTriangles? aCheck.NbSmallTriangles() : 0;
+ if (aNbSmallTriangles > 0)
+ {
+ di << "triangles with null area (in pairs: face / triangle): \n";
+ for (i = 1; i <= aNbSmallTriangles; i++)
+ {
+ Standard_Integer aFaceId = 0, aTriID = 0;
+ aCheck.GetSmallTriangle(i, aFaceId, aTriID);
+
+ const TopoDS_Face& aFace = TopoDS::Face(aMapF.FindKey(aFaceId));
+ TopLoc_Location aLoc;
+ const gp_Trsf& aTrsf = aLoc.Transformation();
+ const Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
+ const Poly_Triangle &aTri = aT->Triangle(aTriID);
+ Standard_Integer aN1, aN2, aN3;
+ aTri.Get(aN1, aN2, aN3);
+ const TColgp_Array1OfPnt& aPoints = aT->Nodes();
+
+ TColgp_Array1OfPnt aPoles(1, 4);
+ aPoles(1) = aPoles(4) = aPoints(aN1).Transformed(aTrsf);
+ aPoles(2) = aPoints(aN2).Transformed(aTrsf);
+ aPoles(3) = aPoints(aN3).Transformed(aTrsf);
+
+ TColStd_Array1OfInteger aMults(1, 4);
+ aMults(1) = aMults(4) = 2;
+ aMults(2) = aMults(3) = 1;
+
+ TColStd_Array1OfReal aKnots(1, 4);
+ aKnots(1) = 1.0;
+ aKnots(2) = 2.0;
+ aKnots(3) = 3.0;
+ aKnots(4) = 4.0;
+
+ Handle(Geom_BSplineCurve) aBS = new Geom_BSplineCurve(aPoles, aKnots, aMults, 1);
+
+ DrawTrSurf::Set(name, aBS);
+
+ if (aT->HasUVNodes())
+ {
+ TColgp_Array1OfPnt2d aPoles2d(1, 4);
+ aPoles2d(1) = aPoles2d(4) = aT->UVNodes()(aN1);
+ aPoles2d(2) = aT->UVNodes()(aN2);
+ aPoles2d(3) = aT->UVNodes()(aN3);
+
+ Handle(Geom2d_BSplineCurve) aBS2d = new Geom2d_BSplineCurve(aPoles2d, aKnots, aMults, 1);
+
+ DrawTrSurf::Set(name, aBS2d);
+ }
+
+ di << "{" << aFaceId << " " << aTriID << "} ";
+ }
+
+ di << "\n";
+ }
+
// output errors summary to DRAW
- if ( nbFree > 0 || nbErr > 0 || nbAsync > 0 || nbFreeNodes > 0)
+ if (nbFree > 0 ||
+ nbErr > 0 ||
+ nbAsync > 0 ||
+ nbFreeNodes > 0 ||
+ (aNbSmallTriangles > 0))
+ {
di << "Free_links " << nbFree
- << " Cross_face_errors " << nbErr
- << " Async_edges " << nbAsync
- << " Free_nodes " << nbFreeNodes << "\n";
-
+ << " Cross_face_errors " << nbErr
+ << " Async_edges " << nbAsync
+ << " Free_nodes " << nbFreeNodes
+ << " Small triangles " << aNbSmallTriangles << "\n";
+ }
Standard_Integer aFaceId = 1;
TopExp_Explorer aFaceExp(shape, TopAbs_FACE);
#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
+#include <IMeshTools_Parameters.hxx>
//=======================================================================
//function : OCC24
if(aShape.IsNull()) {di << "OCC369 FAULTY. Entry shape is NULL \n"; return 0;}
// 3. Build mesh
- BRepMesh_FastDiscret::Parameters aMeshParams;
- aMeshParams.Relative = Standard_True;
+ IMeshTools_Parameters aMeshParams;
+ aMeshParams.Relative = Standard_True;
aMeshParams.Deflection = 0.2;
- aMeshParams.Angle = M_PI / 6;
+ aMeshParams.Angle = M_PI / 6.0;
BRepMesh_IncrementalMesh aMesh(aShape, aMeshParams);
}
#include <gp_Pln.hxx>
#include <BRep_Tool.hxx>
#include <BRepAlgoAPI_Section.hxx>
-#include <BRepMesh_IncrementalMesh.hxx>
#include <Precision.hxx>
#include <Standard_ErrorHandler.hxx>
Handle(BRepMesh_DataStructureOfDelaun) aMeshStructure = new BRepMesh_DataStructureOfDelaun(anAllocator);
Standard_Integer aPtsLower = thePoints.Lower();
Standard_Integer aPtsUpper = thePoints.Upper();
- BRepMesh::Array1OfInteger anIndexes (0, thePoints.Length() - 1);
+ IMeshData::VectorOfInteger anIndexes(aPtsUpper - aPtsLower, anAllocator);
for (Standard_Integer aPtIdx = aPtsLower; aPtIdx <= aPtsUpper; ++aPtIdx)
{
- BRepMesh_Vertex aVertex (thePoints.Value (aPtIdx).XY(), aPtIdx, BRepMesh_Frontier);
- anIndexes.ChangeValue (aPtIdx - aPtsLower) = aMeshStructure->AddNode (aVertex);
+ BRepMesh_Vertex aVertex(thePoints.Value(aPtIdx).XY(), aPtIdx, BRepMesh_Frontier);
+ anIndexes.Append(aMeshStructure->AddNode(aVertex));
}
Standard_Real aPtSum = 0;
}
BRepMesh_Delaun aTriangulation (aMeshStructure, anIndexes);
- const BRepMesh::MapOfInteger& aTriangles = aMeshStructure->ElementsOfDomain();
+ const IMeshData::MapOfInteger& aTriangles = aMeshStructure->ElementsOfDomain();
if (aTriangles.Extent() < 1)
return;
- BRepMesh::MapOfInteger::Iterator aTriangleIt (aTriangles);
+ IMeshData::IteratorOfMapOfInteger aTriangleIt (aTriangles);
for (; aTriangleIt.More(); aTriangleIt.Next())
{
const Standard_Integer aTriangleId = aTriangleIt.Key();
{
const Standard_Boolean aRel = aDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE;
Standard_Real aDef = aRel ? aDrawer->HLRDeviationCoefficient() : aDrawer->MaximalChordialDeviation();
- BRepMesh_FastDiscret::Parameters aMeshParams;
- aMeshParams.Relative = aRel;
- aMeshParams.Angle = aDrawer->HLRAngle();
+ IMeshTools_Parameters aMeshParams;
+ aMeshParams.Relative = aRel;
+ aMeshParams.Angle = aDrawer->HLRAngle();
aMeshParams.Deflection = aDef;
BRepMesh_IncrementalMesh mesh(aShape, aMeshParams);
}
-TKBRep
-TKMath
TKernel
-TKG2d
-TKG3d
-TKGeomBase
+TKMath
+TKBRep
TKTopAlgo
-TKGeomAlgo
-CSF_TBB
+TKShHealing
+TKGeomBase
+TKG3d
+TKG2d
+IMeshData
+IMeshTools
+BRepMeshData
BRepMesh
#include <Vrml_NormalBinding.hxx>
#include <Vrml_Separator.hxx>
#include <Vrml_NormalBinding.hxx>
-#include <BRepMesh_IncrementalMesh.hxx>
//=========================================================================
// function: Add
#include <VrmlData_IndexedFaceSet.hxx>
#include <VrmlData_IndexedLineSet.hxx>
#include <VrmlData_ShapeNode.hxx>
-#include <BRepMesh_IncrementalMesh.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <Geom_Surface.hxx>
iErr=0;
BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh;
anAlgo->ChangeParameters().Deflection = theDeflection;
- anAlgo->ChangeParameters().Angle = theAngle;
+ anAlgo->ChangeParameters().Angle = theAngle;
anAlgo->SetShape(theShape);
theAlgo = anAlgo;
if { [info exists rel_tol] && $rel_tol > 0 } {
- puts "\nChecking triangulation area (triarea command)..."
- set rel_err [expr abs([CheckTriArea result $area_eps])]
- if { $rel_err > $rel_tol } {
- puts "Error : area by triangles differs from the actual area by $rel_err %"
- } else {
- if { [info exists max_rel_tol_diff] && $max_rel_tol_diff > 0} {
- checkreal "area difference" $rel_err $rel_tol $max_rel_tol_diff 0
- } else {
- if { $rel_tol > 1 && $rel_tol < 100 } {
- puts "Error: Improvement: The current area difference is $rel_err instead of $rel_tol"
- }
- }
- }
+ puts "\nChecking triangulation area (triarea command)..."
+ set rel_err [expr abs([CheckTriArea result $area_eps])]
+ if { [info exists max_rel_tol_diff] && $max_rel_tol_diff > 0 } {
+ checkreal "area difference" $rel_err $rel_tol $max_rel_tol_diff 0
+ }
}
# to end a test script
puts "TODO ?OCC7287 Linux: Tcl Exception: Memory leak detected"
puts "TODO ?OCC7287 Linux: TEST INCOMPLETE"
+puts "TODO ?OCC7287 Linux: Checking trend failed"
puts "TODO ?OCC7287 MacOS: Tcl Exception: Memory leak detected"
puts "TODO ?OCC7287 MacOS: TEST INCOMPLETE"
incmesh r 0.1
trinfo r
-checktrinfo r -defl 0.04 -tol_abs_defl 0.01 -tol_rel_defl 0.01
+checktrinfo r -defl 0.1 -tol_abs_defl 0.01 -tol_rel_defl 0.01
vinit
vsetdispmode 1
-puts "TODO OCC26716 ALL: Error: Number of triangles is equal to 0"
-
puts "============"
-puts "OCC26716"
+puts "OCC26716: Mesher cannot create a mesh of brep model due to ShapeFix_Wire::FixShifted()"
puts "============"
puts ""
-################################################################################
-## Mesher cannot create a mesh of brep model due to ShapeFix_Wire::FixShifted()
-################################################################################
restore [locate_data_file bug26716_rev.brep] result
incmesh result 0.1
triangles result
-checktrinfo result -tri -nod
+checktrinfo result -tri 646 -nod 568
checkview -display result -2d -path ${imagedir}/${test_image}.png
vsetdispmode result 1
vfit
-checktrinfo result -tri 453 -nod 447
+checktrinfo result -tri 244 -nod 237
checkview -display result -2d -path ${imagedir}/${test_image}.png
vsetdispmode result 1
vfit
-checktrinfo result -tri 5656 -nod 4088
+checktrinfo result -tri 2788 -nod 2648
checkview -display result -2d -path ${imagedir}/${test_image}.png
igesread [locate_data_file bug22487_351_linz.igs] result *
checkshape result
-
-checkview -display result -3d -path ${imagedir}/${test_image}-3d.png
checkview -display result -2d -path ${imagedir}/${test_image}-2d.png
+
+vinit
+vdefaults -autoTriang 0
+
+incmesh result 0.1 -a 20
+
+vdisplay result
+vfit
+vsetdispmode 1
+
+vviewparams -scale 10.5476 -eye 7.59599 54.7624 -4.57957 -at 58.2815 -22.8528 13.3243 -up -0.123529 -0.298943 -0.946242 -proj -0.536853 0.822087 -0.189635
+
+checkview -screenshot -3d -path ${imagedir}/${test_image}-3d.png
vdisplay result
vfit
-checktrinfo result -tri 9250 -nod 7593
+checktrinfo result -tri 6046 -nod 5924
checkmaxtol result -ref 0.92213088179312575
checknbshapes result -shell 1
incmesh s 0.001
set trinfo_s [trinfo s]
regexp {([0-9]+) triangles} $trinfo_s str nbtri_s
-regexp {deflection ([0-9.+e-]+)} $trinfo_s str defl_s
# face converted to NURBS
nurbsconvert r s
incmesh r 0.001
set trinfo_r [trinfo r]
regexp {([0-9]+) triangles} $trinfo_r str nbtri_r
-regexp {deflection ([0-9.+e-]+)} $trinfo_r str defl_r
+
# check deflections
-if { $defl_s > 0.001 } {
- puts "Error: too big deflection on original face ($defl_s > 0.001)"
-}
-if { $defl_r > 0.001 } {
- puts "Error: too big deflection on NURBS face ($defl_r > 0.001)"
-}
+checktrinfo s -tri -defl 0.001 -tol_abs_defl 1e-6
+checktrinfo r -tri -max_defl 0.001 -tol_abs_defl 1e-6
# compare number of triangles, allow twice more
-if { $nbtri_r > [expr 2. * $nbtri_s] } {
- puts "Error: too many triangles ($nbtri_r, while ~ $nbtri_s would be sufficient)"
+set exptri_s [expr 2. * $nbtri_s]
+if { $nbtri_r > $exptri_s } {
+ puts "Error: too many triangles ($nbtri_r, while ~ $exptri_s would be sufficient)"
}
# extra check: deflection on rough mesh on NURBS
checkshape result
incmesh result 0.1
-checktrinfo result -tri -max_defl 0.1
+checktrinfo result -tri -defl 0.1 -tol_abs_defl 1e-6
incmesh result 0.01
triangles result
-checktrinfo result -tri 79 -nod 81
+checktrinfo result -tri 57 -nod 59
vinit
vdisplay result
trinfo f
-checktrinfo f -tri 21 -nod 22 -defl 0.3345840532742983 -tol_abs_defl 1.e-3 -tol_rel_defl 0.01
+checktrinfo f -tri 20 -nod 21 -defl 0.3345840532742983 -tol_abs_defl 1.e-3 -tol_rel_defl 0.01
vinit
vdisplay f
-puts "TODO OCC24938 ALL: Meshing statuses: Failure ReMesh"
-puts "TODO OCC24938 ALL: Error: Number of triangles is equal to 0"
-puts "TODO OCC24938 ALL: Error: Number of nodes is equal to 0"
-#puts "TODO OCC24938 ALL: Error : area by triangles differs from the actual area by"
-
puts "=========="
-puts "OCC24938"
+puts "OCC24938: BRepMesh_IncrementalMesh hangs"
puts "=========="
puts ""
-########################################
-# BRepMesh_IncrementalMesh hangs
-########################################
-# to prevent loops limit to 5 minutes
-cpulimit 300
+cpulimit 100
restore [locate_data_file bug24938_27773.brep] result
tclean result
incmesh result 1.5 -relative
-checktrinfo result -tri -nod
+checktrinfo result -tri 8 -nod 10 -defl 3.1950444624834377e-05
vinit
vsetdispmode 1
-puts "TODO OCC25061 ALL: ERROR: OCC25061 is reproduced."
-
puts "========"
-puts "OCC25061"
+puts "OCC25061: BRepMesh should skip internal wires with self intersections to produce mesh for the shape anyway"
puts "========"
puts ""
-####################################################################################################
-# BRepMesh should skip internal wires with self intersections to produce mesh for the shape anyway
-####################################################################################################
+
+puts "TODO OCC25061 ALL: Not connected mesh inside face 1"
restore [locate_data_file bug25061_a.brep] a
-puts "TODO CR25469 ALL: Error: second time must be quicker"
-
puts "============"
-puts "CR25503"
+puts "CR25503: BRepMesh - IncrementalMesh always re-meshes the shape even if existing triangulation satisfies the given deflection"
puts "============"
puts ""
-###################################################################################
-# BRepMesh - IncrementalMesh always re-meshes the shape even if existing triangulation satisfies the given deflection
-###################################################################################
puts ""
puts "===> meshing full sphere"
isos a 0
triangles a
-checktrinfo a -tri 3347 -nod 1780 -defl 0.08541878790375132 -tol_rel_defl 0.05 -tol_rel_tri 0.05 -tol_rel_nod 0.05
+checktrinfo a -tri 2971 -nod 1592 -defl 0.083467373173701759 -tol_rel_defl 0.05 -tol_rel_tri 0.05 -tol_rel_nod 0.05
checkview -screenshot -2d -path ${imagedir}/${test_image}.png
puts "TODO CR25628 ALL: Error: BRepMesh fails to mesh face with open wire, considered as correct by checkshape"
puts "========="
-puts "CR25628"
+puts "CR25628: BRepMesh fails to mesh face with open wire, considered as correct by checkshape"
puts "========="
puts ""
-##############################################################################################
-# BRepMesh fails to mesh face with open wire, considered as correct by checkshape
-##############################################################################################
pload XDE
checkshape a_36
set Log [incmesh a_36 0.1]
-if {[regexp "OpenWire" ${Log}] == 1} {
+if {[regexp "UnorientedWire" ${Log}] == 1} {
puts "Error: BRepMesh fails to mesh face with open wire, considered as correct by checkshape"
}
explode c F
set Log [incmesh c_4 0.1]
-if {[regexp "NoError" ${Log}] == 0} {
+if {[regexp "Reused" ${Log}] == 0} {
puts "Error: crescent face is not meshed"
}
-puts "TODO CR25837 ALL: Error : Colors are not equal in default coordinate and in the near coordinates too"
-
puts "========="
-puts "CR25837"
+puts "CR25837: Bad triangulation when IGES loaded in meters"
puts "========="
puts ""
-######################################################
-# Bad triangulation when IGES loaded in meters
-######################################################
pload XDE
set y 200
checkcolor $x $y 0 0 0
+set area [triarea result 1.0e-4]
+set t_area [lindex $area 0]
+set g_area [expr abs([lindex $area 1])]
+set r_area [expr $t_area/$g_area]
+
+checkreal "Relative area" $r_area 1.0 0.01 0.0
+
checkview -screenshot -3d -path ${imagedir}/${test_image}.png
-puts "TODO OCC26291 ALL: Not connected mesh"
-
puts "========"
-puts "OCC26291"
+puts "OCC26291: BRepMesh produces mesh with gap on the attached shape"
puts "========"
puts ""
-#########################################################
-# BRepMesh produces mesh with gap on the attached shape
-#########################################################
restore [locate_data_file bug26291_mesh_gap.brep] a
incmesh a 1
incmesh result 0.1
-checktrinfo result -tri 1055 -nod 537
+checktrinfo result -tri 1041 -nod 530
vinit
vdisplay result
restore [locate_data_file bug26664_f.brep] a
-# adaptive meshing is OK
-tclean a
-incmesh a 1e-4 -adaptive
+set log2 [incmesh a 1e-4]
+vinit
+vsetdispmode 1
+vdisplay a
+vfit
+vdump ${imagedir}/${casename}_1.png
-# non-adaptive meshing fails
-puts "TODO 26664 ALL: Meshing statuses: Failure"
-tclean a
-incmesh a 1e-4
+if { [regexp "NoError" ${log2}] == 1 } {
+ puts "OK : Triangulating a very small polygon is good"
+} else {
+ puts "Error : Triangulating a very small polygon fails"
+}
restore [locate_data_file bug26692_face_bad_shading.brep] a
-vinit
-vclear
-
incmesh a 0.1 -a 2
-vdisplay a
-vfit
-vdump ${imagedir}/${casename}.png
+trinfo a
+
+isos a 0
+triangles a
+checkview -display a -2d -path ${imagedir}/${casename}.png
restore [locate_data_file bug26692_face_bad_shading.brep] a
-vinit
-vclear
-
incmesh a 100
-vdisplay a
-vfit
-vdump ${imagedir}/${casename}.png
+trinfo a
+
+isos a 0
+triangles a
+checkview -display a -2d -path ${imagedir}/${casename}.png
vdisplay result
vfit
-set rel_tol 1
+set rel_tol 0.035439456401028344
+set max_rel_tol_diff 0.001
set area_eps 1
checkview -screenshot -3d -path ${imagedir}/${test_image}.png
-puts "TODO OCC27453 ALL: Not connected mesh"
-
puts "========"
-puts "OCC27453"
+puts "OCC27453: Wrongly meshed surface"
puts "========"
puts ""
-##########################
-# Wrongly meshed surface
-##########################
pload XDE
checkshape result
incmesh result 0.01 -a 0.5
-tricheck result
+if {[ string compare "" [tricheck result] ] != 0} {
+ puts "Error: Wrongly meshed surface"
+}
-puts "TODO OCC28247 ALL: Error: Effect of minSize parameter of BRepMesh_IncrementalMesh seems to be too strong"
-
puts "========="
puts "OCC28247"
puts "========="
-puts "TODO CR28500 ALL: Artifact in shaded view of the shape"
-
puts "======="
-puts "CR28500"
+puts "CR28500: Artifact in shaded view of the shape"
puts "======="
puts ""
-######################################
-# Artifact in shaded view of the shape
-######################################
+
+puts "TODO CR28500 ALL: Artifact in shaded view of the shape"
+puts "TODO CR30056 ALL: Meshing statuses: Failure Reused"
restore [locate_data_file bug28500_shape_mesh_artifact.brep] a
--- /dev/null
+puts "======="
+puts "0026106: BRepMesh - revision of data model"
+puts "======="
+puts ""
+
+restore [locate_data_file bug26106_pipeBT.brep] result
+
+vinit
+vsetdispmode 1
+
+vdisplay result
+vfit
+
+tricheck result
+checktrinfo result -tri 4006 -nod 2092 -max_defl 0.46
+
+checkview -screenshot -3d -path ${imagedir}/${test_image}.png
isos result 0
triangles result
-checktrinfo result -tri 11 -nod 13
+checktrinfo result -tri 10 -nod 12
checkprops result -s 1.3135
checkview -display result -3d -path ${imagedir}/${test_image}.png
-puts "TODO OCC12345 ALL: Error: Number of triangles"
-puts "TODO OCC12345 ALL: Error: Number of nodes"
+###puts "TODO OCC12345 ALL: Error: Number of triangles"
+###puts "TODO OCC12345 ALL: Error: Number of nodes"
puts "TODO OCC12345 ALL: Error : The area of result shape is"
puts "========"
isos result 0
triangles result
-checktrinfo result -tri 32 -nod 28
+checktrinfo result -tri 55 -nod 40
checkprops result -s 0
checkview -display result -3d -path ${imagedir}/${test_image}.png
isos result 0
triangles result
-checktrinfo result -tri 101 -nod 103
+checktrinfo result -tri 91 -nod 93
checkprops result -s 150.283
checkview -display result -3d -path ${imagedir}/${test_image}.png
#View the result of mesh
triangles result
-checktrinfo result -tri 3758 -nod 1959
+checktrinfo result -tri 1890 -nod 1025
checkprops result -s 32.9479
checkshape result
checkview -display result -2d -path ${imagedir}/${test_image}.png
#View the result of mesh
triangles result
-checktrinfo result -tri 3991 -nod 2076
+checktrinfo result -tri 1891 -nod 1026
checkprops result -s 32.9479
checkshape result
checkview -display result -2d -path ${imagedir}/${test_image}.png
#View the result of mesh
triangles result
-checktrinfo result -tri 3972 -nod 2070
+checktrinfo result -tri 2152 -nod 1160
checkprops result -s 36.4284
checkshape result
checkview -display result -2d -path ${imagedir}/${test_image}.png
#View the result of mesh
triangles result
-checktrinfo result -tri 4039 -nod 2104
+checktrinfo result -tri 2153 -nod 1161
checkprops result -s 36.4284
checkshape result
checkview -display result -2d -path ${imagedir}/${test_image}.png
isos result 0
triangles result
-checktrinfo result -tri 1111 -nod 814
+checktrinfo result -tri 522 -nod 426
checkprops result -s 376.873
checkview -screenshot -3d -path ${imagedir}/${test_image}.png
isos result 0
triangles result
-checktrinfo result -tri 11 -nod 13
+checktrinfo result -tri 10 -nod 12
checkprops result -s 1.3135
checkview -display result -3d -path ${imagedir}/${test_image}.png
vfit
vsetdispmode result 1
-checktrinfo result -tri 8970 -nod 4919
+checktrinfo result -tri 21446 -nod 11157
checkprops result -s 24861.2
checkshape result
checkview -display result -2d -path ${imagedir}/${test_image}.png
puts " OCC397 "
puts "========================"
-puts "TODO OCC27226 ALL: Colors are not equal in default"
-puts "TODO OCC27226 ALL: Shading is missing in 3D Viewer"
-
pload QAcommands
restore [locate_data_file OCC397.brep] a
checkprops result -s 92.9029
checkshape result
checkview -screenshot -3d -path ${imagedir}/${test_image}.png
-
-
-puts "TODO OCC25915 ALL: FAILED during Triangulation"
-puts "TODO OCC25915 ALL: Triangulation FAILED for 1 of 2 Faces"
-puts "TODO OCC25915 ALL: Faulty OCC825"
+#puts "TODO OCC25915 ALL: Faulty OCC825"
puts "TODO OCC25915 ALL: Faulty shapes in variables faulty_1 to faulty_"
pload QAcommands
puts "========"
-puts "OCC29311"
+puts "OCC29311: Implementation of the Oriented Bounding Boxes (OBB) functionality"
puts "========"
puts ""
-#################################################
-# Implementation of the Oriented Bounding Boxes (OBB) functionality
-#################################################
-
set NbIters 31
set step [expr 360.0/($NbIters-1) ]
if { $i != $NbIters } { trotate a 283 162 317 2 7 9 $step }
}
-checkreal {Transformed BndBoxes} $VMax $VMin 0.0 0.3
+checkreal {Transformed BndBoxes} $VMax $VMin 0.0 0.35
puts "The box with maximal volume is achieved in $MaxIteration iteration. See \"amax\" shape."
puts "The box with minimal volume is achieved in $MinIteration iteration. See \"amin\" shape."
puts "========"
-puts "OCC29701"
+puts "OCC29701: BRepTools::Update(Face) unexpectedly updates UV points of pcurve"
puts "========"
puts ""
-#################################################
-# BRepTools::Update(Face) unexpectedly updates UV points of pcurve
-#################################################
brestore [locate_data_file bug29701_brepmesh_triangle_bad_collapsed.brep] s
# mesh the face
-repeat 2 {
- if {![regexp "NoError" [incmesh s 0.1]]} {
- puts "Error: Unable to build triangulation"
- }
+if {![regexp "NoError" [incmesh s 0.1]]} {
+ puts "Error: Unable to build triangulation"
+}
+
+if {![regexp "Reused" [incmesh s 0.1]]} {
+ puts "Error: Unable to build triangulation"
}
tcopy s copy
# mesh the copy face
-repeat 2 {
- if {![regexp "NoError" [incmesh copy 0.1]]} {
- puts "Error: Unable to build triangulation on copy shape"
- }
+if {![regexp "NoError" [incmesh copy 0.1]]} {
+ puts "Error: Unable to build triangulation on copy shape"
+}
+
+if {![regexp "Reused" [incmesh copy 0.1]]} {
+ puts "Error: Unable to build triangulation on copy shape"
}
fixshape fixed s
# mesh the fixed face
repeat 2 {
- if {![regexp "NoError" [incmesh fixed 0.1]]} {
+ if {![regexp "Reused" [incmesh fixed 0.1]]} {
puts "Error: Unable to build triangulation on fixed shape"
}
}
puts "========"
-puts "OCC29701"
+puts "OCC29701: BRepTools::Update(Face) unexpectedly updates UV points of pcurve"
puts "========"
puts ""
-#################################################
-# BRepTools::Update(Face) unexpectedly updates UV points of pcurve
-#################################################
brestore [locate_data_file bug29701_hullshape.brep] s
# mesh the face
-repeat 2 {
- if {![regexp "NoError" [incmesh s 0.1]]} {
- puts "Error: Unable to build triangulation"
- }
+if {![regexp "NoError" [incmesh s 0.1]]} {
+ puts "Error: Unable to build triangulation"
+}
+
+if {![regexp "Reused" [incmesh s 0.1]]} {
+ puts "Error: Unable to build triangulation"
}
tcopy s copy
# mesh the copy face
-repeat 2 {
- if {![regexp "NoError" [incmesh copy 0.1]]} {
- puts "Error: Unable to build triangulation on copy shape"
- }
+if {![regexp "NoError" [incmesh copy 0.1]]} {
+ puts "Error: Unable to build triangulation on copy shape"
+}
+
+if {![regexp "Reused" [incmesh copy 0.1]]} {
+ puts "Error: Unable to build triangulation on copy shape"
}
fixshape fixed s
# mesh the fixed face
repeat 2 {
- if {![regexp "NoError" [incmesh fixed 0.1]]} {
+ if {![regexp "Reused" [incmesh fixed 0.1]]} {
puts "Error: Unable to build triangulation on fixed shape"
}
}
puts "========"
-puts "OCC29701"
+puts "OCC29701: BRepTools::Update(Face) unexpectedly updates UV points of pcurve"
puts "========"
puts ""
-#################################################
-# BRepTools::Update(Face) unexpectedly updates UV points of pcurve
-#################################################
brestore [locate_data_file bug29701_Plate_B.brep] s
# mesh the face
-repeat 2 {
- if {![regexp "NoError" [incmesh s 0.1]]} {
- puts "Error: Unable to build triangulation"
- }
+if {![regexp "NoError" [incmesh s 0.1]]} {
+ puts "Error: Unable to build triangulation"
+}
+
+if {![regexp "Reused" [incmesh s 0.1]]} {
+ puts "Error: Unable to build triangulation"
}
tcopy s copy
# mesh the copy face
-repeat 2 {
- if {![regexp "NoError" [incmesh copy 0.1]]} {
- puts "Error: Unable to build triangulation on copy shape"
- }
+if {![regexp "NoError" [incmesh copy 0.1]]} {
+ puts "Error: Unable to build triangulation on copy shape"
+}
+
+if {![regexp "Reused" [incmesh copy 0.1]]} {
+ puts "Error: Unable to build triangulation on copy shape"
}
fixshape fixed s
# mesh the fixed face
repeat 2 {
- if {![regexp "NoError" [incmesh fixed 0.1]]} {
+ if {![regexp "Reused" [incmesh fixed 0.1]]} {
puts "Error: Unable to build triangulation on fixed shape"
}
}
puts ""
puts "TODO OCC29922 ALL: Error: Degenerated edge is not found"
-puts "TODO OCC29922 ALL: Error: Result contains not triangulated face"
restore [locate_data_file bug29807-obj.brep] b1
restore [locate_data_file bug29807-tool.brep] b2
vsetdispmode result 1
vfit
-checktrinfo result -tri 1009 -nod 593
+checktrinfo result -tri 1075 -nod 635
checkview -display result -2d -path ${imagedir}/${test_image}.png
-puts "TODO OCC12345 ALL: Meshing statuses: OpenWire SelfIntersectingWire Failure ReMesh"
-puts "TODO OCC12345 ALL: Error: Number of triangles"
-puts "TODO OCC12345 ALL: Error: Number of nodes"
-puts "TODO OCC12345 ALL: Error: Maximal deflection"
-
puts "============"
puts "OCC15519"
puts "============"
set Deflection 1.
catch {incmesh result ${Deflection} }
-if { [checkplatform -windows] } {
- set good_tri 96265
- set good_nod 71339
- set good_defl 27.956052399907215
-} else {
- set good_tri 95582
- set good_nod 70796
- set good_defl 0.99827404224216676
-}
-
-checktrinfo result -tri ${good_tri} -nod ${good_nod} -defl ${good_defl} -tol_rel_defl 0.001 -tol_rel_tri 0.001 -tol_rel_nod 0.001
+checktrinfo result -tri 52685 -nod 46258 -defl 1.0 -tol_rel_defl 0.001 -tol_rel_tri 0.001 -tol_rel_nod 0.001
checkview -display result -2d -path ${imagedir}/${test_image}.png
-puts "TODO OCC11111 ALL: Error: Maximal deflection"
-
puts "============"
puts "OCC21122"
puts "============"
set Deflection 0.1
catch {incmesh result ${Deflection} }
-checktrinfo result -tri 4322 -nod 4324 -defl 8.8817872205847652e-16 -tol_rel_defl 0.001 -tol_rel_tri 0.001 -tol_rel_nod 0.001
+checktrinfo result -tri 4204 -nod 4206 -defl 1.9388020580310417e-07 -tol_rel_defl 0.1 -tol_rel_tri 0.001 -tol_rel_nod 0.001
checkprops result -s 275.426
checknbshapes result -vertex 964 -edge 964 -wire 1 -face 1 -shell 1 -solid 0 -compsolid 0 -compound 0 -shape 1931
set Deflection 0.001
incmesh result ${Deflection}
-checktrinfo result -tri 394128 -nod 201035 -defl 0.0092442421472207319 -tol_rel_defl 0.001 -tol_rel_tri 0.001 -tol_rel_nod 0.001
+checktrinfo result -tri 346096 -nod 176022 -defl 0.0092442421472206764 -tol_rel_defl 0.001 -tol_rel_tri 0.001 -tol_rel_nod 0.001
vinit
vdisplay result
puts "========"
-puts "OCC428"
-puts "SAM1414"
+puts "OCC428: Excep-tion during vizualization on attached shape in application."
+puts "SAM1414: Excep-tion is raised in the package StdPrs."
puts "========"
-################################################
-## Exception during vizualization on attached shape in application.
-## Exception is raised in the package StdPrs.
-################################################
-
restore [locate_data_file OCC428.brep] result
tclean result
vinit
vdisplay result
vsetdispmode result 1
+vfit
+checkview -screenshot -3d -path ${imagedir}/${test_image}_shade.png
+
vclear
+smallview
isos result 0
triangles result
-vfit
+fit
-checktrinfo result -tri !5496 -nod !5406
-checkview -screenshot -3d -path ${imagedir}/${test_image}.png
+checktrinfo result -tri 10886 -nod 7830
+checkview -screenshot -2d -path ${imagedir}/${test_image}_axo.png
incmesh result .1
triangles result
-checktrinfo result -tri 424 -nod 266
+checktrinfo result -tri 355 -nod 210
checkview -display result -3d -path ${imagedir}/${test_image}.png
# Checking triangulation area (triarea command)...
set max_rel_tol_diff 1
-set rel_tol 0.56
+set rel_tol 2.6907275359547698
set area_eps 0
smallview
-puts "TODO CR26106 ALL: Meshing statuses: OpenWire Failure"
+puts "TODO CR30056 ALL: Meshing statuses: Failure UnorientedWire"
puts "============"
puts "BUC60858"
incmesh result .9
triangles result
-checktrinfo result -tri 91 -nod 93
+checktrinfo result -tri 82 -nod 84
checkview -display result -3d -path ${imagedir}/${test_image}.png
# Start
restore [locate_data_file OCC22313-face_shading_problem.brep] result
+incmesh result 0.1
vinit
vdisplay result
vfit
-puts "TODO OCC22849 ALL: Meshing statuses: OpenWire Failure"
+puts "TODO CR30056 ALL: Meshing statuses: Failure"
puts "============"
puts "OCC22849"
triangles result
vfit
-checktrinfo result -tri 8000 -nod 8358
+checktrinfo result -tri 8048 -nod 8247
checkview -screenshot -3d -path ${imagedir}/${test_image}.png
isos result 0
triangles result
-checktrinfo result -tri !9 -nod !8
+checktrinfo result -tri 8 -nod 8
checkview -screenshot -3d -path ${imagedir}/${test_image}.png
checkarea step_1 3.978e8 1e6 0.001
# STL
-incmesh hammer 38.9076
+incmesh hammer 30
writestl hammer $imagedir/hammer.stl
readstl stl $imagedir/hammer.stl -brep
checkshape stl
readstl res $imagedir/${casename}
file delete $imagedir/${casename}
-checktrinfo res -tri 130 -nod 67
+checktrinfo res -tri 94 -nod 49
# Visual check
checkview -display res -2d -path ${imagedir}/${test_image}.png
readstl res $imagedir/${casename}
file delete $imagedir/${casename}
-checktrinfo res -tri 150 -nod 77
+checktrinfo res -tri 58 -nod 31
# Visual check
checkview -display res -2d -path ${imagedir}/${test_image}.png
readstl res $imagedir/${casename}
file delete $imagedir/${casename}
-checktrinfo res -tri 146 -nod 75
+checktrinfo res -tri 106 -nod 55
# Visual check
checkview -display res -2d -path ${imagedir}/${test_image}.png
readstl res $imagedir/${casename}
file delete $imagedir/${casename}
-checktrinfo res -tri 40 -nod 22
+checktrinfo res -tri 28 -nod 16
# Visual check
checkview -display res -2d -path ${imagedir}/${test_image}.png
readstl res $imagedir/${casename}
file delete $imagedir/${casename}
-checktrinfo res -tri 58 -nod 31
+checktrinfo res -tri 34 -nod 19
# Visual check
checkview -display res -2d -path ${imagedir}/${test_image}.png
readstl res $imagedir/${casename}
file delete $imagedir/${casename}
-checktrinfo res -tri 56 -nod 30
+checktrinfo res -tri 48 -nod 26
# Visual check
checkview -display res -2d -path ${imagedir}/${test_image}.png
set TheFileName shading_018.brep
-set bug_withouttri "OCC22687"
-set nbwithouttri(ALL) 1
+###set bug_withouttri "OCC22687"
+###set nbwithouttri(ALL) 1
+set bug_freenodes "OCC22687"
+set nbfreenodes(All) 88
+if { [string compare $command "shading"] == 0 } {
+ set nbfreenodes(All) 34
+ set rel_tol 0.2366831658635133
+ set max_rel_tol_diff 0.001
+}
###if { [string compare $command "mesh"] != 0 } {
### set bug_freenodes "OCC22687"
### set nbfreenodes(All) 1
+if { [string compare $command "shading"] != 0 } {
+ puts "TODO OCC30056 All: Meshing statuses: SelfIntersectingWire Failure"
+}
+
set TheFileName OCC21961-shd002A8-f204.brep
set bug_area "OCC22687"
set rel_tol 100
set TheFileName OCC22095-selectNoTbb.brep
set bug_area "OCC22687"
-set rel_tol 15.4
+set rel_tol 15.361
+if { [string compare $command "shading"] == 0 } {
+ set rel_tol 14.293
+}
+set max_rel_tol_diff 0.001
set bug_freenodes "OCC22687"
set nbfreenodes(ALL) 2
set TheFileName OCC357.brep
if { [string compare $command "shading"] == 0 } {
#set bug_area "OCC22687"
- set max_rel_tol_diff 1
- set rel_tol 1.86
+ set max_rel_tol_diff 0.25
+ set rel_tol 1.0015290236679502
}
set TheFileName shading_014.brep
+set bug_freenodes "OCC22687"
+set nbfreenodes(All) 1
###if { [string compare $command "shading"] == 0 } {
### set bug_freenodes "OCC22687"
### set nbfreenodes(All) 1
set TheFileName shading_018.brep
- set bug_withouttri "OCC22687"
- set nbwithouttri(All) 1
+###set bug_withouttri "OCC22687"
+###set nbwithouttri(All) 1
+set bug_freenodes "OCC22687"
+set nbfreenodes(All) 88
+if { [string compare $command "shading"] == 0 } {
+ set nbfreenodes(All) 34
+ set rel_tol 0.2366831658635133
+ set max_rel_tol_diff 0.001
+}
###if { [string compare $command "shading"] == 0 } {
### set bug_freenodes "OCC22687"
### set nbfreenodes(All) 1
if { [string compare $command "shading"] == 0 } {
set nbfreenodes(All) 3
} else {
- set bug_freelinks "OCC23105"
+###set bug_freelinks "OCC23105"
set nbfree(ALL) 2
set nbfreenodes(All) 4
}
## set bug_freenodes "OCC23105"
## set nbfreenodes(All) 3
##}
-set bug_withouttri "OCC23106"
-set nbwithouttri(All) 1
+###set bug_withouttri "OCC23106"
+###set nbwithouttri(All) 1
+set bug_freenodes "OCC23105"
+set nbfreenodes(All) 2
set nb 36
}
-set bug_cross "OCC22687"
-set nbcross([checkplatform]) $nb
+###set bug_cross "OCC22687"
+###set nbcross([checkplatform]) $nb
set TheFileName shading_068.brep
-set bug_cross "OCC22687"
-set nbcross(ALL) 1
+###set bug_cross "OCC22687"
+###set nbcross(ALL) 1
if { [string compare $command "shading"] != 0 } {
#set bug_area "OCC22687"
set max_rel_tol_diff 1
- set rel_tol 4
+ set rel_tol 2.47934320863783
}
set TheFileName shading_101.brep
if { [string compare $command "shading"] != 0 } {
set max_rel_tol_diff 0.1
- set rel_tol 0.5
+ set rel_tol 1.2162834127672983
}
set TheFileName shading_109.brep
-if { [string compare ${command} "shading"] == 0 && [string compare ${group} "standard"] == 0} {
- set bug_cross "OCC25503"
- set nbcross(All) 2
-} else {
- set bug_cross "OCC22687"
- set nbcross(All) 4
-}
+###if { [string compare ${command} "shading"] == 0 && [string compare ${group} "standard"] == 0} {
+### set bug_cross "OCC25503"
+### set nbcross(All) 2
+###} else {
+### set bug_cross "OCC22687"
+### set nbcross(All) 4
+###}
set TheFileName shading_112.brep
set bug_area "OCC22687"
if { [string compare $command "shading"] == 0 } {
- set rel_tol 1.7
+ set rel_tol 1.9456
} else {
set rel_tol 1.54
}
+set max_rel_tol_diff 0.001
set TheFileName shading_116.brep
set max_rel_tol_diff 1
if { [string compare $command "shading"] == 0 } {
- set rel_tol 0.273
+ set rel_tol 0.241
} else {
- set rel_tol 0.336
-}
\ No newline at end of file
+ set rel_tol 6.376860334255998
+}
+set bug_freenodes "M8"
+set nbfreenodes(All) 1
set TheFileName shading_147.brep
+if { [string compare $command "shading"] == 0 } {
+ set rel_tol 0.8093314937741523
+ set max_rel_tol_diff 0.001
+}
set TheFileName shading_wrongshape_004.brep
-set bug_area "OCC22687"
-set rel_tol 1.9
-set bug_withouttri "OCC22687"
+###set bug_area "OCC22687"
if { [string compare $command "shading"] == 0 } {
- #puts "TODO OCC23105 ALL: Error: Improvement: The current area difference is"
- set nbwithouttri(All) 2
- set bug_freenodes "OCC22687"
- set nbfreenodes(All) 38
+ set rel_tol 0.06073194250400039
} else {
- set nbwithouttri(All) 2
- set bug_freenodes "OCC23105"
- set nbfreenodes(ALL) 1
+ set rel_tol 0.0021948131898279323
}
+set max_rel_tol_diff 0.001
+###set bug_withouttri "OCC22687"
+###if { [string compare $command "shading"] == 0 } {
+### #puts "TODO OCC23105 ALL: Error: Improvement: The current area difference is"
+### set nbwithouttri(All) 2
+### set bug_freenodes "OCC22687"
+### set nbfreenodes(All) 38
+###} else {
+### set nbwithouttri(All) 2
+### set bug_freenodes "OCC23105"
+### set nbfreenodes(ALL) 1
+###}
set TheFileName shading_wrongshape_007.brep
-set bug_freenodes "OCC22687"
if { [string compare $command "shading"] == 0 } {
- set nbfreenodes(All) 6
+ set bug_freelinks "OCC22687"
+ set bug_freenodes "OCC22687"
+ set nbfreenodes(All) 6
+ set nbfree(All) 3
} else {
- set nbfreenodes(All) 2
## set bug_freelinks "OCC22687"
## set nbfree(All) 8
}
+if { [string compare $command "shading"] != 0 } {
+ puts "TODO OCC30056 All: Meshing statuses: SelfIntersectingWire Failure"
+}
+
set TheFileName shading_wrongshape_008.brep
set bug_withouttri "OCC22687"
set nbwithouttri(All) 2
+if { [string compare $command "shading"] != 0 } {
+ puts "TODO OCC30056 All: Meshing statuses: SelfIntersectingWire Failure"
+}
+
set TheFileName shading_wrongshape_009.brep
set bug_area "OCC22687"
-set rel_tol 10.7
set bug_withouttri "OCC22687"
set bug_freelinks "OCC22687"
set bug_freenodes "OCC22687"
if { [string compare $command "shading"] == 0 } {
+ set rel_tol 7.5981
##set nbt 14
- set nbt 8
+ set nbt 0
set nbl 8
set nbn 83
set nbwithouttri([checkplatform]) $nbt
set nbfree([checkplatform]) $nbl
set nbfreenodes([checkplatform]) $nbn
} else {
+ set rel_tol 5.131
set bug_withouttri "OCC23105"
##set nbt 14
- set nbt 8
+ set nbt 3
set nbn 60
set nbl 11
set nbwithouttri([checkplatform]) $nbt
set nbfree([checkplatform]) $nbl
set nbfreenodes([checkplatform]) $nbn
}
+set max_rel_tol_diff 0.001
+if { [string compare $command "shading"] != 0 } {
+ puts "TODO OCC30056 All: Meshing statuses: SelfIntersectingWire Failure"
+}
+
set TheFileName shading_wrongshape_013.brep
set bug_area "OCC22687"
set rel_tol 100
+if { [string compare $command "shading"] != 0 } {
+ puts "TODO OCC30056 All: Meshing statuses: Failure UnorientedWire"
+}
+
set TheFileName shading_wrongshape_015.brep
set bug_withouttri "OCC22687"
-if { [string compare $command "shading"] != 0 } {
+if { [string compare $command "shading"] == 0 } {
set bug_freenodes "OCC23105"
set nbfreenodes(ALL) 3
+} else {
+ set bug_freenodes "OCC23105"
+ set nbfreenodes(ALL) 11
}
-set nbwithouttri(All) 7
+set nbwithouttri(All) 3
set TheFileName shading_wrongshape_018.brep
-set bug_area "OCC22687"
-set rel_tol 100
-set bug_withouttri "OCC22687"
-set nbwithouttri(All) 1
+###set bug_area "OCC22687"
+###set rel_tol 100
+###set bug_withouttri "OCC22687"
+###set nbwithouttri(All) 1
+if { [string compare $command "shading"] == 0 } {
+ set bug_area "OCC22687"
+ set rel_tol 79.458
+ set bug_freenodes "OCC22687"
+ set nbfreenodes(ALL) 41
+ set bug_freelinks "OCC22687"
+ set nbfree(All) 21
+} else {
+ set bug_area "OCC22687"
+ set rel_tol 77.709
+ set bug_freenodes "OCC22687"
+ set nbfreenodes(ALL) 25
+ set bug_freelinks "OCC22687"
+ set nbfree(All) 4
+}
+set max_rel_tol_diff 0.001
set TheFileName shading_wrongshape_022.brep
-set bug_withouttri "OCC22687"
-set nbwithouttri(All) 2
+
+if { [string compare $command "shading"] != 0 } {
+#set bug_cross "OCC22687"
+#set nbcross(All) 2
+}
\ No newline at end of file
set bug_area "OCC22687"
set bug_freenodes "OCC22687"
set bug_withouttri "OCC22687"
+set nbwithouttri(ALL) 1
if { [string compare $command "shading"] == 0 } {
set rel_tol 1.2
- set nbwithouttri(ALL) 6
+##set nbwithouttri(ALL) 6
set nbfreenodes(ALL) 1
##set bug_freelinks "OCC22687"
##set nbfree(ALL) 2
} else {
set nbfreenodes(ALL) 2
- set nbwithouttri(ALL) 5
+##set nbwithouttri(ALL) 5
}
set TheFileName shading_wrongshape_025.brep
-set bug_area "OCC22687"
-set rel_tol 36.8
set bug_withouttri "OCC22687"
set bug_cross "OCC22687"
+
if { [string compare $command "shading"] == 0 } {
- set nbwithouttri(All) 90
+ set bug_area "OCC22687"
+ set rel_tol 0.4502501798185579
+##set nbwithouttri(All) 90
set nbcross(All) 12
set bug_freenodes "OCC22687"
set nbfreenodes(All) 10
} else {
- set nbwithouttri(All) 90
+ set bug_area "OCC22687"
+ set rel_tol 0.285
+##set nbwithouttri(All) 90
set nbcross(All) 11
set bug_freenodes "OCC23473"
set nbfreenodes(All) 11
+ set bug_freelinks "OCC22687"
+ set nbfree(All) 2
}
+set max_rel_tol_diff 0.001
set TheFileName shading_wrongshape_026.brep
-set bug_area "OCC22687"
-set rel_tol 3.5
-set bug_withouttri "OCC22687"
-set nbwithouttri(All) 3
+if { [string compare $command "shading"] == 0 } {
+ set rel_tol 0.06893312870606805
+} else {
+ set rel_tol 0.0020125629706199506
+}
+set max_rel_tol_diff 0.001
+###set bug_withouttri "OCC22687"
+###set nbwithouttri(All) 3
set TheFileName shading_wrongshape_027.brep
set bug_freenodes "OCC22687"
-set nbfreenodes(All) 6
+#set nbfreenodes(All) 6
if { [string compare $command "shading"] != 0 } {
#set bug_area "OCC22687"
set max_rel_tol_diff 1
- set rel_tol 1.2
+ set rel_tol 0.19838215623500813
} else {
set max_rel_tol_diff 0.01
- set rel_tol 0.052351028422287886
+ set rel_tol 0.12561722204279838
}
set TheFileName shading_wrongshape_030.brep
-set bug_area "OCC22687"
-set rel_tol 6
-set bug_withouttri "OCC22687"
-set nbwithouttri(All) 4
+###set bug_area "OCC22687"
+###set rel_tol 6
+###set bug_withouttri "OCC22687"
+###set nbwithouttri(All) 4
+if { [string compare $command "shading"] == 0 } {
+ set rel_tol 0.5456843734442471
+} else {
+ set rel_tol 0.1783852555846471
+}
+set max_rel_tol_diff 0.001
set TheFileName shading_wrongshape_031.brep
-set bug_area "OCC22687"
-set rel_tol 64
-set bug_withouttri "OCC22687"
-set nbwithouttri(All) 2
+if { [string compare $command "shading"] == 0 } {
+ set bug_area "OCC23184"
+ set rel_tol 4.3058
+} else {
+ set bug_area "OCC23184"
+ set rel_tol 4.1307
+}
+set max_rel_tol_diff 0.001
+
+set nbcross(All) 1
+set bug_cross "OCC23184"
+
+###set bug_area "OCC22687"
+###set rel_tol 64
+###set bug_withouttri "OCC22687"
+###set nbwithouttri(All) 2
bcut res s b
if { [string compare $command "shading"] == 0 } {
- puts "TODO #23111 ALL: Error : incorrect node"
+###puts "TODO #23111 ALL: Error : incorrect node"
explode res f
vinit
vdisplay res
if { $rel_tol == 100 } {
puts "TODO $bug_area All:^\\s*Error : The meshing algo cannot create mesh.\\s*$"
} else {
- puts "TODO ?$bug_area All:^\\s*Error : area by triangles differs from the actual area by \[-.0-9\]+ %\\s*$"
+ puts "TODO ?$bug_area All: Error: area difference = .* is not equal to expected"
}
}
puts "\nChecking triangulation area (triarea command)..."
set rel_err [expr abs([CheckTriArea res $area_eps])]
-if { $rel_err > $rel_tol } {
- puts "Error : area by triangles differs from the actual area by $rel_err %"
-} else {
- if { [info exists max_rel_tol_diff] && $max_rel_tol_diff > 0 } {
- checkreal "area difference" $rel_err $rel_tol $max_rel_tol_diff 0
- } else {
- if { $rel_tol > 1 && $rel_tol < 100 } {
- puts "Error: Improvement: The current area difference is $rel_err instead of $rel_tol"
- }
- }
+if { [info exists max_rel_tol_diff] && $max_rel_tol_diff > 0 } {
+ checkreal "area difference" $rel_err $rel_tol $max_rel_tol_diff 0
}
# Check if topology of mesh is valid
restore [locate_data_file bug27119_GrossPlatePart3Step2TransformedFace.brep] result
dchrono t restart
-incmesh result 1.e-6
+incmesh result 1.e-5
dchrono t stop counter incmesh
set tri 0
regexp { +([-0-9.+eE]+) +nodes} $tri_info full nod
regexp { deflection +([-0-9.+eE]+)} $tri_info full def
-set ref_tri 7855
-set ref_nod 7857
-set ref_def 9.3791641120333225e-013
+set ref_tri 7857
+set ref_nod 7859
+set ref_def 1e-5
set tol_rel 0.01
# Computes deviation of the value from specified one
checkreal "Nb of nodes" $nod $ref_nod 0 $tol_rel
checkreal "Deflection" $def $ref_def 1.e-12 0
-set 3dviewer 1
\ No newline at end of file
+set 3dviewer 1