javascript - 2-डी ज्योमेट्री के लिए एक बाधा समाधान कैसे लागू करें?



algorithm geometry (1)

मैं this तरह के क्षेत्र दृष्टिकोण की कोशिश करेंगे।

  1. प्रत्येक स्लाइडर सभी स्लाइडर्स को पीछे हटा देगा

    दूरी ^ 2 से बढ़े हुए बल के साथ उन सभी की तरह एक ही ध्रुवीयता विद्युत आवेश या स्प्रिंग्स एक दूसरे के बीच जुड़े होंगे।

  2. शीर्ष पर गति द्वारा स्केल किए गए घर्षण जोड़ें

    वास्तव में कोई फर्क नहीं पड़ता अगर वायु v^2 या तरल v^3

  3. गतिज बाधाओं को लागू करें

    क्षैतिज और ऊर्ध्वाधर के लिए केवल फिसलने से यह वास्तव में आसान होना चाहिए।

  4. भौतिक अनुकरण करें और तब तक प्रतीक्षा करें जब तक यह स्थिर अवस्था v=~0 परिवर्तित न हो जाए

    अगर हिट स्थानीय मिनट / अधिकतम पूरी बात को थोड़ा हिला देता है या पूरी चीज को यादृच्छिक रूप से व्यवस्थित करता है और फिर से कोशिश करता है। आप एक और समाधान प्राप्त करने के लिए भी ऐसा कर सकते हैं।

