﻿B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Activity
Version=11.2
@EndOfDesignText@
#Region  Activity Attributes 
	#FullScreen: False
	#IncludeTitle: True
#End Region

#Region ***************************************************** Start ********************************************

Sub Process_Globals
	'These global variables will be declared once when the application starts.
	'These variables can be accessed from all modules.
	
End Sub

Sub Globals
	'These global variables will be redeclared each time the activity is created.
	'These variables can only be accessed from this module.
	Dim Panel1 As Panel
	
	Dim ScreenX0, ScreenY0, ScreenW, ScreenH As Double
	Dim SheetX0, SheetY0, SheetW, SheetH As Double
	Dim ScaleX, ScaleY,SArea As Double
	
	Dim PntMinX, PntMaxX, PntMinY, PntMaxY, PntMaxMinX, PntMaxMinY, PntMeanX, PntMeanY As Double
	Dim Scaletype As Int	: Scaletype = 1			' 0 = top > down		1 = bottom > up
	Dim East, North, Eleva As Label
	
	Dim CadType As Int
	Dim Label10 As Label
	
	Dim PnlDrawing, PnlTemp As B4XView
	Dim cvsDrawing, cvsTemp As B4XCanvas
	Dim xui As XUI
	Dim p As Data
	Dim ExitMap, MapView, MapGen, MapPnt,MapCon,MapArea As ImageView
	Dim TextSize As B4XComboBox
	Dim ShowElev As CheckBox
	
	Dim X1,Y1,X2,Y2,X3,Y3,X5,Y5 As Double
	Dim Dist, Dist1 As Double
	Dim Scale As Double
	Dim PntCol, TinCol, ConCol, TxtCol As Double
	Dim Y1,X1,Y2,X2,Y3,X3 As Double
	Dim Label2 As Label
	
	Dim Panel1, Panel3, Panel4 As Panel
	Dim StartCont, EndCont, Interval As EditText
	Dim ExitCont, OKCont As Button
	Dim Dx, Dy As Double
	Dim ShowCont, ShowPnt, C As Int
	Dim MapImport, MapSwap, MapErase As ImageView
	Dim Query As String
	Dim Rec As Int
	Dim SiteLabel1, JobLabel1 As Label
	Dim SnapZ = 0 As Double
	Dim P1 As Int
	Dim X1 As Double = 0
	Dim Y1 As Double = 0
	Dim X2 As Double = 0
	Dim Y2 As Double = 0
	Dim Z1 As Double = 0
	Dim Z2 As Double = 0
	Dim xx0, yy0, xx1, yy1, xx2, yy2 As Double
	Dim OK As Int=0
	Dim AreaCount =-1 As Int
	Dim Ax(10000),Ay(10000), Az(10000) As Double
	Dim SV As B4XTable
	Dim ReportName As String
	Dim ExitList,ExportList As Button
	Dim Data As List
'	Dim InsidePoints As Int
	
'	Dim FVol,CVol As Double
'	Dim AB As ABExtDrawing
	Dim ColorTin As ImageView
	Dim Shade As Boolean=False
'	Dim OpenGL As OpenGL
	Dim lastX As Float
	Dim lastY As Float
	Dim HeightRanges As List
	Dim ColorsList As List
'	Dim AreaRect As Rect
	Dim Volume As Double
	Dim TotalVolume As Double
	Dim Panel5 As Panel
	Dim EditText1 As EditText
	Dim Butt1, Butt2 As Button
	Dim angleX, angleY As Double
'	Dim zoom As Float = 1.0
	Dim lastX, lastY As Float

	Type BTINModel(East As Double,North As Double,Elev As Double, East1 As Double,North1 As Double,Elev1 As Double, East2 As Double,North2 As Double,Elev2 As Double,Area As Double)
	Dim BTin3D(2000) As BTINModel
	Dim BMaxTins As Int
'	Dim Triangles As List
'	Dim Edges As Map
'	Dim BoundaryEdges As List
	Dim AdjList As Map
'	Dim Point1 As List
'	Dim Point2 As List
End Sub

Sub Activity_Create(FirstTime As Boolean)
	'Do not forget to load the layout file created with the visual designer. For example:
	'Activity.LoadLayout("Layout1")
	Activity.LoadLayout("Stock")
	Activity.Title="Stockpile"
	If CGlobals.Site<>"" Then
		SiteLabel1.Text="Site: " & CGlobals.Site
	End If
	If CGlobals.Job<>"" Then
		JobLabel1.Text="Job: " & CGlobals.Job
	End If
	CadType=0
	AreaCount=0
	Panels
	Panel1.Visible=True
	ProgressDialogShow2("Loading Stockpile Model...", False)
	Sleep(0)
	Engine.GetTriangles(2)
	Label2.Text=CGlobals.MaxTins
	ProgressDialogHide
	PnlDrawing.Visible=True
	cvsDrawing.Initialize(PnlDrawing)
	cvsTemp.Initialize(PnlTemp)
	Scale=1
	CGlobals.MaxPoints=-1
	ShowCont=0
	ShowPnt=1
	InitScale
	PntCol=Colors.Black
	TxtCol=Colors.Black
	TinCol=Colors.Black
	ConCol=Colors.Black
	DrawPoints
	FillTextSize
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)
'	GlSV.Pause ' Must call GLSurfaceView.Pause to halt the rendering thread
'	Timer1.Enabled = False
End Sub

Sub Panels
	Panel1.Visible=False
	Panel3.Visible=False
	Panel4.Visible=False
	Panel5.Visible=False
End Sub

Sub FillTextSize
	Try
		TextSize.cmbBox.Clear
		Dim Items8 As List
		Items8.Initialize
		Items8.AddAll(Array As String("10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20","21","22","23","24","25","26","27","28","29","30"))
		Dim cs As CSBuilder
		Dim l8 As List
		l8.Initialize
		For i =0 To Items8.Size -1
			l8.Add(cs.Initialize.size(18).Typeface(Typeface.DEFAULT_BOLD).Append(Items8.Get(i)).PopAll)
		Next
		TextSize.SetItems(l8)
		TextSize.SelectedIndex=5
	Catch
		Log(LastException)
	End Try
End Sub

#End Region

#Region ************************************************************ Buttons Pressed *************************************

Sub ColorTin_Click
	If Shade=False Then
		Panels
		Panel5.Visible=True
	Else
		Shade=False
		ReDraw
	End If
End Sub

Sub View_Click
	'3D View
	StartActivity("Plot3D")
End Sub

Sub MapView_Click
	'View Functions
	Dim PopupMenu1 As RSPopupMenu
	PopupMenu1.Initialize("PopupMenu1", MapView)
	PopupMenu1.AddMenuItem(0, 0, "Zoom All")
	PopupMenu1.AddMenuItem(1, 1, "Zoom In")
	PopupMenu1.AddMenuItem(2, 2, "Zoom Out")
	PopupMenu1.AddMenuItem(3, 3, "Pan")
	PopupMenu1.Show
End Sub

Sub PopupMenu1_MenuItemClick (ItemId As Int) As Boolean
	Select Case ItemId
		Case 0
			Scale=1
			CadType=0
			Dist=0
			Dist1=0
			Label10.Text=""
			InitScale
			CalcZoom
			cvsTemp.ClearRect(cvsTemp.TargetRect)
			DrawPoints
		Case 1
			'Zoom In
			If CadType<>1 Then
				Label10.Text="Zoom In"
				CadType=1
				Scale=Scale+0.01
				cvsTemp.ClearRect(cvsTemp.TargetRect)
				ReDraw
			Else
				CadType=0
				Label10.Text=""
			End If
		Case 2
			'Zoom Out
			If CadType<>2 Then
				Label10.Text="Zoom Out"
				CadType=2
				If Scale>0.01 Then
					Scale=Scale-0.01
				End If
				cvsTemp.ClearRect(cvsTemp.TargetRect)
				ReDraw
			Else
				CadType=0
				Label10.Text=""
			End If
		Case 3
			'Pan
			Dist=0
			Dist1=0
			If CadType<>3 Then
				Label10.Text="Pan"
				CadType=3
			Else
				CadType=0
				Label10.Text=""
			End If
	End Select
End Sub

Sub MapGen_Click
	'Edit Functions
	Dim PopupMenu4 As RSPopupMenu
	PopupMenu4.Initialize("PopupMenu4", MapGen)
	PopupMenu4.AddMenuItem(0, 0, "Point Color")
	PopupMenu4.AddMenuItem(1, 1, "Text Color")
	PopupMenu4.AddMenuItem(2, 2, "Tin Color")
	PopupMenu4.AddMenuItem(3, 3, "Contour Color")
	PopupMenu4.Show
End Sub

