/* -*- C++ -*- * Copyright ©2004 Hugo Mills * * This software is distributed under the terms of the GNU GPL v3 * For more information on the GPL, see the file COPYING or * visit http://www.gnu.org/ * * This software is distributed without warranty */ #include "xfmap_cylorthographic.h" extern "C" PluginInfo* getmodules(int i) { if(i==0) { PluginInfo_Map* pi = new PluginInfo_Map(); pi->name = "Cylindrical Orthographic"; pi->author = "Hugo Mills"; pi->copyright = "©2005 Hugo Mills"; pi->version = 0x10000; pi->parser = XfMap_CylindricalOrthographic::parser; return pi; } else return NULL; } XfMap* XfMap_CylindricalOrthographic::parser( ConfigLexer* lex, const std::string& type, const std::string& subtype ) { if(type == "cylindrical" && subtype == "orthographic") { double parallel = 0.0; while(!lex->eos()) { if(!readkeyedvalue(lex, "standard-parallels", ¶llel)) throw(UnknownConfigToken(lex)); } return new XfMap_CylindricalOrthographic(degrad(parallel)); } else return NULL; } bool XfMap_CylindricalOrthographic::f(dvec2& result, const dvec3& pos) const { result[0] = atan2(pos[0], pos[2]) / M_PI; result[1] = pos[1] / scale / M_PI; return true; } bool XfMap_CylindricalOrthographic::g(dvec3& result, const dvec2& pos) const { result[1] = pos[1] * scale * M_PI; if(result[1] < -1 || result[1] > 1) return false; if(pos[0] < -1 || pos[0] > 1) return false; double m = sqrt(1-result[1]*result[1]); double a = pos[0] * M_PI; result[0] = m * sin(a); result[2] = m * cos(a); return true; } TraceState* XfMap_CylindricalOrthographic::initpath( TPCInsertIterator it, const dvec3& point) const { CylindricalOrthographic_TraceState* rv = new CylindricalOrthographic_TraceState(); f(rv->previous, point); *it = TracePoint(rv->previous); return rv; } // We define 0.0 <= lambda < 4.0, running anti-clockwise from // bottom-right. Integer values of lambda lie on the corners of the // rectangle. void XfMap_CylindricalOrthographic::pathpoint(TraceState* _state, TPCInsertIterator it, const dvec3& point) const { CylindricalOrthographic_TraceState* state = dynamic_cast(_state); double maxy = 1.0 / (scale * M_PI); dvec2 current; f(current, point); if(fabs(state->previous[0] - current[0]) > 1.75) { if(state->previous[0] < current[0]) { state->previous[0] += 2.0; double frac = (state->previous[0] - 1.0) / (state->previous[0] - current[0]); double y = (state->previous[1] - current[1]) * frac; double lambda = (y + maxy) / (2 * maxy); *it = TracePoint(-1.0, y, 3.0-lambda, false); *it = TracePoint(1.0, y, lambda, true); state->previous = current; } else { state->previous[0] -= 2.0; // FIXME: Similar code to the preceding state->previous = current; } } *it = current; } void XfMap_CylindricalOrthographic::tracepath( TPCInsertIterator it, double lambdafrom, double lambdato) const { double maxy = 1.0 / (scale * M_PI); while(int(lambdafrom) != int(lambdato)) { switch(int(lambdafrom)) { case 0: // Draw to top right *it = TracePoint(1.0, maxy); lambdafrom = 1.0; break; case 1: // Draw to top left *it = TracePoint(-1.0, maxy); lambdafrom = 2.0; break; case 2: // Draw to bottom left *it = TracePoint(-1.0, -maxy); lambdafrom = 3.0; break; case 3: // Draw to bottom right *it = TracePoint(1.0, -maxy); lambdafrom = 0.0; break; } } }