<commit_before>// ---------------------------------------------------------------------
//
// Copyright (C) 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, 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.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/base/utilities.h>
#include <deal.II/base/memory_consumption.h>
#include <deal.II/base/logstream.h>
#include <deal.II/lac/sparsity_tools.h>
#include <deal.II/lac/sparsity_pattern.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/distributed/tria_base.h>

#include <algorithm>
#include <numeric>
#include <iostream>
#include <fstream>

DEAL_II_NAMESPACE_OPEN

namespace parallel
{

  template <int dim, int spacedim>
  Triangulation<dim,spacedim>::Triangulation (MPI_Comm mpi_communicator,
                                              const typename dealii::Triangulation<dim,spacedim>::MeshSmoothing smooth_grid,
                                              const bool check_for_distorted_cells)
    :
    dealii::Triangulation<dim,spacedim>(smooth_grid,check_for_distorted_cells),
    mpi_communicator (Utilities::MPI::
                      duplicate_communicator(mpi_communicator)),
    my_subdomain (Utilities::MPI::this_mpi_process (this->mpi_communicator)),
    n_subdomains(Utilities::MPI::n_mpi_processes(mpi_communicator))
  {
#ifndef DEAL_II_WITH_MPI
    Assert(false, ExcMessage("You compiled deal.II without MPI support, for "
                             "which parallel::Triangulation is not available."));
#endif
    number_cache.n_locally_owned_active_cells.resize (n_subdomains);
  }

  template <int dim, int spacedim>
  void
  Triangulation<dim,spacedim>::copy_triangulation (const dealii::Triangulation<dim, spacedim> &old_tria)
  {
#ifndef DEAL_II_WITH_MPI
    Assert(false, ExcNotImplemented());
#endif
    if (const dealii::parallel::Triangulation<dim,spacedim> *
        old_tria_x = dynamic_cast<const dealii::parallel::Triangulation<dim,spacedim> *>(&old_tria))
      {
        mpi_communicator = Utilities::MPI::duplicate_communicator (old_tria_x->get_communicator ());
      }
  }

  template <int dim, int spacedim>
  std::size_t
  Triangulation<dim,spacedim>::memory_consumption() const
  {
    std::size_t mem=
      this->dealii::Triangulation<dim,spacedim>::memory_consumption()
      + MemoryConsumption::memory_consumption(mpi_communicator)
      + MemoryConsumption::memory_consumption(my_subdomain)
      + MemoryConsumption::memory_consumption(number_cache.n_locally_owned_active_cells)
      + MemoryConsumption::memory_consumption(number_cache.n_global_active_cells)
      + MemoryConsumption::memory_consumption(number_cache.n_global_levels);
    return mem;

  }

  template <int dim, int spacedim>
  Triangulation<dim,spacedim>::~Triangulation ()
  {
#ifdef DEAL_II_WITH_MPI
    // get rid of the unique communicator used here again
    MPI_Comm_free (&this->mpi_communicator);
#endif
  }

  template <int dim, int spacedim>
  Triangulation<dim,spacedim>::NumberCache::NumberCache()
    :
    n_global_active_cells(0),
    n_global_levels(0)
  {}

  template <int dim, int spacedim>
  unsigned int
  Triangulation<dim,spacedim>::n_locally_owned_active_cells () const
  {
    return number_cache.n_locally_owned_active_cells[my_subdomain];
  }

  template <int dim, int spacedim>
  unsigned int
  Triangulation<dim,spacedim>::n_global_levels () const
  {
    return number_cache.n_global_levels;
  }

  template <int dim, int spacedim>
  types::global_dof_index
  Triangulation<dim,spacedim>::n_global_active_cells () const
  {
    return number_cache.n_global_active_cells;
  }

  template <int dim, int spacedim>
  const std::vector<unsigned int> &
  Triangulation<dim,spacedim>::n_locally_owned_active_cells_per_processor () const
  {
    return number_cache.n_locally_owned_active_cells;
  }

  template <int dim, int spacedim>
  MPI_Comm
  Triangulation<dim,spacedim>::get_communicator () const
  {
    return mpi_communicator;
  }

#ifdef DEAL_II_WITH_MPI
  template <int dim, int spacedim>
  void
  Triangulation<dim,spacedim>::update_number_cache ()
  {
    Assert (number_cache.n_locally_owned_active_cells.size()
            ==
            Utilities::MPI::n_mpi_processes (this->mpi_communicator),
            ExcInternalError());

    std::fill (number_cache.n_locally_owned_active_cells.begin(),
               number_cache.n_locally_owned_active_cells.end(),
               0);

    number_cache.ghost_owners.clear ();
    number_cache.level_ghost_owners.clear ();

    if (this->n_levels() == 0)
      {
        // Skip communication done below if we do not have any cells
        // (meaning the Triangulation is empty on all processors). This will
        // happen when called from the destructor of Triangulation, which
        // can get called during exception handling causing a hang in this
        // function.
        number_cache.n_global_active_cells = 0;
        number_cache.n_global_levels = 0;
        return;
      }

    {
      // find ghost owners
      for (typename Triangulation<dim,spacedim>::active_cell_iterator
           cell = this->begin_active();
           cell != this->end();
           ++cell)
        if (cell->is_ghost())
          number_cache.ghost_owners.insert(cell->subdomain_id());

      Assert(number_cache.ghost_owners.size() < Utilities::MPI::n_mpi_processes(mpi_communicator), ExcInternalError());
    }

    if (this->n_levels() > 0)
      for (typename Triangulation<dim,spacedim>::active_cell_iterator
           cell = this->begin_active();
           cell != this->end(); ++cell)
        if (cell->subdomain_id() == my_subdomain)
          ++number_cache.n_locally_owned_active_cells[my_subdomain];

    unsigned int send_value
      = number_cache.n_locally_owned_active_cells[my_subdomain];
    MPI_Allgather (&send_value,
                   1,
                   MPI_UNSIGNED,
                   &number_cache.n_locally_owned_active_cells[0],
                   1,
                   MPI_UNSIGNED,
                   this->mpi_communicator);

    number_cache.n_global_active_cells
      = std::accumulate (number_cache.n_locally_owned_active_cells.begin(),
                         number_cache.n_locally_owned_active_cells.end(),
                         /* ensure sum is computed with correct data type:*/
                         static_cast<types::global_dof_index>(0));
    number_cache.n_global_levels = Utilities::MPI::max(this->n_levels(), this->mpi_communicator);
  }
#else
  template <int dim, int spacedim>
  void
  Triangulation<dim,spacedim>::update_number_cache ()
  {
    Assert (false, ExcNotImplemented());
  }

#endif

  template <int dim, int spacedim>
  types::subdomain_id
  Triangulation<dim,spacedim>::locally_owned_subdomain () const
  {
    Assert (dim > 1, ExcNotImplemented());
    return my_subdomain;
  }

  template <int dim, int spacedim>
  const std::set<unsigned int> &
  Triangulation<dim,spacedim>::
  ghost_owners () const
  {
    return number_cache.ghost_owners;
  }

  template <int dim, int spacedim>
  const std::set<unsigned int> &
  Triangulation<dim,spacedim>::
  level_ghost_owners () const
  {
    return number_cache.level_ghost_owners;
  }

} // end namespace parallel

/*-------------- Explicit Instantiations -------------------------------*/
#include "tria_base.inst"

DEAL_II_NAMESPACE_CLOSE
<commit_msg>remove assert in distributed Tria for dim==1<commit_after>// ---------------------------------------------------------------------
//
// Copyright (C) 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, 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.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/base/utilities.h>
#include <deal.II/base/memory_consumption.h>
#include <deal.II/base/logstream.h>
#include <deal.II/lac/sparsity_tools.h>
#include <deal.II/lac/sparsity_pattern.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/distributed/tria_base.h>

#include <algorithm>
#include <numeric>
#include <iostream>
#include <fstream>

DEAL_II_NAMESPACE_OPEN

namespace parallel
{

  template <int dim, int spacedim>
  Triangulation<dim,spacedim>::Triangulation (MPI_Comm mpi_communicator,
                                              const typename dealii::Triangulation<dim,spacedim>::MeshSmoothing smooth_grid,
                                              const bool check_for_distorted_cells)
    :
    dealii::Triangulation<dim,spacedim>(smooth_grid,check_for_distorted_cells),
    mpi_communicator (Utilities::MPI::
                      duplicate_communicator(mpi_communicator)),
    my_subdomain (Utilities::MPI::this_mpi_process (this->mpi_communicator)),
    n_subdomains(Utilities::MPI::n_mpi_processes(mpi_communicator))
  {
#ifndef DEAL_II_WITH_MPI
    Assert(false, ExcMessage("You compiled deal.II without MPI support, for "
                             "which parallel::Triangulation is not available."));
#endif
    number_cache.n_locally_owned_active_cells.resize (n_subdomains);
  }

  template <int dim, int spacedim>
  void
  Triangulation<dim,spacedim>::copy_triangulation (const dealii::Triangulation<dim, spacedim> &old_tria)
  {
#ifndef DEAL_II_WITH_MPI
    Assert(false, ExcNotImplemented());
#endif
    if (const dealii::parallel::Triangulation<dim,spacedim> *
        old_tria_x = dynamic_cast<const dealii::parallel::Triangulation<dim,spacedim> *>(&old_tria))
      {
        mpi_communicator = Utilities::MPI::duplicate_communicator (old_tria_x->get_communicator ());
      }
  }

  template <int dim, int spacedim>
  std::size_t
  Triangulation<dim,spacedim>::memory_consumption() const
  {
    std::size_t mem=
      this->dealii::Triangulation<dim,spacedim>::memory_consumption()
      + MemoryConsumption::memory_consumption(mpi_communicator)
      + MemoryConsumption::memory_consumption(my_subdomain)
      + MemoryConsumption::memory_consumption(number_cache.n_locally_owned_active_cells)
      + MemoryConsumption::memory_consumption(number_cache.n_global_active_cells)
      + MemoryConsumption::memory_consumption(number_cache.n_global_levels);
    return mem;

  }

  template <int dim, int spacedim>
  Triangulation<dim,spacedim>::~Triangulation ()
  {
#ifdef DEAL_II_WITH_MPI
    // get rid of the unique communicator used here again
    MPI_Comm_free (&this->mpi_communicator);
#endif
  }

  template <int dim, int spacedim>
  Triangulation<dim,spacedim>::NumberCache::NumberCache()
    :
    n_global_active_cells(0),
    n_global_levels(0)
  {}

  template <int dim, int spacedim>
  unsigned int
  Triangulation<dim,spacedim>::n_locally_owned_active_cells () const
  {
    return number_cache.n_locally_owned_active_cells[my_subdomain];
  }

  template <int dim, int spacedim>
  unsigned int
  Triangulation<dim,spacedim>::n_global_levels () const
  {
    return number_cache.n_global_levels;
  }