Sub PopupMenu4_MenuItemClick (ItemId As Int) As Boolean
	Select Case ItemId
		Case 0
			'Select A Point Color
			C=1
			CADColor
		Case 1
			'Select A Text Color
			C=2
			CADColor
		Case 2
			'Select A Tin Color
			C=3
			CADColor
		Case 3
			'Select A Contour Color
			C=4
			CADColor
	End Select
End Sub

Sub CADColor
	Dim cp As ColorPickerDialog
	Dim sf As Object = cp.ShowAsync("Choose Color", "OK", "Cancel", "", Null, False)
	Wait For (sf) Dialog_Result(Result As Int)
	If Result = DialogResponse.POSITIVE Then
		If C=1 Then
			PntCol = cp.RGB
		Else If C=2 Then
			TxtCol=cp.RGB
		Else If C=3 Then
			TinCol=cp.RGB
		Else
			ConCol=cp.RGB
		End If
		DrawPoints
	End If
End Sub

Sub MapCon_Click
	If ShowCont=0 Then
		StartCont.Text=NumberFormat2(Floor(CGlobals.ZMinCont),1,3,3,False)
		EndCont.Text=NumberFormat2(Floor(CGlobals.ZMaxCont),1,3,3,False)
		Interval.Text=NumberFormat2(1,1,3,3,False)
		Panel1.Visible=False
		Panel3.Visible=True
	Else
		ShowCont=0
		DrawPoints
	End If
End Sub

Sub MapPnt_Click
	If ShowPnt=0 Then
		ShowPnt=1
	Else
		ShowPnt=0
	End If
	ReDraw
End Sub

Sub MapArea_Click
	'Edit Functions
	Dim PopupMenu5 As RSPopupMenu
	PopupMenu5.Initialize("PopupMenu5", MapArea)
	PopupMenu5.AddMenuItem(0, 0, "Manual")
	PopupMenu5.AddMenuItem(1, 1, "Auto")
	PopupMenu5.Show
End Sub

Sub PopupMenu5_MenuItemClick (ItemId As Int) As Boolean
	Select Case ItemId
		Case 0
			'Manual Boundary
			ManualVol
		Case 1
			'Auto Boundary
			AutoVol
	End Select
End Sub

Sub ManualVol
	If CadType<>5 Then
		OK=0
		AreaCount=0
		Label10.Text="Calcs"
		CadType=5
		DrawPoints
	Else
		CadType=0
		Label10.Text=""
	End If
	If OK>0 Then
		CadType=0
		Label10.Text=""
		'Calc the Area
		X1=ConvertPhysicToCADX(Ax(0))
		Y1=ConvertPhysicToCADY(Ay(0))
		X2=ConvertPhysicToCADX(Ax(AreaCount))
		Y2=ConvertPhysicToCADY(Ay(AreaCount))
		cvsDrawing.DrawLine(X1, Y1, X2, Y2,Colors.Red, 2)
		cvsDrawing.Invalidate
		Panels
		Panel4.Visible=True
		AreaCalcs
		CadType=0
	End If
End Sub

Sub AutoVol
	Msgbox2Async("This Will Auto Create A Boundary","Boundary","OK","Cancel","",Null,False)
	Wait For Msgbox_Result (Answ As Int)
	If Answ = DialogResponse.POSITIVE Then
		CadType=5
		GetTriangles
		OK=1
	End If
End Sub

Sub ExitMap_Click
	CGlobals.ReadFlag = 0
	Activity.Finish
End Sub

Sub ShowElev_CheckedChange(Checked As Boolean)
	DrawPoints
End Sub

Sub TextSize_SelectedIndexChanged (Index As Int)
	DrawPoints
End Sub

#End Region

#Region ******************************************************** Plot TIN Model ******************************************

Sub ReDraw
	CalcZoom
	DrawPoints
End Sub

Sub InitScale
	Dim i As Int
	
	ScreenX0 = 20dip
	ScreenY0 = 20dip
	ScreenW = (PnlDrawing.Width) - 2 * ScreenX0
	ScreenH = (PnlDrawing.Height) - 2 * ScreenY0

	'Plot TIN Model
	PntMinX = CGlobals.Tin3D(0).East
	PntMaxX = CGlobals.Tin3D(0).East
	PntMinY = CGlobals.Tin3D(0).North
	PntMaxY = CGlobals.Tin3D(0).North

	For i = 1 To CGlobals.MaxTins
		PntMinX = Min(PntMinX, CGlobals.Tin3D(i).East)
		PntMaxX = Max(PntMaxX, CGlobals.Tin3D(i).East)
		PntMinY = Min(PntMinY, CGlobals.Tin3D(i).North)
		PntMaxY = Max(PntMaxY, CGlobals.Tin3D(i).North)
	Next
'	If CGlobals.MaxPoints>-1 Then
'		'Plot Points
'		PntMinX = CGlobals.Points3D(0).East
'		PntMaxX = CGlobals.Points3D(0).East
'		PntMinY = CGlobals.Points3D(0).North
'		PntMaxY = CGlobals.Points3D(0).North
'
'		For i = 1 To CGlobals.MaxPoints
'			PntMinX = Min(PntMinX, CGlobals.Points3D(i).East)
'			PntMaxX = Max(PntMaxX, CGlobals.Points3D(i).East)
'			PntMinY = Min(PntMinY, CGlobals.Points3D(i).North)
'			PntMaxY = Max(PntMaxY, CGlobals.Points3D(i).North)
'		Next
'	End If
	
	If PntMaxX - PntMinX=0 Then
		PntMaxX=100
		PntMinX=-100
	End If
	If PntMaxY - PntMinY=0 Then
		PntMaxY=100
		PntMinY=-100
	End If
	CalcZoom
End Sub

Sub CalcZoom
	If Scale>1 Then
		PntMinX = PntMinX + (100*Scale)
		PntMaxX = PntMaxX  - (100*Scale)
		PntMinY = PntMinY  + (100*Scale)
		PntMaxY = PntMaxY  - (100*Scale)
	Else If Scale<1 Then
		PntMinX = PntMinX - (100*Scale)
		PntMaxX = PntMaxX  + (100*Scale)
		PntMinY = PntMinY  - (100*Scale)
		PntMaxY = PntMaxY  + (100*Scale)
	End If
	CalcLimits
End Sub

Sub CalcLimits
                                                                                                                                                                                                                                                     	PntMinX = PntMinX - Dist
	PntMaxX = PntMaxX - Dist
	PntMinY = PntMinY - Dist1
	PntMaxY = PntMaxY - Dist1

	PntMaxMinX = PntMaxX - PntMinX
	PntMaxMinY = PntMaxY - PntMinY
	PntMeanX = (PntMaxX + PntMinX) / 2
	PntMeanY = (PntMaxY + PntMinY) / 2
'	ScaleX = ScreenW / PntMaxMinX
'	ScaleY = ScreenH / PntMaxMinY
	
	ScaleX = (ScreenW / PntMaxMinX) / Scale
	ScaleY = (ScreenH / PntMaxMinY) / Scale
	If ScaleX > ScaleY Then
		ScaleX = ScaleY
		SheetW = PntMaxMinY * ScreenW / ScreenH
		ScaleX = ScaleY
		SheetX0 = PntMeanX - SheetW / 2
		If Scaletype = 1 Then
			'SheetY0 = PntMinY
			SheetY0 = PntMeanY - SheetH / 2
		Else
			SheetY0 = PntMaxY
			ScaleY = -ScaleY
			ScaleX = -ScaleX
		End If
	Else
		SheetX0 = PntMinX
		SheetH = PntMaxMinX * ScreenH / ScreenW
		ScaleY = ScaleX
		If Scaletype = 1 Then
			SheetY0 = PntMeanY - SheetH / 2
		Else
			ScaleY = -ScaleY
			SheetY0 = PntMeanY + SheetH / 2
			'ScaleX = -ScaleX
		End If
	End If
End Sub

Sub DrawPoints
	Dim i As Int
	Dim BX,BY As Double
	
	cvsDrawing.ClearRect(cvsDrawing.TargetRect)
	i=0
	Do While i<=CGlobals.MaxTins
		DrawLine(CGlobals.Tin3D(i).East,CGlobals.Tin3D(i).North,CGlobals.Tin3D(i).East1,CGlobals.Tin3D(i).North1,CGlobals.Tin3D(i).East2,CGlobals.Tin3D(i).North2,TinCol, 1)
		If ShowPnt=1 Then
			DrawTinPoint(i, PntCol, 1)
		End If
		If ShowElev.Checked=True Then
			DrawElevations(i, TxtCol, 1)
		End If
		i=i+1
	Loop
	If CGlobals.MaxPoints>-1 And ShowPnt=1 Then
		i=0
		Do While i<=CGlobals.MaxPoints
			DrawPoint(CGlobals.Points3D(i).East,CGlobals.Points3D(i).North, PntCol, 1)
			i=i+1
		Loop
	End If
	BX=ConvertPhysicToCADX(CGlobals.Y0)
	BY=ConvertPhysicToCADY(CGlobals.X0)
	cvsDrawing.DrawCircle(BX,BY,4Dip,Colors.Red,True,1)
	If ShowCont=1 Then CalcCont
	cvsDrawing.Invalidate
	If Shade=True Then
		FillTIN
	End If
