<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/util/settings/linksettings.h>
#include <inviwo/core/util/settings/systemsettings.h>
#include <inviwo/qt/editor/networkeditorview.h>
#include <inviwo/core/network/processornetwork.h>
#include <inviwo/qt/editor/inviwomainwindow.h>
#include <inviwo/qt/editor/inviwoeditmenu.h>
#include <modules/qtwidgets/inviwoqtutils.h>

#include <warn/push>
#include <warn/ignore/all>
#include <QMatrix>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QScrollBar>
#include <QApplication>
#include <QClipboard>
#include <qmath.h>
#include <warn/pop>

namespace inviwo {

NetworkEditorView::NetworkEditorView(NetworkEditor* networkEditor, InviwoMainWindow* parent)
    : QGraphicsView(parent)
    , NetworkEditorObserver()
    , mainwindow_(parent)
    , networkEditor_(networkEditor) {

    NetworkEditorObserver::addObservation(networkEditor_);
    QGraphicsView::setScene(networkEditor_);

    setRenderHint(QPainter::Antialiasing, true);
    setMouseTracking(true);
    setDragMode(QGraphicsView::RubberBandDrag);
    setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
    setCacheMode(QGraphicsView::CacheBackground);

    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);

    loadHandle_ = mainwindow_->getInviwoApplication()->getWorkspaceManager()->onLoad(
        [this](Deserializer&) { fitNetwork(); });

    auto editmenu = mainwindow_->getInviwoEditMenu();

    editActionsHandle_ = editmenu->registerItem(std::make_shared<MenuItem>(
        this,
        [this](MenuItemType t) -> bool {
            switch (t) {
                case MenuItemType::cut:
                    return networkEditor_->selectedItems().size() > 0;
                case MenuItemType::copy:
                    return networkEditor_->selectedItems().size() > 0;
                case MenuItemType::paste: {
                    auto clipboard = QApplication::clipboard();
                    auto mimeData = clipboard->mimeData();
                    if (mimeData->formats().contains(
                            QString("application/x.vnd.inviwo.network+xml"))) {
                        return true;
                    } else if (mimeData->formats().contains(QString("text/plain"))) {
                        return true;
                    } else {
                        return false;
                    }
                }
                case MenuItemType::del:
                    return networkEditor_->selectedItems().size() > 0;
                case MenuItemType::select:
                    return true;
                default:
                    return false;
            }

        },
        [this](MenuItemType t) -> void {
            switch (t) {
                case MenuItemType::cut: {
                    auto data = networkEditor_->cut();
                    auto mimedata = util::make_unique<QMimeData>();
                    mimedata->setData(utilqt::toQString(NetworkEditor::getMimeTag()), data);
                    mimedata->setData(QString("text/plain"), data);
                    QApplication::clipboard()->setMimeData(mimedata.release());
                    break;
                }
                case MenuItemType::copy: {
                    auto data = networkEditor_->copy();
                    auto mimedata = util::make_unique<QMimeData>();
                    mimedata->setData(utilqt::toQString(NetworkEditor::getMimeTag()), data);
                    mimedata->setData(QString("text/plain"), data);
                    QApplication::clipboard()->setMimeData(mimedata.release());
                    break;
                }
                case MenuItemType::paste: {
                    auto clipboard = QApplication::clipboard();
                    auto mimeData = clipboard->mimeData();
                    if (mimeData->formats().contains(
                            utilqt::toQString(NetworkEditor::getMimeTag()))) {
                        networkEditor_->paste(
                            mimeData->data(utilqt::toQString(NetworkEditor::getMimeTag())));
                    } else if (mimeData->formats().contains(QString("text/plain"))) {
                        networkEditor_->paste(mimeData->data(QString("text/plain")));
                    }
                    break;
                }
                case MenuItemType::del:
                    networkEditor_->deleteSelection();
                    break;
                case MenuItemType::select:
                    networkEditor_->selectAll();
                    break;
                default:
                    break;
            }

        }));
}

NetworkEditorView::~NetworkEditorView() { QGraphicsView::setScene(nullptr); }

void NetworkEditorView::hideNetwork(bool hide) {
    if (hide) {
        if (scene()) {
            scrollPos_.x = horizontalScrollBar()->value();
            scrollPos_.y = verticalScrollBar()->value();
            QGraphicsView::setScene(nullptr);
        }
    } else {
        if (scene() != networkEditor_) {
            QGraphicsView::setScene(networkEditor_);
            horizontalScrollBar()->setValue(scrollPos_.x);
            verticalScrollBar()->setValue(scrollPos_.y);
        }
    }
}

void NetworkEditorView::mouseDoubleClickEvent(QMouseEvent* e) {
    QGraphicsView::mouseDoubleClickEvent(e);

    if (!e->isAccepted()) {
        fitNetwork();
        e->accept();
    }
}

void NetworkEditorView::resizeEvent(QResizeEvent* e) { QGraphicsView::resizeEvent(e); }

void NetworkEditorView::fitNetwork() {
    const ProcessorNetwork* network = InviwoApplication::getPtr()->getProcessorNetwork();
    if (network) {
        if (network->getProcessors().size() > 0) {
            QRectF br = networkEditor_->itemsBoundingRect().adjusted(-50, -50, 50, 50);
            QSizeF viewsize = size();
            QSizeF brsize = br.size();

            if (brsize.width() < viewsize.width()) {
                br.setLeft(br.left() - 0.5 * (viewsize.width() - brsize.width()));
                br.setRight(br.right() + 0.5 * (viewsize.width() - brsize.width()));
            }
            if (brsize.height() < viewsize.height()) {
                br.setTop(br.top() - 0.5 * (viewsize.height() - brsize.height()));
                br.setBottom(br.bottom() + 0.5 * (viewsize.height() - brsize.height()));
            }

            setSceneRect(br);
            fitInView(br, Qt::KeepAspectRatio);
        }
    }
}

void NetworkEditorView::focusOutEvent(QFocusEvent* e) {
    setDragMode(QGraphicsView::RubberBandDrag);
    QGraphicsView::focusOutEvent(e);
}

void NetworkEditorView::wheelEvent(QWheelEvent* e) {
    QPointF numPixels = e->pixelDelta() / 5.0;
    QPointF numDegrees = e->angleDelta() / 8.0 / 15;

    if (e->modifiers() == Qt::ControlModifier) {
        if (!numPixels.isNull()) {
            zoom(qPow(1.025, std::max(-15.0, std::min(15.0, numPixels.y()))));
        } else if (!numDegrees.isNull()) {
            zoom(qPow(1.025, std::max(-15.0, std::min(15.0, numDegrees.y()))));
        }
    } else if (e->modifiers() & Qt::ShiftModifier) {
        // horizontal scrolling
        auto modifiers = e->modifiers();
        // remove the shift key temporarily from the event
        e->setModifiers(e->modifiers() ^ Qt::ShiftModifier);
        horizontalScrollBar()->event(e);
        // restore previous modifiers
        e->setModifiers(modifiers);
    } else {
        QGraphicsView::wheelEvent(e);
    }
    e->accept();
}

void NetworkEditorView::keyPressEvent(QKeyEvent* keyEvent) {
    if (keyEvent->modifiers() & Qt::ControlModifier) {
        setDragMode(QGraphicsView::ScrollHandDrag);
    }
    QGraphicsView::keyPressEvent(keyEvent);
}

void NetworkEditorView::keyReleaseEvent(QKeyEvent* keyEvent) {
    setDragMode(QGraphicsView::RubberBandDrag);
    QGraphicsView::keyReleaseEvent(keyEvent);
}

void NetworkEditorView::zoom(double dz) {
    if ((dz > 1.0 && matrix().m11() > 8.0) || (dz < 1.0 && matrix().m11() < 0.125)) return;
    scale(dz, dz);
}

void NetworkEditorView::onNetworkEditorFileChanged(const std::string& /*newFilename*/) {
    fitNetwork();
}

}  // namespace inviwo
<commit_msg>Qt: review fix<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/util/settings/linksettings.h>
#include <inviwo/core/util/settings/systemsettings.h>
#include <inviwo/qt/editor/networkeditorview.h>
#include <inviwo/core/network/processornetwork.h>
#include <inviwo/qt/editor/inviwomainwindow.h>
#include <inviwo/qt/editor/inviwoeditmenu.h>
#include <modules/qtwidgets/inviwoqtutils.h>

#include <warn/push>
#include <warn/ignore/all>
#include <QMatrix>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QScrollBar>
#include <QApplication>
#include <QClipboard>
#include <qmath.h>
#include <warn/pop>

namespace inviwo {

NetworkEditorView::NetworkEditorView(NetworkEditor* networkEditor, InviwoMainWindow* parent)
    : QGraphicsView(parent)
    , NetworkEditorObserver()
    , mainwindow_(parent)
    , networkEditor_(networkEditor) {

    NetworkEditorObserver::addObservation(networkEditor_);
    QGraphicsView::setScene(networkEditor_);

    setRenderHint(QPainter::Antialiasing, true);
    setMouseTracking(true);
    setDragMode(QGraphicsView::RubberBandDrag);
    setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
    setCacheMode(QGraphicsView::CacheBackground);

    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);

    loadHandle_ = mainwindow_->getInviwoApplication()->getWorkspaceManager()->onLoad(
        [this](Deserializer&) { fitNetwork(); });

    auto editmenu = mainwindow_->getInviwoEditMenu();

