<commit_before>#ifdef WIN32

#include "native.h"
#include "generic.h"
#include <windows.h>
#include <wchar.h>

/*
 * Marks the given result as failed, using the current value of GetLastError()
 */
void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result) {
    mark_failed_with_code(env, message, GetLastError(), result);
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) {
    jclass infoClass = env->GetObjectClass(info);

    OSVERSIONINFOEX versionInfo;
    versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    if (GetVersionEx((OSVERSIONINFO*)&versionInfo) == 0) {
        mark_failed_with_errno(env, "could not get version info", result);
        return;
    }

    SYSTEM_INFO systemInfo;
    GetNativeSystemInfo(&systemInfo);
    jstring arch = NULL;
    if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
        arch = env->NewStringUTF("amd64");
    } else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
        arch = env->NewStringUTF("x86");
    } else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
        arch = env->NewStringUTF("ia64");
    } else {
        arch = env->NewStringUTF("unknown");
    }

    jmethodID method = env->GetMethodID(infoClass, "windows", "(IIIZLjava/lang/String;)V");
    env->CallVoidMethod(info, method, versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
                        versionInfo.dwBuildNumber, versionInfo.wProductType == VER_NT_WORKSTATION,
                        arch);
}

/*
 * Process functions
 */

JNIEXPORT jint JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getPid(JNIEnv *env, jclass target) {
    return GetCurrentProcessId();
}

/*
 * File system functions
 */
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) {
    wchar_t* volumeName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));

    jclass info_class = env->GetObjectClass(info);
    jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V");

    HANDLE handle = FindFirstVolumeW(volumeName, MAX_PATH+1);
    if (handle == INVALID_HANDLE_VALUE) {
        free(volumeName);
        mark_failed_with_errno(env, "could not find first volume", result);
        return;
    }

    wchar_t* deviceName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));
    wchar_t* pathNames = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));
    wchar_t* fsName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));

    while(true) {
        // Chop off the trailing '\'
        size_t len = wcslen(volumeName);
        if (len < 5) {
            mark_failed_with_message(env, "volume name is too short", result);
            break;
        }
        volumeName[len-1] = L'\0';

        if (QueryDosDeviceW(&volumeName[4], deviceName, MAX_PATH+1) == 0) {
            mark_failed_with_errno(env, "could not query dos device", result);
            break;
        }
        volumeName[len-1] = L'\\';

        DWORD used;
        if (GetVolumePathNamesForVolumeNameW(volumeName, pathNames, MAX_PATH+1, &used) == 0) {
            // TODO - try again if the buffer is too small
            mark_failed_with_errno(env, "could not query volume paths", result);
            break;
        }

        wchar_t* cur = pathNames;
        if (cur[0] != L'\0') {
            if(GetVolumeInformationW(cur, NULL, 0, NULL, NULL, NULL, fsName, MAX_PATH+1) == 0) {
                if (GetLastError() != ERROR_NOT_READY) {
                    mark_failed_with_errno(env, "could not query volume information", result);
                    break;
                }
                wcscpy(fsName, L"unknown");
            }
            for (;cur[0] != L'\0'; cur += wcslen(cur) + 1) {
                env->CallVoidMethod(info, method, env->NewString((jchar*)deviceName, wcslen(deviceName)),
                                    env->NewString((jchar*)fsName, wcslen(fsName)), env->NewString((jchar*)cur, wcslen(cur)), JNI_FALSE);
            }
        }

        if (FindNextVolumeW(handle, volumeName, MAX_PATH) == 0) {
            if (GetLastError() != ERROR_NO_MORE_FILES) {
                mark_failed_with_errno(env, "could find next volume", result);
            }
            break;
        }
    }
    free(volumeName);
    free(deviceName);
    free(pathNames);
    free(fsName);
    FindVolumeClose(handle);
}

/*
 * Console functions
 */

HANDLE getHandle(JNIEnv *env, int output, jobject result) {
    HANDLE handle = output == 0 ? GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE);
    if (handle == INVALID_HANDLE_VALUE) {
        mark_failed_with_errno(env, "could not get console handle", result);
        return NULL;
    }
    return handle;
}

JNIEXPORT jboolean JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_isConsole(JNIEnv *env, jclass target, jint output, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    HANDLE handle = getHandle(env, output, result);
    if (handle == NULL) {
        return JNI_FALSE;
    }
    if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
        if (GetLastError() == ERROR_INVALID_HANDLE) {
            return JNI_FALSE;
        }
        mark_failed_with_errno(env, "could not get console buffer", result);
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_getConsoleSize(JNIEnv *env, jclass target, jint output, jobject dimension, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    HANDLE handle = getHandle(env, output, result);
    if (handle == NULL) {
        mark_failed_with_message(env, "not a console", result);
        return;
    }
    if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }

    jclass dimensionClass = env->GetObjectClass(dimension);
    jfieldID widthField = env->GetFieldID(dimensionClass, "cols", "I");
    env->SetIntField(dimension, widthField, console_info.srWindow.Right - console_info.srWindow.Left + 1);
    jfieldID heightField = env->GetFieldID(dimensionClass, "rows", "I");
    env->SetIntField(dimension, heightField, console_info.srWindow.Bottom - console_info.srWindow.Top + 1);
}

HANDLE current_console = NULL;
WORD original_attributes = 0;
WORD current_attributes = 0;

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_initConsole(JNIEnv *env, jclass target, jint output, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    HANDLE handle = getHandle(env, output, result);
    if (handle == NULL) {
        mark_failed_with_message(env, "not a terminal", result);
        return;
    }
    if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
        if (GetLastError() == ERROR_INVALID_HANDLE) {
            mark_failed_with_message(env, "not a console", result);
        } else {
            mark_failed_with_errno(env, "could not get console buffer", result);
        }
        return;
    }
    current_console = handle;
    original_attributes = console_info.wAttributes;
    current_attributes = original_attributes;
    Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_normal(env, target, result);
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_bold(JNIEnv *env, jclass target, jobject result) {
    current_attributes |= FOREGROUND_INTENSITY;
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_normal(JNIEnv *env, jclass target, jobject result) {
    current_attributes &= ~FOREGROUND_INTENSITY;
    SetConsoleTextAttribute(current_console, current_attributes);
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_reset(JNIEnv *env, jclass target, jobject result) {
    if (!SetConsoleTextAttribute(current_console, original_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_foreground(JNIEnv *env, jclass target, jint color, jobject result) {
    current_attributes &= ~ (FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN);
    switch (color) {
        case 0:
            break;
        case 1:
            current_attributes |= FOREGROUND_RED;
            break;
        case 2:
            current_attributes |= FOREGROUND_GREEN;
            break;
        case 3:
            current_attributes |= FOREGROUND_RED|FOREGROUND_GREEN;
            break;
        case 4:
            current_attributes |= FOREGROUND_BLUE;
            break;
        case 5:
            current_attributes |= FOREGROUND_RED|FOREGROUND_BLUE;
            break;
        case 6:
            current_attributes |= FOREGROUND_GREEN|FOREGROUND_BLUE;
            break;
        default:
            current_attributes |= FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE;
            break;
    }

    SetConsoleTextAttribute(current_console, current_attributes);
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_left(JNIEnv *env, jclass target, jint count, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.X -= count;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_right(JNIEnv *env, jclass target, jint count, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.X += count;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_up(JNIEnv *env, jclass target, jint count, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.Y -= count;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_down(JNIEnv *env, jclass target, jint count, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.Y += count;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_startLine(JNIEnv *env, jclass target, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.X = 0;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_clearToEndOfLine(JNIEnv *env, jclass target, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    DWORD count;
    if (!FillConsoleOutputCharacterW(current_console, L' ', console_info.dwSize.X - console_info.dwCursorPosition.X, console_info.dwCursorPosition, &count)) {
        mark_failed_with_errno(env, "could not clear console", result);
    }
}

#endif
<commit_msg>Fixed terminal reset on windows.<commit_after>#ifdef WIN32

#include "native.h"
#include "generic.h"
#include <windows.h>
#include <wchar.h>

/*
 * Marks the given result as failed, using the current value of GetLastError()
 */
void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result) {
    mark_failed_with_code(env, message, GetLastError(), result);
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) {
    jclass infoClass = env->GetObjectClass(info);

    OSVERSIONINFOEX versionInfo;
    versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    if (GetVersionEx((OSVERSIONINFO*)&versionInfo) == 0) {
        mark_failed_with_errno(env, "could not get version info", result);
        return;
    }

    SYSTEM_INFO systemInfo;
    GetNativeSystemInfo(&systemInfo);
    jstring arch = NULL;
    if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
        arch = env->NewStringUTF("amd64");
    } else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
        arch = env->NewStringUTF("x86");
    } else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
        arch = env->NewStringUTF("ia64");
    } else {
        arch = env->NewStringUTF("unknown");
    }

    jmethodID method = env->GetMethodID(infoClass, "windows", "(IIIZLjava/lang/String;)V");
    env->CallVoidMethod(info, method, versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
                        versionInfo.dwBuildNumber, versionInfo.wProductType == VER_NT_WORKSTATION,
                        arch);
}

/*
 * Process functions
 */

JNIEXPORT jint JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getPid(JNIEnv *env, jclass target) {
    return GetCurrentProcessId();
}

/*
 * File system functions
 */
JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) {
    wchar_t* volumeName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));

    jclass info_class = env->GetObjectClass(info);
    jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V");

    HANDLE handle = FindFirstVolumeW(volumeName, MAX_PATH+1);
    if (handle == INVALID_HANDLE_VALUE) {
        free(volumeName);
        mark_failed_with_errno(env, "could not find first volume", result);
        return;
    }

    wchar_t* deviceName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));
    wchar_t* pathNames = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));
    wchar_t* fsName = (wchar_t*)malloc(sizeof(wchar_t) * (MAX_PATH+1));

    while(true) {
        // Chop off the trailing '\'
        size_t len = wcslen(volumeName);
        if (len < 5) {
            mark_failed_with_message(env, "volume name is too short", result);
            break;
        }
        volumeName[len-1] = L'\0';

        if (QueryDosDeviceW(&volumeName[4], deviceName, MAX_PATH+1) == 0) {
            mark_failed_with_errno(env, "could not query dos device", result);
            break;
        }
        volumeName[len-1] = L'\\';

        DWORD used;
        if (GetVolumePathNamesForVolumeNameW(volumeName, pathNames, MAX_PATH+1, &used) == 0) {
            // TODO - try again if the buffer is too small
            mark_failed_with_errno(env, "could not query volume paths", result);
            break;
        }

        wchar_t* cur = pathNames;
        if (cur[0] != L'\0') {
            if(GetVolumeInformationW(cur, NULL, 0, NULL, NULL, NULL, fsName, MAX_PATH+1) == 0) {
                if (GetLastError() != ERROR_NOT_READY) {
                    mark_failed_with_errno(env, "could not query volume information", result);
                    break;
                }
                wcscpy(fsName, L"unknown");
            }
            for (;cur[0] != L'\0'; cur += wcslen(cur) + 1) {
                env->CallVoidMethod(info, method, env->NewString((jchar*)deviceName, wcslen(deviceName)),
                                    env->NewString((jchar*)fsName, wcslen(fsName)), env->NewString((jchar*)cur, wcslen(cur)), JNI_FALSE);
            }
        }

        if (FindNextVolumeW(handle, volumeName, MAX_PATH) == 0) {
            if (GetLastError() != ERROR_NO_MORE_FILES) {
                mark_failed_with_errno(env, "could find next volume", result);
            }
            break;
        }
    }
    free(volumeName);
    free(deviceName);
    free(pathNames);
    free(fsName);
    FindVolumeClose(handle);
}