End Sub

Sub DrawPoint(A As Double,B As Double, Col As Int, LineW As Int)
	Dim xp, yp As Double
	
	xp = ConvertPhysicToCADX(A)
	yp = ConvertPhysicToCADY(B)
	cvsDrawing.DrawCircle(xp, yp, 2dip, Col, True, .1dip)
End Sub

Sub DrawTinPoint(Pnt As Int, Col As Int, LineW As Int)
	Dim xp, yp As Double
	
	xp = ConvertPhysicToDrawingX(Pnt)
	yp = ConvertPhysicToDrawingY(Pnt)
	cvsDrawing.DrawCircle(xp, yp, 2dip, Col, True, .1dip)
End Sub

Sub DrawElevations(Pnt As Int, Col As Int, LineW As Int)
	Dim xp, yp As Double
	Private fnt As B4XFont
	
	fnt = xui.CreateDefaultFont(TextSize.SelectedIndex)'/(Scale/5))
	xp = Round(ConvertPhysicToDrawingX(Pnt))
	yp = Round(ConvertPhysicToDrawingY(Pnt))
	cvsDrawing.DrawText(CGlobals.Tin3D(Pnt).Elev, xp+2dip, yp-1dip, fnt, Col, "LEFT")
End Sub

Sub DrawLine(A As Double, A1 As Double, B As Double, B1 As Double, C2 As Double, C1 As Double,col As Int, LineW As Double)
	X1 = (A - SheetX0) * ScaleX + ScreenX0
	Y1 = (A1 - SheetY0) * ScaleY + ScreenY0
	X2 = (B - SheetX0) * ScaleX + ScreenX0
	Y2 = (B1 - SheetY0) * ScaleY + ScreenY0
	X3 = (C2 - SheetX0) * ScaleX + ScreenX0
	Y3 = (C1 - SheetY0) * ScaleY + ScreenY0
	
	cvsDrawing.DrawLine(X1, Y1, X2 , Y2, col, LineW)
	cvsDrawing.DrawLine(X2, Y2, X3 , Y3, col, LineW)
	cvsDrawing.DrawLine(X3, Y3, X1 , Y1, col, LineW)
End Sub

Sub DrawLineCon(A As Double, A1 As Double, B As Double, B1 As Double,col As Int, LineW As Double)
	X1 = (A - SheetX0) * ScaleX + ScreenX0
	Y1 = (A1 - SheetY0) * ScaleY + ScreenY0
	X2 = (B - SheetX0) * ScaleX + ScreenX0
	Y2 = (B1 - SheetY0) * ScaleY + ScreenY0
	
	cvsDrawing.DrawLine(X1, Y1, X2 , Y2, col, LineW)
End Sub

#End Region

#Region ******************************************************** Scale Conversions ************************************************

Sub ConvertPhysicToDrawingX(PntI As Double) As Double
	If PntI>-1 Then Return (CGlobals.Tin3D(PntI).East - SheetX0) * ScaleX + ScreenX0
End Sub

Sub ConvertPhysicToCADX(A As Double) As Double
	Return (A - SheetX0) * ScaleX + ScreenX0
End Sub

Sub ConvertPhysicToCADY(A As Double) As Double
	Return (A - SheetY0) * ScaleY + ScreenY0
End Sub

Sub ConvertPhysicToDrawingY(PntI As Double) As Double
	If PntI>-1 Then Return (CGlobals.Tin3D(PntI).North - SheetY0) * ScaleY + ScreenY0
End Sub

Sub ConvertDrawingToPhysic(X As Double, Y As Double) As Data
	p.East = (X - ScreenX0) / ScaleX + SheetX0
	p.North = (Y - ScreenY0) / ScaleY + SheetY0
	Return p
End Sub

#End Region

#Region ************************************************** Screen Actions ****************************************

Private Sub pnlTemp_Touch (Action As Int, X As Double, Y As Double)
	Select Action
		Case PnlTemp.TOUCH_ACTION_DOWN
			ScreenDown(X,Y)
		Case PnlTemp.TOUCH_ACTION_MOVE
			ScreenMove(X,Y)
		Case PnlTemp.TOUCH_ACTION_UP
			ScreenUp(X,Y)
	End Select
End Sub

Sub ScreenDown(X As Double, Y As Double)
	ConvertDrawingToPhysic(X, Y )
	Select Case CadType
		Case 3
			'Pan
			cvsDrawing.ClearRect(cvsDrawing.TargetRect)
			X5=p.East
			Y5=p.North
		Case 5
			'Draw A PolyLine
			ClosePoint(p.East,p.North)
			X=ConvertPhysicToCADX(p.East)
			Y=ConvertPhysicToCADY(p.North)
			X1=p.East
			Y1=p.North
			Z1=SnapZ
			If OK=0 Then
				xx0 = X
				yy0 = Y
				OK=1
				AreaCount=0
				Ax(AreaCount)=p.East
				Ay(AreaCount)=p.North
				Az(AreaCount)=Z1
			End If
	End Select
End Sub

Sub ScreenMove(X As Double, Y As Double)
	ConvertDrawingToPhysic(X, Y )
	East.Text=NumberFormat2(p.East,1,3,3,False)
	North.Text=NumberFormat2(p.North,1,3,3,False)
	
	'Draw Cross
	cvsTemp.ClearRect(cvsTemp.TargetRect)
	If CadType=0 Or CadType>3 Then
		cvsTemp.DrawLine(X, Y-25dip, X , Y+25dip, Colors.Red, 2)
		cvsTemp.DrawLine(X-25dip, Y, X+25dip, Y, Colors.Red, 2)
	End If

	Select Case CadType
		Case 3
			'Pan
			Dist = p.East-X5
			Dist1 = p.North -Y5
			CalcLimits'(Dist,Dist1)
			DrawPoints
		Case 5
			'Line
			xx1 = X
			yy1 = Y
			cvsTemp.DrawLine(xx0, yy0, xx1, yy1, Colors.Red, 2)
	End Select
	cvsTemp.Invalidate
End Sub

Sub ScreenUp(X As Double, Y As Double)
	ConvertDrawingToPhysic(X, Y )
	Select Case CadType
		Case 5
			cvsTemp.ClearRect(cvsTemp.TargetRect)
	End Select
	
	If CadType=0 Then
		Engine.WhichTriangle(p.East,p.North)
		If Engine.Z2=-999999 Then
			Eleva.Text="Outside TIN"
		Else
			Eleva.Text=NumberFormat2(Engine.Z2,1,3,3,False)
		End If
	End If

	Select Case CadType
		Case 1
			'Zoom In
			Scale=Scale+0.01
			ReDraw
		Case 2
			'Zoom Out
			If Scale>0.01 Then 
				Scale=Scale-0.01
			End If
			ReDraw
		Case 3
			'Pan
			DrawPoints
		Case 5
			' Polyline
			ClosePoint(p.East,p.North)
			X=ConvertPhysicToCADX(p.East)
			Y=ConvertPhysicToCADY(p.North)
			X2=p.East
			Y2=p.North
			Z2=SnapZ
			AreaCount=AreaCount+1
			Ax(AreaCount)=p.East
			Ay(AreaCount)=p.North
			Az(AreaCount)=Z2
			xx1=X
			yy1=Y
			cvsDrawing.DrawLine(xx0, yy0, xx1, yy1,Colors.Red, 2)
			OK=1
			X1=X2
			Y1=Y2
			xx0=X
			yy0=y
	End Select
	cvsDrawing.Invalidate
End Sub

#End Region

#Region *************************************************** Contours ******************************************

Sub ExitCont_Click
	Panel3.Visible=False
	Panel1.Visible=True
End Sub

Sub OKCont_Click
	Panel3.Visible=False
	Panel1.Visible=True
	Sleep(0)
	ShowCont=1
	ProgressDialogShow2("Plotting Contours...", False)
	Sleep(0)
	CalcCont
	ProgressDialogHide
End Sub

