00001 //$Header: /home/ben/Mapper/c++/RCS/MapDataDocument_convert_Tracing.cpp,v 6.14 2002/07/14 17:25:32 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
00031 #include <cstdio>
00032 #include <cstdlib>
00033 #include <cstring>
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 "angle_constraint.h"
00047 #include "assoc.h"
00048 #include "constraint.h"
00049 #include "delaunay.h"
00050 #include "vector2.h"
00051 #include "through_constraint.h"
00052
00053
00054
00055 void MapDataDocument::convert_Traced_point(
00056 map< vector2, vector2 *, order_vector2 > &traced_points, //input, output
00057 map< vector2, double, order_vector2 > &point_uncertainties, //input, output
00058 DOM_Element &elem, //input
00059 const double tracing_width,
00060 const double tracing_height,
00061 const double default_uncertainty
00062 )
00063 throw(
00064 error::element_error
00065 )
00066 {
00067 {//preconditions:
00068 assert( 0 < tracing_width );
00069 assert( 0 < tracing_height );
00070 assert( 0 < default_uncertainty );
00071 };
00072 bool anon;
00073 string name;
00074 vector2 position;
00075 vector2 *point;
00076 double uncertainty = default_uncertainty;
00077 {//retrieve the attribute values
00078 require_attribute( elem, "tx" );
00079 require_attribute( elem, "ty" );
00080 if( has_attribute( elem, "point" ) ){
00081 anon = false;
00082 get_attribute( name, elem, "point" );
00083 this->get_attribute( point, elem, "point" );
00084 }else{ //anonymous point
00085 anon = true;
00086 name = "(anonymous)";
00087 vector2 global_position( this->random_position() );
00088 if( has_attribute( elem, "x" ) )
00089 get_attribute( global_position.x, elem, "x" );
00090 ;
00091 if( has_attribute( elem, "y" ) )
00092 get_attribute( global_position.y, elem, "y" );
00093 ;
00094 point = new vector2( global_position );
00095 };
00096 get_attribute( position.x, elem, "tx" );
00097 get_attribute( position.y, elem, "ty" );
00098 if( has_attribute( elem, "uncertainty" ) ){
00099 get_attribute( uncertainty, elem, "uncertainty" );
00100 };
00101 };
00102 {//check attribute values
00103 if( position.x < 0 || tracing_width < position.x )
00104 throw error::attribute_error( elem, "out of range", "tx" );
00105 ;
00106 if( position.y < 0 || tracing_height < position.y )
00107 throw error::attribute_error( elem, "out of range", "ty" );
00108 ;
00109 if( 0 < traced_points.count( position ) )
00110 throw error::element_error( elem, "position already traced" );
00111 ;
00112 if( uncertainty <= 0 )
00113 throw error::attribute_error( elem, "not positive", "uncertainty" );
00114 ;
00115 };
00116 {//Add the traced point to data structures
00117 assert( point );
00118 traced_points[ position ] = point;
00119 point_uncertainties[ position ] = uncertainty;
00120 if( anon ){
00121 this->anon_points_.push_back( point );
00122 };
00123 elem.setUserData( point );
00124 };
00125 }
00126
00127
00128
00129 void MapDataDocument::add_angle_constraint(
00130 const vector2 &vf, //local coordinates
00131 const vector2 &va,
00132 const vector2 &vt,
00133 vector2 *pf, //points, input
00134 vector2 *pa,
00135 vector2 *pt,
00136 const double uf, //uncertainties
00137 const double ua,
00138 const double ut
00139 )
00140 {
00141 {//Preconditions
00142 assert( pf );
00143 assert( pa );
00144 assert( pt );
00145 assert( 0 < uf );
00146 assert( 0 < ua );
00147 assert( 0 < ut );
00148 }
00149 const double r1c1 = vf.x - va.x;
00150 const double r1s1 = vf.y - va.y;
00151 const double r2c2 = vt.x - va.x;
00152 const double r2s2 = vt.y - va.y;
00153 const double r1 = hypot( r1c1, r1s1 );
00154 const double r2 = hypot( r2c2, r2s2 );
00155 assert( 0 < r1 );
00156 assert( 0 < r2 );
00157 const double a1 = atan2( r1s1, r1c1 );
00158 const double a2 = atan2( r2s2, r2c2 );
00159 const double angle = a2 - a1;
00160 const double u1 = (uf + ua)/ r1;
00161 const double u2 = (ut + ua)/ r2;
00162 const double uncertainty = u1 + u2;
00163 angle_constraint *a = new angle_constraint( uncertainty, angle );
00164 assoc( *a, *pa, *pf, *pt );
00165 this->constraints_.push_back( a );
00166 }
00167
00168
00169
00170 void MapDataDocument::convert_Tracing(
00171 DOM_Element &elem,
00172 MapperErrorHandler &err_handler
00173 )
00174 throw(
00175 error::attribute_error
00176 )
00177 {
00178 double length_uncertainty;
00179 double tracing_height;
00180 double tracing_width;
00181 {//process the attributes of the Tracing tag
00182 {//get attributes
00183 get_attribute( length_uncertainty, elem, "length-uncertainty" );
00184 get_attribute( tracing_width, elem, "width" );
00185 get_attribute( tracing_height, elem, "height" );
00186 };
00187 {//check attribute values
00188 if( length_uncertainty <= 0 )
00189 throw error::attribute_error(
00190 elem, "not positive", "length-uncertainty"
00191 );
00192 ;
00193 if( tracing_width <= 0 )
00194 throw error::attribute_error( elem, "not positive", "width" );
00195 ;
00196 if( tracing_height <= 0 )
00197 throw error::attribute_error( elem, "not positive", "height" );
00198 ;
00199 };
00200 }
00201 map< vector2, vector2 *, order_vector2 > traced_points;
00202 map< vector2, double, order_vector2 > point_uncertainties;
00203 {//process children of the element
00204 DOM_NodeList children( elem.getChildNodes() );
00205 for( unsigned i = 0; i < children.getLength(); i++ ){
00206 DOM_Node node( children.item(i) );
00207 if( node.getNodeType() != DOM_Node::ELEMENT_NODE ) continue;
00208 DOM_Element &child( static_cast< DOM_Element & >( node ) );
00209 DOMString tag( child.getTagName() );
00210 try{
00211 if( DOMString("Cite").equals( tag ) )
00212 ;//Do nothing
00213 else if( DOMString("Traced-point").equals( tag ) )
00214 this->convert_Traced_point(
00215 traced_points, point_uncertainties,
00216 child, tracing_width, tracing_height, length_uncertainty
00217 );
00218 else{
00219 throw error::element_error( child, "unexpected element" );
00220 };
00221 }catch( error::element_error &e ){
00222 err_handler.error( e );
00223 };
00224 };
00225 };
00226 delaunay::triangulation triangulation(
00227 -tracing_width, tracing_width*1.1,
00228 tracing_height*1.1, -tracing_height
00229 );
00230 {//create triangulation
00231 for( map< vector2, vector2 *,order_vector2 >::iterator i =
00232 traced_points.begin();
00233 i != traced_points.end();
00234 i++ ){
00235 const vector2 &position( (*i).first );
00236 triangulation.add_point( position );
00237 };
00238 };
00239 {//create constraints
00240 const vector< delaunay::triangle > &triangles(
00241 triangulation.triangles()
00242 );
00243 for( vector< delaunay::triangle >::const_iterator i = triangles.begin();
00244 i != triangles.end();
00245 i++ ){
00246 const delaunay::triangle &t( *i );
00247 if( ! triangulation.border_triangle( t ) ){
00248 //create an angle constraint for each vertex of that triangle
00249
00250 const vector2 &v0( t.vertex(0) );
00251 const vector2 &v1( t.vertex(1) );
00252 const vector2 &v2( t.vertex(2) );
00253 vector2 *p0 = traced_points[ v0 ];
00254 vector2 *p1 = traced_points[ v1 ];
00255 vector2 *p2 = traced_points[ v2 ];
00256 const double u0 = point_uncertainties[ v0 ];
00257 const double u1 = point_uncertainties[ v1 ];
00258 const double u2 = point_uncertainties[ v2 ];
00259
00260 add_angle_constraint(
00261 v0, v1, v2,
00262 p0, p1, p2,
00263 u0, u1, u2
00264 );
00265 add_angle_constraint(
00266 v1, v2, v0,
00267 p1, p2, p0,
00268 u1, u2, u0
00269 );
00270 add_angle_constraint(
00271 v2, v0, v1,
00272 p2, p0, p1,
00273 u2, u0, u1
00274 );
00275 };//else skip that triangle
00276 };
00277 };
00278 }