    editActionsHandle_ = editmenu->registerItem(std::make_shared<MenuItem>(
        this,
        [this](MenuItemType t) -> bool {
            switch (t) {
                case MenuItemType::cut:
                    return networkEditor_->selectedItems().size() > 0;
                case MenuItemType::copy:
                    return networkEditor_->selectedItems().size() > 0;
                case MenuItemType::paste: {
                    auto clipboard = QApplication::clipboard();
                    auto mimeData = clipboard->mimeData();
                    if (mimeData->formats().contains(
                            utilqt::toQString(NetworkEditor::getMimeTag()))) {
                        return true;
                    } else if (mimeData->formats().contains(QString("text/plain"))) {
                        return true;
                    } else {
                        return false;
                    }
                }
                case MenuItemType::del:
                    return networkEditor_->selectedItems().size() > 0;
                case MenuItemType::select:
                    return true;
                default:
                    return false;
            }

        },
        [this](MenuItemType t) -> void {
            switch (t) {
                case MenuItemType::cut: {
                    auto data = networkEditor_->cut();
                    auto mimedata = util::make_unique<QMimeData>();
                    mimedata->setData(utilqt::toQString(NetworkEditor::getMimeTag()), data);
                    mimedata->setData(QString("text/plain"), data);
                    QApplication::clipboard()->setMimeData(mimedata.release());
                    break;
                }
                case MenuItemType::copy: {
                    auto data = networkEditor_->copy();
                    auto mimedata = util::make_unique<QMimeData>();
                    mimedata->setData(utilqt::toQString(NetworkEditor::getMimeTag()), data);
                    mimedata->setData(QString("text/plain"), data);
                    QApplication::clipboard()->setMimeData(mimedata.release());
                    break;
                }
                case MenuItemType::paste: {
                    auto clipboard = QApplication::clipboard();
                    auto mimeData = clipboard->mimeData();
                    if (mimeData->formats().contains(
                            utilqt::toQString(NetworkEditor::getMimeTag()))) {
                        networkEditor_->paste(
                            mimeData->data(utilqt::toQString(NetworkEditor::getMimeTag())));
                    } else if (mimeData->formats().contains(QString("text/plain"))) {
                        networkEditor_->paste(mimeData->data(QString("text/plain")));
                    }
                    break;
                }
                case MenuItemType::del:
                    networkEditor_->deleteSelection();
                    break;
                case MenuItemType::select:
                    networkEditor_->selectAll();
                    break;
                default:
                    break;
            }

        }));
}

NetworkEditorView::~NetworkEditorView() { QGraphicsView::setScene(nullptr); }

void NetworkEditorView::hideNetwork(bool hide) {
    if (hide) {
        if (scene()) {
            scrollPos_.x = horizontalScrollBar()->value();
            scrollPos_.y = verticalScrollBar()->value();
            QGraphicsView::setScene(nullptr);
        }
    } else {
        if (scene() != networkEditor_) {
            QGraphicsView::setScene(networkEditor_);
            horizontalScrollBar()->setValue(scrollPos_.x);
            verticalScrollBar()->setValue(scrollPos_.y);
        }
    }
}

void NetworkEditorView::mouseDoubleClickEvent(QMouseEvent* e) {
    QGraphicsView::mouseDoubleClickEvent(e);

    if (!e->isAccepted()) {
        fitNetwork();
        e->accept();
    }
}

void NetworkEditorView::resizeEvent(QResizeEvent* e) { QGraphicsView::resizeEvent(e); }

void NetworkEditorView::fitNetwork() {
    const ProcessorNetwork* network = InviwoApplication::getPtr()->getProcessorNetwork();
    if (network) {
        if (network->getProcessors().size() > 0) {
            QRectF br = networkEditor_->itemsBoundingRect().adjusted(-50, -50, 50, 50);
            QSizeF viewsize = size();
            QSizeF brsize = br.size();

            if (brsize.width() < viewsize.width()) {
                br.setLeft(br.left() - 0.5 * (viewsize.width() - brsize.width()));
                br.setRight(br.right() + 0.5 * (viewsize.width() - brsize.width()));
            }
            if (brsize.height() < viewsize.height()) {
                br.setTop(br.top() - 0.5 * (viewsize.height() - brsize.height()));
                br.setBottom(br.bottom() + 0.5 * (viewsize.height() - brsize.height()));
            }

            setSceneRect(br);
            fitInView(br, Qt::KeepAspectRatio);
        }
    }
}

void NetworkEditorView::focusOutEvent(QFocusEvent* e) {
    setDragMode(QGraphicsView::RubberBandDrag);
    QGraphicsView::focusOutEvent(e);
}

void NetworkEditorView::wheelEvent(QWheelEvent* e) {
    QPointF numPixels = e->pixelDelta() / 5.0;
    QPointF numDegrees = e->angleDelta() / 8.0 / 15;

    if (e->modifiers() == Qt::ControlModifier) {
        if (!numPixels.isNull()) {
            zoom(qPow(1.025, std::max(-15.0, std::min(15.0, numPixels.y()))));
        } else if (!numDegrees.isNull()) {
            zoom(qPow(1.025, std::max(-15.0, std::min(15.0, numDegrees.y()))));
        }
    } else if (e->modifiers() & Qt::ShiftModifier) {
        // horizontal scrolling
        auto modifiers = e->modifiers();
        // remove the shift key temporarily from the event
        e->setModifiers(e->modifiers() ^ Qt::ShiftModifier);
        horizontalScrollBar()->event(e);
        // restore previous modifiers
        e->setModifiers(modifiers);
    } else {
        QGraphicsView::wheelEvent(e);
    }
    e->accept();
}

void NetworkEditorView::keyPressEvent(QKeyEvent* keyEvent) {
    if (keyEvent->modifiers() & Qt::ControlModifier) {
        setDragMode(QGraphicsView::ScrollHandDrag);
    }
    QGraphicsView::keyPressEvent(keyEvent);
}

void NetworkEditorView::keyReleaseEvent(QKeyEvent* keyEvent) {
    setDragMode(QGraphicsView::RubberBandDrag);
    QGraphicsView::keyReleaseEvent(keyEvent);
}

void NetworkEditorView::zoom(double dz) {
    if ((dz > 1.0 && matrix().m11() > 8.0) || (dz < 1.0 && matrix().m11() < 0.125)) return;
    scale(dz, dz);
}

void NetworkEditorView::onNetworkEditorFileChanged(const std::string& /*newFilename*/) {
    fitNetwork();
}

}  // namespace inviwo
<|endoftext|>


<commit_before>// Copyright (C) 2006  Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//

#ifndef SGTriangle_H
#define SGTrianlge_H

template<typename T>
class SGTriangle {
public:
  SGTriangle()
  { }
  SGTriangle(const SGVec3<T>& v0, const SGVec3<T>& v1, const SGVec3<T>& v2)
  { set(v0, v1, v2); }
  SGTriangle(const SGVec3<T> v[3])
  { set(v); }

  void set(const SGVec3<T>& v0, const SGVec3<T>& v1, const SGVec3<T>& v2)
  {
    _v0 = v0;
    _d[0] = v1 - v0;
    _d[1] = v2 - v0;
  }
  void set(const SGVec3<T> v[3])
  {
    _v0 = v[0];
    _d[0] = v[1] - v[0];
    _d[1] = v[2] - v[0];
  }

  SGVec3d getCenter() const
  {
    SGBoxd box;
    box.expandBy(_v0);
    box.expandBy(_v0 + _d[0]);
    box.expandBy(_v0 + _d[1]);
    return box.getCenter();
  }

  // note that the index is unchecked
  SGVec3<T> getVertex(unsigned i) const
  {
    if (0 < i)
      return _v0 + _d[i-1];
    return _v0;
  }
  /// return the normalized surface normal
  SGVec3<T> getNormal() const
  { return normalize(cross(_d[0], _d[1])); }

  const SGVec3<T>& getBaseVertex() const
  { return _v0; }
  void setBaseVertex(const SGVec3<T>& v)
  { _v0 = v; }
  const SGVec3<T>& getEdge(unsigned i) const
  { return _d[i]; }
  void setEdge(unsigned i, const SGVec3<T>& d)
  { _d[i] = d; }

  // flip the positive side
  void flip()
  {
    SGVec3<T> tmp = _d[0];
    _d[0] = _d[1];
    _d[1] = tmp;
  }
private:
  /// Store one vertex directly, _d is the offset of the other two
  /// vertices wrt the base vertex
  /// For fast intersection tests this format prooves usefull. For that same
  /// purpose also cache the cross product of the _d[i].
  SGVec3<T> _v0;
  SGVec3<T> _d[2];
};

/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s,
           const SGTriangle<T>& triangle)
{
  return s << "triangle: v0 = " << triangle.getVertex(0)
           << ", v1 = " << triangle.getVertex(1)
           << ", v2 = " << triangle.getVertex(2);
}

#endif
<commit_msg>Use template arguments instead of hard coded double.<commit_after>// Copyright (C) 2006  Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//

#ifndef SGTriangle_H
#define SGTrianlge_H

template<typename T>
class SGTriangle {
public:
  SGTriangle()
  { }
  SGTriangle(const SGVec3<T>& v0, const SGVec3<T>& v1, const SGVec3<T>& v2)
  { set(v0, v1, v2); }
  SGTriangle(const SGVec3<T> v[3])
  { set(v); }

  void set(const SGVec3<T>& v0, const SGVec3<T>& v1, const SGVec3<T>& v2)
  {
    _v0 = v0;
    _d[0] = v1 - v0;
    _d[1] = v2 - v0;
  }
  void set(const SGVec3<T> v[3])
  {
    _v0 = v[0];
    _d[0] = v[1] - v[0];
    _d[1] = v[2] - v[0];
  }

  SGVec3<T> getCenter() const
  {
    SGBox<T> box;
    box.expandBy(_v0);
    box.expandBy(_v0 + _d[0]);
    box.expandBy(_v0 + _d[1]);
    return box.getCenter();
  }

  // note that the index is unchecked
  SGVec3<T> getVertex(unsigned i) const
  {
    if (0 < i)
      return _v0 + _d[i-1];
    return _v0;
  }
  /// return the normalized surface normal
  SGVec3<T> getNormal() const
  { return normalize(cross(_d[0], _d[1])); }

  const SGVec3<T>& getBaseVertex() const
  { return _v0; }
  void setBaseVertex(const SGVec3<T>& v)
  { _v0 = v; }
  const SGVec3<T>& getEdge(unsigned i) const
  { return _d[i]; }
  void setEdge(unsigned i, const SGVec3<T>& d)
  { _d[i] = d; }