Sub CalcCont
	Dim i,i1 As Double
	Dim Stx, Sty, Stx1, Sty1, Stx2, Sty2 As Double

	For i=0 To CGlobals.MaxTins
		For i1=StartCont.Text To EndCont.Text Step Interval.Text
			Stx=0: Sty=0
			Stx1=0: Sty1=0
			Stx2=0: Sty2=0
			If (i1>=CGlobals.Tin3D(i).Elev And i1<=CGlobals.Tin3D(i).Elev1) Or (i1<=CGlobals.Tin3D(i).Elev And i1>=CGlobals.Tin3D(i).Elev1) Then
				CalcContour(i1,CGlobals.Tin3D(i).East,CGlobals.Tin3D(i).North,CGlobals.Tin3D(i).East1,CGlobals.Tin3D(i).North1, CGlobals.Tin3D(i).Elev, CGlobals.Tin3D(i).Elev1)
				Stx=Dx: Sty=Dy
			End If
			If (i1>=CGlobals.Tin3D(i).Elev1 And i1<=CGlobals.Tin3D(i).Elev2) Or (i1<=CGlobals.Tin3D(i).Elev1 And i1>=CGlobals.Tin3D(i).Elev2) Then
				CalcContour(i1,CGlobals.Tin3D(i).East1,CGlobals.Tin3D(i).North1,CGlobals.Tin3D(i).East2,CGlobals.Tin3D(i).North2, CGlobals.Tin3D(i).Elev1, CGlobals.Tin3D(i).Elev2)
				Stx1=Dx: Sty1=Dy
			End If
			If (i1>=CGlobals.Tin3D(i).Elev2 And i1<=CGlobals.Tin3D(i).Elev) Or (i1<=CGlobals.Tin3D(i).Elev2 And i1>=CGlobals.Tin3D(i).Elev) Then
				CalcContour(i1,CGlobals.Tin3D(i).East2,CGlobals.Tin3D(i).North2,CGlobals.Tin3D(i).East,CGlobals.Tin3D(i).North, CGlobals.Tin3D(i).Elev2, CGlobals.Tin3D(i).Elev)
				Stx2=Dx: Sty2=Dy
			End If
			'Draw The Line
			If Stx<>0 And Stx1<>0 Then
				DrawLineCon(Stx,Sty,Stx1,Sty1,ConCol, 1)
			End If
			If Stx1<>0 And Stx2<>0 Then
				DrawLineCon(Stx1,Sty1,Stx2,Sty2,ConCol, 1)
			End If
			If Stx2<>0 And Stx<>0 Then
				DrawLineCon(Stx2,Sty2,Stx,Sty,ConCol, 1)
			End If
		Next
		cvsDrawing.Invalidate
	Next
	cvsDrawing.Invalidate
End Sub

Sub CalcContour(ConLev As Double, LX As Double, LY As Double, LX1 As Double, LY1 As Double, LZ As Double, LZ1 As Double)
	Dim m1, m2 As Double

	Dx=0:Dy=0
	If LZ <> LZ1 Then
		m1 = (LX - LX1) / (LZ - LZ1)
		m2 = (LY - LY1) / (LZ - LZ1)
	Else
		m1 = 0 : m2 = 0
	End If
	Dx = LX + ((ConLev - LZ) * m1)
	Dy = LY + ((ConLev - LZ) * m2)
	
End Sub

Sub StartCont_FocusChanged(HasFocus As Boolean)
	If HasFocus =False Then
		If IsNumber(StartCont.Text) = False Then StartCont.Text=0
		StartCont.Text=NumberFormat2(StartCont.Text,1,3,3,False)
	Else
		StartCont.SelectAll
	End If
End Sub

Sub EndCont_FocusChanged(HasFocus As Boolean)
	If HasFocus =False Then
		If IsNumber(EndCont.Text) = False Then EndCont.Text=0
		EndCont.Text=NumberFormat2(EndCont.Text,1,3,3,False)
	Else
		EndCont.SelectAll
	End If
End Sub

Sub Interval_FocusChanged(HasFocus As Boolean)
	If HasFocus =False Then
		If IsNumber(Interval.Text) = False Then Interval.Text=0
		Interval.Text=NumberFormat2(Interval.Text,1,3,3,False)
	Else
		Interval.SelectAll
	End If
End Sub

#End Region

#Region ****************************************************** Import Points ***************************************************

Sub MapImport_Click
	Dim fd As FileDialog
	
	fd.FilePath = File.DirRootExternal
	fd.TextColor=Colors.Black
	fd.FileFilter=".csv,.CSV"
	fd.ScrollingBackgroundColor=Colors.Gray
	Dim sf As Object = fd.ShowAsync("Select Point File", "Import", "Cancel", "", Null, False)
	Wait For (sf) Dialog_Result(Result As Int)
	If Result = DialogResponse.POSITIVE Then
		Msgbox2Async("This Will Override The Existing Stockpile Model" , "Override Stockpile Model", "OK", "Cancel", "", Null,False)
		Wait For Msgbox_Result (Answ As Int)
		If Answ = DialogResponse.POSITIVE Then
			If fd.ChosenName<>"" Then
				ProgressDialogShow2("Importing Points...", False)
				Sleep(0)
				ErasePoints
				cvsDrawing.ClearRect(cvsDrawing.TargetRect)
				ImportTinPoints(fd.FilePath, fd.ChosenName)
			Else
				Msgbox2Async("Select A File To Import" , "Import Points", "OK", "", "", Null,False)
			End If
		End If
	End If
End Sub

Sub ErasePoints
	CGlobals.SQL1.Initialize(File.DirRootExternal  & "/CEASER/DATA/" & CGlobals.Site & "/" & CGlobals.Job & "/", CGlobals.Job & ".sl3", False)
	CGlobals.SQL1.ExecNonQuery("DROP TABLE IF EXISTS Stock")
End Sub

Sub ImportTinPoints(A As String, B As String)
	Dim lst1 As List
	Dim FileName As String
	Dim SU As StringUtils
	Dim i,i1 As Int
	
	i1=-1
	FileName= A & "/" & B
	CGlobals.ZMinCont = 999999
	CGlobals.ZMaxCont = -999999
	Try
		lst1.Initialize
		CGlobals.SQL1.BeginTransaction
		lst1 = SU.LoadCSV("", FileName, ",")
		For i = 0 To lst1.Size - 1
			Dim sColumn() As String
			sColumn = lst1.Get(i)
			If i1<19999 Then
				If sColumn.Length=3 Then
					'Assume Y, X & Z Points
					If IsNumber(sColumn(0))=True And IsNumber(sColumn(1))=True And IsNumber(sColumn(2))=True Then
						i1=i1+1
						CGlobals.Points3D(i).East= NumberFormat2(sColumn(0),1,3,3,False)
						CGlobals.Points3D(i).North= NumberFormat2(sColumn(1),1,3,3,False)
						CGlobals.Points3D(i).Elev= NumberFormat2(sColumn(2),1,3,3,False)
					End If
				Else If sColumn.Length=4 Then
					If IsNumber(sColumn(0))=False And IsNumber(sColumn(1))=True And IsNumber(sColumn(2))=True And IsNumber(sColumn(3))=True Then
						'Assume Name, Y, X & Z
						i1=i1+1
						CGlobals.Points3D(i).East= NumberFormat2(sColumn(1),1,3,3,False)
						CGlobals.Points3D(i).North= NumberFormat2(sColumn(2),1,3,3,False)
						CGlobals.Points3D(i).Elev= NumberFormat2(sColumn(3),1,3,3,False)
					Else If IsNumber(sColumn(0))=True And IsNumber(sColumn(1))=True And IsNumber(sColumn(2))=True And IsNumber(sColumn(3))=True Then
						'Assume No, Y, X & Z
						i1=i1+1
						CGlobals.Points3D(i).East= NumberFormat2(sColumn(1),1,3,3,False)
						CGlobals.Points3D(i).North= NumberFormat2(sColumn(2),1,3,3,False)
						CGlobals.Points3D(i).Elev= NumberFormat2(sColumn(3),1,3,3,False)
					End If
				End If
			End If
			CGlobals.ZMinCont = Min(CGlobals.ZMinCont, CGlobals.Tin3D(i).Elev)
			CGlobals.ZMaxCont = Max(CGlobals.ZMaxCont, CGlobals.Tin3D(i).Elev)
			CGlobals.ZMinCont = Min(CGlobals.ZMinCont, CGlobals.Tin3D(i).Elev1)
			CGlobals.ZMaxCont = Max(CGlobals.ZMaxCont, CGlobals.Tin3D(i).Elev1)
			CGlobals.ZMinCont = Min(CGlobals.ZMinCont, CGlobals.Tin3D(i).Elev2)
			CGlobals.ZMaxCont = Max(CGlobals.ZMaxCont, CGlobals.Tin3D(i).Elev2)
		Next
		CGlobals.SQL1.TransactionSuccessful
	Catch
		Log(LastException.Message)
	End Try
	CGlobals.MaxPoints=i1
	ProgressDialogHide
	ToastMessageShow("Points Have Been Imported", False)
	CGlobals.SQL1.EndTransaction
	CGlobals.MaxTins=-1
	Label2.Text=CGlobals.MaxTins
	Engine.GetTriangles(2)
	InitScale
	DrawPoints
	AddPointsVertex
End Sub

