# Math professors in the house?

Discussion in 'Tools programming' started by SdC, 8 Apr 2007.

1. ### SdC

Joined:
6 Mar 2007
Messages:
35
Country:
Hi all,
My highschool math lessons seem to have made place for other stuff in my head...
I'm programming a polygon manipulation tool, but cannot get around the following problem, and I hope some brilliant soul could give me some help with it:

If I know the points (x1,y1), (x2,y2) and (x3,y3) as well as the distance between the parallel lines (w) how could I deduct the intersections of the parallel lines (x4,y4),(x5,y5)?

2. ### Luis_SáResource contributor

Joined:
16 Sep 2004
Messages:
316
Country:
Hello,

Here is the code I use in SBuilder to draw one "wide line" NP points. For each point I have the X, Y and W (width at this point). Note that I start at point 2. The instruction FillPolygon(PTS) draws the polygon (filling it with a color) whose vertices are PTS(0) PTS(1) PTS(2) and PTS(3). I post here 2 pictures. The first one is the normal one. The second one is the one I get after deleting the FillPolygon(PTS) inside the "If Then ... End If". I hope you can figure out the points PTS(0) PTS(1) PTS(2) and PTS(3) by looking to the pictures.

PX1 = X(1)
PY1 = Y(1)
PW1 = W(1)/2

For K = 2 To NP

PX0 = PX1
PY0 = PY1
PW0 = PW1

PX1 = X(K)
PY1 = Y(K)
PW1 = W(K)/2

UX = PX1 - PX0
UY = PY1 - PY0
U = UX * UX + UY * UY
U = System.Math.Sqrt(U)

UX = UX / U
UY = UY / U
DX = PW0 * UX
DY = PW0 * UY

PTS(0).X = PX0 - DY
PTS(0).Y = PY0 + DX
PTS(1).X = PX0 + DY
PTS(1).Y = PY0 - DX

If K > 2 Then
FillPolygon(PTS)
End If

DX = PW1 * UX
DY = PW1 * UY
PTS(2).X = PX1 + DY
PTS(2).Y = PY1 - DX
PTS(3).X = PX1 - DY
PTS(3).Y = PY1 + DX

FillPolygon(PTS)

Next K

Regards,

Luis

3. ### SdC

Joined:
6 Mar 2007
Messages:
35
Country:
Hi Luis!
Thanks very much, I will look at it today.

-The purpose of this routine is to convert lines from an SBX file (!) and create ASM output to draw VTP1 (!) lines. VTP1 lines are my closest friend and my worst enemy at the same time for the last 4 years. This is my site: http://combatfs.homeip.net
Rhumba and me almost continuously have discussions like this: http://www.fsdeveloper.com/forum/showthread.php?t=4182

The tool I'm developing is cfs2autocoast. Until now, I was converting lines to ground2k project (LWM file) because ground2k3 v.4 is currently the only program to compile VTP1 lines, but the routine is too buggy and Christian lost the source files for it.....

Maybe if I get this project working, you'd be interested in integrating it in sBuilder (a CFS2 checkbox in the BGL compilation form)? I know of about 6 active developers (we hang out at www.sim-outhouse.com) that would make good use of it!

