<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2017 Raffaello D. Di Napoli

This file is part of Lofty.

Lofty is free software: you can redistribute it and/or modify it under the terms of version 2.1 of the GNU
Lesser General Public License as published by the Free Software Foundation.

Lofty 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.
------------------------------------------------------------------------------------------------------------*/

#include <lofty.hxx>
#include <lofty/coroutine.hxx>
#include <lofty/io/binary/buffer.hxx>
#include <lofty/net/udp.hxx>
#include <lofty/thread.hxx>
#include "sockaddr_any.hxx"

#if LOFTY_HOST_API_POSIX
   #include <errno.h> // EINTR errno
   #include <netinet/in.h> // ntohs()
   #include <sys/types.h> // ssize_t
   #include <sys/socket.h> // recvfrom() sendto()
#elif LOFTY_HOST_API_WIN32
   #include <winsock2.h>
   #include <mswsock.h> // WSARecvFrom()
#endif

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace lofty { namespace net { namespace udp {

datagram::datagram(
   ip::address const & address__, ip::port port__,
   _std::shared_ptr<io::binary::memory_stream> data__ /*=nullptr*/
) :
   address_(address__),
   port_(port__),
   data_(_std::move(data__)) {
}

datagram::~datagram() {
}

}}} //namespace lofty::net::udp

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace lofty { namespace net { namespace udp {

client::client() {
}

client::~client() {
}

void client::send(datagram const & dgram) {
   if (!sock_fd) {
      // No socket yet; create one now.
      ip_version = dgram.address().version();
      sock_fd = ip::create_socket(ip_version, ip::transport::udp);
   }
   send_via(dgram, sock_fd);
}

/*static*/ void client::send_via(datagram const & dgram, io::filedesc const & sock_fd) {
   ip::sockaddr_any server_sock_addr(dgram.address(), dgram.port());
   std::int8_t const * buf;
   std::size_t buf_size;
   _std::tie(buf, buf_size) = dgram.data()->peek<std::int8_t>();
#if LOFTY_HOST_API_POSIX
   ::ssize_t bytes_sent;
   for (;;) {
      bytes_sent = ::sendto(
         sock_fd.get(), buf, buf_size, 0, server_sock_addr.sockaddr_ptr(), server_sock_addr.size()
      );
      if (bytes_sent >= 0) {
         break;
      }
      auto err = errno;
      switch (err) {
         case EINTR:
            this_coroutine::interruption_point();
            break;
         case EAGAIN:
   #if EWOULDBLOCK != EAGAIN
         case EWOULDBLOCK:
   #endif
            // Wait for sock_fd.
            this_coroutine::sleep_until_fd_ready(sock_fd.get(), true /*write*/, 0 /*no timeout*/);
            break;
         default:
            exception::throw_os_error(static_cast<errint_t>(err));
      }
   }
#elif LOFTY_HOST_API_WIN32
   const_cast<io::filedesc &>(sock_fd).bind_to_this_coroutine_scheduler_iocp();
   ::WSABUF wsabuf;
   wsabuf.buf = reinterpret_cast<char *>(const_cast<std::int8_t *>(buf));
   wsabuf.len = static_cast< ::ULONG>(buf_size);
   io::overlapped ovl;
   ovl.Offset = 0;
   ovl.OffsetHigh = 0;
   ::DWORD bytes_sent;
   if (::WSASendTo(
      reinterpret_cast< ::SOCKET>(sock_fd.get()), &wsabuf, 1, nullptr, 0 /*no flags*/,
      server_sock_addr.sockaddr_ptr(), server_sock_addr.size(), &ovl, nullptr
   )) {
      auto err = static_cast< ::DWORD>(::WSAGetLastError());
      if (err == ERROR_IO_PENDING) {
         this_coroutine::sleep_until_fd_ready(sock_fd.get(), true /*write*/, 0 /*no timeout*/, &ovl);
         err = ovl.status();
         bytes_sent = ovl.transferred_size();
      }
      if (err != ERROR_SUCCESS) {
         exception::throw_os_error(err);
      }
   } else {
      bytes_sent = static_cast< ::DWORD>(wsabuf.len);
   }
#else
   #error "TODO: HOST_API"
#endif
   this_coroutine::interruption_point();
}

}}} //namespace lofty::net::udp

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace lofty { namespace net { namespace udp {

server::server(ip::address const & address, ip::port const & port) :
   ip::server(address, port, ip::transport::udp) {
}

server::~server() {
}

_std::shared_ptr<datagram> server::receive() {
   // Create a new buffer large enough for a UDP datagram.
   io::binary::buffer buf(0xffff);
   ip::sockaddr_any sender_sock_addr;
#if LOFTY_HOST_API_POSIX
   ::ssize_t bytes_received;
   for (;;) {
      bytes_received = ::recvfrom(
         sock_fd.get(), buf.get_available(), buf.available_size(), 0,
         sender_sock_addr.sockaddr_ptr(), sender_sock_addr.size_ptr()
      );
      if (bytes_received >= 0) {
         break;
      }
      auto err = errno;
      switch (err) {
         case EINTR:
            this_coroutine::interruption_point();
            break;
         case EAGAIN:
   #if EWOULDBLOCK != EAGAIN
         case EWOULDBLOCK:
   #endif
            // Wait for sock_fd.
            this_coroutine::sleep_until_fd_ready(sock_fd.get(), false /*read*/, 0 /*no timeout*/);
            break;
         default:
            exception::throw_os_error(static_cast<errint_t>(err));
      }
   }
#elif LOFTY_HOST_API_WIN32
   sock_fd.bind_to_this_coroutine_scheduler_iocp();
   ::WSABUF wsabuf;
   wsabuf.buf = reinterpret_cast<char *>(buf.get_available());
   wsabuf.len = static_cast< ::ULONG>(buf.available_size());
   io::overlapped ovl;
   ovl.Offset = 0;
   ovl.OffsetHigh = 0;
   ::DWORD flags = 0, bytes_received;
   if (::WSARecvFrom(
      reinterpret_cast< ::SOCKET>(sock_fd.get()), &wsabuf, 1, nullptr, &flags,
      sender_sock_addr.sockaddr_ptr(), sender_sock_addr.size_ptr(), &ovl, nullptr
   )) {
      auto err = static_cast< ::DWORD>(::WSAGetLastError());
      if (err == ERROR_IO_PENDING) {
         this_coroutine::sleep_until_fd_ready(sock_fd.get(), false /*read*/, 0 /*no timeout*/, &ovl);
         err = ovl.status();
         bytes_received = ovl.transferred_size();
      }
      if (err != ERROR_SUCCESS) {
         exception::throw_os_error(err);
      }
   } else {
      bytes_received = static_cast< ::DWORD>(wsabuf.len);
   }
#else
   #error "TODO: HOST_API"
#endif
   this_coroutine::interruption_point();

   buf.mark_as_used(static_cast<std::size_t>(bytes_received));
   buf.shrink_to_fit();
   return _std::make_shared<datagram>(
      sender_sock_addr.address(), sender_sock_addr.port(),
      _std::make_shared<io::binary::memory_stream>(_std::move(buf))
   );
}

void server::send(datagram const & dgram) {
   client::send_via(dgram, sock_fd);
}

}}} //namespace lofty::net::udp
<commit_msg>recvfrom() needs size of sockaddr to be provided<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2017 Raffaello D. Di Napoli

This file is part of Lofty.

Lofty is free software: you can redistribute it and/or modify it under the terms of version 2.1 of the GNU
Lesser General Public License as published by the Free Software Foundation.

Lofty 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.
------------------------------------------------------------------------------------------------------------*/

#include <lofty.hxx>
#include <lofty/coroutine.hxx>
#include <lofty/io/binary/buffer.hxx>
#include <lofty/net/udp.hxx>
#include <lofty/thread.hxx>
#include "sockaddr_any.hxx"

#if LOFTY_HOST_API_POSIX
   #include <errno.h> // EINTR errno
   #include <netinet/in.h> // ntohs()
   #include <sys/types.h> // ssize_t
   #include <sys/socket.h> // recvfrom() sendto()
#elif LOFTY_HOST_API_WIN32
   #include <winsock2.h>
   #include <mswsock.h> // WSARecvFrom()
