vtkVectorGlyph.C 12.3 KB
Newer Older
hrchilds's avatar
hrchilds committed
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
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    $RCSfile: vtkVectorGlyph.cxx,v $
  Language:  C++
  Date:      $Date: 2001/03/20 14:10:58 $
  Version:   $Revision: 1.1 $
  Thanks:    Hank Childs, B Division, Lawrence Livermore Nat'l Laboratory

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
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 name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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 REGENTS 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 "vtkVectorGlyph.h"
hrchilds's avatar
hrchilds committed
44

hrchilds's avatar
hrchilds committed
45 46
#include <math.h>

hrchilds's avatar
hrchilds committed
47
#include <vtkCellArray.h>
48 49
#include <vtkInformation.h>
#include <vtkInformationVector.h>
hrchilds's avatar
hrchilds committed
50
#include <vtkObjectFactory.h>
hrchilds's avatar
hrchilds committed
51
#include <vtkPolyData.h>
pugmire's avatar
pugmire committed
52 53 54 55
#include <vtkSphereSource.h>
#include <vtkTransformFilter.h>
#include <vtkTransform.h>

hrchilds's avatar
hrchilds committed
56
// ****************************************************************************
hrchilds's avatar
hrchilds committed
57 58 59
//  Modifications:
//    Kathleen Bonnell, Wed Mar  6 17:10:03 PST 2002 
//    Replace 'New' method with Macro to match VTK 4.0 API
hrchilds's avatar
hrchilds committed
60
// ****************************************************************************
hrchilds's avatar
hrchilds committed
61 62 63

vtkStandardNewMacro(vtkVectorGlyph);

hrchilds's avatar
hrchilds committed
64 65 66 67 68
// ****************************************************************************
//  Modifications:
//    Jeremy Meredith, Fri Nov 21 12:31:16 PST 2003
//    Added origin offset to the x position.  This lets the glyphs originate
//    or terminate at the nodes (instead of always being centered on them).
hrchilds's avatar
hrchilds committed
69 70 71 72 73
//
//    Jeremy Meredith, Mon Mar 19 14:33:15 EDT 2007
//    Added settings to draw the stem as a cylinder (vs a line), and its
//    width, to increase the number of polygons, and to cap the ends of
//    the cone/cylinder.
pugmire's avatar
pugmire committed
74 75 76 77
//
//    Dave Pugmire, Mon Jul 19 09:38:17 EDT 2010
//    Add ellipsoid glyphing.
//    
hrchilds's avatar
hrchilds committed
78
// ****************************************************************************
hrchilds's avatar
hrchilds committed
79 80 81

vtkVectorGlyph::vtkVectorGlyph()
{
pugmire's avatar
pugmire committed
82
  Arrow = 1;
hrchilds's avatar
hrchilds committed
83 84 85 86
  LineStem = 1;
  HighQuality = 0;
  CapEnds = 0;
  StemWidth = 0.08;
hrchilds's avatar
hrchilds committed
87 88 89
  MakeHead = 1;
  HeadSize = 0.25;
  ConeHead = 1;
hrchilds's avatar
hrchilds committed
90
  OriginOffset = 0.;
hrchilds's avatar
hrchilds committed
91 92 93 94 95 96 97 98
}


// ***************************************************************************
//  Modifications:
//    Kathleen Bonnell, Mon Oct 29 13:22:36 PST 2001
//    Make pt of type vtkIdType to match VTK 4.0 API.
//
hrchilds's avatar
hrchilds committed
99 100 101 102
//    Jeremy Meredith, Fri Nov 21 12:31:16 PST 2003
//    Added origin offset to the x position.  This lets the glyphs originate
//    or terminate at the nodes (instead of always being centered on them).
//
hrchilds's avatar
hrchilds committed
103 104 105 106 107
//    Jeremy Meredith, Mon Mar 19 14:33:15 EDT 2007
//    Added settings to draw the stem as a cylinder (vs a line), and its
//    width, to increase the number of polygons, and to cap the ends of
//    the cone/cylinder.
//
108 109 110
//    Hank Childs, Sun Jan 24 10:26:07 PST 2010
//    Fix problem where glyph heads don't show up in 2D.
//
pugmire's avatar
pugmire committed
111 112 113
//    Dave Pugmire, Mon Jul 19 09:38:17 EDT 2010
//    Add ellipsoid glyphing.    
//
hrchilds's avatar
hrchilds committed
114 115
// ****************************************************************************

