Skip to content

Commit

Permalink
use arrow to exchange data in memory
Browse files Browse the repository at this point in the history
  • Loading branch information
lixun910 committed Sep 27, 2023
1 parent eebca76 commit 23d65a8
Show file tree
Hide file tree
Showing 15 changed files with 4,037 additions and 672 deletions.
606 changes: 0 additions & 606 deletions BuildTools/CommonDistFiles/bundle.js

This file was deleted.

633 changes: 633 additions & 0 deletions BuildTools/CommonDistFiles/web_plugins/bundle.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
}
.geoda-kepler-map {
padding: 0!important;
}</style></head><body><div id="root" data-csv="data.csv"></div><script src="bundle.js"></script></body></html>
}</style></head><body><div id="root" data-arrow="data.arrow"></div><script src="bundle.js"></script></body></html>
16 changes: 11 additions & 5 deletions BuildTools/macosx/GeoDa.m1.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
A14735BA21A65F1800CA69B2 /* perf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A14735B121A65F1700CA69B2 /* perf.cpp */; };
A14735BB21A65F1800CA69B2 /* bd_pr_search.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A14735B221A65F1700CA69B2 /* bd_pr_search.cpp */; };
A14735BC21A65F1800CA69B2 /* brute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A14735B321A65F1700CA69B2 /* brute.cpp */; };
A14744D02AC241D50054D653 /* GeomUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A14744CE2AC241660054D653 /* GeomUtils.cpp */; };
A14C496F1D76174000D9831C /* CsvFieldConfDlg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A14C496D1D76174000D9831C /* CsvFieldConfDlg.cpp */; };
A1648F2526AA000E00D0E191 /* joincount_ratio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1648F2326AA000E00D0E191 /* joincount_ratio.cpp */; };
A16BA470183D626200D3B7DA /* DatasourceDlg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A16BA46E183D626200D3B7DA /* DatasourceDlg.cpp */; };
Expand Down Expand Up @@ -359,6 +360,8 @@
A14735B221A65F1700CA69B2 /* bd_pr_search.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bd_pr_search.cpp; sourceTree = "<group>"; };
A14735B321A65F1700CA69B2 /* brute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = brute.cpp; sourceTree = "<group>"; };
A14735B421A65F1700CA69B2 /* bd_tree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bd_tree.h; sourceTree = "<group>"; };
A14744CE2AC241660054D653 /* GeomUtils.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GeomUtils.cpp; sourceTree = "<group>"; };
A14744CF2AC241660054D653 /* GeomUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeomUtils.h; sourceTree = "<group>"; };
A14C496D1D76174000D9831C /* CsvFieldConfDlg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CsvFieldConfDlg.cpp; sourceTree = "<group>"; };
A14C496E1D76174000D9831C /* CsvFieldConfDlg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CsvFieldConfDlg.h; sourceTree = "<group>"; };
A1648F2326AA000E00D0E191 /* joincount_ratio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = joincount_ratio.cpp; path = Algorithms/joincount_ratio.cpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1221,6 +1224,8 @@
A19F514D1756A11E006E31B4 /* plugins */,
A41C2BB92404470C00C341A2 /* GenColor.h */,
A41C2BBA2404471D00C341A2 /* GenColor.cpp */,
A14744CE2AC241660054D653 /* GeomUtils.cpp */,
A14744CF2AC241660054D653 /* GeomUtils.h */,
DD3BA4471871EE9A00CA4152 /* DefaultVarsPtree.h */,
DD3BA4461871EE9A00CA4152 /* DefaultVarsPtree.cpp */,
DD9C1B361910267900C0A427 /* GdaConst.h */,
Expand Down Expand Up @@ -1852,7 +1857,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n#python3 install_name.py $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks\nif [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n codesign -f -s \"Apple Development: [email protected] (AN5USPSZF6)\" /opt/homebrew/opt/gdal/lib/libgdal.32.dylib\n codesign -f -s \"Apple Development: [email protected] (AN5USPSZF6)\" /opt/homebrew/Cellar/[email protected]/1.1.1o/lib/libcrypto.1.1.dylib\n codesign -f -s \"Apple Development: [email protected] (AN5USPSZF6)\" /Users/xun/github/geoda/BuildTools/macosx/libraries/lib/libwx_osx_cocoau-3.1.4.0.0.dylib\n codesign -f -s \"Apple Development: [email protected] (AN5USPSZF6)\" /Users/xun/github/geoda/BuildTools/macosx/libraries/lib/libwx_osx_cocoau_gl-3.1.4.0.0.dylib\n #install_name_tool -change \"@rpath/libgeos.3.10.1.dylib\" \"/opt/homebrew/opt/geos/lib/libgeos.3.10.1.dylib\" /opt/homebrew/Cellar/geos/3.10.1/lib/libgeos_c.1.16.0.dylib\n #codesign -f -s \"Apple Development: [email protected] (AN5USPSZF6)\" /opt/homebrew/Cellar/geos/3.10.1/lib/libgeos_c.1.16.0.dylib\nelse\n mkdir $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks\n cp /Users/xun/github/geoda/BuildTools/macosx/libraries/lib/libwx_osx_cocoau-3.1.4.0.0.dylib $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/libwx_osx_cocoau-3.1.dylib\n cp /Users/xun/github/geoda/BuildTools/macosx/libraries/lib/libwx_osx_cocoau_gl-3.1.4.0.0.dylib $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/libwx_osx_cocoau_gl-3.1.dylib\n cp /usr/local/opt/gdal/lib/libgdal.29.dylib $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/libgdal.29.dylib\n install_name_tool -id \"GeoDa\" $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/GeoDa\n install_name_tool -change \"/Users/xun/github/geoda/BuildTools/macosx/libraries/lib/libwx_osx_cocoau_gl-3.1.dylib\" \"@executable_path/../Frameworks/libwx_osx_cocoau_gl-3.1.dylib\" $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/GeoDa\n install_name_tool -change \"/Users/xun/github/geoda/BuildTools/macosx/libraries/lib/libwx_osx_cocoau-3.1.dylib\" \"@executable_path/../Frameworks/libwx_osx_cocoau-3.1.dylib\" $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/GeoDa\n install_name_tool -change \"/usr/local/opt/gdal/lib/libgdal.29.dylib\" \"@executable_path/../Frameworks/libgdal.29.dylib\" $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/GeoDa\n install_name_tool -change \"/opt/homebrew/opt/gdal/lib/libgdal.29.dylib\" \"@executable_path/../Frameworks/libgdal.29.dylib\" $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/GeoDa\n python3 install_name.py $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks \"0046C0AE0D6933F7CD8A67875F820AF13CD63439\"\n codesign -f --timestamp -o runtime -s \"0046C0AE0D6933F7CD8A67875F820AF13CD63439\" $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/GeoDa\n codesign -f --timestamp -o runtime -s \"0046C0AE0D6933F7CD8A67875F820AF13CD63439\" $TARGET_BUILD_DIR/$PRODUCT_NAME.app\nfi\n";
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n#python3 install_name.py $TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks\nif [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n codesign -f -s \"Apple Development: [email protected] (AN5USPSZF6)\" /opt/homebrew/opt/gdal/lib/libgdal.32.dylib\n codesign -f -s \"Apple Development: [email protected] (AN5USPSZF6)\" /opt/homebrew/Cellar/[email protected]/1.1.1o/lib/libcrypto.1.1.dylib\n codesign -f -s \"Apple Development: [email protected] (AN5USPSZF6)\" /Users/xun/github/geoda/BuildTools/macosx/libraries/lib/libwx_osx_cocoau-3.1.4.0.0.dylib\n codesign -f -s \"Apple Development: [email protected] (AN5USPSZF6)\" /Users/xun/github/geoda/BuildTools/macosx/libraries/lib/libwx_osx_cocoau_gl-3.1.4.0.0.dylib\n #install_name_tool -change \"@rpath/libgeos.3.10.1.dylib\" \"/opt/homebrew/opt/geos/lib/libgeos.3.10.1.dylib\" /opt/homebrew/Cellar/geos/3.10.1/lib/libgeos_c.1.16.0.dylib\n #codesign -f -s \"Apple Development: [email protected] (AN5USPSZF6)\" /opt/homebrew/Cellar/geos/3.10.1/lib/libgeos_c.1.16.0.dylib \nfi\n";
};
/* End PBXShellScriptBuildPhase section */

