Revision: 76840
http://sourceforge.net/p/brlcad/code/76840
Author: starseeker
Date: 2020-08-19 01:05:00 +0000 (Wed, 19 Aug 2020)
Log Message:
-----------
Remove a few more old, unused files
Modified Paths:
--------------
brlcad/trunk/doc/legal/embedded/CMakeLists.txt
brlcad/trunk/src/libbrep/CMakeLists.txt
Removed Paths:
-------------
brlcad/trunk/doc/legal/embedded/nurbs_fit.txt
brlcad/trunk/src/libbrep/opennurbs_fit.cpp
brlcad/trunk/src/libbrep/opennurbs_fit.h
brlcad/trunk/src/libbrep/surface_tree_queue_tests.patch
Modified: brlcad/trunk/doc/legal/embedded/CMakeLists.txt
===================================================================
--- brlcad/trunk/doc/legal/embedded/CMakeLists.txt 2020-08-19 00:59:34 UTC
(rev 76839)
+++ brlcad/trunk/doc/legal/embedded/CMakeLists.txt 2020-08-19 01:05:00 UTC
(rev 76840)
@@ -37,7 +37,6 @@
mt19937ar.txt
naca.txt
normalize.txt
- nurbs_fit.txt
obr.txt
OpenNURBS.txt
osg.txt
Deleted: brlcad/trunk/doc/legal/embedded/nurbs_fit.txt
===================================================================
--- brlcad/trunk/doc/legal/embedded/nurbs_fit.txt 2020-08-19 00:59:34 UTC
(rev 76839)
+++ brlcad/trunk/doc/legal/embedded/nurbs_fit.txt 2020-08-19 01:05:00 UTC
(rev 76840)
@@ -1,32 +0,0 @@
-Copyright (c) 2011, Thomas Mörwald, Jonathan Balzer, Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of Thomas Mörwald or Jonathan Balzer nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-file:/src/libbrep/opennurbs_fit.cpp
-file:/src/libbrep/opennurbs_fit.h
Modified: brlcad/trunk/src/libbrep/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/libbrep/CMakeLists.txt 2020-08-19 00:59:34 UTC (rev
76839)
+++ brlcad/trunk/src/libbrep/CMakeLists.txt 2020-08-19 01:05:00 UTC (rev
76840)
@@ -46,7 +46,6 @@
shape_recognition/util.cpp
ssx_event.cpp
tools/util.cpp
- #opennurbs_fit.cpp
)
set(libbrep_ignored_files
@@ -55,12 +54,9 @@
cdt/cdt.h
cdt/mesh.h
cdt/RTree.h
- opennurbs_fit.h
- opennurbs_fit.cpp
PullbackCurve.h
shape_recognition/shape_recognition.h
shape_recognition/torus.cpp
- surface_tree_queue_tests.patch
)
CMAKEFILES(${libbrep_ignored_files})
Deleted: brlcad/trunk/src/libbrep/opennurbs_fit.cpp
===================================================================
--- brlcad/trunk/src/libbrep/opennurbs_fit.cpp 2020-08-19 00:59:34 UTC (rev
76839)
+++ brlcad/trunk/src/libbrep/opennurbs_fit.cpp 2020-08-19 01:05:00 UTC (rev
76840)
@@ -1,1557 +0,0 @@
-/** @file opennurbs_fit.cpp
- *
- * Extensions to the openNURBS library, based off of Thomas Mörwald's
- * surface fitting code in the Point Cloud Library (pcl). His code is
- # BSD licensed:
- *
- * Copyright (c) 2011, Thomas Mörwald, Jonathan Balzer, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Thomas Mörwald or Jonathan Balzer nor the names of
its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "common.h"
-
-#include <iostream>
-#include <stdexcept>
-#include <map>
-#include <algorithm>
-
-#include "opennurbs_fit.h"
-#include "vmath.h"
-
-using namespace on_fit;
-
-// ************************
-// * from nurbs_tools.cpp *
-// ************************
-
-void
-NurbsTools::downsample_random (const vector_vec3d &data1, vector_vec3d &data2,
unsigned size)
-{
- if (data1.size () <= size && size > 0) {
- data2 = data1;
- return;
- }
-
- unsigned s = data1.size ();
- data2.clear ();
-
- for (unsigned i = 0; i < size; i++) {
- unsigned rnd = unsigned (s * (double (rand ()) / RAND_MAX));
- data2.push_back (data1[rnd]);
- }
-}
-
-
-void
-NurbsTools::downsample_random (vector_vec3d &data, unsigned size)
-{
- if (data.size () <= size && size > 0)
- return;
-
- unsigned s = data.size ();
-
- vector_vec3d data_tmp;
-
- for (unsigned i = 0; i < size; i++) {
- unsigned rnd = unsigned ((s - 1) * (double (rand ()) / RAND_MAX));
- data_tmp.push_back (data[rnd]);
- }
-
- data = data_tmp;
-}
-
-
-unsigned
-NurbsTools::getClosestPoint (const ON_2dPoint &p, const vector_vec2d &data)
-{
- if (data.empty ())
- throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data
empty.\n");
-
- unsigned idx (0);
- double dist2 (DBL_MAX);
- for (unsigned i = 0; i < data.size (); i++) {
- ON_2dVector v = (data[i] - p);
- double d2 = ON_DotProduct(v, v); // Was the squaredNorm in Eigen
- if (d2 < dist2) {
- idx = i;
- dist2 = d2;
- }
- }
- return idx;
-}
-
-
-unsigned
-NurbsTools::getClosestPoint (const ON_3dPoint &p, const vector_vec3d &data)
-{
- if (data.empty ())
- throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data
empty.\n");
-
- unsigned idx (0);
- double dist2 (DBL_MAX);
- for (unsigned i = 0; i < data.size (); i++) {
- ON_3dVector v = (data[i] - p);
- double d2 = ON_DotProduct(v, v); // Was the squaredNorm in Eigen
- if (d2 < dist2) {
- idx = i;
- dist2 = d2;
- }
- }
- return idx;
-}
-
-
-unsigned
-NurbsTools::getClosestPoint (const ON_2dPoint &p, const ON_2dVector &dir,
const vector_vec2d &data,
- unsigned &idxcp)
-{
- if (data.empty ())
- throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data
empty.\n");
-
- unsigned idx (0);
- idxcp = 0;
- double dist2 (0.0);
- double dist2cp (DBL_MAX);
- for (unsigned i = 0; i < data.size (); i++) {
- ON_2dVector v = (data[i] - p);
- double d2 = ON_DotProduct(v, v);
-
- if (d2 < dist2cp) {
- idxcp = i;
- dist2cp = d2;
- }
-
- if (NEAR_ZERO(d2, SMALL_FASTF))
- return i;
-
- v.Unitize();
-
- double d1 = ON_DotProduct(dir, v);
- if (d1 / d2 > dist2) {
- idx = i;
- dist2 = d1 / d2;
- }
- }
- return idx;
-}
-
-
-ON_3dVector
-NurbsTools::computeMean (const vector_vec3d &data)
-{
- ON_3dVector u(0.0, 0.0, 0.0);
-
- unsigned s = data.size ();
- double ds = 1.0 / s;
-
- for (unsigned i = 0; i < s; i++)
- u += (data[i] * ds);
-
- return u;
-}
-
-
-ON_2dVector
-NurbsTools::computeMean (const vector_vec2d &data)
-{
- ON_2dVector u (0.0, 0.0);
-
- unsigned s = data.size ();
- double ds = 1.0 / s;
-
- for (unsigned i = 0; i < s; i++)
- u += (data[i] * ds);
-
- return u;
-}
-
-
-void
-NurbsTools::pca (const vector_vec3d &data, ON_3dVector &mean, Eigen::Matrix3d
&eigenvectors,
- Eigen::Vector3d &eigenvalues)
-{
- if (data.empty ()) {
- printf ("[NurbsTools::pca] Error, data is empty\n");
- abort ();
- }
-
- mean = computeMean (data);
-
- unsigned s = data.size ();
-
- ON_Matrix Q(3, s);
-
- for (unsigned i = 0; i < s; i++) {
- Q[0][i] = data[i].x - mean.x;
- Q[1][i] = data[i].y - mean.y;
- Q[2][i] = data[i].z - mean.z;
- }
-
- ON_Matrix Qt = Q;
- Qt.Transpose();
-
- ON_Matrix oC;
- oC.Multiply(Q, Qt);
-
- Eigen::Matrix3d C(3, 3);
- for (unsigned i = 0; i < 3; i++) {
- for (unsigned j = 0; j < 3; j++) {
- C(i, j) = oC[i][j];
- }
- }
-
- Eigen::SelfAdjointEigenSolver < Eigen::Matrix3d > eigensolver (C);
- if (eigensolver.info () != Eigen::Success) {
- printf ("[NurbsTools::pca] Can not find eigenvalues.\n");
- abort ();
- }
-
- for (int i = 0; i < 3; ++i) {
- eigenvalues (i) = eigensolver.eigenvalues () (2 - i);
- if (i == 2)
- eigenvectors.col (2) = eigenvectors.col (0).cross (eigenvectors.col
(1));
- else
- eigenvectors.col (i) = eigensolver.eigenvectors ().col (2 - i);
- }
-}
-
-
-// ******************************
-// * from nurbs_solve_eigen.cpp *
-// ******************************
-
-void
-NurbsSolve::assign (unsigned rows, unsigned cols, unsigned dims)
-{
- m_Ksparse.resize(rows, cols);
- //std::cout << "m_Ksparse(rows=" << rows << ", cols=" << cols << "\n";
- m_Ksparse.setZero();
- m_xeig = new ON_Matrix(cols, dims);
- m_xeig->Zero();
- //std::cout << "m_xeig(rows=" << cols << ", cols=" << dims << "\n";
- m_feig = new ON_Matrix(rows, dims);
- m_feig->Zero();
- //std::cout << "m_feig(rows=" << rows << ", cols=" << dims << "\n";
-}
-
-
-void
-NurbsSolve::K (unsigned i, unsigned j, double v)
-{
- m_Ksparse.insert(i, j) = v;
- //std::cout << "m_Ksparse count: " << m_Ksparse.nonZeros() << "\n";
- //std::cout << "m_Ksparse item(" << i << ", " << j << "):" <<
m_Ksparse.coeffRef(i, j) << "\n";
-}
-void
-NurbsSolve::x (unsigned i, unsigned j, double v)
-{
- (*m_xeig)[i][j] = v;
-}
-void
-NurbsSolve::f (unsigned i, unsigned j, double v)
-{
- (*m_feig)[i][j] = v;
-}
-
-
-double
-NurbsSolve::K (unsigned i, unsigned j)
-{
- return m_Ksparse.coeffRef(i, j);
-}
-double
-NurbsSolve::x (unsigned i, unsigned j)
-{
- return (*m_xeig)[i][j];
-}
-double
-NurbsSolve::f (unsigned i, unsigned j)
-{
- return (*m_feig)[i][j];
-}
-
-
-void
-NurbsSolve::resizeF (unsigned rows)
-{
- ON_Matrix *new_feig = new ON_Matrix(rows, (*m_feig).ColCount());
- for (int i = 0; i < (*m_feig).RowCount(); i++) {
- for (int j = 0; j < (*m_feig).ColCount(); j++) {
- (*new_feig)[i][j] = (*m_feig)[i][j];
- }
- }
- delete m_feig;
- m_feig = new_feig;
-}
-
-
-bool
-solveSparseLinearSystemLQ (Eigen::SparseMatrix<double>* A, Eigen::MatrixXd* b,
Eigen::MatrixXd* x)
-{
- Eigen::SparseMatrix<double> At(A->cols(), A->rows());
- Eigen::MatrixXd Atb(A->cols(), b->cols());
-
- At = A->transpose();
- Eigen::SparseMatrix<double> AtA = At * (*A);
- Atb = At * (*b);
-
- Eigen::SimplicialLDLT<Eigen::SparseMatrix<double> > solver;
- solver.compute(AtA);
- if (solver.info()!=Eigen::Success) {
- // decomposition failed
- std::cout << "decomposition failed\n";
- }
-
- (*x) = solver.solve(Atb);
-
- if (solver.info()!=Eigen::Success) {
- std::cout << "solver failed: " << solver.info() << "\n";
- return false;
- } else {
- return true;
- }
-}
-
-
-bool
-NurbsSolve::solve ()
-{
-
- clock_t time_start, time_end;
- time_start = clock ();
-
- Eigen::MatrixXd e_m_xeig = Eigen::MatrixXd::Zero ((*m_xeig).RowCount(),
(*m_xeig).ColCount());
- Eigen::MatrixXd e_m_feig = Eigen::MatrixXd::Zero ((*m_feig).RowCount(),
(*m_feig).ColCount());
-
- for (int i = 0; i < (*m_xeig).RowCount(); i++) {
- for (int j = 0; j < (*m_xeig).ColCount(); j++) {
- e_m_xeig (i, j) = (*m_xeig)[i][j];
- }
- }
- for (int i = 0; i < (*m_feig).RowCount(); i++) {
- for (int j = 0; j < (*m_feig).ColCount(); j++) {
- e_m_feig (i, j) = (*m_feig)[i][j];
- }
- }
-
- bool success = solveSparseLinearSystemLQ (&m_Ksparse, &e_m_feig,
&e_m_xeig);
- if (!success) {
- std::cout << "solver failed!\n";
- return false;
- }
-
- for (int i = 0; i < (*m_xeig).RowCount(); i++) {
- for (int j = 0; j < (*m_xeig).ColCount(); j++) {
- (*m_xeig)[i][j] = e_m_xeig (i, j);
- }
- }
-
- time_end = clock ();
-
- if (!m_quiet) {
- double solve_time = (double)(time_end - time_start) /
(double)(CLOCKS_PER_SEC);
- printf ("[NurbsSolve[Eigen::SimplicialLDLT]::solve_()] solution found!
(%f sec)\n", solve_time);
- }
-
- return true;
-}
-
-
-// ********************************
-// * from fitting_surface_pdm.cpp *
-// ********************************
-
-FittingSurface::FittingSurface (int order, NurbsDataSurface *in_m_data,
ON_3dVector z)
-{
- if (order < 2)
- throw std::runtime_error ("[FittingSurface::FittingSurface] Error order
too low (order<2).");
-
- ON::Begin ();
-
- this->m_data = in_m_data;
- m_nurbs = initNurbsPCA (order, m_data, z);
-
- this->init ();
-}
-
-
-FittingSurface::FittingSurface (NurbsDataSurface *in_m_data, const
ON_NurbsSurface &ns)
-{
- ON::Begin ();
-
- this->m_nurbs = ON_NurbsSurface (ns);
- this->m_data = in_m_data;
-
- this->init ();
-}
-
-
-void
-FittingSurface::refine (int dim)
-{
- std::vector<double> xi;
- std::vector<double> elements = getElementVector (m_nurbs, dim);
-
- for (unsigned i = 0; i < elements.size () - 1; i++)
- xi.push_back (elements[i] + 0.5 * (elements[i + 1] - elements[i]));
-
- for (unsigned i = 0; i < xi.size (); i++)
- m_nurbs.InsertKnot (dim, xi[i], 1);
-
- m_elementsU = getElementVector (m_nurbs, 0);
- m_elementsV = getElementVector (m_nurbs, 1);
- m_minU = m_elementsU[0];
- m_minV = m_elementsV[0];
- m_maxU = m_elementsU[m_elementsU.size () - 1];
- m_maxV = m_elementsV[m_elementsV.size () - 1];
-}
-
-
-void
-FittingSurface::assemble (Parameter param)
-{
- clock_t time_start, time_end;
- time_start = clock ();
-
- int nBnd = m_data->boundary.size ();
- int nInt = m_data->interior.size ();
- int nCurInt = param.regularisation_resU * param.regularisation_resV;
- int nCurBnd = 2 * param.regularisation_resU + 2 *
param.regularisation_resV;
- int nCageReg = (m_nurbs.m_cv_count[0] - 2) * (m_nurbs.m_cv_count[1] - 2);
- int nCageRegBnd = 2 * (m_nurbs.m_cv_count[0] - 1) + 2 *
(m_nurbs.m_cv_count[1] - 1);
-
- if (param.boundary_weight <= 0.0)
- nBnd = 0;
- if (param.interior_weight <= 0.0)
- nInt = 0;
- if (param.boundary_regularisation <= 0.0)
- nCurBnd = 0;
- if (param.interior_regularisation <= 0.0)
- nCurInt = 0;
- if (param.interior_smoothness <= 0.0)
- nCageReg = 0;
- if (param.boundary_smoothness <= 0.0)
- nCageRegBnd = 0;
-
- int ncp = m_nurbs.m_cv_count[0] * m_nurbs.m_cv_count[1];
- int nrows = nBnd + nInt + nCurInt + nCurBnd + nCageReg + nCageRegBnd;
-
- m_solver.assign (nrows, ncp, 3);
-
- unsigned row = 0;
-
- // boundary points should lie on edges of surface
- if (nBnd > 0)
- assembleBoundary (param.boundary_weight, row);
-
- // interior points should lie on surface
- if (nInt > 0)
- assembleInterior (param.interior_weight, row);
-
- // minimal curvature on surface
- if (nCurInt > 0) {
- if (m_nurbs.Order (0) < 3 || m_nurbs.Order (1) < 3)
- printf ("[FittingSurface::assemble] Error insufficient NURBS order
to add curvature regularisation.\n");
- else
- addInteriorRegularisation (2, param.regularisation_resU,
param.regularisation_resV,
- param.interior_regularisation /
param.regularisation_resU, row);
- }
-
- // minimal curvature on boundary
- if (nCurBnd > 0) {
- if (m_nurbs.Order (0) < 3 || m_nurbs.Order (1) < 3)
- printf ("[FittingSurface::assemble] Error insufficient NURBS order
to add curvature regularisation.\n");
- else
- addBoundaryRegularisation (2, param.regularisation_resU,
param.regularisation_resV,
- param.boundary_regularisation /
param.regularisation_resU, row);
- }
-
- // cage regularisation
- if (nCageReg > 0)
- addCageInteriorRegularisation (param.interior_smoothness, row);
-
- if (nCageRegBnd > 0) {
- addCageBoundaryRegularisation (param.boundary_smoothness, NORTH, row);
- addCageBoundaryRegularisation (param.boundary_smoothness, SOUTH, row);
- addCageBoundaryRegularisation (param.boundary_smoothness, WEST, row);
- addCageBoundaryRegularisation (param.boundary_smoothness, EAST, row);
- addCageCornerRegularisation (param.boundary_smoothness * 2.0, row);
- }
-
- time_end = clock ();
- if (!m_quiet) {
- double solve_time = (double)(time_end - time_start) /
(double)(CLOCKS_PER_SEC);
- printf ("[FittingSurface::assemble()] (assemble (%d, %d): %f sec)\n",
nrows, ncp, solve_time);
- }
-}
-
-
-void
-FittingSurface::init ()
-{
- m_elementsU = getElementVector (m_nurbs, 0);
- m_elementsV = getElementVector (m_nurbs, 1);
- m_minU = m_elementsU[0];
- m_minV = m_elementsV[0];
- m_maxU = m_elementsU[m_elementsU.size () - 1];
- m_maxV = m_elementsV[m_elementsV.size () - 1];
-
- in_max_steps = 100;
- in_accuracy = 1e-4;
-
- m_quiet = true;
-}
-
-
-void
-FittingSurface::solve (double damp)
-{
- if (m_solver.solve ())
- updateSurf (damp);
-}
-
-
-void
-FittingSurface::updateSurf (double damp)
-{
- int ncp = m_nurbs.m_cv_count[0] * m_nurbs.m_cv_count[1];
-
- for (int A = 0; A < ncp; A++) {
-
- int I = gl2gr (A);
- int J = gl2gc (A);
-
- ON_3dPoint cp_prev;
- m_nurbs.GetCV (I, J, cp_prev);
-
- ON_3dPoint cp;
- cp.x = cp_prev.x + damp * (m_solver.x (A, 0) - cp_prev.x);
- cp.y = cp_prev.y + damp * (m_solver.x (A, 1) - cp_prev.y);
- cp.z = cp_prev.z + damp * (m_solver.x (A, 2) - cp_prev.z);
-
- m_nurbs.SetCV (I, J, cp);
-
- }
-
-}
-
-
-void
-FittingSurface::setInvMapParams (unsigned max_steps, double accuracy)
-{
- this->in_max_steps = max_steps;
- this->in_accuracy = accuracy;
-}
-
-
-std::vector<double>
-FittingSurface::getElementVector (const ON_NurbsSurface &nurbs, int dim) // !
-{
- std::vector<double> result;
-
- int idx_min = 0;
- int idx_max = nurbs.KnotCount (dim) - 1;
- if (nurbs.IsClosed (dim)) {
- idx_min = nurbs.Order (dim) - 2;
- idx_max = nurbs.KnotCount (dim) - nurbs.Order (dim) + 1;
- }
-
- const double* knots = nurbs.Knot (dim);
-
- result.push_back (knots[idx_min]);
-
- //for (int E=(m_nurbs.Order(0)-2);
E<(m_nurbs.KnotCount(0)-m_nurbs.Order(0)+2); E++) {
- for (int E = idx_min + 1; E <= idx_max; E++) {
-
- if (!NEAR_EQUAL(knots[E], knots[E - 1], SMALL_FASTF)) // do not count
double knots
- result.push_back (knots[E]);
-
- }
-
- return result;
-}
-
-
-void
-FittingSurface::assembleInterior (double wInt, unsigned &row)
-{
- m_data->interior_line_start.clear ();
- m_data->interior_line_end.clear ();
- m_data->interior_error.clear ();
- m_data->interior_normals.clear ();
- unsigned nInt = m_data->interior.size ();
- for (unsigned p = 0; p < nInt; p++) {
- ON_3dVector &pcp = m_data->interior[p];
-
- // inverse mapping
- ON_2dVector params;
- ON_3dPoint pt;
- ON_3dVector tu, tv, n;
- double error;
- if (p < m_data->interior_param.size ()) {
- params = inverseMapping (m_nurbs, pcp, m_data->interior_param[p],
error, pt, tu, tv, in_max_steps, in_accuracy);
- m_data->interior_param[p] = params;
- } else {
- params = findClosestElementMidPoint (m_nurbs, pcp);
- params = inverseMapping (m_nurbs, pcp, params, error, pt, tu, tv,
in_max_steps, in_accuracy);
- m_data->interior_param.push_back (params);
- }
- m_data->interior_error.push_back (error);
-
- n = ON_CrossProduct(tu, tv);
- n.Unitize();
-
- m_data->interior_normals.push_back (n);
- m_data->interior_line_start.push_back (pcp);
- m_data->interior_line_end.push_back (pt);
-
- double w (wInt);
- if (p < m_data->interior_weight.size ())
- w = m_data->interior_weight[p];
-
- addPointConstraint (m_data->interior_param[p], m_data->interior[p], w,
row);
- }
-}
-
-
-void
-FittingSurface::assembleBoundary (double wBnd, unsigned &row)
-{
- m_data->boundary_line_start.clear ();
- m_data->boundary_line_end.clear ();
- m_data->boundary_error.clear ();
- m_data->boundary_normals.clear ();
- unsigned nBnd = m_data->boundary.size ();
- for (unsigned p = 0; p < nBnd; p++) {
- ON_3dVector &pcp = m_data->boundary[p];
-
- double error;
- ON_3dPoint pt;
- ON_3dVector tu, tv, n;
- ON_2dVector params = inverseMappingBoundary (m_nurbs, pcp, error, pt,
tu, tv, in_max_steps, in_accuracy);
- m_data->boundary_error.push_back (error);
-
- if (p < m_data->boundary_param.size ()) {
- m_data->boundary_param[p] = params;
- } else {
- m_data->boundary_param.push_back (params);
- }
-
- n = ON_CrossProduct(tu, tv);
- n.Unitize();
-
- m_data->boundary_normals.push_back (n);
- m_data->boundary_line_start.push_back (pcp);
- m_data->boundary_line_end.push_back (pt);
-
- double w (wBnd);
- if (p < m_data->boundary_weight.size ())
- w = m_data->boundary_weight[p];
-
- addPointConstraint (m_data->boundary_param[p], m_data->boundary[p], w,
row);
- }
-}
-
-
-ON_NurbsSurface
-FittingSurface::initNurbs4Corners (int order, ON_3dPoint ll, ON_3dPoint lr,
ON_3dPoint ur, ON_3dPoint ul)
-{
- std::map<int, std::map<int, ON_3dPoint> > cv_map;
-
- double dc = 1.0 / (order - 1);
-
- for (int i = 0; i < order; i++) {
- double di = dc * i;
- cv_map[i][0] = ll + (lr - ll) * di;
- cv_map[0][i] = ll + (ul - ll) * di;
- cv_map[i][order - 1] = ul + (ur - ul) * di;
- cv_map[order - 1][i] = lr + (ur - lr) * di;
- }
-
- for (int i = 1; i < order - 1; i++) {
- for (int j = 1; j < order - 1; j++) {
- ON_3dPoint du = cv_map[0][j] + (cv_map[order - 1][j] -
cv_map[0][j]) * dc * i;
- ON_3dPoint dv = cv_map[i][0] + (cv_map[i][order - 1] -
cv_map[i][0]) * dc * j;
- cv_map[i][j] = du * 0.5 + dv * 0.5;
- }
- }
-
- ON_NurbsSurface nurbs (3, false, order, order, order, order);
- nurbs.MakeClampedUniformKnotVector (0, 1.0);
- nurbs.MakeClampedUniformKnotVector (1, 1.0);
-
- for (int i = 0; i < order; i++) {
- for (int j = 0; j < order; j++) {
- nurbs.SetCV (i, j, cv_map[i][j]);
- }
- }
- return nurbs;
-}
-
-
-ON_NurbsSurface
-FittingSurface::initNurbsPCA (int order, NurbsDataSurface *m_data, ON_3dVector
z)
-{
- ON_3dVector mean;
- Eigen::Matrix3d eigenvectors;
- Eigen::Vector3d eigenvalues;
-
- unsigned s = m_data->interior.size ();
-
- NurbsTools::pca (m_data->interior, mean, eigenvectors, eigenvalues);
-
- m_data->mean = mean;
- //m_data->eigenvectors = (*eigenvectors);
-
- bool flip (false);
- Eigen::Vector3d ez(z[0], z[1], z[2]);
- if (eigenvectors.col (2).dot (ez) < 0.0)
- flip = true;
-
- eigenvalues = eigenvalues / s; // seems that the eigenvalues are dependent
on the number of points (???)
-
- ON_3dVector sigma(sqrt(eigenvalues[0]), sqrt(eigenvalues[1]),
sqrt(eigenvalues[2]));
-
- ON_NurbsSurface nurbs (3, false, order, order, order, order);
- nurbs.MakeClampedUniformKnotVector (0, 1.0);
- nurbs.MakeClampedUniformKnotVector (1, 1.0);
-
- // +- 2 sigma -> 95, 45 % aller Messwerte
- double dcu = (4.0 * sigma[0]) / (nurbs.Order (0) - 1);
- double dcv = (4.0 * sigma[1]) / (nurbs.Order (1) - 1);
-
- ON_3dVector cv_t, cv;
- Eigen::Vector3d ecv_t, ecv;
- Eigen::Vector3d emean(mean[0], mean[1], mean[2]);
- for (int i = 0; i < nurbs.Order (0); i++) {
- for (int j = 0; j < nurbs.Order (1); j++) {
- cv[0] = -2.0 * sigma[0] + dcu * i;
- cv[1] = -2.0 * sigma[1] + dcv * j;
- cv[2] = 0.0;
- ecv (0) = -2.0 * sigma[0] + dcu * i;
- ecv (1) = -2.0 * sigma[1] + dcv * j;
- ecv (2) = 0.0;
- ecv_t = eigenvectors * ecv + emean;
- cv_t[0] = ecv_t (0);
- cv_t[1] = ecv_t (1);
- cv_t[2] = ecv_t (2);
- if (flip)
- nurbs.SetCV (nurbs.Order (0) - 1 - i, j, ON_3dPoint (cv_t[0],
cv_t[1], cv_t[2]));
- else
- nurbs.SetCV (i, j, ON_3dPoint (cv_t[0], cv_t[1], cv_t[2]));
- }
- }
- return nurbs;
-}
-
-
-ON_NurbsSurface
-FittingSurface::initNurbsPCABoundingBox (int order, NurbsDataSurface *m_data,
ON_3dVector z)
-{
- ON_3dVector mean;
- Eigen::Matrix3d eigenvectors;
- Eigen::Vector3d eigenvalues;
-
- unsigned s = m_data->interior.size ();
- m_data->interior_param.clear ();
-
- NurbsTools::pca (m_data->interior, mean, eigenvectors, eigenvalues);
-
- m_data->mean = mean;
- //m_data->eigenvectors = (*eigenvectors);
-
- bool flip (false);
- Eigen::Vector3d ez(z[0], z[1], z[2]);
- if (eigenvectors.col (2).dot (ez) < 0.0)
- flip = true;
-
- eigenvalues = eigenvalues / s; // seems that the eigenvalues are dependent
on the number of points (???)
- Eigen::Matrix3d eigenvectors_inv = eigenvectors.inverse ();
-
- ON_3dVector v_max(0.0, 0.0, 0.0);
- ON_3dVector v_min(DBL_MAX, DBL_MAX, DBL_MAX);
- Eigen::Vector3d emean(mean[0], mean[1], mean[2]);
- for (unsigned i = 0; i < s; i++) {
- Eigen::Vector3d eint(m_data->interior[i][0], m_data->interior[i][1],
m_data->interior[i][2]);
- Eigen::Vector3d ep = eigenvectors_inv * (eint - emean);
- ON_3dPoint p(ep (0), ep (1), ep(2));
- m_data->interior_param.push_back (ON_2dPoint(p[0], p[1]));
-
- V_MAX(v_max[0], p[0]);
- V_MAX(v_max[1], p[1]);
- V_MAX(v_max[2], p[2]);
-
- V_MIN(v_min[0], p[0]);
- V_MIN(v_min[1], p[1]);
- V_MIN(v_min[2], p[2]);
- }
-
- for (unsigned i = 0; i < s; i++) {
- ON_2dVector &p = m_data->interior_param[i];
- if (v_max[0] > v_min[0] && v_max[0] > v_min[0]) {
- p[0] = (p[0] - v_min[0]) / (v_max[0] - v_min[0]);
- p[1] = (p[1] - v_min[1]) / (v_max[1] - v_min[1]);
- } else {
- throw std::runtime_error ("[NurbsTools::initNurbsPCABoundingBox]
Error: v_max <= v_min");
- }
- }
-
- ON_NurbsSurface nurbs (3, false, order, order, order, order);
-
- nurbs.MakeClampedUniformKnotVector (0, 1.0);
- nurbs.MakeClampedUniformKnotVector (1, 1.0);
-
- double dcu = (v_max[0] - v_min[0]) / (nurbs.Order (0) - 1);
- double dcv = (v_max[1] - v_min[1]) / (nurbs.Order (1) - 1);
-
- ON_3dPoint cv_t, cv;
- Eigen::Vector3d ecv_t2, ecv2;
- Eigen::Vector3d emean2(mean[0], mean[1], mean[2]);
- for (int i = 0; i < nurbs.Order (0); i++) {
- for (int j = 0; j < nurbs.Order (1); j++) {
- cv[0] = v_min[0] + dcu * i;
- cv[1] = v_min[1] + dcv * j;
- cv[2] = 0.0;
- ecv2 (0) = cv[0];
- ecv2 (1) = cv[1];
- ecv2 (2) = cv[2];
- ecv_t2 = eigenvectors * ecv2 + emean2;
- if (flip)
- nurbs.SetCV (nurbs.Order (0) - 1 - i, j, cv_t);
- else
- nurbs.SetCV (i, j, cv_t);
- }
- }
- return nurbs;
-}
-
-
-void
-FittingSurface::addPointConstraint (const ON_2dVector ¶ms, const
ON_3dPoint &point, double weight,
- unsigned &row)
-{
- double *N0 = new double[m_nurbs.Order (0) * m_nurbs.Order (0)];
- double *N1 = new double[m_nurbs.Order (1) * m_nurbs.Order (1)];
-
- int E = ON_NurbsSpanIndex (m_nurbs.m_order[0], m_nurbs.m_cv_count[0],
m_nurbs.m_knot[0], params[0], 0, 0);
- int F = ON_NurbsSpanIndex (m_nurbs.m_order[1], m_nurbs.m_cv_count[1],
m_nurbs.m_knot[1], params[1], 0, 0);
-
- ON_EvaluateNurbsBasis (m_nurbs.Order (0), m_nurbs.m_knot[0] + E,
params[0], N0);
- ON_EvaluateNurbsBasis (m_nurbs.Order (1), m_nurbs.m_knot[1] + F,
params[1], N1);
-
- m_solver.f (row, 0, point[0] * weight);
- m_solver.f (row, 1, point[1] * weight);
- m_solver.f (row, 2, point[2] * weight);
-
- for (int i = 0; i < m_nurbs.Order (0); i++) {
-
- for (int j = 0; j < m_nurbs.Order (1); j++) {
-
- m_solver.K (row, lrc2gl (E, F, i, j), weight * N0[i] * N1[j]);
-
- } // j
-
- } // i
-
- row++;
-
- delete [] N0;
- delete [] N1;
-
-}
-
-
-void
-FittingSurface::addCageInteriorRegularisation (double weight, unsigned &row)
-{
- for (int i = 1; i < (m_nurbs.m_cv_count[0] - 1); i++) {
- for (int j = 1; j < (m_nurbs.m_cv_count[1] - 1); j++) {
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- m_solver.K (row, grc2gl (i + 0, j + 0), -4.0 * weight);
- m_solver.K (row, grc2gl (i + 0, j - 1), 1.0 * weight);
- m_solver.K (row, grc2gl (i + 0, j + 1), 1.0 * weight);
- m_solver.K (row, grc2gl (i - 1, j + 0), 1.0 * weight);
- m_solver.K (row, grc2gl (i + 1, j + 0), 1.0 * weight);
-
- row++;
- }
- }
-}
-
-
-void
-FittingSurface::addCageBoundaryRegularisation (double weight, int side,
unsigned &row)
-{
- int i = 0;
- int j = 0;
-
- switch (side) {
- case SOUTH:
- j = m_nurbs.m_cv_count[1] - 1;
- case NORTH:
- for (i = 1; i < (m_nurbs.m_cv_count[0] - 1); i++) {
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- m_solver.K (row, grc2gl (i + 0, j), -2.0 * weight);
- m_solver.K (row, grc2gl (i - 1, j), 1.0 * weight);
- m_solver.K (row, grc2gl (i + 1, j), 1.0 * weight);
-
- row++;
- }
- break;
-
- case EAST:
- i = m_nurbs.m_cv_count[0] - 1;
- case WEST:
- for (j = 1; j < (m_nurbs.m_cv_count[1] - 1); j++) {
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- m_solver.K (row, grc2gl (i, j + 0), -2.0 * weight);
- m_solver.K (row, grc2gl (i, j - 1), 1.0 * weight);
- m_solver.K (row, grc2gl (i, j + 1), 1.0 * weight);
-
- row++;
- }
- break;
- }
-}
-
-
-void
-FittingSurface::addCageCornerRegularisation (double weight, unsigned &row)
-{
- { // NORTH-WEST
- int i = 0;
- int j = 0;
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- m_solver.K (row, grc2gl (i + 0, j + 0), -2.0 * weight);
- m_solver.K (row, grc2gl (i + 1, j + 0), 1.0 * weight);
- m_solver.K (row, grc2gl (i + 0, j + 1), 1.0 * weight);
-
- row++;
- }
-
- { // NORTH-EAST
- int i = m_nurbs.m_cv_count[0] - 1;
- int j = 0;
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- m_solver.K (row, grc2gl (i + 0, j + 0), -2.0 * weight);
- m_solver.K (row, grc2gl (i - 1, j + 0), 1.0 * weight);
- m_solver.K (row, grc2gl (i + 0, j + 1), 1.0 * weight);
-
- row++;
- }
-
- { // SOUTH-EAST
- int i = m_nurbs.m_cv_count[0] - 1;
- int j = m_nurbs.m_cv_count[1] - 1;
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- m_solver.K (row, grc2gl (i + 0, j + 0), -2.0 * weight);
- m_solver.K (row, grc2gl (i - 1, j + 0), 1.0 * weight);
- m_solver.K (row, grc2gl (i + 0, j - 1), 1.0 * weight);
-
- row++;
- }
-
- { // SOUTH-WEST
- int i = 0;
- int j = m_nurbs.m_cv_count[1] - 1;
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- m_solver.K (row, grc2gl (i + 0, j + 0), -2.0 * weight);
- m_solver.K (row, grc2gl (i + 1, j + 0), 1.0 * weight);
- m_solver.K (row, grc2gl (i + 0, j - 1), 1.0 * weight);
-
- row++;
- }
-
-}
-
-
-void
-FittingSurface::addInteriorRegularisation (int order, int resU, int resV,
double UNUSED(weight), unsigned &row)
-{
- double *N0 = new double[m_nurbs.Order (0) * m_nurbs.Order (0)];
- double *N1 = new double[m_nurbs.Order (1) * m_nurbs.Order (1)];
-
- double dU = (m_maxU - m_minU) / resU;
- double dV = (m_maxV - m_minV) / resV;
-
- for (int u = 0; u < resU; u++) {
- for (int v = 0; v < resV; v++) {
-
- ON_2dPoint params;
- params[0] = m_minU + u * dU + 0.5 * dU;
- params[1] = m_minV + v * dV + 0.5 * dV;
-
- // printf("%f %f, %f %f\n", m_minU, dU, params(0),
params(1));
-
- int E = ON_NurbsSpanIndex (m_nurbs.m_order[0],
m_nurbs.m_cv_count[0], m_nurbs.m_knot[0], params[0], 0, 0);
- int F = ON_NurbsSpanIndex (m_nurbs.m_order[1],
m_nurbs.m_cv_count[1], m_nurbs.m_knot[1], params[1], 0, 0);
-
- ON_EvaluateNurbsBasis (m_nurbs.Order (0), m_nurbs.m_knot[0] + E,
params[0], N0);
- ON_EvaluateNurbsBasis (m_nurbs.Order (1), m_nurbs.m_knot[1] + F,
params[1], N1);
- ON_EvaluateNurbsBasisDerivatives (m_nurbs.Order (0),
m_nurbs.m_knot[0] + E, order, N0); // derivative order?
- ON_EvaluateNurbsBasisDerivatives (m_nurbs.Order (1),
m_nurbs.m_knot[1] + F, order, N1);
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- for (int i = 0; i < m_nurbs.Order (0); i++) {
-
- for (int j = 0; j < m_nurbs.Order (1); j++) {
-
- //m_solver.K (row, lrc2gl (E, F, i, j),
- // weight * (N0[order * m_nurbs.Order (0) + i] *
N1[j] + N0[i] * N1[order * m_nurbs.Order (1) + j]));
-
- } // i
-
- } // j
-
- row++;
-
- }
- }
- delete [] N0;
- delete [] N1;
-}
-
-
-void
-FittingSurface::addBoundaryRegularisation (int order, int resU, int resV,
double weight, unsigned &row)
-{
- double *N0 = new double[m_nurbs.Order (0) * m_nurbs.Order (0)];
- double *N1 = new double[m_nurbs.Order (1) * m_nurbs.Order (1)];
-
- double dU = (m_maxU - m_minU) / resU;
- double dV = (m_maxV - m_minV) / resV;
-
- for (int u = 0; u < resU; u++) {
-
- ON_2dPoint params;
- params[0] = m_minU + u * dU + 0.5 * dU;
- params[1] = m_minV;
-
- int E = ON_NurbsSpanIndex (m_nurbs.m_order[0], m_nurbs.m_cv_count[0],
m_nurbs.m_knot[0], params[0], 0, 0);
- int F = ON_NurbsSpanIndex (m_nurbs.m_order[1], m_nurbs.m_cv_count[1],
m_nurbs.m_knot[1], params[1], 0, 0);
-
- ON_EvaluateNurbsBasis (m_nurbs.Order (0), m_nurbs.m_knot[0] + E,
params[0], N0);
- ON_EvaluateNurbsBasis (m_nurbs.Order (1), m_nurbs.m_knot[1] + F,
params[1], N1);
- ON_EvaluateNurbsBasisDerivatives (m_nurbs.Order (0), m_nurbs.m_knot[0]
+ E, order, N0); // derivative order?
- ON_EvaluateNurbsBasisDerivatives (m_nurbs.Order (1), m_nurbs.m_knot[1]
+ F, order, N1);
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- for (int i = 0; i < m_nurbs.Order (0); i++) {
-
- for (int j = 0; j < m_nurbs.Order (1); j++) {
-
- m_solver.K (row, lrc2gl (E, F, i, j),
- weight * (N0[order * m_nurbs.Order (0) + i] * N1[j]
+ N0[i] * N1[order * m_nurbs.Order (1) + j]));
-
- } // i
-
- } // j
-
- row++;
-
- }
-
- for (int u = 0; u < resU; u++) {
-
- ON_2dPoint params;
- params[0] = m_minU + u * dU + 0.5 * dU;
- params[1] = m_maxV;
-
- int E = ON_NurbsSpanIndex (m_nurbs.m_order[0], m_nurbs.m_cv_count[0],
m_nurbs.m_knot[0], params[0], 0, 0);
- int F = ON_NurbsSpanIndex (m_nurbs.m_order[1], m_nurbs.m_cv_count[1],
m_nurbs.m_knot[1], params[1], 0, 0);
-
- ON_EvaluateNurbsBasis (m_nurbs.Order (0), m_nurbs.m_knot[0] + E,
params[0], N0);
- ON_EvaluateNurbsBasis (m_nurbs.Order (1), m_nurbs.m_knot[1] + F,
params[1], N1);
- ON_EvaluateNurbsBasisDerivatives (m_nurbs.Order (0), m_nurbs.m_knot[0]
+ E, order, N0); // derivative order?
- ON_EvaluateNurbsBasisDerivatives (m_nurbs.Order (1), m_nurbs.m_knot[1]
+ F, order, N1);
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- for (int i = 0; i < m_nurbs.Order (0); i++) {
-
- for (int j = 0; j < m_nurbs.Order (1); j++) {
-
- m_solver.K (row, lrc2gl (E, F, i, j),
- weight * (N0[order * m_nurbs.Order (0) + i] * N1[j]
+ N0[i] * N1[order * m_nurbs.Order (1) + j]));
-
- } // i
-
- } // j
-
- row++;
-
- }
-
- for (int v = 0; v < resV; v++) {
-
- ON_2dPoint params;
- params[0] = m_minU;
- params[1] = m_minV + v * dV + 0.5 * dV;
-
- int E = ON_NurbsSpanIndex (m_nurbs.m_order[0], m_nurbs.m_cv_count[0],
m_nurbs.m_knot[0], params[0], 0, 0);
- int F = ON_NurbsSpanIndex (m_nurbs.m_order[1], m_nurbs.m_cv_count[1],
m_nurbs.m_knot[1], params[1], 0, 0);
-
- ON_EvaluateNurbsBasis (m_nurbs.Order (0), m_nurbs.m_knot[0] + E,
params[0], N0);
- ON_EvaluateNurbsBasis (m_nurbs.Order (1), m_nurbs.m_knot[1] + F,
params[1], N1);
- ON_EvaluateNurbsBasisDerivatives (m_nurbs.Order (0), m_nurbs.m_knot[0]
+ E, order, N0); // derivative order?
- ON_EvaluateNurbsBasisDerivatives (m_nurbs.Order (1), m_nurbs.m_knot[1]
+ F, order, N1);
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- for (int i = 0; i < m_nurbs.Order (0); i++) {
-
- for (int j = 0; j < m_nurbs.Order (1); j++) {
-
- m_solver.K (row, lrc2gl (E, F, i, j),
- weight * (N0[order * m_nurbs.Order (0) + i] * N1[j]
+ N0[i] * N1[order * m_nurbs.Order (1) + j]));
-
- } // i
-
- } // j
-
- row++;
-
- }
-
- for (int v = 0; v < resV; v++) {
-
- ON_2dPoint params;
- params[0] = m_maxU;
- params[1] = m_minV + v * dV + 0.5 * dV;
-
- int E = ON_NurbsSpanIndex (m_nurbs.m_order[0], m_nurbs.m_cv_count[0],
m_nurbs.m_knot[0], params[0], 0, 0);
- int F = ON_NurbsSpanIndex (m_nurbs.m_order[1], m_nurbs.m_cv_count[1],
m_nurbs.m_knot[1], params[1], 0, 0);
-
- ON_EvaluateNurbsBasis (m_nurbs.Order (0), m_nurbs.m_knot[0] + E,
params[0], N0);
- ON_EvaluateNurbsBasis (m_nurbs.Order (1), m_nurbs.m_knot[1] + F,
params[1], N1);
- ON_EvaluateNurbsBasisDerivatives (m_nurbs.Order (0), m_nurbs.m_knot[0]
+ E, order, N0); // derivative order?
- ON_EvaluateNurbsBasisDerivatives (m_nurbs.Order (1), m_nurbs.m_knot[1]
+ F, order, N1);
-
- m_solver.f (row, 0, 0.0);
- m_solver.f (row, 1, 0.0);
- m_solver.f (row, 2, 0.0);
-
- for (int i = 0; i < m_nurbs.Order (0); i++) {
-
- for (int j = 0; j < m_nurbs.Order (1); j++) {
-
- m_solver.K (row, lrc2gl (E, F, i, j),
- weight * (N0[order * m_nurbs.Order (0) + i] * N1[j]
+ N0[i] * N1[order * m_nurbs.Order (1) + j]));
-
- } // i
-
- } // j
-
- row++;
-
- }
- delete [] N0;
- delete [] N1;
-}
-
-
-ON_2dPoint
-FittingSurface::inverseMapping (const ON_NurbsSurface &nurbs, const ON_3dPoint
&pt, const ON_2dPoint &hint, double &error,
- ON_3dPoint &p, ON_3dVector &tu, ON_3dVector
&tv, int maxSteps, double accuracy, bool quiet)
-{
-
- double pointAndTangents[9];
-
- ON_2dVector current, delta;
- ON_Matrix A(2, 2);
- ON_2dVector b;
- ON_3dVector r;
- std::vector<double> elementsU = getElementVector (nurbs, 0);
- std::vector<double> elementsV = getElementVector (nurbs, 1);
- double minU = elementsU[0];
- double minV = elementsV[0];
- double maxU = elementsU[elementsU.size () - 1];
- double maxV = elementsV[elementsV.size () - 1];
-
- current = hint;
-
- for (int k = 0; k < maxSteps; k++) {
-
- nurbs.Evaluate (current[0], current[1], 1, 3, pointAndTangents);
- p[0] = pointAndTangents[0];
- p[1] = pointAndTangents[1];
- p[2] = pointAndTangents[2];
- tu[0] = pointAndTangents[3];
- tu[1] = pointAndTangents[4];
- tu[2] = pointAndTangents[5];
- tv[0] = pointAndTangents[6];
- tv[1] = pointAndTangents[7];
- tv[2] = pointAndTangents[8];
-
- r = p - pt;
-
- b[0] = -ON_DotProduct(r, tu);
- b[1] = -ON_DotProduct(r, tv);
-
- A[0][0] = ON_DotProduct(tu, tu);
- A[0][1] = ON_DotProduct(tu, tv);
- A[1][0] = A[0][1];
- A[1][1] = ON_DotProduct(tv, tv);
-
- Eigen::Vector2d eb(b[0], b[1]);
- Eigen::Vector2d edelta;
- Eigen::Matrix2d eA;
-
- eA (0, 0) = A[0][0];
- eA (0, 1) = A[0][1];
- eA (1, 0) = A[1][0];
- eA (1, 1) = A[1][1];
-
- edelta = eA.ldlt ().solve (eb);
-
- delta[0] = edelta (0);
- delta[1] = edelta (1);
-
- if (sqrt(ON_DotProduct(delta, delta)) < accuracy) {
-
- error = sqrt(ON_DotProduct(r, r));
- return current;
-
- } else {
- current = current + delta;
-
- CLAMP(current[0], minU, maxU);
- CLAMP(current[1], minV, maxV);
- }
-
- }
-
- error = sqrt(ON_DotProduct(r, r));
- if (!quiet) {
- printf ("[FittingSurface::inverseMapping] Warning: Method did not
converge (%e %d)\n", accuracy, maxSteps);
- printf (" %f %f ... %f %f\n", hint[0], hint[1], current[0],
current[1]);
- }
-
- return current;
-
-}
-
-
-ON_2dPoint
-FittingSurface::findClosestElementMidPoint (const ON_NurbsSurface &nurbs,
const ON_3dPoint &pt)
-{
- ON_2dPoint hint;
- ON_3dVector r;
- std::vector<double> elementsU = getElementVector (nurbs, 0);
- std::vector<double> elementsV = getElementVector (nurbs, 1);
-
- double d_shortest (DBL_MAX);
- for (unsigned i = 0; i < elementsU.size () - 1; i++) {
- for (unsigned j = 0; j < elementsV.size () - 1; j++) {
- double points[3];
- double d;
-
- double xi = elementsU[i] + 0.5 * (elementsU[i + 1] - elementsU[i]);
- double eta = elementsV[j] + 0.5 * (elementsV[j + 1] - elementsV[j]);
-
- nurbs.Evaluate (xi, eta, 0, 3, points);
- r[0] = points[0] - pt[0];
- r[1] = points[1] - pt[1];
- r[2] = points[2] - pt[2];
-
- d = ON_DotProduct(r, r);
-
- if ((i == 0 && j == 0) || d < d_shortest) {
- d_shortest = d;
- hint[0] = xi;
- hint[1] = eta;
- }
- }
- }
-
- return hint;
-}
-
-
-ON_2dPoint
-FittingSurface::inverseMappingBoundary (const ON_NurbsSurface &nurbs, const
ON_3dPoint &pt, double &error, ON_3dPoint &p,
- ON_3dVector &tu, ON_3dVector &tv, int
maxSteps, double accuracy, bool quiet)
-{
-
- ON_2dPoint result;
- double min_err = 100.0;
- std::vector<myvec> ini_points;
- double err_tmp;
- ON_3dPoint p_tmp;
- ON_3dVector tu_tmp, tv_tmp;
-
- std::vector<double> elementsU = getElementVector (nurbs, 0);
- std::vector<double> elementsV = getElementVector (nurbs, 1);
-
- // NORTH - SOUTH
- for (unsigned i = 0; i < (elementsV.size () - 1); i++) {
- ini_points.push_back (myvec (WEST, elementsV[i] + 0.5 * (elementsV[i +
1] - elementsV[i])));
- ini_points.push_back (myvec (EAST, elementsV[i] + 0.5 * (elementsV[i +
1] - elementsV[i])));
- }
-
- // WEST - EAST
- for (unsigned i = 0; i < (elementsU.size () - 1); i++) {
- ini_points.push_back (myvec (NORTH, elementsU[i] + 0.5 * (elementsU[i +
1] - elementsU[i])));
- ini_points.push_back (myvec (SOUTH, elementsU[i] + 0.5 * (elementsU[i +
1] - elementsU[i])));
- }
-
- for (unsigned i = 0; i < ini_points.size (); i++) {
-
- ON_2dPoint params = inverseMappingBoundary (nurbs, pt,
ini_points[i].side, ini_points[i].hint, err_tmp, p_tmp,
- tu_tmp, tv_tmp, maxSteps,
accuracy, quiet);
-
- if (i == 0 || err_tmp < min_err) {
- min_err = err_tmp;
- result = params;
- p = p_tmp;
- tu = tu_tmp;
- tv = tv_tmp;
- }
- }
-
- error = min_err;
- return result;
-
-}
-
-
-ON_2dPoint
-FittingSurface::inverseMappingBoundary (const ON_NurbsSurface &nurbs, const
ON_3dPoint &pt, int side, double hint,
- double &error, ON_3dPoint &p,
ON_3dVector &tu, ON_3dVector &tv, int maxSteps,
- double accuracy, bool quiet)
-{
-
- double pointAndTangents[9];
- double current, delta;
- ON_3dVector r, t;
- ON_2dPoint params;
-
- current = hint;
-
- std::vector<double> elementsU = getElementVector (nurbs, 0);
- std::vector<double> elementsV = getElementVector (nurbs, 1);
- double minU = elementsU[0];
- double minV = elementsV[0];
- double maxU = elementsU[elementsU.size () - 1];
- double maxV = elementsV[elementsV.size () - 1];
-
- for (int k = 0; k < maxSteps; k++) {
-
- switch (side) {
-
- case WEST:
-
- params[0] = minU;
- params[1] = current;
- nurbs.Evaluate (minU, current, 1, 3, pointAndTangents);
- p[0] = pointAndTangents[0];
- p[1] = pointAndTangents[1];
- p[2] = pointAndTangents[2];
- tu[0] = pointAndTangents[3];
- tu[1] = pointAndTangents[4];
- tu[2] = pointAndTangents[5];
- tv[0] = pointAndTangents[6];
- tv[1] = pointAndTangents[7];
- tv[2] = pointAndTangents[8];
-
- t = tv; // use tv
-
- break;
- case SOUTH:
-
- params[0] = current;
- params[1] = maxV;
- nurbs.Evaluate (current, maxV, 1, 3, pointAndTangents);
- p[0] = pointAndTangents[0];
- p[1] = pointAndTangents[1];
- p[2] = pointAndTangents[2];
- tu[0] = pointAndTangents[3];
- tu[1] = pointAndTangents[4];
- tu[2] = pointAndTangents[5];
- tv[0] = pointAndTangents[6];
- tv[1] = pointAndTangents[7];
- tv[2] = pointAndTangents[8];
-
- t = tu; // use tu
-
- break;
- case EAST:
-
- params[0] = maxU;
- params[1] = current;
- nurbs.Evaluate (maxU, current, 1, 3, pointAndTangents);
- p[0] = pointAndTangents[0];
- p[1] = pointAndTangents[1];
- p[2] = pointAndTangents[2];
- tu[0] = pointAndTangents[3];
- tu[1] = pointAndTangents[4];
- tu[2] = pointAndTangents[5];
- tv[0] = pointAndTangents[6];
- tv[1] = pointAndTangents[7];
- tv[2] = pointAndTangents[8];
-
- t = tv; // use tv
-
- break;
- case NORTH:
-
- params[0] = current;
- params[1] = minV;
- nurbs.Evaluate (current, minV, 1, 3, pointAndTangents);
- p[0] = pointAndTangents[0];
- p[1] = pointAndTangents[1];
- p[2] = pointAndTangents[2];
- tu[0] = pointAndTangents[3];
- tu[1] = pointAndTangents[4];
- tu[2] = pointAndTangents[5];
- tv[0] = pointAndTangents[6];
- tv[1] = pointAndTangents[7];
- tv[2] = pointAndTangents[8];
-
- t = tu; // use tu
-
- break;
- default:
- throw std::runtime_error
("[FittingSurface::inverseMappingBoundary] ERROR: Specify a boundary!");
-
- }
-
- r[0] = pointAndTangents[0] - pt[0];
- r[1] = pointAndTangents[1] - pt[1];
- r[2] = pointAndTangents[2] - pt[2];
-
- delta = -0.5 * ON_DotProduct(r, t) / ON_DotProduct(t, t);
-
- if (fabs (delta) < accuracy) {
-
- error = sqrt(ON_DotProduct(r, r));
- return params;
-
- } else {
-
- current = current + delta;
-
- bool stop = false;
-
- switch (side) {
-
- case WEST:
- case EAST:
- if (current < minV) {
- params[1] = minV;
- stop = true;
- } else if (current > maxV) {
- params[1] = maxV;
- stop = true;
- }
-
- break;
-
- case NORTH:
- case SOUTH:
- if (current < minU) {
- params[0] = minU;
- stop = true;
- } else if (current > maxU) {
- params[0] = maxU;
- stop = true;
- }
-
- break;
- }
-
- if (stop) {
- error = sqrt(ON_DotProduct(r, r));
- return params;
- }
-
- }
-
- }
-
- error = sqrt(ON_DotProduct(r, r));
- if (!quiet)
- printf (
- "[FittingSurface::inverseMappingBoundary] Warning: Method did not
converge! (residual: %f, delta: %f, params: %f %f)\n",
- error, delta, params[0], params[1]);
-
- return params;
-}
-
-
-/*
- * Local Variables:
- * tab-width: 8
- * mode: C++
- * indent-tabs-mode: t
- * c-file-style: "stroustrup"
- * coding: utf-8
- * End:
- * ex: shiftwidth=4 tabstop=8
- */
Deleted: brlcad/trunk/src/libbrep/opennurbs_fit.h
===================================================================
--- brlcad/trunk/src/libbrep/opennurbs_fit.h 2020-08-19 00:59:34 UTC (rev
76839)
+++ brlcad/trunk/src/libbrep/opennurbs_fit.h 2020-08-19 01:05:00 UTC (rev
76840)
@@ -1,575 +0,0 @@
-/** @File opennurbs_fit.h
- *
- * Extensions to the openNURBS library, based off of Thomas Mörwald's
- * surface fitting code in the Point Cloud Library (pcl). His code is
- * BSD licensed:
- *
- * Copyright (c) 2011, Thomas Mörwald, Jonathan Balzer, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Thomas Mörwald or Jonathan Balzer nor the names of
its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef LIBBREP_OPENNURBS_FIT_H
-#define LIBBREP_OPENNURBS_FIT_H
-
-#include "common.h"
-
-/* system headers */
-#include <vector>
-#include <list>
-#include <map>
-
-/* library headers */
-#include "bio.h" /* needed to include windows.h with protections */
-#define ON_NO_WINDOWS 1 /* don't let opennurbs include windows.h */
-#include "opennurbs.h"
-
-
-#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 6) &&
!defined(__clang__)
-# pragma message "Disabling GCC shadow warnings via pragma due to Eigen
headers..."
-# pragma message "Disabling GCC float equality comparison warnings via pragma
due to Eigen headers..."
-# pragma message "Disabling GCC inline failure warnings via pragma due to
Eigen headers..."
-#endif
-#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >=
6)) && !defined(__clang__)
-# pragma GCC diagnostic push
-#endif
-#if defined(__clang__)
-# pragma clang diagnostic push
-#endif
-#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) &&
!defined(__clang__)
-# pragma GCC diagnostic ignored "-Wshadow"
-# pragma GCC diagnostic ignored "-Wfloat-equal"
-# pragma GCC diagnostic ignored "-Winline"
-#endif
-#if defined(__clang__)
-# pragma clang diagnostic ignored "-Wshadow"
-# pragma clang diagnostic ignored "-Wfloat-equal"
-# pragma clang diagnostic ignored "-Winline"
-#endif
-#undef Success
-#include <Eigen/StdVector>
-#undef Success
-#include <Eigen/Dense>
-#undef Success
-#include <Eigen/Sparse>
-#undef Success
-#include <Eigen/SparseCholesky>
-#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >=
6)) && !defined(__clang__)
-# pragma GCC diagnostic pop
-#endif
-#if defined(__clang__)
-# pragma clang diagnostic pop
-#endif
-
-namespace on_fit
-{
-
-// **********************
-// * from nurbs_data.h *
-// **********************
-
-typedef std::vector<ON_2dVector > vector_vec2d;
-typedef std::vector<ON_3dVector > vector_vec3d;
-
-/** \brief Data structure for NURBS surface fitting
- * (FittingSurface, FittingSurfaceTDM, FittingCylinder, GlobalOptimization,
GlobalOptimizationTDM) */
-struct NurbsDataSurface
-{
- ON_Matrix *eigenvectors;
- ON_3dVector mean;
-
- vector_vec3d interior; ///<< input
- std::vector<double> interior_weight; ///<< input
- std::vector<double> interior_error; ///>> output
- vector_vec2d interior_param; ///>> output
- vector_vec3d interior_line_start; ///>> output
- vector_vec3d interior_line_end; ///>> output
- vector_vec3d interior_normals; ///>> output
-
- vector_vec3d boundary; ///<< input
- std::vector<double> boundary_weight; ///<< input
- std::vector<double> boundary_error; ///>> output
- vector_vec2d boundary_param; ///>> output
- vector_vec3d boundary_line_start; ///>> output
- vector_vec3d boundary_line_end; ///>> output
- vector_vec3d boundary_normals; ///>> output
-
- vector_vec3d common_boundary_point;
- std::vector<unsigned> common_boundary_idx;
- vector_vec2d common_boundary_param;
-
- /** \brief Clear all interior data */
- inline void
- clear_interior ()
- {
- interior.clear ();
- interior_weight.clear ();
- interior_error.clear ();
- interior_param.clear ();
- interior_line_start.clear ();
- interior_line_end.clear ();
- interior_normals.clear ();
- }
-
- /** \brief Clear all boundary data */
- inline void
- clear_boundary ()
- {
- boundary.clear ();
- boundary_weight.clear ();
- boundary_error.clear ();
- boundary_param.clear ();
- boundary_line_start.clear ();
- boundary_line_end.clear ();
- boundary_normals.clear ();
- }
-
- /** \brief Clear all common data */
- inline void
- clear_common_boundary ()
- {
- common_boundary_point.clear ();
- common_boundary_idx.clear ();
- common_boundary_param.clear ();
- }
-
-};
-
-
-// **********************
-// * from nurbs_tools.h *
-// **********************
-enum
-{
- NORTH = 1, NORTHEAST = 2, EAST = 3, SOUTHEAST = 4, SOUTH = 5, SOUTHWEST =
6, WEST = 7, NORTHWEST = 8
-};
-
-
-/** \brief Some useful tools for initialization, point search, ... */
-class NurbsTools
-{
-public:
-
- /** \brief Get the closest point with respect to 'point'
- * \param[in] point The point to which the closest point is searched for.
- * \param[in] data Vector containing the set of points for searching. */
- static unsigned
- getClosestPoint (const ON_2dPoint &point, const vector_vec2d &data);
-
- /** \brief Get the closest point with respect to 'point'
- * \param[in] point The point to which the closest point is searched for.
- * \param[in] data Vector containing the set of points for searching. */
- static unsigned
- getClosestPoint (const ON_3dPoint &point, const vector_vec3d &data);
-
- /** \brief Get the closest point with respect to 'point' in Non-Euclidean
metric
- * \brief Related paper: TODO
- * \param[in] point The point to which the closest point is searched for.
- * \param[in] dir The direction defining 'inside' and 'outside'
- * \param[in] data Vector containing the set of points for searching.
- * \param[out] idxcp Closest point with respect to Euclidean metric. */
- static unsigned
- getClosestPoint (const ON_2dPoint &point, const ON_2dVector &dir, const
vector_vec2d &data,
- unsigned &idxcp);
-
- /** \brief Compute the mean of a set of points
- * \param[in] data Set of points. */
- static ON_3dVector
- computeMean (const vector_vec3d &data);
- /** \brief Compute the mean of a set of points
- * \param[in] data Set of points. */
- static ON_2dVector
- computeMean (const vector_vec2d &data);
-
- /** \brief PCA - principal-component-analysis
- * \param[in] data Set of points.
- * \param[out] mean The mean of the set of points.
- * \param[out] eigenvectors Matrix containing column-wise the
eigenvectors of the set of points.
- * \param[out] eigenvalues The eigenvalues of the set of points with
respect to the eigenvectors. */
- static void
- pca (const vector_vec3d &data, ON_3dVector &mean, Eigen::Matrix3d
&eigenvectors,
- Eigen::Vector3d &eigenvalues);
-
- /** \brief Downsample data points to a certain size.
- * \param[in] data1 The original set of points.
- * \param[out] data2 The downsampled set of points of size 'size'.
- * \param[in] size The desired size of the resulting set of points.
*/
- static void
- downsample_random (const vector_vec3d &data1, vector_vec3d &data2,
unsigned size);
- /** \brief Downsample data points to a certain size.
- * \param[in/out] data1 The set of points for downsampling;
- * will be replaced by the resulting set of points of size 'size'.
- * \param[in] size The desired size of the resulting set of points.
*/
- static void
- downsample_random (vector_vec3d &data1, unsigned size);
-
-};
-
-
-// **********************
-// * from nurbs_solve.h *
-// **********************
-
-/** \brief Solving the linear system of equations using Eigen or UmfPack.
- * (can be defined in on_nurbs.cmake)*/
-class NurbsSolve
-{
-public:
- /** \brief Empty constructor */
- NurbsSolve () :
- m_quiet (true)
- {
- }
-
- /** \brief Assign size and dimension (2D, 3D) of system of equations. */
- void
- assign (unsigned rows, unsigned cols, unsigned dims);
-
- /** \brief Set value for system matrix K (stiffness matrix, basis
functions) */
- void
- K (unsigned i, unsigned j, double v);
- /** \brief Set value for state vector x (control points) */
- void
- x (unsigned i, unsigned j, double v);
- /** \brief Set value for target vector f (force vector) */
- void
- f (unsigned i, unsigned j, double v);
-
- /** \brief Get value for system matrix K (stiffness matrix, basis
functions) */
- double
- K (unsigned i, unsigned j);
- /** \brief Get value for state vector x (control points) */
- double
- x (unsigned i, unsigned j);
- /** \brief Get value for target vector f (force vector) */
- double
- f (unsigned i, unsigned j);
-
- /** \brief Resize target vector f (force vector) */
- void
- resizeF (unsigned rows);
-
- /** \brief Print system matrix K (stiffness matrix, basis functions) */
- void
- printK ();
- /** \brief Print state vector x (control points) */
- void
- printX ();
- /** \brief Print target vector f (force vector) */
- void
- printF ();
-
- /** \brief Solves the system of equations with respect to x.
- * - Using UmfPack incredibly speeds up this function. */
- bool
- solve ();
-
- /** \brief Compute the difference between solution K*x and target f */
- ON_Matrix *diff ();
-
- /** \brief Enable/Disable debug outputs in console. */
- inline void
- setQuiet (bool val)
- {
- m_quiet = val;
- }
-
-private:
- bool m_quiet;
- Eigen::SparseMatrix<double> m_Ksparse;
- ON_Matrix *m_xeig;
- ON_Matrix *m_feig;
-
-};
-
-
-// ******************************
-// * from fitting_surface_pdm.h *
-// ******************************
-
-/** \brief Fitting a B-Spline surface to 3D point-clouds using
point-distance-minimization
- * Based on paper: TODO
- * \author Thomas Moerwald
- * \ingroup surface */
-class FittingSurface
-{
-public:
- ON_NurbsSurface m_nurbs;
- NurbsDataSurface *m_data;
-
- class myvec
- {
- public:
- int side;
- double hint;
- myvec (int in_side, double in_hint)
- {
- this->side = in_side;
- this->hint = in_hint;
- }
- };
-
- /** \brief Parameters for fitting */
- struct Parameter
- {
- double interior_weight;
- double interior_smoothness;
- double interior_regularisation;
-
- double boundary_weight;
- double boundary_smoothness;
- double boundary_regularisation;
-
- unsigned regularisation_resU;
- unsigned regularisation_resV;
-
- Parameter (double intW = 1.0, double intS = 0.000001, double intR =
0.0, double bndW = 1.0,
- double bndS = 0.000001, double bndR = 0.0, unsigned regU =
0, unsigned regV = 0) :
- interior_weight (intW), interior_smoothness (intS),
interior_regularisation (intR), boundary_weight (bndW),
- boundary_smoothness (bndS), boundary_regularisation (bndR),
regularisation_resU (regU),
- regularisation_resV (regV)
- {
-
- }
-
- };
-
- /** \brief Constructor initializing with the B-Spline surface given in
argument 2.
- * \param[in] data pointer to the 3D point-cloud data to be fit.
- * \param[in] ns B-Spline surface used for fitting. */
- FittingSurface (NurbsDataSurface *data, const ON_NurbsSurface &ns);
-
- /** \brief Constructor initializing B-Spline surface using
initNurbsPCA(...).
- * \param[in] order the polynomial order of the B-Spline surface.
- * \param[in] data pointer to the 2D point-cloud data to be fit.
- * \param[in] z vector defining front face of surface. */
- FittingSurface (int order, NurbsDataSurface *data, ON_3dVector z =
ON_3dVector(0.0, 0.0, 1.0));
-
- /** \brief Refines surface by inserting a knot in the middle of each
element.
- * \param[in] dim dimension of refinement (0, 1) */
- void
- refine (int dim);
-
- /** \brief Assemble the system of equations for fitting
- * - for large point-clouds this is time consuming.
- * - should be done once before refinement to initialize the starting
points for point inversion. */
- virtual void
- assemble (Parameter param = Parameter ());
-
- /** \brief Solve system of equations using Eigen or UmfPack (can be
defined in on_nurbs.cmake),
- * and updates B-Spline surface if a solution can be obtained. */
- virtual void
- solve (double damp = 1.0);
-
- /** \brief Update surface according to the current system of equations.
- * \param[in] damp damping factor from one iteration to the other. */
- virtual void
- updateSurf (double damp);
-
- /** \brief Set parameters for inverse mapping
- * \param[in] in_max_steps maximum number of iterations.
- * \param[in] in_accuracy stops iteration if specified accuracy is
reached. */
- void
- setInvMapParams (unsigned in_max_steps, double in_accuracy);
-
- /** \brief Get the elements of a B-Spline surface.*/
- static std::vector<double>
- getElementVector (const ON_NurbsSurface &nurbs, int dim);
-
- /** \brief Inverse mapping / point inversion: Given a point pt, this
function finds the closest
- * point on the B-Spline surface using Newtons method and point-distance
(L2-, Euclidean norm).
- * \param[in] nurbs the B-Spline surface.
- * \param[in] pt the point to which the closest point on the surface will
be computed.
- * \param[in] hint the starting point in parametric domain (warning: may
lead to convergence at local minima).
- * \param[in] error the distance between the point pt and p after
convergence.
- * \param[in] p closest point on surface.
- * \param[in] tu the tangent vector at point p in u-direction.
- * \param[in] tv the tangent vector at point p in v-direction.
- * \param[in] maxSteps maximum number of iterations.
- * \param[in] accuracy convergence criteria: if error is lower than
accuracy the function returns
- * \return closest point on surface in parametric domain.*/
- static ON_2dPoint
- inverseMapping (const ON_NurbsSurface &nurbs, const ON_3dPoint &pt, const
ON_2dPoint &hint,
- double &error, ON_3dPoint &p, ON_3dVector &tu, ON_3dVector
&tv, int maxSteps = 100,
- double accuracy = 1e-6, bool quiet = true);
-
- /** \brief Given a point pt, the function finds the closest midpoint of
the elements of the surface.
- * \param[in] nurbs the B-Spline surface.
- * \param[in] pt the point to which the closest midpoint of the elements
will be computed.
- * return closest midpoint in parametric domain. */
- static ON_2dPoint
- findClosestElementMidPoint (const ON_NurbsSurface &nurbs, const ON_3dPoint
&pt);
-
- /** \brief Inverse mapping / point inversion: Given a point pt, this
function finds the closest
- * point on the boundary of the B-Spline surface using Newtons method and
point-distance (L2-, Euclidean norm).
- * \param[in] nurbs the B-Spline surface.
- * \param[in] pt the point to which the closest point on the surface will
be computed.
- * \param[in] error the distance between the point pt and p after
convergence.
- * \param[in] p closest boundary point on surface.
- * \param[in] tu the tangent vector at point p in u-direction.
- * \param[in] tv the tangent vector at point p in v-direction.
- * \param[in] maxSteps maximum number of iterations.
- * \param[in] accuracy convergence criteria: if error is lower than
accuracy the function returns
- * \return closest point on surface in parametric domain.*/
- static ON_2dPoint
- inverseMappingBoundary (const ON_NurbsSurface &nurbs, const ON_3dPoint
&pt, double &error,
- ON_3dPoint &p, ON_3dVector &tu, ON_3dVector &tv,
int maxSteps = 100,
- double accuracy = 1e-6, bool quiet = true);
-
- /** \brief Inverse mapping / point inversion: Given a point pt, this
function finds the closest
- * point on one side of the boundary of the B-Spline surface using Newtons
method and
- * point-distance (L2-, Euclidean norm).
- * \param[in] nurbs the B-Spline surface.
- * \param[in] pt the point to which the closest point on the surface will
be computed.
- * \param[in] side the side of the boundary (NORTH, SOUTH, EAST, WEST)
- * \param[in] hint the starting point in parametric domain (warning: may
lead to convergence at local minima).
- * \param[in] error the distance between the point pt and p after
convergence.
- * \param[in] p closest boundary point on surface.
- * \param[in] tu the tangent vector at point p in u-direction.
- * \param[in] tv the tangent vector at point p in v-direction.
- * \param[in] maxSteps maximum number of iterations.
- * \param[in] accuracy convergence criteria: if error is lower than
accuracy the function returns
- * \return closest point on surface in parametric domain.*/
- static ON_2dPoint
- inverseMappingBoundary (const ON_NurbsSurface &nurbs, const ON_3dPoint
&pt, int side, double hint,
- double &error, ON_3dPoint &p, ON_3dVector &tu,
ON_3dVector &tv,
- int maxSteps = 100, double accuracy = 1e-6, bool
quiet = true);
-
- /** \brief Initializing a B-Spline surface using 4 corners */
- static ON_NurbsSurface
- initNurbs4Corners (int order, ON_3dPoint ll, ON_3dPoint lr, ON_3dPoint ur,
ON_3dPoint ul);
-
- /** \brief Initializing a B-Spline surface using
principal-component-analysis and eigen values */
- static ON_NurbsSurface
- initNurbsPCA (int order, NurbsDataSurface *data, ON_3dVector z =
ON_3dVector(0.0, 0.0, 1.0));
-
- /** \brief Initializing a B-Spline surface using
principal-component-analysis and bounding box of points */
- static ON_NurbsSurface
- initNurbsPCABoundingBox (int order, NurbsDataSurface *data, ON_3dVector z
= ON_3dVector(0.0, 0.0, 1.0));
-
- /** \brief Enable/Disable debug outputs in console. */
- inline void
- setQuiet (bool val)
- {
- m_quiet = val;
- m_solver.setQuiet(val);
- }
-
-protected:
-
- /** \brief Initialisation of member variables */
- void
- init ();
-
- /** \brief Assemble point-to-surface constraints for interior points. */
- virtual void
- assembleInterior (double wInt, unsigned &row);
-
- /** \brief Assemble point-to-surface constraints for boundary points. */
- virtual void
- assembleBoundary (double wBnd, unsigned &row);
-
- /** \brief Add minimization constraint: point-to-surface distance
(point-distance-minimization). */
- virtual void
- addPointConstraint (const ON_2dVector ¶ms, const ON_3dPoint &point,
double weight, unsigned &row);
- // void addBoundaryPointConstraint(double paramU, double paramV, double
weight, unsigned &row);
-
- /** \brief Add minimization constraint: interior smoothness by control
point regularisation. */
- virtual void
- addCageInteriorRegularisation (double weight, unsigned &row);
-
- /** \brief Add minimization constraint: boundary smoothness by control
point regularisation. */
- virtual void
- addCageBoundaryRegularisation (double weight, int side, unsigned &row);
-
- /** \brief Add minimization constraint: corner smoothness by control point
regularisation. */
- virtual void
- addCageCornerRegularisation (double weight, unsigned &row);
-
- /** \brief Add minimization constraint: interior smoothness by derivatives
regularisation. */
- virtual void
- addInteriorRegularisation (int order, int resU, int resV, double weight,
unsigned &row);
-
- /** \brief Add minimization constraint: boundary smoothness by derivatives
regularisation. */
- virtual void
- addBoundaryRegularisation (int order, int resU, int resV, double weight,
unsigned &row);
-
- NurbsSolve m_solver;
-
- bool m_quiet;
-
- std::vector<double> m_elementsU;
- std::vector<double> m_elementsV;
-
- double m_minU;
- double m_minV;
- double m_maxU;
- double m_maxV;
-
- int in_max_steps;
- double in_accuracy;
-
- // index routines
- int
- grc2gl (int I, int J)
- {
- return m_nurbs.CVCount (1) * I + J;
- } // global row/col index to global lexicographic index
- int
- lrc2gl (int E, int F, int i, int j)
- {
- return grc2gl (E + i, F + j);
- } // local row/col index to global lexicographic index
- int
- gl2gr (int A)
- {
- return (int)(A / m_nurbs.CVCount (1));
- } // global lexicographic in global row index
- int
- gl2gc (int A)
- {
- return (int)(A % m_nurbs.CVCount (1));
- } // global lexicographic in global col index
-};
-
-
-}
-#endif
-
-/*
- * Local Variables:
- * tab-width: 8
- * mode: C++
- * indent-tabs-mode: t
- * c-file-style: "stroustrup"
- * coding: utf-8
- * End:
- * ex: shiftwidth=4 tabstop=8
- */
Deleted: brlcad/trunk/src/libbrep/surface_tree_queue_tests.patch
===================================================================
--- brlcad/trunk/src/libbrep/surface_tree_queue_tests.patch 2020-08-19
00:59:34 UTC (rev 76839)
+++ brlcad/trunk/src/libbrep/surface_tree_queue_tests.patch 2020-08-19
01:05:00 UTC (rev 76840)
@@ -1,2159 +0,0 @@
-Index: src/libbrep/libbrep_curvetree.cpp
-===================================================================
---- src/libbrep/libbrep_curvetree.cpp (revision 0)
-+++ src/libbrep/libbrep_curvetree.cpp (revision 57887)
-@@ -0,0 +1,622 @@
-+/* L I B B R E P _ C U R V E T R E E . C P P
-+ * BRL-CAD
-+ *
-+ * Copyright (c) 2013-2020 United States Government as represented by
-+ * the U.S. Army Research Laboratory.
-+ *
-+ * 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.
-+ *
-+ * This library 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
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with this file; see the file named COPYING for more
-+ * information.
-+ */
-+/** @file libbrep_curvetree.cpp
-+ *
-+ * Brief description
-+ *
-+ */
-+
-+#include "libbrep_curvetree.h"
-+
-+#include "vmath.h"
-+#include <iostream>
-+
-+#include <vector>
-+#include <map>
-+#include <set>
-+#include <queue>
-+#include <limits>
-+
-+// Return 0 if there are no tangent points in the interval, 1
-+// if there is a horizontal tangent, two if there is a vertical
-+// tangent, 3 if a normal split is in order.
-+int ON_Curve_Has_Tangent(const ON_Curve* curve, double min, double max) {
-+
-+ bool tanx1, tanx2, x_changed;
-+ bool tany1, tany2, y_changed;
-+ bool slopex, slopey;
-+ double xdelta, ydelta;
-+ ON_3dVector tangent1, tangent2;
-+ ON_3dPoint p1, p2;
-+ ON_Interval t(min, max);
-+
-+ tangent1 = curve->TangentAt(t[0]);
-+ tangent2 = curve->TangentAt(t[1]);
-+
-+ tanx1 = (tangent1[X] < 0.0);
-+ tanx2 = (tangent2[X] < 0.0);
-+ tany1 = (tangent1[Y] < 0.0);
-+ tany2 = (tangent2[Y] < 0.0);
-+
-+ x_changed =(tanx1 != tanx2);
-+ y_changed =(tany1 != tany2);
-+
-+ if (x_changed && y_changed) return 3; //horz & vert
-+ if (x_changed) return 1;//need to get vertical tangent
-+ if (y_changed) return 2;//need to find horizontal tangent
-+
-+ p1 = curve->PointAt(t[0]);
-+ p2 = curve->PointAt(t[1]);
-+
-+ xdelta = (p2[X] - p1[X]);
-+ slopex = (xdelta < 0.0);
-+ ydelta = (p2[Y] - p1[Y]);
-+ slopey = (ydelta < 0.0);
-+
-+ // If we have no slope change
-+ // in x or y, we have a tangent line
-+ if (NEAR_ZERO(xdelta, TOL) || NEAR_ZERO(ydelta, TOL)) return 0;
-+
-+ if ((slopex != tanx1) || (slopey != tany1)) return 3;
-+
-+ return 0;
-+}
-+
-+int ON_Curve_HV_Split(const ON_Curve *curve, double min, double max, double
*mid) {
-+ // Don't split if min ~= max - that's infinite loop territory
-+ if (NEAR_ZERO(max - min, ON_ZERO_TOLERANCE)) return 0;
-+ // Go HV tangent hunting
-+ int tan_result = ON_Curve_Has_Tangent(curve, min, max);
-+ if (tan_result == 3) return 1;
-+ if (tan_result == 0) return 0;
-+ if (tan_result == 1 || tan_result == 2) {
-+ // If we have a tangent point at the min or max, that's OK
-+ ON_3dVector hv_tangent = curve->TangentAt(max);
-+ if (NEAR_ZERO(hv_tangent.x, TOL2) || NEAR_ZERO(hv_tangent.y, TOL2))
tan_result = 0;
-+ hv_tangent = curve->TangentAt(min);
-+ if (NEAR_ZERO(hv_tangent.x, TOL2) || NEAR_ZERO(hv_tangent.y, TOL2))
tan_result = 0;
-+ // The tangent point is in a bad spot - find it and subdivide on it
-+ if(tan_result) {
-+ bool tanmin;
-+ (tan_result == 1) ? (tanmin = (hv_tangent[X] < 0.0)) : (tanmin =
(hv_tangent[Y] < 0.0));
-+ double hv_mid;
-+ double hv_min = min;
-+ double hv_max = max;
-+ // find the tangent point using binary search
-+ while (fabs(hv_min - hv_max) > TOL2) {
-+ hv_mid = (hv_max + hv_min)/2.0;
-+ hv_tangent = curve->TangentAt(hv_mid);
-+ if ((tan_result == 1 && NEAR_ZERO(hv_tangent[X], TOL2))
-+ ||(tan_result == 2 && NEAR_ZERO(hv_tangent[Y], TOL2))) {
-+ (*mid) = hv_mid;
-+ return 1;
-+ }
-+ if ((tan_result == 1 && ((hv_tangent[X] < 0.0) == tanmin)) ||
-+ (tan_result == 2 && ((hv_tangent[Y] < 0.0) == tanmin)
)) {
-+ hv_min = hv_mid;
-+ } else {
-+ hv_max = hv_mid;
-+ }
-+ }
-+ return 0;
-+ } else {
-+ // The tangent was at the min and/or max, we don't need to split on
account
-+ // of this case
-+ return 0;
-+ }
-+ }
-+ // Shouldn't get here - something went drastically wrong if we did
-+ return -1;
-+}
-+
-+double ON_Curve_Solve_For_V(const ON_Curve *curve, double u, double min,
double max, double tol) {
-+
-+ ON_3dVector Tan_start, Tan_end;
-+ ON_3dPoint p;
-+ double guess, dT;
-+ double Ta = min;
-+ double Tb = max;
-+ ON_3dPoint A = curve->PointAt(Ta);
-+ ON_3dPoint B = curve->PointAt(Tb);
-+ double dU = fabs(A.x - B.x);
-+ if (dU <= tol) {
-+ if (A.y <= B.y) {return A.y;} else {return B.y;};
-+ }
-+ Tan_start = curve->TangentAt(Ta);
-+ Tan_end = curve->TangentAt(Tb);
-+ dT = Tb - Ta;
-+
-+ /* Use quick binary subdivision until derivatives at end points in 'u'
are within 5 percent */
-+ while (!(fabs(dU) <= tol) && !(fabs(dT) <= tol)) {
-+ guess = Ta + dT/2;
-+ p = curve->PointAt(guess);
-+
-+ /* if we hit 'u' exactly, done deal */
-+ if (fabs(p.x-u) <= SMALL_FASTF) return p.y;
-+
-+ if (p.x > u) {
-+ /* v is behind us, back up the end */
-+ Tb = guess;
-+ B = p;
-+ Tan_end = curve->TangentAt(Tb);
-+ } else {
-+ /* v is in front, move start forward */
-+ Ta = guess;
-+ A = p;
-+ Tan_start = curve->TangentAt(Ta);
-+ }
-+ dT = Tb - Ta;
-+ dU = B.x - A.x;
-+ }
-+
-+ dU = fabs(B.x - A.x);
-+ if (dU <= tol) { //vertical
-+ if (A.y <= B.y) {return A.y;} else {return B.y;};
-+ }
-+
-+ guess = Ta + (u - A.x) * dT/dU;
-+ p = curve->PointAt(guess);
-+
-+ int cnt=0;
-+ while ((cnt < 1000) && (!(fabs(p.x-u) <= tol))) {
-+ if (p.x < u) {
-+ Ta = guess;
-+ A = p;
-+ } else {
-+ Tb = guess;
-+ B = p;
-+ }
-+ dU = fabs(B.x - A.x);
-+ if (dU <= tol) { //vertical
-+ if (A.y <= B.y) {return A.y;} else {return B.y;};
-+ }
-+
-+ dT = Tb - Ta;
-+ guess =Ta + (u - A[X]) * dT/dU;
-+ p = curve->PointAt(guess);
-+ cnt++;
-+ }
-+ if (cnt > 999) {
-+ std::cout << "ON_Curve_Solve_For_V(): estimate of 'v' given a trim
curve and 'u' did not converge within iteration bound(" << cnt << ")\n";
-+ }
-+ return p.y;
-+}
-+
-+int ON_Curve_Relative_Size(const ON_Curve *curve, const ON_Surface *srf,
double tmin, double tmax, double factor) {
-+ int retval = 0;
-+ ON_Interval u = srf->Domain(0);
-+ ON_Interval v = srf->Domain(1);
-+ ON_3dPoint a(u[0], v[0], 0.0);
-+ ON_3dPoint b(u[1], v[1], 0.0);
-+ double ab = a.DistanceTo(b);
-+ double cd = curve->PointAt(tmin).DistanceTo(curve->PointAt(tmax));
-+ if (cd > factor*ab) retval = 1;
-+ return retval;
-+}
-+
-+long int ON_CurveTree::New_Trim_Node(int parent, int trim_index, int tmin,
int tmax) {
-+ // Parent node of new node
-+ nodes.push_back(parent);
-+ // Curve parameter information
-+ nodes.push_back(tmin);
-+ nodes.push_back(tmax);
-+ // As yet, the node has no children
-+ nodes.push_back(0);
-+ nodes.push_back(0);
-+ // knots/HV tangents info node
-+ nodes.push_back(0);
-+ // Populate uv_bbox_values
-+ nodes.push_back(uv_bbox_values.size());
-+ for (int i = 0; i < 2; ++i)
uv_bbox_values.push_back(std::numeric_limits<double>::infinity());
-+ for (int i = 2; i < 4; ++i) uv_bbox_values.push_back(-1 *
std::numeric_limits<double>::infinity());
-+ // Trim index in brep
-+ nodes.push_back(trim_index);
-+
-+ return nodes.size() - TRIM_NODE_STEP;
-+}
-+
-+unsigned int ON_CurveTree::Depth(long int node_id) {
-+ if (node_id < first_trim_node) return 0;
-+ int depth = 1;
-+ int parent = nodes[node_id];
-+ while (parent != 0 && parent >= first_trim_node) {
-+ depth++;
-+ parent = nodes[parent];
-+ }
-+ return depth;
-+}
-+
-+int ON_Curve_Flat(const ON_Curve *curve, double min, double max, double tol){
-+ int retval = 1;
-+ // If min ~= max, call it flat
-+ if (NEAR_ZERO(max - min, ON_ZERO_TOLERANCE)) return retval;
-+ ON_3dVector tangent_start = curve->TangentAt(min);
-+ ON_3dVector tangent_end = curve->TangentAt(max);
-+ if (fabs(tangent_start * tangent_end) < tol) retval = 0;
-+ return retval;
-+}
-+
-+void ON_CurveTree::Subdivide_Trim_Node(long int first_node_id, const
ON_BrepTrim *trim) {
-+
-+ // Initialize
-+ ON_3dPoint pmin, pmax;
-+ std::set<long int> leaf_nodes;
-+ const ON_Curve *curve = trim->TrimCurveOf();
-+ const ON_Surface *srf = trim->SurfaceOf();
-+ double c_min, c_max;
-+ int knotcnt = curve->SpanCount();
-+ double *knots = (double *)malloc(sizeof(double) * (knotcnt + 1));
-+ (void)curve->GetSpanVector(knots);
-+ (void)curve->GetDomain(&c_min, &c_max);
-+
-+ // Populate the root node t_coords
-+ t_coords.push_back(c_min);
-+ t_coords.push_back(c_max);
-+ nodes.at(first_node_id + 1) = t_coords.size() - 2;
-+ nodes.at(first_node_id + 2) = t_coords.size() - 1;
-+
-+ // Use a queue to process nodes
-+ std::queue<long int> trim_node_queue;
-+
-+ // Prime the queue with the root node
-+ trim_node_queue.push(first_node_id);
-+
-+ // Begin the core of the tree building process. Pop a node
-+ // off the queue, test it to see if it must be split further,
-+ // and proceed accordingly.
-+ while (!trim_node_queue.empty()) {
-+ int split = 0;
-+ long int node = trim_node_queue.front();
-+ trim_node_queue.pop();
-+ double node_tmin = t_coords.at(nodes.at(node+1));
-+ double node_tmax = t_coords.at(nodes.at(node+2));
-+ //std::cout << "tmin: " << node_tmin << ", tmax: " << node_tmax <<
"\n";
-+ ON_Interval node_ival(node_tmin, node_tmax);
-+
-+ // Determine the depth of this node
-+ int node_depth = this->Depth(node);
-+ //std::cout << "Node depth: " << node_depth << "\n";
-+
-+ // Use a variable for the midpoint, since it may be overridden
-+ // if we have knots or tangent points to split on.
-+ double t_mid = node_ival.Mid();
-+
-+ // If we have knots in the interval, we need to split
-+ split += ON_Interval_Find_Split_Knot(&node_ival, knotcnt, knots,
&t_mid);
-+ if (split) nodes.at(node+5) = 1;
-+ if (split) {
-+ //std::cout << "Knot split:" << node << "," << t_mid << "\n";
-+ //if(NEAR_ZERO(t_mid-node_tmin, TOL2) || NEAR_ZERO(t_mid-node_tmax,
TOL2)) std::cout << "Arrgh! Knots\n";
-+ }
-+ // If we aren't already splitting, check for horizontal and vertical
tangents
-+ if (!split) {
-+ split += ON_Curve_HV_Split(curve, node_tmin, node_tmax, &t_mid);
-+ if (split) nodes.at(node+5) = 1;
-+ if (split) {
-+ //std::cout << "HV split:" << node << "," << t_mid << "\n";
-+ //if(NEAR_ZERO(t_mid-node_tmin, TOL2) ||
NEAR_ZERO(t_mid-node_tmax, TOL2)) std::cout << "Arrgh! HV\n";
-+ }
-+ }
-+
-+ // If we aren't already splitting, check flatness
-+ if (!split) {
-+ split += !ON_Curve_Flat(curve, node_tmin, node_tmax,
BREP_CURVE_FLATNESS);
-+ if (split) {
-+ //std::cout << "Flatness:" << node << "\n";
-+ //if(NEAR_ZERO(t_mid-node_tmin, TOL2) ||
NEAR_ZERO(t_mid-node_tmax, TOL2)) std::cout << "Arrgh! Flat\n";
-+ }
-+ }
-+
-+ // We want subdivided curves to be small relative to their
-+ // parent surface.
-+ if (!split) {
-+ split += ON_Curve_Relative_Size(curve, srf, node_tmin, node_tmax,
BREP_TRIM_SUB_FACTOR);
-+ if (split) {
-+ // std::cout << "Relative:" << node << "\n";
-+ //if(NEAR_ZERO(t_mid-node_tmin, TOL2) ||
NEAR_ZERO(t_mid-node_tmax, TOL2)) std::cout << "Arrgh! Relative\n";
-+ }
-+ }
-+
-+ // If we DO need to split, proceed
-+ if (split) {
-+ long int left_child, right_child;
-+ // Push the new midpoint onto tcoords
-+ t_coords.push_back(t_mid);
-+ left_child = this->New_Trim_Node(node, nodes.at(node+7),
nodes.at(node+1), t_coords.size() - 1);
-+ nodes.at(node+3) = left_child;
-+ trim_node_queue.push(left_child);
-+ right_child = this->New_Trim_Node(node, nodes.at(node+7),
t_coords.size() - 1, nodes.at(node+2));
-+ nodes.at(node+4) = right_child;
-+ trim_node_queue.push(right_child);
-+ } else {
-+ double pmin_u, pmin_v, pmax_u, pmax_v;
-+ leaf_nodes.insert(node);
-+ pmin = curve->PointAt(node_tmin);
-+ pmax = curve->PointAt(node_tmax);
-+ (pmin.x > pmax.x) ? (pmin_u = pmax.x) : (pmin_u = pmin.x);
-+ (pmax.x > pmin.x) ? (pmax_u = pmax.x) : (pmax_u = pmin.x);
-+ (pmin.y > pmax.y) ? (pmin_v = pmax.y) : (pmin_v = pmin.y);
-+ (pmax.y > pmin.y) ? (pmax_v = pmax.y) : (pmax_v = pmin.y);
-+ uv_bbox_values.at(nodes.at(node+6)) = pmin_u;
-+ uv_bbox_values.at(nodes.at(node+6)+1) = pmin_v;
-+ uv_bbox_values.at(nodes.at(node+6)+2) = pmax_u;
-+ uv_bbox_values.at(nodes.at(node+6)+3) = pmax_v;
-+ //std::cout << "node " << node << " bbox:" << pmin_u << "," <<
pmin_v << "," << pmax_u << "," << pmax_v << "\n";
-+ }
-+
-+ }
-+ // Clean up
-+ free(knots);
-+
-+ // Sync bboxes up to the root trim node
-+ std::set<long int> node_set;
-+ std::set<long int>::iterator p_it;
-+ std::set<long int> *parent_nodes, *current_nodes, *temp;
-+ double *p_umin, *p_vmin, *p_umax, *p_vmax;
-+ double *c_umin, *c_vmin, *c_umax, *c_vmax;
-+ current_nodes = &leaf_nodes;
-+ parent_nodes = &node_set;
-+ while (!current_nodes->empty()) {
-+ for (p_it = current_nodes->begin(); p_it != current_nodes->end();
++p_it) {
-+ if ((*p_it) > first_node_id) {
-+ long int parent_id = nodes.at((*p_it));
-+ p_umin = &(uv_bbox_values[nodes.at(parent_id+6)]);
-+ p_vmin = &(uv_bbox_values[nodes.at(parent_id+6)+1]);
-+ p_umax = &(uv_bbox_values[nodes.at(parent_id+6)+2]);
-+ p_vmax = &(uv_bbox_values[nodes.at(parent_id+6)+3]);
-+ //std::cout << "pnode " << parent_id << " bbox:" << *p_umin <<
"," << *p_vmin << "," << *p_umax << "," << *p_vmax << "\n";
-+ c_umin = &(uv_bbox_values[nodes.at((*p_it)+6)]);
-+ c_vmin = &(uv_bbox_values[nodes.at((*p_it)+6)+1]);
-+ c_umax = &(uv_bbox_values[nodes.at((*p_it)+6)+2]);
-+ c_vmax = &(uv_bbox_values[nodes.at((*p_it)+6)+3]);
-+ //std::cout << "cnode " << (*p_it) << " bbox:" << *c_umin <<
"," << *c_vmin << "," << *c_umax << "," << *c_vmax << "\n";
-+ if (*c_umin < *p_umin) (*p_umin) = (*c_umin);
-+ if (*c_vmin < *p_vmin) (*p_vmin) = (*c_vmin);
-+ if (*c_umax > *p_umax) (*p_umax) = (*c_umax);
-+ if (*c_vmax > *p_vmax) (*p_vmax) = (*c_vmax);
-+ if (parent_id > first_node_id) parent_nodes->insert(parent_id);
-+ //std::cout << "pnode u" << parent_id << " bbox:" << *p_umin <<
"," << *p_vmin << "," << *p_umax << "," << *p_vmax << "\n";
-+ }
-+ }
-+ current_nodes->clear();
-+ temp = parent_nodes;
-+ parent_nodes = current_nodes;
-+ current_nodes = temp;
-+ }
-+}
-+
-+// When testing a curve for trimming contributions, the first stage is to
check
-+// the curve tree node to see whether it contains a segment from below the
knot
-+// and HV tangent breakdowns of the curve. If it does not, we need to walk
down
-+// the tree until we have the set of nodes that represent corresponding
sub-segments
-+// that are below the knot and HV tangent breakdowns.
-+//
-+// Once we have an appropriate segment set, do the pnpoly intersection checks.
-+// For anything where the point is not in the segment bounding box, the test
is
-+// simple - if the point is within the bounding box of the node, walk down the
-+// tree until either a determination can be made or the point is found to be
-+// within a leaf node.
-+//
-+// If the point is within a leaf node, the more expensive search against the
-+// actual curve to determine 2D ray intersection status is necessary.
-+bool ON_CurveTree::CurveTrim(double u, double v, long int node) {
-+ bool c = false;
-+ std::set<long int> test_nodes;
-+ std::set<long int>::iterator tn_it;
-+ std::queue<long int> q1, q2;
-+ std::queue<long int> *current_queue, *next_queue, *tmp;
-+ // Get the node or nodes we need into test_nodes
-+ q1.push(node);
-+ current_queue = &q1;
-+ next_queue= &q2;
-+ while (!current_queue->empty()) {
-+ while (!current_queue->empty()) {
-+ long int current_node = current_queue->front();
-+ current_queue->pop();
-+ if (nodes.at(current_node+5) != 1) {
-+ test_nodes.insert(current_node);
-+ } else {
-+ next_queue->push(nodes.at(current_node+3));
-+ next_queue->push(nodes.at(current_node+4));
-+ }
-+ }
-+ tmp = current_queue;
-+ current_queue = next_queue;
-+ next_queue = tmp;
-+ }
-+ // Check node bounding boxes vs uv point
-+ double *c_umin, *c_vmin, *c_umax, *c_vmax;
-+ for(tn_it = test_nodes.begin(); tn_it != test_nodes.end(); ++tn_it) {
-+ c_umin = &uv_bbox_values[nodes.at((*tn_it)+6)];
-+ c_vmin = &uv_bbox_values[nodes.at((*tn_it)+6)+1];
-+ c_umax = &uv_bbox_values[nodes.at((*tn_it)+6)+2];
-+ c_vmax = &uv_bbox_values[nodes.at((*tn_it)+6)+3];
-+ // Are we inside the u interval of the bbox?
-+ if ((u <= *c_umax) && (u > *c_umin)) {
-+ // Are we below the bbox? if so, a v+ ray is guaranteed to
intersect
-+ if (v <= *c_vmin) {
-+ c = !c;
-+ } else {
-+ // We're not below it - are we inside it? If not, no
intersection possible,
-+ // otherwise, need closer look
-+ if (v < *c_vmax) {
-+ // Descend the tree until either we're outside
-+ // the bboxes and can make a determination, or
-+ // we find the leaf node containing the uv point
-+ // and do the full curve test.
-+ current_queue->push((*tn_it));
-+ while (!current_queue->empty()) {
-+ while (!current_queue->empty()) {
-+ long int current_node = current_queue->front();
-+ current_queue->pop();
-+ c_umin = &uv_bbox_values[nodes.at(current_node+6)];
-+ c_vmin = &uv_bbox_values[nodes.at(current_node+6)+1];
-+ c_umax = &uv_bbox_values[nodes.at(current_node+6)+2];
-+ c_vmax = &uv_bbox_values[nodes.at(current_node+6)+3];
-+ if ((u <= *c_umax) && (u >= *c_umin)) {
-+ if (v <= *c_vmin) {
-+ c = !c;
-+ } else {
-+ if (v < *c_vmax) {
-+ // If we are at a leaf, it's time to
do a
-+ // close check. Otherwise, queue the
children
-+ if (nodes.at(current_node + 3)) {
-+
next_queue->push(nodes.at(current_node + 3));
-+
next_queue->push(nodes.at(current_node + 4));
-+ } else {
-+ // We're close to a leaf
-+ const ON_Curve *curve =
this->ctree_face->Brep()->m_C2[(int)nodes.at(current_node + 7)];
-+ double v_curve =
ON_Curve_Solve_For_V(curve, u, nodes.at(current_node + 1),
nodes.at(current_node + 2), TOL3);
-+ if (v <= v_curve) c = !c;
-+ }
-+ }
-+ }
-+ }
-+ }
-+ tmp = current_queue;
-+ current_queue = next_queue;
-+ next_queue = tmp;
-+ }
-+ }
-+ }
-+ }
-+ }
-+ return c;
-+}
-+
-+// Remember - unlike other
-+// trimming loops, points inside the outer loop are untrimmed and
-+// points outside it ARE trimmed. Flip test results accordingly.
-+bool ON_CurveTree::IsTrimmed(double u, double v, std::vector<long int>
*subset, bool pnpoly_state) {
-+ //std::cout << "u :" << u << ", v :" << v << "\n";
-+ int last_loop = 0;
-+ std::set<long int> loops_to_check;
-+ long int node_pos = 0;
-+ // First stage - identify which trimming loop(s) we care about, based on
loop UV bounding boxes
-+ while (last_loop != 1) {
-+ double *p_umin = &uv_bbox_values[nodes.at(node_pos+2)];
-+ double *p_vmin = &uv_bbox_values[nodes.at(node_pos+2)+1];
-+ double *p_umax = &uv_bbox_values[nodes.at(node_pos+2)+2];
-+ double *p_vmax = &uv_bbox_values[nodes.at(node_pos+2)+3];
-+ //std::cout << "loop " << node_pos << " bbox:" << (*p_umin) << "," <<
(*p_vmin) << "," << (*p_umax) << "," << (*p_vmax) << "\n";
-+ // Is uv point inside bbox?
-+ if (!( u < (*p_umin) || v < (*p_vmin) || u > (*p_umax) || v >
(*p_vmax) )) loops_to_check.insert(node_pos);
-+ // Jump the starting position to the next loop.
-+ node_pos = nodes.at(node_pos);
-+ if (node_pos == 0) last_loop = 1;
-+ }
-+ std::set<long int>::iterator l_it;
-+ if (loops_to_check.size() > 1) {
-+ std::cout << "Loops possibly containing UV pt (" << u << "," << v <<
"):";
-+ for(l_it = loops_to_check.begin(); l_it != loops_to_check.end();
++l_it) {
-+ std::cout << " " << (*l_it) << " ";
-+ }
-+ std::cout << "\n";
-+ for(l_it = loops_to_check.begin(); l_it != loops_to_check.end(); ++l_it) {
-+ long int current_node_pos = (*l_it) + 3;
-+ long int final_node_pos = (*l_it) + nodes.at((*l_it)+1) + 3;
-+ while (current_node_pos <= final_node_pos) {
-+ //std::cout << "loop " << (*l_it) << ", trim " <<
nodes.at(current_node_pos) << "\n";
-+ current_node_pos++;
-+ }
-+ }
-+ std::cout << "\n";
-+}
-+}
-+
-+ON_CurveTree::ON_CurveTree(const ON_BrepFace* face)
-+{
-+ // Save the face pointer associated with this tree, in case we
-+ // need to access data from the face
-+ ctree_face = face;
-+
-+ // We can find out in advance how many node elements we will have due to
-+ // trimming loops - populate those elements up front.
-+ long int elements = 0;
-+ for (int loop_index = 0; loop_index < face->LoopCount(); loop_index++) {
-+ elements += face->Loop(loop_index)->TrimCount();
-+ }
-+ elements += (face->LoopCount()) * NON_TRIM_LOOP_STEP;
-+ // Import to initialize to zero - used later as stopping criteria
-+ nodes.assign(elements, 0);
-+
-+ // Any node elements after those already in place will pertain to trim
-+ // nodes - to be able to easily distinguish when an index is referring
-+ // to a loop or a trim, record the index which marks the cross-over point
-+ // in the vector. The test is then a simple < or >= check.
-+ first_trim_node = nodes.size();
-+
-+ // Now that we have the setup, add actual information and handle the trims
-+ long int node_pos = 0;
-+ for (int loop_index = 0; loop_index < face->LoopCount(); loop_index++) {
-+ ON_BrepLoop *loop = face->Loop(loop_index);
-+ nodes.at(node_pos + 1) = loop->TrimCount();
-+ // Populate uv_bbox_values
-+ nodes.at(node_pos + 2) = uv_bbox_values.size();
-+ for (int i = 0; i < 2; ++i)
uv_bbox_values.push_back(std::numeric_limits<double>::infinity());
-+ for (int i = 2; i < 4; ++i) uv_bbox_values.push_back(-1 *
std::numeric_limits<double>::infinity());
-+
-+ for (int trim_index = 0; trim_index < loop->TrimCount(); trim_index++) {
-+ int curve_index = loop->Trim(trim_index)->TrimCurveIndexOf();
-+ long int current_trim_node =
node_pos+NON_TRIM_LOOP_STEP+trim_index;
-+ // Add "leaf" trim node from loop
-+ long int trim_root = this->New_Trim_Node(node_pos, curve_index,
0, 0);
-+ nodes.at(current_trim_node) = trim_root;
-+ // Build KDtree below "leaf" trim
-+ this->Subdivide_Trim_Node(trim_root,
face->Loop(loop_index)->Trim(trim_index));
-+ }
-+ // Now that we've handled the trims, build the loop bbox
-+ double *p_umin = &uv_bbox_values[nodes.at(node_pos+2)];
-+ double *p_vmin = &uv_bbox_values[nodes.at(node_pos+2)+1];
-+ double *p_umax = &uv_bbox_values[nodes.at(node_pos+2)+2];
-+ double *p_vmax = &uv_bbox_values[nodes.at(node_pos+2)+3];
-+ for (int trim_index = 0; trim_index < loop->TrimCount(); trim_index++) {
-+ long int current_trim_node =
nodes.at(node_pos+NON_TRIM_LOOP_STEP+trim_index);
-+ double *c_umin = &uv_bbox_values[nodes.at(current_trim_node+6)];
-+ double *c_vmin = &uv_bbox_values[nodes.at(current_trim_node+6)+1];
-+ double *c_umax = &uv_bbox_values[nodes.at(current_trim_node+6)+2];
-+ double *c_vmax = &uv_bbox_values[nodes.at(current_trim_node+6)+3];
-+ if (*c_umin < *p_umin) (*p_umin) = (*c_umin);
-+ if (*c_vmin < *p_vmin) (*p_vmin) = (*c_vmin);
-+ if (*c_umax > *p_umax) (*p_umax) = (*c_umax);
-+ if (*c_vmax > *p_vmax) (*p_vmax) = (*c_vmax);
-+ }
-+ std::cout << "loop " << node_pos << " bbox:" << (*p_umin) << "," <<
(*p_vmin) << "," << (*p_umax) << "," << (*p_vmax) << "\n";
-+
-+ // Identify the size of this loop node and store it in the first entry
-+ // to enable "walking" of the loops
-+ // Jump the starting position to the next loop.
-+ if (loop_index != face->LoopCount() - 1)
-+ nodes.at(node_pos) = node_pos + loop->TrimCount() +
NON_TRIM_LOOP_STEP + 1;
-+ node_pos = nodes.at(node_pos);
-+ }
-+}
-+
-+ON_CurveTree::~ON_CurveTree() {
-+}
-+
-+// Local Variables:
-+// tab-width: 8
-+// mode: C++
-+// c-basic-offset: 4
-+// indent-tabs-mode: t
-+// c-file-style: "stroustrup"
-+// End:
-+// ex: shiftwidth=4 tabstop=8
-
-Property changes on: src/libbrep/libbrep_curvetree.cpp
-___________________________________________________________________
-Added: svn:mime-type
- + text/plain
-Added: svn:eol-style
- + native
-
-Index: src/libbrep/libbrep_surfacetree.cpp
-===================================================================
---- src/libbrep/libbrep_surfacetree.cpp (revision 0)
-+++ src/libbrep/libbrep_surfacetree.cpp (revision 57887)
-@@ -0,0 +1,439 @@
-+/* L I B B R E P _ S U R F A C E T R E E . C P P
-+ * BRL-CAD
-+ *
-+ * Copyright (c) 2013-2020 United States Government as represented by
-+ * the U.S. Army Research Laboratory.
-+ *
-+ * 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.
-+ *
-+ * This library 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
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with this file; see the file named COPYING for more
-+ * information.
-+ */
-+/** @file libbrep_surfacetree.cpp
-+ *
-+ * Brief description
-+ *
-+ */
-+
-+#include <vector>
-+#include <map>
-+#include <set>
-+#include <queue>
-+#include <iostream>
-+
-+#include "libbrep_surfacetree.h"
-+
-+long int ON_SurfaceTree::New_Node(int parent, int umin, int umax, int vmin,
int vmax) {
-+ // Parent node of new node
-+ nodes.push_back(parent);
-+ // UV information
-+ nodes.push_back(umin);
-+ nodes.push_back(umax);
-+ nodes.push_back(vmin);
-+ nodes.push_back(vmax);
-+ // As yet, the node has no children.
-+ for (int i = 0; i < 4; ++i) nodes.push_back(0);
-+ ON_BoundingBox surf_bbox;
-+ bboxes.Append(surf_bbox);
-+ nodes.push_back(bboxes.Count() - 1);
-+ nodes.push_back(0); // We haven't tested for trimming curves yet.
-+ nodes.push_back(0); // No temporary nodes as yet.
-+ return nodes.size() - SURF_NODE_STEP;
-+}
-+
-+// Split a node to produce new nodes in both U and V directions
-+void ON_SurfaceTree::Node_Split_UV(double u_mid, double v_mid, std::pair<int,
std::vector<int> *> *node, std::queue<std::vector<int> *> *frame_arrays,
std::queue<std::pair<int, std::vector<int> *> > *node_queue) {
-+ std::vector<int> *parent_frame_index = node->second;
-+
-+ // Four new frame index arrays will be needed
-+ std::vector<int> *q1f = NULL;
-+ std::vector<int> *q2f = NULL;
-+ std::vector<int> *q3f = NULL;
-+ std::vector<int> *q4f = NULL;
-+
-+ // Add the midpoint U and V coordinates, which will be the
-+ // only UV values not already present in the double array
-+ uv_coords.push_back(u_mid);
-+ int umid_id = uv_coords.size() - 1;
-+ uv_coords.push_back(v_mid);
-+ int vmid_id = uv_coords.size() - 1;
-+
-+ // Create child nodes. Reuse frame arrays if any are available to reuse
-+
-+ // Create the SW node
-+ long int q1 = this->New_Node(node->first, nodes[node->first+1], umid_id,
nodes[node->first+3], vmid_id);
-+ nodes[node->first+5] = q1;
-+ if (!frame_arrays->empty()) {q1f = frame_arrays->front();
frame_arrays->pop();} else {q1f = new std::vector<int>;}
-+ q1f->assign(13, -1);
-+ q1f->at(0) = parent_frame_index->at(0);
-+ q1f->at(1) = parent_frame_index->at(9);
-+ q1f->at(2) = parent_frame_index->at(4);
-+ q1f->at(3) = parent_frame_index->at(10);
-+ q1f->at(4) = parent_frame_index->at(5);
-+ node_queue->push(std::make_pair(q1,q1f));
-+
-+ // Create the SE node
-+ long int q2 = this->New_Node(node->first, umid_id, nodes[node->first+2],
nodes[node->first+3], vmid_id);
-+ nodes[node->first+6] = q2;
-+ if (!frame_arrays->empty()) {q2f = frame_arrays->front();
frame_arrays->pop();} else {q2f = new std::vector<int>;}
-+ q2f->assign(13, -1);
-+ q2f->at(0) = parent_frame_index->at(9);
-+ q2f->at(1) = parent_frame_index->at(1);
-+ q2f->at(2) = parent_frame_index->at(12);
-+ q2f->at(3) = parent_frame_index->at(4);
-+ q2f->at(4) = parent_frame_index->at(7);
-+ node_queue->push(std::make_pair(q2,q2f));
-+
-+ // Create the NE node
-+ long int q3 = this->New_Node(node->first, umid_id, nodes[node->first+2],
vmid_id, nodes[node->first+4]);
-+ nodes[node->first+7] = q3;
-+ if (!frame_arrays->empty()) {q3f = frame_arrays->front();
frame_arrays->pop();} else {q3f = new std::vector<int>;}
-+ q3f->assign(13, -1);
-+ q3f->at(0) = parent_frame_index->at(4);
-+ q3f->at(1) = parent_frame_index->at(12);
-+ q3f->at(2) = parent_frame_index->at(2);
-+ q3f->at(3) = parent_frame_index->at(11);
-+ q3f->at(4) = parent_frame_index->at(8);
-+ node_queue->push(std::make_pair(q3,q3f));
-+
-+ // Create the NW node
-+ long int q4 = this->New_Node(node->first, nodes[node->first+1], umid_id,
vmid_id, nodes[node->first+4]);
-+ nodes[node->first+8] = q4;
-+ if (!frame_arrays->empty()) {q4f = frame_arrays->front();
frame_arrays->pop();} else {q4f = new std::vector<int>;}
-+ q4f->assign(13, -1);
-+ q4f->at(0) = parent_frame_index->at(10);
-+ q4f->at(1) = parent_frame_index->at(4);
-+ q4f->at(2) = parent_frame_index->at(11);
-+ q4f->at(3) = parent_frame_index->at(3);
-+ q4f->at(4) = parent_frame_index->at(6);
-+ node_queue->push(std::make_pair(q4,q4f));
-+}
-+
-+// Create two child nodes, splitting in the U direction
-+void ON_SurfaceTree::Node_Split_U(double u_mid, std::pair<int,
std::vector<int> *> *node, std::queue<std::vector<int> *> *frame_arrays,
std::queue<std::pair<int, std::vector<int> *> > *node_queue) {
-+ std::vector<int> *parent_frame_index = node->second;
-+
-+ // Two new frame index arrays will be needed
-+ std::vector<int> *q1f = NULL;
-+ std::vector<int> *q2f = NULL;
-+
-+ // Add the midpoint U coordinate, which will be the
-+ // only UV value not already present in the double array
-+ uv_coords.push_back(u_mid);
-+ int umid_id = uv_coords.size() - 1;
-+
-+ // Create child nodes. Reuse frame arrays if any are available to reuse
-+
-+ // Create the W node
-+ long int q1 = this->New_Node(node->first, nodes[node->first+1], umid_id,
nodes[node->first+3], nodes[node->first+4]);
-+ nodes[node->first+5] = q1;
-+ if (!frame_arrays->empty()) {q1f = frame_arrays->front();
frame_arrays->pop();} else {q1f = new std::vector<int>;}
-+ q1f->assign(13, -1);
-+ q1f->at(0) = parent_frame_index->at(0);
-+ q1f->at(1) = parent_frame_index->at(9);
-+ q1f->at(2) = parent_frame_index->at(11);
-+ q1f->at(3) = parent_frame_index->at(3);
-+ q1f->at(10) = parent_frame_index->at(10);
-+ q1f->at(12) = parent_frame_index->at(4);
-+ node_queue->push(std::make_pair(q1,q1f));
-+
-+ // Create the E node
-+ long int q2 = this->New_Node(node->first, umid_id, nodes[node->first+2],
nodes[node->first+3], nodes[node->first+4]);
-+ nodes[node->first+6] = q2;
-+ if (!frame_arrays->empty()) {q2f = frame_arrays->front();
frame_arrays->pop();} else {q2f = new std::vector<int>;}
-+ q2f->assign(13, -1);
-+ q2f->at(0) = parent_frame_index->at(9);
-+ q2f->at(1) = parent_frame_index->at(1);
-+ q2f->at(2) = parent_frame_index->at(2);
-+ q2f->at(3) = parent_frame_index->at(11);
-+ q2f->at(10) = parent_frame_index->at(4);
-+ q2f->at(12) = parent_frame_index->at(12);
-+ node_queue->push(std::make_pair(q2,q2f));
-+
-+}
-+
-+// Create two child nodes, splitting in the V direction
-+void ON_SurfaceTree::Node_Split_V(double v_mid, std::pair<int,
std::vector<int> *> *node, std::queue<std::vector<int> *> *frame_arrays,
std::queue<std::pair<int, std::vector<int> *> > *node_queue) {
-+ std::vector<int> *parent_frame_index = node->second;
-+
-+ // Two new frame index arrays will be needed
-+ std::vector<int> *q1f = NULL;
-+ std::vector<int> *q2f = NULL;
-+
-+ // Add the midpoint V coordinate, which will be the
-+ // only UV value not already present in the double array
-+ uv_coords.push_back(v_mid);
-+ int vmid_id = uv_coords.size() - 1;
-+
-+ // Create child nodes. Reuse frame arrays if any are available to reuse
-+
-+ // Create the S node
@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits