<commit_before>// This file is triangularView of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// 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 "main.h"

template<typename MatrixType> void triangular_square(const MatrixType& m)
{
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;

  RealScalar largerEps = 10*test_precision<RealScalar>();

  typename MatrixType::Index rows = m.rows();
  typename MatrixType::Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols),
             m4(rows, cols),
             r1(rows, cols),
             r2(rows, cols);
  VectorType v2 = VectorType::Random(rows);

  MatrixType m1up = m1.template triangularView<Upper>();
  MatrixType m2up = m2.template triangularView<Upper>();

  if (rows*cols>1)
  {
    VERIFY(m1up.isUpperTriangular());
    VERIFY(m2up.transpose().isLowerTriangular());
    VERIFY(!m2.isLowerTriangular());
  }

//   VERIFY_IS_APPROX(m1up.transpose() * m2, m1.upper().transpose().lower() * m2);

  // test overloaded operator+=
  r1.setZero();
  r2.setZero();
  r1.template triangularView<Upper>() +=  m1;
  r2 += m1up;
  VERIFY_IS_APPROX(r1,r2);

  // test overloaded operator=
  m1.setZero();
  m1.template triangularView<Upper>() = m2.transpose() + m2;
  m3 = m2.transpose() + m2;
  VERIFY_IS_APPROX(m3.template triangularView<Lower>().transpose().toDenseMatrix(), m1);

  // test overloaded operator=
  m1.setZero();
  m1.template triangularView<Lower>() = m2.transpose() + m2;
  VERIFY_IS_APPROX(m3.template triangularView<Lower>().toDenseMatrix(), m1);

  VERIFY_IS_APPROX(m3.template triangularView<Lower>().conjugate().toDenseMatrix(),
                   m3.conjugate().template triangularView<Lower>().toDenseMatrix());

  m1 = MatrixType::Random(rows, cols);
  for (int i=0; i<rows; ++i)
    while (numext::abs2(m1(i,i))<1e-1) m1(i,i) = internal::random<Scalar>();

  Transpose<MatrixType> trm4(m4);
  // test back and forward subsitution with a vector as the rhs
  m3 = m1.template triangularView<Upper>();
  VERIFY(v2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(v2)), largerEps));
  m3 = m1.template triangularView<Lower>();
  VERIFY(v2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Upper>().solve(v2)), largerEps));
  m3 = m1.template triangularView<Upper>();
  VERIFY(v2.isApprox(m3 * (m1.template triangularView<Upper>().solve(v2)), largerEps));
  m3 = m1.template triangularView<Lower>();
  VERIFY(v2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(v2)), largerEps));

  // test back and forward subsitution with a matrix as the rhs
  m3 = m1.template triangularView<Upper>();
  VERIFY(m2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(m2)), largerEps));
  m3 = m1.template triangularView<Lower>();
  VERIFY(m2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Upper>().solve(m2)), largerEps));
  m3 = m1.template triangularView<Upper>();
  VERIFY(m2.isApprox(m3 * (m1.template triangularView<Upper>().solve(m2)), largerEps));
  m3 = m1.template triangularView<Lower>();
  VERIFY(m2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(m2)), largerEps));

  // check M * inv(L) using in place API
  m4 = m3;
  m1.transpose().template triangularView<Eigen::Upper>().solveInPlace(trm4);
  VERIFY_IS_APPROX(m4 * m1.template triangularView<Eigen::Lower>(), m3);

  // check M * inv(U) using in place API
  m3 = m1.template triangularView<Upper>();
  m4 = m3;
  m3.transpose().template triangularView<Eigen::Lower>().solveInPlace(trm4);
  VERIFY_IS_APPROX(m4 * m1.template triangularView<Eigen::Upper>(), m3);

  // check solve with unit diagonal
  m3 = m1.template triangularView<UnitUpper>();
  VERIFY(m2.isApprox(m3 * (m1.template triangularView<UnitUpper>().solve(m2)), largerEps));

//   VERIFY((  m1.template triangularView<Upper>()
//           * m2.template triangularView<Upper>()).isUpperTriangular());

  // test swap
  m1.setOnes();
  m2.setZero();
  m2.template triangularView<Upper>().swap(m1);
  m3.setZero();
  m3.template triangularView<Upper>().setOnes();
  VERIFY_IS_APPROX(m2,m3);

}

template<typename MatrixType> void triangular_rect(const MatrixType& m)
{
  typedef const typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  enum { Rows =  MatrixType::RowsAtCompileTime, Cols =  MatrixType::ColsAtCompileTime };

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols),
             m4(rows, cols),
             r1(rows, cols),
             r2(rows, cols);

  MatrixType m1up = m1.template triangularView<Upper>();
  MatrixType m2up = m2.template triangularView<Upper>();

  if (rows>1 && cols>1)
  {
    VERIFY(m1up.isUpperTriangular());
    VERIFY(m2up.transpose().isLowerTriangular());
    VERIFY(!m2.isLowerTriangular());
  }

  // test overloaded operator+=
  r1.setZero();
  r2.setZero();
  r1.template triangularView<Upper>() +=  m1;
  r2 += m1up;
  VERIFY_IS_APPROX(r1,r2);

  // test overloaded operator=
  m1.setZero();
  m1.template triangularView<Upper>() = 3 * m2;
  m3 = 3 * m2;
  VERIFY_IS_APPROX(m3.template triangularView<Upper>().toDenseMatrix(), m1);

  m1.setZero();
  m1.template triangularView<Lower>() = 3 * m2;
  VERIFY_IS_APPROX(m3.template triangularView<Lower>().toDenseMatrix(), m1);

  m1.setZero();
  m1.template triangularView<StrictlyUpper>() = 3 * m2;
  VERIFY_IS_APPROX(m3.template triangularView<StrictlyUpper>().toDenseMatrix(), m1);

  m1.setZero();
  m1.template triangularView<StrictlyLower>() = 3 * m2;
  VERIFY_IS_APPROX(m3.template triangularView<StrictlyLower>().toDenseMatrix(), m1);
  m1.setRandom();
  m2 = m1.template triangularView<Upper>();
  VERIFY(m2.isUpperTriangular());
  VERIFY(!m2.isLowerTriangular());
  m2 = m1.template triangularView<StrictlyUpper>();
  VERIFY(m2.isUpperTriangular());
  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  m2 = m1.template triangularView<UnitUpper>();
  VERIFY(m2.isUpperTriangular());
  m2.diagonal().array() -= Scalar(1);
  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  m2 = m1.template triangularView<Lower>();
  VERIFY(m2.isLowerTriangular());
  VERIFY(!m2.isUpperTriangular());
  m2 = m1.template triangularView<StrictlyLower>();
  VERIFY(m2.isLowerTriangular());
  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  m2 = m1.template triangularView<UnitLower>();
  VERIFY(m2.isLowerTriangular());
  m2.diagonal().array() -= Scalar(1);
  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  // test swap
  m1.setOnes();
  m2.setZero();
  m2.template triangularView<Upper>().swap(m1);
  m3.setZero();
  m3.template triangularView<Upper>().setOnes();
  VERIFY_IS_APPROX(m2,m3);
}

void bug_159()
{
  Matrix3d m = Matrix3d::Random().triangularView<Lower>();
  EIGEN_UNUSED_VARIABLE(m)
}

void test_triangular()
{
  int maxsize = (std::min)(EIGEN_TEST_MAX_SIZE,20);
  for(int i = 0; i < g_repeat ; i++)
  {
    int r = internal::random<int>(2,maxsize); TEST_SET_BUT_UNUSED_VARIABLE(r)
    int c = internal::random<int>(2,maxsize); TEST_SET_BUT_UNUSED_VARIABLE(c)

    CALL_SUBTEST_1( triangular_square(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( triangular_square(Matrix<float, 2, 2>()) );
    CALL_SUBTEST_3( triangular_square(Matrix3d()) );
    CALL_SUBTEST_4( triangular_square(Matrix<std::complex<float>,8, 8>()) );
    CALL_SUBTEST_5( triangular_square(MatrixXcd(r,r)) );
    CALL_SUBTEST_6( triangular_square(Matrix<float,Dynamic,Dynamic,RowMajor>(r, r)) );

    CALL_SUBTEST_7( triangular_rect(Matrix<float, 4, 5>()) );
    CALL_SUBTEST_8( triangular_rect(Matrix<double, 6, 2>()) );
    CALL_SUBTEST_9( triangular_rect(MatrixXcf(r, c)) );
    CALL_SUBTEST_5( triangular_rect(MatrixXcd(r, c)) );
    CALL_SUBTEST_6( triangular_rect(Matrix<float,Dynamic,Dynamic,RowMajor>(r, c)) );
  }

  CALL_SUBTEST_1( bug_159() );
}
<commit_msg>Add unit test for bug 839.<commit_after>// This file is triangularView of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// 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 "main.h"

template<typename MatrixType> void triangular_square(const MatrixType& m)
{
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;

  RealScalar largerEps = 10*test_precision<RealScalar>();

  typename MatrixType::Index rows = m.rows();
  typename MatrixType::Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols),
             m4(rows, cols),
             r1(rows, cols),
             r2(rows, cols);
  VectorType v2 = VectorType::Random(rows);

  MatrixType m1up = m1.template triangularView<Upper>();
  MatrixType m2up = m2.template triangularView<Upper>();

  if (rows*cols>1)
  {
    VERIFY(m1up.isUpperTriangular());
    VERIFY(m2up.transpose().isLowerTriangular());
    VERIFY(!m2.isLowerTriangular());
  }

//   VERIFY_IS_APPROX(m1up.transpose() * m2, m1.upper().transpose().lower() * m2);

  // test overloaded operator+=
  r1.setZero();
  r2.setZero();
  r1.template triangularView<Upper>() +=  m1;
  r2 += m1up;
  VERIFY_IS_APPROX(r1,r2);

  // test overloaded operator=
  m1.setZero();
  m1.template triangularView<Upper>() = m2.transpose() + m2;
  m3 = m2.transpose() + m2;
  VERIFY_IS_APPROX(m3.template triangularView<Lower>().transpose().toDenseMatrix(), m1);

  // test overloaded operator=
  m1.setZero();
  m1.template triangularView<Lower>() = m2.transpose() + m2;
  VERIFY_IS_APPROX(m3.template triangularView<Lower>().toDenseMatrix(), m1);

  VERIFY_IS_APPROX(m3.template triangularView<Lower>().conjugate().toDenseMatrix(),
                   m3.conjugate().template triangularView<Lower>().toDenseMatrix());

  m1 = MatrixType::Random(rows, cols);
  for (int i=0; i<rows; ++i)
    while (numext::abs2(m1(i,i))<1e-1) m1(i,i) = internal::random<Scalar>();

  Transpose<MatrixType> trm4(m4);
  // test back and forward subsitution with a vector as the rhs
  m3 = m1.template triangularView<Upper>();
  VERIFY(v2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(v2)), largerEps));
  m3 = m1.template triangularView<Lower>();
  VERIFY(v2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Upper>().solve(v2)), largerEps));
  m3 = m1.template triangularView<Upper>();
  VERIFY(v2.isApprox(m3 * (m1.template triangularView<Upper>().solve(v2)), largerEps));
  m3 = m1.template triangularView<Lower>();
  VERIFY(v2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(v2)), largerEps));

  // test back and forward subsitution with a matrix as the rhs
  m3 = m1.template triangularView<Upper>();
  VERIFY(m2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(m2)), largerEps));
  m3 = m1.template triangularView<Lower>();
  VERIFY(m2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Upper>().solve(m2)), largerEps));
  m3 = m1.template triangularView<Upper>();
  VERIFY(m2.isApprox(m3 * (m1.template triangularView<Upper>().solve(m2)), largerEps));
  m3 = m1.template triangularView<Lower>();
  VERIFY(m2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(m2)), largerEps));

  // check M * inv(L) using in place API
  m4 = m3;
  m1.transpose().template triangularView<Eigen::Upper>().solveInPlace(trm4);
  VERIFY_IS_APPROX(m4 * m1.template triangularView<Eigen::Lower>(), m3);

  // check M * inv(U) using in place API
  m3 = m1.template triangularView<Upper>();
  m4 = m3;
  m3.transpose().template triangularView<Eigen::Lower>().solveInPlace(trm4);
  VERIFY_IS_APPROX(m4 * m1.template triangularView<Eigen::Upper>(), m3);

  // check solve with unit diagonal
  m3 = m1.template triangularView<UnitUpper>();
  VERIFY(m2.isApprox(m3 * (m1.template triangularView<UnitUpper>().solve(m2)), largerEps));

