Skip to content

Instantly share code, notes, and snippets.

@avasilkov
Last active January 27, 2016 15:09
Show Gist options
  • Select an option

  • Save avasilkov/8132266273a7edefe6df to your computer and use it in GitHub Desktop.

Select an option

Save avasilkov/8132266273a7edefe6df to your computer and use it in GitHub Desktop.
#ifndef ARCPLACER_H
#define ARCPLACER_H
#include <math.h>
#define loopy(i, n) for(unsigned int i = 0; i < n; i++)
static inline float posMod(float a, float n){
return a - n * floor(a/n);
}
//-180 to 180
inline float normalizeAngle(float angle){
return posMod(angle + M_PI, pi2) - M_PI;
}
//-180 to 180
inline float angleDiff(float angleFrom, float angleTo){
return normalizeAngle(angleTo - angleFrom);//yep, in reverse order
}
struct Arc{
float& cAngle;//current
float pAngle;//preferred
float size;
float hs;//half size
Arc(float& _cAngle, float _pAngle, float _size):
cAngle(_cAngle), pAngle(posMod(_pAngle, pi2)), size(_size), hs(_size*0.5f){
cAngle = pAngle;
}
inline float getStart(){
return cAngle - hs;
}
inline float getEnd(){
return cAngle + hs;
}
//http://mathforum.org/library/drmath/view/67287.html
//CCW ORDER + //size less than 360!//pi2 and positive!
inline bool overlaps(Arc& arc){
float thisStart = getStart();
float c = posMod(arc.getStart() - thisStart, pi2);
return size > c || c > posMod(arc.getEnd() - thisStart, pi2);
}
inline void set(float _pAngle, float _size){
pAngle = posMod(_pAngle, pi2);
cAngle = pAngle;
size = _size;
hs = size*0.5f;
}
};
struct ArcPlacer{
std::vector<Arc> arcs;
ArcPlacer()=default;
void add(float& angleDestRef, float preferredAngle, float arcSize);
std::vector<int> getOverlapped(Arc& arc, int pos);
~ArcPlacer() = default;
};
#endif
#include "arcplacer.h"
#include <fstream>
int main (int argc, char *argv[])
{
std::ofstream data;
data.open ("data.txt", std::ios::out | std::ios::trunc);
ArcPlacer placer;
std::vector<float> placedAngles;
placedAngles.resize(20);
float toRad = M_PI/180;
placer.add(placedAngles[0], 0, 1*toRad);
placer.add(placedAngles[1], 0, 1*toRad);
placer.add(placedAngles[2], 0, 1*toRad);
placer.add(placedAngles[3], M_PI, 20*toRad);
placer.add(placedAngles[4], M_PI, 1*toRad);
placer.add(placedAngles[5], M_PI, 1*toRad);
placer.add(placedAngles[6], M_PI, 1*toRad);
placer.add(placedAngles[7], 0, 1*toRad);
placer.add(placedAngles[8], 0, 1*toRad);
placer.add(placedAngles[9], 0, 1*toRad);
placer.add(placedAngles[10], 0, 1*toRad);
placer.add(placedAngles[11], 0, 20*toRad);
placer.add(placedAngles[12], 0, 1*toRad);
placer.add(placedAngles[13], 0, 1*toRad);
placer.add(placedAngles[14], 0, 1*toRad);
placer.add(placedAngles[15], 0, 1*toRad);
loopy(i, placer.arcs.size()){
data<<placedAngles[i]<<"\n";
}
data.close();
return 0;
}
#include "arcplacer.h"
void ArcPlacer::add ( float& angleDestRef, float preferredAngle, float arcSize ) {
Arc arc(angleDestRef, preferredAngle, arcSize);
std::vector<int> ovs = getOverlapped(arc, -1);//overlapped arcs
if(ovs.size() == 0){
arcs.push_back(arc);
return;
}
float dummy;
Arc buffArc(dummy, 0.0f, 0.0f);
int iterCount = 0;
float refAngle = arc.cAngle;
while(iterCount++ < 360){
float cAngle = normalizeAngle(arc.pAngle - refAngle);
float size = arc.size;
for(int i : ovs){
cAngle += normalizeAngle(arcs[i].pAngle - refAngle);
size += arcs[i].size;
}
cAngle /= ovs.size() + 1.0f;
cAngle += refAngle;
cAngle = posMod(cAngle, pi2);
refAngle = cAngle;
buffArc.set(cAngle, size);
std::vector<int> ovsBefore = std::move(ovs);
ovs = getOverlapped(buffArc, -1);
if(ovs.size() != ovsBefore.size()){
continue;
}
bool stopIter = true;
loopy(i, ovs.size()){
if(ovs[i] != ovsBefore[i]){
stopIter = false;
break;
}
}
if(stopIter){
iterCount = 10000;
break;
}
}
arcs.push_back(arc);
ovs.push_back(arcs.size() - 1);
auto& _arcs = arcs;
std::sort(ovs.begin(), ovs.end(),
[buffArc, _arcs](const int a, const int b){
return angleDiff(buffArc.cAngle, _arcs[a].pAngle) < angleDiff(buffArc.cAngle, _arcs[b].pAngle);
}
);
float startAngle = buffArc.cAngle - buffArc.hs;
loopy(i, ovs.size()){
Arc& _arc = arcs[ovs[i]];
startAngle += _arc.size;
_arc.cAngle = startAngle - _arc.hs;
}
}
std::vector< int > ArcPlacer::getOverlapped ( Arc& arc, int pos ) {
std::vector<int> res;
loopy(i, arcs.size()){
if(arc.overlaps(arcs[i]) && pos != i){
res.push_back(i);
}
}
return res;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment