implement basic trigonometry based app

This commit is contained in:
Basti SK 2024-04-13 22:58:54 +02:00
parent 1423acf036
commit 8a8ba163c6
3 changed files with 350 additions and 11 deletions

View File

@ -292,13 +292,17 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 774CCSDT3V;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = TreeMeasure/Info.plist; INFOPLIST_FILE = TreeMeasure/Info.plist;
INFOPLIST_KEY_NSCameraUsageDescription = "Cam for images";
INFOPLIST_KEY_NSMotionUsageDescription = "uses motion";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main; INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations = "";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@ -319,13 +323,17 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 774CCSDT3V;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = TreeMeasure/Info.plist; INFOPLIST_FILE = TreeMeasure/Info.plist;
INFOPLIST_KEY_NSCameraUsageDescription = "Cam for images";
INFOPLIST_KEY_NSMotionUsageDescription = "uses motion";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main; INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations = "";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",

View File

@ -1,24 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<scenes> <scenes>
<!--View Controller--> <!--View Controller-->
<scene sceneID="tne-QT-ifu"> <scene sceneID="tne-QT-ifu">
<objects> <objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController"> <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="TreeMeasure" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <subviews>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LNi-pI-Zgk">
<rect key="frame" x="0.0" y="159" width="393" height="693"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ly1-6Q-pTM">
<rect key="frame" x="18" y="58" width="361" height="736"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" editable="NO" text="Angle: 00.00 °" textAlignment="center" adjustsFontForContentSizeCategory="YES" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IiL-bT-6AT">
<rect key="frame" x="245" y="0.0" width="116" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<color key="textColor" systemColor="labelColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="contactAdd" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LEE-jc-u9r">
<rect key="frame" x="155" y="351" width="50" height="35"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="tintColor" systemColor="systemRedColor"/>
<buttonConfiguration key="configuration" style="plain"/>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Reference Height" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rwi-Bi-AQl">
<rect key="frame" x="8" y="9" width="113" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="tintColor" systemColor="systemGreenColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="YcO-vl-PHN">
<rect key="frame" x="130" y="504" width="100" height="70"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="tintColor" systemColor="systemGreenColor"/>
<buttonConfiguration key="configuration" style="tinted" title="Snapshot" cornerStyle="large">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" name="AccentColor"/>
</buttonConfiguration>
<connections>
<action selector="addMarker" destination="BYZ-38-t0r" eventType="touchUpInside" id="PCy-IL-vfh"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jSd-fV-31w">
<rect key="frame" x="80" y="643" width="41" height="41"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="tinted" title="-">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" name="AccentColor"/>
</buttonConfiguration>
<connections>
<action selector="zoomOut" destination="BYZ-38-t0r" eventType="touchUpInside" id="lE4-DJ-eBd"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="RqE-Bn-el6">
<rect key="frame" x="235" y="643" width="43" height="41"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="tinted" title="+">
<color key="baseForegroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="baseBackgroundColor" name="AccentColor"/>
</buttonConfiguration>
<connections>
<action selector="zoomIn" destination="BYZ-38-t0r" eventType="touchUpInside" id="LnB-rC-3cW"/>
</connections>
</button>
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="1.0" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="vj3-ds-Ni8">
<rect key="frame" x="130" y="0.0" width="48" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" keyboardType="numberPad"/>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="m" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J1j-Zz-TVo">
<rect key="frame" x="186" y="8" width="13" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="tintColor" systemColor="systemGreenColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="highlightedColor"/>
</label>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" editable="NO" text="Status" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8TS-hA-l13">
<rect key="frame" x="8" y="34" width="353" height="59"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" systemColor="systemGreenColor"/>
<color key="textColor" systemColor="labelColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view> </view>
<connections>
<outlet property="centerButton" destination="LEE-jc-u9r" id="urU-ec-OMg"/>
<outlet property="inputRefHeight" destination="vj3-ds-Ni8" id="mya-G1-k0e"/>
<outlet property="mainView" destination="vj3-ds-Ni8" id="eft-wo-m1M"/>
<outlet property="previewView" destination="LNi-pI-Zgk" id="4kU-Wq-9N2"/>
<outlet property="statusText" destination="8TS-hA-l13" id="QPH-0C-qEM"/>
<outlet property="textView" destination="IiL-bT-6AT" id="YGQ-Gz-IOt"/>
</connections>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="20.610687022900763" y="3.5211267605633805"/>
</scene> </scene>
</scenes> </scenes>
<resources>
<namedColor name="AccentColor">
<color red="0.0" green="0.46000000000000002" blue="0.89000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<systemColor name="labelColor">
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemGreenColor">
<color red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemRedColor">
<color red="1" green="0.23137254900000001" blue="0.18823529410000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document> </document>

View File

