diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..7d31ff441 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +Artem Pavlenko + + diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..d60c31a97 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/INSTALL b/INSTALL new file mode 100644 index 000000000..bfba4b822 --- /dev/null +++ b/INSTALL @@ -0,0 +1,4 @@ +Installation Instructions +************************* + +TODO! diff --git a/README b/README new file mode 100644 index 000000000..e69de29bb diff --git a/SConstruct b/SConstruct new file mode 100644 index 000000000..70822cc44 --- /dev/null +++ b/SConstruct @@ -0,0 +1,81 @@ +#mapnik SConctruct + +import os + +#edit 'settings.py' to match your system settings +opts = Options('settings.py') + +opts.Add('PREFIX', 'Set the install "prefix"', '/opt/mapnik') +opts.Add(PathOption('BOOST_ROOT','boost source root directory','/opt/boost')) +opts.Add(PathOption('AGG_ROOT','agg source root directory','/opt/agg23')) +opts.Add(PathOption('FREETYPE2_ROOT','freetype2 root directory','/opt/freetype2')) +opts.Add(PathOption('PYTHON_ROOT','python root directory','/opt/python')) +opts.Add('PYTHON_VERSION','python version','2.4') +opts.Add(ListOption('DATASOURCES','list of available datasources','postgis',['postgis'])) +opts.Add('POSTGRESQL_ROOT','path to postgresql prefix','/usr/local') + +platform = ARGUMENTS.get("OS",Platform()) + +build_dir = 'build' +build_prefix = build_dir+'/'+str(platform) + +cxx = 'g++' + +env = Environment(CXX=cxx,ENV=os.environ, options=opts) + +cxx_debug='-Wall -ftemplate-depth-100 -O0 -fno-inline -g -pthread' +cxx_release='-Wall -ftemplate-depth-100 -O2 -finline-functions -Wno-inline -pthread -DNDEBUG' + +release_env = env.Copy(CXXFLAGS = cxx_release) +debug_env = env.Copy(CXXFLAGS = cxx_debug) + +if ARGUMENTS.get('debug',0): + env.Append(CXXFLAGS = cxx_debug) + build_prefix+='/debug' +else: + env.Append(CXXFLAGS = cxx_release) + build_prefix+='/release' + +Help(opts.GenerateHelpText(env)) + +conf = Configure(env) + +if not conf.CheckLibWithHeader('ltdl','ltdl.h','C'): + print 'Could not find libltdl/headers , exiting!' + Exit(1) + +if not conf.CheckLib('z'): + print 'Could not find libz , exiting!' + Exit(1) + +if not conf.CheckLibWithHeader('png','png.h','C'): + print 'Could not find libpng/headers, exiting!' + Exit(1) + +if not conf.CheckLib('jpeg'): + print 'Could not find jpeg lib, exiting!' + Exit(1) + +env = conf.Finish() + +Export('env') + +#build boost libs (filesystem, regex, python) +env.SConscript('boost/SConscript') + +#build agg lib +env.SConscript('agg/SConscript') + +#main lib +SConscript('src/SConscript') + +#python ext +SConscript('python/SConscript') + +#datasources +for datasource in Split(env['DATASOURCES']): + env.BuildDir('build/datasources/'+datasource,'src/datasources/'+datasource,duplicate=0) + SConscript('datasources/'+datasource+'/SConscript') + + + diff --git a/agg/SConscript b/agg/SConscript new file mode 100644 index 000000000..3e87edc07 --- /dev/null +++ b/agg/SConscript @@ -0,0 +1,10 @@ +# +import glob + +Import('env') +prefix = env['PREFIX'] +agg_root = env['AGG_ROOT'] +agg_headers = agg_root + '/include' +agg_src_dir = agg_root + '/src/' +agg_src = glob.glob(agg_src_dir + '*.cpp') +agg_lib = env.StaticLibrary('libagg',agg_src,CPPPATH=agg_headers) diff --git a/boost/SConscript b/boost/SConscript new file mode 100644 index 000000000..1aab25682 --- /dev/null +++ b/boost/SConscript @@ -0,0 +1,21 @@ +## +import glob + +Import('env') + +prefix = env['PREFIX'] +boost_root = env['BOOST_ROOT'] + +# boost filesystem +filesystem_src_dir = boost_root + '/libs/filesystem/src/' +boost_fs_src= glob.glob(filesystem_src_dir + '*.cpp') +lib_boost_filesystem = env.SharedLibrary('libboost-filesystem',boost_fs_src,CPPPATH=boost_root) +env.Install(prefix+'/lib',lib_boost_filesystem) +#boost regex +regex_src_dir = boost_root + '/libs/regex/src/' +boost_regex_src = glob.glob(regex_src_dir+ '*.cpp') +lib_boost_regex = env.SharedLibrary('libboost-regex',boost_regex_src,CPPPATH=boost_root) + +env.Install(prefix+'/lib',lib_boost_regex) + + diff --git a/datasources/postgis/Jamfile b/datasources/postgis/Jamfile new file mode 100644 index 000000000..8f610e410 --- /dev/null +++ b/datasources/postgis/Jamfile @@ -0,0 +1,18 @@ +#postgis datasource plugin + +project + : usage-requirements + /opt/postgresql8/include + ; +lib pq + : + : /opt/postgresql8/lib/libpq.so + ; + +lib postgis + : + postgis.cc + postgisfs.cc + pq + ; + diff --git a/datasources/postgis/SConscript b/datasources/postgis/SConscript new file mode 100644 index 000000000..3e5daad6d --- /dev/null +++ b/datasources/postgis/SConscript @@ -0,0 +1,24 @@ +#mapnik + +Import ('env') + +prefix = env['PREFIX'] +boost_root = env['BOOST_ROOT'] +postgresql_root = env['POSTGRESQL_ROOT'] +agg_root = env['AGG_ROOT'] +agg_headers = agg_root + '/include' + +postgresql_headers=postgresql_root+"/include" +postgresql_libs=postgresql_root+"/lib" + +postgis_src = Split( + """ + postgis.cpp + postgisfs.cpp + """ + ) + +headers = ['#include',boost_root,agg_headers,postgresql_headers] +postgis_datasource = env.SharedLibrary('postgis',source=postgis_src,SHLIBPREFIX='',CPPPATH=headers,LIBS="pq",LIBPATH=postgresql_libs) +env.Install(prefix + '/datasources',postgis_datasource) +env.Alias("install",prefix + '/datasources') diff --git a/datasources/postgis/connection.hpp b/datasources/postgis/connection.hpp new file mode 100644 index 000000000..4e65f087b --- /dev/null +++ b/datasources/postgis/connection.hpp @@ -0,0 +1,85 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: connection.hpp 17 2005-03-08 23:58:43Z pavlenko $ + +#ifndef CONNECTION_HPP +#define CONNECTION_HPP + + +#include "libpq-fe.h" +#include "mapnik.hpp" +#include "resultset.hpp" + +using namespace mapnik; + +class ResultSet; + +class Connection +{ +private: + PGconn *conn_; +public: + Connection(const std::string& uri,const std::string& dbname, + const std::string& username,const std::string& password) + { + std::string connStr="host="+uri+" dbname="+dbname+" user="+username+" password="+password; + conn_=PQconnectdb(connStr.c_str()); + if (PQstatus(conn_) == CONNECTION_BAD) + { + std::cerr << "connection to "<< connStr << " failed\n" + << PQerrorMessage(conn_)<< std::endl; + } + else + { + std::cout <<"connected ok "< executeQuery(const std::string& sql,int type=0) const + { + PGresult *result=0; + if (type==1) + { + result=PQexecParams(conn_,sql.c_str(),0,0,0,0,0,1); + return ref_ptr(new ResultSet(result)); + } + result=PQexec(conn_,sql.c_str()); + return ref_ptr(new ResultSet(result)); + } + bool isOK() const + { + return (PQstatus(conn_)!=CONNECTION_BAD); + } + void close() + { + PQfinish(conn_); + } + ~Connection() + { + PQfinish(conn_); + } +}; + +#endif //CONNECTION_HPP diff --git a/datasources/postgis/connection_manager.hpp b/datasources/postgis/connection_manager.hpp new file mode 100644 index 000000000..1ed8f3567 --- /dev/null +++ b/datasources/postgis/connection_manager.hpp @@ -0,0 +1,111 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: connection_manager.hpp 17 2005-03-08 23:58:43Z pavlenko $ + +#ifndef CONNECTION_MANAGER_HPP +#define CONNECTION_MANAGER_HPP + +#include +#include "pool.hpp" +#include "utils.hpp" +#include "connection.hpp" + +using namespace mapnik; +using std::string; + +template +class ConnectionCreator +{ + string url_; + string dbname_; + string user_; + string pass_; +public: + ConnectionCreator(const string& url,const string& dbname, + const string& user,const string& pass) + : url_(url), + dbname_(dbname), + user_(user), + pass_(pass) {} + + T* operator()() const + { + return new T(url_,dbname_,user_,pass_); + } + std::string id() const + { + return url_+":"+dbname_+":"+user_+":"+pass_; + } +}; + +class ConnectionManager : public singleton +{ + + friend class CreateStatic; + typedef Pool PoolType; + typedef std::map > ContType; + typedef ref_ptr HolderType; + ContType pools_; + +public: + + bool registerPool(const ConnectionCreator& creator,int initialSize,int maxSize) + { + Lock lock(&mutex_); + if (pools_.find(creator.id())==pools_.end()) + { + return pools_.insert(std::make_pair(creator.id(), + ref_ptr(new PoolType(creator,initialSize,maxSize)))).second; + } + + return false; + + } + const ref_ptr& getPool(const std::string& key) + { + Lock lock(&mutex_); + ContType::const_iterator itr=pools_.find(key); + if (itr!=pools_.end()) + { + return itr->second; + } + static const ref_ptr emptyPool(0); + return emptyPool; + } + + const HolderType& get(const std::string& key) + { + Lock lock(&mutex_); + ContType::const_iterator itr=pools_.find(key); + if (itr!=pools_.end()) + { + ref_ptr pool=itr->second; + return pool->borrowObject(); + } + static const HolderType EmptyConn(0); + return EmptyConn; + } + +private: + ConnectionManager() {} + ConnectionManager(const ConnectionManager&); + ConnectionManager& operator=(const ConnectionManager); +}; + +#endif //CONNECTION_MANAGER_HPP diff --git a/datasources/postgis/postgis.cpp b/datasources/postgis/postgis.cpp new file mode 100644 index 000000000..c9b7785f6 --- /dev/null +++ b/datasources/postgis/postgis.cpp @@ -0,0 +1,214 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: postgis.cc 44 2005-04-22 18:53:54Z pavlenko $ + +#include "postgis.hpp" +#include +#include +#include +#include +#include +#include "connection_manager.hpp" + +DATASOURCE_PLUGIN(PostgisDatasource); + +const std::string PostgisDatasource::GEOMETRY_COLUMNS="geometry_columns"; +const std::string PostgisDatasource::SPATIAL_REF_SYS="spatial_ref_system"; + +using std::cerr; +using std::cout; +using std::endl; + +using boost::lexical_cast; +using boost::bad_lexical_cast; + +PostgisDatasource::PostgisDatasource(const Parameters& params) + : table_(params.get("table")), + type_(datasource::Vector), + desc_(params.get("name")), + creator_(params.get("host"), + params.get("dbname"), + params.get("user"), + params.get("password")) + +{ + ConnectionManager *mgr=ConnectionManager::instance(); + mgr->registerPool(creator_,10,20); + + ref_ptr > pool=mgr->getPool(creator_.id()); + if (pool) + { + const ref_ptr& conn = pool->borrowObject(); + if (conn && conn->isOK()) + { + PoolGuard,ref_ptr > > guard(conn,pool); + + std::string table_name=table_from_sql(table_); + + std::ostringstream s; + s << "select f_geometry_column,srid,type from "; + s << GEOMETRY_COLUMNS <<" where f_table_name='"< rs=conn->executeQuery(s.str()); + + if (rs->next()) + { + try + { + srid_ = lexical_cast(rs->getValue("srid")); + desc_.set_srid(srid_); + } + catch (bad_lexical_cast &ex) + { + cerr << ex.what() << endl; + } + geometryColumn_=rs->getValue("f_geometry_column"); + std::string postgisType=rs->getValue("type"); + } + rs->close(); + s.str(""); + s << "select xmin(ext),ymin(ext),xmax(ext),ymax(ext)"; + s << " from (select estimated_extent('"<executeQuery(s.str()); + if (rs->next()) + { + try + { + double lox=lexical_cast(rs->getValue(0)); + double loy=lexical_cast(rs->getValue(1)); + double hix=lexical_cast(rs->getValue(2)); + double hiy=lexical_cast(rs->getValue(3)); + extent_.init(lox,loy,hix,hiy); + } + catch (bad_lexical_cast &ex) + { + cerr << ex.what() << endl; + } + } + rs->close(); + + // collect attribute desc + s.str(""); + s << "select * from "<executeQuery(s.str()); + if (rs->next()) + { + int count = rs->getNumFields(); + for (int i=0;igetFieldName(i); + int length = rs->getFieldLength(i); + + int type_oid = rs->getTypeOID(i); + switch (type_oid) + { + case 17285: // geometry + desc_.add_descriptor(attribute_descriptor(fld_name,Geometry)); + break; + case 21: // int2 + case 23: // int4 + desc_.add_descriptor(attribute_descriptor(fld_name,Integer,false,length)); + break; + case 1043: // varchar + desc_.add_descriptor(attribute_descriptor(fld_name,String)); + break; + default: // shouldn't get here + cout << "unknown type_oid="< const& box=q.get_bbox(); + ConnectionManager *mgr=ConnectionManager::instance(); + ref_ptr > pool=mgr->getPool(creator_.id()); + if (pool) + { + const ref_ptr& conn = pool->borrowObject(); + if (conn && conn->isOK()) + { + PoolGuard,ref_ptr > > guard(conn,pool); + std::ostringstream s; + // can we rely on 'gid' name??? + s << "select gid,asbinary("< const& props=q.property_names(); + std::set::const_iterator pos=props.begin(); + while (pos!=props.end()) + { + s <<",\""<<*pos<<"\""; + ++pos; + } + + s << " from " << table_<<" where "< rs=conn->executeQuery(s.str(),1); + fs=new PostgisFeatureset(rs,props.size()); + } + } + return featureset_ptr(fs); +} + +const Envelope& PostgisDatasource::envelope() const +{ + return extent_; +} + +PostgisDatasource::~PostgisDatasource() {} diff --git a/datasources/postgis/postgis.hpp b/datasources/postgis/postgis.hpp new file mode 100644 index 000000000..e7524abe9 --- /dev/null +++ b/datasources/postgis/postgis.hpp @@ -0,0 +1,79 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: postgis.hpp 44 2005-04-22 18:53:54Z pavlenko $ + +#ifndef POSTGIS_HPP +#define POSTGIS_HPP + + +#include "mapnik.hpp" +#include "connection_manager.hpp" +#include + +#include + +using namespace mapnik; + +class PostgisDatasource : public datasource +{ + static const std::string GEOMETRY_COLUMNS; + static const std::string SPATIAL_REF_SYS; + const std::string uri_; + const std::string username_; + const std::string password_; + const std::string table_; + std::string geometryColumn_; + int type_; + int srid_; + mapnik::Envelope extent_; + layer_descriptor desc_; + ConnectionCreator creator_; + static std::string name_; +public: + static std::string name(); + int type() const; + featureset_ptr features(const query& q) const; + mapnik::Envelope const& envelope() const; + layer_descriptor const& get_descriptor() const; + PostgisDatasource(const Parameters ¶ms); + ~PostgisDatasource(); +private: + static std::string table_from_sql(const std::string& sql); + PostgisDatasource(const PostgisDatasource&); + PostgisDatasource& operator=(const PostgisDatasource&); +}; + +class PostgisFeatureset : public Featureset +{ +private: + ref_ptr rs_; + unsigned num_attrs_; + mutable int totalGeomSize_; + mutable int count_; +public: + PostgisFeatureset(const ref_ptr& rs,unsigned num_attrs); + void dispose(); + Feature* next(); + ~PostgisFeatureset(); +private: + PostgisFeatureset(const PostgisFeatureset&); + const PostgisFeatureset& operator=(const PostgisFeatureset&); +}; + +#endif //POSTGIS_HPP diff --git a/datasources/postgis/postgisfs.cpp b/datasources/postgis/postgisfs.cpp new file mode 100644 index 000000000..d10e7f785 --- /dev/null +++ b/datasources/postgis/postgisfs.cpp @@ -0,0 +1,92 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: postgisfs.cc 34 2005-04-04 13:27:23Z pavlenko $ + + +#include "postgis.hpp" + +using boost::lexical_cast; +using boost::bad_lexical_cast; +using std::string; + +PostgisFeatureset::PostgisFeatureset(const ref_ptr& rs, + unsigned num_attrs=0) + : rs_(rs), + num_attrs_(num_attrs), + totalGeomSize_(0), + count_(0) +{ + +} + + +Feature* PostgisFeatureset::next() +{ + Feature *feature=0; + if (rs_->next()) + { + const char* buf = rs_->getValue(0); + int id = (buf[0]&255) << 24 | (buf[1]&255) << 16 | (buf[2] & 255) << 8 | buf[3] & 255; + + int size=rs_->getFieldLength(1); + const char *data=rs_->getValue(1); + geometry_ptr geom=geometry_utils::from_wkb(data,size,-1); + totalGeomSize_+=size; + + if (geom) + { + feature=new Feature(id,geom); + + unsigned start=2; + for (unsigned pos=0;posgetValue(start + pos); + int field_size = rs_->getFieldLength(start + pos); + int oid = rs_->getTypeOID(start + pos); + if (oid==23) + { + int val = (buf[0]&255) << 24 | (buf[1]&255) << 16 | (buf[2] & 255) << 8 | buf[3] & 255; + feature->add_property(val); + } + else if (oid==1043) + { + feature->add_property(string(buf)); + } + else + { + feature->add_property(string("null")); + } + } + ++count_; + } + } + else + { + rs_->close(); + std::cout << "totalGeomSize="< + +namespace mapnik +{ + template + class property_validator : public filter_visitor + { + public: + property_validator(layer_descriptor& desc) + desc_(desc) {} + + void visit(filter& /*filter*/) + { + //not interested + } + void visit(expression& exp) + { + property* pf; + if ((pf = dynamic_cast*>(&exp))) + { + vector const& attr_desc = desc_.get_descriptors(); + for (size_t idx=0; idx < attr_desc.size();++idx) + { + if (attr_desc[idx] == pf->name()) + { + pf->set_index(idx); + break; + } + } + } + } + std::set const& property_names() const + { + return names_; + } + + virtual ~property_validator() {} + private: + property_validator(property_validator const&); + property_validator& operator=(property_validator const&); + private: + layer_descriptor& desc_; + }; +} + +#endif //PROPERTY_HPP diff --git a/datasources/postgis/resultset.hpp b/datasources/postgis/resultset.hpp new file mode 100644 index 000000000..9627ae1e7 --- /dev/null +++ b/datasources/postgis/resultset.hpp @@ -0,0 +1,138 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: resultset.hpp 17 2005-03-08 23:58:43Z pavlenko $ + + +#ifndef RESULTSET_HPP +#define RESULTSET_HPP + +#include "connection.hpp" + +class ResultSet +{ +private: + PGresult* res_; + int pos_; + int numTuples_; + int *refCount_; +public: + ResultSet(PGresult *res) + :res_(res),pos_(-1),refCount_(new int(1)) + { + numTuples_=PQntuples(res_); + } + + ResultSet(const ResultSet& rhs) + :res_(rhs.res_), + pos_(rhs.pos_), + numTuples_(rhs.numTuples_), + refCount_(rhs.refCount_) + { + (*refCount_)++; + } + + ResultSet& operator=(const ResultSet& rhs) + { + if (this==&rhs) return *this; + if (--(refCount_)==0) + { + close(); + delete refCount_,refCount_=0; + } + res_=rhs.res_; + pos_=rhs.pos_; + numTuples_=rhs.numTuples_; + refCount_=rhs.refCount_; + (*refCount_)++; + return *this; + } + + void close() + { + PQclear(res_),res_=0; + } + + ~ResultSet() + { + if (--(*refCount_)==0) + { + PQclear(res_); + delete refCount_,refCount_=0; + } + } + + int getNumFields() const + { + return PQnfields(res_); + } + + bool next() + { + return (++pos_=0) + return PQgetlength(res_,pos_,col); + return 0; + } + + int getTypeOID(int index) const + { + return PQftype(res_,index); + } + + int getTypeOID(const char* name) const + { + int col=PQfnumber(res_,name); + if (col>=0) + return PQftype(res_,col); + return 0; + } + + const char* getValue(int index) const + { + return PQgetvalue(res_,pos_,index); + } + + const char* getValue(const char* name) const + { + int col=PQfnumber(res_,name); + if (col>=0) + return getValue(col); + return 0; + } +}; + +#endif //RESULTSET_HPP + + + diff --git a/datasources/raster/raster_datasource.cpp b/datasources/raster/raster_datasource.cpp new file mode 100644 index 000000000..4c5c36cd4 --- /dev/null +++ b/datasources/raster/raster_datasource.cpp @@ -0,0 +1,91 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: raster_datasource.cc 44 2005-04-22 18:53:54Z pavlenko $ + +#include "raster_datasource.hh" +#include "image_reader.hh" +#include "raster_featureset.hh" +#include "raster_info.hh" + +DATASOURCE_PLUGIN(raster_datasource); + +raster_datasource::raster_datasource(const Parameters& params) + : extent_() +{ + filename_=params.get("file"); + format_=params.get("format"); + + double lox,loy,hix,hiy; + fromString(params.get("lox"),lox); + fromString(params.get("loy"),loy); + fromString(params.get("hix"),hix); + fromString(params.get("hiy"),hiy); + + extent_=Envelope(lox,loy,hix,hiy); +} + + +raster_datasource::~raster_datasource() +{ +} + +std::string raster_datasource::name_="raster"; + +int raster_datasource::type() const +{ + return datasource::Raster; +} + + +std::string raster_datasource::name() +{ + return name_; +} + +bool raster_datasource::parseEnvelope(const std::string& str,Envelope& envelope) +{ + return true; +} + +const mapnik::Envelope& raster_datasource::envelope() const +{ + return extent_; +} + + +featureset_ptr raster_datasource::featuresAll(const CoordTransform& t) const +{ + return featureset_ptr(0); +} + + +featureset_ptr raster_datasource::featuresInBox(const CoordTransform& t, + const mapnik::Envelope& box) const +{ + RasterInfo info(filename_,format_,extent_); + single_file_policy policy(info); //todo: handle different policies! + return featureset_ptr(new RasterFeatureset(policy,box,t)); +} + + +featureset_ptr raster_datasource::featuresAtPoint(const CoordTransform& t, + const coord2d& pt) const +{ + return featureset_ptr(0); +} diff --git a/datasources/raster/raster_datasource.hpp b/datasources/raster/raster_datasource.hpp new file mode 100644 index 000000000..865e932ba --- /dev/null +++ b/datasources/raster/raster_datasource.hpp @@ -0,0 +1,53 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: raster_datasource.hh 44 2005-04-22 18:53:54Z pavlenko $ + +#ifndef RASTER_DATASOURCE_HH +#define RASTER_DATASOURCE_HH + +#include "mapnik.hh" +#include "image_reader.hh" + +using namespace mapnik; + +class raster_datasource : public datasource +{ +private: + std::string filename_; + std::string format_; + mapnik::Envelope extent_; + static std::string name_; +public: + raster_datasource(const Parameters& params); + virtual ~raster_datasource(); + int type() const; + std::string name(); + featureset_ptr featuresAll(const CoordTransform& t) const; + featureset_ptr featuresInBox(const CoordTransform& t,const mapnik::Envelope& box) const; + featureset_ptr featuresAtPoint(const CoordTransform& t,const coord2d& pt) const; + const mapnik::Envelope& envelope() const; +private: + //no copying + raster_datasource(const raster_datasource&); + raster_datasource& operator=(const raster_datasource&); + // + bool parseEnvelope(const std::string& str,Envelope& envelope); +}; + +#endif //RASTER_DATASOURCE_H diff --git a/datasources/raster/raster_featureset.cpp b/datasources/raster/raster_featureset.cpp new file mode 100644 index 000000000..2f245ca10 --- /dev/null +++ b/datasources/raster/raster_featureset.cpp @@ -0,0 +1,81 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "raster_featureset.hh" +#include "image_reader.hh" + +template +RasterFeatureset::RasterFeatureset(const LookupPolicy& policy, + const Envelope& box, + const CoordTransform& t) + : policy_(policy), + id_(1), + extent_(box), + t_(t), + curIter_(policy_.query(box)), + endIter_(policy_.end()) + +{} + +template +RasterFeatureset::~RasterFeatureset() {} + +template +Feature* RasterFeatureset::next() +{ + Feature* f=0; + if (curIter_!=endIter_) + { + try + { + std::cout<<"RasterFeatureset "<format()<<" "<file()< reader(get_image_reader(curIter_->format(),curIter_->file())); + std::cout<width(); + int image_height=reader->height(); + if (image_width>0 && image_height>0) + { + CoordTransform t(image_width,image_height,curIter_->envelope()); + Envelope intersect=extent_.intersect(curIter_->envelope()); + Envelope ext=t.forward(intersect); + + Envelope image_ext=t_.forward(intersect); + + ImageData32 image((int)ext.width(),(int)ext.height()); + reader->read((int)ext.minx(),(int)ext.miny(),image); + ImageData32 target((int)(image_ext.width()+0.5),(int)(image_ext.height()+0.5)); + scale_image(target,image); + + f=new RasterFeature(++id_,RasterPtr(new raster((int)(image_ext.minx()+0.5), + (int)(image_ext.miny()+0.5),target))); + } + } + } + catch (...) + { + } + ++curIter_; + } + return f; +} + + +template class RasterFeatureset; +//template RasterFeatureset; diff --git a/datasources/raster/raster_featureset.hpp b/datasources/raster/raster_featureset.hpp new file mode 100644 index 000000000..09738d327 --- /dev/null +++ b/datasources/raster/raster_featureset.hpp @@ -0,0 +1,115 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef RASTER_FEATURESET_HH +#define RASTER_FEATURESET_HH + +#include "raster_datasource.hh" +#include "raster_info.hh" +#include + +using std::vector; + +class single_file_policy +{ + RasterInfo info_; +public: + class const_iterator + { + enum {start,end}; + bool status_; + const single_file_policy* p_; + public: + explicit const_iterator(const single_file_policy* p) + :status_(start), + p_(p) {} + + const_iterator() + :status_(end){} + + const_iterator(const const_iterator& other) + :status_(other.status_), + p_(other.p_) {} + + const_iterator& operator++() + { + status_=end; + return *this; + } + + const RasterInfo& operator*() const + { + return p_->info_; + } + + const RasterInfo* operator->() const + { + return &(p_->info_); + } + + bool operator!=(const const_iterator& itr) + { + return status_!=itr.status_; + } + }; + + explicit single_file_policy(const RasterInfo& info) + :info_(info) {} + + const_iterator begin() + { + return const_iterator(this); + } + + const_iterator query(const Envelope& box) + { + if (box.intersects(info_.envelope())) + { + return begin(); + } + return end(); + } + + const_iterator end() + { + return const_iterator(); + } +}; + +class os_name_policy +{ + //TODO +}; + +template +class RasterFeatureset : public Featureset +{ + typedef typename LookupPolicy::const_iterator iterator_type; + LookupPolicy policy_; + size_t id_; + Envelope extent_; + CoordTransform t_; + iterator_type curIter_; + iterator_type endIter_; +public: + RasterFeatureset(const LookupPolicy& policy,const Envelope& box,const CoordTransform& t); + virtual ~RasterFeatureset(); + Feature* next(); +}; + +#endif //RASTER_FEATURESET_HH diff --git a/datasources/raster/raster_info.cpp b/datasources/raster/raster_info.cpp new file mode 100644 index 000000000..c27a2f188 --- /dev/null +++ b/datasources/raster/raster_info.cpp @@ -0,0 +1,71 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: raster_info.cc 17 2005-03-08 23:58:43Z pavlenko $ + +#include "raster_info.hh" + +RasterInfo::RasterInfo(const std::string& file,const std::string& format,const mapnik::Envelope& extent,int srid) + :file_(file), + format_(format), + extent_(extent), + srid_(srid) {} + +RasterInfo::RasterInfo(const RasterInfo& rhs) + :file_(rhs.file_), + format_(rhs.format_), + extent_(rhs.extent_), + srid_(rhs.srid_) {} + +void RasterInfo::swap(RasterInfo& other) throw() +{ + file_=other.file_; + format_=other.format_; + extent_=other.extent_; + srid_=other.srid_; +} + + +RasterInfo& RasterInfo::operator=(const RasterInfo& rhs) +{ + RasterInfo tmp(rhs); + swap(tmp); + return *this; +} + + +const Envelope& RasterInfo::envelope() const +{ + return extent_; +} + + +const std::string& RasterInfo::file() const +{ + return file_; +} + +const std::string& RasterInfo::format() const +{ + return format_; +} + +const int RasterInfo::srid() const +{ + return srid_; +} diff --git a/datasources/raster/raster_info.hpp b/datasources/raster/raster_info.hpp new file mode 100644 index 000000000..194d98333 --- /dev/null +++ b/datasources/raster/raster_info.hpp @@ -0,0 +1,46 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: raster_info.hh 17 2005-03-08 23:58:43Z pavlenko $ + +#ifndef RASTER_INFO +#define RASTER_INFO + +#include "raster_datasource.hh" +#include + +using mapnik::Envelope; + +class RasterInfo +{ + std::string file_; + std::string format_; + Envelope extent_; + int srid_; + public: + RasterInfo(const std::string& file,const std::string& format,const Envelope& extent,int srid=-1); + RasterInfo(const RasterInfo& rhs); + RasterInfo& operator=(const RasterInfo& rhs); + const Envelope& envelope() const; + const std::string& file() const; + const std::string& format() const; + const int srid() const; +private: + void swap(RasterInfo& other) throw(); +}; +#endif //RASTER_INFO diff --git a/datasources/shape/Jamfile b/datasources/shape/Jamfile new file mode 100644 index 000000000..34568bf41 --- /dev/null +++ b/datasources/shape/Jamfile @@ -0,0 +1,11 @@ +lib shape : + dbffile.cc + dbf_test.cc + shape.cc + shape_featureset.cc + shapefile.cc + shape_index_featureset.cc + shape_io.cc + shp_index.cc + ; + diff --git a/datasources/shape/SConscript b/datasources/shape/SConscript new file mode 100644 index 000000000..d423b77df --- /dev/null +++ b/datasources/shape/SConscript @@ -0,0 +1,26 @@ +#mapnik + +Import ('env') + +prefix = env['PREFIX'] +boost_root = env['BOOST_ROOT'] +agg_root = env['AGG_ROOT'] +agg_headers = agg_root + '/include' + +shape_src = Split( + """ + dbffile.cc + shape.cc + shape_featureset.cc + shapefile.cc + shape_index_featureset.cc + shape_io.cc + shp_index.cc + """ + ) + +headers = ['#include',boost_root,agg_headers] + +shape_datasource = env.SharedLibrary('shape',source=shape_src,SHLIBPREFIX='',CPPPATH=headers) +env.Install('#stage/datasources',shape_datasource) +#env.Default(shape_datasource) diff --git a/datasources/shape/dbf_test.cpp b/datasources/shape/dbf_test.cpp new file mode 100644 index 000000000..96d78f9d0 --- /dev/null +++ b/datasources/shape/dbf_test.cpp @@ -0,0 +1,60 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include "dbffile.hh" + +using namespace std; + +int main(int argc,char** argv) +{ + if (argc!=2) + { + cout<<"usage: dbfdump "< + +dbf_file::dbf_file() + : num_records_(0), + num_fields_(0), + record_length_(0), + record_(0) {} + +dbf_file::dbf_file(const char* file_name) + :num_records_(0), + num_fields_(0), + record_length_(0), + record_(0) +{ + file_.open(file_name); + if (file_.is_open()) + { + read_header(); + } +} + + +dbf_file::~dbf_file() +{ + ::operator delete(record_); + file_.close(); +} + + +bool dbf_file::open(const std::string& file_name) +{ + file_.open(file_name.c_str()); + if (file_.is_open()) + read_header(); + return file_?true:false; +} + + +bool dbf_file::is_open() +{ + return file_.is_open(); +} + + +void dbf_file::close() +{ + if (file_ && file_.is_open()) + file_.close(); +} + + +int dbf_file::num_records() const +{ + return num_records_; +} + + +int dbf_file::num_fields() const +{ + return num_fields_; +} + + +void dbf_file::move_to(int index) +{ + if (index>0 && index<=num_records_) + { + long pos=(num_fields_<<5)+34+(index-1)*(record_length_+1); + file_.seekg(pos,std::ios::beg); + file_.read(record_,record_length_); + } +} + + +std::string dbf_file::string_value(int col) const +{ + if (col>=0 && col=0 && col=0 && coladd_property(name,str); + break; + } + case 'N': + case 'F': + { + if (str[0]=='*') + { + break; + } + if (fields_[col].dec_>0) + { + double d; + fromString(str,d); + + f->add_property(name,d); + } + else + { + int i; + fromString(str,i); + f->add_property(name,i); + } + break; + } + } + } +} + +void dbf_file::read_header() +{ + char c=file_.get(); + if (c=='\3' || c=='\131') + { + skip(3); + num_records_=read_int(); + assert(num_records_>0); + num_fields_=read_short(); + assert(num_fields_>0); + num_fields_=(num_fields_-33)/32; + skip(22); + int offset=0; + char name[11]; + memset(&name,0,11); + fields_.reserve(num_fields_); + for (int i=0;i0) + { + record_=static_cast(::operator new (sizeof(char)*record_length_)); + } + } +} + + +int dbf_file::read_short() +{ + char b[2]; + file_.read(b,2); + return (b[0] & 0xff) | (b[1] & 0xff) << 8; +} + + +int dbf_file::read_int() +{ + char b[4]; + file_.read(b,4); + return (b[0] & 0xff) | (b[1] & 0xff) << 8 | + (b[2] & 0xff) << 16 | (b[3] & 0xff) <<24; +} + + +void dbf_file::skip(int bytes) +{ + file_.seekg(bytes,std::ios::cur); +} diff --git a/datasources/shape/dbffile.hpp b/datasources/shape/dbffile.hpp new file mode 100644 index 000000000..370b5f5c3 --- /dev/null +++ b/datasources/shape/dbffile.hpp @@ -0,0 +1,73 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef DBFFILE_HH +#define DBFFILE_HH + +#include +#include +#include +#include + +#include "mapnik.hh" + +using namespace mapnik; + +struct field_descriptor +{ + int index_; + std::string name_; + char type_; + int length_; + int dec_; + int offset_; +}; + +class dbf_file +{ + private: + + int num_records_; + int num_fields_; + int record_length_; + std::vector fields_; + std::ifstream file_; + char* record_; + public: + dbf_file(); + dbf_file(const char* file_name); + dbf_file(const std::string& file_name); + ~dbf_file(); + bool open(const std::string& file_name); + bool is_open(); + void close(); + int num_records() const; + int num_fields() const; + const field_descriptor& descriptor(int col) const; + void move_to(int index); + std::string string_value(int col) const; + void add_attribute(int col,Feature* f) const throw(); + private: + dbf_file(const dbf_file&); + dbf_file& operator=(const dbf_file&); + void read_header(); + int read_short(); + int read_int(); + void skip(int bytes); +}; +#endif //DBFFILE_HH diff --git a/datasources/shape/shape.cpp b/datasources/shape/shape.cpp new file mode 100644 index 000000000..4cf6c5145 --- /dev/null +++ b/datasources/shape/shape.cpp @@ -0,0 +1,113 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "shape.hh" +#include "shape_featureset.hh" +#include "shape_index_featureset.hh" + +#include +#include + +DATASOURCE_PLUGIN(shape_datasource); + +shape_datasource::shape_datasource(const Parameters ¶ms) + : shape_name_(params.get("file")), + type_(datasource::Vector), + file_length_(0), + indexed_(false) +{ + try + { + shape_io shape(shape_name_); + init(shape); + } + catch (datasource_exception& ex) + { + std::cerr< extent_; + bool indexed_; + static std::string name_; +public: + int type() const; + static std::string name(); + featureset_ptr features(const query& q) const; + const Envelope& envelope() const; + shape_datasource(const Parameters ¶ms); + virtual ~shape_datasource(); +private: + shape_datasource(const shape_datasource&); + shape_datasource& operator=(const shape_datasource&); + void init(shape_io& shape); +}; + +#endif //SHAPE_HH diff --git a/datasources/shape/shape_featureset.cpp b/datasources/shape/shape_featureset.cpp new file mode 100644 index 000000000..0be40169b --- /dev/null +++ b/datasources/shape/shape_featureset.cpp @@ -0,0 +1,180 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "shape_featureset.hh" +#include + +template +shape_featureset::shape_featureset(const filterT& filter, + const std::string& shape_file, + const std::set& attribute_names, + long file_length ) + : filter_(filter), + shape_type_(shape_io::shape_null), + shape_(shape_file), + query_ext_(), + file_length_(file_length), + count_(0) +{ + shape_.shp().skip(100); + //attributes + typename std::set::const_iterator pos=attribute_names.begin(); + while (pos!=attribute_names.end()) + { + for (int i=0;i +Feature* shape_featureset::next() +{ + Feature* feature=0; + std::streampos pos=shape_.shp().pos(); + + if (pos < std::streampos(file_length_ * 2)) + { + shape_.move_to(pos); + int type=shape_.type(); + int id=shape_.id_; + if (type == shape_io::shape_point) + { + double x=shape_.shp().read_double(); + double y=shape_.shp().read_double(); + geometry_ptr point(new point_impl(-1)); + point->move_to(x,y); + feature=new Feature(id,point); + ++count_; + } + else if (type == shape_io::shape_pointm) + { + double x=shape_.shp().read_double(); + double y=shape_.shp().read_double(); + shape_.shp().read_double();//m + geometry_ptr point(new point_impl(-1)); + point->move_to(x,y); + feature=new Feature(id,point); + ++count_; + } + else if (type == shape_io::shape_pointz) + { + double x=shape_.shp().read_double(); + double y=shape_.shp().read_double(); + shape_.shp().read_double();//z + shape_.shp().read_double();//m + geometry_ptr point(new point_impl(-1)); + point->move_to(x,y); + feature=new Feature(id,point); + ++count_; + } + else + { + while (!filter_.pass(shape_.current_extent())) + { + unsigned reclen=shape_.reclength_; + shape_.move_to(long(shape_.shp().pos()) + 2 * reclen - 36); + if ((long)shape_.shp().pos() >= file_length_ * 2) + return 0; + } + + switch (type) + { + + case shape_io::shape_polyline: + { + geometry_ptr line = shape_.read_polyline(); + feature=new Feature(shape_.id_,line); + ++count_; + break; + } + case shape_io::shape_polylinem: + { + geometry_ptr line = shape_.read_polylinem(); + feature=new Feature(shape_.id_,line); + ++count_; + break; + } + case shape_io::shape_polylinez: + { + geometry_ptr line = shape_.read_polylinez(); + feature=new Feature(shape_.id_,line); + ++count_; + break; + } + case shape_io::shape_polygon: + { + geometry_ptr poly = shape_.read_polygon(); + feature=new Feature(shape_.id_,poly); + ++count_; + break; + } + case shape_io::shape_polygonm: + { + geometry_ptr poly = shape_.read_polygonm(); + feature=new Feature(shape_.id_,poly); + ++count_; + break; + } + case shape_io::shape_polygonz: + { + geometry_ptr poly = shape_.read_polygon(); + feature=new Feature(shape_.id_,poly); + ++count_; + break; + } + default: + return 0; + } + + if (attr_ids_.size()) + { + shape_.dbf().move_to(shape_.id_); + typename std::vector::const_iterator pos=attr_ids_.begin(); + while (pos!=attr_ids_.end()) + { + try + { + shape_.dbf().add_attribute(*pos,feature);//TODO optimize!!! + } + catch (...) + { + //TODO + } + ++pos; + } + } + } + } + if (!feature) + std::cout<<" total shapes read="< +shape_featureset::~shape_featureset() {} + +template class shape_featureset; diff --git a/datasources/shape/shape_featureset.hpp b/datasources/shape/shape_featureset.hpp new file mode 100644 index 000000000..1219080c7 --- /dev/null +++ b/datasources/shape/shape_featureset.hpp @@ -0,0 +1,48 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef SHAPE_FS_HH +#define SHAPE_FS_HH + +#include "shape.hh" + +using namespace mapnik; + +template +class shape_featureset : public Featureset +{ + filterT filter_; + int shape_type_; + shape_io shape_; + Envelope query_ext_; + long file_length_; + std::vector attr_ids_; + mutable Envelope feature_ext_; + mutable int total_geom_size; + mutable int count_; +public: + shape_featureset(const filterT& filter, const std::string& shape_file, + const std::set& attribute_names,long file_length); + virtual ~shape_featureset(); + Feature* next(); +private: + shape_featureset(const shape_featureset&); + const shape_featureset& operator=(const shape_featureset&); +}; + +#endif //SHAPE_FS_HH diff --git a/datasources/shape/shape_index_featureset.cpp b/datasources/shape/shape_index_featureset.cpp new file mode 100644 index 000000000..d2263b7b2 --- /dev/null +++ b/datasources/shape/shape_index_featureset.cpp @@ -0,0 +1,182 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: shape_index_featureset.cc 36 2005-04-05 14:32:18Z pavlenko $ + +#include "shape_index_featureset.hh" + +template +shape_index_featureset::shape_index_featureset(const filterT& filter, + const std::string& shape_file, + const std::set& attribute_names) + : filter_(filter), + shape_type_(0), + shape_(shape_file), + count_(0) + +{ + shape_.shp().skip(100); + std::string indexname(shape_file + ".index"); + std::ifstream file(indexname.c_str(),std::ios::in|std::ios::binary); + if (file) + { + shp_index::query(filter,file,ids_); + file.close(); + } + std::cout<< "query size=" << ids_.size() << "\n"; + itr_ = ids_.begin(); + + // deal with attributes + std::set::const_iterator pos=attribute_names.begin(); + while (pos!=attribute_names.end()) + { + for (int i=0;i +Feature* shape_index_featureset::next() +{ + Feature *f=0; + if (itr_!=ids_.end()) + { + int pos=*itr_++; + shape_.move_to(pos); + int type=shape_.type(); + if (type==shape_io::shape_point) + { + double x=shape_.shp().read_double(); + double y=shape_.shp().read_double(); + geometry_ptr point(new point_impl(-1)); + point->move_to(x,y); + f=new Feature(shape_.id_,point); + ++count_; + } + else if (type == shape_io::shape_pointm) + { + double x=shape_.shp().read_double(); + double y=shape_.shp().read_double(); + shape_.shp().read_double();// m + geometry_ptr point(new point_impl(-1)); + point->move_to(x,y); + f=new Feature(shape_.id_,point); + ++count_; + } + else if (type == shape_io::shape_pointz) + { + double x=shape_.shp().read_double(); + double y=shape_.shp().read_double(); + shape_.shp().read_double();// z + shape_.shp().read_double();// m + geometry_ptr point(new point_impl(-1)); + point->move_to(x,y); + f=new Feature(shape_.id_,point); + ++count_; + } + else + { + while(!filter_.pass(shape_.current_extent()) && + itr_!=ids_.end()) + { + pos=*itr_++; + shape_.move_to(pos); + } + + switch (type) + { + case shape_io::shape_polyline: + { + geometry_ptr line = shape_.read_polyline(); + f=new Feature(shape_.id_,line); + ++count_; + break; + } + case shape_io::shape_polylinem: + { + geometry_ptr line = shape_.read_polylinem(); + f=new Feature(shape_.id_,line); + ++count_; + break; + } + case shape_io::shape_polylinez: + { + geometry_ptr line = shape_.read_polylinez(); + f=new Feature(shape_.id_,line); + ++count_; + break; + } + case shape_io::shape_polygon: + { + + geometry_ptr poly = shape_.read_polygon(); + f=new Feature(shape_.id_,poly); + ++count_; + break; + } + case shape_io::shape_polygonm: + { + geometry_ptr poly = shape_.read_polygonm(); + f=new Feature(shape_.id_,poly); + ++count_; + break; + } + case shape_io::shape_polygonz: + { + geometry_ptr poly = shape_.read_polygonz(); + f=new Feature(shape_.id_,poly); + ++count_; + break; + } + } + if (attr_ids_.size()) + { + shape_.dbf().move_to(shape_.id_); + std::vector::const_iterator pos=attr_ids_.begin(); + while (pos!=attr_ids_.end()) + { + try + { + shape_.dbf().add_attribute(*pos,f);//TODO optimize!!! + } + catch (...) + { + std::cerr<<"exception caught\n"; + } + ++pos; + } + } + } + } + if (!f) std::cout< +shape_index_featureset::~shape_index_featureset() {} + +template class shape_index_featureset; + diff --git a/datasources/shape/shape_index_featureset.hpp b/datasources/shape/shape_index_featureset.hpp new file mode 100644 index 000000000..4d2790007 --- /dev/null +++ b/datasources/shape/shape_index_featureset.hpp @@ -0,0 +1,49 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef SHAPE_SQT_FS_HH +#define SHAPE_SQT_FS_HH + +#include "shape_featureset.hh" +#include +#include + +template +class shape_index_featureset : public Featureset +{ + filterT filter_; + int shape_type_; + shape_io shape_; + std::set ids_; + std::set::iterator itr_; + std::vector attr_ids_; + mutable Envelope feature_ext_; + mutable int total_geom_size; + mutable int count_; + +public: + shape_index_featureset(const filterT& filter,const std::string& shape_file, + const std::set& attribute_names); + virtual ~shape_index_featureset(); + Feature* next(); +private: + //no copying + shape_index_featureset(const shape_index_featureset&); + shape_index_featureset& operator=(const shape_index_featureset&); +}; +#endif //SHAPE_SQT_FS_HH diff --git a/datasources/shape/shape_io.cpp b/datasources/shape/shape_io.cpp new file mode 100644 index 000000000..343e66a72 --- /dev/null +++ b/datasources/shape/shape_io.cpp @@ -0,0 +1,414 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: shape_io.cc 26 2005-03-29 19:18:59Z pavlenko $ + +#include "shape_io.hh" +#include "shape.hh" + + +const std::string shape_io::SHP = ".shp"; +const std::string shape_io::DBF = ".dbf"; + +shape_io::shape_io(const std::string& shape_name) + : type_(shape_null), + reclength_(0), + id_(0) +{ + bool ok = (shp_.open(shape_name + SHP) && + dbf_.open(shape_name + DBF)); + if (!ok) + { + throw datasource_exception("cannot read shape file"); + } +} + +shape_io::~shape_io() +{ + shp_.close(); + dbf_.close(); +} + + +void shape_io::move_to (int pos) +{ + shp_.seek(pos); + id_ = shp_.read_xdr_integer(); + reclength_ = shp_.read_xdr_integer(); + type_ = shp_.read_ndr_integer(); + + if (type_ != shape_point) + { + shp_.read_envelope(cur_extent_); + } +} + +int shape_io::type() const +{ + return type_; +} + +const Envelope& shape_io::current_extent() const +{ + return cur_extent_; +} + +shape_file& shape_io::shp() +{ + return shp_; +} + +shape_file& shape_io::shx() +{ + return shx_; +} + + +dbf_file& shape_io::dbf() +{ + return dbf_; +} + + +geometry_ptr shape_io::read_polyline() +{ + shape_record record(reclength_*2-36); + shp_.read_record(record); + int num_parts=record.read_ndr_integer(); + int num_points=record.read_ndr_integer(); + geometry_ptr line(new line_string_impl(-1)); + + if (num_parts == 1) + { + record.skip(4); + double x=record.read_double(); + double y=record.read_double(); + line->move_to(x,y); + for (int i=1;iline_to(x,y); + } + } + else + { + std::vector parts(num_parts); + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } + } + return line; +} + +geometry_ptr shape_io::read_polylinem() +{ + shape_record record(reclength_*2-36); + shp_.read_record(record); + int num_parts=record.read_ndr_integer(); + int num_points=record.read_ndr_integer(); + geometry_ptr line(new line_string_impl(-1)); + + if (num_parts == 1) + { + record.skip(4); + double x=record.read_double(); + double y=record.read_double(); + line->move_to(x,y); + for (int i=1;iline_to(x,y); + } + } + else + { + std::vector parts(num_parts); + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } + } + // m-range + //double m0=record.read_double(); + //double m1=record.read_double(); + + //for (int i=0;imove_to(x,y); + for (int i=1;iline_to(x,y); + } + } + else + { + std::vector parts(num_parts); + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } + } + // z-range + //double z0=record.read_double(); + //double z1=record.read_double(); + //for (int i=0;i parts(num_parts); + geometry_ptr poly(new polygon_impl(-1)); + + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } + return poly; +} + +geometry_ptr shape_io::read_polygonm() +{ + shape_record record(reclength_*2-36); + shp_.read_record(record); + int num_parts=record.read_ndr_integer(); + int num_points=record.read_ndr_integer(); + std::vector parts(num_parts); + geometry_ptr poly(new polygon_impl(-1)); + + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } + // m-range + //double m0=record.read_double(); + //double m1=record.read_double(); + + //for (int i=0;i parts(num_parts); + geometry_ptr poly(new polygon_impl(-1)); + + for (int i=0;imove_to(x,y); + + for (int j=start+1;jline_to(x,y); + } + } + // z-range + //double z0=record.read_double(); + //double z1=record.read_double(); + //for (int i=0;i cur_extent_; + +public: + enum + { + shape_null = 0, + shape_point = 1, + shape_polyline = 3, + shape_polygon = 5, + shape_multipoint = 8, + shape_pointz = 11, + shape_polylinez = 13, + shape_polygonz = 15, + shape_multipointz = 18, + shape_pointm = 21, + shape_polylinem = 23, + shape_polygonm = 25, + shape_multipointm = 28, + shape_multipatch = 31 + }; + + shape_io(const std::string& shape_name); + ~shape_io(); + shape_file& shp(); + shape_file& shx(); + dbf_file& dbf(); + void move_to(int id); + int type() const; + const Envelope& current_extent() const; + + geometry_ptr read_polyline(); + geometry_ptr read_polylinem(); + geometry_ptr read_polylinez(); + geometry_ptr read_polygon(); + geometry_ptr read_polygonm(); + geometry_ptr read_polygonz(); +private: + //void read_record(const shape_record& record); + // no copying + shape_io(const shape_io&); + shape_io& operator=(const shape_io&); +}; +#endif //SHAPE_IO_HH diff --git a/datasources/shape/shapefile.cpp b/datasources/shape/shapefile.cpp new file mode 100644 index 000000000..43d73820b --- /dev/null +++ b/datasources/shape/shapefile.cpp @@ -0,0 +1,58 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "shapefile.hh" + +shape_file::shape_file() {} + + +shape_file::shape_file(const std::string& file_name) +{ + //file_.rdbuf()->pubsetbuf(buff_,buffer_size); + file_.open(file_name.c_str(),std::ios::in|std::ios::binary); +} + +shape_file::~shape_file() +{ + if (file_ && file_.is_open()) + file_.close(); +} + + +bool shape_file::open(const std::string& file_name) +{ + //file_.rdbuf()->pubsetbuf(buff_,buffer_size); + file_.open(file_name.c_str(),std::ios::in | std::ios::binary); + return file_?true:false; +} + + +bool shape_file::is_open() +{ + return file_.is_open(); +} + + +void shape_file::close() +{ + if (file_ && file_.is_open()) + file_.close(); +} + + + diff --git a/datasources/shape/shapefile.hpp b/datasources/shape/shapefile.hpp new file mode 100644 index 000000000..bc8f1c642 --- /dev/null +++ b/datasources/shape/shapefile.hpp @@ -0,0 +1,195 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: shapefile.hh 33 2005-04-04 13:01:03Z pavlenko $ + +#ifndef SHAPEFILE_HH +#define SHAPEFILE_HH + +#include "mapnik.hh" +#include + +using namespace mapnik; + +struct shape_record +{ + char* data; + size_t size; + size_t pos; + explicit shape_record(size_t size) + : data(static_cast(::operator new(sizeof(char)*size))), + size(size), + pos(0) {} + + char* rawdata() + { + return &data[0]; + } + void skip(unsigned n) + { + pos+=n; + } + int read_ndr_integer() + { + int val=(data[pos] & 0xff) | + (data[pos+1] & 0xff) << 8 | + (data[pos+2] & 0xff) << 16 | + (data[pos+3] & 0xff) << 24; + pos+=4; + return val; + } + + int read_xdr_integer() + { + int val=(data[pos] & 0xff) << 24 | + (data[pos+1] & 0xff) << 16 | + (data[pos+2] & 0xff) << 8 | + (data[pos+3] & 0xff); + pos+=4; + return val; + } + + double read_double() + { + double val; +#ifndef WORDS_BIGENDIAN + std::memcpy(&val,&data[pos],8); +#else + long long bits = ((long long)data[pos] & 0xff) | + ((long long)data[pos+1] & 0xff) << 8 | + ((long long)data[pos+2] & 0xff) << 16 | + ((long long)data[pos+3] & 0xff) << 24 | + ((long long)data[pos+4] & 0xff) << 32 | + ((long long)data[pos+5] & 0xff) << 40 | + ((long long)data[pos+6] & 0xff) << 48 | + ((long long)data[pos+7] & 0xff) << 56 ; + std::memcpy(&val,&bits,8); +#endif + pos+=8; + return val; + } + long remains() + { + return (size-pos); + } + ~shape_record() + { + ::operator delete(data); + } +}; + +class shape_file +{ + std::ifstream file_; + //static const int buffer_size = 16; + //char buff_[buffer_size]; +public: + shape_file(); + shape_file(const std::string& file_name); + ~shape_file(); + bool open(const std::string& file_name); + bool is_open(); + void close(); + + inline void shape_file::read_record(shape_record& rec) + { + file_.read(rec.rawdata(),rec.size); + } + + inline int read_xdr_integer() + { + char b[4]; + file_.read(b, 4); + return b[3] & 0xffu | (b[2] & 0xffu) << 8 | + (b[1] & 0xffu) << 16 | (b[0] & 0xffu) << 24; + } + + inline int read_ndr_integer() + { + char b[4]; + file_.read(b,4); + return b[0]&0xffu | (b[1]&0xffu) << 8 | + (b[2]&0xffu) << 16 | (b[3]&0xffu) << 24; + } + + inline double read_double() + { + double val; +#ifndef WORDS_BIGENDIAN + file_.read(reinterpret_cast(&val),8); +#else + char b[8]; + file_.read(b,8); + long long bits = ((long long)b[0] & 0xff) | + ((long long)b[1] & 0xff) << 8 | + ((long long)b[2] & 0xff) << 16 | + ((long long)b[3] & 0xff) << 24 | + ((long long)b[4] & 0xff) << 32 | + ((long long)b[5] & 0xff) << 40 | + ((long long)b[6] & 0xff) << 48 | + ((long long)b[7] & 0xff) << 56 ; + memcpy(&val,&bits,8); +#endif + return val; + } + + inline void read_envelope(Envelope& envelope) + { +#ifndef WORDS_BIGENDIAN + file_.read(reinterpret_cast(&envelope),sizeof(envelope)); +#else + double minx=read_double(); + double miny=read_double(); + double maxx=read_double(); + double maxy=read_double(); + envelope.init(minx,miny,maxx,maxy); +#endif + } + + inline void skip(std::streampos bytes) + { + file_.seekg(bytes,std::ios::cur); + } + + inline void rewind() + { + seek(100); + } + + inline void seek(std::streampos pos) + { + file_.seekg(pos,std::ios::beg); + } + + + inline std::streampos pos() + { + return file_.tellg(); + } + + + inline bool is_eof() + { + return file_.eof(); + } + +private: + shape_file(const shape_file&); + shape_file& operator=(const shape_file&); +}; +#endif //SHAPEFILE_HH diff --git a/datasources/shape/shp_index.cpp b/datasources/shape/shp_index.cpp new file mode 100644 index 000000000..9b89c111c --- /dev/null +++ b/datasources/shape/shp_index.cpp @@ -0,0 +1,76 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "shp_index.hh" + +template +void shp_index::query(const filterT& filter,std::ifstream& file,std::set& pos) +{ + file.seekg(16,std::ios::beg); + query_node(filter,file,pos); +} + + +template +void shp_index::query_node(const filterT& filter,std::ifstream& file,std::set& ids) +{ + int offset=read_ndr_integer(file); + + Envelope node_ext; + read_envelope(file,node_ext); + + int num_shapes=read_ndr_integer(file); + + if (!filter.pass(node_ext)) + { + file.seekg(offset+num_shapes*4+4,std::ios::cur); + return; + } + + for (int i=0;i +int shp_index::read_ndr_integer(std::ifstream& file) +{ + char b[4]; + file.read(b,4); + return (b[0]&0xff) | (b[1]&0xff)<<8 | (b[2]&0xff)<<16 | (b[3]&0xff)<<24; +} + + +template +void shp_index::read_envelope(std::ifstream& file,Envelope& envelope) +{ + file.read(reinterpret_cast(&envelope),sizeof(envelope)); +} + +template class shp_index; +template class shp_index; diff --git a/datasources/shape/shp_index.hpp b/datasources/shape/shp_index.hpp new file mode 100644 index 000000000..675284d06 --- /dev/null +++ b/datasources/shape/shp_index.hpp @@ -0,0 +1,43 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef SHP_INDEX_HH +#define SHP_INDEX_HH + +#include "mapnik.hh" +#include +#include + +using namespace mapnik; + +template +class shp_index +{ +public: + static void query(const filterT& filter,std::ifstream& file,std::set& pos); +private: + shp_index(); + ~shp_index(); + shp_index(const shp_index&); + shp_index& operator=(const shp_index&); + static int read_ndr_integer(std::ifstream& in); + static void read_envelope(std::ifstream& in,Envelope &envelope); + static void query_node(const filterT& filter,std::ifstream& file,std::set& pos); +}; + +#endif //SHP_INDEX_HH diff --git a/include/attribute.hpp b/include/attribute.hpp new file mode 100644 index 000000000..3469c8983 --- /dev/null +++ b/include/attribute.hpp @@ -0,0 +1,218 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: attribute.hpp 41 2005-04-13 20:21:56Z pavlenko $ + +#ifndef ATTRIBUTE_HPP +#define ATTRIBUTE_HPP + +#include +#include +#include +#include + + +namespace mapnik +{ + template + struct attribute_traits + { + static std::string to_string(const T& value) + { + std::stringstream ss; + ss << value; + return ss.str(); + } + }; + + template <> + struct attribute_traits + { + static std::string to_string(const std::string& value) + { + return value; + } + }; + + class attribute + { + public: + attribute() + : base_(0) {} + + template + attribute(const T& value) + : base_(new attribute_impl(value)) + {} + + attribute(const attribute& rhs) + : base_(rhs.base_ ? rhs.base_->clone() : 0) + {} + + ~attribute() + { + delete base_; + } + + template + attribute& operator=(const T& rhs) + { + attribute(rhs).swap(*this); + return *this; + } + + attribute& operator=(const attribute& rhs) + { + attribute(rhs).swap(*this); + return *this; + } + + bool empty() const + { + return !base_; + } + + const std::type_info & type() const + { + return base_ ? base_->type() : typeid(void); + } + + const std::string to_string() const + { + return base_ ? base_->to_string() : ""; + } + private: + attribute& swap(attribute& rhs) + { + std::swap(base_,rhs.base_); + return *this; + } + + class attribute_base + { + public: + virtual ~attribute_base() {} + virtual attribute_base* clone() const=0; + virtual std::string to_string() const=0; + virtual const std::type_info& type() const=0; + }; + + template > + class attribute_impl : public attribute_base + { + public: + typedef T value_type; + attribute_impl(const value_type& value) + : value_(value) {} + + virtual std::string to_string() const + { + return ATraits::to_string(value_); + } + + virtual attribute_base* clone() const + { + return new attribute_impl(value_); + } + virtual const std::type_info& type() const + { + return typeid(value_); + } + value_type value_; + }; + private: + template + friend value_type* attribute_cast(attribute*); + attribute_base* base_; + }; + + + template + struct bad_attribute_cast : public std::bad_cast + { + virtual const char* what() const throw() + { + return "attribute::failed conversion"; + } + }; + + template + bool is_type(const attribute& attr) + { + return attr.type()==typeid(T); + } + + template + T* attribute_cast(attribute* attr) + { + return attr && attr->type() == typeid(T) + ? &static_cast*>(attr->base_)->value_ + : 0; + } + + template + const T* attribute_cast(const attribute* attr) + { + return attribute_cast(const_cast(attr)); + } + + template + T attribute_cast(const attribute& attr) + { + using namespace boost; + typedef BOOST_DEDUCED_TYPENAME remove_reference::type nonref; + const nonref * result=attribute_cast(&attr); + if (!result) + { + throw bad_attribute_cast(); + } + return *result; + } + + template + T attribute_cast(attribute& attr) + { + using namespace boost; + typedef BOOST_DEDUCED_TYPENAME remove_reference::type nonref; + nonref * result=attribute_cast(&attr); + if (!result) + throw bad_attribute_cast(); + return *result; + } + + + template + attribute attribute_from_string(const std::string& val) + { + std::istringstream is(val); + T t; + is >> t; + return attribute(t); + } + + template + inline std::basic_ostream& + operator << (std::basic_ostream& out, + const attribute& attr) + { + out << attr.to_string(); + return out; + } +} + +#endif //ATTRIBUTE_HPP diff --git a/include/attribute_collector.hpp b/include/attribute_collector.hpp new file mode 100644 index 000000000..27aa1c6fe --- /dev/null +++ b/include/attribute_collector.hpp @@ -0,0 +1,62 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef ATTRIBUTE_COLLECTOR +#define ATTROBUTE_COLLECTOR + +#include "filter.hpp" +#include "expression.hpp" +#include "feature_layer_desc.hpp" + +#include + +namespace mapnik +{ + template + class attribute_collector : public filter_visitor + { + public: + attribute_collector(std::set& names) + : names_(names) {} + + void visit(filter& /*filter*/) + { + //not interested + } + + void visit(expression& exp) + { + property* pf; + if ((pf = dynamic_cast*>(&exp))) + { + names_.insert(pf->name()); + } + } + virtual ~attribute_collector() {} + private: + // no copying + attribute_collector(attribute_collector const&); + attribute_collector& operator=(attribute_collector const&); + private: + std::set& names_; + }; +} + +#endif //ATTRIBUTE_COLLECTOR_HPP diff --git a/include/attribute_descriptor.hpp b/include/attribute_descriptor.hpp new file mode 100644 index 000000000..90ef87db0 --- /dev/null +++ b/include/attribute_descriptor.hpp @@ -0,0 +1,35 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef ATTRIBUTE_DESCRIPTOR +#define ATTRIBUTE_DESCRIPTOR + +#include + +namespace mapnik +{ + struct attribute_desc + { + std::string name; + eType type; + }; +} + +#endif diff --git a/include/color.hpp b/include/color.hpp new file mode 100644 index 000000000..35a60fb7b --- /dev/null +++ b/include/color.hpp @@ -0,0 +1,75 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: color.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef COLOR_HPP +#define COLOR_HPP + +namespace mapnik { + + class Color + { + private: + int rgba_; + public: + Color() + :rgba_(0xffffffff) {} + + Color(int red,int green,int blue) + : rgba_(0xff<<24 | (blue&0xff) << 16 | (green&0xff) << 8 | red&0xff) {} + + explicit Color(int rgba) + : rgba_(rgba) {} + + Color(const Color& rhs) + : rgba_(rhs.rgba_) {} + + Color& operator=(const Color& rhs) + { + if (this==&rhs) return *this; + rgba_=rhs.rgba_; + return *this; + } + inline int blue() const + { + return (rgba_>>16)&0xff; + } + inline int green() const + { + return (rgba_>>8)&0xff; + } + inline int red() const + { + return rgba_&0xff; + } + inline int rgba() const + { + return rgba_; + } + static const Color White; + static const Color Black; + static const Color Gray; + static const Color Red; + static const Color Green; + static const Color Blue; + static const Color Yellow; + }; +} + +#endif //COLOR_HPP diff --git a/include/colorcube.hpp b/include/colorcube.hpp new file mode 100644 index 000000000..ee546bc91 --- /dev/null +++ b/include/colorcube.hpp @@ -0,0 +1,91 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#include "mapnik.hpp" +#include + +#ifndef COLORCUBE_HPP +#define COLORCUBE_HPP + + +namespace mapnik +{ + template + struct color_cube + { + const static unsigned maxcolors=rLevel * gLevel * bLevel + 32; + static unsigned cube[maxcolors]; + static bool initialized; + static unsigned rDiv; + static unsigned gDiv; + static unsigned bDiv; + + static unsigned color(unsigned red,unsigned green,unsigned blue) + { + if (!initialized) + init(); + unsigned index=rgb_level_index(red/rDiv,green/gDiv,blue/bDiv); + return cube[index]; + } + + private: + static unsigned rgb_level_index(unsigned red,unsigned green,unsigned blue) + { + return (red * gLevel * bLevel + green * bLevel + blue); + } + + static void init() + { + unsigned red,green,blue; + unsigned count=0; + for (int r=0;r + //unsigned color_cube::cube[color_cube::maxcolors]; + template + unsigned color_cube::rDiv=52; + template + unsigned color_cube::gDiv=52; + template + unsigned color_cube::bDiv=52; + template + bool color_cube::initialized=false; +} + +#endif diff --git a/include/comparison.hpp b/include/comparison.hpp new file mode 100644 index 000000000..2e5e2a3d8 --- /dev/null +++ b/include/comparison.hpp @@ -0,0 +1,150 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef COMPARISON_HPP +#define COMPARISON_HPP + + +#include "filter.hpp" +#include "expression.hpp" +#include "attribute.hpp" + +#include + +namespace mapnik +{ + template + struct greater_than + { + bool operator() (T const& left, T const& right) const + { + return left > right; + } + static std::string to_string() + { + return ">"; + } + }; + + template + struct greater_than_or_equal + { + bool operator() (T const& left, T const& right) const + { + return left >= right; + } + static std::string to_string() + { + return ">="; + } + }; + template + struct less_than + { + bool operator() (T const& left, T const& right) const + { + return left < right; + } + static std::string to_string() + { + return "<"; + } + }; + template + struct less_than_or_equal + { + bool operator() (T const& left, T const& right) const + { + return left <= right; + } + static std::string to_string() + { + return "<="; + } + }; + template + struct equals + { + bool operator() (T const& left, T const& right) const + { + return left == right; + } + static std::string to_string() + { + return "="; + } + }; + + template + struct not_equals + { + bool operator() (T const& left, T const& right) const + { + return left != right; + } + static std::string to_string() + { + return "<>"; + } + }; + + template + struct compare_filter : public filter + { + compare_filter(expression const& left, + expression const& right) + : filter(), + left_(left.clone()), right_(right.clone()) {} + + compare_filter(compare_filter const& other) + : filter(), + left_(other.left_->clone()),right_(other.right_->clone()) {} + + bool pass(const FeatureT& feature) const + { + return Op()(left_->get_value(feature),right_->get_value(feature)); + } + void accept(filter_visitor& v) + { + left_->accept(v); + right_->accept(v); + v.visit(*this); + } + std::string to_string() const + { + return "("+left_->to_string()+Op::to_string()+right_->to_string()+")"; + } + + filter* clone() const + { + return new compare_filter(*this); + } + virtual ~compare_filter() + { + delete left_; + delete right_; + } + private: + expression* left_; + expression* right_; + }; +} + +#endif //COMPARISON_HPP diff --git a/include/config.hpp b/include/config.hpp new file mode 100644 index 000000000..4250ab415 --- /dev/null +++ b/include/config.hpp @@ -0,0 +1,140 @@ +/* include/config.hpp. Generated by configure. */ +/* include/config.hpp.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if the `closedir' function returns void instead of `int'. */ +/* #undef CLOSEDIR_VOID */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `floor' function. */ +#define HAVE_FLOOR 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `jpeg' library (-ljpeg). */ +#define HAVE_LIBJPEG 1 + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `png' library (-lpng). */ +#define HAVE_LIBPNG 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the `pow' function. */ +#define HAVE_POW 1 + +/* Define to 1 if you have the `sqrt' function. */ +#define HAVE_SQRT 1 + +/* Define to 1 if stdbool.h conforms to C99. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if the system has the type `_Bool'. */ +#define HAVE__BOOL 1 + +/* Name of package */ +#define PACKAGE "mapnik" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "mapnik" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "mapnik 0.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "mapnik" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.1" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Version number of package */ +#define VERSION "0.1" + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* datasource plugins dir */ +#define _DATASOURCE_PLUGINS_DIR "/opt/mapnik/plugins" + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* Define to empty if the keyword `volatile' does not work. Warning: valid + code using `volatile' can become incorrect without. Disable with care. */ +/* #undef volatile */ diff --git a/include/coord.hpp b/include/coord.hpp new file mode 100644 index 000000000..a9f0b5682 --- /dev/null +++ b/include/coord.hpp @@ -0,0 +1,131 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details.#include "memory.hpp" + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: coord.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef COORD_HPP +#define COORD_HPP + +#include +#include + +namespace mapnik +{ + template + struct coord { + typedef T type; + }; + + template + struct coord + { + typedef T type; + T x; + T y; + public: + coord() + : x(),y() {} + coord(T x,T y) + : x(x),y(y) {} + template + coord (const coord& rhs) + : x(type(rhs.x)), + y(type(rhs.y)) {} + + template + coord& operator=(const coord& rhs) + { + if ((void*)this==(void*)&rhs) + { + return *this; + } + x=type(rhs.x); + y=type(rhs.y); + return *this; + } + }; + + template + struct coord + { + typedef T type; + T x; + T y; + T z; + public: + coord() + : x(),y(),z() {} + coord(T x,T y,T z) + : x(x),y(y),z(z) {} + template + coord (const coord& rhs) + : x(type(rhs.x)), + y(type(rhs.y)), + z(type(rhs.z)) {} + + template + coord& operator=(const coord& rhs) + { + if ((void*)this==(void*)&rhs) + { + return *this; + } + x=type(rhs.x); + y=type(rhs.y); + z=type(rhs.z); + return *this; + } + }; + + typedef coord coord2d; + typedef coord coord2i; + + + template + inline std::basic_ostream& + operator << (std::basic_ostream& out, + const coord& c); + + template + inline std::basic_ostream& + operator << (std::basic_ostream& out, + const coord& c) + { + std::basic_ostringstream s; + s.copyfmt(out); + s.width(0); + s<<"coord2("< + inline std::basic_ostream& + operator << (std::basic_ostream& out, + const coord& c) + { + std::basic_ostringstream s; + s.copyfmt(out); + s.width(0); + s<<"coord3("< + +namespace mapnik +{ + + template + class coord_array + { + typedef T coord_type; + coord_type* pt_; + const unsigned size_; + public: + coord_array(unsigned size=0) + : pt_(static_cast(size==0?0: ::operator new (sizeof(coord_type)*size))), + size_(size) {} + + coord_array(const coord_array& rhs) + : pt_(static_cast(rhs.size_==0?0: ::operator new (sizeof(coord_type)*rhs.size_))), + size_(rhs.size_) { + memcpy(pt_,rhs.pt_,sizeof(coord_type)*rhs.size_); + } + + ~coord_array() + { + ::operator delete (pt_); + } + + unsigned size() const + { + return size_; + } + + void set(unsigned index,double x,double y) + { + assert(index CoordinateArray; + + class CoordTransform + { + private: + int width; + int height; + double scale_; + Envelope extent; + coord2d center_; + public: + CoordTransform(int width,int height,const Envelope& extent) + :width(width),height(height),extent(extent),center_(extent.center()) + { + double sx=((double)width)/extent.width(); + double sy=((double)height)/extent.height(); + scale_=std::min(sx,sy); + } + + inline double scale() const + { + return scale_; + } + + double forward_x(double x) const + { + return (x-center_.x)*scale_+0.5*width; + } + + double forward_y(double y) const + { + return -(y-center_.y)*scale_+0.5*height; + } + + inline coord2d& forward(coord2d& c) const + { + c.x=(c.x-center_.x)*scale_+0.5*width; + c.y=-(c.y-center_.y)*scale_+0.5*height; + return c; + } + + inline coord2d& backward(coord2d& c) const + { + c.x=(c.x-0.5*width)/scale_+center_.x; + c.y=-(c.y-0.5*height)/scale_+center_.y; + return c; + } + + inline Envelope forward(const Envelope& e) const + { + + double x0=(e.minx()-center_.x)*scale_+0.5*width; + double x1=(e.maxx()-center_.x)*scale_+0.5*width; + + double y0=-(e.miny()-center_.y)*scale_+0.5*height; + double y1=-(e.maxy()-center_.y)*scale_+0.5*height; + + return Envelope(x0,y0,x1,y1); + } + + inline Envelope backward(const Envelope& e) const + { + + double x0=(e.minx()-0.5*width)/scale_+center_.x; + double x1=(e.maxx()-0.5*width)/scale_+center_.x; + + double y0=-(e.miny()-0.5*height)/scale_+center_.y; + double y1=-(e.maxy()-0.5*height)/scale_+center_.y; + + return Envelope(x0,y0,x1,y1); + } + + inline CoordinateArray& forward(CoordinateArray& coords) const + { + for (unsigned i=0;i +#include +#include "ptr.hpp" +#include "ctrans.hpp" +#include "params.hpp" +#include "feature.hpp" +#include "query.hpp" +#include "feature_layer_desc.hpp" + +namespace mapnik +{ + typedef ref_ptr feature_ptr; + struct Featureset + { + virtual Feature* next()=0; + virtual ~Featureset() {}; + }; + + typedef ref_ptr featureset_ptr; + class datasource_exception : public std::exception + { + private: + const std::string message_; + public: + datasource_exception(const std::string& message=std::string()) + :message_(message) {} + + ~datasource_exception() throw() {} + virtual const char* what() const throw() + { + return message_.c_str(); + } + }; + + class datasource + { + public: + enum { + Vector, + Raster + }; + virtual int type() const=0; + virtual featureset_ptr features(const query& q) const=0; + virtual Envelope const& envelope() const=0; + virtual layer_descriptor const& get_descriptor() const=0; + virtual ~datasource() {}; + }; + + typedef std::string datasource_name(); + typedef datasource* create_ds(const Parameters& params); + typedef void destroy_ds(datasource *ds); + + template + struct datasource_delete + { + static void destroy(DATASOURCE* ds) + { + destroy_ds(ds); + } + }; + + typedef ref_ptr datasource_p; + + /////////////////////////////////////////// + #define DATASOURCE_PLUGIN(classname) \ + extern "C" std::string datasource_name() \ + { \ + return classname::name();\ + }\ + extern "C" datasource* create(const Parameters ¶ms) \ + { \ + return new classname(params);\ + }\ + extern "C" void destroy(datasource *ds) \ + { \ + delete ds;\ + }\ + /////////////////////////////////////////// +} +#endif //DATASOURCE_HPP diff --git a/include/datasource_cache.hpp b/include/datasource_cache.hpp new file mode 100644 index 000000000..ca00d82d5 --- /dev/null +++ b/include/datasource_cache.hpp @@ -0,0 +1,49 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: datasource_cache.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef DSFACTORY_HPP +#define DSFACTORY_HPP + +#include "utils.hpp" +#include "ptr.hpp" +#include "params.hpp" +#include "plugin.hpp" +#include "datasource.hpp" +#include + +namespace mapnik +{ + class datasource_cache : public singleton + { + friend class CreateStatic; + private: + datasource_cache(); + ~datasource_cache(); + datasource_cache(const datasource_cache&); + datasource_cache& operator=(const datasource_cache&); + static std::map > plugins_; + static bool registered_; + static bool insert(const std::string& name,const lt_dlhandle module); + public: + static void register_datasources(const std::string& path); + static ref_ptr create(const Parameters& params); + }; +} +#endif //DSFACTORY_HPP diff --git a/include/envelope.hpp b/include/envelope.hpp new file mode 100644 index 000000000..0e94099b1 --- /dev/null +++ b/include/envelope.hpp @@ -0,0 +1,80 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: envelope.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef ENVELOPE_HPP +#define ENVELOPE_HPP + +#include "coord.hpp" + +namespace mapnik +{ + + template class Envelope + { + public: + typedef Envelope EnvelopeType; + private: + T minx_; + T miny_; + T maxx_; + T maxy_; + public: + Envelope(); + Envelope(T minx,T miny,T maxx,T maxy); + Envelope(const coord& c0,const coord& c1); + Envelope(const EnvelopeType& rhs); + T minx() const; + T miny() const; + T maxx() const; + T maxy() const; + T width() const; + T height() const; + void width(T w); + void height(T h); + coord center() const; + void expand_to_include(T x,T y); + void expand_to_include(const coord& c); + void expand_to_include(const EnvelopeType& other); + bool contains(const coord &c) const; + bool contains(T x,T y) const; + bool contains(const EnvelopeType &other) const; + bool intersects(const coord &c) const; + bool intersects(T x,T y) const; + bool intersects(const EnvelopeType &other) const; + EnvelopeType intersect(const EnvelopeType& other) const; + bool operator==(const EnvelopeType &other) const; + void re_center(T cx,T cy); + void init(T x0,T y0,T x1,T y1); + }; + + template + inline std::basic_ostream& + operator << (std::basic_ostream& out, + const Envelope& e) + { + std::basic_ostringstream s; + s.copyfmt(out); + s.width(0); + s<<"Envelope("< class filter_visitor; + template + struct expression + { + virtual value get_value(FeatureT const& feature) const=0; + virtual void accept(filter_visitor& v)=0; + virtual expression* clone() const=0; + virtual std::string to_string() const=0; + virtual ~expression() {} + }; + + template + class literal : public expression + { + public: + literal(int val) + : expression(), + value_(val) {} + literal(double val) + : expression(), + value_(val) {} + literal(std::string const& val) + : expression(), + value_(val) {} + literal(literal const& other) + : expression(), + value_(other.value_) {} + + value get_value(FeatureT const& /*feature*/) const + { + return value_; + } + void accept(filter_visitor& v) + { + v.visit(*this); + } + expression* clone() const + { + return new literal(*this); + } + std::string to_string() const + { + return "'"+value_.to_string()+"'"; + } + ~literal() {} + private: + value value_; + + }; + + + template + class property : public expression + { + public: + property(std::string const& name) + : expression(), + name_(name), + index_(0), + valid_(false) {} + + property(property const& other) + : expression(), + name_(other.name_), + index_(other.index_), + valid_(other.valid_) {} + + value get_value(FeatureT const& feature) const + { + if (valid_) + { + return feature.get_property(index_); + } + else + { + return value(""); + } + } + void accept(filter_visitor& v) + { + v.visit(*this); + } + expression* clone() const + { + return new property(*this); + } + std::string const& name() const + { + return name_; + } + void set_index(size_t index) + { + index_=index; + valid_=true; + } + std::string to_string() const + { + return "["+name_+"]"; + } + ~property() {} + private: + std::string name_; + size_t index_; + bool valid_; + }; +} + +#endif //EXPRESSION_HPP diff --git a/include/factory.hpp b/include/factory.hpp new file mode 100644 index 000000000..5c22da292 --- /dev/null +++ b/include/factory.hpp @@ -0,0 +1,84 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: factory.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef FACTORY_HPP +#define FACTORY_HPP + +#include +#include +#include "utils.hpp" + +namespace mapnik +{ + template + class default_factory_error + { + public: + struct factory_exception : public std::exception + { + const char* what() const throw() + { + return "uknown object type"; + } + }; + static product_type* on_unknown_type(const key_type&) + { + return 0; + } + }; + + template + < + typename product_type, + typename key_type, + typename product_creator=product_type* (*)(), + template class factory_error_policy=default_factory_error + > + class factory : public singleton >, + factory_error_policy + { + private: + typedef std::map product_map; + product_map map_; + public: + + bool register_product(const key_type& key,product_creator creator) + { + return map_.insert(typename product_map::value_type(key,creator)).second; + } + + bool unregister_product(const key_type& key) + { + return map_.erase(key)==1; + } + + product_type* create_object(const key_type& key,const std::string& file) + { + typename product_map::const_iterator pos=map_.find(key); + if (pos!=map_.end()) + { + return (pos->second)(file); + } + return on_unknown_type(key); + } + }; +} +#endif //FACTORY_HPP diff --git a/include/feature.hpp b/include/feature.hpp new file mode 100644 index 000000000..b134876fd --- /dev/null +++ b/include/feature.hpp @@ -0,0 +1,129 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: feature.hpp 40 2005-04-13 20:20:46Z pavlenko $ + +#ifndef FEATURE_HPP +#define FEATURE_HPP + +#include "geometry.hpp" +#include "raster.hpp" +#include "value.hpp" +#include + +namespace mapnik +{ + typedef ref_ptr raster_ptr; + typedef std::vector properties; + + template + struct feature + { + public: + typedef T1 geometry_type; + typedef T2 raster_type; + private: + int id_; + geometry_type geom_; + raster_type raster_; + properties props_; + public: + explicit feature(int id) + : id_(id), + geom_(), + raster_() {} + + feature(int id,const geometry_type& geom) + : id_(id), + geom_(geom), + raster_() {} + + feature(const feature& rhs) + : id_(rhs.id_), + geom_(rhs.geom_), + raster_(rhs.raster_) {} + + feature& operator=(const feature& rhs) + { + feature tmp; + swap(tmp); + return *this; + } + + ~feature() {} + + int id() const + { + return id_; + } + + void set_geometry(geometry_type& geom) + { + geom_=geom; + } + + geometry_type& get_geometry() + { + return geom_; + } + + const raster_type& get_raster() const + { + return raster_; + } + + void add_property(int v) + { + return props_.push_back(value(v)); + } + + void add_property(double v) + { + return props_.push_back(value(v)); + } + + void add_property(std::string const& v) + { + return props_.push_back(value(v)); + } + + value get_property(size_t index) const + { + assert(index < props_.size()); + return props_[index]; + } + + const properties& get_properties() const + { + return props_; + } + + private: + void swap(const feature& rhs) throw() + { + std::swap(id_,rhs.id_); + std::swap(geom_,rhs.geom_); + std::swap(raster_,rhs.raster_); + std::swap(props_,rhs.props_); + } + }; + + typedef feature Feature; + +} +#endif //FEATURE_HPP diff --git a/include/feature_layer_desc.hpp b/include/feature_layer_desc.hpp new file mode 100644 index 000000000..0dc80877b --- /dev/null +++ b/include/feature_layer_desc.hpp @@ -0,0 +1,249 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details.#include "memory.hh" + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef FEATURE_LAYER_DESC_HPP +#define FEATURE_LAYER_DESC_HPP + +//#include "array.hpp" + +#include +#include +#include + +namespace mapnik +{ + + using std::string; + using std::vector; + using std::cout; + using std::cerr; + using std::endl; + + enum { + Integer=1, + Float =2, + Double =3, + String =4, + Geometry=5, + Object=6 + }; + + class attribute_descriptor + { + public: + attribute_descriptor(string const& name,unsigned type, + bool primary_key=false, + int size=-1, + int precision=-1) + : name_(name), + type_(type), + primary_key_(primary_key), + size_(size), + precision_(precision) {} + + attribute_descriptor(attribute_descriptor const& other) + : name_(other.name_), + type_(other.type_), + primary_key_(other.primary_key_), + size_(other.size_), + precision_(other.precision_) {} + + attribute_descriptor& operator=(attribute_descriptor const& other) + { + if (this == &other) + return *this; + name_=other.name_; + type_=other.type_; + primary_key_=other.primary_key_; + size_=other.size_; + precision_=other.precision_; + return *this; + } + string const& get_name() const + { + return name_; + } + unsigned get_type() const + { + return type_; + } + bool is_primary_key() const + { + return primary_key_; + } + int get_size() const + { + return size_; + } + + int get_precision() const + { + return precision_; + } + private: + string name_; + int type_; + bool primary_key_; + int size_; + int precision_; + }; + + template + inline std::basic_ostream& + operator << (std::basic_ostream& out, + attribute_descriptor const& ad) + { + out << "name=" << ad.get_name() << endl; + out << "type=" << ad.get_type() << endl; + out << "size=" << ad.get_size() << endl; + return out; + } + + class layer_descriptor + { + public: + layer_descriptor(string const& name,int srid=-1) + : name_(name), + srid_(srid) {} + + layer_descriptor(layer_descriptor const& other) + : name_(other.name_), + srid_(other.srid_), + desc_ar_(other.desc_ar_) {} + + void set_name(string const& name) + { + name_=name; + } + string const& get_name() const + { + return name_; + } + + void set_srid(int srid) + { + srid_=srid; + } + + int get_srid() const + { + return srid_; + } + + void add_descriptor(attribute_descriptor const& desc) + { + desc_ar_.push_back(desc); + } + + vector const& get_descriptors() const + { + return desc_ar_; + } + vector& get_descriptors() + { + return desc_ar_; + } + private: + string name_; + int srid_; + vector desc_ar_; + }; + + template + inline std::basic_ostream& + operator << (std::basic_ostream& out, + layer_descriptor const& ld) + { + out << "name=" << ld.get_name() << endl; + out << "srid=" << ld.get_srid() << endl; + vector const& desc_ar=ld.get_descriptors(); + vector::const_iterator pos=desc_ar.begin(); + while (pos != desc_ar.end()) + { + out << *pos++ << endl; + + } + return out; + } + /* + bool layer_descriptor_to_wkb(layer_descriptor const& desc,array<>& wkb) + { + //srid + int srid = desc.get_srid(); + wkb.write(&srid,sizeof(int)); + + //attribute descriptors + vector const& desc_ar = desc.get_descriptors(); + vector::const_iterator itr=desc_ar.begin(); + size_t num_desc = desc_ar.size(); + wkb.write(&num_desc,sizeof(int)); + + while (itr != desc_ar.end()) + { + string name = itr->get_name(); + wkb.write(name.c_str(),name.size()+1); + + unsigned type = static_cast(itr->get_type()); + wkb.write(&type,sizeof(unsigned)); + + bool prim_key = itr->is_primary_key(); + wkb.write(&prim_key,sizeof(bool)); + + int size = itr->get_size(); + wkb.write(&size,sizeof(int)); + + ++itr; + } + return true; + } + + bool layer_descriptor_from_wkb(const char* wkb, layer_descriptor &desc) + { + unsigned pos=0; + int srid; + + memcpy(&srid,wkb+pos,sizeof(int)); + desc.set_srid(srid); + pos+=sizeof(int); + + int num_desc; + memcpy(&num_desc,wkb+pos,sizeof(int)); + pos+=sizeof(int); + + for (int i=0;i + +namespace mapnik +{ + typedef rule rule_type; + + class feature_type_style + { + private: + std::vector rules_; + public: + feature_type_style() {} + + feature_type_style(const feature_type_style& rhs) + : rules_(rhs.rules_) {} + + feature_type_style& operator=(const feature_type_style& rhs) + { + if (this == &rhs) return *this; + rules_=rhs.rules_; + return *this; + } + + void add_rule(const rule_type& rule) + { + rules_.push_back(rule); + } + const std::vector& rules() const + { + return rules_; + } + + ~feature_type_style() {} + }; +} + +#endif //FEATURE_TYPE_STYLE diff --git a/include/fill.hpp b/include/fill.hpp new file mode 100644 index 000000000..20310c765 --- /dev/null +++ b/include/fill.hpp @@ -0,0 +1,32 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef FILL_HPP +#define FILL_HPP + +namespace mapnik +{ + class fill + { + + }; +} + +#endif //FILL_HPP diff --git a/include/filter.hpp b/include/filter.hpp new file mode 100644 index 000000000..108c49929 --- /dev/null +++ b/include/filter.hpp @@ -0,0 +1,65 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef FILTER_HPP +#define FILTER_HPP + +#include "filter_visitor.hpp" +#include "feature.hpp" +namespace mapnik +{ + typedef ref_ptr > filter_ptr; + + template class filter_visitor; + template + struct filter + { + virtual bool pass(const FeatureT& feature) const=0; + virtual filter* clone() const=0; + virtual void accept(filter_visitor& v) = 0; + virtual std::string to_string() const=0; + virtual ~filter() {} + }; + + + template + struct null_filter : public filter + { + + bool pass (const FeatureT&) const + { + return true; + } + + filter* clone() const + { + return new null_filter; + } + std::string to_string() const + { + return "true"; + } + void accept(filter_visitor&) {} + virtual ~null_filter() {} + }; + +} + +#endif //FILTER_HPP diff --git a/include/filter_expression.hpp b/include/filter_expression.hpp new file mode 100644 index 000000000..46e2b721d --- /dev/null +++ b/include/filter_expression.hpp @@ -0,0 +1,61 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef FILTER_TO_STRING_HPP +#define FILTER_TO_STRING_HPP + +#include "filter.hpp" +#include "expression.hpp" +#include + +namespace mapnik +{ + template + class filter_to_string : public filter_visitor + { + private: + std::string text_; + public: + filter_to_string() {} + void visit(filter& /*filter*/) + { + //not interested + } + void visit(expression& exp) + { + property* pf; + if ((pf = dynamic_cast*>(&exp))) + { + names_.insert(pf->name()); + } + } + std::string const& text() const + { + return text_; + } + + virtual ~filter_to_string() {} + private: + filter_to_string(filter_to_string const&); + filter_to_string& operator=(filter_to_string const&); + }; +} + +#endif //FILTER_TO_STRING diff --git a/include/filter_factory.hpp b/include/filter_factory.hpp new file mode 100644 index 000000000..cd0c09a6d --- /dev/null +++ b/include/filter_factory.hpp @@ -0,0 +1,52 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#include "filter_parser.hpp" + +using std::string; + +namespace mapnik +{ + template + class filter_factory + { + public: + filter_factory() {} + filter_ptr compile(string const& str) const + { + stack > > filters; + stack > > exps; + filter_grammar grammar(filters,exps); + char const *text = str.c_str(); + parse_info<> info = parse(text,text+strlen(text),grammar,space_p); + if (info.full && !filters.empty()) + { + cout<<"success parsing filter expression:\n"; + cout<to_string()<<"\n"; + return filters.top(); + } + else + { + cout << "failed at :" << info.stop << "\n"; + return filter_ptr(new null_filter()); + } + } + }; +} diff --git a/include/filter_parser.hpp b/include/filter_parser.hpp new file mode 100644 index 000000000..a37e17713 --- /dev/null +++ b/include/filter_parser.hpp @@ -0,0 +1,440 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef FILTER_PARSER_HPP +#define FILTER_PARSER_HPP + +#include +#include +#include +#include +#include + +#include "value.hpp" +#include "comparison.hpp" +#include "expression.hpp" +#include "filter.hpp" +#include "regex_filter.hpp" + +#include +#include + +using namespace boost::spirit; +using std::string; +using std::cout; +using std::cerr; +using std::stack; + +namespace mapnik +{ + template + struct push_integer + { + push_integer(stack > >& exprs) + : exprs_(exprs) {} + + void operator() (int val) const + { + exprs_.push(ref_ptr >(new literal(val))); + } + stack > >& exprs_; + }; + + template + struct push_real + { + push_real(stack > >& exprs) + : exprs_(exprs) {} + void operator() (double val) const + { + exprs_.push(ref_ptr >(new literal(val))); + } + stack > >& exprs_; + }; + + template + struct push_string + { + push_string(stack > >& exprs) + : exprs_(exprs) {} + + template + void operator() (Iter start,Iter end) const + { + string str(start,end); + char quote='\\'; + string::size_type idx; + idx = str.find(quote); + while (idx != string::npos) + { + str.erase(idx,1); + idx = str.find(quote); + } + cout << "string(\""< >(new literal(str))); + } + stack > >& exprs_; + }; + + template + struct push_property + { + push_property(stack > >& exprs) + : exprs_(exprs) {} + + template + void operator() (Iter start,Iter end) const + { + string str(start,end); + exprs_.push(ref_ptr >(new property(str))); + } + stack > >& exprs_; + }; + + template + struct compose_expression + { + compose_expression(stack > >& exprs) + : exprs_(exprs) {} + + template + void operator() (Iter,Iter) const + { + if (exprs_.size()>=2) + { + ref_ptr > right = exprs_.top(); + exprs_.pop(); + ref_ptr > left = exprs_.top(); + exprs_.pop(); + if (left && right) + { + exprs_.push(ref_ptr >(new math_expr_b(*left,*right))); + } + } + } + stack > >& exprs_; + }; + + template + struct compose_regex + { + compose_regex(stack > >& filters, + stack > >& exprs) + : filters_(filters),exprs_(exprs) {} + + template + void operator() (Iter start,Iter end) const + { + if (exprs_.size()>=1) + { + ref_ptr > exp = exprs_.top(); + exprs_.pop(); + if (exp) + { + std::string pattern(start,end); + try + { + filters_.push(ref_ptr >(new regex_filter(*exp,pattern))); + } + catch (boost::regex_error& ex) + { + cerr< > >& filters_; + stack > >& exprs_; + }; + + + template + struct compose_filter + { + compose_filter(stack > >& filters, + stack > >& exprs) + : filters_(filters),exprs_(exprs) {} + + template + void operator() (Iter,Iter) const + { + if (exprs_.size()>=2) + { + ref_ptr > right = exprs_.top(); + exprs_.pop(); + ref_ptr > left = exprs_.top(); + exprs_.pop(); + if (left && right) + { + filters_.push(ref_ptr >(new compare_filter(*left,*right))); + } + } + } + stack > >& filters_; + stack > >& exprs_; + }; + + template + struct compose_and_filter + { + compose_and_filter(stack > >& filters) + : filters_(filters) {} + + template + void operator() (Iter,Iter) const + { + if (filters_.size()>=2) + { + ref_ptr > right = filters_.top(); + filters_.pop(); + ref_ptr > left = filters_.top(); + filters_.pop(); + if (left && right) + { + filters_.push(ref_ptr >(new logical_and(*left,*right))); + } + } + } + stack > >& filters_; + }; + + template + struct compose_or_filter + { + compose_or_filter(stack > >& filters) + : filters_(filters) {} + + template + void operator() (Iter,Iter) const + { + if (filters_.size()>=2) + { + ref_ptr > right = filters_.top(); + filters_.pop(); + ref_ptr > left = filters_.top(); + filters_.pop(); + if (left && right) + { + filters_.push(ref_ptr >(new logical_or(*left,*right))); + } + } + } + stack > >& filters_; + }; + + template + struct compose_not_filter + { + compose_not_filter(stack > >& filters) + : filters_(filters) {} + + template + void operator() (Iter,Iter) const + { + if (filters_.size()>=1) + { + ref_ptr > filter_ = filters_.top(); + filters_.pop(); + if (filter_) + { + filters_.push(ref_ptr >(new logical_not(*filter_))); + } + } + } + stack > >& filters_; + }; + + template + struct filter_grammar : public grammar > + { + filter_grammar(stack > >& filters_, + stack > >& exprs_) + : filters(filters_),exprs(exprs_) {} + + template + struct definition + { + definition(filter_grammar const& self) + { + typedef boost::spirit::chset chset_t; + + func1_op = "sqrt","sin","cos"; + func2_op = "min","max"; + spatial_op = "Equals","Disjoint","Touches","Within","Overlaps", + "Crosses","Intersects","Contains","DWithin","Beyond","BBOX"; + + chset_t BaseChar (L"\x41-\x5A\x61-\x7A\xC0-\xD6\xD8-\xF6\xF8-\xFF\x100-\x131\x134-\x13E" + L"\x141-\x148\x14A-\x17E\x180-\x1C3\x1CD-\x1F0\x1F4-\x1F5\x1FA-\x217" + L"\x250-\x2A8\x2BB-\x2C1\x386\x388-\x38A\x38C\x38E-\x3A1\x3A3-\x3CE" + L"\x3D0-\x3D6\x3DA\x3DC\x3DE\x3E0\x3E2-\x3F3\x401-\x40C\x40E-\x44F" + L"\x451-\x45C\x45E-\x481\x490-\x4C4\x4C7-\x4C8\x4CB-\x4CC\x4D0-\x4EB" + L"\x4EE-\x4F5\x4F8-\x4F9\x531-\x556\x559\x561-\x586\x5D0-\x5EA" + L"\x5F0-\x5F2\x621-\x63A\x641-\x64A\x671-\x6B7\x6BA-\x6BE\x6C0-\x6CE" + L"\x6D0-\x6D3\x6D5\x6E5-\x6E6\x905-\x939\x93D\x958-\x961\x985-\x98C" + L"\x98F-\x990\x993-\x9A8\x9AA-\x9B0\x9B2\x9B6-\x9B9\x9DC-\x9DD" + L"\x9DF-\x9E1\x9F0-\x9F1\xA05-\xA0A\xA0F-\xA10\xA13-\xA28\xA2A-\xA30" + L"\xA32-\xA33\xA35-\xA36\xA38-\xA39\xA59-\xA5C\xA5E\xA72-\xA74" + L"\xA85-\xA8B\xA8D\xA8F-\xA91\xA93-\xAA8\xAAA-\xAB0\xAB2-\xAB3" + L"\xAB5-\xAB9\xABD\xAE0\xB05-\xB0C\xB0F-\xB10\xB13-\xB28\xB2A-\xB30" + L"\xB32-\xB33\xB36-\xB39\xB3D\xB5C-\xB5D\xB5F-\xB61\xB85-\xB8A" + L"\xB8E-\xB90\xB92-\xB95\xB99-\xB9A\xB9C\xB9E-\xB9F\xBA3-\xBA4" + L"\xBA8-\xBAA\xBAE-\xBB5\xBB7-\xBB9\xC05-\xC0C\xC0E-\xC10\xC12-\xC28" + L"\xC2A-\xC33\xC35-\xC39\xC60-\xC61\xC85-\xC8C\xC8E-\xC90\xC92-\xCA8" + L"\xCAA-\xCB3\xCB5-\xCB9\xCDE\xCE0-\xCE1\xD05-\xD0C\xD0E-\xD10" + L"\xD12-\xD28\xD2A-\xD39\xD60-\xD61\xE01-\xE2E\xE30\xE32-\xE33" + L"\xE40-\xE45\xE81-\xE82\xE84\xE87-\xE88\xE8A\xE8D\xE94-\xE97" + L"\xE99-\xE9F\xEA1-\xEA3\xEA5\xEA7\xEAA-\xEAB\xEAD-\xEAE\xEB0" + L"\xEB2-\xEB3\xEBD\xEC0-\xEC4\xF40-\xF47\xF49-\xF69\x10A0-\x10C5" + L"\x10D0-\x10F6\x1100\x1102-\x1103\x1105-\x1107\x1109\x110B-\x110C" + L"\x110E-\x1112\x113C\x113E\x1140\x114C\x114E\x1150\x1154-\x1155" + L"\x1159\x115F-\x1161\x1163\x1165\x1167\x1169\x116D-\x116E" + L"\x1172-\x1173\x1175\x119E\x11A8\x11AB\x11AE-\x11AF\x11B7-\x11B8" + L"\x11BA\x11BC-\x11C2\x11EB\x11F0\x11F9\x1E00-\x1E9B\x1EA0-\x1EF9" + L"\x1F00-\x1F15\x1F18-\x1F1D\x1F20-\x1F45\x1F48-\x1F4D\x1F50-\x1F57" + L"\x1F59\x1F5B\x1F5D\x1F5F-\x1F7D\x1F80-\x1FB4\x1FB6-\x1FBC\x1FBE" + L"\x1FC2-\x1FC4\x1FC6-\x1FCC\x1FD0-\x1FD3\x1FD6-\x1FDB\x1FE0-\x1FEC" + L"\x1FF2-\x1FF4\x1FF6-\x1FFC\x2126\x212A-\x212B\x212E\x2180-\x2182" + L"\x3041-\x3094\x30A1-\x30FA\x3105-\x312C\xAC00-\xD7A3"); + + chset_t Ideographic(L"\x4E00-\x9FA5\x3007\x3021-\x3029"); + chset_t Letter = BaseChar | Ideographic; + + chset_t CombiningChar(L"\x0300-\x0345\x0360-\x0361\x0483-\x0486\x0591-\x05A1\x05A3-\x05B9" + L"\x05BB-\x05BD\x05BF\x05C1-\x05C2\x05C4\x064B-\x0652\x0670" + L"\x06D6-\x06DC\x06DD-\x06DF\x06E0-\x06E4\x06E7-\x06E8\x06EA-\x06ED" + L"\x0901-\x0903\x093C\x093E-\x094C\x094D\x0951-\x0954\x0962-\x0963" + L"\x0981-\x0983\x09BC\x09BE\x09BF\x09C0-\x09C4\x09C7-\x09C8" + L"\x09CB-\x09CD\x09D7\x09E2-\x09E3\x0A02\x0A3C\x0A3E\x0A3F" + L"\x0A40-\x0A42\x0A47-\x0A48\x0A4B-\x0A4D\x0A70-\x0A71\x0A81-\x0A83" + L"\x0ABC\x0ABE-\x0AC5\x0AC7-\x0AC9\x0ACB-\x0ACD\x0B01-\x0B03\x0B3C" + L"\x0B3E-\x0B43\x0B47-\x0B48\x0B4B-\x0B4D\x0B56-\x0B57\x0B82-\x0B83" + L"\x0BBE-\x0BC2\x0BC6-\x0BC8\x0BCA-\x0BCD\x0BD7\x0C01-\x0C03" + L"\x0C3E-\x0C44\x0C46-\x0C48\x0C4A-\x0C4D\x0C55-\x0C56\x0C82-\x0C83" + L"\x0CBE-\x0CC4\x0CC6-\x0CC8\x0CCA-\x0CCD\x0CD5-\x0CD6\x0D02-\x0D03" + L"\x0D3E-\x0D43\x0D46-\x0D48\x0D4A-\x0D4D\x0D57\x0E31\x0E34-\x0E3A" + L"\x0E47-\x0E4E\x0EB1\x0EB4-\x0EB9\x0EBB-\x0EBC\x0EC8-\x0ECD" + L"\x0F18-\x0F19\x0F35\x0F37\x0F39\x0F3E\x0F3F\x0F71-\x0F84" + L"\x0F86-\x0F8B\x0F90-\x0F95\x0F97\x0F99-\x0FAD\x0FB1-\x0FB7\x0FB9" + L"\x20D0-\x20DC\x20E1\x302A-\x302F\x3099\x309A"); + + chset_t Digit(L"\x0030-\x0039\x0660-\x0669\x06F0-\x06F9\x0966-\x096F\x09E6-\x09EF" + L"\x0A66-\x0A6F\x0AE6-\x0AEF\x0B66-\x0B6F\x0BE7-\x0BEF\x0C66-\x0C6F" + L"\x0CE6-\x0CEF\x0D66-\x0D6F\x0E50-\x0E59\x0ED0-\x0ED9\x0F20-\x0F29"); + + chset_t Extender(L"\x00B7\x02D0\x02D1\x0387\x0640\x0E46\x0EC6\x3005\x3031-\x3035" + L"\x309D-\x309E\x30FC-\x30FE"); + + chset_t NameChar = + Letter + | Digit + | L'.' + | L'-' + | L'_' + | L':' + | CombiningChar + | Extender; + + number = strict_real_p [push_real(self.exprs)] + | int_p [push_integer(self.exprs)]; + + string_ = confix_p(L'\'',(*lex_escape_ch_p) + [push_string(self.exprs)], + '\''); + + property = L'[' >> ( (Letter | L'_' | L':') + >> *NameChar )[push_property(self.exprs)] >> L']'; + + literal = number | string_ | property; + + function = literal | ( func1_op >> L'('>> literal >> L')') | + (func2_op >> L'(' >> literal >> L','>> literal >> L')'); + + factor = function + | L'(' >> or_expr >> L')' + | ( L'-' >> factor) + ; + term = factor + >> *((L'*' >> factor) [compose_expression >(self.exprs)] + | (L'/' >> factor) [compose_expression >(self.exprs)]); + + expression = term >> *((L'+' >> term) [compose_expression >(self.exprs)] + | (L'-' >> term) [compose_expression >(self.exprs)]); + + regex = str_p(L".match")>>L'('>>confix_p(L'\'',(*lex_escape_ch_p) + [compose_regex(self.filters,self.exprs)], + L'\'') >>L')'; + + relation = expression + >> *((L">=" >> expression) + [compose_filter >(self.filters,self.exprs)] + | (L'>' >> expression) + [compose_filter >(self.filters,self.exprs)] + | (L'<' >> expression) + [compose_filter >(self.filters,self.exprs)] + | (L"<=" >> expression) + [compose_filter >(self.filters,self.exprs)] + | regex ); + + equation = relation >> *( ( L'=' >> relation) + [compose_filter >(self.filters,self.exprs)] + | ( L"<>" >> relation) + [compose_filter >(self.filters,self.exprs)]); + + not_expr = equation | *(str_p(L"not") >> equation)[compose_not_filter(self.filters)]; + + and_expr = not_expr >> *(L"and" >> not_expr)[compose_and_filter(self.filters)]; + + or_expr = and_expr >> *(L"or" >> and_expr)[compose_or_filter(self.filters)]; + + filter_statement = or_expr; + } + + boost::spirit::rule const& start() const + { + return filter_statement; + } + + boost::spirit::rule factor; + boost::spirit::rule term; + boost::spirit::rule expression; + boost::spirit::rule relation; + boost::spirit::rule equation; + boost::spirit::rule not_expr; + boost::spirit::rule and_expr; + boost::spirit::rule or_expr; + + boost::spirit::rule filter_statement; + boost::spirit::rule literal; + boost::spirit::rule number; + boost::spirit::rule string_; + boost::spirit::rule property; + boost::spirit::rule function; + boost::spirit::rule regex; + symbols func1_op; + symbols func2_op; + symbols spatial_op; + }; + stack > >& filters; + stack > >& exprs; + }; +} + +#endif //FILTER_PARSER_HPP diff --git a/include/filter_parser_ast.hpp b/include/filter_parser_ast.hpp new file mode 100644 index 000000000..0a2287744 --- /dev/null +++ b/include/filter_parser_ast.hpp @@ -0,0 +1,261 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef FILTER_PARSER_AST_HPP +#define FILTER_PARSER_AST_HPP + +#include +#include + +#include + +using namespace std; +using namespace boost::spirit; + +namespace mapnik +{ + struct filter_grammar_ast : public grammar + { + + static const int integerID = 1; + static const int realID = 2; + static const int stringID = 3; + static const int propertyID = 4; + static const int factorID = 5; + static const int termID = 6; + static const int expressionID = 7; + static const int relationID = 8; + static const int equationID = 9; + static const int and_exprID = 10; + static const int or_exprID = 11; + + template + struct definition + { + + definition(filter_grammar_ast const& /*self*/) + { + real = leaf_node_d[strict_real_p]; + integer = leaf_node_d[int_p]; + number = real | integer; + + string_ = inner_node_d['\''>> leaf_node_d[( (alpha_p | '_') >> + * (alnum_p | '_' ))] >> '\'']; + + property = inner_node_d['[' >> leaf_node_d[ ( (alpha_p | '_') >> * (alnum_p | '_' )) ] >> ']']; + + literal = number | string_ | property; + + factor = literal + | (root_node_d[str_p("not")] >> literal) + | inner_node_d[ch_p('(') >> or_expr >> ch_p(')') ] + | (root_node_d[ch_p('-')] >> factor) + ; + + term = factor + >> *((root_node_d[ch_p('*')] >> factor) | (root_node_d[ch_p('/')] >> factor)); + + expression = term >> *((root_node_d[ch_p('+')] >> term) | (root_node_d[ch_p('-')] >> term)); + relation = expression >> *((root_node_d[str_p(">=")] >> expression) + | (root_node_d[ch_p('>')] >> expression) + | (root_node_d[ch_p('<')] >> expression) + | (root_node_d[str_p("<=")] >> expression)); + + equation = relation >> *( (root_node_d[ch_p('=')] >> relation) + | (root_node_d[str_p("<>")] >> relation)); + and_expr = equation >> *(root_node_d[str_p("and")] >> equation); + or_expr = and_expr >> *(root_node_d[str_p("or")] >> and_expr); + + //spatial_op = str_p("Equals") | "Disjoint" | "Touches" | "Within" + // | "Overlaps" | "Crosses" | "Intersects" | "Contains" | "DWithin" | "Beyond" | "BBOX"; + + filter_statement = or_expr; + } + + rule const& start() const + { + return filter_statement; + } + + rule, parser_tag > factor; + rule, parser_tag > term; + rule, parser_tag > expression; + rule, parser_tag > relation; + rule, parser_tag > equation; + + rule, parser_tag > and_expr; + rule, parser_tag > or_expr; + + rule filter_statement; + rule literal,number; + + rule, parser_tag > integer; + rule, parser_tag > real; + rule, parser_tag > string_; + rule, parser_tag > property; + + + //rule spatial_op; + + }; + + }; + + class node_data + { + public: + enum { + Unknown=0, + Integer=1, + Real =2, + String =3, + Property=4 + }; + node_data() + : type_(Unknown) {} + + node_data(int type) + : type_(type) {} + + node_data(node_data const& other) + : type_(other.type_) {} + + node_data& operator=(node_data const& other) + { + if (this==&other) + return *this; + type_=other.type_; + return *this; + } + ~node_data() {} + private: + int type_; + }; + + typedef char const* iterator_t; + typedef node_val_data_factory factory_t; + typedef tree_match::tree_iterator iter_t; + + void process_node(iter_t const&,string&); + + void walk_ast_tree(tree_parse_info info,string& text) + { + process_node(info.trees.begin(),text); + } + + void process_node(iter_t const& i,string& text) + { + //cout << "In eval_expression. i->value = " << + // string(i->value.begin(), i->value.end()) << + // " i->children.size() = " << i->children.size() << endl; + //std::cout<value.id() == filter_grammar_ast::integerID) + { + assert(i->children.size()==0); + string integer(i->value.begin(), i->value.end()); + text+= integer; + } + else if (i->value.id() == filter_grammar_ast::realID) + { + assert(i->children.size()==0); + string real(i->value.begin(), i->value.end()); + text += real; + } + else if (i->value.id() == filter_grammar_ast::stringID) + { + assert(i->children.size()==0); + string str(i->value.begin(), i->value.end()); + text += str; + } + else if (i->value.id() == filter_grammar_ast::propertyID) + { + assert(i->children.size()==0); + string property_name(i->value.begin(), i->value.end()); + text += property_name; + } + else if (i->value.id() == filter_grammar_ast::expressionID) + { + assert(i->children.size() == 2); + assert(!i->children.begin()->value.is_root()); + process_node(i->children.begin(),text); + text += string(i->value.begin(), i->value.end()); + process_node(i->children.begin()+1,text); + + text +="\n"; + } + else if (i->value.id() == filter_grammar_ast::termID) + { + assert(i->children.size() == 2); + assert(!i->children.begin()->value.is_root()); + process_node(i->children.begin(),text); + text += string(i->value.begin(), i->value.end()); + process_node(i->children.begin()+1,text); + + text +="\n"; + + } + else if (i->value.id() == filter_grammar_ast::relationID) + { + assert(i->children.size() == 2); + assert(!i->children.begin()->value.is_root()); + process_node(i->children.begin(),text); + text += string(i->value.begin(), i->value.end()); + process_node(i->children.begin()+1,text); + + text +="\n"; + + } + else if (i->value.id() == filter_grammar_ast::equationID) + { + assert(i->children.size() == 2); + assert(!i->children.begin()->value.is_root()); + process_node(i->children.begin(),text); + text += string(i->value.begin(), i->value.end()); + process_node(i->children.begin()+1,text); + + text +="\n"; + } + else if (i->value.id() == filter_grammar_ast::and_exprID) + { + assert(i->children.size() == 2); + assert(!i->children.begin()->value.is_root()); + process_node(i->children.begin(),text); + text += string(i->value.begin(), i->value.end()); + process_node(i->children.begin()+1,text); + + text +="\n"; + } + else if (i->value.id() == filter_grammar_ast::or_exprID) + { + assert(i->children.size() == 2); + assert(!i->children.begin()->value.is_root()); + + process_node(i->children.begin(),text); + text += string(i->value.begin(), i->value.end()); + process_node(i->children.begin()+1,text); + + text +="\n"; + + } + } +} + +#endif //FILTER_PARSER_AST_HPP diff --git a/include/filter_visitor.hpp b/include/filter_visitor.hpp new file mode 100644 index 000000000..b655215d1 --- /dev/null +++ b/include/filter_visitor.hpp @@ -0,0 +1,38 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef FILTER_VISITOR_HPP +#define FILTER_VISITOR_HPP + +#include "filter.hpp" +#include "expression.hpp" + +namespace mapnik +{ + template class filter; + template class expression; + template + struct filter_visitor + { + virtual void visit(filter& filter)=0; + virtual void visit(expression&)=0; + virtual ~filter_visitor() {} + }; +} + +#endif //FILTER_VISITOR_HPP diff --git a/include/gamma.hpp b/include/gamma.hpp new file mode 100644 index 000000000..9fab5111e --- /dev/null +++ b/include/gamma.hpp @@ -0,0 +1,47 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: gamma.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef GAMMA_HPP +#define GAMMA_HPP + +namespace mapnik +{ + struct gamma + { + unsigned char g2l[256]; + unsigned char l2g[256]; + gamma(double gamma=2.0) + { + int result; + for (int i=0;i< 256;i++) + { + result=(int)(pow(i/255.0,gamma) * 255.0 + 0.5); + g2l[i]=(unsigned short)result; + } + for (int i = 0; i < 256; i++) + { + result = (int)(pow(i/255.0, 1/gamma) * 255.0 + 0.5); + l2g[i] = (unsigned char)result; + } + } + }; +} + +#endif //GAMMA_HPP diff --git a/include/geom_util.hpp b/include/geom_util.hpp new file mode 100644 index 000000000..a686a9103 --- /dev/null +++ b/include/geom_util.hpp @@ -0,0 +1,227 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: geom_util.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef GEOM_UTIL_HPP +#define GEOM_UTIL_HPP + +#include "geometry.hpp" +#include + +namespace mapnik +{ + + template + bool clip_test(T p,T q,double& tmin,double& tmax) + { + double r; + bool result=true; + if (p<0.0) + { + r=q/p; + if (r>tmax) result=false; + else if (r>tmin) tmin=r; + } + else if (p>0.0) + { + r=q/p; + if (r + bool clip_line(T& x0,T& y0,T& x1,T& y1,const Image* image) + { + double tmin=0.0; + double tmax=1.0; + double dx=x1-x0; + if (clip_test(-dx,x0,tmin,tmax)) + { + if (clip_test(dx,image->width()-x0,tmin,tmax)) + { + double dy=y1-y0; + if (clip_test(-dy,y0,tmin,tmax)) + { + if (clip_test(dy,image->height()-y0,tmin,tmax)) + { + if (tmax<1.0) + { + x1=static_cast(x0+tmax*dx); + y1=static_cast(y0+tmax*dy); + } + if (tmin>0.0) + { + x0+=static_cast(tmin*dx); + y0+=static_cast(tmin*dy); + } + return true; + } + } + } + } + return false; + } + + template + inline bool point_inside_path(Iter start,Iter end,double x,double y) + { + bool inside=false; + double x0=start->x; + double y0=start->y; + double x1,y1; + while (++start!=end) + { + if (start->cmd == SEG_MOVETO) + { + x0=start->x; + y0=start->y; + continue; + } + x1=start->x; + y1=start->y; + if ((((y1 <= y) && (y < y0)) || + ((y0 <= y) && (y < y1))) && + ( x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1)) + inside=!inside; + x0=x1; + y0=y1; + } + return inside; + } + +#define TOL 0.00001 + +/* + (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) + s = ----------------------------- + L^2 +*/ + + inline bool point_in_circle(double x,double y,double cx,double cy,double r) + { + double dx = x - cx; + double dy = y - cy; + double d2 = dx * dx + dy * dy; + return (d2 <= r * r); + } + + inline bool point_on_segment(double x,double y,double x0,double y0,double x1,double y1) + { + double dx = x1 - x0; + double dy = y1 - y0; + if ( fabs(dx) > TOL || fabs(dy) > TOL ) + { + double s = (y0 - y) * dx - (x0 - x) * dy; + return ( fabs (s) < TOL ) ; + } + return false; + } + + inline bool point_on_segment2(double x,double y,double x0,double y0,double x1,double y1) + { + double d = sqrt ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); + double d0 = sqrt ((x0 - x) * (x0 - x) + (y0 - y) * (y0 - y)); + double d1 = sqrt ((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)); + double d2 = d0 + d1; + return ( d2 - d < 0.01); + } + +#undef TOL + + inline bool point_on_path(double x,double y,const geometry& geom) + { + bool on_path=false; + if (geom.num_points()>1) + { + geometry::path_iterator itr=geom.begin(); + geometry::path_iterator end=geom.end(); + + double x0=itr->x; + double y0=itr->y; + + while (++itr!=end) + { + if (itr->cmd == SEG_MOVETO) + { + x0=itr->x; + y0=itr->y; + continue; + } + double x1=itr->x; + double y1=itr->y; + + on_path = point_on_segment(x,y,x0,y0,x1,y1); + if (on_path) + break; + + x0=itr->x; + y0=itr->y; + } + } + return on_path; + } + + inline bool point_on_points (double x,double y,const geometry_type& geom) + { + geometry::path_iterator itr=geom.begin(); + geometry::path_iterator end=geom.end(); + while (itr!=end) + { + double dx = x - itr->x; + double dy = y - itr->y; + double d = sqrt(dx*dx+dy*dy); + + if (d < 0.02) + { + std::cout<<"d="<x="<x<<" itr->y="<y< box_; + explicit filter_in_box(const Envelope& box) + : box_(box) {} + + bool pass(const Envelope& extent) const + { + return extent.intersects(box_); + } + }; + + struct filter_at_point + { + coord2d pt_; + explicit filter_at_point(const coord2d& pt) + : pt_(pt) {} + bool pass(const Envelope& extent) const + { + return extent.contains(pt_); + } + }; + +} + +#endif //GEOM_UTIL_HPP diff --git a/include/geometry.hpp b/include/geometry.hpp new file mode 100644 index 000000000..fb4caaeb6 --- /dev/null +++ b/include/geometry.hpp @@ -0,0 +1,256 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: geometry.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef GEOMETRY_HPP +#define GEOMETRY_HPP + +#include "vertex_vector.hpp" +#include "vertex_transform.hpp" +#include "ctrans.hpp" +#include "ptr.hpp" + +namespace mapnik +{ + enum { + Point = 1, + LineString = 2, + Polygon = 3, + }; + + template class Container=vertex_vector> + class geometry + { + public: + typedef T vertex_type; + typedef typename vertex_type::type value_type; + typedef Container container_type; + private: + int srid_; + mutable unsigned itr_; + protected: + container_type cont_; + public: + geometry (int srid=-1) + : srid_(srid), + itr_(0), + cont_() {} + + virtual int type() const=0; + + virtual bool hit_test(value_type x,value_type y) const=0; + + int srid() const + { + return srid_; + } + + void move_to(value_type x,value_type y) + { + cont_.push_back(x,y,SEG_MOVETO); + } + + void line_to(value_type x,value_type y) + { + cont_.push_back(x,y,SEG_LINETO); + } + + template + class path_iterator + { + typedef vertex vertex_type; + const container_type* cont_; + unsigned pos_; + unsigned cmd_; + vertex_type vertex_; + + private: + + void advance () + { + if (pos_ < cont_->size()) + { + value_type x,y; + vertex_.cmd=cont_->get_vertex(pos_,&x,&y); + vertex_.x=Transform::apply(x); + vertex_.y=Transform::apply(y); + } + else + { + vertex_.cmd=SEG_END; + vertex_.x=0; + vertex_.y=0; + } + ++pos_; + } + + public: + + path_iterator() + : cont_(0), + pos_(0), + cmd_(SEG_END), + vertex_(0,0,cmd_) {} + + explicit path_iterator(const container_type& cont) + : cont_(&cont), + pos_(0), + cmd_(SEG_MOVETO), + vertex_(0,0,cmd_) + { + advance(); + } + + path_iterator& operator++() + { + advance(); + return *this; + } + + const vertex_type& operator*() const + { + return vertex_; + } + + const vertex_type* operator->() const + { + return &vertex_; + } + + bool operator !=(const path_iterator& itr) + { + return vertex_.cmd !=itr.vertex_.cmd; + } + }; + + template + path_iterator begin() const + { + return path_iterator(cont_); + } + + template + path_iterator end() const + { + return path_iterator(); + } + + void transform(const mapnik::CoordTransform& t) + { + for (unsigned pos=0;pos class Container=vertex_vector> + class point : public geometry + { + typedef typename geometry::value_type value_type; + using geometry::cont_; + public: + point(int srid) + : geometry(srid) + {} + + int type() const + { + return Point; + } + bool hit_test(value_type x,value_type y) const + { + return point_on_points(x,y,*this); + } + }; + + template class Container=vertex_vector> + class polygon : public geometry + { + typedef geometry geometry_base; + typedef typename geometry_base::value_type value_type; + + public: + polygon(int srid) + : geometry_base(srid) + {} + + int type() const + { + return Polygon; + } + + bool hit_test(value_type x,value_type y) const + { + typedef typename geometry_base::template path_iterator path_iterator; + path_iterator start = geometry_base::template begin(); + path_iterator end = geometry_base::template end(); + return point_inside_path(start,end,x,y); + } + }; + + template class Container=vertex_vector> + class line_string : public geometry + { + typedef typename geometry::value_type value_type; + public: + line_string(int srid) + : geometry(srid) + {} + + int type() const + { + return LineString; + } + + bool hit_test(value_type x,value_type y) const + { + return point_on_path(x,y,*this); + } + }; + + typedef point point_impl; + typedef line_string line_string_impl; + typedef polygon polygon_impl; + + typedef geometry geometry_type; + typedef ref_ptr geometry_ptr; +} + +#endif //GEOMETRY_HPP diff --git a/include/graphics.hpp b/include/graphics.hpp new file mode 100644 index 000000000..0c98a54c3 --- /dev/null +++ b/include/graphics.hpp @@ -0,0 +1,119 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: graphics.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef GRAPHICS_HPP +#define GRAPHICS_HPP + +#include +#include +#include +#include "style.hpp" +#include "gamma.hpp" +#include "image_data.hpp" + +namespace mapnik +{ + class Image32 + { + private: + unsigned width_; + unsigned height_; + Color background_; + ImageData32 data_; + static gamma gammaTable_; + public: + Image32(int width,int height); + Image32(const Image32& rhs); + ~Image32(); + static void setGamma(double gamma); + void setBackground(const Color& background); + const Color& getBackground() const; + void set_rectangle(unsigned x,unsigned y,const ImageData32& data); + const ImageData32& data() const; + inline ImageData32& data() { + return data_; + } + inline const unsigned char* raw_data() const + { + return data_.getBytes(); + } + + inline unsigned char* raw_data() + { + return data_.getBytes(); + } + + void saveToFile(const std::string& file,const std::string& format="auto"); + private: + + inline bool checkBounds(unsigned x,unsigned y) const + { + return ( x < width_ && y < height_); + } + + public: + inline void setPixel(int x,int y,unsigned int rgba) + { + if (checkBounds(x,y)) + { + data_(x,y)=rgba; + } + } + inline int blendColor(int c0,int c1,int t) + { + int bgRed=(c1>>16)&0xff; + int bgGreen=(c1>>8)&0xff; + int bgBlue=c1&0xff; + + int red=(c0>>16)&0xff; + int green=(c0>>8)&0xff; + int blue=c0&0xff; + + int alpha=t; + + int r=gammaTable_.l2g[(gammaTable_.g2l[red]*alpha+gammaTable_.g2l[bgRed]*(255-alpha))>>8]; + int g=gammaTable_.l2g[(gammaTable_.g2l[green]*alpha+gammaTable_.g2l[bgGreen]*(255-alpha))>>8]; + int b=gammaTable_.l2g[(gammaTable_.g2l[blue]*alpha+gammaTable_.g2l[bgBlue]*(255-alpha))>>8]; + + return 0xff<<24 | r<<16 | g<<8 | b; + } + + inline void blendPixel(int x,int y,unsigned int rgba,int t) + { + if (checkBounds(x,y)) + { + int bg=data_(x,y); + int nc=blendColor(rgba,bg,t); + data_(x,y)=nc; + } + } + + inline unsigned width() const + { + return width_; + } + + inline unsigned height() const + { + return height_; + } + }; +} +#endif //GRAPHICS_HPP diff --git a/include/image_data.hpp b/include/image_data.hpp new file mode 100644 index 000000000..f373f0339 --- /dev/null +++ b/include/image_data.hpp @@ -0,0 +1,122 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: image_data.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef IMAGE_DATA_HPP +#define IMAGE_DATA_HPP + +namespace mapnik +{ + template class ImageData + { + private: + const unsigned width_; + const unsigned height_; + T *pData_; + ImageData& operator=(const ImageData&); + public: + ImageData(unsigned width,unsigned height) + : width_(width), + height_(height), + pData_((width!=0 && height!=0)? static_cast(::operator new(sizeof(T)*width*height)):0) + { + if (pData_) memset(pData_,0,sizeof(T)*width_*height_); + } + + ImageData(const ImageData& rhs) + :width_(rhs.width_), + height_(rhs.height_), + pData_((rhs.width_!=0 && rhs.height_!=0)? new T[rhs.width_*rhs.height_]:0) + { + if (pData_) memcpy(pData_,rhs.pData_,sizeof(T)*rhs.width_* rhs.height_); + } + inline T& operator() (unsigned i,unsigned j) + { + assert(i ImageData32; +} + +#endif //IMAGE_DATA_HPP diff --git a/include/image_reader.hpp b/include/image_reader.hpp new file mode 100644 index 000000000..5affe0831 --- /dev/null +++ b/include/image_reader.hpp @@ -0,0 +1,59 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: image_reader.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef IMAGE_READER_HPP +#define IMAGE_READER_HPP + +#include "mapnik.hpp" +#include +#include + +namespace mapnik +{ + class ImageReaderException : public std::exception + { + private: + std::string message_; + public: + ImageReaderException(const std::string& message) + : message_(message) {} + + ~ImageReaderException() throw() {} + + virtual const char* what() const throw() + { + return message_.c_str(); + } + }; + + struct ImageReader + { + virtual unsigned width() const=0; + virtual unsigned height() const=0; + virtual void read(unsigned x,unsigned y,ImageData32& image)=0; + virtual ~ImageReader() {} + }; + + bool register_image_reader(const std::string& type,ImageReader* (*)(const std::string&)); + ImageReader* get_image_reader(const std::string& type,const std::string& file); + +} + +#endif //IMAGE_READER_HPP diff --git a/include/image_symbolizer.hpp b/include/image_symbolizer.hpp new file mode 100644 index 000000000..b54828cb6 --- /dev/null +++ b/include/image_symbolizer.hpp @@ -0,0 +1,78 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: image_symbolizer.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef IMAGE_SYMBOLIZER_HPP +#define IMAGE_SYMBOLIZER_HPP + +#include "symbolizer.hpp" +#include "image_data.hpp" + +namespace mapnik +{ + struct image_symbolizer : public symbolizer + { + private: + ImageData32 symbol_; + public: + image_symbolizer(std::string const& file, + std::string const& type, + unsigned width,unsigned height) + : symbolizer(), + symbol_(width,height) + { + try + { + std::auto_ptr reader(get_image_reader(type,file)); + std::cout<<"image width="<width()< itr=geom.begin(); + while (itr!=geom.end()) + { + int x=itr->x; + int y=itr->y; + int px=int(x-0.5*w); + int py=int(y-0.5*h); + image.set_rectangle(px,py,symbol_); + ++itr; + } + } + + private: + image_symbolizer(const image_symbolizer&); + image_symbolizer& operator=(const image_symbolizer&); + }; +} + +#endif // IMAGE_SYMBOLIZER_HPP diff --git a/include/image_util.hpp b/include/image_util.hpp new file mode 100644 index 000000000..73591175f --- /dev/null +++ b/include/image_util.hpp @@ -0,0 +1,208 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: image_util.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef IMAGE_UTIL_HPP +#define IMAGE_UTIL_HPP + +namespace mapnik +{ + class ImageUtils + { + public: + static void save_to_file(const std::string& filename,const std::string& type,const Image32& image); + private: + static void save_as_png(const std::string& filename,const Image32& image); + static void save_as_jpeg(const std::string& filename,int quality, const Image32& image); + }; + + template + double distance(T x0,T y0,T x1,T y1) + { + double dx = x1-x0; + double dy = y1-y0; + return sqrt(dx * dx + dy * dy); + } + + template + inline void scale_down2(Image& target,const Image& source) + { + int source_width=source.width(); + int source_height=source.height(); + + int target_width=target.width(); + int target_height=target.height(); + if (target_width + struct image_op + { + static void scale_up(Image& target,const Image& source) + { + if (scale<3) return; + int source_width=source.width(); + int source_height=source.height(); + + int target_width=target.width(); + int target_height=target.height(); + if (target_width + struct image_op + { + static void scale_up(Image& target,const Image& source) + { + int source_width=source.width(); + int source_height=source.height(); + + int target_width=target.width(); + int target_height=target.height(); + if (target_width<2*source_width || target_height<2*source_height) + return; + for (int y=0;y + inline void scale_up(Image& target,const Image& source,unsigned scale) + { + int source_width=source.width(); + int source_height=source.height(); + + int target_width=target.width(); + int target_height=target.height(); + if (target_width + void scale_image(Image& target,const Image& source,unsigned scale) + { + if (scale==2) + { + image_op::scale_up(target,source); + } + else + { + scale_up(target,source,scale); + } + } + + template + inline void scale_image (Image& target,const Image& source) + { + + int source_width=source.width(); + int source_height=source.height(); + + int target_width=target.width(); + int target_height=target.height(); + + if (source_width<1 || source_height<1 || + target_width<1 || target_height<1) return; + int int_part_y=source_height/target_height; + int fract_part_y=source_height%target_height; + int err_y=0; + int int_part_x=source_width/target_width; + int fract_part_x=source_width%target_width; + int err_x=0; + int x=0,y=0,xs=0,ys=0; + int prev_y=-1; + for (y=0;y=target_width) + { + err_x-=target_width; + ++xs; + } + } + prev_y=ys; + } + ys+=int_part_y; + err_y+=fract_part_y; + if (err_y>=target_height) + { + err_y-=target_height; + ++ys; + } + } + } +} + +#endif //IMAGE_UTIL_HPP diff --git a/include/label_placement.hpp b/include/label_placement.hpp new file mode 100644 index 000000000..0a968e909 --- /dev/null +++ b/include/label_placement.hpp @@ -0,0 +1,51 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef LABEL_PLACEMENT_HPP +#define LABEL_PLACEMENT_HPP + +namespace mapnik +{ + struct point_ + { + double x; + double y; + point_() + : x(0),y(0) {} + point_(double x_,double y_) + : x(x_),y(y_) {} + }; + + class label_placement + { + private: + point_ anchor_; + point_ displacement_; + double rotation_; + public: + label_placement() + : anchor_(), + displacement_(), + rotation_(0.0) {} + + }; +} + +#endif //LABEL_PLACEMENT_HPP diff --git a/include/layer.hpp b/include/layer.hpp new file mode 100644 index 000000000..5000cb6ee --- /dev/null +++ b/include/layer.hpp @@ -0,0 +1,74 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: layer.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef LAYER_HPP +#define LAYER_HPP + +#include +#include "feature.hpp" +#include "ptr.hpp" +#include "datasource.hpp" + +namespace mapnik +{ + class Layer + { + private: + Parameters params_; + std::string name_; + double minZoom_; + double maxZoom_; + bool active_; + bool selectable_; + datasource_p ds_; + std::vector styles_; + std::string selection_style_; + mutable std::vector > selection_; + + public: + explicit Layer(const Parameters& params); + Layer(const Layer& l); + Layer& operator=(const Layer& l); + Parameters const& params() const; + const std::string& name() const; + void add_style(std::string const& stylename); + std::vector const& styles() const; + void selection_style(const std::string& name); + const std::string& selection_style() const; + void setMinZoom(double minZoom); + void setMaxZoom(double maxZoom); + double getMinZoom() const; + double getMaxZoom() const; + void setActive(bool active); + bool isActive() const; + void setSelectable(bool selectable); + bool isSelectable() const; + bool isVisible(double scale) const; + void add_to_selection(ref_ptr& feature) const; + std::vector >& selection() const; + void clear_selection() const; + const datasource_p& datasource() const; + const Envelope& envelope() const; + virtual ~Layer(); + private: + void swap(const Layer& other); + }; +} +#endif //LAYER_HPP diff --git a/include/line_aa.hpp b/include/line_aa.hpp new file mode 100644 index 000000000..4629821fa --- /dev/null +++ b/include/line_aa.hpp @@ -0,0 +1,46 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: line_aa.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef LINE_AA_HPP +#define LINE_AA_HPP + +#include "geometry.hpp" +#include "graphics.hpp" +#include "style.hpp" + +namespace mapnik +{ + template class LineRasterizerAA + { + private: + PixBuffer* pixbuf_; + public: + LineRasterizerAA(PixBuffer& pixbuf) + :pixbuf_(&pixbuf) {} + + template + void render(const geometry_type& geom,const Color& c); + private: + LineRasterizerAA(const LineRasterizerAA&); + LineRasterizerAA& operator=(const LineRasterizerAA&); + void render_line(int x0,int y0,int x1,int y1,unsigned rgba); + }; +} +#endif //LINE_AA_HPP diff --git a/include/line_symbolizer.hpp b/include/line_symbolizer.hpp new file mode 100644 index 000000000..1dd1b9db5 --- /dev/null +++ b/include/line_symbolizer.hpp @@ -0,0 +1,189 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: line_symbolizer.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef LINE_SYMBOLIZER_HPP +#define LINE_SYMBOLIZER_HPP + +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_stroke.h" +#include "agg_conv_curve.h" +#include "agg_conv_dash.h" +#include "agg_conv_contour.h" +#include "agg_conv_stroke.h" +#include "agg_vcgen_stroke.h" +#include "agg_conv_adaptor_vcgen.h" +#include "agg_conv_smooth_poly1.h" +#include "agg_conv_marker.h" +#include "agg_arrowhead.h" +#include "agg_vcgen_markers_term.h" +#include "agg_scanline_p.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgba.h" +#include "agg_path_storage.h" +#include "agg_renderer_outline_aa.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_rasterizer_outline.h" +#include "agg_renderer_outline_image.h" + +#include "symbolizer.hpp" +#include "stroke.hpp" +#include "line_aa.hpp" +#include "scanline_aa.hpp" + +namespace mapnik +{ + struct line_symbolizer : public symbolizer + { + private: + stroke stroke_; + public: + + line_symbolizer(stroke const& stroke) + : symbolizer(), + stroke_(stroke) {} + + line_symbolizer(const Color& pen,float width=1.0) + : symbolizer(), + stroke_(pen,width) {} + + void render(geometry_type& geom, Image32& image) const + { + typedef agg::renderer_base ren_base; + agg::row_ptr_cache buf(image.raw_data(),image.width(),image.height(), + image.width()*4); + agg::pixfmt_rgba32 pixf(buf); + ren_base renb(pixf); + + Color const& col = stroke_.get_color(); + double r=col.red()/255.0; + double g=col.green()/255.0; + double b=col.blue()/255.0; + + if (0) //stroke_.width() == 1.0) + { + typedef agg::renderer_outline_aa renderer_oaa; + typedef agg::rasterizer_outline_aa rasterizer_outline_aa; + agg::line_profile_aa prof; + prof.width(stroke_.get_width()); + renderer_oaa ren_oaa(renb, prof); + rasterizer_outline_aa ras_oaa(ren_oaa); + + ren_oaa.color(agg::rgba(r, g, b, stroke_.get_opacity())); + ras_oaa.add_path(geom); + + + //LineRasterizerAA rasterizer(image); + //rasterizer.render(geom,stroke_.get_color()); + + } + else + { + + //typedef agg::renderer_base ren_base; + + typedef agg::renderer_scanline_aa_solid renderer; + renderer ren(renb); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + + if (stroke_.has_dash()) + { + + agg::conv_dash > dash(geom); + dash_array const& d = stroke_.get_dash_array(); + dash_array::const_iterator itr = d.begin(); + dash_array::const_iterator end = d.end(); + while (itr != end) + { + dash.add_dash(itr->first, itr->second); + ++itr; + } + agg::conv_stroke > > stroke(dash); + + line_join_e join=stroke_.get_line_join(); + if ( join == MITER_JOIN) + stroke.generator().line_join(agg::miter_join); + else if( join == MITER_REVERT_JOIN) + stroke.generator().line_join(agg::miter_join); + else if( join == ROUND_JOIN) + stroke.generator().line_join(agg::round_join); + else + stroke.generator().line_join(agg::bevel_join); + + line_cap_e cap=stroke_.get_line_cap(); + if (cap == BUTT_CAP) + stroke.generator().line_cap(agg::butt_cap); + else if (cap == SQUARE_CAP) + stroke.generator().line_cap(agg::square_cap); + else + stroke.generator().line_cap(agg::round_cap); + + stroke.generator().miter_limit(4.0); + stroke.generator().width(stroke_.get_width()); + + ras.clip_box(0,0,image.width(),image.height()); + ras.add_path(stroke); + ren.color(agg::rgba(r, g, b, stroke_.get_opacity())); + agg::render_scanlines(ras, sl, ren); + } + else + { + agg::conv_stroke > stroke(geom); + + line_join_e join=stroke_.get_line_join(); + if ( join == MITER_JOIN) + stroke.generator().line_join(agg::miter_join); + else if( join == MITER_REVERT_JOIN) + stroke.generator().line_join(agg::miter_join); + else if( join == ROUND_JOIN) + stroke.generator().line_join(agg::round_join); + else + stroke.generator().line_join(agg::bevel_join); + + line_cap_e cap=stroke_.get_line_cap(); + if (cap == BUTT_CAP) + stroke.generator().line_cap(agg::butt_cap); + else if (cap == SQUARE_CAP) + stroke.generator().line_cap(agg::square_cap); + else + stroke.generator().line_cap(agg::round_cap); + + stroke.generator().miter_limit(4.0); + stroke.generator().width(stroke_.get_width()); + + ras.clip_box(0,0,image.width(),image.height()); + ras.add_path(stroke); + ren.color(agg::rgba(r, g, b, stroke_.get_opacity())); + agg::render_scanlines(ras, sl, ren); + } + } + + } + private: + line_symbolizer(const line_symbolizer&); + line_symbolizer& operator=(const line_symbolizer&); + }; +} + +#endif //LINE_SYMBOLIZER_HPP diff --git a/include/local_datasource.hpp b/include/local_datasource.hpp new file mode 100644 index 000000000..9b8de74b0 --- /dev/null +++ b/include/local_datasource.hpp @@ -0,0 +1,47 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef LOCAL_DATASOURCE_HPP +#define LOCAL_DATASOURCE_HPP + +#include "mapnik.hpp" +#include + +namespace mapnik +{ + /* + class local_datasource : public datasource + { + public: + local_datasource(Parameters const& params); + int type() const; + static std::string name(); + featureset_ptr features(query const& q) const; + const Envelope& envelope() const; + virtual ~local_datasource(); + private: + static std::string name_; + Envelope extent_; + std::vector + }; + */ +} + +#endif //LOCAL_DATASOURCE_HPP diff --git a/include/logical.hpp b/include/logical.hpp new file mode 100644 index 000000000..1301a7ea2 --- /dev/null +++ b/include/logical.hpp @@ -0,0 +1,169 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef LOGICAL_HPP +#define LOGICAL_HPP + +#include "filter.hpp" + +namespace mapnik +{ + template + struct logical_and : public filter + { + logical_and(filter const& filter1, + filter const& filter2) + : filter(), + filter1_(filter1.clone()), + filter2_(filter2.clone()) {} + + logical_and(logical_and const& other) + : filter(), + filter1_(other.filter1_->clone()), + filter2_(other.filter2_->clone()) {} + + bool pass(const FeatureT& feature) const + { + return (filter1_->pass(feature) && + filter2_->pass(feature)); + } + std::string to_string() const + { + return "("+filter1_->to_string()+" and "+filter2_->to_string()+")"; + } + + filter* clone() const + { + return new logical_and(*this); + } + + void accept(filter_visitor& v) + { + filter1_->accept(v); + filter2_->accept(v); + v.visit(*this); + } + + virtual ~logical_and() + { + delete filter1_; + delete filter2_; + } + + private: + filter* filter1_; + filter* filter2_; + }; + + template + struct logical_or : public filter + { + + logical_or(const filter& filter1,const filter& filter2) + : filter(), + filter1_(filter1.clone()), + filter2_(filter2.clone()) {} + + logical_or(logical_or const& other) + : filter(), + filter1_(other.filter1_->clone()), + filter2_(other.filter2_->clone()) {} + + bool pass(const FeatureT& feature) const + { + if (filter1_->pass(feature)) + { + return true; + } + else + { + return filter2_->pass(feature); + } + } + filter* clone() const + { + return new logical_or(*this); + } + + void accept(filter_visitor& v) + { + filter1_->accept(v); + filter2_->accept(v); + v.visit(*this); + } + std::string to_string() const + { + return "("+filter1_->to_string()+" or "+filter2_->to_string()+")"; + } + virtual ~logical_or() + { + delete filter1_; + delete filter2_; + } + private: + filter* filter1_; + filter* filter2_; + }; + + template + struct logical_not : public filter + { + logical_not(filter const& _filter) + : filter(), + filter_(_filter.clone()) {} + logical_not(logical_not const& other) + : filter(), + filter_(other.filter_->clone()) {} + + int type() const + { + return filter::LOGICAL_OPS; + } + + bool pass(const FeatureT& feature) const + { + return !(filter_->pass(feature)); + } + + filter* clone() const + { + return new logical_not(*this); + } + + void accept(filter_visitor& v) + { + filter_->accept(v); + v.visit(*this); + } + std::string to_string() const + { + return "not ("+filter_->to_string()+")"; + } + + ~logical_not() + { + delete filter_; + } + private: + filter* filter_; + }; +} + +#endif //LOGICAL_HPP diff --git a/include/map.hpp b/include/map.hpp new file mode 100644 index 000000000..8d03f8538 --- /dev/null +++ b/include/map.hpp @@ -0,0 +1,64 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: map.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef MAP_HPP +#define MAP_HPP + +namespace mapnik +{ + class Layer; + + class Map + { + private: + static const int MIN_MAPSIZE=16; + static const int MAX_MAPSIZE=1024; + int width_; + int height_; + int srid_; + Color background_; + std::vector layers_; + Envelope currentExtent_; + public: + Map(int width,int height,int srid=-1); + Map(const Map& rhs); + Map& operator=(const Map& rhs); + size_t layerCount() const; + void addLayer(const Layer& l); + const Layer& getLayer(size_t index) const; + void removeLayer(size_t index); + void removeLayer(const char* lName); + int getWidth() const; + int getHeight() const; + int srid() const; + void setBackground(const Color& c); + const Color& getBackground() const; + void zoom(double zoom); + void zoomToBox(const Envelope& box); + void pan(int x,int y); + void pan_and_zoom(int x,int y,double zoom); + const Envelope& getCurrentExtent() const; + double scale() const; + virtual ~Map(); + private: + void fixAspectRatio(); + }; +} +#endif //MAP_HPP diff --git a/include/mapnik.hpp b/include/mapnik.hpp new file mode 100644 index 000000000..ccb524502 --- /dev/null +++ b/include/mapnik.hpp @@ -0,0 +1,76 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: mapnik.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef MAPNIK_HPP +#define MAPNIK_HPP + +#include +#include +#include +#include "ptr.hpp" +#include "factory.hpp" +#include "filter.hpp" +#include "query.hpp" +#include "rule.hpp" +#include "spatial.hpp" +#include "logical.hpp" +#include "comparison.hpp" +#include "regex_filter.hpp" +#include "utils.hpp" +#include "style.hpp" +#include "symbolizer.hpp" +#include "style_cache.hpp" +#include "geometry.hpp" +#include "geom_util.hpp" +#include "raster.hpp" +#include "feature.hpp" +#include "attribute.hpp" +#include "attribute_collector.hpp" +#include "render.hpp" +#include "graphics.hpp" +#include "image_reader.hpp" +#include "line_symbolizer.hpp" +#include "polygon_symbolizer.hpp" +//#include "image_symbolizer.hpp" +#include "image_util.hpp" +#include "datasource.hpp" +#include "layer.hpp" +#include "datasource_cache.hpp" +#include "wkb.hpp" +#include "map.hpp" +#include "colorcube.hpp" +#include "feature_type_style.hpp" +#include "math_expr.hpp" +#include "value.hpp" +#include "expression.hpp" +#include "filter_visitor.hpp" +#include "filter_parser.hpp" +#include "filter_factory.hpp" +#include "text_symbolizer.hpp" +#include "label_placement.hpp" + +#include "feature_layer_desc.hpp" + +namespace mapnik +{ + //typedef geometry_type geometry_type; +} + +#endif //MAPNIK_HPP diff --git a/include/math_expr.hpp b/include/math_expr.hpp new file mode 100644 index 000000000..68d672b5b --- /dev/null +++ b/include/math_expr.hpp @@ -0,0 +1,126 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef MATH_EXPR_HPP +#define MATH_EXPR_HPP + +#include "expression.hpp" + +namespace mapnik +{ + template + struct add + { + T operator () (T const& left, T const& right) + { + return left + right; + } + static std::string to_string() + { + return "+"; + } + }; + + template + struct sub + { + T operator () (T const& left, T const& right) + { + return left - right; + } + static std::string to_string() + { + return "-"; + } + }; + + template + struct mult + { + T operator () (T const& left, T const& right) + { + return left * right; + } + static std::string to_string() + { + return "*"; + } + }; + + template + struct div + { + T operator () (T const& left, T const& right) + { + return left / right; + } + static std::string to_string() + { + return "/"; + } + }; + + template + struct math_expr_b : public expression + { + math_expr_b(expression const& left, + expression const& right) + : expression(), + left_(left.clone()), + right_(right.clone()) {} + math_expr_b(math_expr_b const& other) + : expression(), + left_(other.left_->clone()), + right_(other.right_->clone()) {} + + value get_value(FeatureT const& feature) const + { + return Op ()(left_->get_value(feature),right_->get_value(feature)); + } + + void accept(filter_visitor& v) + { + left_->accept(v); + right_->accept(v); + v.visit(*this); + } + + expression* clone() const + { + return new math_expr_b(*this); + } + std::string to_string() const + { + return "("+left_->to_string() + Op::to_string() + right_->to_string()+")"; + } + + ~math_expr_b() + { + delete left_; + delete right_; + } + private: + expression* left_; + expression* right_; + }; +}; + + +#endif // diff --git a/include/memory.hpp b/include/memory.hpp new file mode 100644 index 000000000..7a0690f89 --- /dev/null +++ b/include/memory.hpp @@ -0,0 +1,85 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: memory.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef MEMORY_HPP +#define MEMORY_HPP + +#include +#include + +namespace mapnik +{ + class MemoryUtils + { + public: + static size_t alignPointerSize(size_t ptrSize); + private: + MemoryUtils(); + MemoryUtils(const MemoryUtils&); + MemoryUtils& operator=(const MemoryUtils&); + }; + + class MemoryManager + { + public: + virtual void* allocate(size_t size)=0; + virtual void deallocate(void* p)=0; + virtual ~MemoryManager(); + protected: + MemoryManager(); // {} + private: + MemoryManager(const MemoryManager&); + MemoryManager& operator=(const MemoryManager&); + }; + + class Object + { + public: + void* operator new(size_t size); + void* operator new(size_t size, MemoryManager* manager); + void operator delete(void* p); + void operator delete(void* p, MemoryManager* manager); + protected: + virtual ~Object() {} + Object() {} + Object(const Object&) {} + protected: + Object& operator=(const Object&) + { + return *this; + } + }; + + template + class geometry_pool + { + public: + void* allocate() + { + return ::operator new(sizeof(Geometry)); + } + void deallocate(void* p) + { + ::operator delete(p); + } + }; + +} +#endif //MEMORY_HPP diff --git a/include/params.hpp b/include/params.hpp new file mode 100644 index 000000000..484ab5c80 --- /dev/null +++ b/include/params.hpp @@ -0,0 +1,47 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: params.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef PARAMS_HPP +#define PARAMS_HPP + +#include + +namespace mapnik +{ + + typedef std::pair Parameter; + + class Parameters + { + typedef std::map ParamMap; + private: + ParamMap data_; + public: + typedef ParamMap::const_iterator const_iterator; + Parameters() {} + const std::string get(const std::string& name) const; + void add(const Parameter& param); + void add(const std::string& name,const std::string& value); + const_iterator begin() const; + const_iterator end() const; + virtual ~Parameters(); + }; +} +#endif //PARAMS_HPP diff --git a/include/plugin.hpp b/include/plugin.hpp new file mode 100644 index 000000000..eb404034a --- /dev/null +++ b/include/plugin.hpp @@ -0,0 +1,46 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: plugin.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef PLUGIN_HPP +#define PLUGIN_HPP + +#include +#include + +namespace mapnik +{ + class PluginInfo + { + private: + std::string name_; + lt_dlhandle module_; + + public: + PluginInfo (const std::string& name,const lt_dlhandle module); + ~PluginInfo(); + const std::string& name() const; + lt_dlhandle handle() const; + private: + PluginInfo(const PluginInfo&); + PluginInfo& operator=(const PluginInfo&); + }; +} + +#endif //PLUGIN_HPP diff --git a/include/polygon_symbolizer.hpp b/include/polygon_symbolizer.hpp new file mode 100644 index 000000000..967f6b514 --- /dev/null +++ b/include/polygon_symbolizer.hpp @@ -0,0 +1,54 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: polygon_symbolizer.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef POLYGON_SYMBOLIZER_HPP +#define POLYGON_SYMBOLIZER_HPP + +#include "symbolizer.hpp" +#include "scanline_aa.hpp" +#include "line_aa.hpp" + +namespace mapnik +{ + struct polygon_symbolizer : public symbolizer + { + private: + Color fill_; + public: + polygon_symbolizer(const Color& fill) + : symbolizer(), + fill_(fill) {} + + virtual ~polygon_symbolizer() {} + + void render(geometry_type& geom,Image32& image) const + { + ScanlineRasterizerAA rasterizer(image); + rasterizer.render(geom,fill_); + } + + private: + polygon_symbolizer(const polygon_symbolizer&); + polygon_symbolizer& operator=(const polygon_symbolizer&); + + }; +} + +#endif // POLYGON_SYMBOLIZER_HPP diff --git a/include/pool.hpp b/include/pool.hpp new file mode 100644 index 000000000..9ec506954 --- /dev/null +++ b/include/pool.hpp @@ -0,0 +1,120 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: pool.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef POOL_HPP +#define POOL_HPP + +#include +#include +#include +#include + +#include "ptr.hpp" +#include "utils.hpp" + +namespace mapnik +{ + template + class PoolGuard + { + private: + const T& obj_; + PoolT& pool_; + public: + explicit PoolGuard(const T& ptr,PoolT& pool) + : obj_(ptr), + pool_(pool) {} + + ~PoolGuard() + { + pool_->returnObject(obj_); + } + + private: + PoolGuard(); + PoolGuard(const PoolGuard&); + PoolGuard& operator=(const PoolGuard&); + }; + + template class Creator> + class Pool + { + typedef ref_ptr HolderType; + typedef std::deque ContType; + + Creator creator_; + const int initialSize_; + const int maxSize_; + ContType usedPool_; + ContType unusedPool_; + Mutex mutex_; + public: + + Pool(const Creator& creator,int initialSize=5,int maxSize=20) + :creator_(creator), + initialSize_(initialSize), + maxSize_(maxSize) + { + for (int i=0;i + +namespace mapnik +{ + template + class property_index : public filter_visitor + { + public: + property_index(std::set const& names) + : names_(names) {} + + void visit(filter& /*filter*/) + { + //not interested + } + void visit(expression& exp) + { + property* pf; + if ((pf = dynamic_cast*>(&exp))) + { + std::set::iterator pos; + pos = names_.find(pf->name()); + if (pos != names_.end()) + { + size_t idx = std::distance(names_.begin(),pos); + pf->set_index(idx); + } + } + } + virtual ~property_index() {} + private: + // no copying + property_index(property_index const&); + property_index& operator=(property_index const&); + + private: + std::set const& names_; + + }; +} + +#endif //PROPERTY_INDEX_HPP diff --git a/include/ptr.hpp b/include/ptr.hpp new file mode 100644 index 000000000..01a340b28 --- /dev/null +++ b/include/ptr.hpp @@ -0,0 +1,107 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: ptr.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef PTR_HPP +#define PTR_HPP + +namespace mapnik +{ + + template struct DefaultDeletePolicy + { + static void destroy(T* p) + { + delete p; + } + }; + + template class DeallocPolicy=DefaultDeletePolicy> + class ref_ptr + { + private: + T* ptr_; + int* pCount_; + public: + T* operator->() {return ptr_;} + const T* operator->() const {return ptr_;} + T* get() {return ptr_;} + const T* get() const {return ptr_;} + const T& operator *() const {return *ptr_;} + T& operator *() {return *ptr_;} + explicit ref_ptr(T* ptr=0) + :ptr_(ptr),pCount_(new int(1)) {} + ref_ptr(const ref_ptr& rhs) + :ptr_(rhs.ptr_),pCount_(rhs.pCount_) + { + (*pCount_)++; + } + ref_ptr& operator=(const ref_ptr& rhs) + { + if (ptr_==rhs.ptr_) return *this; + if (--(*pCount_)==0) + { + DeallocPolicy::destroy(ptr_); + delete pCount_; + } + ptr_=rhs.ptr_; + pCount_=rhs.pCount_; + (*pCount_)++; + return *this; + } + bool operator !() const + { + return ptr_==0; + } + operator bool () const + { + return ptr_!=0; + } + inline friend bool operator==(const ref_ptr& lhs, + const T* rhs) + { + return lhs.ptr_==rhs; + } + inline friend bool operator==(const T* lhs, + const ref_ptr& rhs) + { + return lhs==rhs.ptr_; + } + inline friend bool operator!=(const ref_ptr& lhs, + const T* rhs) + { + return lhs.ptr_!=rhs; + } + inline friend bool operator!=(const T* lhs, + const ref_ptr& rhs) + { + return lhs!=rhs.ptr_; + } + ~ref_ptr() + { + if (--(*pCount_)==0) + { + DeallocPolicy::destroy(ptr_); + delete pCount_; + } + } + }; +} +#endif //PTR_HPP diff --git a/include/query.hpp b/include/query.hpp new file mode 100644 index 000000000..e458e9172 --- /dev/null +++ b/include/query.hpp @@ -0,0 +1,107 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef QUERY_HPP +#define QUERY_HPP + +#include +#include +#include "filter.hpp" +#include "envelope.hpp" +#include "feature.hpp" + +namespace mapnik +{ + class query + { + private: + Envelope bbox_; + filter* filter_; + std::set names_; + public: + query() + : bbox_(std::numeric_limits::min(), + std::numeric_limits::min(), + std::numeric_limits::max(), + std::numeric_limits::max()), + filter_(new null_filter) + {} + + query(const Envelope& bbox) + : bbox_(bbox), + filter_(new null_filter) + {} + + query(const Envelope& bbox,const filter& f) + : bbox_(bbox), + filter_(f.clone()) + {} + + query(const query& other) + : bbox_(other.bbox_), + filter_(other.filter_->clone()) + {} + + query& operator=(const query& other) + { + filter* tmp=other.filter_->clone(); + delete filter_; + filter_=tmp; + bbox_=other.bbox_; + names_=other.names_; + return *this; + } + + const filter* get_filter() const + { + return filter_; + } + + const Envelope& get_bbox() const + { + return bbox_; + } + + void set_filter(const filter& f) + { + filter* tmp=f.clone(); + delete filter_; + filter_=tmp; + } + + void add_property_name(const std::string& name) + { + names_.insert(name); + } + + const std::set& property_names() const + { + return names_; + } + + ~query() + { + delete filter_; + } + }; +} + + +#endif //QUERY_HPP diff --git a/include/raster.hpp b/include/raster.hpp new file mode 100644 index 000000000..b110b4a7b --- /dev/null +++ b/include/raster.hpp @@ -0,0 +1,40 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: raster.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef RASTER_HPP +#define RASTER_HPP + +#include "graphics.hpp" + +namespace mapnik +{ + struct raster + { + int x_; + int y_; + ImageData32 data_; + raster(int x,int y,ImageData32& data) + : x_(x), + y_(y), + data_(data) {} + }; +} + +#endif //RASTER_HPP diff --git a/include/regex_filter.hpp b/include/regex_filter.hpp new file mode 100644 index 000000000..807990dc9 --- /dev/null +++ b/include/regex_filter.hpp @@ -0,0 +1,79 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef REGEX_FILTER_HPP +#define REGEX_FILTER_HPP + +#include "filter.hpp" +#include "expression.hpp" + +#include + +namespace mapnik +{ + template + struct regex_filter : public filter + { + + regex_filter(expression const& exp, + std::string const& pattern) + : filter(), + exp_(exp.clone()), + pattern_(pattern) {} + + regex_filter(regex_filter const& other) + : filter(), + exp_(other.exp_->clone()), + pattern_(other.pattern_) {} + + bool pass(FeatureT const& feature) const + { + std::string text=exp_->get_value(feature).to_string(); + return boost::regex_match(text,pattern_); + } + + void accept(filter_visitor& v) + { + exp_->accept(v); + v.visit(*this); + } + + filter* clone() const + { + return new regex_filter(*this); + } + std::string to_string() const + { + return exp_->to_string()+".match("+pattern_.str()+")"; + } + ~regex_filter() + { + delete exp_; + } + + private: + expression* exp_; + boost::regex pattern_; + + }; +} + + +#endif //REGEX_FILTER_HPP diff --git a/include/render.hpp b/include/render.hpp new file mode 100644 index 000000000..09b2ae5b4 --- /dev/null +++ b/include/render.hpp @@ -0,0 +1,46 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: render.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef RENDER_HPP +#define RENDER_HPP + +#include +#include "memory.hpp" +#include "ptr.hpp" +#include "style.hpp" +#include "envelope.hpp" +#include "graphics.hpp" +#include "datasource.hpp" +#include "layer.hpp" +#include "map.hpp" + +namespace mapnik +{ + template class Renderer + { + public: + static void render(const Map& map,Image& image); + private: + Renderer(); + static void renderLayer(const Layer& l,const CoordTransform& t,const Envelope& bbox,Image& image); + }; +} + +#endif //RENDER_HPP diff --git a/include/rule.hpp b/include/rule.hpp new file mode 100644 index 000000000..77741b75d --- /dev/null +++ b/include/rule.hpp @@ -0,0 +1,217 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef RULE_HPP +#define RULE_HPP + +#include "symbolizer.hpp" +#include "filter.hpp" +#include +#include +#include + +namespace mapnik +{ + typedef ref_ptr symbolizer_ptr; + typedef std::vector symbolizers; + template class null_filter; + + template class Filter> + class rule + { + typedef Filter filter_type; + typedef ref_ptr filter_ptr; + private: + + std::string name_; + std::string title_; + std::string abstract_; + double min_scale_; + double max_scale_; + symbolizers syms_; + filter_ptr filter_; + bool else_filter_; + public: + rule() + : name_(), + title_(), + abstract_(), + min_scale_(0), + max_scale_(std::numeric_limits::infinity()), + syms_(), + filter_(new null_filter), + else_filter_(false) {} + + rule(const std::string& name,const std::string& title) + : name_(name), + title_(title), + abstract_(), + min_scale_(0), + max_scale_(std::numeric_limits::infinity()), + syms_(), + filter_(new null_filter), + else_filter_(false) {} + + rule(const std::string& name,const std::string& title, + double min_scale_denominator,double max_scale_denominator) + : name_(name), + title_(title), + min_scale_(min_scale_denominator), + max_scale_(max_scale_denominator), + syms_(), + filter_(new null_filter), + else_filter_(false) {} + + rule(const rule& rhs) + : name_(rhs.name_), + title_(rhs.title_), + abstract_(rhs.abstract_), + min_scale_(rhs.min_scale_), + max_scale_(rhs.max_scale_), + syms_(rhs.syms_), + filter_(rhs.filter_), + else_filter_(rhs.else_filter_) {} + + rule& operator=(rule const& rhs) + { + rule tmp(rhs); + swap(tmp); + return *this; + } + + void set_max_scale(double scale) + { + max_scale_=scale; + } + + double get_min_scale() const + { + return min_scale_; + } + + double get_max_scale() const + { + return max_scale_; + } + + void set_min_scale(double scale) + { + min_scale_=scale; + } + + void set_name(std::string const& name) + { + name_=name; + } + + const std::string& get_name() const + { + return name_; + } + + + const std::string& get_title() const + { + return title_; + } + + void set_title(std::string const& title) + { + title_=title; + } + + void set_abstract(const std::string& abstract) + { + abstract_=abstract; + } + + const std::string& get_abstract() const + { + return abstract_; + } + + void append(const symbolizer_ptr& symbol) + { + syms_.push_back(symbol); + } + + void remove_at(size_t index) + { + if (index < syms_.size()) + { + syms_.erase(syms_.begin()+index); + } + } + + const symbolizers& get_symbolizers() const + { + return syms_; + } + + symbolizers::const_iterator begin() + { + return syms_.begin(); + } + + symbolizers::const_iterator end() + { + return syms_.end(); + } + + void set_filter(const filter_ptr& filter) + { + filter_=filter; + } + + const filter_ptr& get_filter() const + { + return filter_; + } + + void set_else(bool else_filter) + { + else_filter_=else_filter; + } + + bool has_else_filter() const + { + return else_filter_; + } + + bool active(double scale) const + { + return ( scale > min_scale_ && scale < max_scale_ ); + } + + private: + + void swap(rule& rhs) throw() + { + name_=rhs.name_; + title_=rhs.title_; + abstract_=rhs.abstract_; + min_scale_=rhs.min_scale_; + max_scale_=rhs.max_scale_; + syms_=rhs.syms_; + filter_=rhs.filter_; + else_filter_=rhs.else_filter_; + } + }; +} + +#endif //RULE_HPP diff --git a/include/scanline.hpp b/include/scanline.hpp new file mode 100644 index 000000000..2ad5948c3 --- /dev/null +++ b/include/scanline.hpp @@ -0,0 +1,44 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: scanline.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef SCANLINE_HPP +#define SCANLINE_HPP + +#include "geometry.hpp" + +namespace mapnik +{ + template class ScanlineRasterizer + { + private: + PixBuffer* pixbuf_; + public: + ScanlineRasterizer(PixBuffer& pixbuf) + :pixbuf_(&pixbuf) {} + + template + void render(const geometry_type& geom,const Color& c); + private: + ScanlineRasterizer(const ScanlineRasterizer&); + ScanlineRasterizer& operator=(const ScanlineRasterizer&); + void render_hline(int x0,int x1,int y,unsigned int rgba); + }; +} +#endif //SCANLINE_HPP diff --git a/include/scanline_aa.hpp b/include/scanline_aa.hpp new file mode 100644 index 000000000..7a31a5523 --- /dev/null +++ b/include/scanline_aa.hpp @@ -0,0 +1,843 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// Credits: +// I gratefully acknowledge the inspiring work of Maxim Shemanarev (McSeem), +// author of Anti-Grain Geometry (http://www.antigrain.com), and also the developers +// of the FreeType library (http://www.freetype.org). I have slightly modified the polygon +// rasterizing algorithm to work with my library, but render_line and +// render_hline remain intact. + + +//$Id: scanline_aa.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef SCANLINE_AA_HPP +#define SCANLINE_AA_HPP + +#include "envelope.hpp" +#include "geometry.hpp" +#include "graphics.hpp" +#include "style.hpp" + +namespace mapnik +{ + enum path_commands_e + { + path_cmd_stop = 0, //----path_cmd_stop + path_cmd_move_to = 1, //----path_cmd_move_to + path_cmd_line_to = 2, //----path_cmd_line_to + path_cmd_curve3 = 3, //----path_cmd_curve3 + path_cmd_curve4 = 4, //----path_cmd_curve4 + path_cmd_end_poly = 6, //----path_cmd_end_poly + path_cmd_mask = 0x0F //----path_cmd_mask + }; + + //------------------------------------------------------------path_flags_e + enum path_flags_e + { + path_flags_none = 0, //----path_flags_none + path_flags_ccw = 0x10, //----path_flags_ccw + path_flags_cw = 0x20, //----path_flags_cw + path_flags_close = 0x40, //----path_flags_close + path_flags_mask = 0xF0 //----path_flags_mask + }; + + inline bool is_vertex(unsigned c) + { + return c >= path_cmd_move_to && c < path_cmd_end_poly; + } + + inline bool is_move_to(unsigned c) + { + return c == path_cmd_move_to; + } + + inline bool is_close(unsigned c) + { + return (c & ~(path_flags_cw | path_flags_ccw)) == + (path_cmd_end_poly | path_flags_close); + } + + inline unsigned clipping_flags(int x, int y, const Envelope& clip_box) + { + return (x > clip_box.maxx()) | + ((y > clip_box.maxy()) << 1) | + ((x < clip_box.minx()) << 2) | + ((y < clip_box.miny()) << 3); + } + + template + inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, + const Envelope& clip_box, + T* x, T* y) + { + const double nearzero = 1e-30; + + double deltax = x2 - x1; + double deltay = y2 - y1; + double xin; + double xout; + double yin; + double yout; + double tinx; + double tiny; + double toutx; + double touty; + double tin1; + double tin2; + double tout1; + unsigned np = 0; + + if(deltax == 0.0) + { + // bump off of the vertical + deltax = (x1 > clip_box.minx()) ? -nearzero : nearzero; + } + + if(deltay == 0.0) + { + // bump off of the horizontal + deltay = (y1 > clip_box.miny()) ? -nearzero : nearzero; + } + + if(deltax > 0.0) + { + // points to right + xin = clip_box.minx(); + xout = clip_box.maxx(); + } + else + { + xin = clip_box.maxx(); + xout = clip_box.minx(); + } + + if(deltay > 0.0) + { + // points up + yin = clip_box.miny(); + yout = clip_box.maxy(); + } + else + { + yin = clip_box.maxy(); + yout = clip_box.miny(); + } + + tinx = (xin - x1) / deltax; + tiny = (yin - y1) / deltay; + + if (tinx < tiny) + { + // hits x first + tin1 = tinx; + tin2 = tiny; + } + else + { + // hits y first + tin1 = tiny; + tin2 = tinx; + } + + if(tin1 <= 1.0) + { + if(0.0 < tin1) + { + *x++ = (T)xin; + *y++ = (T)yin; + ++np; + } + + if(tin2 <= 1.0) + { + toutx = (xout - x1) / deltax; + touty = (yout - y1) / deltay; + + tout1 = (toutx < touty) ? toutx : touty; + + if(tin2 > 0.0 || tout1 > 0.0) + { + if(tin2 <= tout1) + { + if(tin2 > 0.0) + { + if(tinx > tiny) + { + *x++ = (T)xin; + *y++ = (T)(y1 + tinx * deltay); + } + else + { + *x++ = (T)(x1 + tiny * deltax); + *y++ = (T)yin; + } + ++np; + } + + if(tout1 < 1.0) + { + if(toutx < touty) + { + *x++ = (T)xout; + *y++ = (T)(y1 + toutx * deltay); + } + else + { + *x++ = (T)(x1 + touty * deltax); + *y++ = (T)yout; + } + } + else + { + *x++ = x2; + *y++ = y2; + } + ++np; + } + else + { + if(tinx > tiny) + { + *x++ = (T)xin; + *y++ = (T)yout; + } + else + { + *x++ = (T)xout; + *y++ = (T)yin; + } + ++np; + } + } + } + } + return np; + } + + enum + { + poly_base_shift = 8, + poly_base_size = 1 << poly_base_shift, + poly_base_mask = poly_base_size - 1 + }; + + inline int poly_coord(double c) + { + return int(c * poly_base_size); + } + + struct cell_aa + { + short x; + short y; + int packed_coord; + int cover; + int area; + + void set(int x, int y, int c, int a); + void set_coord(int x, int y); + void set_cover(int c, int a); + void add_cover(int c, int a); + }; + + class outline_aa + { + enum { + cell_block_shift = 12, + cell_block_size = 1 << cell_block_shift, + cell_block_mask = cell_block_size - 1, + cell_block_pool = 256, + cell_block_limit = 1024 + }; + + public: + + ~outline_aa(); + outline_aa(); + + void reset(); + + void move_to(int x, int y); + void line_to(int x, int y); + + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + const cell_aa* const* cells(); + unsigned num_cells() { cells(); return m_num_cells; } + bool sorted() const { return m_sorted; } + + private: + outline_aa(const outline_aa&); + const outline_aa& operator = (const outline_aa&); + + void set_cur_cell(int x, int y); + void add_cur_cell(); + void sort_cells(); + void render_hline(int ey, int x1, int y1, int x2, int y2); + void render_line(int x1, int y1, int x2, int y2); + void allocate_block(); + + static void qsort_cells(cell_aa** start, unsigned num); + + private: + unsigned m_num_blocks; + unsigned m_max_blocks; + unsigned m_cur_block; + unsigned m_num_cells; + cell_aa** m_cells; + cell_aa* m_cur_cell_ptr; + cell_aa** m_sorted_cells; + unsigned m_sorted_size; + cell_aa m_cur_cell; + int m_cur_x; + int m_cur_y; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + bool m_sorted; + }; + + enum filling_rule_e + { + fill_non_zero, + fill_even_odd + }; + + template class ScanlineRasterizerAA + { + enum status + { + status_initial, + status_line_to, + status_closed + }; + + struct iterator + { + const cell_aa* const* cells; + int cover; + int last_y; + }; + enum + { + aa_shift = 8, + aa_num = 1 << aa_shift, + aa_mask = aa_num - 1, + aa_2num = aa_num * 2, + aa_2mask = aa_2num - 1 + }; + private: + PixBuffer* pixbuf_; + outline_aa m_outline; + int m_gamma[aa_num]; + filling_rule_e m_filling_rule; + int m_clipped_start_x; + int m_clipped_start_y; + int m_start_x; + int m_start_y; + int m_prev_x; + int m_prev_y; + unsigned m_prev_flags; + unsigned m_status; + Envelope m_clip_box; + bool m_clipping; + iterator m_iterator; + public: + ScanlineRasterizerAA(PixBuffer& pixbuf) + :pixbuf_(&pixbuf), + m_filling_rule(fill_non_zero), + m_clipped_start_x(0), + m_clipped_start_y(0), + m_start_x(0), + m_start_y(0), + m_prev_x(0), + m_prev_y(0), + m_prev_flags(0), + m_status(status_initial), + m_clipping(false) + { + for(int i = 0; i < aa_num; i++) m_gamma[i] = i; + } + + template + void render(const geometry_type& geom,const Color& c); + + private: + ScanlineRasterizerAA(const ScanlineRasterizerAA&); + ScanlineRasterizerAA& operator=(const ScanlineRasterizerAA&); + void render_hline(int x0,int x1,int y,unsigned rgba); + void blend_hline(int x0,int x1,int y,const unsigned char* cover, + unsigned rgba); + int min_x() const { return m_outline.min_x(); } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x(); } + int max_y() const { return m_outline.max_y(); } + void reset(); + void filling_rule(filling_rule_e filling_rule); + void clip_box(double x1, double y1, double x2, double y2); + void reset_clipping(); + template void gamma(const GammaF& gamma_function) + { + int i; + for(i = 0; i < aa_num; i++) + { + m_gamma[i] = int(floor(gamma_function(double(i) / aa_mask) * aa_mask + 0.5)); + } + } + unsigned apply_gamma(unsigned cover) const + { + return m_gamma[cover]; + } + void add_vertex(double x, double y, unsigned cmd); + void move_to(int x, int y); + void line_to(int x, int y); + void close_polygon(); + + void move_to_no_clip(int x, int y); + void line_to_no_clip(int x, int y); + void close_polygon_no_clip(); + void clip_segment(int x, int y); + unsigned calculate_alpha(int area) const + { + int cover = area >> (poly_base_shift*2 + 1 - aa_shift); + + if(cover < 0) cover = -cover; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_2mask; + if(cover > aa_num) + { + cover = aa_2num - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return m_gamma[cover]; + } + + + void sort() + { + m_outline.cells(); + } + + + bool rewind_scanlines() + { + close_polygon(); + m_iterator.cells = m_outline.cells(); + if(m_outline.num_cells() == 0) + { + return false; + } + m_iterator.cover = 0; + m_iterator.last_y = (*m_iterator.cells)->y; + return true; + } + + + template bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + const cell_aa* cur_cell = *m_iterator.cells; + if(cur_cell == 0) return false; + ++m_iterator.cells; + m_iterator.last_y = cur_cell->y; + + for(;;) + { + int coord = cur_cell->packed_coord; + int area = cur_cell->area; + int last_x = cur_cell->x; + + m_iterator.cover += cur_cell->cover; + + //accumulate all cells with the same coordinates + for(; (cur_cell = *m_iterator.cells) != 0; ++m_iterator.cells) + { + if(cur_cell->packed_coord != coord) break; + area += cur_cell->area; + m_iterator.cover += cur_cell->cover; + } + + int alpha; + if(cur_cell == 0 || cur_cell->y != m_iterator.last_y) + { + + if(area) + { + alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area); + if(alpha) + { + sl.add_cell(last_x, alpha); + } + ++last_x; + } + break; + } + + ++m_iterator.cells; + + if(area) + { + alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area); + if(alpha) + { + sl.add_cell(last_x, alpha); + } + ++last_x; + } + + if(cur_cell->x > last_x) + { + alpha = calculate_alpha(m_iterator.cover << (poly_base_shift + 1)); + if(alpha) + { + sl.add_span(last_x, cur_cell->x - last_x, alpha); + } + } + } + if(sl.num_spans()) + { + sl.finalize(m_iterator.last_y); + break; + } + } + return true; + } + }; + + template + void ScanlineRasterizerAA::reset() + { + m_outline.reset(); + m_status = status_initial; + } + + template + void ScanlineRasterizerAA::clip_box(double x1, double y1, double x2, double y2) + { + //reset(); + m_clip_box = Envelope(poly_coord(x1), poly_coord(y1), + poly_coord(x2), poly_coord(y2)); + //m_clip_box.normalize(); + m_clipping = true; + } + + template + void ScanlineRasterizerAA::move_to_no_clip(int x, int y) + { + if(m_status == status_line_to) + { + close_polygon_no_clip(); + } + m_outline.move_to(x,y); + m_clipped_start_x = x; + m_clipped_start_y = y; + m_status = status_line_to; + } + + template + void ScanlineRasterizerAA::line_to_no_clip(int x, int y) + { + if(m_status != status_initial) + { + m_outline.line_to(x , y); + m_status = status_line_to; + } + } + + template + void ScanlineRasterizerAA::close_polygon_no_clip() + { + if(m_status == status_line_to) + { + m_outline.line_to(m_clipped_start_x, m_clipped_start_y); + m_status = status_closed; + } + } + + template + void ScanlineRasterizerAA::clip_segment(int x, int y) + { + unsigned flags = clipping_flags(x, y, m_clip_box); + if(m_prev_flags == flags) + { + if(flags == 0) + { + if(m_status == status_initial) + { + move_to_no_clip(x, y); + } + else + { + line_to_no_clip(x, y); + } + } + } + else + { + + int cx[4]; + int cy[4]; + unsigned n = clip_liang_barsky(m_prev_x, m_prev_y, + x, y, + m_clip_box, + cx, cy); + const int* px = cx; + const int* py = cy; + while(n--) + { + if(m_status == status_initial) + { + move_to_no_clip(*px++, *py++); + } + else + { + line_to_no_clip(*px++, *py++); + } + } + } + + m_prev_flags = flags; + m_prev_x = x; + m_prev_y = y; + } + + template + void ScanlineRasterizerAA::add_vertex(double x, double y, unsigned cmd) + { + if(is_close(cmd)) + { + close_polygon(); + } + else + { + if(is_move_to(cmd)) + { + move_to(poly_coord(x), poly_coord(y)); + } + else + { + if(is_vertex(cmd)) + { + line_to(poly_coord(x), poly_coord(y)); + } + } + } + } + + template + void ScanlineRasterizerAA::move_to(int x, int y) + { + if(m_clipping) + { + if(m_outline.sorted()) + { + reset(); + } + if(m_status == status_line_to) + { + close_polygon(); + } + m_prev_x = m_start_x = x; + m_prev_y = m_start_y = y; + m_status = status_initial; + m_prev_flags = clipping_flags(x, y, m_clip_box); + if(m_prev_flags == 0) + { + move_to_no_clip(x, y); + } + } + else + { + move_to_no_clip(x, y); + } + } + + template + void ScanlineRasterizerAA::line_to(int x, int y) + { + if(m_clipping) + { + clip_segment(x, y); + } + else + { + line_to_no_clip(x, y); + } + } + + template + void ScanlineRasterizerAA::close_polygon() + { + if(m_clipping) + { + clip_segment(m_start_x, m_start_y); + } + close_polygon_no_clip(); + } + + + template class scanline_u + { + public: + typedef T cover_type; + struct span + { + short x; + short len; + cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + ~scanline_u(); + scanline_u(); + + void reset(int min_x, int max_x); + void add_cell(int x, unsigned cover); + void add_cells(int x, unsigned len, const T* covers); + void add_span(int x, unsigned len, unsigned cover); + void finalize(int y) { m_y = y; } + void reset_spans(); + + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - m_spans); } + const_iterator begin() const { return m_spans + 1; } + iterator begin() { return m_spans + 1; } + + private: + scanline_u(const scanline_u&); + const scanline_u& operator = (const scanline_u&); + + private: + int m_min_x; + unsigned m_max_len; + int m_last_x; + int m_y; + cover_type* m_covers; + span* m_spans; + span* m_cur_span; + }; + + template scanline_u::~scanline_u() + { + delete [] m_spans; + delete [] m_covers; + } + + template scanline_u::scanline_u() : + m_min_x(0), + m_max_len(0), + m_last_x(0x7FFFFFF0), + m_covers(0), + m_spans(0), + m_cur_span(0) + { + } + + template void scanline_u::reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; + if(max_len > m_max_len) + { + delete [] m_spans; + delete [] m_covers; + m_covers = new cover_type [max_len]; + m_spans = new span [max_len]; + m_max_len = max_len; + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_cur_span = m_spans; + } + + template inline void scanline_u::reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cur_span = m_spans; + } + + template inline void scanline_u::add_cell(int x, unsigned cover) + { + x -= m_min_x; + m_covers[x] = (unsigned char)cover; + if(x == m_last_x+1) + { + m_cur_span->len++; + } + else + { + m_cur_span++; + m_cur_span->x = (short)(x + m_min_x); + m_cur_span->len = 1; + m_cur_span->covers = m_covers + x; + } + m_last_x = x; + } + + template void scanline_u::add_cells(int x, unsigned len, const T* covers) + { + x -= m_min_x; + memcpy(m_covers + x, covers, len * sizeof(T)); + if(x == m_last_x+1) + { + m_cur_span->len += (short)len; + } + else + { + m_cur_span++; + m_cur_span->x = (short)(x + m_min_x); + m_cur_span->len = (short)len; + m_cur_span->covers = m_covers + x; + } + m_last_x = x + len - 1; + } + + template void scanline_u::add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; + memset(m_covers + x, cover, len); + if(x == m_last_x+1) + { + m_cur_span->len += (short)len; + } + else + { + m_cur_span++; + m_cur_span->x = (short)(x + m_min_x); + m_cur_span->len = (short)len; + m_cur_span->covers = m_covers + x; + } + m_last_x = x + len - 1; + } + + typedef scanline_u scanline_u8; + typedef scanline_u scanline_u16; + typedef scanline_u scanline_u32; +} + +#endif //SCANLINE_AA_HPP diff --git a/include/spatial.hpp b/include/spatial.hpp new file mode 100644 index 000000000..c8ba1e417 --- /dev/null +++ b/include/spatial.hpp @@ -0,0 +1,151 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef SPATIAL_HPP +#define SPATIAL_HPP + +#include "filter.hpp" +#include "filter_visitor.hpp" + +namespace mapnik +{ + + template + struct equals_ : public filter + { + + bool pass(const FeatureT& feature) const + { + return false; + } + + void accept(const filter_visitor& v) + { + v.visit(*this); + } + }; + + template + struct disjoint : public filter + { + + + bool pass(const FeatureT& feature) const + { + return false; + } + + void accept(const filter_visitor& v) + { + v.visit(*this); + } + }; + + template + struct touches : public filter + { + + + bool pass(const FeatureT& feature) const + { + return false; + } + + void accept(const filter_visitor& v) + { + v.visit(*this); + } + }; + + template + struct within : public filter + { + + bool pass(const FeatureT& feature) const + { + return false; + } + + void accept(const filter_visitor& v) + { + v.visit(*this); + } + }; + + template + struct overlaps : public filter + { + + bool pass(const FeatureT& feature) const + { + return false; + } + + void accept(const filter_visitor& v) + { + v.visit(*this); + } + }; + + template + struct crosses : public filter + { + + + bool pass(const FeatureT& feature) const + { + return false; + } + + void accept(const filter_visitor& v) + { + v.visit(*this); + } + }; + + template + struct bbox : public filter + { + private: + Envelope box_; + public: + bbox(const Envelope& box) + : box_(box) {} + + + bool pass(const FeatureT& feature) const + { + return box_.contains(feature.get_geometry()->bbox()); + } + + + filter* clone() const + { + return new bbox(box_); + } + void accept(const filter_visitor& v) + { + v.visit(*this); + } + + + virtual ~bbox() {} + }; +} + +#endif //SPATIAL_HPP diff --git a/include/stroke.hpp b/include/stroke.hpp new file mode 100644 index 000000000..1373fbe13 --- /dev/null +++ b/include/stroke.hpp @@ -0,0 +1,166 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef STROKE_HPP +#define STROKE_HPP + +#include "color.hpp" +#include + +namespace mapnik +{ + using std::pair; + using std::vector; + typedef vector > dash_array; + + enum line_cap_e + { + BUTT_CAP, + SQUARE_CAP, + ROUND_CAP + }; + + enum line_join_e + { + MITER_JOIN, + MITER_REVERT_JOIN, + ROUND_JOIN, + BEVEL_JOIN + }; + + class stroke + { + Color c_; + float width_; + float opacity_; // 0.0 - 1.0 + line_cap_e line_cap_; + line_join_e line_join_; + dash_array dash_; + public: + stroke() + : c_(), + width_(1.0), + opacity_(1.0), + line_cap_(BUTT_CAP), + line_join_(MITER_JOIN), + dash_() {} + + stroke(Color const& c, float width=1.0) + : c_(c), + width_(width), + opacity_(1.0), + line_cap_(BUTT_CAP), + line_join_(MITER_JOIN), + dash_() {} + + stroke(stroke const& other) + : c_(other.c_), + width_(other.width_), + opacity_(other.opacity_), + line_cap_(other.line_cap_), + line_join_(other.line_join_), + dash_(other.dash_) {} + + stroke& operator=(const stroke& rhs) + { + stroke tmp(rhs); + swap(tmp); + return *this; + } + + void set_color(const Color& c) + { + c_=c; + } + + Color const& get_color() const + { + return c_; + } + + float get_width() const + { + return width_; + } + void set_width(float w) + { + width_=w; + } + + void set_opacity(float opacity) + { + if (opacity > 1.0) opacity_=1.0; + else if (opacity < 0.0) opacity_=0.0; + else opacity_=opacity; + } + + float get_opacity() const + { + return opacity_; + } + + void set_line_cap(line_cap_e line_cap) + { + line_cap_=line_cap; + } + + line_cap_e get_line_cap() const + { + return line_cap_; + } + + void set_line_join(line_join_e line_join) + { + line_join_=line_join; + } + + line_join_e get_line_join() const + { + return line_join_; + } + + void add_dash(float dash,float gap) + { + dash_.push_back(std::make_pair(dash,gap)); + } + bool has_dash() const + { + return dash_.size(); + } + + dash_array const& get_dash_array() const + { + return dash_; + } + + private: + void swap(const stroke& other) throw() + { + c_=other.c_; + width_=other.width_; + opacity_=other.opacity_; + line_cap_=other.line_cap_; + line_join_=other.line_join_; + dash_ = other.dash_; + } + }; +} + +#endif //STROKE_HPP diff --git a/include/style.hpp b/include/style.hpp new file mode 100644 index 000000000..bf7a95af5 --- /dev/null +++ b/include/style.hpp @@ -0,0 +1,80 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: style.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef STYLE_HPP +#define STYLE_HPP + +//#include "feature.hpp" +#include "color.hpp" +#include "ptr.hpp" +#include "symbolizer.hpp" +//#include "rule.hpp" + +#include +#include +#include + +namespace mapnik +{ + class Style + { + private: + std::vector > symbols_; + static ref_ptr zero_symbol_; + public: + typedef std::vector >::const_iterator Iterator; + + Style() {} + + Style(const ref_ptr& symbol) + { + symbols_.push_back(symbol); + } + + ~Style() {} + + Style(const Style& rhs) + : symbols_(rhs.symbols_) {} + + Style& operator=(const Style& rhs) + { + if (this==&rhs) return *this; + symbols_=rhs.symbols_; + return *this; + } + + void add(const ref_ptr& symbol) + { + symbols_.push_back(symbol); + } + + Iterator begin() const + { + return symbols_.begin(); + } + + Iterator end() const + { + return symbols_.end(); + } + }; +} + +#endif //STYLE_HPP diff --git a/include/style_cache.hpp b/include/style_cache.hpp new file mode 100644 index 000000000..725981a59 --- /dev/null +++ b/include/style_cache.hpp @@ -0,0 +1,64 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: style_cache.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef STYLE_CACHE_HPP +#define STYLE_CACHE_HPP + +#include "utils.hpp" +#include "ptr.hpp" +#include "style.hpp" +#include +#include "feature_type_style.hpp" + +namespace mapnik { + + class style_cache : public singleton + { + friend class CreateStatic; + private: + static std::map styles_; + style_cache(); + ~style_cache(); + style_cache(const style_cache&); + style_cache& operator=(const style_cache&); + public: + static bool insert(const std::string& name,const Style& style); + static void remove(const std::string& name); + static const Style& find(const std::string& name); + }; + + class named_style_cache : public singleton + { + friend class CreateStatic; + private: + static std::map styles_; + named_style_cache(); + ~named_style_cache(); + named_style_cache(const named_style_cache&); + named_style_cache& operator=(const named_style_cache&); + public: + static bool insert(const std::string& name,const feature_type_style& style); + static void remove(const std::string& name); + static feature_type_style find(const std::string& name); + }; +} + + +#endif //STYLE_CACHE_HPP diff --git a/include/style_factory.hpp b/include/style_factory.hpp new file mode 100644 index 000000000..8022b18fb --- /dev/null +++ b/include/style_factory.hpp @@ -0,0 +1,34 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: style_factory.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef STYLE_FACTORY_HPP +#define STYLE_FACTORY_HPP + +#include "style.hpp" + +namespace mapnik { + + class style_factory + { + }; +} + + +#endif //STYLE_FACTORY_HPP diff --git a/include/symbolizer.hpp b/include/symbolizer.hpp new file mode 100644 index 000000000..630dfd1f3 --- /dev/null +++ b/include/symbolizer.hpp @@ -0,0 +1,39 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: symbolizer.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef SYMBOLIZER_HPP +#define SYMBOLIZER_HPP + +#include "graphics.hpp" +#include "geometry.hpp" +#include + +namespace mapnik +{ + class Image32; + + struct symbolizer + { + virtual void render(geometry_type& geom, Image32& image) const=0; + virtual ~symbolizer() {} + }; +} + +#endif //SYMBOLIZER_HPP diff --git a/include/text.hpp b/include/text.hpp new file mode 100644 index 000000000..df70c28d7 --- /dev/null +++ b/include/text.hpp @@ -0,0 +1,52 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: text.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef TEXT_HPP +#define TEXT_HPP + +#ifdef __HAVE_FREETYPE2__ //TODO:: fix configure.ac AP_CHECK_FREETYPE2 + +#include +#include FT_FREETYPE_H +#include +#include +#include "style.hpp" +#include "graphics.hpp" + +namespace mapnik +{ + template class TextRasterizer + { + private: + PixBuffer* pixbuf_; + std::string fontName_; + public: + TextRasterizer(PixBuffer& pixbuf,const char* fontName) + :pixbuf_(&pixbuf), + fontName_(fontName) {} + void render(const char* text); + private: + TextRasterizer(const TextRasterizer&); + TextRasterizer& operator=(const TextRasterizer&); + void render_bitmap(FT_Bitmap *bitmap,int x,int y); + }; +} +#endif +#endif //TEXT_HPP diff --git a/include/text_symbolizer.hpp b/include/text_symbolizer.hpp new file mode 100644 index 000000000..b69b5292e --- /dev/null +++ b/include/text_symbolizer.hpp @@ -0,0 +1,56 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef TEXT_SYMBOLIZER_HPP +#define TEXT_SYMBOLIZER_HPP + +#include "symbolizer.hpp" +#include "fill.hpp" +#include "expression.hpp" + +namespace mapnik +{ + template + struct text_symbolizer : public symbolizer + { + text_symbolizer(expression const& label,fill const& f) + : label_(label.clone()), + fill_(f) {} + + ~text_symbolizer() + { + delete label_; + } + + void render(geometry_type& geom,Image32& image) const + { + //todo : render text + } + private: + expression* label_; + fill fill_; + + private: + text_symbolizer(const text_symbolizer&); + text_symbolizer& operator=(const text_symbolizer&); + }; +} + +#endif //TEXT_SYMBOLIZER_HPP diff --git a/include/utils.hpp b/include/utils.hpp new file mode 100644 index 000000000..ed98168ed --- /dev/null +++ b/include/utils.hpp @@ -0,0 +1,308 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: utils.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef UTILS_HPP +#define UTILS_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace mapnik +{ + class Mutex; + class Lock; + + template + class CreateUsingNew + { + public: + static T* create() + { + return new T; + } + static void destroy(T* obj) + { + delete obj; + } + }; + + template + class CreateStatic + { + private: + union MaxAlign + { + char t_[sizeof(T)]; + short int shortInt_; + int int_; + long int longInt_; + float float_; + double double_; + long double longDouble_; + struct Test; + int Test::* pMember_; + int (Test::*pMemberFn_)(int); + }; + public: + static T* create() + { + static MaxAlign staticMemory; + return new(&staticMemory) T; + } + static void destroy(volatile T* obj) + { + obj->~T(); + } + }; + + template class CreatePolicy=CreateStatic> class singleton + { + friend class CreatePolicy; + static T* pInstance_; + static bool destroyed_; + singleton(const singleton &rhs); + singleton& operator=(const singleton&); + static void onDeadReference() + { + throw std::runtime_error("dead reference!"); + } + protected: + static Mutex mutex_; + singleton() {} + virtual ~singleton() + { + CreatePolicy::destroy(pInstance_); + destroyed_=true; + } + public: + static T* instance() + { + if (!pInstance_) + { + Lock lock(&mutex_); + if (!pInstance_) + { + if (destroyed_) + { + onDeadReference(); + } + else + { + pInstance_=CreatePolicy::create(); + } + } + } + return pInstance_; + } + }; + + template class CreatePolicy> Mutex singleton::mutex_; + template class CreatePolicy> T* singleton::pInstance_=0; + template class CreatePolicy> bool singleton::destroyed_=false; + + template class Handle + { + T* ptr_; + int* pCount_; + public: + T* operator->() {return ptr_;} + const T* operator->() const {return ptr_;} + Handle(T* ptr) + :ptr_(ptr),pCount_(new int(1)) {} + Handle(const Handle& rhs) + :ptr_(rhs.ptr_),pCount_(rhs.pCount_) + { + (*pCount_)++; + } + Handle& operator=(const Handle& rhs) + { + if (ptr_==rhs.ptr_) return *this; + if (--(*pCount_)==0) + { + delete ptr_; + delete pCount_; + } + ptr_=rhs.ptr_; + pCount_=rhs.pCount_; + (*pCount_)++; + return *this; + } + ~Handle() + { + if (--(*pCount_)==0) + { + delete ptr_; + delete pCount_; + } + } + }; + + class Mutex + { + private: + pthread_mutex_t mutex_; + public: + Mutex() + { + pthread_mutex_init(&mutex_,0); + } + void lock() + { + pthread_mutex_lock(&mutex_); + } + void unlock() + { + pthread_mutex_unlock(&mutex_); + } + bool trylock() + { + return (pthread_mutex_trylock(&mutex_)==0); + } + ~Mutex() + { + pthread_mutex_destroy(&mutex_); + } + }; + + class Lock + { + private: + Mutex* mutex_; + public: + explicit Lock(Mutex* mutex) + :mutex_(mutex) + { + if (mutex_) mutex_->lock(); + } + + ~Lock() + { + if (mutex_) + mutex_->unlock(); + } + private: + Lock(); + Lock(const Lock&); + Lock& operator=(const Lock&); + void* operator new(std::size_t); + void* operator new[](std::size_t); + void operator delete(void*); + void operator delete[](void*); + Lock* operator&(); + }; + + class Functor + { + public: + virtual void operator()() const=0; + }; + + struct timer + { + struct timeval tv_; + timer() + { + gettimeofday (&tv_,0); + } + void start() + { + gettimeofday (&tv_,0); + } + void stop() + { + timeval tv; + gettimeofday (&tv,0); + std::ostringstream s; + long sec=1000*(tv.tv_sec-tv_.tv_sec); + long total_ms=sec+static_cast(0.001*(tv.tv_usec-tv_.tv_usec)); + s << "elapsed time is "< + inline std::string toString(const T& x) + { + std::ostringstream o; + if (!(o << x)) + throw BadConversion(std::string("toString(") + + typeid(x).name() + ")"); + return o.str(); + } + + template + inline void fromString(const std::string& s, T& x, + bool failIfLeftoverChars = true) + { + std::istringstream i(s); + char c; + if (!(i >> x) || (failIfLeftoverChars && i.get(c))) + throw BadConversion("fromString("+s+")"); + } + + + + inline bool space (char c) + { + return isspace(c); + } + + inline bool not_space (char c) + { + return !isspace(c); + } + + inline std::string trim_left(const std::string& str) + { + typedef std::string::const_iterator iter; + iter i = find_if(str.begin(),str.end(),not_space); + return std::string(i,str.end()); + } + inline std::string trim_right(const std::string& str) + { + std::string::size_type idx=str.find_last_not_of(" "); + return str.substr(0,idx+1); + } + inline std::string trim(const std::string& str) + { + return trim_left(trim_right(str)); + } +} + + +#endif //UTILS_HPP diff --git a/include/value.hpp b/include/value.hpp new file mode 100644 index 000000000..03d4fe217 --- /dev/null +++ b/include/value.hpp @@ -0,0 +1,494 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#ifndef VALUE_HPP +#define VALUE_HPP + +#include +#include +#include + +using std::string; +using namespace boost; +namespace mapnik { namespace impl { + + typedef variant value_holder; + + class equals + : public boost::static_visitor + { + public: + template + bool operator()( const T &, const U & ) const + { + return false; + } + + bool operator() (int lhs, int rhs) const + { + return lhs == rhs; + } + + bool operator() (double lhs, double rhs) const + { + return lhs == rhs; + } + + bool operator() (int lhs, double rhs) const + { + return lhs == rhs; + } + + bool operator() (double lhs, int rhs) const + { + return lhs == rhs; + } + + template + bool operator()( const T & lhs, const T & rhs ) const + { + return lhs == rhs; + } + }; + + class greater_than + : public boost::static_visitor + { + public: + template + bool operator()( const T &, const U & ) const + { + return false; + } + + bool operator() (int lhs, int rhs) const + { + return lhs > rhs; + } + + bool operator() (double lhs, double rhs) const + { + return lhs > rhs; + } + + bool operator() (int lhs, double rhs) const + { + return lhs > rhs; + } + + bool operator() (double lhs, int rhs) const + { + return lhs > rhs; + } + + template + bool operator()( const T & lhs, const T & rhs ) const + { + return lhs > rhs; + } + }; + class greater_or_equal + : public boost::static_visitor + { + public: + template + bool operator()( const T &, const U & ) const + { + return false; + } + + bool operator() (int lhs, int rhs) const + { + return lhs >= rhs; + } + + bool operator() (double lhs, double rhs) const + { + return lhs >= rhs; + } + + bool operator() (int lhs, double rhs) const + { + return lhs >= rhs; + } + + bool operator() (double lhs, int rhs) const + { + return lhs >= rhs; + } + + template + bool operator()( const T & lhs, const T & rhs ) const + { + return lhs >= rhs; + } + }; + + class less_than + : public boost::static_visitor + { + public: + template + bool operator()( const T &, const U & ) const + { + return false; + } + + bool operator() (int lhs, int rhs) const + { + return lhs < rhs; + } + + bool operator() (double lhs, double rhs) const + { + return lhs < rhs; + } + + bool operator() (int lhs, double rhs) const + { + return lhs < rhs; + } + + bool operator() (double lhs, int rhs) const + { + return lhs < rhs; + } + + template + bool operator()( const T & lhs, const T & rhs ) const + { + return lhs < rhs; + } + }; + + class less_or_equal + : public boost::static_visitor + { + public: + template + bool operator()( const T &, const U & ) const + { + return false; + } + + bool operator() (int lhs, int rhs) const + { + return lhs <= rhs; + } + + bool operator() (double lhs, double rhs) const + { + return lhs <= rhs; + } + + bool operator() (int lhs, double rhs) const + { + return lhs <= rhs; + } + + bool operator() (double lhs, int rhs) const + { + return lhs <= rhs; + } + + template + bool operator()( const T & lhs, const T & rhs ) const + { + return lhs <= rhs; + } + }; + + struct add : public boost::static_visitor + { + template + value_holder operator() (T1 const& , T2 const&) const + { + return value_holder(); + } + template + value_holder operator() (T const& lhs, T const& rhs) const + { + return lhs + rhs ; + } + value_holder operator() (int lhs,int rhs) const + { + return lhs + rhs; + } + value_holder operator() (double lhs, double rhs) const + { + return lhs + rhs; + } + + value_holder operator() (double lhs, int rhs) const + { + return lhs + rhs; + } + + value_holder operator() (int lhs, double rhs) const + { + return lhs + rhs; + } + }; + + struct sub : public boost::static_visitor + { + template + value_holder operator() (T1 const& lhs, T2 const&) const + { + return value_holder(lhs); + } + + template + value_holder operator() (T const& lhs, T const& rhs) const + { + return lhs - rhs ; + } + + value_holder operator() (string const& lhs,string const& ) const + { + return lhs; + } + + value_holder operator() (int lhs,int rhs) const + { + return lhs - rhs; + } + + value_holder operator() (double lhs, double rhs) const + { + return lhs - rhs; + } + + value_holder operator() (double lhs, int rhs) const + { + return lhs - rhs; + } + + value_holder operator() (int lhs, double rhs) const + { + return lhs - rhs; + } + }; + + struct mult : public boost::static_visitor + { + template + value_holder operator() (T1 const&, T2 const& ) const + { + return value_holder(); + } + template + value_holder operator() (T const& lhs, T const& rhs) const + { + return lhs * rhs; + } + + value_holder operator() (string const& lhs,string const& ) const + { + return lhs; + } + + value_holder operator() (int lhs,int rhs) const + { + return lhs * rhs; + } + + value_holder operator() (double lhs, double rhs) const + { + return lhs * rhs; + } + + value_holder operator() (double lhs, int rhs) const + { + return lhs * rhs; + } + + value_holder operator() (int lhs, double rhs) const + { + return lhs * rhs; + } + }; + + struct div: public boost::static_visitor + { + template + value_holder operator() (T1 const&, T2 const&) const + { + return value_holder(); + } + template + value_holder operator() (T const& lhs, T const& rhs) const + { + return lhs / rhs; + } + + value_holder operator() (string const& lhs,string const&) const + { + return lhs; + } + + value_holder operator() (int lhs,int rhs) const + { + return lhs / rhs; + } + + value_holder operator() (double lhs, double rhs) const + { + return lhs / rhs; + } + + value_holder operator() (double lhs, int rhs) const + { + return lhs / rhs; + } + + value_holder operator() (int lhs, double rhs) const + { + return lhs / rhs; + } + }; +} + + using namespace impl; + + class value + { + public: + value(int i) + : v_(i) {} + + value(double d) + : v_(d) {} + + value(string const& str) + : v_(str) {} + + value(value const& other) + : v_ (other.v_) {} + + bool operator==(value const& other) const + { + return apply_visitor(equals(),v_,other.get()); + } + + bool operator!=(value const& other) const + { + return !(apply_visitor(equals(),v_,other.get())); + } + + bool operator>(value const& other) const + { + return apply_visitor(greater_than(),v_,other.get()); + } + + bool operator>=(value const& other) const + { + return apply_visitor(greater_or_equal(),v_,other.get()); + } + + bool operator<(value const& other) const + { + return apply_visitor(less_than(),v_,other.get()); + } + + bool operator<=(value const& other) const + { + return apply_visitor(less_or_equal(),v_,other.get()); + } + + value& operator+=(value const& other) + { + v_ = apply_visitor(add(),v_,other.get()); + return *this; + } + + value& operator-=(value const& other) + { + v_ = apply_visitor(sub(),v_,other.get()); + return *this; + } + + value& operator*=(value const& other) + { + v_ = apply_visitor(mult(),v_,other.get()); + return *this; + } + + value& operator/=(value const& other) + { + v_ = apply_visitor(div(),v_,other.get()); + return *this; + } + + value_holder const& get() const + { + return v_; + } + + string to_string() const + { + std::stringstream ss; + ss << v_; + return ss.str(); + } + + private: + value_holder v_; + }; + + inline const value operator+(value const& p1,value const& p2) + { + value tmp(p1); + tmp+=p2; + return tmp; + } + + inline const value operator-(value const& p1,value const& p2) + { + value tmp(p1); + tmp-=p2; + return tmp; + } + + inline const value operator*(value const& p1,value const& p2) + { + value tmp(p1); + tmp*=p2; + return tmp; + } + + inline const value operator/(value const& p1,value const& p2) + { + value tmp(p1); + tmp/=p2; + return tmp; + } + + template + inline std::basic_ostream& + operator << (std::basic_ostream& out, + value const& v) + { + out << v.get(); + return out; + } +} + +#endif //VALUE_HPP diff --git a/include/vertex.hpp b/include/vertex.hpp new file mode 100644 index 000000000..99f1e0450 --- /dev/null +++ b/include/vertex.hpp @@ -0,0 +1,110 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details.#include "memory.hpp" + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: vertex.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef VERTEX_HPP +#define VERTEX_HPP + +#include +#include + +namespace mapnik +{ + enum + { + SEG_END =0, + SEG_MOVETO=1, + SEG_LINETO=2, + SEG_CLOSE =3 + }; + + template + struct vertex { + typedef T type; + }; + + template + struct vertex + { + typedef T type; + T x; + T y; + unsigned cmd; + vertex() + : x(0),y(0),cmd(SEG_END) {} + vertex(T x,T y,unsigned cmd) + : x(x),y(y),cmd(cmd) {} + + template + vertex(const vertex& rhs) + : x(type(rhs.x)), + y(type(rhs.y)), + cmd(rhs.cmd) {} + + template vertex operator=(const vertex& rhs) + { + if ((void*)this == (void*)&rhs) + { + return *this; + } + x=type(rhs.x); + y=type(rhs.y); + cmd=rhs.cmd; + return *this; + } + }; + + typedef vertex vertex2d; + typedef vertex vertex2i; + + + template + inline std::basic_ostream& + operator << (std::basic_ostream& out, + const vertex& c); + + template + inline std::basic_ostream& + operator << (std::basic_ostream& out, + const vertex& v) + { + std::basic_ostringstream s; + s.copyfmt(out); + s.width(0); + s<<"vertex2("< + inline std::basic_ostream& + operator << (std::basic_ostream& out, + const vertex& v) + { + std::basic_ostringstream s; + s.copyfmt(out); + s.width(0); + s<<"vertex3("< + struct Shift + { + typedef T0 value_type; + typedef T1 return_type; + static return_type apply(value_type val) + { + return static_cast(val*(1< + struct Shift + { + typedef T0 value_type; + typedef T1 return_type; + static return_type apply(value_type val) + { + return static_cast(val); + } + }; + + template + struct Shift + { + typedef T value_type; + typedef T return_type; + static T& apply(T& val) + { + return val; + } + }; + + typedef Shift NO_SHIFT; + typedef Shift SHIFT0; + typedef Shift SHIFT8; + + + template + struct view_transform; + + template + struct view_transform + { + + }; + + template + struct view_transform + { + + }; + + template + struct view_transform,Envelope,Trans> + { + + }; +} + +#endif //VERTEX_TRANSFORM_HPP diff --git a/include/vertex_vector.hpp b/include/vertex_vector.hpp new file mode 100644 index 000000000..8d40300a6 --- /dev/null +++ b/include/vertex_vector.hpp @@ -0,0 +1,161 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details.#include "memory.hpp" + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// Credits: +// I gratefully acknowledge the inspiring work of Maxim Shemanarev (McSeem), +// author of Anti-Grain Geometry (http://www.antigrain.com). I have used +// the datastructure from AGG as a template for my own. + + +//$Id: vertex_vector.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef VERTEX_VECTOR_HPP +#define VERTEX_VECTOT_HPP + +#include "vertex.hpp" +#include "ctrans.hpp" + +namespace mapnik +{ + template + class vertex_vector + { + typedef typename T::type value_type; + typedef vertex vertex_type; + enum { + block_shift = 8, + block_size = 1<> block_shift; + if (block >= num_blocks_) + { + allocate_block(block); + } + value_type* vertex = vertexs_[block] + ((pos_ & block_mask) << 1); + unsigned char* cmd= commands_[block] + (pos_ & block_mask); + + *cmd = static_cast(command); + *vertex++ = x; + *vertex = y; + ++pos_; + } + unsigned get_vertex(unsigned pos,value_type* x,value_type* y) const + { + if (pos >= pos_) return SEG_END; + unsigned block = pos >> block_shift; + const value_type* vertex = vertexs_[block] + (( pos & block_mask) << 1); + *x = (*vertex++); + *y = (*vertex); + return commands_[block] [pos & block_mask]; + } + unsigned get_at(unsigned pos,value_type& x,value_type& y) const + { + if (pos >= pos_) return SEG_END; + unsigned block = pos >> block_shift; + const value_type* vertex = vertexs_[block] + (( pos & block_mask) << 1); + x = (*vertex++); + y = (*vertex); + return commands_[block] [pos & block_mask]; + } + + unsigned get_at(unsigned pos,vertex_type& v) const + { + if (pos >= pos_) return SEG_END; + unsigned block = pos >> block_shift; + const value_type* vertex = vertexs_[block] + (( pos & block_mask) << 1); + unsigned char* cmd= commands_[block] + (pos_ & block_mask); + v.x=(*vertex++); + v.y=(*vertex); + return commands_[block] [pos & block_mask]; + } + + void transform_at(unsigned pos,const CoordTransform& t) + { + if (pos >= pos_) return; + unsigned block = pos >> block_shift; + value_type* vertex = vertexs_[block] + (( pos & block_mask) << 1); + *vertex=t.forward_x(*vertex); + ++vertex; + *vertex=t.forward_y(*vertex); + } + + private: + vertex_vector(const vertex_vector&); + vertex_vector& operator=(const vertex_vector&); + void allocate_block(unsigned block) + { + if (block >= max_blocks_) + { + value_type** new_vertexs = new value_type* [(max_blocks_ + grow_by) * 2]; + unsigned char** new_commands = (unsigned char**)(new_vertexs + max_blocks_ + grow_by); + if (vertexs_) + { + std::memcpy(new_vertexs,vertexs_,max_blocks_ * sizeof(value_type*)); + std::memcpy(new_commands,commands_,max_blocks_ * sizeof(unsigned char*)); + delete [] vertexs_; + } + vertexs_ = new_vertexs; + commands_ = new_commands; + max_blocks_ += grow_by; + } + vertexs_[block] = new value_type [block_size * 2 + block_size / (sizeof(value_type))]; + commands_[block] = (unsigned char*)(vertexs_[block] + block_size*2); + ++num_blocks_; + } + }; +} + +#endif //VERTEX_VECTOR_HPP diff --git a/include/wkb.hpp b/include/wkb.hpp new file mode 100644 index 000000000..70bce6368 --- /dev/null +++ b/include/wkb.hpp @@ -0,0 +1,39 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: wkb.hpp 39 2005-04-10 20:39:53Z pavlenko $ + +#ifndef WKB_HPP +#define WKB_HPP + +#include "geometry.hpp" +#include "ctrans.hpp" + +namespace mapnik +{ + class geometry_utils + { + public: + static geometry_ptr from_wkb(const char* wkb, unsigned size,int srid); + private: + geometry_utils(); + geometry_utils(const geometry_utils&); + geometry_utils& operator=(const geometry_utils&); + }; +} +#endif //WKB_HPP diff --git a/python/Jamfile b/python/Jamfile new file mode 100644 index 000000000..4c2bfe232 --- /dev/null +++ b/python/Jamfile @@ -0,0 +1,16 @@ +import python ; + +#project : requirements /opt/boost/python//python ; +alias python : /opt/boost/libs/python/build//python/static ; + +python-extension mapnik-python + : mapnik_parameters.cc + mapnik_color.cc + mapnik_layer.cc + mapnik_envelope.cc + mapnik_map.cc + mapnik_image.cc + mapnik_python.cc + python + #/dist/lib/libmapnik.so +; diff --git a/python/SConscript b/python/SConscript new file mode 100644 index 000000000..8a4f448b1 --- /dev/null +++ b/python/SConscript @@ -0,0 +1,81 @@ +import os +import SCons.Errors +import SCons.Defaults +import glob + +Import('env') + +#env.Append(CCFLAGS = ' -DBOOST_PYTHON_DYNAMIC_LIB') + +#boost python +prefix = env['PREFIX'] +boost_root = env['BOOST_ROOT'] +python_root = env['PYTHON_ROOT'] +python_version = env['PYTHON_VERSION'] +python_headers = python_root+'/include/python'+python_version + +boost_python_src_dir = boost_root + '/libs/python/src/' + +boost_python_src = glob.glob(boost_python_src_dir + '*.cpp') +boost_python_src.append(glob.glob(boost_python_src_dir + 'object/*.cpp')) +boost_python_src.append(glob.glob(boost_python_src_dir + 'converter/*.cpp')) + +python_cpppath = python_root+'/include/python'+python_version +lib_boost_python = env.SharedLibrary('libboost-python',boost_python_src,CPPPATH=[boost_root,python_cpppath]) + +env.Install(prefix + '/lib',lib_boost_python) + +agg_root = env['AGG_ROOT'] +agg_headers = agg_root +'/include' +freetype2_root = env['FREETYPE2_ROOT'] + + +def createPythonExtBuilder(env): + """This is a utility function that creates boost-python + etxension Builder in an Environment if it is not there already. + If it is already there, we return the existing one. + """ + + try: + python_ext = env['BUILDERS']['PythonExtension'] + except KeyError: + action_list = [ SCons.Defaults.SharedCheck, + SCons.Defaults.ShLinkAction ] + python_ext = SCons.Builder.Builder(action = action_list, + emitter = "$SHLIBEMITTER", + prefix = '', + suffix = '$SHLIBSUFFIX', + target_scanner = SCons.Defaults.ProgScan, + src_suffix = '$SHOBJSUFFIX', + src_builder = 'SharedObject') + env['BUILDERS']['PythonExtension'] = python_ext + + return python_ext + +createPythonExtBuilder(env) + +mapnik_python_src=Split( + """ + mapnik_color.cpp + mapnik_envelope.cpp + mapnik_image.cpp + mapnik_layer.cpp + mapnik_map.cpp + mapnik_parameters.cpp + mapnik_filter.cpp + mapnik_rule.cpp + mapnik_style.cpp + mapnik_stroke.cpp + mapnik_datasource_cache.cpp + mapnik_python.cpp + """ + ) + +headers =[ '#include',boost_root,freetype2_root,agg_headers,python_headers] + +libraries=['mapnik','agg','boost-filesystem','boost-regex','boost-python'] +libpaths = [prefix+"/lib",'#agg'] + +mapnik_python = env.PythonExtension(target='mapnik',source=mapnik_python_src,CPPPATH=headers,LIBS=libraries,LIBPATH=libpaths) + +env.Alias(target="install",source=env.Install(prefix+'/lib',mapnik_python)) diff --git a/python/hello.py b/python/hello.py new file mode 100755 index 000000000..73d38d075 --- /dev/null +++ b/python/hello.py @@ -0,0 +1,186 @@ +#!/usr/bin/env /opt/python/bin/python +import sys +from qt import * +from qtcanvas import * +from dl import * +sys.setdlopenflags(RTLD_NOW | RTLD_GLOBAL) +from mapnik import * + +def load_styles() : + print 'loading styles...' + styles=style_cache.instance() + styles.insert("mystyle",style(create_polygon_symbolizer(color(255,255,204)))) + styles.insert("water",style(create_polygon_symbolizer(color(102,153,255)))) + styles.insert("parks",style(create_polygon_symbolizer(color(200,230,120)))) + styles.insert("roads",style(create_line_symbolizer(color(204,204,153),2.3))) + styles.insert("dots",style(create_point_symbolizer("/home/artem/smiley.png",12,12))) + print 'done' + +def create_map(width,height) : + + m=map(width,height) + bg=color(102,153,255) + m.background(bg) + + p={"type":"raster", + "format":"tiff", + "name":"world dem", + "file":"/home/artem/projects/data/raster/world_tiled1.tif", + "lox":"-180","loy":"-90","hix":"180","hiy":"90"} + lyr=create_layer(p) + lyr.minzoom(0.2) + lyr.maxzoom(1.0) + m.add(lyr) + + p={"type":"raster", + "format":"tiff", + "name":"world dem", + "file":"/home/artem/projects/data/raster/world_tiled2.tif", + "lox":"-180","loy":"-90","hix":"180","hiy":"90"} + print p + lyr=create_layer(p) + lyr.minzoom(0.005) + lyr.maxzoom(0.2) + m.add(lyr) + + p=parameters() + p.add("type","shape") + p.add("name","usa") + p.add("file","/home/artem/projects/data/usa/dtl_cnty") + lyr=layer(p) + #lyr.maxzoom(0.005) + lyr.style("mystyle") + m.add(lyr) + + p=parameters() + #p.add("type","shape") + #p.add("file","/home/artem/projects/data/usa/mjwater") + p.add("type","postgis") + p.add("host","localhost") + p.add("dbname","gis") + p.add("post","5432") + p.add("user","postgres") + p.add("name","water") + p.add("table","water") + + lyr=layer(p) + lyr.maxzoom(0.005) + lyr.style("water") + m.add(lyr) + + p=parameters() + p.add("type","shape") + p.add("name","parks") + p.add("file","/home/artem/projects/data/usa/parks") + lyr=layer(p) + lyr.maxzoom(0.02) + lyr.style("parks") + m.add(lyr) + + p=parameters() + p.add("type","shape") + p.add("name","tiger") + p.add("file","/home/artem/projects/data/tiger/ca/tiger") + lyr=layer(p) + lyr.maxzoom(0.0005) + lyr.style("roads") + m.add(lyr) + + p=parameters() + #p.add("type","shape") + #p.add("name","maj roads") + p.add("type","postgis") + p.add("host","localhost") + p.add("dbname","gis") + p.add("post","5432") + p.add("user","postgres") + p.add("name","roads") + p.add("table","roads") + + #p.add("file","/home/artem/projects/data/usa/mjrrds") + lyr=layer(p) + lyr.minzoom(0.0005) + lyr.maxzoom(0.005) + lyr.style("roads") + m.add(lyr) + + p=parameters() + #p.add("type","shape") + + p.add("name","cities") + #p.add("file","/home/artem/projects/data/usa/cities") + p.add("type","postgis") + p.add("host","localhost") + p.add("dbname","gis") + p.add("post","5432") + p.add("user","postgres") + p.add("table","cities") + lyr=layer(p) + lyr.style("dots") + m.add(lyr) + + box=envelope(-123.24,37.094,-121.349,38.512) + m.zoom_to_box(box) + return m + +class MapWidget(QWidget) : + def __init__(self,*args): + QWidget.__init__(self,*args) + self.buffer = QPixmap(600,300) + self.buffer.fill(QColor(200,200,200)) + #self.pixbuf.load("/home/artem/map.png") + self.map=create_map(600,300) + + def paintEvent(self,ev): + bitBlt(self,0,0,self.buffer) + + def keyPressEvent(self,ev) : + if ev.key() == 45 : + self.zoom_out() + self.render_image() + elif ev.key() == 61: + self.zoom_in() + self.render_image() + else: + QWidget.keyPressEvent(self,ev) + + def mousePressEvent(self,ev): + if ev.button() == 1 : + self.map.pan(ev.x(),ev.y()) + self.render_image() + else : + print "todo" + + def zoom_in (self) : + self.map.zoom(0.5) + + def zoom_out(self): + self.map.zoom(2.0) + + def render_image (self) : + render_to_file(self.map,"/home/artem/map.png","png") + self.buffer.load("/home/artem/map.png") + self.repaint() + + +class MainWindow(QMainWindow): + def __init__(self,*args): + QMainWindow.__init__(self,*args) + self.setCaption("simple map viewer") + self.painting = MapWidget(self) + self.setCentralWidget(self.painting) + + +def main(args): + app=QApplication(args) + load_styles() + win=MapWidget() + win.resize(600,300) + win.show() + win.setFocusPolicy(QWidget.StrongFocus) + app.connect(app, SIGNAL("lastWindowClosed()"), + app, SLOT("quit()")) + app.exec_loop() + +if __name__=="__main__": + main(sys.argv) diff --git a/python/mapnik_color.cpp b/python/mapnik_color.cpp new file mode 100644 index 000000000..97ac036d6 --- /dev/null +++ b/python/mapnik_color.cpp @@ -0,0 +1,50 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: mapnik_color.cc 17 2005-03-08 23:58:43Z pavlenko $ + + +#include +#include + +using mapnik::Color; + +struct color_pickle_suite : boost::python::pickle_suite +{ + static boost::python::tuple + getinitargs(const Color& c) + { + using namespace boost::python; + return boost::python::make_tuple(c.red(),c.green(),c.blue()); + } +}; + +void export_color () +{ + using namespace boost::python; + class_("color",init<>()) + .def(init()) + .def("red",&Color::red) + .def("green",&Color::green) + .def("blue",&Color::blue) + .def_pickle(color_pickle_suite()) + ; +} + + + diff --git a/python/mapnik_datasource_cache.cpp b/python/mapnik_datasource_cache.cpp new file mode 100644 index 000000000..7177f1a6f --- /dev/null +++ b/python/mapnik_datasource_cache.cpp @@ -0,0 +1,43 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#include "mapnik.hpp" +#include + +void export_datasource_cache() +{ + using mapnik::datasource_cache; + using mapnik::singleton; + using mapnik::CreateStatic; + using namespace boost::python; + class_,boost::noncopyable>("singleton",no_init) + .def("instance",&singleton::instance, + return_value_policy()) + .staticmethod("instance") + ; + + class_ >, + boost::noncopyable>("datasource_cache",no_init) + .def("create",&datasource_cache::create) + .staticmethod("create") + .def("register_datasources",&datasource_cache::register_datasources) + .staticmethod("register_datasources") + ; +} diff --git a/python/mapnik_envelope.cpp b/python/mapnik_envelope.cpp new file mode 100644 index 000000000..93617b51b --- /dev/null +++ b/python/mapnik_envelope.cpp @@ -0,0 +1,50 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: mapnik_envelope.cc 27 2005-03-30 21:45:40Z pavlenko $ + +#include +#include + +using mapnik::coord; +using mapnik::Envelope; + +struct envelope_pickle_suite : boost::python::pickle_suite +{ + static boost::python::tuple + getinitargs(const Envelope& e) + { + using namespace boost::python; + return boost::python::make_tuple(e.minx(),e.miny(),e.maxx(),e.maxy()); + } +}; + +void export_envelope() +{ + using namespace boost::python; + class_ >("envelope",init()) + .def(init<>()) + .def(init&, const coord&>()) + .add_property("minx",&Envelope::minx) + .add_property("miny",&Envelope::miny) + .add_property("maxx",&Envelope::maxx) + .add_property("maxy",&Envelope::maxy) + .def("center",&Envelope::center) + .def_pickle(envelope_pickle_suite()) + ; +} diff --git a/python/mapnik_filter.cpp b/python/mapnik_filter.cpp new file mode 100644 index 000000000..ab1791744 --- /dev/null +++ b/python/mapnik_filter.cpp @@ -0,0 +1,47 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + + +#include +#include + +using mapnik::filter; +using mapnik::filter_ptr; +using mapnik::filter_factory; +using mapnik::Feature; + +namespace +{ + using namespace boost::python; + filter_ptr create_filter(string const& filter_text) + { + filter_factory factory; + return factory.compile(filter_text); + } +} + +void export_filter() +{ + using namespace boost::python; + class_,boost::noncopyable>("filter",no_init) + .def("__str__",&filter::to_string); + ; + def("filter",&create_filter); +} diff --git a/python/mapnik_image.cpp b/python/mapnik_image.cpp new file mode 100644 index 000000000..1a97f88ba --- /dev/null +++ b/python/mapnik_image.cpp @@ -0,0 +1,38 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#include +#include + +using mapnik::Image32; + + +char const* rawdata(const Image32& image) +{ + return (char const* )image.raw_data(); +} + +void export_image() +{ + using namespace boost::python; + class_("image",init()) + ; + def("rawdata",&rawdata); +} diff --git a/python/mapnik_layer.cpp b/python/mapnik_layer.cpp new file mode 100644 index 000000000..d68fb390a --- /dev/null +++ b/python/mapnik_layer.cpp @@ -0,0 +1,114 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: mapnik_layer.cc 17 2005-03-08 23:58:43Z pavlenko $ + + +#include +#include +#include + +using mapnik::Layer; +using mapnik::Parameters; + +struct layer_pickle_suite : boost::python::pickle_suite +{ + + static boost::python::tuple + getinitargs(const Layer& l) + { + using namespace boost::python; + return boost::python::make_tuple(l.params()); + } + static boost::python::tuple + getstate(const Layer& l) + { + using namespace boost::python; + + std::vector const& styles=l.styles(); + std::vector::const_iterator itr=styles.begin(); + list py_styles; + + while (itr!=styles.end()) + { + py_styles.append(*itr++); + } + + return boost::python::make_tuple(l.getMinZoom(), + l.getMaxZoom(), + py_styles); + } + + static void + setstate (Layer& l, boost::python::tuple state) + { + using namespace boost::python; + if (len(state) != 3) + { + PyErr_SetObject(PyExc_ValueError, + ("expected 3-item tuple in call to __setstate__; got %s" + % state).ptr() + ); + throw_error_already_set(); + } + + l.setMinZoom(extract(state[0])); + l.setMaxZoom(extract(state[1])); + + list styles=extract(state[2]); + for (int i=0;i(styles[i])); + } + } +}; + +namespace +{ + //user-friendly wrapper that uses Python dictionary + using namespace boost::python; + Layer create_layer(const dict& d) + { + Parameters params; + list keys=d.keys(); + for (int i=0;i(keys[i]); + std::string value=extract(d[key]); + std::cout<("layer",init("Layer constructor")) + //class_("layer",no_init) + .def("name",&Layer::name,return_value_policy()) + .def("params",&Layer::params,return_value_policy()) + .def("envelope",&Layer::envelope,return_value_policy()) + .def("minzoom",&Layer::setMinZoom) + .def("maxzoom",&Layer::setMaxZoom) + .def("style",&Layer::add_style) + .def_pickle(layer_pickle_suite()) + ; + def("create_layer",&create_layer); +} diff --git a/python/mapnik_map.cpp b/python/mapnik_map.cpp new file mode 100644 index 000000000..9e8bf22a1 --- /dev/null +++ b/python/mapnik_map.cpp @@ -0,0 +1,92 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: mapnik_map.cc 17 2005-03-08 23:58:43Z pavlenko $ + +#include +#include +#include + +using mapnik::Color; +using mapnik::coord; +using mapnik::Envelope; +using mapnik::Layer; +using mapnik::Map; + +struct map_pickle_suite : boost::python::pickle_suite +{ + static boost::python::tuple + getinitargs(const Map& m) + { + using namespace boost::python; + return boost::python::make_tuple(m.getWidth(),m.getHeight(),m.srid()); + } + + static boost::python::tuple + getstate(const Map& m) + { + using namespace boost::python; + list l; + for (unsigned i=0;i ext = extract >(state[0]); + Color bg = extract(state[1]); + m.zoomToBox(ext); + m.setBackground(bg); + list l=extract(state[2]); + for (int i=0;i(l[i])); + } + } +}; + +void export_map() +{ + using namespace boost::python; + class_("map",init >()) + .add_property("width",&Map::getWidth) + .add_property("height",&Map::getHeight) + .def("background",&Map::setBackground) + .def("scale", &Map::scale) + .def("add",&Map::addLayer) + .def("zoom_to_box",&Map::zoomToBox) + .def("pan",&Map::pan) + .def("zoom",&Map::zoom) + .def("pan_and_zoom",&Map::pan_and_zoom) + .def_pickle(map_pickle_suite()) + ; + +} diff --git a/python/mapnik_parameters.cpp b/python/mapnik_parameters.cpp new file mode 100644 index 000000000..273880c9e --- /dev/null +++ b/python/mapnik_parameters.cpp @@ -0,0 +1,94 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: mapnik_parameters.cc 17 2005-03-08 23:58:43Z pavlenko $ + +#include +#include +#include + +using mapnik::Parameter; +using mapnik::Parameters; + + +void (Parameters::*add1)(const Parameter& param)=&Parameters::add; +void (Parameters::*add2)(const std::string&,const std::string&)=&Parameters::add; + +struct parameter_pickle_suite : boost::python::pickle_suite +{ + static boost::python::tuple + getinitargs(const Parameter& p) + { + using namespace boost::python; + return boost::python::make_tuple(p.first,p.second); + } +}; + +struct parameters_pickle_suite : boost::python::pickle_suite +{ + static boost::python::tuple + getstate(const Parameters& p) + { + using namespace boost::python; + dict d; + Parameters::const_iterator pos=p.begin(); + while(pos!=p.end()) + { + d[pos->first]=pos->second; + ++pos; + } + return boost::python::make_tuple(d); + } + + static void setstate(Parameters& p, boost::python::tuple state) + { + using namespace boost::python; + if (len(state) != 1) + { + PyErr_SetObject(PyExc_ValueError, + ("expected 1-item tuple in call to __setstate__; got %s" + % state).ptr() + ); + throw_error_already_set(); + } + dict d = extract(state[0]); + list keys=d.keys(); + for (int i=0;i(keys[i]); + std::string value=extract(d[key]); + p.add(key,value); + } + } +}; + + +void export_parameters() +{ + using namespace boost::python; + class_("parameter",init()) + .def_pickle(parameter_pickle_suite()) + ; + + class_("parameters",init<>()) + .def("add",add1) + .def("add",add2) + .def("get",&Parameters::get) + .def_pickle(parameters_pickle_suite()) + ; +} diff --git a/python/mapnik_python.cpp b/python/mapnik_python.cpp new file mode 100644 index 000000000..4aad6858e --- /dev/null +++ b/python/mapnik_python.cpp @@ -0,0 +1,142 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: mapnik_python.cc 27 2005-03-30 21:45:40Z pavlenko $ + +#include +#include +#include + +#include "mapnik.hpp" +#include "image_symbolizer.hpp" + +using namespace mapnik; + +namespace boost +{ + namespace python + { + + template class DeallocPolicy> + T* get_pointer(ref_ptr< T , DeallocPolicy> const& ptr) + { + return ( T* )ptr.get(); + } + + template + struct pointee > + { + typedef T type; + }; + + template <> struct pointee > + { + typedef datasource type; + }; + } +} + +void export_color(); +void export_layer(); +void export_parameters(); +void export_envelope(); +void export_image(); +void export_map(); +void export_python(); +void export_filter(); +void export_rule(); +void export_style(); +void export_stroke(); +void export_datasource_cache(); + +void render_to_file(const Map& map,const std::string& file,const std::string& format) +{ + Image32 image(map.getWidth(),map.getHeight()); + Renderer::render(map,image); + image.saveToFile(file,format); +} + +void render(const Map& map,Image32& image) +{ + Renderer::render(map,image); +} + + +ref_ptr create_point_symbolizer(std::string const& file,unsigned w,unsigned h) +{ + return ref_ptr(new image_symbolizer(file,"png",w,h)); +} + +ref_ptr create_line_symbolizer(const Color& pen,float width) +{ + return ref_ptr(new line_symbolizer(pen,width)); +} + +ref_ptr create_line_symbolizer2(stroke const& strk) +{ + return ref_ptr(new line_symbolizer(strk)); +} + +ref_ptr create_polygon_symbolizer(const Color& fill) +{ + return ref_ptr(new polygon_symbolizer(fill)); +} + + +BOOST_PYTHON_MODULE(mapnik) +{ + using namespace boost::python; + + class_, + boost::noncopyable>("datasource",no_init) + .def("envelope",&datasource::envelope, + return_value_policy()) + ; + class_ ("symbolizer",no_init) + ; + + export_parameters(); + export_color(); + export_envelope(); + export_image(); + export_filter(); + export_rule(); + export_style(); + export_layer(); + export_stroke(); + export_datasource_cache(); + + + class_ >("coord",init()) + .def_readwrite("x", &coord::x) + .def_readwrite("y", &coord::y) + ; + + export_map(); + + def("render_to_file",&render_to_file); + def("render",&render); + def("point_symbolizer",&create_point_symbolizer); + def("line_symbolizer",&create_line_symbolizer); + def("line_symbolizer",&create_line_symbolizer2); + def("polygon_symbolizer",&create_polygon_symbolizer); + + register_ptr_to_python >(); + register_ptr_to_python(); +} diff --git a/python/mapnik_rule.cpp b/python/mapnik_rule.cpp new file mode 100644 index 000000000..fb4472c6d --- /dev/null +++ b/python/mapnik_rule.cpp @@ -0,0 +1,63 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#include +#include +#include + +using mapnik::rule_type; +using mapnik::filter; +using mapnik::filter_ptr; +using mapnik::Feature; +using mapnik::symbolizers; + +void export_rule() +{ + using namespace boost::python; + + class_("symbolizers",init<>("symbolizers TODO")) + .def(vector_indexing_suite()) + ; + + class_("rule",init<>("default rule constructor")) + //name,title + .def(init()) + //name,title,min_scale_denominator,max_scale_denominator + .def(init()) + .def("name",&rule_type::get_name,return_value_policy()) + .def("name",&rule_type::set_name) + .def("title",&rule_type::get_title,return_value_policy()) + .def("title",&rule_type::set_title) + .def("abstract",&rule_type::get_abstract,return_value_policy()) + .def("abstract",&rule_type::set_abstract) + .def("filter",&rule_type::get_filter,return_value_policy()) + .def("filter",&rule_type::set_filter) + .add_property("min_scale",&rule_type::get_min_scale,&rule_type::set_min_scale) + .add_property("max_scale",&rule_type::get_max_scale,&rule_type::set_max_scale) + .def("set_else",&rule_type::set_else) + .def("has_else",&rule_type::has_else_filter) + .def("active",&rule_type::active) + .def("append",&rule_type::append) + .def("remove",&rule_type::remove_at) + .def("__iter__",boost::python::range(&rule_type::begin,&rule_type::end)) + .def("symbols",&rule_type::get_symbolizers,return_value_policy()) + ; +} + diff --git a/python/mapnik_stroke.cpp b/python/mapnik_stroke.cpp new file mode 100644 index 000000000..ab468edc0 --- /dev/null +++ b/python/mapnik_stroke.cpp @@ -0,0 +1,52 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#include +#include + + +void export_stroke () +{ + using namespace mapnik; + using namespace boost::python; + + enum_("line_cap") + .value("BUTT_CAP",BUTT_CAP) + .value("SQUARE_CAP",SQUARE_CAP) + .value("ROUND_CAP",ROUND_CAP) + ; + enum_("line_join") + .value("MITER_JOIN",MITER_JOIN) + .value("MITER_REVERT_JOIN",MITER_REVERT_JOIN) + .value("ROUND_JOIN",ROUND_JOIN) + .value("BEVEL_JOIN",BEVEL_JOIN) + ; + + class_("stroke",init<>()) + .def(init()) + .def("color",&stroke::get_color,return_value_policy()) + .def("color",&stroke::set_color) + .add_property("width",&stroke::get_width,&stroke::set_width) + .add_property("opacity",&stroke::get_opacity,&stroke::set_opacity) + .add_property("line_cap",&stroke::get_line_cap,&stroke::set_line_cap) + .add_property("line_join",&stroke::get_line_join,&stroke::set_line_join) + .def("add_dash",&stroke::add_dash) + ; +} diff --git a/python/mapnik_style.cpp b/python/mapnik_style.cpp new file mode 100644 index 000000000..e85d6553a --- /dev/null +++ b/python/mapnik_style.cpp @@ -0,0 +1,51 @@ +/* This file is part of python_mapnik (c++/python mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id$ + +#include "mapnik.hpp" +#include + +using mapnik::feature_type_style; +using mapnik::named_style_cache; +using mapnik::singleton; +using mapnik::CreateStatic; + +void export_style() +{ + using namespace boost::python; + class_("style",init<>("default style constructor")) + .def("append_rule",&feature_type_style::add_rule) + //.def("rules",&feature_type_style::rules) + ; + + class_,boost::noncopyable>("singleton",no_init) + .def("instance",&singleton::instance, + return_value_policy()) + .staticmethod("instance") + ; + + class_ >, + boost::noncopyable>("style_cache",no_init) + .def("insert",&named_style_cache::insert) + .staticmethod("insert") + .def("remove",&named_style_cache::remove) + .staticmethod("remove") + ; +} + diff --git a/settings.py b/settings.py new file mode 100644 index 000000000..4a327aecd --- /dev/null +++ b/settings.py @@ -0,0 +1,12 @@ +#edit this file + +PREFIX = '/opt/mapnik' +BOOST_ROOT = '/opt/boost' +FREETYPE2_ROOT = '/opt/freetype2' +PYTHON_VERSION = '2.4' +PYTHON_ROOT = '/opt/python' +AGG_ROOT = '/opt/agg23' + +# postgis datasource +POSTGRESQL_ROOT = '/opt/postgresql8' + diff --git a/src/SConscript b/src/SConscript new file mode 100644 index 000000000..9d15e77f2 --- /dev/null +++ b/src/SConscript @@ -0,0 +1,48 @@ +## +import glob + +Import ('env') + +prefix = env['PREFIX'] +boost_root = env['BOOST_ROOT'] +agg_root = env['AGG_ROOT'] +agg_headers = agg_root + '/include' + +freetype2_root = env['FREETYPE2_ROOT'] + +headers =[ '#include',boost_root,freetype2_root,agg_headers] + +libraries=['rt','z','png','ltdl','jpeg','tiff','agg','boost-filesystem','boost-regex'] +libpaths = [prefix+'/lib','#agg'] +linkflags = '-Wl,-rpath-link,. -Wl,-soname,libmapnik.so' + +source = Split( + """color.cpp + datasource_cache.cpp + envelope.cpp + graphics.cpp + image_reader.cpp + image_util.cpp + layer.cpp + line_aa.cpp + map.cpp + memory.cpp + params.cpp + plugin.cpp + png_reader.cpp + render.cpp + scanline_aa.cpp + scanline.cpp + style_cache.cpp + style.cpp + text.cpp + tiff_reader.cpp + wkb.cpp""" + ) + +lib_mapnik = env.SharedLibrary('libmapnik',source,CPPPATH=headers,LIBS=libraries,LIBPATH=libpaths,LINKFLAGS=linkflags) + +env.Alias(target="install",source=env.Install(prefix+"/lib",lib_mapnik)) +includes = glob.glob('../include' + '/*.hpp') +env.Alias(target="install",source=env.Install(prefix+"/include",includes)) + diff --git a/src/color.cpp b/src/color.cpp new file mode 100644 index 000000000..b8394a96e --- /dev/null +++ b/src/color.cpp @@ -0,0 +1,32 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: color.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include "color.hpp" + +namespace mapnik +{ + const Color Color::White=Color(255,255,255); + const Color Color::Black=Color(0,0,0); + const Color Color::Gray=Color(128,128,128); + const Color Color::Red=Color(255,0,0); + const Color Color::Green=Color(0,255,0); + const Color Color::Blue=Color(0,0,255); + const Color Color::Yellow=Color(255,255,0); +} diff --git a/src/datasource_cache.cpp b/src/datasource_cache.cpp new file mode 100644 index 000000000..2b0c60df8 --- /dev/null +++ b/src/datasource_cache.cpp @@ -0,0 +1,130 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: datasource_cache.cpp 23 2005-03-22 22:16:34Z pavlenko $ + +#include "datasource_cache.hpp" + +#include +#include +#include + +namespace mapnik +{ + using namespace std; + using namespace boost; + + datasource_cache::datasource_cache() + { + if (lt_dlinit()) throw; + } + + datasource_cache::~datasource_cache() + { + lt_dlexit(); + } + + std::map > datasource_cache::plugins_; + bool datasource_cache::registered_=false; + + datasource_p datasource_cache::create(const Parameters& params) + { + datasource *ds=0; + try + { + std::string type=params.get("type"); + map >::iterator itr=plugins_.find(type); + if (itr!=plugins_.end()) + { + if (itr->second->handle()) + { + create_ds* create_datasource = (create_ds*) lt_dlsym(itr->second->handle(), "create"); + if (!create_datasource) + { + std::cerr << "Cannot load symbols: " << lt_dlerror() << std::endl; + } + else + { + ds=create_datasource(params); + } + } + else + { + std::cerr << "Cannot load library: " << " "<< lt_dlerror() << std::endl; + } + } + std::cout<<"datasource="<(ds); + } + + bool datasource_cache::insert(const std::string& type,const lt_dlhandle module) + { + return plugins_.insert(make_pair(type,ref_ptr(new PluginInfo(type,module)))).second; + } + + void datasource_cache::register_datasources(const std::string& str) + { + Lock lock(&mutex_); + filesystem::path path(str); + filesystem::directory_iterator end_itr; + if (exists(path)) + { + for (filesystem::directory_iterator itr(path);itr!=end_itr;++itr ) + { + if (!is_directory( *itr )) + { + std::string file_name(str+"/"+itr->leaf()); + + if (file_name=="." || file_name=="..") + continue; + std::string::size_type len=file_name.size(); + + if (len>3 && + file_name[len-1]=='o' && + file_name[len-2]=='s') + { + lt_dlhandle module=lt_dlopenext(file_name.c_str()); + if (module) + { + datasource_name* ds_name = (datasource_name*) lt_dlsym(module, "datasource_name"); + if (ds_name && insert(ds_name(),module)) + { + std::cout<<"registered datasource : "< + Envelope::Envelope() + :minx_(0),miny_(0),maxx_(-1),maxy_(-1) {} + + template + Envelope::Envelope(T minx_,T miny_,T maxx_,T maxy_) + { + init(minx_,miny_,maxx_,maxy_); + } + + template + Envelope::Envelope(const coord &c0,const coord &c1) + { + init(c0.x,c0.y,c1.x,c1.y); + } + + template + Envelope::Envelope(const Envelope &rhs) + { + init(rhs.minx_,rhs.miny_,rhs.maxx_,rhs.maxy_); + } + + template + inline bool Envelope::operator==(const Envelope& other) const + { + return minx_==other.minx_ && + miny_==other.miny_ && + maxx_==other.maxx_ && + maxy_==other.maxy_; + } + + template + inline T Envelope::minx() const + { + return minx_; + } + + template + inline T Envelope::maxx() const + { + return maxx_; + } + + template + inline T Envelope::miny() const + { + return miny_; + } + + template + inline T Envelope::maxy() const + { + return maxy_; + } + + template + inline T Envelope::width() const + { + return maxx_-minx_; + } + + template + inline T Envelope::height() const + { + return maxy_-miny_; + } + + template + inline void Envelope::width(T w) + { + T cx=center().x; + minx_=static_cast(cx-w*0.5); + maxx_=static_cast(cx+w*0.5); + } + + template + inline void Envelope::height(T h) + { + T cy=center().y; + miny_=static_cast(cy-h*0.5); + maxy_=static_cast(cy+h*0.5); + } + + template + inline coord Envelope::center() const + { + return coord(static_cast(0.5*(minx_+maxx_)), + static_cast(0.5*(miny_+maxy_))); + } + + template + inline void Envelope::expand_to_include(const coord& c) + { + expand_to_include(c.x,c.y); + } + + template + inline void Envelope::expand_to_include(T x,T y) + { + if (xmaxx_) maxx_=x; + if (ymaxy_) maxy_=y; + } + + template + void Envelope::expand_to_include(const Envelope &other) + { + if (other.minx_maxx_) maxx_=other.maxx_; + if (other.miny_maxy_) maxy_=other.maxy_; + } + + template + inline bool Envelope::contains(const coord &c) const + { + return contains(c.x,c.y); + } + + template + inline bool Envelope::contains(T x,T y) const + { + return x>=minx_ && x<=maxx_ && y>=miny_ && y<=maxy_; + } + + template + inline bool Envelope::contains(const Envelope &other) const + { + return other.minx_>=minx_ && + other.maxx_<=maxx_ && + other.miny_>=miny_ && + other.maxy_<=maxy_; + } + + template + inline bool Envelope::intersects(const coord &c) const + { + return intersects(c.x,c.y); + } + + template + bool Envelope::intersects(T x,T y) const + { + return !(x>maxx_ || xmaxy_ || y + inline bool Envelope::intersects(const Envelope &other) const + { + return !(other.minx_>maxx_ || other.maxx_maxy_ || other.maxy_ + inline Envelope Envelope::intersect(const EnvelopeType& other) const + { + + T x0=std::max(minx_,other.minx_); + T y0=std::max(miny_,other.miny_); + + T x1=std::min(maxx_,other.maxx_); + T y1=std::min(maxy_,other.maxy_); + + return Envelope(x0,y0,x1,y1); + } + + template + inline void Envelope::re_center(T cx,T cy) + { + T dx=cx-center().x; + T dy=cy-center().y; + minx_+=dx; + miny_+=dy; + maxx_+=dx; + maxy_+=dy; + } + + template + inline void Envelope::init(T x0,T y0,T x1,T y1) + { + if (x0; + template class Envelope; +} diff --git a/src/graphics.cpp b/src/graphics.cpp new file mode 100644 index 000000000..a9b8907a3 --- /dev/null +++ b/src/graphics.cpp @@ -0,0 +1,84 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: graphics.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include +#include +#include +#include +#include "graphics.hpp" +#include "image_util.hpp" + +namespace mapnik +{ + Image32::Image32(int width,int height) + :width_(width), + height_(height), + data_(width,height) {} + + Image32::Image32(const Image32& rhs) + :width_(rhs.width_), + height_(rhs.height_), + data_(rhs.data_) {} + + Image32::~Image32() {} + + gamma Image32::gammaTable_; + + const ImageData32& Image32::data() const + { + return data_; + } + + void Image32::setBackground(const Color& background) + { + background_=background; + data_.set(background_.rgba()); + } + + const Color& Image32::getBackground() const + { + return background_; + } + + void Image32::set_rectangle(unsigned x0,unsigned y0,const ImageData32& data) + { + if (x0>=width_ || y0>=height_) return; + + unsigned w=std::min(data.width(),width_-x0); + unsigned h=std::min(data.height(),height_-y0); + + for (unsigned y=0;y ImageReaderFactory; + + + bool register_image_reader(const std::string& type,ImageReader* (* fun)(const std::string&)) + { + return ImageReaderFactory::instance()->register_product(type,fun); + } + + ImageReader* get_image_reader(const std::string& type,const std::string& file) + { + return ImageReaderFactory::instance()->create_object(type,file); + } +} diff --git a/src/image_util.cpp b/src/image_util.cpp new file mode 100644 index 000000000..71a25137e --- /dev/null +++ b/src/image_util.cpp @@ -0,0 +1,150 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: image_util.cpp 36 2005-04-05 14:32:18Z pavlenko $ + +#include +#include +#include +#include "graphics.hpp" +#include "image_util.hpp" +#include "memory.hpp" + +namespace mapnik +{ + + //use memory manager for mem allocation in libpng + + png_voidp malloc_fn(png_structp png_ptr,png_size_t size) + { + return Object::operator new(size); + } + void free_fn(png_structp png_ptr, png_voidp ptr) + { + Object::operator delete(ptr); + } + // + void ImageUtils::save_to_file(const std::string& filename,const std::string& type,const Image32& image) + { + //all that should go into image_writer factory + if (type=="png") + { + save_as_png(filename,image); + } + else if (type=="jpeg") + { + save_as_jpeg(filename,85,image); + } + } + + void ImageUtils::save_as_png(const std::string& filename,const Image32& image) + { + FILE *fp=fopen(filename.c_str(), "wb"); + if (!fp) return; + png_voidp mem_ptr=0; + png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, + (png_voidp)mem_ptr,0, 0); + + if (!png_ptr) return; + png_set_mem_fn(png_ptr,mem_ptr,malloc_fn,free_fn); + + // switch on optimization + //#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) + //png_uint_32 mask, flags; + + //flags = png_get_asm_flags(png_ptr); + //mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); + //png_set_asm_flags(png_ptr, flags | mask); + //#endif + png_set_filter (png_ptr, 0, PNG_FILTER_NONE); + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr,(png_infopp)0); + fclose(fp); + return; + } + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return; + } + + png_init_io(png_ptr, fp); + //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); + //png_set_compression_strategy(png_ptr, Z_FILTERED); + png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8, + PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); + png_write_info(png_ptr, info_ptr); + + const ImageData32& imageData=image.data(); + + for (unsigned i=0;i>8)&0xff; + row[index++]=(imageRow[i]>>16)&0xff; + } + row_pointer[0] = &row[0]; + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + delete [] row; + jpeg_finish_compress(&cinfo); + fclose(fp); + jpeg_destroy_compress(&cinfo); + } +} diff --git a/src/layer.cpp b/src/layer.cpp new file mode 100644 index 000000000..85e669b8c --- /dev/null +++ b/src/layer.cpp @@ -0,0 +1,186 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: layer.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include +#include "ptr.hpp" +#include "style.hpp" +#include "datasource.hpp" +#include "datasource_cache.hpp" +#include "layer.hpp" + +namespace mapnik +{ + using namespace std; + + Layer::Layer(const Parameters& params) + :params_(params), + minZoom_(0), + maxZoom_(std::numeric_limits::max()), + active_(true), + selectable_(false), + selection_style_("default_selection") + { + + try + { + name_=params_.get("name"); + volatile datasource_cache* factory=datasource_cache::instance(); + ds_=factory->create(params_); + + } + catch (...) + { + throw; + } + } + + Layer::Layer(const Layer& rhs) + :params_(rhs.params_), + name_(rhs.name_), + minZoom_(rhs.minZoom_), + maxZoom_(rhs.maxZoom_), + active_(rhs.active_), + selectable_(rhs.selectable_), + ds_(rhs.ds_), + styles_(rhs.styles_), + selection_style_(rhs.selection_style_) {} + + Layer& Layer::operator=(const Layer& rhs) + { + Layer tmp(rhs); + swap(tmp); + return *this; + } + + void Layer::swap(const Layer& rhs) + { + params_=rhs.params_; + name_=rhs.name_; + minZoom_=rhs.minZoom_; + maxZoom_=rhs.maxZoom_; + active_=rhs.active_; + selectable_=rhs.selectable_; + ds_=rhs.ds_; + styles_=rhs.styles_; + selection_style_=rhs.selection_style_; + } + + Layer::~Layer() {} + + Parameters const& Layer::params() const + { + return params_; + } + + const string& Layer::name() const + { + return name_; + } + + void Layer::add_style(std::string const& stylename) + { + styles_.push_back(stylename); + } + + std::vector const& Layer::styles() const + { + return styles_; + } + + void Layer::setMinZoom(double minZoom) + { + minZoom_=minZoom; + } + + void Layer::setMaxZoom(double maxZoom) + { + maxZoom_=maxZoom; + } + + double Layer::getMinZoom() const + { + return minZoom_; + } + + double Layer::getMaxZoom() const + { + return maxZoom_; + } + + void Layer::setActive(bool active) + { + active_=active; + } + + bool Layer::isActive() const + { + return active_; + } + + bool Layer::isVisible(double scale) const + { + return isActive() && scale>=minZoom_ && scale& Layer::envelope() const + { + return ds_->envelope(); + } + + void Layer::selection_style(const std::string& name) + { + selection_style_=name; + } + + const std::string& Layer::selection_style() const + { + return selection_style_; + } + + void Layer::add_to_selection(ref_ptr& feature) const + { + selection_.push_back(feature); + } + + vector >& Layer::selection() const + { + return selection_; + } + + void Layer::clear_selection() const + { + selection_.clear(); + } +} diff --git a/src/line_aa.cpp b/src/line_aa.cpp new file mode 100644 index 000000000..fd227f51d --- /dev/null +++ b/src/line_aa.cpp @@ -0,0 +1,146 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: line_aa.cpp 29 2005-04-01 14:30:11Z pavlenko $ + +#include "line_aa.hpp" +#include "geom_util.hpp" + +namespace mapnik +{ + using std::swap; + + template + template + void LineRasterizerAA::render(const geometry_type& path,const Color& c) + { + unsigned rgba=c.rgba(); + typename geometry_type::path_iterator itr=path.template begin(); + + int x0 = 0 ,y0 = 0; + while (itr!=path.template end()) + { + int x1=itr->x; + int y1=itr->y; + if (itr->cmd==SEG_LINETO || itr->cmd==SEG_CLOSE) + { + if (!(x0==x1 && y0==y1)) + { + render_line(x0,y0,x1,y1,rgba); + } + } + x0=x1; + y0=y1; + ++itr; + } + } + + template + inline void LineRasterizerAA::render_line(int x0,int y0,int x1,int y1,unsigned rgba) + { + if (!clip_line(x0,y0,x1,y1,pixbuf_)) return; + if(y0>y1) + { + swap(y0,y1); + swap(x0,x1); + } + pixbuf_->setPixel(x0,y0,rgba); + pixbuf_->setPixel(x1,y1,rgba); + int dx=x1-x0; + int dy=y1-y0; + int xDir; + if(dx>=0) xDir=1; + else + { + xDir=-1; + dx=-dx; + } + if(dx==0) // vertical line + { + for(int y=y0;ysetPixel(x0,y,rgba); + } + return; + } + if(dy==0) // horizontal line + { + if (x0>x1) swap(x0,x1); + for(int x=x0;xsetPixel(x,y0,rgba); + } + return; + } + if(dx==dy) // diagonal line. + { + for(int x=x0,y=y0;ysetPixel(x,y,rgba); + } + return; + } + // line is not horizontal, diagonal, or vertical: use Wu Antialiasing: + int error_acc=0; + int t; + if(dy>dx) // y-major line + { + int error_adj=(dx<<16)/dy; + if(xDir<0) + { + while(--dy) + { + error_acc+=error_adj; + ++y0; + x1=x0-(error_acc>>16); + t=(error_acc>>8)&255; + pixbuf_->blendPixel(x1 , y0, rgba,~t&255); + pixbuf_->blendPixel(x1-1, y0, rgba,t); + } + } + else + { + while(--dy) + { + error_acc+=error_adj; + ++y0; + x1=x0+(error_acc>>16); + t=(error_acc>>8)&255; + pixbuf_->blendPixel(x1 , y0, rgba,~t&255); + pixbuf_->blendPixel(x1+xDir, y0, rgba,t); + } + } + } // x-major line + else + { + int error_adj=(dy<<16)/dx; + while(--dx) + { + error_acc+=error_adj; + x0+=xDir; + y1=y0+(error_acc>>16); + t=(error_acc>>8)&255; + pixbuf_->blendPixel(x0, y1 , rgba,~t&255); + pixbuf_->blendPixel(x0, y1+1, rgba,t); + } + } + } + + template class LineRasterizerAA; + template void LineRasterizerAA::render(const geometry_type&,const Color&); +} diff --git a/src/map.cpp b/src/map.cpp new file mode 100644 index 000000000..4b7da47d3 --- /dev/null +++ b/src/map.cpp @@ -0,0 +1,172 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: map.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include "style.hpp" +#include "datasource.hpp" +#include "layer.hpp" +#include "map.hpp" + +namespace mapnik +{ + + Map::Map(int width,int height,int srid) + : width_(width), + height_(height), + srid_(srid), + background_(Color(255,255,255)) {} + + Map::Map(const Map& rhs) + : width_(rhs.width_), + height_(rhs.height_), + srid_(rhs.srid_), + background_(rhs.background_), + layers_(rhs.layers_), + currentExtent_(rhs.currentExtent_) {} + + Map& Map::operator=(const Map& rhs) + { + if (this==&rhs) return *this; + width_=rhs.width_; + height_=rhs.height_; + srid_=rhs.srid_; + background_=rhs.background_; + layers_=rhs.layers_; + return *this; + } + + size_t Map::layerCount() const + { + return layers_.size(); + } + + void Map::addLayer(const Layer& l) + { + layers_.push_back(l); + } + void Map::removeLayer(size_t index) + { + layers_.erase(layers_.begin()+index); + } + void Map::removeLayer(const char* lName) + { + //todo + } + + const Layer& Map::getLayer(size_t index) const + { + return layers_[index]; + } + + int Map::getWidth() const + { + return width_; + } + + int Map::getHeight() const + { + return height_; + } + + int Map::srid() const + { + return srid_; + } + + void Map::setBackground(const Color& c) + { + background_=c; + } + + const Color& Map::getBackground() const + { + return background_; + } + + void Map::zoom(double factor) + { + coord2d center = currentExtent_.center(); + double w = factor * currentExtent_.width(); + double h = factor * currentExtent_.height(); + currentExtent_ = Envelope(center.x - 0.5 * w, center.y - 0.5 * h, + center.x + 0.5 * w, center.y + 0.5 * h); + } + + void Map::zoomToBox(const Envelope &box) + { + currentExtent_=box; + fixAspectRatio(); + } + + void Map::fixAspectRatio() + { + double ratio1 = (double) width_ / (double) height_; + double ratio2 = currentExtent_.width() / currentExtent_.height(); + if (ratio1 >= 1.0) + { + if (ratio2 > ratio1) + { + currentExtent_.height(currentExtent_.width() / ratio1); + } + else + { + currentExtent_.width(currentExtent_.height() * ratio1); + } + } + else + { + if (ratio2 > ratio1) + { + currentExtent_.width(currentExtent_.height() * ratio1); + } + else + { + currentExtent_.height(currentExtent_.width() / ratio1); + } + } + } + + const Envelope& Map::getCurrentExtent() const + { + return currentExtent_; + } + + void Map::pan(int x,int y) + { + CoordTransform t(width_,height_,currentExtent_); + coord2d pt(x,y); + t.backward(pt); + currentExtent_.re_center(pt.x,pt.y); + } + + void Map::pan_and_zoom(int x,int y,double factor) + { + pan(x,y); + zoom(factor); + } + + double Map::scale() const + { + if (width_>0) + return currentExtent_.width()/width_; + return currentExtent_.width(); + } + + Map::~Map() {} +} diff --git a/src/memory.cpp b/src/memory.cpp new file mode 100644 index 000000000..3c6372638 --- /dev/null +++ b/src/memory.cpp @@ -0,0 +1,59 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: memory.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include "memory.hpp" + +//#define GC_THREADS +//#include "gc.h" + +namespace mapnik +{ + void* Object::operator new(size_t size) + { + void* block=::operator new (size); + return (char*) block; + } + + void* Object::operator new(size_t size,MemoryManager* manager) + { + assert(manager); + size_t headerSize=MemoryUtils::alignPointerSize(sizeof(MemoryManager*)); + void* const block=manager->allocate(headerSize+size); + *(MemoryManager**)block=manager; + return (char*)block+headerSize; + } + + void Object::operator delete(void* p) + { + ::operator delete(p); + } + + void Object::operator delete(void* p, MemoryManager* manager) + { + std::cout <<"operator delete with Manager "<= sizeof(double)) ? sizeof(void*) : sizeof(double); + size_t current=ptrSize % alignment; + return (current==0)?ptrSize:(ptrSize+alignment-current); + } +} diff --git a/src/params.cpp b/src/params.cpp new file mode 100644 index 000000000..c7b2853b0 --- /dev/null +++ b/src/params.cpp @@ -0,0 +1,59 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: params.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include +#include +#include "params.hpp" + +namespace mapnik +{ + + const std::string Parameters::get(const std::string& name) const + { + std::map::const_iterator itr; + itr=data_.find(name); + if (itr!=data_.end()) + return itr->second; + return std::string(); + } + + void Parameters::add(const Parameter& param) + { + data_.insert(param); + } + + void Parameters::add(const std::string& name,const std::string& value) + { + Parameter param(name,value); + data_.insert(param); + } + + std::map::const_iterator Parameters::begin() const + { + return data_.begin(); + } + + std::map::const_iterator Parameters::end() const + { + return data_.end(); + } + + Parameters::~Parameters() {} +} diff --git a/src/plugin.cpp b/src/plugin.cpp new file mode 100644 index 000000000..184fabfb1 --- /dev/null +++ b/src/plugin.cpp @@ -0,0 +1,47 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: plugin.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include "plugin.hpp" + +namespace mapnik +{ + + PluginInfo::PluginInfo (const std::string& name,const lt_dlhandle module) + :name_(name),module_(module) {} + + PluginInfo::~PluginInfo() + { + if (module_) + { + lt_dlclose(module_),module_=0; + } + } + + const std::string& PluginInfo::name() const + { + return name_; + } + + lt_dlhandle PluginInfo::handle() const + { + return module_; + } + +} diff --git a/src/png_reader.cpp b/src/png_reader.cpp new file mode 100644 index 000000000..55c3afad5 --- /dev/null +++ b/src/png_reader.cpp @@ -0,0 +1,195 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: png_reader.cpp 33 2005-04-04 13:01:03Z pavlenko $ + +#include "image_reader.hpp" +#include + +namespace mapnik +{ + class PngReader : public ImageReader + { + private: + std::string fileName_; + unsigned width_; + unsigned height_; + int bit_depth_; + int color_type_; + public: + explicit PngReader(const std::string& fileName); + ~PngReader(); + unsigned width() const; + unsigned height() const; + void read(unsigned x,unsigned y,ImageData32& image); + private: + PngReader(const PngReader&); + PngReader& operator=(const PngReader&); + void init(); + }; + + namespace + { + ImageReader* createPngReader(const std::string& file) + { + return new PngReader(file); + } + const bool registered = register_image_reader("png",createPngReader); + } + + PngReader::PngReader(const std::string& fileName) + : fileName_(fileName), + width_(0), + height_(0), + bit_depth_(0), + color_type_(0) + { + try + { + init(); + } + catch (const ImageReaderException& e) + { + std::cerr<=libpng 1.2.7 + png_set_add_alpha(png_ptr,1,1); + + double gamma; + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma(png_ptr, 2.2, gamma); + + png_read_update_info(png_ptr, info_ptr); + + //START read image rows + unsigned w=std::min((unsigned)image.width(),width_); + unsigned h=std::min((unsigned)image.height(),height_); + + unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr); + unsigned char* row= new unsigned char[rowbytes]; + for (unsigned i=0;i=y0 && i +#include +#include + +namespace mapnik +{ + + template + void Renderer::renderLayer(const Layer& l,const CoordTransform& t, + const Envelope& bbox,Image& image) + { + const datasource_p& ds=l.datasource(); + if (!ds) return; + + volatile named_style_cache* styles=named_style_cache::instance(); + + //get copy + std::vector const& namedStyles=l.styles(); + std::vector::const_iterator stylesIter=namedStyles.begin(); + while (stylesIter!=namedStyles.end()) + { + feature_type_style style=styles->find(*stylesIter++); + + std::set names; + attribute_collector collector(names); + property_index indexer(names); + + query q(bbox); + double scale = 1.0/t.scale(); + std::vector if_rules; + std::vector else_rules; + + bool active_rules=false; + const std::vector& rules=style.rules(); + std::vector::const_iterator ruleIter=rules.begin(); + + while (ruleIter!=rules.end()) + { + if (ruleIter->active(scale)) + { + active_rules=true; + filter_ptr& filter=const_cast(ruleIter->get_filter()); + filter->accept(collector); + filter->accept(indexer); + if (ruleIter->has_else_filter()) + { + else_rules.push_back(const_cast(&(*ruleIter))); + } + else + { + if_rules.push_back(const_cast(&(*ruleIter))); + } + } + ++ruleIter; + } + + std::set::const_iterator namesIter=names.begin(); + // push all property names + while (namesIter!=names.end()) + { + q.add_property_name(*namesIter); + ++namesIter; + } + //only query datasource if there are active rules + if (active_rules) + { + featureset_ptr fs=ds->features(q); + if (fs) + { + Feature* feature=0; + while (feature = fs->next()) + { + bool do_else=true; + geometry_ptr& geom=feature->get_geometry(); + if (geom) + { + geom->transform(t);//todo: transform once + + std::vector::const_iterator itr=if_rules.begin(); + while (itr!=if_rules.end()) + { + const filter_ptr& filter=(*itr)->get_filter(); + if (filter->pass(*feature)) + { + do_else=false; + const symbolizers& symbols = (*itr)->get_symbolizers(); + symbolizers::const_iterator symIter=symbols.begin(); + while (symIter!=symbols.end()) + { + (*symIter)->render(*geom,image); + ++symIter; + } + } + ++itr; + } + if (do_else) + { + //else filter + std::vector::const_iterator itr=else_rules.begin(); + while (itr != else_rules.end()) + { + const symbolizers& symbols = (*itr)->get_symbolizers(); + symbolizers::const_iterator symIter=symbols.begin(); + while (symIter!=symbols.end()) + { + (*symIter)->render(*geom,image); + ++symIter; + } + ++itr; + } + } + } + delete feature; + } + } + if (l.isSelectable() && l.selection().size()) //TODO !!! + { + volatile style_cache* styles=style_cache::instance(); + const Style& style=styles->find(l.selection_style()); + + std::vector >& selection=l.selection(); + + Style::Iterator pos = style.begin(); + if (pos!=style.end()) { + std::vector >::iterator itr=selection.begin(); + + while (itr!=selection.end()) + { + geometry_ptr& geom=(*itr)->get_geometry(); + geom->transform(t); + (*pos)->render(*geom,image); + ++itr; + } + } + l.clear_selection(); + } + } + } + } + + template + void Renderer::render(const Map& map,Image& image) + { + timer clock; + ////////////////////////////////////////////////////// + const Envelope& extent=map.getCurrentExtent(); + std::cout<<"BBOX:"<; +} diff --git a/src/scanline.cpp b/src/scanline.cpp new file mode 100644 index 000000000..f9486cc25 --- /dev/null +++ b/src/scanline.cpp @@ -0,0 +1,46 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: scanline.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include +#include "memory.hpp" +#include "graphics.hpp" +#include "scanline.hpp" + +namespace mapnik +{ + + template + template + void ScanlineRasterizer::render(const geometry_type& geom,const Color& c) + { + // ???? + } + + template + inline void ScanlineRasterizer::render_hline(int x0,int x1,int y,unsigned int rgba) + { + int x; + if (x0<0) x0=0; + if (x1> (int)pixbuf_->width()-1) x1=pixbuf_->width()-1; + for(x=x0;x<=x1;x++) pixbuf_->setPixel(x,y,rgba); + } + + template class ScanlineRasterizer; +} diff --git a/src/scanline_aa.cpp b/src/scanline_aa.cpp new file mode 100644 index 000000000..ba549fc85 --- /dev/null +++ b/src/scanline_aa.cpp @@ -0,0 +1,621 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// Credits: +// I gratefully acknowledge the inspiring work of Maxim Shemanarev (McSeem), +// author of Anti-Grain Geometry (http://www.antigrain.com), and also the developers +// of the FreeType library (http://www.freetype.org). I have slightly modified the polygon +// rasterizing algorithm to work with my library, but render_line and +// render_hline remain intact. + +//$Id: scanline_aa.cpp 29 2005-04-01 14:30:11Z pavlenko $ + +#include "scanline_aa.hpp" + +namespace mapnik +{ + + inline void cell_aa::set_cover(int c, int a) + { + cover = c; + area = a; + } + inline void cell_aa::add_cover(int c, int a) + { + cover += c; + area += a; + } + inline void cell_aa::set_coord(int cx, int cy) + { + x = short(cx); + y = short(cy); + packed_coord = (cy << 16) + cx; + } + inline void cell_aa::set(int cx, int cy, int c, int a) + { + x = short(cx); + y = short(cy); + packed_coord = (cy << 16) + cx; + cover = c; + area = a; + } + + outline_aa::~outline_aa() + { + delete [] m_sorted_cells; + if(m_num_blocks) + { + cell_aa** ptr = m_cells + m_num_blocks - 1; + while(m_num_blocks--) + { + delete [] *ptr; + ptr--; + } + delete [] m_cells; + } + } + + outline_aa::outline_aa() : + m_num_blocks(0), + m_max_blocks(0), + m_cur_block(0), + m_num_cells(0), + m_cells(0), + m_cur_cell_ptr(0), + m_sorted_cells(0), + m_sorted_size(0), + m_cur_x(0), + m_cur_y(0), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_sorted(false) + { + m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0); + } + + void outline_aa::reset() + { + m_num_cells = 0; + m_cur_block = 0; + m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0); + m_sorted = false; + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + void outline_aa::allocate_block() + { + if(m_cur_block >= m_num_blocks) + { + if(m_num_blocks >= m_max_blocks) + { + cell_aa** new_cells = new cell_aa* [m_max_blocks + cell_block_pool]; + if(m_cells) + { + memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_aa*)); + delete [] m_cells; + } + m_cells = new_cells; + m_max_blocks += cell_block_pool; + } + m_cells[m_num_blocks++] = new cell_aa [unsigned(cell_block_size)]; + } + m_cur_cell_ptr = m_cells[m_cur_block++]; + } + + inline void outline_aa::add_cur_cell() + { + if(m_cur_cell.area | m_cur_cell.cover) + { + if((m_num_cells & cell_block_mask) == 0) + { + if(m_num_blocks >= cell_block_limit) return; + allocate_block(); + } + *m_cur_cell_ptr++ = m_cur_cell; + ++m_num_cells; + if(m_cur_cell.x < m_min_x) m_min_x = m_cur_cell.x; + if(m_cur_cell.x > m_max_x) m_max_x = m_cur_cell.x; + } + } + + inline void outline_aa::set_cur_cell(int x, int y) + { + if(m_cur_cell.packed_coord != (y << 16) + x) + { + add_cur_cell(); + m_cur_cell.set(x, y, 0, 0); + } + } + + inline void outline_aa::render_hline(int ey, int x1, int y1, int x2, int y2) + { + int ex1 = x1 >> poly_base_shift; + int ex2 = x2 >> poly_base_shift; + int fx1 = x1 & poly_base_mask; + int fx2 = x2 & poly_base_mask; + + int delta, p, first, dx; + int incr, lift, mod, rem; + + + if(y1 == y2) + { + set_cur_cell(ex2, ey); + return; + } + + + if(ex1 == ex2) + { + delta = y2 - y1; + m_cur_cell.add_cover(delta, (fx1 + fx2) * delta); + return; + } + p = (poly_base_size - fx1) * (y2 - y1); + first = poly_base_size; + incr = 1; + + dx = x2 - x1; + + if(dx < 0) + { + p = fx1 * (y2 - y1); + first = 0; + incr = -1; + dx = -dx; + } + + delta = p / dx; + mod = p % dx; + + if(mod < 0) + { + delta--; + mod += dx; + } + + m_cur_cell.add_cover(delta, (fx1 + first) * delta); + + ex1 += incr; + set_cur_cell(ex1, ey); + y1 += delta; + + if(ex1 != ex2) + { + p = poly_base_size * (y2 - y1 + delta); + lift = p / dx; + rem = p % dx; + + if (rem < 0) + { + lift--; + rem += dx; + } + + mod -= dx; + + while (ex1 != ex2) + { + delta = lift; + mod += rem; + if(mod >= 0) + { + mod -= dx; + delta++; + } + + m_cur_cell.add_cover(delta, (poly_base_size) * delta); + y1 += delta; + ex1 += incr; + set_cur_cell(ex1, ey); + } + } + delta = y2 - y1; + m_cur_cell.add_cover(delta, (fx2 + poly_base_size - first) * delta); + } + + void outline_aa::render_line(int x1, int y1, int x2, int y2) + { + int ey1 = y1 >> poly_base_shift; + int ey2 = y2 >> poly_base_shift; + int fy1 = y1 & poly_base_mask; + int fy2 = y2 & poly_base_mask; + + int dx, dy, x_from, x_to; + int p, rem, mod, lift, delta, first, incr; + + dx = x2 - x1; + dy = y2 - y1; + + + if(ey1 == ey2) + { + render_hline(ey1, x1, fy1, x2, fy2); + return; + } + incr = 1; + if(dx == 0) + { + int ex = x1 >> poly_base_shift; + int two_fx = (x1 - (ex << poly_base_shift)) << 1; + int area; + + first = poly_base_size; + if(dy < 0) + { + first = 0; + incr = -1; + } + + x_from = x1; + + delta = first - fy1; + m_cur_cell.add_cover(delta, two_fx * delta); + + ey1 += incr; + set_cur_cell(ex, ey1); + + delta = first + first - poly_base_size; + area = two_fx * delta; + while(ey1 != ey2) + { + + m_cur_cell.set_cover(delta, area); + ey1 += incr; + set_cur_cell(ex, ey1); + } + + delta = fy2 - poly_base_size + first; + m_cur_cell.add_cover(delta, two_fx * delta); + return; + } + + p = (poly_base_size - fy1) * dx; + + first = poly_base_size; + + if(dy < 0) + { + p = fy1 * dx; + first = 0; + incr = -1; + dy = -dy; + } + + delta = p / dy; + mod = p % dy; + + if(mod < 0) + { + delta--; + mod += dy; + } + + x_from = x1 + delta; + render_hline(ey1, x1, fy1, x_from, first); + + ey1 += incr; + set_cur_cell(x_from >> poly_base_shift, ey1); + + if(ey1 != ey2) + { + p = poly_base_size * dx; + lift = p / dy; + rem = p % dy; + + if(rem < 0) + { + lift--; + rem += dy; + } + mod -= dy; + + while(ey1 != ey2) + { + delta = lift; + mod += rem; + if (mod >= 0) + { + mod -= dy; + delta++; + } + + x_to = x_from + delta; + render_hline(ey1, x_from, poly_base_size - first, x_to, first); + x_from = x_to; + + ey1 += incr; + set_cur_cell(x_from >> poly_base_shift, ey1); + } + } + render_hline(ey1, x_from, poly_base_size - first, x2, fy2); + } + + void outline_aa::move_to(int x, int y) + { + if ( m_sorted ) reset(); + set_cur_cell(x >> poly_base_shift, y >> poly_base_shift); + m_cur_x = x; + m_cur_y = y; + } + + void outline_aa::line_to(int x, int y) + { + render_line(m_cur_x, m_cur_y, x, y); + m_cur_x = x; + m_cur_y = y; + m_sorted = false; + } + + enum + { + qsort_threshold = 9 + }; + + template static inline void swap_cells(T* a, T* b) + { + T temp = *a; + *a = *b; + *b = temp; + } + + template static inline bool less_than(T* a, T* b) + { + return (*a)->packed_coord < (*b)->packed_coord; + } + + void outline_aa::qsort_cells(cell_aa** start, unsigned num) + { + cell_aa** stack[80]; + cell_aa*** top; + cell_aa** limit; + cell_aa** base; + + limit = start + num; + base = start; + top = stack; + + for (;;) + { + int len = int(limit - base); + + cell_aa** i; + cell_aa** j; + cell_aa** pivot; + + if(len > qsort_threshold) + { + pivot = base + len / 2; + swap_cells(base, pivot); + + i = base + 1; + j = limit - 1; + + if(less_than(j, i)) + { + swap_cells(i, j); + } + + if(less_than(base, i)) + { + swap_cells(base, i); + } + + if(less_than(j, base)) + { + swap_cells(base, j); + } + + for(;;) + { + do i++; while( less_than(i, base) ); + do j--; while( less_than(base, j) ); + + if ( i > j ) + { + break; + } + + swap_cells(i, j); + } + + swap_cells(base, j); + + if(j - base > limit - i) + { + top[0] = base; + top[1] = j; + base = i; + } + else + { + top[0] = i; + top[1] = limit; + limit = j; + } + top += 2; + } + else + { + + j = base; + i = j + 1; + + for(; i < limit; j = i, i++) + { + for(; less_than(j + 1, j); j--) + { + swap_cells(j + 1, j); + if (j == base) + { + break; + } + } + } + if(top > stack) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + { + break; + } + } + } + } + + void outline_aa::sort_cells() + { + if(m_num_cells == 0) return; + if(m_num_cells > m_sorted_size) + { + delete [] m_sorted_cells; + m_sorted_size = m_num_cells; + m_sorted_cells = new cell_aa* [m_num_cells + 1]; + } + + cell_aa** sorted_ptr = m_sorted_cells; + cell_aa** block_ptr = m_cells; + cell_aa* cell_ptr; + + unsigned nb = m_num_cells >> cell_block_shift; + unsigned i; + + while(nb--) + { + cell_ptr = *block_ptr++; + i = cell_block_size; + while(i--) + { + *sorted_ptr++ = cell_ptr++; + } + } + + cell_ptr = *block_ptr++; + i = m_num_cells & cell_block_mask; + while(i--) + { + *sorted_ptr++ = cell_ptr++; + } + m_sorted_cells[m_num_cells] = 0; + qsort_cells(m_sorted_cells, m_num_cells); + m_min_y = m_sorted_cells[0]->y; + m_max_y = m_sorted_cells[m_num_cells - 1]->y; + } + + const cell_aa* const* outline_aa::cells() + { + if(!m_sorted) + { + add_cur_cell(); + sort_cells(); + m_sorted = true; + } + return m_sorted_cells; + } + + template + template + void ScanlineRasterizerAA::render(const geometry_type& geom,const Color& c) + { + reset(); + unsigned rgba=c.rgba(); + clip_box(0,0,pixbuf_->width(),pixbuf_->height()); + geometry_type::path_iterator itr=geom.template begin(); + while(itr!=geom.template end()) + { + if (itr->cmd == SEG_MOVETO) + { + move_to(itr->x,itr->y); + } + else if (itr->cmd == SEG_LINETO) + { + line_to(itr->x,itr->y); + } + ++itr; + } + + if(rewind_scanlines()) + { + scanline_u8 sl; + sl.reset(min_x(),max_x()); + while(sweep_scanline(sl)) + { + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename scanline_u8::const_iterator span = sl.begin(); + do + { + int x = span->x; + if(span->len>0) + { + blend_hline(x,span->len,y,span->covers,rgba); + } + ++span; + } while(--num_spans); + } + } + } + template + inline void ScanlineRasterizerAA::blend_hline(int x0,int len,int y,const unsigned char* covers, + unsigned rgba) + { + if (y<0) return; + if (y>(int)pixbuf_->height()-1) return; + + if(x0<0) + { + len -= 0 - x0; + if(len <= 0) return; + covers += 0 - x0; + x0 = 0; + } + if(x0 + len > (int)pixbuf_->width()) + { + len = pixbuf_->width() - x0 + 1; + if(len <= 0) return; + } + for(int x=x0;xblendPixel(x,y,rgba,alpha); + } + } + + + + template + inline void ScanlineRasterizerAA::render_hline(int x0,int x1,int y,unsigned rgba) + { + if (y < 0) return; + if (y > (int)pixbuf_->height() - 1) return; + if (x0 < 0) x0 = 0; + if (x1 >(int)pixbuf_->width() - 1) x1 = pixbuf_->width()-1; + for(int x=x0;x<=x1;x++) pixbuf_->setPixel(x,y,rgba); + } + + template class ScanlineRasterizerAA; + template void ScanlineRasterizerAA::render(const geometry_type&,const Color&); +} diff --git a/src/style.cpp b/src/style.cpp new file mode 100644 index 000000000..3521bc9d9 --- /dev/null +++ b/src/style.cpp @@ -0,0 +1,26 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: style.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include "style.hpp" + +namespace mapnik +{ + ref_ptr Style::zero_symbol_=ref_ptr(0); +} diff --git a/src/style_cache.cpp b/src/style_cache.cpp new file mode 100644 index 000000000..93179724c --- /dev/null +++ b/src/style_cache.cpp @@ -0,0 +1,83 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: style_cache.cpp 37 2005-04-07 17:09:38Z pavlenko $ + +#include "style_cache.hpp" +#include "line_symbolizer.hpp" + +namespace mapnik +{ + + style_cache::style_cache() {} + style_cache::~style_cache() {} + + std::map style_cache::styles_; + + bool style_cache::insert(const std::string& name,const Style& style) + { + Lock lock(&mutex_); + return styles_.insert(make_pair(name,style)).second; + } + + void style_cache::remove(const std::string& name) + { + Lock lock(&mutex_); + styles_.erase(name); + } + + const Style& style_cache::find(const std::string& name) + { + Lock lock(&mutex_); + std::map::iterator itr=styles_.find(name); + if (itr!=styles_.end()) + { + return itr->second; + } + static const Style default_style(ref_ptr(new line_symbolizer(Color(255,0,0)))); + return default_style; + } + //////////////////////////////////////////////////////////////////////////// + named_style_cache::named_style_cache() {} + named_style_cache::~named_style_cache() {} + + std::map named_style_cache::styles_; + + bool named_style_cache::insert(const std::string& name,const feature_type_style& style) + { + Lock lock(&mutex_); + return styles_.insert(make_pair(name,style)).second; + } + + void named_style_cache::remove(const std::string& name) + { + Lock lock(&mutex_); + styles_.erase(name); + } + + feature_type_style named_style_cache::find(const std::string& name) + { + Lock lock(&mutex_); + std::map::iterator itr=styles_.find(name); + if (itr!=styles_.end()) + { + return itr->second; + } + return feature_type_style(); + } +} diff --git a/src/text.cpp b/src/text.cpp new file mode 100644 index 000000000..c7117e6e6 --- /dev/null +++ b/src/text.cpp @@ -0,0 +1,95 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: text.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include "text.hpp" + +#ifdef __HAVE_FREETYPE2__ +namespace mapnik +{ + using namespace std; + template + void TextRasterizer::render(const char* text) + { + FT_Library library; + FT_Face face; + FT_Error error; + error = FT_Init_FreeType( &library ); + if (error) + { + cout<<"an error occurred during library initialization\n"; + return; + } + error = FT_New_Face( library, fontName_.c_str(), 0, &face ); + if (error == FT_Err_Unknown_File_Format ) + { + cout<<"the font file could be opened and read, but it appears\n"; + cout<<"that its font format is unsupported"<glyph; + int x=40,y=200; + int len=strlen(text); + for (int i=0;iglyph,FT_RENDER_MODE_NORMAL); + if (error) continue; + render_bitmap(&slot->bitmap,x+slot->bitmap_left,y-slot->bitmap_top); + x+=slot->advance.x>>6; + y+=slot->advance.y>>6; + } + FT_Done_Face(face); + FT_Done_FreeType(library); + } + + template + void TextRasterizer::render_bitmap(FT_Bitmap *bitmap,int x,int y) + { + int x_max=x+bitmap->width; + int y_max=y+bitmap->rows; + int i,p,j,q; + + Color c(255,200,120); + for (i=x,p=0;ibuffer[q*bitmap->width+p]; + if (gray) + { + pixbuf_->blendPixel(i,j,c.rgba(),gray); + } + } + } + } + + template class TextRasterizer; +} + +#endif diff --git a/src/tiff_reader.cpp b/src/tiff_reader.cpp new file mode 100644 index 000000000..7e96c8775 --- /dev/null +++ b/src/tiff_reader.cpp @@ -0,0 +1,252 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: tiff_reader.cpp 17 2005-03-08 23:58:43Z pavlenko $ + +#include "image_reader.hpp" +#include +#include + +namespace mapnik +{ + + class TiffReader : public ImageReader + { + private: + std::string file_name_; + int read_method_; + unsigned width_; + unsigned height_; + int rows_per_strip_; + int tile_width_; + int tile_height_; + public: + enum + { + generic=1, + stripped, + tiled + }; + explicit TiffReader(const std::string& file_name); + virtual ~TiffReader(); + unsigned width() const; + unsigned height() const; + void read(unsigned x,unsigned y,ImageData32& image); + private: + TiffReader(const TiffReader&); + TiffReader& operator=(const TiffReader&); + void init(); + void read_generic(unsigned x,unsigned y,ImageData32& image); + void read_stripped(unsigned x,unsigned y,ImageData32& image); + void read_tiled(unsigned x,unsigned y,ImageData32& image); + }; + + namespace + { + ImageReader* createTiffReader(const std::string& file) + { + return new TiffReader(file); + } + + const bool registered = register_image_reader("tiff",createTiffReader); + } + + TiffReader::TiffReader(const std::string& file_name) + : file_name_(file_name), + read_method_(generic), + width_(0), + height_(0), + rows_per_strip_(0), + tile_width_(0), + tile_height_(0) + { + try + { + init(); + } + catch (ImageReaderException& ex) + { + std::cerr<=n0;--n) + { + image.setRow(row,tx0-x0,tx1-x0,(const unsigned*)&buf[n*tile_width_+tx0-x]); + ++row; + } + } + } + _TIFFfree(buf); + TIFFClose(tif); + } + } + + + void TiffReader::read_stripped(unsigned x0,unsigned y0,ImageData32& image) + { + TIFF* tif = TIFFOpen(file_name_.c_str(), "r"); + if (tif) + { + uint32* buf = (uint32*)_TIFFmalloc(width_*rows_per_strip_*sizeof(uint32)); + + int width=image.width(); + int height=image.height(); + + unsigned start_y=(y0/rows_per_strip_)*rows_per_strip_; + unsigned end_y=((y0+height)/rows_per_strip_+1)*rows_per_strip_; + bool laststrip=((unsigned)end_y > height_)?true:false; + int row,tx0,tx1,ty0,ty1; + + tx0=x0; + tx1=std::min(width+x0,(unsigned)width_); + + for (unsigned y=start_y; y < end_y; y+=rows_per_strip_) + { + ty0=std::max(y0,y)-y; + ty1=std::min(height+y0,y+rows_per_strip_)-y; + + if (!TIFFReadRGBAStrip(tif,y,buf)) break; + + row=y+ty0-y0; + + int n0=laststrip ? 0:(rows_per_strip_-ty1); + int n1=laststrip ? (ty1-ty0-1):(rows_per_strip_-ty0-1); + for (int n=n1;n>=n0;--n) + { + image.setRow(row,tx0-x0,tx1-x0,(const unsigned*)&buf[n*width_+tx0]); + ++row; + } + } + _TIFFfree(buf); + TIFFClose(tif); + } + } +} + diff --git a/src/wkb.cpp b/src/wkb.cpp new file mode 100644 index 000000000..82daed28b --- /dev/null +++ b/src/wkb.cpp @@ -0,0 +1,285 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: wkb.cpp 19 2005-03-22 13:53:27Z pavlenko $ + +#include "wkb.hpp" +#include "geom_util.hpp" + +namespace mapnik +{ + struct wkb_reader + { + private: + enum wkbByteOrder { + wkbXDR=0, + wkbNDR=1 + }; + const char* wkb_; + unsigned size_; + int srid_; + unsigned pos_; + wkbByteOrder byteOrder_; + bool needSwap_; + public: + + enum wkbGeometryType { + wkbPoint=1, + wkbLineString=2, + wkbPolygon=3, + wkbMultiPoint=4, + wkbMultiLineString=5, + wkbMultiPolygon=6, + wkbGeometryCollection=7 + }; + + wkb_reader(const char* wkb,unsigned size,int srid) + : wkb_(wkb), + size_(size), + srid_(srid), + pos_(0), + byteOrder_((wkbByteOrder)wkb_[0]) + { + ++pos_; + +#ifndef WORDS_BIGENDIAN + needSwap_=byteOrder_?wkbXDR:wkbNDR; +#else + needSwap_=byteOrder_?wkbNDR:wkbXDR; +#endif + } + + ~wkb_reader() {} + + geometry_ptr read() + { + geometry_ptr geom; + int type=read_integer(); + switch (type) + { + case wkbPoint: + geom = read_point(); + break; + case wkbLineString: + geom = read_linestring(); + break; + case wkbPolygon: + geom = read_polygon(); + break; + case wkbMultiPoint: + geom = read_multipoint(); + break; + case wkbMultiLineString: + geom = read_multilinestring(); + break; + case wkbMultiPolygon: + geom=read_multipolygon(); + break; + case wkbGeometryCollection: + break; + default: + break; + } + return geom; + } + + private: + wkb_reader(const wkb_reader&); + wkb_reader& operator=(const wkb_reader&); + + int read_integer() + { + int n; + + if (!needSwap_) + { + memcpy(&n,wkb_+pos_,4); + } + else + { + const char* b=wkb_+pos_; + n = b[3]&0xff | (b[2]&0xff)<<8 | (b[1]&0xff)<<16 | (b[0]&0xff)<<24; + } + pos_+=4; + + return n; + } + + double read_double() + { + double d; + + if (!needSwap_) + { + memcpy(&d,wkb_+pos_,8); + } + else + { + // we rely on the fact that "long long" is in C standard, + // but not in C++ yet + // this is not quite portable + const char* b= wkb_+pos_; + long long n = (long long)b[7]&0xff | + ((long long)b[6]&0xff)<<8 | + ((long long)b[5]&0xff)<<16 | + ((long long)b[4]&0xff)<<24 | + ((long long)b[3]&0xff)<<32 | + ((long long)b[2]&0xff)<<40 | + ((long long)b[1]&0xff)<<48 | + ((long long)b[0]&0xff)<<56; + memcpy(&d,&n,8); + } + pos_+=8; + + return d; + } + + void read_coords(CoordinateArray& ar) + { + int size=sizeof(coord)*ar.size(); + if (!needSwap_) + { + std::memcpy(&ar[0],wkb_+pos_,size); + + } + else + { + for (unsigned i=0;i(srid_)); + double x = read_double(); + double y = read_double(); + pt->move_to(x,y); + return pt; + } + + geometry_ptr read_multipoint() + { + geometry_ptr pt(new point(srid_)); + int num_points = read_integer(); + for (int i=0;imove_to(x,y); + } + return pt; + } + + geometry_ptr read_linestring() + { + geometry_ptr line(new line_string(srid_)); + int num_points=read_integer(); + CoordinateArray ar(num_points); + read_coords(ar); + line->move_to(ar[0].x,ar[0].y); + for (int i=1;iline_to(ar[i].x,ar[i].y); + } + return line; + } + + geometry_ptr read_multilinestring() + { + geometry_ptr line(new line_string(srid_)); + int num_lines=read_integer(); + + for (int i=0;imove_to(ar[0].x,ar[0].y); + + for (int i=1;iline_to(ar[i].x,ar[i].y); + } + } + return line; + } + + geometry_ptr read_polygon() + { + geometry_ptr poly(new polygon(srid_)); + + int num_rings=read_integer(); + + for (int i=0;imove_to(ar[0].x,ar[0].y); + + for (int j=1;jline_to(ar[j].x,ar[j].y); + } + poly->line_to(ar[0].x,ar[0].y); + + } + return poly; + } + + geometry_ptr read_multipolygon() + { + geometry_ptr poly(new polygon(srid_)); + + int num_polys=read_integer(); + for (int i=0;imove_to(ar[0].x,ar[0].y); + for (int j=1;jline_to(ar[j].x,ar[j].y); + } + poly->line_to(ar[0].x,ar[0].y); + } + } + return poly; + } + }; + + + geometry_ptr geometry_utils::from_wkb(const char* wkb, unsigned size,int srid) + { + wkb_reader reader(wkb,size,srid); + return reader.read(); + } +} diff --git a/util/shapeindex/config.hpp b/util/shapeindex/config.hpp new file mode 100644 index 000000000..dc511e617 --- /dev/null +++ b/util/shapeindex/config.hpp @@ -0,0 +1,23 @@ +/* config.hh. Generated by configure. */ +/* config.hh.in. Generated from configure.ac by autoheader. */ + +/* Name of package */ +#define PACKAGE "shapeindex" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bugs@shapeindex" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "shapeindex" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "shapeindex 0.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "shapeindex" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.1" + +/* Version number of package */ +#define VERSION "0.1" diff --git a/util/shapeindex/quadtree.cpp b/util/shapeindex/quadtree.cpp new file mode 100644 index 000000000..994554e29 --- /dev/null +++ b/util/shapeindex/quadtree.cpp @@ -0,0 +1,21 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: quadtree.cc 17 2005-03-08 23:58:43Z pavlenko $ + +#include "quadtree.hh" diff --git a/util/shapeindex/quadtree.hpp b/util/shapeindex/quadtree.hpp new file mode 100644 index 000000000..36ebe8825 --- /dev/null +++ b/util/shapeindex/quadtree.hpp @@ -0,0 +1,287 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: quadtree.hh 17 2005-03-08 23:58:43Z pavlenko $ + +#ifndef QUADTREE_HH +#define QUADTREE_HH + +#include "mapnik.hh" +#include +#include + +using namespace mapnik; + +template +struct quadtree_node +{ + std::vector data_; + Envelope ext_; + quadtree_node* children_[4]; + quadtree_node(const Envelope& ext) + : ext_(ext),data_() + { + memset(children_,0,sizeof(quadtree_node*)*4); + } + + ~quadtree_node() + { + for (int i=0;i<4;++i) + { + if (children_[i]) + { + delete children_[i],children_[i]=0; + } + } + } + + int num_subnodes() const + { + int count=0; + for (int i=0;i<4;++i) + { + if (children_[i]) + { + ++count; + } + } + return count; + } +}; + +template +class quadtree +{ +private: + quadtree_node* root_; + const int maxdepth_; + const double ratio_; +public: + quadtree(const Envelope& extent,int maxdepth,double ratio) + : root_(new quadtree_node(extent)), + maxdepth_(maxdepth), + ratio_(ratio){} + ~quadtree() + { + if (root_) delete root_; + } + void insert(const T& data,const Envelope& item_ext) + { + insert(data,item_ext,root_,maxdepth_); + } + int count() const + { + return count_nodes(root_); + } + int count_items() const + { + int count=0; + count_items(root_,count); + return count; + } + void print() const + { + print(root_); + } + void trim() + { + trim_tree(root_); + } + + void write(std::ostream& out) + { + char header[16]; + memset(header,0,16); + header[0]='m'; + header[1]='a'; + header[2]='p'; + header[4]='n'; + header[5]='i'; + header[6]='k'; + out.write(header,16); + write_node(out,root_); + } + +private: + + void trim_tree(quadtree_node*& node) + { + if (node) + { + for (int i=0;i<4;++i) + { + trim_tree(node->children_[i]); + } + + if (node->num_subnodes()==1 && node->data_.size()==0) + { + for (int i=0;i<4;++i) + { + if (node->children_[i]) + { + node=node->children_[i]; + break; + } + } + } + } + } + + int count_nodes(const quadtree_node* node) const + { + if (!node) + { + return 0; + } + else + { + int count = 1; + for (int i=0;i<4;++i) + { + count += count_nodes(node->children_[i]); + } + return count; + } + } + + void count_items(const quadtree_node* node,int& count) const + { + if (node) + { + count += node->data_.size(); + for (int i=0;i<4;++i) + { + count_items(node->children_[i],count); + } + } + } + + int subnode_offset(const quadtree_node* node) const + { + int offset=0; + for (int i=0;i<4;i++) + { + if (node->children_[i]) + { + offset +=sizeof(Envelope)+(node->children_[i]->data_.size()*sizeof(T))+3*sizeof(int); + offset +=subnode_offset(node->children_[i]); + } + } + return offset; + } + + void write_node(std::ostream& out,const quadtree_node* node) const + { + if (node) + { + int offset=subnode_offset(node); + int shape_count=node->data_.size(); + int recsize=sizeof(Envelope) + 3 * sizeof(int) + shape_count * sizeof(T); + char* node_record=new char[recsize]; + memset(node_record,0,recsize); + memcpy(node_record,&offset,4); + memcpy(node_record+4,&node->ext_,sizeof(Envelope)); + memcpy(node_record+36,&shape_count,4); + for (int i=0;idata_[i]),sizeof(T)); + } + int num_subnodes=0; + for (int i=0;i<4;++i) + { + if (node->children_[i]) + { + ++num_subnodes; + } + } + memcpy(node_record + 40 + shape_count * sizeof(T),&num_subnodes,4); + out.write(node_record,recsize); + delete [] node_record; + + for (int i=0;i<4;++i) + { + write_node(out,node->children_[i]); + } + } + } + + void print(const quadtree_node* node,int level=0) const + { + if (node) + { + typename std::vector::const_iterator itr=node->data_.begin(); + std::string pad; + for (int i=0;iext_<data_.end()) + { + std::cout<<*itr<<" "; + ++itr; + } + std::cout<children_[i],level+4); + } + } + } + + void insert(const T& data,const Envelope& item_ext,quadtree_node* node,int maxdepth) + { + if (node && node->ext_.contains(item_ext)) + { + coord2d c=node->ext_.center(); + + double width=node->ext_.width(); + double height=node->ext_.height(); + + double lox=node->ext_.minx(); + double loy=node->ext_.miny(); + double hix=node->ext_.maxx(); + double hiy=node->ext_.maxy(); + + Envelope ext[4]; + ext[0]=Envelope(lox,loy,lox + width * ratio_,loy + height * ratio_); + ext[1]=Envelope(hix - width * ratio_,loy,hix,loy + height * ratio_); + ext[2]=Envelope(lox,hiy - height*ratio_,lox + width * ratio_,hiy); + ext[3]=Envelope(hix - width * ratio_,hiy - height*ratio_,hix,hiy); + + if (maxdepth > 1) + { + for (int i=0;i<4;++i) + { + if (ext[i].contains(item_ext)) + { + if (!node->children_[i]) + { + node->children_[i]=new quadtree_node(ext[i]); + } + insert(data,item_ext,node->children_[i],maxdepth-1); + return; + } + } + } + node->data_.push_back(data); + } + } +}; +#endif //QUADTREE_HH diff --git a/util/shapeindex/shapeindex.cpp b/util/shapeindex/shapeindex.cpp new file mode 100644 index 000000000..9c40636d5 --- /dev/null +++ b/util/shapeindex/shapeindex.cpp @@ -0,0 +1,210 @@ +/* This file is part of Mapnik (c++ mapping toolkit) + * Copyright (C) 2005 Artem Pavlenko + * + * Mapnik is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +//$Id: shapeindex.cc 27 2005-03-30 21:45:40Z pavlenko $ + +#include +#include +#include "config.hh" +#include "mapnik.hh" +#include "shape.hh" +#include "quadtree.hh" + + +const int MAXDEPTH = 64; +const int DEFAULT_DEPTH = 16; +const double MINRATIO=0.5; +const double MAXRATIO=0.8; +const double DEFAULT_RATIO=0.55; + +const char* argp_program_version = "shapeindex utility version 0.1"; +const char* argp_program_bug_address="bugs@shapeindex"; + +static char doc[] = "shapeindex utility to create spatial index"; + +static char args_doc[]="shape_file"; + +static struct argp_option options[] = { + {"verbose",'v',0, 0,"Produce verbose output"}, + {"quite", 'q',0, 0,"Don't produce any output"}, + {"silent", 's',0, OPTION_ALIAS}, + {0,0,0,0, "shape index options:" }, + {"depth", 'd',"VALUE",0,"maximum depth of the tree (default=16)"}, + {"ratio", 'r',"VALUE",0,"split ratio between 0.5-0.9 (default 0.55)"}, + { 0 } +}; + +struct arguments { + char *args[2]; + int silent; + int verbose; + int depth; + double ratio; +}; + +static error_t +parse_opt ( int key,char *arg, struct argp_state *state) { + struct arguments* arguments = (struct arguments*)state->input; + switch (key) + { + case 'q': + case 's': + arguments->silent = 1; + break; + case 'v': + arguments->verbose = 1; + break; + case 'd': + arguments->depth = arg ? atoi(arg) : DEFAULT_DEPTH; + break; + case 'r': + arguments->ratio = arg ? atof(arg) : DEFAULT_RATIO; + break; + case ARGP_KEY_NO_ARGS: + argp_usage (state); + case ARGP_KEY_ARG: + if (state->arg_num>=1) + //too many arguments. + argp_usage (state); + arguments->args[state->arg_num] = arg; + break; + case ARGP_KEY_END: + if (state->arg_num < 1) + //not enough arguments + argp_usage (state); + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { options, parse_opt, args_doc, doc }; + +using namespace mapnik; + +int main (int argc,char** argv) { + + struct arguments arguments; + + arguments.silent = 0; + arguments.verbose = 0; + arguments.silent = 0; + arguments.depth = DEFAULT_DEPTH; + arguments.ratio = DEFAULT_RATIO; + argp_parse(&argp, argc, argv, 0, 0, &arguments); + + std::cout<<"processing "< extent; + shp.read_envelope(extent); + + if (!arguments.silent) { + //std::cout<<"length="< tree(extent,arguments.depth,arguments.ratio); + int count=0; + while (true) { + + int offset=shp.pos(); + int record_number=shp.read_xdr_integer(); + int content_length=shp.read_xdr_integer(); + + shp.skip(4); + Envelope item_ext; + if (shape_type==shape_io::shape_point) + { + double x=shp.read_double(); + double y=shp.read_double(); + shp.skip(2*content_length-2*8-4); + item_ext=Envelope(x,y,x,y); + + } + else if (shape_type==shape_io::shape_pointz) + { + double x=shp.read_double(); + double y=shp.read_double(); + double z=shp.read_double(); + shp.skip(2*content_length-2*8-4); + item_ext=Envelope(x,y,x,y); + } + + else + { + + shp.read_envelope(item_ext); + shp.skip(2*content_length-4*8-4); + + } + + tree.insert(offset,item_ext); + if (arguments.verbose) { + std::cout<<"record number "<