Array of unique points?
-
When you have an array of arbitrary
points- and you want to ensure that array only contains unique points, how do you filter them out?points.uniq!doesn't seem to work.Example:
` point1 = Geom::Point3d.new 1,1,1
Point3d(1, 1, 1)
point2 = Geom::Point3d.new 10,10,10
Point3d(10, 10, 10)
point3 = Geom::Point3d.new 10,10,10
Point3d(10, 10, 10)
a = [point1, point2, point3]
[Point3d(1, 1, 1), Point3d(10, 10, 10), Point3d(10, 10, 10)]
a.uniq
[Point3d(1, 1, 1), Point3d(10, 10, 10), Point3d(10, 10, 10)]` -
Any chance you are getting the points from an array of vertices? Vertices will respond to the uniq(!) methods. I can't think of any time that I actually sorted by Point3d objects. And I tihnk it was because I found it easier to use vertices, which has always worked out ok for what I was writing.
Chris
-
No, not vertices. computed intersections.
-
atm I got this code:
def self.uniq_points(points) old_points = points.clone new_points = [] until old_points.empty? point = old_points.shift point_exists = false new_points.each { |p| if p == point point_exists = true break end } new_points << point unless point_exists end return new_points endbut I was wondering if there was a better method....
-
Yeah, as I was thinking - each Point3d object is its own object, and therefore different, even though they might share the same coordinates in space.
You need to compare them as strings I suppose, since I see no quicker comparison method(?). Try this line:
` a = [point1.inspect, point2.inspect, point3.inspect]
a.uniq`
That should work, I don't know how slow it will be if its over zillions of points though,
Chris
-
no, not string. you can compare two points -
point1 == point2if return true if they are the same point, withing some tolerance SU has set. But it seems thatarray.uniqdoesn't do this type of comparison... -
Point3d's will be uniq!'d if they have the same ID BUT NOT if they have just the same XYZ values [they aren't really equal are they?], but we can write a simple def to sort it out...
def unique(pointsIN = []) return pointsIN if pointsIN.to_a[0].class != Geom;;Point3d # we'll only process an array of Point3d's ? points_a = []; pointsIN.to_a.compact.each{|p| points_a << p.to_a}; pointsa.uniq! # we compact to remove any 'nil' entries ? pointsOUT = []; points_a.each{|p| pointsOUT << Geom.Point3d.new(p.x, p.y, p.z)} return pointsOUT end#def # Assuming a list [array] of Point3d's that might contain duplicates called 'points' then... points = unique points # will give us a list [array] of unique Point3d's called 'points'...
-
Alternatively, following TT's point1 == point2 idea
def unique(pointsIN = []) pointsOUT=[] pointsIN.to_a.each{|p| duplicated = false pointsOUT.each{|po| if po == p duplicated = true break end#if } pointsOUT << p if not duplicated } return pointsOUT end#def points = points uniqueWhich keeps the Point3d's IDs unchanged...

-
@thomthom said:
But it seems that
array.uniqdoesn't do this type of comparison...Have you tried just adding them to a set?
-
I was pretty sure I'd tried that!
But clearly I haven't!` point1 = Geom::Point3d.new 1,1,1
Point3d(1, 1, 1)
point2 = Geom::Point3d.new 10,10,10
Point3d(10, 10, 10)
point3 = Geom::Point3d.new 10,10,10
Point3d(10, 10, 10)
s = Set.new
#Set:0xbd7da68
s.insert(point1)
#Set:0xbd7da68
s.insert(point2)
#Set:0xbd7da68
s.insert(point3)
#Set:0xbd7da68
s.to_a
[Point3d(1, 1, 1), Point3d(10, 10, 10)]`Very interesting that it evaluates differently. It compares the values, not the objects.

Exactly the kind of solution I was hoping for.
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register LoginAdvertisement