<commit_before>// Copyright (c) 2011 The Native Client Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "debugger/core/debuggee_thread.h"
#include <assert.h>
#include "debugger/base/debug_command_line.h"
#include "debugger/core/debug_api.h"
#include "debugger/core/debug_breakpoint.h"
#include "debugger/core/debug_event.h"
#include "debugger/core/debug_logger.h"
#include "debugger/core/debuggee_iprocess.h"

#pragma warning(disable : 4996)  // Disable sscanf warning.

namespace {
const size_t kMaxStringSize = 32 * 1024;
const char* kNexeUuid = "{7AA7C9CF-89EC-4ed3-8DAD-6DC84302AB11}";
}

namespace debug {
DebuggeeThread::DebuggeeThread(int id,
                               HANDLE handle,
                               IDebuggeeProcess* parent_process)
    : id_(id),
      handle_(handle),
      parent_process_(*parent_process),
      state_(kHalted),
      exit_code_(0),
      triggered_breakpoint_addr_(NULL),
      is_nacl_app_thread_(false) {
  assert(NULL != parent_process);
}

DebugAPI& DebuggeeThread::debug_api() {
  return parent_process().debug_api();
}

void DebuggeeThread::SetState(State new_state) {
  DBG_LOG("TR03.01",
          "msg='DebuggeeThread::SetState' thread_id=%d old_state=%s"
          " new_state=%s",
          id(),
          GetStateName(state_),
          GetStateName(new_state));
  state_ = new_state;
}

bool DebuggeeThread::IsHalted() const {
  return (kHalted == state_);
}

void DebuggeeThread::OnOutputDebugString(DebugEvent* debug_event) {
  std::string debug_str;
  if (parent_process().ReadDebugString(&debug_str)) {
     DBG_LOG("TR03.02", "OutputDebugString=[%s]", debug_str.c_str());
  }

  if (strncmp(debug_str.c_str(), kNexeUuid, strlen(kNexeUuid)) == 0) {
    /// This string is coming from sel_ldr.
    // Here we are passing pointers from sel_ldr to the debugger.
    // One might think that we can't use them because they are
    // valid in sel_ldr address space only. This is not true.
    // ::ReadProcessMemory can be used with these pointers.
    // Note: these pointers are not untrusted NaCl, they are
    // native windows flat pointers.

    // Here's list of possible messages from sel_ldr:
    // "-version 1 -event AppCreate -nap %p -mem_start %p -user_entry_pt
    //     %p -initial_entry_pt %p"
    // "-version 1 -event ThreadCreate -natp %p"
    // "-version 1 -event ThreadExit -natp %p -exit_code %d"
    // "-version 1 -event AppExit -exit_code %d"
    CommandLine debug_info(debug_str);
    std::string event = debug_info.GetStringSwitch("-event", "");
    if ("AppCreate" == event) {
      void* nexe_mem_base = debug_info.GetAddrSwitch("-mem_start");
      void* user_entry_point = debug_info.GetAddrSwitch("-user_entry_pt");
      parent_process().set_nexe_mem_base(nexe_mem_base);
      parent_process().set_nexe_entry_point(user_entry_point);
      debug_event->set_nacl_debug_event_code(DebugEvent::kAppStarted);
      DBG_LOG("TR03.03",
              "NaClAppCreate mem_base=%p entry_point=%p",
              nexe_mem_base,
              user_entry_point);
    } else if ("ThreadCreate" == event) {
      is_nacl_app_thread_ = true;
      debug_event->set_nacl_debug_event_code(
          DebugEvent::kThreadIsAboutToStart);
      DBG_LOG("TR03.07", "ThreadCreate thread_id=%d", id());
    }
  }
}

// Here's what we have to do when we hit our breakpoint:
// a) recover original code at breakpoint adddress.
// b) return IP to the beginning of instruction (simple decrement work).
void DebuggeeThread::OnBreakpoint(DebugEvent* debug_event) {
  DEBUG_EVENT de = debug_event->windows_debug_event();
  void* ex_addr = de.u.Exception.ExceptionRecord.ExceptionAddress;
  void* br_addr = ex_addr;
  if (IsNaClAppThread())
    br_addr = parent_process().FromNexeToFlatAddress(ex_addr);

  Breakpoint* br = parent_process().GetBreakpoint(br_addr);

  DBG_LOG("TR03.04",
          "msg='DebuggeeThread::OnBreakpoint' thread_id=%d ex_addr=%p"
          " br_addr=0x%p our=%s",
          id(),
          ex_addr,
          br_addr,
          (NULL != br) ? "yes" : "no");

  if (NULL != br) {
    // it's our breakpoint.
    triggered_breakpoint_addr_ = br->address();
    br->RecoverCodeAtBreakpoint();
    SetIP(reinterpret_cast<char*>(GetIP()) - 1);
  }
}

bool DebuggeeThread::Continue(ContinueOption option) {
  if (!IsHalted()) {
    DBG_LOG("WARN03.01",
            "msg='DebuggeeThread::Continue(%s) called while thread was in an"
            " incompatible state: %s' thread_id=%d",
            GetContinueOptionName(option),
            GetStateName(state_),
            id());
    return false;
  }
  const DebugEvent& last_debug_event = parent_process().last_debug_event();
  int last_debug_event_id =
      last_debug_event.windows_debug_event().dwDebugEventCode;
  if ((EXIT_THREAD_DEBUG_EVENT == last_debug_event_id) ||
     (EXIT_PROCESS_DEBUG_EVENT == last_debug_event_id)) {
    SetState(kDead);
    return (TRUE == debug_api().ContinueDebugEvent(parent_process().id(),
                                                   id(),
                                                   DBG_CONTINUE));
  }

  if (NULL != triggered_breakpoint_addr_) {
    void* flat_ip = GetIP();
    if (IsNaClAppThread())
      flat_ip = parent_process().FromNexeToFlatAddress(GetIP());

    if (flat_ip == triggered_breakpoint_addr_) {
      return ContinueFromBreakpoint();
    } else {
      // Just in case user changed IP so that it's not pointing to
      // triggered breakpoint, we need to:
      // a) recover breakpoint
      // b) make it not triggered
      Breakpoint* br =
          parent_process().GetBreakpoint(triggered_breakpoint_addr_);
      if (NULL != br)
        br->WriteBreakpointCode();
      triggered_breakpoint_addr_ = NULL;
    }
  }
  if (kSingleStep == option)
    EnableSingleStep(true);

  int flags = DBG_CONTINUE;
  if (kContinueAndPassException == option)
    flags = DBG_EXCEPTION_NOT_HANDLED;

  SetState(kRunning);
  return (TRUE == debug_api().ContinueDebugEvent(parent_process().id(),
                                                 id(),
                                                 flags));
}

/// Implements first steps of 'Continue from breakpoint' algorithm,
/// described in |DebuggeeThread::OnDebugEvent| method.
bool DebuggeeThread::ContinueFromBreakpoint() {
  SetState(kContinueFromBreakpoint);
  EnableSingleStep(true);
  return (TRUE == debug_api().ContinueDebugEvent(parent_process().id(),
                                                 id(),
                                                 DBG_CONTINUE));
}

void DebuggeeThread::OnSingleStep(DebugEvent* debug_event) {
  if (kContinueFromBreakpoint == state_) {
    if (NULL == triggered_breakpoint_addr_) {
      DBG_LOG("ERR03.01",
            "msg=OnSingleStepDueToContinueFromBreakpoint thread_id=%d"
            " triggered_breakpoint_=NULL",
            id());
      SetState(kHalted);
    } else {
      DBG_LOG("TR03.05",
              "msg=OnSingleStepDueToContinueFromBreakpoint thread_id=%d"
              " breakpoint_addr=0x%p",
              id(),
              triggered_breakpoint_addr_);
      // We got here because thread was continuing from breakpoint.
      Breakpoint* br =
          parent_process().GetBreakpoint(triggered_breakpoint_addr_);
      if (NULL != br)
        br->WriteBreakpointCode();
      triggered_breakpoint_addr_ = NULL;
      debug_api().ContinueDebugEvent(parent_process().id(),
                                     id(),
                                     DBG_CONTINUE);
      SetState(kRunning);
    }
  } else {
    SetState(kHalted);
  }
}

void DebuggeeThread::OnDebugEvent(DebugEvent* debug_event) {
  DEBUG_EVENT de = debug_event->windows_debug_event();
  EnableSingleStep(false);

  // Thread expected 'SingleStep' exception due to 'continue from breakpoint'
  // algorithm, but got something else. For example, it happens when breakpoint
  // is set to instruction generating 'memory access violation' exception.
  //
  // Here's description of 'continue from breakpoint' algorithm:
  // a) recover original code at breakpoint address
  // b) enable single step mode of CPU
  // c) call DebugAPI::ContinueDebugEvent
  // d) receive SingleStep exception
  // e) write breakpoint code at breakpoint address
  // f) disable single step mode of CPU
  // h) call DebugAPI::ContinueDebugEvent
  // f) DebuggeeThread is now in 'kRunning' state.
  // Note: we can get different exception on step (d),
  // we have to do the following:
  // 1) disable single step mode of CPU (it's done in first statement in
  //    |DebuggeeThread::OnDebugEvent| method).
  // 2) write breakpoint code at breakpoint address, if IP points
  //    somewhere else.
  if (!debug_event->IsSingleStep() &&
      (kContinueFromBreakpoint == state_) &&
      (NULL != triggered_breakpoint_addr_)) {
    void* flat_ip = GetIP();
    if (IsNaClAppThread())
      flat_ip = parent_process().FromNexeToFlatAddress(flat_ip);

    if (flat_ip != triggered_breakpoint_addr_) {
      Breakpoint* br =
          parent_process().GetBreakpoint(triggered_breakpoint_addr_);
      if (NULL != br)
        br->WriteBreakpointCode();
      triggered_breakpoint_addr_ = NULL;
    }
  }

  // Now we can proceed with debug event.
  switch (de.dwDebugEventCode) {
    case OUTPUT_DEBUG_STRING_EVENT: {
      OnOutputDebugString(debug_event);
      break;
    }
    case EXIT_THREAD_DEBUG_EVENT: {
      exit_code_ = de.u.ExitThread.dwExitCode;
      break;
    }
    case EXIT_PROCESS_DEBUG_EVENT: {
      exit_code_ = de.u.ExitProcess.dwExitCode;
      break;
    }
    case EXCEPTION_DEBUG_EVENT: {
      switch (debug_event->GetExceptionCode()) {
        case EXCEPTION_BREAKPOINT: {
          OnBreakpoint(debug_event);
          break;
        }
        case EXCEPTION_SINGLE_STEP: {
          OnSingleStep(debug_event);
          // Thread halts on all other events unconditionally,
          // but here |OnSingleStep| can decide to continue -
          // in case it's due to 'continue from breakpoint'.
          return;
        }
      }
    }
  }
  // DebugeeThread halts on all debug events, with one exception -
  // when it receives SingleStep while continue from breakpoint.
  SetState(kHalted);
}

void DebuggeeThread::EnableSingleStep(bool enable) {
  DBG_LOG("TR03.06",
          "msg='DebuggeeThread::EnableSingleStep(%s)' thread_id=%d",
          enable ? "true" : "false",
          id());

  if (parent_process().IsWoW()) {
    WOW64_CONTEXT context;
    GetWowContext(&context);
    if (enable)
      context.EFlags |= 1 << 8;
    else
      context.EFlags &= ~(1 << 8);
    SetWowContext(context);
  } else {
    CONTEXT context;
    GetContext(&context);
    if (enable)
      context.EFlags |= 1 << 8;
    else
      context.EFlags &= ~(1 << 8);
    SetContext(context);
  }
}

const char* DebuggeeThread::GetStateName(State state) {
  switch (state) {
    case kRunning: return "kRunning";
    case kHalted: return "kHalted";
    case kContinueFromBreakpoint: return "kContinueFromBreakpoint";
    case kDead: return "kDead";
  }
  return "N/A";
}

const char* DebuggeeThread::GetContinueOptionName(ContinueOption option) {
  switch (option) {
    case kSingleStep: return "kSingleStep";
    case kContinue: return "kContinue";
    case kContinueAndPassException: return "kContinueAndPassException";
  }
  return "N/A";
}

void DebuggeeThread::Kill() {
  if (NULL != handle_)
    debug_api().TerminateThread(handle_, 0);
}

bool DebuggeeThread::GetContext(CONTEXT* context) {
  if (NULL == context)
    return false;
  memset(context, 0, sizeof(*context));
  context->ContextFlags = CONTEXT_ALL;
  return (debug_api().GetThreadContext(handle_, context) != FALSE);
}

bool DebuggeeThread::SetContext(const CONTEXT& context) {
  CONTEXT context_copy = context;
  return (debug_api().SetThreadContext(handle_, &context_copy) != FALSE);
}

bool DebuggeeThread::GetWowContext(WOW64_CONTEXT* context) {
  if (NULL == context)
    return false;
  memset(context, 0, sizeof(*context));
  context->ContextFlags = CONTEXT_ALL;
  return (debug_api().Wow64GetThreadContext(handle_, context) != FALSE);
}

bool DebuggeeThread::SetWowContext(const WOW64_CONTEXT& context) {
  return (debug_api().Wow64SetThreadContext(handle_, &context) != FALSE);
}

void* DebuggeeThread::GetIP() {
  if (parent_process().IsWoW()) {
    WOW64_CONTEXT context;
    GetWowContext(&context);
    return reinterpret_cast<void*>(context.Eip);
  } else {
    CONTEXT context;
    GetContext(&context);
#ifdef _WIN64
    return reinterpret_cast<void*>(context.Rip);
#else
    return reinterpret_cast<void*>(context.Eip);
#endif
  }
}

bool DebuggeeThread::SetIP(void* ip) {
  if (parent_process().IsWoW()) {
    WOW64_CONTEXT context;
    if (!GetWowContext(&context))
      return false;
    context.Eip = reinterpret_cast<DWORD>(ip);
    return SetWowContext(context);
  } else {
    CONTEXT ct;
    if (!GetContext(&ct))
      return false;
#ifdef _WIN64
    ct.Rip = reinterpret_cast<DWORD64>(ip);
#else
    ct.Eip = reinterpret_cast<DWORD>(ip);
#endif
    return SetContext(ct);
  }
}
}  // namespace debug

