Skip to content

Commit adfff0c

Browse files
authored
Merge pull request kodecocodes#630 from mnespor/convex-hull-sometimes-produces-incorrect-result-487
Convex hull sometimes produces incorrect result 487
2 parents 5dc06ac + 6d816c2 commit adfff0c

File tree

6 files changed

+279
-14
lines changed

6 files changed

+279
-14
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ script:
2020
- xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests
2121
- xcodebuild test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests
2222
- xcodebuild test -project ./Comb\ Sort/Tests/Tests.xcodeproj -scheme Tests
23+
- xcodebuild test -project ./Convex\ Hull/Convex\ Hull.xcodeproj -scheme Tests -destination 'platform=iOS Simulator,name=iPhone 7,OS=11.0'
2324
- xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests
2425
- xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests
2526
- xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests

Convex Hull/Convex Hull.xcodeproj/project.pbxproj

Lines changed: 145 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,28 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
1CB614301F89456C00A14493 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CB6142F1F89456C00A14493 /* Tests.swift */; };
11+
1CB614371F8945B300A14493 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E6D68CB1E599CF100161780 /* View.swift */; };
1012
8E6D68BA1E59989400161780 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E6D68B91E59989400161780 /* AppDelegate.swift */; };
1113
8E6D68C11E59989400161780 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8E6D68C01E59989400161780 /* Assets.xcassets */; };
1214
8E6D68C41E59989400161780 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8E6D68C21E59989400161780 /* LaunchScreen.storyboard */; };
1315
8E6D68CC1E599CF100161780 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E6D68CB1E599CF100161780 /* View.swift */; };
1416
/* End PBXBuildFile section */
1517

18+
/* Begin PBXContainerItemProxy section */
19+
1CB614321F89456C00A14493 /* PBXContainerItemProxy */ = {
20+
isa = PBXContainerItemProxy;
21+
containerPortal = 8E6D68AE1E59989400161780 /* Project object */;
22+
proxyType = 1;
23+
remoteGlobalIDString = 8E6D68B51E59989400161780;
24+
remoteInfo = "Convex Hull";
25+
};
26+
/* End PBXContainerItemProxy section */
27+
1628
/* Begin PBXFileReference section */
29+
1CB6142D1F89456C00A14493 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
30+
1CB6142F1F89456C00A14493 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = "<group>"; };
31+
1CB614311F89456C00A14493 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
1732
8E6D68B61E59989400161780 /* Convex Hull.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Convex Hull.app"; sourceTree = BUILT_PRODUCTS_DIR; };
1833
8E6D68B91E59989400161780 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
1934
8E6D68C01E59989400161780 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -23,6 +38,13 @@
2338
/* End PBXFileReference section */
2439

