Nahtlose Umwandlung von Quadrat zu Sechseck


23

Für viele Spiele, die auf einem Gitter gespielt werden, sind Sechsecke die eindeutig überlegene Wahl. Leider haben viele kostenlose Spielekunstseiten nur nahtlose Kachelsätze für quadratische Karten. Bei einem früheren Projekt habe ich einige davon verwendet und sie manuell in Sechsecke konvertiert.

Allerdings bin ich in meinem Alter faul geworden. Es sollte einfach sein, den Prozess mit einem kleinen Skript zu automatisieren.

Allerdings bin ich in meinem Alter faul geworden. Also lagere ich es an Sie aus und verkleide es als Code-Golf-Herausforderung 1 .


Eingang

Die Eingabe ist ein quadratisches Bild in jedem gängigen Bildformat, das 24-Bit-RGB-Farben unterstützt. Sie können anstelle der Bilddaten auch einen Dateinamen als Eingabe verwenden.

Sie können davon ausgehen, dass das Bild quadratisch ist und die Seitenlänge ein Vielfaches von vier ist.

Ausgabe

Die Ausgabe ist die Eingabe-Kachel, wird jedoch in ein Sechseck umgewandelt (das Bild selbst ist quadratisch mit transparenten Bereichen). Sie können es in einer Datei speichern oder auf dem Bildschirm anzeigen.

Auch hier kann jedes gängige Bildformat verwendet werden. Wenn das von Ihnen verwendete Format Transparenz unterstützt, müssen die Hintergrundbereiche transparent sein. Wenn dies nicht der Fall ist, können Sie die Farbe # FF00FF (diese schreckliche Fuchsie) als Ersatz verwenden.

Methode

Wie machen wir das? Die Methode, die ich 2 verwende, drückt das Bild ein wenig vertikal zusammen, aber insgesamt sieht es für die meisten Dinge ziemlich gut aus. Wir werden ein Beispiel mit diesem Eingabebild machen:

Eingang

  • Skalieren: Skaliert das Bild auf ein Verhältnis von 3: 2. Da es sich bei unseren Bildern um Quadrate handelt, skalieren Sie sie einfach auf 75% Breite und 50% Höhe. Unsere Beispieleingabe ist 200x200, daher erhalten wir dieses 150x100-Bild:

zerquetscht

  • Kacheln: Legen Sie Kopien Ihres skalierten Bildes in einem 2x2-Raster ab:

Gitter

  • Zuschneiden: Ergreifen Sie ein Sechseck von geeigneter Größe an einer beliebigen Stelle in diesem 2x2-Raster. Dieses Sechseck ist zur Erleichterung des Kachelns nicht gerade regelmäßig. Nachdem Sie ein Quadrat der Originalgröße (hier 200x200) zugeschnitten haben, schneiden Sie die Ecken aus. Die Schnittlinien sollten von (ungefähr) der Mitte jeder linken / rechten Seite bis zu einem Viertel vom Rand oben / unten verlaufen:

verhexen

Und das ist deine Ausgabe!

Hier ist ein Beispiel, wie es aussehen könnte, wenn es gekachelt ist (hier herausgezoomt):

gefliest

Dies ist Codegolf, also gewinnt der kürzeste Code in Bytes. Es gelten Standardlücken usw.


1 Fühlen Sie sich frei, dies zu glauben oder nicht.
2 Methode eins von dieser hilfreichen Site.


13
Diese Frage bittet um eine Hexagony-Antwort.
Sanchises

22
@sanchises Viel Glück.
Martin Ender

17
Hier wird der zweite Teil von Hex Agony wichtig.
Fehler

2
@ mbomb007 Wahrscheinlich, obwohl das # 00FF00 Grün, das manchmal verwendet wird, bei weitem nicht so schlecht ist. Trotzdem habe ich das Gefühl, dass sie Fuchsie häufiger verwenden, weil niemand, der bei Verstand ist, genau diese Farbe in ihren Sprites haben möchte. Es ist also ziemlich universell: P
Geobits 16.10.15

3
# 3 - Ich warte geduldig darauf, die coolen Algorithmen zu sehen ... dann "
leihe

Antworten:


10

Matlab, 223 215 209 184 163 Bytes

Die Neuskalierung ist recht unkompliziert. Zum Beschneiden der Ecken lege ich ein Koordinatensystem über die Pixel und erstelle eine Maske über vier lineare Ungleichungen, die die Fläche des Sechsecks bestimmen.

​l=imread(input(''));
u=size(l,1);
L=imresize(l,u*[2 3]/4);
L=[L,L;L,L];L=L(1:u,1:u,:);
[x,y]=meshgrid(1:u);
r=u/2;x=x*2;
set(imshow(L),'Al',y<x+r&y+x>r&y+x<5*r&y>x-3*r)

