File: vtkPolyPlane.cxx

package info (click to toggle)
vtk6 6.3.0%2Bdfsg2-8.1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 118,972 kB
  • sloc: cpp: 1,442,790; ansic: 113,395; python: 72,383; tcl: 46,998; xml: 8,119; yacc: 4,525; java: 4,239; perl: 3,108; lex: 1,694; sh: 1,093; asm: 154; makefile: 68; objc: 17
file content (314 lines) | stat: -rw-r--r-- 9,451 bytes parent folder | download | duplicates (5)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPolyPlane.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkPolyPlane.h"

#include "vtkPolyLine.h"
#include "vtkDoubleArray.h"
#include "vtkLine.h"
#include "vtkPoints.h"
#include "vtkObjectFactory.h"
#include "vtkMath.h"

//----------------------------------------------------------------------------
vtkStandardNewMacro(vtkPolyPlane);
vtkCxxSetObjectMacro( vtkPolyPlane, PolyLine, vtkPolyLine );

//----------------------------------------------------------------------------
vtkPolyPlane::vtkPolyPlane()
{
  this->ExtrusionDirection[0] = 0.0;
  this->ExtrusionDirection[1] = 0.0;
  this->ExtrusionDirection[2] = 1.0;

  this->PolyLine = NULL;
  this->Normals = NULL;
}

//----------------------------------------------------------------------------
vtkPolyPlane::~vtkPolyPlane()
{
  this->SetPolyLine( NULL );

  if (this->Normals)
    {
    this->Normals->Delete();
    this->Normals = NULL;
    }
}

//----------------------------------------------------------------------------
unsigned long vtkPolyPlane::GetMTime()
{
  unsigned long mTime = this->Superclass::GetMTime();

  if (this->PolyLine)
    {
    unsigned long p1Time;
    p1Time = this->PolyLine->GetMTime();
    mTime = ( p1Time > mTime ? p1Time : mTime );
    }

  return mTime;
}

//----------------------------------------------------------------------------
// This function returns 1 if p3 is to the left the directed line from p1 to p2
// and -1 otherwise
// This is computed by testing the determinant:
// | 1 p1[0] p1[1] |
// | 1 p2[0] p2[1] |
// | 1 p3[0] p3[1] |
// which is positive if p3 is to the left of the directed line from p1 to p2,
// zero if p3 is on the line and negative if p3 is to the right of the line.
// Credit: Jack Snoeyink's computational geometry course at UNC
static bool leftOf(double p1[2], double p2[2], double p3[2])
{
  double tmp = p1[0] * p2[1] + p1[1] * p3[0] + p2[0] * p3[1]
             - p1[1] * p2[0] - p3[1] * p1[0] - p3[0] * p2[1];
  return tmp > 0;
}

//----------------------------------------------------------------------------
void vtkPolyPlane::ComputeNormals()
{
  if (!this->PolyLine)
    {
    return;
    }

  if (this->GetMTime() > this->NormalComputeTime.GetMTime())
    {
    // Recompute the normal array.

    if (this->Normals)
      {
      // Delete the array if it already exists. We will reallocate later.
      this->Normals->Delete();
      this->Normals = NULL;
      }

    vtkPoints *points = this->PolyLine->GetPoints();
    const vtkIdType nPoints = points->GetNumberOfPoints();
    const vtkIdType nLines = nPoints -1;

    // Allocate an array to store the normals

    this->Normals = vtkDoubleArray::New();
    this->Normals->SetNumberOfComponents(3);
    this->Normals->Allocate(3*nLines);
    this->Normals->SetName("Normals");
    this->Normals->SetNumberOfTuples(nLines);

    // Now interate through all the lines and compute normal of each plane
    // in the polyplane.

    double v1[3], p[3], n[3];

    for (int pIdx = 0; pIdx < nLines; ++pIdx)
      {
      // Compute the plane normal for this segment by taking the cross product
      // of the line direction and the extrusion direction.

      points->GetPoint(pIdx, p);
      points->GetPoint(pIdx+1, v1);

      // The line direction vector
      v1[0] -= p[0];
      v1[1] -= p[1];
      v1[2] -= p[2];

      // 'n' is the computed normal.
      vtkMath::Cross( v1, this->ExtrusionDirection, n );
      vtkMath::Normalize(n);

      // Store the normal in our array.
      this->Normals->SetTuple(pIdx, n);
      }
    }
}

