diff --git a/src/Geometry-Tests/GEllipseTest.class.st b/src/Geometry-Tests/GEllipseTest.class.st index ac54836..8132cd4 100644 --- a/src/Geometry-Tests/GEllipseTest.class.st +++ b/src/Geometry-Tests/GEllipseTest.class.st @@ -12,6 +12,12 @@ GEllipseTest >> actualClass [ ^ GEllipse ] +{ #category : #util } +GEllipseTest >> sortedIntersectionsBetween: shape and: line [ + ^ (shape intersectionsWith: line) asOrderedCollection + sorted: [ :a :b | a asPoint < b asPoint ]. +] + { #category : #tests } GEllipseTest >> testArea [ ellipse := GEllipse center: 5 , -1 vertex: 10 , -1 coVertex: 5 , 2. @@ -29,6 +35,13 @@ GEllipseTest >> testBoundaryContains [ self deny: (ellipse boundaryContains: 3, 0.13). ] +{ #category : #tests } +GEllipseTest >> testEmpty [ + self should: [ GEllipse center: 0,0 vertex: 0,0 coVertex: 0,0. ] raise: Error. + self should: [ GEllipse center: 10,10 vertex: 10,10 coVertex: 10,10. ] raise: Error. + self should: [ GEllipse center: 0,0 vertex: 0,0 coVertex: 0,3. ] raise: Error. +] + { #category : #tests } GEllipseTest >> testEncompassingRectangle [ ellipse := GEllipse center: 4 , -1 vertex: 9 , -1 coVertex: 4 , 2. @@ -210,6 +223,17 @@ GEllipseTest >> testMinorAxis [ self assert: ellipse minorAxis equals: (GSegment with: 10 , 8 with: 10 , 12) ] +{ #category : #tests } +GEllipseTest >> testNonEmpty [ + | shape line intersections | + shape := GEllipse center: 0@0 vertex: 0@10 coVertex: 5@10. + line := GLine through: shape center and: 10@10. + intersections := self sortedIntersectionsBetween: shape and: line. + self assert: intersections isNotEmpty. + self assert: (intersections first asPoint closeTo: -7.4535599249993@ -7.4535599249993). + self assert: (intersections second asPoint closeTo: 7.4535599249993@ 7.4535599249993). +] + { #category : #tests } GEllipseTest >> testPerimeter [ ellipse := GEllipse center: 2,6 vertex: 7, 6 coVertex: 2,9. diff --git a/src/Geometry/GEllipse.class.st b/src/Geometry/GEllipse.class.st index 46f4c63..afb8b88 100644 --- a/src/Geometry/GEllipse.class.st +++ b/src/Geometry/GEllipse.class.st @@ -1,3 +1,13 @@ +" +I am ellipse I have center and 2 vertices. + +Example + +```Smalltalk +""circle radius = 10"" +GEllipse center: 0@0 vertex: 0@10 coVertex: 10@0 +``` +" Class { #name : #GEllipse, #superclass : #GShape, @@ -11,6 +21,14 @@ Class { { #category : #'instance creation' } GEllipse class >> center: aGPoint vertex: aGPoint2 coVertex: aGPoint3 [ + | d1 d2 zero | + d1 := aGPoint - aGPoint2. + d2 := aGPoint - aGPoint3. + zero := GVector x: 0 y: 0."Zero vector" + (d1 = zero and: [ d2 = zero ]) ifTrue: [ + self error: 'This is not an ellipse but a point.' ]. + (d1 = zero or: [ d2 = zero ]) ifTrue: [ + self error: 'This is not an ellipse but a line.' ]. ^ self new center: aGPoint; vertex: aGPoint2; @@ -133,6 +151,7 @@ GEllipse >> intersectionsWithLine: aGLine [ k := center y. a := self semiMajorAxisLength. b := self semiMinorAxisLength. + m := aGLine a / aGLine b negated. c := aGLine c / aGLine b negated. e := c - k. @@ -148,8 +167,8 @@ GEllipse >> intersectionsWithLine: aGLine [ tk := t * k. sqrtContent := (a2m2 + b2 - t2 - k2 + (2 * tk)). sqrtContent >= 0 ifFalse: [ ^ { } ]. "No intersections" + sqrt := (a2m2 + b2 - t2 - k2 + (2 * tk)) sqrt. - x1 := (h * b2 - (m * a2 * e) + (ab * sqrt)) / (a2m2 + b2). x2 := (h * b2 - (m * a2 * e) - (ab * sqrt)) / (a2m2 + b2). y1 := (b2 * t + (k * a2m2) + (abm * sqrt)) / (a2m2 + b2). diff --git a/src/Geometry/GPoint.class.st b/src/Geometry/GPoint.class.st index a84ea4d..23c072a 100644 --- a/src/Geometry/GPoint.class.st +++ b/src/Geometry/GPoint.class.st @@ -116,6 +116,11 @@ GPoint >> asGPoint [ ^ self ] +{ #category : #converting } +GPoint >> asPoint [ + ^ self x @ self y +] + { #category : #accessing } GPoint >> coordinates [ ^ coordinates diff --git a/src/Geometry/GSegment.class.st b/src/Geometry/GSegment.class.st index 49fc97a..83707d8 100644 --- a/src/Geometry/GSegment.class.st +++ b/src/Geometry/GSegment.class.st @@ -74,7 +74,7 @@ GSegment >> distanceTo: aGPoint [ ^ self asGLine distanceTo: aGPoint ] -{ #category : #initialization } +{ #category : #comparing } GSegment >> hash [ ^ v1 hash bitXor: v2 hash ] diff --git a/src/Geometry/ManifestGeometry.class.st b/src/Geometry/ManifestGeometry.class.st deleted file mode 100644 index d7c89cd..0000000 --- a/src/Geometry/ManifestGeometry.class.st +++ /dev/null @@ -1,8 +0,0 @@ -" -I am a project of Euclidean geometry. -" -Class { - #name : #ManifestGeometry, - #superclass : #PackageManifest, - #category : #'Geometry-Manifest' -}