<commit_before>#include "ofxAudioVisualApp.h"

//----------------------- App -----------------------------------------------

void ofxAudioVisualApp::setup() {
	ofSetVerticalSync(true);

	plotHeight = 700;
	bufferSize = 2048;

	fft = ofxFft::create(bufferSize, OF_FFT_WINDOW_HAMMING);
	// To use FFTW, try:
	//fft = ofxFft::create(bufferSize, OF_FFT_WINDOW_HAMMING, OF_FFT_FFTW);

	drawBins.resize(fft->getBinSize());
	middleBins.resize(fft->getBinSize());
	audioBins.resize(fft->getBinSize());

	// 0 output channels,
	// 1 input channel
	// 44100 samples per second
	// [bins] samples per buffer
	// 4 num buffers (latency)

    soundPlayer = new ofSoundPlayer();
    //soundPlayer->load("sounds/Lecture1.wav");
    soundPlayer->setLoop(OF_LOOP_NORMAL);
    soundPlayer->setVolume(1.0);

    ofxNestedFileLoader loader;

    ofSetDataPathRoot("../../../../../SharedData/");
    vector<string> soundPaths = loader.load("lectures");

    for(int i = 0; i < soundPaths.size(); i++) {
        vector<string> tempPath = ofSplitString(soundPaths[i], "/");
        string nameWithExtension = tempPath[tempPath.size()-1];
        vector<string> tempName = ofSplitString(nameWithExtension, ".");
        if(tempName.size() == 2) {
            ofParameter<bool>* clip;
            clip = new ofParameter<bool>;
            clip->set(tempName[0], false);
            soundClips[tempName[0]] = soundPaths[i];
            clips.add(*clip);

        } else {
            ofLogError("Your File name had a '.' in it which is weird..., skipping file: " + nameWithExtension);
        }
    }

    if(soundPaths.size()) {
        soundPlayer->load(soundPaths[0]);
    } else {
        ofLogError("No Lectures Loaded");
    }

    loader.clearPaths();

    vector<string> spectrumPaths = loader.load("spectra");

    for(int i = 0; i < spectrumPaths.size(); i++) {
        vector<string> tempPath = ofSplitString(spectrumPaths[i], "/");
        string nameWithExtension = tempPath[tempPath.size()-1];
        vector<string> tempName = ofSplitString(nameWithExtension, ".");
        if(tempName.size() == 2) {
            ofParameter<bool>* spectrum;
            spectrum = new ofParameter<bool>;
            bool initialValue = i == 0 ? true : false;
            spectrum->set(tempName[0], initialValue);
            spectra[tempName[0]] = spectrumPaths[i];
            spectrumGroup.add(*spectrum);

        } else {
            ofLogError("Your File name had a '.' in it which is weird..., skipping file: " + nameWithExtension);
        }
    }

    if(spectrumPaths.size()) {
        spectrum.load(spectra.begin()->second);
    } else {
        ofLogError("No Spectra Loaded");
    }

    // These need the files to be loaded before adding to gui
    gui.add(clips);
    gui.add(spectrumGroup);
    ofAddListener(clips.parameterChangedE(), this, &ofxAudioVisualApp::onClipChanged);
    ofAddListener(spectrumGroup.parameterChangedE(), this, &ofxAudioVisualApp::onSpectrumChanged);

	ofBackground(0, 0, 0);
    ofSetBackgroundAuto(false);
    ofSetLineWidth(2);
}

void ofxAudioVisualApp::update() {
    int nBandsToGet = fft->getBinSize();
    float * val = ofSoundGetSpectrum(nBandsToGet);		// request 128 values for fft
    for (int i = 0;i < nBandsToGet; i++){
        // let the smoothed value sink to zero:
        drawBins[i] *= 0.96f;
    }

    if (outputOn) {
        for (int i = 0;i < nBandsToGet; i++){
            // take the max, either the smoothed or the incoming:
            if (drawBins[i] < val[i]) drawBins[i] = val[i];
        }
    } else {
        soundMutex.lock();
        for (int i = 0;i < nBandsToGet; i++){
            // take the max, either the smoothed or the incoming:
            if (drawBins[i] < middleBins[i]) drawBins[i] = middleBins[i];
        }
        soundMutex.unlock();
    }
}

void ofxAudioVisualApp::draw() {

    if (backgroundRefresh){
        ofPushStyle();
        ofSetColor(0);
        ofDrawRectangle(0, 0, ofGetWidth(), ofGetHeight());
        ofPopStyle();
    }

}

//----------------------- GUI -----------------------------------------------

void ofxAudioVisualApp::setupGui(){
    settings.add(sampleHeight.set("Sample Height", sampleImage.getHeight()/2, 0, sampleImage.getHeight()));
    settings.add(outputOn.set("Output On", false));
    settings.add(play.set("Play!", false));
    settings.add(backgroundRefresh.set("Background Auto", false));
    settings.add(exposure.set("Speed", 1.0, 0.0, 10.0));
    settings.add(scrub.set("Scrub", 0, 0, 1));
    settings.add(drawSpeed.set("Draw Speed", 1, -5, 5));

    settings.add(colHigh.set("High", ofColor(255)));
    settings.add(colLow.set("Low", ofColor(0)));
    settings.add(usePalette.set("Use palette", false));
    settings.add(spectrumY.set("Sample Y", 0, 0, 100));

    gui.setup("Main");
    gui.add(settings);
    ofAddListener(settings.parameterChangedE(), this, &ofxAudioVisualApp::onSettingChanged);

    gui2.setup();
    gui2.setPosition(230, 10);

    gui2.add(threshold.set("Threshold", 0.0038, 0, 0.009));
    gui2.add(symmetrical.set("Symmetrical", true));

    startEndBin.add(startBin.set("Start Bin", 0, 0, 1024));
    startEndBin.add(endBin.set("End Bin", 1024, 0, 1024));
    gui2.add(startEndBin);
}

void ofxAudioVisualApp::drawGui(ofEventArgs & args){
    ofBackground(50);
    gui.draw();

    gui2.draw();

    ofDrawBitmapString(ofGetTimestampString("%Y/%m/%d  %Z %H:%M:%S"), 20, ofGetHeight() - 20);
    ofDrawBitmapString(ofToString(ofGetFrameRate()), ofGetWidth() - 100, ofGetHeight() - 20);
}

//---------------------------------------------------------------------------

float ofxAudioVisualApp::getAverageVolume(vector<float>& buffer) {
    float n = buffer.size();
    long double average = 0;
    for(int i = 0; i < n; i++) {
        average += buffer[i];
    }
    average /= n;
    return average;
}

void ofxAudioVisualApp::plot(vector<float>& buffer, float scale, float offset) {
	ofNoFill();
	float n = buffer.size();
	ofDrawRectangle(0, 0, n, plotHeight);
	glPushMatrix();
	glTranslatef(0, plotHeight / 2 + offset, 0);
    samplePixels = sampleImage.getPixels();
    ofColor col;
	for (int i = 0; i < n; i ++) {
        col = ofColor(255);// samplePixels.getColor(i/n * samplePixels.getWidth(), sampleHeight);
        ofSetColor(col);
		ofDrawLine(i, 0, i, sqrt(buffer[i]) * scale);
	}
	glPopMatrix();
}

void ofxAudioVisualApp::audioReceived(float* input, int bufferSize, int nChannels) {
	float maxValue = 0;
	for(int i = 0; i < bufferSize; i++) {
		if(abs(input[i]) > maxValue) {
			maxValue = abs(input[i]);
		}
	}
	for(int i = 0; i < bufferSize; i++) {
		input[i] /= maxValue;
	}

	fft->setSignal(input);

	float* curFft = fft->getAmplitude();
	memcpy(&audioBins[0], curFft, sizeof(float) * fft->getBinSize());

	maxValue = 0;
	for(int i = 0; i < fft->getBinSize(); i++) {
		if(abs(audioBins[i]) > maxValue) {
			maxValue = abs(audioBins[i]);
		}
	}
	for(int i = 0; i < fft->getBinSize(); i++) {
		audioBins[i] /= maxValue;
	}

	soundMutex.lock();
	middleBins = audioBins;
	soundMutex.unlock();
}

void ofxAudioVisualApp::onSpectrumChanged(ofAbstractParameter &p) {
    string spectrumName = spectra[p.getName()];
    for(auto it = spectra.begin(); it != spectra.end(); it++) {
        string name = it->first;
        if(name != p.getName()) {
            spectrumGroup.get<bool>(name).setWithoutEventNotifications(false);
        }
    }
    spectrum.load(spectrumName);
}

void ofxAudioVisualApp::onSettingChanged(ofAbstractParameter &p) {
    string name = p.getName();
    if(name == "Play!") {
        ofClear(0);
        if(outputOn) {
            soundPlayer->setSpeed(exposure);
            soundPlayer->stop();
            soundPlayer->play();
            soundPlayer->setPosition(scrub);
        }
//        ofSetFullscreen(true);
    }

    if(name == "Scrub"){
        soundPlayer->setPosition(scrub);
    }

    if(name == "Speed"){
        soundPlayer->setSpeed(exposure);
    }
}