  // flip the positive side
  void flip()
  {
    SGVec3<T> tmp = _d[0];
    _d[0] = _d[1];
    _d[1] = tmp;
  }
private:
  /// Store one vertex directly, _d is the offset of the other two
  /// vertices wrt the base vertex
  /// For fast intersection tests this format prooves usefull. For that same
  /// purpose also cache the cross product of the _d[i].
  SGVec3<T> _v0;
  SGVec3<T> _d[2];
};

/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s,
           const SGTriangle<T>& triangle)
{
  return s << "triangle: v0 = " << triangle.getVertex(0)
           << ", v1 = " << triangle.getVertex(1)
           << ", v2 = " << triangle.getVertex(2);
}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium 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 "webkit/plugins/sad_plugin.h"

#include <algorithm>

#include "base/memory/scoped_ptr.h"
#include "skia/ext/platform_canvas.h"
#include "ui/gfx/blit.h"
#include "ui/gfx/rect.h"

namespace webkit {

void PaintSadPlugin(WebKit::WebCanvas* webcanvas,
                    const gfx::Rect& plugin_rect,
                    const SkBitmap& sad_plugin_bitmap) {
  const int width = plugin_rect.width();
  const int height = plugin_rect.height();

#if WEBKIT_USING_SKIA
  SkCanvas* canvas = webcanvas;
#elif WEBKIT_USING_CG
  // Make a temporary canvas for the background image.
  scoped_ptr<SkCanvas> canvas(skia::CreateBitmapCanvas(width, height, false));
  // Flip the canvas, since the context expects flipped data.
  canvas->translate(0, height);
  canvas->scale(1, -1);
#endif

  SkPaint paint;
  paint.setStyle(SkPaint::kFill_Style);
  paint.setColor(SK_ColorBLACK);
  canvas->drawRectCoords(0, 0, SkIntToScalar(width), SkIntToScalar(height),
                         paint);
  canvas->drawBitmap(
      sad_plugin_bitmap,
      SkIntToScalar(std::max(0, (width - sad_plugin_bitmap.width()) / 2)),
      SkIntToScalar(std::max(0, (height - sad_plugin_bitmap.height()) / 2)));

  // It's slightly less code to make a big SkBitmap of the sad tab image and
  // then copy that to the screen than to use the native APIs. The small speed
  // penalty is not important when drawing crashed plugins.
#if WEBKIT_USING_CG
  BlitCanvasToContext(webcanvas, plugin_rect, canvas.get(), gfx::Point(0, 0));
#endif
}

}  // namespace webkit
<commit_msg>Fixed rendering of sad plugin view by adding approriate translation transform. BUG=89895 Review URL: http://codereview.chromium.org/7473034<commit_after>// Copyright (c) 2011 The Chromium 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 "webkit/plugins/sad_plugin.h"

#include <algorithm>

#include "base/memory/scoped_ptr.h"
#include "skia/ext/platform_canvas.h"
#include "ui/gfx/blit.h"
#include "ui/gfx/rect.h"

namespace webkit {

void PaintSadPlugin(WebKit::WebCanvas* webcanvas,
                    const gfx::Rect& plugin_rect,
                    const SkBitmap& sad_plugin_bitmap) {
  const int width = plugin_rect.width();
  const int height = plugin_rect.height();

#if WEBKIT_USING_SKIA
  SkCanvas* canvas = webcanvas;
  SkAutoCanvasRestore auto_restore(canvas, true);
  // We draw the sad-plugin bitmap at the origin of canvas.
  // Add a translation so that it appears at the origin of plugin rect.
  canvas->translate(plugin_rect.x(), plugin_rect.y());
#elif WEBKIT_USING_CG
  // Make a temporary canvas for the background image.
  scoped_ptr<SkCanvas> canvas(skia::CreateBitmapCanvas(width, height, false));
  // Flip the canvas, since the context expects flipped data.
  canvas->translate(0, height);
  canvas->scale(1, -1);
#endif

  SkPaint paint;
  paint.setStyle(SkPaint::kFill_Style);
  paint.setColor(SK_ColorBLACK);
  canvas->drawRectCoords(0, 0, SkIntToScalar(width), SkIntToScalar(height),
                         paint);
  canvas->drawBitmap(
      sad_plugin_bitmap,
      SkIntToScalar(std::max(0, (width - sad_plugin_bitmap.width()) / 2)),
      SkIntToScalar(std::max(0, (height - sad_plugin_bitmap.height()) / 2)));

  // It's slightly less code to make a big SkBitmap of the sad tab image and
  // then copy that to the screen than to use the native APIs. The small speed
  // penalty is not important when drawing crashed plugins.
#if WEBKIT_USING_CG
  BlitCanvasToContext(webcanvas, plugin_rect, canvas.get(), gfx::Point(0, 0));
#endif
}

}  // namespace webkit
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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

#include "libmesh/quadrature_conical.h"
#include "libmesh/quadrature_gauss.h"
#include "libmesh/quadrature_jacobi.h"

namespace libMesh
{

// See also the files:
// quadrature_conical_2D.C
// quadrature_conical_3D.C
// for additional implementation.

// Constructor
QConical::QConical(const unsigned int d,
		   const Order o) : QBase(d,o)
{
}

// Destructor
QConical::~QConical()
{
}

// Builds and scales a Gauss rule and a Jacobi rule.
// Then combines them to compute points and weights
// of a 2D conical product rule.
void QConical::conical_product_tri(unsigned int p)
{
  // Be sure the underlying rule object was built with the same dimension as the
  // rule we are about to construct.
  libmesh_assert_equal_to (this->get_dim(), 2);

  QGauss  gauss1D(1,static_cast<Order>(_order+2*p));
  QJacobi jac1D(1,static_cast<Order>(_order+2*p),1,0);

  // The Gauss rule needs to be scaled to [0,1]
  std::pair<Real, Real> old_range(-1.0L, 1.0L);
  std::pair<Real, Real> new_range( 0.0L, 1.0L);
  gauss1D.scale(old_range,
		new_range);

  // Now construct the points and weights for the conical product rule.

  // Both rules should have the same number of points.
  libmesh_assert_equal_to (gauss1D.n_points(), jac1D.n_points());

  // Save the number of points as a convenient variable
  const unsigned int n_points = gauss1D.n_points();

  // Both rules should be between x=0 and x=1
  libmesh_assert_greater_equal (gauss1D.qp(0)(0), 0.0);
  libmesh_assert_less_equal (gauss1D.qp(n_points-1)(0), 1.0);
  libmesh_assert_greater_equal (jac1D.qp(0)(0), 0.0);
  libmesh_assert_less_equal (jac1D.qp(n_points-1)(0), 1.0);

  // Resize the points and weights vectors
  _points.resize(n_points * n_points);
  _weights.resize(n_points * n_points);

  // Compute the conical product
  unsigned int gp = 0;
  for (unsigned int i=0; i<n_points; i++)
    for (unsigned int j=0; j<n_points; j++)
      {
	_points[gp](0) = jac1D.qp(j)(0);                          //s[j];
	_points[gp](1) = gauss1D.qp(i)(0) * (1.-jac1D.qp(j)(0)); //r[i]*(1.-s[j]);
	_weights[gp]   = gauss1D.w(i) * jac1D.w(j);              //A[i]*B[j];
	gp++;
      }
}

// Builds and scales a Gauss rule and a Jacobi rule.
// Then combines them to compute points and weights
// of a 3D conical product rule for the Tet.
void QConical::conical_product_tet(unsigned int p)
{
  // Be sure the underlying rule object was built with the same dimension as the
  // rule we are about to construct.
  libmesh_assert_equal_to (this->get_dim(), 3);

  QGauss  gauss1D(1,static_cast<Order>(_order+2*p));
  QJacobi jacA1D(1,static_cast<Order>(_order+2*p),1,0);
  QJacobi jacB1D(1,static_cast<Order>(_order+2*p),2,0);

  // The Gauss rule needs to be scaled to [0,1]
  std::pair<Real, Real> old_range(-1.0L, 1.0L);
  std::pair<Real, Real> new_range( 0.0L, 1.0L);
  gauss1D.scale(old_range,
		new_range);

  // Now construct the points and weights for the conical product rule.

  // All rules should have the same number of points
  libmesh_assert_equal_to (gauss1D.n_points(), jacA1D.n_points());
  libmesh_assert_equal_to (jacA1D.n_points(), jacB1D.n_points());

  // Save the number of points as a convenient variable
  const unsigned int n_points = gauss1D.n_points();

  // All rules should be between x=0 and x=1
  libmesh_assert_greater_equal (gauss1D.qp(0)(0), 0.0);
  libmesh_assert_less_equal (gauss1D.qp(n_points-1)(0), 1.0);
  libmesh_assert_greater_equal (jacA1D.qp(0)(0), 0.0);
  libmesh_assert_less_equal (jacA1D.qp(n_points-1)(0), 1.0);
  libmesh_assert_greater_equal (jacB1D.qp(0)(0), 0.0);
  libmesh_assert_less_equal (jacB1D.qp(n_points-1)(0), 1.0);

  // Resize the points and weights vectors
  _points.resize(n_points * n_points * n_points);
  _weights.resize(n_points * n_points * n_points);

  // Compute the conical product
  unsigned int gp = 0;
  for (unsigned int i=0; i<n_points; i++)
    for (unsigned int j=0; j<n_points; j++)
      for (unsigned int k=0; k<n_points; k++)
      {
	_points[gp](0) = jacB1D.qp(k)(0);                                                  //t[k];
	_points[gp](1) = jacA1D.qp(j)(0)  * (1.-jacB1D.qp(k)(0));                         //s[j]*(1.-t[k]);
	_points[gp](2) = gauss1D.qp(i)(0) * (1.-jacA1D.qp(j)(0)) * (1.-jacB1D.qp(k)(0)); //r[i]*(1.-s[j])*(1.-t[k]);
	_weights[gp]   = gauss1D.w(i)     * jacA1D.w(j)          * jacB1D.w(k);          //A[i]*B[j]*C[k];
	gp++;
      }
}

// Builds and scales a Gauss rule and a Jacobi rule.
// Then combines them to compute points and weights
// of a 3D conical product rule for the Pyramid.  The integral
// over the reference Tet can be written (in LaTeX notation) as:
//
// If := \int_0^1 dz \int_{-(1-z)}^{(1-z)} dy \int_{-(1-z)}^{(1-z)} f(x,y,z) dx (1)
//
// (Imagine a stack of infinitely thin squares which decrease in size as
//  you approach the apex.)  Under the transformation of variables:
//
// z=w
// y=(1-z)v
// x=(1-z)u,
//
// The Jacobian determinant of this transformation is |J|=(1-w)^2, and
// the integral itself is transformed to:
//
// If = \int_0^1 (1-w)^2 dw \int_{-1}^{1} dv \int_{-1}^{1} f((1-w)u, (1-w)v, w) du (2)
//
// The integral can now be approximated by the product of three 1D quadrature rules:
// A Jacobi rule with alpha==2, beta==0 in w, and Gauss rules in v and u.  In this way
// we can obtain 3D rules to any order for which the 1D rules exist.
void QConical::conical_product_pyramid(unsigned int p)
{
  // Be sure the underlying rule object was built with the same dimension as the
  // rule we are about to construct.
  libmesh_assert_equal_to (this->get_dim(), 3);

  QGauss  gauss1D(1,static_cast<Order>(_order+2*p));
  QJacobi jac1D(1,static_cast<Order>(_order+2*p),2,0);

  // These rules should have the same number of points
  libmesh_assert_equal_to (gauss1D.n_points(), jac1D.n_points());

  // Save the number of points as a convenient variable
  const unsigned int n_points = gauss1D.n_points();

  // Resize the points and weights vectors
  _points.resize(n_points * n_points * n_points);
  _weights.resize(n_points * n_points * n_points);

  // Compute the conical product
  unsigned int qp = 0;
  for (unsigned int i=0; i<n_points; ++i)
    for (unsigned int j=0; j<n_points; ++j)
      for (unsigned int k=0; k<n_points; ++k, ++qp)
      {
	const Real xi=gauss1D.qp(i)(0);
	const Real yj=gauss1D.qp(j)(0);
	const Real zk=jac1D.qp(k)(0);

	_points[qp](0) = (1.-zk) * xi;
	_points[qp](1) = (1.-zk) * yj;
	_points[qp](2) = zk;
	_weights[qp]   = gauss1D.w(i) * gauss1D.w(j) * jac1D.w(k);
      }

}

} // namespace libMesh
<commit_msg>Changes in quadrature_conical.C for -Wshadow.<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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