<commit_msg>Add support for running sel_ldr as nexe host.<commit_after>// Copyright (c) 2011 The Native Client Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "debugger/core/debuggee_thread.h"
#include <assert.h>
#include "debugger/base/debug_command_line.h"
#include "debugger/core/debug_api.h"
#include "debugger/core/debug_breakpoint.h"
#include "debugger/core/debug_event.h"
#include "debugger/core/debug_logger.h"
#include "debugger/core/debuggee_iprocess.h"

#pragma warning(disable : 4996)  // Disable sscanf warning.

namespace {
const size_t kMaxStringSize = 32 * 1024;
const char* kNexeUuid = "{7AA7C9CF-89EC-4ed3-8DAD-6DC84302AB11}";
}

namespace debug {
DebuggeeThread::DebuggeeThread(int id,
                               HANDLE handle,
                               IDebuggeeProcess* parent_process)
    : id_(id),
      handle_(handle),
      parent_process_(*parent_process),
      state_(kHalted),
      exit_code_(0),
      triggered_breakpoint_addr_(NULL),
      is_nacl_app_thread_(false) {
  assert(NULL != parent_process);
}

DebugAPI& DebuggeeThread::debug_api() {
  return parent_process().debug_api();
}

void DebuggeeThread::SetState(State new_state) {
  DBG_LOG("TR03.01",
          "msg='DebuggeeThread::SetState' thread_id=%d old_state=%s"
          " new_state=%s",
          id(),
          GetStateName(state_),
          GetStateName(new_state));
  state_ = new_state;
}

bool DebuggeeThread::IsHalted() const {
  return (kHalted == state_);
}

void DebuggeeThread::OnOutputDebugString(DebugEvent* debug_event) {
  std::string debug_str;
  if (parent_process().ReadDebugString(&debug_str)) {
     DBG_LOG("TR03.02", "OutputDebugString=[%s]", debug_str.c_str());
  }

  if (strncmp(debug_str.c_str(), kNexeUuid, strlen(kNexeUuid)) == 0) {
    /// This string is coming from sel_ldr.
    // Here we are passing pointers from sel_ldr to the debugger.
    // One might think that we can't use them because they are
    // valid in sel_ldr address space only. This is not true.
    // ::ReadProcessMemory can be used with these pointers.
    // Note: these pointers are not untrusted NaCl, they are
    // native windows flat pointers.

    // Here's list of possible messages from sel_ldr:
    // "-version 1 -event AppCreate -nap %p -mem_start %p -user_entry_pt
    //     %p -initial_entry_pt %p"
    // "-version 1 -event ThreadCreate -natp %p"
    // "-version 1 -event ThreadExit -natp %p -exit_code %d"
    // "-version 1 -event AppExit -exit_code %d"
    CommandLine debug_info(debug_str);
    std::string event = debug_info.GetStringSwitch("-event", "");
    if ("AppCreate" == event) {
      void* nexe_mem_base = debug_info.GetAddrSwitch("-mem_start");
      void* user_entry_point = debug_info.GetAddrSwitch("-user_entry_pt");
      if (NULL == user_entry_point)  // No IRT present, use -initial_entry_pt.
        user_entry_point = debug_info.GetAddrSwitch("-initial_entry_pt");
      parent_process().set_nexe_mem_base(nexe_mem_base);
      parent_process().set_nexe_entry_point(user_entry_point);
      debug_event->set_nacl_debug_event_code(DebugEvent::kAppStarted);
      DBG_LOG("TR03.03",
              "NaClAppCreate mem_base=%p entry_point=%p",
              nexe_mem_base,
              user_entry_point);
    } else if ("ThreadCreate" == event) {
      is_nacl_app_thread_ = true;
      debug_event->set_nacl_debug_event_code(
          DebugEvent::kThreadIsAboutToStart);
      DBG_LOG("TR03.07", "ThreadCreate thread_id=%d", id());
    }
  }
}

// Here's what we have to do when we hit our breakpoint:
// a) recover original code at breakpoint adddress.
// b) return IP to the beginning of instruction (simple decrement work).
void DebuggeeThread::OnBreakpoint(DebugEvent* debug_event) {
  DEBUG_EVENT de = debug_event->windows_debug_event();
  void* ex_addr = de.u.Exception.ExceptionRecord.ExceptionAddress;
  void* br_addr = ex_addr;
  if (IsNaClAppThread())
    br_addr = parent_process().FromNexeToFlatAddress(ex_addr);

  Breakpoint* br = parent_process().GetBreakpoint(br_addr);

  DBG_LOG("TR03.04",
          "msg='DebuggeeThread::OnBreakpoint' thread_id=%d ex_addr=%p"
          " br_addr=0x%p our=%s",
          id(),
          ex_addr,
          br_addr,
          (NULL != br) ? "yes" : "no");

  if (NULL != br) {
    // it's our breakpoint.
    triggered_breakpoint_addr_ = br->address();
    br->RecoverCodeAtBreakpoint();
    SetIP(reinterpret_cast<char*>(GetIP()) - 1);
  }
}

bool DebuggeeThread::Continue(ContinueOption option) {
  if (!IsHalted()) {
    DBG_LOG("WARN03.01",
            "msg='DebuggeeThread::Continue(%s) called while thread was in an"
            " incompatible state: %s' thread_id=%d",
            GetContinueOptionName(option),
            GetStateName(state_),
            id());
    return false;
  }
  const DebugEvent& last_debug_event = parent_process().last_debug_event();
  int last_debug_event_id =
      last_debug_event.windows_debug_event().dwDebugEventCode;
  if ((EXIT_THREAD_DEBUG_EVENT == last_debug_event_id) ||
     (EXIT_PROCESS_DEBUG_EVENT == last_debug_event_id)) {
    SetState(kDead);
    return (TRUE == debug_api().ContinueDebugEvent(parent_process().id(),
                                                   id(),
                                                   DBG_CONTINUE));
  }

  if (NULL != triggered_breakpoint_addr_) {
    void* flat_ip = GetIP();
    if (IsNaClAppThread())
      flat_ip = parent_process().FromNexeToFlatAddress(GetIP());

    if (flat_ip == triggered_breakpoint_addr_) {
      return ContinueFromBreakpoint();
    } else {
      // Just in case user changed IP so that it's not pointing to
      // triggered breakpoint, we need to:
      // a) recover breakpoint
      // b) make it not triggered
      Breakpoint* br =
          parent_process().GetBreakpoint(triggered_breakpoint_addr_);
      if (NULL != br)
        br->WriteBreakpointCode();
      triggered_breakpoint_addr_ = NULL;
    }
  }
  if (kSingleStep == option)
    EnableSingleStep(true);

  int flags = DBG_CONTINUE;
  if (kContinueAndPassException == option)
    flags = DBG_EXCEPTION_NOT_HANDLED;

  SetState(kRunning);
  return (TRUE == debug_api().ContinueDebugEvent(parent_process().id(),
                                                 id(),
                                                 flags));
}

/// Implements first steps of 'Continue from breakpoint' algorithm,
/// described in |DebuggeeThread::OnDebugEvent| method.
bool DebuggeeThread::ContinueFromBreakpoint() {
  SetState(kContinueFromBreakpoint);
  EnableSingleStep(true);
  return (TRUE == debug_api().ContinueDebugEvent(parent_process().id(),
                                                 id(),
                                                 DBG_CONTINUE));
}

void DebuggeeThread::OnSingleStep(DebugEvent* debug_event) {
  if (kContinueFromBreakpoint == state_) {
    if (NULL == triggered_breakpoint_addr_) {
      DBG_LOG("ERR03.01",
            "msg=OnSingleStepDueToContinueFromBreakpoint thread_id=%d"
            " triggered_breakpoint_=NULL",
            id());
      SetState(kHalted);
    } else {
      DBG_LOG("TR03.05",
              "msg=OnSingleStepDueToContinueFromBreakpoint thread_id=%d"
              " breakpoint_addr=0x%p",
              id(),
              triggered_breakpoint_addr_);
      // We got here because thread was continuing from breakpoint.
      Breakpoint* br =
          parent_process().GetBreakpoint(triggered_breakpoint_addr_);
      if (NULL != br)
        br->WriteBreakpointCode();
      triggered_breakpoint_addr_ = NULL;
      debug_api().ContinueDebugEvent(parent_process().id(),
                                     id(),
                                     DBG_CONTINUE);
      SetState(kRunning);
    }
  } else {
    SetState(kHalted);
  }
}

void DebuggeeThread::OnDebugEvent(DebugEvent* debug_event) {
  DEBUG_EVENT de = debug_event->windows_debug_event();
  EnableSingleStep(false);

  // Thread expected 'SingleStep' exception due to 'continue from breakpoint'
  // algorithm, but got something else. For example, it happens when breakpoint
  // is set to instruction generating 'memory access violation' exception.
  //
  // Here's description of 'continue from breakpoint' algorithm:
  // a) recover original code at breakpoint address
  // b) enable single step mode of CPU
  // c) call DebugAPI::ContinueDebugEvent
  // d) receive SingleStep exception
  // e) write breakpoint code at breakpoint address
  // f) disable single step mode of CPU
  // h) call DebugAPI::ContinueDebugEvent
  // f) DebuggeeThread is now in 'kRunning' state.
  // Note: we can get different exception on step (d),
  // we have to do the following:
  // 1) disable single step mode of CPU (it's done in first statement in
  //    |DebuggeeThread::OnDebugEvent| method).
  // 2) write breakpoint code at breakpoint address, if IP points
  //    somewhere else.
  if (!debug_event->IsSingleStep() &&
      (kContinueFromBreakpoint == state_) &&
      (NULL != triggered_breakpoint_addr_)) {
    void* flat_ip = GetIP();
    if (IsNaClAppThread())
      flat_ip = parent_process().FromNexeToFlatAddress(flat_ip);

    if (flat_ip != triggered_breakpoint_addr_) {
      Breakpoint* br =
          parent_process().GetBreakpoint(triggered_breakpoint_addr_);
      if (NULL != br)
        br->WriteBreakpointCode();
      triggered_breakpoint_addr_ = NULL;
    }
  }

  // Now we can proceed with debug event.
  switch (de.dwDebugEventCode) {
    case OUTPUT_DEBUG_STRING_EVENT: {
      OnOutputDebugString(debug_event);
      break;
    }
    case EXIT_THREAD_DEBUG_EVENT: {
      exit_code_ = de.u.ExitThread.dwExitCode;
      break;
    }
    case EXIT_PROCESS_DEBUG_EVENT: {
      exit_code_ = de.u.ExitProcess.dwExitCode;
      break;
    }
    case EXCEPTION_DEBUG_EVENT: {
      switch (debug_event->GetExceptionCode()) {
        case EXCEPTION_BREAKPOINT: {
          OnBreakpoint(debug_event);
          break;
        }
        case EXCEPTION_SINGLE_STEP: {
          OnSingleStep(debug_event);
          // Thread halts on all other events unconditionally,
          // but here |OnSingleStep| can decide to continue -
          // in case it's due to 'continue from breakpoint'.
          return;
        }
      }
    }
  }
  // DebugeeThread halts on all debug events, with one exception -
  // when it receives SingleStep while continue from breakpoint.
  SetState(kHalted);
}

void DebuggeeThread::EnableSingleStep(bool enable) {
  DBG_LOG("TR03.06",
          "msg='DebuggeeThread::EnableSingleStep(%s)' thread_id=%d",
          enable ? "true" : "false",
          id());

  if (parent_process().IsWoW()) {
    WOW64_CONTEXT context;
    GetWowContext(&context);
    if (enable)
      context.EFlags |= 1 << 8;
    else
      context.EFlags &= ~(1 << 8);
    SetWowContext(context);
  } else {
    CONTEXT context;
    GetContext(&context);
    if (enable)
      context.EFlags |= 1 << 8;
    else
      context.EFlags &= ~(1 << 8);
    SetContext(context);
  }
}

const char* DebuggeeThread::GetStateName(State state) {
  switch (state) {
    case kRunning: return "kRunning";
    case kHalted: return "kHalted";
    case kContinueFromBreakpoint: return "kContinueFromBreakpoint";
    case kDead: return "kDead";
  }
  return "N/A";
}

const char* DebuggeeThread::GetContinueOptionName(ContinueOption option) {
  switch (option) {
    case kSingleStep: return "kSingleStep";
    case kContinue: return "kContinue";
    case kContinueAndPassException: return "kContinueAndPassException";
  }
  return "N/A";
}

void DebuggeeThread::Kill() {
  if (NULL != handle_)
    debug_api().TerminateThread(handle_, 0);
}

bool DebuggeeThread::GetContext(CONTEXT* context) {
  if (NULL == context)
    return false;
  memset(context, 0, sizeof(*context));
  context->ContextFlags = CONTEXT_ALL;
  return (debug_api().GetThreadContext(handle_, context) != FALSE);
}

bool DebuggeeThread::SetContext(const CONTEXT& context) {
  CONTEXT context_copy = context;
  return (debug_api().SetThreadContext(handle_, &context_copy) != FALSE);
}

bool DebuggeeThread::GetWowContext(WOW64_CONTEXT* context) {
  if (NULL == context)
    return false;
  memset(context, 0, sizeof(*context));
  context->ContextFlags = CONTEXT_ALL;
  return (debug_api().Wow64GetThreadContext(handle_, context) != FALSE);
}

bool DebuggeeThread::SetWowContext(const WOW64_CONTEXT& context) {
  return (debug_api().Wow64SetThreadContext(handle_, &context) != FALSE);
}

void* DebuggeeThread::GetIP() {
  if (parent_process().IsWoW()) {
    WOW64_CONTEXT context;
    GetWowContext(&context);
    return reinterpret_cast<void*>(context.Eip);
  } else {
    CONTEXT context;
    GetContext(&context);
#ifdef _WIN64
    return reinterpret_cast<void*>(context.Rip);
#else
    return reinterpret_cast<void*>(context.Eip);
#endif
  }
}

bool DebuggeeThread::SetIP(void* ip) {
  if (parent_process().IsWoW()) {
    WOW64_CONTEXT context;
    if (!GetWowContext(&context))
      return false;
    context.Eip = reinterpret_cast<DWORD>(ip);
    return SetWowContext(context);
  } else {
    CONTEXT ct;
    if (!GetContext(&ct))
      return false;
#ifdef _WIN64
    ct.Rip = reinterpret_cast<DWORD64>(ip);
#else
    ct.Eip = reinterpret_cast<DWORD>(ip);
#endif
    return SetContext(ct);
  }
}
}  // namespace debug

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: attributemap.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: vg $ $Date: 2006-11-21 17:26:10 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_slideshow.hxx"