void ofxAudioVisualApp::onClipChanged(ofAbstractParameter &p) {
    string clipName = soundClips[p.getName()];
    if(soundPlayer->isPlaying()) {
        soundPlayer->stop();
    }
    soundPlayer->load(clipName);
    if(outputOn) {
        soundPlayer->play();
    }
}

void ofxAudioVisualApp::keyPressed(int key) {
    switch (key) {
        case 'f':
            ofToggleFullscreen();
            break;
        case 'b':
            backgroundRefresh = !backgroundRefresh;
            break;
        default:
            break;
    }
}

ofColor ofxAudioVisualApp::getColorLerp(int i) {
    float percent = ofMap(drawBins[i], 0, 0.1, 0, 1, true);
    ofColor inBetween = colLow.get().getLerped(colHigh.get(), percent);
    return inBetween;
}

ofColor ofxAudioVisualApp::getColorFromSpectrum(int i) {
    float percent = ofMap(drawBins[i], 0, 0.1, 0, 1, true);
    ofColor inBetween = spectrum.getColor(ofMap(percent, 0, 1, 0, spectrum.getWidth()-1, true), (int)ofMap(spectrumY, 0, 100, 0, spectrum.getHeight()-1, true));
    return inBetween;
}

ofColor ofxAudioVisualApp::getColor(int i){
    if (usePalette){
        return getColorFromSpectrum(i);
    }else{
        return getColorLerp(i);
    }
}

void ofxAudioVisualApp::exit() {
    ofSoundStreamClose();
}
<commit_msg>Add palette preview<commit_after>#include "ofxAudioVisualApp.h"

//----------------------- App -----------------------------------------------

void ofxAudioVisualApp::setup() {
	ofSetVerticalSync(true);

	plotHeight = 700;
	bufferSize = 2048;

	fft = ofxFft::create(bufferSize, OF_FFT_WINDOW_HAMMING);
	// To use FFTW, try:
	//fft = ofxFft::create(bufferSize, OF_FFT_WINDOW_HAMMING, OF_FFT_FFTW);

	drawBins.resize(fft->getBinSize());
	middleBins.resize(fft->getBinSize());
	audioBins.resize(fft->getBinSize());

	// 0 output channels,
	// 1 input channel
	// 44100 samples per second
	// [bins] samples per buffer
	// 4 num buffers (latency)

    soundPlayer = new ofSoundPlayer();
    //soundPlayer->load("sounds/Lecture1.wav");
    soundPlayer->setLoop(OF_LOOP_NORMAL);
    soundPlayer->setVolume(1.0);

    ofxNestedFileLoader loader;

    ofSetDataPathRoot("../../../../../SharedData/");
    vector<string> soundPaths = loader.load("lectures");

    for(int i = 0; i < soundPaths.size(); i++) {
        vector<string> tempPath = ofSplitString(soundPaths[i], "/");
        string nameWithExtension = tempPath[tempPath.size()-1];
        vector<string> tempName = ofSplitString(nameWithExtension, ".");
        if(tempName.size() == 2) {
            ofParameter<bool>* clip;
            clip = new ofParameter<bool>;
            clip->set(tempName[0], false);
            soundClips[tempName[0]] = soundPaths[i];
            clips.add(*clip);

        } else {
            ofLogError("Your File name had a '.' in it which is weird..., skipping file: " + nameWithExtension);
        }
    }

    if(soundPaths.size()) {
        soundPlayer->load(soundPaths[0]);
    } else {
        ofLogError("No Lectures Loaded");
    }

    loader.clearPaths();

    vector<string> spectrumPaths = loader.load("spectra");

    for(int i = 0; i < spectrumPaths.size(); i++) {
        vector<string> tempPath = ofSplitString(spectrumPaths[i], "/");
        string nameWithExtension = tempPath[tempPath.size()-1];
        vector<string> tempName = ofSplitString(nameWithExtension, ".");
        if(tempName.size() == 2) {
            ofParameter<bool>* spectrum;
            spectrum = new ofParameter<bool>;
            bool initialValue = i == 0 ? true : false;
            spectrum->set(tempName[0], initialValue);
            spectra[tempName[0]] = spectrumPaths[i];
            spectrumGroup.add(*spectrum);

        } else {
            ofLogError("Your File name had a '.' in it which is weird..., skipping file: " + nameWithExtension);
        }
    }

    if(spectrumPaths.size()) {
        spectrum.load(spectra.begin()->second);
    } else {
        ofLogError("No Spectra Loaded");
    }

    // These need the files to be loaded before adding to gui
    gui.add(clips);
    gui.add(spectrumGroup);
    ofAddListener(clips.parameterChangedE(), this, &ofxAudioVisualApp::onClipChanged);
    ofAddListener(spectrumGroup.parameterChangedE(), this, &ofxAudioVisualApp::onSpectrumChanged);

	ofBackground(0, 0, 0);
    ofSetBackgroundAuto(false);
    ofSetLineWidth(2);
}

void ofxAudioVisualApp::update() {
    int nBandsToGet = fft->getBinSize();
    float * val = ofSoundGetSpectrum(nBandsToGet);		// request 128 values for fft
    for (int i = 0;i < nBandsToGet; i++){
        // let the smoothed value sink to zero:
        drawBins[i] *= 0.96f;
    }

    if (outputOn) {
        for (int i = 0;i < nBandsToGet; i++){
            // take the max, either the smoothed or the incoming:
            if (drawBins[i] < val[i]) drawBins[i] = val[i];
        }
    } else {
        soundMutex.lock();
        for (int i = 0;i < nBandsToGet; i++){
            // take the max, either the smoothed or the incoming:
            if (drawBins[i] < middleBins[i]) drawBins[i] = middleBins[i];
        }
        soundMutex.unlock();
    }
}

void ofxAudioVisualApp::draw() {

    if (backgroundRefresh){
        ofPushStyle();
        ofSetColor(0);
        ofDrawRectangle(0, 0, ofGetWidth(), ofGetHeight());
        ofPopStyle();
    }

}

//----------------------- GUI -----------------------------------------------

void ofxAudioVisualApp::setupGui(){
    settings.add(sampleHeight.set("Sample Height", sampleImage.getHeight()/2, 0, sampleImage.getHeight()));
    settings.add(outputOn.set("Output On", false));
    settings.add(play.set("Play!", false));
    settings.add(backgroundRefresh.set("Background Auto", false));
    settings.add(exposure.set("Speed", 1.0, 0.0, 10.0));
    settings.add(scrub.set("Scrub", 0, 0, 1));
    settings.add(drawSpeed.set("Draw Speed", 1, -5, 5));

    settings.add(colHigh.set("High", ofColor(255)));
    settings.add(colLow.set("Low", ofColor(0)));
    settings.add(usePalette.set("Use palette", false));
    settings.add(spectrumY.set("Sample Y", 0, 0, 100));

    gui.setup("Main");
    gui.add(settings);
    ofAddListener(settings.parameterChangedE(), this, &ofxAudioVisualApp::onSettingChanged);

    gui2.setup();
    gui2.setPosition(230, 10);

    gui2.add(threshold.set("Threshold", 0.0038, 0, 0.009));
    gui2.add(symmetrical.set("Symmetrical", true));

    startEndBin.add(startBin.set("Start Bin", 0, 0, 512));
    startEndBin.add(endBin.set("End Bin", 1024, 0, 1024));
    gui2.add(startEndBin);
}

void ofxAudioVisualApp::drawGui(ofEventArgs & args){
    ofBackground(50);
    gui.draw();

    gui2.draw();

    ofDrawBitmapString(ofGetTimestampString("%Y/%m/%d  %Z %H:%M:%S"), 20, ofGetHeight() - 20);
    ofDrawBitmapString(ofToString(ofGetFrameRate()), ofGetWidth() - 100, ofGetHeight() - 20);

    ofPushMatrix();
    ofPushStyle();

    ofTranslate(ofGetWidth() - 270, ofGetHeight() - 270);
    spectrum.update();
    spectrum.draw(0, 0, 200, 200);
    ofNoFill();
    ofSetColor(255);
    ofSetLineWidth(2);
    ofDrawRectangle(0, ofMap(spectrumY, 0, 100, 0, 196), 200, 4);

    ofPopStyle();
    ofPopMatrix();
}

//---------------------------------------------------------------------------

float ofxAudioVisualApp::getAverageVolume(vector<float>& buffer) {
    float n = buffer.size();
    long double average = 0;
    for(int i = 0; i < n; i++) {
        average += buffer[i];
    }
    average /= n;
    return average;
}