Right now, I'm programming in vb.net 2005, and I think you are using vb6?
Maybe we can help each other (I'm very good at upgrading vb6 apps for .NET/ Vista).

I'll let you know how I get on with the routine!
Bye now,
-Sander.

4. ### SdC

Joined:
6 Mar 2007
Messages:
35
Country:
Unfortunately your algorithm is not going to work well for me; it would become too difficult to do the UV map and also roads/railways would become uneven.
The result I need to get is something like:

But the result I get is:

from this code:
Code:
```Public Sub CreatePolygons()

Dim i As Integer
Dim w, a As Double
Dim Preva1X, Preva1Y, Preva2X, Preva2Y As Double

ReDim SegmentPolys(NumberOfPoints - 1)
For i = 1 To NumberOfPoints - 1
If i = 1 Then
'first point parameters
If BeginThinner = True Then w = 8 Else w = getSegmentWidth(0)
'set the first point:
Preva1X = getPointX(0) + (PixDegreeX(w / 2) * Sin(90))
Preva1Y = getPointY(0) + (PixDegreeY(w / 2) * Sin(90))
Preva2X = getPointX(0) - (PixDegreeX(w / 2) * Sin(90))
Preva2Y = getPointY(0) - (PixDegreeY(w / 2) * Sin(90))
w = getSegmentWidth(i)
a = Gamma(i)
ElseIf i <= NumberOfPoints - 2 Then
'middle points parameters
w = getSegmentWidth(i)
a = Gamma(i)
ElseIf i = NumberOfPoints - 1 Then
'last point
If EndThinner = True Then w = 8 Else w = getSegmentWidth(i)
a = 180

End If

SegmentPolys(i - 1) = New LineSegment.RectanglePolygon
' MsgBox(a.ToString)
With SegmentPolys(i - 1)
.b1X = Preva1X
.b1Y = Preva1Y
.b2X = Preva2X
.b2Y = Preva2Y
[COLOR="Red"]                .a1X = getPointX(i) + (PixDegreeX(w / 2) * Sin(a / 2))
.a1Y = getPointY(i) + (PixDegreeY(w / 2) * Sin(a / 2))
.a2X = getPointX(i) - (PixDegreeX(w / 2) * Sin(a / 2))
.a2Y = getPointY(i) - (PixDegreeY(w / 2) * Sin(a / 2))[/COLOR]
End With

Preva1X = SegmentPolys(i - 1).a1X
Preva1Y = SegmentPolys(i - 1).a1Y
Preva2X = SegmentPolys(i - 1).a2X
Preva2Y = SegmentPolys(i - 1).a2Y
Next
End Sub
```
The lines in red indicate the problematic formula's

Last edited: 9 Apr 2007
5. ### arnoAdministratorStaff MemberFSDevConf teamResource contributor

Joined:
28 May 2004
Messages:
23,991
Country:
Hi Sander,

I should have some old code doing something similar here, but at the moment I can't really find it. I used it in my Bumpy tool to convert roads (lines) into polygons.

6. ### SdC

Joined:
6 Mar 2007
Messages:
35
Country:
It would be great if you could dig it up Arno!

7. ### SdC

Joined:
6 Mar 2007
Messages:
35
Country:
Getting pretty close myself:

8. ### Luis_SáResource contributor

Joined:
16 Sep 2004
Messages:
316
Country:
Hello Sander,

VTP1! To say the truth I never used them. About what you said:

1) SBuilder was in fact programmed in VB6. Now I switched to VB2005 and I had to rewrite most of the graphics.

2) There is no problem for me in adding the facility to compile for CFS. The only problem is that I "wrote SB for myself" and I have few comments and, may be, I am the only person that can read the source code. Even for the purpose of helping you with the geometry, I had to look several times to what I have writen to understand it. So, we can keep in touch regarding to adding such funcionality to SB206 (VB6!). I can send you relevant parts of the source code if you think it is useful.

3) I am thinking in converting "lines with width" to polygons in SBuilder for FSX. The reason is that vectored lines with adjustable width are no longer supported. In my implementation (that I will start soon) I will have to check within the code the turns to the right and the turns to the left. When a new segment turns to the right I will use points 3 and 0 (see the drawing) on the left side and I have to solve what is upsetting you (eg to find a kind of intersection near points 0 and 1).

So I will try to explain the algorithm in my previous post. Say that a line starts with points P1, followed by P2, P3 ...

I start to get the vector P1_to_P2. This is vector U (coordinates UX and UY). Note that I normalize U so that it has a lenght of 1. Then I get a vector D with coordinates DX and DY. This vector is aligned with the segment P1 to P2 but the size is now equal to 1/2 of the width of the line.

The part:

PTS(0).X = PX0 - DY
PTS(0).Y = PY0 + DX
PTS(1).X = PX0 + DY
PTS(1).Y = PY0 - DX

is to find the points B and A (or PTS(0) and PTS(1)) as if I had created 2 vectors, DR and DL, from vector D.

May be you now can fully understand the code (if you have not already done so!)

Kind Regards,

Luis

9. ### Luis_SáResource contributor

Joined:
16 Sep 2004
Messages:
316
Country:
Hi again

Take notice that the points can not be very close or you will get something like the bottom line (widths of 5, 50 and 500, top to bottom)

Regards, Luis

10. ### SdC

Joined:
6 Mar 2007
Messages:
35
Country:
Hi Luis,
1) Excellent news!
2) No problem. I'll supply the assembly (dll) when I'm done, you can include with your project, and then you can copy the function you already have to "export SBX file" to send the filestream instead of to "filename" directly to the cf2autocoast.SBXInputfilestream, then call the routine cfs2autocoast.GenerateBGL and that's it! .NET rules! (it would be nice if you could please also allow your own LWM-mask save routine to create LWM1....saves us from having to de-compile-modify-recompile. This is something that would be too difficult for me to re-create)
3) I'm going to bed now I will look at the math again with a fresh mind another day! Thank you!
Regards,
-Sander.