// must be first
#include <canvas/debug.hxx>
#include <canvas/canvastools.hxx>

#include "attributemap.hxx"
#include "tools.hxx"

namespace presentation
{
    namespace internal
    {
        typedef ::canvas::tools::ValueMap< AttributeType > AnimateAttributeMap;

        AttributeType mapAttributeName( const ::rtl::OUString& rAttrName )
        {
            /** Maps attribute name to AttributeType enum.

                String entries are all case-insensitive and MUST
                BE STORED lowercase.

                String entries MUST BE SORTED in ascending order!
            */
            static AnimateAttributeMap::MapEntry lcl_attributeMap[] =
                {
                    { "charcolor", ATTRIBUTE_CHAR_COLOR },

                    { "charfontname", ATTRIBUTE_CHAR_FONT_NAME },

                    { "charheight", ATTRIBUTE_CHAR_HEIGHT },

                    { "charposture", ATTRIBUTE_CHAR_POSTURE },

                    // TODO(Q1): This should prolly be changed in PPT import
                    // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
                    { "charrotation", ATTRIBUTE_ROTATE },

                    { "charunderline", ATTRIBUTE_CHAR_UNDERLINE },

                    { "charweight", ATTRIBUTE_CHAR_WEIGHT },

                    { "color", ATTRIBUTE_COLOR },

                    { "dimcolor", ATTRIBUTE_DIMCOLOR },

                    { "fillcolor", ATTRIBUTE_FILL_COLOR },

                    { "fillstyle", ATTRIBUTE_FILL_STYLE },

                    { "height", ATTRIBUTE_HEIGHT },

                    { "linecolor", ATTRIBUTE_LINE_COLOR },

                    { "linestyle", ATTRIBUTE_LINE_STYLE },

                    { "opacity", ATTRIBUTE_OPACITY },

                    { "rotate", ATTRIBUTE_ROTATE },

                    { "skewx", ATTRIBUTE_SKEW_X },

                    { "skewy", ATTRIBUTE_SKEW_Y },

                    { "visibility", ATTRIBUTE_VISIBILITY },

                    { "width", ATTRIBUTE_WIDTH },

                    { "x", ATTRIBUTE_POS_X },

                    { "y", ATTRIBUTE_POS_Y }
                };

            static AnimateAttributeMap aMap( lcl_attributeMap,
                                             sizeof(lcl_attributeMap)/sizeof(AnimateAttributeMap::MapEntry),
                                             false );

            AttributeType eAttributeType = ATTRIBUTE_INVALID;

            // determine the type from the attribute name
            if( !aMap.lookup( rAttrName,
                              eAttributeType ) )
            {
                OSL_TRACE( "mapAttributeName(): attribute name %s not found in map.",
                           ::rtl::OUStringToOString( rAttrName,
                                                     RTL_TEXTENCODING_ASCII_US ).getStr() );
                return ATTRIBUTE_INVALID;
            }

            return eAttributeType;
        }

    }
}
<commit_msg>INTEGRATION: CWS presfixes09 (1.4.10); FILE MERGED 2006/10/18 19:47:57 thb 1.4.10.3: RESYNC: (1.4-1.5); FILE MERGED 2006/04/12 19:25:04 thb 1.4.10.2: #i37778# Making slideshow engine much more robust against missing/unsupported interfaces and properties; fixed RehearseTimings output offset issue; fixed WaitSymbol output position 2006/03/24 18:23:05 thb 1.4.10.1: #i37778# Moved whole slideshow engine from namespace presentation (which conflicts with one of the UNO subnamespaces) to slideshow<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: attributemap.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 15:12:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_slideshow.hxx"

// must be first
#include <canvas/debug.hxx>
#include <canvas/canvastools.hxx>

#include "attributemap.hxx"
#include "tools.hxx"

namespace slideshow
{
    namespace internal
    {
        typedef ::canvas::tools::ValueMap< AttributeType > AnimateAttributeMap;

        AttributeType mapAttributeName( const ::rtl::OUString& rAttrName )
        {
            /** Maps attribute name to AttributeType enum.

                String entries are all case-insensitive and MUST
                BE STORED lowercase.

                String entries MUST BE SORTED in ascending order!
            */
            static AnimateAttributeMap::MapEntry lcl_attributeMap[] =
                {
                    { "charcolor", ATTRIBUTE_CHAR_COLOR },

                    { "charfontname", ATTRIBUTE_CHAR_FONT_NAME },

                    { "charheight", ATTRIBUTE_CHAR_HEIGHT },

                    { "charposture", ATTRIBUTE_CHAR_POSTURE },

                    // TODO(Q1): This should prolly be changed in PPT import
                    // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
                    { "charrotation", ATTRIBUTE_ROTATE },

                    { "charunderline", ATTRIBUTE_CHAR_UNDERLINE },

                    { "charweight", ATTRIBUTE_CHAR_WEIGHT },

                    { "color", ATTRIBUTE_COLOR },

                    { "dimcolor", ATTRIBUTE_DIMCOLOR },

                    { "fillcolor", ATTRIBUTE_FILL_COLOR },

                    { "fillstyle", ATTRIBUTE_FILL_STYLE },

                    { "height", ATTRIBUTE_HEIGHT },

                    { "linecolor", ATTRIBUTE_LINE_COLOR },

                    { "linestyle", ATTRIBUTE_LINE_STYLE },

                    { "opacity", ATTRIBUTE_OPACITY },

                    { "rotate", ATTRIBUTE_ROTATE },

                    { "skewx", ATTRIBUTE_SKEW_X },

                    { "skewy", ATTRIBUTE_SKEW_Y },

                    { "visibility", ATTRIBUTE_VISIBILITY },

                    { "width", ATTRIBUTE_WIDTH },

                    { "x", ATTRIBUTE_POS_X },

                    { "y", ATTRIBUTE_POS_Y }
                };

            static AnimateAttributeMap aMap( lcl_attributeMap,
                                             sizeof(lcl_attributeMap)/sizeof(*lcl_attributeMap),
                                             false );

            AttributeType eAttributeType = ATTRIBUTE_INVALID;

            // determine the type from the attribute name
            if( !aMap.lookup( rAttrName,
                              eAttributeType ) )
            {
                OSL_TRACE( "mapAttributeName(): attribute name %s not found in map.",
                           ::rtl::OUStringToOString( rAttrName,
                                                     RTL_TEXTENCODING_ASCII_US ).getStr() );
                return ATTRIBUTE_INVALID;
            }

            return eAttributeType;
        }

    }
}
<|endoftext|>


<commit_before>#include "stdafx.h"

#include <string>
#include <iostream>

#include <HBTK/Plot3DParser.h>
#include <HBTK/Plot3DWriter.h>

void print_mesh_info(std::vector<HBTK::StructuredMeshBlock2D> mesh2d,
	std::vector<HBTK::StructuredMeshBlock3D> mesh3d, bool three_dimensional) {
	int n_blocks = (three_dimensional ? (int)mesh3d.size() : (int)mesh2d.size());
	std::cout << "Mesh info:\n";
	std::cout << "\t3D mesh:\t" << (three_dimensional ? "True" : "False") << "\n";
	std::cout << "\tNumber of blocks:\t" << n_blocks << "\n";
	std::cout << "\tBlock\ti\tj\tk\n";
	for (int n = 0; n < n_blocks; n++) {
		std::array<int, 3> idxs;
		if (three_dimensional) idxs = mesh3d[n].extent();
		if (!three_dimensional) {
			auto idxs2d = mesh2d[n].extent();
			idxs[0] = idxs2d[0];
			idxs[1] = idxs2d[1];
			idxs[2] = 1;
		}
		std::cout << "\t" << n << "\t" << idxs[0] << "\t" << idxs[1] << "\t" << idxs[2] << "\n";
	}
	std::cout << "\n";
	for (int n = 0; (n < n_blocks) && three_dimensional; n++) {
		std::cout << "\tBlock " << n << "\n";
		std::array<int, 3> extents = mesh3d[n].extent();
		int ei = extents[0];
		int ej = extents[1];
		int ek = extents[2];
		std::array<double, 3> coord;
		coord = mesh3d[n].coord({ 0, 0, 0 });
		std::cout << "\t\ti0,j0,k0:\t" << coord[0] << " " << coord[1] << " " << coord[2] << "\n";
		coord = mesh3d[n].coord({ei - 1, 0, 0});
		std::cout << "\t\tid,j0,k0:\t" << coord[0] << " " << coord[1] << " " << coord[2] << "\n";
		coord = mesh3d[n].coord({ 0, ej - 1, 0 });
		std::cout << "\t\ti0,jd,k0:\t" << coord[0] << " " << coord[1] << " " << coord[2] << "\n";
		coord = mesh3d[n].coord({ 0, 0, ek - 1 });
		std::cout << "\t\ti0,j0,kd:\t" << coord[0] << " " << coord[1] << " " << coord[2] << "\n";
		coord = mesh3d[n].coord({ ei - 1, ej - 1, ek - 1 });
		std::cout << "\t\tid,jd,kd:\t" << coord[0] << " " << coord[1] << " " << coord[2] << "\n\n";
	}
	std::cout << "\n";
	return;
}

void write_mesh_out_2d(std::vector<HBTK::StructuredMeshBlock2D> mesh2d, bool ascii,
	bool block_count, std::string path) {
	HBTK::Plot3D::Plot3DWriter writer;
	std::cout << "\nWriting to " << path << "\n";
	std::cout << "Writing 2D\n";
	std::cout << "Writing block count?\t" << block_count << "\n";
	std::cout << "ASCII?\t" << ascii << "\n";

	writer.three_dimensional = false;
	writer.write_binary = !ascii;
	writer.no_block_count = !block_count;
	for (auto & mesh : mesh2d) {
		writer.add_mesh_block2d(mesh);
	}
	writer.write(path);
}

void write_mesh_out_3d(std::vector<HBTK::StructuredMeshBlock3D> mesh3d, bool ascii,
	bool block_count, std::string path) {
	HBTK::Plot3D::Plot3DWriter writer;
	std::cout << "\nWriting to " << path << "\n";
	std::cout << "Writing 3D mesh.\n";
	std::cout << "Block count?\t" << (block_count ? "True" : "False") << "\n";
	std::cout << "ASCII?\t" << (ascii ? "True" : "False") << "\n";

	writer.three_dimensional = true;
	writer.write_binary = !ascii;
	writer.no_block_count = !block_count;
	for (auto & mesh : mesh3d) {
		writer.add_mesh_block3d(mesh);
	}
	writer.write(path);
}