[Edit4] C ++ सॉल्वर उदाहरण

  1. स्लाइडर प्रणाली का प्रतिनिधित्व करने के लिए संरचनाएं / कक्षाएं

    बाद के कोड को कम करने के लिए मैं बंद छोरों या दोहरी एंकरिंग का समर्थन नहीं करूंगा। यही कारण है कि i1 स्लाइडर (सबसे सही) किसी भी चीज़ के लिए लंगर नहीं डाला जाता है (केवल बल प्रदान करेगा)। मैं इस स्लाइडर परिभाषा के साथ समाप्त हुआ:

    अधिक जानकारी के लिए class _slider के स्रोत को देखें।

  2. प्रस्तुत करना

    डैश-डैश का अर्थ है निश्चित स्लाइडर। चांदी वाले क्षैतिज होते हैं, एक्वा का मतलब है ऊर्ध्वाधर और पीला माउस द्वारा चुना जाता है। बाद में लाल हो सकता है मतलब डिबग उद्देश्यों के लिए किसी प्रकार की त्रुटि / अटक या कुछ होगा। फोर्स फील्ड सॉल्वर्स के लिए मैं कभी-कभी फील्ड की ताकत को लाल-नीले पैमाने के रूप में जोड़ता हूं, लेकिन यह सुनिश्चित नहीं करता कि मैं इसे यहां लागू करूंगा या नहीं।

    इस सरल को बनाए रखने के लिए मैं ज़ूम / पैन फ़ंक्शंस लागू नहीं करूंगा क्योंकि आपके आयाम बिना ट्रांसफ़ॉर्म किए सीधे रेंडर के लिए सुविधाजनक हैं।

  3. प्रारंभिक सेटअप लागू करें

    sliders sys;
    int i0,i1,a0,a1,a2,a3,a4,b1,b2,b3,b4,b5;
    sys.slider_beg();//ia,ib,   x,    y,    a0,    a1,    b0,    b1,_horizontal
    i0=sys.slider_add(-1,-1, 25.0, 25.0,  -5.0, 405.0,   0.0,   0.0, 0);
    a0=sys.slider_add(i0,-1,  0.0,  0.0,   0.0, 400.0,   0.0,   0.0, 1);
    a1=sys.slider_add(i0,-1,  0.0,100.0,   0.0, 400.0,   0.0,   0.0, 1);
    a2=sys.slider_add(i0,-1,  0.0,200.0,   0.0, 400.0,   0.0,   0.0, 1);
    a3=sys.slider_add(i0,-1,  0.0,300.0,   0.0, 400.0,   0.0,   0.0, 1);
    a4=sys.slider_add(i0,-1,  0.0,400.0,   0.0, 400.0,   0.0,   0.0, 1);
    b1=sys.slider_add(a0,a2, 20.0,  0.0,   0.0, 125.0, 125.0, 250.0, 0);
    b2=sys.slider_add(a3,-1, 40.0,  0.0, -70.0,  30.0,   0.0,   0.0, 0);
    b3=sys.slider_add(a1,-1, 60.0,  0.0, -70.0,  30.0,   0.0,   0.0, 0);
    b4=sys.slider_add(a2,-1, 80.0,  0.0, -30.0,  70.0,   0.0,   0.0, 0);
    b5=sys.slider_add(a3,a1,100.0,  0.0,-125.0,   0.0,-125.0,-250.0, 0);
    i1=sys.slider_add(-1,-1,425.0, 25.0,  -5.0, 405.0,   0.0,   0.0, 0);
    sys.slider_end();

    ia माता-पिता सूचकांक है और ib चाइल्ड इंडेक्स है (स्लाइडर वर्ग स्वयं को माता-पिता के रूप में रखता है, लेकिन यह init के लिए भ्रामक होगा, क्योंकि आपको आइटम से लिंक करने की आवश्यकता होगी जो अभी तक मौजूद नहीं है, इसलिए ib परिवर्तन sys.add में संभाला गया है। समारोह)। sys पूरी चीज को पकड़कर रखने वाला वर्ग है। sys.add सिर्फ नया स्लाइडर जोड़ते हैं और शून्य से इसकी इंडेक्स काउंटिंग लौटाते हैं। x,y माता-पिता के सापेक्ष स्थिति है।

    कोडिंग की मात्रा को कम करने के लिए इस सेटअप को बाधाओं का सामना नहीं करना चाहिए। इस सेटअप का अवलोकन पिछली बुलेट में है।

    सही अवरोध क्षमता सुनिश्चित करने के लिए क्षैतिज स्लाइडर्स के लिए ऊर्ध्वाधर और ऊपर से नीचे के लिए स्लाइडर्स के क्रम को बाएं से दाएं छोड़ दिया जाना चाहिए।

  4. माउस बातचीत

    डिबग के लिए सिर्फ साधारण स्लाइडर आंदोलन और प्रारंभिक सेटअप मूल्यों को समायोजित करना। और अटके हुए मामलों को संभालना। यदि आप पहले से ही संपादन नहीं करते हैं, तो आपको माउस ईवेंट को संभालना होगा, निकटतम स्लाइडर का चयन करना होगा। और अगर माउस बटन दबाया जाता है तो चयनित स्लाइडर माउस स्थिति में ...

  5. शारीरिक बाधा / बातचीत

    मैं इसे थोड़ा सरल करता हूं इसलिए मैंने केवल एक समर्पित फ़ंक्शन बनाया जो निर्दिष्ट स्लाइडर के लिए कहा जाता है और अगर यह या इसके किसी बच्चे / एंकर परिभाषित बाधाओं के साथ संघर्ष में है तो यह वापस आ जाता है। यह कोड और डिबग करने के लिए बहुत आसान है फिर वास्तविक बाधा से मेल खाने की स्थिति को अपडेट करने के लिए।

    उपयोग फिर थोड़ा अधिक कोड है। अद्यतन स्लाइडर के लिए पहले वास्तविक स्थिति संग्रहीत करें। फिर स्लाइडर को नई स्थिति / स्थिति में अपडेट करें। उसके बाद अगर बाधाओं को पूरा नहीं किया जाता है तो वास्तविक स्लाइडर गति को रोकें और अपनी मूल स्थिति को बहाल करें।

    यह थोड़ा धीमा होगा लेकिन मैं पूर्ण बाधा अद्यतनकर्ता को कोड करने के लिए बहुत आलसी हूं (यह कोड वास्तव में जटिल हो सकता है ...)।

    मैं समानांतर और लंबवत 2 बातचीत को पहचानता हूं। समानांतर सीधे आगे है। लेकिन लंबवत प्रारंभिक अवस्था के दौरान स्लाइडर के किनारे और लंबवत स्लाइडर्स के बीच बातचीत होती है, जिसमें पहले से इंटरसेक्टिंग स्लाइडर्स (ए, बी लंगर या सिर्फ क्रॉसिंग) शामिल नहीं है। इसलिए मैंने शुरुआत में स्लाइडर्स ( ic ) को इंटरसेक्ट करने की एक सूची बनाई जिसे इस बातचीत के लिए नजरअंदाज कर दिया जाएगा।

  6. शारीरिक अनुकरण

    सरल न्यूटन - गैर सापेक्ष गति के लिए डी 'एलेबर्ट भौतिकी करेंगे। बस प्रत्येक पुनरावृत्ति पर त्वरण ax,ay क्षेत्र शक्ति और घर्षण के लिए निर्धारित किया है।

  7. फ़ील्ड सॉल्वर

    यह प्रत्येक स्लाइडर के समाधान के लिए अभिसरण के लिए सिमुलेशन त्वरण सेट करने के लिए नियमों / समीकरणों का सेट है। मैंने इलेक्ट्रोस्टैटिक पीछे हटने वाले बल F = -Q/r^2 और गति के रैखिक चक्कर के साथ समाप्त किया। संख्यात्मक समस्याओं से बचने के लिए पूर्ण वेग और त्वरण सीमाएँ भी लागू की हैं।

    समाधान समय और स्थिरता को बढ़ावा देने के लिए मैंने सटीक नियंत्रण मोड जोड़ा जहां इलेक्ट्रिक चार्ज कम हो रहा है जब स्लाइडर्स की अधिकतम अधिकतम गति कम हो रही है।

यहां इसके लिए पूर्ण C ++ / VCL वर्ग कोड:

