Path: blob/devel/ElmerGUI/Application/cad/cadview.cpp
3203 views
/*****************************************************************************1* *2* Elmer, A Finite Element Software for Multiphysical Problems *3* *4* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *5* *6* This program is free software; you can redistribute it and/or *7* modify it under the terms of the GNU General Public License *8* as published by the Free Software Foundation; either version 2 *9* of the License, or (at your option) any later version. *10* *11* This program is distributed in the hope that it will be useful, *12* but WITHOUT ANY WARRANTY; without even the implied warranty of *13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *14* GNU General Public License for more details. *15* *16* You should have received a copy of the GNU General Public License *17* along with this program (in file fem/GPL-2); if not, write to the *18* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *19* Boston, MA 02110-1301, USA. *20* *21*****************************************************************************/2223/*****************************************************************************24* *25* ElmerGUI cadview *26* *27*****************************************************************************28* *29* Authors: Mikko Lyly, Juha Ruokolainen and Peter RÃ¥back *30* Email: [email protected] *31* Web: http://www.csc.fi/elmer *32* Address: CSC - IT Center for Science Ltd. *33* Keilaranta 14 *34* 02101 Espoo, Finland *35* *36* Original Date: 15 Mar 2008 *37* *38*****************************************************************************/3940#if WITH_QT5 || WITH_QT641#include <QtWidgets>42#else43#include <QtGui>44#endif4546#include <iostream>4748#include "cadview.h"4950#if VTK_MAJOR_VERSION >= 851#include <vtkVersionMacros.h>52#include <QVTKOpenGLNativeWidget.h>53#else54#include <QVTKWidget.h>55#endif5657#include <vtkActor.h>58#include <vtkAppendPolyData.h>59#include <vtkCallbackCommand.h>60#include <vtkCleanPolyData.h>61#include <vtkDataSetMapper.h>62#include <vtkFeatureEdges.h>63#include <vtkFloatArray.h>64#include <vtkPoints.h>65#include <vtkPolyDataMapper.h>66#include <vtkPolyDataNormals.h>67#include <vtkPropPicker.h>68#include <vtkProperty.h>69#include <vtkRenderWindow.h>70#include <vtkRenderer.h>71#include <vtkTriangle.h>7273#include <BRepAdaptor_Curve2d.hxx>74#include <BRepBndLib.hxx>75#include <BRepGProp.hxx>76#include <BRepTools.hxx>77#include <BRep_Builder.hxx>78#if OCE_FOUND79#include <BRepMesh.hxx>80#endif81#include <BRep_Tool.hxx>82#include <Bnd_Box.hxx>83#include <GCPnts_TangentialDeflection.hxx>84#include <GProp_GProps.hxx>85#include <GeomLProp_SLProps.hxx>86#include <IGESControl_Reader.hxx>87#include <Poly_Triangulation.hxx>88#include <STEPControl_Reader.hxx>89#include <TopExp_Explorer.hxx>90#include <TopTools_HSequenceOfShape.hxx>91#include <TopoDS.hxx>92#include <TopoDS_Edge.hxx>93#include <TopoDS_Face.hxx>94#include <TopoDS_Shape.hxx>9596using namespace std;97static void pickEventHandler(vtkObject* caller, unsigned long eid,98void* clientdata, void* calldata)99{100CadView* cadView = reinterpret_cast<CadView*>(clientdata);101102#if VTK_MAJOR_VERSION >= 8103QVTKOpenGLNativeWidget* qvtkWidget = cadView->GetQVTKWidget();104#else105QVTKWidget* qvtkWidget = cadView->GetQVTKWidget();106#endif107108#if VTK_MAJOR_VERSION >= 9109vtkAbstractPicker* picker = qvtkWidget->interactor()->GetPicker();110#else111vtkAbstractPicker* picker = qvtkWidget->GetInteractor()->GetPicker();112#endif113vtkPropPicker* propPicker = vtkPropPicker::SafeDownCast(picker);114vtkActor* actor = propPicker->GetActor();115116int faceNumber = cadView->getFaceNumber(actor);117118if (faceNumber > 0) {119vtkProperty *p = actor->GetProperty();120121double color[3];122p->GetColor(color);123124// Toggle color:125//--------------126if (color[0] < 0.5) {127cout << "Selected face: ";128p->SetColor(1, 0, 0);129} else {130cout << "Unselected face: ";131p->SetColor(0, 1, 1);132}133cout << faceNumber << endl;134}135}136137CadView::CadView(QWidget *parent) : QMainWindow(parent) {138setWindowTitle("ElmerGUI geometry viewer");139setWindowIcon(QIcon(":/icons/Mesh3D.png"));140141createActions();142createMenus();143144#if VTK_MAJOR_VERSION >= 8145qVTKWidget = new QVTKOpenGLNativeWidget(this);146qVTKWidget->setFormat(QVTKOpenGLNativeWidget::defaultFormat());147#else148qVTKWidget = new QVTKWidget(this);149#endif150setCentralWidget(qVTKWidget);151152renderer = vtkRenderer::New();153renderer->SetBackground(1, 1, 1);154#if VTK_MAJOR_VERSION >=9155qVTKWidget->renderWindow()->AddRenderer(renderer);156#else157qVTKWidget->GetRenderWindow()->AddRenderer(renderer);158#endif159renderer->GetRenderWindow()->Render();160161vtkPropPicker *propPicker = vtkPropPicker::New();162vtkCallbackCommand *cbcPick = vtkCallbackCommand::New();163#if VTK_MAJOR_VERSION >= 9164qVTKWidget->interactor()->SetPicker(propPicker);165cbcPick->SetClientData(this);166cbcPick->SetCallback(pickEventHandler);167qVTKWidget->interactor()->GetPicker()->AddObserver(vtkCommand::PickEvent,168cbcPick);169#else170qVTKWidget->GetInteractor()->SetPicker(propPicker);171cbcPick->SetClientData(this);172cbcPick->SetCallback(pickEventHandler);173qVTKWidget->GetInteractor()->GetPicker()->AddObserver(vtkCommand::PickEvent,174cbcPick);175#endif176propPicker->Delete();177cbcPick->Delete();178179stlSurfaceData = vtkAppendPolyData::New();180stlEdgeData = vtkAppendPolyData::New();181182cadPreferences = new CadPreferences(this);183184modelLength = 0.0;185numberOfFaces = 0;186fileName = "";187modelDim = -1;188}189190CadView::~CadView() {}191192QSize CadView::minimumSizeHint() const { return QSize(64, 64); }193194QSize CadView::sizeHint() const { return QSize(720, 576); }195196void CadView::createActions() {197exitAct = new QAction(QIcon::fromTheme("emblem-unreadable"), tr("&Quit"), this);198exitAct->setShortcut(tr("Ctrl+Q"));199connect(exitAct, SIGNAL(triggered()), this, SLOT(closeSlot()));200201cadPreferencesAct = new QAction(QIcon::fromTheme("preferences-system"), tr("Preferences..."), this);202cadPreferencesAct->setShortcut(tr("Ctrl+P"));203connect(cadPreferencesAct, SIGNAL(triggered()), this,204SLOT(cadPreferencesSlot()));205206reloadAct = new QAction(QIcon::fromTheme("view-refresh"), tr("Reload geometry"), this);207reloadAct->setShortcut(tr("Ctrl+R"));208connect(reloadAct, SIGNAL(triggered()), this, SLOT(reloadSlot()));209}210211void CadView::createMenus() {212fileMenu = menuBar()->addMenu(tr("&File"));213fileMenu->addAction(reloadAct);214fileMenu->addSeparator();215fileMenu->addAction(exitAct);216217modelMenu = menuBar()->addMenu(tr("&Model"));218modelMenu->addAction(cadPreferencesAct);219}220221void CadView::closeSlot() { close(); }222223void CadView::cadPreferencesSlot() { cadPreferences->show(); }224225void CadView::reloadSlot() {226if (this->fileName.isEmpty())227return;228readFile(this->fileName);229}230231bool CadView::readFile(QString fileName) {232double deflection = cadPreferences->ui.deflection->text().toDouble();233double featureAngle = cadPreferences->ui.featureAngle->text().toDouble();234bool mergePoints = cadPreferences->ui.mergePoints->isChecked();235236if (deflection < 0.0) {237deflection = 0.0005;238cout << "Bad value for deflection. Using: " << deflection << endl;239}240241if (featureAngle < 0.0) {242featureAngle = 30.0;243cout << "Bad value for feature angle. Using: " << featureAngle << endl;244}245246if (stlSurfaceData->GetOutput()->GetNumberOfPoints() > 0)247stlSurfaceData->Delete();248249if (stlEdgeData->GetOutput()->GetNumberOfPoints() > 0)250stlEdgeData->Delete();251252stlSurfaceData = vtkAppendPolyData::New();253stlEdgeData = vtkAppendPolyData::New();254255if (fileName.isEmpty()) {256cout << "File name is empty. Aborting." << endl;257return false;258}259260QFileInfo fileInfo(fileName);261QString fileSuffix = fileInfo.suffix().toLower();262263// TopoDS_Shape shape;264265if (fileSuffix == "brep")266shape = readBrep(fileName);267268if ((fileSuffix == "step") || (fileSuffix == "stp"))269shape = readStep(fileName);270271if ((fileSuffix == "iges") || (fileSuffix == "igs"))272shape = readIges(fileName);273274if (shape.IsNull()) {275cout << "Cad import: No shapes. Aborting" << endl;276return false;277}278279BRepTools::Clean(shape);280281// Check 3D properties:282//----------------------283GProp_GProps System;284BRepGProp::VolumeProperties(shape, System);285double mass = System.Mass();286287if (mass < 1.0e-12) {288QMessageBox message;289message.setIcon(QMessageBox::Warning);290message.setText("Non 3D-shape detected");291message.setInformativeText(292"The cad import features of ElmerGUI are currently limited to 3D "293"models. Please consider using external software or other formats for "294"meshing 1D and 2D geometries.");295message.exec();296}297298// Go:299//-----300this->fileName = fileName;301302actorToFace.clear();303304clearScreen();305306// Compute bounding box:307//----------------------308Bnd_Box boundingBox;309double min[3], max[3];310311BRepBndLib::Add(shape, boundingBox);312boundingBox.Get(min[0], min[1], min[2], max[0], max[1], max[2]);313314cout << "Bounding box: "315<< "[ " << min[0] << ", " << min[1] << ", " << min[2] << "] x "316<< "[ " << max[0] << ", " << max[1] << ", " << max[2] << "]" << endl;317318double length = sqrt((max[2] - min[2]) * (max[2] - min[2]) +319(max[1] - min[1]) * (max[1] - min[1]) +320(max[0] - min[0]) * (max[0] - min[0]));321322deflection *= length; // use relative units323324double t0 = sqrt((max[0] - min[0]) * (max[0] - min[0]));325double t1 = sqrt((max[1] - min[1]) * (max[1] - min[1]));326double t2 = sqrt((max[2] - min[2]) * (max[2] - min[2]));327328modelDim = 3;329330double tol = 1.0e-6 * length;331332if ((t0 < tol) || (t1 < tol) || (t2 < tol)) {333modelDim = 2;334// cout << "Cad import: Shape seems to be 2D. Unable to proceed. Aborting."335// << endl; return false;336}337338// Construct model data and draw surfaces:339//-----------------------------------------340#if OCC_VERSION_HEX >= 0x060800341BRepMesh_IncrementalMesh(shape, deflection);342#else343BRepMesh::Mesh(shape, deflection);344#endif345346numberOfFaces = 0;347TopExp_Explorer expFace;348for (expFace.Init(shape, TopAbs_FACE); expFace.More(); expFace.Next()) {349TopoDS_Face Face = TopoDS::Face(expFace.Current());350351TopLoc_Location Location;352Handle(Poly_Triangulation) Triangulation =353BRep_Tool::Triangulation(Face, Location);354355if (Triangulation.IsNull()) {356cout << "Encountered empty triangulation after face: "357<< numberOfFaces + 1 << endl;358continue;359}360361const gp_Trsf &Transformation = Location.Transformation();362363int nofTriangles = Triangulation->NbTriangles();364int nofNodes = Triangulation->NbNodes();365366if (nofTriangles < 1) {367cout << "No triangles for mesh on face: " << numberOfFaces + 1 << endl;368continue;369}370371if (nofNodes < 1) {372cout << "No nodes for mesh on face: " << numberOfFaces + 1 << endl;373continue;374}375376numberOfFaces++;377378int n0, n1, n2;379vtkPolyData *partGrid = vtkPolyData::New();380vtkTriangle *triangle = vtkTriangle::New();381partGrid->Allocate(nofTriangles, nofTriangles);382383#if OCC_VERSION_HEX >= 0x070600384for (int i = 1; i <= nofTriangles; i++) {385Triangulation->Triangle(i).Get(n0, n1, n2);386387if (Face.Orientation() != TopAbs_FORWARD) {388int tmp = n2;389n2 = n1;390n1 = tmp;391}392393triangle->GetPointIds()->SetId(0, n0 - 1);394triangle->GetPointIds()->SetId(1, n1 - 1);395triangle->GetPointIds()->SetId(2, n2 - 1);396397partGrid->InsertNextCell(triangle->GetCellType(),398triangle->GetPointIds());399}400401double x[3];402vtkPoints *partPoints = vtkPoints::New();403404for (int i = 1; i <= nofNodes; i++) {405gp_XYZ XYZ = Triangulation->Node(i).Coord();406407Transformation.Transforms(XYZ);408x[0] = XYZ.X();409x[1] = XYZ.Y();410x[2] = XYZ.Z();411partPoints->InsertPoint(i - 1, x);412}413#else414const Poly_Array1OfTriangle &Triangles = Triangulation->Triangles();415const TColgp_Array1OfPnt &Nodes = Triangulation->Nodes();416417for (int i = Triangles.Lower(); i <= Triangles.Upper(); i++) {418Triangles(i).Get(n0, n1, n2);419420if (Face.Orientation() != TopAbs_FORWARD) {421int tmp = n2;422n2 = n1;423n1 = tmp;424}425426triangle->GetPointIds()->SetId(0, n0 - Nodes.Lower());427triangle->GetPointIds()->SetId(1, n1 - Nodes.Lower());428triangle->GetPointIds()->SetId(2, n2 - Nodes.Lower());429430partGrid->InsertNextCell(triangle->GetCellType(),431triangle->GetPointIds());432}433434double x[3];435vtkPoints *partPoints = vtkPoints::New();436437for (int i = Nodes.Lower(); i <= Nodes.Upper(); i++) {438gp_XYZ XYZ = Nodes(i).Coord();439440Transformation.Transforms(XYZ);441x[0] = XYZ.X();442x[1] = XYZ.Y();443x[2] = XYZ.Z();444partPoints->InsertPoint(i - Nodes.Lower(), x);445}446#endif447448partGrid->SetPoints(partPoints);449450451// Draw part:452//-----------453vtkCleanPolyData *partCleaner = vtkCleanPolyData::New();454#if VTK_MAJOR_VERSION <= 5455partCleaner->SetInput(partGrid);456#else457partCleaner->SetInputData(partGrid);458partCleaner->Update();459#endif460if (mergePoints) {461partCleaner->PointMergingOn();462} else {463partCleaner->PointMergingOff();464}465466vtkPolyDataNormals *partNormals = vtkPolyDataNormals::New();467partNormals->SetInputConnection(partCleaner->GetOutputPort());468partNormals->SetFeatureAngle(featureAngle);469470vtkDataSetMapper *partMapper = vtkDataSetMapper::New();471partMapper->SetInputConnection(partNormals->GetOutputPort());472partMapper->ScalarVisibilityOff();473474vtkActor *partActor = vtkActor::New();475partActor->SetPickable(1);476partActor->GetProperty()->SetColor(0, 1, 1);477partActor->SetMapper(partMapper);478renderer->AddActor(partActor);479actorToFace.insert(partActor, numberOfFaces);480481vtkFeatureEdges *partFeature = vtkFeatureEdges::New();482partFeature->SetInputConnection(partCleaner->GetOutputPort());483partFeature->SetFeatureAngle(featureAngle);484partFeature->FeatureEdgesOff();485partFeature->BoundaryEdgesOn();486partFeature->NonManifoldEdgesOn();487partFeature->ManifoldEdgesOff();488489vtkDataSetMapper *partFeatureMapper = vtkDataSetMapper::New();490partFeatureMapper->SetInputConnection(partFeature->GetOutputPort());491partFeatureMapper->SetResolveCoincidentTopologyToPolygonOffset();492partFeatureMapper->ScalarVisibilityOff();493494vtkActor *partFeatureActor = vtkActor::New();495partFeatureActor->SetPickable(0);496partFeatureActor->GetProperty()->SetColor(0, 0, 0);497partFeatureActor->SetMapper(partFeatureMapper);498renderer->AddActor(partFeatureActor);499500// Add triangles and edges to STL structures:501//--------------------------------------------502#if VTK_MAJOR_VERSION <= 5503stlSurfaceData->AddInput(partCleaner->GetOutput());504stlEdgeData->AddInput(partFeature->GetOutput());505#else506stlSurfaceData->AddInputData(partCleaner->GetOutput());507stlEdgeData->AddInputData(partFeature->GetOutput());508#endif509510// Clean up:511//----------512partFeatureActor->Delete();513partFeatureMapper->Delete();514partFeature->Delete();515partActor->Delete();516partNormals->Delete();517partMapper->Delete();518partCleaner->Delete();519partGrid->Delete();520partPoints->Delete();521triangle->Delete();522}523524if (numberOfFaces < 1) {525cout << "Cad import: error: no surface triangulation was generated. "526"Aborting."527<< endl;528return false;529}530531stlSurfaceData->Update();532stlEdgeData->Update();533modelLength = stlSurfaceData->GetOutput()->GetLength();534cout << "StlSurfaceData: points: "535<< stlSurfaceData->GetOutput()->GetNumberOfPoints() << endl;536cout << "StlSurfaceData: cells: "537<< stlSurfaceData->GetOutput()->GetNumberOfCells() << endl;538cout << "StlEdgeData: lines: " << stlEdgeData->GetOutput()->GetNumberOfLines()539<< endl;540cout << "StlModelData: length: " << modelLength << endl;541542// Draw:543//------544renderer->ResetCamera();545#if VTK_MAJOR_VERSION >= 9546qVTKWidget->renderWindow()->Render();547#else548qVTKWidget->GetRenderWindow()->Render();549#endif550551QCoreApplication::processEvents();552553return true;554}555556void CadView::generateSTLSlot() {557double meshMinSize = modelLength * cadPreferences->ui.minh->text().toDouble();558double meshMaxSize = modelLength * cadPreferences->ui.maxh->text().toDouble();559bool restrictBySTL = cadPreferences->ui.restrictBySTL->isChecked();560561// Check also the MainWindow meshing preferences:562if (mp->maxh < meshMaxSize)563meshMaxSize = mp->maxh;564double meshFineness = mp->fineness;565566if (meshMaxSize > 0.1 * modelLength)567meshMaxSize = 0.1 * modelLength;568569if (meshMinSize > meshMaxSize)570meshMinSize = meshMaxSize;571572if (meshMinSize < 0)573meshMinSize = modelLength * 0.005;574575if (meshMaxSize < 0)576meshMaxSize = modelLength * 0.1;577578cout << "Cad import: max mesh size: " << meshMaxSize << endl;579cout << "Cad import: mesh fineness: " << meshFineness << endl;580581// Add STL triangles to geometry:582//--------------------------------583vtkCleanPolyData *stlSurface = vtkCleanPolyData::New();584stlSurface->PointMergingOn();585#if VTK_MAJOR_VERSION <= 5586stlSurface->SetInput(stlSurfaceData->GetOutput());587#else588stlSurface->SetInputConnection(stlSurfaceData->GetOutputPort());589#endif590591stlSurface->Update();592593if (stlSurface->GetOutput()->GetNumberOfCells() < 1) {594cout << "Cad import: error: geometry undefined - no STL available" << endl;595return;596}597598double p0[3], p1[3], p2[3];599for (int i = 0; i < stlSurface->GetOutput()->GetNumberOfCells(); i++) {600vtkCell *cell = stlSurface->GetOutput()->GetCell(i);601int nofCellPoints = cell->GetNumberOfPoints();602vtkPoints *cellPoints = cell->GetPoints();603604if (nofCellPoints == 3) {605cellPoints->GetPoint(0, p0);606cellPoints->GetPoint(1, p1);607cellPoints->GetPoint(2, p2);608nglib::Ng_STL_AddTriangle(geom, p0, p1, p2, NULL);609}610}611612// Add STL edges to geometry:613//----------------------------614vtkCleanPolyData *stlEdge = vtkCleanPolyData::New();615stlEdge->PointMergingOn();616#if VTK_MAJOR_VERSION <= 5617stlEdge->SetInput(stlEdgeData->GetOutput());618#else619stlEdge->SetInputConnection(stlEdgeData->GetOutputPort());620#endif621622stlEdge->Update();623624for (int i = 0; i < stlEdge->GetOutput()->GetNumberOfCells(); i++) {625vtkCell *cell = stlEdge->GetOutput()->GetCell(i);626int nofCellPoints = cell->GetNumberOfPoints();627vtkPoints *cellPoints = cell->GetPoints();628629if (nofCellPoints == 2) {630cellPoints->GetPoint(0, p0);631cellPoints->GetPoint(1, p1);632nglib::Ng_STL_AddEdge(geom, p0, p1);633}634}635636// Init STL geometry:637//--------------------638nglib::Ng_STL_InitSTLGeometry(geom);639640// Generate edges:641//-----------------642nglib::Ng_STL_MakeEdges(geom, mesh, mp);643644// Global mesh size restrictions:645//--------------------------------646nglib::Ng_RestrictMeshSizeGlobal(mesh, meshMaxSize);647648// Local mesh size restrictions:649//-------------------------------650if (restrictBySTL)651restrictMeshSizeLocal(mesh, stlSurface->GetOutput(), meshMaxSize,652meshMinSize);653}654655#if VTK_MAJOR_VERSION >= 8656QVTKOpenGLNativeWidget* CadView::GetQVTKWidget()657#else658QVTKWidget* CadView::GetQVTKWidget()659#endif660{661return this->qVTKWidget;662}663664void CadView::clearScreen() {665cout << "Clear screen" << endl;666vtkActorCollection *actors = renderer->GetActors();667vtkActor *lastActor = actors->GetLastActor();668while (lastActor != NULL) {669renderer->RemoveActor(lastActor);670lastActor = actors->GetLastActor();671}672}673674TopoDS_Shape CadView::readBrep(QString fileName) {675TopoDS_Shape shape;676BRep_Builder builder;677Standard_Boolean result;678679result = BRepTools::Read(shape, fileName.toLatin1().data(), builder);680681if (!result)682cout << "Read brep failed" << endl;683684return shape;685}686687TopoDS_Shape CadView::readStep(QString fileName) {688TopoDS_Shape shape;689Handle_TopTools_HSequenceOfShape shapes;690STEPControl_Reader stepReader;691IFSelect_ReturnStatus status;692693status = stepReader.ReadFile(fileName.toLatin1().data());694695if (status == IFSelect_RetDone) {696bool failsonly = false;697stepReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);698699int nbr = stepReader.NbRootsForTransfer();700stepReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);701702for (Standard_Integer n = 1; n <= nbr; n++) {703bool ok = stepReader.TransferRoot(n);704int nbs = stepReader.NbShapes();705706// Display warning if nbs > 1707//----------------------------708if (nbs > 1) {709QMessageBox message;710message.setIcon(QMessageBox::Warning);711message.setText("Loading multiple shapes");712message.setInformativeText(713"The mesh generators of ElmerGUI are currently unable to handle "714"cad files with multiple shapes. Please consider using external "715"software for mesh generation in this case.");716message.exec();717}718719if (nbs > 0) {720shapes = new TopTools_HSequenceOfShape();721for (int i = 1; i <= nbs; i++) {722cout << "Added shape: " << i << endl;723shape = stepReader.Shape(i);724shapes->Append(shape);725}726}727}728}729730return shape;731}732733TopoDS_Shape CadView::readIges(QString fileName) {734TopoDS_Shape shape;735IGESControl_Reader igesReader;736IFSelect_ReturnStatus status;737738status = igesReader.ReadFile(fileName.toLatin1().data());739740if (status == IFSelect_RetDone) {741igesReader.TransferRoots();742shape = igesReader.OneShape();743}744745return shape;746}747748void CadView::restrictMeshSizeLocal(nglib::Ng_Mesh *mesh, vtkPolyData *stlData,749double meshMaxSize, double meshMinSize) {750int n0, n1, n2;751double h, h0, h1, h2;752double t[3], p0[3], p1[3], p2[3];753vtkFloatArray *mshSize = vtkFloatArray::New();754mshSize->SetNumberOfComponents(1);755mshSize->SetNumberOfTuples(stlData->GetNumberOfPoints());756757for (int i = 0; i < stlData->GetNumberOfPoints(); i++)758mshSize->SetComponent(i, 0, meshMaxSize);759760for (int i = 0; i < stlData->GetNumberOfCells(); i++) {761vtkCell *cell = stlData->GetCell(i);762int nofCellPoints = cell->GetNumberOfPoints();763vtkPoints *cellPoints = cell->GetPoints();764765if (nofCellPoints == 3) {766n0 = cell->GetPointId(0);767n1 = cell->GetPointId(1);768n2 = cell->GetPointId(2);769770h0 = mshSize->GetComponent(n0, 0);771h1 = mshSize->GetComponent(n1, 0);772h2 = mshSize->GetComponent(n2, 0);773774cellPoints->GetPoint(0, p0);775cellPoints->GetPoint(1, p1);776cellPoints->GetPoint(2, p2);777778differenceOf(t, p0, p1);779h = lengthOf(t);780if (h < meshMinSize)781h = meshMinSize;782if (h < h1)783mshSize->SetComponent(n1, 0, h);784if (h < h0)785mshSize->SetComponent(n0, 0, h);786787differenceOf(t, p2, p0);788h = lengthOf(t);789if (h < meshMinSize)790h = meshMinSize;791if (h < h2)792mshSize->SetComponent(n2, 0, h);793if (h < h0)794mshSize->SetComponent(n0, 0, h);795796differenceOf(t, p2, p1);797h = lengthOf(t);798if (h < meshMinSize)799h = meshMinSize;800if (h < h2)801mshSize->SetComponent(n2, 0, h);802if (h < h1)803mshSize->SetComponent(n1, 0, h);804}805}806807for (int i = 0; i < stlData->GetNumberOfPoints(); i++) {808h = mshSize->GetComponent(i, 0);809if (h < meshMinSize)810h = meshMinSize;811if (h > meshMaxSize)812h = meshMaxSize;813stlData->GetPoint(i, p0);814nglib::Ng_RestrictMeshSizePoint(mesh, p0, h);815}816817mshSize->Delete();818}819820void CadView::generateSTL() { this->generateSTLSlot(); }821822void CadView::setMesh(nglib::Ng_Mesh *mesh) { this->mesh = mesh; }823824void CadView::setGeom(nglib::Ng_STL_Geometry *geom) { this->geom = geom; }825826void CadView::setMp(nglib::Ng_Meshing_Parameters *mp) { this->mp = mp; }827828void CadView::setDeflection(double deflection) {829if (deflection < 0)830return;831832this->cadPreferences->ui.deflection->setText(QString::number(deflection));833}834835double CadView::lengthOf(double *v) {836return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);837}838839void CadView::differenceOf(double *u, double *v, double *w) {840u[0] = v[0] - w[0];841u[1] = v[1] - w[1];842u[2] = v[2] - w[2];843}844845int CadView::getFaceNumber(vtkActor *actor) {846if (actor == NULL)847return -1;848return actorToFace.value(actor);849}850851int CadView::getDim() { return modelDim; }852853void CadView::generateIn2dFile() {854cout << "Generating In2D file from 2D Iges geometry" << endl;855856QVector<pt> pts;857QVector<seg> segs;858859bool firstPoint = true;860int numberOfFaces = 0;861int numberOfPts = 0;862int numberOfSegs = 0;863gp_Pnt previousPnt;864865// Loop over faces:866//------------------867TopExp_Explorer expFace(shape, TopAbs_FACE);868for (expFace; expFace.More(); expFace.Next()) {869TopoDS_Face Face = TopoDS::Face(expFace.Current());870cout << "Face: " << ++numberOfFaces << endl;871872// Loop over edges:873//------------------874int numberOfEdges = 0;875TopExp_Explorer expEdge(Face, TopAbs_EDGE);876for (expEdge; expEdge.More(); expEdge.Next()) {877TopoDS_Edge Edge = TopoDS::Edge(expEdge.Current());878cout << " Edge: " << ++numberOfEdges << endl;879880// Divide edge into segments:881//----------------------------882double AngularDeflection = 0.1;883double CurvatureDeflection = 0.1;884int MinPoints = 2;885double Tolerance = 1.0e-9;886887BRepAdaptor_Curve2d Curve(Edge, Face);888GCPnts_TangentialDeflection TD(Curve, AngularDeflection,889CurvatureDeflection, MinPoints, Tolerance);890891int nofPoints = TD.NbPoints();892cout << " Points: " << nofPoints << endl;893894// Loop over points:895//-------------------896for (int i = 2; i <= nofPoints; i++) {897gp_Pnt value;898899if (firstPoint) {900value = TD.Value(1);901firstPoint = false;902previousPnt = value;903pt p;904p.n = ++numberOfPts;905p.x = value.X();906p.y = value.Y();907pts.push_back(p);908}909910double p0 = TD.Parameter(i - 1);911double p1 = TD.Parameter(i);912913double dist = sqrt((p1 - p0) * (p1 - p0));914915if (dist < Tolerance) {916cout << " Skipped one (based on parameter)" << endl;917continue;918}919920value = TD.Value(i);921922double dx = value.X() - previousPnt.X();923double dy = value.Y() - previousPnt.Y();924925dist = sqrt(dx * dx + dy * dy);926927if (dist < Tolerance) {928cout << " Skipped one (based on value)" << endl;929continue;930}931932pt p;933p.n = ++numberOfPts;934p.x = value.X();935p.y = value.Y();936pts.push_back(p);937938seg s;939s.p0 = numberOfPts - 1;940s.p1 = numberOfPts;941s.bc = numberOfEdges;942segs.push_back(s);943numberOfSegs++;944945previousPnt = value;946}947}948}949950// Write the in2d file:951//----------------------952fstream file("iges2ng.in2d", ios::out);953954file << "splinecurves2dv2" << endl;955file << "1" << endl << endl;956957file << "points" << endl;958for (int i = 0; i < pts.size() - 1; i++) {959pt p = pts[i];960file << p.n << " " << p.x << " " << p.y << endl;961}962963seg s;964file << endl << "segments" << endl;965for (int i = 0; i < segs.size() - 1; i++) {966s = segs[i];967file << "1 0 2 " << s.p0 << " " << s.p1 << " -bc=" << s.bc << endl;968}969970file << "1 0 2 " << s.p1 << " 1 -bc=" << s.bc << endl;971972file << endl << "materials" << endl;973file << "1 mat1 -maxh=100000" << endl;974975file.close();976}977978979