void print_help() {
	std::cout << "Help:\n";
	std::cout << "This program reads in a Plot3D mesh, and can spit it out in a different format.\n";
	std::cout << "Usage: $PROGRAM inputfile.ext1 [optional outputfile.ext]\n";
	std::cout << "Flags:\n";
	std::cout << "\t-i\tindicates input file flag\n";
	std::cout << "\t-o\tindicates output file flat\n";
	std::cout << "\t-*a\tASCII file\n";
	std::cout << "\t-*b\tBinary file\n";
	std::cout << "\t-i3\t3D mesh (input file only)\n";
	std::cout << "\t-i2\t2D mesh (input file only)\n";
	std::cout << "\t-*n\tNo mesh block count\n";
	std::cout << "\t-oe\tExtrude a 2d input mesh to 3d (z=0, 1)\n";
	std::cout << "\t-sx\tSwitch the j,k local coordinates in mesh blocks in output files.\n";
	std::cout << "\t-sy\tSwitch the i,k local coordinates in mesh blocks in output files.\n";
	std::cout << "\t-sz\tSwitch the i,j local coordinates in mesh blocks in output files.\n";
	std::cout << "\n";
	return;
}

int parse_command_line(int argc, char *argv[], bool &ascii_in, bool &three_dimensional_in, bool &no_block_in,
 std::string &path_in,
	bool &ascii_out, bool &no_block_out, bool &extrude, std::string &path_out, int & swap_axis) {

	bool path_in_set = false;
	std::string arg; // For debugging...
	if (argc == 1) { print_help(); }
	for (int i = 1; i < argc; i++) {
		arg = argv[i];
		if (argv[i][0] == '-') {
			if (argv[i][1] == 'i') {
				switch (argv[i][2]) {
				case 'a':
					ascii_in = true;
					continue;
				case 'b':
					ascii_in = false;
					continue;
				case '3':
					three_dimensional_in = true;
					continue;
				case '2':
					three_dimensional_in = false;
					continue;
				case 'n':
					no_block_in = true;
					continue;
				default:
					return i;
				}
				continue;
			}
			else if (argv[i][1] == 'o') {
				switch (argv[i][2]) {
				case 'a':
					ascii_out = true;
					continue;
				case 'b':
					ascii_out = false;
					continue;
				case 'n':
					no_block_out = true;
					continue;
				case 'e':
					extrude = true;
					continue;
				default:
					return i;
				}
				continue;
			}
			else if (argv[i][1] == 's') {
				switch (argv[i][2]) {
				case 'x':
					swap_axis = 0;
					continue;
				case 'y':
					swap_axis = 1;
					continue;
				case 'z':
					swap_axis = 2;
					continue;
				default:
					return i;
				}
			}
			return i;
		}
		else {
			if (!path_in_set) {
				path_in = argv[i];
				path_in_set = true;
			}
			else {
				path_out = argv[i];
			}
		}
	}

	return 0;
}

int main(int argc, char *argv[])
{
	std::cout << "Plot3D demo\nHJA Bird 2018\n";

	std::string input_path, output_path;
	int swap_axis = -1;
	bool three_dimensional, ascii_in, no_block_count_in;
	bool extrude, ascii_out, no_bc_out;
	HBTK::Plot3D::Plot3DParser parser;
	std::vector<HBTK::StructuredMeshBlock2D> meshes_2d;
	std::vector<HBTK::StructuredMeshBlock3D> meshes_3d;
	ascii_in = ascii_out = three_dimensional = true;
	no_block_count_in = no_bc_out = extrude = false;

	if (int error_arg = parse_command_line(argc, argv, ascii_in, three_dimensional, no_block_count_in,
 input_path,
		ascii_out, no_bc_out, extrude, output_path, swap_axis)) {
		std::cout << "Error at arg " << error_arg << ".\n";
		std::cout << "\t>\t" << argv[error_arg] << "\n";
		print_help();
		return 1;
	}
	if (three_dimensional && extrude) {
		std::cout << "Input mesh is 3D - cannot be extruded.\n"; return 1;
	}

	parser.add_2D_block_function(
		[&](HBTK::StructuredMeshBlock2D mesh) { meshes_2d.emplace_back(mesh); return true; }
	);
	parser.add_3D_block_function(
		[&](HBTK::StructuredMeshBlock3D mesh) { meshes_3d.emplace_back(mesh); return true; }
	);

	parser.number_of_dimensions = (three_dimensional ? 3 : 2);
	parser.parse_as_binary = !ascii_in;
	parser.single_block = no_block_count_in;
	std::cout << "Input:\n" << input_path << "\n";

	try {
		parser.parse(input_path);
		print_mesh_info(meshes_2d, meshes_3d, three_dimensional);
	}
	catch (int i) {
		std::cout << "FAILED!\nDid you get the input flags right? Are you sure this file is good?\n";
		if (i > 0) {
			std::cout << "Error possibly around line " << i << "\n";
		}
		else {
			std::cout << "Error opening:\t" << input_path << "\n";
		}
		return -1;
	}
	catch (...) {
		std::cout << "FAILED for unknown reason. Did you get the input format flags right\n"
			"and are you sure the file is a good one?\n";
		return -1;
	}
	if (output_path != "") {
		if (extrude) {
			for (int n = 0; n < (int)meshes_2d.size(); n++) {
				meshes_3d.emplace_back(meshes_2d[n].extrude_to_3D({ 0, 1 }));
			}
		}
		if (swap_axis > -1) {
			for (int i = 0; i < (int)meshes_3d.size(); i++) {
				auto &mesh = meshes_3d[i];
				switch (swap_axis) {
				case 0:
					std::cout << "Switching j,k internal coordinates of block " << i << ".\n";
					mesh.swap_internal_coordinates_jk();
					continue;
				case 1:
					std::cout << "Switching i,k internal coordinates of block " << i << ".\n";
					mesh.swap_internal_coordinates_ik();
					continue;
				case 2:
					std::cout << "Switching i,j internal coordinates of block " << i << ".\n";
					mesh.swap_internal_coordinates_ij();
					continue;
				}
			}
		}

		if (three_dimensional || extrude) {
			write_mesh_out_3d(meshes_3d, ascii_out, !no_bc_out, output_path);
		}
		else {
			write_mesh_out_2d(meshes_2d, ascii_out, !no_bc_out, output_path);
		}
	}

    return 0;
}

<commit_msg>Prints same for ascii and binary now<commit_after>#include "stdafx.h"

#include <string>
#include <iostream>

#include <HBTK/Plot3DParser.h>
#include <HBTK/Plot3DWriter.h>

void print_mesh_info(std::vector<HBTK::StructuredMeshBlock2D> mesh2d,
	std::vector<HBTK::StructuredMeshBlock3D> mesh3d, bool three_dimensional) {
	int n_blocks = (three_dimensional ? (int)mesh3d.size() : (int)mesh2d.size());
	std::cout << "\t3D mesh:\t" << (three_dimensional ? "True" : "False") << "\n";
	std::cout << "\tNumber of blocks:\t" << n_blocks << "\n";
	std::cout << "\tBlock\ti\tj\tk\n";
	for (int n = 0; n < n_blocks; n++) {
		std::array<int, 3> idxs;
		if (three_dimensional) idxs = mesh3d[n].extent();
		if (!three_dimensional) {
			auto idxs2d = mesh2d[n].extent();
			idxs[0] = idxs2d[0];
			idxs[1] = idxs2d[1];
			idxs[2] = 1;
		}
		std::cout << "\t" << n+1 << "\t" << idxs[0] << "\t" << idxs[1] << "\t" << idxs[2] << "\n";
	}
	std::cout << "\n";
	for (int n = 0; n < n_blocks; n++) {
		std::cout << "\tBlock " << n+1 << "\n";
		std::array<int, 3> extents = { 1, 1, 1 };
		if (three_dimensional) {
			extents = mesh3d[n].extent();
		}
		else {
			extents = { mesh2d[n].extent()[0], mesh2d[n].extent()[1], 1 };
		}
		int ei = extents[0];
		int ej = extents[1];
		int ek = extents[2];
		auto get_coord = [&](std::array<int, 3> c) {
			if (three_dimensional) {
				return mesh3d[n].coord(c);
			}
			else {
				std::array<double, 2> coord2d = mesh2d[n].coord({c[0], c[1]});
				return std::array<double, 3>({ coord2d[0], coord2d[1], coord2d[2] });
			}
		};

		std::array<double, 3> coord;
		coord = get_coord({ 0, 0, 0 });
		std::cout << "\t\ti0,j0,k0:\t" << coord[0] << " " << coord[1] << " " << coord[2] << "\n";
		coord = get_coord({ei - 1, 0, 0});
		std::cout << "\t\tid,j0,k0:\t" << coord[0] << " " << coord[1] << " " << coord[2] << "\n";
		coord = get_coord({ 0, ej - 1, 0 });
		std::cout << "\t\ti0,jd,k0:\t" << coord[0] << " " << coord[1] << " " << coord[2] << "\n";
		coord = get_coord({ 0, 0, ek - 1 });
		std::cout << "\t\ti0,j0,kd:\t" << coord[0] << " " << coord[1] << " " << coord[2] << "\n";
		coord = get_coord({ ei - 1, ej - 1, ek - 1 });
		std::cout << "\t\tid,jd,kd:\t" << coord[0] << " " << coord[1] << " " << coord[2] << "\n\n";
	}
	std::cout << "\n";
	return;
}

void write_mesh_out_2d(std::vector<HBTK::StructuredMeshBlock2D> mesh2d, bool ascii,
	bool block_count, std::string path) {
	HBTK::Plot3D::Plot3DWriter writer;
	std::cout << "\nWriting to " << path << "\n";
	std::cout << "Writing 2D\n";
	std::cout << "Writing block count?\t" << block_count << "\n";
	std::cout << "ASCII?\t" << ascii << "\n";

	writer.three_dimensional = false;
	writer.write_binary = !ascii;
	writer.no_block_count = !block_count;
	for (auto & mesh : mesh2d) {
		writer.add_mesh_block2d(mesh);
	}
	writer.write(path);
}

void write_mesh_out_3d(std::vector<HBTK::StructuredMeshBlock3D> mesh3d, bool ascii,
	bool block_count, std::string path) {
	HBTK::Plot3D::Plot3DWriter writer;
	std::cout << "\nWriting to " << path << "\n";
	std::cout << "Writing 3D mesh.\n";
	std::cout << "Block count?\t" << (block_count ? "True" : "False") << "\n";
	std::cout << "ASCII?\t" << (ascii ? "True" : "False") << "\n";

	writer.three_dimensional = true;
	writer.write_binary = !ascii;
	writer.no_block_count = !block_count;
	for (auto & mesh : mesh3d) {
		writer.add_mesh_block3d(mesh);
	}
	writer.write(path);
}

void print_help() {
	std::cout << "Plot3D parser demo - HJAB 2018\n";
	std::cout << "Help:\n";
	std::cout << "This program reads in a Plot3D mesh, and can spit it out in a different format.\n";
	std::cout << "Usage: $PROGRAM inputfile.ext1 [optional outputfile.ext]\n";
	std::cout << "Flags:\n";
	std::cout << "\t-i\tindicates input file flag\n";
	std::cout << "\t-o\tindicates output file flat\n";
	std::cout << "\t-*a\tASCII file\n";
	std::cout << "\t-*b\tBinary file\n";
	std::cout << "\t-i3\t3D mesh (input file only)\n";
	std::cout << "\t-i2\t2D mesh (input file only)\n";
	std::cout << "\t-*n\tNo mesh block count\n";
	std::cout << "\t-oe\tExtrude a 2d input mesh to 3d (z=0, 1)\n";
	std::cout << "\t-sx\tSwitch the j,k local coordinates in mesh blocks in output files.\n";
	std::cout << "\t-sy\tSwitch the i,k local coordinates in mesh blocks in output files.\n";
	std::cout << "\t-sz\tSwitch the i,j local coordinates in mesh blocks in output files.\n";
	std::cout << "\n";
	return;
}

int parse_command_line(int argc, char *argv[], bool &ascii_in, bool &three_dimensional_in, bool &no_block_in,
 std::string &path_in,
	bool &ascii_out, bool &no_block_out, bool &extrude, std::string &path_out, int & swap_axis) {

	bool path_in_set = false;
	std::string arg; // For debugging...
	if (argc == 1) { print_help(); }
	for (int i = 1; i < argc; i++) {
		arg = argv[i];
		if (argv[i][0] == '-') {
			if (argv[i][1] == 'i') {
				switch (argv[i][2]) {
				case 'a':
					ascii_in = true;
					continue;
				case 'b':
					ascii_in = false;
					continue;
				case '3':
					three_dimensional_in = true;
					continue;
				case '2':
					three_dimensional_in = false;
					continue;
				case 'n':
					no_block_in = true;
					continue;
				default:
					return i;
				}
				continue;
			}
			else if (argv[i][1] == 'o') {
				switch (argv[i][2]) {
				case 'a':
					ascii_out = true;
					continue;
				case 'b':
					ascii_out = false;
					continue;
				case 'n':
					no_block_out = true;
					continue;
				case 'e':
					extrude = true;
					continue;
				default:
					return i;
				}
				continue;
			}
			else if (argv[i][1] == 's') {
				switch (argv[i][2]) {
				case 'x':
					swap_axis = 0;
					continue;
				case 'y':
					swap_axis = 1;
					continue;
				case 'z':
					swap_axis = 2;
					continue;
				default:
					return i;
				}
			}
			return i;
		}
		else {
			if (!path_in_set) {
				path_in = argv[i];
				path_in_set = true;
			}
			else {
				path_out = argv[i];
			}
		}
	}

	return 0;
}