Expand All @@ -1861,6 +1866,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A14744D02AC241D50054D653 /* GeomUtils.cpp in Sources */,
A4502B3824E1F67C001D378F /* SCHCDlg.cpp in Sources */,
DD7974C80F1D250A00496A84 /* TemplateCanvas.cpp in Sources */,
A4ED7D5B209A6B81008685D6 /* HDBScanDlg.cpp in Sources */,
Expand Down Expand Up @@ -2360,11 +2366,11 @@
ONLY_ACTIVE_ARCH = YES;
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-I/opt/homebrew/include",
"-I/opt/homebrew/opt/gdal/include",
"-I/usr/include",
"-I./libraries/lib/wx/include/osx_cocoa-unicode-3.1",
"-I./libraries/include/wx-3.1/",
"-I./temp/boost",
"-I./libraries/lib/wx/include/osx_cocoa-unicode-3.2",
"-I./libraries/include/wx-3.2/",
"-I/opt/homebrew/opt/boost/include",
"-I./libraries/include",
"-I./temp/eigen3",
"-I./temp/spectra/include",
Expand Down
2 changes: 0 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ FetchContent_Declare(
#set(JSON_SPIRIT_VALUE_ENABLED)
FetchContent_MakeAvailable(json_spirit)

message(aaa"${GDAL_LIBRARIES}")

set(CMAKE_CXX_STANDARD 17)
# options
option(UNITTEST "Unit test" ON)
Expand Down
70 changes: 28 additions & 42 deletions Explore/WebGLMapView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <string>
#include <wx/wxprec.h>

#ifndef WX_PRECOMP
Expand Down Expand Up @@ -44,14 +44,15 @@
#include <wx/webviewfshandler.h>

#include "../GenUtils.h"
#include "../GeomUtils.h"
#include "WebGLMapView.h"

IMPLEMENT_CLASS(WebGLMapFrame, TemplateFrame)
BEGIN_EVENT_TABLE(WebGLMapFrame, TemplateFrame)
END_EVENT_TABLE()

WebGLMapFrame::WebGLMapFrame(wxFrame* parent, Project* project, const std::vector<OGRFeature*>& features,
const wxString& title, const wxPoint& pos, const wxSize& size, const int style)
WebGLMapFrame::WebGLMapFrame(wxFrame* parent, Project* project, OGRLayer* layer, const wxString& title,
const wxPoint& pos, const wxSize& size, const int style)
: TemplateFrame(parent, project, title, pos, size, style) {
wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL);

Expand All @@ -77,7 +78,7 @@ WebGLMapFrame::WebGLMapFrame(wxFrame* parent, Project* project, const std::vecto
wxFileSystem::AddHandler(new wxMemoryFSHandler);

// Create the memory files
CreateMemoryFiles(features);
CreateMemoryFiles(layer);

// Create the webview
m_browser = wxWebView::New();
Expand Down Expand Up @@ -108,56 +109,39 @@ WebGLMapFrame::WebGLMapFrame(wxFrame* parent, Project* project, const std::vecto
}

WebGLMapFrame::~WebGLMapFrame() {
wxMemoryFSHandler::RemoveFile("data.csv");
wxMemoryFSHandler::RemoveFile("data.arrow");
wxMemoryFSHandler::RemoveFile("bundle.js");
wxMemoryFSHandler::RemoveFile("index.html");
DeregisterAsActive();
}

std::string bytes_to_hex(const unsigned char* bytes, size_t n_bytes) {
static const char* hex_digits = "0123456789ABCDEF";
std::string hex_string;
for (size_t i = 0; i < n_bytes; ++i) {
const unsigned char c = bytes[i];
hex_string.push_back(hex_digits[c >> 4]);
hex_string.push_back(hex_digits[c & 15]);
}
return hex_string;
}

void WebGLMapFrame::CreateMemoryFiles(const std::vector<OGRFeature*>& features) {
void WebGLMapFrame::CreateMemoryFiles(OGRLayer* layer) {
wxStopWatch sw;
// load web pages under web_plugins/
wxString web_file_path = GenUtils::GetSamplesDir();

wxPathList pathlist;
pathlist.Add(web_file_path);

// Create data.csv by passing in OGRLayer with only geometries and selected variables
wxString csv_filecontent;
const wxString first_line = "id,geom\n";
csv_filecontent << first_line;
for (size_t i = 0; i < features.size(); ++i) {
const OGRFeature* feat = features[i];
const OGRGeometry* geom = feat->GetGeometryRef();
int nBLOBLen = geom->WkbSize();
GByte* pabyGeomBLOB = reinterpret_cast<GByte*>(VSIMalloc(nBLOBLen));
geom->exportToWkb(wkbNDR, pabyGeomBLOB);
// hex-encoded WKB strings
wxString wkb(bytes_to_hex(pabyGeomBLOB, nBLOBLen));
wxString line = wxString::Format(_("%zd,\"%s\"\n"), i, wkb);
// char* pszWKT = NULL;
// geom->exportToWkt(&pszWKT);
// wxString wkt = pszWKT;
// wxString line = wxString::Format(_("%zd,\"%s\"\n"), i, wkt);
csv_filecontent << line;
}
const wxString csv_filename = "data.csv";
wxMemoryFSHandler::AddFile(csv_filename, csv_filecontent);
const std::string ogr_filename = "/vsimem/data.arrow";

const std::string driver_name = "Arrow";
char** options = nullptr;
options = CSLSetNameValue(options, "COMPRESSION", "NONE");
save_ogrlayer(layer, ogr_filename, driver_name, options);
CSLDestroy(options);
// save_ogrlayer(layer, ogr_filename, "GeoJSON");
// read vsimem file in char* buffer
VSILFILE* fp = VSIFOpenL(ogr_filename.c_str(), "rb");
VSIFSeekL(fp, 0, SEEK_END);
const size_t size = VSIFTellL(fp);
VSIFSeekL(fp, 0, SEEK_SET);
char* buffer = new char[size];
VSIFReadL(buffer, 1, size, fp);
VSIFCloseL(fp);
wxMemoryFSHandler::AddFileWithMimeType("data.arrow", buffer, size, "");

wxFile file("/Users/xun/Downloads/wkb.csv", wxFile::write);
file.Write(csv_filecontent);
file.Close();

// Create bundle.js
wxString bundle_path = wxFileName(pathlist.FindValidPath("bundle.js")).GetAbsolutePath();
wxFFile bundle_file(bundle_path);
Expand All @@ -174,9 +158,11 @@ void WebGLMapFrame::CreateMemoryFiles(const std::vector<OGRFeature*>& features)

// replace relative urls in index.html with "memory:bundle.js"
index_content.Replace("bundle.js", custom_scheme + "bundle.js");
index_content.Replace("data.csv", custom_scheme + "data.csv");
index_content.Replace("data.arrow", custom_scheme + "data.arrow");

wxMemoryFSHandler::AddFile("index.html", index_content);

std::cout << "Create Memory File:" << sw.Time() << std::endl;
}

void WebGLMapFrame::OnIdle(wxIdleEvent& WXUNUSED(evt)) {
Expand Down
8 changes: 4 additions & 4 deletions Explore/WebGLMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@

class WebGLMapFrame : public TemplateFrame {
public:
explicit WebGLMapFrame(wxFrame* parent, Project* project, const std::vector<OGRFeature*>& features,
const wxString& title = _("WebGL Map"), const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, const int style = wxDEFAULT_FRAME_STYLE);
explicit WebGLMapFrame(wxFrame* parent, Project* project, OGRLayer* layer, const wxString& title = _("WebGL Map"),
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
const int style = wxDEFAULT_FRAME_STYLE);
virtual ~WebGLMapFrame();

private:
wxWebView* m_browser;
wxString custom_scheme;

void OnIdle(wxIdleEvent& WXUNUSED(evt));
void CreateMemoryFiles(const std::vector<OGRFeature*>& features);
void CreateMemoryFiles(OGRLayer* layer);

DECLARE_CLASS(WebGLMapFrame)
DECLARE_EVENT_TABLE()
Expand Down
2 changes: 1 addition & 1 deletion GeoDa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,7 @@ void GdaFrame::InitWithProject(wxString gda_file_path)

const OGRLayerProxy* ogr_layer = project_p->GetOGRLayerProxy();
if (ogr_layer) {
WebGLMapFrame *glMap = new WebGLMapFrame(this, project_p, ogr_layer->data);
WebGLMapFrame *glMap = new WebGLMapFrame(this, project_p, ogr_layer->layer);
glMap->Show();
}
}
Expand Down
118 changes: 118 additions & 0 deletions GeomUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/
#include "GeomUtils.h"

#include <iostream>

// read vector file using OGR
std::vector<OGRFeature*> read_vector_file(const std::string& filename) {
std::vector<OGRFeature*> data;
Expand Down Expand Up @@ -177,3 +179,119 @@ void vector_to_csv(const std::string& geojson_filename, const std::string& csv_f

CSLDestroy(options);
}

// compute mean center of geometry
void mean_center(const OGRGeometry* geom, OGRPoint* point) {
double x = 0;
double y = 0;
double n = 0;
// get geometry type
const OGRwkbGeometryType geom_type = geom->getGeometryType();
if (geom_type == wkbPoint) {
const OGRPoint* pt = dynamic_cast<const OGRPoint*>(geom);
x = pt->getX();
y = pt->getY();
++n;
} else if (geom_type == wkbMultiPoint) {
const OGRMultiPoint* input_multipoint = dynamic_cast<const OGRMultiPoint*>(geom);
for (int i = 0; i < input_multipoint->getNumGeometries(); ++i) {
const OGRPoint* pt = dynamic_cast<const OGRPoint*>(input_multipoint->getGeometryRef(i));
x += pt->getX();
y += pt->getY();
++n;
}
} else if (geom_type == wkbPolygon) {
const OGRPolygon* input_polygon = dynamic_cast<const OGRPolygon*>(geom);
for (int i = 0; i < input_polygon->getNumInteriorRings() + 1; ++i) {
const OGRLinearRing* input_ring =
i == 0 ? input_polygon->getExteriorRing() : input_polygon->getInteriorRing(i - 1);
const auto& pt_it = input_ring->getPointIterator();
OGRPoint pt;
while (pt_it->getNextPoint(&pt)) {
x += pt.getX();
y += pt.getY();
++n;
}
}
} else if (geom_type == wkbMultiPolygon) {
const OGRMultiPolygon* input_multipolygon = dynamic_cast<const OGRMultiPolygon*>(geom);
for (int i = 0; i < input_multipolygon->getNumGeometries(); ++i) {
const OGRPolygon* input_polygon = dynamic_cast<const OGRPolygon*>(input_multipolygon->getGeometryRef(i));
for (int j = 0; j < input_polygon->getNumInteriorRings() + 1; ++j) {
const OGRLinearRing* input_ring =
j == 0 ? input_polygon->getExteriorRing() : input_polygon->getInteriorRing(j - 1);
const auto& pt_it = input_ring->getPointIterator();
OGRPoint pt;
while (pt_it->getNextPoint(&pt)) {
x += pt.getX();
y += pt.getY();
++n;
}
}
}
} else {
// print error message
std::cout << "Error: invalid geometry type" << std::endl;
}
point->setX(x / n);
point->setY(y / n);
}

// compute center of mass or center of gravity of geometry
void center_of_mass(const OGRGeometry* geom, OGRPoint* point) {
const OGRwkbGeometryType geom_type = geom->getGeometryType();

if (geom_type == wkbPoint) {
const OGRPoint* pt = dynamic_cast<const OGRPoint*>(geom);
point->setX(pt->getX());
point->setY(pt->getY());
} else if (geom->getGeometryType() == wkbPolygon) {
std::vector<OGRPoint*> neutralized_points;

OGRPoint translation;
mean_center(geom, &translation);

const OGRPolygon* input_polygon = dynamic_cast<const OGRPolygon*>(geom);
for (int i = 0; i < input_polygon->getNumInteriorRings() + 1; ++i) {
const OGRLinearRing* input_ring =
i == 0 ? input_polygon->getExteriorRing() : input_polygon->getInteriorRing(i - 1);
const auto& pt_it = input_ring->getPointIterator();
OGRPoint *pt = new OGRPoint();
while (pt_it->getNextPoint(pt)) {
pt->setX(pt->getX() - translation.getX());
pt->setY(pt->getY() - translation.getY());
neutralized_points.push_back(pt);
}
}

double sx = 0;
double sy = 0;
double s_area = 0;

for (size_t i = 0; i < neutralized_points.size(); ++i) {
const OGRPoint* pt = neutralized_points[i];
const OGRPoint* next_pt = neutralized_points[(i + 1) % neutralized_points.size()];
const double area = pt->getX() * next_pt->getY() - next_pt->getX() * pt->getY();
sx += (pt->getX() + next_pt->getX()) * area;
sy += (pt->getY() + next_pt->getY()) * area;
s_area += area;
}

if (s_area == 0) {
point->setX(translation.getX());
point->setY(translation.getY());
} else {
point->setX(sx / (3 * s_area) + translation.getX());
point->setY(sy / (3 * s_area) + translation.getY());
}
} else {
OGRGeometry* convex_hull = geom->ConvexHull();

if (convex_hull) {
center_of_mass(convex_hull, point);
delete convex_hull;
} else {
mean_center(geom, point);
}
}
}
6 changes: 6 additions & 0 deletions GeomUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,10 @@ void vector_to_arrow(const std::string& geojson_filename, const std::string& arr
// convert Geojson to CSV file
void vector_to_csv(const std::string& geojson_filename, const std::string& csv_filename);

// compute mean center of geometry
void mean_center(const OGRGeometry* geom, OGRPoint* point);

// compute center of mass or center of gravity of geometry
void center_of_mass(const OGRGeometry* geom, OGRPoint* point);

#endif
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
# Add test cpp file
set(TEST_SOURCE_FILES
${GEODA_SOURCE_FILES}
test-boost-utils.cpp
test-geom-utils.cpp
test-webgl-map.cpp)

Expand Down
Loading

0 comments on commit 23d65a8

Please sign in to comment.