3 Stimmen

Über: Drehen und Einpassen von Rechtecken

Nach harter Arbeit schaltet mein Gehirn den Dienst ab (es ist 23:40 Uhr in der Türkei)

Ich mache einen Rotationsjob..:

Variablen:

_cx = horizontal center of rect
_cy = vertical center of rect
_cos = cos value of current angle
_sin = sin value of current angle

to rotating any point in this rect :

function getx(x, y)
{
      return _cx + _cos * (x - _cx) - _sin * (y - _cy);
}
function gety(x, y)
{
      return _cy + _sin * (x - _cx) + _cos * (y - _cy);
}

Ich versuche, die Größe des gegebenen Rechtecks vor dem Rotationsprozess auf die maximale Größe zu ändern, die in die ursprünglichen Grenzen passt. wie könnte ich das tun?

danke im Voraus

EDIT: Die Lösung von Igor Krivokon

Das Problem wurde von Igor Krivokon gelöst, und hier ist die modifizierte Version dieser Lösung, die für jeden Winkelwert funktioniert

var h1:Number, h2:Number, hh:Number, ww:Number,
    degt:Number, d2r:Number, r2d:Number, deg:Number,
    sint:Number, cost:Number;
//@angle = given angle in radians
//@r is source/target rectangle
//@d2r is static PI / 180 constant for degree -> radian conversation
//@r2d is static 180 / PI constant for radian -> degree conversation
d2r = 0.017453292519943295769236907683141;
r2d = 57.295779513082320876798154814105;
deg = Math.abs(angle * r2d) % 360;
if(deg < 91)
{
    degt = angle;
}else if(deg < 181){
    degt = (180 - deg) * d2r;
}else if(deg < 271){
    degt = (deg - 180) * d2r;
}else{
    degt = (360 - deg) * d2r;
}

sint = Math.sin(degt);
cost = Math.cos(degt);

h1 = r.height * r.height / (r.width * sint + r.height * cost);
h2 = r.height * r.width / (r.width * cost + r.height * sint);
hh = Math.min(h1, h2);
ww = hh * r.width / r.height;
r.x = (r.width - ww) * .5;
r.y = (r.height - hh) * .5;
r.height = hh;
r.width = ww;

Danke

0 Stimmen

Kurze Erläuterung: Sie haben ein Rechteck R und möchten es um seinen Mittelpunkt drehen und skalieren, um ein Rechteck R' zu erzeugen, das einen möglichst großen Teil der Fläche in R einnimmt?

0 Stimmen

Hallo Tolgahan, Sie können diese Frage nicht beantworten, ohne zumindest das Verhältnis zwischen den Seiten des Rechtecks zu kennen.

0 Stimmen

Ja, und ich möchte R' vor dem Drehen haben

5voto

Igor Krivokon Punkte 9967

Wenn die ursprünglichen Größen h und w waren und Sie sie um den Winkel phi gedreht haben, versuchen Sie, die neue Höhe zu berechnen

h1 = h*h / (w*sin(phi) + h*cos(phi))

und

h2 = h*w / (w*cos(phi) + h*sin(phi))

Wählen Sie die kleinste der beiden Höhen h1 und h2, nämlich h'.

Dann, natürlich, neue Breite w' = h' * w / h .

Bitte probieren Sie es aus - ich hatte keine Zeit, meine Berechnungen zu überprüfen :)

0 Stimmen

Ihre Formel ist in Ordnung, wenn der Winkel a => 0 >= a <= 90 ist, jetzt versuche ich andere Variationen dieses Weges

0 Stimmen

Ich weiß nicht wie, aber das funktioniert super gut. Danke!

0voto

ryansstack Punkte 1306

Teilen Sie das Rechteck in 4 kleinere Rechtecke. Schneiden Sie diese diagonal in zwei Hälften (vor der Drehung, von einer Ecke zu einem Mittelpunkt) und Sie haben 8 Dreiecke. Du brauchst nur 4 davon. Nach der Drehung ragen die Hypotenusen dieser Dreiecke aus dem ursprünglichen Begrenzungsrahmen heraus.