int main(int argc, char *argv[])
{
	std::string input_path, output_path;
	int swap_axis = -1;
	bool three_dimensional, ascii_in, no_block_count_in;
	bool extrude, ascii_out, no_bc_out;
	HBTK::Plot3D::Plot3DParser parser;
	std::vector<HBTK::StructuredMeshBlock2D> meshes_2d;
	std::vector<HBTK::StructuredMeshBlock3D> meshes_3d;
	ascii_in = ascii_out = three_dimensional = true;
	no_block_count_in = no_bc_out = extrude = false;

	if (int error_arg = parse_command_line(argc, argv, ascii_in, three_dimensional, no_block_count_in,
 input_path,
		ascii_out, no_bc_out, extrude, output_path, swap_axis)) {
		std::cout << "Error at arg " << error_arg << ".\n";
		std::cout << "\t>\t" << argv[error_arg] << "\n";
		print_help();
		return 1;
	}
	if (three_dimensional && extrude) {
		std::cout << "Input mesh is 3D - cannot be extruded.\n"; return 1;
	}

	parser.add_2D_block_function(
		[&](HBTK::StructuredMeshBlock2D mesh) { meshes_2d.emplace_back(mesh); return true; }
	);
	parser.add_3D_block_function(
		[&](HBTK::StructuredMeshBlock3D mesh) { meshes_3d.emplace_back(mesh); return true; }
	);

	parser.number_of_dimensions = (three_dimensional ? 3 : 2);
	parser.parse_as_binary = !ascii_in;
	parser.single_block = no_block_count_in;
	std::cout << "Input:\n" << input_path << "\n";

	try {
		parser.parse(input_path);
		std::cout << "Mesh information:\n";
		std::cout << "\tIs ASCII:\t" << (ascii_in ? "TRUE" : "FALSE") << "\n";
		std::cout << "\tInclude block count:\t" << (!no_block_count_in ? "TRUE" : "FALSE") << "\n";
		print_mesh_info(meshes_2d, meshes_3d, three_dimensional);
	}
	catch (int i) {
		std::cout << "FAILED!\nDid you get the input flags right? Are you sure this file is good?\n";
		if (i > 0) {
			std::cout << "Error possibly around line " << i << "\n";
		}
		else {
			std::cout << "Error opening:\t" << input_path << "\n";
		}
		return -1;
	}
	catch (...) {
		std::cout << "FAILED for unknown reason. Did you get the input format flags right\n"
			"and are you sure the file is a good one?\n";
		return -1;
	}
	if (output_path != "") {
		if (extrude) {
			for (int n = 0; n < (int)meshes_2d.size(); n++) {
				meshes_3d.emplace_back(meshes_2d[n].extrude_to_3D({ 0, 1 }));
			}
		}
		if (swap_axis > -1) {
			for (int i = 0; i < (int)meshes_3d.size(); i++) {
				auto &mesh = meshes_3d[i];
				switch (swap_axis) {
				case 0:
					std::cout << "Switching j,k internal coordinates of block " << i << ".\n";
					mesh.swap_internal_coordinates_jk();
					continue;
				case 1:
					std::cout << "Switching i,k internal coordinates of block " << i << ".\n";
					mesh.swap_internal_coordinates_ik();
					continue;
				case 2:
					std::cout << "Switching i,j internal coordinates of block " << i << ".\n";
					mesh.swap_internal_coordinates_ij();
					continue;
				}
			}
		}

		if (three_dimensional || extrude) {
			write_mesh_out_3d(meshes_3d, ascii_out, !no_bc_out, output_path);
		}
		else {
			write_mesh_out_2d(meshes_2d, ascii_out, !no_bc_out, output_path);
		}
	}

    return 0;
}

<|endoftext|>


<commit_before>#ifndef TESTLEVEL
#define TESTLEVEL

#include <Annwvyn.h>
#include "DemoUtils.hpp"
using namespace Annwvyn;

//Custom object:
class Sinbad : public AnnGameObject
{
public:
	void postInit()
	{
		setPosition(0, 0, -5);
		setScale(0.2f, 0.2f, 0.2f);
		setAnimation("Dance");
		playAnimation(true);
		loopAnimation(true);
		setUpPhysics(40, phyShapeType::boxShape);
	}

	void atRefresh()
	{
		//AnnDebug() << "Sinbad position is : " << getPosition();
		//AnnDebug() << getName();
	}
};

class TestLevel : LEVEL
{
public:
	///Construct the Level :
	void load()
	{
		AnnGetEventManager()->addListener(goBackListener = make_shared<GoBackToDemoHub>());
		//Set some ambient light
		AnnGetSceneryManager()->setAmbientLight(AnnColor(.6f, .6f, .6f));

		//We add our brand new 3D object
		auto MyObject = addGameObject("MyObject.mesh");
		MyObject->setPosition(5, 1, 0);//We put it 5 meters to the right, and 1 meter up...
		//MyObject->setUpPhysics(); // <---- This activate the physics for the object as static geometry
		MyObject->setUpPhysics(100, convexShape); // <------- this activate the physics as a dynamic object. We need to tell the shape approximation to use. and a mass in Kg

		//The shape approximation is put at the Object CENTER POINT. The CENTER POINT should be at the object's bounding box CENTER before exporting from blender.

		auto text = std::make_shared<Ann3DTextPlane>(1.0f, 0.5f, "Accent test: '' Hello, Virtual World!\nthis is one line only one line only", 128, 96.0f, "LibSerif", "LiberationSerif-regular.ttf");
		//text->setTextAlign(text->ALIGN_CENTER);
		text->setBackgroundColor(AnnColor(0, 1, 0));
		text->setPosition({ 0, 0.5f, -1 });
		text->setBackgroundImage("background.png");
		text->setMargin(0.1f);

		text->update();
		addManualMovableObject(text);

		//Add other source of light
		auto Sun = addLightObject();
		Sun->setType(AnnLightObject::ANN_LIGHT_DIRECTIONAL);
		Sun->setDirection(AnnVect3::NEGATIVE_UNIT_Y + 1.5f* AnnVect3::NEGATIVE_UNIT_Z);

		//Create objects and register them as content of the level
		auto S = AnnGetGameObjectManager()->createGameObject("Sinbad.mesh", "SuperSinbad", std::make_shared<Sinbad>());
		levelContent.push_back(S);
		S->playSound("media/monster.wav", true, 1);
		S->attachScript("DummyBehavior");

		//Add water
		auto Water = addGameObject("environment/Water.mesh");

		//Add the island
		auto Island = addGameObject("environment/Island.mesh");
		Island->setUpPhysics();

		//Add the sign
		auto Sign(addGameObject("environment/Sign.mesh"));
		Sign->setPosition(1, -0, -2);
		Sign->setUpPhysics(0, phyShapeType::staticShape);
		Sign->setOrientation(Ogre::Quaternion(Ogre::Degree(-45), Ogre::Vector3::UNIT_Y));

		auto t(AnnGetGameObjectManager()->createTriggerObject(std::make_shared<AnnAlignedBoxTriggerObject>()));
		dynamic_cast<AnnAlignedBoxTriggerObject*>(t.get())->setBoundaries(-1, 1, -1, 1, -1, 1);
		levelTrigger.push_back(t);

		//Put some music here
		AnnGetAudioEngine()->playBGM("media/bgm/bensound-happyrock.ogg", 0.4);

		//Place the starting point
		AnnGetPlayer()->setPosition(AnnVect3::ZERO);
		AnnGetPlayer()->setOrientation(Ogre::Euler(0));
		AnnGetPlayer()->resetPlayerPhysics();
	}

	void unload()
	{
		AnnGetEventManager()->removeListener(goBackListener);

		//Do the normal unloading
		AnnLevel::unload();
	}

	void runLogic()
	{
	}

private:
	std::shared_ptr<GoBackToDemoHub> goBackListener;
};

class PhysicsDebugLevel : LEVEL
{
	void load()
	{
		AnnGetSceneryManager()->setWorldBackgroundColor(AnnColor(0, 0, 0));
		AnnGetPhysicsEngine()->getWorld()->setGravity(btVector3(0, 0, 0));
		AnnGetPlayer()->setPosition(AnnVect3::ZERO);
		AnnGetPlayer()->resetPlayerPhysics();
	}

	void runLogic()
	{
		AnnDebug() << "Player position is : " << AnnGetPlayer()->getPosition();
	}
};

#endif //TESTLEVEL<commit_msg>attach dummy script to other object of the level<commit_after>#ifndef TESTLEVEL
#define TESTLEVEL

#include <Annwvyn.h>
#include "DemoUtils.hpp"
using namespace Annwvyn;

//Custom object:
class Sinbad : public AnnGameObject
{
public:
	void postInit()
	{
		setPosition(0, 0, -5);
		setScale(0.2f, 0.2f, 0.2f);
		setAnimation("Dance");
		playAnimation(true);
		loopAnimation(true);
		setUpPhysics(40, phyShapeType::boxShape);
	}

	void atRefresh()
	{
		//AnnDebug() << "Sinbad position is : " << getPosition();
		//AnnDebug() << getName();
	}
};

class TestLevel : LEVEL
{
public:
	///Construct the Level :
	void load()
	{
		AnnGetEventManager()->addListener(goBackListener = make_shared<GoBackToDemoHub>());
		//Set some ambient light
		AnnGetSceneryManager()->setAmbientLight(AnnColor(.6f, .6f, .6f));

		//We add our brand new 3D object
		auto MyObject = addGameObject("MyObject.mesh");
		MyObject->setPosition(5, 1, 0);//We put it 5 meters to the right, and 1 meter up...
		//MyObject->setUpPhysics(); // <---- This activate the physics for the object as static geometry
		MyObject->setUpPhysics(100, convexShape); // <------- this activate the physics as a dynamic object. We need to tell the shape approximation to use. and a mass in Kg
		MyObject->attachScript("DummyBehavior");
		//The shape approximation is put at the Object CENTER POINT. The CENTER POINT should be at the object's bounding box CENTER before exporting from blender.

		auto text = std::make_shared<Ann3DTextPlane>(1.0f, 0.5f, "Accent test: '' Hello, Virtual World!\nthis is one line only one line only", 128, 96.0f, "LibSerif", "LiberationSerif-regular.ttf");
		//text->setTextAlign(text->ALIGN_CENTER);
		text->setBackgroundColor(AnnColor(0, 1, 0));
		text->setPosition({ 0, 0.5f, -1 });
		text->setBackgroundImage("background.png");
		text->setMargin(0.1f);

		text->update();
		addManualMovableObject(text);

		//Add other source of light
		auto Sun = addLightObject();
		Sun->setType(AnnLightObject::ANN_LIGHT_DIRECTIONAL);
		Sun->setDirection(AnnVect3::NEGATIVE_UNIT_Y + 1.5f* AnnVect3::NEGATIVE_UNIT_Z);

		//Create objects and register them as content of the level
		auto S = AnnGetGameObjectManager()->createGameObject("Sinbad.mesh", "SuperSinbad", std::make_shared<Sinbad>());
		levelContent.push_back(S);
		S->playSound("media/monster.wav", true, 1);
		S->attachScript("DummyBehavior");

		//Add water
		auto Water = addGameObject("environment/Water.mesh");

		//Add the island
		auto Island = addGameObject("environment/Island.mesh");
		Island->setUpPhysics();

		//Add the sign
		auto Sign(addGameObject("environment/Sign.mesh"));
		Sign->setPosition(1, -0, -2);
		Sign->setUpPhysics(0, phyShapeType::staticShape);
		Sign->setOrientation(Ogre::Quaternion(Ogre::Degree(-45), Ogre::Vector3::UNIT_Y));

		auto t(AnnGetGameObjectManager()->createTriggerObject(std::make_shared<AnnAlignedBoxTriggerObject>()));
		dynamic_cast<AnnAlignedBoxTriggerObject*>(t.get())->setBoundaries(-1, 1, -1, 1, -1, 1);
		levelTrigger.push_back(t);

		//Put some music here
		AnnGetAudioEngine()->playBGM("media/bgm/bensound-happyrock.ogg", 0.4);

		//Place the starting point
		AnnGetPlayer()->setPosition(AnnVect3::ZERO);
		AnnGetPlayer()->setOrientation(Ogre::Euler(0));
		AnnGetPlayer()->resetPlayerPhysics();
	}

	void unload()
	{
		AnnGetEventManager()->removeListener(goBackListener);

		//Do the normal unloading
		AnnLevel::unload();
	}

	void runLogic()
	{
	}

private:
	std::shared_ptr<GoBackToDemoHub> goBackListener;
};