//---------------------------------------------------------------------------
//--- Sliders solver ver: 1.01 ----------------------------------------------
//---------------------------------------------------------------------------
#ifndef _sliders_h
#define _sliders_h
//---------------------------------------------------------------------------
#include <math.h>
#include "list.h"   // linear dynamic array template List<T> similar to std::vector
//---------------------------------------------------------------------------
const double _slider_w   =   3.00;  // [px] slider half width (for rendering)
const double _slider_gap =   4.00;  // [px] min gap between sliders (for colisions)
const double _acc_limit=   100.00;  // [px/s^2]
const double _vel_limit=   100.00;  // [px/s]
const double _friction =     0.90;  // [-]
const double _charge   =250000.00;  // [px^3/s^2]
//---------------------------------------------------------------------------
class _slider   // one slider (helper class)
    {
public:
    // properties
    double x,y;             // actual relative pos
    bool _horizontal;       // orientation
    double a0,a1;           // slider vertexes 0 is anchor point
    double b0,b1;           // anchor zone for another slider
    int ia;                 // -1 for fixed or index of parrent slider
    int ib;                 // -1 or index of parrent slider
    // computed
    List<int> ic;           // list of slider indexes to ignore for perpendicular constraints
    double a,b;             // force field affected part
    double X,Y;             // actual absolute position
    double vx,vy,ax,ay;     // actual relative vel,acc
    // temp
    int flag;               // temp flag for simulation
    double x0,x1;           // temp variables for solver
    // constructors (can ignore this)
    _slider()           {}
    _slider(_slider& a) { *this=a; }
    ~_slider()          {}
    _slider* operator = (const _slider *a) { *this=*a; return this; }
    //_slider* operator = (const _slider &a) { ...copy... return this; }
    };
//---------------------------------------------------------------------------
class sliders   // whole slider system main class
    {
public:
    List<_slider> slider;           // list of sliders

    double vel_max;                 // max abs velocity of sliders for solver precision control
    double charge;                  // actual charge of sliders for solve()
    int    mode;                    // actual solution precision control mode

    // constructors (can ignore this)
    sliders();
    sliders(sliders& a) { *this=a; }
    ~sliders()          {}
    sliders* operator = (const sliders *a) { *this=*a; return this; }
    //sliders* operator = (const sliders &a) { ...copy... return this; }

    // VCL window API variables (can ignore this)
    double mx0,my0,mx1,my1; // last and actual mouse position
    TShiftState sh0,sh1;    // last and actual mouse buttons and control keys state
    int sel;

    // API (this is important stuff)
    void slider_beg(){ slider.num=0; }  // clear slider list
    int  slider_add(int ia,int ib,double x,double y,double a0,double a1,double b0,double b1,bool _h); // add slider to list
    void slider_end();              // compute slider parameters
    bool constraints(int ix);       // return true if constraints hit
    void positions();               // recompute absolute positions
    void update(double dt);         // update physics simulation with time step dt [sec]
    void solve(bool _init=false);   // set sliders accelerations to solve this
    void stop();                    // stop all movements
    // VCL window API for interaction with GUI (can ignore this)
    void mouse(int x,int y,TShiftState sh);
    void draw(TCanvas *scr);
    };
//---------------------------------------------------------------------------
sliders::sliders()
    {
    mx0=0.0; my0=0.0;
    mx1=0.0; my1=0.0;
    sel=-1;
    }
//---------------------------------------------------------------------------
int sliders::slider_add(int ia,int ib,double x,double y,double a0,double a1,double b0,double b1,bool _h)
    {
    _slider s; double q;
    if (a0>a1) { q=a0; a0=a1; a1=q; }
    if (b0>b1) { q=b0; b0=b1; b1=q; }
    s.x=x; s.vx=0.0; s.ax=0.0;
    s.y=y; s.vy=0.0; s.ay=0.0;
    s.ia=ia; s.a0=a0; s.a1=a1;
    s.ib=-1; s.b0=b0; s.b1=b1;
    s.ic.num=0;
    if ((ib>=0)&&(ib<slider.num)) slider[ib].ib=slider.num;
    s._horizontal=_h;
    s.a=a0; // min
    if (s.a>a1) s.a=a1;
    if (s.a>b0) s.a=b0;
    if (s.a>b1) s.a=b1;
    s.b=a0; // max
    if (s.b<a1) s.b=a1;
    if (s.b<b0) s.b=b0;
    if (s.b<b1) s.b=b1;
    slider.add(s);
    return slider.num-1;
    }
//---------------------------------------------------------------------------
void sliders::slider_end()
    {
    int i,j;
    double a0,a1,b0,b1,x0,x1,w=_slider_gap;
    _slider *si,*sj;
    positions();
    // detect intersecting sliders and add them to propriet ic ignore list
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
     for (sj=si+1   ,j=i+1;j<slider.num;j++,sj++)
      if (si->_horizontal!=sj->_horizontal)
        {
        if (si->_horizontal)
            {
            a0=si->X+si->a; a1=sj->X-w;
            b0=si->X+si->b; b1=sj->X+w;
            x0=si->Y;       x1=sj->Y;
            }
        else{
            a0=si->Y+si->a; a1=sj->Y-w;
            b0=si->Y+si->b; b1=sj->Y+w;
            x0=si->X;       x1=sj->X;
            }
        if (((a0<=b1)&&(b0>=a1))||((a1<=b0)&&(b1>=a0)))
         if ((x0>x1+sj->a-w)&&(x0<x1+sj->b+w))
            {
            si->ic.add(j);
            sj->ic.add(i);
            }
        }
    }
