Browse Source

Splitting algorithmus für polygone hinzugefügt

kolja 6 years ago
parent
commit
b397210f0c
3 changed files with 272 additions and 2 deletions
  1. 2 0
      M2Datei.cpp
  2. 250 2
      Model2D.cpp
  3. 20 0
      Model2D.h

+ 2 - 0
M2Datei.cpp

@@ -319,6 +319,7 @@ Model2DData *M2Datei::ladeModel( const char *name ) const
         char options = 0;
         d.lese( &options, 1 );
         Polygon2D polygon;
+        polygon.schwerpunkt = new Vertex( 0, 0 );
         polygon.transparent = ( options | 4 ) == options;
         polygon.name = new Text();
         if( ( options | 2 ) == options )
@@ -350,6 +351,7 @@ Model2DData *M2Datei::ladeModel( const char *name ) const
             Vertex p;
             d.lese( (char*)&p.x, 4 );
             d.lese( (char*)&p.y, 4 );
+            *polygon.schwerpunkt += p * (float)( 1.0 / vAnz );
             polygon.vertex->add( p );
             if( ( options | 1 ) == options ) // wenn textur
             {

+ 250 - 2
Model2D.cpp

@@ -32,6 +32,8 @@ Model2DData::~Model2DData()
                 polygons->get( i ).tKordinaten->release();
             if( polygons->get( i ).vertex )
                 polygons->get( i ).vertex->release();
+            if( polygons->get( i ).schwerpunkt )
+                delete polygons->get( i ).schwerpunkt;
         }
         polygons = polygons->release();
     }
@@ -379,6 +381,8 @@ void Model2DData::removeModell() // setzt die Vertex daten zur
                 polygons->get( i ).tKordinaten->release();
             if( polygons->get( i ).vertex )
                 polygons->get( i ).vertex->release();
+            if( polygons->get( i ).schwerpunkt )
+                delete polygons->get( i ).schwerpunkt;
         }
         polygons = polygons->release();
     }
@@ -389,6 +393,250 @@ void Model2DData::removeModell() // setzt die Vertex daten zur
     maxP = Punkt( 0, 0 );
 }
 
