An die Mathe Profis: Schnitt zweier Flächen?

  • Hi

    Ich schwitze schon seit graumer Zeit an diesem Problem und es ist mir sogar zum Erklären kompliziert genug ;(

    Ich will folgendes erreichen:
    Ein Mikrofon hat, abhängig von seiner Richtcharakteristik, in jedem Winkel verschiedene Reichweiten.
    z.B: Nierenform: von vorne kommen 100% ins Mikro, von hinten 0%
    Ein Kugelmikro bekommt von rundherum immer 100% Schall

    Nun will ich berechnen, wo bei 2 oder mehr aufgestellten Mikros die Trennlinie verläuft, also wo beide Mikros denselben Schallpegel empfangen

    Zum besseren Verständnis bitte mal dieses Script ausführen:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $PI = ATan(1) * 4
    Global Const $Deg2Rad = $PI / 180
    Global Const $Rad2Deg = 180 / $PI

    [/autoit] [autoit][/autoit] [autoit]

    Global $iWidth = 800;@DesktopWidth
    Global $iHeight = 580;@DesktopHeight

    [/autoit] [autoit][/autoit] [autoit]

    Opt("MustDeclareVars", 1)
    Opt("GUIOnEventMode", 1)
    Opt("MouseCoordMode", 2)

    [/autoit] [autoit][/autoit] [autoit]

    Global $iWidth = 800;@DesktopWidth
    Global $iHeight = 580;@DesktopHeight

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup()
    Global $hGui = GUICreate("Test", $iWidth, $iHeight)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
    Global $hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
    Global $hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
    _GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)

    [/autoit] [autoit][/autoit] [autoit]

    Global $hPen = _GDIPlus_PenCreate(0xFF0088FF, 1)
    Global $hBrush = _GDIPlus_BrushCreateSolid(0xFF00FF00)

    [/autoit] [autoit][/autoit] [autoit]

    GUIRegisterMsg($WM_PAINT, "WM_PAINT")
    GUISetState(@SW_SHOW, $hGui)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While 1
    _Draw()
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _CalcPoints($fX, $fY, $fW, $fH, $fPolar, $fAngle)
    Local $fX1, $fY1, $fX2, $fY2, $fS1, $fS2, $fA, $fTemp
    Local $aPoints[73][2] = [[72]]
    For $i = 0 To 71
    $fA = $i * 5 * $Deg2Rad ; 0-355 Grad
    $fS1 = 1 + 0 * Cos($fA) ; Kugelform
    $fS2 = 0.5 + 0.5 * Cos($fA) ; Nierenform
    $fTemp = Abs(($fS1 * (1 - $fPolar)) + ($fS2 * $fPolar)) / 2 ; Mischung aus Kugel und Niere

    [/autoit] [autoit][/autoit] [autoit]

    $fX1 = $fTemp * Cos($fA) * $fW ; Länge
    $fY1 = $fTemp * Sin($fA) * $fH ; Breite

    [/autoit] [autoit][/autoit] [autoit]

    $fX2 = $fX1 * Cos($fAngle * $Deg2Rad) - $fY1 * Sin($fAngle * $Deg2Rad) ; X um Winkel drehen
    $fY2 = $fX1 * Sin($fAngle * $Deg2Rad) + $fY1 * Cos($fAngle * $Deg2Rad) ; Y um Winkel drehen

    [/autoit] [autoit][/autoit] [autoit]

    $aPoints[$i + 1][0] = $fX2 + $fX ; Ergebnis + X Mittelpunkt
    $aPoints[$i + 1][1] = $fY2 + $fY ; Ergebnis + Y Mittelpunkt
    Next
    Return $aPoints
    EndFunc ;==>_CalcPoints

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _Draw()
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)

    [/autoit] [autoit][/autoit] [autoit]

    Local $aPnt1 = _CalcPoints(200, 200, 300, 150, 1, 45); Mittelpunkt 200,200; Länge 300; Breite 150; NierenForm; Winkel 45 Grad
    Local $aPnt2 = _CalcPoints(300, 200, 300, 150, 1, 90); Mittelpunkt 300,200; Länge 300; Breite 150; NierenForm; Winkel 90 Grad

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsDrawClosedCurve($hGfxBuffer, $aPnt1, $hPen)
    _GDIPlus_GraphicsDrawClosedCurve($hGfxBuffer, $aPnt2, $hPen)

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsFillRect($hGfxBuffer, 200 - 2, 200 - 2, 4, 4, $hBrush)
    _GDIPlus_GraphicsFillRect($hGfxBuffer, 300 - 2, 200 - 2, 4, 4, $hBrush)

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    EndFunc ;==>_Draw

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func WM_PAINT($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_PAINT

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGfxBuffer)
    _GDIPlus_BitmapDispose($hBmpBuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>_Exit

    [/autoit]

    Hier wird 360° um den Mitteplunkt die Formel in _CalcPoints angewandt, um die Richtcharakteristik zu berechnen

    -------------------------

    Erreichen will ich nun wie es folgendes Script zeigt:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt("MustDeclareVars", 1)
    Opt("GUIOnEventMode", 1)
    Opt("MouseCoordMode", 2)

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $PI = ATan(1) * 4
    Global Const $Deg2Rad = $PI / 180
    Global Const $Rad2Deg = 180 / $PI

    [/autoit] [autoit][/autoit] [autoit]

    Global $iWidth = 800;@DesktopWidth
    Global $iHeight = 580;@DesktopHeight

    [/autoit] [autoit][/autoit] [autoit]

    Global $aMic[33][20] = [[3]]
    $aMic[1][0] = 100
    $aMic[1][1] = 100
    $aMic[1][2] = 45
    $aMic[1][3] = 1
    $aMic[1][4] = 1.4
    $aMic[1][5] = 1

    [/autoit] [autoit][/autoit] [autoit]

    $aMic[2][0] = 600
    $aMic[2][1] = 50
    $aMic[2][2] = 135
    $aMic[2][3] = 1
    $aMic[2][4] = 1.4
    $aMic[2][5] = 1

    [/autoit] [autoit][/autoit] [autoit]

    $aMic[3][0] = 400
    $aMic[3][1] = 500
    $aMic[3][2] = 270
    $aMic[3][3] = 1
    $aMic[3][4] = 1.4
    $aMic[3][5] = 1

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup()
    Global $hGui = GUICreate("Test", $iWidth, $iHeight)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
    Global $hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
    Global $hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
    _GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)

    [/autoit] [autoit][/autoit] [autoit]

    Global $hPen = _GDIPlus_PenCreate(0xFF00FF00, 1)

    [/autoit] [autoit][/autoit] [autoit]

    GUIRegisterMsg($WM_PAINT, "WM_PAINT")
    GUISetState(@SW_SHOW, $hGui)

    [/autoit] [autoit][/autoit] [autoit]

    _Draw()

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _Draw()

    [/autoit] [autoit][/autoit] [autoit]

    Local $fX, $fY, $fScale
    Local $bAdd

    [/autoit] [autoit][/autoit] [autoit]

    Local $aPath[$aMic[0][0] + 1][3]

    [/autoit] [autoit][/autoit] [autoit]

    Local $aResult
    For $i = 1 To $aMic[0][0]
    $aResult = DllCall($ghGDIPDll, "uint", "GdipCreatePath", "int", 0, "int*", 0)
    $aPath[$i][0] = $aResult[2]
    $aPath[$i][1] = DllStructCreate("float[142];")
    $aPath[$i][2] = DllStructGetPtr($aPath[$i][1])
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $s = 350 To 500 Step 2
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)
    For $i = 1 To $aMic[0][0]
    For $j = 0 To 70
    $fScale = _CalcPolarScale($aMic[$i][2], $j * 5, $aMic[$i][3], $aMic[$i][4], $aMic[$i][5])
    $fX = Cos($j * 5 * $Deg2Rad) * $s * $fScale + $aMic[$i][0]
    $fY = Sin($j * 5 * $Deg2Rad) * $s * $fScale + $aMic[$i][1]
    $bAdd = True
    For $k = 1 To $aMic[0][0]
    $aResult = DllCall($ghGDIPDll, "uint", "GdipIsVisiblePathPoint", "hwnd", $aPath[$k][0], "float", $fX, "float", $fY, "hwnd", 0, "int*", 0)
    If $aResult[5] Then
    $bAdd = False
    ExitLoop
    EndIf
    Next
    If $bAdd Then
    DllStructSetData($aPath[$i][1], 1, $fX, $j * 2 + 1)
    DllStructSetData($aPath[$i][1], 1, $fY, $j * 2 + 2)
    EndIf
    Next
    DllCall($ghGDIPDll, "uint", "GdipResetPath", "hwnd", $aPath[$i][0])
    DllCall($ghGDIPDll, "uint", "GdipAddPathClosedCurve2", "hwnd", $aPath[$i][0], "ptr", $aPath[$i][2], "int", 71, "float", 0.4)
    DllCall($ghGDIPDll, "uint", "GdipDrawPath", "hwnd", $hGfxBuffer, "hwnd", $hPen, "hwnd", $aPath[$i][0])
    Next
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To $aMic[0][0]
    DllCall($ghGDIPDll, "uint", "GdipDeletePath", "hwnd", $aPath[$i][0])
    Next

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    EndFunc ;==>_Draw

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _CalcPolarScale($fA1, $fA2, $fP, $fSX, $fSY)
    $fA2 = ($fA2 - $fA1) * $Deg2Rad

    [/autoit] [autoit][/autoit] [autoit]

    Local $fX = Cos($fA2) / $fSX
    Local $fY = Sin($fA2) / $fSY

    [/autoit] [autoit][/autoit] [autoit]

    Local $fA = ATan($fY / $fX)
    If $fX < 0 Then $fA = $PI + $fA
    If $fX >= 0 And $fY < 0 Then $fA = $PI * 2 + $fA

    [/autoit] [autoit][/autoit] [autoit]

    Local $fS1 = 1 + 0 * Cos($fA)
    Local $fS2 = 0.5 + 0.5 * Cos($fA)

    [/autoit] [autoit][/autoit] [autoit]

    Local $fT = Abs($fS1 * (1 - $fP) + $fS2 * $fP) / 2

    [/autoit] [autoit][/autoit] [autoit]

    Local $fX1 = $fT * Cos($fA) * $fSX
    Local $fY1 = $fT * Sin($fA) * $fSY

    [/autoit] [autoit][/autoit] [autoit]

    Local $fRet = Sqrt($fX1 ^ 2 + $fY1 ^ 2)
    If $fRet < 0.01 Then $fRet = 0.01
    Return $fRet
    EndFunc ;==>_CalcPolarScale

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func WM_PAINT($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_PAINT

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGfxBuffer)
    _GDIPlus_BitmapDispose($hBmpBuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>_Exit

    [/autoit]


    Grob gesagt hab ich eine Formel, die um jeden Winkel um die eigene Achse verschienden Ergebnisse liefert und ich will herausfinden, wo die Grenze zwischen mehreren Mittelpunkten liegt...

    Kann man das überhaupt berechnen, oder ist mein zweites Script (immer Bereich vergrößern und überprüfen, ob ein Punkt schon im "fremden" Bereich liegt) schon die beste Lösung?!

    Ich hoffe, ich hab mein Anliegen gut genug erklärt, denn ich bin am Ende meines Lateins :D

    Danke


  • z.B: Nierenform: von vorne kommen 100% ins Mikro, von hinten 0%


    Nun will ich berechnen, wo bei 2 oder mehr aufgestellten Mikros die Trennlinie verläuft, also wo beide Mikros denselben Schallpegel empfangen


    Mal eine Freifeldmessung angenommen ist der Schallpegel doch auch abhängig von der Position der Schallquelle.
    Bei der angenommen Nierenform (gleich ausgerichtet) bzw. beim Kugelmikro wäre ein möglicher Punkt für die Schallquelle genau der Mittelpunkt zwischen Mikro1 und Mikro2.
    Alle weiteren Punkte liegen auf einer Geraden, die genau im rechten Winkel zur Geraden durch Mikro1 und Mirko2 verläuft.

    Würde sich auch in Vektoren ausdrücken lassen. Per autoit kann ich dir das aber mangels Können nicht skripten.

    Einmal editiert, zuletzt von nuts (29. Juni 2011 um 00:42)

  • Mal eine Freifeldmessung angenommen ist der Schallpegel doch auch abhängig von der Position der Schallquelle.
    Bei der angenommen Nierenform (gleich ausgerichtet) bzw. beim Kugelmikro wäre ein möglicher Punkt für die Schallquelle genau der Mittelpunkt zwischen Mikro1 und Mikro2.
    Alle weiteren Punkte liegen auf einer Geraden, die genau im rechten Winkel zur Geraden durch Mikro1 und Mirko2 verläuft.

    Würde sich auch in Vektoren ausdrücken lassen. Per autoit kann ich dir das aber mangels Können nicht skripten.

    Ich hab das vielleicht etwas umständlich erklärt...
    Ich will eben genau den Punkt der Schallquelle ermitteln, von dem aus die Mikros denselben Schallpegel bekommen

    Mit Vektoren stell ich mir das in etwa so vor:autoit.de/wcf/attachment/13640/
    Das Verhältnis der roten zu den blauen Linien soll gleich sein, so ergibt sich dann die grüne Linie
    Und hier fehlt mir nun komplett der Ansatz, wie ich das umsetzen soll...

    E

  • Mit einem Kreismikro nimmst du den Mittelpunkt zwischen Mikro1 und Mikro 2 und konstruierst eine Ebene drumrum.


    Beispiel:

    M1=(0|1|0)
    M2=(0|-1|0)

    => S(0|0|0)

    Die Ebenengleichung der Schallquellen:
    Y=(0|0|0) + r* (1|0|0) + s* (0|0|1)

    Die Bewegungsvektoren der Ebene liegen senkrecht zum Vektor M1M2 (Normalenvektor).


    Bei der Nierenform ist das ungleich komplizierter.
    Ist deine Lösung ist für den Schallpegel überhaupt zielführend?
    Muss man nicht den ersten Schnittpunkt der Flächen nehmen und darum eine Gerade konstruieren?

  • Ich bin mir nicht sicher ob Dir das weiterhilft, aber eigentlich müsste man, wenn ich das Problem richtig verstanden habe, nur die "Einzugsbereiche" der beiden Mikrofone als Kugeln darstellen.
    Die Schnittmenge (http://de.wikipedia.org/wiki/Mengenlehre#Schnittmenge) der beiden Kreise bzw. Kugeln beinhaltet dann Punkte (in diesem Fall Signale), die beide Mikrofone gleich-laut empfangen (vermutlich die Punkte, die auf der die Schnittpunkte verbindenden Linie liegen).