#include "libmesh/quadrature_conical.h"
#include "libmesh/quadrature_gauss.h"
#include "libmesh/quadrature_jacobi.h"

namespace libMesh
{

// See also the files:
// quadrature_conical_2D.C
// quadrature_conical_3D.C
// for additional implementation.

// Constructor
QConical::QConical(const unsigned int d,
		   const Order o) : QBase(d,o)
{
}

// Destructor
QConical::~QConical()
{
}

// Builds and scales a Gauss rule and a Jacobi rule.
// Then combines them to compute points and weights
// of a 2D conical product rule.
void QConical::conical_product_tri(unsigned int p)
{
  // Be sure the underlying rule object was built with the same dimension as the
  // rule we are about to construct.
  libmesh_assert_equal_to (this->get_dim(), 2);

  QGauss  gauss1D(1,static_cast<Order>(_order+2*p));
  QJacobi jac1D(1,static_cast<Order>(_order+2*p),1,0);

  // The Gauss rule needs to be scaled to [0,1]
  std::pair<Real, Real> old_range(-1.0L, 1.0L);
  std::pair<Real, Real> new_range( 0.0L, 1.0L);
  gauss1D.scale(old_range,
		new_range);

  // Now construct the points and weights for the conical product rule.

  // Both rules should have the same number of points.
  libmesh_assert_equal_to (gauss1D.n_points(), jac1D.n_points());

  // Save the number of points as a convenient variable
  const unsigned int np = gauss1D.n_points();

  // Both rules should be between x=0 and x=1
  libmesh_assert_greater_equal (gauss1D.qp(0)(0), 0.0);
  libmesh_assert_less_equal (gauss1D.qp(np-1)(0), 1.0);
  libmesh_assert_greater_equal (jac1D.qp(0)(0), 0.0);
  libmesh_assert_less_equal (jac1D.qp(np-1)(0), 1.0);

  // Resize the points and weights vectors
  _points.resize(np * np);
  _weights.resize(np * np);

  // Compute the conical product
  unsigned int gp = 0;
  for (unsigned int i=0; i<np; i++)
    for (unsigned int j=0; j<np; j++)
      {
	_points[gp](0) = jac1D.qp(j)(0);                          //s[j];
	_points[gp](1) = gauss1D.qp(i)(0) * (1.-jac1D.qp(j)(0)); //r[i]*(1.-s[j]);
	_weights[gp]   = gauss1D.w(i) * jac1D.w(j);              //A[i]*B[j];
	gp++;
      }
}

// Builds and scales a Gauss rule and a Jacobi rule.
// Then combines them to compute points and weights
// of a 3D conical product rule for the Tet.
void QConical::conical_product_tet(unsigned int p)
{
  // Be sure the underlying rule object was built with the same dimension as the
  // rule we are about to construct.
  libmesh_assert_equal_to (this->get_dim(), 3);

  QGauss  gauss1D(1,static_cast<Order>(_order+2*p));
  QJacobi jacA1D(1,static_cast<Order>(_order+2*p),1,0);
  QJacobi jacB1D(1,static_cast<Order>(_order+2*p),2,0);

  // The Gauss rule needs to be scaled to [0,1]
  std::pair<Real, Real> old_range(-1.0L, 1.0L);
  std::pair<Real, Real> new_range( 0.0L, 1.0L);
  gauss1D.scale(old_range,
		new_range);

  // Now construct the points and weights for the conical product rule.

  // All rules should have the same number of points
  libmesh_assert_equal_to (gauss1D.n_points(), jacA1D.n_points());
  libmesh_assert_equal_to (jacA1D.n_points(), jacB1D.n_points());

  // Save the number of points as a convenient variable
  const unsigned int np = gauss1D.n_points();

  // All rules should be between x=0 and x=1
  libmesh_assert_greater_equal (gauss1D.qp(0)(0), 0.0);
  libmesh_assert_less_equal (gauss1D.qp(np-1)(0), 1.0);
  libmesh_assert_greater_equal (jacA1D.qp(0)(0), 0.0);
  libmesh_assert_less_equal (jacA1D.qp(np-1)(0), 1.0);
  libmesh_assert_greater_equal (jacB1D.qp(0)(0), 0.0);
  libmesh_assert_less_equal (jacB1D.qp(np-1)(0), 1.0);

  // Resize the points and weights vectors
  _points.resize(np * np * np);
  _weights.resize(np * np * np);

  // Compute the conical product
  unsigned int gp = 0;
  for (unsigned int i=0; i<np; i++)
    for (unsigned int j=0; j<np; j++)
      for (unsigned int k=0; k<np; k++)
      {
	_points[gp](0) = jacB1D.qp(k)(0);                                                  //t[k];
	_points[gp](1) = jacA1D.qp(j)(0)  * (1.-jacB1D.qp(k)(0));                         //s[j]*(1.-t[k]);
	_points[gp](2) = gauss1D.qp(i)(0) * (1.-jacA1D.qp(j)(0)) * (1.-jacB1D.qp(k)(0)); //r[i]*(1.-s[j])*(1.-t[k]);
	_weights[gp]   = gauss1D.w(i)     * jacA1D.w(j)          * jacB1D.w(k);          //A[i]*B[j]*C[k];
	gp++;
      }
}

// Builds and scales a Gauss rule and a Jacobi rule.
// Then combines them to compute points and weights
// of a 3D conical product rule for the Pyramid.  The integral
// over the reference Tet can be written (in LaTeX notation) as:
//
// If := \int_0^1 dz \int_{-(1-z)}^{(1-z)} dy \int_{-(1-z)}^{(1-z)} f(x,y,z) dx (1)
//
// (Imagine a stack of infinitely thin squares which decrease in size as
//  you approach the apex.)  Under the transformation of variables:
//
// z=w
// y=(1-z)v
// x=(1-z)u,
//
// The Jacobian determinant of this transformation is |J|=(1-w)^2, and
// the integral itself is transformed to:
//
// If = \int_0^1 (1-w)^2 dw \int_{-1}^{1} dv \int_{-1}^{1} f((1-w)u, (1-w)v, w) du (2)
//
// The integral can now be approximated by the product of three 1D quadrature rules:
// A Jacobi rule with alpha==2, beta==0 in w, and Gauss rules in v and u.  In this way
// we can obtain 3D rules to any order for which the 1D rules exist.
void QConical::conical_product_pyramid(unsigned int p)
{
  // Be sure the underlying rule object was built with the same dimension as the
  // rule we are about to construct.
  libmesh_assert_equal_to (this->get_dim(), 3);

  QGauss  gauss1D(1,static_cast<Order>(_order+2*p));
  QJacobi jac1D(1,static_cast<Order>(_order+2*p),2,0);

  // These rules should have the same number of points
  libmesh_assert_equal_to (gauss1D.n_points(), jac1D.n_points());

  // Save the number of points as a convenient variable
  const unsigned int np = gauss1D.n_points();

  // Resize the points and weights vectors
  _points.resize(np * np * np);
  _weights.resize(np * np * np);

  // Compute the conical product
  unsigned int q = 0;
  for (unsigned int i=0; i<np; ++i)
    for (unsigned int j=0; j<np; ++j)
      for (unsigned int k=0; k<np; ++k, ++q)
      {
	const Real xi=gauss1D.qp(i)(0);
	const Real yj=gauss1D.qp(j)(0);
	const Real zk=jac1D.qp(k)(0);

	_points[q](0) = (1.-zk) * xi;
	_points[q](1) = (1.-zk) * yj;
	_points[q](2) = zk;
	_weights[q]   = gauss1D.w(i) * gauss1D.w(j) * jac1D.w(k);
      }

}

} // namespace libMesh
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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