//---------------------------------------------------------------------------
bool sliders::constraints(int ix)
    {
    int i,j;
    double a0,a1,b0,b1,x0,x1,x,w=_slider_gap;
    _slider *si,*sj,*sa,*sb,*s;
    s=slider.dat+ix;
    // check parallel neighbors overlapp
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
     if ((i!=ix)&&(si->_horizontal==s->_horizontal))
        {
        if (s->_horizontal)
            {
            a0=s->X+s->a; a1=si->X+si->a;
            b0=s->X+s->b; b1=si->X+si->b;
            x0=s->Y;      x1=si->Y;
            }
        else{
            a0=s->Y+s->a; a1=si->Y+si->a;
            b0=s->Y+s->b; b1=si->Y+si->b;
            x0=s->X;      x1=si->X;
            }
        if (((a0<=b1)&&(b0>=a1))||((a1<=b0)&&(b1>=a0)))
            {
            if ((i<ix)&&(x0<x1+w)) return true;
            if ((i>ix)&&(x0>x1-w)) return true;
            }
        }
    // check perpendicular neighbors overlapp
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
     if ((i!=ix)&&(si->_horizontal!=s->_horizontal))
        {
        // skip ignored sliders for this
        for (j=0;j<s->ic.num;j++)
         if (s->ic[j]==i) { j=-1; break; }
          if (j<0) continue;
        if (s->_horizontal)
            {
            a0=s->X+s->a; a1=si->X-w;
            b0=s->X+s->b; b1=si->X+w;
            x0=s->Y;      x1=si->Y;
            }
        else{
            a0=s->Y+s->a; a1=si->Y-w;
            b0=s->Y+s->b; b1=si->Y+w;
            x0=s->X;      x1=si->X;
            }
        if (((a0<=b1)&&(b0>=a1))||((a1<=b0)&&(b1>=a0)))
         if ((x0>x1+si->a-w)&&(x0<x1+si->b+w))
          return true;
        }
    // conflict a anchor area of parent?
    if (s->ia>=0)
        {
        si=slider.dat+s->ia;
        if (s->_horizontal)
            {
            x0=si->Y+si->a0;
            x1=si->Y+si->a1;
            x=s->Y;
            }
        else{
            x0=si->X+si->a0;
            x1=si->X+si->a1;
            x=s->X;
            }
        if (x<x0+w) return true;
        if (x>x1-w) return true;
        }
    // conflict b anchor area of parent?
    if (s->ib>=0)
        {
        si=slider.dat+s->ib;
        if (si->_horizontal)
            {
            x0=si->X+si->b0;
            x1=si->X+si->b1;
            x=s->X;
            }
        else{
            x0=si->Y+si->b0;
            x1=si->Y+si->b1;
            x=s->Y;
            }
        if (x<x0+w) return true;
        if (x>x1-w) return true;
        }
    // conflict b anchor area with childs?
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
     if ((i!=ix)&&(si->ib==ix))
        {
        if (s->_horizontal)
            {
            x0=s->X+s->b0;
            x1=s->X+s->b1;
            x=si->X;
            }
        else{
            x0=s->Y+s->b0;
            x1=s->Y+s->b1;
            x=si->Y;
            }
        if (x<x0+w) return true;
        if (x>x1-w) return true;
        }

    // check childs too
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
     if ((i!=ix)&&(si->ia==ix))
      if (constraints(i)) return true;
    return false;
    }
//---------------------------------------------------------------------------
void sliders::positions()
    {
    int i,e;
    _slider *si,*sa;
    // set flag = uncomputed
    for (si=slider.dat,i=0;i<slider.num;i++,si++) si->flag=0;
    // iterate until all sliders are computed
    for (e=1;e;)
     for (e=0,si=slider.dat,i=0;i<slider.num;i++,si++)
      if (!si->flag)
        {
        // fixed
        if (si->ia<0)
            {
            si->X=si->x;
            si->Y=si->y;
            si->flag=1;
            continue;
            }
        // a anchored
        sa=slider.dat+si->ia;
        if (sa->flag)
            {
            si->X=sa->X+si->x;
            si->Y=sa->Y+si->y;
            si->flag=1;
            continue;
            }
        e=1; // not finished yet
        }
    }
//---------------------------------------------------------------------------
void sliders::update(double dt)
    {
    int i;
    _slider *si,*sa;
    double x,X;
    // D'Lamnbert integration
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
     if (si->_horizontal)
        {
        x=si->y; si->vy+=si->ay*dt;     // vel = Integral(acc*dt)
                 si->vy*=_friction;     // friction k*vel
        X=si->Y; si->y +=si->vy*dt;     // pos = Integral(vel*dt)
        positions();                    // recompute childs
        if ((si->ia<0)||(constraints(i))) // if fixed or constraint hit (stop and restore original position)
            {
            si->vy=0.0;
            si->y =x;
            si->Y =X;
            positions();                // recompute childs
            }
        }
    else{
        x=si->x; si->vx+=si->ax*dt;     // vel = Integral(acc*dt)
                 si->vx*=_friction;     // friction k*vel
        X=si->X; si->x +=si->vx*dt;     // pos = Integral(vel*dt)
        positions();                    // recompute childs
        if ((si->ia<0)||(constraints(i))) // if fixed or constraint hit (stop and restore original position)
            {
            si->vx=0.0;
            si->x =x;
            si->X =X;
            positions();                // recompute childs
            }
        }
    }
