diff --git a/lrsplines2D/include/GoTools/lrsplines2D/BSplineUniLR.h b/lrsplines2D/include/GoTools/lrsplines2D/BSplineUniLR.h index 6e871dba2..7d29b6428 100644 --- a/lrsplines2D/include/GoTools/lrsplines2D/BSplineUniLR.h +++ b/lrsplines2D/include/GoTools/lrsplines2D/BSplineUniLR.h @@ -173,6 +173,15 @@ class BSplineUniLR : public Streamable return mesh_->kval(pardir_, kn); } + /// All knot values + std::vector getKnots() const + { + std::vector knots(kvec_.size()); + for (int ki=0; ki<(int)kvec_.size(); ++ki) + knots[ki] = mesh_->kval(pardir_, kvec_[ki]); + return knots; + } + /// Count multiplicity in the end of the B-spline int endmult(bool atstart) const; diff --git a/lrsplines2D/src/LRSplineSurface.C b/lrsplines2D/src/LRSplineSurface.C index 00a1f373c..63ed1d2ba 100644 --- a/lrsplines2D/src/LRSplineSurface.C +++ b/lrsplines2D/src/LRSplineSurface.C @@ -1686,14 +1686,16 @@ Point LRSplineSurface::operator()(double u, double v, int u_deriv, int v_deriv) // Distinguish between rational and non-rational to avoid // making temporary storage in the non-rational case double eps = 1.0e-12; - const bool u_on_end = (u >= mesh_.maxParam(XFIXED)-eps); //(u == (*b)->umax()); - const bool v_on_end = (v >= mesh_.maxParam(YFIXED)-eps); // (v == (*b)->vmax()); + // const bool u_on_end = (u >= mesh_.maxParam(XFIXED)-eps); //(u == (*b)->umax()); + // const bool v_on_end = (v >= mesh_.maxParam(YFIXED)-eps); // (v == (*b)->vmax()); if (!rational_) { for (auto b = covering_B_functions.begin(); b != covering_B_functions.end(); ++b, ++ki) { + const bool u_on_end = (u >= (*b)->umax()-eps); + const bool v_on_end = (v >= (*b)->vmax()-eps); // The b-function contains the coefficient. result += (*b)->eval(u, v, @@ -1714,8 +1716,8 @@ Point LRSplineSurface::operator()(double u, double v, int u_deriv, int v_deriv) for (auto b = covering_B_functions.begin(); b != covering_B_functions.end(); ++b, ++ki) { - // const bool u_on_end = (u == (*b)->umax()); - // const bool v_on_end = (v == (*b)->vmax()); + const bool u_on_end = (u == (*b)->umax()); + const bool v_on_end = (v == (*b)->vmax()); // The b-function contains the coefficient. double basis_val_pos = (*b)->evalBasisFunction(u, diff --git a/lrsplines2D/src/LRSplineUtils.C b/lrsplines2D/src/LRSplineUtils.C index cf60fdc72..a41240e1b 100644 --- a/lrsplines2D/src/LRSplineUtils.C +++ b/lrsplines2D/src/LRSplineUtils.C @@ -1273,8 +1273,11 @@ LRSplineUtils::refine_mesh(Direction2D d, double fixed_val, double start, // check that the proposed multiplicity modification is legal for (int i = start_ix; i < end_ix; ++i) { const int cur_m = mesh.nu(d, fixed_ix, i, i+1); - if (absolute && (cur_m > mult)) - THROW("Cannot decrease multiplicity."); + if (absolute && (cur_m > mult)) + { + //THROW("Cannot decrease multiplicity."); + mult = cur_m; + } else if (!absolute && (cur_m+mult > spline_degree + 1)) THROW("Cannot increase multiplicity."); } diff --git a/viewlib/app/vol_and_lr/testLRtesselation.C b/viewlib/app/vol_and_lr/testLRtesselation.C new file mode 100644 index 000000000..16cc8de15 --- /dev/null +++ b/viewlib/app/vol_and_lr/testLRtesselation.C @@ -0,0 +1,74 @@ +/* + * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT, + * Applied Mathematics, Norway. + * + * Contact information: E-mail: tor.dokken@sintef.no + * SINTEF ICT, Department of Applied Mathematics, + * P.O. Box 124 Blindern, + * 0314 Oslo, Norway. + * + * This file is part of GoTools. + * + * GoTools is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * GoTools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with GoTools. If not, see + * . + * + * In accordance with Section 7(b) of the GNU Affero General Public + * License, a covered work must retain the producer line in every data + * file that is created or manipulated using GoTools. + * + * Other Usage + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial activities involving the GoTools library without + * disclosing the source code of your own applications. + * + * This file may be used in accordance with the terms contained in a + * written agreement between you and SINTEF ICT. + */ + +#include "GoTools/viewlib/vol_and_lr/LRSurfaceTesselator.h" +#include "GoTools/lrsplines2D/LRSplineSurface.h" +#include "GoTools/geometry/ObjectHeader.h" +#include "GoTools/tesselator/GenericTriMesh.h" +#include + +using namespace std; +using namespace Go; + +int main( int argc, char* argv[] ) +{ + if (argc != 4) { + std::cout << "Input parameters : Input file, n, m" << std::endl; + exit(-1); + } + + // Read input arguments + std::ifstream file1(argv[1]); + ALWAYS_ERROR_IF(file1.bad(), "Input file not found or file corrupt"); + + int n = atoi(argv[2]); + int m = atoi(argv[3]); + + // Read lrspline surface + ObjectHeader header; + header.read(file1); + shared_ptr surf(new LRSplineSurface()); + surf->read(file1); + + LRSurfaceTesselator tess(*surf); + tess.changeRes(n, m); + tess.tesselate(); + + int stop_break = 1; +} diff --git a/viewlib/include/GoTools/viewlib/vol_and_lr/LRSurfacePropertySheet.h b/viewlib/include/GoTools/viewlib/vol_and_lr/LRSurfacePropertySheet.h new file mode 100644 index 000000000..283b3d647 --- /dev/null +++ b/viewlib/include/GoTools/viewlib/vol_and_lr/LRSurfacePropertySheet.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT, + * Applied Mathematics, Norway. + * + * Contact information: E-mail: tor.dokken@sintef.no + * SINTEF ICT, Department of Applied Mathematics, + * P.O. Box 124 Blindern, + * 0314 Oslo, Norway. + * + * This file is part of GoTools. + * + * GoTools is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * GoTools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with GoTools. If not, see + * . + * + * In accordance with Section 7(b) of the GNU Affero General Public + * License, a covered work must retain the producer line in every data + * file that is created or manipulated using GoTools. + * + * Other Usage + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial activities involving the GoTools library without + * disclosing the source code of your own applications. + * + * This file may be used in accordance with the terms contained in a + * written agreement between you and SINTEF ICT. + */ + +#ifndef _LRSURFACEPROPERTYSHEET_H +#define _LRSURFACEPROPERTYSHEET_H + + +#include "GoTools/viewlib/gvPropertySheet.h" +#include "GoTools/viewlib/ui_RectangularSurfacePropertySheet_form.h" +#include "GoTools/geometry/ParamSurface.h" +#include "GoTools/viewlib/vol_and_lr/gvLRSurfacePaintable.h" +#include "GoTools/viewlib/vol_and_lr/LRSurfaceTesselator.h" + +#include + +class gvData; +//class LRSurfaceTesselator; +//class gvLRSurfacePaintable; + +/** Documentation ... + etc + */ + +class LRSurfacePropertySheet : public QObject, public gvPropertySheet +{ + +Q_OBJECT + +public: + LRSurfacePropertySheet() + {} + + LRSurfacePropertySheet(Go::LRSurfaceTesselator* tess, + gvLRSurfacePaintable* pable, + shared_ptr& surf) + : tess_(tess), pable_(pable), form_(0), obs_(0), surf_(surf) + {} + + virtual ~LRSurfacePropertySheet(); + + virtual void createSheet(QWidget* parent, gvObserver* obs); + +public slots: + void apply(); + + +private: + Go::LRSurfaceTesselator* tess_; + gvLRSurfacePaintable* pable_; + Ui::RectangularSurfacePropertySheet_form* form_; + gvObserver* obs_; + shared_ptr surf_; +}; + + +#endif // _PARAMETRICSURFACEPROPERTYSHEET_H + diff --git a/viewlib/include/GoTools/viewlib/vol_and_lr/LRSurfaceTesselator.h b/viewlib/include/GoTools/viewlib/vol_and_lr/LRSurfaceTesselator.h new file mode 100644 index 000000000..56484fd03 --- /dev/null +++ b/viewlib/include/GoTools/viewlib/vol_and_lr/LRSurfaceTesselator.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT, + * Applied Mathematics, Norway. + * + * Contact information: E-mail: tor.dokken@sintef.no + * SINTEF ICT, Department of Applied Mathematics, + * P.O. Box 124 Blindern, + * 0314 Oslo, Norway. + * + * This file is part of GoTools. + * + * GoTools is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * GoTools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with GoTools. If not, see + * . + * + * In accordance with Section 7(b) of the GNU Affero General Public + * License, a covered work must retain the producer line in every data + * file that is created or manipulated using GoTools. + * + * Other Usage + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial activities involving the GoTools library without + * disclosing the source code of your own applications. + * + * This file may be used in accordance with the terms contained in a + * written agreement between you and SINTEF ICT. + */ + +#ifndef LRSURFACETESSELATOR_H +#define LRSURFACETESSELATOR_H + +#include "GoTools/tesselator/Tesselator.h" +#include "GoTools/tesselator/RegularMesh.h" +#include "GoTools/geometry/ParamSurface.h" +#include "GoTools/geometry/RectDomain.h" +#include "GoTools/utils/BoundingBox.h" +#include "GoTools/tesselator/GenericTriMesh.h" +#include +#include "GoTools/utils/config.h" + +namespace Go +{ + +/** LRSurfaceTesselator: create a mesh for an LR surface with a suitable + triangulation. Trimmed surfaces are currently not supported. +*/ + class Element2D; + class LRSplineSurface; + +class GO_API LRSurfaceTesselator : public Tesselator +{ + +public: + /// Constructor. Surface and mesh size are given. The mesh size relates to + /// the underlying surface in the case of bounded surfaces. + LRSurfaceTesselator(const ParamSurface& surf) + : surf_(surf), m_(20), n_(20) + { + mesh_ = shared_ptr(new GenericTriMesh(0,0,true,true)); + } + + virtual ~LRSurfaceTesselator(); + + virtual void tesselate(); + + // virtual GeneralMesh* getMesh() + // { + // return mesh_.get(); + // } + + /// Fetch the resulting mesh + shared_ptr getMesh() + { + return mesh_; + } + + /// Change mesh size + void changeRes(int n, int m); + + /// Fetch info about mesh size + void getRes(int& n, int& m) + { + m = m_; + n = n_; + } + +private: + const ParamSurface& surf_; + shared_ptr mesh_; + int m_; + int n_; + + void identifyNearTriangles(std::pair gap_par, + std::vector& vx_par, + std::vector& tri, + double del, + std::vector& tri_near, + std::vector& bb_near); + + void identifyJointTriangles(const Point& joint, + std::vector& vx_par, + std::vector& tri, + double del, + std::vector& tri_near, + std::vector& bb_near); + + void updateVertex(Point& par, const LRSplineSurface* lrsf, + RectDomain& dom, Point& vertex_par, + Point& vertex, Point& vertex_norm, + Point& vertex_tex, Element2D *elem=0); + + + double edgeDist(Point curr, Point pa, Point pb, Point& pp); + + bool isInsideTri(Point par, Point pa, Point pb, Point pc); + + void getNextTriangle(int start_ix1, int start_ix2, + Point par1, Point par2, + std::vector& tri_near, + std::vector& tri, + std::vector& vx_par, double pdel, + int& tri_ix1, int& tri_ix2, Point& pp, int& vx_ix, + int& next_ix1, int& next_ix2); + + int parConfiguration(const Point& param, + std::vector& vx_par, + std::vector& tri, + double del, + std::vector& tri_near, + int& ix1, int& ix2, + int edge[], Point& pp); + + void sortAndConnect(std::vector& vx_par, std::vector& vx_ix, + std::vector triangle); + + void jointSplitAtEdge(const Point& joint, + std::vector& pvx, + std::vector& vx_at, + double del, std::vector& par, + std::vector& par_at, + std::vector >& parquart); + + void writeGapTri(std::ofstream& oftg, std::vector& vertex, + unsigned int ix1, unsigned int ix2, + unsigned int ix3); +}; + +} // namespace Go + + + + +#endif // LRSURFACETESSELATOR_H + diff --git a/viewlib/include/GoTools/viewlib/vol_and_lr/gvApplicationVolAndLR.h b/viewlib/include/GoTools/viewlib/vol_and_lr/gvApplicationVolAndLR.h index 6802aa82f..920dbfa39 100644 --- a/viewlib/include/GoTools/viewlib/vol_and_lr/gvApplicationVolAndLR.h +++ b/viewlib/include/GoTools/viewlib/vol_and_lr/gvApplicationVolAndLR.h @@ -65,6 +65,10 @@ public slots: void translate_to_origin(); // All selected objects are translated by the center of their bounding box. void move_vertices_to_origin(); // All selected objects are translated by the center of their bounding box. + virtual void + changeSurfaceResolutions(int new_u_res, + int new_v_res); // Change resolution of + // all selected sfs. protected: void buildExtraGUI(); diff --git a/viewlib/include/GoTools/viewlib/vol_and_lr/gvLRSurfacePaintable.h b/viewlib/include/GoTools/viewlib/vol_and_lr/gvLRSurfacePaintable.h new file mode 100644 index 000000000..f03415091 --- /dev/null +++ b/viewlib/include/GoTools/viewlib/vol_and_lr/gvLRSurfacePaintable.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT, + * Applied Mathematics, Norway. + * + * Contact information: E-mail: tor.dokken@sintef.no + * SINTEF ICT, Department of Applied Mathematics, + * P.O. Box 124 Blindern, + * 0314 Oslo, Norway. + * + * This file is part of GoTools. + * + * GoTools is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * GoTools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with GoTools. If not, see + * . + * + * In accordance with Section 7(b) of the GNU Affero General Public + * License, a covered work must retain the producer line in every data + * file that is created or manipulated using GoTools. + * + * Other Usage + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial activities involving the GoTools library without + * disclosing the source code of your own applications. + * + * This file may be used in accordance with the terms contained in a + * written agreement between you and SINTEF ICT. + */ + +#ifndef _GVLRSURFACEPAINTABLE_H +#define _GVLRSURFACEPAINTABLE_H + +#ifdef _MSC_VER +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#endif +#ifdef __APPLE__ +#include +#else +#include +#endif +#include "GoTools/viewlib/gvPaintable.h" +#include "GoTools/tesselator/GenericTriMesh.h" + +typedef Go::GenericTriMesh genMesh; + +/** gvLRSurfacePaintable: OpenGL calls for a parametric surface. +*/ + +class gvLRSurfacePaintable : public gvPaintable +{ +public: + gvLRSurfacePaintable(genMesh& tri, + const gvColor& ncolor, + const gvColor& scolor, + int id) + : gvPaintable(ncolor, scolor, id), + tri_(tri) + {} + gvLRSurfacePaintable(genMesh& tri, + const gvColor& ncolor, + int id) + : gvPaintable(ncolor, id), + tri_(tri) + {} + + virtual ~gvLRSurfacePaintable(); + + virtual void paint(gvTexture* texture); + + +protected: + genMesh& tri_; + + + void createSurface(); + + void drawSurface(); + +}; + + +#endif // _GVPARAMETRICSURFACEPAINTABLE_H + diff --git a/viewlib/src/vol_and_lr/DataHandlerVolAndLR.C b/viewlib/src/vol_and_lr/DataHandlerVolAndLR.C index 0c763e66e..bd970045a 100644 --- a/viewlib/src/vol_and_lr/DataHandlerVolAndLR.C +++ b/viewlib/src/vol_and_lr/DataHandlerVolAndLR.C @@ -42,6 +42,9 @@ #include "GoTools/viewlib/vol_and_lr/DataHandlerVolAndLR.h" #include "GoTools/viewlib/vol_and_lr/RectangularVolumePropertySheet.h" #include "GoTools/viewlib/vol_and_lr/gvRectangularVolumePaintable.h" +#include "GoTools/viewlib/vol_and_lr/LRSurfaceTesselator.h" +#include "GoTools/viewlib/vol_and_lr/LRSurfacePropertySheet.h" +#include "GoTools/viewlib/vol_and_lr/gvLRSurfacePaintable.h" #include "GoTools/viewlib/gvRectangularSurfacePaintable.h" #include "GoTools/viewlib/RectangularSurfacePropertySheet.h" @@ -122,13 +125,14 @@ void DataHandlerVolAndLR::create(shared_ptr obj, } #endif - shared_ptr te(new RectangularSurfaceTesselator(sf)); - shared_ptr pa - (new gvRectangularSurfacePaintable(*(te->getMesh()), col, id)); + + shared_ptr te(new LRSurfaceTesselator(sf)); + shared_ptr pa + (new gvLRSurfacePaintable(*(te->getMesh()), col, id)); shared_ptr psf = dynamic_pointer_cast(obj); - shared_ptr ps(new RectangularSurfacePropertySheet(te.get(), pa.get(), - psf)); + shared_ptr ps(new LRSurfacePropertySheet(te.get(), pa.get(), + psf)); tesselator_ = te; paintable_ = pa; property_sheet_ = ps; diff --git a/viewlib/src/vol_and_lr/LRSurfacePropertySheet.C b/viewlib/src/vol_and_lr/LRSurfacePropertySheet.C new file mode 100644 index 000000000..bc45ddc93 --- /dev/null +++ b/viewlib/src/vol_and_lr/LRSurfacePropertySheet.C @@ -0,0 +1,108 @@ +/* + * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT, + * Applied Mathematics, Norway. + * + * Contact information: E-mail: tor.dokken@sintef.no + * SINTEF ICT, Department of Applied Mathematics, + * P.O. Box 124 Blindern, + * 0314 Oslo, Norway. + * + * This file is part of GoTools. + * + * GoTools is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * GoTools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with GoTools. If not, see + * . + * + * In accordance with Section 7(b) of the GNU Affero General Public + * License, a covered work must retain the producer line in every data + * file that is created or manipulated using GoTools. + * + * Other Usage + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial activities involving the GoTools library without + * disclosing the source code of your own applications. + * + * This file may be used in accordance with the terms contained in a + * written agreement between you and SINTEF ICT. + */ + +#include "GoTools/viewlib/vol_and_lr/LRSurfacePropertySheet.h" +#include "GoTools/viewlib/ui_RectangularSurfacePropertySheet_form.h" +#include "GoTools/viewlib/vol_and_lr/LRSurfaceTesselator.h" +#include "GoTools/viewlib/vol_and_lr/gvLRSurfacePaintable.h" + +#include "GoTools/viewlib/gvData.h" +#include "GoTools/viewlib/gvObserver.h" + +#include +#include +#include + +using namespace Ui; + + +//=========================================================================== +LRSurfacePropertySheet::~LRSurfacePropertySheet() +//=========================================================================== +{ + if (form_) + { + delete form_; + form_=NULL; + } +} + + +//=========================================================================== +void LRSurfacePropertySheet::createSheet(QWidget* parent, gvObserver* obs) +//=========================================================================== +{ + obs_ = obs; + form_ = new Ui::RectangularSurfacePropertySheet_form();//NULL); //parent); + + QWidget* w = new QWidget(); + form_->setupUi(w); + + w->resize(form_->box->size()); + + QObject::connect(form_->ApplyButton, SIGNAL(clicked()), + this, SLOT(apply())); + QObject::connect(form_->CloseButton, SIGNAL(clicked()), + w, SLOT(close())); + + form_->VisibleCheck->setChecked(pable_->visible()); + int ures, vres; + tess_->getRes(ures, vres); + form_->UresSlider->setValue(ures); + form_->VresSlider->setValue(vres); + + w->show(); +} + + +//=========================================================================== +void LRSurfacePropertySheet::apply() +//=========================================================================== +{ + int ures = form_->UresSlider->value(); + int vres = form_->VresSlider->value(); + if (form_->TurnOrientationCheck->isChecked()) { + surf_->turnOrientation(); + form_->TurnOrientationCheck->setChecked(false); + } + pable_->setVisible(form_->VisibleCheck->isChecked()); + tess_->changeRes(ures, vres); + obs_->observedChanged(); +} + diff --git a/viewlib/src/vol_and_lr/LRSurfaceTesselator.C b/viewlib/src/vol_and_lr/LRSurfaceTesselator.C new file mode 100644 index 000000000..af0615596 --- /dev/null +++ b/viewlib/src/vol_and_lr/LRSurfaceTesselator.C @@ -0,0 +1,1442 @@ +/* + * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT, + * Applied Mathematics, Norway. + * + * Contact information: E-mail: tor.dokken@sintef.no + * SINTEF ICT, Department of Applied Mathematics, + * P.O. Box 124 Blindern, + * 0314 Oslo, Norway. + * + * This file is part of GoTools. + * + * GoTools is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * GoTools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with GoTools. If not, see + * . + * + * In accordance with Section 7(b) of the GNU Affero General Public + * License, a covered work must retain the producer line in every data + * file that is created or manipulated using GoTools. + * + * Other Usage + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial activities involving the GoTools library without + * disclosing the source code of your own applications. + * + * This file may be used in accordance with the terms contained in a + * written agreement between you and SINTEF ICT. + */ + +#include "GoTools/viewlib/vol_and_lr/LRSurfaceTesselator.h" +#include "GoTools/lrsplines2D/LRSplineSurface.h" +#include "GoTools/geometry/LineCloud.h" +#include + +//#define DEBUG + +using std::vector; +using std::pair; + +using namespace Go; + + + +//=========================================================================== +LRSurfaceTesselator::~LRSurfaceTesselator() +//=========================================================================== +{ +} + + +//=========================================================================== +void LRSurfaceTesselator::changeRes(int n, int m) +//=========================================================================== +{ + if ((m != m_) || (n != n_)) { + m_ = m; + n_ = n; + tesselate(); + } +} + + +//=========================================================================== +void LRSurfaceTesselator::tesselate() +//=========================================================================== +{ + double eps = 1.0e-9; + const LRSplineSurface *lrsf = dynamic_cast(&surf_); + if (!lrsf) + return; // Not the right surface type + +#ifdef DEBUG + std::cout << "Tesselate LR surface" << std::endl; +#endif + RectDomain dom = lrsf->containingDomain(); + double umin = lrsf->startparam_u(); + double umax = lrsf->endparam_u(); + double vmin = lrsf->startparam_v(); + double vmax = lrsf->endparam_v(); + + // Construct mesh of element pointers + vector elements; + lrsf->constructElementMesh(elements); + + Mesh2D lrmesh = lrsf->mesh(); + int dim = lrsf->dimension(); + + // Get all knot values in the u-direction + const double* const uknots = lrmesh.knotsBegin(XFIXED); + const double* const uknots_end = lrmesh.knotsEnd(XFIXED); + int nmb_knots_u = lrmesh.numDistinctKnots(XFIXED); + const double* knotu; + + // Get all knot values in the v-direction + const double* const vknots = lrmesh.knotsBegin(YFIXED); + const double* const vknots_end = lrmesh.knotsEnd(YFIXED); + int nmb_knots_v = lrmesh.numDistinctKnots(YFIXED); + const double* knotv; + + double udel = (umax - umin)/(double)(n_-1); + double vdel = (vmax - vmin)/(double)(m_-1); + double upar = umin; + double vpar = vmin; + double tolu = std::max(1.0e-8, 1.0e-8*udel); + double tolv = std::max(1.0e-8, 1.0e-8*vdel); + double pdel = 0.2*std::min(udel, vdel); + + // Evaluate regular mesh + int ki, kj, kr, kh; + Point pos, normal, par; + vector vertex, vertex_norm, vertex_par, vertex_tex; + vertex.reserve(n_*m_); + vertex_par.reserve(n_*m_); + vertex_norm.reserve(n_*m_); + vertex_tex.reserve(n_*m_); + + double tdiv_u = (double)(n_-1); + double tdiv_v = (double)(m_-1); + for (kj=0, kr=0, knotv=vknots, ++knotv; knotv!=vknots_end; ++knotv, ++kj) + { + int lastv = (knotv+1 == vknots_end); + for (; krpoint(pos, upar, vpar, elem); + vertex.push_back(pos); + vertex_par.push_back(Point(upar, vpar)); + if (mesh_->useNormals()) + { + lrsf->normal(normal, upar, vpar, elem); + vertex_norm.push_back(normal); + } + if (mesh_->useTexCoords()) + vertex_tex.push_back(Point((double)kh/tdiv_u, (double)kr/tdiv_v)); + } + } + } + } + + // Define preliminary triangles + int num_tri = 2*(n_-1)*(m_-1); + vector tri; + tri.reserve(3*num_tri); + + for (kr=0; krdegree(XFIXED); + int deg2 = lrsf->degree(YFIXED); + int nknots1 = lrmesh.numDistinctKnots(XFIXED); + vector > gaps; + for (int ka=1; ka > x_segs = lrmesh.segments(XFIXED, ka, deg1+1); + for (size_t ki=0; ki > y_segs = lrmesh.segments(YFIXED, ka, deg2+1); + for (size_t ki=0; ki joints; + if (gaps.size() > 1) + { + // Split gaps at joints + for (size_t ki=0; ki + gaps[ki].second[1] - gaps[ki].first[1]) ? 0 : 1; + double a1 = std::min(gaps[ki].first[i1],gaps[ki].second[i1]); + double a2 = std::max(gaps[ki].first[i1],gaps[ki].second[i1]); + double b = gaps[ki].first[1-i1]; + for (size_t kj=ki+1; kj + gaps[kj].second[1] - gaps[kj].first[1]) ? 0 : 1; + if (i1 == j1) + continue; + double c1 = std::min(gaps[kj].first[j1],gaps[kj].second[j1]); + double c2 = std::max(gaps[kj].first[j1],gaps[kj].second[j1]); + double d = gaps[kj].first[1-j1]; + if (d > a1+eps && d < a2-eps && b > c1+eps && b < c2+eps) + { + double mid[2]; + mid[j1] = b; + mid[i1] = d; + Point mid_gap(mid[0], mid[1]); + gaps.push_back(std::make_pair(mid_gap, gaps[ki].second)); + gaps.push_back(std::make_pair(mid_gap, gaps[kj].second)); + gaps[ki].second = mid_gap; + gaps[kj].second = mid_gap; + joints.push_back(mid_gap); + } + } + } + } + + // Split triangulation at joints +#ifdef DEBUG + std::ofstream oftg("gap_tri.g2"); + std::ofstream oftg0("pre_joint.g2"); +#endif + vector pre_joint_vx; + for (size_t ki=0; ki tri_near; + vector bb; + identifyJointTriangles(joints[ki], vertex_par, tri, pdel, tri_near, bb); + + // Check configuration + int ix1 = -1, ix2 = -1; + int edge0[2]; + Point pp; + int config = parConfiguration(joints[ki], vertex_par, tri, pdel, tri_near, + ix1, ix2, edge0, pp); + + //size_t nvx = vertex_par.size(); + int ix = (config == 1) ? tri[ix1+ix2] : -1; + Element2D* elem[4]; + elem[0] = lrsf->coveringElement(joints[ki][0]-pdel, joints[ki][1]-pdel); + elem[1] = lrsf->coveringElement(joints[ki][0]+pdel, joints[ki][1]-pdel); + elem[2] = lrsf->coveringElement(joints[ki][0]-pdel, joints[ki][1]+pdel); + elem[3] = lrsf->coveringElement(joints[ki][0]+pdel, joints[ki][1]+pdel); + vector > joint_vxs; + joint_vxs.resize(4); + for (int kb=0; kb<4; ++kb) + { + if (ix >= 0) + { +#ifdef DEBUG + writeGapTri(oftg0, vertex, tri[ix1], tri[ix1+1], tri[ix1+2]); +#endif + updateVertex(joints[ki], lrsf, dom, vertex_par[ix], vertex[ix], + vertex_norm[ix], vertex_tex[ix], elem[kb]); + joint_vxs[kb].push_back(ix); + pre_joint_vx.push_back(ix); + ix = -1; +#ifdef DEBUG + writeGapTri(oftg0, vertex, tri[ix1], tri[ix1+1], tri[ix1+2]); +#endif + } + else + { + Point vx, vx_par, vx_norm, vx_tex; + updateVertex(joints[ki], lrsf, dom, vx_par, vx, vx_norm, vx_tex, elem[kb]); + vertex_par.push_back(vx_par); + vertex.push_back(vx); + if (mesh_->useNormals()) + vertex_norm.push_back(vx_norm); + if (mesh_->useTexCoords()) + vertex_tex.push_back(vx_tex); + size_t vx_ix = vertex_par.size() - 1; + joint_vxs[kb].push_back((int)vx_ix); + } + } + + vector edge; + vector ix_tri; + vector gap_vx; + if (config == 1) + { + // For all associated triangles, connect to appropriate vertex + ix = (int)tri[ix1 + ix2]; + vector pvx(2); + vector vx_at(2); + for (size_t kj=0; kj= 0) + { + ix_tri.push_back(ix1); + edge.push_back(edge0[0]); + gap_vx.push_back(-1); + } + if (ix2 >= 0) + { + ix_tri.push_back(ix2); + edge.push_back(edge0[1]); + gap_vx.push_back(-1); + } + } + + vector pvx(2); + vector vx_at(2); + vector par; + vector > quart; + vector gap_vx_ix; + for (size_t kj=0; kj par_at; + jointSplitAtEdge(joints[ki], pvx, vx_at, pdel, par, par_at, quart); + for (size_t kh=0; kh joints[ki][1]) + kx += 2; + auto it = std::find(joint_vxs[kx].begin(), joint_vxs[kx].end(), + (int)tri[idx+kc]); + if (it != joint_vxs[kh].end()) + joint_vxs[kx].push_back((int)tri[idx+kc]); + } + } + } + + for (size_t kr=0; kr= 0) + { + size_t kh; + for (kh=0; khcontains(par[kr][0], par[kr][1])) + { + double u = par[kr][0]; + double v = par[kr][1]; + if ((kx==0 || kx == 2) && fabs(elem2->umax()-u) < eps) + u -= pdel; + else if ((kx==1 || kx == 3) && fabs(u-elem2->umin()) < eps) + u += pdel; + if ((kx==0 || kx == 1) && fabs(elem2->vmax()-v) < eps) + v -= pdel; + else if ((kx==2 || kx == 3) && fabs(v-elem2->vmin()) < eps) + v += pdel; + elem2 = lrsf->coveringElement(u, v); + } + + int ix = gap_vx_ix[kr]; + if (kd == 0 && quart[kr].second < 0 && ix >= 0 && + (kx == 0 || kx == 3)) + { + // Update existing vertex + updateVertex(par[kr], lrsf, dom, vertex_par[ix], vertex[ix], + vertex_norm[ix], vertex_tex[ix], elem2); + joint_vxs[kx].push_back(ix); + pre_joint_vx.push_back(ix); + } + else + { + // New vertex at gap line + Point vx, vx_par, vx_norm, vx_tex; + updateVertex(par[kr], lrsf, dom, vx_par, vx, vx_norm, vx_tex, elem2); + vertex_par.push_back(vx_par); + vertex.push_back(vx); + if (mesh_->useNormals()) + vertex_norm.push_back(vx_norm); + if (mesh_->useTexCoords()) + vertex_tex.push_back(vx_tex); + size_t vx_ix = vertex_par.size() - 1; + joint_vxs[kx].push_back((int)vx_ix); + } + } + } + + + size_t kr = 0; + for (size_t kj=0; kj= 3) + { + vector triang(joint_vxs[kj].size()-2); + size_t kh=0; + for (; kr tmp(3*(triang.size()-kh)); + tri.insert(tri.end(), tmp.begin(), tmp.end()); + } + for (; kh + gaps[ki].second[1] - gaps[ki].first[1]) ? 1 : 0; + vector tri_near; + vector bb; + identifyNearTriangles(gaps[ki], vertex_par, tri, pdel, tri_near, bb); + + #ifdef DEBUG + std::cout << "Near triangles identified" << std::endl; +#endif + // Treat end points + Point curr; + int ka; + int end_ix[2]; + end_ix[0] = end_ix[1] = -1; + for (ka=0, curr=gaps[ki].first; ka<2; ++ka, curr=gaps[ki].second) + { + size_t kr; + for (kr=0; kr near2; + size_t kj; + for (kj=0; kj 1) + { +#ifdef DEBUG + std::cout << "Info to create new vertex" << std::endl; +#endif + // Make new vertex + Point vx, vx_par, vx_norm, vx_tex; + updateVertex(curr, lrsf, dom, vx_par, vx, vx_norm, vx_tex); + vertex_par.push_back(vx_par); + vertex.push_back(vx); + if (mesh_->useNormals()) + vertex_norm.push_back(vx_norm); + if (mesh_->useTexCoords()) + vertex_tex.push_back(vx_tex); + + size_t vx_ix = vertex_par.size() - 1; + end_ix[ka] = (int)vx_ix; + +#ifdef DEBUG + std::cout << "New vertex defined" << std::endl; +#endif + if (config == 2) + { + // Update triangle(s) + for (int kb=0, ix=ix1; kb<2; ++kb, ix=ix2) + { + if (ix < 0) + break; +#ifdef DEBUG + std::cout << "To update, new vertex at edge, ix = " << ix << std::endl; +#endif + tri_near.push_back(tri.size()); + if (edge[kb] == 1) + { + tri.push_back(tri[ix]); + tri.push_back(vx_ix); + tri.push_back(tri[ix+2]); + tri[ix] = vx_ix; + } + else if (edge[kb] == 2) + { + tri.push_back(tri[ix]); + tri.push_back(tri[ix+1]); + tri.push_back(vx_ix); + tri[ix+1] = vx_ix; + } + else + { + tri.push_back(tri[ix]); + tri.push_back(tri[ix+1]); + tri.push_back(vx_ix); + tri[ix] = vx_ix; + } +#ifdef DEBUG + writeGapTri(oftg, vertex, tri[ix], tri[ix+1], tri[ix+2]); + size_t kr=tri.size()-3; + writeGapTri(oftg, vertex, tri[kr], tri[kr+1], tri[kr+2]); +#endif + int stop_break = 1; + } + } + else if (config == 3) //(ix3 >= 0) + { +#ifdef DEBUG + std::cout << "To update, new vertex inside triangle" << std::endl; +#endif + // Split triangle containing the new vertex + tri_near.push_back(tri.size()); + tri.push_back(tri[ix1]); + tri.push_back(tri[ix1+1]); + tri.push_back(vx_ix); + tri_near.push_back(tri.size()); + tri.push_back(tri[ix1+1]); + tri.push_back(tri[ix1+2]); + tri.push_back(vx_ix); + tri[ix1+1] = vx_ix; + +#ifdef DEBUG + writeGapTri(oftg, vertex, tri[ix1], tri[ix1+1], tri[ix1+2]); + size_t kr=tri.size()-6; + writeGapTri(oftg, vertex, tri[kr], tri[kr+1], tri[kr+2]); + kr += 3; + writeGapTri(oftg, vertex, tri[kr], tri[kr+1], tri[kr+2]); +#endif + } +#ifdef DEBUG + std::cout << "Triangulation updated" << std::endl; +#endif + } + } + + #ifdef DEBUG + std::ofstream of("par_tri.g2"); + of << "410 1 0 0" << std::endl; + of << tri.size() << std::endl; + for (size_t kh=0; kh= 0) || (dir == 1 && end_ix[0] < 0)); + if (end_ix[0] < 0) + std::swap(end_ix[0], end_ix[1]); + int xt1 = end_ix[0], xt2 = end_ix[0]; + int tri_ix1 = -1, tri_ix2 = -1; + Point par1 = vertex_par[end_ix[0]]; + Point par2 = (par1.dist(gaps[ki].first) > par1.dist(gaps[ki].second)) ? + gaps[ki].first : gaps[ki].second; + Point pv(0.0, 0.0); + pv[dir] = pdel; + Point pp; + int vx_ix = -1; + int next1, next2; + getNextTriangle(end_ix[0], end_ix[0], par1, par2, tri_near, tri, + vertex_par, pdel, tri_ix1, tri_ix2, pp, vx_ix, + next1, next2); + while (tri_ix1 >= 0 && pp.dimension() == 2) + { + // Compute double vertices + Point v1 = Point(pp[1]-par1[1], par1[0]-pp[0]); + Point p3 = pp - pv; + Point p4 = pp + pv; + Element2D *elem1 = lrsf->coveringElement(p3[0], p3[1]); + Element2D *elem2 = lrsf->coveringElement(p4[0], p4[1]); + int xt3, xt4; + + bool update = true; + if (end_ix[1] >= 0 && end_ix[1] == vx_ix) + update = false; + else + { + for (size_t kh=0; kh= 0) + { + if (update) + updateVertex(pp, lrsf, dom, vertex_par[vx_ix], vertex[vx_ix], + vertex_norm[vx_ix], vertex_tex[vx_ix], elem1); + xt3 = vx_ix; + } + else + { + + Point vx1, vx_par1, vx_norm1, vx_tex1; + updateVertex(pp, lrsf, dom, vx_par1, vx1, vx_norm1, vx_tex1, elem1); + vertex_par.push_back(vx_par1); + vertex.push_back(vx1); + if (mesh_->useNormals()) + vertex_norm.push_back(vx_norm1); + if (mesh_->useTexCoords()) + vertex_tex.push_back(vx_tex1); + xt3 = (int)vertex_par.size() - 1; + } + + Point vx2, vx_par2, vx_norm2, vx_tex2; + updateVertex(pp, lrsf, dom, vx_par2, vx2, vx_norm2, vx_tex2, elem2); + vertex_par.push_back(vx_par2); + vertex.push_back(vx2); + if (mesh_->useNormals()) + vertex_norm.push_back(vx_norm2); + if (mesh_->useTexCoords()) + vertex_tex.push_back(vx_tex2); + xt4 = (int)vertex_par.size() - 1; + + // Identify extra triangles + vector ntri; + if (tri_ix2 > 0 && vx_ix >= 0) + { + for (size_t kh=0; kh pre_ix, post_ix, zero_ix, at_ix; + vector ppar(3); + for (int kc=0; kc<3; ++kc) + { + if (tri[tri_ix+kc] == xt1 || tri[tri_ix+kc] == xt2 || + tri[tri_ix+kc] == end_ix[1]) + zero_ix.push_back(kc); + else + { + ppar[kc] = vertex_par[tri[tri_ix+kc]]; + if (fabs(ppar[kc][dir] - pp[dir]) < eps) + at_ix.push_back(kc); + else if (ppar[kc][dir] < pp[dir]) + pre_ix.push_back(kc); + else + post_ix.push_back(kc); + } + } + + if (pre_ix.size() >= 1) + { + vector vx_ixs; + for (size_t kh=0; kh triang(pre_ix.size()); + size_t first = 0; + if (at_ix.size() > 0) + triang[first++] = &tri[tri_ix]; + if (first < triang.size()) + { + vector tmp(3*(triang.size()-first)); + tri.insert(tri.end(), tmp.begin(), tmp.end()); + for (size_t kh=first; kh= 1) + { + vector vx_ixs; + for (size_t kh=0; kh triang(post_ix.size()); + size_t first = 0; + triang[first++] = &tri[tri_ix]; + if (first < triang.size()) + { + vector tmp(3*(triang.size()-first)); + tri.insert(tri.end(), tmp.begin(), tmp.end()); + for (size_t kh=first; kh at_ix; + int npost = 0; + for (int kc=0; kc<3; ++kc) + { + Point ppar = vertex_par[tri[ntri[kh]+kc]]; + if (fabs(ppar[dir] - pp[dir]) < eps) + at_ix.push_back(kc); + else if (ppar[dir] > pp[dir]) + npost++; + } + + if (at_ix.size() == 1 && npost == 2) + tri[ntri[kh]+at_ix[0]] = xt4; + } + + par1 = vertex_par[xt3]; + int tri_ix3 = -1, tri_ix4 = -1, vx_ix2 = -1; + Point pq; + int next3, next4; + getNextTriangle(next1, next2, par1, par2, tri_near, tri, + vertex_par, pdel, + tri_ix3, tri_ix4, pq, vx_ix2, next3, next4); + + xt1 = xt3; + xt2 = xt4; + tri_ix1 = tri_ix3; + tri_ix2 = tri_ix4; + if (end_ix[1] >= 0 && end_ix[1] == vx_ix) + tri_ix1 = tri_ix2 = -1; + else + { + for (size_t kh=0; khresize((int)vertex.size(), (int)tri.size()/3); + for (size_t ki=0; kivertexArray()[ki*3+ka] = vertex[ki][ka]; + for (; ka<3; ++ka) + mesh_->vertexArray()[ki*3+ka] = 0.0; + mesh_->paramArray()[ki*2] = vertex_par[ki][0]; + mesh_->paramArray()[ki*2+1] = vertex_par[ki][1]; + if (mesh_->useNormals()) + { + for (ka=0; ka<3; ++ka) + mesh_->normalArray()[ki*3+ka] = vertex_norm[ki][ka]; + } + if (mesh_->useTexCoords()) + { + mesh_->texcoordArray()[ki*2] = vertex_tex[ki][0]; + mesh_->texcoordArray()[ki*2+1] = vertex_tex[ki][1]; + } + } + + for (size_t ki=0; kitriangleIndexArray()[ki] = tri[ki]; +} + + + +//=========================================================================== +void LRSurfaceTesselator::identifyJointTriangles(const Point& joint, + vector& vx_par, + vector& tri, + double del, + vector& tri_near, + vector& bb_near) +//=========================================================================== +{ + BoundingBox joint_bb(2); + joint_bb.addUnionWith(joint); + for (size_t ki=0; ki gap_par, + vector& vx_par, + vector& tri, + double del, + vector& tri_near, + vector& bb_near) +//=========================================================================== +{ + Point p1(std::min(gap_par.first[0],gap_par.second[0]), + std::min(gap_par.first[1],gap_par.second[1])); + Point p2(std::max(gap_par.first[0],gap_par.second[0]), + std::max(gap_par.first[1],gap_par.second[1])); + BoundingBox gap_bb(p1, p2); + for (size_t ki=0; kipoint(vertex, par[0], par[1], elem); + if (mesh_->useNormals()) + lrsf->normal(vertex_norm, par[0], par[1], elem); + if (mesh_->useTexCoords()) + { + double t1 = (par[0]-dom.umin())*(double)(n_-1)/(dom.umax()-dom.umin()); + double t2 = (par[1]-dom.vmin())*(double)(m_-1)/(dom.vmax()-dom.vmin()); + vertex_par = Point(t1, t2); + } + vertex_par = par; +} + +//=========================================================================== +double LRSurfaceTesselator::edgeDist(Point curr, Point pa, Point pb, Point& pp) +//=========================================================================== +{ + Point vec = pb - pa; + vec.normalize_checked(); + pp = pa + ((curr - pa)*vec)*vec; + return curr.dist(pp); +} + +//=========================================================================== +bool LRSurfaceTesselator::isInsideTri(Point par, Point pa, Point pb, Point pc) +//=========================================================================== +{ + Point v1 = pc - pa; + Point v2 = pb - pa; + Point vp = par - pa; + double v11 = v1*v1; + double v12 = v1*v2; + double v22 = v2*v2; + double v1p = v1*vp; + double v2p = v2*vp; + double det = v11*v22 - v12*v12; + double beta = (v1p*v22 - v12*v2p)/det; + double gamma = (v11*v2p - v1p*v12)/det; + return (beta > 0.0 && gamma > 0.0 && beta+gamma < 1.0); +} + +//=========================================================================== +void LRSurfaceTesselator::getNextTriangle(int start_ix1, int start_ix2, + Point par1, Point par2, + vector& tri_near, + vector& tri, + vector& vx_par, double pdel, + int& tri_ix1, int& tri_ix2, Point& pp, + int& vx_ix, int& next_ix1, + int& next_ix2) +//=========================================================================== + { + double eps = 1.0e-9; + vx_ix = -1; + + for (size_t kj=0; kj idvx; + for (size_t kr=0; kr<3; ++kr) + if (((int)tri[tri_near[kj]+kr] != start_ix1 && + (int)tri[tri_near[kj]+kr] != start_ix2) || start_ix1 != start_ix2) + idvx.push_back(tri[tri_near[kj]+kr]); + vector pvx(idvx.size()); + for (size_t kr=0; kr::max(); + int tmp_ix = -1; + Point pp1; + for (size_t kr=0; kr 0.0) + { + dd = dd0; + pp1 = pp0; + tmp_ix = (int)kr; + } + } + + if (dd < pdel) + { + pp = pp1; + vx_ix = idvx[tmp_ix]; + next_ix1 = next_ix2 = (int)idvx[tmp_ix]; + if (tri_ix1 < 0) + tri_ix1 = (int)tri_near[kj]; + else + tri_ix2 = (int)tri_near[kj]; + } + else + { + // Next gap point is not at an existing vertex + Point v1 = par2 - par1; + for (size_t kr=0; kr= 0.0 && t1 <= 1.0 && t2 >= 0.0 && t2 <= 1.0 && ppdist > pdel) + { + if (tri_ix1 < 0) + tri_ix1 = (int)tri_near[kj]; + else + tri_ix2 = (int)tri_near[kj]; + std::swap(tri_near[kj], tri_near[tri_near.size()-1]); + tri_near.pop_back(); + + pp = pvx[kr] + t2*v2; + next_ix1 = (int)idvx[kr]; + next_ix2 = (int)idvx[kh]; + break; + } + } + } + } + if (tri_ix1 >=0 && tri_ix2 >= 0) + break; + } + } + + + +//=========================================================================== +int LRSurfaceTesselator::parConfiguration(const Point& param, + vector& vx_par, + vector& tri, + double del, + vector& tri_near, + int& ix1, int& ix2, + int edge[], Point& pp) +//=========================================================================== + { + // Check distance to vertex + size_t kj; + for (kj=0; kj= 0 && ix2 >= 0) + { + double dmin = std::min(dd1, std::min(dd2, dd3)); + if (dmin < dist[0] && dist[0] > dist[1]) + ix1 = -1; + else if (dmin < dist[1]) + ix2 = -1; + } + if (ix1 < 0 || ix2 < 0) + pp = (dd1 < std::min(dd2, dd3)) ? pp1 : + ((dd2 < dd3) ? pp2 : pp3); + if (ix1 < 0) + { + ix1 = (int)tri_near[kr]; + edge[0] = (dd1 < std::min(dd2, dd3)) ? 1 : + ((dd2 < dd3) ? 3 : 2); + dist[0] = std::min(dd1, std::min(dd2, dd3)); + } + else if (ix2 < 0) + { + ix2 = (int)tri_near[kr]; + edge[1] = (dd1 < std::min(dd2, dd3)) ? 1 : + ((dd2 < dd3) ? 3 : 2); + dist[1] = std::min(dd1, std::min(dd2, dd3)); + } + } + + else if (isInsideTri(param, pa, pb, pc)) + ix3 = (int)tri_near[kr]; + } + + if (ix1 > 0) + return 2; + else if (ix3 > 0) + { + ix1 = ix3; + return 3; + } + + return 0; + } + +//=========================================================================== +void LRSurfaceTesselator::sortAndConnect(vector& vx_par, vector& vx_ix, + vector triangle) +//=========================================================================== +{ + if (vx_ix.size() < 3 || vx_ix.size() > 4) + return; // Wrong use + if ((vx_ix.size() == 3 && triangle.size() != 1) || + (vx_ix.size() == 4 && triangle.size() != 2)) + return; + + Point mid(0.0, 0.0); + double fac = 1.0/(double)vx_ix.size(); + for (size_t ki=0; ki angle(vx_ix.size()); + for (size_t ki=0; ki& pvx, + vector& at, + double del, vector& par, + vector& par_at, + vector >& parquart) +//=========================================================================== +{ + if (pvx.size() != 2 || at.size() != 2) + return; + + int quart[2]; + at[0] = at[1] = -1; + quart[0] = quart[1] = 0; + for (int kb=0; kb<2; kb++) + { + for (int kc=0; kc<2; ++kc) + { + if (fabs(pvx[kb][kc]-joint[kc]) < del) + at[kb] = kc; + if (pvx[kb][kc] > joint[kc]) + quart[kb] += ((kc == 1) ? 2 : 1); + } + } + + if (at[0] >= 0 && at[1] == at[0]); + else + { + double low[2], high[2]; + for (int kc=0; kc<2; ++kc) + { + low[kc]= std::min(pvx[0][kc],pvx[1][kc]); + high[kc] = std::max(pvx[0][kc],pvx[1][kc]); + } + for (int kc=0; kc<2; ++kc) + { + if (at[kc] >= 0) + { + int ix = at[kc]; + int jx = 1 - ix; + + Point ppar(2); + ppar[ix] = joint[ix]; + ppar[1-ix] = (at[kc] >= 0) ? pvx[kc][1-ix] : pvx[1-kc][1-ix]; + par.push_back(ppar); + double pval1 = (at[0] >= 0) ? std::min(pvx[0][0], pvx[1][0]) : + ppar[0]; + int qval = (low[kc] <= joint[kc]-del) ? 0 : ((kc == 0) ? 1 : 2); + double pval2 = (fabs(ppar[1-kc]-joint[1-kc]) < del) ? high[1-kc] : ppar[1-kc]; + if (pval2 >= joint[1-kc]+del) + qval += (kc == 0) ? 2 : 1; + + parquart.push_back(std::make_pair(qval, -1)); + par_at.push_back(kc); + } + else + { + if (low[kc] <= joint[kc]-del && high[kc] >= joint[kc]+del) + { + Point ppar(2); + ppar[kc] = joint[kc]; + double z = (joint[kc] - low[kc])/(high[kc] - joint[kc]); + ppar[1-kc] = low[1-kc] + z*(high[1-kc]-low[1-kc])/(1.0+z); + par.push_back(ppar); + int qval1 = (pvx[0][kc] < pvx[1][kc]) ? 0 : ((kc == 0) ? 1 : 2); + int qval2 = (qval1 > 0) ? 0 : ((kc == 0) ? 1 : 2); + if (at[1-kc] >= 0 && 0.5*(low[1-kc] + high[1-kc]) > joint[1-kc]) + { + qval1 += (kc == 0) ? 2 : 1; + qval2 += (kc == 0) ? 2 : 1; + } + else if (at[1-kc] < 0) + { + if (pvx[0][1-kc] > joint[1-kc]) + qval1 += (kc == 0) ? 2 : 1; + if (pvx[1][1-kc] > joint[1-kc]) + qval2 += (kc == 0) ? 2 : 1; + } + parquart.push_back(std::make_pair(qval1, qval2)); + par_at.push_back(-1); + } + } + } + + } +} + +//=========================================================================== +void LRSurfaceTesselator::writeGapTri(std::ofstream& oftg, vector& vertex, + unsigned int ix1, unsigned int ix2, + unsigned int ix3) +//=========================================================================== +{ + oftg << "410 1 0 4 155 50 50 255" << std::endl; + oftg << "3" << std::endl; + oftg << vertex[ix1] << " " << vertex[ix2] << std::endl; + oftg << vertex[ix2] << " " << vertex[ix3] << std::endl; + oftg << vertex[ix3] << " " << vertex[ix1] << std::endl; +} diff --git a/viewlib/src/vol_and_lr/gvApplicationVolAndLR.C b/viewlib/src/vol_and_lr/gvApplicationVolAndLR.C index 7751982b0..ec878b442 100644 --- a/viewlib/src/vol_and_lr/gvApplicationVolAndLR.C +++ b/viewlib/src/vol_and_lr/gvApplicationVolAndLR.C @@ -40,6 +40,7 @@ #include "GoTools/viewlib/vol_and_lr/gvApplicationVolAndLR.h" #include "GoTools/viewlib/gvView.h" +#include "GoTools/viewlib/vol_and_lr/LRSurfaceTesselator.h" #include "GoTools/geometry/SplineSurface.h" #include "GoTools/lrsplines2D/LRSplineSurface.h" #include "GoTools/geometry/BoundedSurface.h" @@ -301,5 +302,52 @@ GeneralMesh* gvApplicationVolAndLR::getMesh(int object_id) gen_mesh = reg_vol_tess->getMesh().get(); } + // 2D LR spline surface + LRSurfaceTesselator* lr_surf_tess = dynamic_cast(tess); + if (lr_surf_tess) + { + gen_mesh = lr_surf_tess->getMesh().get(); + } + + return gen_mesh; } + +//=========================================================================== +void gvApplicationVolAndLR::changeSurfaceResolutions(int new_u_res, int new_v_res) +//=========================================================================== +{ + for (int i = 0; i < data_.numObjects(); ++i) + if (data_.getSelectedStateObject(i)) { + RectangularSurfaceTesselator* tess = + dynamic_cast(data_.tesselator(i).get()); + int u_res = -1, v_res = -1; + if (tess != 0) { + tess->getRes(u_res, v_res); + if ((u_res != new_u_res) || (v_res != new_v_res)) { + tess->changeRes(new_u_res, new_v_res); + } + } else { + ParametricSurfaceTesselator* tess = + dynamic_cast(data_.tesselator(i).get()); + if (tess != 0) { + tess->getRes(u_res, v_res); + if ((u_res != new_u_res) || (v_res != new_v_res)) { + tess->changeRes(new_u_res, new_v_res); + } + } + else + { + LRSurfaceTesselator* tess = + dynamic_cast(data_.tesselator(i).get()); + if (tess != 0) { + tess->getRes(u_res, v_res); + if ((u_res != new_u_res) || (v_res != new_v_res)) { + tess->changeRes(new_u_res, new_v_res); + } + } + } + } + } +} + diff --git a/viewlib/src/vol_and_lr/gvLRSurfacePaintable.C b/viewlib/src/vol_and_lr/gvLRSurfacePaintable.C new file mode 100644 index 000000000..ef77c93ab --- /dev/null +++ b/viewlib/src/vol_and_lr/gvLRSurfacePaintable.C @@ -0,0 +1,132 @@ +/* + * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT, + * Applied Mathematics, Norway. + * + * Contact information: E-mail: tor.dokken@sintef.no + * SINTEF ICT, Department of Applied Mathematics, + * P.O. Box 124 Blindern, + * 0314 Oslo, Norway. + * + * This file is part of GoTools. + * + * GoTools is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * GoTools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with GoTools. If not, see + * . + * + * In accordance with Section 7(b) of the GNU Affero General Public + * License, a covered work must retain the producer line in every data + * file that is created or manipulated using GoTools. + * + * Other Usage + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial activities involving the GoTools library without + * disclosing the source code of your own applications. + * + * This file may be used in accordance with the terms contained in a + * written agreement between you and SINTEF ICT. + */ + +#include "GoTools/viewlib/vol_and_lr/gvLRSurfacePaintable.h" +// #include "GoTools/tesselator/RegularMesh.h" +// #include "GoTools/geometry/CurveLoop.h" +// #include "GoTools/geometry/SplineSurface.h" +// #include "GoTools/geometry/SplineCurve.h" +#include "GoTools/viewlib/gvTexture.h" + +#ifdef _MSC_VER +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#endif +#ifdef __APPLE__ +#include +#include +#else +#include +#include +#endif + + +using namespace Go; + + +//=========================================================================== +gvLRSurfacePaintable::~gvLRSurfacePaintable() +//=========================================================================== +{ +// gluDeleteNurbsRenderer(nurbSurface_); +} + +//=========================================================================== +void gvLRSurfacePaintable::paint(gvTexture* texture) +//=========================================================================== +{ + // Deal with visibility and selection state + if (!visible_) + return; + + // Draw surfaces a little bit behind other things + glEnable (GL_POLYGON_OFFSET_FILL); + glPolygonOffset (1.0, 1.0); + + if (selected_) { + glMaterialfv(GL_FRONT_AND_BACK, + GL_AMBIENT_AND_DIFFUSE, + selected_color_.rgba); + } else { + glMaterialfv(GL_FRONT_AND_BACK, + GL_AMBIENT_AND_DIFFUSE, + normal_color_.rgba); + } + GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 }; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 100.0); + + // Set up the vertex and normal arrays + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glVertexPointer(3, GL_DOUBLE, 0, tri_.vertexArray()); + // std::cout << tri_.vertexArray()[300] << ' ' + // << tri_.vertexArray()[301] << ' ' + // << tri_.vertexArray()[302] << std::endl; + // @@@ We should check for the use of normals and textures in tri_. + glNormalPointer(GL_DOUBLE, 0, tri_.normalArray()); + + bool use_textures = (texture != 0) && tri_.useTexCoords(); + if (use_textures) { + glEnable(GL_TEXTURE_2D); + texture->bind(); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_DOUBLE, 0, tri_.texcoordArray()); + } + + + // Draw the triangle strips + glDrawElements(GL_TRIANGLES, tri_.numTriangles()*3, + GL_UNSIGNED_INT, tri_.triangleIndexArray()); + + if (use_textures) { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisable(GL_POLYGON_OFFSET_FILL); +} + + + +