  template <int dim, int spacedim>
  types::global_dof_index
  Triangulation<dim,spacedim>::n_global_active_cells () const
  {
    return number_cache.n_global_active_cells;
  }

  template <int dim, int spacedim>
  const std::vector<unsigned int> &
  Triangulation<dim,spacedim>::n_locally_owned_active_cells_per_processor () const
  {
    return number_cache.n_locally_owned_active_cells;
  }

  template <int dim, int spacedim>
  MPI_Comm
  Triangulation<dim,spacedim>::get_communicator () const
  {
    return mpi_communicator;
  }

#ifdef DEAL_II_WITH_MPI
  template <int dim, int spacedim>
  void
  Triangulation<dim,spacedim>::update_number_cache ()
  {
    Assert (number_cache.n_locally_owned_active_cells.size()
            ==
            Utilities::MPI::n_mpi_processes (this->mpi_communicator),
            ExcInternalError());

    std::fill (number_cache.n_locally_owned_active_cells.begin(),
               number_cache.n_locally_owned_active_cells.end(),
               0);

    number_cache.ghost_owners.clear ();
    number_cache.level_ghost_owners.clear ();

    if (this->n_levels() == 0)
      {
        // Skip communication done below if we do not have any cells
        // (meaning the Triangulation is empty on all processors). This will
        // happen when called from the destructor of Triangulation, which
        // can get called during exception handling causing a hang in this
        // function.
        number_cache.n_global_active_cells = 0;
        number_cache.n_global_levels = 0;
        return;
      }

    {
      // find ghost owners
      for (typename Triangulation<dim,spacedim>::active_cell_iterator
           cell = this->begin_active();
           cell != this->end();
           ++cell)
        if (cell->is_ghost())
          number_cache.ghost_owners.insert(cell->subdomain_id());

      Assert(number_cache.ghost_owners.size() < Utilities::MPI::n_mpi_processes(mpi_communicator), ExcInternalError());
    }

    if (this->n_levels() > 0)
      for (typename Triangulation<dim,spacedim>::active_cell_iterator
           cell = this->begin_active();
           cell != this->end(); ++cell)
        if (cell->subdomain_id() == my_subdomain)
          ++number_cache.n_locally_owned_active_cells[my_subdomain];

    unsigned int send_value
      = number_cache.n_locally_owned_active_cells[my_subdomain];
    MPI_Allgather (&send_value,
                   1,
                   MPI_UNSIGNED,
                   &number_cache.n_locally_owned_active_cells[0],
                   1,
                   MPI_UNSIGNED,
                   this->mpi_communicator);

    number_cache.n_global_active_cells
      = std::accumulate (number_cache.n_locally_owned_active_cells.begin(),
                         number_cache.n_locally_owned_active_cells.end(),
                         /* ensure sum is computed with correct data type:*/
                         static_cast<types::global_dof_index>(0));
    number_cache.n_global_levels = Utilities::MPI::max(this->n_levels(), this->mpi_communicator);
  }
#else
  template <int dim, int spacedim>
  void
  Triangulation<dim,spacedim>::update_number_cache ()
  {
    Assert (false, ExcNotImplemented());
  }

#endif

  template <int dim, int spacedim>
  types::subdomain_id
  Triangulation<dim,spacedim>::locally_owned_subdomain () const
  {
    return my_subdomain;
  }

  template <int dim, int spacedim>
  const std::set<unsigned int> &
  Triangulation<dim,spacedim>::
  ghost_owners () const
  {
    return number_cache.ghost_owners;
  }

  template <int dim, int spacedim>
  const std::set<unsigned int> &
  Triangulation<dim,spacedim>::
  level_ghost_owners () const
  {
    return number_cache.level_ghost_owners;
  }

} // end namespace parallel

/*-------------- Explicit Instantiations -------------------------------*/
#include "tria_base.inst"

DEAL_II_NAMESPACE_CLOSE
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: HView.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: ihi $ $Date: 2007-11-21 15:02:09 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#include "hsqldb/HView.hxx"
#include "hsqldb/HTools.hxx"

#include "propertyids.hxx"

#include "connectivity/dbexception.hxx"
#include "connectivity/dbtools.hxx"

/** === begin UNO includes === **/
#include <com/sun/star/lang/WrappedTargetException.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/sdbc/XRow.hpp>
/** === end UNO includes === **/

#include <cppuhelper/exc_hlp.hxx>
#include <tools/diagnose_ex.h>
#include <unotools/sharedunocomponent.hxx>

//........................................................................
namespace connectivity { namespace hsqldb
{
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::UNO_QUERY;
    using ::com::sun::star::uno::UNO_QUERY_THROW;
    using ::com::sun::star::uno::Exception;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::uno::Any;
    using ::com::sun::star::uno::makeAny;
    using ::com::sun::star::sdbc::XDatabaseMetaData;
    using ::com::sun::star::sdbc::SQLException;
    using ::com::sun::star::sdbc::XConnection;
    using ::com::sun::star::lang::WrappedTargetException;
    using ::com::sun::star::sdbc::XResultSet;
    using ::com::sun::star::sdbc::XStatement;
    using ::com::sun::star::lang::DisposedException;
    using ::com::sun::star::sdbc::XRow;
    /** === end UNO using === **/

    //====================================================================
    //= HView
    //====================================================================
    //--------------------------------------------------------------------
    HView::HView( const Reference< XConnection >& _rxConnection, sal_Bool _bCaseSensitive,
        const ::rtl::OUString& _rSchemaName, const ::rtl::OUString& _rName )
        :HView_Base( _bCaseSensitive, _rName, _rxConnection->getMetaData(), 0, ::rtl::OUString(), _rSchemaName, ::rtl::OUString() )
        ,m_xConnection( _rxConnection )
    {
    }

    //--------------------------------------------------------------------
    HView::~HView()
    {
    }

    //--------------------------------------------------------------------
    IMPLEMENT_FORWARD_XINTERFACE2( HView, HView_Base, HView_IBASE )
    IMPLEMENT_FORWARD_XTYPEPROVIDER2( HView, HView_Base, HView_IBASE )

    //--------------------------------------------------------------------
    void SAL_CALL HView::alterCommand( const ::rtl::OUString& _rNewCommand ) throw (SQLException, RuntimeException)
    {
        // not really atomic ... as long as we do not have something like
        //   ALTER VIEW <name> TO <command>
        // in HSQL, we need to do it this way ...
        //
        // I can imagine scenarios where this fails, e.g. when dropping the view
        // succeedes, re-creating it fails, some other thread alters a table which
        // the view was based on, and then we try to restore the view with the
        // original command, which then fails, too.
        //
        // However, there's not much chance to prevent this kind of errors without
        // backend support.

        ::rtl::OUString sQualifiedName( ::dbtools::composeTableName(
            m_xMetaData, m_CatalogName, m_SchemaName, m_Name, true, ::dbtools::eInDataManipulation ) );

        ::utl::SharedUNOComponent< XStatement > xStatement; xStatement.set( m_xConnection->createStatement(), UNO_QUERY_THROW );

        // create a statement which can be used to re-create the original view, in case
        // dropping it succeeds, but creating it with a new statement fails
        ::rtl::OUStringBuffer aRestoreCommand;
        aRestoreCommand.appendAscii( "CREATE VIEW " );
        aRestoreCommand.append     ( sQualifiedName );
        aRestoreCommand.appendAscii( " AS " );
        aRestoreCommand.append     ( impl_getCommand_throw( true ) );
        ::rtl::OUString sRestoreCommand( aRestoreCommand.makeStringAndClear() );

        bool bDropSucceeded( false );
        try
        {
            // drop the existing view
            ::rtl::OUStringBuffer aCommand;
            aCommand.appendAscii( "DROP VIEW " );
            aCommand.append     ( sQualifiedName );
            xStatement->execute( aCommand.makeStringAndClear() );
            bDropSucceeded = true;

            // create a new one with the same name
            aCommand.appendAscii( "CREATE VIEW " );
            aCommand.append     ( sQualifiedName );
            aCommand.appendAscii( " AS " );
            aCommand.append     ( _rNewCommand );
            xStatement->execute( aCommand.makeStringAndClear() );
        }
        catch( const SQLException& )
        {
            if ( bDropSucceeded )
                // drop succeeded, but creation failed -> re-create the view with the original
                // statemnet
                xStatement->execute( sRestoreCommand );
            throw;
        }
        catch( const RuntimeException& )
        {
            if ( bDropSucceeded )
                xStatement->execute( sRestoreCommand );
            throw;
        }
        catch( const Exception& )
        {
            if ( bDropSucceeded )
                xStatement->execute( sRestoreCommand );
            DBG_UNHANDLED_EXCEPTION();
        }
    }

    //--------------------------------------------------------------------
    void SAL_CALL HView::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
    {
        if ( _nHandle == PROPERTY_ID_COMMAND )
        {
            // retrieve the very current command, don't rely on the base classes cached value
            // (which we initialized empty, anyway)
            _rValue <<= impl_getCommand_throw( false );
            return;
        }

        HView_Base::getFastPropertyValue( _rValue, _nHandle );
    }

    //--------------------------------------------------------------------
    ::rtl::OUString HView::impl_getCommand_throw( bool _bAllowSQLException ) const
    {
        ::rtl::OUString sCommand;

        try
        {
            ::rtl::OUStringBuffer aCommand;
            aCommand.appendAscii( "SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.SYSTEM_VIEWS " );
            HTools::appendTableFilterCrit( aCommand, m_CatalogName, m_SchemaName, m_Name, false );
            ::utl::SharedUNOComponent< XStatement > xStatement; xStatement.set( m_xConnection->createStatement(), UNO_QUERY_THROW );
            Reference< XResultSet > xResult( xStatement->executeQuery( aCommand.makeStringAndClear() ), UNO_QUERY_THROW );
            if ( !xResult->next() )
            {
                // hmm. There is no view view the name as we know it. Can only mean some other instance
                // dropped this view meanwhile ...
                throw DisposedException();
            }

            Reference< XRow > xRow( xResult, UNO_QUERY_THROW );
            sCommand = xRow->getString( 1 );
        }
        catch( const RuntimeException& ) { throw; }
        catch( const SQLException& e )
        {
            if ( _bAllowSQLException )
                throw;
            throw WrappedTargetException( e.Message, static_cast< XAlterView* >( const_cast< HView* >( this ) ), ::cppu::getCaughtException() );
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }

        return sCommand;
    }

//........................................................................
} } // namespace connectivity::hsqldb
//........................................................................
<commit_msg>INTEGRATION: CWS changefileheader (1.2.64); FILE MERGED 2008/03/28 15:23:38 rt 1.2.64.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: HView.cxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

#include "hsqldb/HView.hxx"
#include "hsqldb/HTools.hxx"

#include "propertyids.hxx"

#include "connectivity/dbexception.hxx"
#include "connectivity/dbtools.hxx"

