/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkPoint_hxx #define itkPoint_hxx #include "itkNumericTraitsPointPixel.h" #include "itkMath.h" #include "itkObject.h" namespace itk { /** * Assignment from a plain array */ template Point & Point::operator=(const ValueType r[TPointDimension]) { BaseArray::operator=(r); return *this; } /** * In place increment by a vector */ template const Point & Point::operator+=(const VectorType & vec) { for (unsigned int i = 0; i < TPointDimension; ++i) { (*this)[i] += vec[i]; } return *this; } /** * In place subtract a vector */ template const Point & Point::operator-=(const VectorType & vec) { for (unsigned int i = 0; i < TPointDimension; ++i) { (*this)[i] -= vec[i]; } return *this; } /* * Add operator with a vector */ template Point Point::operator+(const VectorType & vec) const { Self result; for (unsigned int i = 0; i < TPointDimension; ++i) { result[i] = (*this)[i] + vec[i]; } return result; } /* * Subtract a vector, return a point */ template Point Point::operator-(const VectorType & vec) const { Self result; for (unsigned int i = 0; i < TPointDimension; ++i) { result[i] = (*this)[i] - vec[i]; } return result; } /* * Difference between two points */ template Vector Point::operator-(const Self & pnt) const { VectorType result; for (unsigned int i = 0; i < TPointDimension; ++i) { result[i] = (*this)[i] - pnt[i]; } return result; } /* * Return a vnl_vector_ref */ template vnl_vector_ref Point::GetVnlVector() { return vnl_vector_ref(TPointDimension, this->GetDataPointer()); } /** * Return a vnl_vector const */ template vnl_vector Point::GetVnlVector() const { return vnl_vector(this->GetDataPointer(), TPointDimension); } template auto Point::GetVectorFromOrigin() const -> VectorType { // VectorType knows how to construct from ValueType*. return &(*this)[0]; } /** * Set the point to the median point of the two arguments */ template void Point::SetToMidPoint(const Self & A, const Self & B) { for (unsigned int i = 0; i < TPointDimension; ++i) { (*this)[i] = (A[i] + B[i]) / 2.0; } } /** * Set the point to the barycentric combination of two points */ template void Point::SetToBarycentricCombination(const Self & A, const Self & B, double alpha) { const double wa = alpha; const double wb = 1.0 - alpha; for (unsigned int i = 0; i < TPointDimension; ++i) { (*this)[i] = wa * A[i] + wb * B[i]; } } /** * Set the point to the barycentric combination of three points */ template void Point::SetToBarycentricCombination(const Self & A, const Self & B, const Self & C, double weightForA, double weightForB) { const double weightForC = 1.0 - weightForA - weightForB; for (unsigned int i = 0; i < TPointDimension; ++i) { (*this)[i] = weightForA * A[i] + weightForB * B[i] + weightForC * C[i]; } } /** * Set the point to the barycentric combination of N points */ template void Point::SetToBarycentricCombination(const Self * P, const double * weights, unsigned int N) { this->Fill(T{}); // put this point to null double weightSum = 0.0; for (unsigned int j = 0; j < N - 1; ++j) { const double weight = weights[j]; weightSum += weight; for (unsigned int i = 0; i < TPointDimension; ++i) { (*this)[i] += weight * P[j][i]; } } const double weight = (1.0 - weightSum); for (unsigned int i = 0; i < TPointDimension; ++i) { (*this)[i] += weight * P[N - 1][i]; } } /** * Set the point to the barycentric combination of N points in a Container */ template auto BarycentricCombination::Evaluate(const PointContainerPointer & points, const WeightContainerType & weights) -> PointType { using ValueType = typename PointType::ValueType; PointType barycentre; barycentre.Fill(ValueType{}); // set to null typename TPointContainer::Iterator point = points->Begin(); typename TPointContainer::Iterator final = points->End(); typename TPointContainer::Iterator last = final; --last; // move to the (N)th point double weightSum = 0.0; const unsigned int PointDimension = PointType::PointDimension; unsigned int j = 0; while (point != last) { const double weight = weights[j++]; weightSum += weight; for (unsigned int i = 0; i < PointDimension; ++i) { barycentre[i] += weight * (point->Value())[i]; } ++point; } // Compute directly the last one // to make sure that the weights sum 1 const double weight = (1.0 - weightSum); for (unsigned int i = 0; i < PointDimension; ++i) { barycentre[i] += weight * (last->Value())[i]; } return barycentre; } /** * Print content to an ostream */ template std::ostream & operator<<(std::ostream & os, const Point & vct) { os << '['; if (TPointDimension == 1) { os << vct[0]; } else { for (unsigned int i = 0; i + 1 < TPointDimension; ++i) { os << vct[i] << ", "; } os << vct[TPointDimension - 1]; } os << ']'; return os; } /** * Read content from an istream */ template std::istream & operator>>(std::istream & is, Point & vct) { for (unsigned int i = 0; i < TPointDimension; ++i) { is >> vct[i]; } return is; } } // end namespace itk #endif