geostat/heat.cpp

117 wiersze
3.7 KiB
C++

#include "heat.h"
#include "cache.h"
#include <heatmap.h>
#include <colorschemes/Spectral.h>
#include <Magick++.h>
#include <set>
#include <vector>
#include <string>
#include <assert.h>
#include <filesystem>
std::filesystem::path MAPS_DIR = "maps";
Heat::Heat(const Map* m) : mp(m) {
assert(mp);
#ifdef graphicsmagick
Magick::InitializeMagick(nullptr);
#endif
}
void Heat::generate(const std::string& filename, const pCaches& points, int stamp_size, const std::string& theme) {
heatmap_t* hm = heatmap_new(mp->size_x, mp->size_y);
heatmap_stamp_t* stamp = heatmap_stamp_gen(stamp_size);
std::vector<unsigned char> image(mp->size_x * mp->size_y * 4);
for (auto el : points) {
if (mp->contains(Position(el->pos.lat, el->pos.lon))) {
heatmap_add_point_with_stamp(hm, mp->coordinate_x(Position(el->pos.lat, el->pos.lon)), mp->coordinate_y(Position(el->pos.lat, el->pos.lon)), stamp);
// std::cout << mp->coordinate_x(Position(el.pos.lon, el.pos.lat)) << '\t' << mp->coordinate_y(Position(el.pos.lon, el.pos.lat)) << '\n';
}
}
if (theme == "soft")
heatmap_render_to(hm, heatmap_cs_Spectral_soft, &image[0]);
else if (theme == "exp")
heatmap_render_to(hm, heatmap_cs_Spectral_mixed_exp, &image[0]);
else
throw 0;
heatmap_free(hm);
Magick::Image contour(MAPS_DIR / mp->map_file);
Magick::Image heatmap(mp->size_x, mp->size_y, "RGBA", Magick::CharPixel, &image[0]);
contour.type(Magick::TrueColorType);
contour.composite(heatmap, 0, 0, Magick::OverCompositeOp);
contour.write(filename);
// heatmap.write("geostat_heat.png");
}
void Heat::generate_path(const std::string& filename, const Date_Caches& sorted) {
Magick::Image contour(MAPS_DIR / mp->map_file);
contour.strokeColor("black");
contour.strokeWidth(2);
#ifdef graphicsmagick
std::list<Magick::Drawable> draw;
#else
std::vector<Magick::Drawable> draw;
#endif
const Cache* prev = sorted.begin()->second;
float h = 1. / 3;
float h_step = 2. / 3 / (sorted.size() - 1);
for (auto el = sorted.begin()++; el != sorted.end(); el++) {
draw.push_back(Magick::DrawableStrokeColor(Magick::ColorHSL(h, 1, 0.5)));
h += h_step;
draw.push_back(Magick::DrawableLine(mp->coordinate_x(Position(el->second->pos.lat, el->second->pos.lon)), mp->coordinate_y(Position(el->second->pos.lat, el->second->pos.lon)),
mp->coordinate_x(Position(prev->pos.lat, prev->pos.lon)), mp->coordinate_y(Position(prev->pos.lat, prev->pos.lon))));
prev = el->second;
}
contour.draw(draw);
contour.write(filename);
}
void Heat::generate_anim(const std::string& filename, const Date_Caches& sorted, int dot_size) {
std::vector<Magick::Image> frames;
frames.emplace_back(MAPS_DIR / mp->map_file);
Magick::Image canvas(Magick::Geometry(mp->size_x, mp->size_y), "transparent");
canvas.strokeWidth(1);
canvas.animationDelay(1);
canvas.animationIterations(1);
#ifdef graphicsmagick
canvas.gifDisposeMethod(1);
#else
canvas.gifDisposeMethod(MagickCore::NoneDispose);
canvas.backgroundColor("transparent");
#endif
const Cache* prev = nullptr;
for (auto el = sorted.begin()++; el != sorted.end(); el++) {
if (mp->contains(Position(el->second->pos.lat, el->second->pos.lon))) {
canvas.erase();
if (prev) {
canvas.strokeColor("black");
canvas.fillColor("black");
canvas.draw(Magick::DrawableEllipse(mp->coordinate_x(Position(prev->pos.lat, prev->pos.lon)), mp->coordinate_y(Position(prev->pos.lat, prev->pos.lon)), dot_size, dot_size, 0, 360));
}
prev = el->second;
canvas.strokeColor("red");
canvas.fillColor("red");
canvas.draw(Magick::DrawableEllipse(mp->coordinate_x(Position(prev->pos.lat, prev->pos.lon)), mp->coordinate_y(Position(prev->pos.lat, prev->pos.lon)), dot_size, dot_size, 0, 360));
frames.push_back(canvas);
}
}
Magick::writeImages(frames.begin(), frames.end(), filename);
}