/** === begin UNO includes === **/
#include <com/sun/star/lang/WrappedTargetException.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/sdbc/XRow.hpp>
/** === end UNO includes === **/

#include <cppuhelper/exc_hlp.hxx>
#include <tools/diagnose_ex.h>
#include <unotools/sharedunocomponent.hxx>

//........................................................................
namespace connectivity { namespace hsqldb
{
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::UNO_QUERY;
    using ::com::sun::star::uno::UNO_QUERY_THROW;
    using ::com::sun::star::uno::Exception;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::uno::Any;
    using ::com::sun::star::uno::makeAny;
    using ::com::sun::star::sdbc::XDatabaseMetaData;
    using ::com::sun::star::sdbc::SQLException;
    using ::com::sun::star::sdbc::XConnection;
    using ::com::sun::star::lang::WrappedTargetException;
    using ::com::sun::star::sdbc::XResultSet;
    using ::com::sun::star::sdbc::XStatement;
    using ::com::sun::star::lang::DisposedException;
    using ::com::sun::star::sdbc::XRow;
    /** === end UNO using === **/

    //====================================================================
    //= HView
    //====================================================================
    //--------------------------------------------------------------------
    HView::HView( const Reference< XConnection >& _rxConnection, sal_Bool _bCaseSensitive,
        const ::rtl::OUString& _rSchemaName, const ::rtl::OUString& _rName )
        :HView_Base( _bCaseSensitive, _rName, _rxConnection->getMetaData(), 0, ::rtl::OUString(), _rSchemaName, ::rtl::OUString() )
        ,m_xConnection( _rxConnection )
    {
    }

    //--------------------------------------------------------------------
    HView::~HView()
    {
    }

    //--------------------------------------------------------------------
    IMPLEMENT_FORWARD_XINTERFACE2( HView, HView_Base, HView_IBASE )
    IMPLEMENT_FORWARD_XTYPEPROVIDER2( HView, HView_Base, HView_IBASE )

    //--------------------------------------------------------------------
    void SAL_CALL HView::alterCommand( const ::rtl::OUString& _rNewCommand ) throw (SQLException, RuntimeException)
    {
        // not really atomic ... as long as we do not have something like
        //   ALTER VIEW <name> TO <command>
        // in HSQL, we need to do it this way ...
        //
        // I can imagine scenarios where this fails, e.g. when dropping the view
        // succeedes, re-creating it fails, some other thread alters a table which
        // the view was based on, and then we try to restore the view with the
        // original command, which then fails, too.
        //
        // However, there's not much chance to prevent this kind of errors without
        // backend support.

        ::rtl::OUString sQualifiedName( ::dbtools::composeTableName(
            m_xMetaData, m_CatalogName, m_SchemaName, m_Name, true, ::dbtools::eInDataManipulation ) );

        ::utl::SharedUNOComponent< XStatement > xStatement; xStatement.set( m_xConnection->createStatement(), UNO_QUERY_THROW );

        // create a statement which can be used to re-create the original view, in case
        // dropping it succeeds, but creating it with a new statement fails
        ::rtl::OUStringBuffer aRestoreCommand;
        aRestoreCommand.appendAscii( "CREATE VIEW " );
        aRestoreCommand.append     ( sQualifiedName );
        aRestoreCommand.appendAscii( " AS " );
        aRestoreCommand.append     ( impl_getCommand_throw( true ) );
        ::rtl::OUString sRestoreCommand( aRestoreCommand.makeStringAndClear() );

        bool bDropSucceeded( false );
        try
        {
            // drop the existing view
            ::rtl::OUStringBuffer aCommand;
            aCommand.appendAscii( "DROP VIEW " );
            aCommand.append     ( sQualifiedName );
            xStatement->execute( aCommand.makeStringAndClear() );
            bDropSucceeded = true;

            // create a new one with the same name
            aCommand.appendAscii( "CREATE VIEW " );
            aCommand.append     ( sQualifiedName );
            aCommand.appendAscii( " AS " );
            aCommand.append     ( _rNewCommand );
            xStatement->execute( aCommand.makeStringAndClear() );
        }
        catch( const SQLException& )
        {
            if ( bDropSucceeded )
                // drop succeeded, but creation failed -> re-create the view with the original
                // statemnet
                xStatement->execute( sRestoreCommand );
            throw;
        }
        catch( const RuntimeException& )
        {
            if ( bDropSucceeded )
                xStatement->execute( sRestoreCommand );
            throw;
        }
        catch( const Exception& )
        {
            if ( bDropSucceeded )
                xStatement->execute( sRestoreCommand );
            DBG_UNHANDLED_EXCEPTION();
        }
    }

    //--------------------------------------------------------------------
    void SAL_CALL HView::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
    {
        if ( _nHandle == PROPERTY_ID_COMMAND )
        {
            // retrieve the very current command, don't rely on the base classes cached value
            // (which we initialized empty, anyway)
            _rValue <<= impl_getCommand_throw( false );
            return;
        }

        HView_Base::getFastPropertyValue( _rValue, _nHandle );
    }

    //--------------------------------------------------------------------
    ::rtl::OUString HView::impl_getCommand_throw( bool _bAllowSQLException ) const
    {
        ::rtl::OUString sCommand;

        try
        {
            ::rtl::OUStringBuffer aCommand;
            aCommand.appendAscii( "SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.SYSTEM_VIEWS " );
            HTools::appendTableFilterCrit( aCommand, m_CatalogName, m_SchemaName, m_Name, false );
            ::utl::SharedUNOComponent< XStatement > xStatement; xStatement.set( m_xConnection->createStatement(), UNO_QUERY_THROW );
            Reference< XResultSet > xResult( xStatement->executeQuery( aCommand.makeStringAndClear() ), UNO_QUERY_THROW );
            if ( !xResult->next() )
            {
                // hmm. There is no view view the name as we know it. Can only mean some other instance
                // dropped this view meanwhile ...
                throw DisposedException();
            }

            Reference< XRow > xRow( xResult, UNO_QUERY_THROW );
            sCommand = xRow->getString( 1 );
        }
        catch( const RuntimeException& ) { throw; }
        catch( const SQLException& e )
        {
            if ( _bAllowSQLException )
                throw;
            throw WrappedTargetException( e.Message, static_cast< XAlterView* >( const_cast< HView* >( this ) ), ::cppu::getCaughtException() );
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }

        return sCommand;
    }

//........................................................................
} } // namespace connectivity::hsqldb
//........................................................................
<|endoftext|>


<commit_before>
// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/sfm/pipelines/localization/SfM_Localizer.hpp"
#include "openMVG/sfm/sfm_data_BA_ceres.hpp"

#include "openMVG/multiview/solver_resection_kernel.hpp"
#include "openMVG/multiview/solver_resection_p3p.hpp"
#include "openMVG/robust_estimation/robust_estimator_ACRansac.hpp"
#include "openMVG/robust_estimation/robust_estimator_ACRansacKernelAdaptator.hpp"
#include <openMVG/robust_estimation/robust_estimator_LORansac.hpp>
#include <openMVG/robust_estimation/robust_estimator_LORansacKernelAdaptor.hpp>
#include <openMVG/robust_estimation/score_evaluator.hpp>

