Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 52 additions & 22 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,42 +1,72 @@
cmake_minimum_required(VERSION 3.13.0)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum macOS deployment version")
project(depthmapX)
cmake_minimum_required(VERSION 3.13.0)
set(CMAKE_CXX_STANDARD 17)

option(DEPTHMAPX_ENABLE_IPO "Enable interprocedural optimisation for Release builds" OFF)

if (DEPTHMAPX_ENABLE_IPO)
include(CheckIPOSupported)
check_ipo_supported(RESULT DEPTHMAPX_IPO_SUPPORTED OUTPUT DEPTHMAPX_IPO_ERROR)
if (DEPTHMAPX_IPO_SUPPORTED)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
else()
message(WARNING "IPO/LTO is not supported by this toolchain: ${DEPTHMAPX_IPO_ERROR}")
endif()
endif()

if (MSVC)
# /MP improves build time. /Oi, /Gy and linker folding improve Release runtime/size.
add_compile_options(/MP "$<$<CONFIG:Release>:/Oi>" "$<$<CONFIG:Release>:/Gy>")
add_link_options("$<$<CONFIG:Release>:/OPT:REF>" "$<$<CONFIG:Release>:/OPT:ICF>")
endif()

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(warnings "-Wall -Wextra")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(warnings "/W4 /EHsc")
execute_process(COMMAND make_version_header.bat WORKING_DIRECTORY depthmapX)
endif()

# policy for target sources - we don't expect any old CMakes
cmake_policy(SET CMP0076 NEW)

include_directories(".")

# Get the current working branch
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE APP_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)

# Get the latest abbreviated commit hash of the working branch
execute_process(
COMMAND git log -1 --format=%h
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE APP_COMMIT
OUTPUT_STRIP_TRAILING_WHITESPACE
)

# generate version_defs.h
include_directories(${CMAKE_BINARY_DIR})
configure_file("${CMAKE_SOURCE_DIR}/version_defs.h.in" "${CMAKE_BINARY_DIR}/version_defs.h" @ONLY)
# Generate version metadata without relying on the deprecated Windows WMIC tool.
set(APP_BRANCH "unknown")
set(APP_COMMIT "unknown")
find_package(Git QUIET)
find_package(Threads REQUIRED)
if (GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE APP_BRANCH_RESULT
OUTPUT_VARIABLE APP_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if (NOT APP_BRANCH_RESULT EQUAL 0 OR APP_BRANCH STREQUAL "")
set(APP_BRANCH "unknown")
endif()

string(TIMESTAMP APP_DATE %Y-%m-%d)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --format=%h
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE APP_COMMIT_RESULT
OUTPUT_VARIABLE APP_COMMIT
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if (NOT APP_COMMIT_RESULT EQUAL 0 OR APP_COMMIT STREQUAL "")
set(APP_COMMIT "unknown")
endif()
endif()

string(TIMESTAMP APP_DATE "%Y-%m-%d")
include_directories("${CMAKE_BINARY_DIR}")
configure_file("${CMAKE_SOURCE_DIR}/version_defs.h.in" "${CMAKE_BINARY_DIR}/version_defs.h" @ONLY)

set(modules_core "" CACHE INTERNAL "modules_core" FORCE)
set(MODULES_GUI FALSE)
Expand Down
2 changes: 1 addition & 1 deletion depthmapX/GraphDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ void QGraphDoc::cancel_wait()
else {
m_communicator->Cancel();
}
// Don't cancel --- cancel should be handled by the thread!
// Don't cancel --- cancel should be handled by the thread!
}
}

