Error bar not showing all the values in mschart - vb.net

I am using VB.NET with mschart. I am using ErroBar chartype but i am not able to label all the values (medium, upper and lower). When i set chart.Series("ErrorBar").IsValueShownAsLabel = True, only upper value is shown.
I want to show the center, upper and lower values.
Thanks in advance

The solution adopted by me was a simpler one using annotations as can be seen in the code below
Dim Media1 As New RectangleAnnotation()
Media1.BackColor = Color.Yellow
Media1.Text = FormatNumber(D20, 4)
Dim point As PointF = New PointF(chart.ChartAreas(0).AxisX.ValueToPosition(1), chart.ChartAreas(0).AxisY.ValueToPosition(D20))
Media1.AnchorX = point.X + 10
Media1.AnchorY = point.Y + 2
Media1.AllowMoving = True
Dim L1 As New RectangleAnnotation()
L1.BackColor = Color.Yellow
L1.Text = FormatNumber(D20 - result * My.Settings("IncertezaDensidade20") / 2, 4)
point = New PointF(chart.ChartAreas(0).AxisX.ValueToPosition(1), chart.ChartAreas(0).AxisY.ValueToPosition(D20 - result * My.Settings("IncertezaDensidade20") / 2))
L1.AnchorX = point.X
L1.AnchorY = point.Y + 10
L1.AllowMoving = True
Dim L2 As New RectangleAnnotation()
L2.BackColor = Color.Yellow
L2.Text = FormatNumber(D20 + result * My.Settings("IncertezaDensidade20") / 2, 4)
point = New PointF(chart.ChartAreas(0).AxisX.ValueToPosition(1), chart.ChartAreas(0).AxisY.ValueToPosition(D20 + result * My.Settings("IncertezaDensidade20") / 2))
L2.AnchorX = point.X
L2.AnchorY = point.Y - 5
L2.AllowMoving = True
The chart now, can be seen below

Related

How to solve ArgumentException : The parameter is not valid for drawing Arcs