//---------------------------------------------------------------------------
void sliders::solve(bool _init)
    {
    int i,j,k;
    double a0,a1,b0,b1,x0,x1;
    _slider *si,*sj,*sa;
    // init solution
    if (_init)
        {
        mode=0;
        charge=_charge;
        }
    // clear accelerations and compute actual max velocity
    vel_max=0.0;
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
        {
        si->ax=0.0;
        si->ay=0.0;
        x0=fabs(si->vx); if (vel_max<x0) vel_max=x0;
        x0=fabs(si->vy); if (vel_max<x0) vel_max=x0;
        }
    // precision control of solver
    if ((mode==0)&&(vel_max>25.0)) { mode++; }                  // wait until speed raises
    if ((mode==1)&&(vel_max<10.0)) { mode++; charge*=0.10; }    // scale down forces to lower jitter
    if ((mode==2)&&(vel_max< 1.0)) { mode++; charge*=0.10; }    // scale down forces to lower jitter
    if ((mode==3)&&(vel_max< 0.1)) { mode++; charge =0.00; stop(); } // solution found
    // set x0 as 1D vector to closest parallel neighbor before and x1 after
    for (si=slider.dat,i=0;i<slider.num;i++,si++) { si->x0=0.0; si->x1=0.0; }
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
     for (sj=si+1   ,j=i+1;j<slider.num;j++,sj++)
      if (si->_horizontal==sj->_horizontal)
        {
        // longer side interaction
        if (si->_horizontal)
            {
            a0=si->X+si->a; a1=sj->X+sj->a;
            b0=si->X+si->b; b1=sj->X+sj->b;
            x0=si->Y;       x1=sj->Y;
            }
        else{
            a0=si->Y+si->a; a1=sj->Y+sj->a;
            b0=si->Y+si->b; b1=sj->Y+sj->b;
            x0=si->X;       x1=sj->X;
            }
        if (((a0<=b1)&&(b0>=a1))||((a1<=b0)&&(b1>=a0)))
            {
            x0=x1-x0;
            if ((si->ia>=0)&&(x0<0.0)&&((fabs(si->x0)<_slider_gap)||(fabs(si->x0)>fabs(x0)))) si->x0=-x0;
            if ((si->ia>=0)&&(x0>0.0)&&((fabs(si->x1)<_slider_gap)||(fabs(si->x1)>fabs(x0)))) si->x1=-x0;
            if ((sj->ia>=0)&&(x0<0.0)&&((fabs(sj->x0)<_slider_gap)||(fabs(sj->x0)>fabs(x0)))) sj->x0=+x0;
            if ((sj->ia>=0)&&(x0>0.0)&&((fabs(sj->x1)<_slider_gap)||(fabs(sj->x1)>fabs(x0)))) sj->x1=+x0;
            }
        // shorter side interaction
        if (si->_horizontal)
            {
            a0=si->Y-_slider_gap; a1=sj->Y+_slider_gap;
            b0=si->Y+_slider_gap; b1=sj->Y+_slider_gap;
            x0=si->X;             x1=sj->X;
            }
        else{
            a0=si->X-_slider_gap; a1=sj->X+_slider_gap;
            b0=si->X+_slider_gap; b1=sj->X+_slider_gap;
            x0=si->Y;             x1=sj->Y;
            }
        if (((a0<=b1)&&(b0>=a1))||((a1<=b0)&&(b1>=a0)))
            {
            if (x0<x1) { x0+=si->b; x1+=sj->a; }
            else       { x0+=si->a; x1+=sj->b; }
            x0=x1-x0;
            if (si->ia>=0)
                {
                sa=slider.dat+si->ia;
                if ((sa->ia>=0)&&(x0<0.0)&&((fabs(sa->x0)<_slider_gap)||(fabs(sa->x0)>fabs(x0)))) sa->x0=-x0;
                if ((sa->ia>=0)&&(x0>0.0)&&((fabs(sa->x1)<_slider_gap)||(fabs(sa->x1)>fabs(x0)))) sa->x1=-x0;
                }
            if (sj->ia>=0)
                {
                sa=slider.dat+sj->ia;
                if ((sa->ia>=0)&&(x0<0.0)&&((fabs(sa->x0)<_slider_gap)||(fabs(sa->x0)>fabs(x0)))) sa->x0=+x0;
                if ((sa->ia>=0)&&(x0>0.0)&&((fabs(sa->x1)<_slider_gap)||(fabs(sa->x1)>fabs(x0)))) sa->x1=+x0;
                }
            }
        }
    // set x0 as 1D vector to closest perpendicular neighbor before and x1 after
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
     for (sj=si+1   ,j=i+1;j<slider.num;j++,sj++)
      if (si->_horizontal!=sj->_horizontal)
        {
        // skip ignored sliders for this
        for (k=0;k<si->ic.num;k++)
         if (si->ic[k]==j) { k=-1; break; }
          if (k<0) continue;
        if (si->_horizontal)
            {
            a0=si->X+si->a; a1=sj->X-_slider_w;
            b0=si->X+si->b; b1=sj->X+_slider_w;
            x0=si->Y;
            }
        else{
            a0=si->Y+si->a; a1=sj->Y-_slider_w;
            b0=si->Y+si->b; b1=sj->Y+_slider_w;
            x0=si->X;
            }
        if (((a0<=b1)&&(b0>=a1))||((a1<=b0)&&(b1>=a0)))
            {
            if (si->_horizontal)
                {
                a1=sj->Y+sj->a;
                b1=sj->Y+sj->b;
                }
            else{
                a1=sj->X+sj->a;
                b1=sj->X+sj->b;
                }
            a1-=x0; b1-=x0;
            if (fabs(a1)<fabs(b1)) x0=-a1; else x0=-b1;
            if ((si->ia>=0)&&(x0<0.0)&&((fabs(si->x0)<_slider_gap)||(fabs(si->x0)>fabs(x0)))) si->x0=+x0;
            if ((si->ia>=0)&&(x0>0.0)&&((fabs(si->x1)<_slider_gap)||(fabs(si->x1)>fabs(x0)))) si->x1=+x0;
            if (sj->ia<0) continue;
            sa=slider.dat+sj->ia;
            if ((sa->ia>=0)&&(x0<0.0)&&((fabs(sa->x0)<_slider_gap)||(fabs(sa->x0)>fabs(x0)))) sa->x0=-x0;
            if ((sa->ia>=0)&&(x0>0.0)&&((fabs(sa->x1)<_slider_gap)||(fabs(sa->x1)>fabs(x0)))) sa->x1=-x0;
            }
        }
    // convert x0,x1 distances to acceleration
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
        {
        // driving force F = ~ Q / r^2
        if (fabs(si->x0)>1e-10)  x0=charge/(si->x0*si->x0); else x0=0.0; if (si->x0<0.0) x0=-x0;
        if (fabs(si->x1)>1e-10)  x1=charge/(si->x1*si->x1); else x1=0.0; if (si->x1<0.0) x1=-x1;
        a0=x0+x1;
        // limit acc
        if (a0<-_acc_limit) a0=-_acc_limit;
        if (a0>+_acc_limit) a0=+_acc_limit;
        // store parallel acc to correct axis
        if (si->_horizontal) si->ay=a0;
         else                si->ax=a0;
        // limit vel (+/- one iteration overlap)
        if (si->_horizontal) x0=si->vy;
         else                x0=si->vx;
        if (x0<-_vel_limit)  x0=-_vel_limit;
        if (x0>+_vel_limit)  x0=+_vel_limit;
        if (si->_horizontal) si->vy=x0;
         else                si->vx=x0;
        }
    }
