From 8c00789a08a6c0b242957ac4ec0a47b7c1783c40 Mon Sep 17 00:00:00 2001 From: Peter Abeles Date: Mon, 10 Jun 2024 11:16:14 -0700 Subject: [PATCH 1/3] Added setTo() --- .../struct/packed/PackedArrayPoint2D_F64.java | 13 +++++++++++++ .../struct/packed/PackedArrayPoint2D_I16.java | 13 +++++++++++++ .../struct/packed/PackedArrayPoint2D_I32.java | 13 +++++++++++++ .../struct/packed/PackedArrayPoint3D_F64.java | 13 +++++++++++++ .../struct/packed/PackedArrayPoint4D_F64.java | 13 +++++++++++++ 5 files changed, 65 insertions(+) diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_F64.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_F64.java index d2535f895b..dc6da51724 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_F64.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_F64.java @@ -100,4 +100,17 @@ public final void append( double x, double y ) { array.data[i + 1] = temp.y; } } + + /** + * Makes this array have a value identical to 'src' + * + * @param src original array being copies + * @return Reference to 'this' + */ + public PackedArrayPoint2D_F64 setTo( PackedArrayPoint2D_F64 src ) { + reset(); + reserve(src.size()); + src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y)); + return this; + } } diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I16.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I16.java index 5adb4b5788..8bbd754b87 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I16.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I16.java @@ -100,4 +100,17 @@ public final void append( int x, int y ) { array.data[i + 1] = temp.y; } } + + /** + * Makes this array have a value identical to 'src' + * + * @param src original array being copies + * @return Reference to 'this' + */ + public PackedArrayPoint2D_I16 setTo( PackedArrayPoint2D_I16 src ) { + reset(); + reserve(src.size()); + src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y)); + return this; + } } diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I32.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I32.java index b075232740..574cd3ddd6 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I32.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I32.java @@ -100,4 +100,17 @@ public final void append( int x, int y ) { array.data[i + 1] = temp.y; } } + + /** + * Makes this array have a value identical to 'src' + * + * @param src original array being copies + * @return Reference to 'this' + */ + public PackedArrayPoint2D_I32 setTo( PackedArrayPoint2D_I32 src ) { + reset(); + reserve(src.size()); + src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y)); + return this; + } } diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint3D_F64.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint3D_F64.java index bb840e706e..caa64967bf 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint3D_F64.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint3D_F64.java @@ -110,4 +110,17 @@ public void append( double x, double y, double z) { array.data[i + 2] = temp.z; } } + + /** + * Makes this array have a value identical to 'src' + * + * @param src original array being copies + * @return Reference to 'this' + */ + public PackedArrayPoint3D_F64 setTo( PackedArrayPoint3D_F64 src ) { + reset(); + reserve(src.size()); + src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y, p.z)); + return this; + } } diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint4D_F64.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint4D_F64.java index 29ace138cc..1295ded6ce 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint4D_F64.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint4D_F64.java @@ -117,4 +117,17 @@ public void append( double x, double y, double z, double w ) { array.data[i + 3] = temp.w; } } + + /** + * Makes this array have a value identical to 'src' + * + * @param src original array being copies + * @return Reference to 'this' + */ + public PackedArrayPoint4D_F64 setTo( PackedArrayPoint4D_F64 src ) { + reset(); + reserve(src.size()); + src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y, p.z, p.w)); + return this; + } } From 0333ac87453d3e683583db14327c87f86ec1307c Mon Sep 17 00:00:00 2001 From: Peter Abeles Date: Mon, 10 Jun 2024 18:27:35 -0700 Subject: [PATCH 2/3] - More tweaks to implementations of setTo() for array types - Updated testing --- .../feature/TestPackedTupleArray_B.java | 6 ++++- .../feature/TestPackedTupleArray_F64.java | 6 ++++- .../feature/TestPackedTupleArray_S8.java | 6 ++++- .../feature/TestPackedTupleArray_U8.java | 6 ++++- .../feature/TestPackedTupleBigArray_B.java | 6 ++++- .../feature/TestPackedTupleBigArray_F64.java | 6 ++++- .../feature/TestPackedTupleBigArray_S8.java | 6 ++++- .../feature/TestPackedTupleBigArray_U8.java | 6 ++++- .../struct/packed/PackedArrayPoint2D_F64.java | 12 +++++----- .../struct/packed/PackedArrayPoint2D_I16.java | 12 +++++----- .../struct/packed/PackedArrayPoint2D_I32.java | 12 +++++----- .../struct/packed/PackedArrayPoint3D_F64.java | 12 +++++----- .../struct/packed/PackedArrayPoint4D_F64.java | 12 +++++----- .../packed/PackedBigArrayPoint2D_F64.java | 2 +- .../packed/PackedBigArrayPoint3D_F64.java | 2 +- .../packed/PackedBigArrayPoint4D_F64.java | 15 +++++++++++- .../packed/GenericPackedArrayChecks.java | 2 ++ .../packed/TestPackedArrayPoint2D_F64.java | 15 +++++++++++- .../packed/TestPackedArrayPoint2D_I16.java | 15 +++++++++++- .../packed/TestPackedArrayPoint2D_I32.java | 15 +++++++++++- .../packed/TestPackedArrayPoint3D_F64.java | 21 +++++++++++++---- .../packed/TestPackedArrayPoint4D_F64.java | 23 +++++++++++++++---- .../packed/TestPackedBigArrayPoint2D_F64.java | 19 ++++++++++++--- .../packed/TestPackedBigArrayPoint3D_F64.java | 15 +++++++++++- .../packed/TestPackedBigArrayPoint4D_F64.java | 23 +++++++++++++++---- .../boofcv/testing/BoofStandardJUnit.java | 18 +++++++++++---- 26 files changed, 226 insertions(+), 67 deletions(-) diff --git a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_B.java b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_B.java index 13e9d391fb..5cdf5806b7 100644 --- a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_B.java +++ b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_B.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Peter Abeles. All Rights Reserved. + * Copyright (c) 2024, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * @@ -20,6 +20,7 @@ import boofcv.struct.PackedArray; import boofcv.struct.packed.GenericPackedArrayChecks; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -50,4 +51,7 @@ class TestPackedTupleArray_B extends GenericPackedArrayChecks { } fail("The tuples are identical"); } + + // not implemented yet + @Test void setTo_Standard(){} } diff --git a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_F64.java b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_F64.java index 5f109607ae..373d7cf541 100644 --- a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_F64.java +++ b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_F64.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Peter Abeles. All Rights Reserved. + * Copyright (c) 2024, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * @@ -21,6 +21,7 @@ import boofcv.struct.PackedArray; import boofcv.struct.packed.GenericPackedArrayChecks; import org.ejml.UtilEjml; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -51,4 +52,7 @@ class TestPackedTupleArray_F64 extends GenericPackedArrayChecks { } fail("The tuples are identical"); } + + // not implemented yet + @Test void setTo_Standard(){} } diff --git a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_S8.java b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_S8.java index a9db9a60ee..1f1bf057c3 100644 --- a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_S8.java +++ b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_S8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Peter Abeles. All Rights Reserved. + * Copyright (c) 2024, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * @@ -20,6 +20,7 @@ import boofcv.struct.PackedArray; import boofcv.struct.packed.GenericPackedArrayChecks; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -50,4 +51,7 @@ class TestPackedTupleArray_S8 extends GenericPackedArrayChecks { } fail("The tuples are identical"); } + + // not implemented yet + @Test void setTo_Standard(){} } diff --git a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_U8.java b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_U8.java index 3f4d05c372..959a32fe99 100644 --- a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_U8.java +++ b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleArray_U8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Peter Abeles. All Rights Reserved. + * Copyright (c) 2024, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * @@ -20,6 +20,7 @@ import boofcv.struct.PackedArray; import boofcv.struct.packed.GenericPackedArrayChecks; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -50,4 +51,7 @@ class TestPackedTupleArray_U8 extends GenericPackedArrayChecks { } fail("The tuples are identical"); } + + // not implemented yet + @Test void setTo_Standard(){} } diff --git a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_B.java b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_B.java index a5114df89d..5b65250807 100644 --- a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_B.java +++ b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_B.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Peter Abeles. All Rights Reserved. + * Copyright (c) 2024, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * @@ -20,6 +20,7 @@ import boofcv.struct.PackedArray; import boofcv.struct.packed.GenericPackedArrayChecks; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -50,4 +51,7 @@ class TestPackedTupleBigArray_B extends GenericPackedArrayChecks { } fail("The tuples are identical"); } + + // not implemented yet + @Test void setTo_Standard(){} } diff --git a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_F64.java b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_F64.java index eff4a66c74..1773a95914 100644 --- a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_F64.java +++ b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_F64.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Peter Abeles. All Rights Reserved. + * Copyright (c) 2024, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * @@ -21,6 +21,7 @@ import boofcv.struct.PackedArray; import boofcv.struct.packed.GenericPackedArrayChecks; import org.ejml.UtilEjml; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -51,4 +52,7 @@ class TestPackedTupleBigArray_F64 extends GenericPackedArrayChecks } fail("The tuples are identical"); } + + // not implemented yet + @Test void setTo_Standard(){} } diff --git a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_U8.java b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_U8.java index dc58439ae0..37772a2947 100644 --- a/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_U8.java +++ b/main/boofcv-feature/src/test/java/boofcv/struct/feature/TestPackedTupleBigArray_U8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Peter Abeles. All Rights Reserved. + * Copyright (c) 2024, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * @@ -20,6 +20,7 @@ import boofcv.struct.PackedArray; import boofcv.struct.packed.GenericPackedArrayChecks; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -50,4 +51,7 @@ class TestPackedTupleBigArray_U8 extends GenericPackedArrayChecks } fail("The tuples are identical"); } + + // not implemented yet + @Test void setTo_Standard(){} } diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_F64.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_F64.java index dc6da51724..cee34d9fe9 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_F64.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_F64.java @@ -21,6 +21,7 @@ import boofcv.misc.BoofLambdas; import boofcv.struct.PackedArray; import georegression.struct.point.Point2D_F64; +import lombok.Getter; import org.ddogleg.struct.DogArray_F64; /** @@ -31,10 +32,11 @@ public class PackedArrayPoint2D_F64 implements PackedArray { private static final int DOF = 2; - // Stores tuple in a single continuous array - public final DogArray_F64 array; + /** Stores tuple in a single continuous array */ + @Getter private final DogArray_F64 array; + // tuple that the result is temporarily written to - public final Point2D_F64 temp = new Point2D_F64(); + private final Point2D_F64 temp = new Point2D_F64(); public PackedArrayPoint2D_F64() { array = new DogArray_F64(); @@ -108,9 +110,7 @@ public final void append( double x, double y ) { * @return Reference to 'this' */ public PackedArrayPoint2D_F64 setTo( PackedArrayPoint2D_F64 src ) { - reset(); - reserve(src.size()); - src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y)); + array.setTo(src.array); return this; } } diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I16.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I16.java index 8bbd754b87..774d368675 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I16.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I16.java @@ -21,6 +21,7 @@ import boofcv.misc.BoofLambdas; import boofcv.struct.PackedArray; import georegression.struct.point.Point2D_I16; +import lombok.Getter; import org.ddogleg.struct.DogArray_I16; /** @@ -31,10 +32,11 @@ public class PackedArrayPoint2D_I16 implements PackedArray { private static final int DOF = 2; - // Stores tuple in a single continuous array - public final DogArray_I16 array; + /** Stores tuple in a single continuous array */ + @Getter private final DogArray_I16 array; + // tuple that the result is temporarily written to - public final Point2D_I16 temp = new Point2D_I16(); + private final Point2D_I16 temp = new Point2D_I16(); public PackedArrayPoint2D_I16() { array = new DogArray_I16(); @@ -108,9 +110,7 @@ public final void append( int x, int y ) { * @return Reference to 'this' */ public PackedArrayPoint2D_I16 setTo( PackedArrayPoint2D_I16 src ) { - reset(); - reserve(src.size()); - src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y)); + array.setTo(src.array); return this; } } diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I32.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I32.java index 574cd3ddd6..057e650db9 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I32.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint2D_I32.java @@ -21,6 +21,7 @@ import boofcv.misc.BoofLambdas; import boofcv.struct.PackedArray; import georegression.struct.point.Point2D_I32; +import lombok.Getter; import org.ddogleg.struct.DogArray_I32; /** @@ -31,10 +32,11 @@ public class PackedArrayPoint2D_I32 implements PackedArray { private static final int DOF = 2; - // Stores tuple in a single continuous array - public final DogArray_I32 array; + /** Stores tuple in a single continuous array */ + @Getter private final DogArray_I32 array; + // tuple that the result is temporarily written to - public final Point2D_I32 temp = new Point2D_I32(); + private final Point2D_I32 temp = new Point2D_I32(); public PackedArrayPoint2D_I32() { array = new DogArray_I32(); @@ -108,9 +110,7 @@ public final void append( int x, int y ) { * @return Reference to 'this' */ public PackedArrayPoint2D_I32 setTo( PackedArrayPoint2D_I32 src ) { - reset(); - reserve(src.size()); - src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y)); + array.setTo(src.array); return this; } } diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint3D_F64.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint3D_F64.java index caa64967bf..f93cb29125 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint3D_F64.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint3D_F64.java @@ -21,6 +21,7 @@ import boofcv.misc.BoofLambdas; import boofcv.struct.PackedArray; import georegression.struct.point.Point3D_F64; +import lombok.Getter; import org.ddogleg.struct.DogArray_F64; /** @@ -31,10 +32,11 @@ public class PackedArrayPoint3D_F64 implements PackedArray { private static final int DOF = 3; - // Stores tuple in a single continuous array - public final DogArray_F64 array; + /** Stores tuple in a single continuous array */ + @Getter private final DogArray_F64 array; + // tuple that the result is temporarily written to - public final Point3D_F64 temp = new Point3D_F64(); + private final Point3D_F64 temp = new Point3D_F64(); public PackedArrayPoint3D_F64() { array = new DogArray_F64(); @@ -118,9 +120,7 @@ public void append( double x, double y, double z) { * @return Reference to 'this' */ public PackedArrayPoint3D_F64 setTo( PackedArrayPoint3D_F64 src ) { - reset(); - reserve(src.size()); - src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y, p.z)); + array.setTo(src.array); return this; } } diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint4D_F64.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint4D_F64.java index 1295ded6ce..ae2b6ba61c 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint4D_F64.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedArrayPoint4D_F64.java @@ -21,6 +21,7 @@ import boofcv.misc.BoofLambdas; import boofcv.struct.PackedArray; import georegression.struct.point.Point4D_F64; +import lombok.Getter; import org.ddogleg.struct.DogArray_F64; /** @@ -31,10 +32,11 @@ public class PackedArrayPoint4D_F64 implements PackedArray { private static final int DOF = 4; - // Stores tuple in a single continuous array - public final DogArray_F64 array; + /** Stores tuple in a single continuous array */ + @Getter private final DogArray_F64 array; + // tuple that the result is temporarily written to - public final Point4D_F64 temp = new Point4D_F64(); + private final Point4D_F64 temp = new Point4D_F64(); public PackedArrayPoint4D_F64() { array = new DogArray_F64(); @@ -125,9 +127,7 @@ public void append( double x, double y, double z, double w ) { * @return Reference to 'this' */ public PackedArrayPoint4D_F64 setTo( PackedArrayPoint4D_F64 src ) { - reset(); - reserve(src.size()); - src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y, p.z, p.w)); + array.setTo(src.array); return this; } } diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint2D_F64.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint2D_F64.java index 67aaffa6b7..497450a211 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint2D_F64.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint2D_F64.java @@ -36,7 +36,7 @@ public class PackedBigArrayPoint2D_F64 implements PackedArray { private final BigDogArray_F64 dog; // tuple that the result is temporarily written to - public final Point2D_F64 temp = new Point2D_F64(); + private final Point2D_F64 temp = new Point2D_F64(); /** * Constructor where the default is used for all parameters. diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint3D_F64.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint3D_F64.java index fed1e51549..871ca5dd92 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint3D_F64.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint3D_F64.java @@ -36,7 +36,7 @@ public class PackedBigArrayPoint3D_F64 implements PackedArray { private static final int DOF = 3; // tuple that the result is temporarily written to - public final Point3D_F64 temp = new Point3D_F64(); + private final Point3D_F64 temp = new Point3D_F64(); // Storage for the raw data in an array private final BigDogArray_F64 dog; diff --git a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint4D_F64.java b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint4D_F64.java index d0a4f0adae..d277422721 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint4D_F64.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/packed/PackedBigArrayPoint4D_F64.java @@ -36,7 +36,7 @@ public class PackedBigArrayPoint4D_F64 implements PackedArray { private final BigDogArray_F64 dog; // tuple that the result is temporarily written to - public final Point4D_F64 temp = new Point4D_F64(); + private final Point4D_F64 temp = new Point4D_F64(); /** * Constructor where the default is used for all parameters. @@ -63,6 +63,19 @@ public PackedBigArrayPoint4D_F64( int reservedPoints, int blockSize, BigDogGrowt dog = new BigDogArray_F64(reservedPoints*DOF, blockSize*DOF, growth); } + /** + * Makes this array have a value identical to 'src' + * + * @param src original array being copies + * @return Reference to 'this' + */ + public PackedBigArrayPoint4D_F64 setTo( PackedBigArrayPoint4D_F64 src ) { + reset(); + reserve(src.size()); + src.forIdx(0, src.size(), ( idx, p ) -> append(p.x, p.y, p.z, p.w)); + return this; + } + @Override public void reset() { dog.reset(); } diff --git a/main/boofcv-types/src/test/java/boofcv/struct/packed/GenericPackedArrayChecks.java b/main/boofcv-types/src/test/java/boofcv/struct/packed/GenericPackedArrayChecks.java index 78e0ff9dc3..f450fdf21f 100644 --- a/main/boofcv-types/src/test/java/boofcv/struct/packed/GenericPackedArrayChecks.java +++ b/main/boofcv-types/src/test/java/boofcv/struct/packed/GenericPackedArrayChecks.java @@ -161,4 +161,6 @@ public abstract class GenericPackedArrayChecks extends BoofStandardJUnit { T found = alg.getTemp(1); checkEquals(p, found); } + + @Test void setTo_Standard() {checkSetTo(createAlg().getClass(), true);} } diff --git a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_F64.java b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_F64.java index 2c1c5bd7e0..ce38bb53de 100644 --- a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_F64.java +++ b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_F64.java @@ -50,7 +50,7 @@ public class TestPackedArrayPoint2D_F64 extends GenericPackedArrayChecks assertEquals(0.0, a.distance(dst.getTemp(idx)))); + } } diff --git a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_I16.java b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_I16.java index a3fa1e61ac..ac036fa894 100644 --- a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_I16.java +++ b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_I16.java @@ -49,7 +49,7 @@ public class TestPackedArrayPoint2D_I16 extends GenericPackedArrayChecks assertEquals(0.0, a.distance(dst.getTemp(idx)))); + } } diff --git a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_I32.java b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_I32.java index 6032fba83c..5acbcf1001 100644 --- a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_I32.java +++ b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint2D_I32.java @@ -49,7 +49,7 @@ public class TestPackedArrayPoint2D_I32 extends GenericPackedArrayChecks assertEquals(0.0, a.distance(dst.getTemp(idx)))); + } } diff --git a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint3D_F64.java b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint3D_F64.java index ff347de001..4e5d0a259b 100644 --- a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint3D_F64.java +++ b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint3D_F64.java @@ -34,9 +34,9 @@ public class TestPackedArrayPoint3D_F64 extends GenericPackedArrayChecks assertEquals(0.0, a.distance(dst.getTemp(idx)))); + } } diff --git a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint4D_F64.java b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint4D_F64.java index 76922b3ac9..2c7f74b6e2 100644 --- a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint4D_F64.java +++ b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedArrayPoint4D_F64.java @@ -34,10 +34,10 @@ public class TestPackedArrayPoint4D_F64 extends GenericPackedArrayChecks assertEquals(0.0, a.distance(dst.getTemp(idx)))); + } } diff --git a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint2D_F64.java b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint2D_F64.java index 1adb13d4b3..b9a8c711f4 100644 --- a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint2D_F64.java +++ b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint2D_F64.java @@ -35,8 +35,8 @@ public class TestPackedBigArrayPoint2D_F64 extends GenericPackedArrayChecks assertEquals(0.0, a.distance(dst.getTemp(idx)))); + } } diff --git a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint3D_F64.java b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint3D_F64.java index b6a92ecc4d..0b7e82475d 100644 --- a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint3D_F64.java +++ b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint3D_F64.java @@ -70,7 +70,7 @@ public class TestPackedBigArrayPoint3D_F64 extends GenericPackedArrayChecks assertEquals(0.0, a.distance(dst.getTemp(idx)))); + } } diff --git a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint4D_F64.java b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint4D_F64.java index 8e8e564d34..a38e49c986 100644 --- a/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint4D_F64.java +++ b/main/boofcv-types/src/test/java/boofcv/struct/packed/TestPackedBigArrayPoint4D_F64.java @@ -35,10 +35,10 @@ public class TestPackedBigArrayPoint4D_F64 extends GenericPackedArrayChecks assertEquals(0.0, a.distance(dst.getTemp(idx)))); + } } diff --git a/main/boofcv-types/src/test/java/boofcv/testing/BoofStandardJUnit.java b/main/boofcv-types/src/test/java/boofcv/testing/BoofStandardJUnit.java index cfd85eae4f..ac11dfec00 100644 --- a/main/boofcv-types/src/test/java/boofcv/testing/BoofStandardJUnit.java +++ b/main/boofcv-types/src/test/java/boofcv/testing/BoofStandardJUnit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Peter Abeles. All Rights Reserved. + * Copyright (c) 2024, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * @@ -22,6 +22,7 @@ import boofcv.struct.Configuration; import org.ddogleg.struct.DogArrayPrimitive; import org.ddogleg.struct.FastAccess; +import org.ddogleg.struct.LArrayAccessor; import org.ejml.data.DMatrix; import org.ejml.data.FMatrix; import org.ejml.ops.MatrixFeatures_D; @@ -280,8 +281,8 @@ protected void checkSetTo( Class type, boolean returnThis ) { if (onlyOneOption) assertEquals(f.get(src), f.get(dst), "Field Name: '" + f.getName() + "'"); else if (f.getType().isAssignableFrom(List.class)) { - List listSrc = (List)f.get(src); - List listDst = (List)f.get(dst); + var listSrc = (List)f.get(src); + var listDst = (List)f.get(dst); // if the original list is empty there's nothing that can be tested. if (listSrc.isEmpty()) { @@ -321,8 +322,15 @@ private void checkSameFieldValues( Field[] fields, Object src, Object dst ) thro if (f.getType().isEnum() || f.getType().isPrimitive() || f.get(src) == null) assertEquals(f.get(src), f.get(dst), "Field Name: '" + f.getName() + "' in " + src.getClass().getSimpleName()); else if (f.getType().isAssignableFrom(FastAccess.class)) { - FastAccess listSrc = (FastAccess)f.get(src); - FastAccess listDst = (FastAccess)f.get(dst); + var listSrc = (FastAccess)f.get(src); + var listDst = (FastAccess)f.get(dst); + assertEquals(listSrc.size(), listDst.size()); + for (int i = 0; i < listSrc.size(); i++) { + throw new RuntimeException("Implement!"); + } + } else if (f.getType().isAssignableFrom(LArrayAccessor.class)) { + var listSrc = (LArrayAccessor)f.get(src); + var listDst = (LArrayAccessor)f.get(dst); assertEquals(listSrc.size(), listDst.size()); for (int i = 0; i < listSrc.size(); i++) { throw new RuntimeException("Implement!"); From eb466e93e5710b117184b5da9c2536c3069d437e Mon Sep 17 00:00:00 2001 From: Peter Abeles Date: Mon, 10 Jun 2024 11:48:56 -0700 Subject: [PATCH 3/3] feature/ply-normals - Support for reading vertex normals - Added the concept of face normals --- .../boofcv/io/points/StlDataStructure.java | 14 +- .../java/boofcv/io/points/impl/PlyCodec.java | 167 +++++++++++++----- .../java/boofcv/io/points/impl/PlyReader.java | 2 + .../java/boofcv/io/points/impl/PlyWriter.java | 8 +- .../java/boofcv/visualize/RenderMesh.java | 11 +- .../boofcv/io/points/impl/TestPlyCodec.java | 7 +- .../java/boofcv/visualize/TestRenderMesh.java | 6 +- .../java/boofcv/struct/mesh/VertexMesh.java | 28 ++- .../boofcv/struct/mesh/TestVertexMesh.java | 10 +- 9 files changed, 179 insertions(+), 74 deletions(-) diff --git a/main/boofcv-io/src/main/java/boofcv/io/points/StlDataStructure.java b/main/boofcv-io/src/main/java/boofcv/io/points/StlDataStructure.java index 2500802a9e..9730c443bf 100644 --- a/main/boofcv-io/src/main/java/boofcv/io/points/StlDataStructure.java +++ b/main/boofcv-io/src/main/java/boofcv/io/points/StlDataStructure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Peter Abeles. All Rights Reserved. + * Copyright (c) 2024, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * @@ -63,6 +63,9 @@ public class StlDataStructure { /** What's the name of this Solid */ public String name = ""; + // Internal workspace + Point3D_F64 temp = new Point3D_F64(); + public void reset() { vertexes.reset(); normals.reset(); @@ -124,15 +127,14 @@ private void addNormal( Point3D_F64 v1, Point3D_F64 v2, Point3D_F64 v3 ) { double by = v3.y - v1.y; double bz = v3.z - v1.z; - Point3D_F64 t = vertexes.temp; - GeometryMath_F64.cross(ax, ay, az, bx, by, bz, t); + GeometryMath_F64.cross(ax, ay, az, bx, by, bz, temp); // Ensure the norm is 1 - double n = t.norm(); - t.divideIP(n); + double n = temp.norm(); + temp.divideIP(n); // Save the results - normals.append(t.x, t.y, t.z); + normals.append(temp.x, temp.y, temp.z); } /** diff --git a/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyCodec.java b/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyCodec.java index b3b85ca942..2eac85493f 100644 --- a/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyCodec.java +++ b/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyCodec.java @@ -23,7 +23,9 @@ import boofcv.io.UtilIO; import boofcv.misc.BoofMiscOps; import boofcv.struct.mesh.VertexMesh; +import georegression.struct.GeoTuple3D_F64; import georegression.struct.point.Point2D_F32; +import georegression.struct.point.Point3D_F32; import georegression.struct.point.Point3D_F64; import org.ddogleg.struct.DogArray_I32; import org.jetbrains.annotations.Nullable; @@ -46,22 +48,27 @@ public class PlyCodec { public static void saveAscii( PlyWriter data, Writer outputWriter ) throws IOException { writeAsciiHeader(data.getVertexCount(), data.getPolygonCount(), data.isColor(), data.isTextured(), - outputWriter); + data.isVertexNormals(), outputWriter); boolean color = data.isColor(); var p = new Point3D_F64(); + var v = new Point3D_F64(); for (int i = 0; i < data.getVertexCount(); i++) { data.getVertex(i, p); + outputWriter.write(String.format("%f %f %f", p.x, p.y, p.z)); + if (data.isVertexNormals()) { + data.getVertexNormal(i, v); + outputWriter.write(String.format(" %f %f %f", v.x, v.y, v.z)); + } if (color) { int rgb = data.getColor(i); - int r = (rgb >> 16) & 0xFF; - int g = (rgb >> 8) & 0xFF; + int r = rgb >> 16 & 0xFF; + int g = rgb >> 8 & 0xFF; int b = rgb & 0xFF; - outputWriter.write(String.format("%f %f %f %d %d %d\n", p.x, p.y, p.z, r, g, b)); - } else { - outputWriter.write(String.format("%f %f %f\n", p.x, p.y, p.z)); + outputWriter.write(String.format(" %d %d %d", r, g, b)); } + outputWriter.write('\n'); } var arrayI = new int[100]; var arrayF = new float[100]; @@ -96,7 +103,7 @@ public static void saveCloudAscii( PointCloudReader cloud, boolean saveRgb, Writ } private static void writeAsciiHeader( int vertexCount, int triangleCount, boolean hasColor, boolean hasTexture, - Writer outputWriter ) + boolean hasNormals, Writer outputWriter ) throws IOException { outputWriter.write("ply\n"); outputWriter.write("format ascii 1.0\n"); @@ -105,6 +112,13 @@ private static void writeAsciiHeader( int vertexCount, int triangleCount, boolea "property float x\n" + "property float y\n" + "property float z\n"); + if (hasNormals) { + outputWriter.write(""" + property float nx + property float ny + property float nz + """); + } if (hasColor) { outputWriter.write(""" property uchar red @@ -156,15 +170,19 @@ public static void saveBinary( PlyWriter data, ByteOrder order, boolean saveAsFl String format = "UTF-8"; int dataLength = saveAsFloat ? 4 : 8; writeBinaryHeader(data.getVertexCount(), data.getPolygonCount(), order, data.isColor(), - data.isTextured(), + data.isTextured(), data.isVertexNormals(), saveAsFloat, format, outputWriter); boolean color = data.isColor(); - int end = dataLength*3; - var bytes = ByteBuffer.allocate(dataLength*3 + (color ? 3 : 0)); + int locNorm = dataLength*3; + int locColor = locNorm + (data.isVertexNormals() ? dataLength*3 : 0); + + var bytes = ByteBuffer.allocate(locColor + (color ? 3 : 0)); bytes.order(order); var p = new Point3D_F64(); + var n = new Point3D_F64(); + for (int i = 0; i < data.getVertexCount(); i++) { data.getVertex(i, p); if (saveAsFloat) { @@ -177,14 +195,27 @@ public static void saveBinary( PlyWriter data, ByteOrder order, boolean saveAsFl bytes.putDouble(16, p.z); } + if (data.isVertexNormals()) { + data.getVertexNormal(i, n); + if (saveAsFloat) { + bytes.putFloat(locNorm, (float)n.x); + bytes.putFloat(locNorm + 4, (float)n.y); + bytes.putFloat(locNorm + 8, (float)n.z); + } else { + bytes.putDouble(locNorm, n.x); + bytes.putDouble(locNorm + 8, n.y); + bytes.putDouble(locNorm + 16, n.z); + } + } + if (color) { int rgb = data.getColor(i); - int r = (rgb >> 16) & 0xFF; - int g = (rgb >> 8) & 0xFF; + int r = rgb >> 16 & 0xFF; + int g = rgb >> 8 & 0xFF; int b = rgb & 0xFF; - bytes.put(end, (byte)r); - bytes.put(end + 1, (byte)g); - bytes.put(end + 2, (byte)b); + bytes.put(locColor, (byte)r); + bytes.put(locColor + 1, (byte)g); + bytes.put(locColor + 2, (byte)b); } outputWriter.write(bytes.array()); } @@ -217,7 +248,8 @@ public static void saveBinary( PlyWriter data, ByteOrder order, boolean saveAsFl } private static void writeBinaryHeader( int vertexCount, int triangleCount, ByteOrder order, boolean hasColor, - boolean hasTexture, boolean saveAsFloat, String format, OutputStream outputWriter ) + boolean hasTexture, boolean hasVertexNormals, + boolean saveAsFloat, String format, OutputStream outputWriter ) throws IOException { String dataType = saveAsFloat ? "float" : "double"; outputWriter.write("ply\n".getBytes(format)); @@ -233,19 +265,26 @@ private static void writeBinaryHeader( int vertexCount, int triangleCount, ByteO "property " + dataType + " x\n" + "property " + dataType + " y\n" + "property " + dataType + " z\n").getBytes(format)); + + if (hasVertexNormals) { + outputWriter.write(( + "property " + dataType + " nx\n" + + "property " + dataType + " ny\n" + + "property " + dataType + " nz\n").getBytes(format)); + } if (hasColor) { outputWriter.write( - (""" + """ property uchar red property uchar green property uchar blue - """).getBytes(format)); + """.getBytes(format)); } if (triangleCount > 0) { outputWriter.write(("element face " + triangleCount + "\n" + "property list uchar int vertex_indices\n").getBytes(format)); if (hasTexture) { - outputWriter.write(("property list uchar float texcoord\n").getBytes(format)); + outputWriter.write("property list uchar float texcoord\n".getBytes(format)); } } outputWriter.write("end_header\n".getBytes(format)); @@ -296,7 +335,7 @@ private static void readHeader( InputStream input, Header header ) throws IOExce header.triangleCount = Integer.parseInt(words[2]); } } else if (words[0].equals("property") && previousVertex) { - DataType d = switch (words[1].toLowerCase()) { + DataType d = switch (words[1].toLowerCase(Locale.US)) { case "float" -> DataType.FLOAT; case "double" -> DataType.DOUBLE; case "char" -> DataType.CHAR; @@ -308,22 +347,16 @@ private static void readHeader( InputStream input, Header header ) throws IOExce default -> throw new RuntimeException("Add support for " + words[1]); }; VarType v; - switch (words[2].toLowerCase()) { + switch (words[2].toLowerCase(Locale.US)) { case "x" -> v = VarType.X; case "y" -> v = VarType.Y; case "z" -> v = VarType.Z; - case "red" -> { - v = VarType.R; - header.rgb = true; - } - case "green" -> { - v = VarType.G; - header.rgb = true; - } - case "blue" -> { - v = VarType.B; - header.rgb = true; - } + case "nx" -> v = VarType.NX; + case "ny" -> v = VarType.NY; + case "nz" -> v = VarType.NZ; + case "red" -> v = VarType.R; + case "green" -> v = VarType.G; + case "blue" -> v = VarType.B; default -> v = VarType.UNKNOWN; } header.dataWords.add(new DataWord(v, d)); @@ -342,6 +375,17 @@ private static void readHeader( InputStream input, Header header ) throws IOExce } line = readNextPly(input, true, buffer); } + + // See what type of data is contained + for (int i = 0; i < header.dataWords.size(); i++) { + PlyCodec.DataWord w = header.dataWords.get(i); + switch (w.var) { + case R, G, B -> header.rgb = true; + case NX, NY, NZ -> header.normals = true; + default -> { + } + } + } } public static void readCloud( InputStream input, PointCloudWriter output ) throws IOException { @@ -354,6 +398,8 @@ public static void readCloud( InputStream input, PointCloudWriter output ) throw output.add(x, y, z, rgb); } + @Override public void addVertexNormal( double nx, double ny, double nz ) {} + @Override public void addPolygon( int[] indexes, int offset, int length ) {} @Override public void addTexture( int count, float[] coor ) {} @@ -374,6 +420,10 @@ public static void readMesh( InputStream input, VertexMesh mesh, DogArray_I32 co colorRGB.add(rgb); } + @Override public void addVertexNormal( double nx, double ny, double nz ) { + mesh.vertexNormals.append((float)nx, (float)ny, (float)nz); + } + @Override public void addPolygon( int[] indexes, int offset, int length ) { mesh.offsets.add(mesh.indexes.size + length); mesh.indexes.addAll(indexes, offset, offset + length); @@ -397,15 +447,13 @@ public static void read( InputStream input, PlyReader output ) throws IOExceptio output.initialize(header.vertexCount, header.triangleCount, header.rgb); switch (header.format) { - case ASCII -> readAscii(output, input, header.dataWords, header.vertexCount, - header.rgb, header.triangleCount); + case ASCII -> readAscii(output, input, header); case BINARY_LITTLE, BINARY_BIG -> readCloudBinary(output, input, header); default -> throw new RuntimeException("BUG!"); } } - private static void readAscii( PlyReader output, InputStream reader, List dataWords, - int vertexCount, boolean rgb, int triangleCount ) throws IOException { + private static void readAscii( PlyReader output, InputStream reader, Header header ) throws IOException { var buffer = new StringBuilder(); // storage for read in values @@ -415,15 +463,16 @@ private static void readAscii( PlyReader output, InputStream reader, List F64 = Double.parseDouble(word); @@ -434,6 +483,9 @@ private static void readAscii( PlyReader output, InputStream reader, List x = F64; case Y -> y = F64; case Z -> z = F64; + case NX -> nx = F64; + case NY -> ny = F64; + case NZ -> nz = F64; case R -> r = I32; case G -> g = I32; case B -> b = I32; @@ -442,10 +494,14 @@ private static void readAscii( PlyReader output, InputStream reader, List x = F64; case Y -> y = F64; case Z -> z = F64; + case NX -> nx = F64; + case NY -> ny = F64; + case NZ -> nz = F64; case R -> r = I32; case G -> g = I32; case B -> b = I32; @@ -524,6 +584,10 @@ private static void readCloudBinary( PlyReader output, InputStream reader, Heade } output.addVertex(x, y, z, r << 16 | g << 8 | b); + if (header.normals) { + output.addVertexNormal(nx, ny, nz); + } + //System.out.printf("vertex: %.1e %.1e %.1e | %2x %2x %2x\n", x, y, z, r, g, b); } @@ -594,7 +658,6 @@ private static void readTextureCoor( InputStream reader, DataType valueType, Byt } } output.addTexture(count/2, tempF); - } private static PlyWriter wrapMeshForWriting( VertexMesh mesh, @Nullable DogArray_I32 colorRGB ) { @@ -609,8 +672,17 @@ private static PlyWriter wrapMeshForWriting( VertexMesh mesh, @Nullable DogArray return mesh.texture.size() > 0; } + @Override public boolean isVertexNormals() { + return mesh.vertexNormals.size() >= 0; + } + @Override public void getVertex( int which, Point3D_F64 vertex ) {mesh.vertexes.getCopy(which, vertex);} + @Override public void getVertexNormal( int which, GeoTuple3D_F64 normal ) { + Point3D_F32 tmp = mesh.vertexNormals.getTemp(which); + normal.setTo(tmp.x, tmp.y, tmp.z); + } + @SuppressWarnings("NullAway") @Override public int getColor( int which ) {return colorRGB.get(which);} @@ -651,8 +723,12 @@ private static PlyWriter wrapCloudForWriting( PointCloudReader cloud, boolean sa @Override public boolean isTextured() {return false;} + @Override public boolean isVertexNormals() {return false;} + @Override public void getVertex( int which, Point3D_F64 vertex ) {cloud.get(which, vertex);} + @Override public void getVertexNormal( int which, GeoTuple3D_F64 normal ) {} + @Override public int getColor( int which ) {return cloud.getRGB(which);} @Override public int getIndexes( int which, int[] indexes ) {return 0;} @@ -665,7 +741,10 @@ private static class Header { List dataWords = new ArrayList<>(); int vertexCount = -1; int triangleCount = -1; + // true of rgb colors for each vertex is encoded boolean rgb = false; + // true if normals for each shape is encoded + boolean normals = false; List properties = new ArrayList<>(); Format format = Format.ASCII; } @@ -698,7 +777,7 @@ public DataWord( VarType var, DataType data ) { } private enum VarType { - X, Y, Z, R, G, B, UNKNOWN + X, Y, Z, R, G, B, NX, NY, NZ, UNKNOWN } private enum DataType { diff --git a/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyReader.java b/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyReader.java index a6c88f101f..02d59d5749 100644 --- a/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyReader.java +++ b/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyReader.java @@ -28,6 +28,8 @@ public interface PlyReader { void addVertex( double x, double y, double z, int rgb ); + void addVertexNormal( double nx, double ny, double nz ); + void addPolygon( int[] indexes, int offset, int length ); /** diff --git a/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyWriter.java b/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyWriter.java index 2eaaa85a43..37cfd16c8e 100644 --- a/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyWriter.java +++ b/main/boofcv-io/src/main/java/boofcv/io/points/impl/PlyWriter.java @@ -18,6 +18,7 @@ package boofcv.io.points.impl; +import georegression.struct.GeoTuple3D_F64; import georegression.struct.point.Point3D_F64; /** @@ -33,11 +34,16 @@ public interface PlyWriter { /** True if a vertex has color information or not */ boolean isColor(); - /** True if a vertex has a texture coordinate */ + /** True if a polygon has a texture coordinate */ boolean isTextured(); + /** True if vertexes have normal vectors */ + boolean isVertexNormals(); + void getVertex( int which, Point3D_F64 vertex ); + void getVertexNormal( int which, GeoTuple3D_F64 normal ); + /** * Color of a vertex */ diff --git a/main/boofcv-io/src/main/java/boofcv/visualize/RenderMesh.java b/main/boofcv-io/src/main/java/boofcv/visualize/RenderMesh.java index 6fd35dd42d..986c09cf4b 100644 --- a/main/boofcv-io/src/main/java/boofcv/visualize/RenderMesh.java +++ b/main/boofcv-io/src/main/java/boofcv/visualize/RenderMesh.java @@ -31,6 +31,7 @@ import georegression.metric.Intersection2D_F64; import georegression.struct.point.Point2D_F32; import georegression.struct.point.Point2D_F64; +import georegression.struct.point.Point3D_F32; import georegression.struct.point.Point3D_F64; import georegression.struct.se.Se3_F64; import georegression.struct.shapes.Polygon2D_F32; @@ -79,7 +80,7 @@ public class RenderMesh implements VerbosePrint { public @Getter final Se3_F64 worldToView = new Se3_F64(); /** If true then a polygon will only be rendered if the surface normal is pointed towards the camera */ - public @Getter @Setter boolean checkSurfaceNormal = false; + public @Getter @Setter boolean checkFaceNormal = false; /** If true it will always use the colorizer, even if there is texture information */ public @Getter @Setter boolean forceColorizer = false; @@ -123,8 +124,8 @@ public void render( VertexMesh mesh ) { BoofMiscOps.checkTrue(intrinsics.width > 0 && intrinsics.height > 0, "Intrinsics not set"); // Make sure there are normals if it's configured to use them - if (checkSurfaceNormal && mesh.normals.size() == 0) - mesh.computeNormals(); + if (checkFaceNormal && mesh.faceNormals.size() == 0) + mesh.computeFaceNormals(); // Initialize output images initializeImages(); @@ -161,7 +162,7 @@ public void render( VertexMesh mesh ) { } // Prune using normal vector - if (mesh.normals.size() > 0 && checkSurfaceNormal) { + if (checkFaceNormal) { if (!isFrontVisible(mesh, shapeIdx - 1, idx0, worldCamera)) continue; } @@ -213,7 +214,7 @@ public void render( VertexMesh mesh ) { */ static boolean isFrontVisible( VertexMesh mesh, int shapeIdx, int idx0, Point3D_F64 worldCamera ) { // Get normal in world coordinates - Point3D_F64 normal = mesh.normals.getTemp(shapeIdx); + Point3D_F32 normal = mesh.faceNormals.getTemp(shapeIdx); // vector from the camera to a vertex Point3D_F64 v1 = mesh.vertexes.getTemp(mesh.indexes.get(idx0)); diff --git a/main/boofcv-io/src/test/java/boofcv/io/points/impl/TestPlyCodec.java b/main/boofcv-io/src/test/java/boofcv/io/points/impl/TestPlyCodec.java index f6461530ec..43623f2674 100644 --- a/main/boofcv-io/src/test/java/boofcv/io/points/impl/TestPlyCodec.java +++ b/main/boofcv-io/src/test/java/boofcv/io/points/impl/TestPlyCodec.java @@ -43,12 +43,12 @@ class TestPlyCodec extends BoofStandardJUnit { @Test void encode_decode_3D_ascii() throws IOException { - List expected = new ArrayList<>(); + var expected = new ArrayList(); for (int i = 0; i < 10; i++) { expected.add(new Point3D_F64(i*123.45, i - 1.01, i + 2.34)); } - DogArray found = new DogArray<>(Point3D_F64::new); + var found = new DogArray<>(Point3D_F64::new); var output = new StringWriter(); PlyCodec.saveCloudAscii(PointCloudReader.wrapF64(expected), false, output); @@ -143,6 +143,7 @@ class TestPlyCodec extends BoofStandardJUnit { int numVertexes = 10; for (int i = 0; i < numVertexes; i++) { mesh.vertexes.append(i, 2, 3); + mesh.vertexNormals.append(i, 2, 3); // bound indexes to ensure they are in the valid range mesh.indexes.add((i*3)%numVertexes); @@ -169,6 +170,7 @@ class TestPlyCodec extends BoofStandardJUnit { PlyCodec.readMesh(input, foundMesh, foundColors); assertEquals(mesh.vertexes.size(), mesh.vertexes.size()); + assertEquals(mesh.vertexNormals.size(), mesh.vertexNormals.size()); assertEquals(mesh.texture.size(), mesh.texture.size()); assertTrue(mesh.indexes.isEquals(foundMesh.indexes)); assertTrue(mesh.offsets.isEquals(foundMesh.offsets)); @@ -178,6 +180,7 @@ class TestPlyCodec extends BoofStandardJUnit { Point3D_F64 expected = mesh.vertexes.getTemp(i); Point3D_F64 found = foundMesh.vertexes.getTemp(i); assertEquals(0.0, expected.distance(found)); + assertTrue(mesh.vertexNormals.getTemp(i).isIdentical(foundMesh.vertexNormals.getTemp(i), 1e-4f)); } for (int i = 0; i < mesh.vertexes.size(); i++) { diff --git a/main/boofcv-io/src/test/java/boofcv/visualize/TestRenderMesh.java b/main/boofcv-io/src/test/java/boofcv/visualize/TestRenderMesh.java index cb2068b971..ace9add16e 100644 --- a/main/boofcv-io/src/test/java/boofcv/visualize/TestRenderMesh.java +++ b/main/boofcv-io/src/test/java/boofcv/visualize/TestRenderMesh.java @@ -50,7 +50,7 @@ public class TestRenderMesh extends BoofStandardJUnit { var alg = new RenderMesh(); // turn off checking with normals to simply this test - alg.setCheckSurfaceNormal(false); + alg.setCheckFaceNormal(false); PerspectiveOps.createIntrinsic(300, 200, 90, -1, alg.intrinsics); // Render @@ -198,7 +198,7 @@ public class TestRenderMesh extends BoofStandardJUnit { // This should pass mesh.reset(); mesh.indexes.add(0); - mesh.normals.append(-c, -s, 0); + mesh.faceNormals.append((float)-c, (float)-s, 0); mesh.vertexes.append(r*c, 2 + r*s, 2); assertTrue(RenderMesh.isFrontVisible(mesh, 0, 0, pointCam)); @@ -206,7 +206,7 @@ public class TestRenderMesh extends BoofStandardJUnit { // This should fail mesh.reset(); mesh.indexes.add(0); - mesh.normals.append(c, s, 0); + mesh.faceNormals.append((float)c, (float)s, 0); mesh.vertexes.append(r*c, 2 + r*s, 2); assertFalse(RenderMesh.isFrontVisible(mesh, 0, 0, pointCam)); diff --git a/main/boofcv-types/src/main/java/boofcv/struct/mesh/VertexMesh.java b/main/boofcv-types/src/main/java/boofcv/struct/mesh/VertexMesh.java index 92dcd61464..a3c36dad95 100644 --- a/main/boofcv-types/src/main/java/boofcv/struct/mesh/VertexMesh.java +++ b/main/boofcv-types/src/main/java/boofcv/struct/mesh/VertexMesh.java @@ -18,7 +18,7 @@ package boofcv.struct.mesh; -import boofcv.struct.packed.PackedArrayPoint3D_F64; +import boofcv.struct.packed.PackedArrayPoint3D_F32; import boofcv.struct.packed.PackedBigArrayPoint2D_F32; import boofcv.struct.packed.PackedBigArrayPoint3D_F64; import georegression.geometry.GeometryMath_F64; @@ -40,17 +40,20 @@ public class VertexMesh { /** 3D location of each vertex */ public final PackedBigArrayPoint3D_F64 vertexes = new PackedBigArrayPoint3D_F64(10); - /** Which indexes correspond to each vertex in a shape */ + /** Which indexes correspond to each vertex in a face */ public final DogArray_I32 indexes = new DogArray_I32(); - /** Start index of each shape + the last index */ + /** Start index of each face + the last index */ public final DogArray_I32 offsets = new DogArray_I32(); /** 2D coordinate of textures. units = fraction of width / height */ public final PackedBigArrayPoint2D_F32 texture = new PackedBigArrayPoint2D_F32(); - /** Optional precomputed surface normals for each shape */ - public final PackedArrayPoint3D_F64 normals = new PackedArrayPoint3D_F64(); + /** Optional precomputed normals for each vertex */ + public final PackedArrayPoint3D_F32 vertexNormals = new PackedArrayPoint3D_F32(); + + /** Optional precomputed normal for each face */ + public final PackedArrayPoint3D_F32 faceNormals = new PackedArrayPoint3D_F32(); { offsets.add(0); @@ -140,11 +143,13 @@ public void addShape( List shape ) { /** * Computes normal vectors from shapes */ - public void computeNormals() { + public void computeFaceNormals() { var vector1 = new Vector3D_F64(); var vector2 = new Vector3D_F64(); var norm = new Vector3D_F64(); + faceNormals.reset(); + faceNormals.reserve(offsets.size() - 1); for (int idxShape = 1; idxShape < offsets.size; idxShape++) { int idx0 = offsets.get(idxShape - 1); @@ -154,7 +159,7 @@ public void computeNormals() { GeometryMath_F64.cross(vector1, vector2, norm); norm.normalize(); - normals.append(norm.x, norm.y, norm.z); + faceNormals.append((float)norm.x, (float)norm.y, (float)norm.z); } } @@ -176,6 +181,8 @@ public VertexMesh setTo( VertexMesh src ) { this.indexes.setTo(src.indexes); this.offsets.setTo(src.offsets); this.texture.setTo(src.texture); + this.vertexNormals.setTo(src.vertexNormals); + this.faceNormals.setTo(src.faceNormals); return this; } @@ -184,7 +191,8 @@ public void reset() { indexes.reset(); offsets.reset(); texture.reset(); - normals.reset(); + vertexNormals.reset(); + faceNormals.reset(); offsets.add(0); } @@ -206,4 +214,8 @@ public MeshPolygonAccess toAccess() { public boolean isTextured() { return texture.size() > 0; } + + public boolean isNormals() { + return vertexNormals.size() > 0; + } } diff --git a/main/boofcv-types/src/test/java/boofcv/struct/mesh/TestVertexMesh.java b/main/boofcv-types/src/test/java/boofcv/struct/mesh/TestVertexMesh.java index 1866fe98cc..92369f25f9 100644 --- a/main/boofcv-types/src/test/java/boofcv/struct/mesh/TestVertexMesh.java +++ b/main/boofcv-types/src/test/java/boofcv/struct/mesh/TestVertexMesh.java @@ -79,7 +79,7 @@ public class TestVertexMesh extends BoofStandardJUnit { assertEquals(5, found.size); } - @Test void computeNormals() { + @Test void computeFaceNormals() { var shape = new DogArray<>(Point3D_F64::new); shape.grow().setTo(0,0,0); @@ -92,9 +92,9 @@ public class TestVertexMesh extends BoofStandardJUnit { shape.reverse(); alg.addShape(shape.toList()); - alg.computeNormals(); - assertEquals(0.0, alg.normals.getTemp(0).distance(0,0,-1), UtilEjml.TEST_F64); - assertEquals(0.0, alg.normals.getTemp(1).distance(0,0,1), UtilEjml.TEST_F64); + alg.computeFaceNormals(); + assertEquals(0.0, alg.faceNormals.getTemp(0).distance(0,0,-1), UtilEjml.TEST_F64); + assertEquals(0.0, alg.faceNormals.getTemp(1).distance(0,0,1), UtilEjml.TEST_F64); // try it with a non-triangle shape.reset(); @@ -104,7 +104,7 @@ public class TestVertexMesh extends BoofStandardJUnit { shape.grow().setTo(2,9,0); alg.reset(); alg.addShape(shape.toList()); - assertEquals(0.0, alg.normals.getTemp(0).distance(0,0,-1), UtilEjml.TEST_F64); + assertEquals(0.0, alg.faceNormals.getTemp(0).distance(0,0,-1), UtilEjml.TEST_F64); } private List createRandomShape( int count ) {