#endif

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace lofty { namespace net { namespace udp {

datagram::datagram(
   ip::address const & address__, ip::port port__,
   _std::shared_ptr<io::binary::memory_stream> data__ /*=nullptr*/
) :
   address_(address__),
   port_(port__),
   data_(_std::move(data__)) {
}

datagram::~datagram() {
}

}}} //namespace lofty::net::udp

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace lofty { namespace net { namespace udp {

client::client() {
}

client::~client() {
}

void client::send(datagram const & dgram) {
   if (!sock_fd) {
      // No socket yet; create one now.
      ip_version = dgram.address().version();
      sock_fd = ip::create_socket(ip_version, ip::transport::udp);
   }
   send_via(dgram, sock_fd);
}

/*static*/ void client::send_via(datagram const & dgram, io::filedesc const & sock_fd) {
   ip::sockaddr_any server_sock_addr(dgram.address(), dgram.port());
   std::int8_t const * buf;
   std::size_t buf_size;
   _std::tie(buf, buf_size) = dgram.data()->peek<std::int8_t>();
#if LOFTY_HOST_API_POSIX
   ::ssize_t bytes_sent;
   for (;;) {
      bytes_sent = ::sendto(
         sock_fd.get(), buf, buf_size, 0, server_sock_addr.sockaddr_ptr(), server_sock_addr.size()
      );
      if (bytes_sent >= 0) {
         break;
      }
      auto err = errno;
      switch (err) {
         case EINTR:
            this_coroutine::interruption_point();
            break;
         case EAGAIN:
   #if EWOULDBLOCK != EAGAIN
         case EWOULDBLOCK:
   #endif
            // Wait for sock_fd.
            this_coroutine::sleep_until_fd_ready(sock_fd.get(), true /*write*/, 0 /*no timeout*/);
            break;
         default:
            exception::throw_os_error(static_cast<errint_t>(err));
      }
   }
#elif LOFTY_HOST_API_WIN32
   const_cast<io::filedesc &>(sock_fd).bind_to_this_coroutine_scheduler_iocp();
   ::WSABUF wsabuf;
   wsabuf.buf = reinterpret_cast<char *>(const_cast<std::int8_t *>(buf));
   wsabuf.len = static_cast< ::ULONG>(buf_size);
   io::overlapped ovl;
   ovl.Offset = 0;
   ovl.OffsetHigh = 0;
   ::DWORD bytes_sent;
   if (::WSASendTo(
      reinterpret_cast< ::SOCKET>(sock_fd.get()), &wsabuf, 1, nullptr, 0 /*no flags*/,
      server_sock_addr.sockaddr_ptr(), server_sock_addr.size(), &ovl, nullptr
   )) {
      auto err = static_cast< ::DWORD>(::WSAGetLastError());
      if (err == ERROR_IO_PENDING) {
         this_coroutine::sleep_until_fd_ready(sock_fd.get(), true /*write*/, 0 /*no timeout*/, &ovl);
         err = ovl.status();
         bytes_sent = ovl.transferred_size();
      }
      if (err != ERROR_SUCCESS) {
         exception::throw_os_error(err);
      }
   } else {
      bytes_sent = static_cast< ::DWORD>(wsabuf.len);
   }
#else
   #error "TODO: HOST_API"
#endif
   this_coroutine::interruption_point();
}

}}} //namespace lofty::net::udp

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace lofty { namespace net { namespace udp {

server::server(ip::address const & address, ip::port const & port) :
   ip::server(address, port, ip::transport::udp) {
}

server::~server() {
}

_std::shared_ptr<datagram> server::receive() {
   // Create a new buffer large enough for a UDP datagram.
   io::binary::buffer buf(0xffff);
   ip::sockaddr_any sender_sock_addr;
   sender_sock_addr.set_size_from_ip_version(ip_version);
#if LOFTY_HOST_API_POSIX
   ::ssize_t bytes_received;
   for (;;) {
      bytes_received = ::recvfrom(
         sock_fd.get(), buf.get_available(), buf.available_size(), 0,
         sender_sock_addr.sockaddr_ptr(), sender_sock_addr.size_ptr()
      );
      if (bytes_received >= 0) {
         break;
      }
      auto err = errno;
      switch (err) {
         case EINTR:
            this_coroutine::interruption_point();
            break;
         case EAGAIN:
   #if EWOULDBLOCK != EAGAIN
         case EWOULDBLOCK:
   #endif
            // Wait for sock_fd.
            this_coroutine::sleep_until_fd_ready(sock_fd.get(), false /*read*/, 0 /*no timeout*/);
            break;
         default:
            exception::throw_os_error(static_cast<errint_t>(err));
      }
   }
#elif LOFTY_HOST_API_WIN32
   sock_fd.bind_to_this_coroutine_scheduler_iocp();
   ::WSABUF wsabuf;
   wsabuf.buf = reinterpret_cast<char *>(buf.get_available());
   wsabuf.len = static_cast< ::ULONG>(buf.available_size());
   io::overlapped ovl;
   ovl.Offset = 0;
   ovl.OffsetHigh = 0;
   ::DWORD flags = 0, bytes_received;
   if (::WSARecvFrom(
      reinterpret_cast< ::SOCKET>(sock_fd.get()), &wsabuf, 1, nullptr, &flags,
      sender_sock_addr.sockaddr_ptr(), sender_sock_addr.size_ptr(), &ovl, nullptr
   )) {
      auto err = static_cast< ::DWORD>(::WSAGetLastError());
      if (err == ERROR_IO_PENDING) {
         this_coroutine::sleep_until_fd_ready(sock_fd.get(), false /*read*/, 0 /*no timeout*/, &ovl);
         err = ovl.status();
         bytes_received = ovl.transferred_size();
      }
      if (err != ERROR_SUCCESS) {
         exception::throw_os_error(err);
      }
   } else {
      bytes_received = static_cast< ::DWORD>(wsabuf.len);
   }
#else
   #error "TODO: HOST_API"
#endif
   this_coroutine::interruption_point();

   buf.mark_as_used(static_cast<std::size_t>(bytes_received));
   buf.shrink_to_fit();
   return _std::make_shared<datagram>(
      sender_sock_addr.address(), sender_sock_addr.port(),
      _std::make_shared<io::binary::memory_stream>(_std::move(buf))
   );
}

void server::send(datagram const & dgram) {
   client::send_via(dgram, sock_fd);
}

}}} //namespace lofty::net::udp
<|endoftext|>


<commit_before>/*
 *  This file is part of Poedit (https://poedit.net)
 *
 *  Copyright (C) 2016-2017 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "win10_menubar.h"

#include "hidpi.h"
#include "utility.h"

#include <wx/config.h>
#include <wx/msw/uxtheme.h>
#include <wx/nativewin.h>
#include <wx/recguard.h>

#include <mCtrl/menubar.h>

namespace
{

int g_mctrlInitialized = 0;

const int MENUBAR_OFFSET = -2;

} // anonymous namespace

class wxFrameWithWindows10Menubar::MenuBarWindow : public wxWindow
{
public:
    MenuBarWindow(wxWindow *parent)
        : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE),
          m_mctrlWin(nullptr), m_mctrlHandle(0)
    {
        if (g_mctrlInitialized++ == 0)
            mcMenubar_Initialize();

        m_mctrlHandle = CreateWindowEx
        (
            WS_EX_COMPOSITED,
            MC_WC_MENUBAR,
            _T(""),
            WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NORESIZE | CCS_NOPARENTALIGN,
            0, 0, 1000, 2 * PX(23),
            (HWND)this->GetHWND(),
            (HMENU) -1,
            wxGetInstance(),
            NULL
        );
        SendMessage(m_mctrlHandle, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS);
        SendMessage(m_mctrlHandle, CCM_SETNOTIFYWINDOW, (WPARAM)parent->GetHWND(), 0);

        m_mctrlWin = new mCtrlWrapper(this, m_mctrlHandle);

        {
            wxUxThemeHandle hTheme(this, L"ExplorerMenu::Toolbar");
            SetBackgroundColour(wxRGBToColour(wxUxThemeEngine::GetIfActive()->GetThemeSysColor(hTheme, COLOR_WINDOW)));
        }
    }

    ~MenuBarWindow()
    {
        m_mctrlWin->Destroy();
        ::DestroyWindow(m_mctrlHandle);

        if (--g_mctrlInitialized == 0)
            mcMenubar_Terminate();
    }

    void SetHMENU(WXHMENU menu)
    {
        SendMessage(m_mctrlHandle, MC_MBM_SETMENU, 0, (LPARAM) menu);
        SendMessage(m_mctrlHandle, MC_MBM_REFRESH, 0, 0);
    }

    bool TranslateMenubarMessage(WXMSG *pMsg)
    {
        MSG *msg = (MSG *) pMsg;
        if (mcIsMenubarMessage(m_mctrlHandle, msg))
            return true;

        return false;
    }

    void DoSetSize(int x, int y, int width, int height, int sizeFlags) override
    {
        wxWindow::DoSetSize(x, y, width, height, sizeFlags);
        SendMessage(m_mctrlHandle, MC_MBM_REFRESH, 0, 0);
    }

    wxSize DoGetBestSize() const override
    {
        wxSize sizeBest = wxDefaultSize;
        SIZE size;
        if (::SendMessage(m_mctrlHandle, TB_GETMAXSIZE, 0, (LPARAM) &size))
        {
            sizeBest.x = size.cx;
            sizeBest.y = size.cy + 1;
            CacheBestSize(sizeBest);
        }
        return sizeBest;
    }

private:
    class mCtrlWrapper : public wxNativeWindow
    {
    public:
        mCtrlWrapper(wxWindow *parent, WXHWND wnd) : wxNativeWindow(parent, wxID_ANY, wnd), m_flagReenterMctrl(0) {}

        WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) override
        {
            switch (nMsg)
            {
                case WM_COMMAND:
                case WM_NOTIFY:
                {
                    wxRecursionGuard guard(m_flagReenterMctrl);

                    if (!guard.IsInside())
                    {
                        return MSWDefWindowProc(nMsg, wParam, lParam);
                    }
                    else
                    {
                        return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam);
                    }
                }
            }

            return wxNativeWindow::MSWWindowProc(nMsg, wParam, lParam);
        }

    private:
        wxRecursionGuardFlag m_flagReenterMctrl;
    };

    mCtrlWrapper *m_mctrlWin;
    WXHWND m_mctrlHandle;
};

wxFrameWithWindows10Menubar::wxFrameWithWindows10Menubar(wxWindow *parent,
                                                         wxWindowID id,
                                                         const wxString& title,
                                                         const wxPoint& pos,
                                                         const wxSize& size,
                                                         long style,
                                                         const wxString& name)
    : wxFrame(parent, id, title, pos, size, style, name), m_menuBar(nullptr)
{
    if (ShouldUse())
    {
        m_menuBar = new MenuBarWindow(this);
    }
}

bool wxFrameWithWindows10Menubar::ShouldUse() const
{
    if (!IsWindows10OrGreater())
        return false;

    if (!wxUxThemeEngine::GetIfActive())
        return false;

    if (wxConfig::Get()->ReadBool("/disable_mctrl", false))
        return false;

    // Detect screen readers and use normal menubar with them, because the
    // mCtrl one isn't accessible.
    BOOL running;
    BOOL ret = SystemParametersInfo(SPI_GETSCREENREADER, 0, &running, 0);
    if (ret && running)
        return false;

    return true;
}

wxPoint wxFrameWithWindows10Menubar::GetClientAreaOrigin() const
{
    wxPoint pt = wxFrame::GetClientAreaOrigin();
    if (IsUsed())
    {
        pt.y += m_menuBar->GetSize().y + MENUBAR_OFFSET;
    }
    return pt;
}

void wxFrameWithWindows10Menubar::PositionToolBar()
{
    // Position both the toolbar and our menu bar (which is really another toolbar) here.
    if (!IsUsed())
    {
        wxFrame::PositionToolBar();
        return;
    }

    // don't call our (or even wxTopLevelWindow) version because we want
    // the real (full) client area size, not excluding the tool/status bar
    int width, height;
    wxWindow::DoGetClientSize(&width, &height);

    int y = MENUBAR_OFFSET;

    // use the 'real' MSW position here, don't offset relatively to the
    // client area origin
    int mch = m_menuBar->GetBestSize().y;
    m_menuBar->SetSize(0, y, width, mch, wxSIZE_NO_ADJUSTMENTS);
    y += mch;

    wxToolBar *toolbar = GetToolBar();
    if (toolbar && toolbar->IsShown())
    {
        int tbh = toolbar->GetSize().y;
        toolbar->SetSize(0, y, width + 8, tbh, wxSIZE_NO_ADJUSTMENTS);
    }
}

bool wxFrameWithWindows10Menubar::MSWTranslateMessage(WXMSG *msg)
{
    if (wxFrame::MSWTranslateMessage(msg))
        return true;

    if (IsUsed() && m_menuBar->TranslateMenubarMessage(msg))
        return true;

    return false;
}

WXLRESULT wxFrameWithWindows10Menubar::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
    if (IsUsed())
    {
        // mCtrl doesn't play nice with the wxMSW's menus interaction where accelerators are updated
        // when a menu is opened (which works because TranslateAccelerators() normally sends a fake
        // event for that... if there's a normal menu). We need to refresh menus before accelerators
        // are used so that e.g. disabled state is accurately updated.
        if (message == WM_COMMAND && HIWORD(wParam) == 1/*accel*/)
            GetMenuBar()->UpdateMenus();
    }

    return wxFrame::MSWWindowProc(message, wParam, lParam);
}