// Local includes
#include "libmesh/quadrature_grid.h"

namespace libMesh
{

void QGrid::init_2D(const ElemType _type,
                    unsigned int)
{
#if LIBMESH_DIM > 1

  //-----------------------------------------------------------------------
  // 2D quadrature rules

  // We ignore p - the grid rule is just for experimentation

  switch (_type)
    {

      //---------------------------------------------
      // Quadrilateral quadrature rules
    case QUAD4:
    case QUAD8:
    case QUAD9:
      {
	// We compute the 2D quadrature rule as a tensor
	// product of the 1D quadrature rule.
	QGrid q1D(1,_order);
	q1D.init(EDGE2);
	tensor_product_quad( q1D );
	return;
      }

      //---------------------------------------------
      // Triangle quadrature rules
    case TRI3:
    case TRI6:
      {
        _points.resize((_order + 1)*(_order + 2)/2);
        _weights.resize((_order + 1)*(_order + 2)/2);

        unsigned int pt = 0;
        for (int i = 0; i != _order + 1; ++i)
          {
            for (int j = 0; j != _order + 1 - i; ++j)
              {
                _points[pt](0) = (double)i / (double)_order;
                _points[pt](1) = (double)j / (double)_order;
                _weights[pt] = 1.0 / (double)(_order+1) /
                  (double)(_order+2);
                pt++;
              }
          }
	return;
      }

      //---------------------------------------------
      // Unsupported type
    default:
      {
	libMesh::err << "Element type not supported!:" << _type << std::endl;
	libmesh_error();
      }
    }

  libmesh_error();

  return;

#endif
}

} // namespace libMesh
<commit_msg>Changes in quadrature_grid_2D.C for -Wshadow.<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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

// Local includes
#include "libmesh/quadrature_grid.h"

namespace libMesh
{

void QGrid::init_2D(const ElemType type_in,
                    unsigned int)
{
#if LIBMESH_DIM > 1

  //-----------------------------------------------------------------------
  // 2D quadrature rules

  // We ignore p - the grid rule is just for experimentation

  switch (type_in)
    {

      //---------------------------------------------
      // Quadrilateral quadrature rules
    case QUAD4:
    case QUAD8:
    case QUAD9:
      {
	// We compute the 2D quadrature rule as a tensor
	// product of the 1D quadrature rule.
	QGrid q1D(1,_order);
	q1D.init(EDGE2);
	tensor_product_quad( q1D );
	return;
      }

      //---------------------------------------------
      // Triangle quadrature rules
    case TRI3:
    case TRI6:
      {
        _points.resize((_order + 1)*(_order + 2)/2);
        _weights.resize((_order + 1)*(_order + 2)/2);

        unsigned int pt = 0;
        for (int i = 0; i != _order + 1; ++i)
          {
            for (int j = 0; j != _order + 1 - i; ++j)
              {
                _points[pt](0) = (double)i / (double)_order;
                _points[pt](1) = (double)j / (double)_order;
                _weights[pt] = 1.0 / (double)(_order+1) /
                  (double)(_order+2);
                pt++;
              }
          }
	return;
      }

      //---------------------------------------------
      // Unsupported type
    default:
      {
	libMesh::err << "Element type not supported!:" << type_in << std::endl;
	libmesh_error();
      }
    }

  libmesh_error();

  return;

#endif
}

} // namespace libMesh
<|endoftext|>


<commit_before>#include "freicoinunits.h"

#include <QStringList>

FreicoinUnits::FreicoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<FreicoinUnits::Unit> FreicoinUnits::availableUnits()
{
    QList<FreicoinUnits::Unit> unitlist;
    unitlist.append(FRC);
    unitlist.append(mFRC);
    unitlist.append(uFRC);
    return unitlist;
}

bool FreicoinUnits::valid(int unit)
{
    switch(unit)
    {
    case FRC:
    case mFRC:
    case uFRC:
        return true;
    default:
        return false;
    }
}

QString FreicoinUnits::name(int unit)
{
    switch(unit)
    {
    case FRC: return QString("FRC");
    case mFRC: return QString("mFRC");
    case uFRC: return QString::fromUtf8("μFRC");
    default: return QString("???");
    }
}

QString FreicoinUnits::description(int unit)
{
    switch(unit)
    {
    case FRC: return QString("Freicoins");
    case mFRC: return QString("Milli-Freicoins (1 / 1,000)");
    case uFRC: return QString("Micro-Freicoins (1 / 1,000,000)");
    default: return QString("???");
    }
}

mpq FreicoinUnits::factor(int unit)
{
    switch(unit)
    {
    case uFRC: return mpq("100/1");
    case mFRC: return mpq("100000/1");
    default:
    case FRC:  return mpq("100000000/1");
    }
}

int FreicoinUnits::amountDigits(int unit)
{
    switch(unit)
    {
    case FRC: return 9; // 100,000,000 (# digits, without commas)
    case mFRC: return 12; // 100,000,000,000
    case uFRC: return 15; // 100,000,000,000,000
    default: return 0;
    }
}

int FreicoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case FRC: return 8;
    case mFRC: return 5;
    case uFRC: return 2;
    default: return 0;
    }
}

QString FreicoinUnits::format(int unit, const mpq& n, bool fPlus)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    mpq q = n * COIN / factor(unit);
    return QString::fromStdString(FormatMoney(q, fPlus));
}

QString FreicoinUnits::formatWithUnit(int unit, const mpq& amount, bool plussign)
{
    return format(unit, amount, plussign) + QString(" ") + name(unit);
}

bool FreicoinUnits::parse(int unit, const QString &value, mpq *val_out)
{
    mpq ret_value;
    if (!ParseMoney(value.toStdString(), ret_value))
        return false;
    if(val_out)
    {
        *val_out = ret_value * factor(unit) / COIN;
    }
    return true;
}

int FreicoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant FreicoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}
<commit_msg>FreicoinUnits::amountDigits() now returns the correct value (previous off-by-one error due to a simple arithmetic mistake).<commit_after>#include "freicoinunits.h"

#include <QStringList>

FreicoinUnits::FreicoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<FreicoinUnits::Unit> FreicoinUnits::availableUnits()
{
    QList<FreicoinUnits::Unit> unitlist;
    unitlist.append(FRC);
    unitlist.append(mFRC);
    unitlist.append(uFRC);
    return unitlist;
}

bool FreicoinUnits::valid(int unit)
{
    switch(unit)
    {
    case FRC:
    case mFRC:
    case uFRC:
        return true;
    default:
        return false;
    }
}

QString FreicoinUnits::name(int unit)
{
    switch(unit)
    {
    case FRC: return QString("FRC");
    case mFRC: return QString("mFRC");
    case uFRC: return QString::fromUtf8("μFRC");
    default: return QString("???");
    }
}

QString FreicoinUnits::description(int unit)
{
    switch(unit)
    {
    case FRC: return QString("Freicoins");
    case mFRC: return QString("Milli-Freicoins (1 / 1,000)");
    case uFRC: return QString("Micro-Freicoins (1 / 1,000,000)");
    default: return QString("???");
    }
}

mpq FreicoinUnits::factor(int unit)
{
    switch(unit)
    {
    case uFRC: return mpq("100/1");
    case mFRC: return mpq("100000/1");
    default:
    case FRC:  return mpq("100000000/1");
    }
}

int FreicoinUnits::amountDigits(int unit)
{
    switch(unit)
    {
    case FRC: return 8; // <100,000,000 (# digits, without commas)
    case mFRC: return 11; // <100,000,000,000
    case uFRC: return 14; // <100,000,000,000,000
    default: return 0;
    }
}

int FreicoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case FRC: return 8;
    case mFRC: return 5;
    case uFRC: return 2;
    default: return 0;
    }
}

QString FreicoinUnits::format(int unit, const mpq& n, bool fPlus)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    mpq q = n * COIN / factor(unit);
    return QString::fromStdString(FormatMoney(q, fPlus));
}

QString FreicoinUnits::formatWithUnit(int unit, const mpq& amount, bool plussign)
{
    return format(unit, amount, plussign) + QString(" ") + name(unit);
}

bool FreicoinUnits::parse(int unit, const QString &value, mpq *val_out)
{
    mpq ret_value;
    if (!ParseMoney(value.toStdString(), ret_value))
        return false;
    if(val_out)
    {
        *val_out = ret_value * factor(unit) / COIN;
    }
    return true;
}

int FreicoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant FreicoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2021, OpenNebula Project, OpenNebula Systems                */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

#include "RequestManagerMarketPlace.h"
#include "Nebula.h"
#include "MarketPlaceManager.h"
#include "MarketPlacePool.h"
#include "MarketPlaceAppPool.h"

using namespace std;

/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */

MarketPlaceEnable::MarketPlaceEnable()
    : Request("one.market.enable", "A:sii", "Enable or disable MarketPlcae")
{
    Nebula& nd = Nebula::instance();
    pool       = nd.get_marketpool();

    auth_object = PoolObjectSQL::MARKETPLACE;
    auth_op     = AuthRequest::MANAGE;
};

/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */

