vtkContextPolygon.cxx 3.88 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkContextPolygon.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 "vtkContextPolygon.h"

18
#include <algorithm>
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
#include <vector>

#include "vtkTransform2D.h"

//-----------------------------------------------------------------------------
class vtkContextPolygonPrivate
{
public:
  std::vector<vtkVector2f> points;
};

//-----------------------------------------------------------------------------
vtkContextPolygon::vtkContextPolygon()
  : d(new vtkContextPolygonPrivate)
{
}

36 37 38 39 40 41 42
//-----------------------------------------------------------------------------
vtkContextPolygon::vtkContextPolygon(const vtkContextPolygon &polygon)
  : d(new vtkContextPolygonPrivate)
{
  d->points = polygon.d->points;
}

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
//-----------------------------------------------------------------------------
vtkContextPolygon::~vtkContextPolygon()
{
  delete d;
}

//-----------------------------------------------------------------------------
void vtkContextPolygon::AddPoint(const vtkVector2f &point)
{
  d->points.push_back(point);
}

//-----------------------------------------------------------------------------
void vtkContextPolygon::AddPoint(float x, float y)
{
  this->AddPoint(vtkVector2f(x, y));
}

//-----------------------------------------------------------------------------
vtkVector2f vtkContextPolygon::GetPoint(vtkIdType index) const
{
  return d->points[index];
}

//-----------------------------------------------------------------------------
vtkIdType vtkContextPolygon::GetNumberOfPoints() const
{
  return d->points.size();
}

//-----------------------------------------------------------------------------
void vtkContextPolygon::Clear()
{
  d->points.clear();
}

79 80 81
//-----------------------------------------------------------------------------
bool vtkContextPolygon::Contains(const vtkVector2f &point) const
{
82 83
  float x = point.GetX();
  float y = point.GetY();
84 85 86 87 88 89 90 91 92 93

  // http://en.wikipedia.org/wiki/Point_in_polygon RayCasting method
  // shooting the ray along the x axis
  bool inside = false;
  float xintersection;
  for(size_t i = 0; i < d->points.size(); i++)
    {
    const vtkVector2f &p1 = d->points[i];
    const vtkVector2f &p2 = d->points[(i+1) % d->points.size()];

94 95 96
    if (y > std::min(p1.GetY(), p2.GetY()) &&
        y <= std::max(p1.GetY(),p2.GetY()) &&
        p1.GetY() != p2.GetY())
97
      {
98
      if (x <= std::max(p1.GetX(), p2.GetX()) )
99
        {
100 101
        xintersection = (y - p1.GetY())*(p2.GetX() - p1.GetX())/(p2.GetY() - p1.GetY()) + p1.GetX();
        if ( p1.GetX() == p2.GetX() || x <= xintersection)
102 103 104 105 106 107 108 109 110 111 112
          {
          // each time we intersect we switch if we are in side or not
          inside = !inside;
          }
        }
      }
    }

  return inside;
}

113 114 115 116 117 118 119
//-----------------------------------------------------------------------------
vtkContextPolygon vtkContextPolygon::Transformed(vtkTransform2D *transform) const
{
  vtkContextPolygon transformed;
  transformed.d->points.resize(d->points.size());
  transform->TransformPoints(reinterpret_cast<float *>(&d->points[0]),
                             reinterpret_cast<float *>(&transformed.d->points[0]),
120
                             static_cast<int>(d->points.size()));
121 122
  return transformed;
}
123 124 125 126 127 128 129 130 131 132 133

//-----------------------------------------------------------------------------
vtkContextPolygon& vtkContextPolygon::operator=(const vtkContextPolygon &other)
{
  if(this != &other)
    {
    d->points = other.d->points;
    }

  return *this;
}