00001
00002
00003 #include <bprb/bprb_func_process.h>
00004
00005 #include <vcl_iostream.h>
00006 #include <vcl_sstream.h>
00007 #include <vcl_vector.h>
00008 #include <vcl_string.h>
00009 #include <vcl_ctime.h>
00010 #include <vcl_cstdio.h>
00011 #include <vcl_cassert.h>
00012
00013 #include <vgl/vgl_polygon.h>
00014 #include <vgl/io/vgl_io_polygon.h>
00015
00016 #include <vpl/vpl.h>
00017
00018 #include <vil/vil_image_view.h>
00019 #include <vil/vil_pixel_format.h>
00020 #include <vil/vil_convert.h>
00021
00022 #include <bmdl/bmdl_mesh.h>
00023
00024 #include <imesh/imesh_vertex.h>
00025 #include <imesh/imesh_fileio.h>
00026 #include <imesh/imesh_detection.h>
00027 #include <imesh/imesh_operations.h>
00028 #include <imesh/algo/imesh_operations.h>
00029
00030 #include <vpgl/vpgl_camera.h>
00031 #include <vpgl/file_formats/vpgl_geo_camera.h>
00032 #include <vpgl/vpgl_lvcs_sptr.h>
00033 #include <vpgl/vpgl_lvcs.h>
00034 #include <vul/vul_file.h>
00035
00036 #if HAS_ZLIB
00037 #include <minizip/zip.h>
00038 #endif
00039
00040 #define WRITEBUFFERSIZE (16384)
00041
00042
00043 void update_mesh_coord(imesh_mesh& imesh, vpgl_geo_camera* cam)
00044 {
00045 imesh_vertex_array<3>& vertices = imesh.vertices<3>();
00046 for (unsigned v=0; v<vertices.size(); v++) {
00047 unsigned int x = (unsigned int)vertices(v,0);
00048 unsigned int y = (unsigned int)vertices(v,1);
00049 unsigned int z = (unsigned int)vertices(v,2);
00050 vpgl_lvcs_sptr lvcs = cam->lvcs();
00051 double lon, lat, elev;
00052 cam->img_to_wgs(x, y, z, lon, lat, elev);
00053 vertices[v][0] = lon;
00054 vertices[v][1] = lat;
00055 vertices[v][2] = elev;
00056 }
00057 }
00058
00059 void generate_kml(vcl_string& kml_filename,
00060 imesh_mesh& mesh,
00061 vpgl_geo_camera* lidar_cam)
00062 {
00063 vcl_ofstream os(kml_filename.c_str());
00064
00065 os << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
00066 << "<kml xmlns=\"http://earth.google.com/kml/2.1\">\n"
00067 << "<Document>\n"
00068 << " <name>" << vul_file::strip_directory(kml_filename.c_str()) << "</name>\n"
00069 << " <open>1</open>\n"
00070 << " <Placemark>\n"
00071
00072 << " <visibility>1</visibility>\n"
00073 << " <MultiGeometry>\n";
00074
00075
00076 if (!mesh.has_half_edges())
00077 mesh.build_edge_graph();
00078
00079 imesh_half_edge_set he = mesh.half_edges();
00080 vcl_vector<vcl_set<unsigned int> > cc = imesh_detect_connected_components(he);
00081 for (unsigned i=0; i<cc.size(); i++) {
00082 vcl_set<unsigned int> sel_faces = cc[i];
00083 imesh_mesh building = imesh_submesh_from_faces(mesh, sel_faces);
00084 update_mesh_coord(building, lidar_cam);
00085 imesh_write_kml(os, building);
00086 }
00087
00088 os << " </MultiGeometry>\n"
00089 << " </Placemark>\n"
00090 << "</Document>\n"
00091 << "</kml>\n";
00092
00093 os.close();
00094 imesh_write_obj("meshes.obj", mesh);
00095 }
00096
00097
00098
00099
00100
00101 void
00102 write_kml_collada_wrapper(vcl_ostream& os,
00103 const vcl_string& object_name,
00104 const vgl_point_3d<double>& lookat,
00105 const vgl_point_3d<double>& location,
00106 const vgl_point_3d<double>& orientation,
00107 const vcl_string& filename)
00108 {
00109 os.precision(16);
00110 os << "<?xml version='1.0' encoding='UTF-8'?>\n"
00111 << "<kml xmlns='http://earth.google.com/kml/2.1'>\n"
00112 << "<Folder>\n"
00113 << " <name>" << object_name << "</name>\n"
00114 << " <description><![CDATA[Created with <a href=\"http://sourceforge.vxl.net\">VXL</a>]]></description>\n"
00115 << " <DocumentSource>Brown University imesh library</DocumentSource>\n"
00116 << " <visibility>1</visibility>\n"
00117 << " <LookAt>\n"
00118 << " <heading>0</heading>\n"
00119 << " <tilt>45</tilt>\n"
00120 << " <longitude>" << lookat.x() << "</longitude>\n"
00121 << " <latitude>" << lookat.y() << "</latitude>\n"
00122 << " <altitude>" << lookat.z() << "</altitude>\n"
00123 << " <range>200</range>\n"
00124 << " <altitudeMode>absolute</altitudeMode>\n"
00125 << " </LookAt>\n"
00126 << " <Folder>\n"
00127 << " <name>Tour</name>\n"
00128 << " <Placemark>\n"
00129 << " <name>Camera</name>\n"
00130 << " <visibility>1</visibility>\n"
00131 << " </Placemark>\n"
00132 << " </Folder>\n"
00133 << " <Placemark>\n"
00134 << " <name>Model</name>\n"
00135 << " <description><![CDATA[]]></description>\n"
00136 << " <Style id='default'>\n"
00137 << " </Style>\n"
00138 << " <Model>\n"
00139 << " <altitudeMode>relativeToGround</altitudeMode>\n"
00140 << " <Location>\n"
00141 << " <longitude>" << location.x() << "</longitude>\n"
00142 << " <latitude>" << location.y() << "</latitude>\n"
00143 << " <altitude>" << location.z() << "</altitude>\n"
00144 << " </Location>\n"
00145 << " <Orientation>\n"
00146 << " <heading>" << orientation.x() << "</heading>\n"
00147 << " <tilt>" << orientation.y() << "</tilt>\n"
00148 << " <roll>" << orientation.z() << "</roll>\n"
00149 << " </Orientation>\n"
00150 << " <Scale>\n"
00151 << " <x>1.0</x>\n"
00152 << " <y>1.0</y>\n"
00153 << " <z>1.0</z>\n"
00154 << " </Scale>\n"
00155 << " <Link>\n"
00156 << " <href>" << filename << "</href>\n"
00157 << " </Link>\n"
00158 << " </Model>\n"
00159 << " </Placemark>\n"
00160 << "</Folder>\n"
00161 << "</kml>\n";
00162 }
00163 #if (HAS_ZLIB)
00164 int zip_kmz(zipFile& zf, const char* filenameinzip)
00165 {
00166 FILE * fin;
00167 int size_read;
00168 zip_fileinfo zi;
00169 unsigned long crcFile=0;
00170 int size_buf=0;
00171 void* buf=NULL;
00172
00173 zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
00174 zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
00175 zi.dosDate = 0;
00176 zi.internal_fa = 0;
00177 zi.external_fa = 0;
00178
00179
00180 vcl_time_t time_secs;
00181 vcl_time(&time_secs);
00182
00183
00184 struct vcl_tm *time;
00185 time = vcl_localtime(&time_secs);
00186 zi.tmz_date.tm_sec = time->tm_sec;
00187 zi.tmz_date.tm_min = time->tm_min;
00188 zi.tmz_date.tm_hour = time->tm_hour;
00189 zi.tmz_date.tm_mday = time->tm_mday;
00190 zi.tmz_date.tm_mon = time->tm_mon ;
00191 zi.tmz_date.tm_year = time->tm_year;
00192
00193 int err = 0;
00194 int opt_compress_level=Z_DEFAULT_COMPRESSION;
00195 const char* password=0;
00196
00197 err = zipOpenNewFileInZip3(zf,filenameinzip,&zi,
00198 NULL,0,NULL,0,NULL ,
00199 (opt_compress_level != 0) ? Z_DEFLATED : 0,
00200 opt_compress_level,0,
00201 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
00202 password,crcFile);
00203
00204 if (err != ZIP_OK) {
00205 vcl_printf("error in opening %s in zipfile\n",filenameinzip);
00206 return 0;
00207 }
00208 else {
00209 fin = vcl_fopen(filenameinzip,"rb");
00210 if (fin==NULL) {
00211 err=ZIP_ERRNO;
00212 vcl_printf("error in opening %s for reading\n",filenameinzip);
00213 return 0;
00214 }
00215 }
00216
00217 size_buf = WRITEBUFFERSIZE;
00218 buf = (void*)malloc(size_buf);
00219 if (buf==NULL) {
00220 vcl_printf("Error allocating memory\n");
00221 return ZIP_INTERNALERROR;
00222 }
00223
00224 do {
00225 err = ZIP_OK;
00226 size_read = (int)vcl_fread(buf,1,size_buf,fin);
00227 if (size_read < size_buf)
00228 if (feof(fin)==0) {
00229 vcl_printf("error in reading %s\n",filenameinzip);
00230 err = ZIP_ERRNO;
00231 }
00232
00233 if (size_read>0) {
00234 err = zipWriteInFileInZip (zf,buf,size_read);
00235 if (err<0) {
00236 vcl_printf("error in writing %s in the zipfile\n", filenameinzip);
00237 }
00238 }
00239 } while ((err == ZIP_OK) && (size_read>0));
00240
00241 if (fin)
00242 vcl_fclose(fin);
00243
00244 if (err<0)
00245 err=ZIP_ERRNO;
00246 else {
00247 err = zipCloseFileInZip(zf);
00248 if (err!=ZIP_OK)
00249 vcl_printf("error in closing %s in the zipfile\n", filenameinzip);
00250 }
00251
00252 int errclose = zipClose(zf,NULL);
00253
00254 if (errclose != ZIP_OK) {
00255 vcl_printf("error in closing zipfile\n");
00256 return 0;
00257 }
00258 free(buf);
00259 return ZIP_OK;
00260 }
00261 #endif
00262
00263 void generate_kml_collada(vcl_string& kmz_dir,
00264 imesh_mesh& mesh,
00265 vpgl_geo_camera* lidar_cam,
00266 unsigned& num_of_buildings)
00267 {
00268 if (kmz_dir == "") {
00269 vcl_cerr << "Error: no filename selected.\n";
00270 return;
00271 }
00272
00273 if (!vul_file::is_directory(kmz_dir)) {
00274 vcl_cerr << "Error: Select a directory name.\n";
00275 return;
00276 }
00277
00278 vul_file::change_directory(kmz_dir);
00279 double origin_lat = 0,origin_lon = 0, origin_elev = 0;
00280 double lox, loy,theta;
00281 lidar_cam->lvcs()->get_origin(origin_lat,origin_lon,origin_elev);
00282 lidar_cam->lvcs()->get_transform(lox, loy,theta);
00283
00284 if (!mesh.has_half_edges())
00285 mesh.build_edge_graph();
00286
00287 imesh_half_edge_set he = mesh.half_edges();
00288
00289 vcl_string model_name;
00290
00291 vcl_vector<vcl_set<unsigned int> > cc = imesh_detect_connected_components(he);
00292
00293 for (unsigned i=0; i<cc.size(); i++) {
00294 vcl_set<unsigned int> sel_faces = cc[i];
00295 imesh_mesh building(imesh_submesh_from_faces(mesh, sel_faces));
00296 imesh_triangulate_nonconvex(building);
00297 building.compute_face_normals();
00298
00299
00300 double minz = vcl_numeric_limits<double>::infinity();
00301 double meanx = 0.0, meany = 0.0;
00302 const imesh_vertex_array<3>& verts = building.vertices<3>();
00303 for (unsigned int v=0; v<verts.size(); ++v) {
00304 if (verts[v][2] < minz) {
00305 minz = verts[v][2];
00306 }
00307 meanx += verts[v][0];
00308 meany += verts[v][1];
00309 }
00310 meanx /= verts.size();
00311 meany /= verts.size();
00312
00313 double lon, lat, elev;
00314
00315 lidar_cam->img_to_wgs((unsigned int)meanx, (unsigned int)(-meany), (unsigned int)minz, lon, lat, elev);
00316
00317 vcl_stringstream ss;
00318 ss << "structure_" << i+num_of_buildings;
00319 vcl_string kml_fname = ss.str() + ".kml";
00320 vcl_string dae_fname = ss.str() + ".dae";
00321
00322 vcl_ofstream os (dae_fname.data());
00323 imesh_write_kml_collada(os, building);
00324 os.close();
00325
00326 vcl_ofstream oskml(kml_fname.data());
00327 vgl_point_3d<double> lookat(lon, lat, elev);
00328 vgl_point_3d<double> location(origin_lon, origin_lat, -minz);
00329 vgl_point_3d<double> orientation(lox,loy,theta);
00330 write_kml_collada_wrapper(oskml,ss.str(),lookat,location,orientation,
00331 vul_file::strip_directory(dae_fname));
00332 oskml.close();
00333
00334 #if (HAS_ZLIB)
00335 vcl_string zip_fname = ss.str() + ".kmz";
00336 zipFile zipf = zipOpen(zip_fname.c_str(), APPEND_STATUS_CREATE);
00337 zip_kmz(zipf, dae_fname.c_str());
00338 zipf = zipOpen(zip_fname.c_str(), APPEND_STATUS_ADDINZIP);
00339 zip_kmz(zipf, kml_fname.c_str());
00340 vpl_unlink(kml_fname.c_str());
00341 vpl_unlink(dae_fname.c_str());
00342 #endif
00343 }
00344 num_of_buildings += cc.size();
00345 }
00346
00347
00348 bool generate_mesh(vcl_string fpath_poly,
00349 vil_image_view_base_sptr label_img,
00350 vil_image_view_base_sptr height_img,
00351 vil_image_view_base_sptr ground_img,
00352 vcl_string fpath_mesh,
00353 vpgl_geo_camera* const lidar_cam,
00354 unsigned& num_of_buildings)
00355 {
00356 if (label_img->pixel_format() != VIL_PIXEL_FORMAT_UINT_32) {
00357 vcl_cout << "bmdl_generate_mesh_process::the Label Image pixel format" << label_img->pixel_format() << " undefined" << vcl_endl;
00358 return false;
00359 }
00360 vil_image_view<vxl_uint_32> labels(label_img);
00361
00362 vil_image_view<double> heights;
00363 if (height_img->pixel_format() == VIL_PIXEL_FORMAT_FLOAT) {
00364 vil_convert_cast(vil_image_view<float>(*height_img), heights);
00365 }
00366 else if (height_img->pixel_format() == VIL_PIXEL_FORMAT_DOUBLE) {
00367 heights = static_cast<vil_image_view<double> >(height_img.ptr());
00368 }
00369 else {
00370 vcl_cout << "bmdl_generate_mesh_process::the Height Image pixel format" << height_img->pixel_format() << " undefined" << vcl_endl;
00371 return false;
00372 }
00373
00374 vil_image_view<double> ground;
00375 if (ground_img->pixel_format() == VIL_PIXEL_FORMAT_FLOAT) {
00376 vil_convert_cast(vil_image_view<float>(*ground_img), ground);
00377 }
00378 else if (ground_img->pixel_format() == VIL_PIXEL_FORMAT_DOUBLE) {
00379 ground = static_cast<vil_image_view<double> >(ground_img.ptr());
00380 }
00381 else {
00382 vcl_cout << "bmdl_generate_mesh_process::the Ground Image pixel format" << ground_img->pixel_format() << " undefined" << vcl_endl;
00383 return false;
00384 }
00385
00386
00387 vsl_b_ifstream os(fpath_poly);
00388 unsigned char ver;
00389 vsl_b_read(os, ver);
00390 unsigned int size;
00391 vsl_b_read(os, size);
00392 vgl_polygon<double> polygon;
00393 vcl_vector<vgl_polygon<double> > boundaries;
00394 for (unsigned i = 0; i < size; i++) {
00395 vsl_b_read(os, polygon);
00396 boundaries.push_back(polygon);
00397 }
00398
00399 vcl_vector<bmdl_edge> edges;
00400 vcl_vector<bmdl_region> regions;
00401 unsigned int num_joints = bmdl_mesh::link_boundary_edges(labels, boundaries,
00402 edges, regions);
00403 bmdl_mesh::simplify_edges(edges);
00404 imesh_mesh mesh;
00405 bmdl_mesh::mesh_lidar(edges, regions, num_joints, labels,
00406 heights, ground, mesh);
00407
00408 generate_kml_collada(fpath_mesh, mesh, lidar_cam, num_of_buildings);
00409 return true;
00410 }
00411
00412 bool bmdl_generate_mesh_process(bprb_func_process& pro)
00413 {
00414 if (pro.n_inputs()< 6) {
00415 vcl_cout << "lidar_roi_process: The input number should be 6" << vcl_endl;
00416 return false;
00417 }
00418
00419 unsigned int i=0;
00420 vcl_string file_poly = pro.get_input<vcl_string>(i++);
00421 vil_image_view_base_sptr label_img = pro.get_input<vil_image_view_base_sptr>(i++);
00422 vil_image_view_base_sptr height_img = pro.get_input<vil_image_view_base_sptr>(i++);
00423 vil_image_view_base_sptr ground_img = pro.get_input<vil_image_view_base_sptr>(i++);
00424 vcl_string file_mesh = pro.get_input<vcl_string>(i++);
00425 vpgl_camera_double_sptr camera = pro.get_input<vpgl_camera_double_sptr>(i++);
00426
00427 if (!label_img) {
00428 vcl_cout << "bmdl_generate_mesh_process -- Label image is not set!\n";
00429 return false;
00430 }
00431
00432 if (!height_img) {
00433 vcl_cout << "bmdl_generate_mesh_process -- Label image is not set!\n";
00434 return false;
00435 }
00436
00437 if (!ground_img) {
00438 vcl_cout << "bmdl_generate_mesh_process -- Label image is not set!\n";
00439 return false;
00440 }
00441
00442 if (camera->type_name().compare("vpgl_geo_camera") != 0) {
00443 vcl_cout << "bmdl_generate_mesh_process -- Camera input should be type of lidar!\n";
00444 return false;
00445 }
00446
00447 vpgl_geo_camera* lidar_cam = static_cast<vpgl_geo_camera*>(camera.ptr());
00448 unsigned num_of_buildings=0;
00449 return generate_mesh(file_poly, label_img, height_img, ground_img, file_mesh, lidar_cam, num_of_buildings);
00450 }
00451
00452 bool bmdl_generate_mesh_process_cons(bprb_func_process& pro)
00453 {
00454 vcl_vector<vcl_string> input_types;
00455 input_types.push_back("vcl_string");
00456 input_types.push_back("vil_image_view_base_sptr");
00457 input_types.push_back("vil_image_view_base_sptr");
00458 input_types.push_back("vil_image_view_base_sptr");
00459 input_types.push_back("vcl_string");
00460 input_types.push_back("vpgl_camera_double_sptr");
00461 return pro.set_input_types(input_types);
00462 }