//   VERIFY((  m1.template triangularView<Upper>()
//           * m2.template triangularView<Upper>()).isUpperTriangular());

  // test swap
  m1.setOnes();
  m2.setZero();
  m2.template triangularView<Upper>().swap(m1);
  m3.setZero();
  m3.template triangularView<Upper>().setOnes();
  VERIFY_IS_APPROX(m2,m3);

  m1.setRandom();
  m3 = m1.template triangularView<Upper>();
  Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic> m5(cols, internal::random<int>(1,20));  m5.setRandom();
  Matrix<Scalar, Dynamic, MatrixType::RowsAtCompileTime> m6(internal::random<int>(1,20), rows);  m6.setRandom();
  VERIFY_IS_APPROX(m1.template triangularView<Upper>() * m5, m3*m5);
  VERIFY_IS_APPROX(m6*m1.template triangularView<Upper>(), m6*m3);

}

template<typename MatrixType> void triangular_rect(const MatrixType& m)
{
  typedef const typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  enum { Rows =  MatrixType::RowsAtCompileTime, Cols =  MatrixType::ColsAtCompileTime };

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols),
             m4(rows, cols),
             r1(rows, cols),
             r2(rows, cols);

  MatrixType m1up = m1.template triangularView<Upper>();
  MatrixType m2up = m2.template triangularView<Upper>();

  if (rows>1 && cols>1)
  {
    VERIFY(m1up.isUpperTriangular());
    VERIFY(m2up.transpose().isLowerTriangular());
    VERIFY(!m2.isLowerTriangular());
  }

  // test overloaded operator+=
  r1.setZero();
  r2.setZero();
  r1.template triangularView<Upper>() +=  m1;
  r2 += m1up;
  VERIFY_IS_APPROX(r1,r2);

  // test overloaded operator=
  m1.setZero();
  m1.template triangularView<Upper>() = 3 * m2;
  m3 = 3 * m2;
  VERIFY_IS_APPROX(m3.template triangularView<Upper>().toDenseMatrix(), m1);

  m1.setZero();
  m1.template triangularView<Lower>() = 3 * m2;
  VERIFY_IS_APPROX(m3.template triangularView<Lower>().toDenseMatrix(), m1);

  m1.setZero();
  m1.template triangularView<StrictlyUpper>() = 3 * m2;
  VERIFY_IS_APPROX(m3.template triangularView<StrictlyUpper>().toDenseMatrix(), m1);

  m1.setZero();
  m1.template triangularView<StrictlyLower>() = 3 * m2;
  VERIFY_IS_APPROX(m3.template triangularView<StrictlyLower>().toDenseMatrix(), m1);
  m1.setRandom();
  m2 = m1.template triangularView<Upper>();
  VERIFY(m2.isUpperTriangular());
  VERIFY(!m2.isLowerTriangular());
  m2 = m1.template triangularView<StrictlyUpper>();
  VERIFY(m2.isUpperTriangular());
  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  m2 = m1.template triangularView<UnitUpper>();
  VERIFY(m2.isUpperTriangular());
  m2.diagonal().array() -= Scalar(1);
  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  m2 = m1.template triangularView<Lower>();
  VERIFY(m2.isLowerTriangular());
  VERIFY(!m2.isUpperTriangular());
  m2 = m1.template triangularView<StrictlyLower>();
  VERIFY(m2.isLowerTriangular());
  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  m2 = m1.template triangularView<UnitLower>();
  VERIFY(m2.isLowerTriangular());
  m2.diagonal().array() -= Scalar(1);
  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
  // test swap
  m1.setOnes();
  m2.setZero();
  m2.template triangularView<Upper>().swap(m1);
  m3.setZero();
  m3.template triangularView<Upper>().setOnes();
  VERIFY_IS_APPROX(m2,m3);
}

void bug_159()
{
  Matrix3d m = Matrix3d::Random().triangularView<Lower>();
  EIGEN_UNUSED_VARIABLE(m)
}

void test_triangular()
{
  int maxsize = (std::min)(EIGEN_TEST_MAX_SIZE,20);
  for(int i = 0; i < g_repeat ; i++)
  {
    int r = internal::random<int>(2,maxsize); TEST_SET_BUT_UNUSED_VARIABLE(r)
    int c = internal::random<int>(2,maxsize); TEST_SET_BUT_UNUSED_VARIABLE(c)

    CALL_SUBTEST_1( triangular_square(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( triangular_square(Matrix<float, 2, 2>()) );
    CALL_SUBTEST_3( triangular_square(Matrix3d()) );
    CALL_SUBTEST_4( triangular_square(Matrix<std::complex<float>,8, 8>()) );
    CALL_SUBTEST_5( triangular_square(MatrixXcd(r,r)) );
    CALL_SUBTEST_6( triangular_square(Matrix<float,Dynamic,Dynamic,RowMajor>(r, r)) );

    CALL_SUBTEST_7( triangular_rect(Matrix<float, 4, 5>()) );
    CALL_SUBTEST_8( triangular_rect(Matrix<double, 6, 2>()) );
    CALL_SUBTEST_9( triangular_rect(MatrixXcf(r, c)) );
    CALL_SUBTEST_5( triangular_rect(MatrixXcd(r, c)) );
    CALL_SUBTEST_6( triangular_rect(Matrix<float,Dynamic,Dynamic,RowMajor>(r, c)) );
  }

  CALL_SUBTEST_1( bug_159() );
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 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 PLIB_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE pshm_test

#include "plib.h"

#include <stdlib.h>
#include <time.h>

#ifdef PLIB_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

#ifndef P_OS_MSYS
static void * shm_test_thread (void *arg)
{
	pint		rand_num;
	psize		shm_size;
	ppointer	addr;
	PShm		*shm;

	if (arg == NULL)
		p_uthread_exit (1);

	shm = (PShm *) arg;
	rand_num = rand () % 127;
	shm_size = p_shm_get_size (shm);
	addr = p_shm_get_address (shm);

	if (shm_size == 0 || addr == NULL)
		p_uthread_exit (1);

	if (!p_shm_lock (shm, NULL))
		p_uthread_exit (1);

	for (puint i = 0; i < shm_size; ++i)
		*(((pchar *) addr) + i) = (pchar) rand_num;

	if (!p_shm_unlock (shm, NULL))
		p_uthread_exit (1);

	p_uthread_exit (0);
}
#endif /* !P_OS_MSYS */

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (pshm_invalid_test)
{
#ifndef P_OS_MSYS
	p_lib_init ();

	BOOST_CHECK (p_shm_new (NULL, 0, P_SHM_ACCESS_READWRITE, NULL) == NULL);
	BOOST_CHECK (p_shm_lock (NULL, NULL) == FALSE);
	BOOST_CHECK (p_shm_unlock (NULL, NULL) == FALSE);
	BOOST_CHECK (p_shm_get_address (NULL) == NULL);
	BOOST_CHECK (p_shm_get_size (NULL) == 0);
	p_shm_take_ownership (NULL);

	PShm *shm = p_shm_new ("p_shm_invalid_test", 0, P_SHM_ACCESS_READWRITE, NULL);
	p_shm_take_ownership (shm);
	p_shm_free (shm);

	shm = p_shm_new ("p_shm_invalid_test", 10, (PShmAccessPerms) -1, NULL);
	p_shm_take_ownership (shm);
	p_shm_free (shm);

	p_lib_shutdown ();
#endif
}

BOOST_AUTO_TEST_CASE (pshm_general_test)
{
#ifndef P_OS_MSYS
	PShm		*shm = NULL;
#  ifndef P_OS_HPUX
	PShm		*shm2 = NULL;
#  endif
	ppointer	addr, addr2;
	pint		i;

	p_lib_init ();

	shm = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL);
	BOOST_REQUIRE (shm != NULL);
	p_shm_take_ownership (shm);
	p_shm_free (shm);

	shm = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL);
	BOOST_REQUIRE (shm != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

#  ifndef P_OS_HPUX
	shm2 = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READONLY, NULL);

	if (shm2 == NULL) {
		/* OK, some systems may want exactly the same permissions */
		shm2 = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL);
	}

	BOOST_REQUIRE (shm2 != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm2) == 1024);

	addr2 = p_shm_get_address (shm2);
	BOOST_REQUIRE (shm2 != NULL);
#  endif

	for (i = 0; i < 512; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		*(((pchar *) addr) + i) = 'a';
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}

#  ifndef P_OS_HPUX
	for (i = 0; i < 512; ++i) {
		BOOST_CHECK (p_shm_lock (shm2, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'a');
		BOOST_CHECK (p_shm_unlock (shm2, NULL));
	}
#  else
	for (i = 0; i < 512; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'a');
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}
#  endif

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		*(((pchar *) addr) + i) = 'b';
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}

#  ifndef P_OS_HPUX
	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm2, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) != 'c');
		BOOST_CHECK (p_shm_unlock (shm2, NULL));
	}

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm2, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'b');
		BOOST_CHECK (p_shm_unlock (shm2, NULL));
	}
#  else
	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) != 'c');
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'b');
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}
#  endif

	p_shm_free (shm);

	shm = p_shm_new ("p_shm_test_memory_block_2", 1024, P_SHM_ACCESS_READWRITE, NULL);
	BOOST_REQUIRE (shm != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) != 'b');
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}

	p_shm_free (shm);

#  ifndef P_OS_HPUX
	p_shm_free (shm2);
#  endif

	p_lib_shutdown ();
#endif /* !P_OS_MSYS */
}