class PhysicsDebugLevel : LEVEL
{
	void load()
	{
		AnnGetSceneryManager()->setWorldBackgroundColor(AnnColor(0, 0, 0));
		AnnGetPhysicsEngine()->getWorld()->setGravity(btVector3(0, 0, 0));
		AnnGetPlayer()->setPosition(AnnVect3::ZERO);
		AnnGetPlayer()->resetPlayerPhysics();
	}

	void runLogic()
	{
		AnnDebug() << "Player position is : " << AnnGetPlayer()->getPosition();
	}
};

#endif //TESTLEVEL<|endoftext|>


<commit_before>/// \file
/// \ingroup tutorial_tmva
/// \notebook -nodraw
/// This macro provides a simple example on how to use the trained regression MVAs
/// within an analysis module
///
///  - Project   : TMVA - a Root-integrated toolkit for multivariate data analysis
///  - Package   : TMVA
///  - Exectuable: TMVARegressionApplication
///
/// \macro_output
/// \macro_code
/// \author Andreas Hoecker

#include <cstdlib>
#include <vector>
#include <iostream>
#include <map>
#include <string>

#include "TFile.h"
#include "TTree.h"
#include "TString.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TStopwatch.h"

#include "TMVA/Tools.h"
#include "TMVA/Reader.h"

using namespace TMVA;

void TMVARegressionApplication( TString myMethodList = "" )
{
   //---------------------------------------------------------------
   // This loads the library
   TMVA::Tools::Instance();

   // Default MVA methods to be trained + tested
   std::map<std::string,int> Use;

   // --- Mutidimensional likelihood and Nearest-Neighbour methods
   Use["PDERS"]           = 0;
   Use["PDEFoam"]         = 1;
   Use["KNN"]             = 1;
   //
   // --- Linear Discriminant Analysis
   Use["LD"]		        = 1;
   //
   // --- Function Discriminant analysis
   Use["FDA_GA"]          = 1;
   Use["FDA_MC"]          = 0;
   Use["FDA_MT"]          = 0;
   Use["FDA_GAMT"]        = 0;
   //
   // --- Neural Network
   Use["MLP"] = 1;
   //
   // --- Deep Neural Networks
   Use["DNN_CPU"] = 1;
   //
   // --- Support Vector Machine
   Use["SVM"]             = 0;
   //
   // --- Boosted Decision Trees
   Use["BDT"]             = 0;
   Use["BDTG"]            = 1;
   // ---------------------------------------------------------------

   std::cout << std::endl;
   std::cout << "==> Start TMVARegressionApplication" << std::endl;

   // Select methods (don't look at this code - not of interest)
   if (myMethodList != "") {
      for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) it->second = 0;

      std::vector<TString> mlist = gTools().SplitString( myMethodList, ',' );
      for (UInt_t i=0; i<mlist.size(); i++) {
         std::string regMethod(mlist[i]);

         if (Use.find(regMethod) == Use.end()) {
            std::cout << "Method \"" << regMethod << "\" not known in TMVA under this name. Choose among the following:" << std::endl;
            for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) std::cout << it->first << " ";
            std::cout << std::endl;
            return;
         }
         Use[regMethod] = 1;
      }
   }

   // --------------------------------------------------------------------------------------------------

   // --- Create the Reader object

   TMVA::Reader *reader = new TMVA::Reader( "!Color:!Silent" );

   // Create a set of variables and declare them to the reader
   // - the variable names MUST corresponds in name and type to those given in the weight file(s) used
   Float_t var1, var2;
   reader->AddVariable( "var1", &var1 );
   reader->AddVariable( "var2", &var2 );

   // Spectator variables declared in the training have to be added to the reader, too
   Float_t spec1,spec2;
   reader->AddSpectator( "spec1:=var1*2",  &spec1 );
   reader->AddSpectator( "spec2:=var1*3",  &spec2 );

   // --- Book the MVA methods

   TString dir    = "dataset/weights/";
   TString prefix = "TMVARegression";

   // Book method(s)
   for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) {
      if (it->second) {
         TString methodName = it->first + " method";
         TString weightfile = dir + prefix + "_" + TString(it->first) + ".weights.xml";
         reader->BookMVA( methodName, weightfile );
      }
   }

   // Book output histograms
   TH1* hists[100];
   Int_t nhists = -1;
   for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) {
      TH1* h = new TH1F( it->first.c_str(), TString(it->first) + " method", 100, -100, 600 );
      if (it->second) hists[++nhists] = h;
   }
   nhists++;

   // Prepare input tree (this must be replaced by your data source)
   // in this example, there is a toy tree with signal and one with background events
   // we'll later on use only the "signal" events for the test in this example.
   //
   TFile *input(0);
   TString fname = "./tmva_reg_example.root";
   if (!gSystem->AccessPathName( fname )) {
      input = TFile::Open( fname ); // check if file in local directory exists
   }
   else {
      TFile::SetCacheFileDir(".");
      input = TFile::Open("http://root.cern.ch/files/tmva_reg_example.root", "CACHEREAD"); // if not: download from ROOT server
   }
   if (!input) {
      std::cout << "ERROR: could not open data file" << std::endl;
      exit(1);
   }
   std::cout << "--- TMVARegressionApp        : Using input file: " << input->GetName() << std::endl;

   // --- Event loop

   // Prepare the tree
   // - here the variable names have to corresponds to your tree
   // - you can use the same variables as above which is slightly faster,
   //   but of course you can use different ones and copy the values inside the event loop
   //
   TTree* theTree = (TTree*)input->Get("TreeR");
   std::cout << "--- Select signal sample" << std::endl;
   theTree->SetBranchAddress( "var1", &var1 );
   theTree->SetBranchAddress( "var2", &var2 );

   std::cout << "--- Processing: " << theTree->GetEntries() << " events" << std::endl;
   TStopwatch sw;
   sw.Start();
   for (Long64_t ievt=0; ievt<theTree->GetEntries();ievt++) {

      if (ievt%1000 == 0) {
         std::cout << "--- ... Processing event: " << ievt << std::endl;
      }

      theTree->GetEntry(ievt);

      // Retrieve the MVA target values (regression outputs) and fill into histograms
      // NOTE: EvaluateRegression(..) returns a vector for multi-target regression

      for (Int_t ih=0; ih<nhists; ih++) {
         TString title = hists[ih]->GetTitle();
         Float_t val = (reader->EvaluateRegression( title ))[0];
         hists[ih]->Fill( val );
      }
   }
   sw.Stop();
   std::cout << "--- End of event loop: "; sw.Print();

   // --- Write histograms

   TFile *target  = new TFile( "TMVARegApp.root","RECREATE" );
   for (Int_t ih=0; ih<nhists; ih++) hists[ih]->Write();
   target->Close();

   std::cout << "--- Created root file: \"" << target->GetName()
             << "\" containing the MVA output histograms" << std::endl;

   delete reader;

   std::cout << "==> TMVARegressionApplication is done!" << std::endl << std::endl;
}

int main( int argc, char** argv )
{
   // Select methods (don't look at this code - not of interest)
   TString methodList;
   for (int i=1; i<argc; i++) {
      TString regMethod(argv[i]);
      if(regMethod=="-b" || regMethod=="--batch") continue;
      if (!methodList.IsNull()) methodList += TString(",");
      methodList += regMethod;
   }
   TMVARegressionApplication(methodList);
   return 0;
}
<commit_msg>Fix TMVARegression and Application not using the same default config<commit_after>/// \file
/// \ingroup tutorial_tmva
/// \notebook -nodraw
/// This macro provides a simple example on how to use the trained regression MVAs
/// within an analysis module
///
///  - Project   : TMVA - a Root-integrated toolkit for multivariate data analysis
///  - Package   : TMVA
///  - Exectuable: TMVARegressionApplication
///
/// \macro_output
/// \macro_code
/// \author Andreas Hoecker

#include <cstdlib>
#include <vector>
#include <iostream>
#include <map>
#include <string>

#include "TFile.h"
#include "TTree.h"
#include "TString.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TStopwatch.h"

#include "TMVA/Tools.h"
#include "TMVA/Reader.h"

using namespace TMVA;

void TMVARegressionApplication( TString myMethodList = "" )
{
   //---------------------------------------------------------------
   // This loads the library
   TMVA::Tools::Instance();

   // Default MVA methods to be trained + tested
   std::map<std::string,int> Use;

   // --- Mutidimensional likelihood and Nearest-Neighbour methods
   Use["PDERS"]           = 0;
   Use["PDEFoam"]         = 1;
   Use["KNN"]             = 1;
   //
   // --- Linear Discriminant Analysis
   Use["LD"]		        = 1;
   //
   // --- Function Discriminant analysis
   Use["FDA_GA"]          = 1;
   Use["FDA_MC"]          = 0;
   Use["FDA_MT"]          = 0;
   Use["FDA_GAMT"]        = 0;
   //
   // --- Neural Network
   Use["MLP"] = 1;
   Use["DNN_CPU"] = 0;
   //
   // --- Support Vector Machine
   Use["SVM"]             = 0;
   //
   // --- Boosted Decision Trees
   Use["BDT"]             = 0;
   Use["BDTG"]            = 1;
   // ---------------------------------------------------------------

   std::cout << std::endl;
   std::cout << "==> Start TMVARegressionApplication" << std::endl;

   // Select methods (don't look at this code - not of interest)
   if (myMethodList != "") {
      for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) it->second = 0;

      std::vector<TString> mlist = gTools().SplitString( myMethodList, ',' );
      for (UInt_t i=0; i<mlist.size(); i++) {
         std::string regMethod(mlist[i]);

         if (Use.find(regMethod) == Use.end()) {
            std::cout << "Method \"" << regMethod << "\" not known in TMVA under this name. Choose among the following:" << std::endl;
            for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) std::cout << it->first << " ";
            std::cout << std::endl;
            return;
         }
         Use[regMethod] = 1;
      }
   }

   // --------------------------------------------------------------------------------------------------

   // --- Create the Reader object

   TMVA::Reader *reader = new TMVA::Reader( "!Color:!Silent" );

   // Create a set of variables and declare them to the reader
   // - the variable names MUST corresponds in name and type to those given in the weight file(s) used
   Float_t var1, var2;
   reader->AddVariable( "var1", &var1 );
   reader->AddVariable( "var2", &var2 );

   // Spectator variables declared in the training have to be added to the reader, too
   Float_t spec1,spec2;
   reader->AddSpectator( "spec1:=var1*2",  &spec1 );
   reader->AddSpectator( "spec2:=var1*3",  &spec2 );

   // --- Book the MVA methods

   TString dir    = "dataset/weights/";
   TString prefix = "TMVARegression";

   // Book method(s)
   for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) {
      if (it->second) {
         TString methodName = it->first + " method";
         TString weightfile = dir + prefix + "_" + TString(it->first) + ".weights.xml";
         reader->BookMVA( methodName, weightfile );
      }
   }

   // Book output histograms
   TH1* hists[100];
   Int_t nhists = -1;
   for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) {
      TH1* h = new TH1F( it->first.c_str(), TString(it->first) + " method", 100, -100, 600 );
      if (it->second) hists[++nhists] = h;
   }
   nhists++;

   // Prepare input tree (this must be replaced by your data source)
   // in this example, there is a toy tree with signal and one with background events
   // we'll later on use only the "signal" events for the test in this example.
   //
   TFile *input(0);
   TString fname = "./tmva_reg_example.root";
   if (!gSystem->AccessPathName( fname )) {
      input = TFile::Open( fname ); // check if file in local directory exists
   }
   else {
      TFile::SetCacheFileDir(".");
      input = TFile::Open("http://root.cern.ch/files/tmva_reg_example.root", "CACHEREAD"); // if not: download from ROOT server
   }
   if (!input) {
      std::cout << "ERROR: could not open data file" << std::endl;
      exit(1);
   }
   std::cout << "--- TMVARegressionApp        : Using input file: " << input->GetName() << std::endl;

   // --- Event loop

   // Prepare the tree
   // - here the variable names have to corresponds to your tree
   // - you can use the same variables as above which is slightly faster,
   //   but of course you can use different ones and copy the values inside the event loop
   //
   TTree* theTree = (TTree*)input->Get("TreeR");
   std::cout << "--- Select signal sample" << std::endl;
   theTree->SetBranchAddress( "var1", &var1 );
   theTree->SetBranchAddress( "var2", &var2 );

   std::cout << "--- Processing: " << theTree->GetEntries() << " events" << std::endl;
   TStopwatch sw;
   sw.Start();
   for (Long64_t ievt=0; ievt<theTree->GetEntries();ievt++) {

      if (ievt%1000 == 0) {
         std::cout << "--- ... Processing event: " << ievt << std::endl;
      }

      theTree->GetEntry(ievt);

      // Retrieve the MVA target values (regression outputs) and fill into histograms
      // NOTE: EvaluateRegression(..) returns a vector for multi-target regression

      for (Int_t ih=0; ih<nhists; ih++) {
         TString title = hists[ih]->GetTitle();
         Float_t val = (reader->EvaluateRegression( title ))[0];
         hists[ih]->Fill( val );
      }
   }
   sw.Stop();
   std::cout << "--- End of event loop: "; sw.Print();

   // --- Write histograms

   TFile *target  = new TFile( "TMVARegApp.root","RECREATE" );
   for (Int_t ih=0; ih<nhists; ih++) hists[ih]->Write();
   target->Close();

   std::cout << "--- Created root file: \"" << target->GetName()
             << "\" containing the MVA output histograms" << std::endl;

   delete reader;

   std::cout << "==> TMVARegressionApplication is done!" << std::endl << std::endl;
}

