diff --git a/.gitignore b/.gitignore index 74affe661..ea2cae4da 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,9 @@ rc/Drop-Files-Here-extra-black.png *.opensdf *.exe BuildTools/windows/logger.txt + +BuildTools/.DS_Store + +.DS_Store + +*.DS_Store diff --git a/BuildTools/macosx/GeoDa.xcodeproj/project.pbxproj b/BuildTools/macosx/GeoDa.xcodeproj/project.pbxproj index d04595296..edb1228b8 100644 --- a/BuildTools/macosx/GeoDa.xcodeproj/project.pbxproj +++ b/BuildTools/macosx/GeoDa.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ A11F1B821850437A006F5F98 /* OGRTableOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A11F1B801850437A006F5F98 /* OGRTableOperation.cpp */; }; A12E0F4F1705087A00B6059C /* OGRDataAdapter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A12E0F4E1705087A00B6059C /* OGRDataAdapter.cpp */; }; A13B6B9418760CF100F93ACF /* SaveAsDlg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A13B6B9318760CF100F93ACF /* SaveAsDlg.cpp */; }; + A14C496F1D76174000D9831C /* CsvFieldConfDlg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A14C496D1D76174000D9831C /* CsvFieldConfDlg.cpp */; }; A16BA470183D626200D3B7DA /* DatasourceDlg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A16BA46E183D626200D3B7DA /* DatasourceDlg.cpp */; }; A186F0A11C16508A00AEBA13 /* GdaCartoDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A186F09F1C16508A00AEBA13 /* GdaCartoDB.cpp */; }; A19F51501756A11E006E31B4 /* plugins in Resources */ = {isa = PBXBuildFile; fileRef = A19F514D1756A11E006E31B4 /* plugins */; }; @@ -233,6 +234,8 @@ A12E0F4E1705087A00B6059C /* OGRDataAdapter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OGRDataAdapter.cpp; sourceTree = ""; }; A13B6B9218760CF100F93ACF /* SaveAsDlg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaveAsDlg.h; sourceTree = ""; }; A13B6B9318760CF100F93ACF /* SaveAsDlg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SaveAsDlg.cpp; sourceTree = ""; }; + A14C496D1D76174000D9831C /* CsvFieldConfDlg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CsvFieldConfDlg.cpp; sourceTree = ""; }; + A14C496E1D76174000D9831C /* CsvFieldConfDlg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CsvFieldConfDlg.h; sourceTree = ""; }; A16BA46E183D626200D3B7DA /* DatasourceDlg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatasourceDlg.cpp; sourceTree = ""; }; A16BA46F183D626200D3B7DA /* DatasourceDlg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatasourceDlg.h; sourceTree = ""; }; A171FBFE1792332A000DD5A0 /* GdaException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GdaException.h; sourceTree = ""; }; @@ -750,6 +753,8 @@ DD7974FE0F1D296F00496A84 /* DialogTools */ = { isa = PBXGroup; children = ( + A14C496D1D76174000D9831C /* CsvFieldConfDlg.cpp */, + A14C496E1D76174000D9831C /* CsvFieldConfDlg.h */, A1EBC88D1CD2B2FD001DCFE9 /* AutoUpdateDlg.cpp */, A1EBC88E1CD2B2FD001DCFE9 /* AutoUpdateDlg.h */, A1AC05BD1C8645F300B6FE5F /* AdjustYAxisDlg.cpp */, @@ -1369,6 +1374,7 @@ DDEA3CBE193CEE5C0028B746 /* GdaLexer.cpp in Sources */, DDEA3CBF193CEE5C0028B746 /* GdaParser.cpp in Sources */, DDEA3D01193D17130028B746 /* CalculatorDlg.cpp in Sources */, + A14C496F1D76174000D9831C /* CsvFieldConfDlg.cpp in Sources */, DDA4F0A4196311A9007645E2 /* WeightsMetaInfo.cpp in Sources */, DDA4F0AD196315AF007645E2 /* WeightUtils.cpp in Sources */, DD817EA819676AF100228B0A /* WeightsManState.cpp in Sources */, diff --git a/BuildTools/macosx/auto_build.sh b/BuildTools/macosx/auto_build.sh index 0ace3869d..29e26ec26 100755 --- a/BuildTools/macosx/auto_build.sh +++ b/BuildTools/macosx/auto_build.sh @@ -11,7 +11,7 @@ git pull cd ~/geoda_trunk/o rm * cd ~/geoda_trunk/BuildTools/macosx -./build.sh $CPU $DEBUG +./build.sh $CPU $NODEBUG cd ~/Dropbox/yoursway-create-dmg ./geoda.sh $VERSION mv GeoDa$VERSION-Installer.dmg ~/Dropbox diff --git a/BuildTools/ubuntu/build64.sh b/BuildTools/ubuntu/build64.sh index c205907dc..ed21d8aec 100755 --- a/BuildTools/ubuntu/build64.sh +++ b/BuildTools/ubuntu/build64.sh @@ -644,7 +644,7 @@ echo "%%%%%%%%%%%%%%%%%%%" mkdir ../../o $MAKER make app - cp plugins/x64/*.so build/plugins/ + #cp plugins/x64/*.so build/plugins/ cp ../CommonDistFiles/cache.sqlite build/ cp ../CommonDistFiles/geoda_prefs.sqlite build/ cp ../CommonDistFiles/geoda_prefs.json build/ diff --git a/BuildTools/windows/GeoDa.vcxproj b/BuildTools/windows/GeoDa.vcxproj index 6e37531c5..d55f14972 100644 --- a/BuildTools/windows/GeoDa.vcxproj +++ b/BuildTools/windows/GeoDa.vcxproj @@ -205,6 +205,7 @@ + @@ -271,6 +272,7 @@ + diff --git a/BuildTools/windows/GeoDa.vcxproj.filters b/BuildTools/windows/GeoDa.vcxproj.filters index 86c17239f..f8c8be3c0 100644 --- a/BuildTools/windows/GeoDa.vcxproj.filters +++ b/BuildTools/windows/GeoDa.vcxproj.filters @@ -621,6 +621,9 @@ DialogTools + + DialogTools + @@ -1133,5 +1136,8 @@ DialogTools + + DialogTools + \ No newline at end of file diff --git a/DialogTools/ConnectDatasourceDlg.cpp b/DialogTools/ConnectDatasourceDlg.cpp index 5ed67d39b..8e1e65cbe 100644 --- a/DialogTools/ConnectDatasourceDlg.cpp +++ b/DialogTools/ConnectDatasourceDlg.cpp @@ -33,6 +33,7 @@ #include #include +#include "../DialogTools/CsvFieldConfDlg.h" #include "../DataViewer/DataSource.h" #include "../ShapeOperations/OGRDataAdapter.h" #include "../GenUtils.h" @@ -58,8 +59,6 @@ class DnDFile : public wxFileDropTarget bool DnDFile::OnDropFiles(wxCoord, wxCoord, const wxArrayString& filenames) { size_t nFiles = filenames.GetCount(); - //wxString str; - //str.Printf( wxT("%d files dropped"), (int)nFiles); if (m_pOwner != NULL && nFiles > 0) { @@ -83,8 +82,7 @@ END_EVENT_TABLE() using namespace std; -ConnectDatasourceDlg::ConnectDatasourceDlg(wxWindow* parent, const wxPoint& pos, - const wxSize& size) +ConnectDatasourceDlg::ConnectDatasourceDlg(wxWindow* parent, const wxPoint& pos, const wxSize& size) :datasource(0) { // init controls defined in parent class @@ -98,8 +96,7 @@ ConnectDatasourceDlg::ConnectDatasourceDlg(wxWindow* parent, const wxPoint& pos, m_drag_drop_box->SetDropTarget(new DnDFile(this)); - Bind(wxEVT_COMMAND_MENU_SELECTED, &ConnectDatasourceDlg::BrowseDataSource, - this, DatasourceDlg::ID_DS_START, ID_DS_START + ds_names.Count()); + Bind(wxEVT_COMMAND_MENU_SELECTED, &ConnectDatasourceDlg::BrowseDataSource, this, DatasourceDlg::ID_DS_START, ID_DS_START + ds_names.Count()); } ConnectDatasourceDlg::~ConnectDatasourceDlg() @@ -194,6 +191,7 @@ void ConnectDatasourceDlg::OnOkClick( wxCommandEvent& event ) { LOG_MSG("Entering ConnectDatasourceDlg::OnOkClick"); try { + // Open GeoDa project file direclty if (ds_file_path.GetExt().Lower() == "gda") { GdaFrame* gda_frame = GdaFrame::GetGdaFrame(); if (gda_frame) { @@ -202,8 +200,16 @@ void ConnectDatasourceDlg::OnOkClick( wxCommandEvent& event ) } return; } + + // For csv file, if no csvt file, pop-up a field definition dialog and create a csvt file + //if (ds_file_path.GetExt().Lower() == "csv") { + // wxString csv_path = ds_file_path.GetFullPath(); + // CsvFieldConfDlg csvDlg(this, csv_path); + // csvDlg.ShowModal(); + //} CreateDataSource(); + // Check to make sure to get a layer name wxString layername; int datasource_type = m_ds_notebook->GetSelection(); @@ -238,10 +244,12 @@ void ConnectDatasourceDlg::OnOkClick( wxCommandEvent& event ) return; } - if (layername.IsEmpty()) return; + if (layername.IsEmpty()) + return; // At this point, there is a valid datasource and layername. - if (layer_name.IsEmpty()) layer_name = layername; + if (layer_name.IsEmpty()) + layer_name = layername; EndDialog(wxID_OK); @@ -298,8 +306,7 @@ IDataSource* ConnectDatasourceDlg::CreateDataSource() PromptDSLayers(datasource); if (layer_name.IsEmpty()) { throw GdaException( - wxString("Layer/Table name could not be empty. Please select" - " a layer/table.").mb_str()); + wxString("Layer/Table name could not be empty. Please select a layer/table.").mb_str()); } } @@ -322,10 +329,7 @@ IDataSource* ConnectDatasourceDlg::CreateDataSource() else if (cur_sel == DBTYPE_MYSQL) ds_type = GdaConst::ds_mysql; //else if (cur_sel == 4) ds_type = GdaConst::ds_ms_sql; else { - wxString msg = "The selected database driver is not supported " - "on this platform. Please check GeoDa website " - "for more information about database support " - " and connection."; + wxString msg = "The selected database driver is not supported on this platform. Please check GeoDa website for more information about database support and connection."; throw GdaException(msg.mb_str()); } diff --git a/DialogTools/CreatingWeightDlg.cpp b/DialogTools/CreatingWeightDlg.cpp index 3cea4596e..88a7b9e1a 100644 --- a/DialogTools/CreatingWeightDlg.cpp +++ b/DialogTools/CreatingWeightDlg.cpp @@ -191,8 +191,16 @@ void CreatingWeightDlg::OnCreateNewIdClick( wxCommandEvent& event ) if (dlg.ShowModal() == wxID_OK) { // We know that the new id has been added to the the table in memory - m_id_field->Insert(dlg.GetIdVarName(), 0); + //wxString new_id = dlg.GetIdVarName(); + //m_id_field->Insert(new_id, 0); + //m_id_field->SetSelection(0); + + col_id_map.clear(); + table_int->FillColIdMap(col_id_map); + + InitFields(); m_id_field->SetSelection(0); + EnableDistanceRadioButtons(m_id_field->GetSelection() != wxNOT_FOUND); EnableContiguityRadioButtons((m_id_field->GetSelection() != wxNOT_FOUND) && !project->IsTableOnlyProject()); UpdateCreateButtonState(); @@ -296,17 +304,18 @@ void CreatingWeightDlg::OnCreateClick( wxCommandEvent& event ) { GwtWeight* Wp = 0; double t_val = m_threshold_val; - if (t_val <= 0) t_val = std::numeric_limits::min(); - wmi.SetToThres(id, dist_metric, dist_units, dist_values, - t_val, dist_var_1, dist_tm_1, - dist_var_2, dist_tm_2); + if (t_val <= 0) { + t_val = std::numeric_limits::min(); + } + wmi.SetToThres(id, dist_metric, dist_units, dist_units_str,dist_values, t_val, dist_var_1, dist_tm_1, dist_var_2, dist_tm_2); + if (m_is_arc && m_arc_in_km) { t_val /= GenGeomAlgs::one_mi_in_km; // convert km to mi } + if (t_val > 0) { using namespace SpatialIndAlgs; - Wp = thresh_build(m_XCOO, m_YCOO, t_val * m_thres_delta_factor, - m_is_arc, !m_arc_in_km); + Wp = thresh_build(m_XCOO, m_YCOO, t_val * m_thres_delta_factor, m_is_arc, !m_arc_in_km); if (!Wp || !Wp->gwt) { wxString m; m << "No weights file was created due to all observations "; @@ -327,15 +336,20 @@ void CreatingWeightDlg::OnCreateClick( wxCommandEvent& event ) case KNN: // k nn { - wmi.SetToKnn(id, dist_metric, dist_units, dist_values, m_kNN, dist_var_1, dist_tm_1, dist_var_2, dist_tm_2); + wmi.SetToKnn(id, dist_metric, dist_units, dist_units_str, dist_values, m_kNN, dist_var_1, dist_tm_1, dist_var_2, dist_tm_2); + if (m_kNN > 0 && m_kNN < m_num_obs) { GwtWeight* Wp = 0; Wp = SpatialIndAlgs::knn_build(m_XCOO, m_YCOO, m_kNN, dist_metric == WeightsMetaInfo::DM_arc, dist_units == WeightsMetaInfo::DU_mile); - if (!Wp->gwt) return; + + if (!Wp->gwt) + return; Wp->id_field = id; + WriteWeightFile(0, Wp->gwt, project->GetProjectTitle(), outputfile, id, wmi); if (Wp) delete Wp; done = true; + } else { wxString s; s << "Error: Maximum number of neighbors " << m_num_obs-1; @@ -653,8 +667,8 @@ void CreatingWeightDlg::UpdateThresholdValues() } if (v1 != wxEmptyString || v2 != wxEmptyString) { if (v1 != wxEmptyString) { - int x_sel = (project->IsTableOnlyProject() ? - m_X->GetSelection() : m_X->GetSelection()-2); + // minus 2 is for and selection options in Dropdown + int x_sel = (project->IsTableOnlyProject() ? m_X->GetSelection() : m_X->GetSelection()-2); int col_id = col_id_map[x_sel]; int tm = 0; dist_tm_1 = -1; @@ -666,8 +680,7 @@ void CreatingWeightDlg::UpdateThresholdValues() table_int->GetColData(col_id, tm, m_XCOO); } if (v2 != wxEmptyString) { - int y_sel = (project->IsTableOnlyProject() ? - m_Y->GetSelection() : m_Y->GetSelection()-2); + int y_sel = (project->IsTableOnlyProject() ? m_Y->GetSelection() : m_Y->GetSelection()-2); int col_id = col_id_map[y_sel]; int tm = 0; dist_tm_2 = -1; @@ -914,7 +927,8 @@ void CreatingWeightDlg::InitDlg() m_thres_val_valid = false; m_threshold_val = 0.01; dist_metric = WeightsMetaInfo::DM_euclidean; - dist_units = WeightsMetaInfo::DU_mile; + dist_units = WeightsMetaInfo::DU_unspecified; + dist_units_str = project->project_unit; dist_values = WeightsMetaInfo::DV_centroids; dist_var_1 = ""; dist_tm_1 = -1; @@ -1055,7 +1069,12 @@ void CreatingWeightDlg::SetDistChoiceEuclid(bool update_sel) m_arc_in_km = false; dist_metric = WeightsMetaInfo::DM_euclidean; - dist_units = WeightsMetaInfo::DU_mile; + + // note: the projection information can be used (after version 1.8.10) + // to read the UNIT meta data. + dist_units_str = project->project_unit; + + dist_units = WeightsMetaInfo::DU_unspecified; } void CreatingWeightDlg::SetDistChoiceArcMiles(bool update_sel) diff --git a/DialogTools/CreatingWeightDlg.h b/DialogTools/CreatingWeightDlg.h index 5cda41fb2..f1b021eba 100644 --- a/DialogTools/CreatingWeightDlg.h +++ b/DialogTools/CreatingWeightDlg.h @@ -154,7 +154,9 @@ public TableStateObserver, public WeightsManStateObserver WeightsMetaInfo::DistanceMetricEnum dist_metric; WeightsMetaInfo::DistanceUnitsEnum dist_units; WeightsMetaInfo::DistanceValuesEnum dist_values; - + + wxString dist_units_str; + wxString dist_var_1; long dist_tm_1; wxString dist_var_2; diff --git a/DialogTools/CsvFieldConfDlg.cpp b/DialogTools/CsvFieldConfDlg.cpp new file mode 100644 index 000000000..0c2db5f0d --- /dev/null +++ b/DialogTools/CsvFieldConfDlg.cpp @@ -0,0 +1,218 @@ +/** + * GeoDa TM, Copyright (C) 2011-2015 by Luc Anselin - all rights reserved + * + * This file is part of GeoDa. + * + * GeoDa 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 3 of the License, or + * (at your option) any later version. + * + * GeoDa 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, see . + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stdio.h" +#include +#include + + +#include "../logger.h" +#include "../GeneralWxUtils.h" +#include "../GdaException.h" +#include "../ShapeOperations/OGRDataAdapter.h" +#include "CsvFieldConfDlg.h" + +using namespace std; + + +CsvFieldConfDlg::CsvFieldConfDlg(wxWindow* parent, + wxString _filepath, + wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size ) +: wxDialog(parent, id, title, pos, size) +{ + + LOG_MSG("Entering CsvFieldConfDlg::CsvFieldConfDlg(..)"); + + filepath = _filepath; + wxTextFile tfile; + tfile.Open(filepath); + + // read the first line + wxString str = tfile.GetFirstLine(); + wxStringTokenizer tokenizer(str, ","); + while ( tokenizer.HasMoreTokens() ) + { + wxString token = tokenizer.GetNextToken(); + col_names.push_back(token); + } + + int n_rows = col_names.size(); + int n_cols = 2; // 1 Var name 2 type + + + wxPanel* panel = new wxPanel(this); + panel->SetBackgroundColour(*wxWHITE); + + wxStaticText* lbl = new wxStaticText(panel, wxID_ANY, "Please Specify Data Type for Each Data Column."); + + wxBoxSizer* lbl_box = new wxBoxSizer(wxVERTICAL); + lbl_box->AddSpacer(5); + lbl_box->Add(lbl, 1, wxALIGN_CENTER | wxEXPAND |wxALL, 10); + + fieldGrid = new wxGrid(this, wxID_ANY, wxDefaultPosition, wxSize(300,-1)); + fieldGrid->CreateGrid(n_rows, n_cols, wxGrid::wxGridSelectRows); + fieldGrid->SetColLabelValue(0, "Column Name"); + fieldGrid->SetColLabelValue(1, "Data Type"); + + wxBoxSizer* grid_box = new wxBoxSizer(wxVERTICAL); + grid_box->AddSpacer(5); + grid_box->Add(fieldGrid, 1, wxALIGN_CENTER | wxEXPAND |wxALL, 10); + + wxButton* btn_cancel= new wxButton(panel, wxID_ANY, "Cancel", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); + wxButton* btn_update= new wxButton(panel, wxID_ANY, "OK", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); + + wxBoxSizer* btn_box = new wxBoxSizer(wxHORIZONTAL); + btn_box->Add(btn_cancel, 1, wxALIGN_CENTER |wxEXPAND| wxALL, 10); + btn_box->Add(btn_update, 1, wxALIGN_CENTER | wxEXPAND | wxALL, 10); + + wxBoxSizer* box = new wxBoxSizer(wxVERTICAL); + box->Add(lbl_box, 0, wxALIGN_TOP | wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 10); + box->Add(grid_box, 0, wxALIGN_CENTER| wxEXPAND| wxRIGHT | wxTOP, 0); + box->Add(btn_box, 0, wxALIGN_CENTER| wxLEFT | wxRIGHT | wxTOP, 20); + + panel->SetSizerAndFit(box); + + wxBoxSizer* sizerAll = new wxBoxSizer(wxVERTICAL); + sizerAll->Add(panel, 1, wxEXPAND|wxALL); + SetSizer(sizerAll); + SetAutoLayout(true); + + SetParent(parent); + SetPosition(pos); + Centre(); + + + btn_update->Connect(wxEVT_BUTTON, wxCommandEventHandler(CsvFieldConfDlg::OnOkClick), NULL, this); + btn_cancel->Connect(wxEVT_BUTTON, wxCommandEventHandler(CsvFieldConfDlg::OnCancelClick), NULL, this); + + + vector types; + wxString csvt_path = filepath + "t"; + + if (wxFileExists(csvt_path)) { + // load data type from csvt file + wxTextFile csvt_file; + csvt_file.Open(csvt_path); + + // read the first line + wxString str = csvt_file.GetFirstLine(); + wxStringTokenizer tokenizer(str, ","); + + while ( tokenizer.HasMoreTokens() ) + { + wxString token = tokenizer.GetNextToken().Upper(); + if (token.Contains("INTEGER")) { + types.push_back("Integer"); + } else if (token.Contains("REAL")) { + types.push_back("Real"); + } else { + types.push_back("String"); + } + } + + } else { + // read second line, guess the type + str = tfile.GetNextLine(); + wxStringTokenizer tokenizer1(str, ","); + while ( tokenizer1.HasMoreTokens() ) + { + wxString token = tokenizer1.GetNextToken(); + + wxString val = token.Trim(true).Trim(false); + double d_val = 0; + + if (val.IsNumber()) { + types.push_back("Integer"); + } else if (val.ToDouble(&d_val)) { + types.push_back("Real"); + } else { + types.push_back("String"); + } + } + } + + for (int i=0; iSetCellEditor(i, COL_T, new wxGridCellChoiceEditor(4, strChoices, false)); + + fieldGrid->SetCellValue(i, 0, col_names[i]); + fieldGrid->SetCellValue(i, COL_T, types[i]); + } + + + LOG_MSG("Exiting CsvFieldConfDlg::CsvFieldConfDlg(..)"); +} + + +void CsvFieldConfDlg::OnOkClick( wxCommandEvent& event ) +{ + bool success = false; + + wxString csvt; + + int n_rows = col_names.size(); + for (int r=0; r < n_rows; r++ ) { + wxString type = fieldGrid->GetCellValue(r, 1); + csvt << type; + if (r < n_rows-1) + csvt << ","; + } + + // write back to a CSVT file + wxString csvt_path = filepath + "t"; + wxTextFile file(csvt_path); + file.Open(); + file.Clear(); + + file.AddLine( csvt ); + + file.Write(); + file.Close(); + EndDialog(wxID_OK); +} + +void CsvFieldConfDlg::OnCancelClick( wxCommandEvent& event ) +{ + EndDialog(wxID_CANCEL); +} + diff --git a/DialogTools/CsvFieldConfDlg.h b/DialogTools/CsvFieldConfDlg.h new file mode 100644 index 000000000..532dc1898 --- /dev/null +++ b/DialogTools/CsvFieldConfDlg.h @@ -0,0 +1,56 @@ +/** + * GeoDa TM, Copyright (C) 2011-2015 by Luc Anselin - all rights reserved + * + * This file is part of GeoDa. + * + * GeoDa 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 3 of the License, or + * (at your option) any later version. + * + * GeoDa 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, see . + */ +#ifndef __GEODA_CENTER_CSVFIELDCONF_DLG_H__ +#define __GEODA_CENTER_CSVFIELDCONF_DLG_H__ + + +#include +#include +#include +#include +#include +#include +#include +#include + + + + +class CsvFieldConfDlg: public wxDialog +{ +public: + CsvFieldConfDlg(wxWindow* parent, wxString filepath, + wxWindowID id = wxID_ANY, + const wxString& title = "GeoDa Csv Filed Configuration Dialog", + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxSize(480,420)); + + +private: + wxString filepath; + wxGrid* fieldGrid; + + std::vector col_names; + + void OnOkClick( wxCommandEvent& event ); + void OnCancelClick( wxCommandEvent& event ); + +}; + +#endif diff --git a/DialogTools/ExportDataDlg.cpp b/DialogTools/ExportDataDlg.cpp index 39e2c75df..954985dd0 100644 --- a/DialogTools/ExportDataDlg.cpp +++ b/DialogTools/ExportDataDlg.cpp @@ -32,6 +32,8 @@ #include #include +#include "ogr_srs_api.h" + #include "../Project.h" #include "../DataViewer/TableInterface.h" #include "../DataViewer/DbfTable.h" @@ -479,7 +481,9 @@ ExportDataDlg::CreateOGRLayer(wxString& ds_name, // for shp/dbf reading, we need to convert Main data to GdaShape first // this will spend some time, but keep the rest of code clean. // Note: potential speed/memory performance issue + vector selected_rows; + if ( project_p != NULL && geometries.empty() && !is_save_centroids ) { shape_type = Shapefile::NULL_SHAPE; int num_obs = project_p->main_data.records.size(); @@ -507,7 +511,7 @@ ExportDataDlg::CreateOGRLayer(wxString& ds_name, else if (project_p->main_data.header.shape_type == Shapefile::POLYGON) { PolygonContents* pc; for (int i=0; imain_data.records[i].contents_p; + pc = (PolygonContents*)project_p->main_data.records[i].contents_p; geometries.push_back(new GdaPolygon(pc)); } shape_type = Shapefile::POLYGON; @@ -524,10 +528,39 @@ ExportDataDlg::CreateOGRLayer(wxString& ds_name, selected_rows.push_back(i); } + /* + // explictly set SRS with EPSG information + wxString cstype = "PROJCS"; + if (poOutputSRS->IsGeographic() == 1) { + cstype = "GEOGCS"; + } + + wxString authname= poOutputSRS->GetAuthorityName(cstype.mb_str()); + wxString authCode = poOutputSRS->GetAuthorityCode(cstype.mb_str()); + + if (authname.IsEmpty()) { + int epsg = poOutputSRS->GetEPSGGeogCS(); + poOutputSRS->SetAuthority(cstype.mb_str(), "EPSG", epsg); + } + */ + // convert to OGR geometries vector ogr_geometries; OGRwkbGeometryType geom_type = OGRDataAdapter::GetInstance().MakeOGRGeometries(geometries, shape_type, ogr_geometries, selected_rows); + // NOTE: for GeoJSON, transform to WGS84 automatically + if (spatial_ref && (ds_name.EndsWith(".json") || ds_name.EndsWith(".geojson"))) { + int epsg = spatial_ref->GetEPSGGeogCS(); + if (epsg != 4326) { + OGRSpatialReference wgs84_ref; + wgs84_ref.importFromEPSG(4326); + OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation( spatial_ref, &wgs84_ref ); + for (size_t i=0; i < ogr_geometries.size(); i++) { + ogr_geometries[i]->transform(poCT); + } + } + } + // take care of empty layer name if (layer_name.empty()) { layer_name = table_p ? table_p->GetTableName() : "NO_NAME"; diff --git a/Explore/CorrelParamsDlg.cpp b/Explore/CorrelParamsDlg.cpp index 8799c5b05..8b004239e 100644 --- a/Explore/CorrelParamsDlg.cpp +++ b/Explore/CorrelParamsDlg.cpp @@ -138,7 +138,7 @@ help_btn(0), apply_btn(0) rand_samp_rad = new wxRadioButton(panel, XRCID("ID_RAND_SAMP_RAD"), "Random Sample", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER_VERTICAL); rand_samp_rad->SetValue(correl_params.method != CorrelParams::ALL_PAIRS); Connect(XRCID("ID_RAND_SAMP_RAD"), wxEVT_RADIOBUTTON, wxCommandEventHandler(CorrelParamsFrame::OnRandSampRadioSelected)); - max_iter_txt = new wxStaticText(panel, XRCID("ID_MAX_ITER_TXT"), "Iterations:"); + max_iter_txt = new wxStaticText(panel, XRCID("ID_MAX_ITER_TXT"), "Sample Size:"); { wxString vs; vs << correl_params.max_iterations; @@ -682,13 +682,13 @@ wxString CorrelParamsFrame::GetHelpPageHtml() const s << "Random Sample for data sets with more than 10,000 observations."; s << "The Estimated Pairs gives the number of pairs of centers that will "; s << "be involved in the computation. This is comparable to the "; - s << "Iterations parameter in the Random Sample method."; + s << "sample size parameter in the Random Sample method."; s << "

"; s << "

Random Sample

"; s << "

"; s << "Pairs of observations are chosen at random up to the number "; - s << "of iterations specified. Random Sampling converges very quickly "; + s << "of sample size specified. Random Sampling converges very quickly "; s << "to similar values as in All Pairs, but had the advantage of "; s << "a constant running time. This is the only way to handle very "; s << "large data sets over the entire distance range."; diff --git a/Explore/CorrelogramAlgs.cpp b/Explore/CorrelogramAlgs.cpp index 57d188ce2..3db1f9134 100644 --- a/Explore/CorrelogramAlgs.cpp +++ b/Explore/CorrelogramAlgs.cpp @@ -181,8 +181,7 @@ bool CorrelogramAlgs::MakeCorrAllPairs(const std::vector& pts, size_t pc = 0; for (size_t i=0; i& pts, max_d = d; } Zdist[pc] = d; - if (calc_prods) Zprod[pc] = (Z[i]-mean)*(Z[j]-mean)/var; + if (calc_prods) + Zprod[pc] = (Z[i]-mean)*(Z[j]-mean)/var; ++pc; } } @@ -214,6 +214,11 @@ bool CorrelogramAlgs::MakeCorrAllPairs(const std::vector& pts, size_t ta_cnt = 0; for (size_t i=0, sz=Zdist.size(); i= num_bins) { b=num_bins-1; diff --git a/Explore/LineChartCanvas.cpp b/Explore/LineChartCanvas.cpp index 13ba44f2c..dbb659946 100644 --- a/Explore/LineChartCanvas.cpp +++ b/Explore/LineChartCanvas.cpp @@ -260,7 +260,7 @@ void LineChartCanvas::UpdateStatusBar() if (c.pointWithin(sel1)) { if (!s.IsEmpty()) s << ", "; if (!time_inv) s << table_int->GetTimeString(t) << " "; - s << "mean=" << lcs.Y_avg[t]; + s << "all obs mean=" << lcs.Y_avg[t]; } } for (size_t t=0, tms=sel_circs.size(); tsetPen(*wxBLACK_PEN); + p->setPen(wxPen(*wxBLACK, 1, wxSHORT_DASH)); background_shps.push_back(p); for (size_t t=0; t #include #include + +#include "ogr_srs_api.h" #include "logger.h" #include "FramesManager.h" #include "SaveButtonManager.h" @@ -462,6 +464,7 @@ void Project::SaveDataSourceAs(const wxString& new_ds_name, bool is_update) { LOG_MSG("Entering Project::SaveDataSourceAs"); LOG_MSG("New Datasource Name:" + new_ds_name); + vector geometries; try { // SaveAs only to same datasource @@ -494,12 +497,21 @@ void Project::SaveDataSourceAs(const wxString& new_ds_name, bool is_update) for (size_t i=0; iGetNumberRows(); i++) { selected_rows.push_back(i); } - + + // Create in-memory OGR geometries vector ogr_geometries; - OGRwkbGeometryType geom_type = - OGRDataAdapter::GetInstance().MakeOGRGeometries(geometries, shape_type, - ogr_geometries, - selected_rows); + OGRwkbGeometryType geom_type = OGRDataAdapter::GetInstance().MakeOGRGeometries(geometries, shape_type, ogr_geometries, selected_rows); + + // NOTE: for GeoJSON, automatically transform to WGS84 + if (spatial_ref && ds_type == GdaConst::ds_geo_json) { + OGRSpatialReference wgs84_ref; + wgs84_ref.importFromEPSG(4326); + OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation( spatial_ref, &wgs84_ref ); + for (size_t i=0; i < ogr_geometries.size(); i++) { + ogr_geometries[i]->transform(poCT); + } + } + // Start saving int prog_n_max = 0; @@ -1320,6 +1332,9 @@ bool Project::CommonProjectInit() // convert projection to WGS84 by default if there is projection sourceSR = GetSpatialReference(); + if (sourceSR ) { + project_unit = sourceSR->GetAttrValue("UNIT"); + } // Initialize various managers frames_manager = new FramesManager; diff --git a/Project.h b/Project.h index 4fbb96ea7..8768d7356 100644 --- a/Project.h +++ b/Project.h @@ -197,6 +197,7 @@ class Project { /// main_data is the only public remaining attribute in Project Shapefile::Main main_data; OGRSpatialReference* sourceSR; + wxString project_unit; // ".gda" project file data wxString layer_title; // optional project::layers::layer::title field diff --git a/ShapeOperations/GalWeight.cpp b/ShapeOperations/GalWeight.cpp index 1bdfdd2aa..76e0dc15d 100644 --- a/ShapeOperations/GalWeight.cpp +++ b/ShapeOperations/GalWeight.cpp @@ -246,6 +246,12 @@ bool GalWeight::SaveDIDWeights(Project* project, int num_obs, std::vector& id_vec) @@ -355,7 +367,14 @@ bool Gda::SaveGal(const GalElement* g, ofstream out; out.open(GET_ENCODED_FILENAME(final_fon)); if (!(out.is_open() && out.good())) return false; - + + wxString layer_name(_layer_name); + // if layer_name contains an empty space, the layer name should be + // braced with quotes "layer name" + if (layer_name.Contains(" ")) { + layer_name = "\"" + layer_name + "\""; + } + size_t num_obs = (int) id_vec.size(); out << "0 " << num_obs << " " << layer_name; out << " " << id_var_name << endl; @@ -373,7 +392,7 @@ bool Gda::SaveGal(const GalElement* g, } bool Gda::SaveGal(const GalElement* g, - const wxString& layer_name, + const wxString& _layer_name, const wxString& ofname, const wxString& id_var_name, const std::vector& id_vec) @@ -388,7 +407,14 @@ bool Gda::SaveGal(const GalElement* g, ofstream out; out.open(GET_ENCODED_FILENAME(final_fon)); if (!(out.is_open() && out.good())) return false; - + + wxString layer_name(_layer_name); + + // if layer_name contains an empty space, the layer name should be + // braced with quotes "layer name" + if (layer_name.Contains(" ")) { + layer_name = "\"" + layer_name + "\""; + } size_t num_obs = (int) id_vec.size(); out << "0 " << num_obs << " " << layer_name; out << " " << id_var_name << endl; @@ -407,7 +433,7 @@ bool Gda::SaveGal(const GalElement* g, bool Gda::SaveSpaceTimeGal(const GalElement* g, const std::vector& time_ids, - const wxString& layer_name, + const wxString& _layer_name, const wxString& ofname, const wxString& id_var_name, const std::vector& id_vec) @@ -426,6 +452,13 @@ bool Gda::SaveSpaceTimeGal(const GalElement* g, size_t num_obs = id_vec.size(); size_t num_t = time_ids.size(); size_t n = num_obs * num_t; + + wxString layer_name(_layer_name); + // if layer_name contains an empty space, the layer name should be + // braced with quotes "layer name" + if (layer_name.Contains(" ")) { + layer_name = "\"" + layer_name + "\""; + } out << "0 " << n << " " << layer_name; out << " " << id_var_name << endl; diff --git a/ShapeOperations/GwtWeight.cpp b/ShapeOperations/GwtWeight.cpp index 6e54594eb..2239bd624 100644 --- a/ShapeOperations/GwtWeight.cpp +++ b/ShapeOperations/GwtWeight.cpp @@ -96,6 +96,12 @@ bool GwtWeight::SaveDIDWeights(Project* project, int num_obs, std::vector& id_vec) { using namespace std; - if (g == NULL || layer_name.IsEmpty() || ofname.IsEmpty() + if (g == NULL || _layer_name.IsEmpty() || ofname.IsEmpty() || id_vec.size() == 0) return false; wxFileName wx_fn(ofname); @@ -200,7 +212,14 @@ bool Gda::SaveGwt(const GwtElement* g, ofstream out; out.open(GET_ENCODED_FILENAME(final_ofn)); if (!(out.is_open() && out.good())) return false; - + + wxString layer_name(_layer_name); + // if layer_name contains an empty space, the layer name should be + // braced with quotes "layer name" + if (layer_name.Contains(" ")) { + layer_name = "\"" + layer_name + "\""; + } + size_t num_obs = (int) id_vec.size(); out << "0 " << num_obs << " " << layer_name; out << " " << id_var_name << endl; @@ -218,13 +237,13 @@ bool Gda::SaveGwt(const GwtElement* g, bool Gda::SaveGwt(const GwtElement* g, - const wxString& layer_name, + const wxString& _layer_name, const wxString& ofname, const wxString& id_var_name, const std::vector& id_vec) { using namespace std; - if (g == NULL || layer_name.IsEmpty() || ofname.IsEmpty() + if (g == NULL || _layer_name.IsEmpty() || ofname.IsEmpty() || id_vec.size() == 0) return false; wxFileName wx_fn(ofname); @@ -234,6 +253,13 @@ bool Gda::SaveGwt(const GwtElement* g, out.open(GET_ENCODED_FILENAME(final_ofn)); if (!(out.is_open() && out.good())) return false; + wxString layer_name(_layer_name); + // if layer_name contains an empty space, the layer name should be + // braced with quotes "layer name" + if (layer_name.Contains(" ")) { + layer_name = "\"" + layer_name + "\""; + } + size_t num_obs = (int) id_vec.size(); out << "0 " << num_obs << " " << layer_name; out << " " << id_var_name << endl; diff --git a/ShapeOperations/OGRDataAdapter.cpp b/ShapeOperations/OGRDataAdapter.cpp index 1ecf79f72..8863e4727 100644 --- a/ShapeOperations/OGRDataAdapter.cpp +++ b/ShapeOperations/OGRDataAdapter.cpp @@ -214,66 +214,60 @@ OGRDataAdapter::MakeOGRGeometries(vector& geometries, ogr_geometries.push_back(pt); } else if ( shape_type == Shapefile::POLYGON ) { + GdaPolygon* poly = (GdaPolygon*) geometries[id]; if (poly->isNull()) { - OGRPolygon* polygon = - (OGRPolygon*)OGRGeometryFactory::createGeometry(wkbPolygon); - //OGRLinearRing* ring = - //(OGRLinearRing*)OGRGeometryFactory::createGeometry(wkbLinearRing); + OGRPolygon* polygon = (OGRPolygon*)OGRGeometryFactory::createGeometry(wkbPolygon); + //OGRLinearRing* ring =(OGRLinearRing*)OGRGeometryFactory::createGeometry(wkbLinearRing); //ring->closeRings(); //polygon->addRingDirectly(ring); ogr_geometries.push_back(polygon); + } else { int numParts = poly->n_count; int numPoints = poly->n; double x, y; if ( numParts == 1 ) { - eGType = wkbPolygon; - OGRPolygon* polygon = - (OGRPolygon*)OGRGeometryFactory::createGeometry(wkbPolygon); - OGRLinearRing* ring = - (OGRLinearRing*)OGRGeometryFactory::createGeometry(wkbLinearRing); - for ( int j = 0; j < numPoints; j++ ) { - if ( poly->points_o != NULL ) { - // for created centroids or other geometries, the actual - // points are stored in points_o wxRealPoint[]. - // Note: GdaPolygon::count[] constantly has size = 1 in - // current design, see GdaPolygon class - x = poly->points_o[j].x; - y = poly->points_o[j].y; - } else { - x = poly->pc->points[j].x; - y = poly->pc->points[j].y; - } - ring->addPoint(x,y); - } - ring->closeRings(); - polygon->addRingDirectly(ring); - ogr_geometries.push_back(polygon); - - } else if ( numParts > 1 ) { - eGType = wkbMultiPolygon; - OGRMultiPolygon* multi_polygon = - (OGRMultiPolygon*)OGRGeometryFactory::createGeometry(wkbMultiPolygon); - for ( int num_part = 0; num_part < numParts; num_part++ ) { - OGRPolygon* polygon = - (OGRPolygon*)OGRGeometryFactory::createGeometry(wkbPolygon); - OGRLinearRing* ring = - (OGRLinearRing*)OGRGeometryFactory::createGeometry(wkbLinearRing); - vector startIndexes = poly->pc->parts; - startIndexes.push_back(numPoints); - for ( size_t j = startIndexes[num_part]; - j < startIndexes[num_part+1]; j++ ) { - - x = poly->pc->points[j].x; - y = poly->pc->points[j].y; + eGType = wkbPolygon; + OGRPolygon* polygon = (OGRPolygon*)OGRGeometryFactory::createGeometry(wkbPolygon); + OGRLinearRing* ring = (OGRLinearRing*)OGRGeometryFactory::createGeometry(wkbLinearRing); + for ( int j = 0; j < numPoints; j++ ) { + if ( poly->points_o != NULL ) { + // for created centroids or other geometries, the actual + // points are stored in points_o wxRealPoint[]. + // Note: GdaPolygon::count[] constantly has size = 1 in + // current design, see GdaPolygon class + x = poly->points_o[j].x; + y = poly->points_o[j].y; + } else { + x = poly->pc->points[j].x; + y = poly->pc->points[j].y; + } ring->addPoint(x,y); } ring->closeRings(); polygon->addRingDirectly(ring); - multi_polygon->addGeometryDirectly(polygon); - } - ogr_geometries.push_back(multi_polygon); + ogr_geometries.push_back(polygon); + + } else if ( numParts > 1 ) { + eGType = wkbMultiPolygon; + OGRMultiPolygon* multi_polygon = (OGRMultiPolygon*)OGRGeometryFactory::createGeometry(wkbMultiPolygon); + for ( int num_part = 0; num_part < numParts; num_part++ ) { + OGRPolygon* polygon = (OGRPolygon*)OGRGeometryFactory::createGeometry(wkbPolygon); + OGRLinearRing* ring = (OGRLinearRing*)OGRGeometryFactory::createGeometry(wkbLinearRing); + vector startIndexes = poly->pc->parts; + startIndexes.push_back(numPoints); + for ( size_t j = startIndexes[num_part]; j < startIndexes[num_part+1]; j++ ) { + + x = poly->pc->points[j].x; + y = poly->pc->points[j].y; + ring->addPoint(x,y); + } + ring->closeRings(); + polygon->addRingDirectly(ring); + multi_polygon->addGeometryDirectly(polygon); + } + ogr_geometries.push_back(multi_polygon); } } } diff --git a/ShapeOperations/OGRDatasourceProxy.cpp b/ShapeOperations/OGRDatasourceProxy.cpp index 52fea4e4a..023368354 100644 --- a/ShapeOperations/OGRDatasourceProxy.cpp +++ b/ShapeOperations/OGRDatasourceProxy.cpp @@ -338,6 +338,7 @@ OGRDatasourceProxy::CreateLayer(string layer_name, } OGRSpatialReference *poOutputSRS = spatial_ref; + // PRECISION is for database e.g. MSSQL // LAUNDER is for database: rename desired field name diff --git a/ShapeOperations/PolysToContigWeights.cpp b/ShapeOperations/PolysToContigWeights.cpp index f5aa795a9..c9b71236a 100644 --- a/ShapeOperations/PolysToContigWeights.cpp +++ b/ShapeOperations/PolysToContigWeights.cpp @@ -235,7 +235,7 @@ class PolygonPartition void MakeSmallPartition(const int mX, const double Start, const double Stop); void MakeNeighbors(); - bool edge(PolygonPartition &p, const int host, const int guest); + bool edge(PolygonPartition &p, const int host, const int guest, double precision_threshold); int sweep(PolygonPartition & guest, bool is_queen, double precision_threshold=0.0); }; @@ -653,7 +653,7 @@ wxString getPointStr(const BasePoint& point) /** Method for detecting if an edge is shared between a host and guest polygon. */ bool PolygonPartition::edge(PolygonPartition &p, const int host, - const int guest) + const int guest, double precision_threshold) { using namespace Shapefile; @@ -662,17 +662,17 @@ bool PolygonPartition::edge(PolygonPartition &p, const int host, //BasePoint hostPoint = Points[ succ(host) ]; Point* hostPoint = this->GetPoint(succ(host)); - if (hostPoint->equals(guestPrev)) return true; + if (hostPoint->equals(guestPrev, precision_threshold)) return true; //BasePoint guestSucc= p.Points[ p.succ(guest) ]; Point* guestSucc= p.GetPoint(p.succ(guest)); - if (hostPoint->equals( guestSucc) ) return true; + if (hostPoint->equals( guestSucc, precision_threshold) ) return true; hostPoint= this->GetPoint( prev(host) ); - if (hostPoint->equals( guestSucc )) return true; + if (hostPoint->equals( guestSucc, precision_threshold )) return true; - if (hostPoint->equals( guestPrev )) return true; + if (hostPoint->equals( guestPrev, precision_threshold )) return true; return false; } @@ -754,8 +754,8 @@ int PolygonPartition::sweep(PolygonPartition & guest, bool is_queen, { if (pt->equals( GetPoint(host), precision_threshold) ) { - if (is_queen || edge(guest, host, dot)) { - pY.cleanup(pX, cell); + if (is_queen || edge(guest, host, dot, precision_threshold)) { + pY.cleanup(pX, cell); return 1; } } diff --git a/ShapeOperations/WeightUtils.cpp b/ShapeOperations/WeightUtils.cpp index 6dd8ff212..59c40782e 100644 --- a/ShapeOperations/WeightUtils.cpp +++ b/ShapeOperations/WeightUtils.cpp @@ -56,7 +56,34 @@ wxString WeightUtils::ReadIdField(const wxString& fname) wxInt64 num2 = 0; wxInt64 num_obs = 0; string dbf_name, t_key_field; - ss >> num1 >> num2 >> dbf_name >> t_key_field; + + + string line; + std::getline(ss, line); + wxString header(line); + + // detect if header contains string with empty space, which should be quoted + if (header.Contains("\"")) { + int start_quote = header.find("\""); + int end_quote = header.find("\"", start_quote + 1); + dbf_name = header.SubString(start_quote + 1, end_quote - 1); + t_key_field = header.SubString(end_quote + 1 + 1 /*1 for blank space */, + header.length()-1); + wxString nums = header.SubString(0, start_quote-1); + int break_pos = nums.find(" "); + wxString num1_str = nums.SubString(0, break_pos-1); + wxString num2_str = nums.SubString(break_pos+1, nums.length()-1); + num1_str.ToLongLong(&num1); + num2_str.ToLongLong(&num2); + + } else { + + ss.clear(); + ss.seekg(0, ios::beg); // reset to beginning + ss >> num1 >> num2 >> dbf_name >> t_key_field; + } + + wxString key_field(t_key_field); if (num2 == 0) { key_field = ""; @@ -99,7 +126,33 @@ GalElement* WeightUtils::ReadGal(const wxString& fname, wxInt64 num2 = 0; wxInt64 num_obs = 0; string dbf_name, t_key_field; - ss >> num1 >> num2 >> dbf_name >> t_key_field; + + string line; + std::getline(ss, line); + wxString header(line); + + // detect if header contains string with empty space, which should be quoted + if (header.Contains("\"")) { + int start_quote = header.find("\""); + int end_quote = header.find("\"", start_quote + 1); + dbf_name = header.SubString(start_quote + 1, end_quote - 1); + t_key_field = header.SubString(end_quote + 1 + 1 /*1 for blank space */, + header.length()-1); + wxString nums = header.SubString(0, start_quote-1); + int break_pos = nums.find(" "); + wxString num1_str = nums.SubString(0, break_pos-1); + wxString num2_str = nums.SubString(break_pos+1, nums.length()-1); + num1_str.ToLongLong(&num1); + num2_str.ToLongLong(&num2); + + } else { + + ss.clear(); + ss.seekg(0, ios::beg); // reset to beginning + ss >> num1 >> num2 >> dbf_name >> t_key_field; + } + + wxString key_field(t_key_field); if (num2 == 0) { use_rec_order = true; @@ -346,7 +399,32 @@ GalElement* WeightUtils::ReadGwtAsGal(const wxString& fname, wxInt64 num2 = 0; wxInt64 num_obs = 0; string dbf_name, t_key_field; - ss >> num1 >> num2 >> dbf_name >> t_key_field; + + string line; + std::getline(ss, line); + wxString header(line); + + // detect if header contains string with empty space, which should be quoted + if (header.Contains("\"")) { + int start_quote = header.find("\""); + int end_quote = header.find("\"", start_quote + 1); + dbf_name = header.SubString(start_quote + 1, end_quote - 1); + t_key_field = header.SubString(end_quote + 1 + 1 /*1 for blank space */, + header.length()-1); + wxString nums = header.SubString(0, start_quote-1); + int break_pos = nums.find(" "); + wxString num1_str = nums.SubString(0, break_pos-1); + wxString num2_str = nums.SubString(break_pos+1, nums.length()-1); + num1_str.ToLongLong(&num1); + num2_str.ToLongLong(&num2); + + } else { + + ss.clear(); + ss.seekg(0, ios::beg); // reset to beginning + ss >> num1 >> num2 >> dbf_name >> t_key_field; + } + wxString key_field(t_key_field); if (num2 == 0) { use_rec_order = true; @@ -576,7 +654,32 @@ GwtElement* WeightUtils::ReadGwt(const wxString& fname, wxInt64 num2 = 0; wxInt64 num_obs = 0; string dbf_name, t_key_field; - ss >> num1 >> num2 >> dbf_name >> t_key_field; + + string line; + std::getline(ss, line); + wxString header(line); + + // detect if header contains string with empty space, which should be quoted + if (header.Contains("\"")) { + int start_quote = header.find("\""); + int end_quote = header.find("\"", start_quote + 1); + dbf_name = header.SubString(start_quote + 1, end_quote - 1); + t_key_field = header.SubString(end_quote + 1 + 1 /*1 for blank space */, + header.length()-1); + wxString nums = header.SubString(0, start_quote-1); + int break_pos = nums.find(" "); + wxString num1_str = nums.SubString(0, break_pos-1); + wxString num2_str = nums.SubString(break_pos+1, nums.length()-1); + num1_str.ToLongLong(&num1); + num2_str.ToLongLong(&num2); + + } else { + + ss.clear(); + ss.seekg(0, ios::beg); // reset to beginning + ss >> num1 >> num2 >> dbf_name >> t_key_field; + } + wxString key_field(t_key_field); if (num2 == 0) { use_rec_order = true; diff --git a/ShapeOperations/WeightsManPtree.cpp b/ShapeOperations/WeightsManPtree.cpp index 8eaf0f330..efecdc991 100644 --- a/ShapeOperations/WeightsManPtree.cpp +++ b/ShapeOperations/WeightsManPtree.cpp @@ -174,12 +174,9 @@ void WeightsManPtree::ReadPtree(const boost::property_tree::ptree& pt, e.wmi.dist_units = WeightsMetaInfo::DU_km; } else if (s == "mile") { e.wmi.dist_units = WeightsMetaInfo::DU_mile; - } else if (s == "unspecified" || s.IsEmpty()) { + } else { e.wmi.dist_units = WeightsMetaInfo::DU_unspecified; - } else { - wxString msg("unrecognized value: "); - msg << s << " for key: " << key; - throw GdaException(msg.mb_str()); + e.wmi.dist_units_str = s; } } else if (key == "dist_values") { wxString s = v.second.data(); @@ -269,7 +266,7 @@ void WeightsManPtree::WritePtree(boost::property_tree::ptree& pt, WeightsMetaInfo::WT_rook ? "rook" : "queen")); sssub.put("order", e.wmi.order); - if (e.wmi.inc_lower_orders) { + if (e.wmi.inc_lower_orders == true) { sssub.put("inc_lower_orders", "true"); } else { sssub.put("inc_lower_orders", "false"); @@ -289,7 +286,9 @@ void WeightsManPtree::WritePtree(boost::property_tree::ptree& pt, sssub.put("dist_units", "km"); } else if (e.wmi.dist_units == WeightsMetaInfo::DU_mile) { sssub.put("dist_units", "mile"); - } + } else if (e.wmi.dist_units == WeightsMetaInfo::DU_unspecified) { + sssub.put("dist_units", e.wmi.dist_units_str); + } if (e.wmi.dist_values == WeightsMetaInfo::DV_centroids) { sssub.put("dist_values", "centroids"); } else if (e.wmi.dist_values == diff --git a/SpatialIndAlgs.cpp b/SpatialIndAlgs.cpp index 2f0fbb575..3aa58e9d3 100644 --- a/SpatialIndAlgs.cpp +++ b/SpatialIndAlgs.cpp @@ -1067,7 +1067,7 @@ GwtWeight* SpatialIndAlgs::knn_build(const rtree_pt_lonlat_t& rtree, int nn) } bool SpatialIndAlgs::write_gwt(const GwtWeight* W, - const wxString& layer_name, + const wxString& _layer_name, const wxString& ofname, const wxString& vname, const std::vector& id_vec) @@ -1077,7 +1077,7 @@ bool SpatialIndAlgs::write_gwt(const GwtWeight* W, if (!W) return false; const GwtElement* g = W->gwt; size_t num_obs = W->num_obs; - if (!g || layer_name.IsEmpty() || ofname.IsEmpty() + if (!g || _layer_name.IsEmpty() || ofname.IsEmpty() || id_vec.size() == 0 || num_obs != id_vec.size()) return false; wxFileName gwtfn(ofname); @@ -1087,6 +1087,13 @@ bool SpatialIndAlgs::write_gwt(const GwtWeight* W, out.open(GET_ENCODED_FILENAME(gwt_ofn)); if (!(out.is_open() && out.good())) return false; + wxString layer_name(_layer_name); + // if layer_name contains an empty space, the layer name should be + // braced with quotes "layer name" + if (layer_name.Contains(" ")) { + layer_name = "\"" + layer_name + "\""; + } + out << "0" << " " << num_obs << " " << layer_name; out << " " << vname.mb_str() << endl; diff --git a/VarCalc/WeightsMetaInfo.cpp b/VarCalc/WeightsMetaInfo.cpp index daef9b71e..cfc23ec90 100644 --- a/VarCalc/WeightsMetaInfo.cpp +++ b/VarCalc/WeightsMetaInfo.cpp @@ -30,7 +30,7 @@ void WeightsMetaInfo::SetToDefaults() filename = ""; sym_type = SYM_unknown; order = 1; - inc_lower_orders = true; + inc_lower_orders = false; dist_metric = DM_unspecified; dist_units = DU_unspecified; dist_values = DV_unspecified; @@ -57,7 +57,8 @@ void WeightsMetaInfo::SetToRook(const wxString& idv, sym_type = SYM_symmetric; order = order_; inc_lower_orders = inc_lower_orders_; - if (order < 2) inc_lower_orders = true; + //if (order < 2) + // inc_lower_orders = true; } void WeightsMetaInfo::SetToQueen(const wxString& idv, @@ -69,12 +70,14 @@ void WeightsMetaInfo::SetToQueen(const wxString& idv, sym_type = SYM_symmetric; order = order_; inc_lower_orders = inc_lower_orders_; - if (order < 2) inc_lower_orders = true; + //if (order < 2) + // inc_lower_orders = true; } void WeightsMetaInfo::SetToThres(const wxString& idv, DistanceMetricEnum dist_metric_, DistanceUnitsEnum dist_units_, + wxString dist_units_str_, DistanceValuesEnum dist_values_, double threshold_val_, wxString dist_var1_, long dist_tm1_, @@ -86,6 +89,7 @@ void WeightsMetaInfo::SetToThres(const wxString& idv, sym_type = SYM_symmetric; dist_metric = dist_metric_; dist_units = dist_units_; + dist_units_str = dist_units_str_; dist_values = dist_values_; threshold_val = threshold_val_; if (!dist_var1_.IsEmpty()) { @@ -101,6 +105,7 @@ void WeightsMetaInfo::SetToThres(const wxString& idv, void WeightsMetaInfo::SetToKnn(const wxString& idv, DistanceMetricEnum dist_metric_, DistanceUnitsEnum dist_units_, + wxString dist_units_str_, DistanceValuesEnum dist_values_, long k, wxString dist_var1_, long dist_tm1_, @@ -112,6 +117,7 @@ void WeightsMetaInfo::SetToKnn(const wxString& idv, sym_type = SYM_asymmetric; dist_metric = dist_metric_; dist_units = dist_units_; + dist_units_str = dist_units_str_; dist_values = dist_values_; num_neighbors = k; if (!dist_var1_.IsEmpty()) { @@ -224,8 +230,14 @@ wxString WeightsMetaInfo::DistUnitsToStr() const return "km"; } else if (dist_units == DU_mile) { return "mile"; - } - return "unspecified"; + } else { + // dist_units == DU_unspecified + if (!dist_units_str.IsEmpty()) { + return dist_units_str; + } else { + return "unspecified"; + } + } } diff --git a/VarCalc/WeightsMetaInfo.h b/VarCalc/WeightsMetaInfo.h index 0fea36768..53653d57c 100644 --- a/VarCalc/WeightsMetaInfo.h +++ b/VarCalc/WeightsMetaInfo.h @@ -38,7 +38,7 @@ struct WeightsMetaInfo DM_unspecified, DM_euclidean, DM_arc }; enum DistanceUnitsEnum { - DU_unspecified, DU_km, DU_mile + DU_unspecified, DU_km, DU_mile }; WeightsMetaInfo(); @@ -51,6 +51,7 @@ struct WeightsMetaInfo void SetToThres(const wxString& id_var, DistanceMetricEnum dist_metric, DistanceUnitsEnum dist_units, + wxString dist_units_str, DistanceValuesEnum dist_values, double threshold_val, wxString dist_var_1 = "", long dist_tm_1 = -1, @@ -58,6 +59,7 @@ struct WeightsMetaInfo void SetToKnn(const wxString& id_var, DistanceMetricEnum dist_metric, DistanceUnitsEnum dist_units, + wxString dist_units_str, DistanceValuesEnum dist_values, long k, wxString dist_var_1 = "", long dist_tm_1 = -1, @@ -77,6 +79,8 @@ struct WeightsMetaInfo DistanceMetricEnum dist_metric; DistanceUnitsEnum dist_units; DistanceValuesEnum dist_values; + + wxString dist_units_str; wxString dist_var1; // x-coord wxString dist_var2; // y-coord diff --git a/version.h b/version.h index eee789ed4..df50b044b 100644 --- a/version.h +++ b/version.h @@ -1,11 +1,11 @@ namespace Gda { const int version_major = 1; const int version_minor = 8; - const int version_build = 10; + const int version_build = 12; const int version_subbuild = 0; const int version_year = 2016; - const int version_month = 7; - const int version_day = 14; + const int version_month = 9; + const int version_day = 1; const int version_night = 0; const int version_type = 2; // 0: alpha, 1: beta, 2: release }