void testAreaShader() { 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(14, 6)); p.addCorner(p.numCorners(), Point2(18, 4)); p.addCorner(p.numCorners(), Point2(17, 19)); p.addCorner(p.numCorners(), Point2(6, 20)); p.addCorner(p.numCorners(), Point2(-1, 18)); p.addCorner(p.numCorners(), Point2(-8, 11)); a1->setShape(p); Mercator::Terrain terrain(Mercator::Terrain::SHADED, 16); Mercator::AreaShader* ashade = new Mercator::AreaShader(1); terrain.addShader(ashade, 0); terrain.setBasePoint(0, 0, -1); terrain.setBasePoint(0, 1, 8); terrain.setBasePoint(1, 0, 2); terrain.setBasePoint(1, 1, 11); terrain.addArea(a1); Mercator::Segment* seg = terrain.getSegment(0,0); assert(a1->checkIntersects(*seg)); seg->populateSurfaces(); }
void testAreaShader() { 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(14, 6)); p.addCorner(p.numCorners(), Point2(18, 4)); p.addCorner(p.numCorners(), Point2(17, 19)); p.addCorner(p.numCorners(), Point2(6, 20)); p.addCorner(p.numCorners(), Point2(-1, 18)); p.addCorner(p.numCorners(), Point2(-8, 11)); a1->setShape(p); Mercator::Area* a2 = new Mercator::Area(1, false); WFMath::Polygon<2> p2; p2.addCorner(p2.numCorners(), Point2(25, 18)); p2.addCorner(p2.numCorners(), Point2(72, 22)); p2.addCorner(p2.numCorners(), Point2(60, 30)); p2.addCorner(p2.numCorners(), Point2(27, 28)); p2.addCorner(p2.numCorners(), Point2(25, 45)); p2.addCorner(p2.numCorners(), Point2(3, 41)); p2.addCorner(p2.numCorners(), Point2(-2, 20)); a2->setShape(p2); Mercator::Terrain terrain(Mercator::Terrain::SHADED, 16); Mercator::Shader * base_shader = new Mercator::FillShader(Mercator::Shader::Parameters()); terrain.addShader(base_shader, 0); Mercator::AreaShader* ashade = new Mercator::AreaShader(1); terrain.addShader(ashade, 1); terrain.setBasePoint(0, 0, -1); terrain.setBasePoint(0, 1, 8); terrain.setBasePoint(1, 0, 2); terrain.setBasePoint(1, 1, 11); terrain.setBasePoint(2, 0, 2); terrain.setBasePoint(2, 1, 11); terrain.addArea(a1); // terrain.addArea(a2); Mercator::Segment* seg = terrain.getSegment(0,0); assert(a1->checkIntersects(*seg)); seg->populateSurfaces(); writePGMForSurface("test1.pgm", seg->getSize(), seg->getSurfaces()[1]); seg = terrain.getSegment(1,0); seg->populateSurfaces(); writePGMForSurface("test2.pgm", seg->getSize(), seg->getSurfaces()[1]); }
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 }
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); }
void Polygon::loadFromShape(const WFMath::Polygon<2>& shape) { clear(); for (size_t i = 0; i < shape.numCorners(); ++i) { const WFMath::Point<2>& position = shape[i]; PolygonPoint* point = new PolygonPoint(*getBaseNode(), getPositionProvider(), 0.25, position); point->makeInteractive(mBulletWorld); mPoints.push_back(point); } mRenderer.update(); }
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; }
void testAddToSegment() { Mercator::Area* a1 = new Mercator::Area(1, false); WFMath::Polygon<2> p; p.addCorner(p.numCorners(), Point2(1, 1)); p.addCorner(p.numCorners(), Point2(6, 1)); p.addCorner(p.numCorners(), Point2(6, 6)); p.addCorner(p.numCorners(), Point2(1, 6)); a1->setShape(p); Mercator::Segment * seg1 = new Mercator::Segment(0,0,seg_size); int success = a1->addToSegment(*seg1); assert(success == 0); Mercator::Segment * seg2 = new Mercator::Segment(1 * seg_size,0,seg_size); success = a1->addToSegment(*seg2); assert(success != 0); }
int main() { Mercator::Terrain t; // Add a null test shader to the terrain Mercator::Shader * shader = new TestShader; t.addShader(shader, 0); // Create a test area with a shape which intersects // the Segment at 0,0 Mercator::Area* a1 = new Mercator::Area(0, false); WFMath::Polygon<2> p; p.addCorner(p.numCorners(), WFMath::Point<2>(3, 4)); p.addCorner(p.numCorners(), WFMath::Point<2>(10, 10)); p.addCorner(p.numCorners(), WFMath::Point<2>(14, 6)); p.addCorner(p.numCorners(), WFMath::Point<2>(18, 4)); p.addCorner(p.numCorners(), WFMath::Point<2>(17, 19)); p.addCorner(p.numCorners(), WFMath::Point<2>(6, 20)); p.addCorner(p.numCorners(), WFMath::Point<2>(-1, 18)); p.addCorner(p.numCorners(), WFMath::Point<2>(-8, 11)); a1->setShape(p); // Add enough base points to force the creation of the Segment at 0,0 t.setBasePoint(0, 0, -1); t.setBasePoint(0, 1, 8); t.setBasePoint(1, 0, 2); t.setBasePoint(1, 1, 11); // Get the Segment at 0,0 Mercator::Segment * seg = t.getSegmentAtIndex(0,0); assert(seg != 0); // Get the surfaces, and add one corresponding to the shader we added. // We need to do this as the functions that would normally make it happen // have been stubbed out. Mercator::Segment::Surfacestore & sss = seg->getSurfaces(); Mercator::Surface * sfce = new Mercator::Surface(*seg, *shader); // Force allocation of the surface buffer so we can check later that it // gets destroyed when the area is added to the terrain. sfce->allocate(); assert(sfce->isValid()); // Add the surface to the store for this segment sss[0] = sfce; // Add the area which should cause relevant surface date to be invalidated t.addArea(a1); // We assert this to ensure that the buffer has been de-allocated // by a call to Surface::invalidate caused by adding the Area. assert(!sfce->isValid()); // force the surface to re-allocate sfce->allocate(); assert(sfce->isValid()); // Modify the areas shape p.addCorner(p.numCorners(), WFMath::Point<2>(-9, 12)); a1->setShape(p); // and cause an area update t.updateArea(a1); // Check the surface has been invalidated again assert(!sfce->isValid()); // force the surface to re-allocate sfce->allocate(); assert(sfce->isValid()); t.removeArea(a1); // Check the surface has been invalidated again assert(!sfce->isValid()); }
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; }
int main() { // Test constructor { Mercator::Forest mf; } // Test constructor { Mercator::Forest mf(23); } // Test getArea() { Mercator::Forest mf; Mercator::Area * a = mf.getArea(); assert(a == 0); } // Test species() { Mercator::Forest mf; Mercator::Forest::PlantSpecies & mps = mf.species(); assert(mps.empty()); } { Mercator::Forest forest(4249162ul); Mercator::Forest::PlantSpecies & species = forest.species(); const Mercator::Forest::PlantStore & plants = forest.getPlants(); // Forest is not yet populated assert(plants.empty()); assert(species.empty()); forest.populate(); // Forest has zero area, so even when populated it is empty assert(plants.empty()); assert(species.empty()); Mercator::Area* ar = new Mercator::Area(1, false); WFMath::Polygon<2> p; p.addCorner(p.numCorners(), Point2(5, 8)); p.addCorner(p.numCorners(), Point2(40, -1)); p.addCorner(p.numCorners(), Point2(45, 16)); p.addCorner(p.numCorners(), Point2(30, 28)); p.addCorner(p.numCorners(), Point2(-2, 26)); p.addCorner(p.numCorners(), Point2(1, 5)); ar->setShape(p); forest.setArea(ar); forest.populate(); // Forest has no species, so even when populated it is empty assert(plants.empty()); assert(species.empty()); { Mercator::Species pine; pine.m_probability = 0.04; pine.m_deviation = 1.f; species.push_back(pine); } forest.populate(); // Forest should now contain some plants assert(!plants.empty()); dumpPlants(plants); int plant_count = countPlants(plants); { Mercator::Species oak; oak.m_probability = 0.02; oak.m_deviation = 1.f; species.push_back(oak); } forest.populate(); // Forest should now contain some plants assert(!plants.empty()); assert(countPlants(plants) > plant_count); dumpPlants(plants); std::cout << countPlants(plants) << "," << plant_count << std::endl << std::flush; } }