Joined:
6 Mar 2007
Messages:
35
Country:
12. ### rhumbaflappyModeratorStaff MemberResource contributor

Joined:
2 Jun 2004
Messages:
3,020
Country:
Hi Sander.

Luis' original SBuilder used SCASM routines to make LWM and VTP2 polys and lines. SCASM never included the CFS2 Water ( LWM1 ) or VTP1... in fact the routines used were misnamed in SCASM, as I recall.

SBuilderX was written in VB.NET 2.0, and doesn't make LWM or VTP of any variety.

If the original Sbuilder was made to use BGLC, then it might be possible to include VTP1 and LWM1 code.

Dick

13. ### Luis_SáResource contributor

Joined:
16 Sep 2004
Messages:
316
Country:
Hello,

I saw your forum but could not register. To get (x4 y4) and (x5 y5) as
in the picture of one of your readers, take this (non Pitagoras!)
approach:

1) Say the line is defined by center points P1 P2 P3 P4 ... When you start
at point P1 and go to point P2 you have a 1/2 width to your left where you
find point (x4 y4) and to your right where you find (x5 y5).

2) I call D1 the unitary vector from P1 to P2; D2 the unitary vector from P2 to
P3; D3 from P3 to P4 and so on ...

3) I call DL1 the vector that has the size of 1/2 width of the line and that
is obtained from D1 by rotating it 90 to the left.

4) I call PL1 the point obtained by adding DL1 to P1 (point B in my
hand writen figure). PL2 will be point 0 in the 3rd column of my figure.
In general, point PLN (Point Left Nth) is the point that is 1/2 width
to the left of the line at point PN

5) By using a similar convention I name points PR1 PR2 PR3 ... the points
that are on the right hand side and that are at a distance of 1/2 width from
the center points P1 P2 P3 ...

6) PL1 PL2 PL3 ... and PR1 PR2 PR3 can be easily obtained from my previous
post.

7) To obtain (x4 y4) you need to get the intersection between the lines

PL1 + k1 D1 (where k1 is a scalar between -oo and +oo) and
PL2 + k2 D2 (whre K2 is also any scalar).

The intersecting point is determined by solving:

PL1 + k1 D1 = PL2 + k2 D2

Let me modify the names of (x4 y4) to PLL2 and (x5 y5) to PRR2 (2 because
they are near P2). Using .X and .Y for the coordinates you have
the equations

PL1.X + k1 D1.X = PL2.X + k2 D2.X
PL1.Y + k1 D1.Y = PL2.Y + k2 D2.Y

If the lines really intersect and if they are not colinear there will
be a unique solution for the real numbers k1 and k2. Once you get
them you can either get your (x4, y4) as :

x4 = PLL2.X = PL1.X + k1 D1.X
y4 = PLL2.Y = PL1.Y + k1 D1.Y

or as:

x4 = PLL2.X = PL2.X + k2 D1.X
y4 = PLL2.Y = PL2.Y + k2 D1.Y

8) Point (x5 y5) is determined in an analogous way.

Regards, Luis

14. ### José

Joined:
10 Nov 2006
Messages:
490
Country:
Only some math

Hi,

This is not programing sugestion, but another math approach for the problem.

Knowing the points (x1,y1), (x2,y2) for Line1, one can write its slope, as

m1 = (y2 - y1)/(x2 - x1)

The same for Line2:

m2 = (y3 - y2)/(x3 - x2)

Those lines make an angle, whose bisector is the Line3 (not in your drawing)
that contains the known intersection point (x2,y2) and its slope m3 could be
find as a function from m1 and m2 slopes.

The two searched points are over the Line3 (bisector), at a distance (d)
from point (x2,y2), calculated by:

d = (w/2)/sin(Teta/2)

where Teta is the angle made by the lines 1 and 2, that could be known from
their calculated slopes and w is the value given (distance between lines 1 and 2).

As the solution for the distance is a second degree math expression, it returns
the two searched points.

I wait this could be implemented in programing easily.

Regards,

José

Last edited: 10 Apr 2007
15. ### SdC

Joined:
6 Mar 2007
Messages:
35
Country:
Thank you all for the information and suggestions. I got it working (more or less) last night. The final algorithm is a "Frankenstein" from all suggested solutions