• Login
sketchucation logo sketchucation
  • Login
⚠️ Libfredo 15.4b | Minor release with bugfixes and improvements Update

Array.uniq! for a 3d-point array ???

Scheduled Pinned Locked Moved Developers' Forum
6 Posts 4 Posters 1.1k Views 4 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    artmusicstudio
    last edited by 29 Jun 2014, 16:20

    hi,
    i cannot find the syntax for

    arry.uniq!,

    where the array contains some 3d-points and i have to delete the identical 3d-point from it.

    the array in the ruby-console:

    show array:

    
    roof.each { |e|
    puts e
    	}
    
    

    result:


    (-503,8105m, 0m, 8,999982m)
    (-503,8105m, -57,150823m, 8,999982m)
    (-583,560407m, -92,554593m, 8,999982m)
    (-583,560407m, -92,554593m, 8,999982m)
    (-583,560407m, -59,804506m, 8,999982m)
    (-503,8105m, 0m, 8,999982m)


    roof.uniq!

    does not work.

    zhanx for tips!
    stan

    1 Reply Last reply Reply Quote 0
    • A Offline
      Aerilius
      last edited by 29 Jun 2014, 17:01

      Point3ds are "real" objects and have an identity (two objects with same properties are not the same object). Things that we can compare have a method == that checks whether two objects are "equal" (trivial for numbers and strings). SketchUp's Geom::Point3d.== method checks for example if all coordinates (x, y, z) are equal, and then says two points are equal.

      uniq appears to check for identity and not for equality. So we need to do it on our own, with checking for equality:

      roof = roof.inject([]){ |array, point| array.any?{ |p| p == point } ? array ; array << point }
      

      It does the same as:

      
      roof2 = []
      roof.each{ |point|
        # Check if we have already added any points to 'roof2' that are equal with 'point'.
        any = false
        roof2.each{ |p|
          break any = true if p == point
        }
        # If 'roof2' does not contain an equal point, we can add it.
        roof2.push(point) if not any
      }
      roof = roof2
      
      
      1 Reply Last reply Reply Quote 0
      • T Offline
        TIG Moderator
        last edited by 29 Jun 2014, 17:20

        A Point3d is pretty much an Array, at least for many aspects of most methods, and a three item Array can usually be treated as a Point3d too.
        But as has been said unless your array-of-points [which you want to use .uniq on] is an array of Array objects and not Point3d objects it will not work, since each Point3d has a unique reference already.
        So make an array of points-made-into-arrays [using point.to_a etc] and then use .uniq! on that. Any duplicates that match will be removed - but be aware that if the ordering is important the missing duplicate-point-as-array might make difficulties for you 'down the line'...

        Alternatively, iterate each point and compare it with every other point in the array, using point==point_i - this includes SketchUp's tolerance, so two ALMOST each points are considered equal, but the equivalent array might no be !

        Why do you want to do this?
        There may be alternative ways of approaching the challenge ??

        TIG

        1 Reply Last reply Reply Quote 0
        • A Offline
          artmusicstudio
          last edited by 29 Jun 2014, 20:11

          hi tig,
          your last question was the solution. i needed an hour and two coffies....

          instead of duplicating all startpoints of face edges in a certain height and then creating new edges between them (which caused the problem, when more lines met in one point >> doubled startpoints)

          i just draw the bottom line and its pendant in height "x" directly in the method and place them into another group.

          but anyway: your line for clearing the array is fantastic, although i had the problem, that there was no controll over which of the identical point is deleted and so the result face sometimes was missing a point. but i will study this later.

          so thanx for helping and the advice ! the OTHER WAY seems to work.

          stan

          1 Reply Last reply Reply Quote 0
          • D Offline
            Dan Rathbun
            last edited by 30 Jun 2014, 08:12

            I seem to remember injectrunning slowly in Ruby 1.8.x

            @aerilius said:

            It does the same as:

            
            > roof2 = []
            > roof.each{ |point|
            >   # Check if we have already added any points to 'roof2' that are equal with 'point'.
            >   any = false
            >   roof2.each{ |p|
            >     break any = true if p == point
            >   }
            >   # If 'roof2' does not contain an equal point, we can add it.
            >   roof2.push(point) if not any
            > }
            > roof = roof2
            > 
            

            My condensed edition would be:

            pts = []
            roof.each {|point|
              next unless point.is_a?(Geom;;Point3d)
              pts << point unless pts.any? {|p| p == point }
            }
            
            

            I'm not here much anymore.

            1 Reply Last reply Reply Quote 0
            • D Offline
              Dan Rathbun
              last edited by 30 Jun 2014, 08:31

              @aerilius said:

              Geom::Point3d.== method checks for example if all coordinates (x, y, z) are equal, and then says two points are equal.

              uniq appears to check for identity and not for equality.

              In Ruby 2.x (SketchUp 2014+,) where we now have a block form of the uniq method, that we can tailor to override C internals of the uniq! method, and tell it what and how to do the comparison.
              Ex:
              pts = roof.uniq {|a,b| a.==(b) }
              or:
              pts = roof.uniq {|pt| pt.to_a }

              In the future, perhaps, custom uniq methods could be added to a new PointArray subclass of Array., for the API.
              Of course any author could create such a custom class within their own namespace(s).

              ALSO.. the many od the API classes should have had their eql?() method aliased as the overridden ==() method.
              The uniq methods want to call eql?() instead of ==().

              I'm not here much anymore.

              1 Reply Last reply Reply Quote 0
              • 1 / 1
              1 / 1
              • First post
                1/6
                Last post
              Buy SketchPlus
              Buy SUbD
              Buy WrapR
              Buy eBook
              Buy Modelur
              Buy Vertex Tools
              Buy SketchCuisine
              Buy FormFonts

              Advertisement