Sub AddPointsVertex
	Dim i As Int
	
	Open_TinTable
	ProgressDialogShow2("Generating TIN Model...", False)
	Sleep(0)
	For i=0 To CGlobals.MaxPoints
		Engine.AddVertex(CGlobals.Points3D(i).East,CGlobals.Points3D(i).North,CGlobals.Points3D(i).Elev)
	Next
	Engine.CalculateTriangles
	CGlobals.MaxTins=Engine.TriangleCount
	Rec=-1
	For i = 0 To CGlobals.MaxTins
		CGlobals.Tin3D(i).East=Engine.Vertex(Engine.Triangle(i).vv0).x
		CGlobals.Tin3D(i).North=Engine.Vertex(Engine.Triangle(i).vv0).y
		CGlobals.Tin3D(i).Elev=Engine.Vertex(Engine.Triangle(i).vv0).z
		CGlobals.Tin3D(i).East1=Engine.Vertex(Engine.Triangle(i).vv1).x
		CGlobals.Tin3D(i).North1=Engine.Vertex(Engine.Triangle(i).vv1).y
		CGlobals.Tin3D(i).Elev1=Engine.Vertex(Engine.Triangle(i).vv1).z
		CGlobals.Tin3D(i).East2=Engine.Vertex(Engine.Triangle(i).vv2).x
		CGlobals.Tin3D(i).North2=Engine.Vertex(Engine.Triangle(i).vv2).y
		CGlobals.Tin3D(i).Elev2=Engine.Vertex(Engine.Triangle(i).vv2).z
		TinSave(i)
	Next
	Label2.Text=CGlobals.MaxTins
	InitScale
	DrawPoints
	ProgressDialogHide
End Sub

Sub Open_TinTable
	CGlobals.CreateOtherTables
End Sub

Sub TinSave(A As Int)
	Engine.CalcTinArea(Y1, X1, Y2, X2, Y3, X3)
	Rec=Rec+1
	Query = "INSERT INTO Stock VALUES (?,?,?,?,?,?,?,?,?,?,?)"
	CGlobals.SQL1.ExecNonQuery2(Query, Array As String(Rec, CGlobals.Tin3D(A).East, CGlobals.Tin3D(A).North, CGlobals.Tin3D(A).Elev,CGlobals.Tin3D(A).East1, CGlobals.Tin3D(A).North1, CGlobals.Tin3D(A).Elev1,CGlobals.Tin3D(A).East2, CGlobals.Tin3D(A).North2, CGlobals.Tin3D(A).Elev2, Engine.Area))
End Sub
#End Region

#Region ************************************************************* Calcs *****************************************************

Sub CalcAuto
	Dim i As Int
	
	For i = 0 To AreaCount - 1
		X1=ConvertPhysicToCADX(Ax(i))
		Y1=ConvertPhysicToCADY(Ay(i))
		X2=ConvertPhysicToCADX(Ax(i+1))
		Y2=ConvertPhysicToCADY(Ay(i+1))
		cvsDrawing.DrawLine(X1, Y1, X2, Y2,Colors.Red, 2)
	Next
	X1=ConvertPhysicToCADX(Ax(0))
	Y1=ConvertPhysicToCADY(Ay(0))
	X2=ConvertPhysicToCADX(Ax(AreaCount))
	Y2=ConvertPhysicToCADY(Ay(AreaCount))
	cvsDrawing.DrawLine(X1, Y1, X2, Y2,Colors.Red, 2)
	cvsDrawing.Invalidate
End Sub

Sub GetTriangles
	Dim I As Int = 0
	ProgressDialogShow2("Generating Boundary...", False)
	Sleep(0)
	' Initialize and populate the list of triangles
	Dim Triangles As List
	Triangles.Initialize
    
	For i = 0 To CGlobals.MaxTins - 1
		Dim triangle As List
		triangle.Initialize
		triangle.Add(CGlobals.Tin3D(i).East)
		triangle.Add(CGlobals.Tin3D(i).North)
		triangle.Add(CGlobals.Tin3D(i).Elev)
		triangle.Add(CGlobals.Tin3D(i).East1)
		triangle.Add(CGlobals.Tin3D(i).North1)
		triangle.Add(CGlobals.Tin3D(i).Elev1)
		triangle.Add(CGlobals.Tin3D(i).East2)
		triangle.Add(CGlobals.Tin3D(i).North2)
		triangle.Add(CGlobals.Tin3D(i).Elev2)
		Triangles.Add(triangle)
	Next
    
	' Identify edges
	Dim Edges As Map = IdentifyEdges(Triangles)
    
	' Find boundary edges
	Dim BoundaryEdges As List = FindBoundaryEdges(Edges)
    
	' Extract boundary points
	Dim boundaryPoints As List = ExtractBoundaryPoints(BoundaryEdges)
    
	' Order boundary points
	Dim orderedBoundaryPoints As List = OrderBoundaryPoints(boundaryPoints)
    
	' Log the boundary points
	For Each point As List In orderedBoundaryPoints
		Log("Boundary Point: X=" & point.Get(0) & ", Y=" & point.Get(1) & ", Z=" & point.Get(2))
	Next
    
	' Call CalcAuto to draw the boundary
	CalcAuto
	ProgressDialogHide
End Sub

' Function definitions for identifying and adding edges

Sub IdentifyEdges(Triangles As List) As Map
	Dim Edges As Map
	Edges.Initialize
	For Each tri As List In Triangles
		AddEdge(Edges, tri.Get(0), tri.Get(1), tri.Get(2), tri.Get(3), tri.Get(4), tri.Get(5))
		AddEdge(Edges, tri.Get(3), tri.Get(4), tri.Get(5), tri.Get(6), tri.Get(7), tri.Get(8))
		AddEdge(Edges, tri.Get(6), tri.Get(7), tri.Get(8), tri.Get(0), tri.Get(1), tri.Get(2))
	Next
	Return Edges
End Sub

Sub AddEdge(Edges As Map, X91 As Double, Y91 As Double, Z91 As Double, X92 As Double, Y92 As Double, Z92 As Double)
    Dim edge As String = Min(X91, X92) & ":" & Min(Y91, Y92) & ":" & Min(Z91, Z92) & "-" & Max(X91, X92) & ":" & Max(Y91, Y92) & ":" & Max(Z91, Z92)
    If Edges.ContainsKey(edge) Then
        Edges.Put(edge, Edges.Get(edge) + 1)
    Else
        Edges.Put(edge, 1)
    End If
End Sub


Sub FindBoundaryEdges(Edges As Map) As List
	Dim BoundaryEdges As List
	BoundaryEdges.Initialize
	For Each edge As String In Edges.Keys
		If Edges.Get(edge) = 1 Then
			BoundaryEdges.Add(edge)
		End If
	Next
	Return BoundaryEdges
End Sub

Sub ExtractBoundaryPoints(BoundaryEdges As List) As List
	Dim boundaryPoints As List
	boundaryPoints.Initialize
	For Each edge As String In BoundaryEdges
		Log(edge)
		Dim parts() As String = Regex.Split("-", edge)
		Dim vertex1() As String = Regex.Split(":", parts(0))
		Dim vertex2() As String = Regex.Split(":", parts(1))

		Dim point1 As List
		Dim point2 As List
		point1.Initialize
		point2.Initialize

		point1.Add(vertex1(0))
		point1.Add(vertex1(1))
		point1.Add(vertex1(2))

		point2.Add(vertex2(0))
		point2.Add(vertex2(1))
		point2.Add(vertex2(2))

		boundaryPoints.Add(point1)
		boundaryPoints.Add(point2)
	Next
	Return boundaryPoints
End Sub

Sub PointToKey(point As List) As String
	Return point.Get(0) & ":" & point.Get(1) & ":" & point.Get(2)
End Sub

Sub PopulateAdjList(BoundaryPoints As List) As List
	Dim AdjList As Map
	AdjList.Initialize
    
	For Each edge As String In BoundaryPoints
		Try
			Log(edge)
			Dim parts() As String = Regex.Split("-", edge)
			Dim vertex1() As String = Regex.Split(":", parts(0))
			Dim vertex2() As String = Regex.Split(":", parts(1))
        
			Dim point1 As List
			Dim point2 As List
			point1.Initialize
			point2.Initialize
        
			point1.Add(vertex1(0))
			point1.Add(vertex1(1))
			point1.Add(vertex1(2))
        
			point2.Add(vertex2(0))
			point2.Add(vertex2(1))
			point2.Add(vertex2(2))
        
			Dim key1 As String = PointToKey(point1)
			Dim key2 As String = PointToKey(point2)
        
			' Ensure the list for key1 is initialized
			If Not(AdjList.ContainsKey(key1)) Then
				Dim tempList As List
				tempList.Initialize
				AdjList.Put(key1, tempList)
			End If
        
			' Ensure the list for key2 is initialized
			If Not(AdjList.ContainsKey(key2)) Then
				Dim tempList As List
				tempList.Initialize
				AdjList.Put(key2, tempList)
			End If
        
			' Add point2 to the list associated with key1
			Dim listForKey1 As List = AdjList.Get(key1)
			listForKey1.Add(point2)
        
			' Add point1 to the list associated with key2
			Dim listForKey2 As List = AdjList.Get(key2)
			listForKey2.Add(point1)
		Catch
			Log(LastException)
		End Try
		
	Next
    
	Return AdjList
