void TestSpawnTeleport() {
    std::cout << "TEST EMPTY\n";
    TBoard board(8, 8);

    TUnit::TSegments segments = {
        TSegment(Coords::TColRowPoint(0, 0)),
        TSegment(Coords::TColRowPoint(1, 0)),
        TSegment(Coords::TColRowPoint(1, 1)),
        TSegment(Coords::TColRowPoint(2, 1)),
    };

    /*  xX */
    TUnit unit(
        TSegment(Coords::TColRowPoint(1, 0)),
        std::move(segments)
    );
    auto teleported = board.TeleportUnitToSpawnPosition(unit);
    if (teleported.GetPivot().GetPosition().Column != 4) {
        throw TException("TestSpawnTeleport error")
            << __FILE__ << ":" << __LINE__
            << " :\n" << teleported.GetPivot().GetPosition().Column << "\n"
            << "expected: 4"
        ;
    }
}
Esempio n. 2
0
unsigned CShuangpinSegmentor::_push (unsigned ch)
{
    int startFrom = 0;
    bool isInputPy;
    EShuangpinType shpType;

    m_pystr.push_back (ch);
    const int len = m_pystr.size();
    if (m_hasInvalid) {
        startFrom = len - 1;
        m_segs.push_back (TSegment (ch, startFrom, 1, IPySegmentor::INVALID));
        goto RETURN;
    }

    shpType = s_shpData.getShuangpinType();
    isInputPy = ( islower(ch) ||
                   (ch == ';' && (shpType == MS2003 || shpType == ZIGUANG)) );
    
    if (!isInputPy) { 
        startFrom = len - 1;
        
        IPySegmentor::ESegmentType seg_type;
        if (ch == '\'' && m_inputBuf.size() > 1)
            seg_type = IPySegmentor::SYLLABLE_SEP;
        else
            seg_type = IPySegmentor::STRING;
        m_segs.push_back (TSegment (ch, startFrom, 1, seg_type));
        m_nAlpha += 1;
        m_nLastValidPos += 1;
    } else {
        bool bCompleted = !((len - m_nAlpha)%2) && isInputPy;
        char buf[4];
        if (bCompleted) {
            sprintf(buf, "%c%c", m_pystr[len-2], ch);
        } else {
            sprintf(buf, "%c", ch);
        }
        startFrom = _encode(buf, ch, bCompleted);
        if (startFrom < 0) {
            m_hasInvalid = true;
            startFrom = m_pystr.size() - 1;
            m_segs.push_back (TSegment (ch, startFrom, 1, IPySegmentor::INVALID));
        }
    }

RETURN:;

    if (m_pGetFuzzySyllablesOp && m_pGetFuzzySyllablesOp->isEnabled())
        if ( m_segs.back().m_type == SYLLABLE)
            _addFuzzySyllables (m_segs.back ());

    return startFrom;
}
TSegment TSegment::Slide(EMoveOperations direction) const {
    Coords::THexPoint hexPos = Coords::ToHex(Position);

    switch (direction) {
        case EMoveOperations::SLIDE_EAST: {
            ++hexPos.X;
            --hexPos.Z;
            break;
        }
        case EMoveOperations::SLIDE_WEST: {
            --hexPos.X;
            ++hexPos.Z;
            break;
        }
        case EMoveOperations::SLIDE_SOUTHEAST: {
            --hexPos.Z;
            ++hexPos.Y;
            break;
        }
        case EMoveOperations::SLIDE_SOUTHWEST: {
            --hexPos.X;
            ++hexPos.Y;
            break;
        }
        default: {
            throw TException("Invalid slide operation recieved in ")
                << __FILE__ << ":" << __LINE__;
        }
    }

    Coords::TColRowPoint newPos = Coords::FromHex(hexPos);
    return TSegment(newPos);
}
Esempio n. 4
0
int CHunpinSegmentor::_encode(const char* buf,int ret)
{
    CMappedYin syls;
    syls.reserve(8);
    s_shpData.getMapString(buf, syls);
    if (syls.empty())
        return -1;
	
	
    CMappedYin::const_iterator iter = syls.begin();
    CMappedYin::const_iterator iter_end = syls.end();
	
	m_segs.push_back (TSegment (0, 0, 1, IPySegmentor::SYLLABLE));
	TSegment &s = m_segs.back();
	
	s.m_len = 2;
	s.m_start = ret;
	s.m_syllables.clear();
	s.m_type = IPySegmentor::SYLLABLE; 
	for (; iter!=iter_end; iter++) {
		s.m_syllables.push_back(s_shpData.encodeSyllable(iter->c_str()));
	}
	
	return s.m_start;
    
}
TSegment TSegment::TeleportBy(const Coords::THexPoint& hexDelta) const {
    Coords::THexPoint oldHexPos = Coords::ToHex(Position);
    Coords::THexPoint newHexPos(
        oldHexPos.X + hexDelta.X,
        oldHexPos.Y + hexDelta.Y,
        oldHexPos.Z + hexDelta.Z
    );

    return TSegment(Coords::FromHex(newHexPos));
}
TSegment
TSegment::RotateAround(
    const Coords::TColRowPoint& pivot,
    EMoveOperations direction
) const {
    static const auto shiftCoordsLeft
        = [](const Coords::THexPoint& p) -> Coords::THexPoint {
        //    x y z
        // -> y z x
        return Coords::THexPoint(p.Y, p.Z, p.X);
    };
    static const auto shiftCoordsRight
        = [](const Coords::THexPoint& p) -> Coords::THexPoint {
        //    x y z
        // -> z x y
        return Coords::THexPoint(p.Z, p.X, p.Y);
    };
    static const auto invertSigns
        = [](const Coords::THexPoint& p) -> Coords::THexPoint {
        return Coords::THexPoint(-1* p.X, -1 * p.Y, -1 * p.Z);
    };

    Coords::THexPoint hexPivot = Coords::ToHex(pivot);
    Coords::THexPoint hexSelf = Coords::ToHex(Position);

    Coords::THexPoint hexSelfLocal(
        hexSelf.X - hexPivot.X,
        hexSelf.Y - hexPivot.Y,
        hexSelf.Z - hexPivot.Z
    );

    Coords::THexPoint newHexSelfLocal = hexSelfLocal;
    switch (direction) {
        case EMoveOperations::ROTATE_CLOCKWISE: {
            newHexSelfLocal = invertSigns(shiftCoordsLeft(hexSelfLocal));
            break;
        }
        case EMoveOperations::ROTATE_ANTI_CLOCKWISE: {
            newHexSelfLocal = invertSigns(shiftCoordsRight(hexSelfLocal));
            break;
        }
        default: {
            throw TException("Invalid rotation operation recieved in ")
                << __FILE__ << ":" << __LINE__;
        }
    }

    Coords::THexPoint newPosition(
        hexPivot.X + newHexSelfLocal.X,
        hexPivot.Y + newHexSelfLocal.Y,
        hexPivot.Z + newHexSelfLocal.Z
    );

    return TSegment(Coords::FromHex(newPosition));
}
TUnit TUnit::TeleportTo(const Coords::TColRowPoint& newPivotPos) const {
    Coords::TColRowPoint oldPivotPos = Pivot.GetPosition();
    Coords::THexPoint newPivotHexPos = Coords::ToHex(newPivotPos);
    Coords::THexPoint oldPivotHexPos = Coords::ToHex(oldPivotPos);

    Coords::THexPoint hexDelta(
        newPivotHexPos.X - oldPivotHexPos.X,
        newPivotHexPos.Y - oldPivotHexPos.Y,
        newPivotHexPos.Z - oldPivotHexPos.Z
    );

    return TUnit(TSegment(newPivotPos), TeleportSegments(hexDelta));
}
TWayGraph::TWays
TWayGraph::FindWay(
    const Coords::TColRowPoint& from,
    size_t fromDirection,
    const Coords::TColRowPoint& to,
    size_t toDirection
) {
    FinishPoint = TSegment(to);
    FinishDirection = toDirection;

    size_t rows = Graph.size();
    size_t columns = Graph.front().size();
    for (size_t row = 0; row < rows; ++row) {
        for (size_t column = 0; column < columns; ++column) {
            for (size_t turn = 0; turn < TurnDirections; ++turn) {
                auto& node = Graph.at(row).at(column).at(turn);
                node.Color = EColor::WHITE;
            }
        }
    }
    Dfs(TSegment(from), fromDirection);
    return AllWays;
}
Esempio n. 9
0
void CameraTestTool::mouseMove(const TPointD &p, const TMouseEvent &e) {
  if (m_lastPos.x != -1)  // left mouse button is clicked
  {
    m_scaling = eNoScale;
    return;
  }

  CleanupParameters *cp =
      CleanupSettingsModel::instance()->getCurrentParameters();
  double pixelSize = getPixelSize();

  TPointD size(10 * pixelSize, 10 * pixelSize);
  TRectD r(cp->m_camera.getStageRect());
  TPointD aux(Stage::inch * TPointD(0.5 * cp->m_offx, 0.5 * cp->m_offy));
  r -= aux;
  double maxDist = 5 * pixelSize;

  if (TRectD(r.getP00() - size, r.getP00() + size).contains(p))
    m_scaling = e00;
  else if (TRectD(r.getP01() - size, r.getP01() + size).contains(p))
    m_scaling = e01;
  else if (TRectD(r.getP11() - size, r.getP11() + size).contains(p))
    m_scaling = e11;
  else if (TRectD(r.getP10() - size, r.getP10() + size).contains(p))
    m_scaling = e10;
  else if (isCloseToSegment(p, TSegment(r.getP00(), r.getP10()), maxDist))
    m_scaling = eM0;
  else if (isCloseToSegment(p, TSegment(r.getP10(), r.getP11()), maxDist))
    m_scaling = e1M;
  else if (isCloseToSegment(p, TSegment(r.getP11(), r.getP01()), maxDist))
    m_scaling = eM1;
  else if (isCloseToSegment(p, TSegment(r.getP01(), r.getP00()), maxDist))
    m_scaling = e0M;
  else
    m_scaling = eNoScale;
}
Esempio n. 10
0
		int leftScanlineIntersections(const TQuadratic &q, double t0, double t1,
									  bool &ascending)
		{
			const TPointD &p0 = q.getP0(), &p1 = q.getP1(), &p2 = q.getP2();

			double y1_y0 = y(p1) - y(p0),
				   accel = y(p2) - y(p1) - y1_y0;

			// Fallback to segment case whenever we have too flat quads
			if (std::fabs(accel) < m_tol)
				return leftScanlineIntersections(TSegment(q.getPoint(t0), q.getPoint(t1)), ascending);

			// Calculate new ascension
			int ascends = isAscending(q, t1, t0 < t1);
			bool wasAscending = ascending;

			ascending = (ascends > 0) ? true
									  : (ascends < 0) ? false
													  : (wasAscending = !ascending, ascending); // Couples with the cusps check below

			// In case the y coords are not in range, quit
			int solIdx[2];
			if (!areInYRange(q, t0, t1, solIdx))
				return 0;

			// Identify coordinates for which  q(t) == y
			double poly[3] = {y(p0) - m_y, 2.0 * y1_y0, accel},
				   s[2];

			int sCount = tcg::poly_ops::solve_2(poly, s); // Tolerance dealt at the first bailout above
			if (sCount == 2) {
				// Calculate result
				int result = 0;

				if (solIdx[0] >= 0) {
					result += int(getX(q, s[solIdx[0]]) < m_x && (getY(q, t0) != m_y || ascending == wasAscending)); // Cusp check
				}

				if (solIdx[1] >= 0)
					result += int(getX(q, s[solIdx[1]]) < m_x);

				return result;
			}

			return (assert(sCount == 0), 0); // Should never happen, since m_y is in range. If it ever happens,
											 // it must be close to the extremal - so quit with no intersections.
		}