int main( int argc, char** argv )
{
   // Select methods (don't look at this code - not of interest)
   TString methodList;
   for (int i=1; i<argc; i++) {
      TString regMethod(argv[i]);
      if(regMethod=="-b" || regMethod=="--batch") continue;
      if (!methodList.IsNull()) methodList += TString(",");
      methodList += regMethod;
   }
   TMVARegressionApplication(methodList);
   return 0;
}
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
//
// "Copyright Centre National d'Etudes Spatiales"
//
// License:  LGPL-2
//
// See LICENSE.txt file in the top level directory for more details.
//
//----------------------------------------------------------------------------
// $Id$

#include <ossimSentinel1SarSensorModel.h>
#include <ossim/base/ossimXmlDocument.h>
#include <ossimXmlTools.h>

namespace {// Anonymous namespace
    const ossimString attAzimuthTime      = "azimuthTime";
    const ossimString attFirstValidSample = "firstValidSample";
    const ossimString attGr0              = "gr0";
    const ossimString attGrsrCoefficients = "grsrCoefficients";
    const ossimString attHeight           = "height";
    const ossimString attLatitude         = "latitude";
    const ossimString attLine             = "line";
    const ossimString attLongitude        = "longitude";
    const ossimString attPixel            = "pixel";
    const ossimString attPosition         = "position";
    const ossimString attSlantRangeTime   = "slantRangeTime";
    const ossimString attSr0              = "sr0";
    const ossimString attSrgrCoefficients = "srgrCoefficients";
    const ossimString attTime             = "time";
    const ossimString attVelocity         = "velocity";
    const ossimString attX                = "x";
    const ossimString attY                = "y";
    const ossimString attZ                = "z";
}// Anonymous namespace

#if defined(USE_BOOST_TIME)
            using boost::posix_time::microseconds;
            using boost::posix_time::seconds;
#else
            using ossimplugins::time::microseconds;
            using ossimplugins::time::seconds;
#endif
void ossimplugins::ossimSentinel1SarSensorModel::readCoordinates(
        ossimXmlDocument const& xmlDoc, ossimString const& xpath,
        ossimString const& rg0_xpath, ossimString const& coeffs_xpath,
        std::vector<CoordinateConversionRecordType> & outputRecords)
{
   std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
   xmlDoc.findNodes(xpath, xnodes);

   for(std::vector<ossimRefPtr<ossimXmlNode> >::iterator itNode = xnodes.begin(); itNode!=xnodes.end();++itNode)
   {
      CoordinateConversionRecordType coordRecord;

      coordRecord.azimuthTime = getTimeFromFirstNode(**itNode, attAzimuthTime);

      coordRecord.rg0 = getDoubleFromFirstNode(**itNode, rg0_xpath);;

      ossimString const& s = getTextFromFirstNode(**itNode, coeffs_xpath);
      std::vector<ossimString> ssplit = s.split(" ");

      if (ssplit.empty())
      {
         throw std::runtime_error(("The "+rg0_xpath+" record has an empty coef vector").string());
      }
      for (std::vector<ossimString>::const_iterator cIt = ssplit.begin(), e = ssplit.end()
            ; cIt != e
            ; ++cIt
          )
      {
         coordRecord.coefs.push_back(cIt->toDouble());
      }
      assert(!coordRecord.coefs.empty()&&"The rg0 record has empty coefs vector.");

      outputRecords.push_back(coordRecord);
   }
}

namespace ossimplugins
{
void ossimSentinel1SarSensorModel::readAnnotationFile(const std::string & annotationXml)
{
    ossimRefPtr<ossimXmlDocument> xmlDoc = new ossimXmlDocument(annotationXml);
    const ossimXmlNode & xmlRoot = *xmlDoc->getRoot();

    //Parse specific metadata for Sentinel1
    //TODO add as members to the Sentinel1SarSensorModel
    const std::string & product_type = getTextFromFirstNode(xmlRoot, "adsHeader/productType");
    const std::string & mode         = getTextFromFirstNode(xmlRoot, "adsHeader/mode");
    const std::string & swath        = getTextFromFirstNode(xmlRoot, "adsHeader/swath");
    const std::string & polarisation = getTextFromFirstNode(xmlRoot, "adsHeader/polarisation");

    theProductType = ProductType(product_type);

    // First, lookup position/velocity records
    std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
    xmlDoc->findNodes("/product/generalAnnotation/orbitList/orbit",xnodes);

    //TODO uncomment and adapt following code from s1_inverse to fill
    //SarSensorModel structure

    for(std::vector<ossimRefPtr<ossimXmlNode> >::iterator itNode = xnodes.begin(); itNode!=xnodes.end();++itNode)
    {
        OrbitRecordType orbitRecord;

        // Retrieve acquisition time
        orbitRecord.azimuthTime = getTimeFromFirstNode(**itNode, attTime);

        // Retrieve ECEF position
        ossimXmlNode const& positionNode = getExpectedFirstNode(**itNode, attPosition);
        orbitRecord.position[0] = getDoubleFromFirstNode(positionNode, attX);
        orbitRecord.position[1] = getDoubleFromFirstNode(positionNode, attY);
        orbitRecord.position[2] = getDoubleFromFirstNode(positionNode, attZ);

        // Retrieve ECEF velocity
        ossimXmlNode const& velocityNode = getExpectedFirstNode(**itNode, attVelocity);
        orbitRecord.velocity[0] = getDoubleFromFirstNode(velocityNode, attX);
        orbitRecord.velocity[1] = getDoubleFromFirstNode(velocityNode, attY);
        orbitRecord.velocity[2] = getDoubleFromFirstNode(velocityNode, attZ);

        //Add one orbits record
        theOrbitRecords.push_back(orbitRecord);
    }

    //Parse the near range time (in seconds)
    theNearRangeTime = getDoubleFromFirstNode(xmlRoot, "imageAnnotation/imageInformation/slantRangeTime");

    //Parse the range sampling rate
    theRangeSamplingRate = getDoubleFromFirstNode(xmlRoot, "generalAnnotation/productInformation/rangeSamplingRate");

    //Parse the range resolution
    theRangeResolution = getDoubleFromFirstNode(xmlRoot, "imageAnnotation/imageInformation/rangePixelSpacing");

    //Parse the radar frequency
    theRadarFrequency = getDoubleFromFirstNode(xmlRoot, "generalAnnotation/productInformation/radarFrequency");

    //Parse azimuth time interval
    const double azimuthTimeInterval = getDoubleFromFirstNode(xmlRoot, "imageAnnotation/imageInformation/azimuthTimeInterval");
#if defined(USE_BOOST_TIME)
      theAzimuthTimeInterval = boost::posix_time::precise_duration(azimuthTimeInterval * 1000000.);
#else
      theAzimuthTimeInterval = seconds(azimuthTimeInterval);
#endif
    ossimNotify(ossimNotifyLevel_DEBUG) << "theAzimuthTimeInterval " << theAzimuthTimeInterval.total_microseconds() << "us\n";

    // Now read burst records as well
    xnodes.clear();
    xmlDoc->findNodes("/product/swathTiming/burstList/burst",xnodes);

    if(xnodes.empty())
    {
        BurstRecordType burstRecord;

        burstRecord.startLine = 0;
        burstRecord.azimuthStartTime = getTimeFromFirstNode(xmlRoot,"imageAnnotation/imageInformation/productFirstLineUtcTime");

        ossimNotify(ossimNotifyLevel_DEBUG)<< burstRecord.azimuthStartTime<<'\n';

        burstRecord.azimuthStopTime = getTimeFromFirstNode(xmlRoot,"imageAnnotation/imageInformation/productLastLineUtcTime");
        burstRecord.endLine = getTextFromFirstNode(xmlRoot, "imageAnnotation/imageInformation/numberOfLines").toUInt16()-1;

        theBurstRecords.push_back(burstRecord);
    }
    else
    {
        const unsigned int linesPerBurst = xmlRoot.findFirstNode("swathTiming/linesPerBurst")->getText().toUInt16();
        unsigned int burstId(0);

        for(std::vector<ossimRefPtr<ossimXmlNode> >::iterator itNode = xnodes.begin(); itNode!=xnodes.end();++itNode,++burstId)
        {
            BurstRecordType burstRecord;

            const ossimSarSensorModel::TimeType azTime = getTimeFromFirstNode(**itNode, attAzimuthTime);

            ossimString const& s = getTextFromFirstNode(**itNode, attFirstValidSample);

            long first_valid(0), last_valid(0);
            bool begin_found(false), end_found(false);

            std::vector<ossimString> ssp = s.split(" ");

            for (std::vector<ossimString>::const_iterator sIt = ssp.begin(), e = ssp.end()
                    ; sIt != e && !end_found
                    ; ++sIt
                )
            {
                if(!begin_found)
                {
                    if(*sIt!="-1")
                    {
                        begin_found = true;
                    }
                    else
                    {
                        ++first_valid;
                    }
                    ++last_valid;
                }
                else
                {
                    if(!end_found && *sIt=="-1")
                    {
                        end_found = true;
                    }
                    else
                    {
                        ++last_valid;
                    }
                }
            }

            burstRecord.startLine = burstId*linesPerBurst + first_valid;
            burstRecord.endLine = burstId*linesPerBurst + last_valid;

            burstRecord.azimuthStartTime = azTime + (first_valid*theAzimuthTimeInterval);
            burstRecord.azimuthStopTime = azTime  + (last_valid*theAzimuthTimeInterval);

            theBurstRecords.push_back(burstRecord);
        }
    }

    if(isGRD())
    {
        readCoordinates(*xmlDoc,
                "/product/coordinateConversion/coordinateConversionList/coordinateConversion",
                attSr0, attSrgrCoefficients,
                theSlantRangeToGroundRangeRecords);

        readCoordinates(*xmlDoc,
                "/product/coordinateConversion/coordinateConversionList/coordinateConversion",
                attGr0, attGrsrCoefficients,
                theGroundRangeToSlantRangeRecords);
    }

    xnodes.clear();
    xmlDoc->findNodes("/product/geolocationGrid/geolocationGridPointList/geolocationGridPoint",xnodes);

    for(std::vector<ossimRefPtr<ossimXmlNode> >::iterator itNode = xnodes.begin(); itNode!=xnodes.end();++itNode)
    {
        GCPRecordType gcpRecord;

        // Retrieve acquisition time
        gcpRecord.azimuthTime = getTimeFromFirstNode(**itNode, attAzimuthTime);

        gcpRecord.slantRangeTime = getDoubleFromFirstNode(**itNode, attSlantRangeTime);

        gcpRecord.imPt.x = getDoubleFromFirstNode(**itNode, attPixel);

        // In TOPSAR products, GCPs are weird (they fall in black lines
        // between burst. This code allows moving them to a valid area of
        // the image.
        if(theBurstRecords.size()>2)
        {
            ossimSarSensorModel::TimeType acqStart;
            bool burstFound(false);
            unsigned long acqStartLine(0);

            for(std::vector<BurstRecordType>::reverse_iterator bIt = theBurstRecords.rbegin();bIt!=theBurstRecords.rend() && !burstFound;++bIt)
            {
                if(gcpRecord.azimuthTime >= bIt->azimuthStartTime && gcpRecord.azimuthTime < bIt->azimuthStopTime)
                {
                    burstFound = true;
                    acqStart = bIt->azimuthStartTime;
                    acqStartLine = bIt->startLine;
                }
            }

            if(!burstFound)
            {
                if(gcpRecord.azimuthTime < theBurstRecords.front().azimuthStartTime)
                {
                    acqStart = theBurstRecords.front().azimuthStartTime;
                    acqStartLine = theBurstRecords.front().startLine;
                }
                else if (gcpRecord.azimuthTime >= theBurstRecords.front().azimuthStopTime)
                {
                    acqStart = theBurstRecords.back().azimuthStartTime;
                    acqStartLine = theBurstRecords.back().startLine;
                }
            }
            const DurationType timeSinceStart = gcpRecord.azimuthTime - acqStart;

            gcpRecord.imPt.y= timeSinceStart/theAzimuthTimeInterval + acqStartLine;
            ossimNotify(ossimNotifyLevel_DEBUG) << "timeSinceStart: " << timeSinceStart << " = " << gcpRecord.azimuthTime << " - " << acqStart <<  " (azTime-acqStart)"<< "\n";
            ossimNotify(ossimNotifyLevel_DEBUG) << "imPt_y: " << gcpRecord.imPt.y << " = " << timeSinceStart.total_microseconds() << "/" << theAzimuthTimeInterval.total_microseconds() << "+" << acqStartLine << "\n";
        }
        else
        {
            gcpRecord.imPt.y = getDoubleFromFirstNode(**itNode, attLine);;
        }
        ossimGpt geoPoint;
        gcpRecord.worldPt.lat = getDoubleFromFirstNode(**itNode, attLatitude);
        gcpRecord.worldPt.lon = getDoubleFromFirstNode(**itNode, attLongitude);
        gcpRecord.worldPt.hgt = getDoubleFromFirstNode(**itNode, attHeight);

        theGCPRecords.push_back(gcpRecord);
    }

    this->optimizeTimeOffsetsFromGcps();
}

} // namespace ossimplugins
<commit_msg>BUG: More consistent numbering of lines in bursts<commit_after>//----------------------------------------------------------------------------
//
// "Copyright Centre National d'Etudes Spatiales"
//
// License:  LGPL-2
//
// See LICENSE.txt file in the top level directory for more details.
//
//----------------------------------------------------------------------------
// $Id$