Expand Down
2 changes: 1 addition & 1 deletion depthmapX/UI/AboutDlg.ui
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
<item>
<widget class="QLabel" name="c_vrlink">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/SpaceGroupUCL/depthmapX&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/varoudis/depthmapX&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/SpaceGroupUCL/depthmapX&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/SpaceGroupUCL/depthmapX&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
Expand Down
6 changes: 3 additions & 3 deletions depthmapX/UI/SegmentAnalysisDlg.ui
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<item>
<widget class="QRadioButton" name="c_analysis_type">
<property name="text">
<string>Tulip Analysis (Faster)</string>
<string>Tulip Analysis (Multi-Threaded)</string>
</property>
</widget>
</item>
Expand Down Expand Up @@ -58,14 +58,14 @@
<item>
<widget class="QCheckBox" name="c_choice">
<property name="text">
<string>Include choice (betweenness)</string>
<string>Include choice (betweenness — Serial / Slower)</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="c_radio2">
<property name="text">
<string>Full Angular (Slower)</string>
<string>Full Angular (Multi-Threaded)</string>
</property>
</widget>
</item>
Expand Down
4 changes: 2 additions & 2 deletions depthmapX/UI/licenseagreement.ui
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
</size>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:24pt;&quot;&gt;depthmapX&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Multi-Platform Spatial Network Analysis Software&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/varoudis/depthmapX&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/varoudis/depthmapX&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;(C) 2000-2010 University College London, Alasdair Turner, Eva Friedrich&lt;br/&gt;(C) 2011-2014 Tasos Varoudis, UCL&lt;br/&gt;(C) 2017 Christian Sailer, Petros Koutsolampros&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;In memory of Alasdair Turner &lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:24pt;&quot;&gt;depthmapX&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Multi-Platform Spatial Network Analysis Software&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/SpaceGroupUCL/depthmapX&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/SpaceGroupUCL/depthmapX&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;(C) 2000-2010 University College London, Alasdair Turner, Eva Friedrich&lt;br/&gt;(C) 2011-2014 Tasos Varoudis, UCL&lt;br/&gt;(C) 2017 Christian Sailer, Petros Koutsolampros&lt;br/&gt;(C) 2026 Victor Yu-Chieh Lin&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;In memory of Alasdair Turner &lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
Expand All @@ -47,7 +47,7 @@
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'.SF NS Text'; font-size:13pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Courier New,courier'; font-size:14pt; color:#000000;&quot;&gt;(c) 2000-2010 University College London, Alasdair Turner, Eva Friedrich&lt;br /&gt;(c) 2011-2014, Tasos Varoudis&lt;br /&gt;(c) 2017 Christian Sailer, Petros Koutsolampros&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Courier New,courier'; font-size:14pt; color:#000000;&quot;&gt;(c) 2000-2010 University College London, Alasdair Turner, Eva Friedrich&lt;br /&gt;(c) 2011-2014, Tasos Varoudis&lt;br /&gt;(c) 2017 Christian Sailer, Petros Koutsolampros&lt;br /&gt;(c) 2026 Victor Yu-Chieh Lin&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Courier New,courier'; font-size:14pt; color:#000000;&quot;&gt;This program 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.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
Expand Down
2 changes: 1 addition & 1 deletion depthmapX/dialogs/AboutDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ CAboutDlg::CAboutDlg(QWidget *parent)
QString m_version_info;
m_version_info = QString(tr("Version %1.%2.%3 (%4, %5)")).arg(DEPTHMAPX_MAJOR_VERSION).arg(DEPTHMAPX_MINOR_VERSION).arg(DEPTHMAPX_REVISION_VERSION).arg(APP_GIT_BRANCH).arg(APP_GIT_COMMIT);
QString m_copyright;
m_copyright = QString(tr("(C) 2000-2010 University College London, Alasdair Turner, Eva Friedrich\n(C) 2011-2014 Tasos Varoudis\n(C) 2017 Christian Sailer, Petros Koutsolampros"));
m_copyright = QString(tr("(C) 2000-2010 University College London, Alasdair Turner, Eva Friedrich\n(C) 2011-2014 Tasos Varoudis\n(C) 2017 Christian Sailer, Petros Koutsolampros\n(C) 2026 Victor Yu-Chieh Lin "));
QString m_agreement;
m_agreement = QString(tr("This program 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.\x0D\x0D\x0A\x0D\x0D\x0AThis program 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.\x0D\x0D\x0A\x0D\x0D\x0AYou should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>."));