I'm making a custom winforms button in VB.Net with rounded edges and other features. I create a path using various inputs defined by the user and draw and fill it using pens and brushes.
When I call e.Graphics.FillEllipse(Brush1, Rect1) and e.Graphics.DrawEllips(Pen1, Rect1) it just works fine without any problems, but when I try e.Graphics.FillPath(Brush1, OuterPath) and e.Graphics.DrawPath(Pen1, OuterPath) it doesn't work at all. I get this error:
ArgumentException: The parameter is not valid
I tried giving the right types of each variable used in the process and not letting the compiler decide, creating more variables to calculate and manage the inputs individually to not make all the calculations in the inputs of each function, which makes my work easier honestly, and even using the CType function in the inputs of each function to make sure that the function understands what I want as inputs. But everything failed and I don't know what to do next to fix the issue.
Here is the code:
Private Sub MetaniumButton_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim PathWidth As Integer = Width - BorderSize / 2
Dim PathHeight As Integer = Height - BorderSize / 2
_Roundnes = RoundnesMemory
If PathHeight < Roundenes.Height Then
_Roundnes.Height = PathHeight - 1
End If
If PathWidth < Roundenes.Width Then
_Roundnes.Width = PathWidth - 1
End If
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Dim OuterPath As New GraphicsPath
Dim Rec1 As Rectangle = New Rectangle(CType(BorderSize / 2, Int32), CType(BorderSize / 2, Int32), CType(_Roundnes.Width, Int32), CType(_Roundnes.Height, Int32))
Dim Rec2 As Rectangle = New Rectangle(PathWidth - _Roundnes.Width, BorderSize / 2, _Roundnes.Width, _Roundnes.Height)
Dim Rec3 As Rectangle = New Rectangle(PathWidth - _Roundnes.Width, PathHeight - _Roundnes.Height, _Roundnes.Width, _Roundnes.Height)
Dim Rec4 As Rectangle = New Rectangle(BorderSize / 2, PathHeight - _Roundnes.Height, _Roundnes.Width, _Roundnes.Height)
OuterPath.StartFigure()
OuterPath.AddLine(CInt(_Roundnes.Width / 2 + BorderSize / 2), CInt(BorderSize / 2), CInt(PathWidth - _Roundnes.Width / 2), CInt(BorderSize / 2))
OuterPath.AddArc(Rec1, 180.0, 90.0) ' Here is the problem and it could probably in any AddArc Function i used
OuterPath.AddLine(PathWidth, CInt(_Roundnes.Height / 2 + BorderSize / 2), PathWidth, CInt(PathHeight - _Roundnes.Height / 2))
OuterPath.AddArc(Rec2, -90, 90)
OuterPath.AddLine(CInt(_Roundnes.Width / 2 + BorderSize / 2), PathHeight, CInt(PathWidth - _Roundnes.Width / 2), PathHeight)
OuterPath.AddArc(Rec3, 0, 90)
OuterPath.AddLine(CInt(BorderSize / 2), CInt(_Roundnes.Height / 2), CInt(BorderSize / 2), CInt(PathHeight - _Roundnes.Height / 2))
OuterPath.AddArc(Rec4, 90, 90)
OuterPath.CloseFigure()
e.Graphics.FillPath(Brush1, OuterPath)
e.Graphics.DrawPath(Pen1, OuterPath)
Dim LabelCount As Integer = 0
For Each l As Label In Controls
LabelCount += 1
Next
Dim TextPlace As New Label With {.Name = "TextLabel",
.Text = Text,
.AutoEllipsis = True,
.Size = New Size(Width -
Margin.Left + Margin.Right + 2 * _Roundnes.Width) / 2, Height - (Margin.Top + Margin.Bottom + 2 * _Roundnes.Height) / 2),
.TextAlign = _TextAlign,
.ForeColor = _FontColor,
.BackColor = _MetaniumBackColor,
.Location = New Point((Width - .Width) / 2, (Height - .Height) / 2)}
AddHandler TextPlace.TextChanged, AddressOf MetaniumButton_TextChanged
AddHandler Me.TextChanged, AddressOf MetaniumButton_TextChanged
Controls.Add(TextPlace)
T += 1
If LabelCount <= 0 Then
0: For Each l As Label In Controls
If l.Name = "TextLabel" Then
l.Text = Text
l.AutoEllipsis = True
l.Size = New Size(Width - (Margin.Left + Margin.Right + 2 * _Roundnes.Width) / 2, Height - (Margin.Top + Margin.Bottom + 2 * _Roundnes.Height) / 2)
l.TextAlign = _TextAlign
l.ForeColor = _FontColor
l.BackColor = _MetaniumBackColor
l.Location = New Point((Width - l.Width) / 2, (Height - l.Height) / 2)
End If
Next
ElseIf LabelCount = 1 Then
For Each l As Label In Controls
If l.Name <> "TextLabel" Then
Controls.Remove(l)
Else
GoTo 1
End If
1: GoTo 0
Next
Else
End If
End Sub
When I track down the bug it seems the problem is in the AddArc() function, and I really don't know why it doesn't work. Any help appreciated.
BTW, I use VB.Net Express 2010 with .Net Framework 4.8.
PS: you can post an answer using either VB.Net or C# I can translate the code from both of them.
I solved My problem, and the answer was to initialize the value or Roundnes to (1,1) at least because my code creates the arcs of the edges using Roundnes to know how wide and long the curving edge
so the solution is to add this line of code before the code responsible for creating the arc.
If _Roundnes = New Size(0, 0) Then _Roundnes = New Size(1, 1)
And that's pretty much it! Thank you for helping me out!

Change Number of Categories between Tick-Mark Labels on Chart X-axis