/*
 * Console functions
 */

HANDLE getHandle(JNIEnv *env, int output, jobject result) {
    HANDLE handle = output == 0 ? GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE);
    if (handle == INVALID_HANDLE_VALUE) {
        mark_failed_with_errno(env, "could not get console handle", result);
        return NULL;
    }
    return handle;
}

JNIEXPORT jboolean JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_isConsole(JNIEnv *env, jclass target, jint output, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    HANDLE handle = getHandle(env, output, result);
    if (handle == NULL) {
        return JNI_FALSE;
    }
    if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
        if (GetLastError() == ERROR_INVALID_HANDLE) {
            return JNI_FALSE;
        }
        mark_failed_with_errno(env, "could not get console buffer", result);
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_getConsoleSize(JNIEnv *env, jclass target, jint output, jobject dimension, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    HANDLE handle = getHandle(env, output, result);
    if (handle == NULL) {
        mark_failed_with_message(env, "not a console", result);
        return;
    }
    if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }

    jclass dimensionClass = env->GetObjectClass(dimension);
    jfieldID widthField = env->GetFieldID(dimensionClass, "cols", "I");
    env->SetIntField(dimension, widthField, console_info.srWindow.Right - console_info.srWindow.Left + 1);
    jfieldID heightField = env->GetFieldID(dimensionClass, "rows", "I");
    env->SetIntField(dimension, heightField, console_info.srWindow.Bottom - console_info.srWindow.Top + 1);
}