void MarketPlaceEnable::request_execute(
    xmlrpc_c::paramList const& paramList,
	RequestAttributes& att)
{
    Nebula& nd       = Nebula::instance();
    int  id          = xmlrpc_c::value_int(paramList.getInt(1));
    bool enable_flag = xmlrpc_c::value_boolean(paramList.getBoolean(2));
    std::set<int> apps;

    if ( basic_authorization(id, att) == false )
    {
        return;
    }

    if (auto market = pool->get<MarketPlace>(id))
    {
        if (enable_flag && market->get_state() == MarketPlace::ENABLED ||
            !enable_flag && market->get_state() == MarketPlace::DISABLED)
        {
            success_response(id, att);
            return;
        }

        market->enable(enable_flag);

        if (!enable_flag)
        {
            apps = market->get_marketapp_ids();
            market->clear_marketapps();
        }

        pool->update(market.get());
    }
    else
    {
        att.resp_id = id;
        failure_response(NO_EXISTS, att);
        return;
    }

    if (enable_flag)
    {
        auto mm = nd.get_marketm();
        mm->monitor_market(id);
    }
    else
    {
        MarketPlaceAppPool * apppool = nd.get_apppool();

        string app_error;

        for (auto app_id : apps)
        {
            auto app = apppool->get(app_id);

            if ( app == nullptr )
            {
                continue;
            }

            if ( apppool->drop(app.get(), app_error) != 0 )
            {
                ostringstream oss;

                oss << "Cannot remove " << object_name(PoolObjectSQL::MARKETPLACEAPP)
                    << " " << app_id << ": " << app_error << ". ";

                NebulaLog::warn("ReM", oss.str());
            }
        }

    }

    success_response(id, att);
}
<commit_msg>M #-: Fix compilation warning (#1289)<commit_after>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2021, OpenNebula Project, OpenNebula Systems                */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

#include "RequestManagerMarketPlace.h"
#include "Nebula.h"
#include "MarketPlaceManager.h"
#include "MarketPlacePool.h"
#include "MarketPlaceAppPool.h"

using namespace std;

/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */

MarketPlaceEnable::MarketPlaceEnable()
    : Request("one.market.enable", "A:sii", "Enable or disable MarketPlcae")
{
    Nebula& nd = Nebula::instance();
    pool       = nd.get_marketpool();

    auth_object = PoolObjectSQL::MARKETPLACE;
    auth_op     = AuthRequest::MANAGE;
};

/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */

void MarketPlaceEnable::request_execute(
    xmlrpc_c::paramList const& paramList,
	RequestAttributes& att)
{
    Nebula& nd       = Nebula::instance();
    int  id          = xmlrpc_c::value_int(paramList.getInt(1));
    bool enable_flag = xmlrpc_c::value_boolean(paramList.getBoolean(2));
    std::set<int> apps;

    if ( basic_authorization(id, att) == false )
    {
        return;
    }

    if (auto market = pool->get<MarketPlace>(id))
    {
        if ((enable_flag && market->get_state() == MarketPlace::ENABLED) ||
            (!enable_flag && market->get_state() == MarketPlace::DISABLED))
        {
            success_response(id, att);
            return;
        }

        market->enable(enable_flag);

        if (!enable_flag)
        {
            apps = market->get_marketapp_ids();
            market->clear_marketapps();
        }

        pool->update(market.get());
    }
    else
    {
        att.resp_id = id;
        failure_response(NO_EXISTS, att);
        return;
    }

    if (enable_flag)
    {
        auto mm = nd.get_marketm();
        mm->monitor_market(id);
    }
    else
    {
        MarketPlaceAppPool * apppool = nd.get_apppool();

        string app_error;

        for (auto app_id : apps)
        {
            auto app = apppool->get(app_id);

            if ( app == nullptr )
            {
                continue;
            }

            if ( apppool->drop(app.get(), app_error) != 0 )
            {
                ostringstream oss;

                oss << "Cannot remove " << object_name(PoolObjectSQL::MARKETPLACEAPP)
                    << " " << app_id << ": " << app_error << ". ";

                NebulaLog::warn("ReM", oss.str());
            }
        }

    }

    success_response(id, att);
}
<|endoftext|>