If I have more (or less) data in my Access 2010 graph, I want to decrease (or increase) the number of tick marks on the X-axis. I looked for the right syntax but I couldn't find it.
I did the same for the Y-axis Title and that works fine:
me.Graph1.Object.Axes(2,1).AxisTitles.Caption="g/ml"
For number of tick-marks of the X-axis; I've tried a number of words can not find the right one. It stopped at:
me.Graph.Object.Axes(1,1).Scale.???????? (I want a number of categories = 3 )
Example code from my db for XYScatter chart. xlCategory is for X-axis and xlValue is Y-axis.
this procedure is in a standard module and called by a form and a report
Sub FormatProcGraph(strObject As String, strLabNum As String, booMetric As Boolean, dblOMC, dblMDD)
'format Proctor graph on form and report
Dim obj As Object
Dim gc As Object
Dim intMaxD As Integer
Dim intMinD As Integer
Dim intM As Integer
If strObject Like "Lab*" Then
Set obj = Reports(strObject)
Else
Set obj = Forms(strObject).Controls("ctrProctor").Form
End If
Set gc = obj("gphDensity")
intMaxD = Nz(Int(dblMDD), 0)
intMinD = Nz(Int(DMin("D", "GraphProctor", "Source='Lab' AND LabNum='" & strLabNum & "'")), 0)
With gc
'format y axis scale
If booMetric = True Then
intMaxD = intMaxD + IIf(intMaxD - intMinD < 125, 50, IIf(intMaxD - intMinD < 250, 25, 0))
.Axes(xlValue).MaximumScale = intMaxD
.Axes(xlValue).MinimumScale = intMaxD - 250
.Axes(xlValue).MajorUnit = 50
.Axes(xlValue).MinorUnit = 10
Else
intMaxD = intMaxD + IIf(intMaxD - intMinD < 6, 2, IIf(intMaxD - intMinD < 10, 1, 0))
.Axes(xlValue).MaximumScale = intMaxD
.Axes(xlValue).MinimumScale = intMaxD - 10
.Axes(xlValue).MajorUnit = 2
.Axes(xlValue).MinorUnit = 0.4
End If
'format x axis scale
If Int(dblOMC) > 6 Then
intM = Int(dblOMC) + IIf(dblOMC - Int(dblOMC) >= 0.5, 1, 0)
.Axes(xlCategory).MaximumScale = intM + 7
.Axes(xlCategory).MinimumScale = intM - 5
End If
'y axis label
.Axes(xlValue, xlPrimary).HasTitle = True
If booMetric = True Then
.Axes(xlValue, xlPrimary).AxisTitle.Text = "Dry Density, kg/cu.m"
End If
End With
End Sub
this procedure is behind report
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
'format graphs
Dim MinUWT As Double, MaxUWT As Double
Dim MinDry As Double, MaxDry As Double
Dim MinSoak As Double, MaxSoak As Double
Dim MinRat As Double, MaxRat As Double
With Me
If Not IsNull(!MinOfA) Then
MinUWT = Int(!MinOfU) - IIf(!MaxOfU - !MinOfU <= 2, 3, 1)
MaxUWT = MinUWT + 8
MinDry = Int(!MinOfD / 5) * 5 - (40 - Int((Int(!MaxOfD / 5) * 5 + 5 - Int(!MinOfD / 5) * 5) / 10) * 10) / 2
MaxDry = MinDry + 40
MinSoak = Int(!MinOfS / 5) * 5 - (40 - Int((Int(!MaxOfS / 5) * 5 + 5 - Int(!MinOfS / 5) * 5) / 10) * 10) / 2
MaxSoak = MinSoak + 40
MinRat = Int(!MinOfR / 5) * 5 - (40 - Int((Int(!MaxOfR / 5) * 5 + 5 - Int(!MinOfR / 5) * 5) / 10) * 10) / 2
MaxRat = MinRat + 40
.gphWeight.Axes(xlValue).MinimumScale = MinUWT
.gphWeight.Axes(xlValue).MaximumScale = MaxUWT
.gphITSdry.Axes(xlValue).MinimumScale = MinDry
.gphITSdry.Axes(xlValue).MaximumScale = MaxDry
.gphITSsoak.Axes(xlValue).MinimumScale = MinSoak
.gphITSsoak.Axes(xlValue).MaximumScale = MaxSoak
.gphITSret.Axes(xlValue).MinimumScale = MinRat
.gphITSret.Axes(xlValue).MaximumScale = MaxRat
If Me!Metric = True Then
.gphWeight.Axes(xlValue, xlPrimary).AxisTitle.Text = "Unit Weight, kg/cu.cm"
.gphGradation.Axes(xlCategory, xlPrimary).AxisTitle.Text = "Sieve Size (mm)"
.gphITSdry.Axes(xlValue, xlPrimary).AxisTitle.Text = "ITS Dry, kg/cu.cm"
.gphITSsoak.Axes(xlValue, xlPrimary).AxisTitle.Text = "ITS Soaked, kg/cu.cm"
End If
End If
End With
End Sub

Looking to solve an infinite loop