Bildbeschreibung hier eingeben

PS: Dies wurde zu einem Codegolf- Nim- Spiel mit @ MartinBüttner's Submission: Sie müssen alternativ Ihren Code kürzer machen (bei gleicher Funktionalität) - derjenige, der die letzte Verkürzung bewirken kann, gewinnt =)


Sie können 5 Bytes einsparen, indem Sie die Größenanpassungsberechnung auf ändern [k.*[2 3]/4].
Becher

4
Sollten die Hintergrundbereiche nicht Fuchsia sein, nicht Schwarz?
Blackhole

@Blackhole Danke, dass du mich informiert hast, ich habe es jetzt behoben und mir sogar eine Menge Bytes
erspart

12

Mathematica, 231 211 209 208 201 188 173 Bytes

ImageCrop[ImageCollage@{#,#,#,#},e,Left]~SetAlphaChannel~ColorNegate@Graphics[RegularPolygon@6,ImageSize->1.05e,AspectRatio->1]&@ImageResize[#,{3,2}(e=ImageDimensions@#)/4]&

Dies ist eine unbenannte Funktion, die ein Bildobjekt aufnimmt und ein Bildobjekt zurückgibt:

Bildbeschreibung hier eingeben

Ich denke, es gibt hier nicht viel zu erklären, aber einige Details, die von Bedeutung sind:

  • Normalerweise verwenden Sie zum Kacheln eines Bildes 2x2, ImageAssemble[{{#,#},{#,#}}]dh Sie übergeben ImageAssembleeine 2x2-Matrix mit Kopien des Bildes. Es gibt ImageCollagejedoch eine Art magische Funktion, die versucht, eine Reihe von Bildern so "gut" wie möglich anzuordnen (was auch immer das bedeutet ... Sie können den einzelnen Bildern sogar Gewichte und Zeug geben). Wie auch immer, Sie geben ihm vier Bilder gleicher Größe und mit gleichen (oder keinen) Gewichten, es ordnet sie auch in einem 2x2-Raster an. Dadurch kann ich einige Bytes für die Verschachtelung der Matrix sowie den Funktionsnamen speichern.
  • Das Sechseck wird als einzelnes Polygon über gerendert Graphics. Ich verwende das eingebaute RegularPolygon@6, aber erzwinge ein Seitenverhältnis von 1, um es nach Bedarf zu dehnen. Benötigt leider Graphicsein paar teure Optionen, um Auffüllen und dergleichen zu vermeiden, und rendert auch Schwarz auf Weiß anstelle des Gegenteils. Das Ergebnis wird mit fixiert ColorNegateund dann mit an die Originalkanäle des Bildes angehängt SetAlphaChannel.
  • Graphicslegt eine kleine Menge Polsterung um das Sechseck, aber wir möchten, dass das Alpha-Sechseck die volle Größe des Ausschnitts bedeckt. Sie SetAlphaChannelkönnen jedoch Bilder unterschiedlicher Größe kombinieren, indem Sie sie übereinander zentrieren und auf die kleinste Größe zuschneiden. Das heißt, PlotRangePadding->0wir können das Sechseckbild nicht manuell einstellen, sondern einfach ein wenig mit skalieren ImageSize->1.05e(und wir benötigen trotzdem die Option `ImageSize).

5

HTML5 + Javascript, 562 Bytes

<html><form><input type=text></form><canvas><script>l=document.body.children;l[0].addEventListener("submit",e=>{e.preventDefault();c=l[1].getContext("2d");i=new Image();i.onload=q=>{l[1].width=l[1].height=d=i.width;c.scale(0.75,0.5);c.drawImage(i,0,0);c.drawImage(i,d,0);c.drawImage(i,0,d);c.drawImage(i,d,d);c.globalCompositeOperation="destination-in";c.scale(1/0.75,2);c.beginPath();c.moveTo(d/4,0);c.lineTo(d/4+d/2,0);c.lineTo(d, d/2);c.lineTo(d/4+d/2, d);c.lineTo(d/4, d);c.lineTo(0, d/2);c.closePath();c.fill();};i.src=e.target.children[0].value;})</script>

Übernimmt die Eingabe als Bild-URL über ein Textfeld (die URL zählt hoffentlich als Dateiname). Gibt die Daten auf der Leinwand aus.

Version, die über alle Browser funktioniert (580 Bytes):

<html><form><input type=text></form><canvas><script>l=document.body.children;l[0].addEventListener("submit",function(e){e.preventDefault();c=l[1].getContext("2d");i=new Image();i.onload=function(){l[1].width=l[1].height=d=i.width;c.scale(0.75,0.5);c.drawImage(i,0,0);c.drawImage(i,d,0);c.drawImage(i,0,d);c.drawImage(i,d,d);c.globalCompositeOperation = "destination-in";c.scale(1/0.75,2);c.beginPath();c.moveTo(d/4, 0);c.lineTo(d/4+d/2,0);c.lineTo(d, d/2);c.lineTo(d/4+d/2, d);c.lineTo(d/4, d);c.lineTo(0, d/2);c.closePath();c.fill();};i.src=e.target.children[0].value;})</script>

Testen Sie es mit dem Bild "blocks" von früher über diese URL: http://i.stack.imgur.com/gQAZh.png


Gute Arbeit! Sie könnten schon einige Bytes speichern , indem Sie das Hinzufügen id=Azu dem <form>und id=Bauf die <canvas>dann ersetzt l[0]mit Aund l[1]mit Bund Entfernen l=document.body.children;. (Funktioniert in Firefox 41; ich bin mir nicht sicher, welche anderen Browser dies unterstützen.) Außerdem glaube ich, dass sich neben den geschweiften Klammern ein paar unnötige Semikolons und ein paar zusätzliche Leerzeichen befinden.
ETHproductions

Weitere Tipps: Ich glaube , Sie könnte hinzufügen , id=Cum das <input>, dann ersetzen e.target.children[0]mit C. 0.75ist gleich 3/4, 1/0.75ist gleich 4/3, d/4+d/2ist gleich d*3/4und führende Nullen auf den anderen Dezimalstellen sind nicht erforderlich. Ich glaube auch, dass Sie das erste c.drawImagedurch c[p="drawImage"], dann jedes nachfolgende durch ersetzen könnten c[p]; Sie könnten das gleiche mit tun c.lineTo.
ETHproductions

4

Python 2 + PIL, 320

Liest den Namen der Bilddatei von stdin.

from PIL import ImageDraw as D,Image as I
i=I.open(raw_input())
C=A,B=i.size
i,j=i.resize((int(.75*A),B/2)),I.new('RGBA',C)
W,H=i.size
for a,b in[(0,0),(0,H),(W,0),(W,H)]:j.paste(i,(a,b,a+W,b+H))
p,d=[(0,0),(A/4,0),(0,B/2),(A/4,B),(0,B)],lambda p:D.Draw(j).polygon(p,fill=(0,)*4)
d(p)
d([(A-x,B-y)for x,y in p])
j.show()

Es stimmt, tut mir leid, PILich hatte keine Gelegenheit, es zu versuchen, und ich habe nicht genug darüber nachgedacht. Ich stehe aber immer noch zu meiner Newline-Aussage: P
FryAmTheEggman 16.10.15

2

PHP, 293 Bytes

Ich habe einige Zeilen hinzugefügt, um die Lesbarkeit zu verbessern:

function($t){$s=imagesx($t);imagesettile($i=imagecreatetruecolor($s,$s),$t=imagescale
($t,$a=$s*3/4,$b=$s/2));imagefill($i,0,0,IMG_COLOR_TILED);$z=imagefilledpolygon;$z($i,
[0,0,$s/4,0,0,$b,$s/4,$s,0,$s],5,$f=imagecolorallocate($i,255,0,255));$z($i,[$s,0,$a,
0,$s,$b,$a,$s,$s,$s],5,$f);return$i;}

Hier ist die ungolfed Version:

function squareToHexagon($squareImage)
{
    $size = imagesx($squareImage);
    $tileImage = imagescale($squareImage, $size * 3/4, $size/2);

    $hexagonImage = imagecreatetruecolor($size, $size);
    imagesettile($hexagonImage, $tileImage);
    imagefill($hexagonImage, 0, 0, IMG_COLOR_TILED);

    $fuchsia = imagecolorallocate($hexagonImage, 255, 0, 255);
    imagefilledpolygon(
        $hexagonImage,
        [
            0,       0,
            $size/4, 0,
            0,       $size/2,
            $size/4, $size,
            0,       $size,
        ],
        5,
        $fuchsia
    );
    imagefilledpolygon(
        $hexagonImage,
        [
            $size,       0,
            $size * 3/4, 0,
            $size,       $size/2,
            $size * 3/4, $size,
            $size,       $size,
        ],
        5,
        $fuchsia
    );

    return $hexagonImage;
}

header('Content-type: image/gif');
$squareImage = imagecreatefrompng('squareImage.png');
$hexagonImage = squareToHexagon($squareImage);
imagegif($hexagonImage);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.