BOOST_AUTO_TEST_CASE (pshm_thread_test)
{
#ifndef P_OS_MSYS
	PShm		*shm;
	PUThread	*thr1, *thr2, *thr3;
	ppointer	addr;
	pint		i, val;
	pboolean	test_ok;

	p_lib_init ();

	srand ((puint) time (NULL));

	shm = p_shm_new ("p_shm_test_memory_block", 1024 * 1024, P_SHM_ACCESS_READWRITE, NULL);
	BOOST_REQUIRE (shm != NULL);
	p_shm_take_ownership (shm);
	p_shm_free (shm);

	shm = p_shm_new ("p_shm_test_memory_block", 1024 * 1024, P_SHM_ACCESS_READWRITE, NULL);
	BOOST_REQUIRE (shm != NULL);

	if (p_shm_get_size (shm) != 1024 * 1024) {
		p_shm_free (shm);
		shm = p_shm_new ("p_shm_test_memory_block", 1024 * 1024, P_SHM_ACCESS_READWRITE, NULL);
		BOOST_REQUIRE (shm != NULL);
	}

	BOOST_REQUIRE (p_shm_get_size (shm) == 1024 * 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

	thr1 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr1 != NULL);

	thr2 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr2 != NULL);

	thr3 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr3 != NULL);

	BOOST_CHECK (p_uthread_join (thr1) == 0);
	BOOST_CHECK (p_uthread_join (thr2) == 0);
	BOOST_CHECK (p_uthread_join (thr3) == 0);

	test_ok = TRUE;
	val = *((pchar *) addr);

	for (i = 1; i < 1024 * 1024; ++i)
		if (*(((pchar *) addr) + i) != val) {
			test_ok = FALSE;
			break;
		}

	BOOST_REQUIRE (test_ok == TRUE);

	p_uthread_free (thr1);
	p_uthread_free (thr2);
	p_uthread_free (thr3);
	p_shm_free (shm);

	p_lib_shutdown ();
#endif /* !P_OS_MSYS */
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>tests: Add out of memory checks for PShm<commit_after>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 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 PLIB_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE pshm_test

#include "plib.h"

#include <stdlib.h>
#include <time.h>

#ifdef PLIB_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

#ifndef P_OS_MSYS
static void * shm_test_thread (void *arg)
{
	pint		rand_num;
	psize		shm_size;
	ppointer	addr;
	PShm		*shm;

	if (arg == NULL)
		p_uthread_exit (1);

	shm = (PShm *) arg;
	rand_num = rand () % 127;
	shm_size = p_shm_get_size (shm);
	addr = p_shm_get_address (shm);

	if (shm_size == 0 || addr == NULL)
		p_uthread_exit (1);

	if (!p_shm_lock (shm, NULL))
		p_uthread_exit (1);

	for (puint i = 0; i < shm_size; ++i)
		*(((pchar *) addr) + i) = (pchar) rand_num;

	if (!p_shm_unlock (shm, NULL))
		p_uthread_exit (1);

	p_uthread_exit (0);
}
#endif /* !P_OS_MSYS */

extern "C" ppointer pmem_alloc (psize nbytes)
{
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
{
	P_UNUSED (block);
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" void pmem_free (ppointer block)
{
	P_UNUSED (block);
}

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (pshm_nomem_test)
{
	p_lib_init ();

	PMemVTable vtable;

	vtable.free	= pmem_free;
	vtable.malloc	= pmem_alloc;
	vtable.realloc	= pmem_realloc;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	BOOST_CHECK (p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL) == NULL);

	vtable.malloc	= (ppointer (*)(psize)) malloc;
	vtable.realloc	= (ppointer (*)(ppointer, psize)) realloc;
	vtable.free	= (void (*)(ppointer)) free;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	p_lib_shutdown ();
}

BOOST_AUTO_TEST_CASE (pshm_invalid_test)
{
#ifndef P_OS_MSYS
	p_lib_init ();

	BOOST_CHECK (p_shm_new (NULL, 0, P_SHM_ACCESS_READWRITE, NULL) == NULL);
	BOOST_CHECK (p_shm_lock (NULL, NULL) == FALSE);
	BOOST_CHECK (p_shm_unlock (NULL, NULL) == FALSE);
	BOOST_CHECK (p_shm_get_address (NULL) == NULL);
	BOOST_CHECK (p_shm_get_size (NULL) == 0);
	p_shm_take_ownership (NULL);

	PShm *shm = p_shm_new ("p_shm_invalid_test", 0, P_SHM_ACCESS_READWRITE, NULL);
	p_shm_take_ownership (shm);
	p_shm_free (shm);

	shm = p_shm_new ("p_shm_invalid_test", 10, (PShmAccessPerms) -1, NULL);
	p_shm_take_ownership (shm);
	p_shm_free (shm);

	p_lib_shutdown ();
#endif
}

BOOST_AUTO_TEST_CASE (pshm_general_test)
{
#ifndef P_OS_MSYS
	PShm		*shm = NULL;
#  ifndef P_OS_HPUX
	PShm		*shm2 = NULL;
#  endif
	ppointer	addr, addr2;
	pint		i;

	p_lib_init ();

	shm = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL);
	BOOST_REQUIRE (shm != NULL);
	p_shm_take_ownership (shm);
	p_shm_free (shm);

	shm = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL);
	BOOST_REQUIRE (shm != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

#  ifndef P_OS_HPUX
	shm2 = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READONLY, NULL);

	if (shm2 == NULL) {
		/* OK, some systems may want exactly the same permissions */
		shm2 = p_shm_new ("p_shm_test_memory_block", 1024, P_SHM_ACCESS_READWRITE, NULL);
	}

	BOOST_REQUIRE (shm2 != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm2) == 1024);

	addr2 = p_shm_get_address (shm2);
	BOOST_REQUIRE (shm2 != NULL);
#  endif

	for (i = 0; i < 512; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		*(((pchar *) addr) + i) = 'a';
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}

#  ifndef P_OS_HPUX
	for (i = 0; i < 512; ++i) {
		BOOST_CHECK (p_shm_lock (shm2, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'a');
		BOOST_CHECK (p_shm_unlock (shm2, NULL));
	}
#  else
	for (i = 0; i < 512; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'a');
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}
#  endif

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		*(((pchar *) addr) + i) = 'b';
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}

#  ifndef P_OS_HPUX
	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm2, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) != 'c');
		BOOST_CHECK (p_shm_unlock (shm2, NULL));
	}

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm2, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'b');
		BOOST_CHECK (p_shm_unlock (shm2, NULL));
	}
#  else
	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) != 'c');
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) == 'b');
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}
#  endif

	p_shm_free (shm);

	shm = p_shm_new ("p_shm_test_memory_block_2", 1024, P_SHM_ACCESS_READWRITE, NULL);
	BOOST_REQUIRE (shm != NULL);
	BOOST_REQUIRE (p_shm_get_size (shm) == 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

	for (i = 0; i < 1024; ++i) {
		BOOST_CHECK (p_shm_lock (shm, NULL));
		BOOST_CHECK (*(((pchar *) addr) + i) != 'b');
		BOOST_CHECK (p_shm_unlock (shm, NULL));
	}

	p_shm_free (shm);

#  ifndef P_OS_HPUX
	p_shm_free (shm2);
#  endif

	p_lib_shutdown ();
#endif /* !P_OS_MSYS */
}

BOOST_AUTO_TEST_CASE (pshm_thread_test)
{
#ifndef P_OS_MSYS
	PShm		*shm;
	PUThread	*thr1, *thr2, *thr3;
	ppointer	addr;
	pint		i, val;
	pboolean	test_ok;

	p_lib_init ();

	srand ((puint) time (NULL));

	shm = p_shm_new ("p_shm_test_memory_block", 1024 * 1024, P_SHM_ACCESS_READWRITE, NULL);
	BOOST_REQUIRE (shm != NULL);
	p_shm_take_ownership (shm);
	p_shm_free (shm);

	shm = p_shm_new ("p_shm_test_memory_block", 1024 * 1024, P_SHM_ACCESS_READWRITE, NULL);
	BOOST_REQUIRE (shm != NULL);

	if (p_shm_get_size (shm) != 1024 * 1024) {
		p_shm_free (shm);
		shm = p_shm_new ("p_shm_test_memory_block", 1024 * 1024, P_SHM_ACCESS_READWRITE, NULL);
		BOOST_REQUIRE (shm != NULL);
	}

	BOOST_REQUIRE (p_shm_get_size (shm) == 1024 * 1024);

	addr = p_shm_get_address (shm);
	BOOST_REQUIRE (addr != NULL);

	thr1 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr1 != NULL);

	thr2 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr2 != NULL);

	thr3 = p_uthread_create ((PUThreadFunc) shm_test_thread, (ppointer) shm, true);
	BOOST_REQUIRE (thr3 != NULL);

	BOOST_CHECK (p_uthread_join (thr1) == 0);
	BOOST_CHECK (p_uthread_join (thr2) == 0);
	BOOST_CHECK (p_uthread_join (thr3) == 0);

	test_ok = TRUE;
	val = *((pchar *) addr);

	for (i = 1; i < 1024 * 1024; ++i)
		if (*(((pchar *) addr) + i) != val) {
			test_ok = FALSE;
			break;
		}

	BOOST_REQUIRE (test_ok == TRUE);

	p_uthread_free (thr1);
	p_uthread_free (thr2);
	p_uthread_free (thr3);
	p_shm_free (shm);

	p_lib_shutdown ();
#endif /* !P_OS_MSYS */
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*
 * Renzoku - Re-build, re-test, and re-run a program whenever the code changes
 * Copyright (C) 2015  Colton Wolkins
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */
//#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
//#include "catch.hpp"
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include <sstream>
#include <string>
#include <ctime>
#include "log.hpp"
iLogger* mainLogger;
//#include <valgrind/memcheck.h>

int main( int argc, char* const argv[] )
{
	time_t t = time(0);
	struct tm * now = localtime( & t );
	std::stringstream filename;
	filename << "/tmp/renzoku_test" <<
		'-' << (now->tm_year + 1900) <<
		'-' << (now->tm_mon + 1) <<
		'-' << now->tm_mday <<
		/*'-' << now->tm_hour <<
			'-' << now->tm_min <<
			'-' << now->tm_sec <<
			*/".log";
		mainLogger = new FileLogger(filename.str());
	Catch::Session session;

	// writing to session.configData() here sets defaults
	// this is the preferred way to set them

	int returnCode = session.applyCommandLine( argc, argv );
	if( returnCode != 0 ) // Indicates a command line error
		return returnCode;

	// writing to session.configData() or session.Config() here
	// overrides command line args
	// only do this if you know you need to

	returnCode = session.run();
	delete mainLogger;
	//VALGRIND_DO_LEAK_CHECK;
}
<commit_msg>[tests] Truncate test log file before tests<commit_after>/*
 * Renzoku - Re-build, re-test, and re-run a program whenever the code changes
 * Copyright (C) 2015  Colton Wolkins
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */
//#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
//#include "catch.hpp"
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include <sstream>
#include <string>
#include <ctime>
#include <stdio.h>
#include "log.hpp"
iLogger* mainLogger;
//#include <valgrind/memcheck.h>

