00001 //$Header: /home/ben/Mapper/c++/RCS/MapDataDocument_convert.cpp,v 6.25 2002/07/09 22:50:52 ben Exp $
00002 // Copyright Benedict Adamson 2002.
00003 // This file is part of Mapper.
00004
00005 // Mapper is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009
00010 // Mapper is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013 // GNU General Public License for more details.
00014
00015 // You should have received a copy of the GNU General Public License
00016 // along with Mapper; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00018
00030 #include <cstdio>
00031 #include <cstdlib>
00032 #include <cstring>
00033 #include <map>
00034 #include <memory>
00035
00036 #include <dom/DOM_Attr.hpp>
00037 #include <dom/DOM_DOMException.hpp>
00038 #include <dom/DOM_Element.hpp>
00039 #include <dom/DOM_Document.hpp>
00040 #include <dom/DOM_Node.hpp>
00041
00042 #include <string>
00043
00044 #include "MapDataDocument.h"
00045 #include "MapperErrorHandler.h"
00046 #include "curve.h"
00047 #include "curve_segment.h"
00048 #include "vector2.h"
00049
00050
00051
00052 void MapDataDocument::convert_Curve(
00053 DOM_Element &elem, //input
00054 MapperErrorHandler &err_handler
00055 )
00056 throw(
00057 error::attribute_error
00058 )
00059 {
00060 string id;
00061 vector2 *from;
00062 vector2 *to;
00063 {//retrieve attribute values
00064 get_attribute( id, elem, "id" );
00065 this->get_attribute( from, elem, "from" );
00066 this->get_attribute( to, elem, "to" );
00067 };
00068 curve *c = new curve;
00069 c->param.push_back( from );
00070 c->param.push_back( to );
00071 this->curves_[id] = c;
00072 elem.setUserData( c );
00073 {//set the parameters, from Coord children
00074 DOM_NodeList children(
00075 elem.getElementsByTagName( DOMString("Coord" ) )
00076 );
00077 const unsigned n = children.getLength();
00078 assert( c->param.size() == 2 );
00079 c->param.reserve( n ); //optimisation
00080 for( unsigned i = 0; i < n; i++ ){
00081 DOM_Node node( children.item(i) );
00082 assert( node.getNodeType() == DOM_Node::ELEMENT_NODE );
00083 DOM_Element &child( static_cast< DOM_Element & >( node ) );
00084 try{
00085 vector2 position( this->random_position() );
00086 if( has_attribute( child, "x" ) )
00087 get_attribute( position.x, child, "x" );
00088 ;
00089 if( has_attribute( child, "y" ) )
00090 get_attribute( position.y, child, "y" );
00091 ;
00092 vector2 *p = new vector2( position );
00093 child.setUserData( p );
00094 c->param.push_back( p );
00095 }catch( error::attribute_error &e ){
00096 err_handler.error( e );
00097 };
00098 };
00099 };
00100 }
00101
00102
00103
00104 void MapDataDocument::convert_Fixed_point(
00105 DOM_Element &elem //input
00106 )
00107 throw(
00108 error::attribute_error
00109 )
00110 {
00111 string point_name;
00112 double x;
00113 double y;
00114 {//retrieve attribute values
00115 get_attribute( point_name, elem, "point" );
00116 get_attribute( x, elem, "x" );
00117 get_attribute( y, elem, "y" );
00118 };
00119 map< string, vector2 * >::iterator i =
00120 this->named_points_.find( point_name );
00121 if( i == this->named_points_.end() )
00122 throw error::attribute_error( elem, "point not found", "point" );
00123 ;
00124 vector2 *p = (*i).second;
00125 assert( p );
00126 this->fixed_points_.insert( p );
00127 p->x = x;
00128 p->y = y;
00129 elem.setUserData( p );
00130 }
00131
00132
00133 void MapDataDocument::convert_Point(
00134 DOM_Element &elem //input
00135 )
00136 throw(
00137 error::attribute_error
00138 )
00139 {
00140 string id;
00141 vector2 position( this->random_position() );
00142 {//retrieve attribute values
00143 get_attribute( id, elem, "id" );
00144 if( has_attribute( elem, "x" ) )
00145 get_attribute( position.x, elem, "x" );
00146 ;
00147 if( has_attribute( elem, "y" ) )
00148 get_attribute( position.y, elem, "y" );
00149 ;
00150 };
00151 vector2 *p = new vector2( position );
00152 this->named_points_[id] = p;
00153 elem.setUserData( p );
00154 }
00155
00156
00157
00158 void MapDataDocument::convert_Point_alias(
00159 DOM_Element &elem //input
00160 )
00161 throw(
00162 error::attribute_error
00163 )
00164 {
00165 string id;
00166 vector2 *p;
00167 {//retrieve attribute values
00168 get_attribute( id, elem, "id" );
00169 if( this->named_points_.count( id ) ){
00170 throw error::attribute_error( elem, "already the id of a point", "id" );
00171 };
00172 this->get_attribute( p, elem, "point" );
00173 assert( p );
00174 };
00175 this->named_points_[id] = p;
00176 }
00177
00178
00179
00180 void MapDataDocument::convert_pointrefs(
00181 DOM_Element &elem, //input
00182 const char *tag,
00183 MapperErrorHandler &err_handler
00184 )
00185 {
00186 DOM_NodeList children(
00187 elem.getElementsByTagName( DOMString(tag) )
00188 );
00189 for( unsigned i = 0; i < children.getLength(); i++ ){
00190 DOM_Node node( children.item(i) );
00191 if( node.getNodeType() != DOM_Node::ELEMENT_NODE ) continue;
00192 DOM_Element &child( static_cast< DOM_Element & >( node ) );
00193 try{
00194 vector2 *p;
00195 this->get_attribute( p, child, "point" );
00196 child.setUserData( p );
00197 }catch( error::attribute_error &e ){
00198 err_handler.error( e );
00199 };
00200 };
00201 }
00202
00203
00204
00205 void MapDataDocument::convert_Curve_segments(
00206 DOM_Element &elem, //input
00207 MapperErrorHandler &err_handler
00208 )
00209 {
00210 DOM_NodeList children(
00211 elem.getElementsByTagName( DOMString("Curve-segment") )
00212 );
00213 for( unsigned i = 0; i < children.getLength(); i++ ){
00214 DOM_Node node( children.item(i) );
00215 DOM_Element &child( static_cast< DOM_Element & >( node ) );
00216 try{
00217 curve *c;
00218 vector2 *from;
00219 vector2 *to;
00220 this->get_attribute( c, child, "curve" );
00221 this->get_attribute( to, child, "point" );
00222 {//determine the from point
00223 from = 0;
00224 DOM_Node f = child.getPreviousSibling();
00225 while( !from && !f.isNull() ){
00226 if( f.getNodeType() == DOM_Node::ELEMENT_NODE ){
00227 DOM_Element &sib( static_cast< DOM_Element & >( f ) );
00228 DOMString tag( sib.getTagName() );
00229 if( DOMString("Node").equals( tag ) ||
00230 DOMString("Line-segment").equals( tag ) ||
00231 DOMString("Curve-segment").equals( tag ) )
00232 this->get_attribute( from, sib, "point" );
00233 ;
00234 };
00235 if( !from )
00236 f = f.getPreviousSibling(); //next
00237 ;
00238 };
00239 };
00240 if( c && from && to ){
00241 curve_segment *s = new curve_segment( c, from, to );
00242 child.setUserData( s );
00243 };
00244 }catch( error::attribute_error &e ){
00245 err_handler.error( e );
00246 };
00247 };
00248 }
00249
00250
00251
00252 void MapDataDocument::convert(
00253 MapperErrorHandler &err_handler //input
00254 )
00255 {
00256 DOM_Element root( this->doc.getDocumentElement() );
00257 {//set default values for the attributes of the root tag
00258 this->precision = 6U;
00259 this->origin_ = vector2(0,1);
00260 this->width_ = 1.0;
00261 this->height_ = 1.0;
00262 };
00263 try{//process the attributes of the root tag
00264 {//get attributes
00265 if( has_attribute( root, "precision" ) ){
00266 get_attribute( this->precision, root, "precision" );
00267 };
00268 if( has_attribute( root, "width" ) ){
00269 get_attribute( this->width_, root, "width" );
00270 };
00271 if( has_attribute( root, "height" ) ){
00272 get_attribute( this->height_, root, "height" );
00273 };
00274 if( has_attribute( root, "x" ) ){
00275 get_attribute( this->origin_.x, root, "x" );
00276 };
00277 if( has_attribute( root, "y" ) ){
00278 get_attribute( this->origin_.y, root, "y" );
00279 };
00280 };
00281 {//check attribute values
00282 if( this->width_ <= 0 )
00283 throw error::attribute_error( root, "negative value", "width" );
00284 ;
00285 if( this->height_ <= 0 )
00286 throw error::attribute_error( root, "negative value", "height" );
00287 ;
00288 };
00289 }catch( error::attribute_error &e ){
00290 err_handler.error( e );
00291 };
00292
00293 DOM_NodeList children( root.getChildNodes() );
00294 for( unsigned i = 0; i < children.getLength(); i++ ){
00295 DOM_Node node( children.item(i) );
00296 if( node.getNodeType() != DOM_Node::ELEMENT_NODE ) continue;
00297 DOM_Element &elem( static_cast< DOM_Element & >( node ) );
00298 DOMString tag( elem.getTagName() );
00299 try{
00300 if( DOMString("Area-feature").equals( tag ) ){
00301 this->convert_pointrefs( elem, "Node", err_handler );
00302 this->convert_pointrefs( elem, "Line-segment", err_handler );
00303 this->convert_Curve_segments( elem, err_handler );
00304 }else if( DOMString("Constraint-group").equals( tag ) )
00305 this->convert_Constraint_group( elem, err_handler );
00306 else if( DOMString("Curve").equals( tag ) )
00307 this->convert_Curve( elem, err_handler );
00308 else if( DOMString("Fixed-point").equals( tag ) )
00309 this->convert_Fixed_point( elem );
00310 else if( DOMString("Linear-feature").equals( tag ) ){
00311 this->convert_pointrefs( elem, "Node", err_handler );
00312 this->convert_pointrefs( elem, "Line-segment", err_handler );
00313 this->convert_Curve_segments( elem, err_handler );
00314 }else if( DOMString("Tracing").equals( tag ) )
00315 this->convert_Tracing( elem, err_handler );
00316 else if( DOMString("Point").equals( tag ) )
00317 this->convert_Point( elem );
00318 else if( DOMString("Point-alias").equals( tag ) )
00319 this->convert_Point_alias( elem );
00320 else if( DOMString("Point-feature").equals( tag ) )
00321 this->convert_pointrefs( elem, "Node", err_handler );
00322 else if( DOMString("Units").equals( tag ) ){
00323 DOMString angle_attr( elem.getAttribute( DOMString( "angle" ) ) );
00324 if( !DOMString("degrees").equals( angle_attr ) )
00325 throw error::attribute_error( elem, "unrecognised units", "angle" );
00326 //In a future version, could amend to parse different values.
00327 ;
00328 }else{
00329 throw error::element_error( elem, "unexpected element" );
00330 };
00331 }catch( error::element_error &e ){
00332 err_handler.error( e );
00333 };
00334 };
00335 }
00336
00337
00338
00339 vector2 MapDataDocument::random_position(void) const
00340 {
00341 static const double f = 1.0/(double)RAND_MAX;
00342 return vector2(
00343 this->origin_.x + this->width_ * ((double)rand()) * f,
00344 this->origin_.y - this->height_ * ((double)rand()) * f
00345 );
00346 }