Bestimmen Sie eine Formel für die Hypotenuse (Sie haben den ursprünglichen Winkel, 45, -45, 135, -135, und den Ausgangspunkt, also mx+b), transformieren Sie diese Linien (ändern Sie ihre Steigungen durch Hinzufügen der Drehung), schneiden Sie diese Linien mit den Begrenzungswänden (y = 0, y = w, x = 0, x = h, Abstandsformel, Test auf unendliche Fälle) und finden Sie heraus, welche Hypotenuse am kürzesten ist (Mitte zu Wand, an der Ecke). Da alle Hypotenusen zu Beginn gleich lang waren, müssen Sie nur die Größe aller Hypotenusen auf diesen neuen Wert anpassen, und schon haben Sie Ihr neues Rechteck.

Mache ich es richtig?

0 Stimmen

Ich schätze, es sollte einen einfacheren Weg geben :)

0 Stimmen

Ich kann mir nicht vorstellen, wie das geht :) obwohl ich es auch anders hätte formulieren können: "Finde heraus, wie weit die längste überstehende Ecke herausragt, und ändere ihre Größe"

0voto

krubo Punkte 4881
function resize_factor()
{
    /* Find how far the upper-left corner sticks up beyond the top */
    overtop = gety(0, 0);
    /* Compute a vertical resize factor that would put that point at the top */
    /* (be sure to use floating point arithmetic) */
    vertical_resize = _cy / (_cy - overtop);

    /* Do the same for the lower-left corner sticking out beyond the left */
    /* (using 2*_cy for the height of the rectangle) */
    overleft = getx(0, 2*_cy);    
    horizontal_resize = _cx / (_cx - overleft);

    /* Return whichever resize constraint is stricter */
    return min(vertical_resize, horizontal_resize);
}

function resize_x(x)
{
    /* To get location of a point, after resize, before rotation... */
    /* ...multiply its resize factor by its distance from the center. */
    return resize_factor()*(x - _cx) + _cx;
}

function resize_y(y)
{
    return resize_factor()*(y - _cy) + _cy;
}

/* These resized coordinates can be used inside any other code you want: */
function getx_after_resize_and_rotate(x, y)
{
    return getx( resized_x(x), resized_y(y) );
}

Anmerkungen: Dieser Code geht davon aus, dass sich der Winkel im Uhrzeigersinn um weniger als 90 Grad dreht (denn das ist es, was Ihre Bilder zeigen). Wenn Ihr Winkel etwas anderes ist, müssen Sie möglicherweise alle 4 Ecken überprüfen und feststellen, welche am weitesten oben und links sind.

0voto

bajie Punkte 167
    fitRect: function( rw,rh,radians ){
            var x1 = -rw/2,
                x2 = rw/2,
                x3 = rw/2,
                x4 = -rw/2,
                y1 = rh/2,
                y2 = rh/2,
                y3 = -rh/2,
                y4 = -rh/2;

            var x11 = x1 * Math.cos(radians) + y1 * Math.sin(radians),
                y11 = -x1 * Math.sin(radians) + y1 * Math.cos(radians),
                x21 = x2 * Math.cos(radians) + y2 * Math.sin(radians),
                y21 = -x2 * Math.sin(radians) + y2 * Math.cos(radians), 
                x31 = x3 * Math.cos(radians) + y3 * Math.sin(radians),
                y31 = -x3 * Math.sin(radians) + y3 * Math.cos(radians),
                x41 = x4 * Math.cos(radians) + y4 * Math.sin(radians),
                y41 = -x4 * Math.sin(radians) + y4 * Math.cos(radians);

            var x_min = Math.min(x11,x21,x31,x41),
                x_max = Math.max(x11,x21,x31,x41);

            var y_min = Math.min(y11,y21,y31,y41);
                y_max = Math.max(y11,y21,y31,y41);

            return [x_max-x_min,y_max-y_min];
        }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X