I Can't Get The Function [uniq] To Work Correctly

dear all, I was confused.

plz look to the codes:

pt1=Geom::Point3d.new(1,2,3);
pt2=Geom::Point3d.new(1,2,3);

attr=[pt1,pt2]
attr.uniq!

what’s the result suppose to be ?
the answer IS:
[Point3d(1, 2, 3), Point3d(1, 2, 3)]

you have to code like this

attr.uniq!{ |pt| pt.to_s }

now ,the answer is
[Point3d(1, 2, 3)]

Hash is the same situation.

I think the Point3d::hash function is not working correctly?

anyone can clarify the situation? thank you.

No, the return of the last ruby action is the second item in attr

to see both in Ruby Console you would need to use a p or puts

 attr.uniq!{ |pt| p pt.to_s }
"(0.0254m, 0.0508m, 0.0762m)"
"(0.0254m, 0.0508m, 0.0762m)"
[Point3d(1, 2, 3)]

your use of ‘uniq!’ on 2 identically positioned points is also quite unique…

a more common use is to remove duplicates…

[1,2,3,4,2].uniq!
[1, 2, 3, 4]

john

I am sorry, I think I am not clarify the question clearly

maybe the pic can help me to clarify the question

I want to say, I have to use pt.to_s to get rid of the duplicate pts.

I though the to_s function should not be called.

The Geom::Point3d class doesn’t implement its own hash function. If you want to reduce a set of point to not have duplicate 3d points you need to roll your own.

.uniq let you provide a block, but it is probably not as useful here. Point3d points needs to be compared with a given tolerance. Working out a hash for a 3d point that match that tolerance wouldn’t be easy.

your creating 2 unique items, so calling uniq! has no effect…

if you look at the __id__ you can see they are different…

 pt1=Geom::Point3d.new(1,2,3);
pt2=Geom::Point3d.new(1,2,3);

attr=[pt1.__id__,pt2.__id__]
attr.uniq!

> attr
[70333115913020, 70333115913000]

you need to compare positions of points…
or use to_a

pt1=Geom::Point3d.new(1,2,3);
pt2=Geom::Point3d.new(1,2,3);

attr=[pt1.to_a,pt2.to_a]
 attr.uniq!

# => [[1.0, 2.0, 3.0]]

john

so, here is the question: What does the same point mean?

tolerance is different in different company , different industry, even different people.

It’s not easy way to implement the Point3d::hash to satisfy all the requirements.

But, is it the best way to use the object_id instead?

Maybe , the best default way is to set the tolerance to be Zero, which means the given certain points

can be checked duplicated if they have same position rather than the same object id.

That’s my suggestion , thanks.

The Geom::Point3d class overrides the == method to test for equality to within SketchUp’s standard tolerance. Since this is the logic that SketchUp itself will use internally, it seems to me it is also what you want to use to preserve the semantics of when two points are “the same”.

Edit: never mind! I replied too quickly from my phone without looking at the docs for uniq

(1) It is not smart to use attr as an object reference because it is a global method for all modules and classes:


(2) Using the SketchUp API’s Geom::Point3d#== method.

Using 2 arrays, the original (ary) and a new array that will be unique (uniq_ary):

uniq_ary = []
ary.each {|pt|
  uniq_ary << pt unless uniq_ary.any? {|i| i == pt }
}

Or, one array using the block forms of the Array class’ delete_if and count methods:


ary.delete_if {|pt|
  ary.count {|i| i == pt } > 1
}

* Note that the block form of the count method is Ruby 2.x (SketchUp 2014) and higher.

1 Like

OK, to discuss the question ,see these codes.

    pt1=Geom::Point3d.new(1,2,3)
    pt2=Geom::Point3d.new(4,6,7);
    pt3=Geom::Point3d.new(pt2);

    pt2==pt3
    pt2.eql?(pt3);

pt2 == pt3? true
pt2.eql?(pt3) false

why?
the same operations have different result. just because the two objects have no same object id?
I say “SAME” , just from the significant understood by human nature but not from the computer concept.

pt1=Geom::Point3d.new(1,2,3)
pt2=Geom::Point3d.new(4,6,7)
pt3=Geom::Point3d.new(pt2);

my_array=[pt1,pt2,pt3];
my_array.uniq!

To a newbie, what’s the result he expects?

In my opinion, OO programming should based on the significant but not on the computer concept, such as object id…

Geom::Point3d#== has been over written but Geom::Point3d#eql? and Geom::Point3d#hash have not.

That’s what I am confusing.

Thanks all.

HI, all guys

I am not challenge all you guys.

I respect you all very much, you are great.

I love SU very much, amazing product I have met.

The topic just talks about my little confusion

when I am reading the article here
http://stackoverflow.com/questions/7156955/whats-the-difference-between-equal-eql-and

thank you

Beware - this would not perform a tolerance comparison. This would be very prone to floating point precision issues.

There are some things with the old SU classes like this - stems back from the very beginning. For instance, you have to use point.clone and not point.dup to get a copy of points and vectors.