namespace openMVG {
namespace sfm {

struct ResectionSquaredResidualError
{
  // Compute the residual of the projection distance(pt2D, Project(P,pt3D))
  // Return the squared error
  static double Error(const Mat34 & P, const Vec2 & pt2D, const Vec3 & pt3D)
  {
    const Vec2 x = Project(P, pt3D);
    return (x - pt2D).squaredNorm();
  }
};

bool SfM_Localizer::Localize
(
  const Pair & image_size,
  const cameras::IntrinsicBase * optional_intrinsics,
  Image_Localizer_Match_Data & resection_data,
  geometry::Pose3 & pose,
  robust::EROBUST_ESTIMATOR estimator
)
{
  // --
  // Compute the camera pose (resectioning)
  // --
  Mat34 P;
  resection_data.vec_inliers.clear();

  // Setup the admissible upper bound residual error
  const double dPrecision =
    resection_data.error_max == std::numeric_limits<double>::infinity() ?
    std::numeric_limits<double>::infinity() :
    Square(resection_data.error_max);

  size_t MINIMUM_SAMPLES = 0;
  const cameras::Pinhole_Intrinsic * pinhole_cam = dynamic_cast<const cameras::Pinhole_Intrinsic *>(optional_intrinsics);
  if (pinhole_cam == nullptr || !pinhole_cam->isValid())
  {
    //--
    // Classic resection (try to compute the entire P matrix)
    typedef openMVG::resection::kernel::SixPointResectionSolver SolverType;
    MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;

    typedef openMVG::robust::ACKernelAdaptorResection<
      SolverType, ResectionSquaredResidualError, openMVG::robust::UnnormalizerResection, Mat34>
      KernelType;

    KernelType kernel(resection_data.pt2D, image_size.first, image_size.second,
      resection_data.pt3D);
    // Robust estimation of the Projection matrix and its precision
    const std::pair<double,double> ACRansacOut =
      openMVG::robust::ACRANSAC(kernel, resection_data.vec_inliers, resection_data.max_iteration, &P, dPrecision, true);
    // Update the upper bound precision of the model found by AC-RANSAC
    resection_data.error_max = ACRansacOut.first;
  }
  else
  {
    // undistort the points if the camera has a distortion model
    Mat pt2Dundistorted;
    const bool has_disto = pinhole_cam->have_disto();
    if(has_disto)
    {
      const std::size_t numPts = resection_data.pt2D.cols();
      pt2Dundistorted = Mat2X(2, numPts);
      for(std::size_t iPoint = 0; iPoint < numPts; ++iPoint)
      {
        pt2Dundistorted.col(iPoint) = pinhole_cam->get_ud_pixel(resection_data.pt2D.col(iPoint));
      }
    }

    switch(estimator)
    {
      case robust::ROBUST_ESTIMATOR_ACRANSAC:
      {
        //--
        // Since K calibration matrix is known, compute only [R|t]
        typedef openMVG::euclidean_resection::P3PSolver SolverType;
        MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;

        typedef openMVG::robust::ACKernelAdaptorResection_K<
                SolverType, ResectionSquaredResidualError,
                openMVG::robust::UnnormalizerResection, Mat34> KernelType;

        // otherwise we just pass the input points
        KernelType kernel = KernelType(has_disto ? pt2Dundistorted : resection_data.pt2D, resection_data.pt3D, pinhole_cam->K());

        // Robust estimation of the Projection matrix and its precision
        const std::pair<double, double> ACRansacOut =
                openMVG::robust::ACRANSAC(kernel, resection_data.vec_inliers, resection_data.max_iteration, &P, dPrecision, true);
        // Update the upper bound precision of the model found by AC-RANSAC
        resection_data.error_max = ACRansacOut.first;
        break;
      }

      case robust::ROBUST_ESTIMATOR_LORANSAC:
      {

        // just a safeguard
        if(resection_data.error_max == std::numeric_limits<double>::infinity())
        {
          throw std::invalid_argument("[SfM_Localizer::Localize] the threshold of the LORANSAC is set to infinity!");
        }

        // use the P3P solver for generating the model
        typedef openMVG::euclidean_resection::P3PSolver SolverType;
        MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;
        // use the six point algorithm as Least square solution to refine the model
        typedef openMVG::resection::kernel::SixPointResectionSolver SolverLSType;

        typedef openMVG::robust::KernelAdaptorResectionLORansac_K<SolverType,
                ResectionSquaredResidualError,
                openMVG::robust::UnnormalizerResection,
                SolverLSType,
                Mat34> KernelType;

        // otherwise we just pass the input points
        KernelType kernel = KernelType(has_disto ? pt2Dundistorted : resection_data.pt2D, resection_data.pt3D, pinhole_cam->K());

        // this is just stupid and ugly, the threshold should be always give as pixel
        // value, the scorer should be not aware of the fact that we treat squared errors
        // and normalization inside the kernel
        // @todo refactor, maybe move scorer directly inside the kernel
        const double threshold = resection_data.error_max * resection_data.error_max / (kernel.normalizer2()(0, 0) * kernel.normalizer2()(0, 0));
        robust::ScorerEvaluator<KernelType> scorer(threshold);
        P = robust::LO_RANSAC(kernel, scorer, &resection_data.vec_inliers);
        break;
      }

      default:
        throw std::runtime_error("[SfM_Localizer::Localize] Only ACRansac and LORansac are supported!");
    }
  }

  // Test if the mode support some points (more than those required for estimation)
  const bool bResection = (resection_data.vec_inliers.size() > MINIMUM_SAMPLES * OPENMVG_MINIMUM_SAMPLES_COEF);
#ifdef WANTS_POPART_COUT
  if (!bResection)
  {
    std::cout << "bResection is false";
    std::cout << " because resection_data.vec_inliers.size() = " << resection_data.vec_inliers.size();
    std::cout << " and MINIMUM_SAMPLES = " << MINIMUM_SAMPLES << std::endl;
  }
#endif

  if (bResection)
  {
    resection_data.projection_matrix = P;
    Mat3 K, R;
    Vec3 t;
    KRt_From_P(P, &K, &R, &t);
    pose = geometry::Pose3(R, -R.transpose() * t);
  }
#ifdef WANTS_POPART_COUT
  std::cout << "\n"
    << "-------------------------------" << "\n"
    << "-- Robust Resection " << "\n"
    << "-- Resection status: " << bResection << "\n"
    << "-- #Points used for Resection: " << resection_data.pt2D.cols() << "\n"
    << "-- #Points validated by robust Resection: " << resection_data.vec_inliers.size() << "\n"
    << "-- Threshold: " << resection_data.error_max << "\n"
    << "-------------------------------" << std::endl;
#endif
  return bResection;
}

bool SfM_Localizer::RefinePose
(
  cameras::IntrinsicBase * intrinsics,
  geometry::Pose3 & pose,
  const Image_Localizer_Match_Data & matching_data,
  bool b_refine_pose,
  bool b_refine_intrinsic
)
{
  // Setup a tiny SfM scene with the corresponding 2D-3D data
  SfM_Data sfm_data;
  // view
  sfm_data.views.insert( std::make_pair(0, std::make_shared<View>("",0, 0, 0)));
  // pose
  sfm_data.poses[0] = pose;
  // intrinsic (the shared_ptr does not take the ownership, will not release the input pointer)
  std::shared_ptr<cameras::IntrinsicBase> localIntrinsics(intrinsics->clone());
  sfm_data.intrinsics[0] = localIntrinsics;
  // structure data (2D-3D correspondences)
  for (size_t i = 0; i < matching_data.vec_inliers.size(); ++i)
  {
    const size_t idx = matching_data.vec_inliers[i];
    Landmark landmark;
    landmark.X = matching_data.pt3D.col(idx);
    landmark.obs[0] = Observation(matching_data.pt2D.col(idx), UndefinedIndexT);
    sfm_data.structure[i] = std::move(landmark);
  }

  Bundle_Adjustment_Ceres bundle_adjustment_obj;
  BA_Refine refineOptions = BA_REFINE_NONE;
  if(b_refine_pose)
    refineOptions |= BA_REFINE_ROTATION | BA_REFINE_TRANSLATION;
  if(b_refine_intrinsic)
    refineOptions |= BA_REFINE_INTRINSICS_ALL;

  const bool b_BA_Status = bundle_adjustment_obj.Adjust(sfm_data, refineOptions);
  if (!b_BA_Status)
    return false;

  pose = sfm_data.poses[0];
  if(b_refine_intrinsic)
    intrinsics->assign(*localIntrinsics);
  return true;
}

} // namespace sfm
} // namespace openMVG
<commit_msg>[sfm] bugfix localize loransac, wrong normalization for threshold<commit_after>
// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/sfm/pipelines/localization/SfM_Localizer.hpp"
#include "openMVG/sfm/sfm_data_BA_ceres.hpp"

#include "openMVG/multiview/solver_resection_kernel.hpp"
#include "openMVG/multiview/solver_resection_p3p.hpp"
#include "openMVG/robust_estimation/robust_estimator_ACRansac.hpp"
#include "openMVG/robust_estimation/robust_estimator_ACRansacKernelAdaptator.hpp"
#include <openMVG/robust_estimation/robust_estimator_LORansac.hpp>
#include <openMVG/robust_estimation/robust_estimator_LORansacKernelAdaptor.hpp>
#include <openMVG/robust_estimation/score_evaluator.hpp>

namespace openMVG {
namespace sfm {

struct ResectionSquaredResidualError
{
  // Compute the residual of the projection distance(pt2D, Project(P,pt3D))
  // Return the squared error
  static double Error(const Mat34 & P, const Vec2 & pt2D, const Vec3 & pt3D)
  {
    const Vec2 x = Project(P, pt3D);
    return (x - pt2D).squaredNorm();
  }
};

bool SfM_Localizer::Localize
(
  const Pair & image_size,
  const cameras::IntrinsicBase * optional_intrinsics,
  Image_Localizer_Match_Data & resection_data,
  geometry::Pose3 & pose,
  robust::EROBUST_ESTIMATOR estimator
)
{
  // --
  // Compute the camera pose (resectioning)
  // --
  Mat34 P;
  resection_data.vec_inliers.clear();

  // Setup the admissible upper bound residual error
  const double dPrecision =
    resection_data.error_max == std::numeric_limits<double>::infinity() ?
    std::numeric_limits<double>::infinity() :
    Square(resection_data.error_max);

  size_t MINIMUM_SAMPLES = 0;
  const cameras::Pinhole_Intrinsic * pinhole_cam = dynamic_cast<const cameras::Pinhole_Intrinsic *>(optional_intrinsics);
  if (pinhole_cam == nullptr || !pinhole_cam->isValid())
  {
    //--
    // Classic resection (try to compute the entire P matrix)
    typedef openMVG::resection::kernel::SixPointResectionSolver SolverType;
    MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;

    typedef openMVG::robust::ACKernelAdaptorResection<
      SolverType, ResectionSquaredResidualError, openMVG::robust::UnnormalizerResection, Mat34>
      KernelType;

    KernelType kernel(resection_data.pt2D, image_size.first, image_size.second,
      resection_data.pt3D);
    // Robust estimation of the Projection matrix and its precision
    const std::pair<double,double> ACRansacOut =
      openMVG::robust::ACRANSAC(kernel, resection_data.vec_inliers, resection_data.max_iteration, &P, dPrecision, true);
    // Update the upper bound precision of the model found by AC-RANSAC
    resection_data.error_max = ACRansacOut.first;
  }
  else
  {
    // undistort the points if the camera has a distortion model
    Mat pt2Dundistorted;
    const bool has_disto = pinhole_cam->have_disto();
    if(has_disto)
    {
      const std::size_t numPts = resection_data.pt2D.cols();
      pt2Dundistorted = Mat2X(2, numPts);
      for(std::size_t iPoint = 0; iPoint < numPts; ++iPoint)
      {
        pt2Dundistorted.col(iPoint) = pinhole_cam->get_ud_pixel(resection_data.pt2D.col(iPoint));
      }
    }

    switch(estimator)
    {
      case robust::ROBUST_ESTIMATOR_ACRANSAC:
      {
        //--
        // Since K calibration matrix is known, compute only [R|t]
        typedef openMVG::euclidean_resection::P3PSolver SolverType;
        MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;

        typedef openMVG::robust::ACKernelAdaptorResection_K<
                SolverType, ResectionSquaredResidualError,
                openMVG::robust::UnnormalizerResection, Mat34> KernelType;

        // otherwise we just pass the input points
        KernelType kernel = KernelType(has_disto ? pt2Dundistorted : resection_data.pt2D, resection_data.pt3D, pinhole_cam->K());

        // Robust estimation of the Projection matrix and its precision
        const std::pair<double, double> ACRansacOut =
                openMVG::robust::ACRANSAC(kernel, resection_data.vec_inliers, resection_data.max_iteration, &P, dPrecision, true);
        // Update the upper bound precision of the model found by AC-RANSAC
        resection_data.error_max = ACRansacOut.first;
        break;
      }

      case robust::ROBUST_ESTIMATOR_LORANSAC:
      {

        // just a safeguard
        if(resection_data.error_max == std::numeric_limits<double>::infinity())
        {
          throw std::invalid_argument("[SfM_Localizer::Localize] the threshold of the LORANSAC is set to infinity!");
        }

        // use the P3P solver for generating the model
        typedef openMVG::euclidean_resection::P3PSolver SolverType;
        MINIMUM_SAMPLES = SolverType::MINIMUM_SAMPLES;
        // use the six point algorithm as Least square solution to refine the model
        typedef openMVG::resection::kernel::SixPointResectionSolver SolverLSType;

        typedef openMVG::robust::KernelAdaptorResectionLORansac_K<SolverType,
                ResectionSquaredResidualError,
                openMVG::robust::UnnormalizerResection,
                SolverLSType,
                Mat34> KernelType;

        // otherwise we just pass the input points
        KernelType kernel = KernelType(has_disto ? pt2Dundistorted : resection_data.pt2D, resection_data.pt3D, pinhole_cam->K());

        // this is just stupid and ugly, the threshold should be always give as pixel
        // value, the scorer should be not aware of the fact that we treat squared errors
        // and normalization inside the kernel
        // @todo refactor, maybe move scorer directly inside the kernel
        const double threshold = resection_data.error_max * resection_data.error_max * (kernel.normalizer2()(0, 0) * kernel.normalizer2()(0, 0));
        robust::ScorerEvaluator<KernelType> scorer(threshold);
        P = robust::LO_RANSAC(kernel, scorer, &resection_data.vec_inliers);
        break;
      }

      default:
        throw std::runtime_error("[SfM_Localizer::Localize] Only ACRansac and LORansac are supported!");
    }
  }

  // Test if the mode support some points (more than those required for estimation)
  const bool bResection = (resection_data.vec_inliers.size() > MINIMUM_SAMPLES * OPENMVG_MINIMUM_SAMPLES_COEF);
#ifdef WANTS_POPART_COUT
  if (!bResection)
  {
    std::cout << "bResection is false";
    std::cout << " because resection_data.vec_inliers.size() = " << resection_data.vec_inliers.size();
    std::cout << " and MINIMUM_SAMPLES = " << MINIMUM_SAMPLES << std::endl;
  }
#endif

  if (bResection)
  {
    resection_data.projection_matrix = P;
    Mat3 K, R;
    Vec3 t;
    KRt_From_P(P, &K, &R, &t);
    pose = geometry::Pose3(R, -R.transpose() * t);
  }
#ifdef WANTS_POPART_COUT
  std::cout << "\n"
    << "-------------------------------" << "\n"
    << "-- Robust Resection " << "\n"
    << "-- Resection status: " << bResection << "\n"
    << "-- #Points used for Resection: " << resection_data.pt2D.cols() << "\n"
    << "-- #Points validated by robust Resection: " << resection_data.vec_inliers.size() << "\n"
    << "-- Threshold: " << resection_data.error_max << "\n"
    << "-------------------------------" << std::endl;
#endif
  return bResection;
}

bool SfM_Localizer::RefinePose
(
  cameras::IntrinsicBase * intrinsics,
  geometry::Pose3 & pose,
  const Image_Localizer_Match_Data & matching_data,
  bool b_refine_pose,
  bool b_refine_intrinsic
)
{
  // Setup a tiny SfM scene with the corresponding 2D-3D data
  SfM_Data sfm_data;
  // view
  sfm_data.views.insert( std::make_pair(0, std::make_shared<View>("",0, 0, 0)));
  // pose
  sfm_data.poses[0] = pose;
  // intrinsic (the shared_ptr does not take the ownership, will not release the input pointer)
  std::shared_ptr<cameras::IntrinsicBase> localIntrinsics(intrinsics->clone());
  sfm_data.intrinsics[0] = localIntrinsics;
  // structure data (2D-3D correspondences)
  for (size_t i = 0; i < matching_data.vec_inliers.size(); ++i)
  {
    const size_t idx = matching_data.vec_inliers[i];
    Landmark landmark;
    landmark.X = matching_data.pt3D.col(idx);
    landmark.obs[0] = Observation(matching_data.pt2D.col(idx), UndefinedIndexT);
    sfm_data.structure[i] = std::move(landmark);
  }

  Bundle_Adjustment_Ceres bundle_adjustment_obj;
  BA_Refine refineOptions = BA_REFINE_NONE;
  if(b_refine_pose)
    refineOptions |= BA_REFINE_ROTATION | BA_REFINE_TRANSLATION;
  if(b_refine_intrinsic)
    refineOptions |= BA_REFINE_INTRINSICS_ALL;

  const bool b_BA_Status = bundle_adjustment_obj.Adjust(sfm_data, refineOptions);
  if (!b_BA_Status)
    return false;

  pose = sfm_data.poses[0];
  if(b_refine_intrinsic)
    intrinsics->assign(*localIntrinsics);
  return true;
}

} // namespace sfm
} // namespace openMVG
<|endoftext|>


