Hi,
Any idea how to fill a region inside a polygon with hatched lines.
regards.
Hi,
Any idea how to fill a region inside a polygon with hatched lines.
regards.
You could set the path as a clip and then use a tiled image with your hatch pattern.
HI vinn,
I could not get what do you want to suggest.Can you just explain it briefly with some example
I can do better than that. Here is a full sample program that compiles and runs and does exactly what I described:
#include "juce.h"
namespace binaries
{
extern const char* crosshatch_png;
const int crosshatch_pngSize = 174;
}
static const unsigned char temp8[] = {137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,63,0,0,0,63,8,0,0,0,0,114,52,79,3,0,0,0,1,115,82,71,
66,0,174,206,28,233,0,0,0,2,98,75,71,68,0,255,135,143,204,191,0,0,0,9,112,72,89,115,0,0,11,19,0,0,11,19,1,0,154,156,
24,0,0,0,7,116,73,77,69,7,218,12,30,2,34,22,90,165,127,91,0,0,0,50,73,68,65,84,72,199,237,206,177,13,0,48,12,195,48,231,
255,163,221,35,60,150,128,118,49,77,151,46,205,13,109,247,38,252,252,252,252,252,252,252,252,252,252,252,252,252,252,31,248,31,219,226,150,149,132,194,
157,83,0,0,0,0,73,69,78,68,174,66,96,130,0,0};
const char* binaries::crosshatch_png = (const char*) temp8;
Image loadImageAsAlphaChannel (const void* rawData,
const int numBytesOfData)
{
Image orig = ImageFileFormat::loadFrom(rawData, numBytesOfData);
Image dup = Image (Image::ARGB, orig.getWidth(), orig.getHeight(), false);
if (orig.isRGB())
{
// bug in Juce brings grayscale PNG in as RGB so deal with it
// convert the Red channel to the alpha of the destination
Image::BitmapData src (orig, false);
Image::BitmapData dst (dup, true);
for (int y=0; y<orig.getHeight(); y++ )
{
PixelRGB* psrc = reinterpret_cast<PixelRGB*> (src.getLinePointer (y));
PixelARGB* pdst = reinterpret_cast<PixelARGB*> (dst.getLinePointer (y));
for( int x=orig.getWidth(); x; x-- )
(pdst++)->setAlpha (psrc++->getRed());
}
}
else
{
jassertfalse;
}
return dup;
}
void tintImageTiled (Graphics& g,
Image image,
const Rectangle<int>& bounds,
int xOffset,
int yOffset)
{
int w = image.getWidth();
int h = image.getHeight();
xOffset %= w;
yOffset %= h;
for (int y = bounds.getY()-yOffset; y<bounds.getBottom(); y+=h )
{
for (int x = bounds.getX()-xOffset; x<bounds.getRight(); x+=w )
{
int sourceX=0;
int sourceY=0;
int destWidth = w;
int destHeight = h;
int destX = x;
int destY = y;
if (destX < bounds.getX())
{
sourceX += (bounds.getX() - destX);
destWidth -= bounds.getX() - destX;
destX = bounds.getX();
}
if (destX + destWidth > bounds.getRight())
destWidth -= (destX + destWidth) - bounds.getRight();
if (destY < bounds.getY())
{
sourceY += (bounds.getY() - destY);
destHeight -= bounds.getY() - destY;
destY = bounds.getY();
}
if (destY + destHeight > bounds.getBottom())
destHeight -= (destY + destHeight) - bounds.getBottom();
g.drawImage (image, destX, destY, destWidth, destHeight,
sourceX, sourceY, destWidth, destHeight, true);
}
}
}
struct ContentComponent : Component
{
Image m_image;
ContentComponent()
{
setSize(512, 384);
m_image = loadImageAsAlphaChannel (binaries::crosshatch_png, binaries::crosshatch_pngSize);
}
void paint (Graphics& g)
{
int w = getLocalBounds().getWidth();
int h = getLocalBounds().getHeight();
g.setColour (Colours::white);
g.fillAll();
Path p;
p.startNewSubPath (10, 10);
p.lineTo (w-100, 50);
p.lineTo (w-300, h-100);
p.lineTo (w-350, h-60);
p.lineTo (75, 100);
p.closeSubPath ();
g.setColour (Colours::blue);
g.reduceClipRegion (p);
tintImageTiled (g, m_image, p.getBounds().getSmallestIntegerContainer(), 0, 0);
// frame
g.setColour (Colours::black);
g.strokePath (p, 4);
}
};
struct MainWindow : DocumentWindow
{
MainWindow()
: DocumentWindow (JUCE_T("Test")
, Colours::black
, DocumentWindow::allButtons
, true )
{
ContentComponent* p = new ContentComponent;
setResizable (true, false);
setContentComponent (p, true, true);
centreWithSize (getWidth(), getHeight());
setVisible( true );
}
~MainWindow() {}
void closeButtonPressed() { JUCEApplication::quit(); }
};
struct MainApp : JUCEApplication
{
MainApp() : mainWindow(0) { s_app=this; }
~MainApp() { s_app=0; }
static MainApp& GetInstance() { return *s_app; }
const String getApplicationName() { return JUCE_T("JuceTest"); }
const String getApplicationVersion() { return JUCE_T("0.1.0"); }
bool moreThanOneInstanceAllowed() { return true; }
void anotherInstanceStarted (const String& commandLine) {}
void initialise (const String& commandLine)
{
mainWindow = new MainWindow;
}
void shutdown()
{
delete mainWindow;
}
static MainApp* s_app;
MainWindow* mainWindow;
};
MainApp* MainApp::s_app = 0;
START_JUCE_APPLICATION (MainApp)
Here is the PNG image that I used to produce the hatch pattern. You can substitute your own image and then run the BinaryBuilder to embed it in your application:
[attachment=0]CrossHatch.png[/attachment]
Note that there is still a bug in the Juce PNG loader, it brings grayscale images in as RGB. There is also another thing I consider a bug / usability issue which is that Juce won’t treat a single channel Image as an Alpha channel, so some hacking is required to use a Grayscale image in a tinting operation (thats why I have to swizzle bits in loadImageAsAlphaChannel).
Hey Vinn,
Thanks a lot…that was really helpful.
regards.
Another option would be to draw a series of lines. To make the calculations easier you can just draw vertical lines at a given spacing after setting an appropriate rotation transform.
Thanks Vinn.