//----------------------------------------------------------------------------
// Evaluate the distance to the poly plane for point x[3].
double vtkPolyPlane::EvaluateFunction(double x[3])
{
  // Sanity check
  if (!this->PolyLine || !this->PolyLine->GetPoints())
    {
    return 0;
    }

  double xFlat[3] = {x[0], x[1], 0.0};

  // No error checking, for speed... We will assume that we have a polyline
  // and that it has at least 2 points.
  // traverse the list of points in the polyline.
  vtkPoints *points = this->PolyLine->GetPoints();

  const vtkIdType nPoints = points->GetNumberOfPoints();
  const vtkIdType nLines = nPoints -1;

  // At least 2 points needed to define a polyplane.
  if (nLines < 1)
    {
    return 0;
    }

  // compute normals
  this->ComputeNormals();


  double p1[3], p2[3], t, closest[3];
  double minDistance2 = VTK_DOUBLE_MAX, distance2, signedDistance = VTK_DOUBLE_MAX, sign = 1;

  // Iterate through all the lines.

  for (int pIdx = 0; pIdx < nLines; ++pIdx)
    {

    // Get the end points of this line segment in the polyline
    points->GetPoint(pIdx, p1);
    points->GetPoint(pIdx+1, p2);

    // Flatten it.
    p1[2] = 0;
    p2[2] = 0;

    // Compute distance-squared to finite line. Store the closest point.
    distance2 = vtkLine::DistanceToLine( xFlat, p1, p2, t, closest );

    // if the closest point on the line is on the segment
    if (t >= 0 && t <= 1)
      {
      // if this is the minimum distance found, use that distance
      // and record whether it was right of or left of the line
      if (distance2 < minDistance2)
        {
        minDistance2 = distance2;
        sign = leftOf(p1,p2,xFlat) ? 1 : -1;
        }
      }
    // if the closest point on the line is before the segment starts
    else if (t < 0)
      {
      // compute the distance to the first point on the segment
      distance2 = vtkMath::Distance2BetweenPoints(p1,xFlat);
      // if that is the closest distance use that distance
      if (distance2 < minDistance2)
        {
        minDistance2 = distance2;
        // if this is not the first segment
        if (pIdx > 0)
          {
          double p0[3];
          points->GetPoint(pIdx-1,p0);
          bool leftOf01 = leftOf(p0,p1,xFlat);
          bool leftOf12 = leftOf(p1,p2,xFlat);
          // if the segment before turned left to make this one,
          // the point is to the left only if it is left of both of them
          if (leftOf(p0,p1,p2))
            {
            sign = (leftOf01 && leftOf12) ? 1 : -1;
            }
          // if the segment before turned right to make this one,
          // the point is to the left if it is left of either one
          else
            {
            sign = (leftOf01 || leftOf12) ? 1 : -1;
            }
          }
        // if this is the first segment record if the point is right of
        // or left of the line
        else
          {
          sign = leftOf(p1,p2,xFlat) ? 1 : -1;
          }
        }
      }
    // if the closest point is after the segment ends
    else if (t > 1)
      {
      // compute the distance to the last point on the segment
      distance2 = vtkMath::Distance2BetweenPoints(p2,xFlat);
      // if that is closer than the minimum distance
      if (distance2 < minDistance2)
        {
        // record the distance and
        minDistance2 = distance2;
        // if this is not the last segment
        if (pIdx + 1 < nLines)
          {
          double p3[3];
          points->GetPoint(pIdx+2,p3);
          bool leftOf12 = leftOf(p1,p2,xFlat);
          bool leftOf23 = leftOf(p2,p3,xFlat);
          // if the turn at the end of this segment is a left turn
          // the point is left of the polyline only if left of both
          if (leftOf(p1,p2,p3))
            {
            sign = (leftOf12 && leftOf23) ? 1 : -1;
            }
          // if the turn is a right turn, the point is left of the
          // polyline if it is left of either
          else
            {
            sign = (leftOf12 || leftOf23) ? 1 : -1;
            }
          }
        // if this is the last segment record if the point
        // is left of the segment
        else
          {
          sign = leftOf(p1,p2,xFlat) ? 1 : -1;
          }
        }
      }
    }
  // compute the signed distance to the point
  // negative if it is right of the polyline
  signedDistance = sqrt(minDistance2) * sign;

  return signedDistance;
}

//----------------------------------------------------------------------------
// Evaluate function gradient at point x[3]. We simply return [0,1,0], ie the
// Y Axis.
void vtkPolyPlane::EvaluateGradient(double vtkNotUsed(x)[3], double n[3])
{
  n[0] = 0;
  n[1] = 1;
  n[2] = 0;
}

//----------------------------------------------------------------------------
void vtkPolyPlane::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "ExtrusionDirection: (" << this->ExtrusionDirection[0] << ", "
    << this->ExtrusionDirection[1] << ", " << this->ExtrusionDirection[2] << ")\n";

  os << indent << "PolyLine: " << this->PolyLine << "\n";
  if (this->PolyLine)
    {
    this->PolyLine->PrintSelf(os,indent.GetNextIndent());
    }

  os << indent << "Normals: " << this->Normals << "\n";
  if (this->Normals)
    {
    this->Normals->PrintSelf(os,indent.GetNextIndent());
    }
}