<commit_before>//
// logsum -- a port of Sean Eddy's fast table-driven log sum
// This code was originally part of HMMER. This version is used with
// Sean Eddy's permission as public domain code.
//
// Modification Notice
//
//   By: Matei David, Ontario Institute for Cancer Research
//   When: 2015
//   Reason:
//     Reorganized as C++ header-only library,
//     with implicit lookup table initialization.
//

/* p7_FLogsum() function used in the Forward() algorithm.
 *
 * Contents:
 *    1. Floating point log sum.
 *    2. Benchmark driver.
 *    3. Unit tests.
 *    4. Test driver.
 *    5. Example.
 *    6. Copyright and license information.
 *
 * Exegesis:
 *
 * Internally, HMMER3 profile scores are in nats: floating point
 * log-odds probabilities, with the log odds taken relative to
 * background residue frequencies, and the log to the base e.
 *
 * The Forward algorithm needs to calculate sums of probabilities.
 * Given two log probabilities A and B, where s1 = \log
 * \frac{a}{f}, and s2 = \log \frac{b}{g}, we need to
 * calculate C = \log \frac{a + b}{h}.
 *
 * The Forward algorithm guarantees that the null model denominator
 * terms f = g = h, because it is always concerned with summing terms
 * that describe different parses of the same target sequence prefix,
 * and the product of the background frequencies for the same sequence
 * prefix is a constant.
 *
 * The naive solution is C = log(e^{A} + e^{B}), but this requires
 * expensive calls to log() and exp().
 *
 * A better solution is C = A + log(1 + e^{-(A-B)}), for A >= B.  For
 * sufficiently small B << A, e^-{A-B} becomes less than the
 * machine's FLT_EPSILON, and C ~= A. (This is at about (A-B) >
 * -15.9, for the typical FLT_EPSILON of 1.2e-7.)
 *
 * With some loss of accuracy [1], we can precalculate log(1 +
 * e^{-(A-B)}) for a discretized range of differences (A-B), and
 * compute C = A + table_lookup(A-B). This is what HMMER's
 * p7_FLogsum() function does.
 *
 * This only applies to the generic (serial) implementation.
 * See footnote [2] for discussion of why we remain unable to
 * implement an efficient log-space SIMD vector implementation of
 * Forward.
 */

#ifndef __LOGSUM_HPP
#define __LOGSUM_HPP

#include <cassert>
#include <cmath>

/* p7_LOGSUM_SCALE defines the precision of the calculation; the
 * default of 1000.0 means rounding differences to the nearest 0.001
 * nat. p7_LOGSUM_TBL defines the size of the lookup table; the
 * default of 16000 means entries are calculated for differences of 0
 * to 16.000 nats (when p7_LOGSUM_SCALE is 1000.0).  e^{-p7_LOGSUM_TBL /
 * p7_LOGSUM_SCALE} should be on the order of the machine FLT_EPSILON,
 * typically 1.2e-7.
 */
#define p7_LOGSUM_TBL   16000
#define p7_LOGSUM_SCALE 1000.f
#define ESL_MAX(a,b)    (((a)>(b))?(a):(b))
#define ESL_MIN(a,b)    (((a)<(b))?(a):(b))
#define eslINFINITY     INFINITY
#define TRUE            1
#define FALSE           0
#define eslOK           1

namespace logsum
{

struct p7_FLogsum_Helper
{
    /* Function:  flogsum_lookup()
     * Synposis:  Holds the main lookup table used in logspace sum computations.
     *
     * Purpose:   Encapsulate static array inside a function to avoid the need for a separate definition.
     */
    static inline float*
    flogsum_lookup(void)
    {
        static float _flogsum_lookup[p7_LOGSUM_TBL]; /* p7_LOGSUM_TBL=16000: (A-B) = 0..16 nats, steps of 0.001 */
        return _flogsum_lookup;
    }

    /* Function:  p7_FLogsumInit()
     * Synopsis:  Initialize the p7_Logsum() function.
     *
     * Purpose:   Initialize the lookup table for <p7_FLogsum()>.
     *            This function must be called once before any
     *            call to <p7_FLogsum()>.
     *
     *            The precision of the lookup table is determined
     *            by the compile-time <p7_LOGSUM_TBL> constant.
     *
     * Returns:   <eslOK> on success.
     */
    static int
    p7_FLogsumInit(void)
    {
        static int firsttime = TRUE;
        if (!firsttime) return eslOK;
        firsttime = FALSE;

        int i;
        for (i = 0; i < p7_LOGSUM_TBL; i++)
        {
            flogsum_lookup()[i] = std::log(1. + std::exp((double) -i / p7_LOGSUM_SCALE));
        }

        return eslOK;
    }

    /* Function:  p7_FLogsum()
     * Synopsis:  Approximate $\log(e^a + e^b)$.
     *
     * Purpose:   Returns a fast table-driven approximation to
     *            $\log(e^a + e^b)$.
     *
     *            Either <a> or <b> (or both) may be $-\infty$,
     *            but neither may be $+\infty$ or <NaN>.
     *
     * Note:      This function is a critical optimization target, because
     *            it's in the inner loop of generic Forward() algorithms.
     */
    static inline float
    p7_FLogsum(float a, float b)
    {
        // static object whose constructor initializes the lookup table
        static Table_Initializer _init;

        const float max = ESL_MAX(a, b);
        const float min = ESL_MIN(a, b);

        return (min == -eslINFINITY || (max-min) >= 15.7f)
            ? max
            : max + flogsum_lookup()[(int)((max-min)*p7_LOGSUM_SCALE)];
    }

    /* Function:  p7_FLogsumError()
     * Synopsis:  Compute absolute error in probability from Logsum.
     *
     * Purpose:   Compute the absolute error in probability space
     *            resulting from <p7_FLogsum()>'s table lookup
     *            approximation: approximation result - exact result.
     *
     *            This is of course computable analytically for
     *            any <a,b> given <p7_LOGSUM_TBL>; but the function
     *            is useful for some routines that want to determine
     *            if <p7_FLogsum()> has been compiled in its
     *            exact slow mode for debugging purposes. Testing
     *            <p7_FLogsumError(-0.4, -0.5) > 0.0001>
     *            for example, suffices to detect that the function
     *            is compiled in its fast approximation mode given
     *            the defaults.
     */
    static float
    p7_FLogsumError(float a, float b)
    {
        float approx = p7_FLogsum(a,b);
        float exact  = std::log(std::exp(a) + std::exp(b));
        return (std::exp(approx) - std::exp(exact));
    }

    /* Struct:  Table_Initializer
     * Purpose: Initialize the lookup table on construction.
     *
     */
    struct Table_Initializer
    {
        Table_Initializer()
        {
            p7_FLogsumInit();
        }
    }; // struct Table_Initializer
}; // struct p7_FLogsum_Helper

/*
 * Publish main methods outside of the helper struct.
 */
inline float p7_FLogsum(float a, float b) { return p7_FLogsum_Helper::p7_FLogsum(a, b); }
inline float p7_FLogsumError(float a, float b) { return p7_FLogsum_Helper::p7_FLogsumError(a, b); }

} // namespace logsum

#endif

#ifdef SAMPLE_p7LOGSUM

/*

g++ -std=c++11 -DSAMPLE_p7LOGSUM -x c++ logsum.hpp -o sample-logsum

*/

#include <iostream>
#include <sstream>

using namespace std;
using namespace logsum;

int main(int argc, char* argv[])
{
    if (argc != 3)
    {
        cerr << "use: " << argv[0] << " <a> <b>" << endl;
        return EXIT_FAILURE;
    }

    float a;
    float b;
    float result;

    istringstream(argv[1]) >> a;
    istringstream(argv[2]) >> b;

    result = p7_FLogsum(a, b);
    cout << "p7_FLogsum(" << a << ", " << b << ") = " << result << endl;

    result = log(exp(a) + exp(b));
    cout << "log(exp(" << a << ") + exp(" << b << ")) = " << result << endl;

    cout << "Absolute error in probability: " << p7_FLogsumError(a, b) << endl;
}

#endif

#ifdef BENCHMARK_p7LOGSUM

/*

Compare with the original logsum.{h,cpp} (not included in this repo).
Assuming they are in /somedir.

Compile:
DIR=/somedir; g++ -std=c++11 -DBENCHMARK_p7LOGSUM -x c++ -I${DIR} logsum.hpp ${DIR}/logsum.cpp -o benchmark-logsum

Run:
./benchmark-logsum 42 0
./benchmark-logsum 42 1

*/

#include <chrono>
#include <iostream>
#include <random>
#include <set>
#include <sstream>
#include <vector>

#include "logsum.h"

using namespace std;

int main(int argc, char* argv[])
{
    if (argc < 3)
    {
        cerr << "use: " << argv[0] << " <seed> <version>" << endl
             << "where <version> is 0 for old, 1 for new" << endl;
        return EXIT_FAILURE;
    }
    size_t seed = 0;
    unsigned version = 0;
    istringstream(argv[1]) >> seed;
    istringstream(argv[2]) >> version;
    if (seed == 0)
    {
        seed = chrono::high_resolution_clock::now().time_since_epoch().count();
    }
    clog << "seed: " << seed << endl;
    clog << "version: " << version << endl;
    const unsigned n = 1000000;
    set< float > s;
    mt19937 rg(seed);
    uniform_real_distribution< float > unif;
    for (unsigned i = 0; i < n; ++i)
    {
        s.insert(unif(rg));
    }
    p7_FLogsumInit();

    // start timer
    auto start_time = chrono::high_resolution_clock::now();

    if (version == 0)
    {
        while (s.size() > 1)
        {
            float a = *s.begin();
            s.erase(s.begin());
            float b = *s.begin();
            s.erase(s.begin());
            s.insert(::p7_FLogsum(a, b));
        }
    }
    else if (version == 1)
    {
        while (s.size() > 1)
        {
            float a = *s.begin();
            s.erase(s.begin());
            float b = *s.begin();
            s.erase(s.begin());
            s.insert(logsum::p7_FLogsum(a, b));
        }
    }

    // end timer
    auto end_time = chrono::high_resolution_clock::now();

    cout << "time: " << chrono::duration_cast< chrono::milliseconds >(end_time - start_time).count() << endl
         << "result: " << *s.begin() << endl;
}

#endif
<commit_msg>force initializer to be marked as used<commit_after>//
// logsum -- a port of Sean Eddy's fast table-driven log sum
// This code was originally part of HMMER. This version is used with
// Sean Eddy's permission as public domain code.
//
// Modification Notice
//
//   By: Matei David, Ontario Institute for Cancer Research
//   When: 2015
//   Reason:
//     Reorganized as C++ header-only library,
//     with implicit lookup table initialization.
//

/* p7_FLogsum() function used in the Forward() algorithm.
 *
 * Contents:
 *    1. Floating point log sum.
 *    2. Benchmark driver.
 *    3. Unit tests.
 *    4. Test driver.
 *    5. Example.
 *    6. Copyright and license information.
 *
 * Exegesis:
 *
 * Internally, HMMER3 profile scores are in nats: floating point
 * log-odds probabilities, with the log odds taken relative to
 * background residue frequencies, and the log to the base e.
 *
 * The Forward algorithm needs to calculate sums of probabilities.
 * Given two log probabilities A and B, where s1 = \log
 * \frac{a}{f}, and s2 = \log \frac{b}{g}, we need to
 * calculate C = \log \frac{a + b}{h}.
 *
 * The Forward algorithm guarantees that the null model denominator
 * terms f = g = h, because it is always concerned with summing terms
 * that describe different parses of the same target sequence prefix,
 * and the product of the background frequencies for the same sequence
 * prefix is a constant.
 *
 * The naive solution is C = log(e^{A} + e^{B}), but this requires
 * expensive calls to log() and exp().
 *
 * A better solution is C = A + log(1 + e^{-(A-B)}), for A >= B.  For
 * sufficiently small B << A, e^-{A-B} becomes less than the
 * machine's FLT_EPSILON, and C ~= A. (This is at about (A-B) >
 * -15.9, for the typical FLT_EPSILON of 1.2e-7.)
 *
 * With some loss of accuracy [1], we can precalculate log(1 +
 * e^{-(A-B)}) for a discretized range of differences (A-B), and
 * compute C = A + table_lookup(A-B). This is what HMMER's
 * p7_FLogsum() function does.
 *
 * This only applies to the generic (serial) implementation.
 * See footnote [2] for discussion of why we remain unable to
 * implement an efficient log-space SIMD vector implementation of
 * Forward.
 */

#ifndef __LOGSUM_HPP
#define __LOGSUM_HPP

#include <cassert>
#include <cmath>

/* p7_LOGSUM_SCALE defines the precision of the calculation; the
 * default of 1000.0 means rounding differences to the nearest 0.001
 * nat. p7_LOGSUM_TBL defines the size of the lookup table; the
 * default of 16000 means entries are calculated for differences of 0
 * to 16.000 nats (when p7_LOGSUM_SCALE is 1000.0).  e^{-p7_LOGSUM_TBL /
 * p7_LOGSUM_SCALE} should be on the order of the machine FLT_EPSILON,
 * typically 1.2e-7.
 */
#define p7_LOGSUM_TBL   16000
#define p7_LOGSUM_SCALE 1000.f
#define ESL_MAX(a,b)    (((a)>(b))?(a):(b))
#define ESL_MIN(a,b)    (((a)<(b))?(a):(b))
#define eslINFINITY     INFINITY
#define TRUE            1
#define FALSE           0
#define eslOK           1

namespace logsum
{

struct p7_FLogsum_Helper
{
    /* Function:  flogsum_lookup()
     * Synposis:  Holds the main lookup table used in logspace sum computations.
     *
     * Purpose:   Encapsulate static array inside a function to avoid the need for a separate definition.
     */
    static inline float*
    flogsum_lookup(void)
    {
        static float _flogsum_lookup[p7_LOGSUM_TBL]; /* p7_LOGSUM_TBL=16000: (A-B) = 0..16 nats, steps of 0.001 */
        return _flogsum_lookup;
    }

    /* Function:  p7_FLogsumInit()
     * Synopsis:  Initialize the p7_Logsum() function.
     *
     * Purpose:   Initialize the lookup table for <p7_FLogsum()>.
     *            This function must be called once before any
     *            call to <p7_FLogsum()>.
     *
     *            The precision of the lookup table is determined
     *            by the compile-time <p7_LOGSUM_TBL> constant.
     *
     * Returns:   <eslOK> on success.
     */
    static int
    p7_FLogsumInit(void)
    {
        static int firsttime = TRUE;
        if (!firsttime) return eslOK;
        firsttime = FALSE;

        int i;
        for (i = 0; i < p7_LOGSUM_TBL; i++)
        {
            flogsum_lookup()[i] = std::log(1. + std::exp((double) -i / p7_LOGSUM_SCALE));
        }

        return eslOK;
    }

    /* Function:  p7_FLogsum()
     * Synopsis:  Approximate $\log(e^a + e^b)$.
     *
     * Purpose:   Returns a fast table-driven approximation to
     *            $\log(e^a + e^b)$.
     *
     *            Either <a> or <b> (or both) may be $-\infty$,
     *            but neither may be $+\infty$ or <NaN>.
     *
     * Note:      This function is a critical optimization target, because
     *            it's in the inner loop of generic Forward() algorithms.
     */
    static inline float
    p7_FLogsum(float a, float b)
    {
        // static object whose constructor initializes the lookup table
        static Table_Initializer _init;
        (void)_init;

        const float max = ESL_MAX(a, b);
        const float min = ESL_MIN(a, b);

        return (min == -eslINFINITY || (max-min) >= 15.7f)
            ? max
            : max + flogsum_lookup()[(int)((max-min)*p7_LOGSUM_SCALE)];
    }

    /* Function:  p7_FLogsumError()
     * Synopsis:  Compute absolute error in probability from Logsum.
     *
     * Purpose:   Compute the absolute error in probability space
     *            resulting from <p7_FLogsum()>'s table lookup
     *            approximation: approximation result - exact result.
     *
     *            This is of course computable analytically for
     *            any <a,b> given <p7_LOGSUM_TBL>; but the function
     *            is useful for some routines that want to determine
     *            if <p7_FLogsum()> has been compiled in its
     *            exact slow mode for debugging purposes. Testing
     *            <p7_FLogsumError(-0.4, -0.5) > 0.0001>
     *            for example, suffices to detect that the function
     *            is compiled in its fast approximation mode given
     *            the defaults.
     */
    static float
    p7_FLogsumError(float a, float b)
    {
        float approx = p7_FLogsum(a,b);
        float exact  = std::log(std::exp(a) + std::exp(b));
        return (std::exp(approx) - std::exp(exact));
    }

    /* Struct:  Table_Initializer
     * Purpose: Initialize the lookup table on construction.
     *
     */
    struct Table_Initializer
    {
        Table_Initializer()
        {
            p7_FLogsumInit();
        }
    }; // struct Table_Initializer
}; // struct p7_FLogsum_Helper

/*
 * Publish main methods outside of the helper struct.
 */
inline float p7_FLogsum(float a, float b) { return p7_FLogsum_Helper::p7_FLogsum(a, b); }
inline float p7_FLogsumError(float a, float b) { return p7_FLogsum_Helper::p7_FLogsumError(a, b); }

} // namespace logsum

#endif

#ifdef SAMPLE_p7LOGSUM

/*

g++ -std=c++11 -DSAMPLE_p7LOGSUM -x c++ logsum.hpp -o sample-logsum

*/

#include <iostream>
#include <sstream>

using namespace std;
using namespace logsum;

int main(int argc, char* argv[])
{
    if (argc != 3)
    {
        cerr << "use: " << argv[0] << " <a> <b>" << endl;
        return EXIT_FAILURE;
    }

    float a;
    float b;
    float result;

    istringstream(argv[1]) >> a;
    istringstream(argv[2]) >> b;

    result = p7_FLogsum(a, b);
    cout << "p7_FLogsum(" << a << ", " << b << ") = " << result << endl;

    result = log(exp(a) + exp(b));
    cout << "log(exp(" << a << ") + exp(" << b << ")) = " << result << endl;

    cout << "Absolute error in probability: " << p7_FLogsumError(a, b) << endl;
}