int main( int argc, char* const argv[] )
{
	time_t t = time(0);
	struct tm * now = localtime( & t );
	std::stringstream filename;
	filename << "/tmp/renzoku_test" <<
		'-' << (now->tm_year + 1900) <<
		'-' << (now->tm_mon + 1) <<
		'-' << now->tm_mday <<
		/*
		'-' << now->tm_hour <<
		'-' << now->tm_min <<
		'-' << now->tm_sec <<
		*/
		".log";
	{
		FILE* f = fopen(filename.str().c_str(), "w+");
		fclose(f);
	}
	mainLogger = new FileLogger(filename.str());
	Catch::Session session;

	// writing to session.configData() here sets defaults
	// this is the preferred way to set them

	int returnCode = session.applyCommandLine( argc, argv );
	if( returnCode != 0 ) // Indicates a command line error
		return returnCode;

	// writing to session.configData() or session.Config() here
	// overrides command line args
	// only do this if you know you need to

	returnCode = session.run();
	delete mainLogger;
	//VALGRIND_DO_LEAK_CHECK;
}
<|endoftext|>


<commit_before>#include "ClientDataModel.hpp"

#include <graphene/app/api.hpp>
#include <graphene/chain/protocol/protocol.hpp>

#include <fc/rpc/websocket_api.hpp>

using namespace graphene::app;

ChainDataModel::ChainDataModel( fc::thread& t, QObject* parent )
:QObject(parent),m_thread(&t){}

Asset* ChainDataModel::getAsset(qint64 id)
{
   auto& by_id_idx = m_assets.get<::by_id>();
   auto itr = by_id_idx.find(id);
   if( itr == by_id_idx.end() )
   {
      auto tmp = new Asset;
      tmp->id = id; --m_account_query_num;
      tmp->symbol = QString::number( --m_account_query_num);
      auto result = m_assets.insert( tmp );
      assert( result.second );

      /** execute in app thread */
      m_thread->async( [this,id](){
         try {
           ilog( "look up symbol.." );
           auto result = m_db_api->get_assets( {asset_id_type(id)} );
           wdump((result));

           /** execute in main */
           Q_EMIT queueExecute( [this,result,id](){
              wlog( "process result" );
              auto& by_id_idx = this->m_assets.get<::by_id>();
              auto itr = by_id_idx.find(id);
              assert( itr != by_id_idx.end() );

              if( result.size() == 0 || !result.front() )
              {
                  elog( "delete later" );
                  (*itr)->deleteLater();
                  by_id_idx.erase( itr );
              }
              else
              {
                 by_id_idx.modify( itr,
                    [=]( Asset* a ){
                       a->setProperty("symbol", QString::fromStdString(result.front()->symbol) );
                       a->setProperty("precision", result.front()->precision );
                    }
                 );
              }
           });
         }
         catch ( const fc::exception& e )
         {
            Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) );
         }
       });
      return *result.first;
   }
   return *itr;
}

Asset* ChainDataModel::getAsset(QString symbol)
{
   auto& by_symbol_idx = m_assets.get<by_symbol_name>();
   auto itr = by_symbol_idx.find(symbol);
   if( itr == by_symbol_idx.end() )
   {
      auto tmp = new Asset;
      tmp->id = --m_account_query_num;
      tmp->symbol = symbol;
      auto result = m_assets.insert( tmp );
      assert( result.second );

      /** execute in app thread */
      m_thread->async( [this,symbol](){
         try {
           ilog( "look up symbol.." );
           auto result = m_db_api->lookup_asset_symbols( {symbol.toStdString()} );
           /** execute in main */
           Q_EMIT queueExecute( [this,result,symbol](){
              wlog( "process result" );
              auto& by_symbol_idx = this->m_assets.get<by_symbol_name>();
              auto itr = by_symbol_idx.find(symbol);
              assert( itr != by_symbol_idx.end() );

              if( result.size() == 0 || !result.front() )
              {
                  elog( "delete later" );
                  (*itr)->deleteLater();
                  by_symbol_idx.erase( itr );
              }
              else
              {
                 by_symbol_idx.modify( itr,
                    [=]( Asset* a ){
                       a->setProperty("id", result.front()->id.instance() );
                       a->setProperty("precision", result.front()->precision );
                    }
                 );
              }
           });
         }
         catch ( const fc::exception& e )
         {
            Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) );
         }
       });
      return *result.first;
   }
   return *itr;
}

Account* ChainDataModel::getAccount(ObjectId id)
{
   auto& by_id_idx = m_accounts.get<::by_id>();
   auto itr = by_id_idx.find(id);
   if( itr == by_id_idx.end() )
   {
      auto tmp = new Account;
      QQmlEngine::setObjectOwnership(tmp, QQmlEngine::CppOwnership);
      tmp->id = id; --m_account_query_num;
      tmp->name = QString::number( --m_account_query_num);
      auto result = m_accounts.insert( tmp );
      assert( result.second );

      /** execute in app thread */
      m_thread->async( [this,id](){
         try {
           ilog( "look up names.." );
           auto result = m_db_api->get_accounts( {account_id_type(id)} );
           /** execute in main */
           Q_EMIT queueExecute( [this,result,id](){
              wlog( "process result" );
              auto& by_id_idx = this->m_accounts.get<::by_id>();
              auto itr = by_id_idx.find(id);
              assert( itr != by_id_idx.end() );

              if( result.size() == 0 || !result.front() )
              {
                  elog( "delete later" );
                  (*itr)->deleteLater();
                  by_id_idx.erase( itr );
              }
              else
              {
                 by_id_idx.modify( itr,
                    [=]( Account* a ){
                       a->setProperty("name", QString::fromStdString(result.front()->name) );
                    }
                 );
              }
           });
         }
         catch ( const fc::exception& e )
         {
            Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) );
         }
       });
      return *result.first;
   }
   return *itr;
}

Account* ChainDataModel::getAccount(QString name)
{
   auto& by_name_idx = m_accounts.get<by_account_name>();
   auto itr = by_name_idx.find(name);
   if( itr == by_name_idx.end() )
   {
      auto tmp = new Account;
      QQmlEngine::setObjectOwnership(tmp, QQmlEngine::CppOwnership);
      tmp->id = --m_account_query_num;
      tmp->name = name;
      auto result = m_accounts.insert( tmp );
      assert( result.second );

      /** execute in app thread */
      m_thread->async( [this,name](){
         try {
           ilog( "look up names.." );
           auto result = m_db_api->lookup_account_names( {name.toStdString()} );
           /** execute in main */
           Q_EMIT queueExecute( [this,result,name](){
              wlog( "process result" );
              auto& by_symbol_idx = this->m_accounts.get<by_account_name>();
              auto itr = by_symbol_idx.find(name);
              assert( itr != by_symbol_idx.end() );

              if( result.size() == 0 || !result.front() )
              {
                  elog( "delete later" );
                  (*itr)->deleteLater();
                  by_symbol_idx.erase( itr );
              }
              else
              {
                 by_symbol_idx.modify( itr,
                    [=]( Account* a ){
                       a->setProperty("id", ObjectId(result.front()->id.instance()));
                    }
                 );
              }
           });
         }
         catch ( const fc::exception& e )
         {
            Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) );
         }
       });
      return *result.first;
   }
   return *itr;
}

QQmlListProperty<Balance> Account::balances()
{
   return QQmlListProperty<Balance>(this, m_balances);
}

GrapheneApplication::GrapheneApplication( QObject* parent )
:QObject( parent ),m_thread("app")
{
   connect( this, &GrapheneApplication::queueExecute,
            this, &GrapheneApplication::execute );

   m_model = new ChainDataModel( m_thread, this );

   connect( m_model, &ChainDataModel::queueExecute,
            this, &GrapheneApplication::execute );

   connect( m_model, &ChainDataModel::exceptionThrown,
            this, &GrapheneApplication::exceptionThrown );
}

GrapheneApplication::~GrapheneApplication()
{
}

void GrapheneApplication::setIsConnected( bool v )
{
   if( v != m_isConnected )
   {
      m_isConnected = v;
      Q_EMIT isConnectedChanged( m_isConnected );
   }
}

void GrapheneApplication::start( QString apiurl, QString user, QString pass )
{
   if( !m_thread.is_current() )
   {
      m_done = m_thread.async( [=](){ return start( apiurl, user, pass ); }  );
      return;
   }
   try {
      m_client = std::make_shared<fc::http::websocket_client>();
      ilog( "connecting...${s}", ("s",apiurl.toStdString()) );
      auto con  = m_client->connect( apiurl.toStdString() );
      m_connectionClosed = con->closed.connect([this]{queueExecute([this]{setIsConnected(false);});});
      auto apic = std::make_shared<fc::rpc::websocket_api_connection>(*con);
      auto remote_api = apic->get_remote_api< login_api >(1);
      auto db_api = apic->get_remote_api< database_api >(0);
      if( !remote_api->login( user.toStdString(), pass.toStdString() ) )
      {
         elog( "login failed" );
         Q_EMIT loginFailed();
         return;
      }

      ilog( "connecting..." );
      queueExecute( [=](){
         m_model->setDatabaseAPI( db_api );
      });

      queueExecute( [=](){setIsConnected( true );} );
   } catch ( const fc::exception& e )
   {
      Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) );
   }
}
Q_SLOT void GrapheneApplication::execute( const std::function<void()>& func )const
{
   func();
}
<commit_msg>[GUI] Fix ownership of asset objects<commit_after>#include "ClientDataModel.hpp"

#include <graphene/app/api.hpp>
#include <graphene/chain/protocol/protocol.hpp>

#include <fc/rpc/websocket_api.hpp>

using namespace graphene::app;

ChainDataModel::ChainDataModel( fc::thread& t, QObject* parent )
:QObject(parent),m_thread(&t){}

Asset* ChainDataModel::getAsset(qint64 id)
{
   auto& by_id_idx = m_assets.get<::by_id>();
   auto itr = by_id_idx.find(id);
   if( itr == by_id_idx.end() )
   {
      auto tmp = new Asset;
      QQmlEngine::setObjectOwnership(tmp, QQmlEngine::CppOwnership);
      tmp->id = id; --m_account_query_num;
      tmp->symbol = QString::number( --m_account_query_num);
      auto result = m_assets.insert( tmp );
      assert( result.second );

      /** execute in app thread */
      m_thread->async( [this,id](){
         try {
           ilog( "look up symbol.." );
           auto result = m_db_api->get_assets( {asset_id_type(id)} );
           wdump((result));

           /** execute in main */
           Q_EMIT queueExecute( [this,result,id](){
              wlog( "process result" );
              auto& by_id_idx = this->m_assets.get<::by_id>();
              auto itr = by_id_idx.find(id);
              assert( itr != by_id_idx.end() );

              if( result.size() == 0 || !result.front() )
              {
                  elog( "delete later" );
                  (*itr)->deleteLater();
                  by_id_idx.erase( itr );
              }
              else
              {
                 by_id_idx.modify( itr,
                    [=]( Asset* a ){
                       a->setProperty("symbol", QString::fromStdString(result.front()->symbol) );
                       a->setProperty("precision", result.front()->precision );
                    }
                 );
              }
           });
         }
         catch ( const fc::exception& e )
         {
            Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) );
         }
       });
      return *result.first;
   }
   return *itr;
}