//---------------------------------------------------------------------------
void sliders::stop()
    {
    int i;
    _slider *si;
    for (si=slider.dat,i=0;i<slider.num;i++,si++)
        {
        si->vx=0.0;
        si->vy=0.0;
        si->ax=0.0;
        si->ay=0.0;
        }
    }
//---------------------------------------------------------------------------
void sliders::mouse(int x,int y,TShiftState sh)
    {
    int i,q0,q1;
    double d,dd;
    _slider *si;
    // update mouse state
    mx0=mx1; my0=my1; sh0=sh1;
    mx1=x;   my1=y;   sh1=sh;
    // slider movement with left mouse button
    q0=sh0.Contains(ssLeft);
    q1=sh1.Contains(ssLeft);
    if ((sel>=0)&&(q1))
        {
        si=slider.dat+sel;
        // stop simulation for selected slider
        si->vx=0.0;
        si->vy=0.0;
        si->ax=0.0;
        si->ay=0.0;
        // use mouse position instead
        if (si->ia>=0)
            {
            if (si->_horizontal){ d=si->y; dd=si->Y; si->y+=my1-si->Y; si->Y=my1; si->vy=0.0; si->ay=0.0; positions(); if (constraints(sel)) { si->y=d; si->Y=dd; positions(); }}
             else               { d=si->x; dd=si->X; si->x+=mx1-si->X; si->X=mx1; si->vx=0.0; si->ax=0.0; positions(); if (constraints(sel)) { si->x=d; si->X=dd; positions(); }}
            }
        }
    // select slider (if not left mouse button used)
    if (!q1)
     for (sel=-1,d=_slider_w+1.0,si=slider.dat,i=0;i<slider.num;i++,si++)
        {
        dd=_slider_w+1.0;
        if (si->_horizontal){ if ((mx1>=si->X+si->a)&&(mx1<=si->X+si->b)) dd=fabs(my1-si->Y); }
         else               { if ((my1>=si->Y+si->a)&&(my1<=si->Y+si->b)) dd=fabs(mx1-si->X); }
        if ((dd<d)&&(dd<=_slider_w)) { sel=i; d=dd; }
        }
    }