Expand Down
29 changes: 29 additions & 0 deletions depthmapX/version_defs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (C) 2018 Christian Sailer
// This program 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.

// This program 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 <http://www.gnu.org/licenses/>.

// This file is autogenerated - do not modify it directly!

#pragma once

#ifndef APP_DATE
#define APP_DATE "/00/00"
#endif

#ifndef APP_GIT_BRANCH
#define APP_GIT_BRANCH "master"
#endif

#ifndef APP_GIT_COMMIT
#define APP_GIT_COMMIT "02ceaec"
#endif
9 changes: 5 additions & 4 deletions genlib/comm.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#pragma once

//#include <io.h>
#include <atomic>
#include <fstream>
#include <string>
#include <chrono>
Expand Down Expand Up @@ -66,7 +67,7 @@ class Communicator {
enum { NUM_STEPS, CURRENT_STEP, NUM_RECORDS, CURRENT_RECORD };

protected:
bool m_cancelled;
std::atomic_bool m_cancelled;
bool m_delete_flag;
// nb. converted to Win32 UTF-16 Unicode path (AT 31.01.11) Linux, MacOS use UTF-8 (AT 29.04.11)
std::string m_infilename;
Expand All @@ -80,7 +81,7 @@ class Communicator {
m_infile = NULL;
m_infile2 = NULL;
m_outfile = NULL;
m_cancelled = false;
m_cancelled.store(false, std::memory_order_relaxed);
m_delete_flag = false;
}
//
Expand Down Expand Up @@ -130,8 +131,8 @@ class Communicator {
}
void SetOutfile(const char *filename) { m_outfile = new std::ofstream(filename); }
//
bool IsCancelled() const { return m_cancelled; }
void Cancel() { m_cancelled = true; }
bool IsCancelled() const { return m_cancelled.load(std::memory_order_acquire); }
void Cancel() { m_cancelled.store(true, std::memory_order_release); }
//
std::ifstream &getInFileStream() { return *m_infile; }
std::ifstream &GetInfile2() { return *m_infile2; }
Expand Down
6 changes: 2 additions & 4 deletions genlib/pafmath.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ inline double prandomr(int set = 0) { return double(pafrand(set)) / double(PAF_R
// note, in order to stop confusing myself I have ln defined:
#define ln(X) log(X)

inline double log2(double a) { return (ln(a) * M_1_LN2); }

// Hillier Hanson dvalue
/*
inline double dvalue(double k)
Expand All @@ -69,10 +67,10 @@ inline double dvalue(double k)
*/

// Hillier Hanson dvalue (from Kruger 1989 -- see Teklenburg et al)
inline double dvalue(double k) { return 2.0 * (k * (log2((k + 2.0) / 3.0) - 1.0) + 1.0) / ((k - 1.0) * (k - 2.0)); }
inline double dvalue(double k) { return 2.0 * (k * (std::log2((k + 2.0) / 3.0) - 1.0) + 1.0) / ((k - 1.0) * (k - 2.0)); }

// Hillier Hanson pvalue
inline double pvalue(double k) { return 2.0 * (k - log2(k) - 1.0) / ((k - 1.0) * (k - 2.0)); }
inline double pvalue(double k) { return 2.0 * (k - std::log2(k) - 1.0) / ((k - 1.0) * (k - 2.0)); }

// Teklenburg integration (correction 31.01.11 due to Ulrich Thaler
inline double teklinteg(double nodecount, double totaldepth) {
Expand Down
138 changes: 138 additions & 0 deletions genlib/parallel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// genlib - a component of the depthmapX - spatial network analysis platform
// Copyright (C) 2026 depthmapX contributors

#pragma once

#include "genlib/comm.h"

#include <algorithm>
#include <atomic>
#include <chrono>
#include <cstdlib>
#include <exception>
#include <limits>
#include <mutex>
#include <string>
#include <thread>
#include <vector>

namespace depthmapX {

inline size_t configuredAnalysisThreadCount(size_t taskCount, size_t estimatedBytesPerWorker = 0) {
size_t requested = 0;
if (const char *value = std::getenv("DEPTHMAPX_THREADS")) {
try {
requested = static_cast<size_t>(std::stoul(value));
} catch (...) {
requested = 0;
}
}

if (requested == 0 && taskCount < 256) {
return 1;
}

size_t hardwareThreads = static_cast<size_t>(std::thread::hardware_concurrency());
if (hardwareThreads == 0) {
hardwareThreads = 2;
}

size_t workers = requested > 0 ? std::min(requested, hardwareThreads)
: std::min<size_t>(hardwareThreads, 8);
workers = std::max<size_t>(1, std::min(workers, taskCount));

// Keep per-analysis scratch allocations under a conservative 512 MiB budget by default.
if (estimatedBytesPerWorker > 0) {
constexpr size_t MEMORY_BUDGET = size_t(512) * 1024 * 1024;
const size_t memoryLimitedWorkers = std::max<size_t>(1, MEMORY_BUDGET / estimatedBytesPerWorker);
workers = std::min(workers, memoryLimitedWorkers);
}

return std::max<size_t>(1, workers);
}

template <typename Function>
void parallelFor(size_t taskCount, size_t workerCount, Communicator *comm, Function &&function) {
if (taskCount == 0) {
return;
}

workerCount = std::max<size_t>(1, std::min(workerCount, taskCount));
if (workerCount == 1) {
for (size_t task = 0; task < taskCount; ++task) {
if (comm && comm->IsCancelled()) {
throw Communicator::CancelledException();
}
function(task, size_t(0));
if (comm && (((task + 1) & 0x3f) == 0 || task + 1 == taskCount)) {
comm->CommPostMessage(Communicator::CURRENT_RECORD, static_cast<int>(task + 1));
}
}
return;
}

std::atomic<size_t> completed{0};
std::atomic_bool stop{false};
std::exception_ptr workerException;
std::mutex exceptionMutex;

std::vector<std::thread> workers;
workers.reserve(workerCount);
for (size_t worker = 0; worker < workerCount; ++worker) {
workers.emplace_back([&, worker]() {
// Static cyclic scheduling keeps reductions repeatable while still spreading
// neighbouring roots across the available workers.
for (size_t task = worker; task < taskCount && !stop.load(std::memory_order_relaxed);
task += workerCount) {
if (comm && comm->IsCancelled()) {
stop.store(true, std::memory_order_relaxed);
break;
}

try {
function(task, worker);
completed.fetch_add(1, std::memory_order_release);
} catch (...) {
{
std::lock_guard<std::mutex> lock(exceptionMutex);
if (!workerException) {
workerException = std::current_exception();
}
}
stop.store(true, std::memory_order_relaxed);
break;
}
}
});
}

size_t lastReported = std::numeric_limits<size_t>::max();
while (!stop.load(std::memory_order_relaxed) && completed.load(std::memory_order_acquire) < taskCount) {
if (comm && comm->IsCancelled()) {
stop.store(true, std::memory_order_relaxed);
break;
}
const size_t current = completed.load(std::memory_order_acquire);
if (comm && current != lastReported) {
comm->CommPostMessage(Communicator::CURRENT_RECORD, static_cast<int>(current));
lastReported = current;
}
std::this_thread::sleep_for(std::chrono::milliseconds(25));
}

for (std::thread &worker : workers) {
worker.join();
}

if (workerException) {
std::rethrow_exception(workerException);
}
if (comm && comm->IsCancelled()) {
throw Communicator::CancelledException();
}
if (comm) {
comm->CommPostMessage(Communicator::CURRENT_RECORD, static_cast<int>(completed.load()));
}
}

} // namespace depthmapX
Loading