Asset* ChainDataModel::getAsset(QString symbol)
{
   auto& by_symbol_idx = m_assets.get<by_symbol_name>();
   auto itr = by_symbol_idx.find(symbol);
   if( itr == by_symbol_idx.end() )
   {
      auto tmp = new Asset;
      QQmlEngine::setObjectOwnership(tmp, QQmlEngine::CppOwnership);
      tmp->id = --m_account_query_num;
      tmp->symbol = symbol;
      auto result = m_assets.insert( tmp );
      assert( result.second );

      /** execute in app thread */
      m_thread->async( [this,symbol](){
         try {
           ilog( "look up symbol.." );
           auto result = m_db_api->lookup_asset_symbols( {symbol.toStdString()} );
           /** execute in main */
           Q_EMIT queueExecute( [this,result,symbol](){
              wlog( "process result" );
              auto& by_symbol_idx = this->m_assets.get<by_symbol_name>();
              auto itr = by_symbol_idx.find(symbol);
              assert( itr != by_symbol_idx.end() );

              if( result.size() == 0 || !result.front() )
              {
                  elog( "delete later" );
                  (*itr)->deleteLater();
                  by_symbol_idx.erase( itr );
              }
              else
              {
                 by_symbol_idx.modify( itr,
                    [=]( Asset* a ){
                       a->setProperty("id", result.front()->id.instance() );
                       a->setProperty("precision", result.front()->precision );
                    }
                 );
              }
           });
         }
         catch ( const fc::exception& e )
         {
            Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) );
         }
       });
      return *result.first;
   }
   return *itr;
}

Account* ChainDataModel::getAccount(ObjectId id)
{
   auto& by_id_idx = m_accounts.get<::by_id>();
   auto itr = by_id_idx.find(id);
   if( itr == by_id_idx.end() )
   {
      auto tmp = new Account;
      QQmlEngine::setObjectOwnership(tmp, QQmlEngine::CppOwnership);
      tmp->id = id; --m_account_query_num;
      tmp->name = QString::number( --m_account_query_num);
      auto result = m_accounts.insert( tmp );
      assert( result.second );

      /** execute in app thread */
      m_thread->async( [this,id](){
         try {
           ilog( "look up names.." );
           auto result = m_db_api->get_accounts( {account_id_type(id)} );
           /** execute in main */
           Q_EMIT queueExecute( [this,result,id](){
              wlog( "process result" );
              auto& by_id_idx = this->m_accounts.get<::by_id>();
              auto itr = by_id_idx.find(id);
              assert( itr != by_id_idx.end() );

              if( result.size() == 0 || !result.front() )
              {
                  elog( "delete later" );
                  (*itr)->deleteLater();
                  by_id_idx.erase( itr );
              }
              else
              {
                 by_id_idx.modify( itr,
                    [=]( Account* a ){
                       a->setProperty("name", QString::fromStdString(result.front()->name) );
                    }
                 );
              }
           });
         }
         catch ( const fc::exception& e )
         {
            Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) );
         }
       });
      return *result.first;
   }
   return *itr;
}

Account* ChainDataModel::getAccount(QString name)
{
   auto& by_name_idx = m_accounts.get<by_account_name>();
   auto itr = by_name_idx.find(name);
   if( itr == by_name_idx.end() )
   {
      auto tmp = new Account;
      QQmlEngine::setObjectOwnership(tmp, QQmlEngine::CppOwnership);
      tmp->id = --m_account_query_num;
      tmp->name = name;
      auto result = m_accounts.insert( tmp );
      assert( result.second );

      /** execute in app thread */
      m_thread->async( [this,name](){
         try {
           ilog( "look up names.." );
           auto result = m_db_api->lookup_account_names( {name.toStdString()} );
           /** execute in main */
           Q_EMIT queueExecute( [this,result,name](){
              wlog( "process result" );
              auto& by_name_idx = this->m_accounts.get<by_account_name>();
              auto itr = by_name_idx.find(name);
              assert( itr != by_name_idx.end() );

              if( result.size() == 0 || !result.front() )
              {
                  elog( "delete later" );
                  (*itr)->deleteLater();
                  by_name_idx.erase( itr );
              }
              else
              {
                 by_name_idx.modify( itr,
                    [=]( Account* a ){
                       a->setProperty("id", ObjectId(result.front()->id.instance()));
                    }
                 );
              }
           });
         }
         catch ( const fc::exception& e )
         {
            Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) );
         }
       });
      return *result.first;
   }
   return *itr;
}

QQmlListProperty<Balance> Account::balances()
{
   return QQmlListProperty<Balance>(this, m_balances);
}

GrapheneApplication::GrapheneApplication( QObject* parent )
:QObject( parent ),m_thread("app")
{
   connect( this, &GrapheneApplication::queueExecute,
            this, &GrapheneApplication::execute );

   m_model = new ChainDataModel( m_thread, this );

   connect( m_model, &ChainDataModel::queueExecute,
            this, &GrapheneApplication::execute );

   connect( m_model, &ChainDataModel::exceptionThrown,
            this, &GrapheneApplication::exceptionThrown );
}

GrapheneApplication::~GrapheneApplication()
{
}

void GrapheneApplication::setIsConnected( bool v )
{
   if( v != m_isConnected )
   {
      m_isConnected = v;
      Q_EMIT isConnectedChanged( m_isConnected );
   }
}

void GrapheneApplication::start( QString apiurl, QString user, QString pass )
{
   if( !m_thread.is_current() )
   {
      m_done = m_thread.async( [=](){ return start( apiurl, user, pass ); }  );
      return;
   }
   try {
      m_client = std::make_shared<fc::http::websocket_client>();
      ilog( "connecting...${s}", ("s",apiurl.toStdString()) );
      auto con  = m_client->connect( apiurl.toStdString() );
      m_connectionClosed = con->closed.connect([this]{queueExecute([this]{setIsConnected(false);});});
      auto apic = std::make_shared<fc::rpc::websocket_api_connection>(*con);
      auto remote_api = apic->get_remote_api< login_api >(1);
      auto db_api = apic->get_remote_api< database_api >(0);
      if( !remote_api->login( user.toStdString(), pass.toStdString() ) )
      {
         elog( "login failed" );
         Q_EMIT loginFailed();
         return;
      }

      ilog( "connecting..." );
      queueExecute( [=](){
         m_model->setDatabaseAPI( db_api );
      });

      queueExecute( [=](){setIsConnected( true );} );
   } catch ( const fc::exception& e )
   {
      Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) );
   }
}
Q_SLOT void GrapheneApplication::execute( const std::function<void()>& func )const
{
   func();
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkSampleFunction.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkSampleFunction.h"
#include "vtkMath.h"
#include "vtkScalars.h"
#include "vtkNormals.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkSampleFunction* vtkSampleFunction::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkSampleFunction");
  if(ret)
    {
    return (vtkSampleFunction*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkSampleFunction;
}

// Construct with ModelBounds=(-1,1,-1,1,-1,1), SampleDimensions=(50,50,50),
// Capping turned off, and normal generation on.
vtkSampleFunction::vtkSampleFunction()
{
  this->ModelBounds[0] = -1.0;
  this->ModelBounds[1] = 1.0;
  this->ModelBounds[2] = -1.0;
  this->ModelBounds[3] = 1.0;
  this->ModelBounds[4] = -1.0;
  this->ModelBounds[5] = 1.0;

  this->SampleDimensions[0] = 50;
  this->SampleDimensions[1] = 50;
  this->SampleDimensions[2] = 50;

  this->Capping = 0;
  this->CapValue = VTK_LARGE_FLOAT;

  this->ImplicitFunction = NULL;

  this->ComputeNormals = 1;
  this->Scalars = NULL;
}

vtkSampleFunction::~vtkSampleFunction()
{
  this->SetScalars(NULL);
  this->SetImplicitFunction(NULL);
}

// Specify the dimensions of the data on which to sample.
void vtkSampleFunction::SetSampleDimensions(int i, int j, int k)
{
  int dim[3];

  dim[0] = i;
  dim[1] = j;
  dim[2] = k;

  this->SetSampleDimensions(dim);
}

// Specify the dimensions of the data on which to sample.
void vtkSampleFunction::SetSampleDimensions(int dim[3])
{
  vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")");

  if ( dim[0] != this->SampleDimensions[0] ||
       dim[1] != this->SampleDimensions[1] ||
       dim[2] != this->SampleDimensions[2] )
    {
    for ( int i=0; i<3; i++)
      {
      this->SampleDimensions[i] = (dim[i] > 0 ? dim[i] : 1);
      }
    this->Modified();
    }
}

void vtkSampleFunction::ExecuteInformation()
{
  int i;
  float ar[3], origin[3];
  vtkStructuredPoints *output = this->GetOutput();

  output->SetScalarType(VTK_FLOAT);
  output->SetNumberOfScalarComponents(1);

  output->SetWholeExtent(0, this->SampleDimensions[0]-1,
			 0, this->SampleDimensions[1]-1,
			 0, this->SampleDimensions[2]-1);

  output->SetDimensions(this->GetSampleDimensions());

  for (i=0; i < 3; i++)
    {
    origin[i] = this->ModelBounds[2*i];
    if ( this->SampleDimensions[i] <= 1 )
      {
      ar[i] = 1;
      }
    else
      {
      ar[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i])
              / (this->SampleDimensions[i] - 1);
      }
    }
  output->SetOrigin(origin);
  output->SetSpacing(ar);
}

void vtkSampleFunction::Execute()
{
  int ptId;
  vtkNormals *newNormals=NULL;
  int numPts;
  float *p, s;
  vtkStructuredPoints *output = this->GetOutput();

  vtkDebugMacro(<< "Sampling implicit function");
  //
  // Initialize self; create output objects
  //

  if ( !this->ImplicitFunction )
    {
    vtkErrorMacro(<<"No implicit function specified");
    return;
    }

  numPts = this->SampleDimensions[0] * this->SampleDimensions[1]
           * this->SampleDimensions[2];

  if (this->Scalars == NULL)
    {
    this->Scalars = vtkScalars::New(); //ref count is 1
    this->Scalars->Register(this);
    this->Scalars->Delete();
    }
  this->Scalars->SetNumberOfScalars(numPts);

  //
  // Traverse all points evaluating implicit function at each point
  //
  for (ptId=0; ptId < numPts; ptId++ )
    {
    p = output->GetPoint(ptId);
    s = this->ImplicitFunction->FunctionValue(p);
    this->Scalars->SetScalar(ptId,s);
    }
  //
  // If normal computation turned on, compute them
  //
  if ( this->ComputeNormals )
    {
    float n[3];
    newNormals = vtkNormals::New();
    newNormals->SetNumberOfNormals(numPts);
    for (ptId=0; ptId < numPts; ptId++ )
      {
      p = output->GetPoint(ptId);
      this->ImplicitFunction->FunctionGradient(p, n);
      n[0] *= -1;
      n[1] *= -1;
      n[2] *= -1;
      vtkMath::Normalize(n);
      newNormals->SetNormal(ptId,n);
      }
    }
  //
  // If capping is turned on, set the distances of the outside of the volume
  // to the CapValue.
  //
  if ( this->Capping )
    {
    this->Cap(this->Scalars);
    }
  //
  // Update self
  //
  output->GetPointData()->SetScalars(this->Scalars); //ref count is now 2

  if (newNormals)
    {
    output->GetPointData()->SetNormals(newNormals);
    newNormals->Delete();
    }
}