//---------------------------------------------------------------------------
void sliders::draw(TCanvas *scr)
    {
    int i,j,n;
    double w=_slider_w,r,x,y,a0,a1;
    AnsiString txt;
    _slider *s;
    scr->Brush->Style=bsClear;
    #define _line(aa,bb)           \
    if (s->_horizontal)            \
        {                          \
        scr->MoveTo(s->X+aa,s->Y); \
        scr->LineTo(s->X+bb,s->Y); \
        }                          \
    else{                          \
        scr->MoveTo(s->X,s->Y+aa); \
        scr->LineTo(s->X,s->Y+bb); \
        }
    scr->Pen->Color=clSilver;
    scr->Font->Color=clWhite;
    scr->TextOutA(40,40,AnsiString().sprintf("mode %i",mode));
    scr->TextOutA(40,60,AnsiString().sprintf("vel: %.3lf [px/s]",vel_max));
    scr->TextOutA(40,80,AnsiString().sprintf("  Q: %.3lf [px^3/s^2]",charge));
    scr->Font->Color=clYellow;
    for (s=slider.dat,i=0;i<slider.num;i++,s++)
        {
        if (s->_horizontal) scr->Pen->Color=clSilver;
         else               scr->Pen->Color=clAqua;
        if (i==sel)
            {
            scr->Pen->Color=clYellow;
            txt=AnsiString().sprintf(" ix:%i ia:%i ib:%i ic:",sel,s->ia,s->ib);
            for (j=0;j<=s->ic.num;j++) txt+=AnsiString().sprintf(" %i",s->ic[j]);
            scr->TextOutA(40,100,txt);
            scr->TextOutA(40,120,AnsiString().sprintf("pos: %.1lf %.1lf [px]",s->X,s->Y));
            scr->TextOutA(40,140,AnsiString().sprintf("vel: %.3lf %.3lf [px/s]",s->vx,s->vy));
            scr->TextOutA(40,160,AnsiString().sprintf("acc: %.3lf %.3lf [px/s^2]",s->ax,s->ay));
            scr->Pen->Color=clYellow;
            }
        if (s->ia<0) scr->Pen->Style=psDash;
         else        scr->Pen->Style=psSolid;
        // a anchor loop
        x=s->X;
        y=s->Y;
        if (s->ia>=0) scr->Ellipse(x-w,y-w,x+w,y+w);
        // b anchor loop
        r=0.5*fabs(s->b1-s->b0);
        if (s->_horizontal)
            {
            x=s->X+0.5*(s->b0+s->b1);
            y=s->Y;
            scr->RoundRect(x-r,y-w,x+r,y+w,w,w);
            }
        else{
            x=s->X;
            y=s->Y+0.5*(s->b0+s->b1);
            scr->RoundRect(x-w,y-r,x+w,y+r,w,w);
            }
        // a line cutted by a anchor loop
        a0=s->a0; a1=s->a1;
        if ((s->ia>=0)&&(a0<=+w)&&(a1>=-w))
            {
            if (a0<-w) _line(s->a0,-w);
            if (a1>+w) _line( w,s->a1);
            }
        else _line(s->a0,s->a1);
        }
    scr->Font->Color=clDkGray;
    scr->Pen->Style=psSolid;
    scr->Brush->Style=bsSolid;
    #undef _line
    }
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

आप वीसीएल सामान को अनदेखा कर सकते हैं यह मेरी ऐप विंडो और रेंडरिंग के साथ बातचीत के लिए सिर्फ एपीआई है। सॉल्वर को खुद भी इससे कुछ नहीं चाहिए। मैंने अपने डायनामिक लीनियर एरे टेम्प्लेट List<T> इस्तेमाल किया, इसलिए यहाँ कुछ स्पष्टीकरण दिए गए हैं:

  • List<double> xxx; double xxx[];
  • xxx.add(5); सूची के अंत में 5 जोड़ता है
  • xxx[7] एक्सेस एरे तत्व (सुरक्षित)
  • xxx.dat[7] एक्सेस ऐरे एलिमेंट (असुरक्षित लेकिन तेज़ प्रत्यक्ष एक्सेस)
  • xxx.num सरणी का वास्तविक उपयोग किया गया आकार है
  • xxx.reset() सरणी को साफ़ करता है और xxx.num=0 सेट करता है
  • xxx.allocate(100) 100 वस्तुओं के लिए xxx.allocate(100) स्थान

इस तरह से बुलेट # 3 से उचित इनिट के बाद उपयोग सरल है:

sys.solve(true);
for (;;)
 {
 sys.solve();
 sys.update(0.040); // just time step
 if (sys.mode==4) break; // stop if solution found or stuck
 }

चक्र के बजाय मैं इसे टाइमर में कॉल करता हूं और विंडो को फिर से बनाता हूं ताकि मुझे एनीमेशन दिखाई दे:

चापलूसी गैर-समान जीआईएफ सैंपल दर को हथियाने (अनियमित रूप से सिमुलेशन से कुछ फ़्रेमों को छोड़ देने) के कारण है।