116 117
int
vtkVectorGlyph::RequestData(
bonnell's avatar
bonnell committed
118 119 120
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
hrchilds's avatar
hrchilds committed
121
{
122 123 124 125 126 127 128 129 130 131
    vtkDebugMacro(<<"Executing vtkVectorGlyph");

    // get the info objects
    vtkInformation *outInfo = outputVector->GetInformationObject(0);

    //
    // Initialize some frequently used values.
    //
    vtkPolyData *output = vtkPolyData::SafeDownCast(
        outInfo->Get(vtkDataObject::DATA_OBJECT()));
hrchilds's avatar
hrchilds committed
132 133 134 135 136 137 138 139 140

    vtkPoints *pts = vtkPoints::New();
    output->SetPoints(pts);
    pts->Delete();
  
    vtkCellArray *lines = vtkCellArray::New();
    output->SetLines(lines);
    lines->Delete();

hrchilds's avatar
hrchilds committed
141
    vtkCellArray *polys = vtkCellArray::New();
hrchilds's avatar
hrchilds committed
142 143 144
    output->SetPolys(polys);
    polys->Delete();

pugmire's avatar
pugmire committed
145
    if (Arrow)
hrchilds's avatar
hrchilds committed
146
    {
pugmire's avatar
pugmire committed
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
        //
        // The vector will be with the bounding box x,y,z=-0.5,0.5.
        // The head will start at (0.5, 0., 0.) and
        // the tail will end at (-0.5,0.,0.)
        // 
        float realHeadSize = MakeHead ? this->HeadSize : 0;
        float endOfHead = 0.5 - realHeadSize;
        float proportion = realHeadSize;
        float cylThickness = this->StemWidth;
        
        vtkIdType pt[4];
        
        // Determine the number of points around the glyph cone/cylinder
        // (For a 2D glyph, 2 steps makes a triangle head & rectangle stem.)
        int nSteps = (!ConeHead) ? 2 : (HighQuality ? 16 : 6);
        
        // Determine the total number of points
        int nPts = 3 + nSteps + (LineStem ? 0 : nSteps*2);
        pts->SetNumberOfPoints(nPts);
        
        // Add the points along the central axis
        pts->SetPoint(0, OriginOffset + 0.5, 0., 0.);
        pts->SetPoint(1, OriginOffset - 0.5, 0., 0.);
        pts->SetPoint(2, OriginOffset + endOfHead, 0., 0.);
        
        // Add the points around the base of the cone
hrchilds's avatar
hrchilds committed
173 174 175
        for (int i=0; i<nSteps; i++)
        {
            float theta = 2*M_PI * float(i)/float(nSteps);
pugmire's avatar
pugmire committed
176 177 178 179 180 181 182 183
            float x = OriginOffset + endOfHead;
            float y = proportion * 0.5 * cos(theta);
            float z;
            if (ConeHead)
                z = proportion * 0.5 * sin(theta); 
            else
                z = 0;
            pts->SetPoint(3 + i, x, y, z);
hrchilds's avatar
hrchilds committed
184
        }
pugmire's avatar
pugmire committed
185 186 187
        
        // Draw the stem as a line or cylinder(3d)/rectangle(2d)
        if (LineStem)
hrchilds's avatar
hrchilds committed
188
        {
pugmire's avatar
pugmire committed
189 190 191 192 193 194 195 196 197 198 199 200
            lines->InsertNextCell(2);
            lines->InsertCellPoint(0);
            lines->InsertCellPoint(1);
        }
        else
        {
            float startx = OriginOffset - 0.5;
            float endx;
            // If we're in 3D and not capping the cone's base, then extend the
            // cylinder all the way to where it intersects the cone's facets.
            // Otherwise, just stop at the base of the cone.
            if (ConeHead && !CapEnds)
hrchilds's avatar
hrchilds committed
201
            {
pugmire's avatar
pugmire committed
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
                float len = (realHeadSize<cylThickness)?realHeadSize:cylThickness;
                endx = OriginOffset + .5 - len;
            }
            else
            {
                endx = OriginOffset + endOfHead;
            }
            
            for (int i=0; i<nSteps; i++)
            {
                float theta = 2*M_PI * float(i)/float(nSteps);
                float y = cylThickness * 0.5 * cos(theta);
                float z = cylThickness * 0.5 * sin(theta); 
                pts->SetPoint(3 + 1*nSteps + i, startx, y, z);
                pts->SetPoint(3 + 2*nSteps + i, endx,   y, z);
            }
            for (int i=0; i<nSteps; i++)
            {
                pt[0] = 3 + 1*nSteps + i;
                pt[1] = 3 + 1*nSteps + (i+1)%nSteps;
                pt[2] = 3 + 2*nSteps + (i+1)%nSteps;
                pt[3] = 3 + 2*nSteps + i;
                polys->InsertNextCell(4, pt);
                
                // If we're in 2D, no point in capping the end of a rectangle
                // even if "CapEnds" is true.
                if (CapEnds && ConeHead)
hrchilds's avatar
hrchilds committed
229
                {
pugmire's avatar
pugmire committed
230 231 232
                    pt[0] = 1;
                    pt[1] = 3 + 1*nSteps + i;
                    pt[2] = 3 + 1*nSteps + (i+1)%nSteps;
hrchilds's avatar
hrchilds committed
233
                    polys->InsertNextCell(3, pt);
pugmire's avatar
pugmire committed
234 235 236 237 238 239 240
                    if (realHeadSize < cylThickness)
                    {
                        pt[0] = 2;
                        pt[1] = 3 + 2*nSteps + (i+1)%nSteps;
                        pt[2] = 3 + 2*nSteps + i;
                        polys->InsertNextCell(3, pt);
                    }
hrchilds's avatar
hrchilds committed
241 242 243
                }
            }
        }
pugmire's avatar
pugmire committed
244 245 246
        
        // If asked, draw a head as either a cone or a triangle
        if (MakeHead)
hrchilds's avatar
hrchilds committed
247
        {
pugmire's avatar
pugmire committed
248
            if (ConeHead)
hrchilds's avatar
hrchilds committed
249
            {
pugmire's avatar
pugmire committed
250
                for (int i=0; i<nSteps; i++)
hrchilds's avatar
hrchilds committed
251
                {
pugmire's avatar
pugmire committed
252 253 254
                    pt[0] = 0;
                    pt[1] = 3 + i;
                    pt[2] = 3 + (i+1)%nSteps;
hrchilds's avatar
hrchilds committed
255
                    polys->InsertNextCell(3, pt);
pugmire's avatar
pugmire committed
256 257 258 259 260 261 262
                    if (CapEnds)
                    {
                        pt[0] = 2;
                        pt[1] = 3 + (i+1)%nSteps;
                        pt[2] = 3 + i;
                        polys->InsertNextCell(3, pt);
                    }
hrchilds's avatar
hrchilds committed
263 264
                }
            }
pugmire's avatar
pugmire committed
265 266 267 268 269 270 271
            else
            {
                pt[0] = 0;
                pt[1] = 3;
                pt[2] = 4;
                polys->InsertNextCell(3, pt);
            }
hrchilds's avatar
hrchilds committed
272
        }
pugmire's avatar
pugmire committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
    }
    else
    {
        vtkSphereSource *sphere = vtkSphereSource::New();
        int res = (HighQuality ? 40 : 20);
        sphere->SetThetaResolution(res);
        sphere->SetPhiResolution(res);
        sphere->SetCenter(OriginOffset, OriginOffset, OriginOffset);
        sphere->SetRadius(1.0);
        sphere->Update();
        
        vtkTransformFilter *xform = vtkTransformFilter::New();
        vtkTransform *trn = vtkTransform::New();
        trn->Scale(1.0, 0.3333, 0.3333);
        xform->SetTransform(trn);
        
289
        xform->SetInputConnection(sphere->GetOutputPort());
pugmire's avatar
pugmire committed
290 291 292 293 294 295 296 297 298 299 300 301
        xform->Update();
        vtkPolyData *spoly = (vtkPolyData *)xform->GetOutput();
        int np = spoly->GetPoints()->GetNumberOfPoints();
        pts->SetNumberOfPoints(np);
        
        //set points.
        for (int i = 0; i < np; i++)
            pts->SetPoint(i, spoly->GetPoints()->GetPoint(i));
        
        //set polys.
        np = spoly->GetPolys()->GetNumberOfCells();
        for (int i = 0; i < np; i++)
hrchilds's avatar
hrchilds committed
302
        {
pugmire's avatar
pugmire committed
303 304 305
            vtkIdType n, *p;
            spoly->GetPolys()->GetNextCell(n, p);
            polys->InsertNextCell(n, p);
hrchilds's avatar
hrchilds committed
306
        }
pugmire's avatar
pugmire committed
307 308 309
        sphere->Delete();
        xform->Delete();
        trn->Delete();
hrchilds's avatar
hrchilds committed
310
    }
311
    return 1;
hrchilds's avatar
hrchilds committed
312 313
}

hrchilds's avatar
hrchilds committed
314
// ****************************************************************************
315 316 317 318 319 320 321 322 323
//  Method: vtkVectorGlyph::FillInputPortInformation
//
// ****************************************************************************

int
vtkVectorGlyph::FillInputPortInformation(int port, vtkInformation *info)
{
    info->Remove(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
324
    return 1;
325 326 327 328 329
}

// ****************************************************************************
//  Method: vtkVectorGlyph::PrintSelf
//
hrchilds's avatar
hrchilds committed
330 331 332 333 334
//  Modifications:
//    Jeremy Meredith, Mon Mar 19 14:33:15 EDT 2007
//    Added settings to draw the stem as a cylinder (vs a line), and its
//    width, to increase the number of polygons, and to cap the ends of
//    the cone/cylinder.
335
//
pugmire's avatar
pugmire committed
336 337
//    Dave Pugmire, Mon Jul 19 09:38:17 EDT 2010
//    Add ellipsoid glyphing.        
338
//
hrchilds's avatar
hrchilds committed
339
// ****************************************************************************
340 341 342

void
vtkVectorGlyph::PrintSelf(ostream &os, vtkIndent indent)
hrchilds's avatar
hrchilds committed
343
{
bonnell's avatar
bonnell committed
344 345 346 347 348 349 350 351 352
   this->Superclass::PrintSelf(os, indent);
   os << indent << "Arrow:    " << this->Arrow << "\n";
   os << indent << "MakeHead: " << this->MakeHead << "\n";
   os << indent << "ConeHead: " << this->ConeHead << "\n";
   os << indent << "LineStem: " << this->LineStem << "\n";
   os << indent << "StemWidth: " << this->StemWidth << "\n";
   os << indent << "CapEnds:  " << this->CapEnds << "\n";
   os << indent << "HighQuality: " << this->HighQuality << "\n";
   os << indent << "Relative Size of Heads: " << this->HeadSize << "\n";
hrchilds's avatar
hrchilds committed
353
}
bonnell's avatar
bonnell committed
354