Esempio n. 11
0
int CShuangpinSegmentor::_encode(const char* buf, char ch, bool isComplete)
{
    CMappedYin syls;
    syls.reserve(8);
    s_shpData.getMapString(buf, syls);
    if (syls.empty())
        return -1;

    const int len = m_pystr.size();
    CMappedYin::const_iterator iter = syls.begin();
    CMappedYin::const_iterator iter_end = syls.end();

    if (isComplete) {
        TSegment &s = m_segs.back();
        s.m_len = 2;
        s.m_start = len - s.m_len;
        s.m_syllables.clear();
        s.m_type = IPySegmentor::SYLLABLE; 
        for (; iter!=iter_end; iter++) {
            s.m_syllables.push_back(s_shpData.encodeSyllable(iter->c_str()));
        }
        m_nLastValidPos += 1;
        return s.m_start;
    } else {
        TSegment s;
        s.m_len = 1;
        s.m_start = len - s.m_len;
        m_nLastValidPos += 1;

        for (; iter != iter_end; ++iter) {
            TSyllable syl = s_shpData.encodeSyllable(iter->c_str());
            if ((int)syl != 0) {
                s.m_syllables.push_back(syl);
                m_segs.push_back (s);
            } else {
                m_segs.push_back (TSegment (ch, s.m_start, 1, IPySegmentor::STRING));
            }
        }
        return s.m_start;
    }
}
Esempio n. 12
0
int intersect(const TQuadratic &q, const TSegment &s,
              std::vector<DoublePair> &intersections, bool firstIsQuad) {
  int solutionNumber = 0;

  // Note the line `a*x+b*y+c = 0` we search for solutions
  //  di a*x(t)+b*y(t)+c=0 in [0,1]
  double a = s.getP0().y - s.getP1().y, b = s.getP1().x - s.getP0().x,
         c = -(a * s.getP0().x + b * s.getP0().y);

  // se il segmento e' un punto
  if (0.0 == a && 0.0 == b) {
    double outParForQuad = q.getT(s.getP0());

    if (areAlmostEqual(q.getPoint(outParForQuad), s.getP0())) {
      if (firstIsQuad)
        intersections.push_back(DoublePair(outParForQuad, 0));
      else
        intersections.push_back(DoublePair(0, outParForQuad));
      return 1;
    }
    return 0;
  }

  if (q.getP2() - q.getP1() ==
      q.getP1() - q.getP0()) {  // the second is a segment....
    if (firstIsQuad)
      return intersect(TSegment(q.getP0(), q.getP2()), s, intersections);
    else
      return intersect(s, TSegment(q.getP0(), q.getP2()), intersections);
  }

  std::vector<TPointD> bez, pol;
  bez.push_back(q.getP0());
  bez.push_back(q.getP1());
  bez.push_back(q.getP2());

  bezier2poly(bez, pol);

  std::vector<double> poly_1(3, 0), sol;

  poly_1[0] = a * pol[0].x + b * pol[0].y + c;
  poly_1[1] = a * pol[1].x + b * pol[1].y;
  poly_1[2] = a * pol[2].x + b * pol[2].y;

  if (!(rootFinding(poly_1, sol))) return 0;

  double segmentPar, solution;

  TPointD v10(s.getP1() - s.getP0());
  for (UINT i = 0; i < sol.size(); ++i) {
    solution = sol[i];
    if ((0.0 <= solution && solution <= 1.0) ||
        areAlmostEqual(solution, 0.0, 1e-6) ||
        areAlmostEqual(solution, 1.0, 1e-6)) {
      segmentPar = (q.getPoint(solution) - s.getP0()) * v10 / (v10 * v10);
      if ((0.0 <= segmentPar && segmentPar <= 1.0) ||
          areAlmostEqual(segmentPar, 0.0, 1e-6) ||
          areAlmostEqual(segmentPar, 1.0, 1e-6)) {
        TPointD p1 = q.getPoint(solution);
        TPointD p2 = s.getPoint(segmentPar);
        assert(areAlmostEqual(p1, p2, 1e-1));

        if (firstIsQuad)
          intersections.push_back(DoublePair(solution, segmentPar));
        else
          intersections.push_back(DoublePair(segmentPar, solution));
        solutionNumber++;
      }
    }
  }

  return solutionNumber;
}
Esempio n. 13
0
int intersectCloseControlPoints(const TQuadratic &c0, const TQuadratic &c1,
                                std::vector<DoublePair> &intersections) {
  int ret = -2;

  double dist1          = tdistance2(c0.getP0(), c0.getP1());
  if (dist1 == 0) dist1 = 1e-20;
  double dist2          = tdistance2(c0.getP1(), c0.getP2());
  if (dist2 == 0) dist2 = 1e-20;
  double val0           = std::max(dist1, dist2) / std::min(dist1, dist2);
  double dist3          = tdistance2(c1.getP0(), c1.getP1());
  if (dist3 == 0) dist3 = 1e-20;
  double dist4          = tdistance2(c1.getP1(), c1.getP2());
  if (dist4 == 0) dist4 = 1e-20;
  double val1           = std::max(dist3, dist4) / std::min(dist3, dist4);

  if (val0 > 1000000 &&
      val1 > 1000000)  // both c0 and c1 approximated by segments
  {
    TSegment s0 = TSegment(c0.getP0(), c0.getP2());
    TSegment s1 = TSegment(c1.getP0(), c1.getP2());
    ret         = intersect(s0, s1, intersections);
    for (UINT i = intersections.size() - ret; i < (int)intersections.size();
         i++) {
      intersections[i].first = (dist1 < dist2)
                                   ? sqrt(intersections[i].first)
                                   : 1 - sqrt(1 - intersections[i].first);
      intersections[i].second = (dist3 < dist4)
                                    ? sqrt(intersections[i].second)
                                    : 1 - sqrt(1 - intersections[i].second);
    }
    // return ret;
  } else if (val0 > 1000000)  // c0 only approximated segment
  {
    TSegment s0 = TSegment(c0.getP0(), c0.getP2());
    ret         = intersect(s0, c1, intersections);
    for (UINT i = intersections.size() - ret; i < (int)intersections.size();
         i++)
      intersections[i].first = (dist1 < dist2)
                                   ? sqrt(intersections[i].first)
                                   : 1 - sqrt(1 - intersections[i].first);
    // return ret;
  } else if (val1 > 1000000)  // only c1 approximated segment
  {
    TSegment s1 = TSegment(c1.getP0(), c1.getP2());
    ret         = intersect(c0, s1, intersections);
    for (UINT i = intersections.size() - ret; i < (int)intersections.size();
         i++)
      intersections[i].second = (dist3 < dist4)
                                    ? sqrt(intersections[i].second)
                                    : 1 - sqrt(1 - intersections[i].second);
    // return ret;
  }

  /*
if (ret!=-2)
{
std::vector<DoublePair> intersections1;
int ret1 = intersect(c0, c1, intersections1, false);
if (ret1>ret)
{
intersections = intersections1;
return ret1;
}
}
*/

  return ret;
}
Esempio n. 14
0
int intersect(const TQuadratic &c0, const TQuadratic &c1,
              std::vector<DoublePair> &intersections, bool checksegments) {
  int ret;

  // Works baddly, sometimes patch intersections...
  if (checksegments) {
    ret = intersectCloseControlPoints(c0, c1, intersections);
    if (ret != -2) return ret;
  }

  double a = c0.getP0().x - 2 * c0.getP1().x + c0.getP2().x;
  double b = 2 * (c0.getP1().x - c0.getP0().x);
  double d = c0.getP0().y - 2 * c0.getP1().y + c0.getP2().y;
  double e = 2 * (c0.getP1().y - c0.getP0().y);

  double coeff = b * d - a * e;
  int i        = 0;

  if (areAlmostEqual(coeff, 0.0))  // c0 is a Segment, or a single point!!!
  {
    TSegment s = TSegment(c0.getP0(), c0.getP2());
    ret        = intersect(s, c1, intersections);
    if (a == 0 && d == 0)  // values of t in s coincide with values of t in c0
      return ret;

    for (i = intersections.size() - ret; i < (int)intersections.size(); i++) {
      intersections[i].first = c0.getT(s.getPoint(intersections[i].first));
    }
    return ret;
  }

  double c = c0.getP0().x;
  double f = c0.getP0().y;

  double g = c1.getP0().x - 2 * c1.getP1().x + c1.getP2().x;
  double h = 2 * (c1.getP1().x - c1.getP0().x);
  double k = c1.getP0().x;

  double m = c1.getP0().y - 2 * c1.getP1().y + c1.getP2().y;
  double p = 2 * (c1.getP1().y - c1.getP0().y);
  double q = c1.getP0().y;

  if (areAlmostEqual(h * m - g * p,
                     0.0))  // c1 is a Segment, or a single point!!!
  {
    TSegment s = TSegment(c1.getP0(), c1.getP2());
    ret        = intersect(c0, s, intersections);
    if (g == 0 && m == 0)  // values of t in s coincide with values of t in c0
      return ret;

    for (i = intersections.size() - ret; i < (int)intersections.size(); i++) {
      intersections[i].second = c1.getT(s.getPoint(intersections[i].second));
    }
    return ret;
  }

  double a2 = (g * d - a * m);
  double b2 = (h * d - a * p);
  double c2 = ((k - c) * d + (f - q) * a);

  coeff = 1.0 / coeff;

  double A   = (a * a + d * d) * coeff * coeff;
  double aux = A * c2 + (a * b + d * e) * coeff;

  std::vector<double> t;
  std::vector<double> solutions;

  t.push_back(aux * c2 + a * c + d * f - k * a - d * q);
  aux += A * c2;
  t.push_back(aux * b2 - h * a - d * p);
  t.push_back(aux * a2 + A * b2 * b2 - g * a - d * m);
  t.push_back(2 * A * a2 * b2);
  t.push_back(A * a2 * a2);

  rootFinding(t, solutions);
  //  solutions.push_back(0.0); //per convenzione; un valore vale l'altro....

  for (i = 0; i < (int)solutions.size(); i++) {
    if (solutions[i] < 0) {
      if (areAlmostEqual(solutions[i], 0, 1e-6))
        solutions[i] = 0;
      else
        continue;
    } else if (solutions[i] > 1) {
      if (areAlmostEqual(solutions[i], 1, 1e-6))
        solutions[i] = 1;
      else
        continue;
    }

    DoublePair tt;
    tt.second = solutions[i];
    tt.first  = coeff * (tt.second * (a2 * tt.second + b2) + c2);
    if (tt.first < 0) {
      if (areAlmostEqual(tt.first, 0, 1e-6))
        tt.first = 0;
      else
        continue;
    } else if (tt.first > 1) {
      if (areAlmostEqual(tt.first, 1, 1e-6))
        tt.first = 1;
      else
        continue;
    }

    intersections.push_back(tt);

    assert(areAlmostEqual(c0.getPoint(tt.first), c1.getPoint(tt.second), 1e-1));
  }
  return intersections.size();
}
Esempio n. 15
0
int TRegion::Imp::leftScanlineIntersections(
	const TPointD &p,
	double(TPointD::*h), double(TPointD::*v)) const
{
	struct Locals {
		const Imp *m_this;
		double m_x, m_y,
			m_tol;
		double TPointD::*m_h,
			TPointD::*m_v;

		inline double x(const TPointD &p) const { return p.*m_h; }
		inline double y(const TPointD &p) const { return p.*m_v; }

		inline double get(const TQuadratic &q, double t, double(TPointD::*val)) const
		{
			double one_t = 1.0 - t;
			return one_t * (one_t * q.getP0().*val + t * q.getP1().*val) + t * (one_t * q.getP1().*val + t * q.getP2().*val);
		}

		inline double getX(const TQuadratic &q, double t) const { return get(q, t, m_h); }
		inline double getY(const TQuadratic &q, double t) const { return get(q, t, m_v); }

		void getEdgeData(int e, TEdge *&ed, TStroke *&s,
						 int &chunk0, const TThickQuadratic *&q0, double &t0,
						 int &chunk1, const TThickQuadratic *&q1, double &t1) const
		{
			ed = m_this->m_edge[e];
			s = ed->m_s;

			s->getChunkAndT(ed->m_w0, chunk0, t0);
			s->getChunkAndT(ed->m_w1, chunk1, t1);

			q0 = s->getChunk(chunk0);
			q1 = s->getChunk(chunk1);
		}

		bool isInYRange(double y0, double y1) const
		{
			return (y0 <= m_y && m_y < y1)	 // Assuming the first endpoint is vertical-including,
				   || (y1 < m_y && m_y <= y0); // while the latter is not. Vertical conditions are EXACT.
		}

		bool areInYRange(const TQuadratic &q, double t0, double t1,
						 int(&solIdx)[2]) const
		{
			assert(0.0 <= t0 && t0 <= 1.0), assert(0.0 <= t1 && t1 <= 1.0);

			const TPointD &p0 = q.getP0(), &p1 = q.getP1(), &p2 = q.getP2();

			double der[2] = {y(p1) - y(p0), y(p0) - y(p1) + y(p2) - y(p1)},
				   s;

			double y0 = getY(q, t0), y1 = getY(q, t1);

			if (tcg::poly_ops::solve_1(der, &s, m_tol)) {
				if (t0 <= s && s < t1) {
					double ys = getY(q, s);

					solIdx[0] = (ys < m_y && m_y <= y0 || y0 <= m_y && m_y < ys) ? 0 : -1;
					solIdx[1] = (ys < m_y && m_y < y1 || y1 < m_y && m_y < ys) ? 1 : -1;
				} else if (t1 < s && s <= t0) {
					double ys = getY(q, s);

					solIdx[0] = (ys < m_y && m_y <= y0 || y0 <= m_y && m_y < ys) ? 1 : -1;
					solIdx[1] = (ys < m_y && m_y < y1 || y1 < m_y && m_y < ys) ? 0 : -1;
				} else {
					solIdx[0] = isInYRange(y0, y1) ? (t0 < s) ? 0 : 1
												   : -1;
					solIdx[1] = -1;
				}
			} else
				solIdx[1] = solIdx[0] = -1;

			return (solIdx[0] >= 0 || solIdx[1] >= 0);
		}

		int leftScanlineIntersections(const TSegment &seg, bool &ascending)
		{
			const TPointD &p0 = seg.getP0(), &p1 = seg.getP1();
			bool wasAscending = ascending;

			ascending = (y(p1) > y(p0)) ? true
										: (y(p1) < y(p0)) ? false
														  : (wasAscending = !ascending, ascending); // Couples with the cusp check below

			if (!isInYRange(y(p0), y(p1)))
				return 0;

			if (m_y == y(p0))
				return int(x(p0) < m_x && ascending == wasAscending); // Cusps treated here

			double y1_y0 = y(p1) - y(p0), // (x, m_y) in (p0, p1) from here on
				poly[2] = {(m_y - y(p0)) * (x(p1) - x(p0)), -y1_y0},
				   sx_x0;

			return tcg::poly_ops::solve_1(poly, &sx_x0, m_tol) ? int(sx_x0 < m_x - x(p0))
															   : int(x(p0) < m_x && x(p1) < m_x); // Almost horizontal segments are
		}																						  // flattened along the axes

		int isAscending(const TThickQuadratic &q, double t, bool forward)
		{
			double y0 = y(q.getP0()), y1 = y(q.getP1()), y2 = y(q.getP2()),
				   y1_y0 = y1 - y0, y2_y1 = y2 - y1;

			double yspeed_2 = tcg::numeric_ops::lerp(y1_y0, y2_y1, t) * (2 * int(forward) - 1),
				   yaccel = y2_y1 - y1_y0;

			return (yspeed_2 > 0.0) ? 1
									: (yspeed_2 < 0.0) ? -1
													   : tcg::numeric_ops::sign(yaccel);
		}

		int leftScanlineIntersections(const TQuadratic &q, double t0, double t1,
									  bool &ascending)
		{
			const TPointD &p0 = q.getP0(), &p1 = q.getP1(), &p2 = q.getP2();

			double y1_y0 = y(p1) - y(p0),
				   accel = y(p2) - y(p1) - y1_y0;

			// Fallback to segment case whenever we have too flat quads
			if (std::fabs(accel) < m_tol)
				return leftScanlineIntersections(TSegment(q.getPoint(t0), q.getPoint(t1)), ascending);

			// Calculate new ascension
			int ascends = isAscending(q, t1, t0 < t1);
			bool wasAscending = ascending;

			ascending = (ascends > 0) ? true
									  : (ascends < 0) ? false
													  : (wasAscending = !ascending, ascending); // Couples with the cusps check below

			// In case the y coords are not in range, quit
			int solIdx[2];
			if (!areInYRange(q, t0, t1, solIdx))
				return 0;

			// Identify coordinates for which  q(t) == y
			double poly[3] = {y(p0) - m_y, 2.0 * y1_y0, accel},
				   s[2];

			int sCount = tcg::poly_ops::solve_2(poly, s); // Tolerance dealt at the first bailout above
			if (sCount == 2) {
				// Calculate result
				int result = 0;

				if (solIdx[0] >= 0) {
					result += int(getX(q, s[solIdx[0]]) < m_x && (getY(q, t0) != m_y || ascending == wasAscending)); // Cusp check
				}

				if (solIdx[1] >= 0)
					result += int(getX(q, s[solIdx[1]]) < m_x);

				return result;
			}

			return (assert(sCount == 0), 0); // Should never happen, since m_y is in range. If it ever happens,
											 // it must be close to the extremal - so quit with no intersections.
		}

	} locals = {this, p.*h, p.*v, 1e-4, h, v};

	TEdge *ed;
	TStroke *s;
	int chunk0, chunk1;
	const TThickQuadratic *q0, *q1;
	double t0, t1;

	UINT e, eCount = m_edge.size();

	int leftInters = 0;
	bool ascending = (locals.getEdgeData(eCount - 1, ed, s, chunk0, q0, t0, chunk1, q1, t1),
					  locals.isAscending(*q1, t1, (t0 < t1)));

	for (e = 0; e != eCount; ++e) {
		// Explore current edge
		{
			// Retrieve edge data
			locals.getEdgeData(e, ed, s, chunk0, q0, t0, chunk1, q1, t1);

			// Compare edge against scanline segment
			if (chunk0 != chunk1) {
				if (chunk0 < chunk1) {
					leftInters += locals.leftScanlineIntersections(*q0, t0, 1.0, ascending);

					for (int c = chunk0 + 1; c != chunk1; ++c)
						leftInters += locals.leftScanlineIntersections(*s->getChunk(c), 0.0, 1.0, ascending);

					leftInters += locals.leftScanlineIntersections(*q1, 0.0, t1, ascending);
				} else {
					leftInters += locals.leftScanlineIntersections(*q0, t0, 0.0, ascending);

					for (int c = chunk0 - 1; c != chunk1; --c)
						leftInters += locals.leftScanlineIntersections(*s->getChunk(c), 1.0, 0.0, ascending);

					leftInters += locals.leftScanlineIntersections(*q1, 1.0, t1, ascending);
				}
			} else
				leftInters += locals.leftScanlineIntersections(*q0, t0, t1, ascending);
		}

		// Explore autoclose segment at the end of current edge
		{
			int nextE = (e + 1) % int(m_edge.size());

			const TPointD &p0 = m_edge[e]->m_s->getPoint(m_edge[e]->m_w1),
						  &p1 = m_edge[nextE]->m_s->getPoint(m_edge[nextE]->m_w0);

			leftInters += locals.leftScanlineIntersections(TSegment(p0, p1), ascending);
		}
	}

	return leftInters;
}
Esempio n. 16
0
// TOTEST
unsigned CHunpinSegmentor::_push (unsigned ch)
{
	m_pystr.push_back (ch);
	
	TSegmentVec::iterator ite =  m_segs.size() > 0 ? m_segs.end() - 1 : m_segs.begin() - 1;
	const unsigned maxStringCount = 6;
	unsigned syllableCount = 0;
	unsigned stringCount = 0;
	for(; ite != m_segs.begin() - 1 ; ite --) {
		stringCount += (*ite).m_len;
		syllableCount ++;
		if (stringCount > maxStringCount) {
			syllableCount --;
			break;
		}
	}

	unsigned strlen = m_pystr.size();
	unsigned ret;

	for(int index = syllableCount ; index >= 0; index --) {

		TSegmentVec::iterator it = m_segs.end() - index;
		unsigned tmpl;
		unsigned v;
		if(index != 0) {
			
			if((strlen - (*it).m_start) == 2) {
				char buf[4];
				sprintf(buf, "%c%c", m_pystr[(*it).m_start], m_pystr[(*it).m_start+1]);
				int startFrom = _encode(buf);
				if(startFrom >= 0)  break;
			}
			
			v = m_pytrie.match_longest (m_pystr.rbegin(), m_pystr.rbegin() + strlen - (*it).m_start, tmpl);

			if(tmpl == (strlen - (*it).m_start)) {
				TSegmentVec new_segs(1, TSegment(v, (*it).m_start, tmpl));
				m_segs.erase (m_segs.end()-index, m_segs.end());
				std::copy (new_segs.rbegin(), new_segs.rend(), back_inserter (m_segs));

				break;
			}
		}
		else {
			v = m_pytrie.match_longest (m_pystr.rbegin(), m_pystr.rbegin() + 1, tmpl);
			if(tmpl == 0) {
				IPySegmentor::ESegmentType seg_type;
				if (ch == '\'' && m_inputBuf.size() > 1) {

					seg_type = IPySegmentor::SYLLABLE_SEP;
				}
				else if (islower (ch)) {

					seg_type = IPySegmentor::INVALID;
				}
				else {

					seg_type = IPySegmentor::STRING;
				}
				ret = m_pystr.size () - 1;
				m_segs.push_back (TSegment (ch, ret, 1, seg_type));

			}
			else {
				ret = m_pystr.size () - 1;
				m_segs.push_back (TSegment (v, ret, 1));				
			}
		}
	}	
	
	TSegment &last_seg = m_segs.back();
	if (m_pGetFuzzySyllablesOp && m_pGetFuzzySyllablesOp->isEnabled())
        if ( m_segs.back().m_type == SYLLABLE)
            _addFuzzySyllables (last_seg);
	
	return last_seg.m_start;

}