+bool Model2DData::calcHitPoint( Vertex pos, Vertex dir, char *polygonName, Vertex &hitpoint, Vertex &moveSpeed, float &rotSpeed ) const
+{
+    bool ret = 0;
+    for( auto *polygon = &polygons->getArray(); polygon && polygon->set; polygon = polygon->next )
+    {
+        if( polygon->var.name->istGleich( polygonName ) )
+        {
+            int anz = polygon->var.vertex->getEintragAnzahl();
+            for( int i = 0; i < anz; i++ )
+            {
+                Vertex a = polygon->var.vertex->get( i );
+                Vertex b = polygon->var.vertex->get( ( i + 1 ) % anz );
+                b -= a;
+                float offset = 0;
+                if( dir.y != 0 && dir.x != 0 )
+                    offset = ( ( a.y - pos.y ) / dir.y - ( a.x - pos.x ) / dir.x ) / ( b.x / dir.x - b.y / dir.y ); // solve hitpoint equasion
+                else if( dir.y == 0 )
+                    offset = ( pos.y - a.y ) / b.y;
+                else if( dir.x == 0 )
+                    offset = ( pos.x - a.x ) / b.x;
+                Vertex point = a + ( b * offset );
+                if( offset >= 0 && offset <= 1 )
+                {
+                    if( !ret || ( hitpoint - pos ).getLengthSq() > ( point - pos ).getLengthSq() )
+                    {
+                        Vertex normal = b.CW90().normalize();
+                        Vertex kNorm = Vertex( dir ).normalize();
+                        moveSpeed = normal * ( normal * kNorm ) * dir.getLengthSq();
+                        normal = ( point - *polygon->var.schwerpunkt ).CW90().normalize();
+                        Vertex rotKraft = normal * ( normal * kNorm ) * dir.getLength();
+                        rotSpeed = ( ( rotKraft.getLength() * ( point - *polygon->var.schwerpunkt ).getLength() ) / 180.f ) * 3.14f;
+                        if( point.x >= polygon->var.schwerpunkt->x )
+                        {
+                            if( point.y >= polygon->var.schwerpunkt->y && rotKraft.x > 0 && rotKraft.y < 0 )
+                                rotSpeed = -rotSpeed;
+                            if( point.y < polygon->var.schwerpunkt->y && rotKraft.x < 0 && rotKraft.y < 0 )
+                                rotSpeed = -rotSpeed;
+                        }
+                        else
+                        {
+                            if( point.y >= polygon->var.schwerpunkt->y && rotKraft.x > 0 && rotKraft.y > 0 )
+                                rotSpeed = -rotSpeed;
+                            if( point.y < polygon->var.schwerpunkt->y && rotKraft.x < 0 && rotKraft.y > 0 )
+                                rotSpeed = -rotSpeed;
+                        }
+                        hitpoint = point;
+                    }
+                    ret = 1;
+                }
+            }
+        }
+    }
+    return ret;
+}
+
+bool Model2DData::split( Vertex pos, Vertex dir, char *polygonName, Polygon2D &partA, Polygon2D &partB, Punkt &posA, Punkt &posB, std::function< double() > random ) const
+{
+    Vertex originalDir = dir;
+    bool ret = 0;
+    int num = 0;
+    for( auto *polygon = &polygons->getArray(); polygon && polygon->set; polygon = polygon->next, num++ )
+    {
+        if( polygon->var.name->istGleich( polygonName ) )
+        {
+            while( istPunktInnen( pos, num ) )
+            {
+                pos -= dir;
+            }
+            int anz = polygon->var.vertex->getEintragAnzahl();
+            Vertex startPoint;
+            Vertex texturSP;
+            int leftI = 0;
+            int rightI = 0;
+            Vertex txtChpPix( 0, 0 );
+            for( int i = 0; i < anz; i++ )
+            {
+                Vertex a = polygon->var.vertex->get( i );
+                Vertex b = polygon->var.vertex->get( ( i + 1 ) % anz );
+                b -= a;
+                if( ( txtChpPix.x == 0 || txtChpPix.y == 0 ) && b.x != 0 && b.y != 0 )
+                {
+                    Vertex ta = polygon->var.tKordinaten->get( i );
+                    Vertex tb = polygon->var.tKordinaten->get( ( i + 1 ) % anz );
+                    tb -= ta;
+                    txtChpPix = Vertex( tb.x / b.x, tb.y / b.y );
+                }
+                float offset = 0;
+                if( dir.y != 0 && dir.x != 0 )
+                    offset = ( ( a.y - pos.y ) / dir.y - ( a.x - pos.x ) / dir.x ) / ( b.x / dir.x - b.y / dir.y ); // solve hitpoint equasion
+                else if( dir.y == 0 )
+                    offset = ( pos.y - a.y ) / b.y;
+                else if( dir.x == 0 )
+                    offset = ( pos.x - a.x ) / b.x;
+                Vertex point = a + ( b * offset );
+                if( offset >= 0 && offset <= 1 )
+                {
+                    if( !ret || ( startPoint - pos ).getLengthSq() > ( point - pos ).getLengthSq() )
+                    {
+                        leftI = i;
+                        rightI = ( i + 1 ) % anz;
+                        startPoint = point;
+                        texturSP = polygon->var.tKordinaten->get( i ) + ( polygon->var.tKordinaten->get( ( i + 1 ) % anz ) - polygon->var.tKordinaten->get( i ) ) * offset;
+                    }
+                    ret = 1;
+                }
+            }
+            if( ret )
+            {
+                partA.transparent = polygon->var.transparent;
+                partA.schwerpunkt = new Vertex( 0, 0 );
+                partA.tKordinaten = new Array< Vertex >();
+                partA.name = new Text( polygon->var.name->getText() );
+                partA.vertex = new Array< Vertex >();
+                partB.transparent = polygon->var.transparent;
+                partB.schwerpunkt = new Vertex( 0, 0 );
+                partB.tKordinaten = new Array< Vertex >();
+                partB.name = new Text( polygon->var.name->getText() );
+                partB.vertex = new Array< Vertex >();
+                *partA.schwerpunkt += startPoint;
+                *partB.schwerpunkt += startPoint;
+                partA.vertex->add( startPoint );
+                partB.vertex->add( startPoint );
+                partA.tKordinaten->add( texturSP );
+                partB.tKordinaten->add( texturSP );
+                int leftIE = 0;
+                int rightIE = 0;
+                while( 1 )
+                {
+                    pos = startPoint;
+                    Vertex next = startPoint + dir;
+                    Vertex nextT = texturSP + Vertex( dir.x * txtChpPix.x, dir.y * txtChpPix.y );
+                    ret = 0;
+                    bool needOne = !istPunktInnen( next );
+                    int bestI = -1;
+                    float bo1 = 1000;
+                    float bo2 = 1000;
+                    for( int i = 0; i < anz; i++ )
+                    {
+                        if( i == leftI )
+                            continue;
+                        Vertex a = polygon->var.vertex->get( i );
+                        Vertex b = polygon->var.vertex->get( ( i + 1 ) % anz );
+                        b -= a;
+                        float offset1 = 0;
+                        if( dir.y != 0 && dir.x != 0 )
+                            offset1 = ( ( a.y - pos.y ) / dir.y - ( a.x - pos.x ) / dir.x ) / ( b.x / dir.x - b.y / dir.y ); // solve hitpoint equasion
+                        else if( dir.y == 0 )
+                            offset1 = ( pos.y - a.y ) / b.y;
+                        else if( dir.x == 0 )
+                            offset1 = ( pos.x - a.x ) / b.x;
+                        Vertex point = a + ( b * offset1 );
+                        float offset2 = 0;
+                        if( dir.x != 0 )
+                            offset2 = ( point.x - pos.x ) / dir.x;
+                        else
+                            offset2 = ( point.y - pos.y ) / dir.y;
+                        if( needOne && min( abs( bo1 ), abs( bo1 - 1 ) ) + min( abs( bo2 ), bo2 - 1 ) > min( abs( offset1 ), abs( offset1 - 1 ) ) + min( abs( offset2 ), abs( offset2 - 1 ) ) )
+                        {
+                            bo1 = offset1;
+                            bo2 = offset2;
+                            bestI = i;
+                        }
+                        if( offset1 >= 0 && offset1 <= 1 && offset2 >= 0 && offset2 <= 1 )
+                        {
+                            if( !ret || ( startPoint - pos ).getLengthSq() > ( point - pos ).getLengthSq() )
+                            {
+                                leftIE = i;
+                                rightIE = ( i + 1 ) % anz;
+                                startPoint = point;
+                                texturSP = polygon->var.tKordinaten->get( i ) + ( polygon->var.tKordinaten->get( ( i + 1 ) % anz ) - polygon->var.tKordinaten->get( i ) ) * offset1;
+                            }
+                            ret = 1;
+                        }
+                    }
+                    if( needOne && !ret )
+                    {
+                        Vertex a = polygon->var.vertex->get( bestI );
+                        Vertex b = polygon->var.vertex->get( ( bestI + 1 ) % anz );
+                        b -= a;
+                        leftIE = bestI;
+                        rightIE = ( bestI + 1 ) % anz;
+                        startPoint = a + ( b * bo1 );
+                        texturSP = polygon->var.tKordinaten->get( bestI ) + ( polygon->var.tKordinaten->get( ( bestI + 1 ) % anz ) - polygon->var.tKordinaten->get( bestI ) ) * bo1;
+                        ret = 1;
+                    }
+                    if( ret )
+                        break;
+                    *partA.schwerpunkt += next;
+                    *partB.schwerpunkt += next;
+                    partA.vertex->add( next );
+                    partB.vertex->add( next );
+                    partA.tKordinaten->add( nextT );
+                    partB.tKordinaten->add( nextT );
+                    startPoint = next;
+                    texturSP = nextT;
+                    dir = originalDir.rotation( (float)(random() - 0.5) );
+                }
+                *partA.schwerpunkt += startPoint;
+                *partB.schwerpunkt += startPoint;
+                partA.vertex->add( startPoint );
+                partB.vertex->add( startPoint );
+                partA.tKordinaten->add( texturSP );
+                partB.tKordinaten->add( texturSP );
+                for( int i = rightIE; i != leftI; i++ )
+                {
+                    i = i % anz;
+                    if( i == leftI )
+                        break;
+                    *partA.schwerpunkt += polygon->var.vertex->get( i );
+                    partA.vertex->add( polygon->var.vertex->get( i ) );
+                    partA.tKordinaten->add( polygon->var.tKordinaten->get( i ) );
+                }
+                *partA.schwerpunkt += polygon->var.vertex->get( leftI );
+                partA.vertex->add( polygon->var.vertex->get( leftI ) );
+                partA.tKordinaten->add( polygon->var.tKordinaten->get( leftI ) );
+                for( int i = leftIE; i != rightI; i-- )
+                {
+                    if( i < 0 )
+                        i += anz;
+                    if( i == rightI )
+                        break;
+                    *partB.schwerpunkt += polygon->var.vertex->get( i );
+                    partB.vertex->add( polygon->var.vertex->get( i ) );
+                    partB.tKordinaten->add( polygon->var.tKordinaten->get( i ) );
+                }
+                *partB.schwerpunkt += polygon->var.vertex->get( rightI );
+                partB.vertex->add( polygon->var.vertex->get( rightI ) );
+                partB.tKordinaten->add( polygon->var.tKordinaten->get( rightI ) );
+                *partA.schwerpunkt /= (float)partA.vertex->getEintragAnzahl();
+                *partB.schwerpunkt /= (float)partB.vertex->getEintragAnzahl();
+                posA = (Punkt)*partA.schwerpunkt;
+                posB = (Punkt)*partB.schwerpunkt;
+                for( int i = 0; i < partA.vertex->getEintragAnzahl(); i++ )
+                    partA.vertex->set( partA.vertex->get( i ) - *partA.schwerpunkt, i );
+                for( int i = 0; i < partB.vertex->getEintragAnzahl(); i++ )
+                    partB.vertex->set( partB.vertex->get( i ) - *partB.schwerpunkt, i );
+                *partA.schwerpunkt = Vertex( 0, 0 );
+                *partB.schwerpunkt = Vertex( 0, 0 );
+            }
+        }
+    }
+    return ret;
+}
+
 // Reference Counting
 Model2DData *Model2DData::getThis()
 {
@@ -424,7 +672,7 @@ Model2D::~Model2D()
 {
     if( rData )
         rData->release();
-	textur->release();
+    textur->release();
 }
 
 // nicht constant
@@ -518,7 +766,7 @@ void Model2D::render( Bild &zRObj )
 {
     if( !rData || hatStyleNicht( Model2D::Style::Sichtbar ) || !rData->polygons )
         return;
-	Zeichnung::render( zRObj );
+    Zeichnung::render( zRObj );
     int num = 0;
     for( auto *p = &rData->vListen->getArray(); p && p->set; p = p->next, num++ )
     {

+ 20 - 0
Model2D.h

@@ -20,6 +20,7 @@ namespace Framework
         Text *name;
         Array< Vertex > *vertex;
         Array< Vertex > *tKordinaten;
+        Vertex *schwerpunkt;
     };
 
     // Die Daten für ein 2D Model
@@ -53,6 +54,25 @@ namespace Framework
         __declspec( dllexport ) bool erstelleModell( Array< Polygon2D > *polygons );
         // Löscht die erstellten Dreiecklisten und die Eckpunkte
         __declspec( dllexport ) void removeModell();
+        // gibt das polygon mit einem bestimmten namen zurück
+        //  pos: Der Stützvektor der Linie
+        //  dir: Der richtungsvektor der Linie
+        //  polygonName: Der Name des polygons mit dem der schnittpunkt berechnet werden soll
+        //  hitPoint: eine referenz auf die variable in dem der schnittpunkt gespeichert werden soll
+        //  moveSpeed: die aus der Krafteinwirkung resultierende bewegungsgeschwindigkeit
+        //  rotSpeed: die aus der Krafteinwirkung resultierende drehgeschwindigkeit
+        //  return: 1, fals ein Schnittpunkt existiert
+        __declspec( dllexport ) bool calcHitPoint( Vertex pos, Vertex dir, char *polygonName, Vertex &hitpoint, Vertex &moveSpeed, float &rotSpeed ) const;
+        // Teil ein bestimmtes polygon in zwei teile
+        //  pos: Startposition des risses
+        //  dir: Startrichtung des risses
+        //  polygonName: der Name des Polygons
+        //  partA: ein Zeiger auf ein Model2DData objekt, in dem die eine hälfte gespeichert werden soll (ausgabe)
+        //  partB: ein Zeiger auf ein Model2DData objekt, in dem die andere hälfte gespeichert werden soll (ausgabe)
+        //  posA: die Position des einen neuen Polygons (ausgabe)
+        //  posB: die Position des anderen neuen Polygons (ausgabe)
+        //  random: eine funktion die zufällige werte zurückgibt
+        __declspec( dllexport ) bool split( Vertex pos, Vertex dir, char *polygonName, Polygon2D &partA, Polygon2D &partB, Punkt &posA, Punkt &posB, std::function< double() > random ) const;
         // Erhöht den Reference Counting Zähler.
         //  return: this.
         __declspec( dllexport ) Model2DData *getThis();