Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tcenterlinevectorizer.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tstopwatch.h"
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
//#include "timage_io.h"
Toshihiro Shimizu 890ddd
//#include "tstrokeutil.h"
Toshihiro Shimizu 890ddd
//#include "tspecialstyleid.h"
Toshihiro Shimizu 890ddd
#include "trastercm.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
//#include "dpiscale.h"
Toshihiro Shimizu 890ddd
#include "tregion.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define SEARCH_WINDOW 3
Toshihiro Shimizu 890ddd
#define JUNCTION_THICKNESS_RATIO 0.7
Toshihiro Shimizu 890ddd
#define JOIN_LIMIT 0.8
Toshihiro Shimizu 890ddd
#define THICKNESS_LIMIT 0.2
Toshihiro Shimizu 890ddd
#define THICKNESS_LIMIT_2 0.04
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#undef DEBUG
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct ControlPoint {
Shinya Kitaoka 120a6e
  TStroke *m_stroke;
Shinya Kitaoka 120a6e
  int m_index;
Shinya Kitaoka 120a6e
  ControlPoint(TStroke *stroke, int index) : m_stroke(stroke), m_index(index) {}
Shinya Kitaoka 120a6e
  TPointD getPoint() const { return m_stroke->getControlPoint(m_index); }
Shinya Kitaoka 120a6e
  void setPoint(const TPointD &p) {
Shinya Kitaoka 120a6e
    TThickPoint point = m_stroke->getControlPoint(m_index);
Shinya Kitaoka 120a6e
    point.x           = p.x;
Shinya Kitaoka 120a6e
    point.y           = p.y;
Shinya Kitaoka 120a6e
    m_stroke->setControlPoint(m_index, point);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void renormalizeImage(TVectorImage *vi) {
Shinya Kitaoka 120a6e
  int i, j;
Shinya Kitaoka 120a6e
  int n = vi->getStrokeCount();
Shinya Kitaoka 120a6e
  std::vector<controlpoint> points;</controlpoint>
Shinya Kitaoka 120a6e
  points.reserve(n * 2);
Shinya Kitaoka 120a6e
  for (i = 0; i < n; i++) {
Shinya Kitaoka 120a6e
    TStroke *stroke = vi->getStroke(i);
Shinya Kitaoka 120a6e
    int m           = stroke->getControlPointCount();
Shinya Kitaoka 120a6e
    if (m > 0) {
Shinya Kitaoka 120a6e
      if (m == 1)
Shinya Kitaoka 120a6e
        points.push_back(ControlPoint(stroke, 0));
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        points.push_back(ControlPoint(stroke, 0));
Shinya Kitaoka 120a6e
        points.push_back(ControlPoint(stroke, m - 1));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  int count = points.size();
Shinya Kitaoka 120a6e
  for (i = 0; i < count; i++) {
Shinya Kitaoka 120a6e
    ControlPoint &pi = points[i];
Shinya Kitaoka 120a6e
    TPointD posi     = pi.getPoint();
Shinya Kitaoka 120a6e
    TPointD center   = posi;
Shinya Kitaoka 120a6e
    std::vector<int> neighbours;</int>
Shinya Kitaoka 120a6e
    neighbours.push_back(i);
Shinya Kitaoka 120a6e
    for (j = i + 1; j < count; j++) {
Shinya Kitaoka 120a6e
      TPointD posj = points[j].getPoint();
Shinya Kitaoka 120a6e
      double d     = tdistance(posj, posi);
Shinya Kitaoka 120a6e
      if (d < 0.01) {
Shinya Kitaoka 120a6e
        /*if(d>0)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
int yy = 123;
Shinya Kitaoka 120a6e
}*/
Shinya Kitaoka 120a6e
        neighbours.push_back(j);
Shinya Kitaoka 120a6e
        center += posj;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    int m = neighbours.size();
Shinya Kitaoka 120a6e
    if (m == 1) continue;
Shinya Kitaoka 120a6e
    center = center * (1.0 / m);
Shinya Kitaoka 120a6e
    for (j = 0; j < m; j++) points[neighbours[j]].setPoint(center);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class Node;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class DataPixel {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TPoint m_pos;
Shinya Kitaoka 120a6e
  int m_value;
Shinya Kitaoka 120a6e
  bool m_ink;
Shinya Kitaoka 120a6e
  // int m_index;
Shinya Kitaoka 120a6e
  Node *m_node;
Shinya Kitaoka 120a6e
  DataPixel() : m_value(0), m_ink(false), /*m_index(0), */ m_node(0) {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
#ifdef WIN32
Toshihiro Shimizu 890ddd
template class DV_EXPORT_API TSmartPointerT<trastert<datapixel>>;</trastert<datapixel>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
typedef TRasterPT<datapixel> DataRasterP;</datapixel>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class Junction;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class Node {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Node *m_other;
Shinya Kitaoka 120a6e
  DataPixel *m_pixel;
Shinya Kitaoka 120a6e
  Node *m_prev, *m_next;
Shinya Kitaoka 120a6e
  Junction *m_junction;
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
  bool m_flag;
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  bool m_visited;
Shinya Kitaoka 120a6e
  Node()
Shinya Kitaoka 120a6e
      : m_pixel(0)
Shinya Kitaoka 120a6e
      , m_prev(0)
Shinya Kitaoka 120a6e
      , m_next(0)
Shinya Kitaoka 120a6e
      , m_junction(0)
Shinya Kitaoka 120a6e
      ,
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
      m_flag(false)
Shinya Kitaoka 120a6e
      ,
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
      m_visited(false) {
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ProtoStroke;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class Junction {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TThickPoint m_center;
Shinya Kitaoka 120a6e
  std::deque<node *=""> m_nodes;</node>
Shinya Kitaoka 120a6e
  int m_junctionOrder;
Shinya Kitaoka 120a6e
  std::vector<protostroke *=""> m_protoStrokes;</protostroke>
Shinya Kitaoka 120a6e
  bool m_locked;
Shinya Kitaoka 120a6e
  Junction()
Shinya Kitaoka 120a6e
      : m_center()
Shinya Kitaoka 120a6e
      , m_nodes()
Shinya Kitaoka 120a6e
      , m_junctionOrder(0)
Shinya Kitaoka 120a6e
      , m_protoStrokes()
Shinya Kitaoka 120a6e
      , m_locked(false) {}
Shinya Kitaoka 120a6e
  bool isConvex();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class ProtoStroke {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TPointD m_startDirection, m_endDirection;
Shinya Kitaoka 120a6e
  Junction *m_startJunction, *m_endJunction;
Shinya Kitaoka 120a6e
  std::deque<tthickpoint> m_points;</tthickpoint>
Shinya Kitaoka 120a6e
  ProtoStroke()
Shinya Kitaoka 120a6e
      : m_points()
Shinya Kitaoka 120a6e
      , m_startDirection()
Shinya Kitaoka 120a6e
      , m_endDirection()
Shinya Kitaoka 120a6e
      , m_startJunction(0)
Shinya Kitaoka 120a6e
      , m_endJunction(0) {}
Shinya Kitaoka 120a6e
  ProtoStroke(std::deque<tthickpoint>::iterator it_b,</tthickpoint>
Shinya Kitaoka 120a6e
              std::deque<tthickpoint>::iterator it_e)</tthickpoint>
Shinya Kitaoka 120a6e
      : m_points(it_b, it_e)
Shinya Kitaoka 120a6e
      , m_startDirection()
Shinya Kitaoka 120a6e
      , m_endDirection()
Shinya Kitaoka 120a6e
      , m_startJunction(0)
Shinya Kitaoka 120a6e
      , m_endJunction(0) {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class ProtoRegion {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TPointD m_center;
Shinya Kitaoka 120a6e
  bool m_isConvex;
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> m_points;</tthickpoint>
Shinya Kitaoka 120a6e
  ProtoRegion(bool isConvex) : m_points(), m_isConvex(isConvex), m_center() {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class JunctionMerge {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Junction *m_junction;
Shinya Kitaoka 120a6e
  Node *m_startNode, *m_endNode;
Shinya Kitaoka 120a6e
  bool m_isNext;
Shinya Kitaoka 120a6e
  JunctionMerge(Junction *junction)
Shinya Kitaoka 120a6e
      : m_junction(junction), m_startNode(0), m_endNode(0), m_isNext(true) {}
Shinya Kitaoka 120a6e
  JunctionMerge(Junction *junction, Node *startNode, Node *endNode, bool isNext)
Shinya Kitaoka 120a6e
      : m_junction(junction)
Shinya Kitaoka 120a6e
      , m_startNode(startNode)
Shinya Kitaoka 120a6e
      , m_endNode(endNode)
Shinya Kitaoka 120a6e
      , m_isNext(isNext) {}
Shinya Kitaoka 120a6e
  bool operator==(const JunctionMerge &op2) {
Shinya Kitaoka 120a6e
    return (m_junction == op2.m_junction);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class JunctionLink {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Junction *m_first;
Shinya Kitaoka 120a6e
  Junction *m_second;
Shinya Kitaoka 120a6e
  int m_order;
Shinya Kitaoka 120a6e
  JunctionLink(Junction *first, Junction *second)
Shinya Kitaoka 120a6e
      : m_first(first), m_second(second), m_order(0) {}
Shinya Kitaoka 120a6e
  bool operator==(const JunctionLink &op2) const {
Shinya Kitaoka 120a6e
    return (m_first == op2.m_first && m_second == op2.m_second) ||
Shinya Kitaoka 120a6e
           (m_first == op2.m_second && m_second == op2.m_first);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class CenterLineVectorizer {
Shinya Kitaoka 120a6e
  TPalette *m_palette;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  //	int m_delta[8];
Shinya Kitaoka 120a6e
  //	int m_radius;
Shinya Kitaoka 120a6e
  TRasterP m_src;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  VectorizerConfiguration m_configuration;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
  TRaster32P m_output;
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  DataRasterP m_dataRaster;
Shinya Kitaoka 120a6e
  vector<pair<int, datarasterp="">> m_dataRasterArray;</pair<int,>
Shinya Kitaoka 120a6e
  TVectorImageP m_vimage;
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
  TVectorImageP m_rimage;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
  vector<vector<tthickpoint>> m_outlines;</vector<tthickpoint>
Shinya Kitaoka 120a6e
  vector<tpointd> m_unvisitedNodes;</tpointd>
Shinya Kitaoka 120a6e
  vector<vector<node *="">> m_junctionPolygons;</vector<node>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  vector<node *=""> m_nodes;</node>
Shinya Kitaoka 120a6e
  vector<junction *=""> m_junctions;</junction>
Shinya Kitaoka 120a6e
  vector<junctionlink> m_links;</junctionlink>
Shinya Kitaoka 120a6e
  list<protostroke> m_protoStrokes;</protostroke>
Shinya Kitaoka 120a6e
  list<protoregion> m_protoRegions;</protoregion>
Shinya Kitaoka 120a6e
  // list< std::vector<tthickpoint> > m_protoHoles;</tthickpoint>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Node *findOtherSide(Node *node);
Shinya Kitaoka 120a6e
  bool testOtherSide(Node *na1, Node *nb1, double &startDist2);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD computeCenter(Node *na, Node *nb, double &r);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool isHole(Node *startNode);
Shinya Kitaoka 120a6e
  void traceLine(DataPixel *pix);  // , vector<tthickpoint> &points);</tthickpoint>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPoint computeGradient(DataPixel *pix) {
Shinya Kitaoka 120a6e
    assert(m_dataRaster);
Shinya Kitaoka 120a6e
    const int wrap = m_dataRaster->getWrap();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TPoint g(0, 0);
Shinya Kitaoka 120a6e
    int n, s, w, e, nw, sw, ne, se;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    w  = pix[-1].m_value;
Shinya Kitaoka 120a6e
    nw = pix[-1 + wrap].m_value;
Shinya Kitaoka 120a6e
    sw = pix[-1 - wrap].m_value;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    e  = pix[+1].m_value;
Shinya Kitaoka 120a6e
    ne = pix[+1 + wrap].m_value;
Shinya Kitaoka 120a6e
    se = pix[+1 - wrap].m_value;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    n = pix[+wrap].m_value;
Shinya Kitaoka 120a6e
    s = pix[-wrap].m_value;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    g.y = -sw + ne - se + nw + 2 * (n - s);
Shinya Kitaoka 120a6e
    g.x = -sw + ne + se - nw + 2 * (e - w);
Shinya Kitaoka 120a6e
    return g;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  CenterLineVectorizer(const VectorizerConfiguration &configuration,
Shinya Kitaoka 120a6e
                       TPalette *palette)
Shinya Kitaoka 120a6e
      : m_configuration(configuration), m_palette(palette) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ~CenterLineVectorizer();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void clearNodes();
Shinya Kitaoka 120a6e
  void createNodes();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void clearJunctions();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void makeOutputRaster();
Shinya Kitaoka 120a6e
  void makeDataRaster(const TRasterP &src);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  DataPixel *findUnvisitedInkPixel();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool linkNextProtoStroke(ProtoStroke *const dstProtoStroke,
Shinya Kitaoka 120a6e
                           Junction *const currJunction, const int k);
Shinya Kitaoka 120a6e
  void joinProtoStrokes(ProtoStroke *const dstProtoStroke);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void resolveUnvisitedNode(Node *node);
Shinya Kitaoka 120a6e
  Junction *mergeJunctions(const std::list<junctionmerge> &junctions);</junctionmerge>
Shinya Kitaoka 120a6e
  void joinJunctions();
Shinya Kitaoka 120a6e
  void createJunctionPolygon(Junction *junction);
Shinya Kitaoka 120a6e
  void handleLinks();
Shinya Kitaoka 120a6e
  void handleJunctions();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void createStrokes();
Shinya Kitaoka 120a6e
  void createRegions();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void vectorize();
Shinya Kitaoka 120a6e
  void init();
Shinya Kitaoka 120a6e
  //	void click(const TPoint &p);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Node *createNode(DataPixel *pix);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void link(DataPixel *pix, DataPixel *from, DataPixel *to);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*#ifdef DEBUG
Shinya Kitaoka 120a6e
  inline TPixel32 &getOutPix(DataPixel*pix) {return
Toshihiro Shimizu 890ddd
m_output->pixels()[pix->m_index]; }
Shinya Kitaoka 120a6e
  void outputNodes(Node *node);
Shinya Kitaoka 120a6e
  void outputInks();
Toshihiro Shimizu 890ddd
#endif*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  // not implemented
Shinya Kitaoka 120a6e
  CenterLineVectorizer(const CenterLineVectorizer &);
Shinya Kitaoka 120a6e
  CenterLineVectorizer &operator=(const CenterLineVectorizer &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class CompareJunctionNodes {
Shinya Kitaoka 120a6e
  TPointD m_center;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  CompareJunctionNodes(TPointD center) : m_center(center) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool operator()(const Node *n1, const Node *n2) {
Shinya Kitaoka 120a6e
    TPointD p1 = convert(n1->m_pixel->m_pos) - m_center;
Shinya Kitaoka 120a6e
    TPointD p2 = convert(n2->m_pixel->m_pos) - m_center;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double alpha1, alpha2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (p1.x > 0)
Shinya Kitaoka 120a6e
      alpha1 = -p1.y / sqrt(norm2(p1));
Shinya Kitaoka 120a6e
    else if (p1.x < 0)
Shinya Kitaoka 120a6e
      alpha1 = 2 + p1.y / sqrt(norm2(p1));
Shinya Kitaoka 120a6e
    else  //(p1.x = 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (p1.y > 0)
Shinya Kitaoka 120a6e
        alpha1 = -1;
Shinya Kitaoka 120a6e
      else if (p1.y < 0)
Shinya Kitaoka 120a6e
        alpha1 = 1;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        assert(true);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (p2.x > 0)
Shinya Kitaoka 120a6e
      alpha2 = -p2.y / sqrt(norm2(p2));
Shinya Kitaoka 120a6e
    else if (p2.x < 0)
Shinya Kitaoka 120a6e
      alpha2 = 2 + p2.y / sqrt(norm2(p2));
Shinya Kitaoka 120a6e
    else  //(p2.x = 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (p2.y > 0)
Shinya Kitaoka 120a6e
        alpha2 = -1;
Shinya Kitaoka 120a6e
      else if (p2.y < 0)
Shinya Kitaoka 120a6e
        alpha2 = 1;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        assert(true);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (alpha2 - alpha1 > 0)
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    else if (alpha2 - alpha1 < 0)
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      return false;  // n1->m_pixel->m_pos == n2->m_pixel->m_pos!!
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline bool collinear(const TPointD &a, const TPointD &b, const TPointD &c) {
Shinya Kitaoka 120a6e
  double area = (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
Shinya Kitaoka 120a6e
  return area == 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline bool right(const TPointD &a, const TPointD &b, const TPointD &c) {
Shinya Kitaoka 120a6e
  double area = (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
Shinya Kitaoka 120a6e
  return area < 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
enum RectIntersectionResult { parallel, coincident, intersected };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
RectIntersectionResult rectsIntersect(const TPointD &a1, const TPointD &a2,
Shinya Kitaoka 120a6e
                                      const TPointD &b1, const TPointD &b2,
Shinya Kitaoka 120a6e
                                      TPointD &intersection) {
Shinya Kitaoka 120a6e
  double ma, mb, ca, cb;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (a2.x == a1.x && b2.x == b1.x) {
Shinya Kitaoka 120a6e
    if (collinear(a1, a2, b1) && collinear(a1, a2, b2))
Shinya Kitaoka 120a6e
      return coincident;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      return parallel;
Shinya Kitaoka 120a6e
  } else if (a1.x == a2.x) {
Shinya Kitaoka 120a6e
    mb             = (b2.y - b1.y) / (b2.x - b1.x);
Shinya Kitaoka 120a6e
    cb             = b1.y - mb * b1.x;
Shinya Kitaoka 120a6e
    intersection.x = a1.x;
Shinya Kitaoka 120a6e
    intersection.y = mb * intersection.x + cb;
Shinya Kitaoka 120a6e
    return intersected;
Shinya Kitaoka 120a6e
  } else if (b1.x == b2.x) {
Shinya Kitaoka 120a6e
    ma             = (a2.y - a1.y) / (a2.x - a1.x);
Shinya Kitaoka 120a6e
    ca             = a1.y - ma * a1.x;
Shinya Kitaoka 120a6e
    intersection.x = b1.x;
Shinya Kitaoka 120a6e
    intersection.y = ma * intersection.x + ca;
Shinya Kitaoka 120a6e
    return intersected;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    ma = (a2.y - a1.y) / (a2.x - a1.x);
Shinya Kitaoka 120a6e
    mb = (b2.y - b1.y) / (b2.x - b1.x);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (ma == mb) {
Shinya Kitaoka 120a6e
      if (collinear(a1, a2, b1) && collinear(a1, a2, b2))
Shinya Kitaoka 120a6e
        return coincident;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        return parallel;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ca = a1.y - ma * a1.x;
Shinya Kitaoka 120a6e
    cb = b1.y - mb * b1.x;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    intersection.x = (ca - cb) / (mb - ma);
Shinya Kitaoka 120a6e
    intersection.y = ma * intersection.x + ca;
Shinya Kitaoka 120a6e
    return intersected;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool Junction::isConvex() {
Shinya Kitaoka 120a6e
  int nonConvexAngles = 0;
Shinya Kitaoka 120a6e
  assert(m_nodes.size() > 2);
Shinya Kitaoka 120a6e
  std::deque<node *="">::iterator it   = m_nodes.begin();</node>
Shinya Kitaoka 120a6e
  std::deque<node *="">::iterator it_e = m_nodes.end() - 2;</node>
Shinya Kitaoka 120a6e
  for (; it != it_e; ++it) {
Shinya Kitaoka 120a6e
    if (right(convert((*(it))->m_pixel->m_pos),
Shinya Kitaoka 120a6e
              convert((*(it + 1))->m_pixel->m_pos),
Shinya Kitaoka 120a6e
              convert((*(it + 2))->m_pixel->m_pos)))
Shinya Kitaoka 120a6e
      nonConvexAngles++;
Shinya Kitaoka 120a6e
    if (nonConvexAngles > 1) return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (right(convert((*(it))->m_pixel->m_pos),
Shinya Kitaoka 120a6e
            convert((*(it + 1))->m_pixel->m_pos),
Shinya Kitaoka 120a6e
            convert((*(m_nodes.begin()))->m_pixel->m_pos)))
Shinya Kitaoka 120a6e
    nonConvexAngles++;
Shinya Kitaoka 120a6e
  if (nonConvexAngles > 1) return false;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
CenterLineVectorizer::~CenterLineVectorizer() {
Shinya Kitaoka 120a6e
  clearNodes();
Shinya Kitaoka 120a6e
  clearJunctions();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
  m_outlines.clear();
Shinya Kitaoka 120a6e
  m_unvisitedNodes.clear();
Shinya Kitaoka 120a6e
  m_junctionPolygons.clear();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_links.clear();
Shinya Kitaoka 120a6e
  m_protoStrokes.clear();
Shinya Kitaoka 120a6e
  m_protoRegions.clear();
Shinya Kitaoka 120a6e
  // m_protoHoles.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::clearNodes() {
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_nodes.size(); i++) delete m_nodes[i];
Shinya Kitaoka 120a6e
  m_nodes.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::clearJunctions() {
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_junctions.size(); i++) delete m_junctions[i];
Shinya Kitaoka 120a6e
  m_junctions.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::link(DataPixel *pix, DataPixel *srcPix,
Shinya Kitaoka 120a6e
                                DataPixel *dstPix) {
Shinya Kitaoka 120a6e
  Node *srcNode = 0, *dstNode = 0, *node = 0;
Shinya Kitaoka 120a6e
  Node *tmp;
Shinya Kitaoka 120a6e
  for (tmp = pix->m_node; tmp; tmp = tmp->m_other) {
Shinya Kitaoka 120a6e
    if (tmp->m_pixel == 0) continue;
Shinya Kitaoka 120a6e
    if (tmp->m_prev && tmp->m_prev->m_pixel == srcPix) {
Shinya Kitaoka 120a6e
      assert(srcNode == 0);
Shinya Kitaoka 120a6e
      if (node) {
Shinya Kitaoka 120a6e
        assert(node->m_next->m_pixel == dstPix);
Shinya Kitaoka 120a6e
        assert(node->m_prev == 0);
Shinya Kitaoka 120a6e
        node->m_prev        = tmp->m_prev;
Shinya Kitaoka 120a6e
        tmp->m_prev->m_next = node;
Shinya Kitaoka 120a6e
        tmp->m_next = tmp->m_prev = 0;
Shinya Kitaoka 120a6e
        tmp->m_pixel              = 0;
Shinya Kitaoka 120a6e
        return;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      assert(tmp->m_next == 0);
Shinya Kitaoka 120a6e
      srcNode = tmp->m_prev;
Shinya Kitaoka 120a6e
      node    = tmp;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (tmp->m_next && tmp->m_next->m_pixel == dstPix) {
Shinya Kitaoka 120a6e
      assert(dstNode == 0);
Shinya Kitaoka 120a6e
      if (node) {
Shinya Kitaoka 120a6e
        assert(node->m_prev->m_pixel == srcPix);
Shinya Kitaoka 120a6e
        assert(node->m_next == 0);
Shinya Kitaoka 120a6e
        node->m_next        = tmp->m_next;
Shinya Kitaoka 120a6e
        tmp->m_next->m_prev = node;
Shinya Kitaoka 120a6e
        tmp->m_next = tmp->m_prev = 0;
Shinya Kitaoka 120a6e
        tmp->m_pixel              = 0;
Shinya Kitaoka 120a6e
        return;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      assert(tmp->m_prev == 0);
Shinya Kitaoka 120a6e
      dstNode = tmp->m_next;
Shinya Kitaoka 120a6e
      node    = tmp;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!node) node       = createNode(pix);
Shinya Kitaoka 120a6e
  if (!srcNode) srcNode = createNode(srcPix);
Shinya Kitaoka 120a6e
  if (!dstNode) dstNode = createNode(dstPix);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!node->m_next) {
Shinya Kitaoka 120a6e
    node->m_next = dstNode;
Shinya Kitaoka 120a6e
    assert(dstNode->m_prev == 0);
Shinya Kitaoka 120a6e
    dstNode->m_prev = node;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!node->m_prev) {
Shinya Kitaoka 120a6e
    node->m_prev = srcNode;
Shinya Kitaoka 120a6e
    assert(srcNode->m_next == 0);
Shinya Kitaoka 120a6e
    srcNode->m_next = node;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(node->m_next == dstNode);
Shinya Kitaoka 120a6e
  assert(node->m_prev == srcNode);
Shinya Kitaoka 120a6e
  assert(dstNode->m_prev == node);
Shinya Kitaoka 120a6e
  assert(srcNode->m_next == node);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline int colorDistance2(const TPixel32 &c0, const TPixel32 &c1) {
Shinya Kitaoka 120a6e
  return ((c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) +
Shinya Kitaoka 120a6e
          (c0.b - c1.b) * (c0.b - c1.b));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
#define MAX_TOLERANCE 20
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tcolorstyles.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::makeDataRaster(const TRasterP &src) {
Shinya Kitaoka 120a6e
  m_vimage = new TVectorImage();
Shinya Kitaoka 120a6e
  if (!src) return;
Shinya Kitaoka 120a6e
  m_src = src;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  clearNodes();
Shinya Kitaoka 120a6e
  clearJunctions();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int ii, x, y = 0;
Shinya Kitaoka 120a6e
  TRaster32P srcRGBM = (TRaster32P)m_src;
Shinya Kitaoka 120a6e
  TRasterCM32P srcCM = (TRasterCM32P)m_src;
Shinya Kitaoka 120a6e
  TRasterGR8P srcGR  = (TRasterGR8P)m_src;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DataRasterP dataRaster(m_src->getSize().lx + 2, m_src->getSize().ly + 2);
Shinya Kitaoka 120a6e
  int ly              = dataRaster->getLy();
Shinya Kitaoka 120a6e
  int lx              = dataRaster->getLx();
Shinya Kitaoka 120a6e
  int wrap            = dataRaster->getWrap();
Shinya Kitaoka 120a6e
  DataPixel *dataPix0 = dataRaster->pixels(0);
Shinya Kitaoka 120a6e
  DataPixel *dataPix1 = dataRaster->pixels(0) + m_src->getLx() + 1;
Shinya Kitaoka 120a6e
  for (y = 0; y < ly; y++, dataPix0 += wrap, dataPix1 += wrap) {
Shinya Kitaoka 120a6e
    dataPix0->m_pos.x = 0;
Shinya Kitaoka 120a6e
    dataPix1->m_pos.x = lx - 1;
Shinya Kitaoka 120a6e
    dataPix0->m_pos.y = dataPix1->m_pos.y = y;
Shinya Kitaoka 120a6e
    dataPix0->m_value = dataPix1->m_value = 0;
Shinya Kitaoka 120a6e
    dataPix0->m_ink = dataPix1->m_ink = false;
Shinya Kitaoka 120a6e
    dataPix0->m_node = dataPix1->m_node = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  dataPix0 = dataRaster->pixels(0);
Shinya Kitaoka 120a6e
  dataPix1 = dataRaster->pixels(ly - 1);
Shinya Kitaoka 120a6e
  for (x = 0; x < lx; x++, dataPix0++, dataPix1++) {
Shinya Kitaoka 120a6e
    dataPix0->m_pos.x = dataPix1->m_pos.x = x;
Shinya Kitaoka 120a6e
    dataPix0->m_pos.y                     = 0;
Shinya Kitaoka 120a6e
    dataPix1->m_pos.y                     = ly - 1;
Shinya Kitaoka 120a6e
    dataPix0->m_value = dataPix1->m_value = 0;
Shinya Kitaoka 120a6e
    dataPix0->m_ink = dataPix1->m_ink = false;
Shinya Kitaoka 120a6e
    dataPix0->m_node = dataPix1->m_node = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (srcRGBM) {
Shinya Kitaoka 120a6e
    assert(m_palette);
Shinya Kitaoka 120a6e
    int inkId = m_palette->addStyle(m_configuration.m_inkColor);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_dataRasterArray.push_back(pair<int, datarasterp="">(inkId, dataRaster));</int,>
Shinya Kitaoka 120a6e
    int maxDistance2 =
Shinya Kitaoka 120a6e
        m_configuration.m_threshold * m_configuration.m_threshold;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (y = 0; y < m_src->getLy(); y++) {
Shinya Kitaoka 120a6e
      TPixel32 *inPix    = srcRGBM->pixels(y);
Shinya Kitaoka 120a6e
      TPixel32 *inEndPix = inPix + srcRGBM->getLx();
Shinya Kitaoka 120a6e
      DataPixel *dataPix = dataRaster->pixels(y + 1) + 1;
Shinya Kitaoka 120a6e
      x                  = 0;
Shinya Kitaoka 120a6e
      while (inPix < inEndPix) {
Shinya Kitaoka 120a6e
        *dataPix      = DataPixel();
Shinya Kitaoka 120a6e
        int distance2 = colorDistance2(m_configuration.m_inkColor, *inPix);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // int value = (inPix->r + 2*inPix->g + inPix->b)>>2;
Shinya Kitaoka 120a6e
        if (y == 0 || y == m_src->getLy() - 1 || x == 0 ||
Shinya Kitaoka 120a6e
            x == m_src->getLx() - 1) {
Shinya Kitaoka 120a6e
          dataPix->m_value = 255;
Shinya Kitaoka 120a6e
          dataPix->m_ink   = false;
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          dataPix->m_value = (inPix->r + 2 * inPix->g + inPix->b) >> 2;
Shinya Kitaoka 120a6e
          dataPix->m_ink   = (distance2 < maxDistance2);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        dataPix->m_pos.x = x++;
Shinya Kitaoka 120a6e
        dataPix->m_pos.y = y;
Shinya Kitaoka 120a6e
        dataPix->m_node  = 0;
Shinya Kitaoka 120a6e
        // dataPix->m_index = index++;
Shinya Kitaoka 120a6e
        inPix++;
Shinya Kitaoka 120a6e
        dataPix++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (srcGR) {
Shinya Kitaoka 120a6e
    assert(m_palette);
Shinya Kitaoka 120a6e
    int inkId = m_palette->addStyle(m_configuration.m_inkColor);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_dataRasterArray.push_back(pair<int, datarasterp="">(inkId, dataRaster));</int,>
Shinya Kitaoka 120a6e
    int threshold = m_configuration.m_threshold;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (y = 0; y < m_src->getLy(); y++) {
Shinya Kitaoka 120a6e
      TPixelGR8 *inPix    = srcGR->pixels(y);
Shinya Kitaoka 120a6e
      TPixelGR8 *inEndPix = inPix + srcGR->getLx();
Shinya Kitaoka 120a6e
      DataPixel *dataPix  = dataRaster->pixels(y + 1) + 1;
Shinya Kitaoka 120a6e
      x                   = 0;
Shinya Kitaoka 120a6e
      while (inPix < inEndPix) {
Shinya Kitaoka 120a6e
        *dataPix = DataPixel();
Shinya Kitaoka 120a6e
        // int distance2 = colorDistance2(m_configuration.m_inkColor, *inPix);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // int value = (inPix->r + 2*inPix->g + inPix->b)>>2;
Shinya Kitaoka 120a6e
        if (y == 0 || y == m_src->getLy() - 1 || x == 0 ||
Shinya Kitaoka 120a6e
            x == m_src->getLx() - 1) {
Shinya Kitaoka 120a6e
          dataPix->m_value = 255;
Shinya Kitaoka 120a6e
          dataPix->m_ink   = false;
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          dataPix->m_value = inPix->value;
Shinya Kitaoka 120a6e
          dataPix->m_ink   = (inPix->value < threshold);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        dataPix->m_pos.x = x++;
Shinya Kitaoka 120a6e
        dataPix->m_pos.y = y;
Shinya Kitaoka 120a6e
        dataPix->m_node  = 0;
Shinya Kitaoka 120a6e
        // dataPix->m_index = index++;
Shinya Kitaoka 120a6e
        inPix++;
Shinya Kitaoka 120a6e
        dataPix++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  else if (srcCM) {
Shinya Kitaoka 120a6e
    int currInk, nextInk = 0;
Shinya Kitaoka 120a6e
    do {
Shinya Kitaoka 120a6e
      int threshold =
Shinya Kitaoka 120a6e
          m_configuration.m_threshold;  // tolerance: 1->MAX thresh: 1-255
Shinya Kitaoka 120a6e
      currInk = nextInk;
Shinya Kitaoka 120a6e
      nextInk = 0;
Shinya Kitaoka 120a6e
      m_dataRasterArray.push_back(pair<int, datarasterp="">(currInk, dataRaster));</int,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // inizializza la parte centrale
Shinya Kitaoka 120a6e
      for (y = 0; y < srcCM->getLy(); y++) {
Shinya Kitaoka 120a6e
        TPixelCM32 *inPix    = srcCM->pixels(y);
Shinya Kitaoka 120a6e
        TPixelCM32 *inEndPix = inPix + m_src->getLx();
Shinya Kitaoka 120a6e
        DataPixel *dataPix   = dataRaster->pixels(y + 1) + 1;
Shinya Kitaoka 120a6e
        x                    = 0;
Shinya Kitaoka 120a6e
        while (inPix < inEndPix) {
Shinya Kitaoka 120a6e
          *dataPix  = DataPixel();
Shinya Kitaoka 120a6e
          int value = inPix->getTone();
Shinya Kitaoka 120a6e
          if (value < 255 && !m_configuration.m_ignoreInkColors) {
Shinya Kitaoka 120a6e
            int ink = inPix->getInk();
Shinya Kitaoka 120a6e
            if (currInk == 0) {
Shinya Kitaoka 120a6e
              currInk                        = ink;
Shinya Kitaoka 120a6e
              m_dataRasterArray.back().first = ink;
Shinya Kitaoka 120a6e
            } else if (ink != currInk) {
Shinya Kitaoka 120a6e
              value = 255;
Shinya Kitaoka 120a6e
              if (nextInk == 0) {
Shinya Kitaoka 120a6e
                for (ii = 0; ii < (int)m_dataRasterArray.size() - 1; ii++)
Shinya Kitaoka 120a6e
                  if (m_dataRasterArray[ii].first == ink) break;
Shinya Kitaoka 120a6e
                if (ii == (int)m_dataRasterArray.size() - 1) nextInk = ink;
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          // TPixel col = m_palette->getStyle(inPix->getInk())->getMainColor();
Shinya Kitaoka 120a6e
          dataPix->m_pos.x = x++;
Shinya Kitaoka 120a6e
          dataPix->m_pos.y = y;
Shinya Kitaoka 120a6e
          dataPix->m_value = value;
Shinya Kitaoka 120a6e
          dataPix->m_ink   = (value < threshold);
Shinya Kitaoka 120a6e
          dataPix->m_node  = 0;
Shinya Kitaoka 120a6e
          // dataPix->m_index = index++;
Shinya Kitaoka 120a6e
          inPix++;
Shinya Kitaoka 120a6e
          dataPix++;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } while (nextInk != 0);
Shinya Kitaoka 120a6e
    if (m_configuration.m_ignoreInkColors) {
Shinya Kitaoka 120a6e
      assert(m_dataRasterArray.size() == 1);
Shinya Kitaoka 120a6e
      m_dataRasterArray.back().first = 1;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    assert(false);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::init() {
Shinya Kitaoka 120a6e
  int y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*m_links.clear();
Shinya Kitaoka 120a6e
  m_protoStrokes.clear();
Shinya Kitaoka 120a6e
  m_protoRegions.clear();
Shinya Kitaoka 120a6e
  clearNodes();
Shinya Kitaoka 120a6e
  clearJunctions();*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  DataRasterP dataRaster = m_dataRaster;
Shinya Kitaoka 120a6e
  const int wrap         = dataRaster->getWrap();
Shinya Kitaoka 120a6e
  const int delta[]      = {-wrap - 1, -wrap, -wrap + 1, 1,
Shinya Kitaoka 120a6e
                       wrap + 1,  wrap,  wrap - 1,  -1};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (y = 1; y < dataRaster->getLy() - 1; y++) {
Shinya Kitaoka 120a6e
    DataPixel *pix    = dataRaster->pixels(y);
Shinya Kitaoka 120a6e
    DataPixel *endPix = pix + dataRaster->getLx() - 1;
Shinya Kitaoka 120a6e
    pix++;
Shinya Kitaoka 120a6e
    for (pix++; pix < endPix; ++pix) {
Shinya Kitaoka 120a6e
      if ((pix->m_ink == false) || (pix[-wrap].m_ink && pix[wrap].m_ink &&
Shinya Kitaoka 120a6e
                                    pix[-1].m_ink && pix[1].m_ink))
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      int i;
Shinya Kitaoka 120a6e
      for (i = 0; i < 8; i++)
Shinya Kitaoka 120a6e
        if (pix[delta[i]].m_ink && pix[delta[(i + 1) & 0x7]].m_ink == false)
Shinya Kitaoka 120a6e
          break;
Shinya Kitaoka 120a6e
      int start = i;
Shinya Kitaoka 120a6e
      if (i == 8) continue;  // punto isolato
Shinya Kitaoka 120a6e
      for (;;) {
Shinya Kitaoka 120a6e
        int j = (i + 1) & 0x7;
Shinya Kitaoka 120a6e
        assert(i < 8 && pix[delta[i]].m_ink);
Shinya Kitaoka 120a6e
        assert(j < 8 && pix[delta[j]].m_ink == false);
Shinya Kitaoka 120a6e
        do
Shinya Kitaoka 120a6e
          j = (j + 1) & 0x7;
Shinya Kitaoka 120a6e
        while (pix[delta[j]].m_ink == false);
Shinya Kitaoka 120a6e
        assert(j < 8 && pix[delta[j]].m_ink);
Shinya Kitaoka 120a6e
        if (((i + 2) & 0x7) != j || (i & 1) == 0) {
Shinya Kitaoka 120a6e
          // il bianco comprende anche un fianco
Shinya Kitaoka 120a6e
          link(pix, pix + delta[i], pix + delta[j]);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        i = j;
Shinya Kitaoka 120a6e
        assert(i < 8);
Shinya Kitaoka 120a6e
        while (pix[delta[(i + 1) & 0x7]].m_ink) i = (i + 1) & 0x7;
Shinya Kitaoka 120a6e
        assert(i < 8 && pix[delta[i]].m_ink);
Shinya Kitaoka 120a6e
        assert(pix[delta[(i + 1) & 0x7]].m_ink == false);
Shinya Kitaoka 120a6e
        if (i == start) break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
Toshihiro Shimizu 890ddd
    int i;
Toshihiro Shimizu 890ddd
    for(i = 0;i<(int)m_nodes.size();i++)
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
                Node *node = m_nodes[i];
Shinya Kitaoka 120a6e
                if(node->m_pixel==0) continue;
Shinya Kitaoka 120a6e
                assert(node->m_prev);
Shinya Kitaoka 120a6e
                assert(node->m_next);
Shinya Kitaoka 120a6e
                assert(node->m_prev->m_next == node);
Shinya Kitaoka 120a6e
                assert(node->m_next->m_prev == node);
Shinya Kitaoka 120a6e
        }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    for(i = 0;i<m_dataraster->getLx()*m_dataRaster->getLy(); i++)</m_dataraster->
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
                DataPixel *pix = m_dataRaster->pixels()+i;
Shinya Kitaoka 120a6e
                for(Node *node = pix->m_node; node; node=node->m_other)
Shinya Kitaoka 120a6e
                {
Shinya Kitaoka 120a6e
                        if(node->m_pixel==0) continue;
Shinya Kitaoka 120a6e
                        assert(node->m_pixel == pix);
Shinya Kitaoka 120a6e
                        assert(node->m_prev);
Shinya Kitaoka 120a6e
                        assert(node->m_next);
Shinya Kitaoka 120a6e
                        assert(node->m_prev->m_next == node);
Shinya Kitaoka 120a6e
                        assert(node->m_next->m_prev == node);
Shinya Kitaoka 120a6e
                }
Shinya Kitaoka 120a6e
        }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPointD CenterLineVectorizer::computeCenter(Node *na, Node *nb, double &r) {
Shinya Kitaoka 120a6e
  TPointD pa = convert(na->m_pixel->m_pos);
Shinya Kitaoka 120a6e
  TPointD pb = convert(nb->m_pixel->m_pos);
Shinya Kitaoka 120a6e
  r          = THICKNESS_LIMIT;
Shinya Kitaoka 120a6e
  if (pa == pb) return pa;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD center((pa + pb) * 0.5);
Shinya Kitaoka 120a6e
  r = norm(pa - pb) * 0.5;
Shinya Kitaoka 120a6e
  return center;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*	double vsum = 0.0;
Shinya Kitaoka 120a6e
  TPointD d = pa-pb;
Shinya Kitaoka 120a6e
  if(fabs(d.x)>fabs(d.y))
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
          if(pa.x>pb.x) tswap(pa,pb);
Shinya Kitaoka 120a6e
          for(int x = pa.x; x<=pb.x; x++)
Shinya Kitaoka 120a6e
          {
Shinya Kitaoka 120a6e
                  int y = pa.y + (pb.y-pa.y)*(x-pa.x)/(pb.x-pa.x);
Shinya Kitaoka 120a6e
                  int v = 255-m_dataRaster->pixels(y)[x].m_value;
Shinya Kitaoka 120a6e
                  center += v * TPointD(x,y);
Shinya Kitaoka 120a6e
                  vsum += v;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
{
Shinya Kitaoka 120a6e
          if(pa.y>pb.y) tswap(pa,pb);
Shinya Kitaoka 120a6e
          for(int y = pa.y; y<=pb.y; y++)
Shinya Kitaoka 120a6e
          {
Shinya Kitaoka 120a6e
                  int x = pa.x + (pb.x-pa.x)*(y-pa.y)/(pb.y-pa.y);
Shinya Kitaoka 120a6e
                  int v = 255-m_dataRaster->pixels(y)[x].m_value;
Shinya Kitaoka 120a6e
                  center += v * TPointD(x,y);
Shinya Kitaoka 120a6e
                  vsum += v;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
  assert(vsum>0);
Shinya Kitaoka 120a6e
  r = 0.5*vsum/255.0;
Shinya Kitaoka 120a6e
  return center * (1/vsum);
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double computeDistance2(Node *na, Node *nb) {
Shinya Kitaoka 120a6e
  assert(na->m_pixel);
Shinya Kitaoka 120a6e
  assert(nb->m_pixel);
Shinya Kitaoka 120a6e
  TPointD d = convert(na->m_pixel->m_pos - nb->m_pixel->m_pos);
Shinya Kitaoka 120a6e
  return d * d;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Node *CenterLineVectorizer::findOtherSide(Node *node) {
Shinya Kitaoka 120a6e
  DataPixel *pix = node->m_pixel;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPoint dir = -computeGradient(pix);
Shinya Kitaoka 120a6e
  if (dir == TPoint(0, 0)) return 0;
Shinya Kitaoka 120a6e
  TPoint d1(tsign(dir.x), 0), d2(0, tsign(dir.y));
Shinya Kitaoka 120a6e
  int num = abs(dir.y), den = abs(dir.x);
Shinya Kitaoka 120a6e
  if (num > den) {
Shinya Kitaoka 120a6e
    tswap(d1, d2);
Shinya Kitaoka 120a6e
    tswap(num, den);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TPoint pos = pix->m_pos;
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0;; i++) {
Shinya Kitaoka 120a6e
    TPoint q(pos.x + d1.x * i + d2.x * num * i / den,
Shinya Kitaoka 120a6e
             pos.y + d1.y * i + d2.y * num * i / den);
Shinya Kitaoka 120a6e
    // if (!m_dataRaster->getBounds().contains(q)) break;
Shinya Kitaoka 120a6e
    DataPixel *nextPix = m_dataRaster->pixels(q.y) + q.x;
Shinya Kitaoka 120a6e
    if (nextPix->m_ink == false) break;
Shinya Kitaoka 120a6e
    pix = nextPix;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  assert(pix);
Shinya Kitaoka 120a6e
  if (!pix->m_node) {
Shinya Kitaoka 120a6e
    const int wrap = m_dataRaster->getWrap();
Shinya Kitaoka 120a6e
    if (pix[-1].m_node)
Shinya Kitaoka 120a6e
      pix--;
Shinya Kitaoka 120a6e
    else if (pix[1].m_node)
Shinya Kitaoka 120a6e
      pix++;
Shinya Kitaoka 120a6e
    else if (pix[wrap].m_node)
Shinya Kitaoka 120a6e
      pix += wrap;
Shinya Kitaoka 120a6e
    else if (pix[-wrap].m_node)
Shinya Kitaoka 120a6e
      pix -= wrap;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      assert(0);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!pix->m_node) return 0;
Shinya Kitaoka 120a6e
  Node *q                                 = pix->m_node;
Shinya Kitaoka 120a6e
  while (q->m_pixel == 0 && q->m_other) q = q->m_other;
Shinya Kitaoka 120a6e
  assert(q && q->m_pixel == pix);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0; i < 5; i++) {
Shinya Kitaoka 120a6e
    if (!q->m_prev) break;
Shinya Kitaoka 120a6e
    q = q->m_prev;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Node *best       = q;
Shinya Kitaoka 120a6e
  double bestDist2 = computeDistance2(q, node);
Shinya Kitaoka 120a6e
  for (i = 0; i < 10; i++) {
Shinya Kitaoka 120a6e
    q = q->m_next;
Shinya Kitaoka 120a6e
    if (!q) break;
Shinya Kitaoka 120a6e
    double dist2 = computeDistance2(q, node);
Shinya Kitaoka 120a6e
    if (dist2 < bestDist2) {
Shinya Kitaoka 120a6e
      bestDist2 = dist2;
Shinya Kitaoka 120a6e
      best      = q;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return best;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPointD findDirection(Node *na, Node *nb, int skip) {
Shinya Kitaoka 120a6e
  for (int i = 0; i < skip; i++) {
Shinya Kitaoka 120a6e
    na = na->m_next;
Shinya Kitaoka 120a6e
    nb = nb->m_prev;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TPointD p0 =
Shinya Kitaoka 120a6e
      0.5 * (convert(na->m_pixel->m_pos) + convert(nb->m_pixel->m_pos));
Shinya Kitaoka 120a6e
  na = na->m_next;
Shinya Kitaoka 120a6e
  nb = nb->m_prev;
Shinya Kitaoka 120a6e
  TPointD p1 =
Shinya Kitaoka 120a6e
      0.5 * (convert(na->m_pixel->m_pos) + convert(nb->m_pixel->m_pos));
Shinya Kitaoka 120a6e
  na = na->m_next;
Shinya Kitaoka 120a6e
  nb = nb->m_prev;
Shinya Kitaoka 120a6e
  TPointD p2 =
Shinya Kitaoka 120a6e
      0.5 * (convert(na->m_pixel->m_pos) + convert(nb->m_pixel->m_pos));
Shinya Kitaoka 120a6e
  TPointD dir = 0.25 * (3 * (p1 - p0) + (p2 - p1));
Shinya Kitaoka 120a6e
  double dirn = norm(dir);
Shinya Kitaoka 120a6e
  if (dirn > 0)
Shinya Kitaoka 120a6e
    return dir * (1 / dirn);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return dir;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void setEndpointsDirections(ProtoStroke &protoStroke) {
Shinya Kitaoka 120a6e
  assert(!protoStroke.m_points.empty());
Shinya Kitaoka 120a6e
  int size              = protoStroke.m_points.size();
Shinya Kitaoka 120a6e
  double startThickness = 0, endThickness = 0;
Shinya Kitaoka 120a6e
  if (size == 1) return;
Shinya Kitaoka 120a6e
  if (size < 5) {
Shinya Kitaoka 120a6e
    protoStroke.m_startDirection =
Shinya Kitaoka 120a6e
        protoStroke.m_points[0] - protoStroke.m_points[1];
Shinya Kitaoka 120a6e
    protoStroke.m_endDirection =
Shinya Kitaoka 120a6e
        protoStroke.m_points[size - 1] - protoStroke.m_points[size - 2];
Shinya Kitaoka 120a6e
  } else if (size < 10) {
Shinya Kitaoka 120a6e
    assert(protoStroke.m_points.front() != protoStroke.m_points.back());
Shinya Kitaoka 120a6e
    protoStroke.m_startDirection =
Shinya Kitaoka 120a6e
        protoStroke.m_points[0] - protoStroke.m_points[2];
Shinya Kitaoka 120a6e
    protoStroke.m_endDirection =
Shinya Kitaoka 120a6e
        protoStroke.m_points[size - 1] - protoStroke.m_points[size - 3];
Shinya Kitaoka 120a6e
    startThickness =
Shinya Kitaoka 120a6e
        0.5 * (protoStroke.m_points[1].thick + protoStroke.m_points[2].thick);
Shinya Kitaoka 120a6e
    endThickness = 0.5 * (protoStroke.m_points[size - 2].thick +
Shinya Kitaoka 120a6e
                          protoStroke.m_points[size - 3].thick);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    protoStroke.m_startDirection = 4 * protoStroke.m_points[0];
Shinya Kitaoka 120a6e
    protoStroke.m_endDirection   = 4 * protoStroke.m_points[size - 1];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int i = 0; i < 4; ++i) {
Shinya Kitaoka 120a6e
      protoStroke.m_startDirection -= protoStroke.m_points[3 + i];
Shinya Kitaoka 120a6e
      protoStroke.m_endDirection -= protoStroke.m_points[size - 4 - i];
Shinya Kitaoka 120a6e
      startThickness += protoStroke.m_points[i].thick;
Shinya Kitaoka 120a6e
      endThickness += protoStroke.m_points[size - i - 1].thick;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    protoStroke.m_startDirection = protoStroke.m_startDirection * (1 / 4.0);
Shinya Kitaoka 120a6e
    protoStroke.m_endDirection   = protoStroke.m_endDirection * (1 / 4.0);
Shinya Kitaoka 120a6e
    startThickness *= (1 / 4.0);
Shinya Kitaoka 120a6e
    endThickness *= (1 / 4.0);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double startNorm = norm(protoStroke.m_startDirection);
Shinya Kitaoka 120a6e
  if (startNorm)
Shinya Kitaoka 120a6e
    protoStroke.m_startDirection =
Shinya Kitaoka 120a6e
        protoStroke.m_startDirection * (1 / startNorm);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double endNorm = norm(protoStroke.m_endDirection);
Shinya Kitaoka 120a6e
  if (endNorm)
Shinya Kitaoka 120a6e
    protoStroke.m_endDirection = protoStroke.m_endDirection * (1 / endNorm);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (startThickness != 0)
Shinya Kitaoka 120a6e
    protoStroke.m_points[0].thick     = protoStroke.m_points[1].thick =
Shinya Kitaoka 120a6e
        protoStroke.m_points[2].thick = startThickness;
Shinya Kitaoka 120a6e
  if (endThickness != 0)
Shinya Kitaoka 120a6e
    protoStroke.m_points[size - 1].thick =
Shinya Kitaoka 120a6e
        protoStroke.m_points[size - 2].thick =
Shinya Kitaoka 120a6e
            protoStroke.m_points[size - 3].thick = endThickness;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool CenterLineVectorizer::testOtherSide(Node *na1, Node *nb1,
Shinya Kitaoka 120a6e
                                         double &startDist2) {
Shinya Kitaoka 120a6e
  if (na1->m_pixel->m_pos == nb1->m_pixel->m_pos || na1->m_next == nb1 ||
Shinya Kitaoka 120a6e
      na1->m_prev == nb1 || na1->m_next->m_next == nb1 ||
Shinya Kitaoka 120a6e
      na1->m_prev->m_prev == nb1)
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Node *na2 = na1->m_next;
Shinya Kitaoka 120a6e
  for (int i = 1; i < 3; ++i) {
Shinya Kitaoka 120a6e
    na2       = na2->m_next;
Shinya Kitaoka 120a6e
    Node *nb2 = findOtherSide(na2);
Shinya Kitaoka 120a6e
    if (nb2 == 0 && i == 3) return true;
Shinya Kitaoka 120a6e
    if (nb2 == 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double newStartDist2                       = computeDistance2(na2, nb2);
Shinya Kitaoka 120a6e
    if (newStartDist2 > startDist2) startDist2 = newStartDist2;
Shinya Kitaoka 120a6e
    for (int j = 0; j < 3 * i + 1; ++j) {
Shinya Kitaoka 120a6e
      if (nb2 == nb1) return true;
Shinya Kitaoka 120a6e
      nb2 = nb2->m_next;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
bool CenterLineVectorizer::isHole(Node *startNode)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
        Node *node = startNode;
Shinya Kitaoka 120a6e
        for(int i=0; i<20; ++i)
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
                node = node->m_next;
Shinya Kitaoka 120a6e
                if(node == startNode)
Shinya Kitaoka 120a6e
                {
Shinya Kitaoka 120a6e
                        std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
                        do
Shinya Kitaoka 120a6e
                        {
Shinya Kitaoka 120a6e
                                node = node->m_next;
Shinya Kitaoka 120a6e
                                node->m_visited = true;
Shinya Kitaoka 120a6e
                                node->m_flag = true;
Shinya Kitaoka 120a6e
                                points.push_back(convert(node->m_pixel->m_pos));
Shinya Kitaoka 120a6e
                        }
Shinya Kitaoka 120a6e
                        while(node != startNode);
Shinya Kitaoka 120a6e
                        m_protoHoles.push_back(points);
Shinya Kitaoka 120a6e
                        return true;
Shinya Kitaoka 120a6e
                }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool isJunction(const Node *na, const Node *nb) {
Shinya Kitaoka 120a6e
  TPointD pa = convert(na->m_pixel->m_pos);
Shinya Kitaoka 120a6e
  TPointD pb = convert(nb->m_pixel->m_pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Node *na0 = na->m_prev;
Shinya Kitaoka 120a6e
  Node *na1 = na->m_next;
Shinya Kitaoka 120a6e
  Node *nb0 = nb->m_next;
Shinya Kitaoka 120a6e
  Node *nb1 = nb->m_prev;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD da = convert(na1->m_pixel->m_pos) - pa;
Shinya Kitaoka 120a6e
  TPointD db = convert(nb1->m_pixel->m_pos) - pb;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD da0 = pa - convert(na0->m_pixel->m_pos);
Shinya Kitaoka 120a6e
  TPointD db0 = pb - convert(nb0->m_pixel->m_pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if ((da0.x * da.x + da0.y * da.y) / (norm(da0) * norm(da)) <= 0) {
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((db0.x * db.x + db0.y * db.y) / (norm(db0) * norm(db)) <= 0) {
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (right(TPointD(0, 0), da, db)) {
Shinya Kitaoka 120a6e
    if ((da.x * db.x + da.y * db.y) / (norm(da) * norm(db)) <= 0) {
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if ((da.x * db.x + da.y * db.y) / (norm(da) * norm(db)) <= -0.5) {
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return false;
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::traceLine(DataPixel *pix) {
Shinya Kitaoka 120a6e
  Junction *startJunction = 0;
Shinya Kitaoka 120a6e
  Junction *endJunction   = 0;
Shinya Kitaoka 120a6e
  assert(m_dataRaster);
Shinya Kitaoka 120a6e
  const int wrap = m_dataRaster->getWrap();
Shinya Kitaoka 120a6e
  //  TRect bounds = m_dataRaster->getBounds();
Shinya Kitaoka 120a6e
  if (!pix->m_ink) return;
Shinya Kitaoka 120a6e
  while (pix->m_node == 0) pix -= wrap;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Node *node                                               = pix->m_node;
Shinya Kitaoka 120a6e
  while (node && node->m_pixel == 0 && node->m_other) node = node->m_other;
Shinya Kitaoka 120a6e
  assert(node && node->m_pixel == pix);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Node *naa = node;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool isSamePixel;
Shinya Kitaoka 120a6e
  if (node->m_other && node->m_other->m_pixel &&
Shinya Kitaoka 120a6e
      (node->m_pixel->m_pos == node->m_other->m_pixel->m_pos)) {
Shinya Kitaoka 120a6e
    node        = node->m_other;
Shinya Kitaoka 120a6e
    isSamePixel = true;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    node        = findOtherSide(node);
Shinya Kitaoka 120a6e
    isSamePixel = false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (node == 0) return;
Shinya Kitaoka 120a6e
  Node *nbb = node;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (naa->m_visited || nbb->m_visited) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double startDist2 = computeDistance2(naa, nbb);
Shinya Kitaoka 120a6e
  if (startDist2 > 2000) return;
Shinya Kitaoka 120a6e
  if (startDist2 < THICKNESS_LIMIT_2) startDist2 = THICKNESS_LIMIT_2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // try to detect errors in findOtherSide
Shinya Kitaoka 120a6e
  if (!isSamePixel && !testOtherSide(naa, nbb, startDist2)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double minDist2 = 0;
Shinya Kitaoka 120a6e
  double maxDist2 = startDist2 + 3.0;
Shinya Kitaoka 120a6e
  if (startDist2 > 36) {
Shinya Kitaoka 120a6e
    minDist2 = startDist2 / 2;
Shinya Kitaoka 120a6e
    maxDist2 = startDist2 + 0.25 * startDist2;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (naa->m_next == nbb || naa->m_prev == nbb) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  naa->m_visited = nbb->m_visited = true;
Shinya Kitaoka 120a6e
  std::deque<tthickpoint> dpoints;</tthickpoint>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int k = 0; k < 2; k++) {
Shinya Kitaoka 120a6e
    Node *na = naa;
Shinya Kitaoka 120a6e
    Node *nb = nbb;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (;;) {
Shinya Kitaoka 120a6e
      TPoint &pa = na->m_pixel->m_pos;
Shinya Kitaoka 120a6e
      TPoint &pb = nb->m_pixel->m_pos;
Shinya Kitaoka 120a6e
      TPoint ba  = pb - pa;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      Node *na1 = na->m_next;
Shinya Kitaoka 120a6e
      Node *nb1 = nb->m_prev;
Shinya Kitaoka 120a6e
      // if (!na1 || !nb1) break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPoint da = na1->m_pixel->m_pos - pb;
Shinya Kitaoka 120a6e
      TPoint db = nb1->m_pixel->m_pos - pa;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (na1->m_junction || nb1->m_junction) {
Shinya Kitaoka 120a6e
        na1->m_visited = true;
Shinya Kitaoka 120a6e
        nb1->m_visited = true;
Shinya Kitaoka 120a6e
        TPointD p1;
Shinya Kitaoka 120a6e
        if (na1->m_junction && nb1->m_junction) {
Shinya Kitaoka 120a6e
          //					assert(na1->m_junction ==
Shinya Kitaoka 38fd86
          // nb1->m_junction);
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          if (na1->m_junction) {
Shinya Kitaoka 120a6e
            p1              = convert(nb1->m_pixel->m_pos);
Shinya Kitaoka 120a6e
            nb1->m_junction = na1->m_junction;
Shinya Kitaoka 120a6e
            na1->m_junction->m_nodes.push_front(nb1);
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            p1              = convert(na1->m_pixel->m_pos);
Shinya Kitaoka 120a6e
            na1->m_junction = nb1->m_junction;
Shinya Kitaoka 120a6e
            nb1->m_junction->m_nodes.push_back(na1);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        double r;
Shinya Kitaoka 120a6e
        TPointD center;
Shinya Kitaoka 120a6e
        TThickPoint point;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        center                     = computeCenter(na, nb, r);
Shinya Kitaoka 120a6e
        if (r < THICKNESS_LIMIT) r = THICKNESS_LIMIT;
Shinya Kitaoka 120a6e
        point                      = TThickPoint(center, r);
Shinya Kitaoka 120a6e
        if (k == 0)
Shinya Kitaoka 120a6e
          dpoints.push_front(point);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          dpoints.push_back(point);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        center                     = computeCenter(na1, nb1, r);
Shinya Kitaoka 120a6e
        if (r < THICKNESS_LIMIT) r = THICKNESS_LIMIT;
Shinya Kitaoka 120a6e
        point                      = TThickPoint(center, r);
Shinya Kitaoka 120a6e
        if (k == 0)
Shinya Kitaoka 120a6e
          dpoints.push_front(point);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          dpoints.push_back(point);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (k == 0)
Shinya Kitaoka 120a6e
          startJunction = na1->m_junction;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          endJunction = na1->m_junction;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      //			if(da*ba>-db*ba)
Shinya Kitaoka 120a6e
      if (norm2(db) >= norm2(da)) {
Shinya Kitaoka 120a6e
        if (na1->m_visited) break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        na            = na1;
Shinya Kitaoka 120a6e
        na->m_visited = true;
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
        getOutPix(na->m_pixel) = TPixel32::Red;
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        if (nb1->m_visited) break;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        nb            = nb1;
Shinya Kitaoka 120a6e
        nb->m_visited = true;
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
        getOutPix(nb->m_pixel) = TPixel32::Green;
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      double distance2                = computeDistance2(na, nb);
Shinya Kitaoka 120a6e
      if (distance2 < 0.25) distance2 = 0.25;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      double r;
Shinya Kitaoka 120a6e
      TPointD center             = computeCenter(na, nb, r);
Shinya Kitaoka 120a6e
      if (r < THICKNESS_LIMIT) r = THICKNESS_LIMIT;
Shinya Kitaoka 120a6e
      TThickPoint point(center, r);
Shinya Kitaoka 120a6e
      TPointI pos = convert(center);
Shinya Kitaoka 120a6e
      // TPixel32  *inPix = m_src->pixels(pos.y);
Shinya Kitaoka 120a6e
      // inPix += pos.x;
Shinya Kitaoka 120a6e
      // int value = (inPix->r + 2*inPix->g + inPix->b)>>2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (distance2 > maxDist2 || distance2 < minDist2 || na->m_next == nb ||
Shinya Kitaoka 120a6e
          na->m_prev == nb
Shinya Kitaoka 120a6e
          //|| isJunction(na, nb)
Shinya Kitaoka 120a6e
          //|| !(value<200)
Shinya Kitaoka 120a6e
          ) {
Shinya Kitaoka 120a6e
        if (na->m_next == nb || na->m_prev == nb || na->m_next->m_next == nb ||
Shinya Kitaoka 120a6e
            na->m_prev->m_prev == nb) {
Shinya Kitaoka 120a6e
          if (k == 0) {
Shinya Kitaoka 120a6e
            if (!dpoints.empty()) dpoints.pop_front();
Shinya Kitaoka 120a6e
            if (!dpoints.empty()) dpoints.pop_front();
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            if (!dpoints.empty()) dpoints.pop_back();
Shinya Kitaoka 120a6e
            if (!dpoints.empty()) dpoints.pop_back();
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        //				if(k==0) dpoints.push_front(point);
Shinya Kitaoka 120a6e
        //				else dpoints.push_back(point);
Shinya Kitaoka 120a6e
        na->m_junction = nb->m_junction = new Junction();
Shinya Kitaoka 120a6e
        na->m_junction->m_nodes.push_back(nb);
Shinya Kitaoka 120a6e
        nb->m_junction->m_nodes.push_back(na);
Shinya Kitaoka 120a6e
        m_junctions.push_back(na->m_junction);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (k == 0)
Shinya Kitaoka 120a6e
          startJunction = na->m_junction;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          endJunction = na->m_junction;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (k == 0)
Shinya Kitaoka 120a6e
        dpoints.push_front(point);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        dpoints.push_back(point);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    tswap(naa, nbb);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (dpoints.size() == 0)
Shinya Kitaoka 120a6e
    naa->m_visited = nbb->m_visited = false;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    m_protoStrokes.push_back(ProtoStroke(dpoints.begin(), dpoints.end()));
Shinya Kitaoka 120a6e
    setEndpointsDirections(m_protoStrokes.back());
Shinya Kitaoka 120a6e
    if (startJunction) {
Shinya Kitaoka 120a6e
      m_protoStrokes.back().m_startJunction = startJunction;
Shinya Kitaoka 120a6e
      startJunction->m_protoStrokes.push_back(&m_protoStrokes.back());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (endJunction) {
Shinya Kitaoka 120a6e
      m_protoStrokes.back().m_endJunction = endJunction;
Shinya Kitaoka 120a6e
      endJunction->m_protoStrokes.push_back(&m_protoStrokes.back());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Node *CenterLineVectorizer::createNode(DataPixel *pix) {
Shinya Kitaoka 120a6e
  Node *node    = new Node();
Shinya Kitaoka 120a6e
  node->m_pixel = pix;
Shinya Kitaoka 120a6e
  node->m_other = pix->m_node;
Shinya Kitaoka 120a6e
  pix->m_node   = node;
Shinya Kitaoka 120a6e
  m_nodes.push_back(node);
Shinya Kitaoka 120a6e
  return node;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::createNodes() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
void CenterLineVectorizer::outputNodes(Node *node) {
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
  Node *start = node, *curr = node;
Shinya Kitaoka 120a6e
  int i = 0;
Shinya Kitaoka 120a6e
  do {
Shinya Kitaoka 120a6e
    TThickPoint point(convert(curr->m_pixel->m_pos), 0);
Shinya Kitaoka 120a6e
    points.push_back(point);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    curr->m_flag = true;
Shinya Kitaoka 120a6e
    assert(curr->m_next);
Shinya Kitaoka 120a6e
    curr = curr->m_next;
Shinya Kitaoka 120a6e
    i++;
Shinya Kitaoka 120a6e
  } while (curr != start);
Shinya Kitaoka 120a6e
  TThickPoint point(convert(curr->m_pixel->m_pos), 0);
Shinya Kitaoka 120a6e
  points.push_back(point);
Shinya Kitaoka 120a6e
  m_outlines.push_back(points);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool CenterLineVectorizer::linkNextProtoStroke(
Shinya Kitaoka 120a6e
    ProtoStroke *const dstProtoStroke, Junction *const currJunction, int k) {
Shinya Kitaoka 120a6e
  assert(dstProtoStroke);
Shinya Kitaoka 120a6e
  assert(currJunction);
Shinya Kitaoka 120a6e
  //	if(dstProtoStroke->m_startJunction == dstProtoStroke->m_endJunction)
Shinya Kitaoka 120a6e
  return false;
Shinya Kitaoka 120a6e
  if (k == 0 && dstProtoStroke->m_startJunction->m_locked ||
Shinya Kitaoka 120a6e
      k == 1 && dstProtoStroke->m_endJunction->m_locked)
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ProtoStroke *srcProtoStroke = 0;
Shinya Kitaoka 120a6e
  Junction *nextJunction      = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<protostroke *="">::iterator it;</protostroke>
Shinya Kitaoka 120a6e
  std::vector<protostroke *="">::iterator it_e =</protostroke>
Shinya Kitaoka 120a6e
      currJunction->m_protoStrokes.end();
Shinya Kitaoka 120a6e
  std::vector<protostroke *="">::iterator it_candidate = it_e;</protostroke>
Shinya Kitaoka 120a6e
  double candidateProbability                       = JOIN_LIMIT;
Shinya Kitaoka 120a6e
  int candidate_k;
Shinya Kitaoka 120a6e
  for (it = currJunction->m_protoStrokes.begin(); it != it_e; it++) {
Shinya Kitaoka 120a6e
    // erase dstProtoStroke in currJunction
Shinya Kitaoka 120a6e
    if (*it == dstProtoStroke) {
Shinya Kitaoka 120a6e
      it   = currJunction->m_protoStrokes.erase(it);
Shinya Kitaoka 120a6e
      it_e = currJunction->m_protoStrokes.end();
Shinya Kitaoka 120a6e
      if (candidateProbability == JOIN_LIMIT) it_candidate = it_e;
Shinya Kitaoka 120a6e
      if (it == it_e) break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    double probability;
Shinya Kitaoka 120a6e
    int next_k;
Shinya Kitaoka 120a6e
    if (((*it))->m_startJunction == currJunction)
Shinya Kitaoka 120a6e
      next_k = 0;
Shinya Kitaoka 120a6e
    else if ((*it)->m_endJunction == currJunction)
Shinya Kitaoka 120a6e
      next_k = 1;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      assert(false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (k == 0) {
Shinya Kitaoka 120a6e
      if (next_k == 0)
Shinya Kitaoka 120a6e
        probability = 1 - norm2(dstProtoStroke->m_startDirection +
Shinya Kitaoka 120a6e
                                (*it)->m_startDirection);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        probability =
Shinya Kitaoka 120a6e
            1 - norm2(dstProtoStroke->m_startDirection + (*it)->m_endDirection);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      if (next_k == 0)
Shinya Kitaoka 120a6e
        probability =
Shinya Kitaoka 120a6e
            1 - norm2(dstProtoStroke->m_endDirection + (*it)->m_startDirection);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        probability =
Shinya Kitaoka 120a6e
            1 - norm2(dstProtoStroke->m_endDirection + (*it)->m_endDirection);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (probability > candidateProbability ||
Shinya Kitaoka 120a6e
        //			currJunction->m_junctionOrder == 2 ||
Shinya Kitaoka 120a6e
        (*it)->m_points.size() < 3) {
Shinya Kitaoka 120a6e
      it_candidate         = it;
Shinya Kitaoka 120a6e
      candidateProbability = probability;
Shinya Kitaoka 120a6e
      candidate_k          = next_k;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (it_candidate == it_e) return false;
Shinya Kitaoka 120a6e
  srcProtoStroke = *it_candidate;
Shinya Kitaoka 120a6e
  assert(srcProtoStroke);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((*it_candidate)->m_startJunction == (*it_candidate)->m_endJunction)
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  /*	if(k==0)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
          if(	candidate_k == 0 && dstProtoStroke->m_startJunction ==
Toshihiro Shimizu 890ddd
(*it_candidate)->m_endJunction ||
Shinya Kitaoka 120a6e
                  candidate_k == 1 && dstProtoStroke->m_startJunction ==
Toshihiro Shimizu 890ddd
(*it_candidate)->m_startJunction	)
Shinya Kitaoka 120a6e
                  return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  else if(k==1)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
          if(	candidate_k == 0 && dstProtoStroke->m_endJunction ==
Toshihiro Shimizu 890ddd
(*it_candidate)->m_endJunction ||
Shinya Kitaoka 120a6e
                  candidate_k == 1 && dstProtoStroke->m_endJunction ==
Toshihiro Shimizu 890ddd
(*it_candidate)->m_startJunction	)
Shinya Kitaoka 120a6e
                  return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
  if (candidate_k == 0)
Shinya Kitaoka 120a6e
    nextJunction = (*it_candidate)->m_endJunction;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    nextJunction = (*it_candidate)->m_startJunction;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (k == 0) {
Shinya Kitaoka 120a6e
    if (candidate_k == 0) {
Shinya Kitaoka 120a6e
      dstProtoStroke->m_points.insert(dstProtoStroke->m_points.begin(),
Shinya Kitaoka 120a6e
                                      srcProtoStroke->m_points.rbegin(),
Shinya Kitaoka 120a6e
                                      srcProtoStroke->m_points.rend());
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      dstProtoStroke->m_points.insert(dstProtoStroke->m_points.begin(),
Shinya Kitaoka 120a6e
                                      srcProtoStroke->m_points.begin(),
Shinya Kitaoka 120a6e
                                      srcProtoStroke->m_points.end());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (candidate_k == 0) {
Shinya Kitaoka 120a6e
      dstProtoStroke->m_points.insert(dstProtoStroke->m_points.end(),
Shinya Kitaoka 120a6e
                                      srcProtoStroke->m_points.begin(),
Shinya Kitaoka 120a6e
                                      srcProtoStroke->m_points.end());
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      dstProtoStroke->m_points.insert(dstProtoStroke->m_points.end(),
Shinya Kitaoka 120a6e
                                      srcProtoStroke->m_points.rbegin(),
Shinya Kitaoka 120a6e
                                      srcProtoStroke->m_points.rend());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  srcProtoStroke->m_points.clear();
Shinya Kitaoka 120a6e
  srcProtoStroke->m_startJunction = 0;
Shinya Kitaoka 120a6e
  srcProtoStroke->m_endJunction   = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // refresh currJunction
Shinya Kitaoka 120a6e
  currJunction->m_protoStrokes.erase(it_candidate);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // refresh nextJunction
Shinya Kitaoka 120a6e
  if (nextJunction) {
Shinya Kitaoka 120a6e
    it = std::find(nextJunction->m_protoStrokes.begin(),
Shinya Kitaoka 120a6e
                   nextJunction->m_protoStrokes.end(), srcProtoStroke);
Shinya Kitaoka 120a6e
    assert(it != nextJunction->m_protoStrokes.end());
Shinya Kitaoka 120a6e
    nextJunction->m_protoStrokes.erase(it);
Shinya Kitaoka 120a6e
    nextJunction->m_protoStrokes.push_back(dstProtoStroke);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (k == 0) {
Shinya Kitaoka 120a6e
    dstProtoStroke->m_startJunction = nextJunction;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (candidate_k == 0)
Shinya Kitaoka 120a6e
      dstProtoStroke->m_startDirection = srcProtoStroke->m_endDirection;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      dstProtoStroke->m_startDirection = srcProtoStroke->m_startDirection;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    dstProtoStroke->m_endJunction = nextJunction;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (candidate_k == 0)
Shinya Kitaoka 120a6e
      dstProtoStroke->m_endDirection = srcProtoStroke->m_endDirection;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      dstProtoStroke->m_endDirection = srcProtoStroke->m_startDirection;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!nextJunction) return false;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::joinProtoStrokes(ProtoStroke *const dstProtoStroke) {
Shinya Kitaoka 120a6e
  // std::deque<tthickpoint> &dstPoints = dstProtoStroke->m_points;</tthickpoint>
Shinya Kitaoka 120a6e
  for (int k = 0; k < 2; k++) {
Shinya Kitaoka 120a6e
    for (;;) {
Shinya Kitaoka 120a6e
      Junction *currJunction;
Shinya Kitaoka 120a6e
      if (k == 0 && !dstProtoStroke->m_startJunction)
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      else if (k == 0)
Shinya Kitaoka 120a6e
        currJunction = dstProtoStroke->m_startJunction;
Shinya Kitaoka 120a6e
      else if (!dstProtoStroke->m_endJunction)
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        currJunction = dstProtoStroke->m_endJunction;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (!linkNextProtoStroke(dstProtoStroke, currJunction, k)) break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  std::vector<protostroke *="">::iterator it;</protostroke>
Shinya Kitaoka 120a6e
  if (dstProtoStroke->m_startJunction) {
Shinya Kitaoka 120a6e
    it = std::find(dstProtoStroke->m_startJunction->m_protoStrokes.begin(),
Shinya Kitaoka 120a6e
                   dstProtoStroke->m_startJunction->m_protoStrokes.end(),
Shinya Kitaoka 120a6e
                   dstProtoStroke);
Shinya Kitaoka 120a6e
    if (it != dstProtoStroke->m_startJunction->m_protoStrokes.end())
Shinya Kitaoka 120a6e
      dstProtoStroke->m_startJunction->m_protoStrokes.erase(it);
Shinya Kitaoka 120a6e
    dstProtoStroke->m_startJunction = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (dstProtoStroke->m_endJunction) {
Shinya Kitaoka 120a6e
    it = std::find(dstProtoStroke->m_endJunction->m_protoStrokes.begin(),
Shinya Kitaoka 120a6e
                   dstProtoStroke->m_endJunction->m_protoStrokes.end(),
Shinya Kitaoka 120a6e
                   dstProtoStroke);
Shinya Kitaoka 120a6e
    if (it != dstProtoStroke->m_endJunction->m_protoStrokes.end())
Shinya Kitaoka 120a6e
      dstProtoStroke->m_endJunction->m_protoStrokes.erase(it);
Shinya Kitaoka 120a6e
    dstProtoStroke->m_endJunction = 0;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool y_intersect(const double y0, const TPointD p1, const TPointD p2,
Shinya Kitaoka 120a6e
                 double &x0) {
Shinya Kitaoka 120a6e
  if ((y0 < p1.y && y0 < p2.y) || (y0 > p1.y && y0 > p2.y)) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  x0 = (p1.x * (p2.y - y0) + p2.x * (y0 - p1.y)) / (p2.y - p1.y);
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool isContained(TThickPoint point, std::deque<node *=""> &polygon) {</node>
Shinya Kitaoka 120a6e
  std::deque<node *="">::iterator it_b = polygon.begin();</node>
Shinya Kitaoka 120a6e
  std::deque<node *="">::iterator it_e = polygon.end();</node>
Shinya Kitaoka 120a6e
  std::deque<node *="">::iterator it;</node>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int intersectionsNumber = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (it = it_b; it < it_e; ++it) {
Shinya Kitaoka 120a6e
    double x;
Shinya Kitaoka 120a6e
    TPointD p1, p2;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    p1 = convert((*it)->m_pixel->m_pos);
Shinya Kitaoka 120a6e
    if ((it + 1) == it_e)
Shinya Kitaoka 120a6e
      p2 = convert((*it_b)->m_pixel->m_pos);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      p2 = convert((*(it + 1))->m_pixel->m_pos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (point.y == p1.y || point.y == p2.y || p1.y == p2.y) continue;
Shinya Kitaoka 120a6e
    if (y_intersect(point.y, p1, p2, x) && x >= point.x) ++intersectionsNumber;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return (intersectionsNumber % 2 == 0) ? false : true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Junction *CenterLineVectorizer::mergeJunctions(
Shinya Kitaoka 120a6e
    const std::list<junctionmerge> &junctions) {</junctionmerge>
Shinya Kitaoka 120a6e
  Junction *newJunction = new Junction();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::list<junctionmerge>::const_iterator it_junction;</junctionmerge>
Shinya Kitaoka 120a6e
  std::deque<node *="">::iterator it_startNode, it_endNode;</node>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (it_junction = junctions.begin(); it_junction != junctions.end();
Shinya Kitaoka 120a6e
       ++it_junction) {
Shinya Kitaoka 120a6e
    newJunction->m_center += it_junction->m_junction->m_center;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::deque<node *="">::iterator it_node;</node>
Shinya Kitaoka 120a6e
    if (it_junction->m_startNode == 0 && it_junction->m_endNode == 0) {
Shinya Kitaoka 120a6e
      for (it_node = it_junction->m_junction->m_nodes.begin();
Shinya Kitaoka 120a6e
           it_node != it_junction->m_junction->m_nodes.end(); ++it_node) {
Shinya Kitaoka 120a6e
        (*it_node)->m_junction = newJunction;
Shinya Kitaoka 120a6e
        newJunction->m_nodes.push_back(*it_node);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      //			if(
Shinya Kitaoka 38fd86
      // isContained(it_junction->m_junction->m_center, newJunction->m_nodes) )
Shinya Kitaoka 38fd86
      // continue;
Shinya Kitaoka 120a6e
      /*			if(
Shinya Kitaoka 120a6e
      it_junction->m_junction->m_nodes.size() < 3)
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
              std::vector<protostroke*>::iterator it_protoStroke;</protostroke*>
Shinya Kitaoka 120a6e
              bool ignoreJunction = false;
Shinya Kitaoka 120a6e
              for(it_protoStroke =
Shinya Kitaoka 120a6e
      it_junction->m_junction->m_protoStrokes.begin();
Shinya Kitaoka 120a6e
                      it_protoStroke!=it_junction->m_junction->m_protoStrokes.end();
Shinya Kitaoka 120a6e
                      ++it_protoStroke)
Shinya Kitaoka 120a6e
              {
Shinya Kitaoka 38fd86
                      if(	(*it_protoStroke)->m_startJunction ==
Shinya Kitaoka 38fd86
      newJunction
Shinya Kitaoka 120a6e
      ||
Shinya Kitaoka 120a6e
                              (*it_protoStroke)->m_endJunction == newJunction )
Shinya Kitaoka 120a6e
                      {
Shinya Kitaoka 120a6e
                              ignoreJunction = true;
Shinya Kitaoka 120a6e
                              break;
Shinya Kitaoka 120a6e
                      }
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
              if(ignoreJunction) continue;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      it_startNode =
Shinya Kitaoka 120a6e
          std::find(newJunction->m_nodes.begin(), newJunction->m_nodes.end(),
Shinya Kitaoka 120a6e
                    it_junction->m_startNode);
Shinya Kitaoka 120a6e
      assert(it_startNode != newJunction->m_nodes.end());
Shinya Kitaoka 120a6e
      it_endNode = std::find(it_junction->m_junction->m_nodes.begin(),
Shinya Kitaoka 120a6e
                             it_junction->m_junction->m_nodes.end(),
Shinya Kitaoka 120a6e
                             it_junction->m_endNode);
Shinya Kitaoka 120a6e
      assert(it_endNode != it_junction->m_junction->m_nodes.end());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      for (it_node = it_junction->m_junction->m_nodes.begin();
Shinya Kitaoka 120a6e
           it_node != it_junction->m_junction->m_nodes.end(); ++it_node) {
Shinya Kitaoka 120a6e
        (*it_node)->m_junction = newJunction;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (it_junction->m_isNext) {
Shinya Kitaoka 120a6e
        ++it_startNode;
Shinya Kitaoka 120a6e
        newJunction->m_nodes.insert(
Shinya Kitaoka 120a6e
            it_startNode, it_junction->m_junction->m_nodes.begin(), it_endNode);
Shinya Kitaoka 120a6e
        it_startNode =
Shinya Kitaoka 120a6e
            std::find(newJunction->m_nodes.begin(), newJunction->m_nodes.end(),
Shinya Kitaoka 120a6e
                      it_junction->m_startNode);
Shinya Kitaoka 120a6e
        assert(it_startNode != newJunction->m_nodes.end());
Shinya Kitaoka 120a6e
        ++it_startNode;
Shinya Kitaoka 120a6e
        newJunction->m_nodes.insert(it_startNode, it_endNode,
Shinya Kitaoka 120a6e
                                    it_junction->m_junction->m_nodes.end());
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        ++it_endNode;
Shinya Kitaoka 120a6e
        newJunction->m_nodes.insert(
Shinya Kitaoka 120a6e
            it_startNode, it_junction->m_junction->m_nodes.begin(), it_endNode);
Shinya Kitaoka 120a6e
        it_startNode =
Shinya Kitaoka 120a6e
            std::find(newJunction->m_nodes.begin(), newJunction->m_nodes.end(),
Shinya Kitaoka 120a6e
                      it_junction->m_startNode);
Shinya Kitaoka 120a6e
        assert(it_startNode != newJunction->m_nodes.end());
Shinya Kitaoka 120a6e
        newJunction->m_nodes.insert(it_startNode, it_endNode,
Shinya Kitaoka 120a6e
                                    it_junction->m_junction->m_nodes.end());
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::vector<protostroke *="">::iterator it_protoStroke;</protostroke>
Shinya Kitaoka 120a6e
    for (it_protoStroke = it_junction->m_junction->m_protoStrokes.begin();
Shinya Kitaoka 120a6e
         it_protoStroke != it_junction->m_junction->m_protoStrokes.end();
Shinya Kitaoka 120a6e
         ++it_protoStroke) {
Shinya Kitaoka 120a6e
      if ((*it_protoStroke)->m_startJunction == it_junction->m_junction) {
Shinya Kitaoka 120a6e
        (*it_protoStroke)->m_startJunction = newJunction;
Shinya Kitaoka 120a6e
        newJunction->m_protoStrokes.push_back(*it_protoStroke);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if ((*it_protoStroke)->m_endJunction == it_junction->m_junction) {
Shinya Kitaoka 120a6e
        (*it_protoStroke)->m_endJunction = newJunction;
Shinya Kitaoka 120a6e
        newJunction->m_protoStrokes.push_back(*it_protoStroke);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::vector<junctionlink>::iterator it_links;</junctionlink>
Shinya Kitaoka 120a6e
    for (it_links = m_links.begin(); it_links != m_links.end(); ++it_links) {
Shinya Kitaoka 120a6e
      if (it_links->m_first == it_junction->m_junction)
Shinya Kitaoka 120a6e
        it_links->m_first = newJunction;
Shinya Kitaoka 120a6e
      if (it_links->m_second == it_junction->m_junction)
Shinya Kitaoka 120a6e
        it_links->m_second = newJunction;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // erase old junction
Shinya Kitaoka 120a6e
    std::vector<junction *="">::iterator it;</junction>
Shinya Kitaoka 120a6e
    it = std::find(m_junctions.begin(), m_junctions.end(),
Shinya Kitaoka 120a6e
                   it_junction->m_junction);
Shinya Kitaoka 120a6e
    assert(it != m_junctions.end());
Shinya Kitaoka 120a6e
    delete it_junction->m_junction;
Shinya Kitaoka 120a6e
    m_junctions.erase(it);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  double size           = junctions.size();
Shinya Kitaoka 120a6e
  newJunction->m_center = newJunction->m_center * (1 / size);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<protostroke *="">::iterator it_protoStroke;</protostroke>
Shinya Kitaoka 120a6e
  for (it_protoStroke = newJunction->m_protoStrokes.begin();
Shinya Kitaoka 120a6e
       it_protoStroke != newJunction->m_protoStrokes.end(); ++it_protoStroke) {
Shinya Kitaoka 120a6e
    if ((*it_protoStroke)->m_points.size() < 6 &&
Shinya Kitaoka 120a6e
        (*it_protoStroke)->m_startJunction == newJunction &&
Shinya Kitaoka 120a6e
        (*it_protoStroke)->m_endJunction == newJunction) {
Shinya Kitaoka 120a6e
      (*it_protoStroke)->m_points.clear();
Shinya Kitaoka 120a6e
      (*it_protoStroke)->m_startJunction = (*it_protoStroke)->m_endJunction = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      ProtoStroke *protoStroke = *it_protoStroke;
Shinya Kitaoka 120a6e
      for (;;) {
Shinya Kitaoka 120a6e
        std::vector<protostroke *="">::iterator it;</protostroke>
Shinya Kitaoka 120a6e
        it = std::find(newJunction->m_protoStrokes.begin(),
Shinya Kitaoka 120a6e
                       newJunction->m_protoStrokes.end(), protoStroke);
Shinya Kitaoka 120a6e
        if (it == newJunction->m_protoStrokes.end()) break;
Shinya Kitaoka 120a6e
        newJunction->m_protoStrokes.erase(it);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (newJunction->m_protoStrokes.empty()) break;
Shinya Kitaoka 120a6e
      it_protoStroke = newJunction->m_protoStrokes.begin();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return newJunction;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::joinJunctions() {
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_junctions.size(); i++) {
Shinya Kitaoka 120a6e
    Junction *currJunction = m_junctions[i];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //		if(currJunction->m_nodes.size() <= 2) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::list<junctionmerge> joinJunctions;</junctionmerge>
Shinya Kitaoka 120a6e
    joinJunctions.push_back(JunctionMerge(currJunction));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    //		std::sort(currJunction->m_nodes.begin(),
Shinya Kitaoka 38fd86
    // currJunction->m_nodes.end());
Shinya Kitaoka 120a6e
    std::deque<node *="">::iterator it;</node>
Shinya Kitaoka 120a6e
    for (it = currJunction->m_nodes.begin(); it != currJunction->m_nodes.end();
Shinya Kitaoka 120a6e
         it++) {
Shinya Kitaoka 120a6e
      Node *currNode = *it;
Shinya Kitaoka 120a6e
      Node *prevNode = *it;
Shinya Kitaoka 120a6e
      Node *nextNode = *it;
Shinya Kitaoka 120a6e
      std::vector<junctionlink>::iterator it_link;</junctionlink>
Shinya Kitaoka 120a6e
      int j;
Shinya Kitaoka 120a6e
      for (j = 0; true; ++j) {
Shinya Kitaoka 120a6e
        prevNode            = prevNode->m_prev;
Shinya Kitaoka 120a6e
        prevNode->m_visited = true;
Shinya Kitaoka 120a6e
        if (prevNode->m_junction != 0 && prevNode->m_junction != currJunction) {
Shinya Kitaoka 120a6e
          // double junctionMaxDist = 3.5*currJunction->m_center.thick;
Shinya Kitaoka 120a6e
          it_link = std::find(m_links.begin(), m_links.end(),
Shinya Kitaoka 120a6e
                              JunctionLink(currJunction, prevNode->m_junction));
Shinya Kitaoka 120a6e
          /*					if(	j >= 1*SEARCH_WINDOW &&
Toshihiro Shimizu 890ddd
						norm(currJunction->m_center - prevNode->m_junction->m_center) >= 
Toshihiro Shimizu 890ddd
junctionMaxDist)
Toshihiro Shimizu 890ddd
					{
Toshihiro Shimizu 890ddd
						assert(false);
Toshihiro Shimizu 890ddd
						if(it_link == m_links.end())
Toshihiro Shimizu 890ddd
							m_links.push_back(JunctionLink(currJunction, prevNode->m_junction));
Toshihiro Shimizu 890ddd
						else
Toshihiro Shimizu 890ddd
							++(it_link->m_order);
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					else*/ if (it_link == m_links.end() &&
Shinya Kitaoka 120a6e
                                                   std::find(
Shinya Kitaoka 120a6e
                                                       joinJunctions.begin(),
Shinya Kitaoka 120a6e
                                                       joinJunctions.end(),
Shinya Kitaoka 120a6e
                                                       JunctionMerge(
Shinya Kitaoka 120a6e
                                                           prevNode
Shinya Kitaoka 120a6e
                                                               ->m_junction)) ==
Shinya Kitaoka 120a6e
                                                       joinJunctions.end()) {
Shinya Kitaoka 120a6e
            joinJunctions.push_back(
Shinya Kitaoka 120a6e
                JunctionMerge(prevNode->m_junction, currNode, prevNode, false));
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        if (prevNode->m_visited) break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      for (j = 0; true; ++j) {
Shinya Kitaoka 120a6e
        nextNode            = nextNode->m_next;
Shinya Kitaoka 120a6e
        prevNode->m_visited = true;
Shinya Kitaoka 120a6e
        if (nextNode->m_junction != 0 && nextNode->m_junction != currJunction) {
Shinya Kitaoka 120a6e
          // double junctionMaxDist = 3.5*currJunction->m_center.thick;
Shinya Kitaoka 120a6e
          it_link = std::find(m_links.begin(), m_links.end(),
Shinya Kitaoka 120a6e
                              JunctionLink(currJunction, nextNode->m_junction));
Shinya Kitaoka 120a6e
          /*					if(	j >= 1*SEARCH_WINDOW &&
Toshihiro Shimizu 890ddd
						norm(currJunction->m_center - nextNode->m_junction->m_center) >= 
Toshihiro Shimizu 890ddd
junctionMaxDist )
Toshihiro Shimizu 890ddd
					{
Toshihiro Shimizu 890ddd
						assert(false);
Toshihiro Shimizu 890ddd
						if(it_link == m_links.end())
Toshihiro Shimizu 890ddd
							m_links.push_back(JunctionLink(currJunction, nextNode->m_junction));
Toshihiro Shimizu 890ddd
						else
Toshihiro Shimizu 890ddd
							++(it_link->m_order);
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					else*/ if (it_link == m_links.end() &&
Shinya Kitaoka 120a6e
                                                   std::find(
Shinya Kitaoka 120a6e
                                                       joinJunctions.begin(),
Shinya Kitaoka 120a6e
                                                       joinJunctions.end(),
Shinya Kitaoka 120a6e
                                                       JunctionMerge(
Shinya Kitaoka 120a6e
                                                           nextNode
Shinya Kitaoka 120a6e
                                                               ->m_junction)) ==
Shinya Kitaoka 120a6e
                                                       joinJunctions.end()) {
Shinya Kitaoka 120a6e
            joinJunctions.push_back(
Shinya Kitaoka 120a6e
                JunctionMerge(nextNode->m_junction, currNode, nextNode, true));
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        if (nextNode->m_visited) break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (joinJunctions.size() > 1) {
Shinya Kitaoka 120a6e
      // erase duplicate junctions
Shinya Kitaoka 120a6e
      //			joinJunctions.sort();
Shinya Kitaoka 120a6e
      //			std::sort(joinJunctions.begin(),
Shinya Kitaoka 38fd86
      // joinJunctions.end());
Shinya Kitaoka 120a6e
      //			std::list<junctionmerge>::iterator it_newEnd;</junctionmerge>
Shinya Kitaoka 120a6e
      //			it_newEnd = std::unique(joinJunctions.begin(),
Shinya Kitaoka 38fd86
      // joinJunctions.end());
Shinya Kitaoka 120a6e
      //			assert(it_newEnd == joinJunctions.end());
Shinya Kitaoka 120a6e
      //			joinJunctions.erase(it_newEnd,
Shinya Kitaoka 38fd86
      // joinJunctions.end());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      Junction *newJunction = mergeJunctions(joinJunctions);
Shinya Kitaoka 120a6e
      assert(newJunction);
Shinya Kitaoka 120a6e
      m_junctions.push_back(newJunction);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    joinJunctions.clear();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
void CenterLineVectorizer::resolveUnvisitedNode(Node *node)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
        assert(node->m_visited == false);
Shinya Kitaoka 120a6e
        assert(node->m_junction == 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        JunctionLink link(0,0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        Node* currNode = node;
Shinya Kitaoka 120a6e
        for(int i=0; i<4*SEARCH_WINDOW; i++)
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
                currNode = currNode->m_next;
Shinya Kitaoka 120a6e
                assert(currNode);
Shinya Kitaoka 120a6e
                if(currNode->m_junction)
Shinya Kitaoka 120a6e
                {
Shinya Kitaoka 120a6e
                        link.m_first = currNode->m_junction;
Shinya Kitaoka 120a6e
                        break;
Shinya Kitaoka 120a6e
                }
Shinya Kitaoka 120a6e
                if(currNode->m_visited) break;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if(!link.m_first) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        int steps = 0;
Shinya Kitaoka 120a6e
        for(i=0; i<4*SEARCH_WINDOW; i++)
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
                currNode = currNode->m_prev;
Shinya Kitaoka 120a6e
                assert(currNode);
Shinya Kitaoka 120a6e
                if(currNode->m_junction)
Shinya Kitaoka 120a6e
                {
Shinya Kitaoka 120a6e
                        link.m_second = currNode->m_junction;
Shinya Kitaoka 120a6e
                        break;
Shinya Kitaoka 120a6e
                }
Shinya Kitaoka 120a6e
                if(currNode->m_visited) break;
Shinya Kitaoka 120a6e
                currNode->m_visited = true;
Shinya Kitaoka 120a6e
                ++steps;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if(	(link.m_first) && (link.m_second) && (link.m_first !=
Shinya Kitaoka 120a6e
link.m_second)
Shinya Kitaoka 120a6e
                && steps >= 2*SEARCH_WINDOW && norm(link.m_first->m_center -
Toshihiro Shimizu 890ddd
link.m_second->m_center) > 2.5 &&
Shinya Kitaoka 120a6e
                std::find(m_links.begin(), m_links.end(), link) == m_links.end()
Shinya Kitaoka 120a6e
&&
Shinya Kitaoka 120a6e
                std::find(m_links.begin(), m_links.end(),
Shinya Kitaoka 120a6e
JunctionLink(link.m_second,
Toshihiro Shimizu 890ddd
link.m_first) ) == m_links.end() )
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
                m_links.push_back(link);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
                for(int i=0; i<4*SEARCH_WINDOW; i++)
Shinya Kitaoka 120a6e
                {
Shinya Kitaoka 120a6e
                        currNode = currNode->m_next;
Shinya Kitaoka 120a6e
                        assert(currNode);
Shinya Kitaoka 120a6e
                        if(currNode->m_junction) break;
Shinya Kitaoka 120a6e
                        currNode->m_visited = false;
Shinya Kitaoka 120a6e
                }
Shinya Kitaoka 120a6e
        }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::createJunctionPolygon(Junction *junction) {
Shinya Kitaoka 120a6e
  // int size = junction->m_nodes.size();
Shinya Kitaoka 120a6e
  //	std::sort(junction->m_nodes.begin(), junction->m_nodes.end(),
Shinya Kitaoka 38fd86
  // CompareJunctionNodes(junction->m_center));
Shinya Kitaoka 120a6e
  //	std::reverse(junction->m_nodes.begin(), junction->m_nodes.end());
Shinya Kitaoka 38fd86
  // std::deque<node*>::iterator it, it_temp;</node*>
Shinya Kitaoka 120a6e
  std::deque<node *="">::iterator it, it_temp;</node>
Shinya Kitaoka 120a6e
  for (it = junction->m_nodes.begin(); it != junction->m_nodes.end(); it++) {
Shinya Kitaoka 120a6e
    int step = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    Node *currNode;
Shinya Kitaoka 120a6e
    Node *otherNode;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (it + 1 == junction->m_nodes.end())
Shinya Kitaoka 120a6e
      otherNode = *junction->m_nodes.begin();
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      otherNode = *(it + 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /*		currNode = (*it)->m_prev;
Shinya Kitaoka 120a6e
    if(!currNode->m_visited)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
            step=0;
Shinya Kitaoka 120a6e
            while(!currNode->m_visited && currNode->m_junction != junction)
Shinya Kitaoka 120a6e
            {
Shinya Kitaoka 120a6e
                    it = junction->m_nodes.insert(it+1, currNode);
Shinya Kitaoka 120a6e
                    currNode->m_visited = true;
Shinya Kitaoka 120a6e
                    currNode = currNode->m_prev;
Shinya Kitaoka 120a6e
                    ++step;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
            if(currNode->m_junction != junction)
Shinya Kitaoka 120a6e
                    for(int i=0; i
Shinya Kitaoka 120a6e
                    {
Shinya Kitaoka 120a6e
                            currNode = currNode->m_next;
Shinya Kitaoka 120a6e
                            currNode->m_visited = false;
Shinya Kitaoka 120a6e
                            it = junction->m_nodes.erase(it);
Shinya Kitaoka 120a6e
                            --it;
Shinya Kitaoka 120a6e
                    }
Shinya Kitaoka 120a6e
            else
Shinya Kitaoka 120a6e
            {
Shinya Kitaoka 120a6e
                    if(currNode != otherNode)
Shinya Kitaoka 120a6e
                    {
Shinya Kitaoka 120a6e
                            it_temp = std::find(junction->m_nodes.begin(),
Shinya Kitaoka 120a6e
junction->m_nodes.end(),
Toshihiro Shimizu 890ddd
currNode);
Shinya Kitaoka 120a6e
                            if(it+1 == junction->m_nodes.end())
Shinya Kitaoka 120a6e
                                    std::swap(*junction->m_nodes.begin(),
Shinya Kitaoka 120a6e
*it_temp);
Shinya Kitaoka 120a6e
                            else
Shinya Kitaoka 120a6e
                                    std::swap(*(it+1), *it_temp);
Shinya Kitaoka 120a6e
                    }
Shinya Kitaoka 120a6e
                    continue;
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
    currNode = (*it)->m_next;
Shinya Kitaoka 120a6e
    if (!currNode->m_visited) {
Shinya Kitaoka 120a6e
      step = 0;
Shinya Kitaoka 120a6e
      while (!currNode->m_visited && currNode->m_junction != junction) {
Shinya Kitaoka 120a6e
        it                  = junction->m_nodes.insert(it + 1, currNode);
Shinya Kitaoka 120a6e
        currNode->m_visited = true;
Shinya Kitaoka 120a6e
        currNode            = currNode->m_next;
Shinya Kitaoka 120a6e
        ++step;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (currNode->m_junction != junction)  //|| currNode != otherNode)
Shinya Kitaoka 120a6e
        for (int i = 0; i < step; ++i) {
Shinya Kitaoka 120a6e
          currNode            = currNode->m_prev;
Shinya Kitaoka 120a6e
          currNode->m_visited = false;
Shinya Kitaoka 120a6e
          it                  = junction->m_nodes.erase(it);
Shinya Kitaoka 120a6e
          --it;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        //				assert(*(it+1) == otherNode || (it+1 ==
Shinya Kitaoka 38fd86
        // junction->m_nodes.end() && *junction->m_nodes.begin() == otherNode)
Shinya Kitaoka 38fd86
        // );
Shinya Kitaoka 120a6e
        if (currNode != otherNode) {
Shinya Kitaoka 120a6e
          Node tempNode = *otherNode;
Shinya Kitaoka 120a6e
          *otherNode    = *currNode;
Shinya Kitaoka 120a6e
          *currNode     = tempNode;
Shinya Kitaoka 38fd86
          //					it_temp =
Shinya Kitaoka d1f6c4
          // std::find(junction->m_nodes.begin(),
Shinya Kitaoka 38fd86
          // junction->m_nodes.end(), currNode);
Shinya Kitaoka 120a6e
          //					assert(it_temp !=
Shinya Kitaoka 38fd86
          // junction->m_nodes.end());
Shinya Kitaoka 120a6e
          //					if(it+1 ==
Shinya Kitaoka 38fd86
          // junction->m_nodes.end())
Shinya Kitaoka 120a6e
          //						std::swap(*junction->m_nodes.begin(),
Shinya Kitaoka 120a6e
          //*it_temp);
Shinya Kitaoka 120a6e
          //					else
Shinya Kitaoka 120a6e
          //						std::swap(*(it+1),
Shinya Kitaoka 120a6e
          //*it_temp);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::handleLinks() {
Shinya Kitaoka 120a6e
  std::vector<junctionlink>::iterator it_links;</junctionlink>
Shinya Kitaoka 120a6e
  for (it_links = m_links.begin(); it_links != m_links.end(); ++it_links) {
Shinya Kitaoka 120a6e
    ProtoStroke linkingProtoStroke;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // initialize points
Shinya Kitaoka 120a6e
    TThickPoint p1 = it_links->m_first->m_center;
Shinya Kitaoka 120a6e
    TThickPoint p2 = it_links->m_second->m_center - p1;
Shinya Kitaoka 120a6e
    linkingProtoStroke.m_points.push_back(
Shinya Kitaoka 120a6e
        TThickPoint(p1, JUNCTION_THICKNESS_RATIO * p1.thick));
Shinya Kitaoka 120a6e
    linkingProtoStroke.m_points.push_back(TThickPoint(
Shinya Kitaoka 120a6e
        p1 + 0.5 * p2, JUNCTION_THICKNESS_RATIO * (p1.thick + 0.5 * p2.thick)));
Shinya Kitaoka 120a6e
    linkingProtoStroke.m_points.push_back(
Shinya Kitaoka 120a6e
        TThickPoint(p1 + p2, JUNCTION_THICKNESS_RATIO * (p1.thick + p2.thick)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // initialize directions
Shinya Kitaoka 120a6e
    setEndpointsDirections(linkingProtoStroke);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // initialize junctions
Shinya Kitaoka 120a6e
    /*		linkingProtoStroke.m_startJunction = it_links->first;
Shinya Kitaoka 120a6e
    linkingProtoStroke.m_endJunction = it_links->second;*/
Shinya Kitaoka 120a6e
    m_protoStrokes.push_back(linkingProtoStroke);
Shinya Kitaoka 120a6e
    /*		it_links->first->m_protoStrokes.push_back(&m_protoStrokes.back());
Shinya Kitaoka 120a6e
    it_links->second->m_protoStrokes.push_back(&m_protoStrokes.back());*/
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool isFalseBranch(int k, ProtoStroke *protoStroke, int recursionOrder,
Shinya Kitaoka 120a6e
                   TThickPoint &edge) {
Shinya Kitaoka 120a6e
  if (recursionOrder > 3) return false;
Shinya Kitaoka 120a6e
  ++recursionOrder;
Shinya Kitaoka 120a6e
  if (k == 0) {
Shinya Kitaoka 120a6e
    if (protoStroke->m_points.front().thick > 3.0) return false;
Shinya Kitaoka 120a6e
    if (protoStroke->m_points.size() <= 20) {
Shinya Kitaoka 120a6e
      if (protoStroke->m_endJunction) {
Shinya Kitaoka 120a6e
        if (protoStroke->m_endJunction->m_protoStrokes.size() == 1) {
Shinya Kitaoka 120a6e
          edge = protoStroke->m_points.back();
Shinya Kitaoka 120a6e
          protoStroke->m_endJunction->m_protoStrokes.clear();
Shinya Kitaoka 120a6e
          protoStroke->m_points.clear();
Shinya Kitaoka 120a6e
          protoStroke->m_startJunction = 0;
Shinya Kitaoka 120a6e
          protoStroke->m_endJunction   = 0;
Shinya Kitaoka 120a6e
          return true;
Shinya Kitaoka 120a6e
        } else if (protoStroke->m_endJunction->m_protoStrokes.size() == 2) {
Shinya Kitaoka 120a6e
          ProtoStroke *nextProtoStroke;
Shinya Kitaoka 120a6e
          int next_k;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          if (protoStroke->m_endJunction->m_protoStrokes[0] == protoStroke)
Shinya Kitaoka 120a6e
            nextProtoStroke = protoStroke->m_endJunction->m_protoStrokes[1];
Shinya Kitaoka 120a6e
          else if (protoStroke->m_endJunction->m_protoStrokes[1] == protoStroke)
Shinya Kitaoka 120a6e
            nextProtoStroke = protoStroke->m_endJunction->m_protoStrokes[0];
Shinya Kitaoka 120a6e
          if (nextProtoStroke->m_startJunction == protoStroke->m_endJunction)
Shinya Kitaoka 120a6e
            next_k = 0;
Shinya Kitaoka 120a6e
          else if (nextProtoStroke->m_endJunction == protoStroke->m_endJunction)
Shinya Kitaoka 120a6e
            next_k = 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          if (isFalseBranch(next_k, nextProtoStroke, recursionOrder, edge)) {
Shinya Kitaoka 120a6e
            protoStroke->m_endJunction->m_protoStrokes.clear();
Shinya Kitaoka 120a6e
            protoStroke->m_points.clear();
Shinya Kitaoka 120a6e
            protoStroke->m_startJunction = 0;
Shinya Kitaoka 120a6e
            protoStroke->m_endJunction   = 0;
Shinya Kitaoka 120a6e
            return true;
Shinya Kitaoka 120a6e
          } else
Shinya Kitaoka 120a6e
            return false;
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          return false;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      edge = protoStroke->m_points.back();
Shinya Kitaoka 120a6e
      protoStroke->m_points.clear();
Shinya Kitaoka 120a6e
      protoStroke->m_startJunction = 0;
Shinya Kitaoka 120a6e
      protoStroke->m_endJunction   = 0;
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (k == 1) {
Shinya Kitaoka 120a6e
    if (protoStroke->m_points.back().thick > 3.0) return false;
Shinya Kitaoka 120a6e
    if (protoStroke->m_points.size() <= 20) {
Shinya Kitaoka 120a6e
      if (protoStroke->m_startJunction) {
Shinya Kitaoka 120a6e
        if (protoStroke->m_startJunction->m_protoStrokes.size() == 1) {
Shinya Kitaoka 120a6e
          edge = protoStroke->m_points.front();
Shinya Kitaoka 120a6e
          protoStroke->m_startJunction->m_protoStrokes.clear();
Shinya Kitaoka 120a6e
          protoStroke->m_points.clear();
Shinya Kitaoka 120a6e
          protoStroke->m_startJunction = 0;
Shinya Kitaoka 120a6e
          protoStroke->m_endJunction   = 0;
Shinya Kitaoka 120a6e
          return true;
Shinya Kitaoka 120a6e
        } else if (protoStroke->m_startJunction->m_protoStrokes.size() == 2) {
Shinya Kitaoka 120a6e
          ProtoStroke *nextProtoStroke;
Shinya Kitaoka 120a6e
          int next_k;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          if (protoStroke->m_startJunction->m_protoStrokes[0] == protoStroke)
Shinya Kitaoka 120a6e
            nextProtoStroke = protoStroke->m_startJunction->m_protoStrokes[1];
Shinya Kitaoka 120a6e
          else if (protoStroke->m_startJunction->m_protoStrokes[1] ==
Shinya Kitaoka 120a6e
                   protoStroke)
Shinya Kitaoka 120a6e
            nextProtoStroke = protoStroke->m_startJunction->m_protoStrokes[0];
Shinya Kitaoka 120a6e
          if (nextProtoStroke->m_startJunction == protoStroke->m_startJunction)
Shinya Kitaoka 120a6e
            next_k = 0;
Shinya Kitaoka 120a6e
          else if (nextProtoStroke->m_endJunction ==
Shinya Kitaoka 120a6e
                   protoStroke->m_startJunction)
Shinya Kitaoka 120a6e
            next_k = 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          if (isFalseBranch(next_k, nextProtoStroke, recursionOrder, edge)) {
Shinya Kitaoka 120a6e
            protoStroke->m_startJunction->m_protoStrokes.clear();
Shinya Kitaoka 120a6e
            protoStroke->m_points.clear();
Shinya Kitaoka 120a6e
            protoStroke->m_startJunction = 0;
Shinya Kitaoka 120a6e
            protoStroke->m_endJunction   = 0;
Shinya Kitaoka 120a6e
            return true;
Shinya Kitaoka 120a6e
          } else
Shinya Kitaoka 120a6e
            return false;
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          return false;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      edge = protoStroke->m_points.front();
Shinya Kitaoka 120a6e
      protoStroke->m_points.clear();
Shinya Kitaoka 120a6e
      protoStroke->m_startJunction = 0;
Shinya Kitaoka 120a6e
      protoStroke->m_endJunction   = 0;
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::handleJunctions() {
Shinya Kitaoka 120a6e
  std::vector<junction *="">::iterator it_junction = m_junctions.begin();</junction>
Shinya Kitaoka 120a6e
  for (it_junction = m_junctions.begin(); it_junction < m_junctions.end();
Shinya Kitaoka 120a6e
       it_junction++) {
Shinya Kitaoka 120a6e
    Junction *currJunction = *it_junction;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (currJunction->m_protoStrokes.empty()) {
Shinya Kitaoka 120a6e
      std::deque<node *="">::iterator it_node;</node>
Shinya Kitaoka 120a6e
      for (it_node = currJunction->m_nodes.begin();
Shinya Kitaoka 120a6e
           it_node != currJunction->m_nodes.end(); ++it_node) {
Shinya Kitaoka 120a6e
        (*it_node)->m_junction = 0;
Shinya Kitaoka 120a6e
        (*it_node)->m_visited  = false;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      delete currJunction;
Shinya Kitaoka 120a6e
      it_junction = m_junctions.erase(it_junction);
Shinya Kitaoka 120a6e
      --it_junction;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::vector<protostroke *="">::iterator it;</protostroke>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // set polygon center
Shinya Kitaoka 120a6e
    /*		double size = currJunction->m_nodes.size();
Shinya Kitaoka 120a6e
    std::deque<node*>::iterator it_node;</node*>
Shinya Kitaoka 120a6e
    for(it_node = currJunction->m_nodes.begin();
Toshihiro Shimizu 890ddd
it_node!=currJunction->m_nodes.end(); it_node++)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
            currJunction->m_center += convert( (*it_node)->m_pixel->m_pos );
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    currJunction->m_center = currJunction->m_center * (1/size);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    size = currJunction->m_protoStrokes.size();
Shinya Kitaoka 120a6e
    if(size == 0)
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
            currJunction->m_center.thick = THICKNESS_LIMIT;
Shinya Kitaoka 120a6e
            continue;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
    double size = currJunction->m_protoStrokes.size();
Shinya Kitaoka 120a6e
    for (it = currJunction->m_protoStrokes.begin();
Shinya Kitaoka 120a6e
         it != currJunction->m_protoStrokes.end(); it++) {
Shinya Kitaoka 120a6e
      if (((*it))->m_startJunction == currJunction &&
Shinya Kitaoka 120a6e
          (*it)->m_endJunction == currJunction) {
Shinya Kitaoka 120a6e
        currJunction->m_center += 0.5 * (*it)->m_points.front();
Shinya Kitaoka 120a6e
        currJunction->m_center += 0.5 * (*it)->m_points.back();
Shinya Kitaoka 120a6e
      } else if (((*it))->m_startJunction == currJunction) {
Shinya Kitaoka 120a6e
        currJunction->m_center += (*it)->m_points.front();
Shinya Kitaoka 120a6e
      } else if ((*it)->m_endJunction == currJunction) {
Shinya Kitaoka 120a6e
        currJunction->m_center += (*it)->m_points.back();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    currJunction->m_center = currJunction->m_center * (1 / size);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
  int j = 0;
Shinya Kitaoka 120a6e
  for (; j < (int)m_nodes.size(); j++) {
Shinya Kitaoka 120a6e
    Node *node = m_nodes[j];
Shinya Kitaoka 120a6e
    if (!node->m_visited && node->m_pixel) {
Shinya Kitaoka 120a6e
      m_unvisitedNodes.push_back(convert(node->m_pixel->m_pos));
Shinya Kitaoka 120a6e
      //			resolveUnvisitedNode(node);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (j = 0; j < (int)m_nodes.size(); j++) {
Shinya Kitaoka 120a6e
    Node *node = m_nodes[j];
Shinya Kitaoka 120a6e
    //		assert(node->m_visited || !node->m_pixel);
Shinya Kitaoka 120a6e
    if (node->m_pixel == 0 || node->m_flag) continue;
Shinya Kitaoka 120a6e
    outputNodes(node);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  joinJunctions();
Shinya Kitaoka 120a6e
  //	return;
Shinya Kitaoka 120a6e
  for (it_junction = m_junctions.begin(); it_junction < m_junctions.end();
Shinya Kitaoka 120a6e
       it_junction++) {
Shinya Kitaoka 120a6e
    Junction *currJunction = *it_junction;
Shinya Kitaoka 120a6e
    if (currJunction->m_center.thick < 2 * THICKNESS_LIMIT)
Shinya Kitaoka 120a6e
      currJunction->m_center.thick = 2 * THICKNESS_LIMIT;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::vector<protostroke *="">::iterator it, it_next;</protostroke>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    createJunctionPolygon(currJunction);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    currJunction->m_junctionOrder = currJunction->m_protoStrokes.size();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (currJunction->m_protoStrokes.size() == 3) {
Shinya Kitaoka 120a6e
      std::vector<protostroke *="">::iterator it_e =</protostroke>
Shinya Kitaoka 120a6e
          currJunction->m_protoStrokes.end();
Shinya Kitaoka 120a6e
      std::vector<protostroke *="">::iterator it_candidate1 = it_e,</protostroke>
Shinya Kitaoka 120a6e
                                           it_candidate2 = it_e;
Shinya Kitaoka 120a6e
      int candidate1_k, candidate2_k;
Shinya Kitaoka 120a6e
      double candidateProbability = JOIN_LIMIT;
Shinya Kitaoka 120a6e
      int k, next_k;
Shinya Kitaoka 120a6e
      for (it = currJunction->m_protoStrokes.begin(); it != it_e; it++) {
Shinya Kitaoka 120a6e
        if (((*it))->m_startJunction == currJunction)
Shinya Kitaoka 120a6e
          k = 0;
Shinya Kitaoka 120a6e
        else if ((*it)->m_endJunction == currJunction)
Shinya Kitaoka 120a6e
          k = 1;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          assert(false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (isFalseBranch(k, *it, 0, currJunction->m_center)) {
Shinya Kitaoka 120a6e
          currJunction->m_protoStrokes.erase(it);
Shinya Kitaoka 120a6e
          currJunction->m_locked = true;
Shinya Kitaoka 120a6e
          break;
Shinya Kitaoka 120a6e
        }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        it_next = it;
Shinya Kitaoka 120a6e
        it_next++;
Shinya Kitaoka 120a6e
        for (; it_next != it_e; it_next++) {
Shinya Kitaoka 120a6e
          double probability;
Shinya Kitaoka 120a6e
          if (((*it_next))->m_startJunction == currJunction)
Shinya Kitaoka 120a6e
            next_k = 0;
Shinya Kitaoka 120a6e
          else if ((*it_next)->m_endJunction == currJunction)
Shinya Kitaoka 120a6e
            next_k = 1;
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            assert(false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          if (k == 0) {
Shinya Kitaoka 120a6e
            if (next_k == 0)
Shinya Kitaoka 120a6e
              probability = 1 - norm2((*it)->m_startDirection +
Shinya Kitaoka 120a6e
                                      (*it_next)->m_startDirection);
Shinya Kitaoka 120a6e
            else
Shinya Kitaoka 120a6e
              probability = 1 - norm2((*it)->m_startDirection +
Shinya Kitaoka 120a6e
                                      (*it_next)->m_endDirection);
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            if (next_k == 0)
Shinya Kitaoka 120a6e
              probability = 1 - norm2((*it)->m_endDirection +
Shinya Kitaoka 120a6e
                                      (*it_next)->m_startDirection);
Shinya Kitaoka 120a6e
            else
Shinya Kitaoka 120a6e
              probability =
Shinya Kitaoka 120a6e
                  1 - norm2((*it)->m_endDirection + (*it_next)->m_endDirection);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          if (probability > candidateProbability ||
Shinya Kitaoka 120a6e
              (*it)->m_points.size() < 3) {
Shinya Kitaoka 120a6e
            candidateProbability = probability;
Shinya Kitaoka 120a6e
            it_candidate1        = it;
Shinya Kitaoka 120a6e
            it_candidate2        = it_next;
Shinya Kitaoka 120a6e
            candidate1_k         = k;
Shinya Kitaoka 120a6e
            candidate2_k         = next_k;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (currJunction->m_protoStrokes.size() == 3 && it_candidate1 != it_e &&
Shinya Kitaoka 120a6e
          it_candidate2 != it_e) {
Shinya Kitaoka 120a6e
        TThickPoint p1 = (candidate1_k == 0)
Shinya Kitaoka 120a6e
                             ? (*it_candidate1)->m_points.front()
Shinya Kitaoka 120a6e
                             : (*it_candidate1)->m_points.back();
Shinya Kitaoka 120a6e
        TThickPoint p2 = (candidate2_k == 0)
Shinya Kitaoka 120a6e
                             ? (*it_candidate2)->m_points.front()
Shinya Kitaoka 120a6e
                             : (*it_candidate2)->m_points.back();
Shinya Kitaoka 120a6e
        currJunction->m_center = 0.5 * (p1 + p2);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (false || currJunction->m_protoStrokes.size() == 2) {
Shinya Kitaoka 120a6e
      TPointD a1, a2, b1, b2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (currJunction->m_protoStrokes[0]->m_startJunction == currJunction) {
Shinya Kitaoka 120a6e
        a1 = currJunction->m_protoStrokes[0]->m_points.front();
Shinya Kitaoka 120a6e
        a2 = currJunction->m_protoStrokes[0]->m_startDirection - a1;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        assert(currJunction->m_protoStrokes[0]->m_endJunction == currJunction);
Shinya Kitaoka 120a6e
        a1 = currJunction->m_protoStrokes[0]->m_points.back();
Shinya Kitaoka 120a6e
        a2 = currJunction->m_protoStrokes[0]->m_endDirection - a1;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (currJunction->m_protoStrokes[1]->m_startJunction == currJunction) {
Shinya Kitaoka 120a6e
        b1 = currJunction->m_protoStrokes[1]->m_points.front();
Shinya Kitaoka 120a6e
        b2 = currJunction->m_protoStrokes[1]->m_startDirection - b1;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        assert(currJunction->m_protoStrokes[1]->m_endJunction == currJunction);
Shinya Kitaoka 120a6e
        b1 = currJunction->m_protoStrokes[1]->m_points.back();
Shinya Kitaoka 120a6e
        b2 = currJunction->m_protoStrokes[1]->m_endDirection - b1;
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*			TPointD intersection;
Toshihiro Shimizu 890ddd
			RectIntersectionResult res;
Toshihiro Shimizu 890ddd
			res = rectsIntersect(a1, a2, b1, b2, intersection);
Toshihiro Shimizu 890ddd
//			assert(res == intersected);
Toshihiro Shimizu 890ddd
			if( norm(intersection - currJunction->m_center) < 5 && res == 
Toshihiro Shimizu 890ddd
intersected)
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				currJunction->m_center.x = intersection.x;
Toshihiro Shimizu 890ddd
				currJunction->m_center.y = intersection.y;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
*/		}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
if (true || currJunction->m_nodes.size() <= 12 || currJunction->isConvex()) {
Shinya Kitaoka 120a6e
  TThickPoint junctionPoint(currJunction->m_center);
Shinya Kitaoka 120a6e
  for (it = currJunction->m_protoStrokes.begin();
Shinya Kitaoka 120a6e
       it != currJunction->m_protoStrokes.end(); it++) {
Shinya Kitaoka 120a6e
    assert((*it)->m_startJunction == currJunction ||
Shinya Kitaoka 120a6e
           (*it)->m_endJunction == currJunction);
Shinya Kitaoka 120a6e
    if ((*it)->m_startJunction == currJunction) {
Shinya Kitaoka 120a6e
      TPointD deltaPoint = (*it)->m_points.front() - junctionPoint;
Shinya Kitaoka 120a6e
      double deltaThick  = (*it)->m_points.front().thick - junctionPoint.thick;
Shinya Kitaoka 120a6e
      if (norm2(deltaPoint) > 0.2) {
Shinya Kitaoka 120a6e
        if (norm2(deltaPoint) > 2) {
Shinya Kitaoka 120a6e
          (*it)->m_points.push_front(
Shinya Kitaoka 120a6e
              TThickPoint(junctionPoint + 0.7 * deltaPoint,
Shinya Kitaoka 120a6e
                          junctionPoint.thick + 0.7 * deltaThick));
Shinya Kitaoka 120a6e
          (*it)->m_points.push_front(
Shinya Kitaoka 120a6e
              TThickPoint(junctionPoint + 0.4 * deltaPoint,
Shinya Kitaoka 120a6e
                          junctionPoint.thick + 0.4 * deltaThick));
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        (*it)->m_points.push_front(
Shinya Kitaoka 120a6e
            TThickPoint(junctionPoint + 0.0 * deltaPoint,
Shinya Kitaoka 120a6e
                        junctionPoint.thick + 0.0 * deltaThick));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if ((*it)->m_endJunction == currJunction) {
Shinya Kitaoka 120a6e
      TPointD deltaPoint = (*it)->m_points.back() - junctionPoint;
Shinya Kitaoka 120a6e
      double deltaThick  = (*it)->m_points.back().thick - junctionPoint.thick;
Shinya Kitaoka 120a6e
      if (norm2(deltaPoint) > 0.2) {
Shinya Kitaoka 120a6e
        if (norm2(deltaPoint) > 2) {
Shinya Kitaoka 120a6e
          (*it)->m_points.push_back(
Shinya Kitaoka 120a6e
              TThickPoint(junctionPoint + 0.7 * deltaPoint,
Shinya Kitaoka 120a6e
                          junctionPoint.thick + 0.7 * deltaThick));
Shinya Kitaoka 120a6e
          (*it)->m_points.push_back(
Shinya Kitaoka 120a6e
              TThickPoint(junctionPoint + 0.4 * deltaPoint,
Shinya Kitaoka 120a6e
                          junctionPoint.thick + 0.4 * deltaThick));
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        (*it)->m_points.push_back(
Shinya Kitaoka 120a6e
            TThickPoint(junctionPoint + 0.0 * deltaPoint,
Shinya Kitaoka 120a6e
                        junctionPoint.thick + 0.0 * deltaThick));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
} else {
Shinya Kitaoka 120a6e
  ProtoRegion region(currJunction->isConvex());
Shinya Kitaoka 120a6e
  region.m_center = currJunction->m_center;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::deque<node *="">::iterator it_nodes;</node>
Shinya Kitaoka 120a6e
  for (it_nodes = currJunction->m_nodes.begin();
Shinya Kitaoka 120a6e
       it_nodes != currJunction->m_nodes.end(); it_nodes++)
Shinya Kitaoka 120a6e
    region.m_points.push_back(
Shinya Kitaoka 120a6e
        TThickPoint(convert((*it_nodes)->m_pixel->m_pos), 0.0));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  region.m_points.push_back(TThickPoint(
Shinya Kitaoka 120a6e
      convert((*currJunction->m_nodes.begin())->m_pixel->m_pos), 0.0));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_protoRegions.push_back(region);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (it = currJunction->m_protoStrokes.begin();
Shinya Kitaoka 120a6e
       it != currJunction->m_protoStrokes.end(); it++) {
Shinya Kitaoka 120a6e
    if ((*it)->m_startJunction == currJunction &&
Shinya Kitaoka 120a6e
        (*it)->m_endJunction == currJunction) {
Shinya Kitaoka 120a6e
      if ((*it)->m_points.size() < 10) (*it)->m_points.clear();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if ((*it)->m_startJunction == currJunction) {
Shinya Kitaoka 120a6e
      (*it)->m_startJunction = 0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if ((*it)->m_endJunction == currJunction) {
Shinya Kitaoka 120a6e
      (*it)->m_endJunction = 0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  currJunction->m_protoStrokes.clear();
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // handleLinks();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::createStrokes() {
Shinya Kitaoka 120a6e
  std::list<protostroke>::iterator it_centerlines = m_protoStrokes.begin();</protostroke>
Shinya Kitaoka 120a6e
  for (; it_centerlines != m_protoStrokes.end(); it_centerlines++) {
Shinya Kitaoka 120a6e
    if (!it_centerlines->m_points.empty()) {
Shinya Kitaoka 120a6e
      joinProtoStrokes(&(*it_centerlines));
Shinya Kitaoka 120a6e
      if (it_centerlines->m_points.size() <= 1) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
      std::deque<tthickpoint>::iterator it;</tthickpoint>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (m_configuration.m_smoothness > 0)  // gmt: prima era true
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        // gmt, 30-3-2006:
Shinya Kitaoka 120a6e
        /*
Shinya Kitaoka 120a6e
        it = it_centerlines->m_points.begin()+1;
Shinya Kitaoka 120a6e
        for(;;)
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
                if( it >=
Shinya Kitaoka 120a6e
        it_centerlines->m_points.end()-(m_configuration.m_smoothness+1)) break;
Shinya Kitaoka 120a6e
                for(int j=0; j
Shinya Kitaoka 120a6e
                        it = it_centerlines->m_points.erase(it);
Shinya Kitaoka 120a6e
                ++it;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
        // gmt. credo che l'idea sia di lasciare un punto e
Shinya Kitaoka 120a6e
        // toglierne m_configuration.m_smoothness e cosi' via fino alla fine
Shinya Kitaoka 120a6e
        // n.b. ho modificato il comportamento sugli eventuali ultimi punti
Shinya Kitaoka 120a6e
        // (
Shinya Kitaoka 120a6e
        // vengono tolti
Shinya Kitaoka 120a6e
        std::deque<tthickpoint> &points = it_centerlines->m_points;</tthickpoint>
Shinya Kitaoka 120a6e
        it                              = points.begin();
Shinya Kitaoka 120a6e
        for (;;) {
Shinya Kitaoka 120a6e
          if (it == points.end()) break;
Shinya Kitaoka 120a6e
          ++it;
Shinya Kitaoka 120a6e
          int maxD = std::distance(it, points.end());
Shinya Kitaoka 120a6e
          int d    = tmin(maxD, m_configuration.m_smoothness);
Shinya Kitaoka 120a6e
          if (d == 0) break;
Shinya Kitaoka 120a6e
          it = points.erase(it, it + d);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      it = it_centerlines->m_points.begin();
Shinya Kitaoka 120a6e
      points.push_back(*it);
Shinya Kitaoka 120a6e
      assert(it->thick >= THICKNESS_LIMIT);
Shinya Kitaoka 120a6e
      TThickPoint old = *it;
Shinya Kitaoka 120a6e
      for (it++; it != it_centerlines->m_points.end(); ++it) {
Shinya Kitaoka 120a6e
        assert(it->thick >= THICKNESS_LIMIT);
Shinya Kitaoka 120a6e
        TThickPoint point(0.5 * (*it + old), 0.5 * (it->thick + old.thick));
Shinya Kitaoka 120a6e
        points.push_back(point);
Shinya Kitaoka 120a6e
        old = *it;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      points.push_back(it_centerlines->m_points.back());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int n = points.size();
Shinya Kitaoka 120a6e
      if (n > 5) {
Shinya Kitaoka 120a6e
        double *rr = new double[n];
Shinya Kitaoka 120a6e
        int i;
Shinya Kitaoka 120a6e
        for (i = 0; i < n; i++) rr[i] = points[i].thick;
Shinya Kitaoka 120a6e
        for (i            = 2; i < n - 2; i++)
Shinya Kitaoka 120a6e
          points[i].thick = 0.8 * (1 / 5.0) * (/*rr[i-4]+rr[i-3]*/ +rr[i - 2] +
Shinya Kitaoka 120a6e
                                               rr[i - 1] + rr[i] + rr[i + 1] +
Shinya Kitaoka 120a6e
                                               rr[i + 2] /*+rr[i+3]+rr[i+4]*/);
Shinya Kitaoka 120a6e
        points[0].thick = points[1].thick =
Shinya Kitaoka 120a6e
            points[2].thick;  //=points[3].thick;//=points[4].thick;
Shinya Kitaoka 120a6e
        points[n - 1].thick = points[n - 2].thick =
Shinya Kitaoka 120a6e
            points[n - 3].thick;  //=points[n-4].thick;//=points[n-5].thick;
Shinya Kitaoka 120a6e
        delete[] rr;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      TStroke *stroke =
Shinya Kitaoka 120a6e
          TStroke::interpolate(points, m_configuration.m_interpolationError);
Shinya Kitaoka 120a6e
      stroke->setStyle(m_configuration.m_strokeStyleId);  // FirstUserStyle+2);
Shinya Kitaoka 120a6e
      m_vimage->addStroke(stroke);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::createRegions() {
Shinya Kitaoka 120a6e
  std::list<protoregion>::iterator it_regions;</protoregion>
Shinya Kitaoka 120a6e
  for (it_regions = m_protoRegions.begin(); it_regions != m_protoRegions.end();
Shinya Kitaoka 120a6e
       it_regions++) {
Shinya Kitaoka 120a6e
    assert(it_regions->m_points.size() > 4);
Shinya Kitaoka 120a6e
    TStroke *stroke = TStroke::interpolate(it_regions->m_points, 0.1);
Shinya Kitaoka 120a6e
    stroke->setSelfLoop();
Shinya Kitaoka 120a6e
    stroke->setStyle(m_configuration.m_strokeStyleId);
Shinya Kitaoka 120a6e
    m_vimage->addStroke(stroke);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /*
Shinya Kitaoka 120a6e
    if(it_regions->m_isConvex)
Shinya Kitaoka 120a6e
            m_vimage->fill(it_regions->m_center, TPalette::DefaultStrokeStyle);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
            TPointD internalPoint;
Shinya Kitaoka 120a6e
            internalPoint = rotate90(it_regions->m_points[1] -
Toshihiro Shimizu 890ddd
it_regions->m_points[0]);
Shinya Kitaoka 120a6e
            assert(norm2(internalPoint) != 0);
Shinya Kitaoka 120a6e
            normalize(internalPoint);
Shinya Kitaoka 120a6e
            internalPoint = internalPoint*0.001 + 0.5*(it_regions->m_points[1] +
Toshihiro Shimizu 890ddd
it_regions->m_points[0]);
Shinya Kitaoka 120a6e
            m_vimage->fill(internalPoint, TPalette::DefaultStrokeStyle);
Shinya Kitaoka 120a6e
    }*/
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CenterLineVectorizer::vectorize() {
Shinya Kitaoka 120a6e
  int j = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (j = 0; j < (int)m_nodes.size(); j++) {
Shinya Kitaoka 120a6e
    Node *node = m_nodes[j];
Shinya Kitaoka 120a6e
    if (node->m_pixel == 0 || node->m_visited) continue;
Shinya Kitaoka 120a6e
    traceLine(node->m_pixel);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  handleJunctions();
Shinya Kitaoka 120a6e
  createStrokes();
Shinya Kitaoka 120a6e
  createRegions();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
void printTime(TStopWatch &sw, string name) {
2fc36c
  stringstream ss;
Shinya Kitaoka 120a6e
  ss << name << " : ";
Shinya Kitaoka 120a6e
  sw.print(ss);
Shinya Kitaoka 120a6e
  ss << '\n' << '\0';
Shinya Kitaoka 120a6e
  string s = ss.str();
Shinya Kitaoka 120a6e
  TSystem::outputDebug(s);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
void CenterLineVectorizer::outputInks() {
Shinya Kitaoka 120a6e
  for (int i = 0; i < m_dataRaster->getLx() * m_dataRaster->getLy(); i++) {
Shinya Kitaoka 120a6e
    DataPixel *pix = m_dataRaster->pixels() + i;
Shinya Kitaoka 120a6e
    if (pix->m_ink)
Shinya Kitaoka 120a6e
      getOutPix(pix) = TPixel32::Black;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      getOutPix(pix) = TPixel32::White;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TVectorImageP centerlineVectorize(const TImageP &image,
Shinya Kitaoka 120a6e
                                  const VectorizerConfiguration &c,
Shinya Kitaoka 120a6e
                                  TPalette *palette) {
Shinya Kitaoka 120a6e
  CenterLineVectorizer vectorizer(c, palette);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterImageP ri = image;
Shinya Kitaoka 120a6e
  TToonzImageP vi  = image;
Shinya Kitaoka 120a6e
  if (ri)
Shinya Kitaoka 120a6e
    vectorizer.makeDataRaster(ri->getRaster());
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    vectorizer.makeDataRaster(vi->getRaster());
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)vectorizer.m_dataRasterArray.size(); i++) {
Shinya Kitaoka 120a6e
    vectorizer.m_dataRaster = vectorizer.m_dataRasterArray[i].second;
Shinya Kitaoka 120a6e
    vectorizer.m_configuration.m_strokeStyleId =
Shinya Kitaoka 120a6e
        vectorizer.m_dataRasterArray[i].first;
Shinya Kitaoka 120a6e
    vectorizer.init();
Shinya Kitaoka 120a6e
    vectorizer.vectorize();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  renormalizeImage(vectorizer.m_vimage.getPointer());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return vectorizer.m_vimage;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class OutlineVectorizer : public CenterLineVectorizer {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  list<vector<tthickpoint>> m_protoOutlines;</vector<tthickpoint>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void traceOutline(Node *initialNode);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  OutlineVectorizer(const VectorizerConfiguration &configuration,
Shinya Kitaoka 120a6e
                    TPalette *palette)
Shinya Kitaoka 120a6e
      : CenterLineVectorizer(configuration, palette) {}
Shinya Kitaoka 120a6e
  ~OutlineVectorizer();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void createOutlineStrokes();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  // not implemented
Shinya Kitaoka 120a6e
  OutlineVectorizer(const OutlineVectorizer &);
Shinya Kitaoka 120a6e
  OutlineVectorizer &operator=(const OutlineVectorizer &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
OutlineVectorizer::~OutlineVectorizer() { m_protoOutlines.clear(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OutlineVectorizer::traceOutline(Node *initialNode) {
Shinya Kitaoka 120a6e
  Node *startNode = initialNode;
Shinya Kitaoka 120a6e
  Node *node;
Shinya Kitaoka 120a6e
  do {
Shinya Kitaoka 120a6e
    if (!startNode) break;
Shinya Kitaoka 120a6e
    node = findOtherSide(startNode);
Shinya Kitaoka 120a6e
    if (!node) break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double startDist2 = computeDistance2(startNode, node);
Shinya Kitaoka 120a6e
    if (startDist2 > 0.1) break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    startNode = startNode->m_next;
Shinya Kitaoka 120a6e
    //		assert(startNode != initialNode);
Shinya Kitaoka 120a6e
  } while (startNode != initialNode);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!startNode) return;
Shinya Kitaoka 120a6e
  node = startNode;
Shinya Kitaoka 120a6e
  std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
  do {
Shinya Kitaoka 120a6e
    node = node->m_next;
Shinya Kitaoka 120a6e
    if (!node) break;
Shinya Kitaoka 120a6e
    node->m_visited = true;
Shinya Kitaoka 120a6e
    points.push_back(TThickPoint(convert(node->m_pixel->m_pos), 0));
Shinya Kitaoka 120a6e
  } while (node != startNode);
Shinya Kitaoka 120a6e
  m_protoOutlines.push_back(points);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OutlineVectorizer::createOutlineStrokes() {
Shinya Kitaoka 120a6e
  m_vimage->enableRegionComputing(true, false);
Shinya Kitaoka 120a6e
  int j;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (j = 0; j < (int)m_nodes.size(); j++) {
Shinya Kitaoka 120a6e
    Node *node = m_nodes[j];
Shinya Kitaoka 120a6e
    if (node->m_pixel == 0 || node->m_visited) continue;
Shinya Kitaoka 120a6e
    traceOutline(node);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DEBUG
Shinya Kitaoka 120a6e
  for (j = 0; j < (int)m_nodes.size(); j++) {
Shinya Kitaoka 120a6e
    Node *node = m_nodes[j];
Shinya Kitaoka 120a6e
    //		assert(node->m_visited || !node->m_pixel);
Shinya Kitaoka 120a6e
    if (node->m_pixel == 0 || node->m_flag) continue;
Shinya Kitaoka 120a6e
    outputNodes(node);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::list<std::vector<tthickpoint>>::iterator it_outlines =</std::vector<tthickpoint>
Shinya Kitaoka 120a6e
      m_protoOutlines.begin();
Shinya Kitaoka 120a6e
  for (; it_outlines != m_protoOutlines.end(); it_outlines++) {
Shinya Kitaoka 120a6e
    if (it_outlines->size() > 3) {
Shinya Kitaoka 120a6e
      std::vector<tthickpoint> points;</tthickpoint>
Shinya Kitaoka 120a6e
      std::vector<tthickpoint>::iterator it;</tthickpoint>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (it_outlines->size() > 10) {
Shinya Kitaoka 120a6e
        it = it_outlines->begin() + 1;
Shinya Kitaoka 120a6e
        for (;;) {
Shinya Kitaoka 120a6e
          if (it >= it_outlines->end() - (m_configuration.m_smoothness + 1))
Shinya Kitaoka 120a6e
            break;
Shinya Kitaoka 120a6e
          for (j = 0; j < m_configuration.m_smoothness; j++)
Shinya Kitaoka 120a6e
            it = it_outlines->erase(it);
Shinya Kitaoka 120a6e
          ++it;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      points.push_back(it_outlines->front());
Shinya Kitaoka 120a6e
      it              = it_outlines->begin();
Shinya Kitaoka 120a6e
      TThickPoint old = *it;
Shinya Kitaoka 120a6e
      ++it;
Shinya Kitaoka 120a6e
      for (; it != it_outlines->end(); ++it) {
Shinya Kitaoka 120a6e
        TThickPoint point((1 / 2.0) * (*it + old));
Shinya Kitaoka 120a6e
        points.push_back(point);
Shinya Kitaoka 120a6e
        old = *it;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      points.push_back(it_outlines->back());
Shinya Kitaoka 120a6e
      points.push_back(it_outlines->front());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*TPointD internalPoint;
Shinya Kitaoka 120a6e
      internalPoint = rotate90(points[1] - points[0]);
Shinya Kitaoka 120a6e
      assert(norm2(internalPoint) != 0);
Shinya Kitaoka 120a6e
      normalize(internalPoint);
Shinya Kitaoka 120a6e
      internalPoint = internalPoint*0.001 + points[0];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPointD externalPoint;
Shinya Kitaoka 120a6e
      externalPoint = rotate270(points[1] - points[0]);
Shinya Kitaoka 120a6e
      assert(norm2(externalPoint) != 0);
Shinya Kitaoka 120a6e
      normalize(externalPoint);
Shinya Kitaoka 120a6e
      externalPoint = externalPoint*0.001 + points[0];*/
Shinya Kitaoka 120a6e
      TStroke *stroke =
Shinya Kitaoka 120a6e
          TStroke::interpolate(points, m_configuration.m_interpolationError);
Shinya Kitaoka 120a6e
      stroke->setStyle(m_configuration.m_strokeStyleId);
Shinya Kitaoka 120a6e
      stroke->setSelfLoop();
Shinya Kitaoka 120a6e
      m_vimage->addStroke(stroke);
Shinya Kitaoka 120a6e
      //			TStroke *stroke = TStroke::interpolate(points,
Shinya Kitaoka 38fd86
      // m_configuration.interpolationError);
Shinya Kitaoka 120a6e
      //     		stroke->setStyle(strokeStyleId);
Shinya Kitaoka 120a6e
      //			m_vimage->addStroke(stroke);//,
Shinya Kitaoka 38fd86
      // TPalette::DefaultStrokeStyle, TPalette::DefaultFillStyle);
Shinya Kitaoka 120a6e
      // internalPoints.push_back(internalPoint);
Shinya Kitaoka 120a6e
      // m_vimage->fill(externalPoint, TPalette::DefaultFillStyle);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // m_vimage->autoFill(m_configuration.m_strokeStyleId);
Shinya Kitaoka 120a6e
  // for (UINT i=0; i
Shinya Kitaoka 120a6e
  //  m_vimage->fill(internalPoints[i],fillStyleId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TVectorImageP outlineVectorize(const TImageP &image,
Shinya Kitaoka 120a6e
                               const VectorizerConfiguration &configuration,
Shinya Kitaoka 120a6e
                               TPalette *palette) {
Shinya Kitaoka 120a6e
  TVectorImageP out;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  OutlineVectorizer vectorizer(configuration, palette);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterImageP ri = image;
Shinya Kitaoka 120a6e
  TToonzImageP vi  = image;
Shinya Kitaoka 120a6e
  if (ri)
Shinya Kitaoka 120a6e
    vectorizer.makeDataRaster(ri->getRaster());
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    vectorizer.makeDataRaster(vi->getRaster());
Shinya Kitaoka 120a6e
  int layersCount = vectorizer.m_dataRasterArray.size();
Shinya Kitaoka 120a6e
  if (layersCount > 1) {
Shinya Kitaoka 120a6e
    out = new TVectorImage();
Shinya Kitaoka 120a6e
    out->setPalette(palette);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)layersCount; i++) {
Shinya Kitaoka 120a6e
    vectorizer.m_dataRaster = vectorizer.m_dataRasterArray[i].second;
Shinya Kitaoka 120a6e
    vectorizer.m_configuration.m_strokeStyleId =
Shinya Kitaoka 120a6e
        vectorizer.m_dataRasterArray[i].first;
Shinya Kitaoka 120a6e
    vectorizer.m_protoOutlines.clear();
Shinya Kitaoka 120a6e
    vectorizer.init();
Shinya Kitaoka 120a6e
    vectorizer.createOutlineStrokes();
Shinya Kitaoka 120a6e
    renormalizeImage(vectorizer.m_vimage.getPointer());
Shinya Kitaoka 120a6e
    vectorizer.m_vimage->setPalette(palette);
Shinya Kitaoka 120a6e
    if (layersCount > 1) out->mergeImage(vectorizer.m_vimage, TAffine());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (i != (int)layersCount - 1) vectorizer.m_vimage = new TVectorImage();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return (layersCount == 1) ? vectorizer.m_vimage : out;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Shinya Kitaoka 120a6e
void applyFillColors(TRegion *r, const TRasterP &ras, TPalette *palette,
Shinya Kitaoka 120a6e
                     const TPoint &offset, bool leaveUnpainted) {
Shinya Kitaoka 120a6e
  TPointD pd;
Shinya Kitaoka 120a6e
  TRasterCM32P rt = (TRasterCM32P)ras;
Shinya Kitaoka 120a6e
  TRaster32P rr   = (TRaster32P)ras;
Shinya Kitaoka 120a6e
  TRasterGR8P rgr = (TRasterGR8P)ras;
Shinya Kitaoka 120a6e
  assert(rt || rr || rgr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (/*r->getStyle()==0 && */ r->getInternalPoint(pd)) {
Shinya Kitaoka 120a6e
    TPoint p = convert(pd) + offset;
Shinya Kitaoka 120a6e
    if (ras->getBounds().contains(p)) {
Shinya Kitaoka 120a6e
      int styleId = 0;
Shinya Kitaoka 120a6e
      if (rt) {
Shinya Kitaoka 120a6e
        TPixelCM32 col = rt->pixels(p.y)[p.x];
Shinya Kitaoka 120a6e
        int tone       = col.getTone();
Shinya Kitaoka 120a6e
        if (tone < 100) {
Shinya Kitaoka 120a6e
          styleId                                      = col.getInk();
Shinya Kitaoka 120a6e
          if (styleId == 0 && !leaveUnpainted) styleId = col.getPaint();
Shinya Kitaoka 120a6e
        } else if (!leaveUnpainted || col.getPaint() == 0) {
Shinya Kitaoka 120a6e
          styleId                   = col.getPaint();
Shinya Kitaoka 120a6e
          if (styleId == 0) styleId = col.getInk();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        TPixel32 color;
Shinya Kitaoka 120a6e
        if (rr)
Shinya Kitaoka 120a6e
          color = rr->pixels(p.y)[p.x];
Shinya Kitaoka 120a6e
        else {
Shinya Kitaoka 120a6e
          int val = rgr->pixels(p.y)[p.x].value;
Shinya Kitaoka 120a6e
          color   = (val < 80) ? TPixel32::Black : TPixel32::White;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        styleId = palette->getClosestStyle(color);
Shinya Kitaoka 120a6e
        if (palette->getStyle(styleId)->getMainColor() != color)
Shinya Kitaoka 120a6e
          styleId = palette->addStyle(color);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      r->fill(pd, styleId);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)r->getSubregionCount(); i++)
Shinya Kitaoka 120a6e
    applyFillColors(r->getSubregion(i), ras, palette, offset, leaveUnpainted);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void applyFillColors(TVectorImageP vi, const TImageP &img, TPalette *palette,
Shinya Kitaoka 120a6e
                     bool leaveUnpainted) {
Shinya Kitaoka 120a6e
  TToonzImageP ti  = (TToonzImageP)img;
Shinya Kitaoka 120a6e
  TRasterImageP ri = (TRasterImageP)img;
Shinya Kitaoka 120a6e
  TRectD vb        = vi->getBBox();
Shinya Kitaoka 120a6e
  TRectD tb        = img->getBBox();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterP ras;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (ti)
Shinya Kitaoka 120a6e
    ras = ti->getRaster();
Shinya Kitaoka 120a6e
  else if (ri)
Shinya Kitaoka 120a6e
    ras = ri->getRaster();
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    assert(false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  vi->findRegions();
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)vi->getRegionCount(); i++)
Shinya Kitaoka 120a6e
    applyFillColors(vi->getRegion(i), ras, palette,
Shinya Kitaoka 120a6e
                    convert(tb.getP00() - vb.getP00()), leaveUnpainted);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TVectorImageP vectorize(const TImageP &img, const VectorizerConfiguration &c,
Shinya Kitaoka 120a6e
                        TPalette *plt) {
Shinya Kitaoka 120a6e
  TVectorImageP vi = c.m_outline ? outlineVectorize(img, c, plt)
Shinya Kitaoka 120a6e
                                 : centerlineVectorize(img, c, plt);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  applyFillColors(vi, img, plt, c.m_leaveUnpainted);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // else if (c.m_outline)
Shinya Kitaoka 120a6e
  //  vi->autoFill(c.m_strokeStyleId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD center;
Shinya Kitaoka 120a6e
  if (TToonzImageP ti = img)
Shinya Kitaoka 120a6e
    center = ti->getRaster()->getCenterD();
Shinya Kitaoka 120a6e
  else if (TRasterImageP ri = img)
Shinya Kitaoka 120a6e
    center = ri->getRaster()->getCenterD();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TAffine aff = TTranslation(-center);
Shinya Kitaoka 120a6e
  vi->transform(aff);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return vi;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------