Skip to content
Snippets Groups Projects
blurredsegmentproto.cpp 6.6 KiB
Newer Older
even's avatar
even committed
#include "blurredsegmentproto.h"


BlurredSegmentProto::BlurredSegmentProto (int maxWidth, Pt2i pix)
{
  this->maxWidth.set (maxWidth);
  plist = new BiPtList (pix);
  leftOK = false;
  rightOK = false;
  bsFlat = false;
  bsOK = false;
  convexhull = NULL;
  chChanged = false;
  dss = NULL;
}


BlurredSegmentProto::BlurredSegmentProto (int maxWidth, Pt2i center,
                  const vector<Pt2i> &leftPts, const vector<Pt2i> &rightPts)
{
  this->maxWidth.set (maxWidth);
  plist = new BiPtList (center);
  leftOK = false;
  rightOK = false;
  bsFlat = false;
  bsOK = false;
  convexhull = NULL;
  chChanged = false;
  dss = NULL;

  vector<Pt2i>::const_iterator itr = rightPts.begin ();
  vector<Pt2i>::const_iterator itl = leftPts.begin ();
  bool scanningRight = true;
  bool scanningLeft = true;
  while (scanningRight || scanningLeft)
  {
    if (scanningRight)
    {
even's avatar
even committed
      if (itr == rightPts.end ()) scanningRight = false;
      else
        addRight (*itr++);
even's avatar
even committed
    }
    if (scanningLeft)
    {
      if (itl == leftPts.end ()) scanningLeft = false;
      else
even's avatar
even committed
        addLeft (*itl++);
even's avatar
even committed
    }
  }
}


BlurredSegmentProto::~BlurredSegmentProto ()
{
  if (convexhull != NULL) delete convexhull;
}


even's avatar
even committed
AbsRat BlurredSegmentProto::minimalWidth () const
even's avatar
even committed
{
  return (convexhull != NULL ? convexhull->rationalThickness ()
                             : AbsRat (0, 1));
}


DigitalStraightLine *BlurredSegmentProto::getLine () const
{
  if (bsOK)
  {
    Pt2i s, e, v;
    convexhull->antipodalEdgeAndVertex (s, e, v);
    return (new DigitalStraightLine (s, e, v));
  }
  if (bsFlat) return (new DigitalStraightLine (getLastLeft (), getLastRight (),
                                               DigitalStraightLine::DSL_THIN));
  return (NULL);
}


bool BlurredSegmentProto::addLeft (Pt2i pix)
{
  if (bsOK)     // convexhull defined
  {
    bool res = addPoint (pix, true);
    return (res);
  }

  else if (bsFlat)    // leftOK && rightOK
  {
    AbsRat height = plist->heightToEnds (pix);
    if (height.greaterThan (maxWidth)) return false;
    if (height.numerator () != 0)
    {
      convexhull = new ConvexHull (pix, plist->frontPoint (),
                                        plist->backPoint ());
      bsOK = true;
    }
    plist->addFront (pix);
  }

  else if (leftOK)    // thus ! rightOK
  {
    AbsRat height = plist->heightToEnds (pix);
    if (height.greaterThan (maxWidth)) return false;
    if (height.numerator () == 0) bsFlat = true;
    else
    {
      convexhull = new ConvexHull (pix, plist->frontPoint (),
                                        plist->backPoint ());
      bsOK = true;
    }
    plist->addFront (pix);
  }

  else if (rightOK)
  {
    AbsRat height = plist->heightToEnds (pix);
    if (height.greaterThan (maxWidth)) return false;
    if (height.numerator () == 0) bsFlat = true;
    else
    {
      convexhull = new ConvexHull (pix, plist->frontPoint (),
                                        plist->backPoint ());
      bsOK = true;
    }
    plist->addFront (pix);
  }

  else   // only the central point is ok
  {
    plist->addFront (pix);
    leftOK = true;
  }

  chChanged = true;
  return true;
}