I have a piece of code that generates a dungeon in Java and Python but seems to create an infinite loop in visual basic. There might be a slight problem that I'm overlooking.
Dim Touching As Boolean = True
While Touching = True
Touching = False
'Run through all the rooms and check if they overlap
For i = 0 To numRooms
Dim aPos As Point = RoomXY(i)
Dim aDime As Point = RoomWH(i)
For j = 0 To numRooms
Dim bPos As Point = RoomXY(j)
Dim bDime As Point = RoomWH(j)
If (aPos = bPos) And (aDime = bDime) Then
Continue For
Else
'Check for overlapping
Dim H_Overlaps As Boolean = (aPos.X <= bPos.X + bDime.X) And (bPos.X <= aPos.X + aDime.X)
Dim V_Overlaps As Boolean = (aPos.Y <= bPos.Y + bDime.Y) And (bPos.Y <= aPos.Y + aDime.Y)
If H_Overlaps AndAlso V_Overlaps Then
Touching = True
'Find the minimum amount of movment that stops the squares from touching
Dim dx = Math.Min(Math.Abs((aPos.X + aDime.X) - (bPos.X + 2)), Math.Abs(aPos.X - (bPos.X + bDime.X + 2)))
Dim dy = Math.Min(Math.Abs((aPos.Y + aDime.Y) - (bPos.Y + 2)), Math.Abs(aPos.Y - (bPos.Y + bDime.Y + 2)))
If dx <= dy Then
dy = 0
Else
dx = 0
End If
If aPos.X >= bPos.X Then
RoomXY(i) = New Point(RoomXY(i).X + (dx / 2), RoomXY(i).Y)
RoomXY(j) = New Point(RoomXY(j).X - (dx / 2), RoomXY(j).Y)
Else
RoomXY(i) = New Point(RoomXY(i).X - (dx / 2), RoomXY(i).Y)
RoomXY(j) = New Point(RoomXY(j).X + (dx / 2), RoomXY(j).Y)
End If
If aPos.Y >= bPos.Y Then
RoomXY(i) = New Point(RoomXY(i).X, RoomXY(i).Y + (dy / 2))
RoomXY(j) = New Point(RoomXY(j).X, RoomXY(j).Y - (dy / 2))
Else
RoomXY(i) = New Point(RoomXY(i).X, RoomXY(i).Y - (dy / 2))
RoomXY(j) = New Point(RoomXY(j).X, RoomXY(j).Y + (dy / 2))
End If
End If
End If
Next
Next
End While
This piece is of code is given room dimensions, checks if they overlap and then shifts them away from each other. I've tried everything, but I can't seem to break the infinite loop.

Show WinForm below a cell