void ofxAudioVisualApp::plot(vector<float>& buffer, float scale, float offset) {
	ofNoFill();
	float n = buffer.size();
	ofDrawRectangle(0, 0, n, plotHeight);
	glPushMatrix();
	glTranslatef(0, plotHeight / 2 + offset, 0);
    samplePixels = sampleImage.getPixels();
    ofColor col;
	for (int i = 0; i < n; i ++) {
        col = ofColor(255);// samplePixels.getColor(i/n * samplePixels.getWidth(), sampleHeight);
        ofSetColor(col);
		ofDrawLine(i, 0, i, sqrt(buffer[i]) * scale);
	}
	glPopMatrix();
}

void ofxAudioVisualApp::audioReceived(float* input, int bufferSize, int nChannels) {
	float maxValue = 0;
	for(int i = 0; i < bufferSize; i++) {
		if(abs(input[i]) > maxValue) {
			maxValue = abs(input[i]);
		}
	}
	for(int i = 0; i < bufferSize; i++) {
		input[i] /= maxValue;
	}

	fft->setSignal(input);

	float* curFft = fft->getAmplitude();
	memcpy(&audioBins[0], curFft, sizeof(float) * fft->getBinSize());

	maxValue = 0;
	for(int i = 0; i < fft->getBinSize(); i++) {
		if(abs(audioBins[i]) > maxValue) {
			maxValue = abs(audioBins[i]);
		}
	}
	for(int i = 0; i < fft->getBinSize(); i++) {
		audioBins[i] /= maxValue;
	}

	soundMutex.lock();
	middleBins = audioBins;
	soundMutex.unlock();
}

void ofxAudioVisualApp::onSpectrumChanged(ofAbstractParameter &p) {
    string spectrumName = spectra[p.getName()];
    for(auto it = spectra.begin(); it != spectra.end(); it++) {
        string name = it->first;
        if(name != p.getName()) {
            spectrumGroup.get<bool>(name).setWithoutEventNotifications(false);
        }
    }
    spectrum.load(spectrumName);
}

void ofxAudioVisualApp::onSettingChanged(ofAbstractParameter &p) {
    string name = p.getName();
    if(name == "Play!") {
        ofClear(0);
        if(outputOn) {
            soundPlayer->setSpeed(exposure);
            soundPlayer->stop();
            soundPlayer->play();
            soundPlayer->setPosition(scrub);
        }
//        ofSetFullscreen(true);
    }

    if(name == "Scrub"){
        soundPlayer->setPosition(scrub);
    }

    if(name == "Speed"){
        soundPlayer->setSpeed(exposure);
    }
}

void ofxAudioVisualApp::onClipChanged(ofAbstractParameter &p) {
    string clipName = soundClips[p.getName()];
    if(soundPlayer->isPlaying()) {
        soundPlayer->stop();
    }
    soundPlayer->load(clipName);
    if(outputOn) {
        soundPlayer->play();
    }
}

void ofxAudioVisualApp::keyPressed(int key) {
    switch (key) {
        case 'f':
            ofToggleFullscreen();
            break;
        case 'b':
            backgroundRefresh = !backgroundRefresh;
            break;
        default:
            break;
    }
}

ofColor ofxAudioVisualApp::getColorLerp(int i) {
    float percent = ofMap(drawBins[i], 0, 0.1, 0, 1, true);
    ofColor inBetween = colLow.get().getLerped(colHigh.get(), percent);
    return inBetween;
}

ofColor ofxAudioVisualApp::getColorFromSpectrum(int i) {
    float percent = ofMap(drawBins[i], 0, 0.1, 0, 1, true);
    ofColor inBetween = spectrum.getColor(ofMap(percent, 0, 1, 0, spectrum.getWidth()-1, true), (int)ofMap(spectrumY, 0, 100, 0, spectrum.getHeight()-1, true));
    return inBetween;
}

ofColor ofxAudioVisualApp::getColor(int i){
    if (usePalette){
        return getColorFromSpectrum(i);
    }else{
        return getColorLerp(i);
    }
}

void ofxAudioVisualApp::exit() {
    ofSoundStreamClose();
}
<|endoftext|>


<commit_before>#include <v8.h>
#include <node.h>
#include <string>
#include <cstdlib>
#include "libsass/sass_interface.h"

using namespace v8;

void WorkOnContext(uv_work_t* req) {
    sass_context* ctx = static_cast<sass_context*>(req->data);
    sass_compile(ctx);
}

void MakeCallback(uv_work_t* req) {
    HandleScope scope;
    TryCatch try_catch;
    sass_context* ctx = static_cast<sass_context*>(req->data);

    if (ctx->error_status == 0) {
        // if no error, do callback(null, result)
        const unsigned argc = 2;
        Local<Value> argv[argc] = {
            Local<Value>::New(Null()),
            Local<Value>::New(String::New(ctx->output_string))
        };

        ctx->callback->Call(Context::GetCurrent()->Global(), argc, argv);
    } else {
        // if error, do callback(error)
        const unsigned argc = 1;
        Local<Value> argv[argc] = {
            Local<Value>::New(String::New(ctx->error_message))
        };

        ctx->callback->Call(Context::GetCurrent()->Global(), argc, argv);
    }
    if (try_catch.HasCaught()) {
        node::FatalException(try_catch);
    }
}

Handle<Value> Render(const Arguments& args) {
    HandleScope scope;
    sass_context* ctx = sass_new_context();
    String::AsciiValue astr(args[0]);
    Local<Function> callback = Local<Function>::Cast(args[1]);

    ctx->source_string = new char[strlen(*astr)+1];
    strcpy(ctx->source_string, *astr);
    ctx->options.include_paths = 0;
    ctx->options.output_style = SASS_STYLE_NESTED;
    ctx->callback = Persistent<Function>::New(callback);
    ctx->request.data = ctx;

    int status = uv_queue_work(uv_default_loop(), &ctx->request, WorkOnContext, MakeCallback);
    assert(status == 0);

    return Undefined();
}

void RegisterModule(v8::Handle<v8::Object> target) {
    NODE_SET_METHOD(target, "render", Render);
}

NODE_MODULE(binding, RegisterModule);
<commit_msg>remember to free memory<commit_after>#include <v8.h>
#include <node.h>
#include <string>
#include <cstdlib>
#include "libsass/sass_interface.h"

using namespace v8;

void WorkOnContext(uv_work_t* req) {
    sass_context* ctx = static_cast<sass_context*>(req->data);
    sass_compile(ctx);
}

void MakeCallback(uv_work_t* req) {
    HandleScope scope;
    TryCatch try_catch;
    sass_context* ctx = static_cast<sass_context*>(req->data);

    if (ctx->error_status == 0) {
        // if no error, do callback(null, result)
        const unsigned argc = 2;
        Local<Value> argv[argc] = {
            Local<Value>::New(Null()),
            Local<Value>::New(String::New(ctx->output_string))
        };

        ctx->callback->Call(Context::GetCurrent()->Global(), argc, argv);
    } else {
        // if error, do callback(error)
        const unsigned argc = 1;
        Local<Value> argv[argc] = {
            Local<Value>::New(String::New(ctx->error_message))
        };

        ctx->callback->Call(Context::GetCurrent()->Global(), argc, argv);
    }
    if (try_catch.HasCaught()) {
        node::FatalException(try_catch);
    }
    sass_free_context(ctx);
}

Handle<Value> Render(const Arguments& args) {
    HandleScope scope;
    sass_context* ctx = sass_new_context();
    String::AsciiValue astr(args[0]);
    Local<Function> callback = Local<Function>::Cast(args[1]);

    ctx->source_string = new char[strlen(*astr)+1];
    strcpy(ctx->source_string, *astr);
    ctx->options.include_paths = 0;
    ctx->options.output_style = SASS_STYLE_NESTED;
    ctx->callback = Persistent<Function>::New(callback);
    ctx->request.data = ctx;

    int status = uv_queue_work(uv_default_loop(), &ctx->request, WorkOnContext, MakeCallback);
    assert(status == 0);

    return Undefined();
}

void RegisterModule(v8::Handle<v8::Object> target) {
    NODE_SET_METHOD(target, "render", Render);
}

NODE_MODULE(binding, RegisterModule);
<|endoftext|>