#endif

#ifdef BENCHMARK_p7LOGSUM

/*

Compare with the original logsum.{h,cpp} (not included in this repo).
Assuming they are in /somedir.

Compile:
DIR=/somedir; g++ -std=c++11 -DBENCHMARK_p7LOGSUM -x c++ -I${DIR} logsum.hpp ${DIR}/logsum.cpp -o benchmark-logsum

Run:
./benchmark-logsum 42 0
./benchmark-logsum 42 1

*/

#include <chrono>
#include <iostream>
#include <random>
#include <set>
#include <sstream>
#include <vector>

#include "logsum.h"

using namespace std;

int main(int argc, char* argv[])
{
    if (argc < 3)
    {
        cerr << "use: " << argv[0] << " <seed> <version>" << endl
             << "where <version> is 0 for old, 1 for new" << endl;
        return EXIT_FAILURE;
    }
    size_t seed = 0;
    unsigned version = 0;
    istringstream(argv[1]) >> seed;
    istringstream(argv[2]) >> version;
    if (seed == 0)
    {
        seed = chrono::high_resolution_clock::now().time_since_epoch().count();
    }
    clog << "seed: " << seed << endl;
    clog << "version: " << version << endl;
    const unsigned n = 1000000;
    set< float > s;
    mt19937 rg(seed);
    uniform_real_distribution< float > unif;
    for (unsigned i = 0; i < n; ++i)
    {
        s.insert(unif(rg));
    }
    p7_FLogsumInit();

    // start timer
    auto start_time = chrono::high_resolution_clock::now();

    if (version == 0)
    {
        while (s.size() > 1)
        {
            float a = *s.begin();
            s.erase(s.begin());
            float b = *s.begin();
            s.erase(s.begin());
            s.insert(::p7_FLogsum(a, b));
        }
    }
    else if (version == 1)
    {
        while (s.size() > 1)
        {
            float a = *s.begin();
            s.erase(s.begin());
            float b = *s.begin();
            s.erase(s.begin());
            s.insert(logsum::p7_FLogsum(a, b));
        }
    }

    // end timer
    auto end_time = chrono::high_resolution_clock::now();

    cout << "time: " << chrono::duration_cast< chrono::milliseconds >(end_time - start_time).count() << endl
         << "result: " << *s.begin() << endl;
}

#endif
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//	Copyright (c) 2012, Guido Pola.
//
//	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.
//
//	File Name:		MainWindow.cpp
//	Authors:		Guido Pola <prodito@live.com>
//	Description:
//------------------------------------------------------------------------------

#include "Torrentor.h"
#include "TorrentorMessages.h"

#include <Autolock.h>
#include <Application.h>
#include <MenuBar.h>
#include <Menu.h>
#include <MenuItem.h>

#include <StatusBar.h>
#include <StringView.h>
#include <ScrollView.h>

#include <Notification.h>
#include <Roster.h>

#include <ListView.h>
#include <ListItem.h>

#include <assert.h>

#include "MainWindow.h"

#include "ToolBar.h"

#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>

#include <ControlLook.h>

#include "TorrentRefFilter.h"

#include <SpaceLayoutItem.h>

#include "IconView.h"
#include "DownloadView.h"
#include "DownloadItem.h"

#include "InfoWindow.h"

#include "PreferencesWindow.h"

#include <Alert.h>

enum
{
	MENU_FILE_OPEN_TORRENT		= 0x400000,
	MENU_FILE_OPEN_TORRENT_URL,
	MENU_EDIT_PREFERENCES,
	MENU_TORRENT_INSPECT,
	MENU_TORRENT_OPEN_DOWNLOAD,
	MENU_TORRENT_REMOVE,
};

MainWindow::MainWindow(BRect frame)
	: BWindow(frame, "Torrentor!", B_DOCUMENT_WINDOW,
			  B_AUTO_UPDATE_SIZE_LIMITS |
			  B_ASYNCHRONOUS_CONTROLS |
			  B_NOT_ZOOMABLE )
{
	SetPulseRate(1000000);

	//
	//
	//
	SetLayout(new BGroupLayout(B_VERTICAL, 0.0));

	CreateMenuBar();

	fDownloadView 	= new DownloadView;

//	BStringView* fStatusText = new BStringView("status", "Laralala");
//	fStatusText->SetAlignment(B_ALIGN_LEFT);
//	fStatusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
///	fStatusText->SetExplicitMinSize(BSize(150, 12));

	AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0)
		.Add(fMenuBar)
		.Add(fDownloadView->ScrollView())
/*
		.Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
		.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
			.AddGlue()
			.Add(fRemoveMissingButton)
			.Add(fRemoveFinishedButton)
			.SetInsets(12, 5, 12, 5)
		)*/
	);

	//
	//
	//
	fOpenPanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, B_FILE_NODE, true, NULL,
								new TorrentRefFilter);

	//
	//
	//
	fPreferencesWindow = new PreferencesWindow();

	//
	CenterOnScreen();
}

MainWindow::~MainWindow()
{
	fPreferencesWindow->Lock();
	fPreferencesWindow->QuitRequested();
	fPreferencesWindow->Quit();

	delete fPreferencesWindow;
	delete fOpenPanel;
}

void MainWindow::InitWindow()
{
}

//
//	File ->
//			- Open Torrent
//			- Open From URL
//			---------------
//			- Pause all torrents
//			- Resume all torrents
//			---------------
//			Quit
//	---------------------------------
//	Edit ->
//			-
//
//	---------------------------------
//
void MainWindow::CreateMenuBar()
{
	//
	//
	//
	fMenuBar = new BMenuBar(BRect(0, 0, 0, 0), "MainMenuBar");

	BMenu* menu = new BMenu("File");

	//
	//
	//
	//menu->AddItem(new BMenuItem("New Torrent", NULL));
	menu->AddItem(new BMenuItem("Open Torrent", new BMessage(MENU_FILE_OPEN_TORRENT)));
	menu->AddItem(new BMenuItem("Opem From Magnet", new BMessage(MENU_FILE_OPEN_TORRENT_URL)));
	menu->AddItem(new BSeparatorItem);
	menu->AddItem(new BMenuItem("Start All Torrents", NULL));
	menu->AddItem(new BMenuItem("Pause All Torrent", NULL));
	menu->AddItem(new BSeparatorItem);
	menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED)));

	//menu->AddItem(new BMenuItem("Open" B_UTF8_ELLIPSIS, new BMessage(MENU_FILE_OPEN), 'O'));

	//
	//
	//
	fMenuBar->AddItem(menu);

	//
	//
	//
	menu = new BMenu("Edit");
	menu->AddItem(new BMenuItem("Select All", NULL));
	menu->AddItem(new BMenuItem("Deselect All", NULL));
	menu->AddItem(new BSeparatorItem);
	menu->AddItem(new BMenuItem("Preferences", new BMessage(MENU_EDIT_PREFERENCES)));
/*
	//
	//
	//
	BMenuItem* item = new BMenuItem("Preferences", new BMessage(MENU_EDIT_PREFERENCES));

	item->SetTarget(be_app);

	menu->AddItem(item);
*/
	fMenuBar->AddItem(menu);

	//
	//
	//
	menu = new BMenu("Torrent");
	menu->AddItem(new BMenuItem("Inspect", new BMessage(MENU_TORRENT_INSPECT)));
	menu->AddItem(new BMenuItem("Open download folder", new BMessage(MENU_TORRENT_OPEN_DOWNLOAD)));
	menu->AddItem(new BSeparatorItem);
	menu->AddItem(new BMenuItem("Remove", new BMessage(MENU_TORRENT_REMOVE)));
	//menu->AddItem(new BMenuItem("Select All", NULL));

	fMenuBar->AddItem(menu);

	//
	//
	//
	menu = new BMenu("View");

	fMenuBar->AddItem(menu);

	//
	//
	//
	menu = new BMenu("Help");

	fMenuBar->AddItem(menu);
}

void MainWindow::MessageReceived(BMessage* message)
{
	switch( message->what )
	{
	case MENU_FILE_OPEN_TORRENT:
		fOpenPanel->Show();
		break;
	case MENU_FILE_OPEN_TORRENT_URL:
		be_app->PostMessage(MSG_OPEN_MAGNET_REQUEST);
		break;
	case MENU_EDIT_PREFERENCES:
		OpenPreferencesWindow();
		break;
	case MENU_TORRENT_INSPECT:
		OnTorrentInspect();
		break;
	case MENU_TORRENT_OPEN_DOWNLOAD:
		OpenTorrentDownloadFolder();
		break;
	case MENU_TORRENT_REMOVE:
		OnMenuTorrentRemove();
		break;
	default:
		BWindow::MessageReceived(message);
		break;
	}
}

bool MainWindow::QuitRequested()
{
	be_app->PostMessage(B_QUIT_REQUESTED);
	return(true);
}

void MainWindow::OnTorrentInspect()
{

	if( const DownloadItem* item = fDownloadView->ItemSelected() )
	{
		//
		// Get the torrent object.
		//
		const TorrentObject* torrent = item->GetTorrentObject();

		//
		// @TODO: check if inspect window is already created.
		//
		InfoWindow* window = new InfoWindow(torrent);

		window->Show();
	}
}

void MainWindow::OpenPreferencesWindow()
{
//	BAutolock _Lock(fPreferencesWindow);

	if (fPreferencesWindow->IsHidden())
		fPreferencesWindow->Show();
	else
		fPreferencesWindow->Activate();
}

void MainWindow::OpenTorrentDownloadFolder()
{

	entry_ref ref;

	if( const DownloadItem* item = fDownloadView->ItemSelected() )
	{
		//
		// Get the torrent object.
		//
		const TorrentObject* torrent = item->GetTorrentObject();

		//
		// Build the download path.
		//
		BString DownloadPath = torrent->DownloadFolder();

		//
		//
		//
		if( torrent->IsFolder() )
		{
			BString FolderName = torrent->Info()->files[ 0 ].name;

			FolderName.Truncate(FolderName.FindFirst('/'));

			DownloadPath << "/" << FolderName;
		}

		status_t status = get_ref_for_path(DownloadPath.String(), &ref);
		if (status == B_OK)
			status = be_roster->Launch(&ref);
	}

/*const char* kTrackerSignature = "application/x-vnd.Be-TRAK";

	if( const DownloadItem* item = fDownloadView->ItemSelected() )
	{
		const TorrentObject* torrent = item->GetTorrentObject();

		entry_ref ref;
		status_t status = get_ref_for_path(torrent->GetDownloadDir(), &ref);

		if( status == B_OK )
		{
			BMessage message(B_REFS_RECEIVED);
			message.AddRef("refs", &ref);

			BMessenger messenger(kTrackerSignature);
			messenger.SendMessage(&message);

		}
	}
*/
}