End Sub

Sub OrderBoundaryPoints(boundaryPoints As List) As List
	Dim AdjList As Map
	AdjList.Initialize
	PopulateAdjList(boundaryPoints)
    
	Dim orderedPoints As List
	orderedPoints.Initialize
    
	' Assuming the first point as starting point
	Dim currentPoint As List = boundaryPoints.Get(0)
	Dim key As String = PointToKey(currentPoint)
	orderedPoints.Add(currentPoint)
    
	Log("Starting key: " & key)
	Do While AdjList.ContainsKey(key)
		Dim adjListForCurrent As List = AdjList.Get(key)
		If adjListForCurrent.IsInitialized And adjListForCurrent.Size > 0 Then
			Log("Current key: " & key & ", List size: " & adjListForCurrent.Size)
			Dim nextPoint As List = adjListForCurrent.Get(0)
            
			' Remove the point from the adjacency list to avoid reprocessing it
			adjListForCurrent.RemoveAt(0)
            
			orderedPoints.Add(nextPoint)
			key = PointToKey(nextPoint)
			Log("Next key: " & key)
		Else
			Exit
		End If
	Loop
    
	Return orderedPoints
End Sub

Sub ClosePoint(A As Double, A1 As Double)' As Data
	'Find a Close Point
	Dim i As Int
	Dim Td,Tx As Double
	
	Td=99999999
	P1=-1
	SnapZ=0
	
	For i = 0 To CGlobals.MaxTins
		Tx= Power(CGlobals.Tin3D(i).East-A,2) + Power(CGlobals.Tin3D(i).North -A1,2)
		If Tx<Td Then
			Td=Tx
			P1=i
			p.East=CGlobals.Tin3D(i).East
			p.North=CGlobals.Tin3D(i).North
			SnapZ=CGlobals.Tin3D(i).Elev
		End If
	Next
End Sub

Sub AreaCalcs
	Dim Peri, PArea As Double
	
	ProgressDialogShow2("Calculating Areas & Volumes...", False)
	Sleep(10)

	'Calc the Volume
	CalcBTIN
	CalcVolume
End Sub

Sub ExitList_Click
	Panels
	Panel1.Visible=True
	Activity.Title="Stockpile"
	ProgressDialogShow2("Loading Stockpile Model...", False)
	Sleep(0)
	Engine.GetTriangles(2)
	Label2.Text=CGlobals.MaxTins
	ProgressDialogHide
	DrawPoints
End Sub

Sub CalcBTIN
	For i=0 To CGlobals.MaxPoints
		Engine.AddVertex(CGlobals.Points3D(i).East,CGlobals.Points3D(i).North,CGlobals.Points3D(i).Elev)
	Next
	Engine.CalculateTriangles
	BMaxTins=Engine.TriangleCount
	For i = 0 To BMaxTins
		BTin3D(i).East=Engine.Vertex(Engine.Triangle(i).vv0).x
		BTin3D(i).North=Engine.Vertex(Engine.Triangle(i).vv0).y
		BTin3D(i).Elev=Engine.Vertex(Engine.Triangle(i).vv0).z
		BTin3D(i).East1=Engine.Vertex(Engine.Triangle(i).vv1).x
		BTin3D(i).North1=Engine.Vertex(Engine.Triangle(i).vv1).y
		BTin3D(i).Elev1=Engine.Vertex(Engine.Triangle(i).vv1).z
		BTin3D(i).East2=Engine.Vertex(Engine.Triangle(i).vv2).x
		BTin3D(i).North2=Engine.Vertex(Engine.Triangle(i).vv2).y
		BTin3D(i).Elev2=Engine.Vertex(Engine.Triangle(i).vv2).z
	Next
End Sub

Sub CalcVolume
	Dim Peri, PArea As Double
	Dim Triangles As List
	Dim Boundary As List
	Dim vertices As List
	
	SV.Clear
	SV.DefaultDataFormatter.GetDefaultFormat.GroupingCharacter = ""
	SV.DefaultDataFormatter.GetDefaultFormat.MinimumFractions = 3
	
	ReportName =  CGlobals.Site & "_" & CGlobals.Job & "_AreaVol Calcs.csv"
	Activity.Title="Stockpile Calcs"
	SV.AddColumn("No", SV.COLUMN_TYPE_TEXT)
	SV.AddColumn("East", SV.COLUMN_TYPE_TEXT)
	SV.AddColumn("North", SV.COLUMN_TYPE_TEXT)
	SV.AddColumn("Elev", SV.COLUMN_TYPE_TEXT)
		
	Peri=0
	PArea=0
	SArea=0
	vertices.Initialize
	Triangles.Initialize
	Boundary.Initialize
	For i = 0 To CGlobals.MaxTins
		vertices.Add(Array As Float(CGlobals.Tin3D(i).East,CGlobals.Tin3D(i).North, CGlobals.Tin3D(i).Elev))
		vertices.Add(Array As Float(CGlobals.Tin3D(i).East1,CGlobals.Tin3D(i).North1, CGlobals.Tin3D(i).Elev1))
		vertices.Add(Array As Float(CGlobals.Tin3D(i).East2,CGlobals.Tin3D(i).North2, CGlobals.Tin3D(i).Elev2))
		Triangles.Add(Array As Int(0, 1, 2)) ' indices of vertices
	Next
    
	Sleep(50)
	For i=0 To AreaCount
		Boundary.Add(Array As Float(Ax(i), Ay(i)))
	Next
	Boundary.Add(Array As Float(Ax(0), Ay(0)))
	
'	Clip TIN To Boundary
	Sleep(50)
	Dim clippedTriangles As List = ClipTIN(vertices, Triangles, Boundary)
	
	' Calculate volume
	CalculateVolume(vertices, clippedTriangles)
'	Log("Volume: " & Volume)
	
	'Calc The Slope Area
	Dim slopeAreas As Map = CalculateSlopeAreas(vertices, clippedTriangles)
'	For Each key As String In slopeAreas.Keys
'		Log("Slope Range: " & key & ", Area: " & slopeAreas.Get(key))
'	Next

	Data.Initialize
	For i=0 To AreaCount
		Dim row(4) As Object
		row(0) = i+1
		row(1) = NumberFormat2(Ax(i),1,3,3,False)
		row(2) = NumberFormat2(Ay(i),1,3,3,False)
		row(3) = NumberFormat2(Az(i),1,3,3,False)
		Data.Add(row)
	Next
	
	'Calc The Perimeter
	For i=0 To AreaCount-1
		Engine.Join_Polar(Ax(i),Ay(i),Ax(i+1),Ay(i+1),1)
		Peri=Peri+Engine.CD
	Next
	
	'Calc The Plane Area
	For i=0 To AreaCount-1
		Engine.CalcCoordArea(Ax(i),Ay(i),Ax(i+1),Ay(i+1))
		PArea=PArea+Engine.Area
	Next
	Engine.CalcCoordArea(Ax(AreaCount),Ay(AreaCount),Ax(0),Ay(0))
	PArea=PArea+Engine.Area
	PArea=Abs(PArea*0.5)

	'Next Display the Areas
	Dim row(4) As Object
	row(0) = "Perimeter"
	row(1) = NumberFormat2(Peri,1,3,3,False)
	row(2) = ""
	row(3) = ""
	Data.Add(row)
	SV.SetData(Data)
	
	Dim row(4) As Object
	row(0) = "Plane Area"
	row(1) = NumberFormat2(PArea,1,3,3,False)
	row(2) = ""
	row(3) = ""
	Data.Add(row)
	SV.SetData(Data)
	
	Dim row(4) As Object
	row(0) = "Slope Area"
	row(1) = NumberFormat2(SArea,1,3,3,False)
	row(2) = ""
	row(3) = ""
	Data.Add(row)
	SV.SetData(Data)
	
	Dim row(4) As Object
	row(0) = "Volume"
	row(1) = NumberFormat2(TotalVolume,1,3,3,False)
	row(2) = ""
	row(3) = ""
	Data.Add(row)
	SV.SetData(Data)
	ProgressDialogHide
End Sub

Sub ClipTIN(vertices1 As List, Triangles1 As List, Boundary1 As List) As List
	Dim clippedTriangles As List
	
	clippedTriangles.Initialize
    
	For Each triangle() As Int In Triangles1
		Dim v1() As Float = vertices1.Get(triangle(0))
		Dim v2() As Float = vertices1.Get(triangle(1))
		Dim v3() As Float = vertices1.Get(triangle(2))
        
		If PointInPolygon(v1, Boundary1) And PointInPolygon(v2, Boundary1) And PointInPolygon(v3, Boundary1) Then
			clippedTriangles.Add(triangle)
		End If
	Next
    
	Return clippedTriangles