<commit_before>/*===================================================================

BlueBerry Platform

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#ifdef __MINGW32__
// We need to inlclude winbase.h here in order to declare
// atomic intrinsics like InterlockedIncrement correctly.
// Otherwhise, they would be declared wrong within qatomic_windows.h .
#include <windows.h>
#endif

#include "berryHelpContentView.h"

#include "berryHelpPluginActivator.h"
#include "berryHelpEditor.h"
#include "berryHelpEditorInput.h"
#include "berryHelpWebView.h"
#include "berryQHelpEngineWrapper.h"

#include <berryIWorkbenchPage.h>

#include <QSortFilterProxyModel>
#include <QHelpContentWidget>
#include <QLayout>
#include <QMenu>
#include <QHeaderView>
#include <QDir>

namespace berry {

HelpContentWidget::HelpContentWidget()
  : QTreeView(0)
  , m_SortModel(new QSortFilterProxyModel(this))
  , m_SourceModel(0)
{
  header()->hide();
  setUniformRowHeights(true);
  connect(this, SIGNAL(activated(QModelIndex)),
          this, SLOT(showLink(QModelIndex)));

  m_SortModel->setDynamicSortFilter(true);
  QTreeView::setModel(m_SortModel);
}

QModelIndex HelpContentWidget::indexOf(const QUrl &link)
{
  QHelpContentModel *contentModel =
      qobject_cast<QHelpContentModel*>(m_SourceModel);
  if (!contentModel || link.scheme() != QLatin1String("qthelp"))
    return QModelIndex();

  m_syncIndex = QModelIndex();
  for (int i=0; i<contentModel->rowCount(); ++i)
  {
    QHelpContentItem *itm =
        contentModel->contentItemAt(contentModel->index(i, 0));
    if (itm && itm->url().host() == link.host())
    {
      QString path = link.path();
      if (path.startsWith(QLatin1Char('/')))
        path = path.mid(1);
      if (searchContentItem(contentModel, contentModel->index(i, 0), path))
      {
        return m_syncIndex;
      }
    }
  }
  return QModelIndex();
}

void HelpContentWidget::setModel(QAbstractItemModel *model)
{
  m_SourceModel = model;
  m_SortModel->setSourceModel(model);
}

bool HelpContentWidget::searchContentItem(QHelpContentModel *model,
                                          const QModelIndex &parent, const QString &path)
{
  QHelpContentItem *parentItem = model->contentItemAt(parent);
  if (!parentItem)
    return false;

  if (QDir::cleanPath(parentItem->url().path()) == path)
  {
    m_syncIndex = m_SortModel->mapFromSource(parent);
    return true;
  }

  for (int i=0; i<parentItem->childCount(); ++i)
  {
    if (searchContentItem(model, model->index(i, 0, parent), path))
      return true;
  }
  return false;
}

QUrl HelpContentWidget::GetUrl(const QModelIndex &index)
{
  QHelpContentModel *contentModel = qobject_cast<QHelpContentModel*>(m_SourceModel);
  if (!contentModel)
    return QUrl();

  QHelpContentItem *item = contentModel->contentItemAt(m_SortModel->mapToSource(index));
  if (!item)
    return QUrl();
  QUrl url = item->url();
    if (url.isValid())
      return url;
  return QUrl();
}

void HelpContentWidget::showLink(const QModelIndex &index)
{
  QHelpContentModel *contentModel = qobject_cast<QHelpContentModel*>(m_SourceModel);
  if (!contentModel)
    return;

  QHelpContentItem *item = contentModel->contentItemAt(m_SortModel->mapToSource(index));
  if (!item)
    return;
  QUrl url = item->url();
  if (url.isValid())
    emit linkActivated(url);
}

HelpContentView::HelpContentView()
  : m_ContentWidget(0)
{
}

HelpContentView::~HelpContentView()
{
}

void HelpContentView::CreateQtPartControl(QWidget* parent)
{
  if (m_ContentWidget == 0)
  {
    QVBoxLayout* verticalLayout = new QVBoxLayout(parent);
    verticalLayout->setSpacing(0);
    verticalLayout->setContentsMargins(0, 0, 0, 0);

    QHelpEngineWrapper& helpEngine = HelpPluginActivator::getInstance()->getQHelpEngine();
    m_ContentWidget = new HelpContentWidget();
    m_ContentWidget->setModel(helpEngine.contentModel());
    m_ContentWidget->sortByColumn(0, Qt::AscendingOrder);
    connect(helpEngine.contentModel(), SIGNAL(contentsCreationStarted()),
            this, SLOT(setContentsWidgetBusy()));
    connect(helpEngine.contentModel(), SIGNAL(contentsCreated()),
            this, SLOT(unsetContentsWidgetBusy()));
    verticalLayout->addWidget(m_ContentWidget);

    m_ContentWidget->setContextMenuPolicy(Qt::CustomContextMenu);

    connect(m_ContentWidget, SIGNAL(customContextMenuRequested(QPoint)),
            this, SLOT(showContextMenu(QPoint)));
    connect(m_ContentWidget, SIGNAL(linkActivated(QUrl)), this, SLOT(linkActivated(QUrl)));
  }
}

void HelpContentView::linkActivated(const QUrl &link)
{
  IWorkbenchPage::Pointer page = this->GetSite()->GetPage();
  HelpPluginActivator::linkActivated(page, link);
}

void HelpContentView::showContextMenu(const QPoint &pos)
{
  if (!m_ContentWidget->indexAt(pos).isValid())
      return;

  QModelIndex index = m_ContentWidget->indexAt(pos);
  QUrl url = m_ContentWidget->GetUrl(index);

  QMenu menu;
  QAction *curTab = menu.addAction(tr("Open Link"));
  QAction *newTab = menu.addAction(tr("Open Link in New Tab"));

  if (!HelpWebView::canOpenPage(url.path()))
    newTab->setEnabled(false);

  menu.move(m_ContentWidget->mapToGlobal(pos));

  QAction *action = menu.exec();
  if (curTab == action)
  {
    linkActivated(url);
  }
  else if (newTab == action)
  {
    IEditorInput::Pointer input(new HelpEditorInput(url));
    this->GetSite()->GetPage()->OpenEditor(input, HelpEditor::EDITOR_ID);
  }
}

void HelpContentView::SetFocus()
{
  m_ContentWidget->setFocus();
}

void HelpContentView::setContentsWidgetBusy()
{
  m_ContentWidget->setCursor(Qt::WaitCursor);
}

void HelpContentView::unsetContentsWidgetBusy()
{
  m_ContentWidget->unsetCursor();
}

}
<commit_msg>Added clicked signal to allow loading of help content with single-click.<commit_after>/*===================================================================

BlueBerry Platform

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#ifdef __MINGW32__
// We need to inlclude winbase.h here in order to declare
// atomic intrinsics like InterlockedIncrement correctly.
// Otherwhise, they would be declared wrong within qatomic_windows.h .
#include <windows.h>
#endif

#include "berryHelpContentView.h"

#include "berryHelpPluginActivator.h"
#include "berryHelpEditor.h"
#include "berryHelpEditorInput.h"
#include "berryHelpWebView.h"
#include "berryQHelpEngineWrapper.h"

#include <berryIWorkbenchPage.h>

#include <QSortFilterProxyModel>
#include <QHelpContentWidget>
#include <QLayout>
#include <QMenu>
#include <QHeaderView>
#include <QDir>

namespace berry {

HelpContentWidget::HelpContentWidget()
  : QTreeView(0)
  , m_SortModel(new QSortFilterProxyModel(this))
  , m_SourceModel(0)
{
  header()->hide();
  setUniformRowHeights(true);
  connect(this, SIGNAL(activated(QModelIndex)),
          this, SLOT(showLink(QModelIndex)));
  connect(this, SIGNAL(clicked(QModelIndex)),
          this, SLOT(showLink(QModelIndex)));

  m_SortModel->setDynamicSortFilter(true);
  QTreeView::setModel(m_SortModel);
}

QModelIndex HelpContentWidget::indexOf(const QUrl &link)
{
  QHelpContentModel *contentModel =
      qobject_cast<QHelpContentModel*>(m_SourceModel);
  if (!contentModel || link.scheme() != QLatin1String("qthelp"))
    return QModelIndex();

  m_syncIndex = QModelIndex();
  for (int i=0; i<contentModel->rowCount(); ++i)
  {
    QHelpContentItem *itm =
        contentModel->contentItemAt(contentModel->index(i, 0));
    if (itm && itm->url().host() == link.host())
    {
      QString path = link.path();
      if (path.startsWith(QLatin1Char('/')))
        path = path.mid(1);
      if (searchContentItem(contentModel, contentModel->index(i, 0), path))
      {
        return m_syncIndex;
      }
    }
  }
  return QModelIndex();
}

void HelpContentWidget::setModel(QAbstractItemModel *model)
{
  m_SourceModel = model;
  m_SortModel->setSourceModel(model);
}

bool HelpContentWidget::searchContentItem(QHelpContentModel *model,
                                          const QModelIndex &parent, const QString &path)
{
  QHelpContentItem *parentItem = model->contentItemAt(parent);
  if (!parentItem)
    return false;

  if (QDir::cleanPath(parentItem->url().path()) == path)
  {
    m_syncIndex = m_SortModel->mapFromSource(parent);
    return true;
  }

  for (int i=0; i<parentItem->childCount(); ++i)
  {
    if (searchContentItem(model, model->index(i, 0, parent), path))
      return true;
  }
  return false;
}

QUrl HelpContentWidget::GetUrl(const QModelIndex &index)
{
  QHelpContentModel *contentModel = qobject_cast<QHelpContentModel*>(m_SourceModel);
  if (!contentModel)
    return QUrl();

  QHelpContentItem *item = contentModel->contentItemAt(m_SortModel->mapToSource(index));
  if (!item)
    return QUrl();
  QUrl url = item->url();
    if (url.isValid())
      return url;
  return QUrl();
}

void HelpContentWidget::showLink(const QModelIndex &index)
{
  QHelpContentModel *contentModel = qobject_cast<QHelpContentModel*>(m_SourceModel);
  if (!contentModel)
    return;

  QHelpContentItem *item = contentModel->contentItemAt(m_SortModel->mapToSource(index));
  if (!item)
    return;
  QUrl url = item->url();
  if (url.isValid())
    emit linkActivated(url);
}

HelpContentView::HelpContentView()
  : m_ContentWidget(0)
{
}

HelpContentView::~HelpContentView()
{
}

void HelpContentView::CreateQtPartControl(QWidget* parent)
{
  if (m_ContentWidget == 0)
  {
    QVBoxLayout* verticalLayout = new QVBoxLayout(parent);
    verticalLayout->setSpacing(0);
    verticalLayout->setContentsMargins(0, 0, 0, 0);

    QHelpEngineWrapper& helpEngine = HelpPluginActivator::getInstance()->getQHelpEngine();
    m_ContentWidget = new HelpContentWidget();
    m_ContentWidget->setModel(helpEngine.contentModel());
    m_ContentWidget->sortByColumn(0, Qt::AscendingOrder);
    connect(helpEngine.contentModel(), SIGNAL(contentsCreationStarted()),
            this, SLOT(setContentsWidgetBusy()));
    connect(helpEngine.contentModel(), SIGNAL(contentsCreated()),
            this, SLOT(unsetContentsWidgetBusy()));
    verticalLayout->addWidget(m_ContentWidget);

    m_ContentWidget->setContextMenuPolicy(Qt::CustomContextMenu);

    connect(m_ContentWidget, SIGNAL(customContextMenuRequested(QPoint)),
            this, SLOT(showContextMenu(QPoint)));
    connect(m_ContentWidget, SIGNAL(linkActivated(QUrl)), this, SLOT(linkActivated(QUrl)));
  }
}

void HelpContentView::linkActivated(const QUrl &link)
{
  IWorkbenchPage::Pointer page = this->GetSite()->GetPage();
  HelpPluginActivator::linkActivated(page, link);
}

void HelpContentView::showContextMenu(const QPoint &pos)
{
  if (!m_ContentWidget->indexAt(pos).isValid())
      return;

  QModelIndex index = m_ContentWidget->indexAt(pos);
  QUrl url = m_ContentWidget->GetUrl(index);

  QMenu menu;
  QAction *curTab = menu.addAction(tr("Open Link"));
  QAction *newTab = menu.addAction(tr("Open Link in New Tab"));

  if (!HelpWebView::canOpenPage(url.path()))
    newTab->setEnabled(false);

  menu.move(m_ContentWidget->mapToGlobal(pos));

  QAction *action = menu.exec();
  if (curTab == action)
  {
    linkActivated(url);
  }
  else if (newTab == action)
  {
    IEditorInput::Pointer input(new HelpEditorInput(url));
    this->GetSite()->GetPage()->OpenEditor(input, HelpEditor::EDITOR_ID);
  }
}

void HelpContentView::SetFocus()
{
  m_ContentWidget->setFocus();
}

void HelpContentView::setContentsWidgetBusy()
{
  m_ContentWidget->setCursor(Qt::WaitCursor);
}

void HelpContentView::unsetContentsWidgetBusy()
{
  m_ContentWidget->unsetCursor();
}

}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_GEOMETRY_IS_EMPTY_HPP
#define MAPNIK_GEOMETRY_IS_EMPTY_HPP

#include <mapnik/geometry.hpp>

namespace mapnik { namespace geometry {

namespace detail {

struct geometry_is_empty
{
    bool operator() (mapnik::geometry::geometry<double> const& geom) const
    {
        return mapnik::util::apply_visitor(*this, geom);
    }

    bool operator() (mapnik::geometry::point<double> const&) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::line_string<double> const& geom) const
    {
        return geom.empty();
    }

    bool operator() (mapnik::geometry::polygon<double> const& geom) const
    {
        return geom.empty();
    }

    bool operator() (mapnik::geometry::multi_point<double> const& geom) const
    {
        return geom.empty();
    }

    bool operator() (mapnik::geometry::multi_line_string<double> const& geom) const
    {
        return geom.empty();
    }

    bool operator() (mapnik::geometry::multi_polygon<double> const& geom) const
    {
        return geom.empty();
    }

    bool operator() (mapnik::geometry::geometry_collection<double> const& geom) const
    {
        return geom.empty();
    }

    template <typename T>
    bool operator() (T const& geom) const
    {
        return true;
    }

};

struct geometry_has_empty
{
    bool operator() (mapnik::geometry::geometry<double> const& geom) const
    {
        return mapnik::util::apply_visitor(*this, geom);
    }

    bool operator() (mapnik::geometry::geometry_empty const&) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::point<double> const&) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::line_string<double> const& geom) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::polygon<double> const& geom) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::multi_point<double> const& geom) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::multi_line_string<double> const& geom) const
    {
        return test_multigeometry(geom);
    }

    bool operator() (mapnik::geometry::multi_polygon<double> const& geom) const
    {
        return test_multigeometry(geom);
    }

    bool operator() (mapnik::geometry::geometry_collection<double> const& geom) const
    {
        for (auto const & item : geom)
        {
            if (geometry_is_empty()(item) || (*this)(item))
            {
                return true;
            }
        }
        return false;
    }

    template <typename T>
    bool operator() (T const& geom) const
    {
        return true;
    }

private:
    template <typename T>
    bool test_multigeometry(T const & geom) const
    {
        for (auto const & item : geom)
        {
            if (item.empty())
            {
                return true;
            }
        }
        return false;
    }
};

}

template <typename GeomType>
inline bool is_empty(GeomType const& geom)
{
    return detail::geometry_is_empty()(geom);
}

template <typename GeomType>
inline bool has_empty(GeomType const& geom)
{
    return detail::geometry_has_empty()(geom);
}

}}

#endif // MAPNIK_GEOMETRY_IS_EMPTY_HPP
<commit_msg>fix multiple -Wunused-parameter warnings [skip ci]<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_GEOMETRY_IS_EMPTY_HPP
#define MAPNIK_GEOMETRY_IS_EMPTY_HPP

#include <mapnik/geometry.hpp>

namespace mapnik { namespace geometry {

namespace detail {

struct geometry_is_empty
{
    bool operator() (mapnik::geometry::geometry<double> const& geom) const
    {
        return mapnik::util::apply_visitor(*this, geom);
    }

    bool operator() (mapnik::geometry::point<double> const&) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::line_string<double> const& geom) const
    {
        return geom.empty();
    }

    bool operator() (mapnik::geometry::polygon<double> const& geom) const
    {
        return geom.empty();
    }

    bool operator() (mapnik::geometry::multi_point<double> const& geom) const
    {
        return geom.empty();
    }

    bool operator() (mapnik::geometry::multi_line_string<double> const& geom) const
    {
        return geom.empty();
    }

    bool operator() (mapnik::geometry::multi_polygon<double> const& geom) const
    {
        return geom.empty();
    }

    bool operator() (mapnik::geometry::geometry_collection<double> const& geom) const
    {
        return geom.empty();
    }

    template <typename T>
    bool operator() (T const&) const
    {
        return true;
    }

};

struct geometry_has_empty
{
    bool operator() (mapnik::geometry::geometry<double> const& geom) const
    {
        return mapnik::util::apply_visitor(*this, geom);
    }

    bool operator() (mapnik::geometry::geometry_empty const&) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::point<double> const&) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::line_string<double> const&) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::polygon<double> const&) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::multi_point<double> const&) const
    {
        return false;
    }

    bool operator() (mapnik::geometry::multi_line_string<double> const& geom) const
    {
        return test_multigeometry(geom);
    }

    bool operator() (mapnik::geometry::multi_polygon<double> const& geom) const
    {
        return test_multigeometry(geom);
    }

    bool operator() (mapnik::geometry::geometry_collection<double> const& geom) const
    {
        for (auto const & item : geom)
        {
            if (geometry_is_empty()(item) || (*this)(item))
            {
                return true;
            }
        }
        return false;
    }

    template <typename T>
    bool operator() (T const&) const
    {
        return true;
    }

private:
    template <typename T>
    bool test_multigeometry(T const & geom) const
    {
        for (auto const & item : geom)
        {
            if (item.empty())
            {
                return true;
            }
        }
        return false;
    }
};

}

template <typename GeomType>
inline bool is_empty(GeomType const& geom)
{
    return detail::geometry_is_empty()(geom);
}

template <typename GeomType>
inline bool has_empty(GeomType const& geom)
{
    return detail::geometry_has_empty()(geom);
}

}}

#endif // MAPNIK_GEOMETRY_IS_EMPTY_HPP
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2012 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <boost/cstdint.hpp>
#include "agg_span_image_filter_rgba.h"

namespace mapnik {

using namespace agg;

template<class Source>
class span_image_resample_rgba_affine :
        public span_image_resample_affine<Source>
{
public:
    typedef Source source_type;
    typedef typename source_type::color_type color_type;
    typedef typename source_type::order_type order_type;
    typedef span_image_resample_affine<source_type> base_type;
    typedef typename base_type::interpolator_type interpolator_type;
    typedef typename color_type::value_type value_type;
    typedef typename color_type::long_type long_type;
    enum base_scale_e
    {
        base_shift      = color_type::base_shift,
        base_mask       = color_type::base_mask,
        downscale_shift = image_filter_shift
    };

    //--------------------------------------------------------------------
    span_image_resample_rgba_affine() {}
    span_image_resample_rgba_affine(source_type& src,
                                    interpolator_type& inter,
                                    const image_filter_lut& filter) :
        base_type(src, inter, filter)
    {}

    //--------------------------------------------------------------------
    void generate(color_type* span, int x, int y, unsigned len)
    {
        base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
                                        y + base_type::filter_dy_dbl(), len);

        long_type fg[4];

        int diameter     = base_type::filter().diameter();
        int filter_scale = diameter << image_subpixel_shift;
        int radius_x     = (diameter * base_type::m_rx) >> 1;
        int radius_y     = (diameter * base_type::m_ry) >> 1;
        int len_x_lr     =
            (diameter * base_type::m_rx + image_subpixel_mask) >>
            image_subpixel_shift;

        const boost::int16_t* weight_array = base_type::filter().weight_array();

        do
        {
            base_type::interpolator().coordinates(&x, &y);

            x += base_type::filter_dx_int() - radius_x;
            y += base_type::filter_dy_int() - radius_y;

            fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2;

            int y_lr = y >> image_subpixel_shift;
            int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
                        base_type::m_ry_inv) >>
                image_subpixel_shift;
            int total_weight = 0;
            int x_lr = x >> image_subpixel_shift;
            int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
                        base_type::m_rx_inv) >>
                image_subpixel_shift;

            int x_hr2 = x_hr;
            const value_type* fg_ptr =
                (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
            for(;;)
            {
                int weight_y = weight_array[y_hr];
                x_hr = x_hr2;
                for(;;)
                {
                    int weight = (weight_y * weight_array[x_hr] +
                                  image_filter_scale / 2) >>
                        downscale_shift;

                    fg[0] += *fg_ptr++ * weight;
                    fg[1] += *fg_ptr++ * weight;
                    fg[2] += *fg_ptr++ * weight;
                    fg[3] += *fg_ptr   * weight;

                    total_weight += weight;
                    x_hr  += base_type::m_rx_inv;
                    if(x_hr >= filter_scale) break;
                    fg_ptr = (const value_type*)base_type::source().next_x();
                }
                y_hr += base_type::m_ry_inv;
                if(y_hr >= filter_scale) break;
                fg_ptr = (const value_type*)base_type::source().next_y();
            }

            if (total_weight)
            {
                fg[3] /= total_weight;
                fg[0] /= total_weight;
                fg[1] /= total_weight;
                fg[2] /= total_weight;

                if(fg[0] < 0) fg[0] = 0;
                if(fg[1] < 0) fg[1] = 0;
                if(fg[2] < 0) fg[2] = 0;
                if(fg[3] < 0) fg[3] = 0;
            }
            else
            {
                fg[0] = 0;
                fg[1] = 0;
                fg[2] = 0;
                fg[3] = 0;
            }

            if(fg[order_type::R] > base_mask)         fg[order_type::R] = base_mask;
            if(fg[order_type::G] > base_mask)         fg[order_type::G] = base_mask;
            if(fg[order_type::B] > base_mask)         fg[order_type::B] = base_mask;
            if(fg[order_type::A] > base_mask)         fg[order_type::A] = base_mask;

            span->r = (value_type)fg[order_type::R];
            span->g = (value_type)fg[order_type::G];
            span->b = (value_type)fg[order_type::B];
            span->a = (value_type)fg[order_type::A];

            ++span;
            ++base_type::interpolator();
        } while(--len);
    }
};
}
<commit_msg>restore pristine agg2.4 agg:span_image_resample_rgba_affine - refs #1227<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2012 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <boost/cstdint.hpp>
#include "agg_span_image_filter_rgba.h"

namespace mapnik {

using namespace agg;

template<class Source>
class span_image_resample_rgba_affine :
public span_image_resample_affine<Source>
{
public:
    typedef Source source_type;
    typedef typename source_type::color_type color_type;
    typedef typename source_type::order_type order_type;
    typedef span_image_resample_affine<source_type> base_type;
    typedef typename base_type::interpolator_type interpolator_type;
    typedef typename color_type::value_type value_type;
    typedef typename color_type::long_type long_type;
    enum base_scale_e
    {
        base_shift      = color_type::base_shift,
        base_mask       = color_type::base_mask,
        downscale_shift = image_filter_shift
    };

    //--------------------------------------------------------------------
    span_image_resample_rgba_affine() {}
    span_image_resample_rgba_affine(source_type& src,
                                    interpolator_type& inter,
                                    const image_filter_lut& filter) :
        base_type(src, inter, filter)
    {}

    //--------------------------------------------------------------------
    void generate(color_type* span, int x, int y, unsigned len)
    {
        base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
                                        y + base_type::filter_dy_dbl(), len);

        long_type fg[4];

        int diameter     = base_type::filter().diameter();
        int filter_scale = diameter << image_subpixel_shift;
        int radius_x     = (diameter * base_type::m_rx) >> 1;
        int radius_y     = (diameter * base_type::m_ry) >> 1;
        int len_x_lr     =
            (diameter * base_type::m_rx + image_subpixel_mask) >>
                image_subpixel_shift;

        const int16* weight_array = base_type::filter().weight_array();

        do
        {
            base_type::interpolator().coordinates(&x, &y);

            x += base_type::filter_dx_int() - radius_x;
            y += base_type::filter_dy_int() - radius_y;

            fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2;

            int y_lr = y >> image_subpixel_shift;
            int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) *
                            base_type::m_ry_inv) >>
                                image_subpixel_shift;
            int total_weight = 0;
            int x_lr = x >> image_subpixel_shift;
            int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) *
                            base_type::m_rx_inv) >>
                                image_subpixel_shift;

            int x_hr2 = x_hr;
            const value_type* fg_ptr =
                (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr);
            for(;;)
            {
                int weight_y = weight_array[y_hr];
                x_hr = x_hr2;
                for(;;)
                {
                    int weight = (weight_y * weight_array[x_hr] +
                                 image_filter_scale / 2) >>
                                 downscale_shift;

                    fg[0] += *fg_ptr++ * weight;
                    fg[1] += *fg_ptr++ * weight;
                    fg[2] += *fg_ptr++ * weight;
                    fg[3] += *fg_ptr++ * weight;
                    total_weight += weight;
                    x_hr  += base_type::m_rx_inv;
                    if(x_hr >= filter_scale) break;
                    fg_ptr = (const value_type*)base_type::source().next_x();
                }
                y_hr += base_type::m_ry_inv;
                if(y_hr >= filter_scale) break;
                fg_ptr = (const value_type*)base_type::source().next_y();
            }

            fg[0] /= total_weight;
            fg[1] /= total_weight;
            fg[2] /= total_weight;
            fg[3] /= total_weight;

            if(fg[0] < 0) fg[0] = 0;
            if(fg[1] < 0) fg[1] = 0;
            if(fg[2] < 0) fg[2] = 0;
            if(fg[3] < 0) fg[3] = 0;

            if(fg[order_type::A] > base_mask)         fg[order_type::A] = base_mask;
            if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A];
            if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A];
            if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A];

            span->r = (value_type)fg[order_type::R];
            span->g = (value_type)fg[order_type::G];
            span->b = (value_type)fg[order_type::B];
            span->a = (value_type)fg[order_type::A];

            ++span;
            ++base_type::interpolator();
        } while(--len);
    }
};
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_UTIL_IS_CLOCKWISE_HPP
#define MAPNIK_UTIL_IS_CLOCKWISE_HPP

#include <cassert>

namespace mapnik { namespace util {

template <typename T>
bool is_clockwise(T const& ring)
{
    double area = 0.0;
    std::size_t num_points = ring.size();
    assert(num_point > 2);
    double orig_x = ring[0].x;
    double orig_y = ring[0].y;
    for (std::size_t i = 0; i < num_points; ++i)
    {
        auto const& p0 = ring[i];
        auto const& p1 = ring[(i + 1) % num_points];
        double x0 = p0.x - orig_x;
        double y0 = p0.y - orig_y;
        double x1 = p1.x - orig_x;
        double y1 = p1.y - orig_y;
        area += x0 * y1 - x1 * y0;
    }
    return (area < 0.0) ? true : false;
}
}}

#endif //MAPNIK_UTIL_IS_CLOCKWISE_HPP
<commit_msg>fix debug assert compile<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_UTIL_IS_CLOCKWISE_HPP
#define MAPNIK_UTIL_IS_CLOCKWISE_HPP

#include <cassert>

namespace mapnik { namespace util {

template <typename T>
bool is_clockwise(T const& ring)
{
    double area = 0.0;
    std::size_t num_points = ring.size();
    assert(num_points > 2);
    double orig_x = ring[0].x;
    double orig_y = ring[0].y;
    for (std::size_t i = 0; i < num_points; ++i)
    {
        auto const& p0 = ring[i];
        auto const& p1 = ring[(i + 1) % num_points];
        double x0 = p0.x - orig_x;
        double y0 = p0.y - orig_y;
        double x1 = p1.x - orig_x;
        double y1 = p1.y - orig_y;
        area += x0 * y1 - x1 * y0;
    }
    return (area < 0.0) ? true : false;
}
}}

#endif //MAPNIK_UTIL_IS_CLOCKWISE_HPP
<|endoftext|>


<commit_before>/**
 * Copyright 2018 Sergei A. Fedorov
 * polar.hpp
 *
 *  Created on: Dec 30, 2018
 *      Author: ser-fedorov
 */

