-
Notifications
You must be signed in to change notification settings - Fork 185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement shapeutil_visit_crossing_edge_pairs
#135
base: master
Are you sure you want to change the base?
Conversation
Worth noting an oddity between the CPP and Go implementations, the edge crossings
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would like to add this functionality.
Can you explain your basic process for converting this? Is it a straightforward translation of the C++ code?
Where did you do something differently from C++?
// VisitCrossingEdgePairs finds all crossing edge pairs in an index. | ||
func VisitCrossingEdgePairs(index *ShapeIndex, crossingType CrossingType, visitor EdgePairVisitor) bool { | ||
needAdjacent := crossingType == CrossingTypeAll | ||
for it := index.Iterator(); !it.Done(); it.Next() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why this doesn't call VisitCrossings
like the C++ does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two lines below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It calls visitCrossings
in a loop. Could this be a single call to VisitCrossings
, like the C++ does? It looks like you're reimplementing VisitCrossings
.
The main obstacle to a 1:1 port are CPP function overloading, this necessitates some function renaming as Golang doesn't support overloading. There are numerous differences, I'm not going to even try to list them all, most notably is the one I commented about above, different struct definitions between the two, use of pointers in CPP but values in Go, porting stdlib fiction calls, etc. Functionally the code is the same, you can probably ask an AI to summarize if you're not comfortable reviewing by eye. |
crosser.RestartAt(b.Edge.V0) | ||
} | ||
sign := crosser.ChainCrossingSign(b.Edge.V1) | ||
// missinglink: enum ordering is reversed compared to C++ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what to get out of "missinglink:"? Is this
// Note that enum ordering is reversed compared to C++
// TODO(missinglink): Make them match.
?
} | ||
|
||
func FindCrossingError(shape Shape, a, b ShapeEdge, isInterior bool) error { | ||
ap := shape.ChainPosition(int(a.ID.EdgeID)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason not to have is_polygon in the error messages?
polygon := makePolygon(tc.polygonStr, true) | ||
testHasCrossingPermutations(t, polygon.loops, 0, tc.hasCrossing) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do these test cases match up with the C++ coverage? I don't see a FindSelfIntersection
test.
TEST(GetCrossingEdgePairs, NoIntersectionsOneIndex) {
TEST(GetCrossingEdgePairs, NoIntersectionsTwoIndexes) {
TEST(GetCrossingEdgePairs, EdgeGridOneIndex) {
TEST(GetCrossingEdgePairs, EdgeGridTwoIndexes) {
TEST(FindSelfIntersection, Basic) {
|
||
import "fmt" | ||
|
||
type ShapeEdgeVector []ShapeEdge |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be package private since it's only used in private methods
|
||
import "fmt" | ||
|
||
type ShapeEdgeVector []ShapeEdge |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Go slice types of types should generally be named as the plural of the type. e.g. shapeEdges []ShapeEdge.
(also Vector is used through s2 already as an X,Y,Z object, so the name would be somewhat confusing that the defined type has no ShapeEdge but no Vector part.)
return true | ||
} | ||
|
||
// Visits all pairs of crossing edges in the given S2ShapeIndex, terminating |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://go.dev/doc/comment#func
Func comments should start with the name of the function. (here and all others)
|
||
type EdgePairVisitor func(a, b ShapeEdge, isInterior bool) bool | ||
|
||
// getShapeEdges returns all edges in the given S2ShapeIndexCell. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace all C++ type names with the Go counterparts in comments.
e.g. S2ShapeIndexCell -> ShapeIndexCell
return true | ||
} | ||
|
||
func FindCrossingError(shape Shape, a, b ShapeEdge, isInterior bool) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be private and needs the corresponding doc comments from c++
} | ||
} | ||
|
||
func testHasCrossingPermutations(t *testing.T, loops []*Loop, i int, hasCrossing bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add the c++ function comments to this
} | ||
|
||
func TestGetCrossingEdgePairsGrid(t *testing.T) { | ||
kGridSize := 10.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const gridSize = 10.0
t.Errorf("Fail") | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are none of the two index versions of the tests. Can you add a TODO for them to be added?
|
||
index.Add(&shape) | ||
if len(getCrossingEdgePairsBruteForce(index, CrossingTypeAll)) != 112 { | ||
t.Errorf("Fail") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error messages should be more descriptive than just 'fail'
"testing" | ||
) | ||
|
||
type EdgePair struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be private
if isInterior { | ||
if ap.ChainID != bp.ChainID { | ||
return fmt.Errorf( | ||
"Loop %d edge %d crosses loop %d edge %d", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and elsewhere: Error messages should start with lower-case, since they may be wrapped with more context (https://google.github.io/styleguide/go/decisions.html#error-strings)
// However, the vertical lines do not reach the top line as it curves on the | ||
// surface of the sphere: despite "epsilon" those 9 are not even very close | ||
// to intersecting. Thus 9 * 12 = 108 interior and four more at the corners | ||
// when CrossingType::ALL is used. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CrossingTypeAll
index.Add(polygon) | ||
|
||
if hasCrossing != FindSelfIntersection(index) { | ||
t.Error("Test failed: expected and actual crossing results do not match") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idiomatic Go style is like
if got := FindSelfIntersection(index); got != hasCrossing {
t.Errorf("FindSelfIntersection got %v, want %v", got, hasCrossing)
}
It would be nice to include something about the loops (FindSelfIntersection(%s)
), though there isn't a loopToString textformat function yet.
This PR implements
shapeutil_visit_crossing_edge_pairs
which is required to resolve #108.If this is something you'd be interested in merging then let me know.
All the tests (so far) are passing, it just needs to be cleaned up a bit.