End Sub

Sub PointInPolygon(point() As Float, polygon As List) As Boolean
	Dim x As Float = point(0)
	Dim y As Float = point(1)
	Dim inside As Boolean = False
    
	Dim j As Int = polygon.Size - 1
	For i = 0 To polygon.Size - 1
		Dim vertexI() As Float = polygon.Get(i)
		Dim vertexJ() As Float = polygon.Get(j)
        
		Dim xi As Float = vertexI(0)
		Dim yi As Float = vertexI(1)
		Dim xj As Float = vertexJ(0)
		Dim yj As Float = vertexJ(1)
        
		Dim intersect As Boolean = ((yi > y) <> (yj > y)) And (x < (xj - xi) * (y - yi) / (yj - yi) + xi)
		If intersect Then
			inside = Not(inside)
			Return inside
		End If
		j = i
	Next
    
	Return inside
End Sub

Sub CalculateVolume(Vertices1 As List, Triangles1 As List) As Float
	Dim v4() As Float
	
	TotalVolume = 0
	For Each triangle() As Int In Triangles1
		Dim v1() As Float = Vertices1.Get(triangle(0))
		If WhichTriangle(v1(0),v1(1))>-999999 Then
			v4(0)=WhichTriangle(v1(0),v1(1))
		End If
		
		Dim v2() As Float = Vertices1.Get(triangle(1))
		If WhichTriangle(v2(0),v2(1))>-999999 Then
			v4(1)=WhichTriangle(v2(0),v2(1))
		End If
'		v4(1)=WhichTriangle(v2(0),v2(1))
		
		Dim v3() As Float = Vertices1.Get(triangle(2))
		If WhichTriangle(v3(0),v3(1))>-999999 Then
			v4(2)=WhichTriangle(v3(0),v3(1))
		End If
'		v4(20)=WhichTriangle(v3(0),v3(1))
		
'		Dim v4() As Float = vertices.Get(3) ' Reference plane vertex
        
		' Calculate the volume of the tetrahedron
		TetrahedronVolume(v1, v2, v3, v4)
		TotalVolume = TotalVolume + Volume
	Next
    
	Return Abs(TotalVolume) ' Volume should be positive
End Sub

Public Sub WhichTriangle(E As Double, N As Double) As Double
	Dim i5 As Int
	Dim TinArea,Area1,Area2,Area3,Area0 As Double
	
	For i5=0 To CGlobals.MaxTins
		TinArea=Engine.CalcTinArea(BTin3D(i5).East,BTin3D(i5).North,BTin3D(i5).East1,BTin3D(i5).North1,BTin3D(i5).East2,BTin3D(i5).North2)
		Area1=Engine.CalcTinArea(E,N,BTin3D(i5).East,BTin3D(i5).North,BTin3D(i5).East1,BTin3D(i5).North1)
		Area2=Engine.CalcTinArea(E,N,BTin3D(i5).East1,BTin3D(i5).North1,BTin3D(i5).East2,BTin3D(i5).North2)
		Area3=Engine.CalcTinArea(E,N,BTin3D(i5).East2,BTin3D(i5).North2,BTin3D(i5).East,BTin3D(i5).North)
		Area0=Area1+Area2+Area3
		If Area0*100<=TinArea*100 Then
			'Point is inside Triangle - Calc The Height
			Z2=CalcTinZ(E, N, i5)
			Return Z2
		End If
	Next
	Return -999999
End Sub

Sub CalcTinZ(X55 As Double, Y55 As Double, i5 As Int) As Double
	Dim a1,b1,c1,d1,Z5 As Double
	
	a1 = BTin3D(i5).North * (BTin3D(i5).Elev1 - BTin3D(i5).Elev2) + BTin3D(i5).North1 * (BTin3D(i5).Elev2 - BTin3D(i5).Elev) + BTin3D(i5).North2 * (BTin3D(i5).Elev - BTin3D(i5).Elev1)
	b1 = BTin3D(i5).Elev * (BTin3D(i5).East1 - BTin3D(i5).East2) + BTin3D(i5).Elev1 * (BTin3D(i5).East2 - BTin3D(i5).East) + BTin3D(i5).Elev2 * (BTin3D(i5).East - BTin3D(i5).East1)
	c1 = BTin3D(i5).East * (BTin3D(i5).North1 - BTin3D(i5).North2) + BTin3D(i5).East1 * (BTin3D(i5).North2 - BTin3D(i5).North) + BTin3D(i5).East2 * (BTin3D(i5).North - BTin3D(i5).North1)
	d1 = BTin3D(i5).East * (BTin3D(i5).North1 * BTin3D(i5).Elev2 - BTin3D(i5).North2 * BTin3D(i5).Elev1) - BTin3D(i5).East1 * (BTin3D(i5).North2 * BTin3D(i5).Elev - BTin3D(i5).North * BTin3D(i5).Elev2) - BTin3D(i5).East2 * (BTin3D(i5).North * BTin3D(i5).Elev1 - BTin3D(i5).North1 * BTin3D(i5).Elev)
	
	If Abs(c) > 0.0001 Then
		Z5 = 0 -(a1 * X55 + b1 * Y55 + d1) / c
	Else
		Z5 = -999999
	End If
	Return Z5
End Sub

Sub TetrahedronVolume(v1() As Float, v2() As Float, v3() As Float, v4() As Float) As Float
	
	Dim X1v As Float = v1(0) - v4(0)
	Dim Y1v As Float = v1(1) - v4(1)
	Dim Z1v As Float = v1(2) - v4(2)
    
	Dim X2v As Float = v2(0) - v4(0)
	Dim Y2v As Float = v2(1) - v4(1)
	Dim Z2v As Float = v2(2) - v4(2)
    
	Dim X3v As Float = v3(0) - v4(0)
	Dim Y3v As Float = v3(1) - v4(1)
	Dim Z3v As Float = v3(2) - v4(2)
    
	Volume = (X1v * (Y2v * Z3v - Y3v * Z2v) - Y1v * (X2v * Z3v - X3v * Z2v) + Z1v * (X2v * Y3v - X3v * Y2v)) / 6
	Return Volume
End Sub

Sub CalculateSlopeAreas(vertices1 As List, Triangles1 As List) As Map
	Dim slopeAreas As Map
	slopeAreas.Initialize
    
	For Each triangle() As Int In Triangles1
		Dim v1() As Float = vertices1.Get(triangle(0))
		Dim v2() As Float = vertices1.Get(triangle(1))
		Dim v3() As Float = vertices1.Get(triangle(2))
        
		Dim slope As Float = CalculateSlope(v1, v2, v3)
		Dim area As Float = TriangleArea(v1, v2, v3)
        
		Dim slopeRange As String = GetSlopeRange(slope)
		If slopeAreas.ContainsKey(slopeRange) Then
			slopeAreas.Put(slopeRange, slopeAreas.Get(slopeRange) + area)
		Else
			slopeAreas.Put(slopeRange, area)
		End If
		SArea=SArea + area
	Next
    
	Return slopeAreas
End Sub

Sub CalculateSlope(v1() As Float, v2() As Float, v3() As Float) As Float
	' Calculate the slope of the triangle
	Dim dz1 As Float = v2(2) - v1(2)
	Dim dz2 As Float = v3(2) - v1(2)
	Dim dx1 As Float = v2(0) - v1(0)
	Dim dx2 As Float = v3(0) - v1(0)
	Dim dy1 As Float = v2(1) - v1(1)
	Dim dy2 As Float = v3(1) - v1(1)
    
	Dim normalX As Float = dy1 * dz2 - dz1 * dy2
	Dim normalY As Float = dz1 * dx2 - dx1 * dz2
	Dim normalZ As Float = dx1 * dy2 - dy1 * dx2
    
	Dim slope As Float = ATan2(Sqrt(normalX * normalX + normalY * normalY), Abs(normalZ))
	Return slope
End Sub

Sub TriangleArea(v1() As Float, v2() As Float, v3() As Float) As Float
	' Calculate the area of the triangle
	Dim Av,Bv,Cv,S,Area As Double
	
	Av = Sqrt(Power((v2(0) - v1(0)),2) + Power((v2(1) - v1(1)),2))
	Bv = Sqrt(Power((v3(0) - v2(0)),2) + Power((v3(1) - v2(1)),2))
	Cv = Sqrt(Power((v3(0) - v1(0)),2) + Power((v3(1) - v1(1)),2))
	S = (Av + Bv + Cv) / 2
	Area = Sqrt(s * (s - Av) * (s - Bv) * (s - Cv))
	Return Area
End Sub

Sub GetSlopeRange(slope As Float) As String
	' Define slope ranges
	If slope < 10 Then
		Return "0-10"
	Else If slope < 20 Then
		Return "10-20"
	Else
		Return "20+"
	End If