How can I show I winform that I create in VB.NET just below the active cell?
I have no idea how to solve this. I found the following promising solutions:
Excel addin: Cell absolute position
-The accepted solution seems too complicated to work reliably. I got an error on the first row (Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long)
-The second solution looked promising, but it didn't give me the right positions for my windows form.
The following adaptations of the second proposed solution does not create any errors but does not put the windows form in the correct position:
Public Sub GetScreenPositionFromCell(cell As Excel.Range, excel As Excel.Application)
Dim x As Double
Dim y As Double
If Not excel.ActiveWindow Is Nothing Then
x = excel.ActiveWindow.PointsToScreenPixelsX(cell.Left)
y = excel.ActiveWindow.PointsToScreenPixelsY(cell.Top)
End If
Me.Left = x
Me.Top = y
Me.Show()
Me.TopMost = True
End Sub
EDIT: #Loating, here is how I have used your code. It's great and I am very happy that you are taking your time to help me with a solution. The x-coordinates seems to work while the x-coordinates are a bit off and more or less off depending on the zoom level.
Public Sub ShowMeBelowActiveCell()
Dim ExcelApp As Excel.Application = CType(AddinExpress.MSO.ADXAddinModule.CurrentInstance, AddinModule).ExcelApp
Dim excelWindow = ExcelApp.ActiveWindow
Dim cell = ExcelApp.ActiveCell
Dim zoomFactor As Double = excelWindow.Zoom / 100
Dim ws = cell.Worksheet
' PointsToScreenPixels returns different values if the scroll is not currently 1
' Temporarily set the scroll back to 1 so that PointsToScreenPixels returns a
' value we know how to handle.
Dim origScrollCol = excelWindow.ScrollColumn
Dim origScrollRow = excelWindow.ScrollRow
excelWindow.ScrollColumn = 1
excelWindow.ScrollRow = 1
' (x,y) are screen coordinates for the top left corner of the top left cell
Dim x As Integer = excelWindow.PointsToScreenPixelsX(0)
' e.g. window.x + row header width
Dim y As Integer = excelWindow.PointsToScreenPixelsY(0)
' e.g. window.y + ribbon height + column headers height
Dim dpiX As Single = 0
Dim dpiY As Single = 0
Using g = Drawing.Graphics.FromHwnd(IntPtr.Zero)
dpiX = g.DpiX
dpiY = g.DpiY
End Using
' Note: Each column width / row height has to be calculated individually.
' Before, tried to use this approach:
' var r2 = (Microsoft.Office.Interop.Excel.Range) cell.Worksheet.Cells[origScrollRow, origScrollCol];
' double dw = cell.Left - r2.Left;
' double dh = cell.Top - r2.Top;
' However, that only works when the zoom factor is a whole number.
' A fractional zoom (e.g. 1.27) causes each individual row or column to round to the closest whole number,
' which means having to loop through.
For i As Integer = origScrollCol To cell.Column - 1
Dim col = DirectCast(ws.Cells(cell.Row, i), Microsoft.Office.Interop.Excel.Range)
Dim ww As Double = col.Width * dpiX / 72
Dim newW As Double = zoomFactor * ww
x += CInt(Math.Round(newW))
Next
For i As Integer = origScrollRow To cell.Row - 1
Dim row = DirectCast(ws.Cells(i, cell.Column), Microsoft.Office.Interop.Excel.Range)
Dim hh As Double = row.Height * dpiY / 72
Dim newH As Double = zoomFactor * hh
y += CInt(Math.Round(newH))
Next
excelWindow.ScrollColumn = origScrollCol
excelWindow.ScrollRow = origScrollRow
Me.StartPosition = Windows.Forms.FormStartPosition.Manual
Me.Location = New Drawing.Point(x, y)
Me.Show()
End Sub
End Class
When the ScrollColumn and ScrollRow are both 1, then PointsToScreenPixelsX/Y seems to return the top left point of the top left visible cell in screen coordinates. Using this, the offset width and height to the active cell is calculated, taking into consideration the zoom setting.
var excelApp = Globals.ThisAddIn.Application;
var excelWindow = excelApp.ActiveWindow;
var cell = excelApp.ActiveCell;
double zoomFactor = excelWindow.Zoom / 100;
var ws = cell.Worksheet;
var ap = excelWindow.ActivePane; // might be split panes
var origScrollCol = ap.ScrollColumn;
var origScrollRow = ap.ScrollRow;
excelApp.ScreenUpdating = false;
// when FreezePanes == true, ap.ScrollColumn/Row will only reset
// as much as the location of the frozen splitter
ap.ScrollColumn = 1;
ap.ScrollRow = 1;
// PointsToScreenPixels returns different values if the scroll is not currently 1
// Temporarily set the scroll back to 1 so that PointsToScreenPixels returns a
// value we know how to handle.
// (x,y) are screen coordinates for the top left corner of the top left cell
int x = ap.PointsToScreenPixelsX(0); // e.g. window.x + row header width
int y = ap.PointsToScreenPixelsY(0); // e.g. window.y + ribbon height + column headers height
float dpiX = 0;
float dpiY = 0;
using (var g = Graphics.FromHwnd(IntPtr.Zero)) {
dpiX = g.DpiX;
dpiY = g.DpiY;
}
int deltaRow = 0;
int deltaCol = 0;
int fromCol = origScrollCol;
int fromRow = origScrollRow;
if (excelWindow.FreezePanes) {
fromCol = 1;
fromRow = 1;
deltaCol = origScrollCol - ap.ScrollColumn; // Note: ap.ScrollColumn/Row <> 1
deltaRow = origScrollRow - ap.ScrollRow; // see comment: when FreezePanes == true ...
}
// Note: Each column width / row height has to be calculated individually.
// Before, tried to use this approach:
// var r2 = (Microsoft.Office.Interop.Excel.Range) cell.Worksheet.Cells[origScrollRow, origScrollCol];
// double dw = cell.Left - r2.Left;
// double dh = cell.Top - r2.Top;
// However, that only works when the zoom factor is a whole number.
// A fractional zoom (e.g. 1.27) causes each individual row or column to round to the closest whole number,
// which means having to loop through.
for (int i = fromCol; i < cell.Column; i++) {
// skip the columns between the frozen split and the first visible column
if (i >= ap.ScrollColumn && i < ap.ScrollColumn + deltaCol)
continue;
var col = ((Microsoft.Office.Interop.Excel.Range) ws.Cells[cell.Row, i]);
double ww = col.Width * dpiX / 72;
double newW = zoomFactor * ww;
x += (int) Math.Round(newW);
}
for (int i = fromRow; i < cell.Row; i++) {
// skip the columns between the frozen split and the first visible column
if (i >= ap.ScrollRow && i < ap.ScrollRow + deltaRow)
continue;
var row = ((Microsoft.Office.Interop.Excel.Range) ws.Cells[i, cell.Column]);
double hh = row.Height * dpiY / 72;
double newH = zoomFactor * hh;
y += (int) Math.Round(newH);
}
ap.ScrollColumn = origScrollCol;
ap.ScrollRow = origScrollRow;
excelApp.ScreenUpdating = true;
Form f = new Form();
f.StartPosition = FormStartPosition.Manual;
f.Location = new Point(x, y);
f.Show();