#ifndef PUSHKIN_MATH_POLAR_COORD_HPP_
#define PUSHKIN_MATH_POLAR_COORD_HPP_

#include <pushkin/math/angles.hpp>
#include <pushkin/math/detail/conversion.hpp>
#include <pushkin/math/detail/vector_expressions.hpp>

namespace psst {
namespace math {

namespace axes {

struct polar {
    static constexpr std::size_t min_components = 2;
    static constexpr std::size_t max_components = 2;
    static constexpr std::size_t rho            = 0;
    static constexpr std::size_t phi            = 1;
    static constexpr std::size_t r              = rho;
    static constexpr std::size_t azimuth        = phi;

    using value_policy = utils::template_tuple<math::value_policy::no_change,
                                               math::value_policy::clamp_zero_to_two_pi>;
};

//@{
/** @name Polar coordinates */
template <typename VectorType, typename T>
struct axis_access<2, polar, VectorType, T> : basic_axis_access<VectorType, T, polar> {
    using base_type = basic_axis_access<VectorType, T, polar>;

    PSST_MATH_COORD_ACCESS(r);
    PSST_MATH_COORD_ACCESS(rho);
    PSST_MATH_COORD_ACCESS(phi);
    PSST_MATH_COORD_ACCESS(azimuth);
};
//@}

}    // namespace axes

namespace expr {

inline namespace v {

//@{
/** @name Vector scalar muliply for polar coordinates */
template <typename LHS, typename RHS>
struct vector_scalar_multiply<axes::polar, LHS, RHS>
    : binary_vector_expression_axes<vector_scalar_multiply, axes::polar, LHS, RHS>,
      binary_expression<LHS, RHS> {
    using base_type  = binary_vector_expression_axes<vector_scalar_multiply, axes::polar, LHS, RHS>;
    using value_type = typename base_type::value_type;

    using expression_base = binary_expression<LHS, RHS>;
    using expression_base::expression_base;

    template <std::size_t N>
    constexpr value_type
    at() const
    {
        static_assert(N < base_type::size, "Vector multiply component index is out of range");
        if constexpr (N != axes::polar::rho) {
            // In polar coordinates only the first component (rho) is multiplied
            return this->lhs_.template at<N>();
        } else {
            return this->lhs_.template at<N>() * this->rhs_;
        }
    }
};

//@}
//@{
/** @name Vector scalar division for polar coordinates */
template <typename LHS, typename RHS>
struct vector_scalar_divide<axes::polar, LHS, RHS>
    : binary_vector_expression_axes<vector_scalar_divide, axes::polar, LHS, RHS>,
      binary_expression<LHS, RHS> {
    using base_type  = binary_vector_expression_axes<vector_scalar_divide, axes::polar, LHS, RHS>;
    using value_type = typename base_type::value_type;

    using expression_base = binary_expression<LHS, RHS>;
    using expression_base::expression_base;

    template <std::size_t N>
    constexpr value_type
    at() const
    {
        static_assert(N < base_type::size, "Vector divide component index is out of range");
        if constexpr (N != axes::polar::rho) {
            // In polar coordinates only the first component (rho) is divided
            return this->lhs_.template at<N>();
        } else {
            return this->lhs_.template at<N>() / this->rhs_;
        }
    }
};
//@}
//@{
/** @name Magnitude squared for polar coordinates */
template <typename Expr>
struct vector_magnitude_squared<axes::polar, Expr>
    : scalar_expression<vector_magnitude_squared<axes::polar, Expr>,
                        scalar_expression_result_t<Expr>>,
      unary_expression<Expr> {
    static_assert(is_vector_expression_v<Expr>, "Argument to magnitude must be a vector");

    using expression_base = unary_expression<Expr>;
    using expression_base::expression_base;

    constexpr auto
    value() const
    {
        return this->arg_.rho() * this->arg_.rho();
    }
};

//@}
//@{
/** @name Magnitude for polar coordinates */
template <typename Expr>
struct vector_magnitude<axes::polar, Expr>
    : scalar_expression<vector_magnitude<axes::polar, Expr>, scalar_expression_result_t<Expr>>,
      unary_expression<Expr> {
    static_assert(is_vector_expression_v<Expr>, "Argument to magnitude must be a vector");

    using expression_base = unary_expression<Expr>;
    using expression_base::expression_base;

    constexpr auto
    value() const
    {
        using std::abs;
        return abs(this->arg_.rho());
    }
};

//@}

//@{
template <typename Expr>
struct vector_normalize<axes::polar, Expr>
    : unary_vector_expression_axes<vector_normalize, axes::polar, Expr>, unary_expression<Expr> {
    using base_type       = unary_vector_expression_axes<vector_normalize, axes::polar, Expr>;
    using value_type      = typename base_type::value_type;
    using expression_base = unary_expression<Expr>;
    using expression_base::expression_base;

    template <std::size_t N>
    constexpr auto
    at() const
    {
        static_assert(N < base_type::size, "Vector normalize component index is out of range");
        if (N == axes::polar::rho) {
            return value_type{1};
        } else {
            if (this->arg_.rho() < 0) {
                return zero_to_two_pi(this->arg_.azimuth() + pi<value_type>::value);
            } else {
                return this->arg_.azimuth();
            }
        }
    }
};

//@}

//@{
/** @name Polar to XYZW conversion */
template <typename T, typename U, std::size_t Cartesian, typename Expression>
struct conversion<vector<T, 2, axes::polar>, vector<U, Cartesian, axes::xyzw>, Expression>
    : vector_conversion_expression<vector<T, 2, axes::polar>, vector<U, Cartesian, axes::xyzw>,
                                   Expression>,
      unary_expression<Expression> {
    using base_type = vector_conversion_expression<vector<T, 2, axes::polar>,
                                                   vector<U, Cartesian, axes::xyzw>, Expression>;

    using expression_base = unary_expression<Expression>;
    using expression_base::expression_base;

    template <std::size_t N>
    constexpr auto
    at() const
    {
        using std::cos;
        using std::sin;
        static_assert(N < base_type::size,
                      "Polar to XYZW conversion component index is out of bounds");
        if constexpr (N == axes::xyzw::x) {
            return this->arg_.rho() * cos(this->arg_.phi());
        } else if constexpr (N == axes::xyzw::y) {
            return this->arg_.rho() * sin(this->arg_.phi());
        } else {
            return T{0};
        }
    }
};
//@}

//@{
/** @name XYZW to polar conversion */
template <typename T, typename U, std::size_t Cartesian, typename Expression>
struct conversion<vector<U, Cartesian, axes::xyzw>, vector<T, 2, axes::polar>, Expression>
    : vector_conversion_expression<vector<U, Cartesian, axes::xyzw>, vector<T, 2, axes::polar>,
                                   Expression>,
      unary_expression<Expression> {
    using base_type = vector_conversion_expression<vector<U, Cartesian, axes::xyzw>,
                                                   vector<T, 2, axes::polar>, Expression>;

    using expression_base = unary_expression<Expression>;
    using expression_base::expression_base;

    template <std::size_t N>
    constexpr auto
    at() const
    {
        using std::atan2;
        static_assert(N < base_type::size,
                      "XYZW to polar conversion component index is out of bounds");
        if constexpr (N == axes::polar::rho) {
            return magnitude(this->arg_);
        } else if constexpr (N == axes::polar::azimuth) {
            return atan2(this->arg_.y(), this->arg_.x());
        }
    }
};
//@}

}    // namespace v

}    // namespace expr

template <typename T>
using polar_coord = vector<T, 2, axes::polar>;

}    // namespace math
}    // namespace psst