<commit_before>/*****************************************************************************************
*                                                                                *
* OpenSpace                                                                             *
*                                                                                *
* Copyright (c) 2014-2019                                                               *
*                                                                                *
* 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 <modules/autonavigation/pathcurves.h>

#include <modules/autonavigation/helperfunctions.h>
#include <openspace/query/query.h>
#include <openspace/scene/scenegraphnode.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/projection.hpp>

namespace {
    constexpr const char* _loggerCat = "PathCurve";
    const double Epsilon = 1E-7;
} // namespace

namespace openspace::autonavigation {

PathCurve::~PathCurve() {}

const double PathCurve::length() const {
    return _length;
}

// Approximate the curve length using Simpson's rule
double PathCurve::arcLength(double limit) {
    const int n = 30; // resolution, must be even for Simpson's rule
    const double h = limit / (double)n;

    // Points to be multiplied by 1
    double endPoints = glm::length(positionAt(0.0 + h) - positionAt(0.0)) + glm::length(positionAt(1.0) - positionAt(1.0 - h));

    // Points to be multiplied by 4
    double times4 = 0.0;
    for (int i = 1; i < n; i += 2) {
        float t = h * i;
        times4 += glm::length(positionAt(t + h) - positionAt(t));
    }

    // Points to be multiplied by 2
    double times2 = 0.0;
    for (int i = 2; i < n; i += 2) {
        float t = h * i;
        times2 += glm::length(positionAt(t + h) - positionAt(t));
    }

    return (h / 3.0) * (endPoints + 4.0 * times4 + 2.0 *times2);
}

glm::dquat PathCurve::rotationAt(double u) {
    return _rotationInterpolator.rotationAt(u);
}

// TODO: remove when not needed
// Created for debugging
std::vector<glm::dvec3> PathCurve::getPoints() {
    return _points;
}

Bezier3Curve::Bezier3Curve(const CameraState& start, const CameraState& end) {
    // default rotation interpolation
    _rotationInterpolator = RotationInterpolator{ start, end, this, PiecewiseSlerp };

    glm::dvec3 startNodePos = sceneGraphNode(start.referenceNode)->worldPosition();
    glm::dvec3 endNodePos = sceneGraphNode(end.referenceNode)->worldPosition();
    double startNodeRadius = sceneGraphNode(start.referenceNode)->boundingSphere();
    double endNodeRadius = sceneGraphNode(end.referenceNode)->boundingSphere();

    glm::dvec3 startNodeToStartPos = start.position - startNodePos;
    glm::dvec3 endNodeToEndPos = end.position - endNodePos;

    double startTangentLength = 2.0 * startNodeRadius;
    double endTangentLength = 2.0 * endNodeRadius;
    glm::dvec3 startTangentDirection = normalize(startNodeToStartPos);
    glm::dvec3 endTangentDirection = normalize(endNodeToEndPos);

    // Start by going outwards
    _points.push_back(start.position);
    _points.push_back(start.position + startTangentLength * startTangentDirection);

    if (start.referenceNode != end.referenceNode) {

        glm::dvec3 startNodeToEndNode = endNodePos - startNodePos;
        glm::dvec3 startToEndDirection = normalize(end.position - start.position);

        // Assuming we move straigh out to point to a distance proportional to radius, angle is enough to check collision risk
        double cosStartAngle = glm::dot(startTangentDirection, startToEndDirection);
        double cosEndAngle = glm::dot(endTangentDirection, startToEndDirection);
        double cosStartDir = glm::dot(startTangentDirection, endTangentDirection);

        //TODO: investigate suitable values, could be risky close to surface..
        bool TARGET_BEHIND_STARTNODE = cosStartAngle < -0.8;
        bool TARGET_BEHIND_ENDNODE = cosEndAngle > 0.8;
        bool TARGET_IN_OPPOSITE_DIRECTION = cosStartAngle > 0.7;

        // Avoid collision with startnode by adding control points on the side of it
        if (TARGET_BEHIND_STARTNODE) {
            glm::dvec3 parallell = glm::proj(startNodeToStartPos, startNodeToEndNode);
            glm::dvec3 orthogonal = normalize(startNodeToStartPos - parallell);
            double dist = 5.0 * startNodeRadius;
            glm::dvec3 extraKnot = startNodePos + dist * orthogonal;

            _points.push_back(extraKnot + parallell);
            _points.push_back(extraKnot);
            _points.push_back(extraKnot - parallell);
        }

        // Zoom out, to get a better understanding in a 180 degree turn situation
        if (TARGET_IN_OPPOSITE_DIRECTION) {
            glm::dvec3 parallell = glm::proj(startNodeToStartPos, startNodeToEndNode);
            glm::dvec3 orthogonal = normalize(startNodeToStartPos - parallell);
            double dist = 0.5 * glm::length(startNodeToEndNode);
            // Distant middle point
            glm::dvec3 extraKnot = startNodePos + dist * normalize(parallell) + 3.0 * dist * orthogonal;

            _points.push_back(extraKnot - 0.3 * dist *  normalize(parallell));
            _points.push_back(extraKnot);
            _points.push_back(extraKnot + 0.3 * dist *  normalize(parallell));
        }

        // Avoid collision with endnode by adding control points on the side of it
        if (TARGET_BEHIND_ENDNODE) {
            glm::dvec3 parallell = glm::proj(endNodeToEndPos, startNodeToEndNode);
            glm::dvec3 orthogonal = normalize(endNodeToEndPos - parallell);
            double dist = 5.0 * endNodeRadius;
            glm::dvec3 extraKnot = endNodePos + dist * orthogonal;

            _points.push_back(extraKnot - parallell);
            _points.push_back(extraKnot);
            _points.push_back(extraKnot + parallell);
        }
    }

    _points.push_back(end.position + endTangentLength * endTangentDirection);
    _points.push_back(end.position);

    _nrSegments = (unsigned int)std::floor((_points.size() - 1) / 3.0);

    // default values for the curve parameter - equally spaced
    for (double t = 0.0; t <= 1.0; t += 1.0 / _nrSegments) {
        _parameterIntervals.push_back(t);
    }

    _length = arcLength(1.0);

    initParameterIntervals();
}

// Interpolate a list of control points and knot times
glm::dvec3 Bezier3Curve::positionAt(double u) {
    ghoul_assert(u >= 0 && u <= 1.0, "Interpolation variable out of range [0, 1]");

    size_t nrPoints = _points.size();
    size_t nrTimes = _parameterIntervals.size();

    ghoul_assert(nrPoints > 4, "Minimum of four control points needed for interpolation!");
    ghoul_assert((nrPoints - 1) % 3 == 0, "A vector containing 3n + 1 control points must be provided!");
    ghoul_assert(_nrSegments == (nrTimes - 1), "Number of interval times must match number of intervals");

    if (abs(u) < Epsilon)
        return _points.front();

    if (abs(1.0 - u) < Epsilon)
        return _points.back();

    // compute current segment, by first finding iterator to the first value that is larger than s
    std::vector<double>::iterator segmentEndIt =
        std::lower_bound(_parameterIntervals.begin(), _parameterIntervals.end(), u);
    unsigned int segmentIdx = (segmentEndIt - 1) - _parameterIntervals.begin();

    double segmentStart = _parameterIntervals[segmentIdx];
    double segmentDuration = (_parameterIntervals[segmentIdx + 1] - _parameterIntervals[segmentIdx]);
    double sScaled = (u - segmentStart) / segmentDuration;

    unsigned int idx = segmentIdx * 3;

    // Interpolate using De Casteljau's algorithm
    return interpolation::cubicBezier(sScaled, _points[idx], _points[idx + 1],
        _points[idx + 2], _points[idx + 3]);
}

// compute curve parameter intervals based on relative arc length
void Bezier3Curve::initParameterIntervals() {
    std::vector<double> newIntervals;
    for (double t = 0.0; t <= 1.0; t += 1.0 / _nrSegments) {
        newIntervals.push_back(arcLength(t) / _length);
    }
    _parameterIntervals.swap(newIntervals);
}

LinearCurve::LinearCurve(const CameraState& start, const CameraState& end) {
    _points.push_back(start.position);
    _points.push_back(end.position);
    _length = glm::distance(end.position, start.position);
    _rotationInterpolator = RotationInterpolator{ start, end, this, Slerp };
}

glm::dvec3 LinearCurve::positionAt(double u) {
    ghoul_assert(u >= 0 && u <= 1.0, "Interpolation variable out of range [0, 1]");
    return interpolation::linear(u, _points[0], _points[1]);
}

// TODO: Iprove handling of pauses
PauseCurve::PauseCurve(const CameraState& state) {
    _points.push_back(state.position);
    _length = 1.0; // OBS! Length of a pause curve makes no sense, but it also doesn't matter
    _rotationInterpolator = RotationInterpolator{ state, state, this, Fixed };
}

glm::dvec3 PauseCurve::positionAt(double u) {
    ghoul_assert(u >= 0 && u <= 1.0, "Interpolation variable out of range [0, 1]");
    return _points[0];
}

} // namespace openspace::autonavigation
<commit_msg>consistent types<commit_after>/*****************************************************************************************
*                                                                                *
* OpenSpace                                                                             *
*                                                                                *
* Copyright (c) 2014-2019                                                               *
*                                                                                *
* 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 <modules/autonavigation/pathcurves.h>

#include <modules/autonavigation/helperfunctions.h>
#include <openspace/query/query.h>
#include <openspace/scene/scenegraphnode.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/projection.hpp>

namespace {
    constexpr const char* _loggerCat = "PathCurve";
    const double Epsilon = 1E-7;
} // namespace

namespace openspace::autonavigation {

PathCurve::~PathCurve() {}

const double PathCurve::length() const {
    return _length;
}

// Approximate the curve length using Simpson's rule
double PathCurve::arcLength(double limit) {
    const int n = 30; // resolution, must be even for Simpson's rule
    const double h = limit / (double)n;

    // Points to be multiplied by 1
    double endPoints = glm::length(positionAt(0.0 + h) - positionAt(0.0)) + glm::length(positionAt(1.0) - positionAt(1.0 - h));

    // Points to be multiplied by 4
    double times4 = 0.0;
    for (int i = 1; i < n; i += 2) {
        double t = h * i;
        times4 += glm::length(positionAt(t + h) - positionAt(t));
    }

    // Points to be multiplied by 2
    double times2 = 0.0;
    for (int i = 2; i < n; i += 2) {
        double t = h * i;
        times2 += glm::length(positionAt(t + h) - positionAt(t));
    }

    return (h / 3.0) * (endPoints + 4.0 * times4 + 2.0 *times2);
}

glm::dquat PathCurve::rotationAt(double u) {
    return _rotationInterpolator.rotationAt(u);
}

// TODO: remove when not needed
// Created for debugging
std::vector<glm::dvec3> PathCurve::getPoints() {
    return _points;
}

Bezier3Curve::Bezier3Curve(const CameraState& start, const CameraState& end) {
    // default rotation interpolation
    _rotationInterpolator = RotationInterpolator{ start, end, this, PiecewiseSlerp };

    glm::dvec3 startNodePos = sceneGraphNode(start.referenceNode)->worldPosition();
    glm::dvec3 endNodePos = sceneGraphNode(end.referenceNode)->worldPosition();
    double startNodeRadius = sceneGraphNode(start.referenceNode)->boundingSphere();
    double endNodeRadius = sceneGraphNode(end.referenceNode)->boundingSphere();

    glm::dvec3 startNodeToStartPos = start.position - startNodePos;
    glm::dvec3 endNodeToEndPos = end.position - endNodePos;

    double startTangentLength = 2.0 * startNodeRadius;
    double endTangentLength = 2.0 * endNodeRadius;
    glm::dvec3 startTangentDirection = normalize(startNodeToStartPos);
    glm::dvec3 endTangentDirection = normalize(endNodeToEndPos);

    // Start by going outwards
    _points.push_back(start.position);
    _points.push_back(start.position + startTangentLength * startTangentDirection);

    if (start.referenceNode != end.referenceNode) {

        glm::dvec3 startNodeToEndNode = endNodePos - startNodePos;
        glm::dvec3 startToEndDirection = normalize(end.position - start.position);

        // Assuming we move straigh out to point to a distance proportional to radius, angle is enough to check collision risk
        double cosStartAngle = glm::dot(startTangentDirection, startToEndDirection);
        double cosEndAngle = glm::dot(endTangentDirection, startToEndDirection);
        double cosStartDir = glm::dot(startTangentDirection, endTangentDirection);

        //TODO: investigate suitable values, could be risky close to surface..
        bool TARGET_BEHIND_STARTNODE = cosStartAngle < -0.8;
        bool TARGET_BEHIND_ENDNODE = cosEndAngle > 0.8;
        bool TARGET_IN_OPPOSITE_DIRECTION = cosStartAngle > 0.7;

        // Avoid collision with startnode by adding control points on the side of it
        if (TARGET_BEHIND_STARTNODE) {
            glm::dvec3 parallell = glm::proj(startNodeToStartPos, startNodeToEndNode);
            glm::dvec3 orthogonal = normalize(startNodeToStartPos - parallell);
            double dist = 5.0 * startNodeRadius;
            glm::dvec3 extraKnot = startNodePos + dist * orthogonal;

            _points.push_back(extraKnot + parallell);
            _points.push_back(extraKnot);
            _points.push_back(extraKnot - parallell);
        }

        // Zoom out, to get a better understanding in a 180 degree turn situation
        if (TARGET_IN_OPPOSITE_DIRECTION) {
            glm::dvec3 parallell = glm::proj(startNodeToStartPos, startNodeToEndNode);
            glm::dvec3 orthogonal = normalize(startNodeToStartPos - parallell);
            double dist = 0.5 * glm::length(startNodeToEndNode);
            // Distant middle point
            glm::dvec3 extraKnot = startNodePos + dist * normalize(parallell) + 3.0 * dist * orthogonal;

            _points.push_back(extraKnot - 0.3 * dist *  normalize(parallell));
            _points.push_back(extraKnot);
            _points.push_back(extraKnot + 0.3 * dist *  normalize(parallell));
        }

        // Avoid collision with endnode by adding control points on the side of it
        if (TARGET_BEHIND_ENDNODE) {
            glm::dvec3 parallell = glm::proj(endNodeToEndPos, startNodeToEndNode);
            glm::dvec3 orthogonal = normalize(endNodeToEndPos - parallell);
            double dist = 5.0 * endNodeRadius;
            glm::dvec3 extraKnot = endNodePos + dist * orthogonal;

            _points.push_back(extraKnot - parallell);
            _points.push_back(extraKnot);
            _points.push_back(extraKnot + parallell);
        }
    }

    _points.push_back(end.position + endTangentLength * endTangentDirection);
    _points.push_back(end.position);

    _nrSegments = (unsigned int)std::floor((_points.size() - 1) / 3.0);

    // default values for the curve parameter - equally spaced
    for (double t = 0.0; t <= 1.0; t += 1.0 / _nrSegments) {
        _parameterIntervals.push_back(t);
    }

    _length = arcLength(1.0);

    initParameterIntervals();
}

// Interpolate a list of control points and knot times
glm::dvec3 Bezier3Curve::positionAt(double u) {
    ghoul_assert(u >= 0 && u <= 1.0, "Interpolation variable out of range [0, 1]");

    size_t nrPoints = _points.size();
    size_t nrTimes = _parameterIntervals.size();

    ghoul_assert(nrPoints > 4, "Minimum of four control points needed for interpolation!");
    ghoul_assert((nrPoints - 1) % 3 == 0, "A vector containing 3n + 1 control points must be provided!");
    ghoul_assert(_nrSegments == (nrTimes - 1), "Number of interval times must match number of intervals");

    if (abs(u) < Epsilon)
        return _points.front();

    if (abs(1.0 - u) < Epsilon)
        return _points.back();

    // compute current segment, by first finding iterator to the first value that is larger than s
    std::vector<double>::iterator segmentEndIt =
        std::lower_bound(_parameterIntervals.begin(), _parameterIntervals.end(), u);
    unsigned int segmentIdx = (segmentEndIt - 1) - _parameterIntervals.begin();

    double segmentStart = _parameterIntervals[segmentIdx];
    double segmentDuration = (_parameterIntervals[segmentIdx + 1] - _parameterIntervals[segmentIdx]);
    double sScaled = (u - segmentStart) / segmentDuration;

    unsigned int idx = segmentIdx * 3;

    // Interpolate using De Casteljau's algorithm
    return interpolation::cubicBezier(sScaled, _points[idx], _points[idx + 1],
        _points[idx + 2], _points[idx + 3]);
}

// compute curve parameter intervals based on relative arc length
void Bezier3Curve::initParameterIntervals() {
    std::vector<double> newIntervals;
    for (double t = 0.0; t <= 1.0; t += 1.0 / _nrSegments) {
        newIntervals.push_back(arcLength(t) / _length);
    }
    _parameterIntervals.swap(newIntervals);
}

LinearCurve::LinearCurve(const CameraState& start, const CameraState& end) {
    _points.push_back(start.position);
    _points.push_back(end.position);
    _length = glm::distance(end.position, start.position);
    _rotationInterpolator = RotationInterpolator{ start, end, this, Slerp };
}

glm::dvec3 LinearCurve::positionAt(double u) {
    ghoul_assert(u >= 0 && u <= 1.0, "Interpolation variable out of range [0, 1]");
    return interpolation::linear(u, _points[0], _points[1]);
}

// TODO: Iprove handling of pauses
PauseCurve::PauseCurve(const CameraState& state) {
    _points.push_back(state.position);
    _length = 1.0; // OBS! Length of a pause curve makes no sense, but it also doesn't matter
    _rotationInterpolator = RotationInterpolator{ state, state, this, Fixed };
}

glm::dvec3 PauseCurve::positionAt(double u) {
    ghoul_assert(u >= 0 && u <= 1.0, "Interpolation variable out of range [0, 1]");
    return _points[0];
}

} // namespace openspace::autonavigation
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2008, Carnegie Mellon University.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Carnegie Mellon University nor the names of
 *    other contributors may be used to endorse or promote products
 *    derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * (This is the Modified BSD License.  See also
 * http://www.opensource.org/licenses/bsd-license.php )
 */