void wxFrameWithWindows10Menubar::InternalSetMenuBar()
{
    if (IsUsed())
    {
        m_menuBar->SetHMENU(m_hMenu);
    }
    else
    {
        wxFrame::InternalSetMenuBar();
    }
}
<commit_msg>Fix main window size restoration on Windows 10<commit_after>/*
 *  This file is part of Poedit (https://poedit.net)
 *
 *  Copyright (C) 2016-2017 Vaclav Slavik
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 *
 */

#include "win10_menubar.h"

#include "hidpi.h"
#include "utility.h"

#include <wx/config.h>
#include <wx/msw/uxtheme.h>
#include <wx/nativewin.h>
#include <wx/recguard.h>

#include <mCtrl/menubar.h>

namespace
{

int g_mctrlInitialized = 0;

const int MENUBAR_OFFSET = -2;

} // anonymous namespace

class wxFrameWithWindows10Menubar::MenuBarWindow : public wxWindow
{
public:
    MenuBarWindow(wxWindow *parent)
        : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE),
          m_mctrlWin(nullptr), m_mctrlHandle(0)
    {
        if (g_mctrlInitialized++ == 0)
            mcMenubar_Initialize();

        m_mctrlHandle = CreateWindowEx
        (
            WS_EX_COMPOSITED,
            MC_WC_MENUBAR,
            _T(""),
            WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NORESIZE | CCS_NOPARENTALIGN,
            0, 0, 1000, 2 * PX(23),
            (HWND)this->GetHWND(),
            (HMENU) -1,
            wxGetInstance(),
            NULL
        );
        SendMessage(m_mctrlHandle, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS);
        SendMessage(m_mctrlHandle, CCM_SETNOTIFYWINDOW, (WPARAM)parent->GetHWND(), 0);

        m_mctrlWin = new mCtrlWrapper(this, m_mctrlHandle);

        {
            wxUxThemeHandle hTheme(this, L"ExplorerMenu::Toolbar");
            SetBackgroundColour(wxRGBToColour(wxUxThemeEngine::GetIfActive()->GetThemeSysColor(hTheme, COLOR_WINDOW)));
        }
    }

    ~MenuBarWindow()
    {
        m_mctrlWin->Destroy();
        ::DestroyWindow(m_mctrlHandle);

        if (--g_mctrlInitialized == 0)
            mcMenubar_Terminate();
    }

    void SetHMENU(WXHMENU menu)
    {
        SendMessage(m_mctrlHandle, MC_MBM_SETMENU, 0, (LPARAM) menu);
        SendMessage(m_mctrlHandle, MC_MBM_REFRESH, 0, 0);
    }

    bool TranslateMenubarMessage(WXMSG *pMsg)
    {
        MSG *msg = (MSG *) pMsg;
        if (mcIsMenubarMessage(m_mctrlHandle, msg))
            return true;

        return false;
    }

    void DoSetSize(int x, int y, int width, int height, int sizeFlags) override
    {
        wxWindow::DoSetSize(x, y, width, height, sizeFlags);
        SendMessage(m_mctrlHandle, MC_MBM_REFRESH, 0, 0);
    }

    wxSize DoGetBestSize() const override
    {
        wxSize sizeBest = wxDefaultSize;
        SIZE size;
        if (::SendMessage(m_mctrlHandle, TB_GETMAXSIZE, 0, (LPARAM) &size))
        {
            sizeBest.x = size.cx;
            sizeBest.y = size.cy + 1;
            CacheBestSize(sizeBest);
        }
        return sizeBest;
    }

private:
    class mCtrlWrapper : public wxNativeWindow
    {
    public:
        mCtrlWrapper(wxWindow *parent, WXHWND wnd) : wxNativeWindow(parent, wxID_ANY, wnd), m_flagReenterMctrl(0) {}

        WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) override
        {
            switch (nMsg)
            {
                case WM_COMMAND:
                case WM_NOTIFY:
                {
                    wxRecursionGuard guard(m_flagReenterMctrl);

                    if (!guard.IsInside())
                    {
                        return MSWDefWindowProc(nMsg, wParam, lParam);
                    }
                    else
                    {
                        return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam);
                    }
                }
            }

            return wxNativeWindow::MSWWindowProc(nMsg, wParam, lParam);
        }

    private:
        wxRecursionGuardFlag m_flagReenterMctrl;
    };

    mCtrlWrapper *m_mctrlWin;
    WXHWND m_mctrlHandle;
};

wxFrameWithWindows10Menubar::wxFrameWithWindows10Menubar(wxWindow *parent,
                                                         wxWindowID id,
                                                         const wxString& title,
                                                         const wxPoint& pos,
                                                         const wxSize& size,
                                                         long style,
                                                         const wxString& name)
    : wxFrame(parent, id, title, pos, size, style, name), m_menuBar(nullptr)
{
    if (ShouldUse())
    {
        m_menuBar = new MenuBarWindow(this);
    }
}

bool wxFrameWithWindows10Menubar::ShouldUse() const
{
    if (!IsWindows10OrGreater())
        return false;

    if (!wxUxThemeEngine::GetIfActive())
        return false;

    if (wxConfig::Get()->ReadBool("/disable_mctrl", false))
        return false;

    // Detect screen readers and use normal menubar with them, because the
    // mCtrl one isn't accessible.
    BOOL running;
    BOOL ret = SystemParametersInfo(SPI_GETSCREENREADER, 0, &running, 0);
    if (ret && running)
        return false;

    return true;
}

wxPoint wxFrameWithWindows10Menubar::GetClientAreaOrigin() const
{
    wxPoint pt = wxFrame::GetClientAreaOrigin();
    if (IsUsed())
    {
        pt.y += wxMax(m_menuBar->GetSize().y, m_menuBar->GetBestSize().y) + MENUBAR_OFFSET;
    }
    return pt;
}

void wxFrameWithWindows10Menubar::PositionToolBar()
{
    // Position both the toolbar and our menu bar (which is really another toolbar) here.
    if (!IsUsed())
    {
        wxFrame::PositionToolBar();
        return;
    }

    // don't call our (or even wxTopLevelWindow) version because we want
    // the real (full) client area size, not excluding the tool/status bar
    int width, height;
    wxWindow::DoGetClientSize(&width, &height);

    int y = MENUBAR_OFFSET;

    // use the 'real' MSW position here, don't offset relatively to the
    // client area origin
    int mch = m_menuBar->GetBestSize().y;
    m_menuBar->SetSize(0, y, width, mch, wxSIZE_NO_ADJUSTMENTS);
    y += mch;

    wxToolBar *toolbar = GetToolBar();
    if (toolbar && toolbar->IsShown())
    {
        int tbh = toolbar->GetSize().y;
        toolbar->SetSize(0, y, width + 8, tbh, wxSIZE_NO_ADJUSTMENTS);
    }
}

bool wxFrameWithWindows10Menubar::MSWTranslateMessage(WXMSG *msg)
{
    if (wxFrame::MSWTranslateMessage(msg))
        return true;

    if (IsUsed() && m_menuBar->TranslateMenubarMessage(msg))
        return true;

    return false;
}

WXLRESULT wxFrameWithWindows10Menubar::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
    if (IsUsed())
    {
        // mCtrl doesn't play nice with the wxMSW's menus interaction where accelerators are updated
        // when a menu is opened (which works because TranslateAccelerators() normally sends a fake
        // event for that... if there's a normal menu). We need to refresh menus before accelerators
        // are used so that e.g. disabled state is accurately updated.
        if (message == WM_COMMAND && HIWORD(wParam) == 1/*accel*/)
            GetMenuBar()->UpdateMenus();
    }

    return wxFrame::MSWWindowProc(message, wParam, lParam);
}

void wxFrameWithWindows10Menubar::InternalSetMenuBar()
{
    if (IsUsed())
    {
        m_menuBar->SetHMENU(m_hMenu);
    }
    else
    {
        wxFrame::InternalSetMenuBar();
    }
}
<|endoftext|>


<commit_before>//
// Created by hippomormor on 6/4/16.
//

#include "CV_Handler.h"
#include "Color.h"

#define CASCADE_FRAMES 10

Cascade *cascade;
Color *color;
Nav *navData;

using namespace std;

CV_Handler::CV_Handler(void) {

}

void CV_Handler::run(Nav *nav) {
    navData = nav;
    frontCamSelected = true;
    greySelected = false;
    cascade = new Cascade();
    color = new Color();
    video_channel = nodeHandle.resolveName("ardrone/image_raw");
    video_subscriber = nodeHandle.subscribe(video_channel,10, &CV_Handler::video, this);

    ros::Rate r(25);
    while(nodeHandle.ok()) {
        ros::spinOnce();
        r.sleep();
    }
}

CV_Handler::~CV_Handler(void) {
    delete(cascade);
    delete(color);
}

void CV_Handler::video(sensor_msgs::ImageConstPtr img) {
    size_t size = img->width * img->height;

    // Convert from ROS image message to OpenCV Mat with cv_bridge
    cv_bridge::CvImagePtr cv_ptrBw = cv_bridge::toCvCopy(img, sensor_msgs::image_encodings::MONO8);
    cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(img, sensor_msgs::image_encodings::BGR8);

    // Save size constraints to data structure
    storedImageBW.resize(CVD::ImageRef(img->width, img->height));
    storedImage.resize(CVD::ImageRef(img->width, img->height));

    cascadeMutex.lock();

    // Copy image to CVD data structure
    memcpy(storedImageBW.data(), cv_ptrBw->image.data, size);
    memcpy(storedImage.data(), cv_ptr->image.data, size * 3);

    cascadeMutex.unlock();

    show();
}