@ -6,14 +6,223 @@
// //
import UIKit import UIKit
import AVFoundation
import CoreMotion
class ViewController: UIViewController { class ViewController: UIViewController {
@IBOutlet weak var textView: UITextView!
@IBOutlet weak var inputRefHeight: UITextField!
@IBOutlet weak var statusText: UITextView!
@IBOutlet weak var centerButton: UIButton!
@IBOutlet weak var previewView: UIView!
@IBOutlet var mainView: UIView!
// Cam Variables
var captureSession: AVCaptureSession!
var videoPreviewLayer: AVCaptureVideoPreviewLayer!
var globalQueue: OperationQueue!
var backCamera: AVCaptureDevice!
// VariablesForCalculations
var globalDegrees: Double!
var globalAttitude: Double!
var globalGravityAngle: Double!
var topPole: Double!
var bottomPole: Double!
var topTree: Double!
// Motion Variables
var motionManager: CMMotionManager!
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
// Do any additional setup after loading the view.
// init motion manager
motionManager = CMMotionManager();
// init vars for calculations
topPole = 0;
bottomPole = 0;
topTree = 0;
statusText.text = "To start, please snapshot the top of the reference height."
// enable tap out of edit for ref. heigth
let tap = UITapGestureRecognizer(target: self, action: #selector(UIInputViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
@objc func dismissKeyboard() {
view.endEditing(true)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// start and prepare cam related things
captureSession = AVCaptureSession()
backCamera = AVCaptureDevice.default(for: AVMediaType.video)
do {
let input = try AVCaptureDeviceInput(device: backCamera)
if(captureSession.canAddInput(input)) {
captureSession.addInput(input)
setupLivePreview()
}
}
catch let error {
print("Error Unable to initialize back camera: \(error.localizedDescription)")
}
// start monitoring the motion sensor
startMotionMonitor();
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.captureSession.stopRunning()
motionManager.stopDeviceMotionUpdates()
}
@IBAction func addMarker() {
let l = Double(inputRefHeight.text ?? "1.0") ?? 1.0
if(topPole == 0) {
topPole = globalAttitude
if globalGravityAngle < 0 {
topPole = globalAttitude * -1
}
statusText.text = "Snaphost Angle: " + String(format: "%.2f", globalDegrees) + "°.\nNext, snapshot the bottom of the reference height."
return;
}
if(bottomPole == 0) {
bottomPole = globalAttitude
if globalGravityAngle < 0 {
bottomPole = bottomPole * -1
}
statusText.text = "Snapshot Angle: " + String(format: "%.2f", globalDegrees) + "°\nFinally, snapshot the top of the tree."
return;
}
if(topTree == 0) {
topTree = globalAttitude
if globalGravityAngle < 0 {
topTree = topTree * -1
}
}
if((topPole != 0) && (bottomPole != 0) && (topTree != 0)) {
let alpha3 = topPole - Double.pi / 2
let alpha2 = bottomPole - Double.pi / 2
let alpha1 = topTree - Double.pi / 2
let e = abs(l / ( tan(alpha3) - tan(alpha2)))
let h1 = e * tan(alpha1)
let h2 = e * tan(alpha2)
let h = abs(h1 - h2)
statusText.text = "Height: " + String( format: "%.4f", h) + " m\nSnapshot top of the reference height to measure again."
//reset
topTree = 0
bottomPole = 0
topPole = 0
}
}
@IBAction func changeZoom() {
if(backCamera.videoZoomFactor > 1) {
setZoomFactor(factor: backCamera.videoZoomFactor + 10)
} else {
setZoomFactor(factor: backCamera.maxAvailableVideoZoomFactor)
}
}
@IBAction func zoomOut() {
if(backCamera.videoZoomFactor > 1) {
setZoomFactor(factor: backCamera.videoZoomFactor - 1)
}
}
@IBAction func zoomIn() {
if(backCamera.videoZoomFactor < backCamera.maxAvailableVideoZoomFactor) {
setZoomFactor(factor: backCamera.videoZoomFactor + 1)
}
}
func setZoomFactor(factor: CGFloat) {
do {
try backCamera.lockForConfiguration()
if(factor <= backCamera.maxAvailableVideoZoomFactor) {
backCamera.videoZoomFactor = factor
}
backCamera.unlockForConfiguration()
} catch let error {
print("Error Unable to set zoom for back camera: \(error.localizedDescription)")
}
}
func startMotionMonitor() {
globalQueue = OperationQueue()
if motionManager.isDeviceMotionAvailable == true {
motionManager.deviceMotionUpdateInterval = 0.5
motionManager.startDeviceMotionUpdates(using: .xMagneticNorthZVertical, to: self.globalQueue, withHandler: { (data, error) in
if let attitude = data?.attitude {
// Get the pitch (in radians) and convert to degrees for display.
self.globalDegrees = (attitude.pitch * 180.0/Double.pi)
self.globalAttitude = attitude.pitch
DispatchQueue.main.async {
self.textView.text = "Angle: " + String(format: "%.2f", self.globalDegrees) + "°";
}
}
if let gravity = data?.gravity {
self.globalGravityAngle = gravity.z;
}
// we are looking up!
if self.globalGravityAngle > 0 {
self.globalDegrees = 180 - self.globalDegrees;
}
})
}
} }
func setupLivePreview() {
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer.connection?.videoOrientation = .portrait
previewView.layer.addSublayer(videoPreviewLayer)
DispatchQueue.global(qos: .userInitiated).async { //[weak self] in
self.captureSession.startRunning()
DispatchQueue.main.async {
self.videoPreviewLayer.frame = self.previewView.bounds
}
}
}
} }