#endif /* PUSHKIN_MATH_POLAR_COORD_HPP_ */
<commit_msg>cc: clamp polar azimuth value when converting<commit_after>/**
 * Copyright 2018 Sergei A. Fedorov
 * polar.hpp
 *
 *  Created on: Dec 30, 2018
 *      Author: ser-fedorov
 */

#ifndef PUSHKIN_MATH_POLAR_COORD_HPP_
#define PUSHKIN_MATH_POLAR_COORD_HPP_

#include <pushkin/math/angles.hpp>
#include <pushkin/math/detail/conversion.hpp>
#include <pushkin/math/detail/vector_expressions.hpp>

namespace psst {
namespace math {

namespace axes {

struct polar {
    static constexpr std::size_t min_components = 2;
    static constexpr std::size_t max_components = 2;
    static constexpr std::size_t rho            = 0;
    static constexpr std::size_t phi            = 1;
    static constexpr std::size_t r              = rho;
    static constexpr std::size_t azimuth        = phi;

    using value_policy = utils::template_tuple<math::value_policy::no_change,
                                               math::value_policy::clamp_zero_to_two_pi>;
};

//@{
/** @name Polar coordinates */
template <typename VectorType, typename T>
struct axis_access<2, polar, VectorType, T> : basic_axis_access<VectorType, T, polar> {
    using base_type = basic_axis_access<VectorType, T, polar>;