#include <ossimSentinel1SarSensorModel.h>
#include <ossim/base/ossimXmlDocument.h>
#include <ossimXmlTools.h>

namespace {// Anonymous namespace
    const ossimString attAzimuthTime      = "azimuthTime";
    const ossimString attFirstValidSample = "firstValidSample";
    const ossimString attGr0              = "gr0";
    const ossimString attGrsrCoefficients = "grsrCoefficients";
    const ossimString attHeight           = "height";
    const ossimString attLatitude         = "latitude";
    const ossimString attLine             = "line";
    const ossimString attLongitude        = "longitude";
    const ossimString attPixel            = "pixel";
    const ossimString attPosition         = "position";
    const ossimString attSlantRangeTime   = "slantRangeTime";
    const ossimString attSr0              = "sr0";
    const ossimString attSrgrCoefficients = "srgrCoefficients";
    const ossimString attTime             = "time";
    const ossimString attVelocity         = "velocity";
    const ossimString attX                = "x";
    const ossimString attY                = "y";
    const ossimString attZ                = "z";
}// Anonymous namespace

#if defined(USE_BOOST_TIME)
            using boost::posix_time::microseconds;
            using boost::posix_time::seconds;
#else
            using ossimplugins::time::microseconds;
            using ossimplugins::time::seconds;
#endif
void ossimplugins::ossimSentinel1SarSensorModel::readCoordinates(
        ossimXmlDocument const& xmlDoc, ossimString const& xpath,
        ossimString const& rg0_xpath, ossimString const& coeffs_xpath,
        std::vector<CoordinateConversionRecordType> & outputRecords)
{
   std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
   xmlDoc.findNodes(xpath, xnodes);

   for(std::vector<ossimRefPtr<ossimXmlNode> >::iterator itNode = xnodes.begin(); itNode!=xnodes.end();++itNode)
   {
      CoordinateConversionRecordType coordRecord;

      coordRecord.azimuthTime = getTimeFromFirstNode(**itNode, attAzimuthTime);

      coordRecord.rg0 = getDoubleFromFirstNode(**itNode, rg0_xpath);;

      ossimString const& s = getTextFromFirstNode(**itNode, coeffs_xpath);
      std::vector<ossimString> ssplit = s.split(" ");

      if (ssplit.empty())
      {
         throw std::runtime_error(("The "+rg0_xpath+" record has an empty coef vector").string());
      }
      for (std::vector<ossimString>::const_iterator cIt = ssplit.begin(), e = ssplit.end()
            ; cIt != e
            ; ++cIt
          )
      {
         coordRecord.coefs.push_back(cIt->toDouble());
      }
      assert(!coordRecord.coefs.empty()&&"The rg0 record has empty coefs vector.");

      outputRecords.push_back(coordRecord);
   }
}

namespace ossimplugins
{
void ossimSentinel1SarSensorModel::readAnnotationFile(const std::string & annotationXml)
{
    ossimRefPtr<ossimXmlDocument> xmlDoc = new ossimXmlDocument(annotationXml);
    const ossimXmlNode & xmlRoot = *xmlDoc->getRoot();

    //Parse specific metadata for Sentinel1
    //TODO add as members to the Sentinel1SarSensorModel
    const std::string & product_type = getTextFromFirstNode(xmlRoot, "adsHeader/productType");
    const std::string & mode         = getTextFromFirstNode(xmlRoot, "adsHeader/mode");
    const std::string & swath        = getTextFromFirstNode(xmlRoot, "adsHeader/swath");
    const std::string & polarisation = getTextFromFirstNode(xmlRoot, "adsHeader/polarisation");

    theProductType = ProductType(product_type);

    // First, lookup position/velocity records
    std::vector<ossimRefPtr<ossimXmlNode> > xnodes;
    xmlDoc->findNodes("/product/generalAnnotation/orbitList/orbit",xnodes);

    //TODO uncomment and adapt following code from s1_inverse to fill
    //SarSensorModel structure

    for(std::vector<ossimRefPtr<ossimXmlNode> >::iterator itNode = xnodes.begin(); itNode!=xnodes.end();++itNode)
    {
        OrbitRecordType orbitRecord;

        // Retrieve acquisition time
        orbitRecord.azimuthTime = getTimeFromFirstNode(**itNode, attTime);

        // Retrieve ECEF position
        ossimXmlNode const& positionNode = getExpectedFirstNode(**itNode, attPosition);
        orbitRecord.position[0] = getDoubleFromFirstNode(positionNode, attX);
        orbitRecord.position[1] = getDoubleFromFirstNode(positionNode, attY);
        orbitRecord.position[2] = getDoubleFromFirstNode(positionNode, attZ);

        // Retrieve ECEF velocity
        ossimXmlNode const& velocityNode = getExpectedFirstNode(**itNode, attVelocity);
        orbitRecord.velocity[0] = getDoubleFromFirstNode(velocityNode, attX);
        orbitRecord.velocity[1] = getDoubleFromFirstNode(velocityNode, attY);
        orbitRecord.velocity[2] = getDoubleFromFirstNode(velocityNode, attZ);

        //Add one orbits record
        theOrbitRecords.push_back(orbitRecord);
    }

    //Parse the near range time (in seconds)
    theNearRangeTime = getDoubleFromFirstNode(xmlRoot, "imageAnnotation/imageInformation/slantRangeTime");

    //Parse the range sampling rate
    theRangeSamplingRate = getDoubleFromFirstNode(xmlRoot, "generalAnnotation/productInformation/rangeSamplingRate");

    //Parse the range resolution
    theRangeResolution = getDoubleFromFirstNode(xmlRoot, "imageAnnotation/imageInformation/rangePixelSpacing");

    //Parse the radar frequency
    theRadarFrequency = getDoubleFromFirstNode(xmlRoot, "generalAnnotation/productInformation/radarFrequency");

    //Parse azimuth time interval
    const double azimuthTimeInterval = getDoubleFromFirstNode(xmlRoot, "imageAnnotation/imageInformation/azimuthTimeInterval");
#if defined(USE_BOOST_TIME)
      theAzimuthTimeInterval = boost::posix_time::precise_duration(azimuthTimeInterval * 1000000.);
#else
      theAzimuthTimeInterval = seconds(azimuthTimeInterval);
#endif
    ossimNotify(ossimNotifyLevel_DEBUG) << "theAzimuthTimeInterval " << theAzimuthTimeInterval.total_microseconds() << "us\n";

    // Now read burst records as well
    xnodes.clear();
    xmlDoc->findNodes("/product/swathTiming/burstList/burst",xnodes);

    if(xnodes.empty())
    {
        BurstRecordType burstRecord;

        burstRecord.startLine = 0;
        burstRecord.azimuthStartTime = getTimeFromFirstNode(xmlRoot,"imageAnnotation/imageInformation/productFirstLineUtcTime");

        ossimNotify(ossimNotifyLevel_DEBUG)<< burstRecord.azimuthStartTime<<'\n';

        burstRecord.azimuthStopTime = getTimeFromFirstNode(xmlRoot,"imageAnnotation/imageInformation/productLastLineUtcTime");
        burstRecord.endLine = getTextFromFirstNode(xmlRoot, "imageAnnotation/imageInformation/numberOfLines").toUInt16()-1;

        theBurstRecords.push_back(burstRecord);
    }
    else
    {
        const unsigned int linesPerBurst = xmlRoot.findFirstNode("swathTiming/linesPerBurst")->getText().toUInt16();
        unsigned int burstId(0);

        for(std::vector<ossimRefPtr<ossimXmlNode> >::iterator itNode = xnodes.begin(); itNode!=xnodes.end();++itNode,++burstId)
        {
            BurstRecordType burstRecord;

            const ossimSarSensorModel::TimeType azTime = getTimeFromFirstNode(**itNode, attAzimuthTime);

            ossimString const& s = getTextFromFirstNode(**itNode, attFirstValidSample);

            long first_valid(0), last_valid(0);
            bool begin_found(false), end_found(false);

            std::vector<ossimString> ssp = s.split(" ");

            for (std::vector<ossimString>::const_iterator sIt = ssp.begin(), e = ssp.end()
                    ; sIt != e && !end_found
                    ; ++sIt
                )
            {
                if(!begin_found)
                {
                    if(*sIt!="-1")
                    {
                        begin_found = true;
                    }
                    else
                    {
                        ++first_valid;
                    }
                    ++last_valid;
                }
                else
                {
                    if(!end_found && *sIt=="-1")
                    {
                        end_found = true;
                        --last_valid;
                    }
                    else
                    {
                        ++last_valid;
                    }
                }
            }

            burstRecord.startLine = burstId*linesPerBurst + first_valid;
            burstRecord.endLine = burstId*linesPerBurst + last_valid;

            burstRecord.azimuthStartTime = azTime + (first_valid*theAzimuthTimeInterval);
            burstRecord.azimuthStopTime = azTime  + (last_valid*theAzimuthTimeInterval);

            theBurstRecords.push_back(burstRecord);
        }
    }

    if(isGRD())
    {
        readCoordinates(*xmlDoc,
                "/product/coordinateConversion/coordinateConversionList/coordinateConversion",
                attSr0, attSrgrCoefficients,
                theSlantRangeToGroundRangeRecords);

        readCoordinates(*xmlDoc,
                "/product/coordinateConversion/coordinateConversionList/coordinateConversion",
                attGr0, attGrsrCoefficients,
                theGroundRangeToSlantRangeRecords);
    }

    xnodes.clear();
    xmlDoc->findNodes("/product/geolocationGrid/geolocationGridPointList/geolocationGridPoint",xnodes);

    for(std::vector<ossimRefPtr<ossimXmlNode> >::iterator itNode = xnodes.begin(); itNode!=xnodes.end();++itNode)
    {
        GCPRecordType gcpRecord;

        // Retrieve acquisition time
        gcpRecord.azimuthTime = getTimeFromFirstNode(**itNode, attAzimuthTime);

        gcpRecord.slantRangeTime = getDoubleFromFirstNode(**itNode, attSlantRangeTime);

        gcpRecord.imPt.x = getDoubleFromFirstNode(**itNode, attPixel);

        // In TOPSAR products, GCPs are weird (they fall in black lines
        // between burst. This code allows moving them to a valid area of
        // the image.
        if(theBurstRecords.size()>2)
        {
            ossimSarSensorModel::TimeType acqStart;
            bool burstFound(false);
            unsigned long acqStartLine(0);

            for(std::vector<BurstRecordType>::reverse_iterator bIt = theBurstRecords.rbegin();bIt!=theBurstRecords.rend() && !burstFound;++bIt)
            {
                if(gcpRecord.azimuthTime >= bIt->azimuthStartTime && gcpRecord.azimuthTime < bIt->azimuthStopTime)
                {
                    burstFound = true;
                    acqStart = bIt->azimuthStartTime;
                    acqStartLine = bIt->startLine;
                }
            }

            if(!burstFound)
            {
                if(gcpRecord.azimuthTime < theBurstRecords.front().azimuthStartTime)
                {
                    acqStart = theBurstRecords.front().azimuthStartTime;
                    acqStartLine = theBurstRecords.front().startLine;
                }
                else if (gcpRecord.azimuthTime >= theBurstRecords.front().azimuthStopTime)
                {
                    acqStart = theBurstRecords.back().azimuthStartTime;
                    acqStartLine = theBurstRecords.back().startLine;
                }
            }
            const DurationType timeSinceStart = gcpRecord.azimuthTime - acqStart;

            gcpRecord.imPt.y= timeSinceStart/theAzimuthTimeInterval + acqStartLine;
            ossimNotify(ossimNotifyLevel_DEBUG) << "timeSinceStart: " << timeSinceStart << " = " << gcpRecord.azimuthTime << " - " << acqStart <<  " (azTime-acqStart)"<< "\n";
            ossimNotify(ossimNotifyLevel_DEBUG) << "imPt_y: " << gcpRecord.imPt.y << " = " << timeSinceStart.total_microseconds() << "/" << theAzimuthTimeInterval.total_microseconds() << "+" << acqStartLine << "\n";
        }
        else
        {
            gcpRecord.imPt.y = getDoubleFromFirstNode(**itNode, attLine);;
        }
        ossimGpt geoPoint;
        gcpRecord.worldPt.lat = getDoubleFromFirstNode(**itNode, attLatitude);
        gcpRecord.worldPt.lon = getDoubleFromFirstNode(**itNode, attLongitude);
        gcpRecord.worldPt.hgt = getDoubleFromFirstNode(**itNode, attHeight);

        theGCPRecords.push_back(gcpRecord);
    }

    this->optimizeTimeOffsetsFromGcps();
}

} // namespace ossimplugins
<|endoftext|>