File: beziercurve.cc

package info (click to toggle)
asymptote 2.69%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 18,532 kB
  • sloc: cpp: 61,286; ansic: 48,418; python: 8,585; javascript: 4,283; sh: 4,069; perl: 1,564; lisp: 1,505; makefile: 609; yacc: 554; lex: 446
file content (94 lines) | stat: -rw-r--r-- 1,828 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*****
 * drawbezierpatch.cc
 * Author: John C. Bowman
 *
 * Render a Bezier curve.
 *****/

#include "bezierpatch.h"
#include "beziercurve.h"

namespace camp {

#ifdef HAVE_GL

void BezierCurve::init(double res)
{
  this->res=res;
  res2=res*res;

  MaterialIndex=materialIndex;
}

inline triple normal(triple bP, triple bPP)
{
  return dot(bP,bP)*bPP-dot(bP,bPP)*bP;
}

void BezierCurve::render(const triple *p, bool straight)
{
  triple p0=p[0];
  triple p3=p[3];
  triple n0,n1;

  if(straight) {
    n0=n1=triple(0.0,0.0,1.0);
  } else {
    triple p1=p[1];
    triple p2=p[2];

    n0=normal(p1-p0,p0+p2-2.0*p1);
    n1=normal(p3-p2,p3+p1-2.0*p2);
  }

  GLuint i0=data.vertex(p0,n0);
  GLuint i3=data.vertex(p3,n1);

  if(straight) {
    std::vector<GLuint> &q=data.indices;
    q.push_back(i0);
    q.push_back(i3);
  } else
    render(p,i0,i3);
  append();
}

// Use a uniform partition to draw a Bezier curve.
// p is an array of 4 triples representing the control points.
// Ii are the vertex indices.
void BezierCurve::render(const triple *p, GLuint I0, GLuint I1)
{
  triple p0=p[0];
  triple p1=p[1];
  triple p2=p[2];
  triple p3=p[3];
  if(Straightness(p0,p1,p2,p3) < res2) { // Segment is flat
    triple P[]={p0,p3};
    if(!offscreen(2,P)) {
      std::vector<GLuint> &q=data.indices;
      q.push_back(I0);
      q.push_back(I1);
    }
  } else { // Segment is not flat
    if(offscreen(4,p)) return;
    triple m0=0.5*(p0+p1);
    triple m1=0.5*(p1+p2);
    triple m2=0.5*(p2+p3);
    triple m3=0.5*(m0+m1);
    triple m4=0.5*(m1+m2);
    triple m5=0.5*(m3+m4);

    triple s0[]={p0,m0,m3,m5};
    triple s1[]={m5,m4,m2,p3};

    triple n0=normal(bezierPh(p0,p1,p2,p3),bezierPPh(p0,p1,p2,p3));
    GLuint i0=data.vertex(m5,n0);

    render(s0,I0,i0);
    render(s1,i0,I1);
  }
}

#endif

} //namespace camp