bool BlurredSegmentProto::addRight (Pt2i pix)
{
  if (bsOK)     // bs != NULL
  {
    bool res = addPoint (pix, false);
    return (res);
  }

  else if (bsFlat)    // leftOK && rightOK
  {
    AbsRat height = plist->heightToEnds (pix);
    if (height.greaterThan (maxWidth)) return false;
    if (height.numerator () != 0)
    {
      convexhull = new ConvexHull (plist->frontPoint (),
                                   plist->backPoint (), pix);
      bsOK = true;
    }
    plist->addBack (pix);
  }

  else if (rightOK)    // thus ! leftOK
  {
    AbsRat height = plist->heightToEnds (pix);
    if (height.greaterThan (maxWidth)) return false;
    if (height.numerator () == 0) bsFlat = true;
    else
    {
      convexhull = new ConvexHull (plist->frontPoint (),
                                   plist->backPoint (), pix);
      bsOK = true;
    }
    plist->addBack (pix);
  }

  else if (leftOK)
  {
    AbsRat height = plist->heightToEnds (pix);
    if (height.greaterThan (maxWidth)) return false;
    if (height.numerator () == 0) bsFlat = true;
    else
    {
      convexhull = new ConvexHull (plist->frontPoint (),
                                   plist->backPoint (), pix);
      bsOK = true;
    }
    plist->addBack (pix);
  }

  else   // only the central point is ok
  {
    plist->addBack (pix);
    rightOK = true;
  }

  chChanged = true;
  return true;
}


bool BlurredSegmentProto::addPoint (Pt2i p, bool onleft)
{
  bool inserted = convexhull->addPointDS (p, onleft);
even's avatar
even committed
  if ((minimalWidth ()).greaterThan (maxWidth))
even's avatar
even committed
  {
    if (inserted) convexhull->restore ();
    return false;
  }
 
  if (onleft) plist->addFront (p);
  else plist->addBack (p);
  chChanged = true;
  return true;
}


void BlurredSegmentProto::removeLeft (int n)
{
  if (bsOK) plist->removeFront (n);
}


void BlurredSegmentProto::removeRight (int n)
{
  if (bsOK) plist->removeBack (n);
}
 

Vr2i BlurredSegmentProto::getSupportVector ()
{
  if (bsOK)
  {
    Pt2i s, e, v;
    convexhull->antipodalEdgeAndVertex (s, e, v);
    return (s.vectorTo (e));
  }
  if (bsFlat || leftOK || rightOK)
    return (getLastLeft().vectorTo (getLastRight ()));
  return (Vr2i (1, 0));    // hardly better with only one point !
}


BlurredSegment *BlurredSegmentProto::endOfBirth ()
{
  DigitalStraightSegment *seg = NULL;
  if (bsOK)
  {
    int xmin, ymin, xmax, ymax;
    plist->findExtrema (xmin, ymin, xmax, ymax);
    Pt2i s, e, v;
    convexhull->antipodalEdgeAndVertex (s, e, v);
    seg = new DigitalStraightSegment (s, e, v, xmin, ymin, xmax, ymax);
  }
  else if (bsFlat || rightOK || leftOK)
  {
    Pt2i llast = plist->frontPoint ();
    Pt2i rlast = plist->backPoint ();
even's avatar
even committed
    if (llast.equals (rlast)) // Strange, should not be flat, rightok or leftok
    {
      plist = NULL;
      return (NULL);
    }
even's avatar
even committed
    int xmin = llast.x ();
    if (rlast.x () < llast.x ()) xmin = rlast.x ();
    int ymin = llast.y ();
    if (rlast.y () < llast.y ()) ymin = rlast.y ();
    int xmax = llast.x ();
    if (rlast.x () > llast.x ()) xmax = rlast.x ();
    int ymax = llast.y ();
    if (rlast.y () > llast.y ()) ymax = rlast.y ();
    seg = new DigitalStraightSegment (llast, rlast,
                                      DigitalStraightLine::DSL_THIN,
                                      xmin, ymin, xmax, ymax);
  }
even's avatar
even committed
  Pt2i aps (-1, -1), ape (-1, -1), apv (-1, -1);
  if (convexhull != NULL)
    convexhull->antipodalEdgeAndVertex (aps, ape, apv);
  BlurredSegment *bbs = new BlurredSegment (plist, seg, aps, ape, apv);
even's avatar
even committed
  plist = NULL;  // NECESSARY TO AVOID CONTENTS CLEARANCE !!!
  return (bbs);
}