unsigned long vtkSampleFunction::GetMTime()
{
  unsigned long mTime=this->vtkSource::GetMTime();
  unsigned long impFuncMTime;

  if ( this->ImplicitFunction != NULL )
    {
    impFuncMTime = this->ImplicitFunction->GetMTime();
    mTime = ( impFuncMTime > mTime ? impFuncMTime : mTime );
    }

  return mTime;
}

void vtkSampleFunction::Cap(vtkScalars *s)
{
  int i,j,k;
  int idx;
  int d01=this->SampleDimensions[0]*this->SampleDimensions[1];

// i-j planes
  k = 0;
  for (j=0; j<this->SampleDimensions[1]; j++)
    {
    for (i=0; i<this->SampleDimensions[0]; i++)
      {
      s->SetScalar(i+j*this->SampleDimensions[1], this->CapValue);
      }
    }

  k = this->SampleDimensions[2] - 1;
  idx = k*d01;
  for (j=0; j<this->SampleDimensions[1]; j++)
    {
    for (i=0; i<this->SampleDimensions[0]; i++)
      {
      s->SetScalar(idx+i+j*this->SampleDimensions[1], this->CapValue);
      }
    }

// j-k planes
  i = 0;
  for (k=0; k<this->SampleDimensions[2]; k++)
    {
    for (j=0; j<this->SampleDimensions[1]; j++)
      {
      s->SetScalar(j*this->SampleDimensions[0]+k*d01, this->CapValue);
      }
    }

  i = this->SampleDimensions[0] - 1;
  for (k=0; k<this->SampleDimensions[2]; k++)
    {
    for (j=0; j<this->SampleDimensions[1]; j++)
      {
      s->SetScalar(i+j*this->SampleDimensions[0]+k*d01, this->CapValue);
      }
    }

// i-k planes
  j = 0;
  for (k=0; k<this->SampleDimensions[2]; k++)
    {
    for (i=0; i<this->SampleDimensions[0]; i++)
      {
      s->SetScalar(i+k*d01, this->CapValue);
      }
    }

  j = this->SampleDimensions[1] - 1;
  idx = j*this->SampleDimensions[0];
  for (k=0; k<this->SampleDimensions[2]; k++)
    {
    for (i=0; i<this->SampleDimensions[0]; i++)
      {
      s->SetScalar(idx+i+k*d01, this->CapValue);
      }
    }
}

void vtkSampleFunction::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkStructuredPointsSource::PrintSelf(os,indent);

  os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", "
               << this->SampleDimensions[1] << ", "
               << this->SampleDimensions[2] << ")\n";
  os << indent << "ModelBounds: \n";
  os << indent << "  Xmin,Xmax: (" << this->ModelBounds[0] << ", " << this->ModelBounds[1] << ")\n";
  os << indent << "  Ymin,Ymax: (" << this->ModelBounds[2] << ", " << this->ModelBounds[3] << ")\n";
  os << indent << "  Zmin,Zmax: (" << this->ModelBounds[4] << ", " << this->ModelBounds[5] << ")\n";

  if ( this->Scalars )
    {
    os << indent << "Scalars: " << this->Scalars << "\n";
    }
  else
    {
    os << indent << "Scalars: (none)\n";
    }

  if ( this->ImplicitFunction )
    {
    os << indent << "Implicit Function: " << this->ImplicitFunction << "\n";
    }
  else
    {
    os << indent << "No Implicit function defined\n";
    }

  os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
  os << indent << "Cap Value: " << this->CapValue << "\n";

  os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n");
}

<commit_msg>ENH:Code more readable<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkSampleFunction.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkSampleFunction.h"
#include "vtkMath.h"
#include "vtkScalars.h"
#include "vtkNormals.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------------
vtkSampleFunction* vtkSampleFunction::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkSampleFunction");
  if(ret)
    {
    return (vtkSampleFunction*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkSampleFunction;
}

// Construct with ModelBounds=(-1,1,-1,1,-1,1), SampleDimensions=(50,50,50),
// Capping turned off, and normal generation on.
vtkSampleFunction::vtkSampleFunction()
{
  this->ModelBounds[0] = -1.0;
  this->ModelBounds[1] = 1.0;
  this->ModelBounds[2] = -1.0;
  this->ModelBounds[3] = 1.0;
  this->ModelBounds[4] = -1.0;
  this->ModelBounds[5] = 1.0;

  this->SampleDimensions[0] = 50;
  this->SampleDimensions[1] = 50;
  this->SampleDimensions[2] = 50;

  this->Capping = 0;
  this->CapValue = VTK_LARGE_FLOAT;

  this->ImplicitFunction = NULL;

  this->ComputeNormals = 1;
  this->Scalars = NULL;
}

vtkSampleFunction::~vtkSampleFunction()
{
  this->SetScalars(NULL);
  this->SetImplicitFunction(NULL);
}

// Specify the dimensions of the data on which to sample.
void vtkSampleFunction::SetSampleDimensions(int i, int j, int k)
{
  int dim[3];

  dim[0] = i;
  dim[1] = j;
  dim[2] = k;

  this->SetSampleDimensions(dim);
}

// Specify the dimensions of the data on which to sample.
void vtkSampleFunction::SetSampleDimensions(int dim[3])
{
  vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")");

  if ( dim[0] != this->SampleDimensions[0] ||
       dim[1] != this->SampleDimensions[1] ||
       dim[2] != this->SampleDimensions[2] )
    {
    for ( int i=0; i<3; i++)
      {
      this->SampleDimensions[i] = (dim[i] > 0 ? dim[i] : 1);
      }
    this->Modified();
    }
}

void vtkSampleFunction::ExecuteInformation()
{
  int i;
  float ar[3], origin[3];
  vtkStructuredPoints *output = this->GetOutput();

  output->SetScalarType(VTK_FLOAT);
  output->SetNumberOfScalarComponents(1);

  output->SetWholeExtent(0, this->SampleDimensions[0]-1,
			 0, this->SampleDimensions[1]-1,
			 0, this->SampleDimensions[2]-1);

  output->SetDimensions(this->GetSampleDimensions());

  for (i=0; i < 3; i++)
    {
    origin[i] = this->ModelBounds[2*i];
    if ( this->SampleDimensions[i] <= 1 )
      {
      ar[i] = 1;
      }
    else
      {
      ar[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i])
              / (this->SampleDimensions[i] - 1);
      }
    }
  output->SetOrigin(origin);
  output->SetSpacing(ar);
}

void vtkSampleFunction::Execute()
{
  int ptId;
  vtkNormals *newNormals=NULL;
  int numPts;
  float *p, s;
  vtkStructuredPoints *output = this->GetOutput();

  vtkDebugMacro(<< "Sampling implicit function");
  //
  // Initialize self; create output objects
  //

  if ( !this->ImplicitFunction )
    {
    vtkErrorMacro(<<"No implicit function specified");
    return;
    }

  numPts = this->SampleDimensions[0] * this->SampleDimensions[1]
           * this->SampleDimensions[2];

  if (this->Scalars == NULL)
    {
    this->Scalars = vtkScalars::New(); //ref count is 1
    this->Scalars->Register(this);
    this->Scalars->Delete();
    }
  this->Scalars->SetNumberOfScalars(numPts);

  //
  // Traverse all points evaluating implicit function at each point
  //
  for (ptId=0; ptId < numPts; ptId++ )
    {
    p = output->GetPoint(ptId);
    s = this->ImplicitFunction->FunctionValue(p);
    this->Scalars->SetScalar(ptId,s);
    }
  //
  // If normal computation turned on, compute them
  //
  if ( this->ComputeNormals )
    {
    float n[3];
    newNormals = vtkNormals::New();
    newNormals->SetNumberOfNormals(numPts);
    for (ptId=0; ptId < numPts; ptId++ )
      {
      p = output->GetPoint(ptId);
      this->ImplicitFunction->FunctionGradient(p, n);
      n[0] *= -1;
      n[1] *= -1;
      n[2] *= -1;
      vtkMath::Normalize(n);
      newNormals->SetNormal(ptId,n);
      }
    }
  //
  // If capping is turned on, set the distances of the outside of the volume
  // to the CapValue.
  //
  if ( this->Capping )
    {
    this->Cap(this->Scalars);
    }
  //
  // Update self
  //
  output->GetPointData()->SetScalars(this->Scalars); //ref count is now 2

  if (newNormals)
    {
    output->GetPointData()->SetNormals(newNormals);
    newNormals->Delete();
    }
}

unsigned long vtkSampleFunction::GetMTime()
{
  unsigned long mTime=this->vtkSource::GetMTime();
  unsigned long impFuncMTime;

  if ( this->ImplicitFunction != NULL )
    {
    impFuncMTime = this->ImplicitFunction->GetMTime();
    mTime = ( impFuncMTime > mTime ? impFuncMTime : mTime );
    }

  return mTime;
}

void vtkSampleFunction::Cap(vtkScalars *s)
{
  int i,j,k;
  int idx;
  int d01=this->SampleDimensions[0]*this->SampleDimensions[1];

// i-j planes
  k = 0;
  for (j=0; j<this->SampleDimensions[1]; j++)
    {
    for (i=0; i<this->SampleDimensions[0]; i++)
      {
      s->SetScalar(i+j*this->SampleDimensions[1], this->CapValue);
      }
    }

  k = this->SampleDimensions[2] - 1;
  idx = k*d01;
  for (j=0; j<this->SampleDimensions[1]; j++)
    {
    for (i=0; i<this->SampleDimensions[0]; i++)
      {
      s->SetScalar(idx+i+j*this->SampleDimensions[1], this->CapValue);
      }
    }

// j-k planes
  i = 0;
  for (k=0; k<this->SampleDimensions[2]; k++)
    {
    for (j=0; j<this->SampleDimensions[1]; j++)
      {
      s->SetScalar(j*this->SampleDimensions[0]+k*d01, this->CapValue);
      }
    }

  i = this->SampleDimensions[0] - 1;
  for (k=0; k<this->SampleDimensions[2]; k++)
    {
    for (j=0; j<this->SampleDimensions[1]; j++)
      {
      s->SetScalar(i+j*this->SampleDimensions[0]+k*d01, this->CapValue);
      }
    }

// i-k planes
  j = 0;
  for (k=0; k<this->SampleDimensions[2]; k++)
    {
    for (i=0; i<this->SampleDimensions[0]; i++)
      {
      s->SetScalar(i+k*d01, this->CapValue);
      }
    }

  j = this->SampleDimensions[1] - 1;
  idx = j*this->SampleDimensions[0];
  for (k=0; k<this->SampleDimensions[2]; k++)
    {
    for (i=0; i<this->SampleDimensions[0]; i++)
      {
      s->SetScalar(idx+i+k*d01, this->CapValue);
      }
    }
}