Trouble with VB.NET Liang-Barsky implementation

After some research, I've decided to use the Liang-Barsky line clipping algorithm in my 2D game. Google did not deliver on any VB.NET implementations of this algorithm but plenty C/++ ones. Therefore, as I have knowledge in C++, decided to port one found on Skytopia over to VB.Net. Unfortunately, it does not work with:
Public Class PhysicsObject
Public Function CollideRay(ByVal p0 As Point, ByVal p1 As Point, ByRef clip0 As Point, ByRef clip1 As Point) As Boolean
Dim t0 As Double = 0.0
Dim t1 As Double = 1.0
Dim xdelta As Double = p1.X - p0.X
Dim ydelta As Double = p1.Y - p0.Y
Dim p, q, r As Double
For edge = 0 To 3
' Traverse through left, right, bottom, top edges
If (edge = 0) Then
p = -xdelta
q = -(AABB.Left - p0.X)
ElseIf (edge = 1) Then
p = xdelta
q = (AABB.Right - p0.X)
ElseIf (edge = 2) Then
p = -ydelta
q = -(AABB.Bottom - p0.Y)
ElseIf (edge = 3) Then
p = ydelta
q = (AABB.Top - p0.Y)
End If
r = q / p
If p = 0 And q < 0 Then Return False ' Don't draw line at all. (parallel line outside)
If p < 0 Then
If r > t1 Then
Return False ' Don't draw line at all.
ElseIf r > t0 Then
t0 = r ' Line is clipped!
End If
ElseIf p > 0 Then
If r < t0 Then
Return False ' Don't draw line at all.
ElseIf r < t1 Then
t1 = r ' Line is clipped!
End If
End If
Next
clip0.X = p0.X + t0 * xdelta
clip0.Y = p0.Y + t0 * ydelta
clip1.X = p0.X + t1 * xdelta
clip1.Y = p0.Y + t1 * ydelta
Return True ' (clipped) line is drawn
End Function
Public AABB As Rectangle
End Class
I'm using the class/method like:
Dim testPhysics As PhysicsObject = New PhysicsObject
testPhysics.AABB = New Rectangle(30, 30, 20, 20)
Dim p0, p1 As Point
p0 = New Point(0, 0)
p1 = New Point(120, 120)
Dim clip0, clip1 As Point
clip0 = New Point(-1, -1)
clip1 = New Point(-1, -1)
GlobalRenderer.Graphics.DrawLine(Pens.LimeGreen, p0, p1)
If testPhysics.CollideRay(p0, p1, clip0, clip1) Then
GlobalRenderer.Graphics.DrawLine(Pens.Magenta, clip0, clip1)
End If
However, the CollideRay method fails on its 3rd edge iteration (edge = 3), r < t0, therefore the function returns false.
I'm wondering if anyone can spot some issue with my CollideRay function which would result in this behaviour, because I'm well and truly stumped.
Thanks in advance.
The code assumes a different coordinate system, note that topEdge is larger than bottomEdge in the linked web page. Your test works with normal graphics coordinates where Bottom is larger than Top. You have to swap the bottom and top arguments.