/**
 * This is C++ porting codes of direct/src/showbase/SfxPlayer.py
 */

#include "render_pipeline/rppanda/showbase/sfx_player.hpp"

#include <audioSound.h>

#include "render_pipeline/rppanda/showbase/showbase.hpp"

namespace rppanda {

bool SfxPlayer::use_inverse_suqare_ = false;

class SfxPlayer::Impl
{
public:
    void set_cutoff_distance(float d);

    float cutoff_volume_;
    float cutoff_distance_;
    float raw_cutoff_distance_;
    float distance_scale_;
};

void SfxPlayer::Impl::set_cutoff_distance(float d)
{
    cutoff_distance_ = d;

    // this is the 'raw' distance at which the volume of a sound will
    // be equal to the cutoff volume
    raw_cutoff_distance_ = std::sqrt(1. / cutoff_volume_);

    // this is a scale factor to convert distances so that a sound
    // located at self.cutoffDistance will have a volume
    // of self.cutoffVolume
    distance_scale_ = raw_cutoff_distance_ / cutoff_distance_;
}

SfxPlayer::SfxPlayer(): impl_(std::make_unique<Impl>())
{
    // volume attenuates according to the inverse square of the
    // distance from the source. volume = 1/(distance^2)
    // this is the volume at which a sound is nearly inaudible
    impl_->cutoff_volume_ = 0.02;

    // cutoff for inverse square attenuation
    if (use_inverse_suqare_)
    {
        set_cutoff_distance(300.0f);
    }
    else
    {
        // Distance at which sounds can no longer be heard
        // This was determined experimentally
        set_cutoff_distance(120.0f);
    }
}

SfxPlayer::~SfxPlayer() = default;

float SfxPlayer::get_cutoff_distance()
{
    return impl_->cutoff_distance_;
}

float SfxPlayer::get_localized_volume(NodePath node, boost::optional<NodePath> listener_node, boost::optional<float> cutoff)
{
    if (node.is_empty())
        return 0;

    float d;
    if (listener_node && listener_node.value().is_empty())
        d = node.get_distance(listener_node.value());
    else
        d = node.get_distance(ShowBase::get_global_ptr()->get_cam());

    if (cutoff && d > cutoff.value())
        return 0;

    if (use_inverse_suqare_)
    {
        float sd = d * impl_->distance_scale_;
        return (std::min)(1.0f, 1.0f / (sd ? sd*sd : 1.0f));
    }
    else
    {
        return 1 - (d / (cutoff ? cutoff.value() : 1.0f));
    }
}

void SfxPlayer::set_cutoff_distance(float d)
{
    impl_->set_cutoff_distance(d);
}

void SfxPlayer::play_sfx(AudioSound* sfx, bool looping, bool interrupt, boost::optional<float> volume,
    float time, boost::optional<NodePath> node, boost::optional<NodePath> listener_node,
    boost::optional<float> cutoff)
{
    if (!sfx)
        return;

    if (!cutoff)
        cutoff = impl_->cutoff_distance_;

    set_final_volume(sfx, node, volume, listener_node, cutoff.value());

    if (interrupt || (sfx->status() != AudioSound::PLAYING))
    {
        sfx->set_time(time);
        sfx->set_loop(looping);
        sfx->play();
    }
}

void SfxPlayer::set_final_volume(AudioSound* sfx, boost::optional<NodePath> node, boost::optional<float> volume,
    boost::optional<NodePath> listener_node, boost::optional<float> cutoff)
{
    // If we have either a node or a volume, we need to adjust the sfx
    // The volume passed in multiplies the distance base volume

    if (!node && !volume)
        return;

    float final_volume;
    if (node)
        final_volume = get_localized_volume(node.value(), listener_node, cutoff);
    else
        final_volume = 1.0f;

    if (volume)
        final_volume *= volume.value();

    if (node)
        final_volume *= node.value().get_net_audio_volume();

    sfx->set_volume(final_volume);
}

}
<commit_msg>Patch panda3d/panda3d@d786709<commit_after>/**
 * Copyright (c) 2008, Carnegie Mellon University.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Carnegie Mellon University nor the names of
 *    other contributors may be used to endorse or promote products
 *    derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * (This is the Modified BSD License.  See also
 * http://www.opensource.org/licenses/bsd-license.php )
 */

/**
 * This is C++ porting codes of direct/src/showbase/SfxPlayer.py
 */

#include "render_pipeline/rppanda/showbase/sfx_player.hpp"

#include <audioSound.h>

#include "render_pipeline/rppanda/showbase/showbase.hpp"

namespace rppanda {

bool SfxPlayer::use_inverse_suqare_ = false;

class SfxPlayer::Impl
{
public:
    void set_cutoff_distance(float d);

    float cutoff_volume_;
    float cutoff_distance_;
    float raw_cutoff_distance_;
    float distance_scale_;
};

void SfxPlayer::Impl::set_cutoff_distance(float d)
{
    cutoff_distance_ = d;

    // this is the 'raw' distance at which the volume of a sound will
    // be equal to the cutoff volume
    raw_cutoff_distance_ = std::sqrt(1. / cutoff_volume_);

    // this is a scale factor to convert distances so that a sound
    // located at self.cutoffDistance will have a volume
    // of self.cutoffVolume
    distance_scale_ = raw_cutoff_distance_ / cutoff_distance_;
}

SfxPlayer::SfxPlayer(): impl_(std::make_unique<Impl>())
{
    // volume attenuates according to the inverse square of the
    // distance from the source. volume = 1/(distance^2)
    // this is the volume at which a sound is nearly inaudible
    impl_->cutoff_volume_ = 0.02;

    // cutoff for inverse square attenuation
    if (use_inverse_suqare_)
    {
        set_cutoff_distance(300.0f);
    }
    else
    {
        // Distance at which sounds can no longer be heard
        // This was determined experimentally
        set_cutoff_distance(120.0f);
    }
}

SfxPlayer::~SfxPlayer() = default;

float SfxPlayer::get_cutoff_distance()
{
    return impl_->cutoff_distance_;
}

float SfxPlayer::get_localized_volume(NodePath node, boost::optional<NodePath> listener_node, boost::optional<float> cutoff)
{
    if (node.is_empty())
        return 0;

    float d;
    if (listener_node && listener_node.value().is_empty())
        d = node.get_distance(listener_node.value());
    else
        d = node.get_distance(ShowBase::get_global_ptr()->get_cam());

    if (!cutoff)
        cutoff = impl_->cutoff_distance_;

    if (d > cutoff.value())
        return 0;

    if (use_inverse_suqare_)
    {
        float sd = d * impl_->distance_scale_;
        return (std::min)(1.0f, 1.0f / (sd ? sd*sd : 1.0f));
    }
    else
    {
        return 1 - (d / (cutoff ? cutoff.value() : 1.0f));
    }
}

void SfxPlayer::set_cutoff_distance(float d)
{
    impl_->set_cutoff_distance(d);
}

void SfxPlayer::play_sfx(AudioSound* sfx, bool looping, bool interrupt, boost::optional<float> volume,
    float time, boost::optional<NodePath> node, boost::optional<NodePath> listener_node,
    boost::optional<float> cutoff)
{
    if (!sfx)
        return;

    set_final_volume(sfx, node, volume, listener_node, cutoff);

    if (interrupt || (sfx->status() != AudioSound::PLAYING))
    {
        sfx->set_time(time);
        sfx->set_loop(looping);
        sfx->play();
    }
}

void SfxPlayer::set_final_volume(AudioSound* sfx, boost::optional<NodePath> node, boost::optional<float> volume,
    boost::optional<NodePath> listener_node, boost::optional<float> cutoff)
{
    // If we have either a node or a volume, we need to adjust the sfx
    // The volume passed in multiplies the distance base volume

    if (!node && !volume)
        return;

    float final_volume;
    if (node)
        final_volume = get_localized_volume(node.value(), listener_node, cutoff);
    else
        final_volume = 1.0f;

    if (volume)
        final_volume *= volume.value();

    if (node)
        final_volume *= node.value().get_net_audio_volume();

    sfx->set_volume(final_volume);
}

}
<|endoftext|>