void MainWindow::OnMenuTorrentRemove()
{
	//
	//
	//
	if( const DownloadItem* selectedItem = fDownloadView->ItemSelected() )
	{
		//
		// Ask if the user want to delete local data or the torrent only.
		//
		BAlert* alert = new BAlert("Remove torrent", "Remove the selected torrent?",
    						"Cancel", "Remove torrent only", "Remove with data",
    						B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT);

    	int32 buttonIndex 	= alert->Go();
    	bool removeData 	= buttonIndex == 2;

		//
		// Return if the user press cancel.
		//
		if( buttonIndex == 0 )
			return;

		//
		//
		//
		fDownloadView->RemoveItem(selectedItem);

		//
		//
		//
		selectedItem->GetTorrentObject()->Remove(removeData);
	}
}

void MainWindow::Update()
{
//	if( fListView->LockLooper() )
//	{
//		fListView->Invalidate();
//		fListView->UnlockLooper();
//	}
}

void MainWindow::AddTorrent(TorrentObject* torrentObject)
{
	torrentObject->Update();

	//
	// @TODO: fDownloadView->AddItem(torrentObject);
	//
	fDownloadView->AddItem(torrentObject);
}
<commit_msg>Typo in File menu<commit_after>//------------------------------------------------------------------------------
//	Copyright (c) 2012, Guido Pola.
//
//	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.
//
//	File Name:		MainWindow.cpp
//	Authors:		Guido Pola <prodito@live.com>
//	Description:
//------------------------------------------------------------------------------

#include "Torrentor.h"
#include "TorrentorMessages.h"

#include <Autolock.h>
#include <Application.h>
#include <MenuBar.h>
#include <Menu.h>
#include <MenuItem.h>

#include <StatusBar.h>
#include <StringView.h>
#include <ScrollView.h>

#include <Notification.h>
#include <Roster.h>

#include <ListView.h>
#include <ListItem.h>

#include <assert.h>

#include "MainWindow.h"

#include "ToolBar.h"

#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>

#include <ControlLook.h>

#include "TorrentRefFilter.h"

#include <SpaceLayoutItem.h>

#include "IconView.h"
#include "DownloadView.h"
#include "DownloadItem.h"

#include "InfoWindow.h"

#include "PreferencesWindow.h"

#include <Alert.h>

enum
{
	MENU_FILE_OPEN_TORRENT		= 0x400000,
	MENU_FILE_OPEN_TORRENT_URL,
	MENU_EDIT_PREFERENCES,
	MENU_TORRENT_INSPECT,
	MENU_TORRENT_OPEN_DOWNLOAD,
	MENU_TORRENT_REMOVE,
};

MainWindow::MainWindow(BRect frame)
	: BWindow(frame, "Torrentor!", B_DOCUMENT_WINDOW,
			  B_AUTO_UPDATE_SIZE_LIMITS |
			  B_ASYNCHRONOUS_CONTROLS |
			  B_NOT_ZOOMABLE )
{
	SetPulseRate(1000000);

	//
	//
	//
	SetLayout(new BGroupLayout(B_VERTICAL, 0.0));

	CreateMenuBar();

	fDownloadView 	= new DownloadView;

//	BStringView* fStatusText = new BStringView("status", "Laralala");
//	fStatusText->SetAlignment(B_ALIGN_LEFT);
//	fStatusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
///	fStatusText->SetExplicitMinSize(BSize(150, 12));

	AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0)
		.Add(fMenuBar)
		.Add(fDownloadView->ScrollView())
/*
		.Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
		.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
			.AddGlue()
			.Add(fRemoveMissingButton)
			.Add(fRemoveFinishedButton)
			.SetInsets(12, 5, 12, 5)
		)*/
	);

	//
	//
	//
	fOpenPanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, B_FILE_NODE, true, NULL,
								new TorrentRefFilter);

	//
	//
	//
	fPreferencesWindow = new PreferencesWindow();

	//
	CenterOnScreen();
}

MainWindow::~MainWindow()
{
	fPreferencesWindow->Lock();
	fPreferencesWindow->QuitRequested();
	fPreferencesWindow->Quit();

	delete fPreferencesWindow;
	delete fOpenPanel;
}

void MainWindow::InitWindow()
{
}

//
//	File ->
//			- Open Torrent
//			- Open From URL
//			---------------
//			- Pause all torrents
//			- Resume all torrents
//			---------------
//			Quit
//	---------------------------------
//	Edit ->
//			-
//
//	---------------------------------
//
void MainWindow::CreateMenuBar()
{
	//
	//
	//
	fMenuBar = new BMenuBar(BRect(0, 0, 0, 0), "MainMenuBar");

	BMenu* menu = new BMenu("File");

	//
	//
	//
	//menu->AddItem(new BMenuItem("New Torrent", NULL));
	menu->AddItem(new BMenuItem("Open Torrent", new BMessage(MENU_FILE_OPEN_TORRENT)));
	menu->AddItem(new BMenuItem("Open From Magnet", new BMessage(MENU_FILE_OPEN_TORRENT_URL)));
	menu->AddItem(new BSeparatorItem);
	menu->AddItem(new BMenuItem("Start All Torrents", NULL));
	menu->AddItem(new BMenuItem("Pause All Torrent", NULL));
	menu->AddItem(new BSeparatorItem);
	menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED)));

	//menu->AddItem(new BMenuItem("Open" B_UTF8_ELLIPSIS, new BMessage(MENU_FILE_OPEN), 'O'));

	//
	//
	//
	fMenuBar->AddItem(menu);

	//
	//
	//
	menu = new BMenu("Edit");
	menu->AddItem(new BMenuItem("Select All", NULL));
	menu->AddItem(new BMenuItem("Deselect All", NULL));
	menu->AddItem(new BSeparatorItem);
	menu->AddItem(new BMenuItem("Preferences", new BMessage(MENU_EDIT_PREFERENCES)));
/*
	//
	//
	//
	BMenuItem* item = new BMenuItem("Preferences", new BMessage(MENU_EDIT_PREFERENCES));

	item->SetTarget(be_app);

	menu->AddItem(item);
*/
	fMenuBar->AddItem(menu);

	//
	//
	//
	menu = new BMenu("Torrent");
	menu->AddItem(new BMenuItem("Inspect", new BMessage(MENU_TORRENT_INSPECT)));
	menu->AddItem(new BMenuItem("Open download folder", new BMessage(MENU_TORRENT_OPEN_DOWNLOAD)));
	menu->AddItem(new BSeparatorItem);
	menu->AddItem(new BMenuItem("Remove", new BMessage(MENU_TORRENT_REMOVE)));
	//menu->AddItem(new BMenuItem("Select All", NULL));

	fMenuBar->AddItem(menu);

	//
	//
	//
	menu = new BMenu("View");

	fMenuBar->AddItem(menu);

	//
	//
	//
	menu = new BMenu("Help");

	fMenuBar->AddItem(menu);
}

void MainWindow::MessageReceived(BMessage* message)
{
	switch( message->what )
	{
	case MENU_FILE_OPEN_TORRENT:
		fOpenPanel->Show();
		break;
	case MENU_FILE_OPEN_TORRENT_URL:
		be_app->PostMessage(MSG_OPEN_MAGNET_REQUEST);
		break;
	case MENU_EDIT_PREFERENCES:
		OpenPreferencesWindow();
		break;
	case MENU_TORRENT_INSPECT:
		OnTorrentInspect();
		break;
	case MENU_TORRENT_OPEN_DOWNLOAD:
		OpenTorrentDownloadFolder();
		break;
	case MENU_TORRENT_REMOVE:
		OnMenuTorrentRemove();
		break;
	default:
		BWindow::MessageReceived(message);
		break;
	}
}

bool MainWindow::QuitRequested()
{
	be_app->PostMessage(B_QUIT_REQUESTED);
	return(true);
}

void MainWindow::OnTorrentInspect()
{

	if( const DownloadItem* item = fDownloadView->ItemSelected() )
	{
		//
		// Get the torrent object.
		//
		const TorrentObject* torrent = item->GetTorrentObject();

		//
		// @TODO: check if inspect window is already created.
		//
		InfoWindow* window = new InfoWindow(torrent);

		window->Show();
	}
}

void MainWindow::OpenPreferencesWindow()
{
//	BAutolock _Lock(fPreferencesWindow);

	if (fPreferencesWindow->IsHidden())
		fPreferencesWindow->Show();
	else
		fPreferencesWindow->Activate();
}

void MainWindow::OpenTorrentDownloadFolder()
{

	entry_ref ref;

	if( const DownloadItem* item = fDownloadView->ItemSelected() )
	{
		//
		// Get the torrent object.
		//
		const TorrentObject* torrent = item->GetTorrentObject();

		//
		// Build the download path.
		//
		BString DownloadPath = torrent->DownloadFolder();

		//
		//
		//
		if( torrent->IsFolder() )
		{
			BString FolderName = torrent->Info()->files[ 0 ].name;

			FolderName.Truncate(FolderName.FindFirst('/'));

			DownloadPath << "/" << FolderName;
		}

		status_t status = get_ref_for_path(DownloadPath.String(), &ref);
		if (status == B_OK)
			status = be_roster->Launch(&ref);
	}

/*const char* kTrackerSignature = "application/x-vnd.Be-TRAK";

	if( const DownloadItem* item = fDownloadView->ItemSelected() )
	{
		const TorrentObject* torrent = item->GetTorrentObject();

		entry_ref ref;
		status_t status = get_ref_for_path(torrent->GetDownloadDir(), &ref);

		if( status == B_OK )
		{
			BMessage message(B_REFS_RECEIVED);
			message.AddRef("refs", &ref);

			BMessenger messenger(kTrackerSignature);
			messenger.SendMessage(&message);

		}
	}
*/
}

void MainWindow::OnMenuTorrentRemove()
{
	//
	//
	//
	if( const DownloadItem* selectedItem = fDownloadView->ItemSelected() )
	{
		//
		// Ask if the user want to delete local data or the torrent only.
		//
		BAlert* alert = new BAlert("Remove torrent", "Remove the selected torrent?",
    						"Cancel", "Remove torrent only", "Remove with data",
    						B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT);

    	int32 buttonIndex 	= alert->Go();
    	bool removeData 	= buttonIndex == 2;

		//
		// Return if the user press cancel.
		//
		if( buttonIndex == 0 )
			return;

		//
		//
		//
		fDownloadView->RemoveItem(selectedItem);

		//
		//
		//
		selectedItem->GetTorrentObject()->Remove(removeData);
	}
}

void MainWindow::Update()
{
//	if( fListView->LockLooper() )
//	{
//		fListView->Invalidate();
//		fListView->UnlockLooper();
//	}
}

void MainWindow::AddTorrent(TorrentObject* torrentObject)
{
	torrentObject->Update();

	//
	// @TODO: fDownloadView->AddItem(torrentObject);
	//
	fDownloadView->AddItem(torrentObject);
}
<|endoftext|>