void TRegion::Imp::computeScanlineIntersections(double y, vector<double> &intersections) const { TRectD bbox = getBBox(); if (y <= bbox.y0 || y >= bbox.y1) return; assert(intersections.empty()); UINT i, firstSide = 0; vector<int> sides; for (i = 0; i < m_edge.size(); i++) { TEdge *e = m_edge[i]; TStroke *s = e->m_s; if (s->getBBox().y0 > y || s->getBBox().y1 < y) continue; int chunkIndex0, chunkIndex1; double t0, t1; s->getChunkAndT(e->m_w0, chunkIndex0, t0); s->getChunkAndT(e->m_w1, chunkIndex1, t1); if (chunkIndex0 > chunkIndex1) { findIntersections(y, *s->getChunk(chunkIndex0), t0, 0, intersections, sides); for (int j = chunkIndex0 - 1; j > chunkIndex1; j--) findIntersections(y, *s->getChunk(j), 1, 0, intersections, sides); findIntersections(y, *s->getChunk(chunkIndex1), 1, t1, intersections, sides); } else if (chunkIndex0 < chunkIndex1) { findIntersections(y, *s->getChunk(chunkIndex0), t0, 1, intersections, sides); for (int j = chunkIndex0 + 1; j < chunkIndex1; j++) findIntersections(y, *s->getChunk(j), 0, 1, intersections, sides); findIntersections(y, *s->getChunk(chunkIndex1), 0, t1, intersections, sides); } else { findIntersections(y, *s->getChunk(chunkIndex0), t0, t1, intersections, sides); } } if (intersections.size() > 0 && intersections.front() == intersections.back()) { intersections.pop_back(); if (!sides.empty() && sides.front() == sides.back() && intersections.size() > 0) intersections.erase(intersections.begin()); } std::sort(intersections.begin(), intersections.end()); assert(intersections.size() % 2 == 0); }
bool TRegion::Imp::contains(const TStroke &s, bool mayIntersect) const { if (!getBBox().contains(s.getBBox())) return false; if (mayIntersect && thereAreintersections(s)) return false; return contains(s.getThickPoint(0.5)); }
//----------------------------------------------------------------------------- bool TRegion::Imp::contains(const TPointD &p) const { bool leftAreOdd = false; if (!getBBox().contains(p)) return false; //printContains(p); UINT i; int side = 0; for (i = 0; i < m_edge.size() * 2; i++) //i pari, esplora gli edge, //i dispari esplora i segmenti di autoclose tra un edge e il successivo { if (i & 0x1) { TPointD p0 = m_edge[i / 2]->m_s->getPoint(m_edge[i / 2]->m_w1); TPointD p1; if (i / 2 < m_edge.size() - 1) p1 = m_edge[i / 2 + 1]->m_s->getPoint(m_edge[i / 2 + 1]->m_w0); else p1 = m_edge[0]->m_s->getPoint(m_edge[0]->m_w0); if (tmin(p0.y, p1.y) > p.y || tmax(p0.y, p1.y) < p.y) continue; if (!areAlmostEqual(p0, p1, 1e-2)) side = findSides(p, TQuadratic(p0, 0.5 * (p0 + p1), p1), 0.0, 1.0, leftAreOdd, side); continue; } TEdge *e = m_edge[i / 2]; TStroke *s = e->m_s; if (s->getBBox().y0 > p.y || s->getBBox().y1 < p.y) continue; double t0, t1; int chunkIndex0, chunkIndex1; const TThickQuadratic *q0, *q1; s->getChunkAndT(e->m_w0, chunkIndex0, t0); s->getChunkAndT(e->m_w1, chunkIndex1, t1); q0 = s->getChunk(chunkIndex0); q1 = s->getChunk(chunkIndex1); if (i == 0 && areAlmostEqual(q0->getPoint(t0).y, p.y)) { double tEnd; int chunkIndexEnd; TEdge *edgeEnd = m_edge.back(); edgeEnd->m_s->getChunkAndT(edgeEnd->m_w1, chunkIndexEnd, tEnd); assert(areAlmostEqual(edgeEnd->m_s->getChunk(chunkIndexEnd)->getPoint(tEnd).y, p.y)); side = edgeEnd->m_s->getChunk(chunkIndexEnd)->getSpeed(tEnd).y > 0 ? 1 : -1; } if (chunkIndex0 != chunkIndex1) { /*if (chunkIndex0>chunkIndex1) { tswap(chunkIndex0, chunkIndex1); tswap(t0, t1); }*/ if (chunkIndex0 > chunkIndex1) { side = findSides(p, *q0, t0, 0, leftAreOdd, side); for (int j = chunkIndex0 - 1; j > chunkIndex1; j--) side = findSides(p, *s->getChunk(j), 1, 0, leftAreOdd, side); side = findSides(p, *q1, 1, t1, leftAreOdd, side); } else { side = findSides(p, *q0, t0, 1, leftAreOdd, side); for (int j = chunkIndex0 + 1; j < chunkIndex1; j++) side = findSides(p, *s->getChunk(j), 0, 1, leftAreOdd, side); side = findSides(p, *q1, 0, t1, leftAreOdd, side); } } else side = findSides(p, *q0, t0, t1, leftAreOdd, side); if (i & 0x1) delete q0; } return leftAreOdd; }