HANDLE current_console = NULL;
WORD original_attributes = 0;
WORD current_attributes = 0;

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_initConsole(JNIEnv *env, jclass target, jint output, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    HANDLE handle = getHandle(env, output, result);
    if (handle == NULL) {
        mark_failed_with_message(env, "not a terminal", result);
        return;
    }
    if (!GetConsoleScreenBufferInfo(handle, &console_info)) {
        if (GetLastError() == ERROR_INVALID_HANDLE) {
            mark_failed_with_message(env, "not a console", result);
        } else {
            mark_failed_with_errno(env, "could not get console buffer", result);
        }
        return;
    }
    current_console = handle;
    original_attributes = console_info.wAttributes;
    current_attributes = original_attributes;
    Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_normal(env, target, result);
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_bold(JNIEnv *env, jclass target, jobject result) {
    current_attributes |= FOREGROUND_INTENSITY;
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_normal(JNIEnv *env, jclass target, jobject result) {
    current_attributes &= ~FOREGROUND_INTENSITY;
    SetConsoleTextAttribute(current_console, current_attributes);
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_reset(JNIEnv *env, jclass target, jobject result) {
    current_attributes = original_attributes;
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_foreground(JNIEnv *env, jclass target, jint color, jobject result) {
    current_attributes &= ~ (FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN);
    switch (color) {
        case 0:
            break;
        case 1:
            current_attributes |= FOREGROUND_RED;
            break;
        case 2:
            current_attributes |= FOREGROUND_GREEN;
            break;
        case 3:
            current_attributes |= FOREGROUND_RED|FOREGROUND_GREEN;
            break;
        case 4:
            current_attributes |= FOREGROUND_BLUE;
            break;
        case 5:
            current_attributes |= FOREGROUND_RED|FOREGROUND_BLUE;
            break;
        case 6:
            current_attributes |= FOREGROUND_GREEN|FOREGROUND_BLUE;
            break;
        default:
            current_attributes |= FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE;
            break;
    }

    SetConsoleTextAttribute(current_console, current_attributes);
    if (!SetConsoleTextAttribute(current_console, current_attributes)) {
        mark_failed_with_errno(env, "could not set text attributes", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_left(JNIEnv *env, jclass target, jint count, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.X -= count;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_right(JNIEnv *env, jclass target, jint count, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.X += count;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_up(JNIEnv *env, jclass target, jint count, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.Y -= count;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_down(JNIEnv *env, jclass target, jint count, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.Y += count;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_startLine(JNIEnv *env, jclass target, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    console_info.dwCursorPosition.X = 0;
    if (!SetConsoleCursorPosition(current_console, console_info.dwCursorPosition)) {
        mark_failed_with_errno(env, "could not set cursor position", result);
    }
}

JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_clearToEndOfLine(JNIEnv *env, jclass target, jobject result) {
    CONSOLE_SCREEN_BUFFER_INFO console_info;
    if (!GetConsoleScreenBufferInfo(current_console, &console_info)) {
        mark_failed_with_errno(env, "could not get console buffer", result);
        return;
    }
    DWORD count;
    if (!FillConsoleOutputCharacterW(current_console, L' ', console_info.dwSize.X - console_info.dwCursorPosition.X, console_info.dwCursorPosition, &count)) {
        mark_failed_with_errno(env, "could not clear console", result);
    }
}

#endif
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <rai/core/core.hpp>

namespace {
class test_visitor : public rai::message_visitor
{
public:
    test_visitor () :
    keepalive_count (0),
    publish_count (0),
    confirm_req_count (0),
    confirm_ack_count (0),
    bulk_pull_count (0),
    bulk_push_count (0),
    frontier_req_count (0)
    {
    }
    void keepalive (rai::keepalive const &)
    {
        ++keepalive_count;
    }
    void publish (rai::publish const &)
    {
        ++publish_count;
    }
    void confirm_req (rai::confirm_req const &)
    {
        ++confirm_req_count;
    }
    void confirm_ack (rai::confirm_ack const &)
    {
        ++confirm_ack_count;
    }
    void bulk_pull (rai::bulk_pull const &)
    {
        ++bulk_pull_count;
    }
    void bulk_push (rai::bulk_push const &)
    {
        ++bulk_push_count;
    }
    void frontier_req (rai::frontier_req const &)
    {
        ++frontier_req_count;
    }
    uint64_t keepalive_count;
    uint64_t publish_count;
    uint64_t confirm_req_count;
    uint64_t confirm_ack_count;
    uint64_t bulk_pull_count;
    uint64_t bulk_push_count;
    uint64_t frontier_req_count;
};
}

TEST (message_parser, exact_confirm_ack_size)
{
    rai::system system (24000, 1);
    test_visitor visitor;
    rai::message_parser parser (visitor, system.clients [0]->network.work);
    auto block (std::unique_ptr <rai::send_block> (new rai::send_block));
    block->work = system.clients [0]->ledger.create_work (*block);
    rai::confirm_ack message (std::move (block));
    std::vector <uint8_t> bytes;
    {
        rai::vectorstream stream (bytes);
        message.serialize (stream);
    }
    ASSERT_EQ (0, visitor.confirm_ack_count);
    ASSERT_FALSE (parser.error);
    parser.deserialize_confirm_ack (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.confirm_ack_count);
    ASSERT_FALSE (parser.error);
    bytes.push_back (0);
    parser.deserialize_confirm_ack (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.confirm_ack_count);
    ASSERT_TRUE (parser.error);
}

TEST (message_parser, exact_confirm_req_size)
{
    rai::system system (24000, 1);
    test_visitor visitor;
    rai::message_parser parser (visitor, system.clients [0]->network.work);
    auto block (std::unique_ptr <rai::send_block> (new rai::send_block));
    block->work = system.clients [0]->ledger.create_work (*block);
    rai::confirm_req message (std::move (block));
    std::vector <uint8_t> bytes;
    {
        rai::vectorstream stream (bytes);
        message.serialize (stream);
    }
    ASSERT_EQ (0, visitor.confirm_req_count);
    ASSERT_FALSE (parser.error);
    parser.deserialize_confirm_req (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.confirm_req_count);
    ASSERT_FALSE (parser.error);
    bytes.push_back (0);
    parser.deserialize_confirm_req (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.confirm_req_count);
    ASSERT_TRUE (parser.error);
}

TEST (message_parser, exact_publish_size)
{
    rai::system system (24000, 1);
    test_visitor visitor;
    rai::message_parser parser (visitor, system.clients [0]->network.work);
	auto block (std::unique_ptr <rai::send_block> (new rai::send_block));
	block->hashables.previous = 1;
    block->work = system.clients [0]->ledger.create_work (*block);
	rai::publish message (std::move (block));
    std::vector <uint8_t> bytes;
    {
        rai::vectorstream stream (bytes);
        message.serialize (stream);
    }
    ASSERT_EQ (0, visitor.publish_count);
    ASSERT_FALSE (parser.error);
    parser.deserialize_publish (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.publish_count);
    ASSERT_FALSE (parser.error);
    bytes.push_back (0);
    parser.deserialize_publish (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.publish_count);
    ASSERT_TRUE (parser.error);
}

TEST (message_parser, exact_keepalive_size)
{
    rai::system system (24000, 1);
    test_visitor visitor;
    rai::message_parser parser (visitor, system.clients [0]->network.work);
    rai::keepalive message;
    std::vector <uint8_t> bytes;
    {
        rai::vectorstream stream (bytes);
        message.serialize (stream);
    }
    ASSERT_EQ (0, visitor.keepalive_count);
    ASSERT_FALSE (parser.error);
    parser.deserialize_keepalive (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.keepalive_count);
    ASSERT_FALSE (parser.error);
    bytes.push_back (0);
    parser.deserialize_keepalive (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.keepalive_count);
    ASSERT_TRUE (parser.error);
}<commit_msg>Fixing tests to have non-zero root.<commit_after>#include <gtest/gtest.h>
#include <rai/core/core.hpp>

namespace {
class test_visitor : public rai::message_visitor
{
public:
    test_visitor () :
    keepalive_count (0),
    publish_count (0),
    confirm_req_count (0),
    confirm_ack_count (0),
    bulk_pull_count (0),
    bulk_push_count (0),
    frontier_req_count (0)
    {
    }
    void keepalive (rai::keepalive const &)
    {
        ++keepalive_count;
    }
    void publish (rai::publish const &)
    {
        ++publish_count;
    }
    void confirm_req (rai::confirm_req const &)
    {
        ++confirm_req_count;
    }
    void confirm_ack (rai::confirm_ack const &)
    {
        ++confirm_ack_count;
    }
    void bulk_pull (rai::bulk_pull const &)
    {
        ++bulk_pull_count;
    }
    void bulk_push (rai::bulk_push const &)
    {
        ++bulk_push_count;
    }
    void frontier_req (rai::frontier_req const &)
    {
        ++frontier_req_count;
    }
    uint64_t keepalive_count;
    uint64_t publish_count;
    uint64_t confirm_req_count;
    uint64_t confirm_ack_count;
    uint64_t bulk_pull_count;
    uint64_t bulk_push_count;
    uint64_t frontier_req_count;
};
}

TEST (message_parser, exact_confirm_ack_size)
{
    rai::system system (24000, 1);
    test_visitor visitor;
    rai::message_parser parser (visitor, system.clients [0]->network.work);
    auto block (std::unique_ptr <rai::send_block> (new rai::send_block));
    block->hashables.previous = 1;
    block->work = system.clients [0]->ledger.create_work (*block);
    rai::confirm_ack message (std::move (block));
    std::vector <uint8_t> bytes;
    {
        rai::vectorstream stream (bytes);
        message.serialize (stream);
    }
    ASSERT_EQ (0, visitor.confirm_ack_count);
    ASSERT_FALSE (parser.error);
    parser.deserialize_confirm_ack (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.confirm_ack_count);
    ASSERT_FALSE (parser.error);
    bytes.push_back (0);
    parser.deserialize_confirm_ack (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.confirm_ack_count);
    ASSERT_TRUE (parser.error);
}

TEST (message_parser, exact_confirm_req_size)
{
    rai::system system (24000, 1);
    test_visitor visitor;
    rai::message_parser parser (visitor, system.clients [0]->network.work);
    auto block (std::unique_ptr <rai::send_block> (new rai::send_block));
    block->hashables.previous = 1;
    block->work = system.clients [0]->ledger.create_work (*block);
    rai::confirm_req message (std::move (block));
    std::vector <uint8_t> bytes;
    {
        rai::vectorstream stream (bytes);
        message.serialize (stream);
    }
    ASSERT_EQ (0, visitor.confirm_req_count);
    ASSERT_FALSE (parser.error);
    parser.deserialize_confirm_req (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.confirm_req_count);
    ASSERT_FALSE (parser.error);
    bytes.push_back (0);
    parser.deserialize_confirm_req (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.confirm_req_count);
    ASSERT_TRUE (parser.error);
}

TEST (message_parser, exact_publish_size)
{
    rai::system system (24000, 1);
    test_visitor visitor;
    rai::message_parser parser (visitor, system.clients [0]->network.work);
	auto block (std::unique_ptr <rai::send_block> (new rai::send_block));
	block->hashables.previous = 1;
    block->work = system.clients [0]->ledger.create_work (*block);
	rai::publish message (std::move (block));
    std::vector <uint8_t> bytes;
    {
        rai::vectorstream stream (bytes);
        message.serialize (stream);
    }
    ASSERT_EQ (0, visitor.publish_count);
    ASSERT_FALSE (parser.error);
    parser.deserialize_publish (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.publish_count);
    ASSERT_FALSE (parser.error);
    bytes.push_back (0);
    parser.deserialize_publish (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.publish_count);
    ASSERT_TRUE (parser.error);
}

TEST (message_parser, exact_keepalive_size)
{
    rai::system system (24000, 1);
    test_visitor visitor;
    rai::message_parser parser (visitor, system.clients [0]->network.work);
    rai::keepalive message;
    std::vector <uint8_t> bytes;
    {
        rai::vectorstream stream (bytes);
        message.serialize (stream);
    }
    ASSERT_EQ (0, visitor.keepalive_count);
    ASSERT_FALSE (parser.error);
    parser.deserialize_keepalive (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.keepalive_count);
    ASSERT_FALSE (parser.error);
    bytes.push_back (0);
    parser.deserialize_keepalive (bytes.data (), bytes.size ());
    ASSERT_EQ (1, visitor.keepalive_count);
    ASSERT_TRUE (parser.error);
}<|endoftext|>


<commit_before>#include "characterization.hpp"
#include "chan_vese_active_contour.hpp"

// 2001 Chan-Vese active contour implementation
//
// Chan, Tony F., and Luminita A. Vese.
//      "Active contours without edges."
//      IEEE Transactions on image processing 10.2 (2001): 266-277.
//

// assign checkerboard pattern from IPOL
void initializePhiCheckerboard(Mat& phi) {
    for ( int i = 0; i < phi.rows; ++i ) {
        for ( int j = 0; j < phi.cols; ++j ) {
            phi.at<double>(i, j) = sin(M_PI/5*i)*sin(M_PI/5*j);
        }
    }
}

// assign circle pattern
void initializePhiCircle(Mat& phi, int width, int height) {
    int w = floor(width/2) - 50;
    int h = floor(height/2) - 50;
    for ( int i = 0; i < phi.rows; ++i ) {
        for ( int j = 0; j < phi.cols; ++j ) {
            phi.at<double>(i, j) = -sqrt(pow(j-w-50, 2) + pow(i-h-50, 2)) + min(w, h);
        }
    }
}

double areaInsideContour(Mat phi) {
    return (double)foreground<double>(phi).size();
}

double regionAverage(Mat src, Mat phi, RegionType region) {
    assert (src.size() == phi.size());
    double total_intensity = 0.0;
    int area = 0;
    for (int row = 0; row < phi.rows; ++row) {
        for ( int col = 0; col < phi.cols; ++col ) {
            if ((region == INSIDE && phi.at<double>(row, col) >= 0) ||
                (region == OUTSIDE && phi.at<double>(row, col) < 0)) {
                ++area;
                total_intensity += src.at<uchar>(row, col);
            }
        }
    }
    return total_intensity / area;
}

double diracDelta (double phi_n, double dt) {
    // d/dt of H(phi) = 1/2*(1 + (2/PI)*arctan(phi))
    //return dt / M_PI*(1 + pow(phi_n, 2));
    return dt / (M_PI*(pow(dt, 2) + pow(phi_n, 2)));
    //return (abs(phi_n - 0.0) < 0.1) ? 1.0 : 0.0;
}

//
// Computes a single iteration of the Chan Vese active contour algorithm.
// Returns true if the contour converged, false otherwise.
//
bool activeContour(Mat src, Mat& phi) {

    double mu = 1.0;        // length weight
    double v = 0.5;         // area weight, typically 0 (nu)
    double lambda1 = 1.0;   // c1 weight (average intensity inside contour)
    double lambda2 = 1.0;   // c2 weight (average intensity outside contour)

    int h  = 1.0;                       // space step, where (i*h, j*h) are
                                        // the pixel locations
    double dt = 0.25;                   // artificial time step t >= 0
    double threshold_tolerance = 0.01;  // stopping condition

    double area = areaInsideContour(phi);
    double c1 = regionAverage(src, phi, INSIDE);  // pixel avg inside contour
    double c2 = regionAverage(src, phi, OUTSIDE); // pixel avg outside contour
    cout << "c1: " << c1 << " c2: " << c2 << endl;

    int u0 = 0;
    double phi_n, phi_n_plus_1 = 0.0;
    double delta = 0.0;
    double total_energy;
    Point p;

    double phi_diff = 0.0;
    // TODO: fix edge cases, currently not processing borders of image
    for (int i = 1; i < phi.rows-1; ++i) {
        for (int j = 1; j < phi.cols-1; ++j) {
            u0 = src.at<uchar>(i, j);           // current point intensity
            phi_n = phi.at<double>(i, j);        // current phi value
            delta = diracDelta(phi_n, dt);      // dirac delta
            p = Point(j, i);

            // Calculate curve energy
            // --------------------------------------
            double phix, phiy, divr, divl, divu, divd = 0.0;
            double pcurr = phi.at<double>(p.y, p.x);
            phix = phi.at<double>(p.y, p.x+1) - pcurr;
            phiy = (phi.at<double>(p.y+1, p.x) - phi.at<double>(p.y-1, p.x)) / 2;
            divr = (1/sqrt(h + pow(phix, 2) + pow(phiy, 2)));
            // ------------
            phix = pcurr - phi.at<double>(p.y, p.x-1);
            divl = (1/sqrt(h + pow(phix, 2) + pow(phiy, 2)));
            // ------------
            phix = (phi.at<double>(p.y, p.x+1) - phi.at<double>(p.y, p.x-1)) / 2;
            phiy = phi.at<double>(p.y+1, p.x) - pcurr;
            divd = (1/sqrt(h + pow(phix, 2) + pow(phiy, 2)));
            // ------------
            phiy = pcurr - phi.at<double>(p.y-1, p.x);
            divu = (1/sqrt(h + pow(phix, 2) + pow(phiy, 2)));
            // --------------------------------------

            double dist1 = pow(u0 - c1, 2);
            double dist2 = pow(u0 - c2, 2);

            double div = (1 + dt*delta*mu*(divr + divl + divd + divu));
            total_energy = (pcurr + dt*delta*(
                        mu*(phi.at<double>(p.y,p.x+1)*divr +
                            phi.at<double>(p.y,p.x-1)*divl +
                            phi.at<double>(p.y+1,p.x)*divd +
                            phi.at<double>(p.y-1,p.x)*divu)
                        - v*area - lambda1*dist1 + lambda2*dist2)) / div;

            phi_diff += abs(pcurr - total_energy);
            phi.at<double>(i, j) = total_energy;
        }
    }

    // normalize total difference in old vs new phi (describes the contour)
    phi_diff = phi_diff / (phi.rows * phi.cols);
    cout << "difference: " << phi_diff << endl;

    // TODO: optionally reinitialize phi

    return (phi_diff < threshold_tolerance);
}

void getContourMaskFromPhi(Mat phi, Mat& contourMask) {
    contourMask = Mat::zeros(phi.size(), CV_8UC1);
    vector<Point> contour = foreground<double>(phi);
    for (auto point: contour) {
        contourMask.at<uchar>(point.y, point.x) = 255;
    }
}

<commit_msg>cleanup chan vese<commit_after>#include "characterization.hpp"
#include "chan_vese_active_contour.hpp"

// 2001 Chan-Vese active contour implementation
//
// Chan, Tony F., and Luminita A. Vese.
//      "Active contours without edges."
//      IEEE Transactions on image processing 10.2 (2001): 266-277.
//

// assign checkerboard pattern from IPOL
void initializePhiCheckerboard(Mat& phi) {
    for ( int i = 0; i < phi.rows; ++i ) {
        for ( int j = 0; j < phi.cols; ++j ) {
            phi.at<double>(i, j) = sin(M_PI/5*i)*sin(M_PI/5*j);
        }
    }
}

// assign circle pattern
void initializePhiCircle(Mat& phi, int width, int height) {
    int w = floor(width/2) - 50;
    int h = floor(height/2) - 50;
    for ( int i = 0; i < phi.rows; ++i ) {
        for ( int j = 0; j < phi.cols; ++j ) {
            phi.at<double>(i, j) = -sqrt(pow(j-w-50, 2) + pow(i-h-50, 2)) + min(w, h);
        }
    }
}

double areaInsideContour(Mat phi) {
    return (double)foreground<double>(phi).size();
}

double regionAverage(Mat src, Mat phi, RegionType region) {
    assert (src.size() == phi.size());
    double total_intensity = 0.0;
    int area = 0;
    for (int row = 0; row < phi.rows; ++row) {
        for ( int col = 0; col < phi.cols; ++col ) {
            if ((region == INSIDE && phi.at<double>(row, col) >= 0) ||
                (region == OUTSIDE && phi.at<double>(row, col) < 0)) {
                ++area;
                total_intensity += src.at<uchar>(row, col);
            }
        }
    }
    return total_intensity / area;
}

double diracDelta (double phi_n, double dt) {
    // d/dt of H(phi) = 1/2*(1 + (2/PI)*arctan(phi))
    return dt / (M_PI*(pow(dt, 2) + pow(phi_n, 2)));
}

//
// Computes a single iteration of the Chan Vese active contour algorithm.
// Returns true if the contour converged, false otherwise.
//
bool activeContour(Mat src, Mat& phi) {

    double mu = 1.0;        // length weight
    double v = 0.5;         // area weight, typically 0 (nu)
    double lambda1 = 1.0;   // c1 weight (average intensity inside contour)
    double lambda2 = 1.0;   // c2 weight (average intensity outside contour)

    int h  = 1.0;                       // space step, where (i*h, j*h) are
                                        // the pixel locations
    double dt = 0.25;                   // artificial time step t >= 0
    double threshold_tolerance = 0.01;  // stopping condition

    double area = areaInsideContour(phi);
    double c1 = regionAverage(src, phi, INSIDE);  // pixel avg inside contour
    double c2 = regionAverage(src, phi, OUTSIDE); // pixel avg outside contour
    cout << "c1: " << c1 << " c2: " << c2 << endl;

    int u0 = 0;
    double phi_n, phi_n_plus_1 = 0.0;
    double delta = 0.0;
    double total_energy;
    Point p;

    double phi_diff = 0.0;
    // TODO: fix edge cases, currently not processing borders of image
    for (int i = 1; i < phi.rows-1; ++i) {
        for (int j = 1; j < phi.cols-1; ++j) {
            u0 = src.at<uchar>(i, j);           // current point intensity
            phi_n = phi.at<double>(i, j);        // current phi value
            delta = diracDelta(phi_n, dt);      // dirac delta
            p = Point(j, i);

            // Calculate curve energy
            // --------------------------------------
            double phix, phiy, divr, divl, divu, divd = 0.0;
            double pcurr = phi.at<double>(p.y, p.x);
            phix = phi.at<double>(p.y, p.x+1) - pcurr;
            phiy = (phi.at<double>(p.y+1, p.x) - phi.at<double>(p.y-1, p.x)) / 2;
            divr = (1/sqrt(h + pow(phix, 2) + pow(phiy, 2)));
            // ------------
            phix = pcurr - phi.at<double>(p.y, p.x-1);
            divl = (1/sqrt(h + pow(phix, 2) + pow(phiy, 2)));
            // ------------
            phix = (phi.at<double>(p.y, p.x+1) - phi.at<double>(p.y, p.x-1)) / 2;
            phiy = phi.at<double>(p.y+1, p.x) - pcurr;
            divd = (1/sqrt(h + pow(phix, 2) + pow(phiy, 2)));
            // ------------
            phiy = pcurr - phi.at<double>(p.y-1, p.x);
            divu = (1/sqrt(h + pow(phix, 2) + pow(phiy, 2)));
            // --------------------------------------

            double dist1 = pow(u0 - c1, 2);
            double dist2 = pow(u0 - c2, 2);

            double div = (1 + dt*delta*mu*(divr + divl + divd + divu));
            total_energy = (pcurr + dt*delta*(
                        mu*(phi.at<double>(p.y,p.x+1)*divr +
                            phi.at<double>(p.y,p.x-1)*divl +
                            phi.at<double>(p.y+1,p.x)*divd +
                            phi.at<double>(p.y-1,p.x)*divu)
                        - v*area - lambda1*dist1 + lambda2*dist2)) / div;

            phi_diff += abs(pcurr - total_energy);
            phi.at<double>(i, j) = total_energy;
        }
    }

    // normalize total difference in old vs new phi (describes the contour)
    phi_diff = phi_diff / (phi.rows * phi.cols);
    cout << "difference: " << phi_diff << endl;

    // TODO: optionally reinitialize phi

    return (phi_diff < threshold_tolerance);
}

void getContourMaskFromPhi(Mat phi, Mat& contourMask) {
    contourMask = Mat::zeros(phi.size(), CV_8UC1);
    vector<Point> contour = foreground<double>(phi);
    for (auto point: contour) {
        contourMask.at<uchar>(point.y, point.x) = 255;
    }
}

<|endoftext|>


<commit_before>/***************************************************************************
                          kopete.cpp  -  description
                             -------------------
    begin                : Wed Dec 26 03:12:10 CLST 2001
    copyright            : (C) 2001 by Duncan Mac-Vicar Prett
    email                : duncan@puc.cl
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <qvaluelist.h>
#include <qlist.h>
#include <qlayout.h>

#include <kconfig.h>
#include <kdebug.h>
#include <kcrash.h>
#include <kglobal.h>
#include <kiconloader.h>

#include <kopete.h>
#include <preferencesdialog.h>
#include <kopetewindow.h>
#include "plugin.h"
#include "pluginloader.h"
#include "pluginmodule.h"
#include <addwizardimpl.h>
#include "systemtray.h"

class Plugins;

Kopete::Kopete(): KUniqueApplication(true, true, true)
{
	//plugins = new PluginManager;
	allConnected = false;

	mLibraryLoader = new LibraryLoader;
	mIconLoader = KGlobal::iconLoader();
	mPref=new PreferencesDialog;
	Plugins *blah = new Plugins(this);

	mainwindow = new KopeteWindow;
	setMainWidget(mainwindow);
	mainwindow->statusBar()->show();

  	mPref->hide();

	KConfig *config=KGlobal::config();
	config->setGroup("");
	/* Ups! the user dont have plugins selected. */
	if (!config->hasKey("Modules"))
	{
		QStringList modules;
		modules.append("icq.plugin");
		modules.append("msn.plugin");
		config->writeEntry("Modules", modules);
	}
	tray = new KopeteSystemTray();
	/* Ok, load saved plugins */
	loadPlugins();
}

Kopete::~Kopete()
{
	delete mPref;
	delete mLibraryLoader;
	delete mainwindow;

	// Only use this if cant find crash cause :-)
	//KCrash::setCrashHandler(Kopete::cleverKCrashHack);
}
void Kopete::slotPreferences()
{
  mPref->show();
  mPref->raise();
}
/** No descriptions */
void Kopete::slotExit()
{
	quit();
}

KopeteSystemTray *Kopete::systemTray()
{
	return tray;
}

/** No descriptions */
void Kopete::readOptions()
{
	/*
  KConfig *config = KGlobal::config();
  config->setGroup("General");
	visible = config->readBoolEntry("Visible",true);
	QSize size          = config->readSizeEntry("Geometry");
  config->readBoolEntry("Idle Detection",false);
  config->readNumEntry("MaxIdle",15);

  if(!size.isEmpty())
  {
    resize(size);
  }
  QPoint pos=config->readPointEntry("Position");
  if(!pos.isNull())
  {
    move(pos);
  }
  config->setGroup("ICQ");
  QString icqNick = config->readEntry( "icqNick" );
  QString icqUIN = config->readEntry( "icqUIN" );
	QString icqPass = config->readEntry( "icqPass" );
	config->setGroup("MSN");
  QString msnNick = config->readEntry( "msnNick" );
  QString msnID = config->readEntry( "msnID" );
	QString msnPass = config->readEntry( "msnPass" );

	autoConnect=-1;
  if ( profiles.count() == 0 )
    slotSettings();
  else
  {
    //Construct menu...
    for ( int i = 0 ; i < profiles.count() ; i++ )
    {
      KAction *tmpaction = new KMsnAction( profiles[i] , //Name
                                        0           , //Accel
                                        this        , //Receiver
                                        SLOT(slotConnector( int ) ),
                                        actionCollection(),//Parent (not sure...)
                                        profiles[i] , //Internal name
                                        i );          //ID, needed for connecting
      //Add actions to the submenu
      fileConnector->insert( tmpaction );
      //And add them to our list...
      actions.append( tmpaction );
      //.. and make sure that they're deleted when we delete them
      actions.setAutoDelete( true );

      if (autoStr == profiles[i])
	autoConnect=i;
    }
  }

*/
}
/** No descriptions */
void Kopete::saveOptions(){
}

/** Connect to all loaded protocol plugins */
void Kopete::slotConnectAll()
{
	QValueList<KopeteLibraryInfo> l = kopeteapp->libraryLoader()->loaded();
    for (QValueList<KopeteLibraryInfo>::Iterator i = l.begin(); i != l.end(); ++i)
	{
		kdDebug() << "Kopete: [Connect All]: "<<(*i).name <<"\n";
		Plugin *tmpprot = (kopeteapp->libraryLoader())->mLibHash[(*i).specfile]->plugin;
		IMProtocol *prot =  static_cast<IMProtocol*>(tmpprot);
		if ( !(prot->isConnected()))
		{
			prot->Connect();
		}
	}
	allConnected = true;
	mainWindow()->actionConnect->setEnabled(false);
    mainWindow()->actionDisconnect->setEnabled(true);
}

/** Connect to all loaded protocol plugins */
void Kopete::slotDisconnectAll()
{
	QValueList<KopeteLibraryInfo> l = kopeteapp->libraryLoader()->loaded();
    for (QValueList<KopeteLibraryInfo>::Iterator i = l.begin(); i != l.end(); ++i)
	{
		kdDebug() << "Kopete: [Disconnect All]: "<<(*i).name <<"\n";
		Plugin *tmpprot = (kopeteapp->libraryLoader())->mLibHash[(*i).specfile]->plugin;
		IMProtocol *prot =  static_cast<IMProtocol*>(tmpprot);
		if (prot->isConnected())
		{
			prot->Disconnect();
		}
	}
	allConnected = false;
	mainWindow()->actionConnect->setEnabled(true);
    mainWindow()->actionDisconnect->setEnabled(false);
}

/** No descriptions */
void Kopete::slotAboutPlugins()
{
	AboutPlugins *aboutPl;
	aboutPl = new AboutPlugins(mainwindow);
	aboutPl->show();

}
/** Add a contact through Wizard */
void Kopete::slotAddContact()
{
	AddWizardImpl *tmpdialog = new AddWizardImpl(this->mainWindow());
	tmpdialog->show();
}

/** No descriptions */
void Kopete::slotSetAway()
{
}/** No descriptions */
void Kopete::initPlugins()
{

}
/** No descriptions */
void Kopete::loadPlugins()
{
	mLibraryLoader->loadAll();
}

void Kopete::cleverKCrashHack(int)
{
	// do nothing

	// Understand that the KDE libraries have a memory leak, and
	// the playlist cannot be unloaded without causing a crash
	// in QApplication::windowMapper() or something similar.
	// this is just to prevent the KCrash window from appearing
	// and bugging the user regularly

	// someone fix the libraries.
	kdDebug() << "Crashed.\n" << endl;
	_exit(255);
}
/** No descriptions */
KStatusBar *Kopete::statusBar()
{
	return mainwindow->statusBar();
}
/** No descriptions */
ContactList *Kopete::contactList()
{
	return mainwindow->contactlist;

}
<commit_msg>- More functions to the systray<commit_after>/***************************************************************************
                          kopete.cpp  -  description
                             -------------------
    begin                : Wed Dec 26 03:12:10 CLST 2001
    copyright            : (C) 2001 by Duncan Mac-Vicar Prett
    email                : duncan@puc.cl
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <qvaluelist.h>
#include <qlist.h>
#include <qlayout.h>

#include <kconfig.h>
#include <kdebug.h>
#include <kcrash.h>
#include <kglobal.h>
#include <kiconloader.h>

#include <kopete.h>
#include <preferencesdialog.h>
#include <kopetewindow.h>
#include "plugin.h"
#include "pluginloader.h"
#include "pluginmodule.h"
#include <addwizardimpl.h>
#include "systemtray.h"

class Plugins;

Kopete::Kopete(): KUniqueApplication(true, true, true)
{
	//plugins = new PluginManager;
	allConnected = false;

	mLibraryLoader = new LibraryLoader;
	mIconLoader = KGlobal::iconLoader();
	mPref=new PreferencesDialog;
	Plugins *blah = new Plugins(this);

	mainwindow = new KopeteWindow;
	setMainWidget(mainwindow);
	mainwindow->statusBar()->show();
  	mPref->hide();

	KConfig *config=KGlobal::config();
	config->setGroup("");
	/* Ups! the user dont have plugins selected. */
	if (!config->hasKey("Modules"))
	{
		QStringList modules;
		modules.append("icq.plugin");
		modules.append("msn.plugin");
		config->writeEntry("Modules", modules);
	}
	tray = new KopeteSystemTray();
	tray->getContextMenu()->insertSeparator();
	mainwindow->actionAddContact->plug( tray->getContextMenu() );
	tray->getContextMenu()->insertSeparator();
	mainwindow->actionConnect->plug( tray->getContextMenu() );
	mainwindow->actionDisconnect->plug( tray->getContextMenu() );
  	mainwindow->actionPrefs->plug( tray->getContextMenu() );
	tray->getContextMenu()->insertSeparator();
	/* Ok, load saved plugins */
	loadPlugins();
}

Kopete::~Kopete()
{
	delete mPref;
	delete mLibraryLoader;
	delete mainwindow;

	// Only use this if cant find crash cause :-)
	//KCrash::setCrashHandler(Kopete::cleverKCrashHack);
}
void Kopete::slotPreferences()
{
  mPref->show();
  mPref->raise();
}
/** No descriptions */
void Kopete::slotExit()
{
	quit();
}

KopeteSystemTray *Kopete::systemTray()
{
	return tray;
}

/** No descriptions */
void Kopete::readOptions()
{
	/*
  KConfig *config = KGlobal::config();
  config->setGroup("General");
	visible = config->readBoolEntry("Visible",true);
	QSize size          = config->readSizeEntry("Geometry");
  config->readBoolEntry("Idle Detection",false);
  config->readNumEntry("MaxIdle",15);

  if(!size.isEmpty())
  {
    resize(size);
  }
  QPoint pos=config->readPointEntry("Position");
  if(!pos.isNull())
  {
    move(pos);
  }
  config->setGroup("ICQ");
  QString icqNick = config->readEntry( "icqNick" );
  QString icqUIN = config->readEntry( "icqUIN" );
	QString icqPass = config->readEntry( "icqPass" );
	config->setGroup("MSN");
  QString msnNick = config->readEntry( "msnNick" );
  QString msnID = config->readEntry( "msnID" );
	QString msnPass = config->readEntry( "msnPass" );

	autoConnect=-1;
  if ( profiles.count() == 0 )
    slotSettings();
  else
  {
    //Construct menu...
    for ( int i = 0 ; i < profiles.count() ; i++ )
    {
      KAction *tmpaction = new KMsnAction( profiles[i] , //Name
                                        0           , //Accel
                                        this        , //Receiver
                                        SLOT(slotConnector( int ) ),
                                        actionCollection(),//Parent (not sure...)
                                        profiles[i] , //Internal name
                                        i );          //ID, needed for connecting
      //Add actions to the submenu
      fileConnector->insert( tmpaction );
      //And add them to our list...
      actions.append( tmpaction );
      //.. and make sure that they're deleted when we delete them
      actions.setAutoDelete( true );

      if (autoStr == profiles[i])
	autoConnect=i;
    }
  }

*/
}
/** No descriptions */
void Kopete::saveOptions(){
}

/** Connect to all loaded protocol plugins */
void Kopete::slotConnectAll()
{
	QValueList<KopeteLibraryInfo> l = kopeteapp->libraryLoader()->loaded();
    for (QValueList<KopeteLibraryInfo>::Iterator i = l.begin(); i != l.end(); ++i)
	{
		kdDebug() << "Kopete: [Connect All]: "<<(*i).name <<"\n";
		Plugin *tmpprot = (kopeteapp->libraryLoader())->mLibHash[(*i).specfile]->plugin;
		IMProtocol *prot =  static_cast<IMProtocol*>(tmpprot);
		if ( !(prot->isConnected()))
		{
			prot->Connect();
		}
	}
	allConnected = true;
	mainWindow()->actionConnect->setEnabled(false);
    mainWindow()->actionDisconnect->setEnabled(true);
}

/** Connect to all loaded protocol plugins */
void Kopete::slotDisconnectAll()
{
	QValueList<KopeteLibraryInfo> l = kopeteapp->libraryLoader()->loaded();
    for (QValueList<KopeteLibraryInfo>::Iterator i = l.begin(); i != l.end(); ++i)
	{
		kdDebug() << "Kopete: [Disconnect All]: "<<(*i).name <<"\n";
		Plugin *tmpprot = (kopeteapp->libraryLoader())->mLibHash[(*i).specfile]->plugin;
		IMProtocol *prot =  static_cast<IMProtocol*>(tmpprot);
		if (prot->isConnected())
		{
			prot->Disconnect();
		}
	}
	allConnected = false;
	mainWindow()->actionConnect->setEnabled(true);
    mainWindow()->actionDisconnect->setEnabled(false);
}

/** No descriptions */
void Kopete::slotAboutPlugins()
{
	AboutPlugins *aboutPl;
	aboutPl = new AboutPlugins(mainwindow);
	aboutPl->show();

}
/** Add a contact through Wizard */
void Kopete::slotAddContact()
{
	AddWizardImpl *tmpdialog = new AddWizardImpl(this->mainWindow());
	tmpdialog->show();
}

/** No descriptions */
void Kopete::slotSetAway()
{
}/** No descriptions */
void Kopete::initPlugins()
{

}
/** No descriptions */
void Kopete::loadPlugins()
{
	mLibraryLoader->loadAll();
}

void Kopete::cleverKCrashHack(int)
{
	// do nothing

	// Understand that the KDE libraries have a memory leak, and
	// the playlist cannot be unloaded without causing a crash
	// in QApplication::windowMapper() or something similar.
	// this is just to prevent the KCrash window from appearing
	// and bugging the user regularly

	// someone fix the libraries.
	kdDebug() << "Crashed.\n" << endl;
	_exit(255);
}
/** No descriptions */
KStatusBar *Kopete::statusBar()
{
	return mainwindow->statusBar();
}
/** No descriptions */
ContactList *Kopete::contactList()
{
	return mainwindow->contactlist;

}
<|endoftext|>


<commit_before>#include "ksp/principia.hpp"

#include <map>
#include <string>
#include <vector>

#include "geometry/grassmann.hpp"
#include "geometry/permutation.hpp"
#include "geometry/rotation.hpp"
#include "ksp/utilities.hpp"
#include "physics/body.hpp"
#include "physics/n_body_system.hpp"
#include "quantities/quantities.hpp"
#include "quantities/named_quantities.hpp"

using principia::geometry::DebugString;
using principia::geometry::Permutation;
using principia::geometry::Quaternion;
using principia::geometry::Rotation;
using principia::geometry::Vector;
using principia::physics::Body;
using principia::physics::NBodySystem;
using principia::quantities::GravitationalParameter;
using principia::quantities::Length;
using principia::quantities::SIUnit;
using principia::quantities::DebugString;
using principia::si::Hour;
using principia::si::Second;

#define LOG_UNITY(message) UnityEngine::Debug::Log(                            \
    gcnew System::String(                                                      \
        (std::string(__FILE__) + ":" + std::to_string(__LINE__) + ", in " +    \
         __FUNCSIG__ + "]" + (message)).c_str()));

namespace principia {
namespace ksp {

Principia::~Principia() {
  FreeAllOwnedPointers();
}

Principia::!Principia() {
  FreeAllOwnedPointers();
}

void Principia::Start() {
  gui_style = gcnew UnityEngine::GUIStyle(UnityEngine::GUI::skin->button);

  gui_style->normal->textColor    = UnityEngine::Color::white;
  gui_style->focused->textColor   = UnityEngine::Color::white;
  gui_style->hover->textColor     = UnityEngine::Color::yellow;
  gui_style->active->textColor    = UnityEngine::Color::yellow;
  gui_style->onNormal->textColor  = UnityEngine::Color::green;
  gui_style->onFocused->textColor = UnityEngine::Color::green;
  gui_style->onHover->textColor   = UnityEngine::Color::green;
  gui_style->onActive->textColor  = UnityEngine::Color::green;
  gui_style->padding              = gcnew UnityEngine::RectOffset(8, 8, 8, 8);

  RenderingManager::AddToPostDrawQueue(
      3,                                           // queueSpot
      gcnew Callback(this, &Principia::DrawGUI));  // drawFunction
  main_window_position_ = UnityEngine::Rect(
      UnityEngine::Screen::width / 2.0f,   // left
      UnityEngine::Screen::height / 2.0f,  // top
      10.0f,                               // width
      10.0f);                              // height
  reference_frame_window_position_ = UnityEngine::Rect(
      UnityEngine::Screen::width / 3.0f,   // left
      UnityEngine::Screen::height / 3.0f,  // top
      10.0f,                               // width
      10.0f);                              // height
  integrator_->Initialize(integrator_->Order5Optimal());
  rendering::MapRenderer::CreateAndAttach(
    gcnew rendering::RenderingFunction(this, &Principia::DrawTrajectories));
}

void Principia::FixedUpdate() {
  if (simulating_) {
    if (system_->bodies().front()->times().back() - UniversalTime() >
            *Δt_ * sampling_period_) {
      system_->Integrate(*integrator_, UniversalTime(), *Δt_, sampling_period_);
    }
  }
}

void Principia::OnDestroy() {
  FreeAllOwnedPointers();
}

void Principia::DrawGUI() {
  UnityEngine::GUI::skin = HighLogic::Skin;
  main_window_position_ = UnityEngine::GUILayout::Window(
      1,  // id
      main_window_position_,
      gcnew UnityEngine::GUI::WindowFunction(this, &Principia::DrawMainWindow),
      "Traces of Various Descriptions",
      UnityEngine::GUILayout::MinWidth(500));
  if (simulating_) {
    reference_frame_window_position_ = UnityEngine::GUILayout::Window(
        2,  // id
        reference_frame_window_position_,
        gcnew UnityEngine::GUI::WindowFunction(
            this,
            &Principia::DrawReferenceFrameWindow),
        "Reference Frame",
        UnityEngine::GUILayout::MinWidth(500));
  }
}

void Principia::DrawMainWindow(int window_id) {
  UnityEngine::GUILayout::BeginVertical();

  if (UnityEngine::GUILayout::Button(
          simulating_ ? "Switch to Keplerian" : "Switch to Newtonian"),
          gui_style,
          UnityEngine::GUILayout::ExpandWidth(true)) {
    simulating_ = !simulating_;
    if (simulating_) {
      SetUpSystem();
    }
  }

  UnityEngine::GUILayout::BeginHorizontal();
  UnityEngine::GUILayout::Label("prediction_length_ =");
  System::String^ prediction_length_string = UnityEngine::GUILayout::TextArea(
      (*prediction_length_ / Hour).ToString(),  // text
      UnityEngine::GUILayout::Width(250));      // options
  double prediction_length_hours;
  if (System::Double::TryParse(prediction_length_string,
                               prediction_length_hours)) {
    *prediction_length_ = prediction_length_hours * Hour;
  }
  UnityEngine::GUILayout::Label("h");
  UnityEngine::GUILayout::EndHorizontal();

  UnityEngine::GUILayout::BeginHorizontal();
  UnityEngine::GUILayout::Label(L"Δt_ =");
  System::String^ timestep_string = UnityEngine::GUILayout::TextArea(
      (*Δt_ / Second).ToString(),           // text
      UnityEngine::GUILayout::Width(250));  // options
  double timestep_seconds;
  if (System::Double::TryParse(timestep_string, timestep_seconds)) {
    *Δt_ = timestep_seconds * Second;
  }
  UnityEngine::GUILayout::Label("s");
  UnityEngine::GUILayout::EndHorizontal();

  UnityEngine::GUILayout::BeginHorizontal();
  UnityEngine::GUILayout::Label("sampling_period_ =");
  System::String^ sampling_period_string = UnityEngine::GUILayout::TextArea(
      sampling_period_.ToString(),          // text
      UnityEngine::GUILayout::Width(250));  // options
  int new_sampling_period;
  if (System::Int32::TryParse(sampling_period_string, new_sampling_period)) {
    sampling_period_ = new_sampling_period;
  }
  UnityEngine::GUILayout::EndHorizontal();

  UnityEngine::GUILayout::EndVertical();
  UnityEngine::GUI::DragWindow(UnityEngine::Rect(0.0f, 0.0f, 10000.0f, 20.0f));
}

// Layout:
// o Sun        o Surface
// o Planet 1   o Centric
// o Planet 2   o Barycentric rotating
// o Planet 3
// ...
void Principia::DrawReferenceFrameWindow(int window_id) {
  UnityEngine::GUILayout::BeginHorizontal();
  UnityEngine::GUILayout::BeginVertical(UnityEngine::GUILayout::Width(250));
  for each (CelestialBody^ body in FlightGlobals::Bodies) {
    if (UnityEngine::GUILayout::Toggle(
            rendering_reference_body_ == body,  // value
            body->name) &&                     // text
        rendering_reference_body_ != body) {
      rendering_reference_body_ = body;
    }
  }
  UnityEngine::GUILayout::EndVertical();
  UnityEngine::GUILayout::BeginVertical(
      UnityEngine::GUILayout::ExpandWidth(true));
  for (auto const& type : kRenderingFrameTypes) {
    // Do not show the barycentric option for the sun, since the sun has no
    // primary.
    if ((rendering_reference_body_ != sun_ || type != kBarycentric) &&
        UnityEngine::GUILayout::Toggle(
            rendering_frame_type_ == type,        // value
            Manage(kFrameTypeNames.at(type))) &&  // text
        rendering_frame_type_ != type) {
      rendering_frame_type_ = type;
    }
  }
  UnityEngine::GUILayout::EndVertical();
  UnityEngine::GUILayout::EndHorizontal();
  UnityEngine::GUI::DragWindow(UnityEngine::Rect(0.0f, 0.0f, 10000.0f, 20.0f));
}

void Principia::DrawTrajectories(float camera_distance) {
  if (MapView::MapIsEnabled && simulating_) {
    Time const universal_time = UniversalTime();
    for each (Vessel^ ksp_vessel in FlightGlobals::Vessels) {
      std::string id = Unmanage(ksp_vessel->id.ToString());
      if (vessels_->count(id)) {
        Body<IntegrationFrame>* vessel    = vessels_->at(id);
        Body<IntegrationFrame>* reference =
            celestials_->at(Unmanage(rendering_reference_body_->name);
        UnityEngine::LineRenderer^ line_;
//        if (rendering_frame_type_)
      }
    }
  }
}

Displacement<IntegrationFrame> IntegrationPosition(CelestialBody^ const body);
VelocityChange<IntegrationFrame> IntegrationVelocity(CelestialBody^ const body);

Displacement<IntegrationFrame> IntegrationPosition(Vessel^ const body);
VelocityChange<IntegrationFrame> IntegrationVelocity(Vessel^ const body);

void Principia::SetUpSystem() {
  *celestials_ = std::map<std::string, Body<IntegrationFrame>*>();
  *vessels_    = std::map<std::string, Body<IntegrationFrame>*>();
  Time const universal_time = UniversalTime();
  std::vector<Body<IntegrationFrame>*>* const bodies =
      new std::vector<Body<IntegrationFrame>*>;
  sun_ = FlightGlobals::Bodies[0];
  rendering_reference_body_ = sun_;
  for each (CelestialBody^ body in FlightGlobals::Bodies) {
    GravitationalParameter const gravitational_parameter =
        body->gravParameter * SIUnit<GravitationalParameter>();
    bodies->push_back(new Body<IntegrationFrame>(gravitational_parameter));
    Displacement<IntegrationFrame> const   position =
      IntegrationPosition(body) - IntegrationPosition(sun_);
    VelocityChange<IntegrationFrame> const velocity =
      IntegrationVelocity(body) - IntegrationVelocity(sun_);
    bodies->back()->AppendToTrajectory({position}, {velocity}, universal_time);
    celestials_->insert({Unmanage(body->name),
                         bodies->back()});
    LOG_UNITY(std::string("\nAdded CelestialBody ") + Unmanage(body->name) +
              "\nGM = " + DebugString(gravitational_parameter) +
              "\nq  = " + DebugString(position) +
              "\nv  = " + DebugString(velocity));
  }
  for each (Vessel^ body in FlightGlobals::Vessels) {
    bodies->push_back(new Body<IntegrationFrame>(GravitationalParameter()));
    Displacement<IntegrationFrame> const   position =
        IntegrationPosition(body) - IntegrationPosition(sun_);
    VelocityChange<IntegrationFrame> const velocity =
        IntegrationVelocity(body) - IntegrationVelocity(sun_);
    bodies->back()->AppendToTrajectory({position}, {velocity}, universal_time);
    vessels_->insert({Unmanage(body->id.ToString()), bodies->back()});
    LOG_UNITY(std::string("\nAdded Vessel ") + Unmanage(body->name) +
              "\nq  = " + DebugString(position) +
              "\nv  = " + DebugString(velocity));
  }
  Reset(system_, new NBodySystem<IntegrationFrame>(bodies));
}

void Principia::FreeAllOwnedPointers() {
  Reset(prediction_length_, nullptr);
  Reset(Δt_, nullptr);
  Reset(system_, nullptr);
  Reset(celestials_, nullptr);
  Reset(vessels_, nullptr);
}

struct World;
struct AliceWorld;

Permutation<AliceWorld, World> const LookingGlass =
    Permutation<AliceWorld, World>(Permutation<AliceWorld, World>::XZY);

Rotation<IntegrationFrame, World> PlanetariumRotation() {
  UnityEngine::QuaternionD planetarium_rotation = Planetarium::Rotation;
  return Rotation<IntegrationFrame, World>(
      Quaternion(planetarium_rotation.w,
                 {planetarium_rotation.x,
                  planetarium_rotation.y,
                  planetarium_rotation.z}));
}

Displacement<World> WorldPosition(CelestialBody^ const body) {
  Vector3d const position = body->position;
  return Displacement<World>({
      position.x * SIUnit<Length>(),
      position.y * SIUnit<Length>(),
      position.z * SIUnit<Length>()});
}

Displacement<IntegrationFrame> IntegrationPosition(CelestialBody^ const body) {
  return PlanetariumRotation().Inverse()(WorldPosition(body));
}

VelocityChange<World> WorldVelocity(CelestialBody^ const body) {
  Vector3d const frame_velocity = body->GetFrameVel();
  return VelocityChange<World>({
      frame_velocity.x * SIUnit<Speed>(),
      frame_velocity.y * SIUnit<Speed>(),
      frame_velocity.z * SIUnit<Speed>()});
}

VelocityChange<IntegrationFrame> IntegrationVelocity(
    CelestialBody^ const body) {
  return PlanetariumRotation().Inverse()(WorldVelocity(body));
}

Displacement<AliceWorld> OffsetFromReferenceBody(Vessel^ const body) {
  Vector3d const result = body->orbitDriver->pos;
    return Displacement<AliceWorld>({
      result.x * SIUnit<Length>(),
      result.y * SIUnit<Length>(),
      result.z * SIUnit<Length>()});
}

Displacement<World> WorldPosition(Vessel^ const body) {
  return WorldPosition(body->orbitDriver->orbit->referenceBody) +
      LookingGlass(OffsetFromReferenceBody(body));
}

Displacement<IntegrationFrame> IntegrationPosition(Vessel^ const body) {
  return PlanetariumRotation().Inverse()(WorldPosition(body));
}

VelocityChange<World> WorldVelocity(Vessel^ const body) {
  Vector3d const frame_velocity = body->orbitDriver->orbit->GetFrameVel();
  return VelocityChange<World>({
      frame_velocity.x * SIUnit<Speed>(),
      frame_velocity.y * SIUnit<Speed>(),
      frame_velocity.z * SIUnit<Speed>()});
}

VelocityChange<IntegrationFrame> IntegrationVelocity(Vessel^ const body) {
  return PlanetariumRotation().Inverse()(WorldVelocity(body));
}

}  // namespace ksp
}  // namespace principia
<commit_msg>gargle_blaster<commit_after>#include "ksp/principia.hpp"

#include <map>
#include <string>
#include <vector>

#include "geometry/grassmann.hpp"
#include "geometry/permutation.hpp"
#include "geometry/rotation.hpp"
#include "ksp/utilities.hpp"
#include "physics/body.hpp"
#include "physics/n_body_system.hpp"
#include "quantities/quantities.hpp"
#include "quantities/named_quantities.hpp"

using principia::geometry::DebugString;
using principia::geometry::Permutation;
using principia::geometry::Quaternion;
using principia::geometry::Rotation;
using principia::geometry::Vector;
using principia::physics::Body;
using principia::physics::NBodySystem;
using principia::quantities::GravitationalParameter;
using principia::quantities::Length;
using principia::quantities::SIUnit;
using principia::quantities::DebugString;
using principia::si::Hour;
using principia::si::Second;

#define LOG_UNITY(message) UnityEngine::Debug::Log(                            \
    gcnew System::String(                                                      \
        (std::string(__FILE__) + ":" + std::to_string(__LINE__) + ", in " +    \
         __FUNCSIG__ + "]" + (message)).c_str()));

namespace principia {
namespace ksp {

Principia::~Principia() {
  FreeAllOwnedPointers();
}

Principia::!Principia() {
  FreeAllOwnedPointers();
}

void Principia::Start() {
  gui_style = gcnew UnityEngine::GUIStyle(UnityEngine::GUI::skin->button);

  gui_style->normal->textColor    = UnityEngine::Color::white;
  gui_style->focused->textColor   = UnityEngine::Color::white;
  gui_style->hover->textColor     = UnityEngine::Color::yellow;
  gui_style->active->textColor    = UnityEngine::Color::yellow;
  gui_style->onNormal->textColor  = UnityEngine::Color::green;
  gui_style->onFocused->textColor = UnityEngine::Color::green;
  gui_style->onHover->textColor   = UnityEngine::Color::green;
  gui_style->onActive->textColor  = UnityEngine::Color::green;
  gui_style->padding              = gcnew UnityEngine::RectOffset(8, 8, 8, 8);

  RenderingManager::AddToPostDrawQueue(
      3,                                           // queueSpot
      gcnew Callback(this, &Principia::DrawGUI));  // drawFunction
  main_window_position_ = UnityEngine::Rect(
      UnityEngine::Screen::width / 2.0f,   // left
      UnityEngine::Screen::height / 2.0f,  // top
      10.0f,                               // width
      10.0f);                              // height
  reference_frame_window_position_ = UnityEngine::Rect(
      UnityEngine::Screen::width / 3.0f,   // left
      UnityEngine::Screen::height / 3.0f,  // top
      10.0f,                               // width
      10.0f);                              // height
  integrator_->Initialize(integrator_->Order5Optimal());
  rendering::MapRenderer::CreateAndAttach(
    gcnew rendering::RenderingFunction(this, &Principia::DrawTrajectories));
}

void Principia::FixedUpdate() {
  if (simulating_) {
    if (system_->bodies().front()->times().back() - UniversalTime() >
            *Δt_ * sampling_period_) {
      system_->Integrate(*integrator_, UniversalTime(), *Δt_, sampling_period_);
    }
  }
}

void Principia::OnDestroy() {
  FreeAllOwnedPointers();
}

void Principia::DrawGUI() {
  UnityEngine::GUI::skin = HighLogic::Skin;
  main_window_position_ = UnityEngine::GUILayout::Window(
      1,  // id
      main_window_position_,
      gcnew UnityEngine::GUI::WindowFunction(this, &Principia::DrawMainWindow),
      "Traces of Various Descriptions",
      UnityEngine::GUILayout::MinWidth(500));
  if (simulating_) {
    reference_frame_window_position_ = UnityEngine::GUILayout::Window(
        2,  // id
        reference_frame_window_position_,
        gcnew UnityEngine::GUI::WindowFunction(
            this,
            &Principia::DrawReferenceFrameWindow),
        "Reference Frame",
        UnityEngine::GUILayout::MinWidth(500));
  }
}

void Principia::DrawMainWindow(int window_id) {
  UnityEngine::GUILayout::BeginVertical();

  if (UnityEngine::GUILayout::Button(
          simulating_ ? "Switch to Keplerian" : "Switch to Newtonian"),
          gui_style,
          UnityEngine::GUILayout::ExpandWidth(true)) {
    simulating_ = !simulating_;
    if (simulating_) {
      SetUpSystem();
    }
  }

  UnityEngine::GUILayout::BeginHorizontal();
  UnityEngine::GUILayout::Label("prediction_length_ =");
  System::String^ prediction_length_string = UnityEngine::GUILayout::TextArea(
      (*prediction_length_ / Hour).ToString(),  // text
      UnityEngine::GUILayout::Width(250));      // options
  double prediction_length_hours;
  if (System::Double::TryParse(prediction_length_string,
                               prediction_length_hours)) {
    *prediction_length_ = prediction_length_hours * Hour;
  }
  UnityEngine::GUILayout::Label("h");
  UnityEngine::GUILayout::EndHorizontal();

  UnityEngine::GUILayout::BeginHorizontal();
  UnityEngine::GUILayout::Label(L"Δt_ =");
  System::String^ timestep_string = UnityEngine::GUILayout::TextArea(
      (*Δt_ / Second).ToString(),           // text
      UnityEngine::GUILayout::Width(250));  // options
  double timestep_seconds;
  if (System::Double::TryParse(timestep_string, timestep_seconds)) {
    *Δt_ = timestep_seconds * Second;
  }
  UnityEngine::GUILayout::Label("s");
  UnityEngine::GUILayout::EndHorizontal();

  UnityEngine::GUILayout::BeginHorizontal();
  UnityEngine::GUILayout::Label("sampling_period_ =");
  System::String^ sampling_period_string = UnityEngine::GUILayout::TextArea(
      sampling_period_.ToString(),          // text
      UnityEngine::GUILayout::Width(250));  // options
  int new_sampling_period;
  if (System::Int32::TryParse(sampling_period_string, new_sampling_period)) {
    sampling_period_ = new_sampling_period;
  }
  UnityEngine::GUILayout::EndHorizontal();

  UnityEngine::GUILayout::EndVertical();
  UnityEngine::GUI::DragWindow(UnityEngine::Rect(0.0f, 0.0f, 10000.0f, 20.0f));
}

// Layout:
// o Sun        o Surface
// o Planet 1   o Centric
// o Planet 2   o Barycentric rotating
// o Planet 3
// ...
void Principia::DrawReferenceFrameWindow(int window_id) {
  UnityEngine::GUILayout::BeginHorizontal();
  UnityEngine::GUILayout::BeginVertical(UnityEngine::GUILayout::Width(250));
  for each (CelestialBody^ body in FlightGlobals::Bodies) {
    if (UnityEngine::GUILayout::Toggle(
            rendering_reference_body_ == body,  // value
            body->name) &&                     // text
        rendering_reference_body_ != body) {
      rendering_reference_body_ = body;
    }
  }
  UnityEngine::GUILayout::EndVertical();
  UnityEngine::GUILayout::BeginVertical(
      UnityEngine::GUILayout::ExpandWidth(true));
  for (auto const& type : kRenderingFrameTypes) {
    // Do not show the barycentric option for the sun, since the sun has no
    // primary.
    if ((rendering_reference_body_ != sun_ || type != kBarycentric) &&
        UnityEngine::GUILayout::Toggle(
            rendering_frame_type_ == type,        // value
            Manage(kFrameTypeNames.at(type))) &&  // text
        rendering_frame_type_ != type) {
      rendering_frame_type_ = type;
    }
  }
  UnityEngine::GUILayout::EndVertical();
  UnityEngine::GUILayout::EndHorizontal();
  UnityEngine::GUI::DragWindow(UnityEngine::Rect(0.0f, 0.0f, 10000.0f, 20.0f));
}

void Principia::DrawTrajectories(float camera_distance) {
  if (MapView::MapIsEnabled && simulating_) {
    Time const universal_time = UniversalTime();
    for each (Vessel^ ksp_vessel in FlightGlobals::Vessels) {
      std::string id = Unmanage(ksp_vessel->id.ToString());
      if (vessels_->count(id)) {
        Body<IntegrationFrame>* vessel    = vessels_->at(id);
        Body<IntegrationFrame>* reference =
            celestials_->at(Unmanage(rendering_reference_body_->name));
        UnityEngine::LineRenderer^ line_;
        for (std::size_t i = 0; i < vessel->positions().size(); ++i) {
          Displacement<RenderingFrame> offset_from_reference_body;
          switch (rendering_frame_type_) {
            case kSurface:
              break;
            case kCentric:
              break;
            case kBarycentric:
              break;
          }
        }
      }
    }
  }
}

Displacement<IntegrationFrame> IntegrationPosition(CelestialBody^ const body);
VelocityChange<IntegrationFrame> IntegrationVelocity(CelestialBody^ const body);

Displacement<IntegrationFrame> IntegrationPosition(Vessel^ const body);
VelocityChange<IntegrationFrame> IntegrationVelocity(Vessel^ const body);

void Principia::SetUpSystem() {
  *celestials_ = std::map<std::string, Body<IntegrationFrame>*>();
  *vessels_    = std::map<std::string, Body<IntegrationFrame>*>();
  Time const universal_time = UniversalTime();
  std::vector<Body<IntegrationFrame>*>* const bodies =
      new std::vector<Body<IntegrationFrame>*>;
  sun_ = FlightGlobals::Bodies[0];
  rendering_reference_body_ = sun_;
  for each (CelestialBody^ body in FlightGlobals::Bodies) {
    GravitationalParameter const gravitational_parameter =
        body->gravParameter * SIUnit<GravitationalParameter>();
    bodies->push_back(new Body<IntegrationFrame>(gravitational_parameter));
    Displacement<IntegrationFrame> const   position =
      IntegrationPosition(body) - IntegrationPosition(sun_);
    VelocityChange<IntegrationFrame> const velocity =
      IntegrationVelocity(body) - IntegrationVelocity(sun_);
    bodies->back()->AppendToTrajectory({position}, {velocity}, universal_time);
    celestials_->insert({Unmanage(body->name),
                         bodies->back()});
    LOG_UNITY(std::string("\nAdded CelestialBody ") + Unmanage(body->name) +
              "\nGM = " + DebugString(gravitational_parameter) +
              "\nq  = " + DebugString(position) +
              "\nv  = " + DebugString(velocity));
  }
  for each (Vessel^ body in FlightGlobals::Vessels) {
    bodies->push_back(new Body<IntegrationFrame>(GravitationalParameter()));
    Displacement<IntegrationFrame> const   position =
        IntegrationPosition(body) - IntegrationPosition(sun_);
    VelocityChange<IntegrationFrame> const velocity =
        IntegrationVelocity(body) - IntegrationVelocity(sun_);
    bodies->back()->AppendToTrajectory({position}, {velocity}, universal_time);
    vessels_->insert({Unmanage(body->id.ToString()), bodies->back()});
    LOG_UNITY(std::string("\nAdded Vessel ") + Unmanage(body->name) +
              "\nq  = " + DebugString(position) +
              "\nv  = " + DebugString(velocity));
  }
  Reset(system_, new NBodySystem<IntegrationFrame>(bodies));
}

void Principia::FreeAllOwnedPointers() {
  Reset(prediction_length_, nullptr);
  Reset(Δt_, nullptr);
  Reset(system_, nullptr);
  Reset(celestials_, nullptr);
  Reset(vessels_, nullptr);
}

struct World;
struct AliceWorld;

Permutation<AliceWorld, World> const LookingGlass =
    Permutation<AliceWorld, World>(Permutation<AliceWorld, World>::XZY);

Rotation<IntegrationFrame, World> PlanetariumRotation() {
  UnityEngine::QuaternionD planetarium_rotation = Planetarium::Rotation;
  return Rotation<IntegrationFrame, World>(
      Quaternion(planetarium_rotation.w,
                 {planetarium_rotation.x,
                  planetarium_rotation.y,
                  planetarium_rotation.z}));
}

Displacement<World> WorldPosition(CelestialBody^ const body) {
  Vector3d const position = body->position;
  return Displacement<World>({
      position.x * SIUnit<Length>(),
      position.y * SIUnit<Length>(),
      position.z * SIUnit<Length>()});
}

Displacement<IntegrationFrame> IntegrationPosition(CelestialBody^ const body) {
  return PlanetariumRotation().Inverse()(WorldPosition(body));
}

VelocityChange<World> WorldVelocity(CelestialBody^ const body) {
  Vector3d const frame_velocity = body->GetFrameVel();
  return VelocityChange<World>({
      frame_velocity.x * SIUnit<Speed>(),
      frame_velocity.y * SIUnit<Speed>(),
      frame_velocity.z * SIUnit<Speed>()});
}

VelocityChange<IntegrationFrame> IntegrationVelocity(
    CelestialBody^ const body) {
  return PlanetariumRotation().Inverse()(WorldVelocity(body));
}

Displacement<AliceWorld> OffsetFromReferenceBody(Vessel^ const body) {
  Vector3d const result = body->orbitDriver->pos;
    return Displacement<AliceWorld>({
      result.x * SIUnit<Length>(),
      result.y * SIUnit<Length>(),
      result.z * SIUnit<Length>()});
}

Displacement<World> WorldPosition(Vessel^ const body) {
  return WorldPosition(body->orbitDriver->orbit->referenceBody) +
      LookingGlass(OffsetFromReferenceBody(body));
}

Displacement<IntegrationFrame> IntegrationPosition(Vessel^ const body) {
  return PlanetariumRotation().Inverse()(WorldPosition(body));
}

VelocityChange<World> WorldVelocity(Vessel^ const body) {
  Vector3d const frame_velocity = body->orbitDriver->orbit->GetFrameVel();
  return VelocityChange<World>({
      frame_velocity.x * SIUnit<Speed>(),
      frame_velocity.y * SIUnit<Speed>(),
      frame_velocity.z * SIUnit<Speed>()});
}

VelocityChange<IntegrationFrame> IntegrationVelocity(Vessel^ const body) {
  return PlanetariumRotation().Inverse()(WorldVelocity(body));
}

}  // namespace ksp
}  // namespace principia
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_CPPU_MACROS_HXX
#define INCLUDED_CPPU_MACROS_HXX

#include <sal/types.h>

/** Namespace name for compiler/ platform, e.g. gcc3, msci */
#define CPPU_CURRENT_NAMESPACE CPPU_ENV

/// @cond INTERNAL

/** Patching the GCC 3 incomatible alignment change for Linux.

    This macro is appended by cppumaker to every first member of a struct, if
    the struct inherits from a base struct and the first member is neither
    double nor sal_[u]Int64.  (The double/sal_[u]Int64 restriction is due to a
    bug in GCC prior to version 3.3, which would cause __alignof__ of such a
    struct to become 8 instead of 4 if CPPU_GCC3_ALIGN were added to its first
    member.)
*/
#if defined(__GNUC__)
#define CPPU_GCC3_ALIGN( base_struct ) __attribute__ ((aligned (__alignof__ (base_struct))))
#else
#define CPPU_GCC3_ALIGN( base_struct )
#endif

/**
   Exporting the symbols necessary for exception handling on GCC.

   These macros are used in the headers generated by cppumaker for UNO exception
   types, to ensure that exception handling does not fail on GCC.
*/
#define CPPU_GCC_DLLPUBLIC_EXPORT SAL_EXCEPTION_DLLPUBLIC_EXPORT
#define CPPU_GCC_DLLPRIVATE SAL_EXCEPTION_DLLPRIVATE

/// @endcond

#endif // INCLUDED_CPPU_MACROS_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>CPPU_CURRENT_NAMESPACE is impl detail, mark @deprecated<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_CPPU_MACROS_HXX
#define INCLUDED_CPPU_MACROS_HXX

#include <sal/types.h>

/** Namespace name for compiler/ platform, e.g. gcc3, msci

    @deprecated implementation detail, not to be used by client code
*/
#define CPPU_CURRENT_NAMESPACE CPPU_ENV

/// @cond INTERNAL

/** Patching the GCC 3 incomatible alignment change for Linux.

    This macro is appended by cppumaker to every first member of a struct, if
    the struct inherits from a base struct and the first member is neither
    double nor sal_[u]Int64.  (The double/sal_[u]Int64 restriction is due to a
    bug in GCC prior to version 3.3, which would cause __alignof__ of such a
    struct to become 8 instead of 4 if CPPU_GCC3_ALIGN were added to its first
    member.)
*/
#if defined(__GNUC__)
#define CPPU_GCC3_ALIGN( base_struct ) __attribute__ ((aligned (__alignof__ (base_struct))))
#else
#define CPPU_GCC3_ALIGN( base_struct )
#endif

/**
   Exporting the symbols necessary for exception handling on GCC.

   These macros are used in the headers generated by cppumaker for UNO exception
   types, to ensure that exception handling does not fail on GCC.
*/
#define CPPU_GCC_DLLPUBLIC_EXPORT SAL_EXCEPTION_DLLPUBLIC_EXPORT
#define CPPU_GCC_DLLPRIVATE SAL_EXCEPTION_DLLPRIVATE

/// @endcond

#endif // INCLUDED_CPPU_MACROS_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>