diff --git a/.clang-format b/.clang-format index 411b009..45b9502 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,4 @@ -## This config file is only relevant for clang-format version 8.0.0 +## This config file is only relevant for clang-format version 19.1.4 ## ## Examples of each format style can be found on the in the clang-format documentation ## See: https://clang.llvm.org/docs/ClangFormatStyleOptions.html for details of each option @@ -10,142 +10,309 @@ ## maintaining a consistent code style. ## ## EXAMPLE apply code style enforcement before commit: -# Utilities/Maintenance/clang-format.bash --clang ${PATH_TO_CLANG_FORMAT_8.0.0} --modified +# Utilities/Maintenance/clang-format.bash --clang ${PATH_TO_CLANG_FORMAT_19.1.4} --modified ## EXAMPLE apply code style enforcement after commit: -# Utilities/Maintenance/clang-format.bash --clang ${PATH_TO_CLANG_FORMAT_8.0.0} --last +# Utilities/Maintenance/clang-format.bash --clang ${PATH_TO_CLANG_FORMAT_19.1.4} --last --- -# This configuration requires clang-format version 8.0.0 exactly. -BasedOnStyle: Mozilla +# This configuration requires clang-format version 19.1.4 exactly. Language: Cpp AccessModifierOffset: -2 AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: true -AlignEscapedNewlines: Right -AlignOperands: true -AlignTrailingComments: true -# clang 9.0 AllowAllArgumentsOnNextLine: true -# clang 9.0 AllowAllConstructorInitializersOnNextLine: true +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseArrows: false + AlignCaseColons: false +AlignConsecutiveTableGenBreakingDAGArgColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenCondOperatorColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveTableGenDefinitionColons: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: false +AllowBreakBeforeNoexceptSpecifier: Never +AllowShortBlocksOnASingleLine: Never +AllowShortCaseExpressionOnASingleLine: true AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Inline -# clang 9.0 AllowShortLambdasOnASingleLine: All -# clang 9.0 features AllowShortIfStatementsOnASingleLine: Never -AllowShortIfStatementsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true +#AllowShortFunctionsOnASingleLine: Inline Only merge functions defined inside a class. Implies empty. +#AllowShortFunctionsOnASingleLine: None (in configuration: None) Never merge functions into a single line. +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: All AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability BinPackArguments: false BinPackParameters: false -BreakBeforeBraces: Custom +BitFieldColonSpacing: Both BraceWrapping: - # clang 9.0 feature AfterCaseLabel: false + AfterCaseLabel: true AfterClass: true - AfterControlStatement: true + AfterControlStatement: Always AfterEnum: true + AfterExternBlock: true AfterFunction: true AfterNamespace: true AfterObjCDeclaration: true AfterStruct: true AfterUnion: true - AfterExternBlock: true BeforeCatch: true BeforeElse: true -## This is the big change from historical ITK formatting! -# Historically ITK used a style similar to https://en.wikipedia.org/wiki/Indentation_style#Whitesmiths_style -# with indented braces, and not indented code. This style is very difficult to automatically -# maintain with code beautification tools. Not indenting braces is more common among -# formatting tools. + BeforeLambdaBody: false + BeforeWhile: false IndentBraces: false SplitEmptyFunction: false SplitEmptyRecord: false SplitEmptyNamespace: false +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave +BreakAfterJavaFieldAnnotations: false +BreakAfterReturnType: All +BreakArrays: true BreakBeforeBinaryOperators: None -#clang 6.0 BreakBeforeInheritanceComma: true -BreakInheritanceList: BeforeComma +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Custom +BreakBeforeInlineASMColon: OnlyMultiline BreakBeforeTernaryOperators: true -#clang 6.0 BreakConstructorInitializersBeforeComma: true BreakConstructorInitializers: BeforeComma -BreakAfterJavaFieldAnnotations: false +BreakFunctionDefinitionParameters: false +BreakInheritanceList: BeforeComma BreakStringLiterals: true +BreakTemplateDeclarations: Yes ## The following line allows larger lines in non-documentation code ColumnLimit: 120 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 2 ContinuationIndentWidth: 2 Cpp11BracedListStyle: false DerivePointerAlignment: false DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock ExperimentalAutoDetectBinPacking: false FixNamespaceComments: true ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE IncludeBlocks: Preserve IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 + SortPriority: 0 + CaseSensitive: false - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 + SortPriority: 0 + CaseSensitive: false - Regex: '.*' Priority: 1 + SortPriority: 0 + CaseSensitive: false IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false IndentCaseLabels: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true IndentPPDirectives: AfterHash +IndentRequiresClause: true IndentWidth: 2 IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 JavaScriptQuotes: Leave JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: true + AtStartOfFile: true +LambdaBodyIndentation: Signature +LineEnding: DeriveLF MacroBlockBegin: '' MacroBlockEnd: '' +MainIncludeChar: Quote MaxEmptyLinesToKeep: 2 NamespaceIndentation: None ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: false +PackConstructorInitializers: BinPack PenaltyBreakAssignment: 2 PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 ## The following line allows larger lines in non-documentation code PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 PenaltyBreakString: 1000 PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Middle +PPIndentWidth: -1 +QualifierAlignment: Custom +QualifierOrder: + - friend + - static + - inline + - constexpr + - const + - type +ReferenceAlignment: Pointer ReflowComments: true +RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false # We may want to sort the includes as a separate pass -SortIncludes: false +SortIncludes: Never +SortJavaStaticImport: Before # We may want to revisit this later -SortUsingDeclarations: false +SortUsingDeclarations: Never SpaceAfterCStyleCast: false -# SpaceAfterLogicalNot: false +SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false SpaceBeforeRangeBasedForLoopColon: true -SpaceInEmptyParentheses: false +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false SpacesBeforeTrailingComments: 1 -SpacesInAngles: false +SpacesInAngles: Never SpacesInContainerLiterals: false -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + ExceptDoubleParentheses: false + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false SpacesInSquareBrackets: false -Standard: Cpp11 +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT StatementMacros: - Q_UNUSED - QT_REQUIRE_VERSION + - ITK_GCC_PRAGMA_PUSH + - ITK_GCC_PRAGMA_POP + - ITK_GCC_SUPPRESS_Wfloat_equal + - ITK_GCC_SUPPRESS_Wformat_nonliteral + - ITK_GCC_SUPPRESS_Warray_bounds + - ITK_CLANG_PRAGMA_PUSH + - ITK_CLANG_PRAGMA_POP + - ITK_CLANG_SUPPRESS_Wzero_as_null_pointer_constant + - CLANG_PRAGMA_PUSH + - CLANG_PRAGMA_POP + - CLANG_SUPPRESS_Wfloat_equal + - INTEL_PRAGMA_WARN_PUSH + - INTEL_PRAGMA_WARN_POP + - INTEL_SUPPRESS_warning_1292 + - itkTemplateFloatingToIntegerMacro + - itkLegacyMacro +TableGenBreakInsideDAGArg: DontBreak TabWidth: 2 UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE ... diff --git a/include/itkPointFeature.h b/include/itkPointFeature.h index 885d1a6..c904bdf 100644 --- a/include/itkPointFeature.h +++ b/include/itkPointFeature.h @@ -65,7 +65,7 @@ class PointFeature : public itk::MeshToMeshFilter>; using PointsLocatorTypePointer = typename PointsLocatorType::Pointer; - //using FeatureType = std::vector; + // using FeatureType = std::vector; using FeatureType = typename itk::VectorContainer; using FeatureTypePointer = typename FeatureType::Pointer; @@ -76,12 +76,12 @@ class PointFeature : public itk::MeshToMeshFilter -PointFeature -::PointFeature() +PointFeature::PointFeature() {} template -typename PointFeature::Vector4d -PointFeature::ComputePairFeatures(const Vector3d &p1, - const Vector3d &n1, - const Vector3d &p2, - const Vector3d &n2) { - Vector4d result; - Vector3d dp2p1 = p2 - p1; - result[3] = dp2p1.GetNorm(); - - if (result[3] == 0.0){ - return Vector4d(); - } +typename PointFeature::Vector4d +PointFeature::ComputePairFeatures(const Vector3d & p1, + const Vector3d & n1, + const Vector3d & p2, + const Vector3d & n2) +{ + Vector4d result; + Vector3d dp2p1 = p2 - p1; + result[3] = dp2p1.GetNorm(); - auto n1_copy = n1; - auto n2_copy = n2; - - double angle1 = n1_copy * (dp2p1) / result[3]; - double angle2 = n2_copy * (dp2p1) / result[3]; - if (std::acos(std::fabs(angle1)) > std::acos(std::fabs(angle2))) { - n1_copy = n2; - n2_copy = n1; - dp2p1 *= -1.0; - result[2] = -angle2; - } else { - result[2] = angle1; - } + if (result[3] == 0.0) + { + return Vector4d(); + } - auto v = itk::CrossProduct(dp2p1, n1_copy); - double v_norm = v.GetNorm(); - if (v_norm == 0.0) { - return Vector4d(); - } - v /= v_norm; - auto w = itk::CrossProduct(n1_copy, v); - result[1] = v * (n2_copy); - result[0] = std::atan2(w * (n2_copy), n1_copy * (n2_copy)); + auto n1_copy = n1; + auto n2_copy = n2; + + double angle1 = n1_copy * (dp2p1) / result[3]; + double angle2 = n2_copy * (dp2p1) / result[3]; + if (std::acos(std::fabs(angle1)) > std::acos(std::fabs(angle2))) + { + n1_copy = n2; + n2_copy = n1; + dp2p1 *= -1.0; + result[2] = -angle2; + } + else + { + result[2] = angle1; + } + + auto v = itk::CrossProduct(dp2p1, n1_copy); + double v_norm = v.GetNorm(); + if (v_norm == 0.0) + { + return Vector4d(); + } + v /= v_norm; + auto w = itk::CrossProduct(n1_copy, v); + result[1] = v * (n2_copy); + result[0] = std::atan2(w * (n2_copy), n1_copy * (n2_copy)); - return result; + return result; } template typename PointFeature::FeatureTypePointer -PointFeature::ComputeSPFHFeature( - TInputPointSet * input, - TInputPointSet * input_normals, - double radius, - unsigned int neighbors) - { - PointsLocatorTypePointer kdtree = PointsLocatorType::New(); - kdtree->SetPoints(input->GetPoints()); - kdtree->Initialize(); +PointFeature::ComputeSPFHFeature(TInputPointSet * input, + TInputPointSet * input_normals, + double radius, + unsigned int neighbors) +{ + PointsLocatorTypePointer kdtree = PointsLocatorType::New(); + kdtree->SetPoints(input->GetPoints()); + kdtree->Initialize(); + + unsigned long int num_of_points = input->GetNumberOfPoints(); + std::vector feature1(33 * num_of_points, 0); + + auto ProcessPoint = [&](int i) { + auto point = input->GetPoint(i); + auto normal = input_normals->GetPoint(i); - unsigned long int num_of_points = input->GetNumberOfPoints(); - std::vector feature1(33 * num_of_points, 0); + typename PointsLocatorType::NeighborsIdentifierType indices; + kdtree->FindClosestNPoints(point, neighbors, indices); - auto ProcessPoint = [&] (int i) + if (indices.size() > 1) { - auto point = input->GetPoint(i); - auto normal = input_normals->GetPoint(i); - - typename PointsLocatorType::NeighborsIdentifierType indices; - kdtree->FindClosestNPoints(point, neighbors, indices); + std::vector> neighbor_vect; + neighbor_vect.reserve(indices.size()); - if (indices.size() > 1) + for (size_t k = 0; k < indices.size(); k++) + { + auto point_diff = point - input->GetPoint(indices[k]); + double dist = point_diff.GetNorm(); + + // skip the point itself + if (dist == 0.0) + continue; + + if (dist < radius) { - std::vector< std::pair > neighbor_vect; - neighbor_vect.reserve(indices.size()); - - for (size_t k = 0; k < indices.size(); k++) - { - auto point_diff = point - input->GetPoint(indices[k]); - double dist = point_diff.GetNorm(); - - // skip the point itself - if (dist == 0.0) - continue; - - if (dist < radius) - { - dist = dist*dist; - neighbor_vect.push_back( std::make_pair(dist, indices[k])); - } - } - - unsigned int neighbor_count = std::min(neighbors, (unsigned int)neighbor_vect.size()); - - // only compute SPFH feature when a point has neighbors - double hist_incr = 100.0 / (double)neighbor_count; - for (size_t k = 0; k < neighbor_count; k++) - { - auto point2 = input->GetPoint(neighbor_vect[k].second); - auto normal2 = input_normals->GetPoint(neighbor_vect[k].second); - - Vector3d temp_point_vector1, temp_point_vector2; - Vector3d temp_normal_vector1, temp_normal_vector2; - - // skip the point itself, compute histogram - for (int ik = 0; ik < 3; ++ik) - { - temp_point_vector1[ik] = point[ik]; - temp_normal_vector1[ik] = normal[ik]; - temp_point_vector2[ik] = point2[ik]; - temp_normal_vector2[ik] = normal2[ik]; - } - - Vector4d pair_feature = ComputePairFeatures(temp_point_vector1, temp_normal_vector1, - temp_point_vector2, - temp_normal_vector2); - - int h_index = (int)(floor(11 * (pair_feature[0] + itk::Math::pi) / (2.0 * itk::Math::pi))); - if (h_index < 0) - { - h_index = 0; - } - if (h_index >= 11) - { - h_index = 10; - } - unsigned int temp_index = h_index*num_of_points + i; - feature1[temp_index] = hist_incr + feature1[temp_index]; - - h_index = (int)(floor(11 * (pair_feature[1] + 1.0) * 0.5)); - if (h_index < 0) - { - h_index = 0; - } - if (h_index >= 11) - { - h_index = 10; - } - temp_index = (h_index + 11)*num_of_points + i; - feature1[temp_index] = hist_incr + feature1[temp_index]; - - h_index = (int)(floor(11 * (pair_feature[2] + 1.0) * 0.5)); - if (h_index < 0) - { - h_index = 0; - } - if (h_index >= 11) - { - h_index = 10; - } - temp_index = (h_index + 22)*num_of_points + i; - feature1[temp_index] = hist_incr + feature1[temp_index]; - } + dist = dist * dist; + neighbor_vect.push_back(std::make_pair(dist, indices[k])); } - }; + } - itk::MultiThreaderBase::Pointer mt = itk::MultiThreaderBase::New(); - mt->ParallelizeArray(0, num_of_points, ProcessPoint, nullptr); + unsigned int neighbor_count = std::min(neighbors, (unsigned int)neighbor_vect.size()); + + // only compute SPFH feature when a point has neighbors + double hist_incr = 100.0 / (double)neighbor_count; + for (size_t k = 0; k < neighbor_count; k++) + { + auto point2 = input->GetPoint(neighbor_vect[k].second); + auto normal2 = input_normals->GetPoint(neighbor_vect[k].second); + + Vector3d temp_point_vector1, temp_point_vector2; + Vector3d temp_normal_vector1, temp_normal_vector2; + + // skip the point itself, compute histogram + for (int ik = 0; ik < 3; ++ik) + { + temp_point_vector1[ik] = point[ik]; + temp_normal_vector1[ik] = normal[ik]; + temp_point_vector2[ik] = point2[ik]; + temp_normal_vector2[ik] = normal2[ik]; + } - // This is done to optimize the code by avoiding GetElement, SetElement overhead. - auto feature = FeatureType::New(); - feature->CastToSTLContainer() = feature1; - return feature; + Vector4d pair_feature = + ComputePairFeatures(temp_point_vector1, temp_normal_vector1, temp_point_vector2, temp_normal_vector2); + + int h_index = (int)(floor(11 * (pair_feature[0] + itk::Math::pi) / (2.0 * itk::Math::pi))); + if (h_index < 0) + { + h_index = 0; + } + if (h_index >= 11) + { + h_index = 10; + } + unsigned int temp_index = h_index * num_of_points + i; + feature1[temp_index] = hist_incr + feature1[temp_index]; + + h_index = (int)(floor(11 * (pair_feature[1] + 1.0) * 0.5)); + if (h_index < 0) + { + h_index = 0; + } + if (h_index >= 11) + { + h_index = 10; + } + temp_index = (h_index + 11) * num_of_points + i; + feature1[temp_index] = hist_incr + feature1[temp_index]; + + h_index = (int)(floor(11 * (pair_feature[2] + 1.0) * 0.5)); + if (h_index < 0) + { + h_index = 0; + } + if (h_index >= 11) + { + h_index = 10; + } + temp_index = (h_index + 22) * num_of_points + i; + feature1[temp_index] = hist_incr + feature1[temp_index]; + } + } + }; + + itk::MultiThreaderBase::Pointer mt = itk::MultiThreaderBase::New(); + mt->ParallelizeArray(0, num_of_points, ProcessPoint, nullptr); + + // This is done to optimize the code by avoiding GetElement, SetElement overhead. + auto feature = FeatureType::New(); + feature->CastToSTLContainer() = feature1; + return feature; } template void -PointFeature::ComputeFPFHFeature( - TInputPointSet * input, - TInputPointSet * input_normals, - double radius, - unsigned int neighbors) +PointFeature::ComputeFPFHFeature(TInputPointSet * input, + TInputPointSet * input_normals, + double radius, + unsigned int neighbors) +{ + unsigned long int num_of_points = input->GetNumberOfPoints(); + std::vector fpfh2(33 * num_of_points, 0.0); + + PointsLocatorTypePointer kdtree = PointsLocatorType::New(); + kdtree->SetPoints(input->GetPoints()); + kdtree->Initialize(); + + auto spfh = ComputeSPFHFeature(input, input_normals, radius, neighbors); + + auto & spfh1 = spfh->CastToSTLContainer(); + + // Method to perform processing in parallel + auto ProcessPoint = [&](int i) { + auto point = input->GetPoint(i); + + typename PointsLocatorType::NeighborsIdentifierType indices; + kdtree->FindClosestNPoints(point, neighbors, indices); + + if (indices.size() > 1) + { + double sum[3] = { 0.0, 0.0, 0.0 }; + + std::vector> neighbor_vect; + neighbor_vect.reserve(indices.size()); + + for (size_t k = 0; k < indices.size(); k++) { - unsigned long int num_of_points = input->GetNumberOfPoints(); - std::vector fpfh2(33 * num_of_points, 0.0); + auto point_diff = point - input->GetPoint(indices[k]); + double dist = point_diff.GetNorm(); - PointsLocatorTypePointer kdtree = PointsLocatorType::New(); - kdtree->SetPoints(input->GetPoints()); - kdtree->Initialize(); + // skip the point itself + if (dist == 0.0) + continue; - auto spfh = ComputeSPFHFeature(input, input_normals, radius, neighbors); - - auto & spfh1 = spfh->CastToSTLContainer(); + if (dist < radius) + { + dist = dist * dist; + neighbor_vect.push_back(std::make_pair(dist, indices[k])); + } + } - // Method to perform processing in parallel - auto ProcessPoint = [&] (int i) + // Take only first neighbors in sorted order + unsigned int neighbor_count = std::min(neighbors, (unsigned int)neighbor_vect.size()); + for (size_t k = 0; k < neighbor_count; k++) + { + for (int j = 0; j < 33; j++) { - auto point = input->GetPoint(i); - - typename PointsLocatorType::NeighborsIdentifierType indices; - kdtree->FindClosestNPoints(point, neighbors, indices); - - if (indices.size() > 1) - { - double sum[3] = {0.0, 0.0, 0.0}; - - std::vector< std::pair > neighbor_vect; - neighbor_vect.reserve(indices.size()); - - for (size_t k = 0; k < indices.size(); k++) - { - auto point_diff = point - input->GetPoint(indices[k]); - double dist = point_diff.GetNorm(); - - // skip the point itself - if (dist == 0.0) - continue; - - if (dist < radius) - { - dist = dist*dist; - neighbor_vect.push_back( std::make_pair(dist, indices[k])); - } - } - - // Take only first neighbors in sorted order - unsigned int neighbor_count = std::min(neighbors, (unsigned int)neighbor_vect.size()); - for (size_t k = 0; k < neighbor_count; k++) - { - for (int j = 0; j < 33; j++) - { - double val = spfh1[j*num_of_points + neighbor_vect[k].second]/neighbor_vect[k].first; - sum[j / 11] += val; - fpfh2[j*num_of_points + i] = fpfh2[j*num_of_points + i] + val; - } - } - - for (int j = 0; j < 3; j++) - { - if (sum[j] != 0.0) - { - sum[j] = 100.0 / sum[j]; - } - } - - for (int j = 0; j < 33; j++) - { - fpfh2[j*num_of_points + i] = fpfh2[j*num_of_points + i] * sum[j / 11]; - fpfh2[j*num_of_points + i] = fpfh2[j*num_of_points + i] + spfh1[j*num_of_points + i]; - } - } - }; - - itk::MultiThreaderBase::Pointer mt = itk::MultiThreaderBase::New(); - mt->ParallelizeArray(0, num_of_points, ProcessPoint, nullptr); - - // This is done to optimize the code by avoiding GetElement, SetElement overhead. - this->m_FpfhFeature = FeatureType::New(); - this->m_FpfhFeature->CastToSTLContainer() = fpfh2; + double val = spfh1[j * num_of_points + neighbor_vect[k].second] / neighbor_vect[k].first; + sum[j / 11] += val; + fpfh2[j * num_of_points + i] = fpfh2[j * num_of_points + i] + val; + } + } + + for (int j = 0; j < 3; j++) + { + if (sum[j] != 0.0) + { + sum[j] = 100.0 / sum[j]; + } + } + + for (int j = 0; j < 33; j++) + { + fpfh2[j * num_of_points + i] = fpfh2[j * num_of_points + i] * sum[j / 11]; + fpfh2[j * num_of_points + i] = fpfh2[j * num_of_points + i] + spfh1[j * num_of_points + i]; + } } + }; + + itk::MultiThreaderBase::Pointer mt = itk::MultiThreaderBase::New(); + mt->ParallelizeArray(0, num_of_points, ProcessPoint, nullptr); + + // This is done to optimize the code by avoiding GetElement, SetElement overhead. + this->m_FpfhFeature = FeatureType::New(); + this->m_FpfhFeature->CastToSTLContainer() = fpfh2; +} template void -PointFeature -::PrintSelf(std::ostream & os, Indent indent) const +PointFeature::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); } @@ -288,10 +287,10 @@ template void PointFeature::GenerateData() { - auto input = this->GetInput(); - auto output = this->GetOutput(); - auto inPts = input->GetPoints(); - + auto input = this->GetInput(); + [[maybe_unused]] auto output = this->GetOutput(); // Exercise function + [[maybe_unused]] auto inPts = input->GetPoints(); // Exercise function + itkDebugMacro(<< "Executing connectivity"); // Check input/allocate storage