यदि आप व्यवहार को बदलना चाहते हैं if आप vel,acc लिमिट्स, भीम गुणांक और मोड नियंत्रण के लिए स्थिरांक के साथ खेल सकते हैं। यदि आप माउस हैंडलर भी लागू करते हैं तो आप बाईं माउस बटन के साथ स्लाइडर्स को स्थानांतरित कर सकते हैं ताकि आप अटके हुए मामलों से बाहर निकल सकें ...

यहाँ अकेले Win32 डेमो ( BDS2006 C ++ के साथ संकलित) खड़ा है

  • बड़े मैजेंटा बटन के नीचे धीमे डाउनलोड पर Demo क्लिक करें, पंजीकरण की आवश्यकता नहीं है डाउनलोड शुरू करने के लिए 4 अक्षर अल्फ़ान्यूमेरिक कोड दर्ज करें।

सॉल्वर फोर्स की गणना कैसे काम करती है, इसके बारे में अधिक जानकारी के लिए संबंधित / अनुवर्ती प्रश्न देखें:

  • बल से आयताकार आकार के लिए बल निर्देशित लेआउट

मेरे पास धातु के फिसलने वाले टुकड़ों का एक सेट है जो निम्नलिखित तरीके से x और y अक्ष के लिए विवश हैं:

मुझे एक ही स्लाइडर द्वारा विवश सभी टुकड़ों के बीच क्षैतिज दूरी और स्लाइडिंग टुकड़ों और स्लाइडर्स के बीच ऊर्ध्वाधर दूरी को अधिकतम करने की आवश्यकता होगी। इसे कैसे हल किया जा सकता है?

किसी भी सलाह और सुझाव से इस समस्या का समाधान हो सकता है।

मैंने पहले कुछ बहुत ही शक्तिशाली पुस्तकालयों जैसे कैसोवरी और jsLPSolver को देखा, लेकिन मुझे मुख्य एल्गोरिथ्म को समझने में थोड़ी परेशानी हुई और कैसे व्यवहार्यता के लिए कसौटी की जाँच की जाती है और फिर संभावित समाधान कैसे रैंक किए जाते हैं।

ऊपर इस तरह की समस्याओं के लिए 2-डी ज्यामितीय बाधा समाधान के लिए जावास्क्रिप्ट (सरल) स्टब में कैसे लागू किया जा सकता है?

संपादित करें:

मेरे पास इनपुट डेटा है:

maxW = 300, maxH = 320

टुकड़ों को निम्नानुसार परिभाषित किया जाता है (अनिवार्य नहीं, हर समाधान स्वीकार किया जाता है):

slidingPiece = [pX, pY, width, height, anchorPoint, loopDistance];

मैं यह समझाने की कोशिश करूंगा कि "अधिकतम" के तहत मेरा क्या मतलब है।

क्षैतिज रिक्ति:

a0-b1, b1-b2, b2-b4, b4-b5 और b5-maxX एक ही होंगे, अर्थात अधिकतम X ऊर्ध्वाधर खण्डों के सबसे बड़े भाग + 1 (5) से विभाजित होगा। b1-b3 और b3-b5 तब उपलब्ध शेष स्थान द्वारा निर्धारित किया जाएगा।

कार्यक्षेत्र रिक्ति:

b1-a3, a3-a4 और a0-b5 समान होंगे। आदर्श रूप से, a-b3, b3-b4, a2-b2, b4-a3 और b2-a4 भी समान मूल्य होंगे। A1-b4 और b3-a2 को अधिकतम करना b3-b4 को अधिकतम करने के समान है। वही a2-b2 और b4-a3 पर लागू होता है: दूरी b2-b4 तब अधिकतम ऋणात्मक मान होगा।

तो, मुझे प्रत्येक स्लाइडिंग टुकड़े के बीच की दूरी को अधिकतम करने की आवश्यकता है और वाई-बाधा के ऊपर या नीचे उसके निकटतम।

इस समस्या के 2-डी ज्यामितीय प्रतिनिधित्व से पता चलता है कि क्षैतिज रिक्ति एंकरों की ऊर्ध्वाधर दूरी (लंगरित टुकड़ों के ऊर्ध्वाधर चौराहे के कारण) से निर्भर करती है, जो बदले में टुकड़ों की क्षैतिज स्थिति से निर्भर करती है। उदाहरण के लिए सोचो, बी 2 कुछ हद तक ऊपर है। इस स्थिति में, b1 और b2 अब इंटरसेक्ट नहीं हो रहे हैं और समान x मान बन जाएंगे, यानी अधिकतम X 4 से विभाजित होगा।

कुछ अन्य मामलों में, उदाहरण के लिए b2 उपरोक्त भाग में अधिक लंबा है - और लंगर a2 को पार कर जाएगा, फिर इसे a1 तक फैला दिया जाएगा। यही कारण है कि समाधान का एक सेट होगा, कुछ संभव और कुछ अन्य, क्योंकि उदाहरण के लिए, वैश्विक अधिकतम वाई बाधा टूट जाएगी।






integer-programming