    PSST_MATH_COORD_ACCESS(r);
    PSST_MATH_COORD_ACCESS(rho);
    PSST_MATH_COORD_ACCESS(phi);
    PSST_MATH_COORD_ACCESS(azimuth);
};
//@}

}    // namespace axes

namespace expr {

inline namespace v {

//@{
/** @name Vector scalar muliply for polar coordinates */
template <typename LHS, typename RHS>
struct vector_scalar_multiply<axes::polar, LHS, RHS>
    : binary_vector_expression_axes<vector_scalar_multiply, axes::polar, LHS, RHS>,
      binary_expression<LHS, RHS> {
    using base_type  = binary_vector_expression_axes<vector_scalar_multiply, axes::polar, LHS, RHS>;
    using value_type = typename base_type::value_type;

    using expression_base = binary_expression<LHS, RHS>;
    using expression_base::expression_base;

    template <std::size_t N>
    constexpr value_type
    at() const
    {
        static_assert(N < base_type::size, "Vector multiply component index is out of range");
        if constexpr (N != axes::polar::rho) {
            // In polar coordinates only the first component (rho) is multiplied
            return this->lhs_.template at<N>();
        } else {
            return this->lhs_.template at<N>() * this->rhs_;
        }
    }
};

//@}
//@{
/** @name Vector scalar division for polar coordinates */
template <typename LHS, typename RHS>
struct vector_scalar_divide<axes::polar, LHS, RHS>
    : binary_vector_expression_axes<vector_scalar_divide, axes::polar, LHS, RHS>,
      binary_expression<LHS, RHS> {
    using base_type  = binary_vector_expression_axes<vector_scalar_divide, axes::polar, LHS, RHS>;
    using value_type = typename base_type::value_type;

    using expression_base = binary_expression<LHS, RHS>;
    using expression_base::expression_base;

    template <std::size_t N>
    constexpr value_type
    at() const
    {
        static_assert(N < base_type::size, "Vector divide component index is out of range");
        if constexpr (N != axes::polar::rho) {
            // In polar coordinates only the first component (rho) is divided
            return this->lhs_.template at<N>();
        } else {
            return this->lhs_.template at<N>() / this->rhs_;
        }
    }
};
//@}
//@{
/** @name Magnitude squared for polar coordinates */
template <typename Expr>
struct vector_magnitude_squared<axes::polar, Expr>
    : scalar_expression<vector_magnitude_squared<axes::polar, Expr>,
                        scalar_expression_result_t<Expr>>,
      unary_expression<Expr> {
    static_assert(is_vector_expression_v<Expr>, "Argument to magnitude must be a vector");

    using expression_base = unary_expression<Expr>;
    using expression_base::expression_base;

    constexpr auto
    value() const
    {
        return this->arg_.rho() * this->arg_.rho();
    }
};

//@}
//@{
/** @name Magnitude for polar coordinates */
template <typename Expr>
struct vector_magnitude<axes::polar, Expr>
    : scalar_expression<vector_magnitude<axes::polar, Expr>, scalar_expression_result_t<Expr>>,
      unary_expression<Expr> {
    static_assert(is_vector_expression_v<Expr>, "Argument to magnitude must be a vector");

    using expression_base = unary_expression<Expr>;
    using expression_base::expression_base;

    constexpr auto
    value() const
    {
        using std::abs;
        return abs(this->arg_.rho());
    }
};

//@}

//@{
template <typename Expr>
struct vector_normalize<axes::polar, Expr>
    : unary_vector_expression_axes<vector_normalize, axes::polar, Expr>, unary_expression<Expr> {
    using base_type       = unary_vector_expression_axes<vector_normalize, axes::polar, Expr>;
    using value_type      = typename base_type::value_type;
    using expression_base = unary_expression<Expr>;
    using expression_base::expression_base;

    template <std::size_t N>
    constexpr auto
    at() const
    {
        static_assert(N < base_type::size, "Vector normalize component index is out of range");
        if (N == axes::polar::rho) {
            return value_type{1};
        } else {
            if (this->arg_.rho() < 0) {
                return zero_to_two_pi(this->arg_.azimuth() + pi<value_type>::value);
            } else {
                return this->arg_.azimuth();
            }
        }
    }
};

//@}

//@{
/** @name Polar to XYZW conversion */
template <typename T, typename U, std::size_t Cartesian, typename Expression>
struct conversion<vector<T, 2, axes::polar>, vector<U, Cartesian, axes::xyzw>, Expression>
    : vector_conversion_expression<vector<T, 2, axes::polar>, vector<U, Cartesian, axes::xyzw>,
                                   Expression>,
      unary_expression<Expression> {
    using base_type = vector_conversion_expression<vector<T, 2, axes::polar>,
                                                   vector<U, Cartesian, axes::xyzw>, Expression>;

    using expression_base = unary_expression<Expression>;
    using expression_base::expression_base;

    template <std::size_t N>
    constexpr auto
    at() const
    {
        using std::cos;
        using std::sin;
        static_assert(N < base_type::size,
                      "Polar to XYZW conversion component index is out of bounds");
        if constexpr (N == axes::xyzw::x) {
            return this->arg_.rho() * cos(this->arg_.phi());
        } else if constexpr (N == axes::xyzw::y) {
            return this->arg_.rho() * sin(this->arg_.phi());
        } else {
            return T{0};
        }
    }
};
//@}

//@{
/** @name XYZW to polar conversion */
template <typename T, typename U, std::size_t Cartesian, typename Expression>
struct conversion<vector<U, Cartesian, axes::xyzw>, vector<T, 2, axes::polar>, Expression>
    : vector_conversion_expression<vector<U, Cartesian, axes::xyzw>, vector<T, 2, axes::polar>,
                                   Expression>,
      unary_expression<Expression> {
    using base_type = vector_conversion_expression<vector<U, Cartesian, axes::xyzw>,
                                                   vector<T, 2, axes::polar>, Expression>;

    using expression_base = unary_expression<Expression>;
    using expression_base::expression_base;

    template <std::size_t N>
    constexpr auto
    at() const
    {
        using std::atan2;
        static_assert(N < base_type::size,
                      "XYZW to polar conversion component index is out of bounds");
        if constexpr (N == axes::polar::rho) {
            return magnitude(this->arg_);
        } else if constexpr (N == axes::polar::azimuth) {
            return zero_to_two_pi(atan2(this->arg_.y(), this->arg_.x()));
        }
    }
};
//@}

}    // namespace v

}    // namespace expr

template <typename T>
using polar_coord = vector<T, 2, axes::polar>;

}    // namespace math
}    // namespace psst