void CV_Handler::show(void) {
    cv::Mat image;

    if (greySelected) {
        // Convert CVD byte array to OpenCV matrix (use CV_8UC1 format - unsigned 8 bit MONO)
        cv::Mat imageBW(storedImageBW.size().y,
                        storedImageBW.size().x,
                        CV_8UC1,
                        storedImageBW.data());
        image = imageBW;
    } else {
        // Convert CVD byte array to OpenCV matrix (use CV_8UC3 format - unsigned 8 bit BGR 3 channel)
        cv::Mat imageBGR(storedImage.size().y,
                         storedImage.size().x,
                         CV_8UC3,
                 storedImage.data());
        image = imageBGR;
        //image = color->checkColorsTest(std::vector<Cascade::cubeInfo>(), image);
    }

    cv::imshow("VideoMis", image);
    if (cv::waitKey(10) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
        system("kill $(ps aux | grep ros | grep -v grep | awk '{print $2}')");
}

void CV_Handler::swapCam(bool frontCam) {
    cam_service = nodeHandle.serviceClient<std_srvs::Empty>(nodeHandle.resolveName("ardrone/togglecam"),1);
    if (frontCamSelected != frontCam) {
        cam_service.call(toggleCam_srv_srvs);
        frontCamSelected = frontCam;
    }
}

std::vector<Cascade::cubeInfo> CV_Handler::checkCubes(void) {
    int frameCount = 0;
    int biggestArray = 0;
    typedef std::vector<Cascade::cubeInfo> cascadeArray;
    std::vector<cascadeArray> cascades;
    std::vector<Cascade::cubeInfo> cubes;

    while (true) {
        cascadeMutex.lock();

        cv::Mat imageBW(storedImageBW.size().y,
                        storedImageBW.size().x,
                        CV_8UC1,
                        storedImageBW.data());

        cv::Mat image(storedImage.size().y,
                      storedImage.size().x,
                      CV_8UC3,
                      storedImage.data());

        cascadeMutex.unlock();

        cascades.push_back(cascade->checkCascade(imageBW));

        if (++frameCount == CASCADE_FRAMES)
            break;
    }
    if (!cascades.empty()) {
        for (unsigned int i = 0; i < cascades.size(); i++) {
           if (!cascades[i].empty() && cascades[i].size() > cascades[biggestArray].size())
              biggestArray = i;
        }

       // cubes = calculatePosition(cascades[biggestArray]);

        std::cout << "The biggest array is Nr. " << biggestArray << std::endl;
        std::cout << "x: " << cascades[biggestArray][0].x << std::endl;
        std::cout << "xDist: " << cascades[biggestArray][0].xDist << std::endl;
        std::cout << "y: " << cascades[biggestArray][0].y << std::endl;
        std::cout << "yDist: " << cascades[biggestArray][0].yDist << std::endl;
    }
    return std::vector<Cascade::cubeInfo>();
}

std::vector<Cascade::cubeInfo> CV_Handler::calculatePosition(std::vector<Cascade::cubeInfo> cubes) {
    double xFactor = 95.8 / 640;
    double yFactor = 51.7 / 360;

    for (unsigned int i = 0; i < cubes.size(); i++) {
        cubes[i].xDist = xFactor / navData->getPosition().z;
        cubes[i].yDist = yFactor / navData->getPosition().z;
    }
    return cubes;
}<commit_msg>Forgot something..<commit_after>//
// Created by hippomormor on 6/4/16.
//

#include "CV_Handler.h"
#include "Color.h"

#define CASCADE_FRAMES 10

Cascade *cascade;
Color *color;
Nav *navData;

using namespace std;

CV_Handler::CV_Handler(void) {

}

void CV_Handler::run(Nav *nav) {
    navData = nav;
    frontCamSelected = true;
    greySelected = false;
    cascade = new Cascade();
    color = new Color();
    video_channel = nodeHandle.resolveName("ardrone/image_raw");
    video_subscriber = nodeHandle.subscribe(video_channel,10, &CV_Handler::video, this);

    ros::Rate r(25);
    while(nodeHandle.ok()) {
        ros::spinOnce();
        r.sleep();
    }
}

CV_Handler::~CV_Handler(void) {
    delete(cascade);
    delete(color);
}

void CV_Handler::video(sensor_msgs::ImageConstPtr img) {
    size_t size = img->width * img->height;

    // Convert from ROS image message to OpenCV Mat with cv_bridge
    cv_bridge::CvImagePtr cv_ptrBw = cv_bridge::toCvCopy(img, sensor_msgs::image_encodings::MONO8);
    cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(img, sensor_msgs::image_encodings::BGR8);

    // Save size constraints to data structure
    storedImageBW.resize(CVD::ImageRef(img->width, img->height));
    storedImage.resize(CVD::ImageRef(img->width, img->height));

    cascadeMutex.lock();

    // Copy image to CVD data structure
    memcpy(storedImageBW.data(), cv_ptrBw->image.data, size);
    memcpy(storedImage.data(), cv_ptr->image.data, size * 3);

    cascadeMutex.unlock();

    show();
}

void CV_Handler::show(void) {
    cv::Mat image;

    if (greySelected) {
        // Convert CVD byte array to OpenCV matrix (use CV_8UC1 format - unsigned 8 bit MONO)
        cv::Mat imageBW(storedImageBW.size().y,
                        storedImageBW.size().x,
                        CV_8UC1,
                        storedImageBW.data());
        image = imageBW;
    } else {
        // Convert CVD byte array to OpenCV matrix (use CV_8UC3 format - unsigned 8 bit BGR 3 channel)
        cv::Mat imageBGR(storedImage.size().y,
                         storedImage.size().x,
                         CV_8UC3,
                 storedImage.data());
        image = imageBGR;
        //image = color->checkColorsTest(std::vector<Cascade::cubeInfo>(), image);
    }

    cv::imshow("VideoMis", image);
    if (cv::waitKey(10) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
        system("kill $(ps aux | grep ros | grep -v grep | awk '{print $2}')");
}

void CV_Handler::swapCam(bool frontCam) {
    cam_service = nodeHandle.serviceClient<std_srvs::Empty>(nodeHandle.resolveName("ardrone/togglecam"),1);
    if (frontCamSelected != frontCam) {
        cam_service.call(toggleCam_srv_srvs);
        frontCamSelected = frontCam;
    }
}

std::vector<Cascade::cubeInfo> CV_Handler::checkCubes(void) {
    int frameCount = 0;
    int biggestArray = 0;
    typedef std::vector<Cascade::cubeInfo> cascadeArray;
    std::vector<cascadeArray> cascades;
    std::vector<Cascade::cubeInfo> cubes;

    while (true) {
        cascadeMutex.lock();

        cv::Mat imageBW(storedImageBW.size().y,
                        storedImageBW.size().x,
                        CV_8UC1,
                        storedImageBW.data());

        cv::Mat image(storedImage.size().y,
                      storedImage.size().x,
                      CV_8UC3,
                      storedImage.data());

        cascadeMutex.unlock();

        cascades.push_back(cascade->checkCascade(imageBW));

        if (++frameCount == CASCADE_FRAMES)
            break;
    }
    if (!cascades.empty()) {
        for (unsigned int i = 0; i < cascades.size(); i++) {
           if (!cascades[i].empty() && cascades[i].size() > cascades[biggestArray].size())
              biggestArray = i;
        }

        cascades[biggestArray] = calculatePosition(cascades[biggestArray]);

        std::cout << "The biggest array is Nr. " << biggestArray << std::endl;
        std::cout << "x: " << cascades[biggestArray][0].x << std::endl;
        std::cout << "xDist: " << cascades[biggestArray][0].xDist << std::endl;
        std::cout << "y: " << cascades[biggestArray][0].y << std::endl;
        std::cout << "yDist: " << cascades[biggestArray][0].yDist << std::endl;
    }
    return std::vector<Cascade::cubeInfo>();
}

std::vector<Cascade::cubeInfo> CV_Handler::calculatePosition(std::vector<Cascade::cubeInfo> cubes) {
    double xFactor = 95.8 / 640;
    double yFactor = 51.7 / 360;

    for (unsigned int i = 0; i < cubes.size(); i++) {
        cubes[i].xDist = xFactor / navData->getPosition().z;
        cubes[i].yDist = yFactor / navData->getPosition().z;
    }
    return cubes;
}<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2018)

#ifndef DUNE_GDT_OPERATORS_ADVECTION_FV_HH
#define DUNE_GDT_OPERATORS_ADVECTION_FV_HH

#include <dune/xt/common/type_traits.hh>
#include <dune/xt/grid/type_traits.hh>
#include <dune/xt/grid/walker/filters.hh>

#include <dune/gdt/local/operators/advection-fv.hh>

#include "interfaces.hh"
#include "localizable-operator.hh"

namespace Dune {
namespace GDT {

/**
 * \note See OperatorInterface for a description of the template arguments.
 *
 * \sa OperatorInterface
 */
template <class AssemblyGridView,
          class SV,
          size_t m = 1,
          class SF = double,
          class SGV = AssemblyGridView,
          class RF = SF,
          class RGV = AssemblyGridView,
          class RV = SV>
class AdvectionFvOperator : public OperatorInterface<SV,
                                                     SGV,
                                                     m,
                                                     1,
                                                     SF,
                                                     typename XT::Common::multiplication_promotion<SF, RF>::type,
                                                     m,
                                                     1,
                                                     RF,
                                                     RGV,
                                                     RV>
{
  // No need to check the rest, is done in OperatorInterface.
  static_assert(XT::Grid::is_view<AssemblyGridView>::value, "");
  static_assert((AssemblyGridView::dimension == SGV::dimension) && (AssemblyGridView::dimension == RGV::dimension), "");

  using ThisType = AdvectionFvOperator<AssemblyGridView, SV, m, SF, SGV, RF, RGV, RV>;
  using BaseType = OperatorInterface<SV,
                                     SGV,
                                     m,
                                     1,
                                     SF,
                                     typename XT::Common::multiplication_promotion<SF, RF>::type,
                                     m,
                                     1,
                                     RF,
                                     RGV,
                                     RV>;
  using AGV = AssemblyGridView;

public:
  using AssemblyGridViewType = AssemblyGridView;
  using NumericalFluxType = NumericalFluxInterface<AssemblyGridView::dimension, m, RF>;

  using I = XT::Grid::extract_intersection_t<AGV>;
  using BoundaryTreatmentByCustomNumericalFluxOperatorType =
      LocalAdvectionFvBoundaryTreatmentByCustomNumericalFluxOperator<I, SV, SGV, m, SF, RF, RGV, RV>;
  using BoundaryTreatmentByCustomExtrapolationOperatorType =
      LocalAdvectionFvBoundaryTreatmentByCustomExtrapolationOperator<I, SV, SGV, m, SF, RF, RGV, RV>;

  using typename BaseType::SourceSpaceType;
  using typename BaseType::RangeSpaceType;

  using typename BaseType::SourceVectorType;
  using typename BaseType::RangeVectorType;

  AdvectionFvOperator(
      const AssemblyGridViewType& assembly_grid_view,
      const NumericalFluxType& numerical_flux,
      const SourceSpaceType& source_space,
      const RangeSpaceType& range_space,
      const XT::Grid::IntersectionFilter<AGV>& periodicity_exception = XT::Grid::ApplyOn::NoIntersections<AGV>())
    : BaseType(numerical_flux.parameter_type())
    , assembly_grid_view_(assembly_grid_view)
    , numerical_flux_(numerical_flux)
    , source_space_(source_space)
    , range_space_(range_space)
    , periodicity_exception_(periodicity_exception.copy())
  {
  }

  AdvectionFvOperator(ThisType&& source) = default;

  bool linear() const override final
  {
    return numerical_flux_.linear();
  }

  const SourceSpaceType& source_space() const override final
  {
    return source_space_;
  }

  const RangeSpaceType& range_space() const override final
  {
    return range_space_;
  }

  /// \name Non-periodic boundary treatment
  /// \{

  ThisType&
  append(typename BoundaryTreatmentByCustomNumericalFluxOperatorType::LambdaType numerical_boundary_treatment_flux,
         const XT::Common::ParameterType& boundary_treatment_parameter_type = {},
         const XT::Grid::IntersectionFilter<AGV>& filter = XT::Grid::ApplyOn::BoundaryIntersections<AGV>())
  {
    boundary_treatments_by_custom_numerical_flux_.emplace_back(
        new BoundaryTreatmentByCustomNumericalFluxOperatorType(numerical_boundary_treatment_flux,
                                                               boundary_treatment_parameter_type),
        filter.copy());
    return *this;
  }

  ThisType& append(typename BoundaryTreatmentByCustomExtrapolationOperatorType::LambdaType extrapolation,
                   const XT::Common::ParameterType& extrapolation_parameter_type = {},
                   const XT::Grid::IntersectionFilter<AGV>& filter = XT::Grid::ApplyOn::BoundaryIntersections<AGV>())
  {
    boundary_treatments_by_custom_extrapolation_.emplace_back(
        new BoundaryTreatmentByCustomExtrapolationOperatorType(
            numerical_flux_, extrapolation, extrapolation_parameter_type),
        filter.copy());
    return *this;
  }

  /// \}

  using BaseType::apply;

  void apply(const SourceVectorType& source,
             RangeVectorType& range,
             const XT::Common::Parameter& param = {}) const override final
  {
    // some checks
    DUNE_THROW_IF(!source.valid(), Exceptions::operator_error, "source contains inf or nan!");
    DUNE_THROW_IF(!(this->parameter_type() <= param.type()),
                  Exceptions::operator_error,
                  "this->parameter_type() = " << this->parameter_type() << "\n   param.type() = " << param.type());
    range.set_all(0);
    const auto source_function = make_discrete_function(source_space_, source);
    auto range_function = make_discrete_function(range_space_, range);
    // set up the actual operator
    auto localizable_op = make_localizable_operator(assembly_grid_view_, source_function, range_function);
    // treat all inner intersections
    localizable_op.append(LocalAdvectionFvCouplingOperator<I, SV, SGV, m, SF, RF, RGV, RV>(numerical_flux_),
                          param,
                          XT::Grid::ApplyOn::InnerIntersectionsOnce<AGV>());
    // treat periodic boundaries
    localizable_op.append(LocalAdvectionFvCouplingOperator<I, SV, SGV, m, SF, RF, RGV, RV>(numerical_flux_),
                          param,
                          *(XT::Grid::ApplyOn::PeriodicBoundaryIntersectionsOnce<AGV>() && !(*periodicity_exception_)));
    // treat boundaries by custom numerical flux
    for (const auto& boundary_treatment : boundary_treatments_by_custom_numerical_flux_) {
      const auto& boundary_op = *boundary_treatment.first;
      const auto& filter = *boundary_treatment.second;
      localizable_op.append(boundary_op, param, filter);
    }
    // treat boundaries by custom extrapolation
    for (const auto& boundary_treatment : boundary_treatments_by_custom_extrapolation_) {
      const auto& boundary_op = *boundary_treatment.first;
      const auto& filter = *boundary_treatment.second;
      localizable_op.append(boundary_op, param, filter);
    }
    // do the actual work
    localizable_op.assemble(/*use_tbb=*/true);
    DUNE_THROW_IF(!range.valid(), Exceptions::operator_error, "range contains inf or nan!");
  } // ... apply(...)

private:
  const AssemblyGridViewType& assembly_grid_view_;
  const NumericalFluxType& numerical_flux_;
  const SourceSpaceType& source_space_;
  const RangeSpaceType& range_space_;
  std::unique_ptr<XT::Grid::IntersectionFilter<AssemblyGridViewType>> periodicity_exception_;
  std::list<std::pair<std::unique_ptr<BoundaryTreatmentByCustomNumericalFluxOperatorType>,
                      std::unique_ptr<XT::Grid::IntersectionFilter<AGV>>>>
      boundary_treatments_by_custom_numerical_flux_;
  std::list<std::pair<std::unique_ptr<BoundaryTreatmentByCustomExtrapolationOperatorType>,
                      std::unique_ptr<XT::Grid::IntersectionFilter<AGV>>>>
      boundary_treatments_by_custom_extrapolation_;
}; // class AdvectionFvOperator

template <class VectorType, class AGV, size_t m, class RF, class SGV, class SF, class RGV>
std::enable_if_t<XT::LA::is_vector<VectorType>::value,
                 AdvectionFvOperator<AGV, VectorType, m, SF, SGV, RF, RGV, VectorType>>
make_advection_fv_operator(
    const AGV& assembly_grid_view,
    const NumericalFluxInterface<AGV::dimension, m, RF>& numerical_flux,
    const SpaceInterface<SGV, m, 1, SF>& source_space,
    const SpaceInterface<RGV, m, 1, RF>& range_space,
    const XT::Grid::IntersectionFilter<AGV>& periodicity_exception = XT::Grid::ApplyOn::NoIntersections<AGV>())
{
  return AdvectionFvOperator<AGV, VectorType, m, SF, SGV, RF, RGV, VectorType>(
      assembly_grid_view, numerical_flux, source_space, range_space, periodicity_exception);
}

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_OPERATORS_ADVECTION_FV_HH
<commit_msg>[operators.advection] minor update<commit_after>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2018)

#ifndef DUNE_GDT_OPERATORS_ADVECTION_FV_HH
#define DUNE_GDT_OPERATORS_ADVECTION_FV_HH

#include <dune/xt/common/type_traits.hh>
#include <dune/xt/grid/type_traits.hh>
#include <dune/xt/grid/walker/filters.hh>

#include <dune/gdt/local/operators/advection-fv.hh>

#include "interfaces.hh"
#include "localizable-operator.hh"

namespace Dune {
namespace GDT {

/**
 * \note See OperatorInterface for a description of the template arguments.
 *
 * \sa OperatorInterface
 */
template <class AssemblyGridView,
          class SV,
          size_t m = 1,
          class SF = double,
          class SGV = AssemblyGridView,
          class RF = SF,
          class RGV = AssemblyGridView,
          class RV = SV>
class AdvectionFvOperator : public OperatorInterface<SV,
                                                     SGV,
                                                     m,
                                                     1,
                                                     SF,
                                                     typename XT::Common::multiplication_promotion<SF, RF>::type,
                                                     m,
                                                     1,
                                                     RF,
                                                     RGV,
                                                     RV>
{
  // No need to check the rest, is done in OperatorInterface.
  static_assert(XT::Grid::is_view<AssemblyGridView>::value, "");
  static_assert((AssemblyGridView::dimension == SGV::dimension) && (AssemblyGridView::dimension == RGV::dimension), "");

  using ThisType = AdvectionFvOperator<AssemblyGridView, SV, m, SF, SGV, RF, RGV, RV>;
  using BaseType = OperatorInterface<SV,
                                     SGV,
                                     m,
                                     1,
                                     SF,
                                     typename XT::Common::multiplication_promotion<SF, RF>::type,
                                     m,
                                     1,
                                     RF,
                                     RGV,
                                     RV>;
  using AGV = AssemblyGridView;

public:
  using AssemblyGridViewType = AssemblyGridView;
  using NumericalFluxType = NumericalFluxInterface<AssemblyGridView::dimension, m, RF>;

  using I = XT::Grid::extract_intersection_t<AGV>;
  using BoundaryTreatmentByCustomNumericalFluxOperatorType =
      LocalAdvectionFvBoundaryTreatmentByCustomNumericalFluxOperator<I, SV, SGV, m, SF, RF, RGV, RV>;
  using BoundaryTreatmentByCustomExtrapolationOperatorType =
      LocalAdvectionFvBoundaryTreatmentByCustomExtrapolationOperator<I, SV, SGV, m, SF, RF, RGV, RV>;

  using typename BaseType::SourceSpaceType;
  using typename BaseType::RangeSpaceType;

  using typename BaseType::SourceVectorType;
  using typename BaseType::RangeVectorType;

  AdvectionFvOperator(
      const AssemblyGridViewType& assembly_grid_view,
      const NumericalFluxType& numerical_flux,
      const SourceSpaceType& source_space,
      const RangeSpaceType& range_space,
      const XT::Grid::IntersectionFilter<AGV>& periodicity_exception = XT::Grid::ApplyOn::NoIntersections<AGV>())
    : BaseType(numerical_flux.parameter_type())
    , assembly_grid_view_(assembly_grid_view)
    , numerical_flux_(numerical_flux.copy())
    , source_space_(source_space)
    , range_space_(range_space)
    , periodicity_exception_(periodicity_exception.copy())
  {
  }

  AdvectionFvOperator(ThisType&& source) = default;

  bool linear() const override final
  {
    return numerical_flux_->linear();
  }

  const SourceSpaceType& source_space() const override final
  {
    return source_space_;
  }

  const RangeSpaceType& range_space() const override final
  {
    return range_space_;
  }

  /// \name Non-periodic boundary treatment
  /// \{

  ThisType&
  append(typename BoundaryTreatmentByCustomNumericalFluxOperatorType::LambdaType numerical_boundary_treatment_flux,
         const XT::Common::ParameterType& boundary_treatment_parameter_type = {},
         const XT::Grid::IntersectionFilter<AGV>& filter = XT::Grid::ApplyOn::BoundaryIntersections<AGV>())
  {
    boundary_treatments_by_custom_numerical_flux_.emplace_back(
        new BoundaryTreatmentByCustomNumericalFluxOperatorType(numerical_boundary_treatment_flux,
                                                               boundary_treatment_parameter_type),
        filter.copy());
    return *this;
  }

  ThisType& append(typename BoundaryTreatmentByCustomExtrapolationOperatorType::LambdaType extrapolation,
                   const XT::Common::ParameterType& extrapolation_parameter_type = {},
                   const XT::Grid::IntersectionFilter<AGV>& filter = XT::Grid::ApplyOn::BoundaryIntersections<AGV>())
  {
    boundary_treatments_by_custom_extrapolation_.emplace_back(
        new BoundaryTreatmentByCustomExtrapolationOperatorType(
            *numerical_flux_, extrapolation, extrapolation_parameter_type),
        filter.copy());
    return *this;
  }

  /// \}

  using BaseType::apply;

  void apply(const SourceVectorType& source,
             RangeVectorType& range,
             const XT::Common::Parameter& param = {}) const override final
  {
    // some checks
    DUNE_THROW_IF(!source.valid(), Exceptions::operator_error, "source contains inf or nan!");
    DUNE_THROW_IF(!(this->parameter_type() <= param.type()),
                  Exceptions::operator_error,
                  "this->parameter_type() = " << this->parameter_type() << "\n   param.type() = " << param.type());
    range.set_all(0);
    const auto source_function = make_discrete_function(source_space_, source);
    auto range_function = make_discrete_function(range_space_, range);
    // set up the actual operator
    auto localizable_op = make_localizable_operator(assembly_grid_view_, source_function, range_function);
    // contributions from inner intersections
    localizable_op.append(LocalAdvectionFvCouplingOperator<I, SV, SGV, m, SF, RF, RGV, RV>(*numerical_flux_),
                          param,
                          XT::Grid::ApplyOn::InnerIntersectionsOnce<AGV>());
    // contributions from periodic boundaries
    localizable_op.append(LocalAdvectionFvCouplingOperator<I, SV, SGV, m, SF, RF, RGV, RV>(*numerical_flux_),
                          param,
                          *(XT::Grid::ApplyOn::PeriodicBoundaryIntersectionsOnce<AGV>() && !(*periodicity_exception_)));
    // contributions from other boundaries by custom numerical flux
    for (const auto& boundary_treatment : boundary_treatments_by_custom_numerical_flux_) {
      const auto& boundary_op = *boundary_treatment.first;
      const auto& filter = *boundary_treatment.second;
      localizable_op.append(boundary_op, param, filter);
    }
    // contributions from other boundaries by custom extrapolation
    for (const auto& boundary_treatment : boundary_treatments_by_custom_extrapolation_) {
      const auto& boundary_op = *boundary_treatment.first;
      const auto& filter = *boundary_treatment.second;
      localizable_op.append(boundary_op, param, filter);
    }
    // do the actual work
    localizable_op.assemble(/*use_tbb=*/true);
    DUNE_THROW_IF(!range.valid(), Exceptions::operator_error, "range contains inf or nan!");
  } // ... apply(...)

private:
  const AssemblyGridViewType& assembly_grid_view_;
  const std::unique_ptr<const NumericalFluxType> numerical_flux_;
  const SourceSpaceType& source_space_;
  const RangeSpaceType& range_space_;
  std::unique_ptr<XT::Grid::IntersectionFilter<AssemblyGridViewType>> periodicity_exception_;
  std::list<std::pair<std::unique_ptr<BoundaryTreatmentByCustomNumericalFluxOperatorType>,
                      std::unique_ptr<XT::Grid::IntersectionFilter<AGV>>>>
      boundary_treatments_by_custom_numerical_flux_;
  std::list<std::pair<std::unique_ptr<BoundaryTreatmentByCustomExtrapolationOperatorType>,
                      std::unique_ptr<XT::Grid::IntersectionFilter<AGV>>>>
      boundary_treatments_by_custom_extrapolation_;
}; // class AdvectionFvOperator

template <class VectorType, class AGV, size_t m, class RF, class SGV, class SF, class RGV>
std::enable_if_t<XT::LA::is_vector<VectorType>::value,
                 AdvectionFvOperator<AGV, VectorType, m, SF, SGV, RF, RGV, VectorType>>
make_advection_fv_operator(
    const AGV& assembly_grid_view,
    const NumericalFluxInterface<AGV::dimension, m, RF>& numerical_flux,
    const SpaceInterface<SGV, m, 1, SF>& source_space,
    const SpaceInterface<RGV, m, 1, RF>& range_space,
    const XT::Grid::IntersectionFilter<AGV>& periodicity_exception = XT::Grid::ApplyOn::NoIntersections<AGV>())
{
  return AdvectionFvOperator<AGV, VectorType, m, SF, SGV, RF, RGV, VectorType>(
      assembly_grid_view, numerical_flux, source_space, range_space, periodicity_exception);
}

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_OPERATORS_ADVECTION_FV_HH
<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_GRID_PROVIDER_STARCD_HH
#define DUNE_STUFF_GRID_PROVIDER_STARCD_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#else
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#if HAVE_DUNE_GRID
//#if HAVE_ALUGRID || HAVE_ALBERTA || HAVE_UG
//#if defined ALUGRID_CONFORM || defined ALUGRID_CUBE || defined ALUGRID_SIMPLEX || defined ALBERTAGRID || defined UGGRID

#include <iostream>
#include <fstream>
#include <sstream>
#include <type_traits>

#include <boost/assign/list_of.hpp>

#include <dune/common/parametertree.hh>
#include <dune/common/shared_ptr.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/geometry/type.hh>

#include <dune/grid/common/gridfactory.hh>
#include <dune/grid/utility/structuredgridfactory.hh>
#include <dune/grid/sgrid.hh>

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/string.hh>

#include "interface.hh"

namespace Dune {
namespace Stuff {
namespace Grid {
namespace Provider {

/**
 * \brief   StarCD grid provider
 */
#if defined HAVE_CONFIG_H || defined HAVE_CMAKE_CONFIG
template< class GridImp = Dune::GridSelector::GridType >
#else // defined HAVE_CONFIG_H || defined HAVE_CMAKE_CONFIG
template< class GridImp = Dune::SGrid< 2, 2 > >
#endif // defined HAVE_CONFIG_H || defined HAVE_CMAKE_CONFIG
class StarCD
  : public Interface< GridImp >
{
public:
  //! Type of the provided grid.
  typedef GridImp GridType;

  typedef Interface< GridType > BaseType;

  typedef StarCD< GridType > ThisType;

  //! Dimension of the provided grid.
  static const unsigned int dim = BaseType::dim;

  //! Type of the grids coordinates.
  typedef typename BaseType::CoordinateType CoordinateType;

  //! Unique identifier: \c stuff.grid.provider.starcd
  static const std::string id()
  {
    return BaseType::id() + ".starcd";
  }

  StarCD(const std::string filename)
  {
    // set up the grid factory
    GridFactory<GridType> factory;

    // set the name of the vertex file
    const std::string vertexFileName = filename + ".vrt";

    // set the vertex input stream
    std::ifstream vertexFile(vertexFileName);
    if (!vertexFile)
        DUNE_THROW(Dune::IOError, "Could not open " << vertexFileName);

    std::string line;

    if (!std::getline(vertexFile,line))
      DUNE_THROW(Dune::IOError, "File " << vertexFileName << " is too short!");
    if (! (line == "PROSTAR_VERTEX"))
      DUNE_THROW(Dune::IOError, "First line of File " << vertexFileName << " (" << line << "is not equal to 'PROSTAR_VERTEX' !");
    if (!std::getline(vertexFile,line))
      DUNE_THROW(Dune::IOError, "File " << vertexFileName << " is too short!");

    // read the vertices
    int numberOfVertices = 0;
    Dune::FieldVector<double,dim> position;

    while(std::getline(vertexFile,line))
    {
        numberOfVertices++;
        const std::vector<double> items = Dune::Stuff::Common::tokenize<double>(line, " ");
        assert(items.size() == dim + 1);
        for (unsigned int ii = 0; ii < dim; ++ii)
          position[ii] = items[ii + 1];
        std::cout << position << std::endl;
        factory.insertVertex(position);
    }
    std::cout << numberOfVertices << " vertices read." << std::endl;

    // set the name of the element file
    std::string elementFileName = filename + ".cel";

    // set the element input stream
    std::ifstream elementFile(elementFileName);
    if (!elementFile)
        DUNE_THROW(Dune::IOError, "Could not open " << elementFileName);

    if (!std::getline(elementFile,line))
      DUNE_THROW(Dune::IOError, "File " << elementFileName << " is too short!");
    if (!(line == "PROSTAR_CELL"))
      DUNE_THROW(Dune::IOError, "First line of File " << elementFileName << " (" << line << "is not equal to 'PROSTAR_CELL' !");
    if (!std::getline(elementFile,line))
      DUNE_THROW(Dune::IOError, "File " << elementFileName << " is too short!");

    // read the elements
    unsigned int numberOfElements = 0;
    unsigned int numberOfPrisms = 0;
    unsigned int numberOfCubes = 0;
    unsigned int numberOfVerticesCube = (unsigned int)pow(2, dim);
    unsigned int numberOfVerticesPrism = 6;

    std::vector<unsigned int> cubeVertices(numberOfVerticesCube);
    std::vector<unsigned int> prismVertices(numberOfVerticesPrism);
    std::string firstLine;
    std::string secondLine;
    while(std::getline(elementFile, firstLine))
    {
        std::getline(elementFile, secondLine);
        std::cout << firstLine << std::endl;
        std::cout << secondLine << std::endl;
        numberOfElements++;

        const std::vector<int> items1 = Dune::Stuff::Common::tokenize<int>(firstLine, " ");
        std::vector<int> items2 = Dune::Stuff::Common::tokenize<int>(secondLine, " ");

//        for (unsigned int j=0; j<items1.size(); j++)
//        {
//            std::cout << "items1[j]: " << items1[j] << std::endl;
//        }
//        for (unsigned int j=0; j<items2.size(); j++)
//        {
//            std::cout << "items2[j]: " << items2[j] << std::endl;
//        }

        // Erase zeros at the beginning of the line
        items2.erase(std::remove(items2.begin(), items2.end(), 0), items2.end());

//        std::cout << "second line without zeros:"  << std::endl;
//        for (unsigned int j=0; j<items2.size(); j++)
//        {
//            std::cout << "items2[j]: " << items2[j] << std::endl;
//        }

        if ((!items1[0]==items2[0]) || (!numberOfElements==items2[0]))
          DUNE_THROW(Dune::IOError, "Elementindices do not correspond!");

        if (items2.size() == numberOfVerticesCube + 1) //cube
        {
          numberOfCubes++;
          for (unsigned int k = 0; k < numberOfVerticesCube; k++)
          {
            cubeVertices[k] = items2[k+1];
//            std::cout << "cubeVertices[k]: " << cubeVertices[k] << std::endl;
          }
          //im StarCDReader werden cubes so eingelesen:
          //        std::vector<unsigned int> cubeVertices(8);
          //        for (int k = 0; k < 8; k++)
          //            cubeVertices[k] = vertices[k] - 1;
          //        std::swap(cubeVertices[2], cubeVertices[3]);
          //        std::swap(cubeVertices[6], cubeVertices[7]);
          // warum werden die vertices vertauscht und warum wird von ihnen immer 1 abgezogen?

          factory.insertElement(Dune::GeometryType(Dune::GeometryType::cube,dim), cubeVertices);
        }
        else if (items2.size() == numberOfVerticesPrism + 1) //prism
        {
          numberOfPrisms++;
          for (unsigned int k = 0; k < numberOfVerticesPrism; k++)
          {
            prismVertices[k] = items2[k+1];
//            std::cout << "prismVertices[k]: " << prismVertices[k] << std::endl;
          }
          //im StarCDReader werden prisms so eingelesen:
          //       std::vector<unsigned int> prismVertices(6);
          //       for (int k = 0; k < 3; k++)
          //         prismVertices[k] = vertices[k] - 1;  // warum wird 1 abgezogen?
          //       for (int k = 3; k < 6; k++)
          //         prismVertices[k] =vertices[k+1] - 1; // warum wird 1 abgezogen?

//          factory.insertElement(Dune::GeometryType(Dune::GeometryType::prism,dim), prismVertices);
        }
        else //not cube or prism
        {
          DUNE_THROW(Dune::IOError, "Type of element " << numberOfElements << " is not cube or prism!");
        }
    } //while loop

    if (!numberOfElements == (numberOfCubes + numberOfPrisms))
      DUNE_THROW(Dune::IOError, "Number of Elements (" << numberOfElements << ") is not equal to number of cubes (" << numberOfCubes << ") and number of prisms (" << numberOfPrisms << ").");

    std::cout << numberOfElements << " elements read: "
              << numberOfPrisms << " prisms and "          << numberOfCubes << " cubes." << std::endl;

    // finish off the construction of the grid object
    std::cout << "Starting createGrid() ... " << std::endl;
    factory.createGrid();

//    dune_static_assert(!(Dune::is_same< GridType, Dune::YaspGrid< dim > >::value), "StarCDReader does not work with YaspGrid!");
//    dune_static_assert(!(Dune::is_same< GridType, Dune::SGrid< 2, 2 > >::value), "StarCDReader does not work with SGrid!");

//    grid_ = Dune::shared_ptr< GridType >(factory.createGrid());
  } //constructor

  StarCD(ThisType& other)
    : grid_(other.grid_)
  {}

  StarCD(const ThisType& other)
    : grid_(other.grid_)
  {}

  static ThisType createFromParamTree(const Dune::ParameterTree& paramTree, const std::string subName = id())
  {
    // get correct paramTree
    Dune::Stuff::Common::ExtendedParameterTree extendedParamTree;
    if (paramTree.hasSub(subName))
      extendedParamTree = paramTree.sub(subName);
    else
      extendedParamTree = paramTree;
    // create and return
    if (!extendedParamTree.hasKey("filename"))
      DUNE_THROW(Dune::RangeError,
                 "\nMissing key 'filename' in the following Dune::ParameterTree:\n" << extendedParamTree.reportString("  "));
    const std::string filename = extendedParamTree.get("filename", "meaningless_default_value");
    return StarCD(filename);
  }

  ThisType& operator=(ThisType& other)
  {
    if (this != &other) {
      grid_ = other.grid();
    }
    return this;
  }

  //! access to shared ptr
  virtual Dune::shared_ptr<GridType> grid()
  {
    return grid_;
  }

  //! const access to shared ptr
  virtual const Dune::shared_ptr< const GridType > grid() const
  {
    return grid_;
  }

private:
  Dune::shared_ptr< GridType > grid_;
}; // class StarCD

} // namespace Provider
} // namespace Grid
} // namespace Stuff
} // namespace Dune

//#endif // defined ALUGRID_CONFORM || defined ALUGRID_CUBE || defined ALUGRID_SIMPLEX || defined ALBERTAGRID || defined UGGRID
//#endif // HAVE_ALUGRID || HAVE_ALBERTA || HAVE_UG
#endif // HAVE_DUNE_GRID

#endif // DUNE_STUFF_GRID_PROVIDER_STARCD_HH
<commit_msg>[...grid.provider.starcd]<commit_after>#ifndef DUNE_STUFF_GRID_PROVIDER_STARCD_HH
#define DUNE_STUFF_GRID_PROVIDER_STARCD_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#else
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#if HAVE_DUNE_GRID
//#if HAVE_ALUGRID || HAVE_ALBERTA || HAVE_UG
//#if defined ALUGRID_CONFORM || defined ALUGRID_CUBE || defined ALUGRID_SIMPLEX || defined ALBERTAGRID || defined UGGRID

#include <iostream>
#include <fstream>
#include <sstream>
#include <type_traits>

#include <boost/assign/list_of.hpp>

#include <dune/common/parametertree.hh>
#include <dune/common/shared_ptr.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/geometry/type.hh>

#include <dune/grid/common/gridfactory.hh>
#include <dune/grid/utility/structuredgridfactory.hh>
#include <dune/grid/sgrid.hh>

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/string.hh>

#include "interface.hh"

namespace Dune {
namespace Stuff {
namespace Grid {
namespace Provider {

/**
 * \brief   StarCD grid provider
 */
#if defined HAVE_CONFIG_H || defined HAVE_CMAKE_CONFIG
template< class GridImp = Dune::GridSelector::GridType >
#else // defined HAVE_CONFIG_H || defined HAVE_CMAKE_CONFIG
template< class GridImp = Dune::SGrid< 2, 2 > >
#endif // defined HAVE_CONFIG_H || defined HAVE_CMAKE_CONFIG
class StarCD
  : public Interface< GridImp >
{
public:
  //! Type of the provided grid.
  typedef GridImp GridType;

  typedef Interface< GridType > BaseType;

  typedef StarCD< GridType > ThisType;

  //! Dimension of the provided grid.
  static const unsigned int dim = BaseType::dim;

  //! Type of the grids coordinates.
  typedef typename BaseType::CoordinateType CoordinateType;

  //! Unique identifier: \c stuff.grid.provider.starcd
  static const std::string id()
  {
    return BaseType::id() + ".starcd";
  }

  StarCD(const std::string filename)
  {
    // set up the grid factory
    GridFactory<GridType> factory;

    // set the name of the vertex file
    const std::string vertexFileName = filename + ".vrt";

    // set the vertex input stream
    std::ifstream vertexFile(vertexFileName);
    if (!vertexFile)
        DUNE_THROW(Dune::IOError, "Could not open " << vertexFileName);

    std::string line;

    if (!std::getline(vertexFile,line))
      DUNE_THROW(Dune::IOError, "File " << vertexFileName << " is too short!");
    if (! (line == "PROSTAR_VERTEX"))
      DUNE_THROW(Dune::IOError, "First line of File " << vertexFileName << " (" << line << "is not equal to 'PROSTAR_VERTEX' !");
    if (!std::getline(vertexFile,line))
      DUNE_THROW(Dune::IOError, "File " << vertexFileName << " is too short!");

    // read the vertices
    int numberOfVertices = 0;
    Dune::FieldVector<double,dim> position;

    while(std::getline(vertexFile,line))
    {
        numberOfVertices++;
        const std::vector<double> items = Dune::Stuff::Common::tokenize<double>(line, " ");
        assert(items.size() == dim + 1);
        for (unsigned int ii = 0; ii < dim; ++ii)
          position[ii] = items[ii + 1];
//        std::cout << position << std::endl;
        factory.insertVertex(position);
    }
    std::cout << numberOfVertices << " vertices read." << std::endl;

    // set the name of the element file
    std::string elementFileName = filename + ".cel";

    // set the element input stream
    std::ifstream elementFile(elementFileName);
    if (!elementFile)
        DUNE_THROW(Dune::IOError, "Could not open " << elementFileName);

    if (!std::getline(elementFile,line))
      DUNE_THROW(Dune::IOError, "File " << elementFileName << " is too short!");
    if (!(line == "PROSTAR_CELL"))
      DUNE_THROW(Dune::IOError, "First line of File " << elementFileName << " (" << line << "is not equal to 'PROSTAR_CELL' !");
    if (!std::getline(elementFile,line))
      DUNE_THROW(Dune::IOError, "File " << elementFileName << " is too short!");

    // read the elements
    unsigned int numberOfElements = 0;
    unsigned int numberOfPrisms = 0;
    unsigned int numberOfCubes = 0;
    unsigned int numberOfVerticesCube = (unsigned int)pow(2, dim);
    unsigned int numberOfVerticesPrism = 6;

    std::vector<unsigned int> cubeVertices(numberOfVerticesCube);
    std::vector<unsigned int> prismVertices(numberOfVerticesPrism);
    std::string firstLine;
    std::string secondLine;
    while(std::getline(elementFile, firstLine))
    {
        std::getline(elementFile, secondLine);
//        std::cout << firstLine << std::endl;
//        std::cout << secondLine << std::endl;
        numberOfElements++;

        const std::vector<int> items1 = Dune::Stuff::Common::tokenize<int>(firstLine, " ");
        std::vector<int> items2 = Dune::Stuff::Common::tokenize<int>(secondLine, " ");

//        for (unsigned int j=0; j<items1.size(); j++)
//        {
//            std::cout << "items1[j]: " << items1[j] << std::endl;
//        }
//        for (unsigned int j=0; j<items2.size(); j++)
//        {
//            std::cout << "items2[j]: " << items2[j] << std::endl;
//        }

        // Erase zeros at the beginning of the line
        items2.erase(std::remove(items2.begin(), items2.end(), 0), items2.end());

//        std::cout << "second line without zeros:"  << std::endl;
//        for (unsigned int j=0; j<items2.size(); j++)
//        {
//            std::cout << "items2[j]: " << items2[j] << std::endl;
//        }

        if ((!items1[0]==items2[0]) || (!numberOfElements==items2[0]))
          DUNE_THROW(Dune::IOError, "Elementindices do not correspond!");

        if (items2.size() == numberOfVerticesCube + 1) //cube
        {
          numberOfCubes++;
          for (unsigned int k = 0; k < numberOfVerticesCube; k++)
          {
            cubeVertices[k] = items2[k+1] - 1;
//            std::cout << "cubeVertices[k]: " << cubeVertices[k] << std::endl;
          }
          std::swap(cubeVertices[2], cubeVertices[3]);
          std::swap(cubeVertices[6], cubeVertices[7]);
          factory.insertElement(Dune::GeometryType(Dune::GeometryType::cube,dim), cubeVertices);
        }
        else if (items2.size() == numberOfVerticesPrism + 1) //prism
        {
          numberOfPrisms++;
          for (unsigned int k = 0; k < numberOfVerticesPrism; k++)
          {
            prismVertices[k] = items2[k+1] - 1;
//            std::cout << "prismVertices[k]: " << prismVertices[k] << std::endl;
          }
//          factory.insertElement(Dune::GeometryType(Dune::GeometryType::prism,dim), prismVertices);
        }
        else //not cube or prism
        {
          DUNE_THROW(Dune::IOError, "Type of element " << numberOfElements << " is not cube or prism!");
        }
    } //while loop

    if (!numberOfElements == (numberOfCubes + numberOfPrisms))
      DUNE_THROW(Dune::IOError, "Number of Elements (" << numberOfElements << ") is not equal to number of cubes (" << numberOfCubes << ") and number of prisms (" << numberOfPrisms << ").");

    std::cout << numberOfElements << " elements read: "
              << numberOfPrisms << " prisms and "          << numberOfCubes << " cubes." << std::endl;

    // finish off the construction of the grid object
    std::cout << "Starting createGrid() ... " << std::endl;
    factory.createGrid();

//    dune_static_assert(!(Dune::is_same< GridType, Dune::YaspGrid< dim > >::value), "StarCDReader does not work with YaspGrid!");
//    dune_static_assert(!(Dune::is_same< GridType, Dune::SGrid< 2, 2 > >::value), "StarCDReader does not work with SGrid!");

//    grid_ = Dune::shared_ptr< GridType >(factory.createGrid());
  } //constructor

  StarCD(ThisType& other)
    : grid_(other.grid_)
  {}

  StarCD(const ThisType& other)
    : grid_(other.grid_)
  {}

  static ThisType createFromParamTree(const Dune::ParameterTree& paramTree, const std::string subName = id())
  {
    // get correct paramTree
    Dune::Stuff::Common::ExtendedParameterTree extendedParamTree;
    if (paramTree.hasSub(subName))
      extendedParamTree = paramTree.sub(subName);
    else
      extendedParamTree = paramTree;
    // create and return
    if (!extendedParamTree.hasKey("filename"))
      DUNE_THROW(Dune::RangeError,
                 "\nMissing key 'filename' in the following Dune::ParameterTree:\n" << extendedParamTree.reportString("  "));
    const std::string filename = extendedParamTree.get("filename", "meaningless_default_value");
    return StarCD(filename);
  }

  ThisType& operator=(ThisType& other)
  {
    if (this != &other) {
      grid_ = other.grid();
    }
    return this;
  }

  //! access to shared ptr
  virtual Dune::shared_ptr<GridType> grid()
  {
    return grid_;
  }

  //! const access to shared ptr
  virtual const Dune::shared_ptr< const GridType > grid() const
  {
    return grid_;
  }

private:
  Dune::shared_ptr< GridType > grid_;
}; // class StarCD

} // namespace Provider
} // namespace Grid
} // namespace Stuff
} // namespace Dune

//#endif // defined ALUGRID_CONFORM || defined ALUGRID_CUBE || defined ALUGRID_SIMPLEX || defined ALBERTAGRID || defined UGGRID
//#endif // HAVE_ALUGRID || HAVE_ALBERTA || HAVE_UG
#endif // HAVE_DUNE_GRID

#endif // DUNE_STUFF_GRID_PROVIDER_STARCD_HH
<|endoftext|>


<commit_before>#include <limits.h>
#include <numeric>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <algorithm>
#include <string>
#include <stdint.h>
#include <sstream>
using namespace std;
typedef uint8_t u8;
typedef vector<u8> VU8;
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<bool> VB;
typedef pair<int,int> PI;
typedef long long int lint;
typedef unsigned long long int luint;

#define FOR0(i, n) for(int i = 0; i < n; i++)

#if 1
#define C cout
#else
#include <fstream>
ofstream C("/dev/null");
#endif

#if 1
#define INS \
{ \
   static int calls; \
   calls++; \
   cout << __FUNCTION__ << ":" << calls << endl; \
}
#else
#define INS
#endif
template<class T>
void pv(const vector<T> &v){
   if(!v.size()){
      cout <<"{}\n";
      return;
   }
   cout << "{";
   FOR0(i,v.size()-1){
      cout << v[i] <<", ";
   }
   cout << v[v.size()-1] << "}\n";
}

static const int BLANK = 10;
class State
{
//   int nbsh;
   char h[15];//max
   public:
   State() /*: nbsh(0)*/
   {
      memset(h, BLANK, sizeof(h));
   }
   void set(int i, char val){
      int old = h[i];
      h[i] = val;
//      if(old==BLANK && val != BLANK) nbsh++;
//      if(old!=BLANK && val == BLANK) nbsh--;
   }
   int GetNumBish(int k) const
   {
      int nbsh = 0;
      if(!k) return 0;
      assert(k > 0);
      FOR0(i,k){
         nbsh += (h[i] != BLANK);
      }
      return nbsh;
   }
   bool find(int k, int v) const
   {
      if(!k) return false;
      FOR0(i, k){
         if(h[i] == v) return true;
      }
      return false;
   }
   void print(int k){
      if(!k) return;
      FOR0(i, k){
         C << (int)h[i] << ' ';
      }
      C << endl;
   }
};

class Solver
{
   int nb,n;
   int nsol;

   bool IsSolution(const State &st, int k){
      return st.GetNumBish(k) == nb;
   }

   void findNextMoves(const State &st, int k, char *nxt, int &nnxt)
   {
      nnxt = 0;
      if(st.GetNumBish(k) + 2*n-k-1 > nb){
         nxt[nnxt++] = BLANK;
      }

      int kk = min(k, 2*n-2-k);
      int mx = (kk&1)? (1+kk/2) : (kk/2);
      for(int i = -mx; i <=mx; i++){
         if(i == 0 && (kk&1)) continue; //odd excludes 0
         if(!st.find(k, i)){
            nxt[nnxt++] = i;
         }
      }
   }

   void backtrace(State &st, int k)
   {
      if(IsSolution(st,k)){
//         C << "Sol ";
//         st.print(k);
//         nsol++;
         return;
      }
      char nxt[9];
      int nnxt;
      findNextMoves(st, k, nxt, nnxt);
 //     C << "k=" << k << " nnxt=" << nnxt << endl;
      FOR0(i,nnxt){
         st.set(k, nxt[i]);
         if(IsSolution(st,k+1)){
            C << "Sol ";
            st.print(k+1);
            nsol++;
         }else{
            backtrace(st, k+1);
         }
      }
   }
   public:
   int solve(int n, int nb)
   {
      this->nb = nb;
      this->n = n;
      nsol=0;
      if(nb > 2*n -1){
         return 0;
      }
      State st;
      backtrace(st, 0);
      return nsol;
   }
};

int main(int argc, char **argv)
{
   int n,k;
   while(cin >> n >> k, n){
      Solver slv;
      cout << slv.solve(n,k) << endl;
   }
   return 0;
}
<commit_msg>time exceeded<commit_after>#include <limits.h>
#include <numeric>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define NDEBUG 1
#include <assert.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <algorithm>
#include <string>
#include <stdint.h>
#include <sstream>
using namespace std;
typedef uint8_t u8;
typedef vector<u8> VU8;
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<bool> VB;
typedef pair<int,int> PI;
typedef long long int lint;
typedef unsigned long long int luint;

#define FOR0(i, n) for(int i = 0; i < n; i++)

#if 0
#define C cout
#else
#include <fstream>
ofstream C("/dev/null");
#endif

#if 1
#define INS \
{ \
   static int calls; \
   calls++; \
   cout << __FUNCTION__ << ":" << calls << endl; \
}
#else
#define INS
#endif
template<class T>
void pv(const vector<T> &v){
   if(!v.size()){
      cout <<"{}\n";
      return;
   }
   cout << "{";
   FOR0(i,v.size()-1){
      cout << v[i] <<", ";
   }
   cout << v[v.size()-1] << "}\n";
}

static const int BLANK = 10;
class State
{
//   int nbsh;
   char h[15];//max
   public:
   State() /*: nbsh(0)*/
   {
      memset(h, BLANK, sizeof(h));
   }
   void set(int i, char val){
      int old = h[i];
      h[i] = val;
//      if(old==BLANK && val != BLANK) nbsh++;
//      if(old!=BLANK && val == BLANK) nbsh--;
   }
   int GetNumBish(int k) const
   {
      int nbsh = 0;
      FOR0(i,k){
         nbsh += (h[i] != BLANK);
      }
      return nbsh;
   }
   bool find(int k, int v) const
   {
      FOR0(i, k){
         if(h[i] == v) return true;
      }
      return false;
   }
   void print(int k){
      FOR0(i, k){
         C << (int)h[i] << ' ';
      }
      C << endl;
   }
};

class Solver
{
   int nb,n;
   int nsol;

   bool IsSolution(const State &st, int k){
      return st.GetNumBish(k) == nb;
   }

   void findNextMoves(const State &st, int k, char *nxt, int &nnxt)
   {
      nnxt = 0;
      if(st.GetNumBish(k) + 2*n-k-1 > nb){
         nxt[nnxt++] = BLANK;
      }

      int kk = min(k, 2*n-2-k);
      for(int i = -kk; i <=kk; i+=2){
         if(!st.find(k, i)){
            nxt[nnxt++] = i;
         }
      }
   }

   void backtrace(State &st, int k)
   {
      char nxt[9];
      int nnxt;
      findNextMoves(st, k, nxt, nnxt);
//      C << "k=" << k << " nnxt=" << nnxt << endl;
      FOR0(i,nnxt){
         st.set(k, nxt[i]);
         if(IsSolution(st,k+1)){
//            C << "Sol ";
//            st.print(k+1);
            nsol++;
         }else{
            backtrace(st, k+1);
         }
      }
   }
   public:
   int solve(int n, int nb)
   {
      this->nb = nb;
      this->n = n;
      nsol=0;
      if(nb > 2*n -1){
         return 0;
      }
      if(nb == 0) return 1;
      State st;
      backtrace(st, 0);
      return nsol;
   }
};

int main(int argc, char **argv)
{
   int n,k;
   while(cin >> n >> k, n){
      Solver slv;
      cout << slv.solve(n,k) << endl;
   }
   return 0;
}
<|endoftext|>