2540
/* Begin PBXFrameworksBuildPhase section */
41+
1CB6142A1F89456C00A14493 /* Frameworks */ = {
42+
isa = PBXFrameworksBuildPhase;
43+
buildActionMask = 2147483647;
44+
files = (
45+
);
46+
runOnlyForDeploymentPostprocessing = 0;
47+
};
2648
8E6D68B31E59989400161780 /* Frameworks */ = {
2749
isa = PBXFrameworksBuildPhase;
2850
buildActionMask = 2147483647;
@@ -33,10 +55,20 @@
3355
/* End PBXFrameworksBuildPhase section */
3456

3557
/* Begin PBXGroup section */
58+
1CB6142E1F89456C00A14493 /* Tests */ = {
59+
isa = PBXGroup;
60+
children = (
61+
1CB6142F1F89456C00A14493 /* Tests.swift */,
62+
1CB614311F89456C00A14493 /* Info.plist */,
63+
);
64+
path = Tests;
65+
sourceTree = "<group>";
66+
};
3667
8E6D68AD1E59989400161780 = {
3768
isa = PBXGroup;
3869
children = (
3970
8E6D68B81E59989400161780 /* Convex Hull */,
71+
1CB6142E1F89456C00A14493 /* Tests */,
4072
8E6D68B71E59989400161780 /* Products */,
4173
);
4274
sourceTree = "<group>";
@@ -45,6 +77,7 @@
4577
isa = PBXGroup;
4678
children = (
4779
8E6D68B61E59989400161780 /* Convex Hull.app */,
80+
1CB6142D1F89456C00A14493 /* Tests.xctest */,
4881
);
4982
name = Products;
5083
sourceTree = "<group>";
@@ -64,6 +97,24 @@
6497
/* End PBXGroup section */
6598

6699
/* Begin PBXNativeTarget section */
100+
1CB6142C1F89456C00A14493 /* Tests */ = {
101+
isa = PBXNativeTarget;
102+
buildConfigurationList = 1CB614341F89456C00A14493 /* Build configuration list for PBXNativeTarget "Tests" */;
103+
buildPhases = (
104+
1CB614291F89456C00A14493 /* Sources */,
105+
1CB6142A1F89456C00A14493 /* Frameworks */,
106+
1CB6142B1F89456C00A14493 /* Resources */,
107+
);
108+
buildRules = (
109+
);
110+
dependencies = (
111+
1CB614331F89456C00A14493 /* PBXTargetDependency */,
112+
);
113+
name = Tests;
114+
productName = Tests;
115+
productReference = 1CB6142D1F89456C00A14493 /* Tests.xctest */;
116+
productType = "com.apple.product-type.bundle.unit-test";
117+
};
67118
8E6D68B51E59989400161780 /* Convex Hull */ = {
68119
isa = PBXNativeTarget;
69120
buildConfigurationList = 8E6D68C81E59989400161780 /* Build configuration list for PBXNativeTarget "Convex Hull" */;
@@ -87,10 +138,15 @@
87138
8E6D68AE1E59989400161780 /* Project object */ = {
88139
isa = PBXProject;
89140
attributes = {
90-
LastSwiftUpdateCheck = 0820;
141+
LastSwiftUpdateCheck = 0900;
91142
LastUpgradeCheck = 0820;
92143
ORGANIZATIONNAME = Workmoose;
93144
TargetAttributes = {
145+
1CB6142C1F89456C00A14493 = {
146+
CreatedOnToolsVersion = 9.0;
147+
ProvisioningStyle = Automatic;
148+
TestTargetID = 8E6D68B51E59989400161780;
149+
};
94150
8E6D68B51E59989400161780 = {
95151
CreatedOnToolsVersion = 8.2.1;
96152
DevelopmentTeam = 7C4LVS3ZVC;
@@ -112,11 +168,19 @@
112168
projectRoot = "";
113169
targets = (
114170
8E6D68B51E59989400161780 /* Convex Hull */,
171+
1CB6142C1F89456C00A14493 /* Tests */,
115172
);
116173
};
117174
/* End PBXProject section */
118175

119176
/* Begin PBXResourcesBuildPhase section */
177+
1CB6142B1F89456C00A14493 /* Resources */ = {
178+
isa = PBXResourcesBuildPhase;
179+
buildActionMask = 2147483647;
180+
files = (
181+
);
182+
runOnlyForDeploymentPostprocessing = 0;
183+
};
120184
8E6D68B41E59989400161780 /* Resources */ = {
121185
isa = PBXResourcesBuildPhase;
122186
buildActionMask = 2147483647;
@@ -129,6 +193,15 @@
129193
/* End PBXResourcesBuildPhase section */
130194

131195
/* Begin PBXSourcesBuildPhase section */
196+
1CB614291F89456C00A14493 /* Sources */ = {
197+
isa = PBXSourcesBuildPhase;
198+
buildActionMask = 2147483647;
199+
files = (
200+
1CB614371F8945B300A14493 /* View.swift in Sources */,
201+
1CB614301F89456C00A14493 /* Tests.swift in Sources */,
202+
);
203+
runOnlyForDeploymentPostprocessing = 0;
204+
};
132205
8E6D68B21E59989400161780 /* Sources */ = {
133206
isa = PBXSourcesBuildPhase;
134207
buildActionMask = 2147483647;
@@ -140,6 +213,14 @@
140213
};
141214
/* End PBXSourcesBuildPhase section */
142215

216+
/* Begin PBXTargetDependency section */
217+
1CB614331F89456C00A14493 /* PBXTargetDependency */ = {
218+
isa = PBXTargetDependency;
219+
target = 8E6D68B51E59989400161780 /* Convex Hull */;
220+
targetProxy = 1CB614321F89456C00A14493 /* PBXContainerItemProxy */;
221+
};
222+
/* End PBXTargetDependency section */
223+
143224
/* Begin PBXVariantGroup section */
144225
8E6D68C21E59989400161780 /* LaunchScreen.storyboard */ = {
145226
isa = PBXVariantGroup;
@@ -152,6 +233,60 @@
152233
/* End PBXVariantGroup section */
153234

154235
/* Begin XCBuildConfiguration section */
236+
1CB614351F89456C00A14493 /* Debug */ = {
237+
isa = XCBuildConfiguration;
238+
buildSettings = {
239+
BUNDLE_LOADER = "$(TEST_HOST)";
240+
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
241+
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
242+
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
243+
CLANG_WARN_COMMA = YES;
244+
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
245+
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
246+
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
247+
CLANG_WARN_STRICT_PROTOTYPES = YES;
248+
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
249+
CODE_SIGN_IDENTITY = "iPhone Developer";
250+
CODE_SIGN_STYLE = Automatic;
251+
GCC_C_LANGUAGE_STANDARD = gnu11;
252+
INFOPLIST_FILE = Tests/Info.plist;
253+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
254+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
255+
PRODUCT_BUNDLE_IDENTIFIER = com.mnespor.Tests;
256+
PRODUCT_NAME = "$(TARGET_NAME)";
257+
SWIFT_VERSION = 4.0;
258+
TARGETED_DEVICE_FAMILY = "1,2";
259+
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Convex Hull.app/Convex Hull";
260+
};
261+
name = Debug;
262+
};
263+
1CB614361F89456C00A14493 /* Release */ = {
264+
isa = XCBuildConfiguration;
265+
buildSettings = {
266+
BUNDLE_LOADER = "$(TEST_HOST)";
267+
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
268+
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
269+
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
270+
CLANG_WARN_COMMA = YES;
271+
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
272+
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
273+
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
274+
CLANG_WARN_STRICT_PROTOTYPES = YES;
275+
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
276+
CODE_SIGN_IDENTITY = "iPhone Developer";
277+
CODE_SIGN_STYLE = Automatic;
278+
GCC_C_LANGUAGE_STANDARD = gnu11;
279+
INFOPLIST_FILE = Tests/Info.plist;
280+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
281+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
282+
PRODUCT_BUNDLE_IDENTIFIER = com.mnespor.Tests;
283+
PRODUCT_NAME = "$(TARGET_NAME)";
284+
SWIFT_VERSION = 4.0;
285+
TARGETED_DEVICE_FAMILY = "1,2";
286+
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Convex Hull.app/Convex Hull";
287+
};
288+
name = Release;
289+
};
155290
8E6D68C61E59989400161780 /* Debug */ = {
156291
isa = XCBuildConfiguration;
157292
buildSettings = {
@@ -274,6 +409,15 @@
274409
/* End XCBuildConfiguration section */
275410

276411
/* Begin XCConfigurationList section */
412+
1CB614341F89456C00A14493 /* Build configuration list for PBXNativeTarget "Tests" */ = {
413+
isa = XCConfigurationList;
414+
buildConfigurations = (
415+
1CB614351F89456C00A14493 /* Debug */,
416+
1CB614361F89456C00A14493 /* Release */,
417+
);
418+
defaultConfigurationIsVisible = 0;
419+
defaultConfigurationName = Release;
420+
};
277421
8E6D68B11E59989400161780 /* Build configuration list for PBXProject "Convex Hull" */ = {
278422
isa = XCConfigurationList;
279423
buildConfigurations = (
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "0900"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
</BuildAction>
9+
<TestAction
10+
buildConfiguration = "Debug"
11+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
12+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
13+
language = ""
14+
shouldUseLaunchSchemeArgsEnv = "YES">
15+
<Testables>
16+
<TestableReference
17+
skipped = "NO">
18+
<BuildableReference
19+
BuildableIdentifier = "primary"
20+
BlueprintIdentifier = "1CB6142C1F89456C00A14493"
21+
BuildableName = "Tests.xctest"
22+
BlueprintName = "Tests"
23+
ReferencedContainer = "container:Convex Hull.xcodeproj">
24+
</BuildableReference>
25+
</TestableReference>
26+
</Testables>
27+
<AdditionalOptions>
28+
</AdditionalOptions>
29+
</TestAction>
30+
<LaunchAction
31+
buildConfiguration = "Debug"
32+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
33+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
34+
language = ""
35+
launchStyle = "0"
36+
useCustomWorkingDirectory = "NO"
37+
ignoresPersistentStateOnLaunch = "NO"
38+
debugDocumentVersioning = "YES"
39+
debugServiceExtension = "internal"
40+
allowLocationSimulation = "YES">
41+
<AdditionalOptions>
42+
</AdditionalOptions>
43+
</LaunchAction>
44+
<ProfileAction
45+
buildConfiguration = "Release"
46+
shouldUseLaunchSchemeArgsEnv = "YES"
47+
savedToolIdentifier = ""
48+
useCustomWorkingDirectory = "NO"
49+
debugDocumentVersioning = "YES">
50+
</ProfileAction>
51+
<AnalyzeAction
52+
buildConfiguration = "Debug">
53+
</AnalyzeAction>
54+
<ArchiveAction
55+
buildConfiguration = "Release"
56+
revealArchiveInOrganizer = "YES">
57+
</ArchiveAction>
58+
</Scheme>

Convex Hull/Convex Hull/View.swift

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,23 +93,11 @@ class View: UIView {
9393
}
9494

9595
var pts = points
96-
97-
// calculate parameters of general line equation y = a * x + b
98-
let a = (p1.y - p2.y) / (p1.x - p2.x)
99-
let b = p1.y - a * p1.x
100-
101-
// calculate normal line's growth factor
102-
let a1 = -1 / a
103-
10496
var maxDist: CGFloat = -1
10597
var maxPoint: CGPoint = pts.first!
10698

10799
for p in pts { // for every point check the distance from our line
108-
let b1 = p.y - a1 * p.x // calculate offset to line equation for given point p
109-
let x = -(b - b1)/(a - a1) // calculate x where the two lines intersect
110-
let y = a * x + b // calculate y value of this intersect point
111-
112-
let dist = pow(x - p.x, 2) + pow(y - p.y, 2) // calculate distance squared between intersection point and point p
100+
let dist = distance(from: p, to: (p1, p2))
113101
if dist > maxDist { // if distance is larger than current maxDist remember new point p
114102
maxDist = dist
115103
maxPoint = p
@@ -150,6 +138,22 @@ class View: UIView {
150138
findHull(s2, maxPoint, p2)
151139
}
152140

141+
func distance(from p: CGPoint, to line: (CGPoint, CGPoint)) -> CGFloat {
142+
// If line.0 and line.1 are the same point, they don't define a line (and, besides,
143+
// would cause division by zero in the distance formula). Return the distance between
144+
// line.0 and point p instead.
145+
if line.0 == line.1 {
146+
return sqrt(pow(p.x - line.0.x, 2) + pow(p.y - line.0.y, 2))
147+
}
148+
149+
// from Deza, Michel Marie; Deza, Elena (2013), Encyclopedia of Distances (2nd ed.), Springer, p. 86, ISBN 9783642309588
150+
return abs((line.1.y - line.0.y) * p.x
151+
- (line.1.x - line.0.x) * p.y
152+
+ line.1.x * line.0.y
153+
- line.1.y * line.0.x)
154+
/ sqrt(pow(line.1.y - line.0.y, 2) + pow(line.1.x - line.0.x, 2))
155+
}
156+
153157
override func draw(_ rect: CGRect) {
154158

155159
let context = UIGraphicsGetCurrentContext()

Convex Hull/Tests/Info.plist

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>$(DEVELOPMENT_LANGUAGE)</string>
7+
<key>CFBundleExecutable</key>
8+
<string>$(EXECUTABLE_NAME)</string>
9+
<key>CFBundleIdentifier</key>
10+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11+
<key>CFBundleInfoDictionaryVersion</key>
12+
<string>6.0</string>
13+
<key>CFBundleName</key>
14+
<string>$(PRODUCT_NAME)</string>
15+
<key>CFBundlePackageType</key>
16+
<string>BNDL</string>
17+
<key>CFBundleShortVersionString</key>
18+
<string>1.0</string>
19+
<key>CFBundleVersion</key>
20+
<string>1</string>
21+
</dict>
22+
</plist>

0 commit comments

Comments
 (0)