#endif /* PUSHKIN_MATH_POLAR_COORD_HPP_ */
<|endoftext|>


<commit_before>#ifndef GENERICPLANET_HPP
#define GENERICPLANET_HPP

#include "glload/gl_3_2.h"
#include <glm/glm.hpp>

#include "sceneitems/planet.hpp"

#include "modelloader/vertexbuffer.hpp"

namespace sceneitems {
	class GenericPlanet : public sceneitems::Planet {
		private:
			GLuint colourUBO;
		public:
			/**
			 * Constructor.
			 *
			 * @param initialLocation The initial location of this planet.
			 * @param mySize Size in 10km-radius increments.
			 * @param density Density multiplier.
			 */
			GenericPlanet(glm::vec3 initialLocation, unsigned int mySize);

			virtual void render(glm::mat4& parentMatrix) const override;
	};
}

#endif // GENERICPLANET_HPP
<commit_msg>Remove outdated code documentation and unused include<commit_after>#ifndef GENERICPLANET_HPP
#define GENERICPLANET_HPP

#include "glload/gl_3_2.h"
#include <glm/glm.hpp>

#include "sceneitems/planet.hpp"

namespace sceneitems {
	class GenericPlanet : public sceneitems::Planet {
		private:
			GLuint colourUBO;
		public:
			/**
			 * Constructor.
			 *
			 * @param initialLocation The initial location of this planet.
			 * @param mySize Size in 10km-radius increments.
			 */
			GenericPlanet(glm::vec3 initialLocation, unsigned int mySize);

			virtual void render(glm::mat4& parentMatrix) const override;
	};
}

#endif // GENERICPLANET_HPP
<|endoftext|>