void vtkSampleFunction::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkStructuredPointsSource::PrintSelf(os,indent);

  os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", "
               << this->SampleDimensions[1] << ", "
               << this->SampleDimensions[2] << ")\n";
  os << indent << "ModelBounds: \n";
  os << indent << "  Xmin,Xmax: (" << this->ModelBounds[0]
     << ", " << this->ModelBounds[1] << ")\n";
  os << indent << "  Ymin,Ymax: (" << this->ModelBounds[2]
     << ", " << this->ModelBounds[3] << ")\n";
  os << indent << "  Zmin,Zmax: (" << this->ModelBounds[4]
     << ", " << this->ModelBounds[5] << ")\n";

  if ( this->Scalars )
    {
    os << indent << "Scalars: " << this->Scalars << "\n";
    }
  else
    {
    os << indent << "Scalars: (none)\n";
    }

  if ( this->ImplicitFunction )
    {
    os << indent << "Implicit Function: " << this->ImplicitFunction << "\n";
    }
  else
    {
    os << indent << "No Implicit function defined\n";
    }

  os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
  os << indent << "Cap Value: " << this->CapValue << "\n";

  os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n");
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkVolumeProperty.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/

#include "vtkVolumeProperty.h"

// Construct a new vtkVolumeProperty with default values
vtkVolumeProperty::vtkVolumeProperty()
{
  this->InterpolationType		= VTK_NEAREST_INTERPOLATION;

  this->ColorChannels			= 1;

  this->GrayTransferFunction		= NULL;
  this->RGBTransferFunction		= NULL;
  this->ScalarOpacity			= NULL;
  this->GradientOpacity			= NULL;

  this->Shade				= 0;
  this->Ambient				= 0.1;
  this->Diffuse				= 0.7;
  this->Specular			= 0.2;
  this->SpecularPower			= 10.0;
  this->RGBTextureCoefficient           = 0.0;
}

// Destruct a vtkVolumeProperty
vtkVolumeProperty::~vtkVolumeProperty()
{
  if (this->GrayTransferFunction != NULL)
    {
    this->GrayTransferFunction->UnRegister(this);
    }

  if (this->RGBTransferFunction != NULL)
    {
    this->RGBTransferFunction->UnRegister(this);
    }

  if (this->ScalarOpacity != NULL)
    {
    this->ScalarOpacity->UnRegister(this);
    }

  if (this->GradientOpacity != NULL)
    {
    this->GradientOpacity->UnRegister(this);
    }
}

void vtkVolumeProperty::UpdateMTimes()
{
  this->Modified();
  this->GrayTransferFunctionMTime.Modified();
  this->RGBTransferFunctionMTime.Modified();
  this->ScalarOpacityMTime.Modified();
  this->GradientOpacityMTime.Modified();
}

void vtkVolumeProperty::SetGradientOpacityScale( float v )
{
  vtkWarningMacro( << "This is an obsolete method.\n" <<
    "Set the opacity scale in the vtkEncodedGradientEstimator" );
}

float vtkVolumeProperty::GetGradientOpacityScale( )
{
  vtkWarningMacro( << "This is an obsolete method.\n" <<
    "Get the opacity scale from the vtkEncodedGradientEstimator" );

  return 0;
}

void vtkVolumeProperty::SetGradientOpacityBias( float v )
{
  vtkErrorMacro( << "This is an obsolete method.\n" <<
    "Set the opacity bias in the vtkEncodedGradientEstimator" );
}

float vtkVolumeProperty::GetGradientOpacityBias( )
{
  vtkWarningMacro( << "This is an obsolete method.\n" <<
    "Get the opacity bias from the vtkEncodedGradientEstimator" );
  return 0.0;
}

unsigned long int vtkVolumeProperty::GetMTime()
{
  unsigned long mTime=this->vtkObject::GetMTime();
  unsigned long time;

  // Color MTimes
  if (this->ColorChannels == 1)
    {
    if (this->GrayTransferFunction)
      {
      // time that Gray transfer function pointer was set
      time = this->GrayTransferFunctionMTime;
      mTime = (mTime > time ? mTime : time);

      // time that Gray transfer function was last modified
      time = this->GrayTransferFunction->GetMTime();
      mTime = (mTime > time ? mTime : time);
      }
    }
  else if (this->ColorChannels == 3)
    {
    if (this->RGBTransferFunction)
      {
      // time that RGB transfer function pointer was set
      time = this->RGBTransferFunctionMTime;
      mTime = (mTime > time ? mTime : time);

      // time that RGB transfer function was last modified
      time = this->RGBTransferFunction->GetMTime();
      mTime = (mTime > time ? mTime : time);
      }
    }

  // Opacity MTimes
  if (this->ScalarOpacity)
    {
    // time that Scalar opacity transfer function pointer was set
    time = this->ScalarOpacityMTime;
    mTime = (mTime > time ? mTime : time);

    // time that Scalar opacity transfer function was last modified
    time = this->ScalarOpacity->GetMTime();
    mTime = (mTime > time ? mTime : time);
    }

  if (this->GradientOpacity)
    {
    // time that Gradient opacity transfer function pointer was set
    time = this->GradientOpacityMTime;
    mTime = (mTime > time ? mTime : time);

    // time that Gradient opacity transfer function was last modified
    time = this->GradientOpacity->GetMTime();
    mTime = (mTime > time ? mTime : time);
    }

  return mTime;
}

// Set the color of a volume to a gray transfer function
void vtkVolumeProperty::SetColor( vtkPiecewiseFunction *function )
{
  if (this->GrayTransferFunction != function )
    {
    if (this->GrayTransferFunction != NULL)
      {
      this->GrayTransferFunction->UnRegister(this);
      }
    this->GrayTransferFunction	= function;
    if (this->GrayTransferFunction != NULL)
      {
      this->GrayTransferFunction->Register(this);
      }

    this->GrayTransferFunctionMTime.Modified();
    this->Modified();
    }

  if (this->ColorChannels != 1 )
    {
    this->ColorChannels		= 1;
    this->Modified();
    }
}

// Get the currently set gray transfer function. Create one if none set.
vtkPiecewiseFunction *vtkVolumeProperty::GetGrayTransferFunction()
{
  if (this->GrayTransferFunction == NULL )
    {
    this->GrayTransferFunction = vtkPiecewiseFunction::New();
    this->GrayTransferFunction->Register(this);
    this->GrayTransferFunction->Delete();
    this->GrayTransferFunction->AddPoint(    0, 0.0 );
    this->GrayTransferFunction->AddPoint( 1024, 1.0 );
    }

  return this->GrayTransferFunction;
}

// Set the color of a volume to an RGB transfer function
void vtkVolumeProperty::SetColor( vtkColorTransferFunction *function )
{
  if (this->RGBTransferFunction != function )
    {
    if (this->RGBTransferFunction != NULL)
      {
      this->RGBTransferFunction->UnRegister(this);
      }
    this->RGBTransferFunction	= function;
    if (this->RGBTransferFunction != NULL)
      {
      this->RGBTransferFunction->Register(this);
      }
    this->RGBTransferFunctionMTime.Modified();
    this->Modified();
    }

  if (this->ColorChannels != 3 )
    {
    this->ColorChannels		= 3;
    this->Modified();
    }
}

// Get the currently set RGB transfer function. Create one if none set.
vtkColorTransferFunction *vtkVolumeProperty::GetRGBTransferFunction()
{
  if (this->RGBTransferFunction == NULL )
    {
    this->RGBTransferFunction = vtkColorTransferFunction::New();
    this->RGBTransferFunction->Register(this);
    this->RGBTransferFunction->Delete();
    this->RGBTransferFunction->AddRedPoint(      0, 0.0 );
    this->RGBTransferFunction->AddRedPoint(   1024, 1.0 );
    this->RGBTransferFunction->AddGreenPoint(    0, 0.0 );
    this->RGBTransferFunction->AddGreenPoint( 1024, 1.0 );
    this->RGBTransferFunction->AddBluePoint(     0, 0.0 );
    this->RGBTransferFunction->AddBluePoint(  1024, 1.0 );
    }

  return this->RGBTransferFunction;
}

// Set the scalar opacity of a volume to a transfer function
void vtkVolumeProperty::SetScalarOpacity( vtkPiecewiseFunction *function )
{
  if ( this->ScalarOpacity != function )
    {
    if (this->ScalarOpacity != NULL)
      {
      this->ScalarOpacity->UnRegister(this);
      }
    this->ScalarOpacity	= function;
    if (this->ScalarOpacity != NULL)
      {
      this->ScalarOpacity->Register(this);
      }

    this->ScalarOpacityMTime.Modified();
    this->Modified();
    }
}

// Get the scalar opacity transfer function. Create one if none set.
vtkPiecewiseFunction *vtkVolumeProperty::GetScalarOpacity()
{
  if( this->ScalarOpacity == NULL )
    {
    this->ScalarOpacity = vtkPiecewiseFunction::New();
    this->ScalarOpacity->Register(this);
    this->ScalarOpacity->Delete();
    this->ScalarOpacity->AddPoint(    0, 1.0 );
    this->ScalarOpacity->AddPoint( 1024, 1.0 );
    }

  return this->ScalarOpacity;
}

// Set the gradient opacity transfer function
void vtkVolumeProperty::SetGradientOpacity( vtkPiecewiseFunction *function )
{
  if ( this->GradientOpacity != function )
    {
    if (this->GradientOpacity != NULL)
      {
      this->GradientOpacity->UnRegister(this);
      }
    this->GradientOpacity	= function;
    if (this->GradientOpacity != NULL)
      {
      this->GradientOpacity->Register(this);
      }

    this->GradientOpacityMTime.Modified();
    this->Modified();
    }
}

// Get the gradient opacity transfer function. Create one if none set.
vtkPiecewiseFunction *vtkVolumeProperty::GetGradientOpacity()
{
  if ( this->GradientOpacity == NULL )
    {
    this->GradientOpacity = vtkPiecewiseFunction::New();
    this->GradientOpacity->Register(this);
    this->GradientOpacity->Delete();
    this->GradientOpacity->AddPoint(   0, 1.0 );
    this->GradientOpacity->AddPoint( 255, 1.0 );
    }

  return this->GradientOpacity;
}

// Print the state of the volume property.
void vtkVolumeProperty::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os,indent);

  os << indent << "Interpolation Type: "
     << this->GetInterpolationTypeAsString() << "\n";

  os << indent << "Color Channels: " << this->ColorChannels << "\n";

  if( this->ColorChannels == 1 )
    {
      os << indent << "Gray Color Transfer Function: " \
	 << this->GrayTransferFunction << "\n";
    }
  else if( this->ColorChannels == 3 )
    {
      os << indent << "RGB Color Transfer Function: " \
	 << this->RGBTransferFunction << "\n";
    }

  os << indent << "Scalar Opacity Transfer Function: " \
     << this->ScalarOpacity << "\n";

  os << indent << "Gradient Opacity Transfer Function: " \
     << this->GradientOpacity << "\n";

  os << indent << "Shade: " << this->Shade << "\n";

  if( this->Shade )
    {
    os << indent << indent << "Ambient: " << this->Ambient << "\n";
    os << indent << indent << "Diffuse: " << this->Diffuse << "\n";
    os << indent << indent << "Specular: " << this->Specular << "\n";
    os << indent << indent << "SpecularPower: " << this->SpecularPower << "\n";
    }

  // These variables should not be printed to the user:
  // this->GradientOpacityMTime
  // this->GrayTransferFunctionMTime
  // this->RGBTransferFunctionMTime
  // this->ScalarOpacityMTime

}