End Sub

Sub ExportList_Click
	Dim SU As StringUtils

	If File.Exists(File.DirRootExternal  & "/CEASER/DATA/" & CGlobals.Site & "/" & CGlobals.Job & "/Reports","") = False Then
		File.MakeDir(File.DirRootExternal  & "/CEASER/DATA/" & CGlobals.Site & "/", CGlobals.Job & "/Reports")
	End If
		
	Data.Initialize
	Dim rs As ResultSet = SV.sql1.ExecQuery("SELECT * FROM Data")
	Do While rs.NextRow
		Dim row(SV.Columns.Size) As String
		For i = 0 To SV.Columns.Size - 1
			Dim c1 As B4XTableColumn = SV.Columns.Get(i)
			row(i) = rs.GetString(c1.SQLID)
		Next
		Data.Add(row)
	Loop
	
	Try
		SU.SaveCSV2(File.DirRootExternal,"/CEASER/DATA/" & CGlobals.Site & "/" & CGlobals.Job & "/Reports/" & ReportName, ",", Data, Array("No","East", "North", "Elev", "Plane Area", "Slope Area"))
		ToastMessageShow("Area & Vol Calcs Exported", False)
	Catch
		Log(LastException)
	End Try
End Sub

#End Region

#Region ***************************************************** Smooth Contours *****************************************************

'Sub ExtractContourPoints(TINModel As List) As List
'	Dim contourPoints As List
'	contourPoints.Initialize
'    
'	' Loop through the TIN model to extract contour points
'	For Each triangle As Triangle In tinModelTINModel
'		' Add the vertices of the triangle to the contour points list
'		contourPoints.Add(triangle.Vertex1)
'		contourPoints.Add(triangle.Vertex2)
'		contourPoints.Add(triangle.Vertex3)
'	Next
'    
'	Return contourPoints
'End Sub
'
'Sub SmoothContourPoints(contourPoints As List) As List
'	Dim smoothedPoints As List
'	smoothedPoints.Initialize
'    
'	For i = 0 To contourPoints.Size - 2
'		Dim p0 As Vertex = contourPoints.Get(i)
'		Dim P1 As Vertex = contourPoints.Get(i + 1)P1
'        
'		' Calculate new points
'		Dim q As Vertex = CreateVertex(0.75 * p0.X + 0.25 * P1.X, 0.75 * p0.Y + 0.25 * P1.P1P1Y)
'		Dim r As Vertex = CreateVertex(0.25 * p0.X + 0.75 * P1.X, 0.25 * p0.Y + 0.75 *P1P1 P1.Y)
'        
'		smoothedPoints.Add(q)
'		smoothedPoints.Add(r)
'	Next
'    
'	Return smoothedPoints
'End Sub
'
'Sub CreateVertex(X As Double, Y As Double) As Vertex
'	Dim vertex As Vertex
'	vertex.Initialize
'	vertex.X = X
'	vertex.Y = Y
'	Return vertex
'End Sub
'
'Sub UpdateTINModelWithSmoothedContour(TINModel As List, smoothedContour As List)
'	' Update the TIN model with the smoothed contour points
'	' This step will depend on how your TIN model is structured
'	' For simplicity, let's assume you replace the original points with the smoothed points
'	For i = 0 To TINModel.Size - 1
'		Dim triangle As Triangle = TINModel.Get(i)
'		triangle.Vertex1 = smoothedContour.Get(i * 3)
'		triangle.Vertex2 = smoothedContour.Get(i * 3 + 1)
'		triangle.Vertex3 = smoothedContour.Get(i * 3 + 2)
'	Next
'End Sub

#End Region

#Region ****************************************************** Shade TIN Model **********************************************************

Sub EditText1_FocusChanged(HasFocus As Boolean)
	If HasFocus =False Then
		If IsNumber(EditText1.Text) = False Then EditText1.Text=2
		EditText1.Text=NumberFormat2(EditText1.Text,1,0,0,False)
	Else
		EditText1.SelectAll
	End If
End Sub

Sub Butt2_Click
	If IsNumber(EditText1.Text)=False Or EditText1.Text<1 Then
		EditText1.Text=2
	End If
	EndCont.RequestFocus
	Panels
	Panel1.Visible=True
	ProgressDialogShow2("Generating Height Shading...",False)
	Sleep(0)
	FillTIN
	Shade=True
End Sub

Sub Butt1_Click
	'Exit
	Panels
	Panel1.Visible=True
End Sub

Sub FillTIN
	Dim i As Int
	Dim triangles As List
	Dim vertices As List
	
	HeightRanges.Initialize
	ColorsList.Initialize
	
	For i=Floor(CGlobals.ZMinCont) To Floor(CGlobals.ZMaxCont) Step EditText1.Text
		HeightRanges.Add(i)
		Dim ratio As Float = (i - CGlobals.ZMinCont) / (CGlobals.ZMaxCont - CGlobals.ZMinCont)
		Dim red As Int = 255 * ratio
		Dim blue As Int = 255 * (1 - ratio)
		ColorsList.Add(Colors.RGB(red, 0, blue))
	Next
	
	i=0
	Do While i<=CGlobals.MaxTins
		
		vertices.Initialize
		vertices.Add(Array As Float(CGlobals.Tin3D(i).East, CGlobals.Tin3D(i).North, CGlobals.Tin3D(i).Elev)) ' x, y, height
		vertices.Add(Array As Float(CGlobals.Tin3D(i).East1, CGlobals.Tin3D(i).North1, CGlobals.Tin3D(i).Elev1))
		vertices.Add(Array As Float(CGlobals.Tin3D(i).East2, CGlobals.Tin3D(i).North2, CGlobals.Tin3D(i).Elev2))
	    
		triangles.Initialize
		triangles.Add(Array As Int(0, 1, 2)) ' Indices of vertices forming a triangle
    
		ColorTINModel(vertices, triangles)
		i=i+1
	Loop
	DrawLegend
	ProgressDialogHide
End Sub

Sub ColorTINModel(Vertices1 As List, Triangles1 As List)
	For Each triangle() As Int In Triangles1
		Dim v1() As Float = Vertices1.Get(triangle(0))
		Dim v2() As Float = Vertices1.Get(triangle(1))
		Dim v3() As Float = Vertices1.Get(triangle(2))
        
		' Calculate average height
		Dim avgHeight As Float = (v1(2) + v2(2) + v3(2)) / 3
        
		' Determine color based on height
		Dim color As Int = GetColorFromHeight(avgHeight)
        
		' Draw the filled triangle
		DrawFilledTriangle(v1(0), v1(1), v2(0), v2(1), v3(0), v3(1), color)
	Next
End Sub

Sub DrawFilledTriangle(Y21 As Float, X21 As Float, Y22 As Float, X22 As Float, Y23 As Float, X23 As Float, color As Int)
	Dim path As B4XPath
	
	X21 = ConvertToDrawingX(X21)
	Y21 = ConvertToDrawingY(Y21)
	X22 = ConvertToDrawingX(X22)
	Y22 = ConvertToDrawingY(Y22)
	X23 = ConvertToDrawingX(X23)
	Y23 = ConvertToDrawingY(Y23)
	path.Initialize(Y21, X21)
	path.LineTo(Y22, X22)
	path.LineTo(Y23, X23)
	path.LineTo(Y21, X21)
    
	cvsDrawing.DrawPath(path, color, True, 1)
	cvsDrawing.Invalidate
End Sub

Sub GetColorFromHeight(Height As Float) As Int
	' Map height to a color gradient from blue (low) to red (high)
	Dim ratio As Float = (Height - CGlobals.ZMinCont) / (CGlobals.ZMaxCont - CGlobals.ZMinCont)
	Dim red As Int = 255 * ratio
	Dim blue As Int = 255 * (1 - ratio)
	Dim color As Int = Colors.RGB(red, 0, blue)
	Return color
End Sub

Sub ConvertToDrawingY(A As Double) As Double
	Return (A - SheetX0) * ScaleX + ScreenX0
End Sub

Sub ConvertToDrawingX(B As Double) As Double
	Return (B - SheetY0) * ScaleY + ScreenY0
End Sub

Sub DrawLegend
	Dim i As Int
	Dim fnt As B4XFont
	Dim Color As Int
	Dim Top As Int
	
	fnt = xui.CreateDefaultFont(12)
	For i = 1 To HeightRanges.Size - 1
		Color = ColorsList.Get(i)
		Top = (i * 30) + 25
		cvsDrawing.DrawLine(10,Top,40,Top,Color,25)
		cvsDrawing.DrawText(HeightRanges.Get(i-1) & " - " & HeightRanges.Get(i),47,Top+8,fnt, Colors.Black, "LEFT")
	Next
    cvsDrawing.Invalidate
End Sub

#End Region



