Skip to content
Snippets Groups Projects
Select Git revision
  • 9af627087fcd1197d1f7d10cc8a20894616576f0
  • master default
  • cgnsUnstructured
  • partitioning
  • poppler
  • HighOrderBLCurving
  • gmsh_3_0_4
  • gmsh_3_0_3
  • gmsh_3_0_2
  • gmsh_3_0_1
  • gmsh_3_0_0
  • gmsh_2_16_0
  • gmsh_2_15_0
  • gmsh_2_14_1
  • gmsh_2_14_0
  • gmsh_2_13_2
  • gmsh_2_13_1
  • gmsh_2_12_0
  • gmsh_2_11_0
  • gmsh_2_10_1
  • gmsh_2_10_0
  • gmsh_2_9_3
  • gmsh_2_9_2
  • gmsh_2_9_1
  • gmsh_2_9_0
  • gmsh_2_8_6
26 results

Nurbs.cpp

Blame
  • Forked from gmsh / gmsh
    Source project has a limited visibility.
    Nurbs.cpp 11.45 KiB
    // $Id: Nurbs.cpp,v 1.18 2006-01-07 16:12:32 geuzaine Exp $
    //
    // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
    //
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2 of the License, or
    // (at your option) any later version.
    //
    // This program 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 General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software
    // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
    // USA.
    // 
    // Please report all bugs and problems to <gmsh@geuz.org>.
    
    #include "Gmsh.h"
    #include "Nurbs.h"
    #include "Mesh.h"
    #include "Geo.h"
    #include "GeoUtils.h"
    #include "Create.h"
    #include "CAD.h"
    
    extern Mesh *THEM;
    
    // Cubic spline
    
    Vertex InterpolateCubicSpline(Vertex * v[4], double t, double mat[4][4],
                                  int derivee, double t1, double t2)
    {
      Vertex V;
      int i, j;
      double vec[4], T[4];
    
      V.Pos.X = V.Pos.Y = V.Pos.Z = 0.0;
      V.lc = (1 - t) * v[1]->lc + t * v[2]->lc;
      V.w = (1 - t) * v[1]->w + t * v[2]->w;
    
      if(derivee) {
        T[3] = 0.;
        T[2] = 1.;
        T[1] = 2. * t;
        T[0] = 3. * t * t;
      }
      else {
        T[3] = 1.;
        T[2] = t;
        T[1] = t * t;
        T[0] = t * t * t;
      }
    
      for(i = 0; i < 4; i++) {
        vec[i] = 0.0;
      }
    
      /* X */
      for(i = 0; i < 4; i++) {
        for(j = 0; j < 4; j++) {
          vec[i] += mat[i][j] * v[j]->Pos.X;
        }
      }
    
      for(j = 0; j < 4; j++) {
        V.Pos.X += T[j] * vec[j];
        vec[j] = 0.0;
      }
    
      /* Y */
      for(i = 0; i < 4; i++) {
        for(j = 0; j < 4; j++) {
          vec[i] += mat[i][j] * v[j]->Pos.Y;
        }
      }
    
      for(j = 0; j < 4; j++) {
        V.Pos.Y += T[j] * vec[j];
        vec[j] = 0.0;
      }
    
      /* Z */
      for(i = 0; i < 4; i++) {
        for(j = 0; j < 4; j++) {
          vec[i] += mat[i][j] * v[j]->Pos.Z;
        }
      }
      for(j = 0; j < 4; j++) {
        V.Pos.Z += T[j] * vec[j];
        vec[j] = 0.0;
      }
    
      if(derivee) {
        V.Pos.X /= ((t2 - t1));
        V.Pos.Y /= ((t2 - t1));
        V.Pos.Z /= ((t2 - t1));
      }
    
      return V;
    }
    
    
    // Uniform BSplines
    
    Vertex InterpolateUBS(Curve * Curve, double u, int derivee)
    {
      int NbControlPoints, NbCurves, iCurve;
      double t, t1, t2;
      Vertex *v[4];
    
      NbControlPoints = List_Nbr(Curve->Control_Points);
      NbCurves = NbControlPoints - 3;
    
      iCurve = (int)(u * (double)NbCurves) + 1;
    
      if(iCurve > NbCurves)
        iCurve = NbCurves;
      else if (iCurve < 1)
        iCurve = 1;
    
      t1 = (double)(iCurve - 1) / (double)(NbCurves);
      t2 = (double)(iCurve) / (double)(NbCurves);
    
      t = (u - t1) / (t2 - t1);
    
      List_Read(Curve->Control_Points, iCurve - 1, &v[0]);
      List_Read(Curve->Control_Points, iCurve, &v[1]);
      List_Read(Curve->Control_Points, iCurve + 1, &v[2]);
      List_Read(Curve->Control_Points, iCurve + 2, &v[3]);
    
      return InterpolateCubicSpline(v, t, Curve->mat, derivee, t1, t2);
    }
    
    // Non Uniform BSplines
    
    int findSpan(double u, int deg, int n, float *U)
    {
      if(u >= U[n])
        return n - 1;
      if(u <= U[0])
        return deg;
    
      int low = deg;
      int high = n + 1;
      int mid = (low + high) / 2;
    
      while(u < U[mid] || u >= U[mid + 1]) {
        if(u < U[mid])
          high = mid;
        else
          low = mid;
        mid = (low + high) / 2;
      }
      return mid;
    }
    
    void basisFuns(double u, int i, int deg, float *U, double *N)
    {
      double left[1000];
      double *right = &left[deg + 1];
    
      double temp, saved;
    
      //N.resize(deg+1) ;
    
      N[0] = 1.0;
      for(int j = 1; j <= deg; j++) {
        left[j] = u - U[i + 1 - j];
        right[j] = U[i + j] - u;
        saved = 0.0;
        for(int r = 0; r < j; r++) {
          temp = N[r] / (right[r + 1] + left[j - r]);
          N[r] = saved + right[r + 1] * temp;
          saved = left[j - r] * temp;
        }
        N[j] = saved;
      }
    }
    
    Vertex InterpolateNurbs(Curve * Curve, double u, int derivee)
    {
      static double Nb[1000];
      int span =
        findSpan(u, Curve->degre, List_Nbr(Curve->Control_Points), Curve->k);
      Vertex p, *v;
    
      basisFuns(u, span, Curve->degre, Curve->k, Nb);
      p.Pos.X = p.Pos.Y = p.Pos.Z = p.w = p.lc = 0.0;
      for(int i = Curve->degre; i >= 0; --i) {
        List_Read(Curve->Control_Points, span - Curve->degre + i, &v);
        p.Pos.X += Nb[i] * v->Pos.X;
        p.Pos.Y += Nb[i] * v->Pos.Y;
        p.Pos.Z += Nb[i] * v->Pos.Z;
        p.w += Nb[i] * v->w;
        p.lc += Nb[i] * v->lc;
      }
      return p;
    }
    
    Vertex InterpolateNurbsSurface(Surface * s, double u, double v)
    {
      int uspan = findSpan(u, s->OrderU, s->Nu, s->ku);
      int vspan = findSpan(v, s->OrderV, s->Nv, s->kv);
      double Nu[1000], Nv[1000];
      Vertex sp, temp[1000], *pv;
    
      basisFuns(u, uspan, s->OrderU, s->ku, Nu);
      basisFuns(v, vspan, s->OrderV, s->kv, Nv);
    
      int l, ll, kk;
      for(l = 0; l <= s->OrderV; l++) {
        temp[l].Pos.X = temp[l].Pos.Y = temp[l].Pos.Z = temp[l].w = temp[l].lc =
          0.0;
        for(int k = 0; k <= s->OrderU; k++) {
          kk = uspan - s->OrderU + k;
          ll = vspan - s->OrderV + l;
          List_Read(s->Control_Points, kk + s->Nu * ll, &pv);
          temp[l].Pos.X += Nu[k] * pv->Pos.X;
          temp[l].Pos.Y += Nu[k] * pv->Pos.Y;
          temp[l].Pos.Z += Nu[k] * pv->Pos.Z;
          temp[l].w += Nu[k] * pv->w;
          temp[l].lc += Nu[k] * pv->lc;
        }
      }
      sp.Pos.X = sp.Pos.Y = sp.Pos.Z = sp.w = sp.lc = 0.0;
      for(l = 0; l <= s->OrderV; l++) {
        sp.Pos.X += Nv[l] * temp[l].Pos.X;
        sp.Pos.Y += Nv[l] * temp[l].Pos.Y;
        sp.Pos.Z += Nv[l] * temp[l].Pos.Z;
        sp.w += Nv[l] * temp[l].w;
        sp.lc += Nv[l] * temp[l].lc;
      }
      return sp;
    }
    
    
    // Surface creation helpers
    
    void CreateNurbsSurfaceSupport(int Num, int Order1, int Order2,
                                   List_T * List, List_T * ku, List_T * kv)
    {
      // This routine has been heavily modified to fit the new interfaces,
      // but has not been tested since then. It's probably full of bugs
      // now.
      List_T *ListOfDouble_L;
      List_T *ListCP = List_Create(2, 2, sizeof(int));
    
      for(int j = 0; j < List_Nbr(List); j++) {
        List_Read(List, j, &ListOfDouble_L);
        for(int i = 0; i < List_Nbr(ListOfDouble_L); i++) {
          double d;
          List_Read(ListOfDouble_L, i, &d);
          int N = (int)d;
          List_Add(ListCP, &N);
        }
      }
      List_Read(List, 0, &ListOfDouble_L);
      int Nu = List_Nbr(List);
      int Nv = List_Nbr(ListOfDouble_L);
    
      Surface *s = Create_Surface(Num, MSH_SURF_NURBS);
      s->Support = NULL;
      s->Control_Points = List_Create(4, 1, sizeof(Vertex *));
      s->OrderU = Order1;
      s->OrderV = Order2;
      s->Nu = Nu;
      s->Nv = Nv;
      for(int i = 0; i < List_Nbr(ListCP); i++) {
        int j;
        List_Read(ListCP, i, &j);
        Vertex *v = FindPoint(j, THEM);
        if(v){
          List_Add(s->Control_Points, &v);
        }
        else{
          Msg(GERROR, "Unknown control point %d in nurbs surface", j);
        }
      }
    
      s->ku = (float *)malloc(List_Nbr(ku) * sizeof(float));
      s->kv = (float *)malloc(List_Nbr(kv) * sizeof(float));
    
      double kumin = 0., kumax = 1.;
      double kvmin = 0., kvmax = 1.;
    
      for(int i = 0; i < List_Nbr(ku); i++) {
        double d;
        List_Read(ku, i, &d);
        float f = (float)((d - kumin) / (kumax - kumin));
        s->ku[i] = f;
      }
      for(int i = 0; i < List_Nbr(kv); i++) {
        double d;
        List_Read(kv, i, &d);
        float f = (float)((d - kvmin) / (kvmax - kvmin));
        s->kv[i] = f;
      }
    
      List_Delete(ListCP);
    
      End_Surface(s);
      Tree_Add(THEM->Surfaces, &s);
    }
    
    void CreateNurbsSurface(int Num, int Order1, int Order2, List_T * List,
                            List_T * ku, List_T * kv)
    {
      // This routine has been heavily modified to fit the new interfaces,
      // but has not been tested since then. It's probably full of bugs
      // now.
    
      List_T *ListOfDouble_L, *Listint, *ListCP;
      int Loop[4];
    
      ListCP = List_Create(2, 2, sizeof(int));
    
      double kumin, kumax;
      List_Read(ku, 0, &kumin);
      List_Read(ku, List_Nbr(ku) - 1, &kumax);
      double kvmin, kvmax;
      List_Read(kv, 0, &kvmin);
      List_Read(kv, List_Nbr(kv) - 1, &kvmax);
      for(int j = 0; j < List_Nbr(List); j++) {
        List_Read(List, j, &ListOfDouble_L);
        for(int i = 0; i < List_Nbr(ListOfDouble_L); i++) {
          double d;
          List_Read(ListOfDouble_L, i, &d);
          int N = (int)d;
          List_Add(ListCP, &N);
        }
      }
    
      // 1st and 3rd gen
      List_Read(List, 0, &ListOfDouble_L);
      Listint = ListOfDouble2ListOfInt(ListOfDouble_L);
      if(recognize_seg(MSH_SEGM_NURBS, Listint, &Loop[0])) {
      }
      else {
        Loop[0] = NEWREG();
        Curve *c = Create_Curve(Loop[0], MSH_SEGM_NURBS, Order1, Listint, NULL, 
    			    -1, -1, kumin, kumax);
        Tree_Add(THEM->Curves, &c);
        CreateReversedCurve(THEM, c);
        c->k = (float *)malloc(4 * List_Nbr(ku) * sizeof(float));
        for(int i = 0; i < List_Nbr(ku); i++) {
          double d;
          List_Read(ku, i, &d);
          c->k[i] = (float)d /*((d-kumin)/(kumax-kumin)) */ ;
        }
      }
      List_Delete(Listint);
    
      List_Read(List, List_Nbr(List) - 1, &ListOfDouble_L);
      Listint = ListOfDouble2ListOfInt(ListOfDouble_L);
      if(recognize_seg(MSH_SEGM_NURBS, Listint, &Loop[2])) {
      }
      else {
        Loop[2] = NEWREG();
        Curve *c = Create_Curve(Loop[2], MSH_SEGM_NURBS, Order1, Listint, NULL, 
    			    -1, -1, kumin, kumax);
        Tree_Add(THEM->Curves, &c);
        CreateReversedCurve(THEM, c);
        c->k = (float *)malloc(4 * List_Nbr(ku) * sizeof(float));
        for(int i = 0; i < List_Nbr(ku); i++) {
          double d;
          List_Read(ku, i, &d);
          c->k[i] = (float)d /*((d-kumin)/(kumax-kumin)) */ ;
        }
      }
      List_Delete(Listint);
    
      // 2nd and 4th gen
      List_T *List1 = List_Create(List_Nbr(List), 1, sizeof(double));
      List_T *List2 = List_Create(List_Nbr(List), 1, sizeof(double));
      for(int i = 0; i < List_Nbr(List); i++) {
        List_Read(List, i, &ListOfDouble_L);
        List_Add(List1, List_Pointer(ListOfDouble_L, 0));
        List_Add(List2, List_Pointer(ListOfDouble_L, List_Nbr(ListOfDouble_L) - 1));
      }
    
      Listint = ListOfDouble2ListOfInt(List1);
      if(recognize_seg(MSH_SEGM_NURBS, Listint, &Loop[1])) {
      }
      else {
        Loop[1] = NEWREG();
        Curve *c = Create_Curve(Loop[1], MSH_SEGM_NURBS, Order2, Listint, NULL, 
    			    -1, -1, kumin, kumax);
        Tree_Add(THEM->Curves, &c);
        CreateReversedCurve(THEM, c);
        c->k = (float *)malloc(4 * List_Nbr(kv) * sizeof(float));
        for(int i = 0; i < List_Nbr(kv); i++) {
          double d;
          List_Read(kv, i, &d);
          c->k[i] = (float)d /*((d-kvmin)/(kvmax-kvmin)) */ ;
        }
      }
      List_Delete(Listint);
    
      Listint = ListOfDouble2ListOfInt(List2);
      if(recognize_seg(MSH_SEGM_NURBS, Listint, &Loop[3])) {
      }
      else {
        Loop[3] = NEWREG();
        Curve *c = Create_Curve(Loop[3], MSH_SEGM_NURBS, Order2, Listint, NULL,
    			    -1, -1, kumin, kumax);
        Tree_Add(THEM->Curves, &c);
        CreateReversedCurve(THEM, c);
        c->k = (float *)malloc(4 * List_Nbr(kv) * sizeof(float));
        for(int i = 0; i < List_Nbr(kv); i++) {
          double d;
          List_Read(kv, i, &d);
          c->k[i] = (float)d /*((d-kvmin)/(kvmax-kvmin)) */ ;
        }
      }
      List_Delete(Listint);
      List_Delete(List1);
      List_Delete(List2);
    
      Listint = List_Create(10, 10, sizeof(int));
      int l0 = -Loop[0];
      List_Add(Listint, &l0);
      List_Add(Listint, &Loop[1]);
      List_Add(Listint, &Loop[2]);
      int l3 = -Loop[3];
      List_Add(Listint, &l3);
    
      int topnew = NEWREG();
      CreateNurbsSurfaceSupport(topnew, Order1, Order2, List, ku, kv);
    
      int il = NEWREG();
      SurfaceLoop *l = Create_SurfaceLoop(il, Listint);
      Tree_Add(THEM->SurfaceLoops, &l);
      List_Reset(Listint);
      List_Add(Listint, &il);
    
      Surface *s = Create_Surface(NEWREG(), MSH_SURF_TRIMMED);
      setSurfaceGeneratrices(s, Listint);
      s->Support = s;
      End_Surface(s);
      Tree_Add(THEM->Surfaces, &s);
    
      List_Delete(Listint);
      List_Delete(ListCP);
    }