<commit_msg>ERR: Fixed printself defect<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkVolumeProperty.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/

#include "vtkVolumeProperty.h"

// Construct a new vtkVolumeProperty with default values
vtkVolumeProperty::vtkVolumeProperty()
{
  this->InterpolationType		= VTK_NEAREST_INTERPOLATION;

  this->ColorChannels			= 1;

  this->GrayTransferFunction		= NULL;
  this->RGBTransferFunction		= NULL;
  this->ScalarOpacity			= NULL;
  this->GradientOpacity			= NULL;

  this->Shade				= 0;
  this->Ambient				= 0.1;
  this->Diffuse				= 0.7;
  this->Specular			= 0.2;
  this->SpecularPower			= 10.0;
  this->RGBTextureCoefficient           = 0.0;
}

// Destruct a vtkVolumeProperty
vtkVolumeProperty::~vtkVolumeProperty()
{
  if (this->GrayTransferFunction != NULL)
    {
    this->GrayTransferFunction->UnRegister(this);
    }

  if (this->RGBTransferFunction != NULL)
    {
    this->RGBTransferFunction->UnRegister(this);
    }

  if (this->ScalarOpacity != NULL)
    {
    this->ScalarOpacity->UnRegister(this);
    }

  if (this->GradientOpacity != NULL)
    {
    this->GradientOpacity->UnRegister(this);
    }
}

void vtkVolumeProperty::UpdateMTimes()
{
  this->Modified();
  this->GrayTransferFunctionMTime.Modified();
  this->RGBTransferFunctionMTime.Modified();
  this->ScalarOpacityMTime.Modified();
  this->GradientOpacityMTime.Modified();
}

void vtkVolumeProperty::SetGradientOpacityScale( float v )
{
  vtkWarningMacro( << "This is an obsolete method.\n" <<
    "Set the opacity scale in the vtkEncodedGradientEstimator" );
}

float vtkVolumeProperty::GetGradientOpacityScale( )
{
  vtkWarningMacro( << "This is an obsolete method.\n" <<
    "Get the opacity scale from the vtkEncodedGradientEstimator" );

  return 0;
}

void vtkVolumeProperty::SetGradientOpacityBias( float v )
{
  vtkErrorMacro( << "This is an obsolete method.\n" <<
    "Set the opacity bias in the vtkEncodedGradientEstimator" );
}

float vtkVolumeProperty::GetGradientOpacityBias( )
{
  vtkWarningMacro( << "This is an obsolete method.\n" <<
    "Get the opacity bias from the vtkEncodedGradientEstimator" );
  return 0.0;
}

unsigned long int vtkVolumeProperty::GetMTime()
{
  unsigned long mTime=this->vtkObject::GetMTime();
  unsigned long time;

  // Color MTimes
  if (this->ColorChannels == 1)
    {
    if (this->GrayTransferFunction)
      {
      // time that Gray transfer function pointer was set
      time = this->GrayTransferFunctionMTime;
      mTime = (mTime > time ? mTime : time);

      // time that Gray transfer function was last modified
      time = this->GrayTransferFunction->GetMTime();
      mTime = (mTime > time ? mTime : time);
      }
    }
  else if (this->ColorChannels == 3)
    {
    if (this->RGBTransferFunction)
      {
      // time that RGB transfer function pointer was set
      time = this->RGBTransferFunctionMTime;
      mTime = (mTime > time ? mTime : time);

      // time that RGB transfer function was last modified
      time = this->RGBTransferFunction->GetMTime();
      mTime = (mTime > time ? mTime : time);
      }
    }

  // Opacity MTimes
  if (this->ScalarOpacity)
    {
    // time that Scalar opacity transfer function pointer was set
    time = this->ScalarOpacityMTime;
    mTime = (mTime > time ? mTime : time);

    // time that Scalar opacity transfer function was last modified
    time = this->ScalarOpacity->GetMTime();
    mTime = (mTime > time ? mTime : time);
    }

  if (this->GradientOpacity)
    {
    // time that Gradient opacity transfer function pointer was set
    time = this->GradientOpacityMTime;
    mTime = (mTime > time ? mTime : time);

    // time that Gradient opacity transfer function was last modified
    time = this->GradientOpacity->GetMTime();
    mTime = (mTime > time ? mTime : time);
    }

  return mTime;
}

// Set the color of a volume to a gray transfer function
void vtkVolumeProperty::SetColor( vtkPiecewiseFunction *function )
{
  if (this->GrayTransferFunction != function )
    {
    if (this->GrayTransferFunction != NULL)
      {
      this->GrayTransferFunction->UnRegister(this);
      }
    this->GrayTransferFunction	= function;
    if (this->GrayTransferFunction != NULL)
      {
      this->GrayTransferFunction->Register(this);
      }

    this->GrayTransferFunctionMTime.Modified();
    this->Modified();
    }

  if (this->ColorChannels != 1 )
    {
    this->ColorChannels		= 1;
    this->Modified();
    }
}

// Get the currently set gray transfer function. Create one if none set.
vtkPiecewiseFunction *vtkVolumeProperty::GetGrayTransferFunction()
{
  if (this->GrayTransferFunction == NULL )
    {
    this->GrayTransferFunction = vtkPiecewiseFunction::New();
    this->GrayTransferFunction->Register(this);
    this->GrayTransferFunction->Delete();
    this->GrayTransferFunction->AddPoint(    0, 0.0 );
    this->GrayTransferFunction->AddPoint( 1024, 1.0 );
    }

  return this->GrayTransferFunction;
}

// Set the color of a volume to an RGB transfer function
void vtkVolumeProperty::SetColor( vtkColorTransferFunction *function )
{
  if (this->RGBTransferFunction != function )
    {
    if (this->RGBTransferFunction != NULL)
      {
      this->RGBTransferFunction->UnRegister(this);
      }
    this->RGBTransferFunction	= function;
    if (this->RGBTransferFunction != NULL)
      {
      this->RGBTransferFunction->Register(this);
      }
    this->RGBTransferFunctionMTime.Modified();
    this->Modified();
    }

  if (this->ColorChannels != 3 )
    {
    this->ColorChannels		= 3;
    this->Modified();
    }
}

// Get the currently set RGB transfer function. Create one if none set.
vtkColorTransferFunction *vtkVolumeProperty::GetRGBTransferFunction()
{
  if (this->RGBTransferFunction == NULL )
    {
    this->RGBTransferFunction = vtkColorTransferFunction::New();
    this->RGBTransferFunction->Register(this);
    this->RGBTransferFunction->Delete();
    this->RGBTransferFunction->AddRedPoint(      0, 0.0 );
    this->RGBTransferFunction->AddRedPoint(   1024, 1.0 );
    this->RGBTransferFunction->AddGreenPoint(    0, 0.0 );
    this->RGBTransferFunction->AddGreenPoint( 1024, 1.0 );
    this->RGBTransferFunction->AddBluePoint(     0, 0.0 );
    this->RGBTransferFunction->AddBluePoint(  1024, 1.0 );
    }

  return this->RGBTransferFunction;
}

// Set the scalar opacity of a volume to a transfer function
void vtkVolumeProperty::SetScalarOpacity( vtkPiecewiseFunction *function )
{
  if ( this->ScalarOpacity != function )
    {
    if (this->ScalarOpacity != NULL)
      {
      this->ScalarOpacity->UnRegister(this);
      }
    this->ScalarOpacity	= function;
    if (this->ScalarOpacity != NULL)
      {
      this->ScalarOpacity->Register(this);
      }

    this->ScalarOpacityMTime.Modified();
    this->Modified();
    }
}

// Get the scalar opacity transfer function. Create one if none set.
vtkPiecewiseFunction *vtkVolumeProperty::GetScalarOpacity()
{
  if( this->ScalarOpacity == NULL )
    {
    this->ScalarOpacity = vtkPiecewiseFunction::New();
    this->ScalarOpacity->Register(this);
    this->ScalarOpacity->Delete();
    this->ScalarOpacity->AddPoint(    0, 1.0 );
    this->ScalarOpacity->AddPoint( 1024, 1.0 );
    }

  return this->ScalarOpacity;
}

// Set the gradient opacity transfer function
void vtkVolumeProperty::SetGradientOpacity( vtkPiecewiseFunction *function )
{
  if ( this->GradientOpacity != function )
    {
    if (this->GradientOpacity != NULL)
      {
      this->GradientOpacity->UnRegister(this);
      }
    this->GradientOpacity	= function;
    if (this->GradientOpacity != NULL)
      {
      this->GradientOpacity->Register(this);
      }

    this->GradientOpacityMTime.Modified();
    this->Modified();
    }
}

// Get the gradient opacity transfer function. Create one if none set.
vtkPiecewiseFunction *vtkVolumeProperty::GetGradientOpacity()
{
  if ( this->GradientOpacity == NULL )
    {
    this->GradientOpacity = vtkPiecewiseFunction::New();
    this->GradientOpacity->Register(this);
    this->GradientOpacity->Delete();
    this->GradientOpacity->AddPoint(   0, 1.0 );
    this->GradientOpacity->AddPoint( 255, 1.0 );
    }

  return this->GradientOpacity;
}

// Print the state of the volume property.
void vtkVolumeProperty::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os,indent);

  os << indent << "Interpolation Type: "
     << this->GetInterpolationTypeAsString() << "\n";

  os << indent << "Color Channels: " << this->ColorChannels << "\n";

  if( this->ColorChannels == 1 )
    {
      os << indent << "Gray Color Transfer Function: "
	 << this->GrayTransferFunction << "\n";
    }
  else if( this->ColorChannels == 3 )
    {
      os << indent << "RGB Color Transfer Function: "
	 << this->RGBTransferFunction << "\n";
    }

  os << indent << "Scalar Opacity Transfer Function: "
     << this->ScalarOpacity << "\n";

  os << indent << "Gradient Opacity Transfer Function: "
     << this->GradientOpacity << "\n";

  os << indent << "RGB Texture Coefficient: "
     << this->RGBTextureCoefficient << endl;

  os << indent << "Shade: " << this->Shade << "\n";
  os << indent << indent << "Ambient: " << this->Ambient << "\n";
  os << indent << indent << "Diffuse: " << this->Diffuse << "\n";
  os << indent << indent << "Specular: " << this->Specular << "\n";
  os << indent << indent << "SpecularPower: " << this->SpecularPower << "\n";

  // These variables should not be printed to the user:
  // this->GradientOpacityMTime
  // this->GrayTransferFunctionMTime
  // this->RGBTransferFunctionMTime
  // this->ScalarOpacityMTime

}

<|endoftext|>