Пример #1
0
void AreaShader::shadeArea(Surface& s, const Area* ar) const
{
    WFMath::Polygon<2> clipped = ar->clipToSegment(s.m_segment);
    assert(clipped.isValid());
    
    if (clipped.numCorners() == 0) return;
 
    Point2 segOrigin = s.m_segment.getRect().lowCorner();
    clipped.shift(Point2(0,0) - segOrigin);
    scanConvert(clipped, s);
}
Пример #2
0
static void scanConvert(const WFMath::Polygon<2>& inPoly, Surface& sf)
{
    if (!inPoly.isValid()) return;
    
    std::list<Edge> pending;
    std::vector<Edge> active;

    Point2 lastPt = inPoly.getCorner(inPoly.numCorners() - 1);
    for (std::size_t p=0; p < inPoly.numCorners(); ++p) {
        Point2 curPt = inPoly.getCorner(p);
        
        // skip horizontal edges
        if (curPt.y() != lastPt.y())
            pending.emplace_back(lastPt, curPt);
        
        lastPt = curPt;
    }
    
    if (pending.empty()) return;
    
    // sort edges by starting (lowest) z value
    pending.sort();
    active.push_back(pending.front());
    pending.pop_front();
    
    // advance to the row of the first z value, and ensure z sits in the
    // middle of sample rows - we do this by offseting by 1/2 a row height
    // if you don't do this, you'll find alternating rows are over/under
    // sampled, producing a charming striped effect.
    WFMath::CoordType z = std::floor(active.front().start().y()) + ROW_HEIGHT * 0.5f;
    
    for (; !pending.empty() || !active.empty();  z += ROW_HEIGHT)
    {
        while (!pending.empty() && (pending.front().start().y() <= z)) {
            active.push_back(pending.front());
            pending.pop_front();
        }
        
        // sort by x value - note active will be close to sorted anyway
        std::sort(active.begin(), active.end(), EdgeAtZ(z));
        
        // delete finished edges
        for (unsigned int i=0; i< active.size(); ) {
            if (active[i].end().y() <= z)
                active.erase(active.begin() + i);
            else
                ++i;
        }
        
        // draw pairs of active edges
        for (unsigned int i=1; i < active.size(); i += 2)
            span(sf, z, active[i - 1].xValueAtZ(z), active[i].xValueAtZ(z));
    } // of active edges loop
}
Пример #3
0
WFMath::Polygon<2> sutherlandHodgmanKernel(const WFMath::Polygon<2>& inpoly, Clip clipper)
{
    WFMath::Polygon<2> outpoly;
    
    if (!inpoly.isValid()) return inpoly;
    std::size_t points = inpoly.numCorners();
    if (points < 3) return outpoly; // i.e an invalid result
    
    Point2 lastPt = inpoly.getCorner(points - 1);
    bool lastInside = clipper.inside(lastPt);
    
    for (std::size_t p = 0; p < points; ++p) {
    
        Point2 curPt = inpoly.getCorner(p);
        bool inside = clipper.inside(curPt);
        
        if (lastInside) {
            if (inside) {
                // emit curPt
                outpoly.addCorner(outpoly.numCorners(), curPt);
            } else {
                // emit intersection of edge with clip line
                outpoly.addCorner(outpoly.numCorners(), clipper.clip(lastPt, curPt));
            }
        } else {
            if (inside) {
                // emit both
                outpoly.addCorner(outpoly.numCorners(), clipper.clip(lastPt, curPt));
                outpoly.addCorner(outpoly.numCorners(), curPt);
            } else {
                // don't emit anything
            }
        } // last was outside
        
        lastPt = curPt;
        lastInside = inside;
    }
    
    return outpoly;
}
Пример #4
0
void Area::setShape(const WFMath::Polygon<2>& p)
{
    assert(p.isValid());
    m_shape = p;
    m_box = p.boundingBox();
}
Пример #5
0
int main(int argc, char* argv[])
{
    Mercator::Area* a1 = new Mercator::Area(1, false);
    
    WFMath::Polygon<2> p;
    p.addCorner(p.numCorners(), Point2(3, 4));
    p.addCorner(p.numCorners(), Point2(10, 10));
    p.addCorner(p.numCorners(), Point2(-1, 18));
    p.addCorner(p.numCorners(), Point2(-8, 11));
    
    a1->setShape(p);
    
    Mercator::Terrain terrain(Mercator::Terrain::SHADED, seg_size);

    Mercator::AreaShader* ashade = new Mercator::AreaShader(1);
    terrain.addShader(ashade, 0);
    
    terrain.setBasePoint(-2, -1, 5);
    terrain.setBasePoint(-2, 0, 2);
    terrain.setBasePoint(-2, 1, 19);
    
    terrain.setBasePoint(-1, -1, 4);
    terrain.setBasePoint(-1, 0, 6);
    terrain.setBasePoint(-1, 1, 10);
    
    terrain.setBasePoint(0, -1, 2);
    terrain.setBasePoint(0, 0, -1);
    terrain.setBasePoint(0, 1, 8);
    terrain.setBasePoint(0, 2, 11);
    
    terrain.setBasePoint(1, -1, 7);
    terrain.setBasePoint(1, 0, 2);
    terrain.setBasePoint(1, 1, 11);
    terrain.setBasePoint(1, 2, 9);
    
    terrain.setBasePoint(2, -1, 3);
    terrain.setBasePoint(2, 0, 8);
    terrain.setBasePoint(2, 1, 2);

    terrain.setBasePoint(3, -1, 6);
    terrain.setBasePoint(3, 0, 7);
    terrain.setBasePoint(3, 1, 9);
    
    terrain.addArea(a1);
    
    Mercator::Segment* seg = terrain.getSegment(0,0);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));
    
    seg = terrain.getSegment(1,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);
    assert(a1->checkIntersects(*seg) == false);

    WFMath::Polygon<2> clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());
    
    seg = terrain.getSegment(-1,0);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));
    
    clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());
    
    seg = terrain.getSegment(0,1);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));
    
    clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());

    seg = terrain.getSegment(2,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);
    assert(a1->checkIntersects(*seg) == false);

    p.clear();
    p.addCorner(p.numCorners(), Point2(3 + seg_size, 4));
    p.addCorner(p.numCorners(), Point2(10 + seg_size, 10));
    p.addCorner(p.numCorners(), Point2(-1 + seg_size, 18));
    p.addCorner(p.numCorners(), Point2(-8 + seg_size, 11));
    
    a1->setShape(p);

    terrain.updateArea(a1);

    seg = terrain.getSegment(0,0);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));
    
    seg = terrain.getSegment(1,0);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));

    clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());
    
    seg = terrain.getSegment(-1,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);
    assert(a1->checkIntersects(*seg) == false);
    
    seg = terrain.getSegment(0,1);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));
    
    clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());

    seg = terrain.getSegment(2,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);
    assert(a1->checkIntersects(*seg) == false);

    clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());

    terrain.removeArea(a1);

    seg = terrain.getSegment(0,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);

    seg = terrain.getSegment(1,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);

    seg = terrain.getSegment(-1,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);

    seg = terrain.getSegment(0,1);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);

    testAreaShader();

    testAddToSegment();
    
    return EXIT_SUCCESS;
}